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