Fix Werrors with GCC-14.1.0
[platform/upstream/rpm.git] / plugins / msmmanifest.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 <stdarg.h>
32 #include <string.h>
33 #include <sys/types.h>
34 #include <sys/stat.h>
35 #include <unistd.h>
36
37 #include <libxml/xmlreader.h>
38 #include <sys/capability.h>
39
40 #include "msm.h"
41
42 #include "rpmio/rpmbase64.h"
43 #include "rpmio/rpmlog.h"
44
45 /* We'll support only the basic set of characters */
46 #define ASCII(s) (const char *)s
47 #define XMLCHAR(s) (const xmlChar *)s
48
49 static int msmVerifyAccessType(const char* type)
50 {
51     int res = 0, idx = 0;
52
53     if (type) {
54         if (strnlen(type, SMACK_ACCESS_TYPE_LENGTH + 1) >
55             SMACK_ACCESS_TYPE_LENGTH) {
56             rpmlog(RPMLOG_ERR, "Lenght of the access type is bigger than allowed value: %s\n", type);
57             return -1;
58         }
59         while ( type[idx] != '\0' ){
60             if ((type[idx] !='a') && (type[idx]!='r') && (type[idx]!='w') &&
61                 (type[idx]!='x') && (type[idx]!='t') && (type[idx]!='l') && (type[idx] !='-')) {
62                 rpmlog(RPMLOG_ERR, "Not allowed character in access type: %s\n", type);
63                 res = -1;
64                 break;
65             }
66             idx++;
67         }
68     } else return -1; 
69
70     return res;
71 }
72
73 static int msmVerifySmackLabel(const char* label)
74 {
75     int res = 0, idx = 0;
76
77     if (label) {
78         if (strlen(ASCII(label)) > SMACK_LABEL_LENGTH) { //smack limitation on lenght
79             rpmlog(RPMLOG_ERR, "Domain or label name  %s lenght is longer than defined SMACK_LABEL_LENGTH\n", label);
80             return -1; 
81         }
82         if (strlen(ASCII(label)) == 0){
83             rpmlog(RPMLOG_ERR, "An attempt to define an empty domain or label name\n");
84             return -1; 
85         }
86         if (label[0] == '-') {
87             rpmlog(RPMLOG_ERR, "Dash is not allowed as first character in smack label: %s\n", label);
88             return -1;
89         }
90         while ( label[idx] != '\0' ){
91             if ((label[idx] =='\"') || (label[idx] =='\'') || (label[idx] =='/') ||
92                 (label[idx] =='\\') || (label[idx] > '~') || (label[idx] <= ' ')) {
93                 rpmlog(RPMLOG_ERR, "Not allowed character in smack label: %s, position: %d \n", label, idx);
94                 res = -1;
95                 break;
96             }
97             idx++;
98         }
99     } else return -1; 
100
101     return res;
102 }
103
104 static int msmVerifyLabelPrefix(const char* sub_label, const char* domain_name) 
105 {
106     char *tmp = NULL;
107     char sep[]= "::";
108
109     tmp = calloc(strlen(domain_name) + 3, sizeof (const char));
110     if (!tmp) 
111         return -1;
112
113     strncpy(tmp, domain_name, strlen(domain_name));
114     strncpy(tmp + strlen(domain_name), sep, 2);
115
116     if (strstr(ASCII(sub_label), tmp) != ASCII(sub_label)) { //sub label name should be prefixed by domain name and "::"
117         rpmlog(RPMLOG_ERR, "Label name %s isn't prefixed by domain name %s\n", ASCII(sub_label), domain_name);
118         msmFreePointer((void**)&tmp);
119         return -1;
120     } 
121
122     msmFreePointer((void**)&tmp);
123     return 0;
124 }
125
126 static int msmNextChildElement(xmlTextReaderPtr reader, int depth) 
127 {
128     int ret = xmlTextReaderRead(reader);
129     int cur = xmlTextReaderDepth(reader);
130     while (ret == 1) {
131         /* rpmlog(RPMLOG_DEBUG, "node %s %d\n", 
132            ASCII(xmlTextReaderConstName(reader)), 
133            xmlTextReaderDepth(reader));
134         */
135         switch (xmlTextReaderNodeType(reader)) {
136         case XML_READER_TYPE_ELEMENT:
137         case XML_READER_TYPE_TEXT:
138             if (cur == depth+1) 
139                 return 1;
140             break;
141         case XML_READER_TYPE_END_ELEMENT:
142             if (cur == depth) 
143                 return 0;
144             break;
145         default:
146             if (cur <= depth)
147                 return 0;
148             break;
149         }
150         ret = xmlTextReaderRead(reader);
151         cur = xmlTextReaderDepth(reader);
152     }
153     return ret;
154 }
155
156 static ac_domain_x *msmFreeACDomain(ac_domain_x *ac_domain)
157 {
158     if (ac_domain) {
159         ac_domain_x *prev = ac_domain->prev;
160         msmFreePointer((void**)&ac_domain->name);
161         msmFreePointer((void**)&ac_domain->type);
162         msmFreePointer((void**)&ac_domain->match);
163         msmFreePointer((void**)&ac_domain->plist);
164         msmFreePointer((void**)&ac_domain);
165         return prev;
166     } else return NULL;
167 }
168
169 static annotation_x *msmProcessAnnotation(xmlTextReaderPtr reader)
170 {
171     const xmlChar *name, *value;
172
173     name = xmlTextReaderGetAttribute(reader, XMLCHAR("name"));
174     value = xmlTextReaderGetAttribute(reader, XMLCHAR("value"));
175     rpmlog(RPMLOG_DEBUG, "annotation %s %s\n", ASCII(name), ASCII(value));
176
177     if (name && value) {
178         annotation_x *annotation = calloc(1, sizeof(annotation_x));
179         if (annotation) {
180             annotation->name = ASCII(name);
181             annotation->value = ASCII(value);
182             return annotation;
183         }
184     }
185     msmFreePointer((void**)&name);
186     msmFreePointer((void**)&value);
187     return NULL;
188 }
189
190 static int msmProcessMember(xmlTextReaderPtr reader, member_x *member) 
191 {
192     const xmlChar *node, *name;
193     int ret, depth;
194
195     name = xmlTextReaderGetAttribute(reader, XMLCHAR("name"));
196     rpmlog(RPMLOG_DEBUG, "member %s\n", ASCII(name));
197     member->name = ASCII(name);
198
199     if (!name) return -1;
200
201     depth = xmlTextReaderDepth(reader);
202     while ((ret = msmNextChildElement(reader, depth))) {
203         node = xmlTextReaderConstName(reader);
204         if (!node) return -1;
205
206         if (!strcmp(ASCII(node), "annotation")) {
207             annotation_x *annotation = msmProcessAnnotation(reader);
208             if (annotation) {
209                 member->annotation = annotation;
210             } else return -1;
211         } else return -1;
212
213         if (ret < 0) return -1;
214     }
215     return ret;
216 }
217
218 static int msmProcessInterface(xmlTextReaderPtr reader, interface_x *interface) 
219 {
220     const xmlChar *node, *name;
221     int ret, depth;
222
223     name = xmlTextReaderGetAttribute(reader, XMLCHAR("name"));
224     rpmlog(RPMLOG_DEBUG, "interface %s\n", ASCII(name));
225     interface->name = ASCII(name);
226
227     if (!name) return -1;
228
229     depth = xmlTextReaderDepth(reader);
230     while ((ret = msmNextChildElement(reader, depth))) {
231         node = xmlTextReaderConstName(reader);
232         if (!node) return -1;
233
234         if (!strcmp(ASCII(node), "method")) {
235             member_x *member = calloc(1, sizeof(member_x));
236             if (member) {
237                 member->type = DBUS_METHOD;
238                 ret = msmProcessMember(reader, member);
239                 LISTADD(interface->members, member);
240             } else return -1;
241         } else if (!strcmp(ASCII(node), "signal")) {
242             member_x *member = calloc(1, sizeof(member_x));
243             if (member) {
244                 member->type = DBUS_SIGNAL;
245                 ret = msmProcessMember(reader, member);
246                 LISTADD(interface->members, member);
247             } else return -1;
248         } else if (!strcmp(ASCII(node), "annotation")) {
249             annotation_x *annotation = msmProcessAnnotation(reader);
250             if (annotation) {
251                 interface->annotation = annotation;
252             } else return -1;
253         } else return -1;
254
255         if (ret < 0) return -1;
256     }
257     return ret;
258 }
259
260 static int msmProcessNode(xmlTextReaderPtr reader, node_x *nodex) 
261 {
262     const xmlChar *node, *name;
263     int ret, depth;
264
265     name = xmlTextReaderGetAttribute(reader, XMLCHAR("name"));
266     rpmlog(RPMLOG_DEBUG, "node %s\n", ASCII(name));
267     nodex->name = ASCII(name);
268
269     if (!name) return -1;
270
271     depth = xmlTextReaderDepth(reader);
272     while ((ret = msmNextChildElement(reader, depth))) {
273         node = xmlTextReaderConstName(reader);
274         if (!node) return -1;
275
276         if (!strcmp(ASCII(node), "interface")) {
277             interface_x *interface = calloc(1, sizeof(interface_x));
278             if (interface) {
279                 ret = msmProcessInterface(reader, interface);
280                 LISTADD(nodex->interfaces, interface);
281             } else return -1;
282         } else if (!strcmp(ASCII(node), "method")) {
283             member_x *member = calloc(1, sizeof(member_x));
284             if (member) {
285                 member->type = DBUS_METHOD;
286                 ret = msmProcessMember(reader, member);
287                 LISTADD(nodex->members, member);
288             } else return -1;
289         } else if (!strcmp(ASCII(node), "signal")) {
290             member_x *member = calloc(1, sizeof(member_x));
291             if (member) {
292                 member->type = DBUS_SIGNAL;
293                 ret = msmProcessMember(reader, member);
294                 LISTADD(nodex->members, member);
295             } else return -1;
296         } else if (!strcmp(ASCII(node), "annotation")) {
297             annotation_x *annotation = msmProcessAnnotation(reader);
298             if (annotation) {
299                 nodex->annotation = annotation;
300             } else return -1;
301         } else return -1;
302
303         if (ret < 0) return -1;
304     }
305     return ret;
306 }
307
308 static int msmProcessDBus(xmlTextReaderPtr reader, dbus_x *dbus) 
309 {
310     const xmlChar *node, *name, *own, *bus;
311     int ret, depth;
312
313     name = xmlTextReaderGetAttribute(reader, XMLCHAR("name"));
314     own = xmlTextReaderGetAttribute(reader, XMLCHAR("own"));
315     bus = xmlTextReaderGetAttribute(reader, XMLCHAR("bus"));
316     rpmlog(RPMLOG_DEBUG, "dbus %s %s %s\n", ASCII(name), ASCII(own), ASCII(bus));
317     dbus->name = ASCII(name);
318     dbus->own = ASCII(own);
319     dbus->bus = ASCII(bus);    
320
321     if (!name || !bus) return -1;
322     if (strcmp(dbus->bus, "session") && strcmp(dbus->bus, "system"))
323         return -1;
324
325     depth = xmlTextReaderDepth(reader);
326     while ((ret = msmNextChildElement(reader, depth))) {
327         node = xmlTextReaderConstName(reader);
328         if (!node) return -1;
329
330         if (!strcmp(ASCII(node), "node")) {
331             node_x *nodex = calloc(1, sizeof(node_x));
332             if (nodex) {
333                 ret = msmProcessNode(reader, nodex);
334                 LISTADD(dbus->nodes, nodex);
335             } else return -1;
336         } else if (!strcmp(ASCII(node), "annotation")) {
337             annotation_x *annotation = msmProcessAnnotation(reader);
338             if (annotation) {
339                 dbus->annotation = annotation;
340             } else return -1;
341         } else return -1;
342
343         if (ret < 0) return -1;
344     }
345     return ret;
346 }
347
348 static ac_domain_x *msmProcessACDomain(xmlTextReaderPtr reader, sw_source_x *sw_source, const char* pkg_name)
349 {
350     const xmlChar *name, *match, *policy, *plist;
351
352     name = xmlTextReaderGetAttribute(reader, XMLCHAR("name"));
353     match = xmlTextReaderGetAttribute(reader, XMLCHAR("match"));
354     policy = xmlTextReaderGetAttribute(reader, XMLCHAR("policy"));
355     plist = xmlTextReaderGetAttribute(reader, XMLCHAR("plist"));
356     rpmlog(RPMLOG_DEBUG, "ac_domain %s match %s policy %s plist %s\n", ASCII(name), ASCII(match), ASCII(policy), ASCII(plist));
357
358     if (!((!name && !match) || (name && match))) {
359         ac_domain_x *ac_domain = calloc(1, sizeof(ac_domain_x));
360         if (ac_domain) {
361             ac_domain->name = ASCII(name);
362             ac_domain->match = ASCII(match);
363             ac_domain->type = ASCII(policy);
364             ac_domain->plist = ASCII(plist);
365             ac_domain->sw_source = sw_source;
366             ac_domain->pkg_name = pkg_name;     
367             return ac_domain;
368         }
369     }
370     rpmlog(RPMLOG_ERR, "Mandatory argument is missing for ac domain definition\n");
371     rpmlog(RPMLOG_ERR, "ac_domain %s match %s policy %s plist %s\n", ASCII(name), ASCII(match), ASCII(policy), ASCII(plist));
372     msmFreePointer((void**)&name);
373     msmFreePointer((void**)&match);
374     msmFreePointer((void**)&policy);
375     msmFreePointer((void**)&plist);
376     return NULL;
377 }
378
379 static filesystem_x *msmProcessFilesystem(xmlTextReaderPtr reader)
380 {
381     const xmlChar *path, *label, *type, *exec_label;
382
383     path = xmlTextReaderGetAttribute(reader, XMLCHAR("path"));
384     label = xmlTextReaderGetAttribute(reader, XMLCHAR("label"));
385     exec_label = xmlTextReaderGetAttribute(reader, XMLCHAR("exec_label"));
386     type = xmlTextReaderGetAttribute(reader, XMLCHAR("type"));
387
388     rpmlog(RPMLOG_DEBUG, "filesystem path %s label %s exec label %s type %s\n", 
389            ASCII(path), ASCII(label), ASCII(exec_label), ASCII(type));
390
391    if (path && (label || exec_label)) {
392         if ((label) && (msmVerifySmackLabel(ASCII(label)) < 0)) {
393             goto fail;
394         }
395         if ((exec_label) && (msmVerifySmackLabel(ASCII(exec_label)) < 0)) {
396             goto fail;
397         }
398
399         filesystem_x *filesystem = calloc(1, sizeof(filesystem_x));
400         if (filesystem) {
401             filesystem->path = ASCII(path);
402             filesystem->label = ASCII(label);
403             filesystem->exec_label = ASCII(exec_label);
404             filesystem->type = ASCII(type);
405             return filesystem;
406         }
407
408     } else {
409         rpmlog(RPMLOG_ERR, "Mandatory argument is missing for filesystem assign request\n");
410         rpmlog(RPMLOG_ERR, "filesystem path %s label %s exec label %s\n", 
411                ASCII(path), ASCII(label), ASCII(exec_label));
412     }
413
414 fail:
415     msmFreePointer((void**)&path);
416     msmFreePointer((void**)&label);
417     msmFreePointer((void**)&exec_label);
418     msmFreePointer((void**)&type);
419     return NULL;
420 }
421
422 static int msmProcessProvide(xmlTextReaderPtr reader, provide_x *provide, sw_source_x *current, manifest_x *mfx, const char* pkg_name)
423 {
424     const xmlChar *node, *name, *origin;
425     int ret, depth;
426
427     name = xmlTextReaderGetAttribute(reader, XMLCHAR("name"));
428     rpmlog(RPMLOG_DEBUG, "assign %s\n", ASCII(name));
429     provide->name = ASCII(name);
430
431     if (provide->name && 
432        (strcmp(provide->name, "_system_") || mfx->sw_source->parent))
433         return -1; /* only _system_ is accepted from root sw source */
434
435     depth = xmlTextReaderDepth(reader);
436     while ((ret = msmNextChildElement(reader, depth))) {
437         node = xmlTextReaderConstName(reader);
438         if (!node) return -1;
439
440         if (!strcmp(ASCII(node), "dbus")) {
441             dbus_x *dbus = calloc(1, sizeof(dbus_x));
442             if (dbus) {
443                 ret = msmProcessDBus(reader, dbus);
444                 LISTADD(provide->dbuss, dbus);
445             } else return -1;
446         } else if (!strcmp(ASCII(node), "ac_domain")) {
447             ac_domain_x *ac_domain = msmProcessACDomain(reader, current, pkg_name);
448             if (ac_domain) {
449                 const char *name = ac_domain->name;
450                 LISTADD(provide->ac_domains, ac_domain);
451                 if (!name) return -1;
452                 if (mfx && !provide->name) {
453                     ac_domain->name = malloc(strlen(mfx->name) + 2 +
454                                               strlen(name) + 1);
455                     if (!ac_domain->name) return -1;
456                     sprintf((char *)ac_domain->name, "%s::%s", mfx->name, name);
457                     msmFreePointer((void**)&name);
458                 }
459             } else return -1;
460
461        } else if (!strcmp(ASCII(node), "for")) {
462             origin = xmlTextReaderGetAttribute(reader, XMLCHAR("origin"));
463             rpmlog(RPMLOG_DEBUG, "for %s\n", ASCII(origin));
464             if (!origin) return -1;
465             if (provide->origin) { 
466                 msmFreePointer((void**)&origin);
467                 return -1;
468             }
469             provide->origin = ASCII(origin);
470             if (strcmp(ASCII(origin), "trusted") && 
471                 strcmp(ASCII(origin), "current") &&
472                 strcmp(ASCII(origin), "all"))
473                 return -1;
474
475         } else if (!strcmp(ASCII(node), "filesystem")) {
476             filesystem_x *filesystem = msmProcessFilesystem(reader);
477             if (filesystem) {
478                 LISTADD(provide->filesystems, filesystem);
479             } else return -1;
480
481         } else {
482             rpmlog(RPMLOG_ERR, "No allowed element in assign section: %s\n", ASCII(node));
483             return -1;
484         }
485
486         if (ret < 0) return ret;
487     }
488
489     return ret;
490 }
491
492 static int msmProcessPackage(xmlTextReaderPtr reader, package_x *package, sw_source_x *current)
493 {
494     const xmlChar *node, *name, *modified;
495     int ret, depth;
496
497     /* config processing */
498     name = xmlTextReaderGetAttribute(reader, XMLCHAR("name"));
499     modified = xmlTextReaderGetAttribute(reader, XMLCHAR("modified"));
500     rpmlog(RPMLOG_DEBUG, "package %s %s\n", name, modified);
501
502     package->name = ASCII(name);
503     package->modified = ASCII(modified);
504     package->sw_source = current;
505
506     depth = xmlTextReaderDepth(reader);
507     while ((ret = msmNextChildElement(reader, depth))) {
508         node = xmlTextReaderConstName(reader);
509         if (!node) return -1;
510
511         if (!strcmp(ASCII(node), "provide")) {
512             provide_x *provide = calloc(1, sizeof(provide_x));
513             if (provide) {
514                 LISTADD(package->provides, provide);
515                 ret = msmProcessProvide(reader, provide, current, NULL, package->name);
516             } else return -1;
517         } else return -1;
518
519         if (ret < 0) return ret;
520     }
521     return ret;
522 }
523
524 static int msmProcessRequest(xmlTextReaderPtr reader, request_x *request) 
525 {
526     const xmlChar *node, *name;
527     int ret, depth, requestPresent = 0;
528
529     rpmlog(RPMLOG_DEBUG, "request \n");
530     depth = xmlTextReaderDepth(reader);
531     while ((ret = msmNextChildElement(reader, depth))) {
532         node = xmlTextReaderConstName(reader);
533         if (!node) return -1;
534
535         if (!strcmp(ASCII(node), "domain")) {
536             if (requestPresent) {
537                 rpmlog(RPMLOG_ERR, "A second domain defined inside a request section. Abort package installation\n");
538                 return -1;
539             }
540             name = xmlTextReaderGetAttribute(reader, XMLCHAR("name"));   
541             rpmlog(RPMLOG_DEBUG, "ac domain name %s\n", ASCII(name));
542             if (name) {
543                 request->ac_domain = ASCII(name);
544                 requestPresent = 1;
545             } else {
546                 rpmlog(RPMLOG_ERR, "No ac domain name defined in request.\n");
547                 return -1;
548             }
549         } else {
550             rpmlog(RPMLOG_ERR, "Not allowed element in request section: %s\n", ASCII(node));
551             return -1;
552         }
553     }
554     return ret;
555 }
556
557 static int msmProcessDRequest(xmlTextReaderPtr reader, define_x *define) 
558 {
559     const xmlChar *node = NULL, *label = NULL, *type = NULL;
560     int ret, depth;
561
562     rpmlog(RPMLOG_DEBUG, "request\n");
563
564     if (!define->name) {
565         rpmlog(RPMLOG_ERR, "An attempt to define a domain without a name. Abort.\n");
566         return -1;
567     }
568
569     depth = xmlTextReaderDepth(reader);
570     while ((ret = msmNextChildElement(reader, depth))) {
571         node = xmlTextReaderConstName(reader);
572         if (!node) return -1;
573
574         if (!strcmp(ASCII(node), "smack")) {
575             label = xmlTextReaderGetAttribute(reader, XMLCHAR("request"));
576             type = xmlTextReaderGetAttribute(reader, XMLCHAR("type"));
577             rpmlog(RPMLOG_DEBUG, "request label %s type %s\n", ASCII(label), ASCII(type));
578             if (label && type) {
579                 if (msmVerifyAccessType(ASCII(type)) < 0) {
580                     msmFreePointer((void**)&label);
581                     msmFreePointer((void**)&type);      
582                     return -1; 
583                 }
584                 if (msmVerifySmackLabel(ASCII(label)) < 0) {
585                     msmFreePointer((void**)&label);
586                     msmFreePointer((void**)&type);
587                     return -1;
588                 }
589                 d_request_x *request = calloc(1, sizeof(d_request_x));
590                 if (request) {
591                     request->label_name = ASCII(label);
592                     request->ac_type = ASCII(type);
593                     LISTADD(define->d_requests, request);
594                 } else {
595                     msmFreePointer((void**)&label);
596                     msmFreePointer((void**)&type);
597                     return -1;
598                 }
599             } else  {
600                 rpmlog(RPMLOG_ERR, "One of the mandatory arguments for domain request is missing. Abort installation\n");
601                 rpmlog(RPMLOG_ERR, "smack request label %s type %s\n", ASCII(label), ASCII(type));
602                 msmFreePointer((void**)&label);
603                 msmFreePointer((void**)&type);  
604                 return -1;
605             }
606         } else {
607             rpmlog(RPMLOG_ERR, "Not allowed element in domain request section: %s\n", ASCII(node));
608             return -1;
609         }
610         if (ret < 0) return ret;
611     }
612
613     return ret;
614 }
615
616 static int msmProcessDPermit(xmlTextReaderPtr reader, define_x *define) 
617 {
618     const xmlChar *node, *label, *type, *to_label;
619     int ret, depth;
620
621     rpmlog(RPMLOG_DEBUG, "permit\n");
622
623     if (!define->name) {
624         rpmlog(RPMLOG_ERR, "An attempt to define a domain without a name. Abort.\n");
625         return -1;
626     }
627
628     depth = xmlTextReaderDepth(reader);
629
630     while ((ret = msmNextChildElement(reader, depth))) {
631         node = xmlTextReaderConstName(reader);
632         if (!node) return -1;
633
634         if (!strcmp(ASCII(node), "smack")) {
635             label = xmlTextReaderGetAttribute(reader, XMLCHAR("permit"));
636             to_label = xmlTextReaderGetAttribute(reader, XMLCHAR("to"));
637             type = xmlTextReaderGetAttribute(reader, XMLCHAR("type"));
638             rpmlog(RPMLOG_DEBUG, "permit %s to %s type %s\n", ASCII(label), ASCII(to_label), ASCII(type));
639
640             if (label && type) {
641                 if (msmVerifyAccessType(ASCII(type)) < 0) {
642                     msmFreePointer((void**)&label);
643                     msmFreePointer((void**)&to_label);
644                     msmFreePointer((void**)&type);      
645                     return -1; 
646                 }
647                 if (msmVerifySmackLabel(ASCII(label)) < 0) {
648                     msmFreePointer((void**)&label);
649                     msmFreePointer((void**)&to_label);
650                     msmFreePointer((void**)&type);
651                     return -1;
652                 }
653                 if ((to_label) && (msmVerifyLabelPrefix(ASCII(to_label), define->name) < 0)) {
654                     msmFreePointer((void**)&label);
655                     msmFreePointer((void**)&to_label);
656                     msmFreePointer((void**)&type);
657                     return -1;
658                 }
659                 d_permit_x *permit = calloc(1, sizeof(d_permit_x));
660                 if (permit) {
661                     permit->label_name = ASCII(label);
662                     permit->to_label_name = ASCII(to_label);
663                     permit->ac_type = ASCII(type);
664                     LISTADD(define->d_permits, permit);
665                 } else {
666                     msmFreePointer((void**)&label);
667                     msmFreePointer((void**)&to_label);
668                     msmFreePointer((void**)&type);
669                     return -1;
670                 }
671             } else  {
672                 rpmlog(RPMLOG_ERR, "One of the mandatory arguments for domain permit is missing. Abort installation\n");
673                 rpmlog(RPMLOG_ERR, "smack permit label %s type %s\n", ASCII(label), ASCII(type));
674                 msmFreePointer((void**)&label);
675                 msmFreePointer((void**)&to_label);
676                 msmFreePointer((void**)&type);  
677                 return -1;
678             }
679         } else {
680             rpmlog(RPMLOG_ERR, "Not allowed element in domain permit section: %s\n", ASCII(node));
681             return -1;
682         }
683         if (ret < 0) return ret;
684     }
685
686     return ret;
687 }
688
689 static int msmProcessDProvide(xmlTextReaderPtr reader, define_x *define) 
690 {
691     const xmlChar *node, *label;
692     int ret = 0, depth;
693
694     rpmlog(RPMLOG_DEBUG, "provide\n");
695
696     if (!define->name) {
697         rpmlog(RPMLOG_ERR, "An attempt to define a domain without a name. Abort.\n");
698         return -1;
699     }
700
701     depth = xmlTextReaderDepth(reader);
702     while ((ret = msmNextChildElement(reader, depth))) {
703         node = xmlTextReaderConstName(reader);
704         if (!node) return -1;
705         if (!strcmp(ASCII(node), "label")) {
706             label = xmlTextReaderGetAttribute(reader, XMLCHAR("name"));
707             rpmlog(RPMLOG_DEBUG, "label %s \n", ASCII(label));
708
709             if (label) {
710                 if (msmVerifySmackLabel(ASCII(label)) < 0) {
711                     msmFreePointer((void**)&label);
712                     return -1;
713                 }
714                 if (msmVerifyLabelPrefix(ASCII(label), define->name) < 0) {
715                     msmFreePointer((void**)&label);
716                     return -1;
717                 }
718                 d_provide_x *provide = calloc(1, sizeof(d_provide_x));
719                 if (provide) {
720                     provide->label_name = ASCII(label);
721                     LISTADD(define->d_provides, provide);
722                 } else {
723                     msmFreePointer((void**)&label);
724                     return -1;
725                 }
726             } else {
727                  rpmlog(RPMLOG_INFO, "Label name is empty. Label provide is ignored\n");
728                  continue;
729             }
730         } else {
731             rpmlog(RPMLOG_ERR, "Not allowed element in domain provide section: %s\n", ASCII(node));
732             return -1;
733         }
734         if (ret < 0) return ret;
735     }
736
737     return ret;
738 }
739
740 static int msmProcessDefine(xmlTextReaderPtr reader, define_x *define, manifest_x *mfx, sw_source_x *current) 
741 {
742     const xmlChar *node, *name, *policy, *plist;
743     int ret, depth, domainPresent = 0;
744
745     rpmlog(RPMLOG_DEBUG, "define\n");
746
747     depth = xmlTextReaderDepth(reader);
748
749     while ((ret = msmNextChildElement(reader, depth))) {
750         node = xmlTextReaderConstName(reader);
751         if (!node) return -1;
752         if (!strcmp(ASCII(node), "domain")) {
753             if (domainPresent) {
754                 rpmlog(RPMLOG_ERR, "Only one domain is allowed per define section. Abort installation\n");
755                 return -1;
756             }
757             domainPresent = 1;
758             name = xmlTextReaderGetAttribute(reader, XMLCHAR("name"));
759             policy = xmlTextReaderGetAttribute(reader, XMLCHAR("policy"));
760             plist = xmlTextReaderGetAttribute(reader, XMLCHAR("plist"));
761             rpmlog(RPMLOG_DEBUG, "domain %s policy %s plist %s\n", 
762                    ASCII(name), ASCII(policy), ASCII(plist));
763
764             if (name) { 
765                 if (msmVerifySmackLabel(ASCII(name)) < 0) {
766                     msmFreePointer((void**)&name);
767                     msmFreePointer((void**)&policy);            
768                     msmFreePointer((void**)&plist);
769                     return -1; 
770                 }
771
772                 define->name = ASCII(name);
773                 define->policy = ASCII(policy);
774                 define->plist = ASCII(plist);
775                 // store defined ac domain name 
776                 ac_domain_x *ac_domain = calloc(1, sizeof(ac_domain_x));
777                 if (ac_domain) {
778                     if (define->name) {
779                         ac_domain->name = strdup(define->name);
780                     }
781                     ac_domain->match = strdup("trusted"); // hardcode trusted policy for ac domain definition
782                     if (define->policy) {
783                         ac_domain->type = strdup(define->policy);
784                     }   
785                     if (define->plist) {
786                         ac_domain->plist = strdup(define->plist);
787                     }                             
788                     ac_domain->sw_source = current;
789                     ac_domain->pkg_name = mfx->name;
790                     if (!mfx->provides){
791                         provide_x *provide = calloc(1, sizeof(provide_x));
792                         if (provide) {
793                             LISTADD(mfx->provides, provide);
794                         } else { 
795                             if (ac_domain) {
796                                 msmFreeACDomain(ac_domain);
797                                 return -1;
798                             }
799                         }
800                     }
801                     LISTADD(mfx->provides->ac_domains, ac_domain);
802                 } else return -1;
803             } else {
804                 rpmlog(RPMLOG_ERR, "Domain name must be defined. Abort installation\n");
805                 msmFreePointer((void**)&policy);        
806                 msmFreePointer((void**)&plist);
807                 return -1; 
808             }
809         } else if (!strcmp(ASCII(node), "request")) {
810             int res = msmProcessDRequest(reader, define);
811             if (res < 0) return res;
812         } else if (!strcmp(ASCII(node), "permit")) {
813             int res = msmProcessDPermit(reader, define);
814             if (res < 0) return res;
815         } else if (!strcmp(ASCII(node), "provide")) {
816             int res = msmProcessDProvide(reader, define);
817             if (res < 0) return res;
818         } else {
819             rpmlog(RPMLOG_ERR, "Not allowed element in domain define section: %s\n", ASCII(node));
820             return -1;
821         }
822         if (ret < 0) return ret;
823     }
824     return ret;
825 }
826
827 int msmFindSWSourceByKey(sw_source_x *sw_source, void *param)
828 {
829     origin_x *origin;
830     keyinfo_x *keyinfo;
831     keyinfo_x *current_keyinfo = (keyinfo_x*)param;
832
833     for (origin = sw_source->origins; origin; origin = origin->prev) {
834             for (keyinfo = origin->keyinfos; keyinfo; keyinfo = keyinfo->prev) {
835                 if (strncmp((const char*)current_keyinfo->keydata, (const char*)keyinfo->keydata, 
836                     strlen((const char*)current_keyinfo->keydata)) == 0
837                    && (current_keyinfo->keylen == keyinfo->keylen))
838                         return 0;
839             }
840     }
841     return 1;
842 }
843
844 int msmFindSWSourceByName(sw_source_x *sw_source, void *param)
845 {
846     const char *name = (const char *)param;
847     return strcmp(sw_source->name, name); 
848 }
849
850 int msmFindSWSourceBySignature(sw_source_x *sw_source, void *param, void* param2)
851 {
852     origin_x *origin;
853     keyinfo_x *keyinfo;
854     pgpDigParams sig = (pgpDigParams)param;
855     DIGEST_CTX ctx = (DIGEST_CTX)param2;
856     pgpDigParams key = NULL;
857
858     for (origin = sw_source->origins; origin; origin = origin->prev) {
859         for (keyinfo = origin->keyinfos; keyinfo; keyinfo = keyinfo->prev) {
860             if (pgpPrtParams(keyinfo->keydata, keyinfo->keylen, PGPTAG_PUBLIC_KEY, &key)) {
861                 rpmlog(RPMLOG_ERR, "invalid sw source key\n");
862                 return -1;
863             }
864             if (pgpVerifySignature(key, sig, ctx) == RPMRC_OK) {
865                 return 0;
866             }
867         }
868     }
869     return 1;
870 }
871
872 static int msmProcessKeyinfo(xmlTextReaderPtr reader, origin_x *origin, sw_source_x *parent) 
873 {
874     const xmlChar *keydata;
875     keyinfo_x *keyinfo;
876     int ret, depth;
877
878     depth = xmlTextReaderDepth(reader);
879     while ((ret = msmNextChildElement(reader, depth))) {
880         keydata = xmlTextReaderConstValue(reader);
881         rpmlog(RPMLOG_DEBUG, "keyinfo %.40s...\n", ASCII(keydata));
882         if (!keydata) return -1;
883         keyinfo = calloc(1, sizeof(keyinfo_x));
884         if (keyinfo) {
885             if ((ret = rpmBase64Decode(ASCII(keydata), (void **)&keyinfo->keydata, &keyinfo->keylen))) {
886                 rpmlog(RPMLOG_ERR, "Failed to decode keyinfo %s, %d\n", keydata, ret);
887                 ret = -1;
888             }
889             if (!ret) {
890                 // check that keys aren't matching
891                 sw_source_x *old = msmSWSourceTreeTraversal(parent, msmFindSWSourceByKey, (void *)keyinfo, NULL);
892                 if (old) {
893                     rpmlog(RPMLOG_ERR, "SW source with this key has already been installed\n");
894                     return -1; 
895                 }
896             }
897             LISTADD(origin->keyinfos, keyinfo);
898         } else return -1;
899
900         if (ret < 0) return ret;
901     }
902     return ret;
903 }
904
905 static access_x *msmProcessAccess(xmlTextReaderPtr reader, origin_x *origin) 
906 {
907     const xmlChar *data, *type;
908
909     data = xmlTextReaderGetAttribute(reader, XMLCHAR("data"));
910     type = xmlTextReaderGetAttribute(reader, XMLCHAR("type"));
911     rpmlog(RPMLOG_DEBUG, "access %s %s\n", ASCII(data), ASCII(type));
912
913     if (data) {
914         access_x *access = calloc(1, sizeof(access_x));
915         if (access) {
916             access->data = ASCII(data);
917             access->type = ASCII(type);
918             return access;
919         }
920     }
921     msmFreePointer((void**)&data);
922     msmFreePointer((void**)&type);
923     return NULL;
924 }
925
926 static int msmProcessOrigin(xmlTextReaderPtr reader, origin_x *origin, sw_source_x *parent)  
927 {
928     const xmlChar *node, *type;
929     int ret, depth;
930
931     type = xmlTextReaderGetAttribute(reader, XMLCHAR("type"));
932     rpmlog(RPMLOG_DEBUG, "origin %s\n", ASCII(type));
933     origin->type = ASCII(type);
934
935     depth = xmlTextReaderDepth(reader);
936     while ((ret = msmNextChildElement(reader, depth))) {
937         node = xmlTextReaderConstName(reader);
938         if (!node) return -1;
939         if (!strcmp(ASCII(node), "keyinfo")) {
940             ret = msmProcessKeyinfo(reader, origin, parent);
941         } else if (!strcmp(ASCII(node), "access")) {
942             access_x *access = msmProcessAccess(reader, origin);
943             if (access) {
944                 LISTADD(origin->accesses, access);
945             } else return -1;
946         } else return -1;
947
948         if (ret < 0) return ret;
949     }
950     return ret;
951 }
952
953 static int msmProcessDeny(xmlTextReaderPtr reader, sw_source_x *sw_source) 
954 {
955     const xmlChar *node;
956     int ret, depth;
957
958     rpmlog(RPMLOG_DEBUG, "deny\n");
959
960     depth = xmlTextReaderDepth(reader);
961     while ((ret = msmNextChildElement(reader, depth))) {
962         node = xmlTextReaderConstName(reader);
963         if (!node) return -1;
964         if (!strcmp(ASCII(node), "ac_domain")) {
965             ac_domain_x *ac_domain = msmProcessACDomain(reader, sw_source, NULL);
966             if (ac_domain) {
967                 if (ac_domain->name) {
968                     HASH_ADD_KEYPTR(hh, sw_source->denys, ac_domain->name, 
969                                     strlen(ac_domain->name), ac_domain);
970                 } else {
971                     LISTADD(sw_source->denymatches, ac_domain);
972                 }
973             } else return -1;
974         } else return -1;
975         if (ret < 0) return ret;
976     }
977     return ret;
978 }
979
980 static int msmProcessAllow(xmlTextReaderPtr reader, sw_source_x *sw_source) 
981 {
982     const xmlChar *node;    
983     int ret, depth;
984
985     rpmlog(RPMLOG_DEBUG, "allow\n");
986
987     depth = xmlTextReaderDepth(reader);
988     while ((ret = msmNextChildElement(reader, depth))) {
989         node = xmlTextReaderConstName(reader);
990         if (!node) return -1;
991         if (!strcmp(ASCII(node), "deny")) {
992             ret = msmProcessDeny(reader, sw_source);
993         } else if (!strcmp(ASCII(node), "ac_domain")) {
994             ac_domain_x *ac_domain = msmProcessACDomain(reader, sw_source, NULL);
995             if (ac_domain) {
996                 if (ac_domain->name) {
997                     HASH_ADD_KEYPTR(hh, sw_source->allows, ac_domain->name, 
998                                     strlen(ac_domain->name), ac_domain);
999                 } else {
1000                     LISTADD(sw_source->allowmatches, ac_domain);
1001                 }
1002             } else return -1;
1003         } else return -1;
1004         if (ret < 0) return ret;
1005     }
1006     return ret;
1007 }
1008
1009 static int msmProcessSWSource(xmlTextReaderPtr reader, sw_source_x *sw_source, const char *parentkey, manifest_x *mfx) 
1010 {
1011     const xmlChar *name, *node, *rank, *rankkey;
1012     sw_source_x *current;
1013     int ret, depth, len;
1014     int rankval = 0;
1015
1016     /* config processing */
1017     current = sw_source;
1018
1019     name = xmlTextReaderGetAttribute(reader, XMLCHAR("name"));
1020     rank = xmlTextReaderGetAttribute(reader, XMLCHAR("rank"));
1021     rankkey = xmlTextReaderGetAttribute(reader, XMLCHAR("rankkey"));
1022     rpmlog(RPMLOG_DEBUG, "sw source %s rank %s key %s\n", 
1023            ASCII(name), ASCII(rank), ASCII(rankkey));
1024
1025     sw_source->name = ASCII(name);
1026
1027     if (rankkey) {
1028         /* config processing */
1029         sw_source->rankkey = ASCII(rankkey);
1030     } else {
1031         if (rank) {
1032             rankval = atoi(ASCII(rank));
1033             msmFreePointer((void**)&rank); /* rankkey is used from now on */
1034         }
1035     }
1036     if (!sw_source->name) return -1; /* sw source must have name */
1037     if (!mfx && rankkey) return -1; /* manifest cannot set rankkey itself */
1038
1039     if (!mfx) {
1040         sw_source_x *old = msmSWSourceTreeTraversal(sw_source->parent, msmFindSWSourceByName, (void *)sw_source->name, NULL);
1041         if (old && old->parent != sw_source->parent) {
1042             if (!old->parent && old == sw_source->parent) {
1043                 /* root sw source upgrade (it's signed by root) */
1044                 parentkey = "";
1045             } else {
1046                 rpmlog(RPMLOG_ERR, "SW source called %s has already been installed\n", 
1047                        sw_source->name);
1048                 return -1; /* sw_source names are unique (allow upgrade though) */
1049             }
1050         }
1051         /* rank algorithm is copied from harmattan dpkg wrapper */
1052         if (rankval > RANK_LIMIT) rankval = RANK_LIMIT;
1053         if (rankval < -RANK_LIMIT) rankval = -RANK_LIMIT;
1054         rankval += RANK_LIMIT;
1055
1056         len = strlen(parentkey) + 1 + 5 + 1 + 5 + 1 + strlen(sw_source->name) + 1;
1057         if (!(sw_source->rankkey = malloc(len))) return -1;
1058         sprintf((char *)sw_source->rankkey, "%s/%05d/%05d.%s", 
1059                 parentkey, rankval, RANK_LIMIT, sw_source->name);
1060     }
1061
1062     depth = xmlTextReaderDepth(reader);
1063     while ((ret = msmNextChildElement(reader, depth))) {
1064         node = xmlTextReaderConstName(reader);
1065         if (!node) return -1;
1066         if (!strcmp(ASCII(node), "allow")) {
1067             ret = msmProcessAllow(reader, sw_source);
1068         } else if (!strcmp(ASCII(node), "deny")) {
1069             ret = msmProcessDeny(reader, sw_source);
1070         } else if (!strcmp(ASCII(node), "origin")) {
1071             origin_x *origin = calloc(1, sizeof(origin_x));
1072             if (origin) {
1073                 LISTADD(sw_source->origins, origin);
1074                 ret = msmProcessOrigin(reader, origin, sw_source->parent);
1075             } else return -1;
1076         } else if (!strcmp(ASCII(node), "package")) {
1077             /* config processing */
1078             if (!mfx) return -1;
1079             package_x *package = calloc(1, sizeof(package_x));
1080             if (package) {
1081                 LISTADD(sw_source->packages, package);
1082                 ret = msmProcessPackage(reader, package, current);
1083             } else return -1;
1084         } else if (!strcmp(ASCII(node), "sw_source")) {
1085             /* config processing */
1086             if (!mfx) return -1;
1087             sw_source_x *sw_source = calloc(1, sizeof(sw_source_x));
1088             if (sw_source) {
1089                 sw_source->parent = current;
1090                 LISTADD(mfx->sw_sources, sw_source);
1091             } else return -1;
1092             ret = msmProcessSWSource(reader, sw_source, "", mfx);
1093         } else return -1;
1094
1095         if (ret < 0) return ret;
1096     }
1097     return ret;
1098 }
1099
1100 static int msmProcessAttributes(xmlTextReaderPtr reader, manifest_x *mfx) 
1101 {
1102     const xmlChar *node, *type;
1103     int ret, depth, attributePresent = 0;
1104
1105     rpmlog(RPMLOG_DEBUG, "attributes\n");
1106     depth = xmlTextReaderDepth(reader);
1107
1108     while ((ret = msmNextChildElement(reader, depth))) {
1109         node = xmlTextReaderConstName(reader);
1110         if (!node) return -1;
1111         if (!strcmp(ASCII(node), "package")) {
1112             if (attributePresent) {
1113                 rpmlog(RPMLOG_ERR, "Only one attribute is currently allowed per attribute section. Abort installation\n");
1114                 return -1;
1115             }
1116             attributePresent = 1;
1117             type = xmlTextReaderGetAttribute(reader, XMLCHAR("type"));
1118             rpmlog(RPMLOG_DEBUG, "package type is %s\n", ASCII(type));
1119
1120             if (type) { 
1121                 if ((strcmp(type, "system") != 0) &&
1122                     (strcmp(type, "application") != 0)){
1123                     rpmlog(RPMLOG_ERR, "Not allowed attribute name in a package type specification. Abort installation.\n");
1124                     msmFreePointer((void**)&type);
1125                     return -1; 
1126                 }
1127                 mfx->package_type = ASCII(type);            
1128             } else {
1129                 rpmlog(RPMLOG_ERR, "Type name must be defined. Abort installation\n");
1130                 return -1; 
1131             }
1132         } else {
1133             rpmlog(RPMLOG_ERR, "Not allowed element in attribute section: %s\n", ASCII(node));
1134             return -1;
1135         }
1136         if (ret < 0) return ret;
1137     }
1138     return ret;
1139 }
1140
1141 static int msmProcessMsm(xmlTextReaderPtr reader, manifest_x *mfx, sw_source_x *current)
1142 {
1143     const xmlChar *node;
1144     int ret, depth;
1145     int assignPresent = 0, requestPresent = 0, attributesPresent = 0; /* there must be only one section per manifest */
1146     mfx->sw_source = current;
1147
1148     rpmlog(RPMLOG_DEBUG, "manifest\n");
1149
1150     depth = xmlTextReaderDepth(reader);
1151     while ((ret = msmNextChildElement(reader, depth))) {
1152         node = xmlTextReaderConstName(reader);
1153         if (!node) return -1;
1154         if (!strcmp(ASCII(node), "assign")) {
1155             if (assignPresent) {
1156                 rpmlog(RPMLOG_ERR, "A second assign section in manifest isn't allowed. Abort installation.\n");
1157                 return -1; 
1158             }
1159             assignPresent = 1;
1160             provide_x *provide = calloc(1, sizeof(provide_x));
1161             if (provide) {
1162                 LISTADD(mfx->provides, provide);
1163                 ret = msmProcessProvide(reader, provide, current, mfx, NULL);
1164             } else return -1;
1165         } else if (!strcmp(ASCII(node), "attributes")) {
1166             if (attributesPresent) {
1167                 rpmlog(RPMLOG_ERR, "A second attribute section in manifest isn't allowed. Abort installation.\n");
1168                 return -1; 
1169             }
1170             attributesPresent = 1;
1171             ret = msmProcessAttributes(reader, mfx);
1172         } else if (!strcmp(ASCII(node), "define")) {
1173             define_x *define = calloc(1, sizeof(define_x));
1174             if (define) {
1175                 LISTADD(mfx->defines, define);
1176                 ret = msmProcessDefine(reader, define, mfx, current);
1177             } else return -1;
1178         } else if (!strcmp(ASCII(node), "request")) {
1179             if (requestPresent) {
1180                 rpmlog(RPMLOG_ERR, "A second request section in manifest isn't allowed. Abort installation.\n");
1181                 return -1; 
1182             }
1183             requestPresent = 1;
1184             mfx->request = calloc(1, sizeof(request_x));
1185             if (mfx->request) {
1186                 ret = msmProcessRequest(reader, mfx->request);
1187             } else return -1;
1188         } else if (!strcmp(ASCII(node), "sw_source")) {
1189             sw_source_x *sw_source = calloc(1, sizeof(sw_source_x));
1190             if (sw_source) {
1191                 char parentkey[256] = { 0 };
1192                 sw_source->parent = current;
1193                 if (sw_source->parent) {
1194                     snprintf(parentkey, sizeof(parentkey), 
1195                              "%s", sw_source->parent->rankkey);
1196                     char *sep = strrchr(parentkey, '/');
1197                     if (sep) *sep = '\0';
1198                 }
1199                 LISTADD(mfx->sw_sources, sw_source);
1200                 ret = msmProcessSWSource(reader, sw_source, parentkey, NULL);
1201             } else return -1;
1202         } else return -1;
1203         if (ret < 0) return ret;
1204     }
1205     return ret;
1206 }
1207
1208 static int msmProcessConfig(xmlTextReaderPtr reader, manifest_x *mfx)
1209 {
1210     const xmlChar *node;
1211     int ret, depth;
1212
1213     rpmlog(RPMLOG_DEBUG, "config\n");
1214
1215     depth = xmlTextReaderDepth(reader);
1216     if ((ret = msmNextChildElement(reader, depth))) {
1217         node = xmlTextReaderConstName(reader);
1218         if (!node) return -1;
1219         if (!strcmp(ASCII(node), "sw_source")) {
1220             mfx->sw_sources = calloc(1, sizeof(sw_source_x));
1221             if (!mfx->sw_sources) return -1;
1222             ret = msmProcessSWSource(reader, mfx->sw_sources, "", mfx);
1223         } else return -1;
1224     }
1225     return ret;
1226 }
1227
1228 static int msmProcessManifest(xmlTextReaderPtr reader, manifest_x *mfx, sw_source_x *current) 
1229 {
1230     const xmlChar *node;
1231     int ret;
1232
1233     if ((ret = msmNextChildElement(reader, -1))) {
1234         node = xmlTextReaderConstName(reader);
1235         if (!node) return -1;
1236         if (!strcmp(ASCII(node), "manifest")) {
1237             ret = msmProcessMsm(reader, mfx, current);
1238         } else if (!strcmp(ASCII(node), "config")) {
1239             ret = msmProcessConfig(reader, mfx);
1240         } else return -1;
1241     }
1242     return ret;
1243 }
1244
1245 static filesystem_x *msmFreeFilesystem(filesystem_x *filesystem)
1246 {    
1247     if (filesystem) {
1248         filesystem_x *prev = filesystem->prev;
1249         msmFreePointer((void**)&filesystem->path);
1250         msmFreePointer((void**)&filesystem->label);
1251         msmFreePointer((void**)&filesystem->exec_label);
1252         msmFreePointer((void**)&filesystem->type);
1253         msmFreePointer((void**)&filesystem);
1254         return prev;
1255     } else
1256         return NULL;
1257 }
1258
1259 static member_x *msmFreeMember(member_x *member)
1260
1261     if (member) {
1262         member_x *prev = member->prev;
1263         msmFreePointer((void**)&member->name);
1264         if (member->annotation) {
1265             msmFreePointer((void**)&member->annotation->name);
1266             msmFreePointer((void**)&member->annotation->value);
1267             msmFreePointer((void**)&member->annotation);
1268         }
1269         msmFreePointer((void**)&member);
1270         return prev;
1271     } else
1272         return NULL;
1273 }
1274
1275 static interface_x *msmFreeInterface(interface_x *interface)
1276 {
1277     member_x *member;
1278
1279     if (interface) {
1280         interface_x *prev = interface->prev;
1281         msmFreePointer((void**)&interface->name);
1282         if (interface->annotation) {
1283             msmFreePointer((void**)&interface->annotation->name);
1284             msmFreePointer((void**)&interface->annotation->value);
1285             msmFreePointer((void**)&interface->annotation);
1286         }
1287         for (member = interface->members; member; member = msmFreeMember(member));
1288         msmFreePointer((void**)&interface);
1289         return prev;
1290     } else
1291         return NULL;
1292 }
1293
1294 static node_x *msmFreeNode(node_x *node)
1295 {    
1296     member_x *member;
1297     interface_x *interface;
1298
1299     if (node) {
1300         node_x *prev = node->prev;
1301         msmFreePointer((void**)&node->name);
1302         if (node->annotation) {
1303             msmFreePointer((void**)&node->annotation->name);
1304             msmFreePointer((void**)&node->annotation->value);
1305             msmFreePointer((void**)&node->annotation);
1306         }
1307         for (member = node->members; member; member = msmFreeMember(member));
1308         for (interface = node->interfaces; interface; interface = msmFreeInterface(interface));
1309         msmFreePointer((void**)&node);
1310         return prev;
1311     } else
1312         return NULL;
1313 }
1314
1315 static dbus_x *msmFreeDBus(dbus_x *dbus)
1316 {
1317     node_x *node;
1318
1319     if (dbus) {
1320         dbus_x *prev = dbus->prev;
1321         msmFreePointer((void**)&dbus->name);
1322         msmFreePointer((void**)&dbus->own);
1323         msmFreePointer((void**)&dbus->bus);
1324         if (dbus->annotation) {
1325             msmFreePointer((void**)&dbus->annotation->name);
1326             msmFreePointer((void**)&dbus->annotation->value);
1327             msmFreePointer((void**)&dbus->annotation);
1328         }
1329         for (node = dbus->nodes; node; node = msmFreeNode(node));
1330         msmFreePointer((void**)&dbus);
1331         return prev;
1332     } else return NULL;
1333 }
1334
1335 static provide_x *msmFreeProvide(provide_x *provide) 
1336 {
1337     ac_domain_x *ac_domain;
1338     filesystem_x *filesystem;
1339     provide_x *prev = provide->prev;
1340     dbus_x *dbus;
1341
1342     if (provide) {
1343         for (ac_domain = provide->ac_domains; ac_domain; ac_domain = msmFreeACDomain(ac_domain));
1344         if (provide->filesystems)
1345             for (filesystem = provide->filesystems; filesystem; filesystem = msmFreeFilesystem(filesystem));
1346         msmFreePointer((void**)&provide->name);
1347         msmFreePointer((void**)&provide->origin);
1348         for (dbus = provide->dbuss; dbus; dbus = msmFreeDBus(dbus));
1349         msmFreePointer((void**)&provide);
1350     }
1351     return prev;
1352 }
1353
1354 static file_x *msmFreeFile(file_x *file)
1355 {
1356     file_x *prev = file->prev;
1357     msmFreePointer((void**)&file->path);
1358     msmFreePointer((void**)&file);
1359     return prev;
1360 }
1361
1362 package_x *msmFreePackage(package_x *package)
1363 {
1364     provide_x *provide;
1365     package_x *prev = package->prev;
1366     for (provide = package->provides; provide; provide = msmFreeProvide(provide));
1367     msmFreePointer((void**)&package->name);
1368     msmFreePointer((void**)&package->modified);
1369     msmFreePointer((void**)&package);
1370     return prev;
1371 }
1372
1373 static keyinfo_x *msmFreeKeyinfo(keyinfo_x *keyinfo)
1374 {
1375     keyinfo_x *prev = keyinfo->prev;
1376     msmFreePointer((void**)&keyinfo->keydata);
1377     msmFreePointer((void**)&keyinfo);
1378     return prev;
1379 }
1380
1381 static access_x *msmFreeAccess(access_x *access)
1382 {
1383     access_x *prev = access->prev;
1384     msmFreePointer((void**)&access->data);
1385     msmFreePointer((void**)&access->type);
1386     msmFreePointer((void**)&access);
1387     return prev;
1388 }
1389
1390 static origin_x *msmFreeOrigin(origin_x *origin)
1391 {
1392     keyinfo_x *keyinfo;
1393     access_x *access;
1394     origin_x *prev = origin->prev;
1395     for (keyinfo = origin->keyinfos; keyinfo; keyinfo = msmFreeKeyinfo(keyinfo));
1396     for (access = origin->accesses; access; access = msmFreeAccess(access));
1397     msmFreePointer((void**)&origin->type);
1398     msmFreePointer((void**)&origin);
1399     return prev;
1400 }
1401
1402 static sw_source_x *msmFreeSWSource(sw_source_x *sw_source)
1403 {
1404     package_x *package;
1405     ac_domain_x *ac_domain, *temp;
1406     origin_x *origin;
1407     sw_source_x *next = sw_source->next;
1408
1409     rpmlog(RPMLOG_DEBUG, "freeing sw source %s\n", sw_source->name);
1410
1411     for (package = sw_source->packages; package; package = msmFreePackage(package));
1412     for (ac_domain = sw_source->allowmatches; ac_domain; ac_domain = msmFreeACDomain(ac_domain));
1413     if (sw_source->allows) {
1414         HASH_ITER(hh, sw_source->allows, ac_domain, temp) {
1415             HASH_DELETE(hh, sw_source->allows, ac_domain);
1416             msmFreeACDomain(ac_domain);
1417         }
1418     }
1419
1420     for (ac_domain = sw_source->denymatches; ac_domain; ac_domain = msmFreeACDomain(ac_domain));
1421     if (sw_source->denys) {
1422         HASH_ITER(hh, sw_source->denys, ac_domain, temp) {
1423             HASH_DELETE(hh, sw_source->denys, ac_domain);
1424             msmFreeACDomain(ac_domain);
1425         }
1426     }
1427     for (origin = sw_source->origins; origin; origin = msmFreeOrigin(origin));
1428     msmFreePointer((void**)&sw_source->name);
1429     msmFreePointer((void**)&sw_source->rankkey);
1430     msmFreePointer((void**)&sw_source);
1431     return next;
1432 }
1433
1434 static d_request_x *msmFreeDRequest(d_request_x *d_request)
1435 {
1436     d_request_x *next = d_request->next;
1437     rpmlog(RPMLOG_DEBUG, "freeing domain request %s\n", d_request->label_name);
1438     msmFreePointer((void**)&d_request->label_name);
1439     msmFreePointer((void**)&d_request->ac_type);
1440     msmFreePointer((void**)&d_request);
1441     return next;
1442 }
1443
1444 static d_permit_x *msmFreeDPermit(d_permit_x *d_permit)
1445 {
1446     d_permit_x *next = d_permit->next;
1447     rpmlog(RPMLOG_DEBUG, "freeing domain permit %s\n", d_permit->label_name);
1448     msmFreePointer((void**)&d_permit->label_name);
1449     msmFreePointer((void**)&d_permit->to_label_name);
1450     msmFreePointer((void**)&d_permit->ac_type);
1451     msmFreePointer((void**)&d_permit);
1452     return next;
1453 }
1454
1455 static d_provide_x *msmFreeDProvide(d_provide_x *d_provide)
1456 {
1457     d_provide_x *next = d_provide->next;
1458     rpmlog(RPMLOG_DEBUG, "freeing domain provide %s\n", d_provide->label_name);
1459     msmFreePointer((void**)&d_provide->label_name);
1460     msmFreePointer((void**)&d_provide);
1461     return next;
1462 }
1463
1464 static define_x *msmFreeDefine(define_x *define)
1465 {
1466     define_x *next = define->next;
1467     d_request_x *d_request;
1468     d_permit_x *d_permit;
1469     d_provide_x *d_provide;
1470
1471     msmFreePointer((void**)&define->name);
1472     msmFreePointer((void**)&define->policy);
1473     msmFreePointer((void**)&define->plist);
1474
1475     if (define->d_requests) {
1476         LISTHEAD(define->d_requests, d_request);        
1477         for (; d_request; d_request = msmFreeDRequest(d_request));
1478     }
1479     rpmlog(RPMLOG_DEBUG, "after freeing define requests\n");
1480     if (define->d_permits) {
1481         LISTHEAD(define->d_permits, d_permit);  
1482         for (; d_permit; d_permit = msmFreeDPermit(d_permit));
1483     }
1484     rpmlog(RPMLOG_DEBUG, "after freeing define permits\n");
1485     if (define->d_provides) {
1486         LISTHEAD(define->d_provides, d_provide);        
1487         for (; d_provide; d_provide = msmFreeDProvide(d_provide));
1488     }
1489     rpmlog(RPMLOG_DEBUG, "after freeing provides\n");
1490     msmFreePointer((void**)&define); 
1491     return next;
1492 }
1493
1494 manifest_x* msmFreeManifestXml(manifest_x* mfx)
1495 {
1496     provide_x *provide;
1497     file_x *file;
1498     sw_source_x *sw_source;
1499     define_x *define;
1500
1501     rpmlog(RPMLOG_DEBUG, "in msmFreeManifestXml\n");
1502     if (mfx) {
1503         if (mfx->provides)
1504             for (provide = mfx->provides; provide; provide = msmFreeProvide(provide));
1505         rpmlog(RPMLOG_DEBUG, "after freeing provides\n");
1506         if (mfx->request) {
1507             msmFreePointer((void**)&mfx->request->ac_domain);
1508             msmFreePointer((void**)&mfx->request);
1509         }
1510         rpmlog(RPMLOG_DEBUG, "after freeing requests\n");
1511         for (file = mfx->files; file; file = msmFreeFile(file));
1512         rpmlog(RPMLOG_DEBUG, "after freeing files\n");
1513         if (mfx->sw_sources) {
1514             LISTHEAD(mfx->sw_sources, sw_source);       
1515             for (; sw_source; sw_source = msmFreeSWSource(sw_source));
1516         }
1517         msmFreePointer((void**)&mfx->name);
1518         rpmlog(RPMLOG_DEBUG, "after freeing name\n");
1519         if (mfx->defines) {
1520             LISTHEAD(mfx->defines, define);
1521             for (; define; define = msmFreeDefine(define));            
1522         }
1523         rpmlog(RPMLOG_DEBUG, "after freeing defines \n");
1524         msmFreePointer((void**)&mfx);
1525     }
1526     return mfx; 
1527 }
1528
1529 manifest_x *msmProcessManifestXml(const char *buffer, int size, sw_source_x *current, const char *packagename) 
1530 {
1531     xmlTextReaderPtr reader;
1532     manifest_x *mfx = NULL;
1533
1534     reader = xmlReaderForMemory(buffer, size, NULL, NULL, 0);
1535     if (reader) {
1536         mfx = calloc(1, sizeof(manifest_x));
1537         if (mfx) {
1538             mfx->name = strdup(packagename);
1539             if (msmProcessManifest(reader, mfx, current) < 0) {
1540             /* error in parcing. Let's display some hint where we failed */
1541                 rpmlog(RPMLOG_DEBUG, "Syntax error in processing manifest in the above line\n");
1542                 mfx = msmFreeManifestXml(mfx);
1543             }
1544         }
1545         xmlFreeTextReader(reader);
1546     } else {
1547         rpmlog(RPMLOG_ERR, "Unable to create xml reader\n");
1548     }
1549     return mfx;
1550 }
1551
1552 manifest_x *msmProcessDevSecPolicyXml(const char *filename) 
1553 {
1554     xmlTextReaderPtr reader;
1555     manifest_x *mfx = NULL;
1556
1557     reader = xmlReaderForFile(filename, NULL, 0);
1558     if (reader) {
1559         mfx = calloc(1, sizeof(manifest_x));
1560         if (mfx) {
1561             if (msmProcessManifest(reader, mfx, NULL) < 0) {
1562                 mfx = msmFreeManifestXml(mfx);
1563             }
1564         }
1565         xmlFreeTextReader(reader);
1566     } else {
1567         rpmlog(RPMLOG_ERR, "Unable to open device security policy %s\n", filename);
1568     }
1569     return mfx;
1570 }