Fix building issue for tizen_base(configure: error: --with-msm given, but attr/xattr...
[platform/upstream/rpm.git] / plugins / msmxattr.c
1 /*
2  * This file is part of MSM security plugin
3  * Greatly based on the code of MSSF security plugin
4  *
5  * Copyright (C) 2010 Nokia Corporation and/or its subsidiary(-ies).
6  *
7  * Contact: Tero Aho <ext-tero.aho@nokia.com>
8  *
9  * Copyright (C) 2011 - 2013 Intel Corporation.
10  *
11  * Contact: Elena Reshetova <elena.reshetova@intel.com>
12  *
13  * This program is free software; you can redistribute it and/or modify it
14  * under the terms of the GNU General Public License as published by
15  * the Free Software Foundation; either version 2 of the License, or
16  * (at your option) any later version.
17  *
18  * This program is distributed in the hope that it will be useful, but
19  * WITHOUT ANY WARRANTY; without even the implied warranty of
20  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
21  * General Public License for more details.
22  *
23  * You should have received a copy of the GNU General Public License
24  * along with this program; if not, write to the Free Software
25  * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA
26  * 02110-1301 USA
27  */
28
29 #include <stdio.h>
30 #include <stdlib.h>
31 #include <errno.h>
32 #include <string.h>
33
34 #include <sys/types.h>
35 #include <sys/stat.h>
36 #include <unistd.h>
37 #include <pwd.h>
38 #include <grp.h>
39 #include <sys/xattr.h>
40 #include <uthash.h>
41 #include <magic.h>
42 #include "rpmio/rpmlog.h"
43 #include "rpm/rpmlib.h"
44 #include <rpm/rpmmacro.h>
45 #include <rpm/rpmts.h>
46
47 #include "msm.h"
48
49 static ac_domain_x *all_ac_domains = NULL; /* hash of all provided ac domains */
50 static package_x *allpackages = NULL; /* hash of all installed packages */
51
52 static int msmCheckDomainRequestOrPermit(manifest_x *mfx, const char* domain);
53
54 void msmFreeInternalHashes(void)
55 {
56     if (all_ac_domains) {
57         HASH_CLEAR(hh,all_ac_domains);
58     }
59
60     if (allpackages) {
61         HASH_CLEAR(hh,allpackages);
62     }
63 }
64
65 static int msmCheckACDomainRules(ac_domain_x *ac_domain, 
66                                     sw_source_x *requested, sw_source_x *provided)
67 {
68     sw_source_x *sw_source;
69
70     /* go through sw source and its parents: ac domains must not match */
71     /* deny or deny wildcards and must match allow or allow wildcards */
72     /* in the whole path up to the level of the providing sw source */ 
73
74     for (sw_source = requested; sw_source->parent && sw_source->parent != sw_source; sw_source = sw_source->parent) {
75         ac_domain_x *denied;
76         ac_domain_x *allowed;
77         /* check first if requested ac domain is denied */
78         HASH_FIND(hh, sw_source->denys, ac_domain->name, strlen(ac_domain->name), denied);
79         if (denied) return 0; /* matched deny */
80         for (denied = sw_source->denymatches; denied; denied = denied->prev)
81             if (!strwcmp(denied->match, ac_domain->name)) 
82                 return 0; /* matched deny wildcard */
83
84         /* not denied, now check if it's in allows or allowmatches */
85         HASH_FIND(hh, sw_source->allows, ac_domain->name, strlen(ac_domain->name), allowed);
86         if (allowed) continue; /* matched allow */
87         for (allowed = sw_source->allowmatches; allowed; allowed = allowed->prev)
88             if (!strwcmp(allowed->match, ac_domain->name)) 
89                 break; /* matched allow wildcard */
90         if (allowed) continue; /* matched allow wildcard */
91
92         if (strcmp(sw_source->rankkey, provided->rankkey) <= 0)
93             return 1; /* ranked higher (or same sw source), allow */
94         return 0; /* not mentioned, deny */
95     }
96     return 1; /* still here, allow for root sw source */
97 }
98
99 static int msmCheckLabelProvisioning(manifest_x *mfx, const char* label) 
100 {
101
102     d_provide_x *provide = NULL;
103     define_x *define = NULL;
104
105     if ((mfx) && (label) && (mfx->defines)) {
106         for (define = mfx->defines; define; define = define->prev) {
107             for (provide = define->d_provides; provide; provide = provide->prev) {
108                 if (strcmp(provide->label_name, label) == 0)
109                     return 0;
110             }
111         }
112     }
113     rpmlog(RPMLOG_ERR, "Label %s hasn't been provided in the manifest\n", label);
114     return -1;
115 }
116
117 static int msmSetSmackRules(struct smack_accesses *smack_accesses, ac_domain_x *ac_domains, const char *aid)
118 {
119     ac_domain_x *ac_domain;
120     int ret = 0;
121
122     if (!smack_accesses) return ret;
123     for (ac_domain = ac_domains; ac_domain; ac_domain = ac_domain->prev) {
124         if (ac_domain->allowed) {
125             ret = smack_accesses_add(smack_accesses, aid, ac_domain->name, "rw");
126             if (ret < 0) {
127                 rpmlog(RPMLOG_ERR, "smack_add failed for %s %s\n", 
128                        aid, ac_domain->name);
129                 return ret;
130             }
131         }/* else if (!ac_domain->allowed && !ac_domain->newer) {
132             // remove not allowed rule in case something has changed 
133             smack_rule_set_remove(rule_set, aid, ac_domain->name, NULL);
134         }*/
135     }
136     return ret;
137 }
138
139 static int msmIsProvideAllowed(ac_domain_x *provided, sw_source_x *sw_source, const char *origin)
140 {
141
142     /* first check provided ac_domain attributes */
143     if (provided->sw_source == sw_source) {
144         /* allowed always if ac_domain is provided in the same sw source */
145         return 1;
146     } else if (origin && !strcmp(origin, "current")) {
147         /* denied if ac_domain is only meant for current sw source */
148         return 0;
149     }
150     if (origin && !strcmp(origin, "all")) {
151         /* ac_domain is allowed for all sw sources */
152         return 1;
153     }
154     if (!origin || !strcmp(origin, "trusted")) {
155         if (strcmp(sw_source->rankkey, provided->sw_source->rankkey) < 0) {
156             /* higher ranked sw sources are allowed if ac_domain is trusted */
157             return 1;
158         } /* else flow through to check denys and allows below */
159     } else return 0;
160
161     return msmCheckACDomainRules(provided, sw_source, provided->sw_source);
162 }
163
164 static int msmSetSmackProvide(struct smack_accesses *smack_accesses, provide_x *provide, sw_source_x *sw_source)
165 {
166     ac_domain_x *ac_domain;
167     sw_source_x *current = sw_source;
168     int ret = -1;
169
170     if (!provide || (!provide->ac_domains)) return 0;
171
172     /* set smack rules for all sw sources */
173     LISTHEAD(current, sw_source);
174     for (; sw_source; sw_source = sw_source->next) {
175         if (!sw_source->newer) {
176             for (ac_domain = provide->ac_domains; ac_domain; ac_domain = ac_domain->prev) {
177                 ac_domain->allowed = msmIsProvideAllowed(ac_domain, sw_source, ac_domain->origin);
178                 rpmlog(RPMLOG_DEBUG, "%s ac_domain %s provided in %s for %s\n", (ac_domain->allowed ? "allowing" : "not allowing"), 
179                        ac_domain->name, ac_domain->sw_source->name, sw_source->name);
180             }
181 /* FIXME(José Bollo): I'm removing this call that has the effect to create rules having the
182 sw_source->name as subject. I'm thinking that this behaviour is not expected.
183 It is solving the bug https://bugs.tizen.org/jira/browse/PTREL-638.
184
185             if (smack_accesses)
186                 ret = msmSetSmackRules(smack_accesses, provide->ac_domains, sw_source->name);
187             else 
188 */
189                 ret = 0;
190         }
191     }
192     return ret;
193 }
194
195 static int msmSetupZypperRepo(access_x *access, sw_source_x *sw_source)
196 {
197     struct stat sb;
198     char path[FILENAME_MAX+1];
199     FILE *file = NULL;
200     char data[512];
201     int ret = -1;
202
203     /* NOTE: Creating zypper repos manually here! */
204     /* A library call would be the correct way, but calling c++ from c */
205     /* is not nice. On the other hand, now there is no libzypp dependency. */
206
207     char *sysconfdir = rpmExpand("%{?_sysconfdir}", NULL);
208     if (!sysconfdir || !strcmp(sysconfdir, "")) {
209         rpmlog(RPMLOG_ERR, "Failed to expand %%_sysconfdir macro\n");
210         goto exit;
211     }
212     snprintf(path, sizeof(path), "%s/zypp", sysconfdir);
213     if (stat(path, &sb) == -1) {
214         rpmlog(RPMLOG_ERR, "Failed to stat %s: %s\n", 
215                path, strerror(errno));
216         goto exit;
217     }
218     snprintf(path, sizeof(path), "%s/zypp/repos.d", sysconfdir);
219     if (stat(path, &sb) == -1) {
220         if (mkdir(path, 0755) == -1) {
221             rpmlog(RPMLOG_ERR, "Failed to create %s: %s\n", 
222                    path, strerror(errno));
223             goto exit;
224         }
225     }
226     snprintf(path, sizeof(path), "%s/zypp/repos.d/%s.repo", 
227              sysconfdir, sw_source->name);
228     file = fopen(path, "w");
229     if (!file) {
230         rpmlog(RPMLOG_ERR, "Failed to open %s: %s\n", 
231                path, strerror(errno));
232         goto exit;
233     }
234     snprintf(data, sizeof(data), 
235              "[%s]\n"
236              "name=%s\n"
237              "enabled=1\n"
238              "autorefresh=0\n"
239              "baseurl=%s\n"
240              "type=%s\n"
241              "keeppackages=0\n", 
242              sw_source->name, sw_source->name, access->data, 
243              (access->type ? access->type : "NONE"));
244
245     if (fputs(data, file) == EOF) {
246         rpmlog(RPMLOG_ERR, "Failed to write %s: %s\n", 
247                path, strerror(errno));
248         goto exit;
249     }
250     rpmlog(RPMLOG_DEBUG, "added zypper repository %s for sw source %s\n", 
251            path, sw_source->name);
252
253     ret = 0;
254  exit:
255     if (file) fclose(file);
256     msmFreePointer((void**)&sysconfdir);
257
258     return ret;
259 }
260
261 static int msmSetSmackSWSource(struct smack_accesses *smack_accesses, sw_source_x *sw_source)
262 {
263     package_x *package, *temp;
264     provide_x *provide;
265
266     if (!allpackages) return 0;
267
268     if (sw_source->older) {
269         ac_domain_x *ac_domain, *temp;
270         /* remove old domain rules in case of upgrade */
271         //smack_rule_set_remove_by_subject(rule_set, sw_source->name, NULL);
272         /* make sure domain's credentials point to upgraded domain */
273         HASH_ITER(hh, all_ac_domains, ac_domain, temp) {
274             if (ac_domain->sw_source == sw_source->older)
275                 ac_domain->sw_source = sw_source;
276         }
277     }
278
279     /* iterate through all packages to create smack rules for the domain */
280     HASH_ITER(hh, allpackages, package, temp) {
281         if (sw_source->older) {
282             /* make sure domain's packages point to upgraded domain */
283             if (package->sw_source == sw_source->older)
284                 package->sw_source = sw_source;
285         }
286         if (!package->newer) {
287             for (provide = package->provides; provide; provide = provide->prev) {
288                 if (msmSetSmackProvide(smack_accesses, provide, package->sw_source))
289                     return -1;
290             }
291         }
292     }
293     return 0;
294 }
295
296 int msmSetupSWSources(struct smack_accesses *smack_accesses, manifest_x *mfx, rpmts ts) 
297 {
298     sw_source_x *sw_source;
299     origin_x *origin;
300     keyinfo_x *keyinfo;
301     access_x *access;
302     ac_domain_x *allow;
303     ac_domain_x *deny;
304     ac_domain_x *ac_domain;
305     int ret;
306     rpmRC rc;
307
308     LISTHEAD(mfx->sw_sources, sw_source);
309
310     while (sw_source) {
311         sw_source_x *next = sw_source->next;
312         sw_source_x *parent = sw_source->parent;
313         if (ts) {
314             for (origin = sw_source->origins; origin; origin = origin->prev) {
315                 for (keyinfo = origin->keyinfos; keyinfo; keyinfo = keyinfo->prev) {
316                     rpmlog(RPMLOG_DEBUG, "setting keyinfo for sw source %s\n", 
317                            sw_source->name);
318                     rc = rpmtsImportPubkey(ts, keyinfo->keydata, keyinfo->keylen);
319                     if (rc != RPMRC_OK) {
320                         rpmlog(RPMLOG_ERR, "Key import failed for sw source %s\n",
321                                sw_source->name);
322                         return rc;
323                     }
324                 }
325                 for (access = origin->accesses; access; access = access->prev) {
326                     rpmlog(RPMLOG_DEBUG, "setting access %s for sw source %s\n", 
327                            access->data, sw_source->name);
328                     if (origin->type && !strcmp(origin->type, "ZYPPER")) {
329                         ret = msmSetupZypperRepo(access, sw_source);
330                         if (ret) {
331                             rpmlog(RPMLOG_ERR, 
332                                    "Failed to set access %s for sw source %s\n",
333                                    access->data, sw_source->name);
334                             return ret;
335                         }
336                     }
337                 }
338             }
339         } else {
340             /* config processing */
341             ret = msmSetupPackages(NULL, sw_source->packages, NULL);
342             if (ret) {
343                 rpmlog(RPMLOG_ERR, "Setup packages failed for sw source %s\n",
344                        sw_source->name);
345                 return ret;
346             }
347         }
348         if (ts) {
349             for (allow = sw_source->allows; allow; allow = allow->hh.next) {
350                 HASH_FIND(hh, all_ac_domains, allow->name, strlen(allow->name), ac_domain);
351                 if (ac_domain) {
352                     rpmlog(RPMLOG_DEBUG, "sw source %s allows access to ac domain %s\n", 
353                            sw_source->name, allow->name);
354                 } else {
355                     rpmlog(RPMLOG_WARNING, "sw source %s allows access to ac domain %s which doesn't exist\n", 
356                            sw_source->name, allow->name);
357                 }
358             }
359             for (allow = sw_source->allowmatches; allow; allow = allow->prev)
360                 rpmlog(RPMLOG_DEBUG, "sw source %s allows access to ac domain match %s\n", 
361                        sw_source->name, allow->match);
362
363             for (deny = sw_source->denys; deny; deny = deny->hh.next) {
364                 HASH_FIND(hh, all_ac_domains, deny->name, strlen(deny->name), ac_domain);
365                 if (ac_domain) {
366                     rpmlog(RPMLOG_DEBUG, "sw source %s denies access to ac domain %s\n", 
367                            sw_source->name, deny->name);
368                 } else {
369                     rpmlog(RPMLOG_WARNING, "sw source %s denies access to ac domain %s which doesn't exist\n", 
370                            sw_source->name, deny->name);
371                 }
372             }
373             for (deny = sw_source->denymatches; deny; deny = deny->prev)
374                 rpmlog(RPMLOG_DEBUG, "sw source %s denies access to ac domain match %s\n", 
375                        sw_source->name, deny->match);
376
377             if (parent) {
378                 if (strcmp(parent->name, sw_source->name)) {
379                     sw_source_x *older;
380                     for (older = parent; older; older = older->next) {
381                         if (!strcmp(sw_source->name, older->name)) {
382                             sw_source->older = older;
383                             older->newer = sw_source;
384                             break;
385                         }
386                     }
387                 } else if (!parent->parent) {
388                     /* root sw_source upgrade */
389                     sw_source->older = parent;
390                     parent->newer = sw_source;
391                     sw_source->parent = NULL;
392                 } else return -1;
393
394                 LISTDEL(mfx->sw_sources, sw_source); /* take out from sw sources list */
395                 NODEADD(parent, sw_source); /* add to sw source tree */
396             }
397
398             /* set smack rules for the new/upgraded sw source */
399             ret = msmSetSmackSWSource(smack_accesses, sw_source);
400             if (ret) {
401                 rpmlog(RPMLOG_ERR, "Setting smack rules failed for sw source %s\n",
402                        sw_source->name);
403                 return ret;
404             }
405
406         }
407         sw_source = next;
408     }
409     return 0;
410 }
411
412 static void msmRemoveDBusConfig(package_x *package, dbus_x *dbuss)
413 {
414     dbus_x *dbus;
415
416     for (dbus = dbuss; dbus; dbus = dbus->prev) {
417         char path[FILENAME_MAX+1];
418         snprintf(path, sizeof(path), "/etc/dbus-1/%s.d/manifest.%s.conf", 
419                  dbus->bus, package->name);
420         unlink(path);
421     }
422 }
423
424 static int msmSetupDBusRule(FILE *file, const char *creds, int type, const char *service, const char *name, const char *parentType, const char *parentValue, manifest_x *mfx)
425 {
426     char data[1024];
427
428     if (creds && *creds) {
429         // check first that it is of an allowed value
430         if (msmCheckDomainRequestOrPermit(mfx, creds) != 0) {
431                 rpmlog(RPMLOG_ERR, "The label %s isn't allowed to be accessed by device security policy\n", creds);
432                 return -1;
433         }
434         switch (type) {
435         case DBUS_SERVICE:
436             snprintf(data, sizeof(data), 
437                      "  <policy context=\"default\">\n"
438                      "    <deny send_destination=\"%s\"/>\n"
439                      "  </policy>\n"
440                      "  <policy smack=\"%s\">\n"
441                      "    <allow send_destination=\"%s\"/>\n"
442                      "  </policy>\n",
443                      name, creds, name);
444             break;
445         case DBUS_PATH:
446             snprintf(data, sizeof(data), 
447                      "  <policy context=\"default\">\n"
448                      "    <deny send_destination=\"%s\" send_path=\"%s\"/>\n"
449                      "    <deny receive_sender=\"%s\" receive_path=\"%s\"/>\n"
450                      "  </policy>\n"
451                      "  <policy smack=\"%s\">\n"
452                      "    <allow send_destination=\"%s\" send_path=\"%s\"/>\n"
453                      "    <allow receive_sender=\"%s\" receive_path=\"%s\"/>\n"
454                      "  </policy>\n",
455                      service, name, service, name, creds,
456                      service, name, service, name);
457             break;
458         case DBUS_INTERFACE:
459             snprintf(data, sizeof(data), 
460                      "  <policy context=\"default\">\n"
461                      "    <deny send_destination=\"%s\" send_interface=\"%s\"/>\n"
462                      "    <deny receive_sender=\"%s\" receive_interface=\"%s\"/>\n"
463                      "  </policy>\n"
464                      "  <policy smack=\"%s\">\n"
465                      "    <allow send_destination=\"%s\" send_interface=\"%s\"/>\n"
466                      "    <allow receive_sender=\"%s\" receive_interface=\"%s\"/>\n"
467                      "  </policy>\n",
468                      service, name, service, name, creds,
469                      service, name, service, name);
470             break;
471         case DBUS_METHOD:
472             snprintf(data, sizeof(data), 
473                      "  <policy context=\"default\">\n"
474                      "    <deny send_destination=\"%s\" send_%s=\"%s\" send_member=\"%s\"/>\n"
475                      "  </policy>\n"
476                      "  <policy smack=\"%s\">\n"
477                      "    <allow send_destination=\"%s\" send_%s=\"%s\" send_member=\"%s\"/>\n"
478                      "  </policy>\n",
479                      service, parentType, parentValue, name, creds,
480                      service, parentType, parentValue, name);
481             break;
482         case DBUS_SIGNAL:
483             snprintf(data, sizeof(data), 
484                      "  <policy context=\"default\">\n"
485                      "    <deny receive_sender=\"%s\" receive_%s=\"%s\" receive_member=\"%s\"/>\n"
486                      "  </policy>\n"
487                      "  <policy smack=\"%s\">\n"
488                      "    <allow receive_sender=\"%s\" receive_%s=\"%s\" receive_member=\"%s\"/>\n"
489                      "  </policy>\n",
490                      service, parentType, parentValue, name, creds,
491                      service, parentType, parentValue, name);
492             break;
493         default:
494             return -1;
495         }
496     } else {
497         switch (type) {
498         case DBUS_SERVICE:
499             snprintf(data, sizeof(data), 
500                      "  <policy context=\"default\">\n"
501                      "    <allow send_destination=\"%s\"/>\n"
502                      "  </policy>\n",
503                      name);
504             break;
505         case DBUS_PATH:
506             snprintf(data, sizeof(data), 
507                      "  <policy context=\"default\">\n"
508                      "    <allow send_destination=\"%s\" send_path=\"%s\"/>\n"
509                      "    <allow receive_sender=\"%s\" receive_path=\"%s\"/>\n"
510                      "  </policy>\n",
511                      service, name, service, name);
512             break;
513         case DBUS_INTERFACE:
514             snprintf(data, sizeof(data), 
515                      "  <policy context=\"default\">\n"
516                      "    <allow send_destination=\"%s\" send_interface=\"%s\"/>\n"
517                      "    <allow receive_sender=\"%s\" receive_interface=\"%s\"/>\n"
518                      "  </policy>\n",
519                      service, name, service, name);
520             break;
521         case DBUS_METHOD:
522             snprintf(data, sizeof(data), 
523                      "  <policy context=\"default\">\n"
524                      "    <allow send_destination=\"%s\" send_%s=\"%s\" send_member=\"%s\"/>\n"
525                      "  </policy>\n",
526                      service, parentType, parentValue, name);
527             break;
528         case DBUS_SIGNAL:
529             snprintf(data, sizeof(data), 
530                      "  <policy context=\"default\">\n"
531                      "    <allow receive_sender=\"%s\" receive_%s=\"%s\" receive_member=\"%s\"/>\n"
532                      "  </policy>\n",
533                      service, parentType, parentValue, name);
534             break;
535         default:
536             return -1;
537         }
538     }
539     if (fputs(data, file) == EOF) {
540         rpmlog(RPMLOG_ERR, "Failed to write DBus rule %s: %s\n", 
541                data, strerror(errno));
542         return -1;
543     }
544     return 0;
545 }
546
547 static int msmSetupDBusConfig(package_x *package, dbus_x *dbus, int phase, manifest_x *mfx)
548 {
549     char path[FILENAME_MAX+1];
550     FILE *file = NULL;
551     char data[512];
552     node_x *node;
553     interface_x *interface;
554     member_x *member;
555     int ret = 0;
556
557     char *sysconfdir = rpmExpand("%{?_sysconfdir}", NULL);
558     if (!sysconfdir || !strcmp(sysconfdir, "")) {
559         rpmlog(RPMLOG_ERR, "Failed to expand %%_sysconfdir macro\n");
560         ret = -1;
561         goto exit;
562     }
563     snprintf(path, sizeof(path), "%s/dbus-1/%s.d/manifest.%s.conf", 
564              sysconfdir, dbus->bus, package->name);
565
566     file = fopen(path, phase ? "a" : "w");
567     if (!file) {
568         rpmlog(RPMLOG_ERR, "Cannot open %s: %s\n", path, strerror(errno));
569         ret = -1;
570         goto exit;
571     }
572
573     if (phase == 0) {
574         snprintf(data, sizeof(data), 
575                  "<!-- This configuration is automatically generated from Manifest by RPM %s security plugin -->\n"
576                  "<!DOCTYPE busconfig PUBLIC \"-//freedesktop//DTD D-BUS Bus Configuration 1.0//EN\" \"http://www.freedesktop.org/standards/dbus/1.0/busconfig.dtd\">\n"
577                  "<busconfig>\n",
578                  rpmEVR);
579         if (fputs(data, file) == EOF) {
580             rpmlog(RPMLOG_ERR, "Failed to write %s: %s\n", 
581                    path, strerror(errno));
582             ret = -1;
583             goto exit;
584         }
585     }
586
587     if (phase >= 0) {
588         if (dbus->own) {
589             snprintf(data, sizeof(data), 
590                          "  <policy context=\"default\">\n"
591                          "    <deny own=\"%s\"/>\n"
592                          "  </policy>\n"
593                          "  <policy smack=\"%s\">\n"
594                          "    <allow own=\"%s\"/>\n"
595                          "  </policy>\n",
596                          dbus->name, dbus->own, dbus->name);
597             if (fputs(data, file) == EOF) {
598                 rpmlog(RPMLOG_ERR, "Failed to write %s: %s\n", 
599                        path, strerror(errno));
600                 ret = -1;
601                 goto exit;
602             }
603         }
604         if (dbus->annotation) {
605             msmSetupDBusRule(file, dbus->annotation->value, DBUS_SERVICE, 
606                              NULL, dbus->name, NULL, NULL, mfx);
607         }
608         for (node = dbus->nodes; node; node = node->prev) {
609             if (node->annotation) {
610                 ret = msmSetupDBusRule(file, node->annotation->value, DBUS_PATH,
611                                  dbus->name, node->name, NULL, NULL, mfx);
612                 if (ret < 0) goto exit;
613             }
614             for (member = node->members; member; member = member->prev) {
615                 if (member->annotation) {
616                     ret = msmSetupDBusRule(file, member->annotation->value, member->type, 
617                                      dbus->name, member->name, 
618                                      "path", node->name, mfx);
619                     if (ret < 0) goto exit;
620                 }
621             }
622             for (interface = node->interfaces; interface; interface = interface->prev) {
623                 if (interface->annotation) {
624                     ret = msmSetupDBusRule(file, interface->annotation->value, DBUS_INTERFACE, 
625                                      dbus->name, interface->name, NULL, NULL, mfx);
626                     if (ret < 0) goto exit;
627                 }
628                 for (member = interface->members; member; member = member->prev) {
629                     if (member->annotation) {
630                         ret = msmSetupDBusRule(file, member->annotation->value, member->type, 
631                                          dbus->name, member->name,
632                                          "interface", interface->name, mfx);
633                         if (ret < 0) goto exit;
634                     }
635                 }
636             }
637         }
638     }
639
640     if (phase < 0) {
641         snprintf(data, sizeof(data), "</busconfig>\n");
642         if (fputs(data, file) == EOF) {
643             rpmlog(RPMLOG_ERR, "Failed to write %s: %s\n", 
644                    path, strerror(errno));
645             ret = -1;
646             goto exit;
647         }
648         rpmlog(RPMLOG_DEBUG, "wrote dbus config %s\n", path);   
649     }
650     ret = 0;
651
652  exit:
653     if (file) fclose(file);
654     if (ret < 0) unlink(path);
655     msmFreePointer((void**)&sysconfdir);
656     return ret;
657 }
658
659 static int msmIsRequestAllowed(manifest_x *mfx, ac_domain_x *provided)
660 {  
661     if (mfx->sw_source == provided->sw_source) {
662         /* allowed always if ac domain is provided in the same sw source */
663         return 1;
664     } else if (provided->origin && !strcmp(provided->origin, "current")) {
665         /* denied if ac domain is only meant for current sw source */
666         return 0;
667     }
668     if (provided->origin && !strcmp(provided->origin, "all")) {
669         /* ac_domain is allowed for all sw sources */
670         return 1;
671     }
672     if (!provided->origin || !strcmp(provided->origin, "trusted")) {
673         if (strcmp(mfx->sw_source->rankkey, provided->sw_source->rankkey) < 0) {
674             /* higher ranked sw sources are allowed if ac domain is trusted */
675             return 1;
676         } /* else flow through to check denys and allows below */
677     } else return 0;
678
679     return msmCheckACDomainRules(provided, mfx->sw_source, provided->sw_source);
680 }
681
682 static int msmCheckDomainJoinPossibility(manifest_x *mfx, ac_domain_x *defined_ac_domain) 
683 {
684
685     char *tmp = NULL, *pch = NULL;
686     unsigned int found = 0;
687
688     if ((!mfx) || (!defined_ac_domain))
689         return -1; 
690
691     if (defined_ac_domain->type) {
692         if (strcmp(defined_ac_domain->type, "restricted") == 0) {
693             if (defined_ac_domain->plist) {
694                 tmp = calloc(strlen(defined_ac_domain->plist) + 1, sizeof(char));
695                 if (!tmp) return -1; 
696                 strncpy(tmp, defined_ac_domain->plist, strlen(defined_ac_domain->plist));
697                 pch = strtok (tmp, ", ");
698                 while (pch != NULL) {
699                     if (strcmp(pch, mfx->name) == 0) {
700                         found = 1; 
701                         break;
702                     }                                   
703                     pch = strtok(NULL, ", ");
704                 }
705                 msmFreePointer((void**)&tmp);
706             }
707             if (found != 1) {
708                 rpmlog(RPMLOG_ERR, "Request for a domain name %s isn't allowed ", mfx->request->ac_domain);
709                 rpmlog(RPMLOG_ERR, "because ac domain is marked as restricted\n");
710                 return -1;
711             }
712         } else if (strcmp(defined_ac_domain->type, "shared") == 0) {
713             return 0;                   
714         } else {
715             // domain hasn't been marked as shared 
716             rpmlog(RPMLOG_ERR, "Request for a domain name %s isn't allowed ", mfx->request->ac_domain);
717             rpmlog(RPMLOG_ERR, "because ac domain is marked as private\n");
718             return -1;
719         }
720     } else { 
721         // by default ac domains are private
722         rpmlog(RPMLOG_ERR, "Request for a domain name %s isn't allowed ", mfx->request->ac_domain);
723         rpmlog(RPMLOG_ERR, "because ac domain is marked as private\n");
724         return -1;
725     }
726     return 0;
727 }
728
729 int msmSetupRequests(manifest_x *mfx) 
730 {
731     ac_domain_x *defined_ac_domain = NULL; 
732     define_x *define = NULL;
733
734     if ((!mfx) || (!mfx->request) || (!mfx->request->ac_domain))
735         return -1;
736         
737     HASH_FIND(hh, all_ac_domains, mfx->request->ac_domain, strlen(mfx->request->ac_domain), defined_ac_domain);
738     if (!defined_ac_domain){ // request for a undefined domain. 
739         rpmlog(RPMLOG_ERR, "Request for a domain name %s that hasn't been yet defined by any package\n", mfx->request->ac_domain);
740         return -1;
741     }
742     //now check that the package can join the requested AC domain
743     if (mfx->defines){
744         LISTHEAD(mfx->defines, define);
745         while(define) {
746             rpmlog(RPMLOG_DEBUG, "define->name %s mfx->request->ac_domain %s\n", define->name, mfx->request->ac_domain);
747             if (strcmp(define->name, mfx->request->ac_domain) == 0)
748                 //ac domain is requested from the same package where it was define. This case is always allowed
749                 return 0;
750             define = define->next;
751         }               
752     } 
753     //need to check if developer allowed other packages to join this domain
754     if (msmCheckDomainJoinPossibility(mfx, defined_ac_domain) < 0) {
755         return -1;
756     }
757     // now checking if security policy allows to join this domain
758     if (msmIsRequestAllowed(mfx, defined_ac_domain)) {
759         rpmlog(RPMLOG_DEBUG, "Request for a domain name %s is allowed based on package sw source\n", mfx->request->ac_domain);
760         return 0;               
761     } else {
762         rpmlog(RPMLOG_ERR, "Request for a domain name %s isn't allowed based on package sw source\n", mfx->request->ac_domain);
763         return -1;
764     }
765 }
766
767 static int msmSetupProvides(struct smack_accesses *smack_accesses, package_x *package)
768 {
769     provide_x *provide;
770     ac_domain_x *ac_domain;
771
772     for (provide = package->provides; provide; provide = provide->prev) {
773         for (ac_domain = provide->ac_domains; ac_domain; ac_domain = ac_domain->prev) {
774             ac_domain_x *current_d = NULL;
775             ac_domain->origin = provide->origin;
776
777             HASH_FIND(hh, all_ac_domains, ac_domain->name, strlen(ac_domain->name), current_d);
778             if (current_d) { /* ac domain has been previously defined */
779                 if (strcmp(ac_domain->pkg_name, current_d->pkg_name) == 0) { /* check that it was provided by same package */           
780                     HASH_DELETE(hh, all_ac_domains, current_d);
781                     HASH_ADD_KEYPTR(hh, all_ac_domains, ac_domain->name, strlen(ac_domain->name), ac_domain);
782                     current_d->newer = ac_domain;
783                     ac_domain->older = current_d;
784                     rpmlog(RPMLOG_DEBUG, "package %s upgraded ac domain %s\n", ac_domain->pkg_name, ac_domain->name);             
785                 } else {
786                     rpmlog(RPMLOG_ERR, "package %s can't upgrade ac domain %s previously defined in package %s\n", 
787                                                                         ac_domain->pkg_name, ac_domain->name, current_d->pkg_name);
788                     return -1;
789                 }
790             } else {
791                 HASH_ADD_KEYPTR(hh, all_ac_domains, ac_domain->name, strlen(ac_domain->name), ac_domain);
792                 rpmlog(RPMLOG_DEBUG, "package %s defined ac domain %s\n", ac_domain->pkg_name, ac_domain->name);                
793             }
794         }
795         int ret = msmSetSmackProvide(smack_accesses, provide, package->sw_source);
796         if (ret < 0) {
797             rpmlog(RPMLOG_ERR, "Failed to set smack rules for provide\n");
798             return -1;
799         }
800     }
801     return 0;
802 }
803
804 int msmSetupDBusPolicies(package_x *package, manifest_x *mfx) 
805 {
806     dbus_x *session = NULL;
807     dbus_x *system = NULL;
808     provide_x *provide;
809     dbus_x *dbus;
810     int ret = 0;
811
812     for (provide = package->provides; provide; provide = provide->prev) {
813         for (dbus = provide->dbuss; dbus; dbus = dbus->prev) {
814             if (!strcmp(dbus->bus, "session")) {
815                 ret = msmSetupDBusConfig(package, dbus, session ? 1 : 0, mfx);
816                 session = dbus;
817             } else if (!strcmp(dbus->bus, "system")) {
818                 ret = msmSetupDBusConfig(package, dbus, system ? 1 : 0, mfx);
819                 system = dbus;
820             } else return -1;
821             if (ret < 0) return ret;
822         }
823        if (session) ret = msmSetupDBusConfig(package, session, -1, mfx);
824        if (system) ret = msmSetupDBusConfig(package, system, -1, mfx);
825        session = system = NULL;
826     }
827     return ret;
828 }
829
830 static int msmCheckDomainRequestOrPermit(manifest_x *mfx, const char* domain) 
831 {
832     ac_domain_x *defined_ac_domain = NULL;
833     define_x *define = NULL;
834     char* name = NULL;
835
836     if ((!mfx) || (!domain))
837         return -1;
838
839     name = calloc(strlen(domain) + 1, sizeof(char));
840     if (!name) return -1;
841     strncpy(name, domain, strlen(domain));
842     strtok(name, ":");  // remove label name if present
843     rpmlog(RPMLOG_DEBUG, "label name %s domain name %s \n", domain, name);
844
845     HASH_FIND(hh, all_ac_domains, name, strlen(name), defined_ac_domain);
846     if (!defined_ac_domain) // request or permit for an undefined domain.
847         // FIXME: maybe this should be changed to a command-line option that
848         // would be used during the image build?
849         rpmlog(RPMLOG_WARNING, "The domain '%s' has not been yet defined by "\
850                "any package\n", domain);
851
852     //now check that this ac_domain can be requested
853     if (mfx->defines) {
854         LISTHEAD(mfx->defines, define);
855         while (define) {
856             rpmlog(RPMLOG_DEBUG, "define->name %s domain %s\n", define->name,
857                    name);
858             if (strcmp(define->name, name) == 0) {
859                 // AC domain access is requested or permitted from the same
860                 // package where it was defined. This case is always allowed.
861                 msmFreePointer((void**)&name);
862                 return 0;
863             }
864             define = define->next;
865         }
866     } 
867
868     // no need to check if developer allowed other packages to
869     // request/permit this domain because this isn't a request to
870     // belong to a domain, but request/permit for domain access
871     if (!defined_ac_domain)
872         // FIXME: maybe this should be changed to a command-line option that
873         // would be used during the image build?
874         rpmlog(RPMLOG_WARNING, "Request/Permit to access the domain '%s' is "\
875                "unknown\n", name);
876     else if (msmIsRequestAllowed(mfx, defined_ac_domain))
877         // request or permit is allowed by domain policy
878         rpmlog(RPMLOG_DEBUG, "Request/Permit to access the domain '%s' is "\
879                "allowed based on package SW source\n", name);
880     else {
881         rpmlog(RPMLOG_ERR, "Request/Permit access the domain '%s' is not "\
882                "allowed based on package SW source\n", name);
883         msmFreePointer((void**)&name);
884         return -1;
885     }
886
887     msmFreePointer((void**)&name);
888     return 0;
889 }
890
891 int msmSetupDefines(struct smack_accesses *smack_accesses, manifest_x *mfx)
892 {
893     d_request_x *d_request;
894     define_x *define;
895     d_permit_x *d_permit;
896     ac_domain_x * defined_ac_domain = NULL;
897     int ret;
898
899     if ( (!mfx) || (!mfx->defines)) {
900         rpmlog(RPMLOG_ERR, "Failed to setup define\n");
901         return -1;
902     }
903
904     LISTHEAD(mfx->defines, define);
905
906     while (define) {
907         define_x *next = define->next;
908         if (!define->name) {
909             rpmlog(RPMLOG_ERR, "Attempt to define a domain with empty name. Abort\n");
910             return -1;
911         }
912         /* need to check if domain hasn't been already defined by other package */
913
914         HASH_FIND(hh, all_ac_domains, define->name, strlen(define->name), defined_ac_domain);
915         if ((defined_ac_domain) && (defined_ac_domain->pkg_name)) { // this domain has been previously defined
916             if (strcmp(defined_ac_domain->pkg_name, mfx->name) != 0) {
917                 rpmlog(RPMLOG_ERR, "Attempt to define a domain name %s that has been already defined by package %s\n",
918                        define->name, defined_ac_domain->pkg_name);
919                 return -1;
920             }
921         }
922
923         if (define->d_requests) {
924             for (d_request = define->d_requests; d_request; d_request = d_request->prev) {
925                 // first check if the current's package sw source can grant access to requested domain
926                 if (msmCheckDomainRequestOrPermit(mfx, d_request->label_name) < 0) {
927                     return -1;
928                 }
929                 if (smack_accesses_add(smack_accesses, define->name, d_request->label_name, d_request->ac_type) < 0) {
930                     rpmlog(RPMLOG_ERR, "Failed to set smack rules for domain requests\n");
931                     return -1;
932                 }    
933             }
934         }
935
936         if (define->d_permits) {
937             for (d_permit = define->d_permits; d_permit; d_permit = d_permit->prev) {
938                 // first check if the current's package sw source can grant access to permited domain
939                 if (msmCheckDomainRequestOrPermit(mfx, d_permit->label_name) < 0) {
940                     return -1;
941                 }
942                 if (!d_permit->to_label_name)
943                     ret = smack_accesses_add(smack_accesses, d_permit->label_name, define->name, d_permit->ac_type);
944                 else {
945                     if (msmCheckLabelProvisioning(mfx, d_permit->to_label_name) < 0) {
946                         return -1;
947                     }
948                     ret = smack_accesses_add(smack_accesses, d_permit->label_name, d_permit->to_label_name, d_permit->ac_type);
949                 }
950                 if (ret < 0) {
951                     rpmlog(RPMLOG_ERR, "Failed to set smack rules for domain permits\n");
952                     return -1;
953                 }    
954             }
955         } 
956
957         define = next;
958     }
959
960     return 0;
961 }
962
963 package_x *msmCreatePackage(const char *name, sw_source_x *sw_source, provide_x *provides, const char *modified)
964 {
965     if (!name) return NULL;
966
967     package_x *package = calloc(1, sizeof(package_x));
968     if (package) {
969         package->name = strdup(name);
970         if (!package->name) goto exit;
971         package->sw_source = sw_source;
972         package->provides = provides;
973         if (modified) {
974             package->modified = strdup(modified);
975             if (!package->modified) goto exit;
976         }
977     }
978     return package;
979
980  exit:
981     msmFreePointer((void**)&package->name);
982     msmFreePointer((void**)&package->modified);
983     msmFreePointer((void**)&package);
984
985     return NULL;
986 }
987
988 int msmSetupSmackRules(struct smack_accesses *smack_accesses, const char* package_name, int flag, int SmackEnabled)
989 {
990     int ret = 0;
991     int empty = 0;
992     char * buffer = calloc(strlen(SMACK_RULES_PATH) + strlen(package_name) + 1, sizeof(char));
993     if (!buffer) return -1;    
994     strncpy(buffer, SMACK_RULES_PATH, strlen(SMACK_RULES_PATH));
995     strncpy(buffer + strlen(SMACK_RULES_PATH), package_name, strlen(package_name));
996     rpmlog(RPMLOG_DEBUG, "smack rule file path %s, SmackEnabled %d\n", buffer, SmackEnabled);
997
998     if (flag == SMACK_UNINSTALL) { /* uninstallation case */
999         FILE* fd = fopen(buffer, "r");
1000         if (fd) {
1001             rpmlog(RPMLOG_DEBUG, "uninstall case \n");
1002             struct smack_accesses *old_rule_set = NULL;
1003             ret = smack_accesses_new(&old_rule_set);
1004             if (ret != 0) return -1;
1005             ret = smack_accesses_add_from_file(old_rule_set, fileno(fd));
1006             if (ret == 0) {
1007                 if (SmackEnabled == 1) 
1008                     ret = smack_accesses_clear(old_rule_set); /* deletes rules from kernel */
1009             }
1010             smack_accesses_free(old_rule_set);
1011             fclose(fd);
1012             remove(buffer); /* delete rules file from system */
1013         }
1014     } else { /*installation case */
1015         /* first attempt to clean previous version of rules, if exists */
1016         FILE* fd = fopen(buffer, "r");
1017         if (fd) {
1018             struct smack_accesses *old_rule_set = NULL;
1019             ret = smack_accesses_new(&old_rule_set);
1020             if (ret != 0) return -1;
1021             ret = smack_accesses_add_from_file(old_rule_set, fileno(fd));
1022             if (ret == 0) {
1023                 if (SmackEnabled == 1) 
1024                     ret = smack_accesses_clear(old_rule_set); /* deletes old rules from kernel */
1025             }
1026             fclose(fd);
1027             smack_accesses_free(old_rule_set);
1028         } 
1029         /* now write new rules to the system */
1030         fd = fopen(buffer, "w");
1031         if (!fd) {
1032             rpmlog(RPMLOG_ERR, "Can't write smack rules\n");
1033             return -1;
1034         }
1035         ret = smack_accesses_save(smack_accesses, fileno(fd));
1036         rpmlog(RPMLOG_DEBUG, "ret in installation %d\n", ret);
1037         if (!ret) {
1038             empty = !ftell(fd);
1039             if (SmackEnabled == 1) 
1040                 ret = smack_accesses_apply(smack_accesses);
1041         }
1042         fclose(fd);
1043         if (empty)
1044             unlink(buffer); /* status not checked because it dont care */
1045     }    
1046     free(buffer);
1047     if (ret)
1048         return -1;
1049     return 0;   
1050
1051 }
1052
1053 int msmSetupPackages(struct smack_accesses *smack_accesses, package_x *packages, sw_source_x *sw_source)
1054 {
1055     package_x *package, *first = NULL;
1056     char *p_rankkey, *c_rankkey; 
1057     for (package = packages; package; package = package->prev) {
1058         package_x *current_p;
1059         rpmlog(RPMLOG_DEBUG, "before HASH_FIND, package->name %s\n", package->name);
1060         HASH_FIND(hh, allpackages, package->name, strlen(package->name), current_p);
1061         if (current_p) {
1062             if (!current_p->sw_source) {
1063                 return -1;
1064             }
1065             p_rankkey = strdup(package->sw_source->rankkey);
1066             c_rankkey = strdup(current_p->sw_source->rankkey);
1067             p_rankkey = strtok(p_rankkey, ".");
1068             c_rankkey = strtok(c_rankkey, ".");
1069             /* this is an upgrade, remove old one from config */
1070             if ((strcmp(p_rankkey, c_rankkey) < 0) ||
1071                 (strcmp(package->sw_source->name, current_p->sw_source->name) == 0)) {
1072                 HASH_DELETE(hh, allpackages, current_p);
1073                 rpmlog(RPMLOG_DEBUG, "sw source %s upgraded package %s previously provided in sw source %s\n", 
1074                                                                 package->sw_source->name, package->name, current_p->sw_source->name);
1075                 current_p->newer = package;
1076                 package->older = current_p;
1077             } else {
1078                 /* upgrade from lower or similary ranked sw source is not allowed */ 
1079                 rpmlog(RPMLOG_ERR, "sw source %s tried to upgrade package %s previously provided in sw source %s\n", 
1080                                                                 package->sw_source->name, package->name, current_p->sw_source->name);
1081                 return -1;
1082             }
1083             msmFreePointer((void**)&p_rankkey);
1084             msmFreePointer((void**)&c_rankkey);
1085         } else {
1086             if (sw_source) {
1087             rpmlog(RPMLOG_DEBUG, "sw source %s provided package %s\n", package->sw_source->name, package->name);
1088             }
1089         }
1090         rpmlog(RPMLOG_DEBUG, "before HASH_ADD_KEYPTR\n");
1091         HASH_ADD_KEYPTR(hh, allpackages, package->name, strlen(package->name), package);   
1092         /* set sw source smack rules*/
1093         if ((msmSetupProvides(smack_accesses, package)) < 0 ) {
1094                 msmCancelPackage(package->name);  
1095                 return -1;
1096         }
1097         first = package;
1098     }
1099     if (sw_source && packages) {
1100         /* catenate list to sw_source config */
1101         LISTCAT(sw_source->packages, first, packages);
1102     }
1103     return 0;
1104 }
1105
1106 package_x *msmCheckPackage(const char *name)
1107 {
1108     package_x *package = NULL;
1109     if (name)
1110         HASH_FIND(hh, allpackages, name, strlen(name), package);
1111     return package;
1112 }
1113
1114 static void msmCancelACDomain(const char *name)
1115 {
1116     if (name) {
1117         ac_domain_x *domain;
1118         HASH_FIND(hh, all_ac_domains, name, strlen(name), domain);
1119         if (domain) {
1120             HASH_DELETE(hh, all_ac_domains, domain);
1121             if (domain->older) {
1122                 /* resume previous version */
1123                 HASH_ADD_KEYPTR(hh, all_ac_domains, domain->older->name, strlen(domain->older->name), domain->older);
1124                 domain->older->older = domain->older->newer;
1125                 domain->older->newer = NULL;
1126                 domain->newer = domain->older;
1127                 domain->older = NULL;
1128             } else {
1129                 /* no previous, just take this one out */
1130                 domain->newer = domain;
1131             }
1132         }
1133     }
1134 }
1135
1136 void msmCancelPackage(const char *name)
1137 {
1138     provide_x *provide;
1139     ac_domain_x *ac_domain;
1140
1141     if (name) {
1142         package_x *package;
1143         HASH_FIND(hh, allpackages, name, strlen(name), package);
1144         if (package) {
1145             HASH_DELETE(hh, allpackages, package);
1146             if (package->older) {
1147                 /* resume previous version */
1148                 HASH_ADD_KEYPTR(hh, allpackages, package->older->name, strlen(package->older->name), package->older);
1149                 package->older->older = package->older->newer;
1150                 package->older->newer = NULL;
1151                 package->newer = package->older;
1152                 package->older = NULL;
1153             } else {
1154                 /* no previous, just take this one out */
1155                 package->newer = package;
1156             }
1157            /* need to clean up the all_ac_domain list, too */
1158            for (provide = package->provides; provide; provide = provide->prev) {
1159                for (ac_domain = provide->ac_domains; ac_domain; ac_domain = ac_domain->prev) 
1160                     msmCancelACDomain(ac_domain->name);
1161            }
1162         }
1163     }
1164 }
1165
1166 static int is_executable(const char* path, magic_t cookie) 
1167 {
1168    const char* buffer = NULL;
1169    int result = -1;
1170    char* ptr = NULL;
1171
1172    if ((!path) || (!cookie))
1173         return result;
1174
1175    buffer = magic_file(cookie, path);
1176    rpmlog(RPMLOG_DEBUG, "buffer: %s\n", buffer);        
1177
1178    if (buffer != NULL) { 
1179         ptr = strstr(buffer,"executable");
1180         if (ptr) result = 0;    
1181         ptr = strstr(buffer,"ELF");
1182         if (ptr) result = 0;            
1183    }
1184
1185    return result;
1186 }
1187
1188 int msmSetFileXAttributes(manifest_x *mfx, const char* filepath, magic_t cookie) 
1189 {
1190     provide_x *provide = NULL;
1191     filesystem_x *filesystem = NULL;    
1192     size_t len = 0, match = 0;
1193     const char *label = NULL;
1194     const char *exec_label = NULL;
1195     const char *type = NULL;
1196     const char isolatedLabel[] = SMACK_ISOLATED_LABEL;
1197     struct stat st;
1198     int execLabeldefined = 0;
1199
1200     if (!filepath) return -1;
1201     if (mfx->name) {
1202         package_x *package = msmCheckPackage(mfx->name);
1203         if (!package) return -1;
1204         for (provide = package->provides; provide; provide = provide->prev) {
1205             for (filesystem = provide->filesystems; filesystem; filesystem = filesystem->prev) {
1206                 if (!strcmp(filepath, filesystem->path)) {
1207                     /* exact match */
1208                     label = filesystem->label;
1209                     exec_label = filesystem->exec_label;
1210                     if (filesystem->type) type = filesystem->type;
1211                     goto found;
1212                 }
1213                 len = strlen(filesystem->path);
1214                 rpmlog(RPMLOG_DEBUG, "filepath: %s, filesystem->type %s\n", filepath, filesystem->type);
1215                 //rpmlog(RPMLOG_DEBUG, "filesystem->path: %s, length %d, match %d\n", filesystem->path, len, match);
1216                 //rpmlog(RPMLOG_DEBUG, "filesystem->path + len - 1: %s\n", filesystem->path + len - 1);
1217                 if (len > match) {
1218                     if ((!strncmp(filepath, filesystem->path, len)) && (filesystem->type)) {
1219                         /* partial match and the directory marked as transmutable*/
1220                         label = filesystem->label;
1221                         exec_label = filesystem->exec_label;
1222                         match = len;
1223                     }
1224                     if (!strncmp(filesystem->path + len - 1, "*", 1)) { 
1225                         if (!strncmp(filepath, filesystem->path, len - 1))  {
1226                             /* partial match and the path is marked with wildcard*/
1227                             label = filesystem->label;
1228                             exec_label = filesystem->exec_label;
1229                             match = len - 1;
1230                         }
1231                     }
1232                 }
1233             }
1234         }
1235     } else 
1236         return -1;
1237
1238  found:
1239     if (exec_label) {
1240         execLabeldefined = 1;
1241 #if 0
1242         if ((strcmp(exec_label, "none") == 0) 
1243             || ( (mfx->request) && (mfx->request->ac_domain) && (strcmp(exec_label, mfx->request->ac_domain) == 0))) {
1244             // these labels are allowed
1245         } else {
1246             // ignore all other exec labels, because they aren't allowed for security reasons
1247             exec_label = NULL;
1248             rpmlog(RPMLOG_DEBUG, "It isn't allowed to label the file with smack64label other than requested ac domain or \"none\" value\n");
1249             rpmlog(RPMLOG_DEBUG, "The default ac domain label will be used instead\n");
1250         }
1251 #endif
1252     }   
1253     if ((!label) || (!exec_label)) {
1254         /* no match, use default label of AC domain */
1255         if (mfx->request) { //AC domain is requested in manifest
1256             if (mfx->request->ac_domain) {
1257                 if (!label) label = mfx->request->ac_domain;
1258                 if (!exec_label) exec_label = mfx->request->ac_domain;
1259             } else {
1260                 rpmlog(RPMLOG_DEBUG, "Request for AC domain is empty. Can't identify default file label\n");
1261                 rpmlog(RPMLOG_DEBUG, "File will be labelled with the label \"Isolated\"\n");
1262                 if (!label) label = isolatedLabel;
1263                 if (!exec_label) exec_label = isolatedLabel;
1264             }
1265         } else { // no request of domain
1266             rpmlog(RPMLOG_DEBUG, "The request section is missing. Can't identify default file label\n");
1267             rpmlog(RPMLOG_DEBUG, "File will be labelled with the label \"Isolated\"\n");
1268             if (!label) label = isolatedLabel;
1269             if (!exec_label) exec_label = isolatedLabel;
1270         }
1271     } 
1272     
1273     rpmlog(RPMLOG_DEBUG, "setting SMACK64 %s for %s\n", label, filepath);
1274     if (lsetxattr(filepath, SMACK64, label, strlen(label), 0) < 0 ) {
1275         rpmlog(RPMLOG_ERR, "Failed to set SMACK64 %s for %s: %s\n", 
1276                label, filepath, strerror(errno));
1277     }
1278     if ((is_executable(filepath, cookie)) == 0) {
1279         if ((exec_label) && (strcmp(exec_label, "none") == 0)) {
1280             // do not set SMACK64EXEC
1281             rpmlog(RPMLOG_DEBUG, "not setting SMACK64EXEC for %s as requested in manifest\n", filepath);
1282         } else {
1283             if ((mfx->package_type && (strcmp(mfx->package_type, "application") == 0))
1284                 || (execLabeldefined == 1)) {
1285                 rpmlog(RPMLOG_INFO, "setting SMACK64EXEC %s for %s\n", exec_label, filepath);
1286                 if (lsetxattr(filepath, SMACK64EXEC, exec_label, strlen(exec_label), 0) < 0 ) {
1287                     rpmlog(RPMLOG_ERR, "Failed to set SMACK64EXEC %s for %s: %s\n", 
1288                            exec_label, filepath, strerror(errno));
1289                 }
1290            }
1291        }
1292    }
1293    if (type) { //marked as transmutable
1294        if ((lstat(filepath, &st) != -1) && (S_ISDIR(st.st_mode))) { //check that it is a directory
1295            char at_true[] = "TRUE";
1296            rpmlog(RPMLOG_DEBUG, "setting SMACK64TRANSMUTE %s for %s\n", at_true, filepath);
1297            if (lsetxattr(filepath, SMACK64TRANSMUTE, at_true, strlen(at_true), 0) < 0) {
1298                rpmlog(RPMLOG_ERR, "Failed to set SMACK64TRANSMUTE %s for %s: %s\n", 
1299                       at_true, filepath, strerror(errno));
1300            }
1301        } else {
1302            rpmlog(RPMLOG_DEBUG, "No setting up of transmute attr for a non-directory, path %s\n", filepath);
1303        }
1304    }
1305    return 0;
1306 }
1307
1308 void msmRemoveRules(struct smack_accesses *smack_accesses, manifest_x *mfx, int SmackEnabled)
1309 {
1310     provide_x *provide;
1311     package_x *package;
1312
1313     HASH_FIND(hh, allpackages, mfx->name, strlen(mfx->name), package);
1314     if (!package)
1315         return;
1316
1317     if ((mfx->defines) || (mfx->sw_sources)) {
1318         /* remove smack rule file and rule set from kernel */
1319         rpmlog(RPMLOG_DEBUG, "removing smack rules for %s\n", mfx->name);
1320         msmSetupSmackRules(smack_accesses, mfx->name, SMACK_UNINSTALL, SmackEnabled);
1321     }
1322     for (provide = mfx->provides; provide; provide = provide->prev) {
1323         if (provide->dbuss && !package->older) 
1324             msmRemoveDBusConfig(package, provide->dbuss);
1325     }
1326 }
1327
1328 void msmRemoveConfig(manifest_x *mfx)
1329 {
1330     package_x *package;
1331
1332     HASH_FIND(hh, allpackages, mfx->name, strlen(mfx->name), package);
1333     if (package) {
1334         if (!package->older) {
1335             /* set newer to remove from config list */
1336             package->newer = package;
1337             rpmlog(RPMLOG_DEBUG, "removing package for %s\n", mfx->name);
1338         }
1339     }
1340 }
1341
1342 sw_source_x *msmSWSourceTreeTraversal(sw_source_x *sw_sources, int (func)(sw_source_x *, void *, void*), void *param, void* param2)
1343 {
1344     sw_source_x *sw_source;
1345
1346     if (sw_sources) {
1347         LISTHEAD(sw_sources, sw_source);
1348         /* sw source tree is actually a list ordered into tree traversal path */
1349         for (; sw_source; sw_source = sw_source->next)
1350             if (!sw_source->newer)
1351                 if (!(func)(sw_source, param, param2)) return sw_source;
1352     }
1353     return NULL;
1354 }
1355