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