optflags: set _FORTIFY_SOURCE for preproc
[platform/upstream/rpm.git] / plugins / msm-plugin.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 <errno.h>
30 #include <sys/types.h>
31 #include <unistd.h>
32 #include <sys/wait.h>
33 #include <sys/prctl.h>
34 #include <sys/capability.h>
35 #include <sys/stat.h>
36
37 #include <rpm/rpmfileutil.h>
38 #include <rpm/rpmpgp.h>
39 #include <rpm/rpmkeyring.h>
40 #include <rpm/rpmdb.h>
41 #include <lib/rpmts_internal.h>
42
43 #include "rpmio/rpmbase64.h"
44 #include "rpmio/rpmlog.h"
45 #include "rpm/rpmfileutil.h"
46
47 #include "msm.h"
48
49 /*hooks that are used in msm plugin */
50
51 rpmPluginHook PLUGIN_HOOKS = \
52         PLUGINHOOK_INIT | \
53         PLUGINHOOK_CLEANUP | \
54         PLUGINHOOK_TSM_PRE | \
55         PLUGINHOOK_TSM_POST | \
56         PLUGINHOOK_PSM_PRE | \
57         PLUGINHOOK_PSM_POST | \
58         PLUGINHOOK_FSM_COMMIT | \
59         PLUGINHOOK_FSM_INIT | \
60         PLUGINHOOK_FILE_CONFLICT | \
61         PLUGINHOOK_VERIFY;
62
63
64 typedef struct fileconflict {
65     const char *path;
66     const char *pkg_name;
67     sw_source_x *sw_source;
68     UT_hash_handle hh;
69 } fileconflict;
70
71 typedef struct packagecontext {
72     char *data;                                 /*!< base64 manifest data */
73     manifest_x *mfx;                            /*!< parsed manifest data */
74     rpmte te;                                   /*!< related te */
75     struct packagecontext *next;                /*!< next in linked list */
76     struct smack_accesses *smack_accesses;      /*!<  handle to smack_accesses */
77 } packagecontext;
78
79 static rpmts ts = NULL;                         /* rpm transaction */
80 static manifest_x *dsp = NULL;                  /* pointer to device security policy file */
81 static packagecontext *context = NULL;
82 static sw_source_x *current = NULL;
83 static packagecontext *contextsHead = NULL;
84 static packagecontext *contextsTail = NULL;
85 static fileconflict *allfileconflicts = NULL;
86 static char* ownSmackLabel = NULL;              /* rpm smack security context */
87 static int SmackEnabled = 0;                    /* indicates if Smack is enabled in kernel or not */
88 static magic_t cookie = NULL;
89 static int package_created = 0;
90
91 /* Support functions */
92
93 /**
94  * Frees the given pointer and sets it to NULL
95  * @param ptr   address of pointer to be freed
96  * @return NULL
97  */
98 static packagecontext *msmFree(packagecontext *ctx)
99 {
100     while (ctx) {
101         packagecontext *next = ctx->next;
102         msmFreePointer((void**)&ctx->data);
103         ctx->mfx = msmFreeManifestXml(ctx->mfx);
104         if (ctx->smack_accesses) smack_accesses_free(ctx->smack_accesses);
105         msmFreePointer((void**)&ctx);
106         ctx = next;
107     }
108     return NULL;
109 }
110
111 /**
112  * Frees the given pointer and sets it to NULL
113  * @param ptr   address of pointer to be freed
114  * @return
115  */
116 void msmFreePointer(void** ptr)
117 {
118     if (*ptr)
119         free(*ptr);
120     *ptr = NULL;
121     return;
122 }
123
124 /**
125  * Creates a new package context
126  * @param te    rpm te struct
127  * @return created package context
128  */
129 static packagecontext *msmNew(rpmte te)
130 {
131     Header h;
132     struct rpmtd_s msm;
133     int count;
134     packagecontext *ctx = NULL;
135     const char *sw_source = NULL;
136
137     rpmtdReset(&msm);
138     
139     h = rpmteHeader(te);
140     if (!h) return NULL;
141     
142     ctx = xcalloc(1, sizeof(*ctx));
143     if (!ctx) {
144         goto exit1;
145     }
146     ctx->te = te;
147
148     if (!headerIsEntry(h, RPMTAG_SECMANIFEST)) {
149         goto exit1;
150     }
151
152     if (!headerGet(h, RPMTAG_SECMANIFEST, &msm, HEADERGET_MINMEM)) {
153         goto exit1;
154     }
155
156     count = rpmtdCount(&msm);
157     if (count != 1) {
158         goto exit2;
159     }
160
161     ctx->data = xstrdup(rpmtdNextString(&msm));
162     rpmlog(RPMLOG_DEBUG, "%s manifest b64 data: %.40s...\n", 
163            rpmteN(ctx->te), ctx->data);
164  exit2:
165     rpmtdFreeData(&msm);
166  exit1:
167     if (rpmteType(ctx->te) == TR_ADDED) {
168         /* Save sw_source name into database, we need it when package */
169         /* is removed because signature verify is not called then. */
170         if (current) sw_source = current->name;
171         if (!sw_source || !headerPutString(h, RPMTAG_SECSWSOURCE, sw_source)) {
172             rpmlog(RPMLOG_ERR, "Failed to save sw source for %s, sw_source: %s\n", 
173                    rpmteN(ctx->te), sw_source);
174             msmFreePointer((void**)&ctx->data);
175             msmFreePointer((void**)&ctx);
176         }
177     }
178     headerFree(h);
179
180     return ctx;
181 }
182
183 /**
184  * Creates and adds a te package context to a context list
185  * @param te    rpm te struct
186  * @return created and added package context
187  */
188 static packagecontext *msmAddTE(rpmte te)
189 {
190     packagecontext *ctx = msmNew(te);
191     if (ctx) {
192         /* add the new policy to the list */
193         if (!contextsHead) {
194             contextsHead = ctx;
195             contextsTail = ctx;
196         } else {
197             if (rpmteType(te) == TR_ADDED) {
198                 /* add to the end of the list */
199                 contextsTail->next = ctx;
200                 contextsTail = ctx;
201             } else {
202                 /* add to the beginning of the list */
203                 ctx->next = contextsHead;
204                 contextsHead = ctx;
205             }
206         }
207     }
208     return ctx;
209 }
210
211 /* -------------------- */
212
213 /* Implementation of hooks */
214 /* Hooks are listed in the call sequence inside rpm code */
215
216 rpmRC PLUGINHOOK_INIT_FUNC(rpmts _ts, const char *name, const char *opts)
217 {
218     ts = _ts;
219
220     if (!ts)
221         return RPMRC_FAIL;
222
223     if (msmLoadDeviceSecurityPolicy(ts->rootDir, &dsp) == RPMRC_FAIL)
224         return RPMRC_FAIL;
225
226     if (!dsp)
227         return RPMRC_FAIL;
228
229     /* smackfs path doesn't need to be prefixed with ts->rootDir 
230        since it is only used for loading rules to kernel and libsmack will load it
231        by itself to the correct path */
232
233     if (smack_smackfs_path() == NULL) {
234         rpmlog(RPMLOG_INFO, "Smackfs isn't mounted at %s. Going to the image build mode. \n", smack_smackfs_path());
235         ownSmackLabel = strdup("_");
236         SmackEnabled = 0;
237     } else {
238         /* check its own security context and store it for the case when packages without manifest will be installed */
239         int res = smack_new_label_from_self(&ownSmackLabel);
240         SmackEnabled = 1;
241         if (res < 0) {
242             rpmlog(RPMLOG_ERR, "Failed to obtain rpm security context\n");
243             return RPMRC_FAIL;
244         }
245     }
246
247     rpmlog(RPMLOG_DEBUG, "rpm security context: %s\n", ownSmackLabel);
248
249     if (msmSetupSmackRulesDir(ts->rootDir) == RPMRC_FAIL)
250         return RPMRC_FAIL;
251
252     cookie = magic_open(0); 
253     if (!cookie)
254         return RPMRC_FAIL; 
255
256     if (magic_load(cookie, NULL) != 0) {
257         rpmlog(RPMLOG_ERR, "cannot load magic database - %s\n", magic_error(cookie));   
258         magic_close(cookie);
259         cookie = NULL;
260         return RPMRC_FAIL;
261     }
262
263     return RPMRC_OK;
264 }
265
266 rpmRC PLUGINHOOK_FILE_CONFLICT_FUNC(rpmts ts, char* path,
267                                       Header oldHeader, rpmfi oldFi, 
268                                       int rpmrc)
269 {
270     fileconflict *fc;
271     if ((!path) || (!dsp))
272         return rpmrc;
273
274     rpmlog(RPMLOG_DEBUG, "FILE_CONFLICT_FUNC hook path %s\n",path);
275
276     /* uncomment this code if you wish that plugin obeys --replacefiles rpm flag
277     if (rpmtsFilterFlags(ts) & RPMPROB_FILTER_REPLACEOLDFILES) {
278         return rpmrc;
279     } */
280
281     const char *sw_source_name = headerGetString(oldHeader, RPMTAG_SECSWSOURCE);
282     const char *pkg_name = headerGetString(oldHeader, RPMTAG_NAME);
283     if (!sw_source_name || !pkg_name) {
284         return rpmrc; /* no sw source or package name - abnormal state */
285     }
286
287     sw_source_x *sw_source = msmSWSourceTreeTraversal(dsp->sw_sources, msmFindSWSourceByName, (void *)sw_source_name, NULL);
288     if (!sw_source)
289         return rpmrc; /* no old sw_source - abnormal state */
290
291     HASH_FIND(hh, allfileconflicts, path, strlen(path), fc);
292     if (!fc) {
293         /* Add new file conflict into hash */
294         fc = xcalloc(1, sizeof(*fc));
295         if (!fc) return RPMRC_FAIL;
296         fc->path = path;
297         fc->sw_source = sw_source;
298         fc->pkg_name = strdup(pkg_name);
299         if (!fc->pkg_name) return RPMRC_FAIL;
300         HASH_ADD_KEYPTR(hh, allfileconflicts, path, strlen(path), fc);
301     } else {
302         /* Many packages have installed the same file */
303         if (strcmp(sw_source->rankkey, fc->sw_source->rankkey) <= 0) {
304             /* Change sw source to the higher ranked one */
305             fc->sw_source = sw_source;
306         }
307         msmFreePointer((void**)&path);
308     }
309
310     return rpmrc;
311 }
312
313 rpmRC PLUGINHOOK_TSM_PRE_FUNC(rpmts ts)
314 {
315     if (!dsp) {
316         rpmlog(RPMLOG_ERR, "Device security policy is missing. Unable to proceed\n");
317         return RPMRC_FAIL;
318     }
319
320     return RPMRC_OK;
321 }
322
323 rpmRC PLUGINHOOK_VERIFY_FUNC(rpmKeyring keyring, rpmtd sigtd, pgpDigParams sig, DIGEST_CTX ctx, int rpmrc)
324 {
325     current = NULL;
326
327     if (!dsp) {
328         rpmlog(RPMLOG_ERR, "No device policy found\n");
329         return rpmrc;
330     } 
331
332     if (rpmrc == RPMRC_NOKEY) {
333         /* No key, revert to unknown sw source. */
334         rpmlog(RPMLOG_ERR, "no key for signature, cannot search sw source\n");
335         goto exit;
336     }
337     if (rpmrc) {
338         /* RPM failed to verify signature */
339         rpmlog(RPMLOG_ERR, "Invalid signature, cannot search sw source\n");
340         goto exit;
341     }
342     if (sigtd->tag != RPMSIGTAG_RSA) {
343         /* Not RSA, revert to unknown sw source. */
344         rpmlog(RPMLOG_DEBUG, "not an RSA signature, cannot search sw source\n");
345         goto exit;
346     }
347
348     current = msmSWSourceTreeTraversal(dsp->sw_sources, msmFindSWSourceBySignature, sig, ctx);
349     if (current)
350         rpmlog(RPMLOG_DEBUG, "signature matches sw source %s\n", current->name);
351     else
352         rpmlog(RPMLOG_DEBUG, "valid signature but no matching sw source\n");
353
354  exit:
355     if (!current) {
356         current = msmSWSourceTreeTraversal(dsp->sw_sources, msmFindSWSourceByName, (void *)"_default_", NULL);
357         if (current) {
358             rpmlog(RPMLOG_DEBUG, "using _default_ sw source\n");
359         } else { // for now in case default sw source isn't there yet, allow to think that it is coming from root
360             current = msmSWSourceTreeTraversal(dsp->sw_sources, msmFindSWSourceByName, (void *)"root", NULL);
361             if (current)
362                 rpmlog(RPMLOG_DEBUG, "using _root_ sw source now for testing\n");
363         }
364     }
365
366     return rpmrc;
367 }
368
369 rpmRC PLUGINHOOK_PSM_PRE_FUNC(rpmte te)
370 {
371     packagecontext *ctx = NULL;
372     manifest_x *mfx = NULL;
373     char *xml = NULL;
374     size_t xmllen;
375     rpmRC rc = RPMRC_OK;
376     int ret = 0;
377
378     package_created = 0;
379
380     if (!dsp) {
381         rpmlog(RPMLOG_ERR, "Device security policy is missing. Unable to proceed\n");
382         return RPMRC_FAIL;
383     }
384
385     if (!current) {
386         /* this means that verify hook has not been called */
387         current = msmSWSourceTreeTraversal(dsp->sw_sources, msmFindSWSourceByName, (void *)"_default_", NULL);
388         if (current) {
389             rpmlog(RPMLOG_DEBUG, "using _default_ sw source\n");
390         } else { 
391             rpmlog(RPMLOG_ERR, "Default source isn't avaliable. Package source can't be determined. Abort installation\n");
392             goto fail;
393         }
394     }
395
396     ctx = msmAddTE(te);
397     if (!ctx) {
398         rpmlog(RPMLOG_ERR, "Failed to create security context for %s\n", rpmteNEVRA(te));
399         goto fail;
400     }
401
402     if (rpmteType(ctx->te) == TR_REMOVED) {
403         /* Verify hook is not called before remove, */
404         /* so get the sw_source name from package header */
405         Header h = rpmteHeader(te);
406         if (h) {
407             const char *name = headerGetString(h, RPMTAG_SECSWSOURCE);
408             if (name) { 
409                 current = msmSWSourceTreeTraversal(dsp->sw_sources, msmFindSWSourceByName, (void *)name, NULL);
410                 rpmlog(RPMLOG_DEBUG, "removing %s from sw source %s\n",
411                        rpmteN(ctx->te), name);
412             }
413             headerFree(h);
414         }
415         package_created = 1;
416         /* if (!current) {
417             rpmlog(RPMLOG_INFO, "no sw source for removing %s\n", rpmteN(ctx->te));
418             goto exit;
419         }*/
420     }
421
422     if (!ctx->data) {
423         rpmlog(RPMLOG_INFO, "No manifest in this package. Creating default one\n");
424
425         /* create default manifest manually. Make the package to belong to the domain where rpm is running */
426
427         mfx = calloc(1, sizeof(manifest_x));
428         if (!mfx)  goto fail;
429         mfx->sw_source = current;
430         mfx->name = strdup(rpmteN(ctx->te));
431         mfx->request = calloc(1, sizeof(request_x));
432         if (!mfx->request) {
433             msmFreePointer((void**)&mfx->name);
434             msmFreePointer((void**)&mfx);
435             goto fail;
436         }
437         mfx->request->ac_domain = strdup(ownSmackLabel);
438         rpmlog(RPMLOG_DEBUG, "Done with manifest creation\n");
439     } else {
440         if (rpmBase64Decode(ctx->data, (void **) &xml, &xmllen) != 0) {
441             rpmlog(RPMLOG_ERR, "Failed to decode manifest for %s\n",
442                    rpmteN(ctx->te));
443             goto fail;
444         }
445
446         rpmlog(RPMLOG_DEBUG, "parsing %s manifest: \n%s", rpmteN(ctx->te), xml);
447         mfx = msmProcessManifestXml(xml, xmllen, current, rpmteN(ctx->te));
448
449         if (!mfx) {
450             rpmlog(RPMLOG_ERR, "Failed to parse manifest for %s\n",
451             rpmteN(ctx->te));
452             goto fail;
453         }
454     }
455
456     ctx->mfx = mfx;
457
458     int res = smack_accesses_new(&(ctx->smack_accesses)); 
459     if (res != 0) {
460         rpmlog(RPMLOG_ERR, "Failed to create smack access set\n");
461         goto fail;
462     }
463
464     if (rpmteType(ctx->te) == TR_ADDED) {
465         rpmlog(RPMLOG_DEBUG, "Installing the package\n");
466         package_x *package = NULL;
467
468         /*if (rootSWSource) {
469             // this is the first package that brings the policy
470             package = msmCreatePackage(mfx->name, mfx->sw_sources, 
471                                             mfx->provides, NULL);
472         } else */
473         if (mfx->sw_source) {
474             /* all packages must have sw_source */
475             package = msmCreatePackage(mfx->name, mfx->sw_source, 
476                                             mfx->provides, NULL);
477         } else {
478             rpmlog(RPMLOG_ERR, "Package doesn't have a sw source. Abnormal situation. Abort.\n");
479             goto fail;
480         }
481
482         if (!package) {
483             rpmlog(RPMLOG_ERR, "Package could not be created. \n");
484             goto fail; 
485         }
486  
487         mfx->provides = NULL; /* owned by package now */
488
489         if (!package->sw_source) { /* this must never happen */
490             rpmlog(RPMLOG_ERR, "Install failed. Check that configuration has at least root sw source installed.\n");
491             msmFreePackage(package);
492             package = NULL;
493             goto fail;
494         }
495
496         rpmlog(RPMLOG_DEBUG, "adding %s manifest data to system, package_name %s\n", 
497                rpmteN(ctx->te), package->name);
498
499         if (msmSetupPackages(ctx->smack_accesses, package, package->sw_source)) {
500             rpmlog(RPMLOG_ERR, "Package setup failed for %s\n", rpmteN(ctx->te) );
501             msmFreePackage(package);
502             package = NULL;
503             goto fail;
504         }
505
506         package_created = 1;
507         
508         /*if (rootSWSource) {
509             // current configuration becomes dsp
510             dsp = ctx->mfx;
511         } */
512
513         rpmlog(RPMLOG_DEBUG, "Starting the security setup...\n");
514         unsigned int smackLabel = 0;
515
516         /*if (rootSWSource || ctx->mfx->sw_source) {*/
517         if (ctx->mfx->sw_source) {
518             if (ctx->mfx->sw_sources) {
519                 smackLabel = 1; /* setting this one on since this manifest doesn't have any define/request section */
520                 ret = msmSetupSWSources(ctx->smack_accesses, ctx->mfx, ts);
521                 if (ret) {
522                     rpmlog(RPMLOG_ERR, "SW source setup failed for %s\n",
523                             rpmteN(ctx->te));
524                     goto fail;
525                 }
526             }           
527             if (ctx->mfx->defines) {
528                 ret = msmSetupDefines(ctx->smack_accesses, ctx->mfx);
529                 if (ret) {
530                     rpmlog(RPMLOG_ERR, "AC domain setup failed for %s\n",
531                            rpmteN(ctx->te));
532                     goto fail;
533                 } else {
534                     smackLabel = 1;
535                 }
536             }           
537             if (ctx->mfx->request) {    
538                 if (ctx->mfx->request->ac_domain)
539                     smackLabel = 1;
540                 ret = msmSetupRequests(ctx->mfx);
541                 if (ret) {
542                     rpmlog(RPMLOG_ERR, "Request setup failed for %s\n",
543                            rpmteN(ctx->te));
544                     goto fail;
545                 }
546             }
547             if (package->provides) {
548                 ret = msmSetupDBusPolicies(package, ctx->mfx);
549                 if (ret) {
550                     rpmlog(RPMLOG_ERR, "Setting up dbus policies for %s failed\n",
551                            rpmteN(ctx->te));
552                     goto fail;
553                 }
554             }
555             if (ctx->smack_accesses) {
556                 ret = msmSetupSmackRules(ctx->smack_accesses, ctx->mfx->name, 0, SmackEnabled);
557                 smack_accesses_free(ctx->smack_accesses);
558                 ctx->smack_accesses = NULL;
559                 if (ret) {
560                     rpmlog(RPMLOG_ERR, "Setting up smack rules for %s failed\n",
561                            rpmteN(ctx->te));
562                     goto fail; 
563                 }
564             }
565
566             /* last check is needed in order to catch in advance 
567                the situation when no ac domain defined or requested */
568             if (smackLabel == 0) {
569                 rpmlog(RPMLOG_ERR, "No ac domain defined or requested for package %s. Abort.\n",   rpmteN(ctx->te));
570                 goto fail;
571             }
572         }
573
574     } else if (rpmteDependsOn(ctx->te)) { /* TR_REMOVED */
575         package_created = 1;
576         rpmlog(RPMLOG_DEBUG, "upgrading package %s by %s\n",
577                rpmteNEVR(ctx->te), rpmteNEVR(rpmteDependsOn(ctx->te)));
578     } else if (mfx->sw_sources) {
579         rpmlog(RPMLOG_ERR, "Cannot remove sw source package %s\n",
580                rpmteN(ctx->te));
581         goto fail;
582     }
583
584     rpmlog(RPMLOG_DEBUG, "Finished with pre psm hook \n");
585
586     goto exit;
587
588  fail: /* error, cancel the rpm operation */
589     rc = RPMRC_FAIL;
590
591  exit: /* success, continue rpm operation */
592     context = ctx;
593     msmFreePointer((void**)&xml);
594
595     return rc;
596 }
597
598 rpmRC PLUGINHOOK_FSM_INIT_FUNC(const char* path, mode_t mode)
599 {
600     /* Check if there any conflicts that prevent file being written to the disk */
601
602     fileconflict *fc;
603     packagecontext *ctx = context;
604     char *cleanedPath = NULL, *dupPath = NULL;
605
606     rpmlog(RPMLOG_DEBUG, "Started with FSM_INIT_FUNC hook for file: %s\n", path);
607
608     if (!ctx) return RPMRC_FAIL; 
609     if (!path) return RPMRC_FAIL; 
610
611     dupPath = strdup(path);
612     cleanedPath = strchr(dupPath, ';');
613     if (cleanedPath)
614         *cleanedPath = '\0';
615
616     HASH_FIND(hh, allfileconflicts, dupPath, strlen(dupPath), fc);
617     msmFreePointer((void**)&dupPath);
618
619     if (fc) {
620         //rpmlog(RPMLOG_DEBUG, "rpmteN(ctx->te) %s fc->pkg_name: %s\n", rpmteN(ctx->te), fc->pkg_name);
621         /* There is a conflict, see if we are not allowed to overwrite */
622         if ((!current || 
623            (strcmp(current->rankkey, fc->sw_source->rankkey) >= 0)) &&
624            (strcmp(rpmteN(ctx->te), fc->pkg_name))) {
625             rpmlog(RPMLOG_ERR, "%s has file conflict in %s from sw source %s\n",
626                    rpmteN(ctx->te), fc->path, fc->sw_source->name);
627             return RPMRC_FAIL;
628         }
629         rpmlog(RPMLOG_DEBUG, "%s from %s overwrites %s from %s\n",
630                rpmteN(ctx->te), current->name, fc->path, fc->sw_source->name);
631     }
632
633     rpmlog(RPMLOG_DEBUG, "Finished with FSM_INIT_FUNC hook for file: %s\n", path);
634
635     return RPMRC_OK;
636 }
637
638 rpmRC PLUGINHOOK_FSM_COMMIT_FUNC(const char* path, mode_t mode, int type)
639 {
640     /* Setup xattrs for the given path */
641
642     packagecontext *ctx = context;
643
644     rpmlog(RPMLOG_DEBUG, "Started with FSM_COMMIT_FUNC hook for file: %s\n", path);
645
646     if (!ctx) return RPMRC_FAIL;
647     if (!path) return RPMRC_FAIL;
648
649     /* the type option is ignored for now */
650
651     if (ctx->mfx) {
652         file_x *file = xcalloc(1, sizeof(*file));
653         if (file) {
654             file->path = strndup(path, strlen(path) + 1);
655             LISTADD(ctx->mfx->files, file);
656             if (rpmteType(ctx->te) == TR_ADDED) {
657                 if (msmSetFileXAttributes(ctx->mfx, file->path, cookie) < 0) {
658                     rpmlog(RPMLOG_ERR, "Setting of extended attributes failed for file %s from package %s\n",
659                            file->path, rpmteN(ctx->te));
660                     return RPMRC_FAIL;
661                 }
662             } 
663
664         } else
665             return RPMRC_FAIL;
666     } else {
667         rpmlog(RPMLOG_ERR, "Manifest is missing while it should be present for the package %s\n",
668                rpmteN(ctx->te));
669         return RPMRC_FAIL;
670     }
671
672     rpmlog(RPMLOG_DEBUG, "Finished with FSM_COMMIT_FUNC hook for file: %s\n", path);
673     return RPMRC_OK;
674 }
675
676 rpmRC PLUGINHOOK_PSM_POST_FUNC(rpmte te, int rpmrc)
677 {
678
679     packagecontext *ctx = context;
680     if (!ctx) return RPMRC_FAIL;
681
682     if (!package_created) {
683         /* failure in rpm pre psm hook, rollback */
684         return RPMRC_FAIL;
685     }
686
687     if (rpmrc) {
688         /* failure in rpm psm, rollback */
689         if (rpmteType(ctx->te) == TR_ADDED)
690             msmCancelPackage(ctx->mfx->name);
691         return RPMRC_FAIL;
692     }
693
694     if (!ctx->mfx){
695         rpmlog(RPMLOG_ERR, "Manifest is missing while it should be present for the package %s\n",
696                rpmteN(ctx->te));
697         return RPMRC_FAIL;
698     }
699
700     /* if (rootSWSource) {
701         // current configuration becomes dsp
702         dsp = context->mfx;
703     } */
704
705     if (rpmteType(ctx->te) == TR_REMOVED) {
706         if (ctx->mfx->sw_source) {
707             if (rpmteDependsOn(ctx->te)) {
708                 rpmlog(RPMLOG_DEBUG, "upgrading %s manifest data\n", 
709                        rpmteN(ctx->te));
710             } else {
711                 rpmlog(RPMLOG_DEBUG, "removing %s manifest data\n", 
712                        rpmteN(ctx->te));
713                 if (ctx->mfx->defines || ctx->mfx->provides || ctx->mfx->sw_sources) {
714                     msmRemoveRules(ctx->smack_accesses, ctx->mfx, SmackEnabled);
715                 }           
716                 msmRemoveConfig(ctx->mfx);
717             }
718         }
719     }
720
721     return rpmrc;
722 }
723
724 rpmRC PLUGINHOOK_TSM_POST_FUNC(rpmts ts, int rpmrc)
725 {
726     packagecontext *ctx = context;
727     msmFreeInternalHashes(); // free hash structures first
728
729     if (dsp) {
730         msmSaveDeviceSecPolicyXml(dsp, ts->rootDir);
731         /* if (!rootSWSource) dsp = msmFreeManifestXml(dsp); */
732         dsp = msmFreeManifestXml(dsp);
733
734     }
735     if (!ctx) return RPMRC_FAIL;
736     return RPMRC_OK;
737 }
738
739 rpmRC PLUGINHOOK_CLEANUP_FUNC(void)
740 {
741
742     ts = NULL;
743
744     contextsHead = contextsTail = msmFree(contextsHead);
745     contextsHead = contextsTail = NULL;
746
747     if (allfileconflicts) {
748         fileconflict *fc, *temp;
749         HASH_ITER(hh, allfileconflicts, fc, temp) {
750             HASH_DELETE(hh, allfileconflicts, fc);
751             msmFreePointer((void**)&fc->path);
752             msmFreePointer((void**)&fc->pkg_name);
753             msmFreePointer((void**)&fc);
754         }
755     }
756
757     msmFreePointer((void**)&ownSmackLabel);
758     if (cookie) magic_close(cookie);
759
760     return RPMRC_OK;
761 }