Fix memory leaks.
[libpwmd.git] / src / xml.c
blob63ce44f1d15506768fc8b9d47123e0c0a1f88889
1 /*
2 Copyright (C) 2006, 2007, 2008, 2009, 2010, 2011, 2012, 2013, 2014, 2015,
3 2016
4 Ben Kibbey <bjk@luxsci.net>
6 This file is part of pwmd.
8 Pwmd is free software: you can redistribute it and/or modify
9 it under the terms of the GNU General Public License as published by
10 the Free Software Foundation, either version 2 of the License, or
11 (at your option) any later version.
13 Pwmd is distributed in the hope that it will be useful,
14 but WITHOUT ANY WARRANTY; without even the implied warranty of
15 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
16 GNU General Public License for more details.
18 You should have received a copy of the GNU General Public License
19 along with Pwmd. If not, see <http://www.gnu.org/licenses/>.
21 #ifdef HAVE_CONFIG_H
22 #include <config.h>
23 #endif
25 #include <stdio.h>
26 #include <stdlib.h>
27 #include <unistd.h>
28 #include <err.h>
29 #include <string.h>
30 #include <sys/stat.h>
31 #include <fcntl.h>
32 #include <ctype.h>
33 #include <libxml/xmlwriter.h>
34 #include <wctype.h>
35 #include <sys/types.h>
36 #include <pwd.h>
38 #ifndef _
39 #include "gettext.h"
40 #define _(msgid) gettext(msgid)
41 #endif
43 #include "pwmd-error.h"
44 #include "util-misc.h"
45 #include "xml.h"
46 #include "mem.h"
47 #include "rcfile.h"
48 #include "commands.h"
50 extern void log_write (const char *fmt, ...);
53 * 'element' must be allocated.
55 int
56 is_literal_element (char **element)
58 char *p;
60 if (!element || !*element)
61 return 0;
63 if (*(*element) == '!')
65 char *c;
67 for (p = *element, c = p + 1; *c; c++)
68 *p++ = *c;
70 *p = 0;
71 return 1;
74 return 0;
77 int
78 valid_xml_attribute_value (const char *str)
80 const char *p = str;
82 if (!p || !*p)
83 return 1;
85 while (*p)
87 if (*p++ == '\n')
88 return 0;
91 return 1;
94 int
95 valid_xml_attribute (const char *str)
97 wchar_t *wc;
98 size_t len, c;
99 int ret = valid_xml_element ((xmlChar *)str);
101 if (!ret)
102 return ret;
104 wc = str_to_wchar ((const char *)str);
105 if (!wc)
106 return 0;
108 len = wcslen (wc);
109 for (c = 0; c < len; c++)
111 switch (wc[c])
113 case '-':
114 case '.':
115 case '0' ... '9':
116 case 0xB7:
117 case 0x0300 ... 0x036F:
118 case 0x203F ... 0x2040:
119 if (!c)
121 xfree (wc);
122 return 0;
124 case ':': break;
125 case '_': break;
126 case 'A' ... 'Z': break;
127 case 'a' ... 'z': break;
128 case 0xC0 ... 0xD6: break;
129 case 0xD8 ... 0xF6: break;
130 case 0xF8 ... 0x2FF: break;
131 case 0x370 ... 0x37D: break;
132 case 0x37F ... 0x1FFF: break;
133 case 0x200C ... 0x200D: break;
134 case 0x2070 ... 0x218F: break;
135 case 0x2C00 ... 0x2FEF: break;
136 case 0x3001 ... 0xD7FF: break;
137 case 0xF900 ... 0xFDCF: break;
138 case 0xFDF0 ... 0xFFFD: break;
139 case 0x10000 ... 0xEFFFF: break;
140 default:
141 xfree (wc);
142 return 0;
146 xfree (wc);
147 return 1;
151 valid_xml_element (xmlChar *str)
153 wchar_t *wc;
154 size_t len, c;
156 if (!str || !*str || *str == '!')
157 return 0;
159 wc = str_to_wchar ((const char *)str);
160 if (!wc)
161 return 0;
163 len = wcslen (wc);
164 for (c = 0; c < len; c++)
166 if (iswspace(wc[c]))
168 xfree (wc);
169 return 0;
173 xfree (wc);
174 return 1;
178 valid_element_path (char **path, int with_content)
180 char **dup = NULL, **p;
182 if (!path || !*path)
183 return 0;
185 /* Save some memory by not duplicating the element content. */
186 if (with_content)
188 int i, t = strv_length (path);
190 for (i = 0; i < t - 1; i++)
192 char **tmp = xrealloc (dup, (i + 2) * sizeof (char *));
194 if (!tmp)
196 strv_free (dup);
197 return 0;
200 dup = tmp;
201 dup[i] = str_dup (path[i]);
202 dup[i + 1] = NULL;
205 else
206 dup = strv_dup (path);
208 if (!dup)
209 return 0;
211 for (p = dup; *p && *(*p); p++)
213 is_literal_element (&(*p));
214 if (!valid_xml_element ((xmlChar *) * p))
216 strv_free (dup);
217 return 0;
221 strv_free (dup);
222 return 1;
225 gpg_error_t
226 attr_ctime (struct client_s *client, xmlNodePtr n)
228 char *buf = str_asprintf ("%li", time (NULL));
229 gpg_error_t rc;
231 if (!buf)
232 return GPG_ERR_ENOMEM;
234 rc = add_attribute (client, n, "_ctime", buf);
235 xfree (buf);
236 return rc;
239 static gpg_error_t
240 acl_check (struct client_s *client, xmlNodePtr n)
242 gpg_error_t rc = GPG_ERR_EACCES;
243 xmlChar *acl = node_has_attribute (n, (xmlChar *) "_acl");
244 char **users = acl ? str_split((char *)acl, ",", 0) : NULL;
245 char **p;
246 int allowed = 0;
248 if (!acl || !*acl || !users || !*users)
250 xmlFree (acl);
251 strv_free(users);
252 return peer_is_invoker(client);
255 if (!peer_is_invoker(client))
257 xmlFree (acl);
258 strv_free(users);
259 return 0;
262 for (p = users; p && *p; p++)
264 #ifdef WITH_GNUTLS
265 rc = acl_check_common (client, *p,
266 client->thd->remote ? 0 : client->thd->peer->uid,
267 client->thd->remote ? 0 : client->thd->peer->gid,
268 &allowed);
269 #else
270 rc = acl_check_common (client, *p, client->thd->peer->uid,
271 client->thd->peer->gid, &allowed);
272 #endif
275 xmlFree(acl);
276 strv_free(users);
278 // ATTR LIST makes use of FLAG_ACL_IGNORE to allow listing of element
279 // attributes that the client is not normally allowed access to.
280 if ((rc == GPG_ERR_EACCES || !allowed) && client->flags & FLAG_ACL_IGNORE)
282 rc = 0;
283 client->flags &= ~FLAG_ACL_IGNORE;
285 // This flag is used in ATTR LIST to prevent listing attributes of
286 // children whose parent ACL does not allow access to the client.
287 client->flags |= FLAG_ACL_ERROR;
288 allowed = 1;
291 if (rc)
292 return rc;
294 return allowed ? 0 : GPG_ERR_EACCES;
297 static char *
298 create_acl_user (struct client_s *client)
300 #ifdef WITH_GNUTLS
301 if (client->thd->remote)
302 return str_asprintf ("#%s", client->thd->tls->fp);
303 #endif
305 return get_username (client->thd->peer->uid);
308 static gpg_error_t
309 create_new_element (struct client_s *client, int verify, xmlNodePtr parent,
310 const char *name, xmlNodePtr * result)
312 xmlNodePtr n;
313 gpg_error_t rc;
315 // Allow any client to create a non-existing root element.
316 if (parent->parent->type != XML_DOCUMENT_NODE)
318 rc = acl_check(client, parent);
319 if (rc)
320 return rc;
323 n = xmlNewNode (NULL, (xmlChar *) "element");
324 if (!n)
325 return GPG_ERR_ENOMEM;
327 rc = add_attribute (client, n, "_name", name);
328 if (!rc)
329 rc = attr_ctime (client, n);
331 if (!rc && verify && parent->parent->type != XML_DOCUMENT_NODE)
332 rc = is_element_owner (client, parent);
334 if (!rc)
336 xmlNodePtr p = xmlAddChild (parent, n);
337 char *user = create_acl_user (client);
339 if (result)
340 *result = p;
342 rc = add_attribute(client, p, "_acl", user);
343 xfree (user);
345 else
346 xmlFreeNode (n);
348 return rc;
351 gpg_error_t
352 new_root_element (struct client_s *client, xmlDocPtr doc, char *name)
354 xmlNodePtr root = xmlDocGetRootElement (doc);
355 char *p = name;
357 if (!p || !root)
358 return GPG_ERR_BAD_DATA;
360 if (*p == '!')
361 p++;
363 if (!valid_xml_element ((xmlChar *) p))
364 return GPG_ERR_INV_VALUE;
366 return create_new_element (client, 0, root, p, NULL);
369 static xmlDocPtr
370 create_dtd ()
372 xmlDocPtr doc;
373 xmlTextWriterPtr wr = xmlNewTextWriterDoc (&doc, 0);
375 if (!wr)
376 return NULL;
378 if (xmlTextWriterStartDocument (wr, NULL, "UTF-8", "yes"))
379 goto fail;
381 if (xmlTextWriterStartDTD (wr, (xmlChar *) "pwmd", NULL, NULL) == -1)
382 goto fail;
384 if (xmlTextWriterWriteDTDElement (wr, (xmlChar *) "pwmd",
385 (xmlChar *) "(element)") == -1)
386 goto fail;
388 xmlTextWriterEndDTDElement (wr);
390 if (xmlTextWriterWriteDTDAttlist (wr, (xmlChar *) "element",
391 (xmlChar *) "_name CDATA #REQUIRED") ==
393 goto fail;
395 xmlTextWriterEndDTDAttlist (wr);
396 xmlTextWriterEndDTD (wr);
398 if (xmlTextWriterStartElement (wr, (xmlChar *) "pwmd"))
399 goto fail;
401 xmlTextWriterEndElement (wr);
402 xmlTextWriterEndDocument (wr);
403 xmlFreeTextWriter (wr);
404 return doc;
406 fail:
407 xmlTextWriterEndDocument (wr);
408 xmlFreeTextWriter (wr);
409 xmlFreeDoc (doc);
410 return NULL;
413 xmlDocPtr
414 new_document ()
416 return create_dtd ();
419 xmlNodePtr
420 find_element_node (xmlNodePtr node)
422 xmlNodePtr n = node;
424 if (n && n->type == XML_ELEMENT_NODE)
425 return n;
427 for (n = node; n; n = n->next)
429 if (n->type == XML_ELEMENT_NODE)
430 return n;
433 return NULL;
436 static xmlNodePtr
437 resolve_path (struct client_s *client, xmlDocPtr doc, xmlChar * path,
438 char ***result, gpg_error_t * rc)
440 xmlNodePtr n;
441 char **req;
443 req = str_split ((char *) path, "\t", 0);
444 if (!req)
446 *rc = GPG_ERR_ENOMEM;
447 return NULL;
450 n = find_root_element (client, doc, &req, rc, NULL, 0, 0);
451 if (*rc)
453 strv_free (req);
454 return n;
457 if (req[1])
458 n = find_elements (client, doc, n->children, req + 1, rc, NULL, NULL, NULL,
459 0, 0, NULL, 0);
461 if (*rc)
462 strv_free (req);
463 else
464 *result = req;
466 return n;
470 * Lists root element names; the value of the attribute "_name" of an element
471 * "element". If there's a target attribute both literal and non-literal
472 * element names will be added. This is the primary reason why XML entities
473 * cannot be used. There wouldn't be a way to get the literal an non-literal
474 * element paths.
476 gpg_error_t
477 list_root_elements (struct client_s *client, xmlDocPtr doc,
478 struct string_s ** result, int verbose, int with_target)
480 xmlNodePtr n = NULL;
481 struct slist_s *list = NULL;
482 int total, i;
483 struct string_s *string;
484 gpg_error_t rc = 0;
486 n = xmlDocGetRootElement (doc);
487 if (!n || !n->children)
488 return GPG_ERR_NO_DATA;
490 for (n = n->children; n; n = n->next)
492 xmlAttrPtr a;
493 xmlChar *val, *target;
494 struct slist_s *tlist;
495 char *tmp;
497 if (n->type != XML_ELEMENT_NODE)
498 continue;
500 a = xmlHasProp (n, (xmlChar *) "_name");
501 if (!a || !a->children->content)
502 continue;
504 val = xmlNodeGetContent (a->children);
505 if (!val)
507 rc = GPG_ERR_ENOMEM;
508 goto fail;
511 tmp = str_asprintf ("!%s%s", (char *) val,
512 verbose ? find_element_node (n->children) ? " +"
513 : "" : "");
515 if (!tmp)
517 xmlFree (val);
518 rc = GPG_ERR_ENOMEM;
519 goto fail;
522 tlist = slist_append (list, tmp);
523 if (!tlist)
525 xmlFree (val);
526 rc = GPG_ERR_ENOMEM;
527 goto fail;
530 list = tlist;
531 target = node_has_attribute (n, (xmlChar *) "target");
532 if (target)
534 char *t = NULL;
536 if (verbose)
538 char **req = NULL;
539 xmlNodePtr tnode = resolve_path (client, doc, target, &req, &rc);
541 if (rc == GPG_ERR_ELEMENT_NOT_FOUND || rc == GPG_ERR_ELOOP
542 || rc == GPG_ERR_EACCES)
544 t = str_asprintf ("%s %s%s%s", (char *) val,
545 rc == GPG_ERR_ELOOP ? "O" :
546 rc == GPG_ERR_EACCES ? "P" : "E",
547 with_target ? "T " : "",
548 with_target ? (char *)target : "");
549 rc = 0;
551 else if (!rc)
553 struct string_s *realpath = NULL;
555 if (with_target)
557 rc = build_realpath (client, doc, (char *) target,
558 &realpath);
559 if (rc)
561 strv_free (req);
562 xmlFree (val);
563 xmlFree (target);
564 goto fail;
567 realpath = string_prepend (realpath, "T ");
570 t = str_asprintf ("%s%s%s%s", (char *) val,
571 (tnode
572 && find_element_node (tnode->children))
573 || realpath ? " " : "", tnode
574 && find_element_node (tnode->children) ?
575 "+" : "", realpath ? realpath->str : "");
577 if (realpath)
578 string_free (realpath, 1);
581 if (req)
582 strv_free (req);
584 else
585 t = str_dup ((char *) val);
587 if (!t || rc)
589 xmlFree (val);
590 xmlFree (target);
591 rc = rc ? rc : GPG_ERR_ENOMEM;
592 goto fail;
595 tlist = slist_append (list, t);
596 if (!tlist)
598 xmlFree (val);
599 xfree (t);
600 xmlFree (target);
601 rc = GPG_ERR_ENOMEM;
602 goto fail;
605 list = tlist;
608 xmlFree (val);
609 xmlFree (target);
612 total = slist_length (list);
613 if (!total)
614 return GPG_ERR_NO_DATA;
616 string = string_new (NULL);
617 if (!string)
619 rc = GPG_ERR_ENOMEM;
620 goto fail;
623 for (i = 0; i < total; i++)
625 char *val = slist_nth_data (list, i);
627 string_append_printf (string, "%s\n", val);
630 string = string_truncate (string, string->len - 1);
631 *result = string;
633 fail:
634 total = slist_length (list);
635 for (i = 0; i < total; i++)
636 xfree (slist_nth_data (list, i));
638 slist_free (list);
639 return rc;
643 * Prevents a sibling element past the current element path with the same
644 * element name.
646 static xmlNodePtr
647 find_stop_node (xmlNodePtr node)
649 xmlNodePtr n;
651 for (n = node->parent->children; n; n = n->next)
653 if (n == node)
654 return n->next;
657 return NULL;
660 xmlNodePtr
661 create_target_elements_cb (struct client_s *client, int verify,
662 xmlNodePtr node, char **path, gpg_error_t *rc,
663 void *data)
665 int i;
666 char **req = path;
667 xmlNodePtr parent = data;
669 for (i = 0; req[i] && *req[i]; i++)
671 xmlNodePtr n;
673 if (parent && node == parent)
675 *rc = GPG_ERR_CONFLICT;
676 return NULL;
679 is_literal_element (&req[i]);
681 if ((n = find_element (client, node, req[i],
682 find_stop_node (node), rc)) == NULL ||
683 (n && n->parent == node->parent))
686 if (!*rc)
687 *rc = create_new_element (client, verify, node, req[i], &node);
689 if (*rc)
690 return NULL;
692 else
693 node = n;
696 return node;
699 xmlNodePtr
700 find_text_node (xmlNodePtr node)
702 xmlNodePtr n = node;
704 if (n && n->type == XML_TEXT_NODE)
705 return n;
707 for (n = node; n; n = n->next)
709 if (n->type == XML_TEXT_NODE)
710 return n;
713 return NULL;
716 xmlNodePtr
717 create_elements_cb (struct client_s *client, int verify, xmlNodePtr node,
718 char **elements, gpg_error_t * rc, void *data)
720 int i;
721 char **req = elements;
723 if (*rc && *rc != GPG_ERR_ELEMENT_NOT_FOUND)
724 return NULL;
726 if (node->type == XML_TEXT_NODE)
727 node = node->parent;
729 for (i = 0; req[i] && *req[i]; i++)
731 xmlNodePtr n;
734 * Strip the first '!' if needed. If there's another, it's an
735 * rc. The syntax has already been checked before calling this
736 * function.
738 is_literal_element (&req[i]);
739 n = find_element (client, node, req[i], find_stop_node (node), rc);
740 if (*rc)
741 return NULL;
744 * If the found element has the same parent as the current element,
745 * they are siblings and the new element needs to be created as a
746 * child of the current element (node).
748 if (n && n->parent == node->parent)
749 n = NULL;
751 if (!n)
753 *rc = create_new_element (client, 0, node, req[i], &node);
754 if (*rc)
755 return NULL;
757 else
758 node = n;
761 return node;
764 /* The root element is really req[0]. It is need as a pointer in case there is
765 * a target attribute so it can be updated. */
766 xmlNodePtr
767 find_root_element (struct client_s *client, xmlDocPtr doc, char ***req,
768 gpg_error_t * rc, int *target, int recursion_depth,
769 int stop)
771 xmlNodePtr n = xmlDocGetRootElement (doc);
772 int depth = 0;
773 char *root = str_dup (*req[0]);
774 int literal = is_literal_element (&root);
776 if (!root)
778 *rc = GPG_ERR_ENOMEM;
779 return NULL;
782 *rc = 0;
783 recursion_depth++;
785 if (max_recursion_depth >= 1 && recursion_depth > max_recursion_depth)
787 xmlChar *t = xmlGetNodePath (n);
789 log_write ("%s: %s", pwmd_strerror (GPG_ERR_ELOOP), t);
790 xmlFree (t);
791 xfree (root);
792 *rc = GPG_ERR_ELOOP;
793 return NULL;
796 while (n)
798 if (n->type == XML_ELEMENT_NODE)
800 if (depth == 0 && xmlStrEqual (n->name, (xmlChar *) "pwmd"))
802 n = n->children;
803 depth++;
804 continue;
807 if (depth == 1 && xmlStrEqual (n->name, (xmlChar *) "element"))
809 xmlChar *content = node_has_attribute (n, (xmlChar *) "_name");
811 if (!content)
812 continue;
814 if (xmlStrEqual (content, (xmlChar *) root))
816 char **nreq, **tmp = NULL;
817 int acl = client->flags & FLAG_ACL_IGNORE;
819 *rc = acl_check(client, n);
820 if ((*rc && *rc != GPG_ERR_EACCES)
821 || (*rc == GPG_ERR_EACCES && !acl))
823 xmlFree (content);
824 xfree (root);
825 return n;
828 if (acl)
830 *rc = 0;
831 // This flag is cleared in acl_check() but we always
832 // allow ATTR LIST of root elements.
833 client->flags |= FLAG_ACL_IGNORE;
836 if (literal == 1)
838 xmlFree (content);
839 xfree (root);
840 return n;
843 xmlFree (content);
844 content = node_has_attribute (n, (xmlChar *) "target");
846 if (content && target)
847 *target = 1;
849 if (!content || stop)
851 if (content)
852 xmlFree (content);
854 xfree (root);
855 return n;
858 if (strchr ((char *) content, '\t'))
860 nreq = str_split ((char *) content, "\t", 0);
861 xmlFree (content);
863 #if 0
865 * FIXME ENOMEM
867 if (!nreq)
869 *rc = GPG_ERR_ENOMEM;
870 return NULL;
872 #endif
874 tmp = *req;
875 tmp = strv_catv (nreq, tmp + 1);
876 strv_free (nreq);
878 if (!tmp)
880 xfree (root);
881 *rc = GPG_ERR_ENOMEM;
882 return NULL;
885 strv_free (*req);
886 *req = tmp;
888 else
890 if (strv_printf (&tmp, "%s", content) == 0)
892 xmlFree (content);
893 xfree (root);
894 *rc = GPG_ERR_ENOMEM;
895 return NULL;
898 xmlFree (content);
899 nreq = *req;
900 nreq = strv_catv (tmp, nreq + 1);
901 strv_free (tmp);
903 if (!nreq)
905 *rc = GPG_ERR_ENOMEM;
906 xfree (root);
907 return NULL;
910 strv_free (*req);
911 *req = nreq;
914 xfree (root);
915 return find_root_element (client, doc, req, rc, target,
916 recursion_depth, 0);
919 xmlFree (content);
923 n = n->next;
926 xfree (root);
927 *rc = GPG_ERR_ELEMENT_NOT_FOUND;
928 return NULL;
931 xmlNodePtr
932 find_element (struct client_s *client, xmlNodePtr node, char *element,
933 xmlNodePtr stop, gpg_error_t *rc)
935 xmlNodePtr n;
937 *rc = 0;
939 if (!node || !element)
940 return NULL;
942 for (n = node; n; n = n->next)
944 if (n->type != XML_ELEMENT_NODE)
945 continue;
947 if (n == stop)
948 break;
950 xmlChar *a = node_has_attribute (n, (xmlChar *) "_name");
952 if (a && xmlStrEqual (a, (xmlChar *) element))
954 xmlFree (a);
956 // Prevent ATTR LIST showing child element attributes for a parent
957 // whos ACL denies the client.
958 if (client->flags & FLAG_ACL_ERROR)
960 *rc = GPG_ERR_EACCES;
961 return NULL;
964 *rc = acl_check(client, n);
965 if (*rc)
966 n = NULL;
968 return n;
971 xmlFree (a);
974 return NULL;
977 xmlChar *
978 node_has_attribute (xmlNodePtr n, xmlChar * attr)
980 xmlAttrPtr a = xmlHasProp (n, attr);
982 if (!a)
983 return NULL;
985 if (!a->children || !a->children->content)
986 return NULL;
988 return xmlGetProp (n, attr);
991 static int
992 element_to_literal (char **element)
994 char *p = str_asprintf ("!%s", *element);
996 if (!p)
997 return 0;
999 xfree (*element);
1000 *element = p;
1001 return 1;
1004 /* Resolves elements in 'req' one at a time. It's recursive in case of
1005 * "target" attributes. */
1006 xmlNodePtr
1007 find_elements (struct client_s *client, xmlDocPtr doc, xmlNodePtr node,
1008 char **req, gpg_error_t * rc, int *target,
1009 xmlNodePtr (*found_fn) (struct client_s *, xmlNodePtr, char **,
1010 gpg_error_t *, char **, void *),
1011 xmlNodePtr (*not_found_fn) (struct client_s *, int, xmlNodePtr,
1012 char **, gpg_error_t *, void *),
1013 int is_list_command, int recursion_depth, void *data, int stop)
1015 xmlNodePtr n, last, last_node;
1016 char **p;
1017 int found = 0;
1019 *rc = 0;
1020 recursion_depth++;
1022 if (max_recursion_depth >= 1 && recursion_depth > max_recursion_depth)
1024 xmlChar *t = xmlGetNodePath (node);
1026 log_write ("%s: %s", pwmd_strerror (GPG_ERR_ELOOP), t);
1027 xmlFree (t);
1028 recursion_depth--;
1029 *rc = GPG_ERR_ELOOP;
1030 return NULL;
1033 for (last_node = last = n = node, p = req; *p; p++)
1035 xmlNodePtr tmp;
1036 char *t;
1037 int literal;
1039 if (!*(*p))
1041 *rc = GPG_ERR_ELEMENT_NOT_FOUND;
1042 return NULL;
1045 t = str_dup (*p);
1046 if (!t)
1048 *rc = GPG_ERR_ENOMEM;
1049 return NULL;
1052 literal = is_literal_element (&t);
1053 n = find_element (client, last, t, NULL, rc);
1054 xfree (t);
1055 if (!n)
1057 if (!*rc)
1058 *rc = GPG_ERR_ELEMENT_NOT_FOUND;
1060 /* Fixes ATTR LIST when an element does not exist and the parent
1061 * denies access to children. Fixes leaking information about the
1062 * current elements children. */
1063 if (*rc == GPG_ERR_ELEMENT_NOT_FOUND && last_node != n)
1065 gpg_error_t trc = acl_check (client, last_node);
1066 if (trc)
1067 *rc = trc;
1070 if (not_found_fn)
1071 return not_found_fn (client, 0,
1072 found ? last_node : last_node->parent, p,
1073 rc, data);
1074 return NULL;
1077 last = n->children;
1078 last_node = n;
1079 found = 1;
1081 if (literal == 0)
1083 xmlChar *content = node_has_attribute (n, (xmlChar *) "target");
1084 char **nreq = NULL, **nnreq;
1086 if (!content)
1088 if (is_list_command == 1)
1090 if (element_to_literal (&(*p)) == 0)
1092 *rc = GPG_ERR_ENOMEM;
1093 return NULL;
1097 continue;
1100 if (target)
1101 *target = 1;
1103 if (!*(p + 1) && stop)
1105 xmlFree (content);
1106 return n;
1109 if (strchr ((char *) content, '\t') != NULL)
1111 if ((nreq = str_split ((char *) content, "\t", 0)) == NULL)
1113 xmlFree (content);
1114 *rc = GPG_ERR_INV_VALUE;
1115 return NULL;
1118 else
1120 if ((nreq = str_split ((char *) content, " ", 0)) == NULL)
1122 xmlFree (content);
1123 *rc = GPG_ERR_INV_VALUE;
1124 return NULL;
1128 xmlFree (content);
1129 tmp = find_root_element (client, doc, &nreq, rc, target, 0, 0);
1130 if (*rc)
1132 strv_free (nreq);
1133 if (not_found_fn && *rc == GPG_ERR_EACCES)
1134 return not_found_fn (client, 0, NULL, p, rc, data);
1135 return tmp;
1138 if (found_fn)
1140 found_fn (client, tmp, nreq, rc, p + 1, data);
1142 if (*rc)
1144 strv_free (nreq);
1145 return NULL;
1149 if (!*(nreq + 1) && !*(p + 1))
1151 strv_free (nreq);
1152 return tmp;
1155 nnreq = strv_catv (nreq + 1, p + 1);
1156 strv_free (nreq);
1158 // FIXME ENOMEM
1159 if (!nnreq || !*nnreq)
1161 strv_free (nnreq);
1162 return tmp;
1165 if (tmp->children)
1167 n = find_elements (client, doc, tmp->children, nnreq, rc, NULL,
1168 found_fn, not_found_fn, is_list_command,
1169 recursion_depth, data, stop);
1170 if (!n)
1172 strv_free (nnreq);
1173 return NULL;
1176 else
1178 strv_free (nnreq);
1179 if (not_found_fn)
1180 return not_found_fn (client, 0, tmp, p, rc, data);
1182 *rc = GPG_ERR_ELEMENT_NOT_FOUND;
1183 return NULL;
1186 if (*(p + 1))
1188 char **zz = p + 1, **qq = nnreq;
1190 if (strv_length (nnreq) > strv_length (p + 1))
1191 qq = nnreq + 1;
1193 for (; *qq && *zz; zz++)
1195 xfree (*zz);
1196 *zz = str_dup (*qq++);
1198 if (!*zz)
1200 *rc = GPG_ERR_ENOMEM;
1201 n = NULL;
1202 break;
1207 strv_free (nnreq);
1208 return n;
1212 return n;
1215 static int
1216 update_element_list (struct element_list_s *elements)
1218 char *line;
1219 struct slist_s *l;
1221 if (!elements || !elements->elements)
1222 return 1;
1224 line = strv_join ("\t", elements->elements);
1226 if (!line)
1227 return 0;
1229 strv_free (elements->elements);
1230 elements->elements = NULL;
1231 l = slist_append (elements->list, line);
1233 if (!l)
1234 return 0;
1236 elements->list = l;
1237 return 1;
1240 static gpg_error_t
1241 path_list_recurse (struct client_s *client, xmlDocPtr doc, xmlNodePtr node,
1242 struct element_list_s *elements)
1244 gpg_error_t rc = 0;
1245 xmlNodePtr n;
1246 gpg_error_t error_flag = 0;
1248 for (n = node; n; n = n->next)
1250 xmlChar *target = NULL;
1251 xmlChar *a = node_has_attribute (n, (xmlChar *) "_name");
1252 gpg_error_t err = 0;
1253 char *path = NULL;
1255 rc = 0;
1256 if (!a)
1257 continue;
1259 if (n->type != XML_ELEMENT_NODE)
1260 goto children;
1262 rc = acl_check(client, n);
1264 if (elements->verbose)
1266 if (strv_printf
1267 (&elements->elements, "%s\t!%s%s%s", elements->prefix, a,
1268 !rc && find_element_node (n->children) ? " +" : "",
1269 rc == GPG_ERR_EACCES ? " P" : rc ? " E" : "") == 0)
1271 xmlFree (a);
1272 return GPG_ERR_ENOMEM;
1275 else
1276 if (strv_printf (&elements->elements, "%s\t!%s", elements->prefix, a)
1277 == 0)
1279 xmlFree (a);
1280 return GPG_ERR_ENOMEM;
1283 if (update_element_list (elements) == 0)
1285 xmlFree (a);
1286 return GPG_ERR_ENOMEM;
1289 if (rc == GPG_ERR_EACCES)
1291 xmlFree(a);
1292 error_flag = rc;
1293 continue;
1295 else if (rc)
1297 xmlFree (a);
1298 return rc;
1301 target = node_has_attribute (n, (xmlChar *) "target");
1302 if (target)
1304 char *tmp;
1305 char *save = elements->prefix;
1306 int r = elements->resolving;
1307 char **req = NULL;
1308 xmlNodePtr tnode;
1309 struct string_s *realpath = NULL;
1311 tnode = resolve_path (client, doc, target, &req, &rc);
1312 if (rc == GPG_ERR_ELOOP || rc == GPG_ERR_ELEMENT_NOT_FOUND
1313 || rc == GPG_ERR_EACCES)
1315 if (rc == GPG_ERR_ELOOP)
1317 xmlChar *t = xmlGetNodePath (n);
1319 log_write ("%s: %s", pwmd_strerror (GPG_ERR_ELOOP), t);
1320 xmlFree (t);
1323 if (elements->verbose)
1325 error_flag = err = rc;
1326 rc = 0;
1329 else if (!elements->verbose && rc)
1331 xmlFree (a);
1332 xmlFree (target);
1333 return rc;
1336 path = str_asprintf("%s\t%s", elements->prefix, a);
1337 rc = validate_target_attribute (client, client->doc, path, tnode);
1338 xfree (path);
1339 if (rc == GPG_ERR_ELOOP || rc == GPG_ERR_EACCES
1340 || rc == GPG_ERR_ELEMENT_NOT_FOUND)
1342 if (rc != GPG_ERR_ELEMENT_NOT_FOUND)
1343 error_flag = err = rc;
1345 rc = 0;
1347 else if (rc)
1349 xmlFree (a);
1350 xmlFree (target);
1351 return rc;
1354 if (err)
1356 strv_printf (&elements->elements, "%s\t%s %s%s%s",
1357 elements->prefix, a,
1358 err == GPG_ERR_ELOOP ? "O" :
1359 err == GPG_ERR_EACCES ? "P" : "E",
1360 elements->with_target ? "T " : "",
1361 elements->with_target ? (char *)target : "");
1363 else if (!err && elements->with_target)
1365 rc = build_realpath (client, doc, (char *) target, &realpath);
1366 if (rc)
1368 xmlFree (a);
1369 xmlFree (target);
1370 return rc;
1373 realpath = string_prepend (realpath, "T ");
1376 if (!err && elements->verbose)
1378 if (!strv_printf (&elements->elements, "%s\t%s%s%s%s",
1379 elements->prefix, a,
1380 (tnode && find_element_node (tnode->children))
1381 || realpath ? " " : "", tnode
1382 && find_element_node (tnode->children) ? "+" :
1383 "", realpath ? realpath->str : ""))
1385 xmlFree (a);
1386 xmlFree (target);
1387 return GPG_ERR_ENOMEM;
1390 else if (!err)
1391 if (!strv_printf
1392 (&elements->elements, "%s\t%s", elements->prefix, a))
1394 xmlFree (a);
1395 xmlFree (target);
1396 return GPG_ERR_ENOMEM;
1399 if (realpath)
1400 string_free (realpath, 1);
1402 tmp = strv_join ("\t", elements->elements);
1403 if (!tmp)
1405 xmlFree (a);
1406 xmlFree (target);
1407 return GPG_ERR_ENOMEM;
1410 if (update_element_list (elements) == 0)
1412 xfree (tmp);
1413 xmlFree (a);
1414 xmlFree (target);
1415 return GPG_ERR_ENOMEM;
1418 if (!err && elements->recurse)
1420 /* Prune element flags. */
1421 if (elements->verbose && strchr (tmp, ' '))
1423 char *p;
1425 for (p = tmp; *p; p++)
1427 if (*p == ' ')
1429 *p = 0;
1430 break;
1435 elements->prefix = tmp;
1436 elements->resolving = 1;
1437 rc = create_path_list (client, doc, elements, (char *) target);
1438 elements->resolving = r;
1439 elements->prefix = save;
1441 if (rc && gpg_err_code (rc) != GPG_ERR_ELOOP
1442 && gpg_err_code(rc) != GPG_ERR_EACCES)
1444 xfree (tmp);
1445 xmlFree (target);
1446 xmlFree (a);
1447 return rc;
1450 error_flag = err = rc;
1451 rc = 0;
1454 xfree (tmp);
1455 xmlFree (target);
1458 children:
1459 if (n->children && elements->recurse)
1461 char *tmp = str_asprintf ("%s\t!%s", elements->prefix, a);
1462 char *save = elements->prefix;
1464 if (!tmp)
1466 xmlFree (a);
1467 return GPG_ERR_ENOMEM;
1470 elements->prefix = tmp;
1471 rc = path_list_recurse (client, doc, n->children, elements);
1472 xfree (elements->prefix);
1473 elements->prefix = save;
1475 if (rc)
1477 if (gpg_err_code(rc) == GPG_ERR_ELOOP
1478 || gpg_err_code (rc) == GPG_ERR_EACCES
1479 || gpg_err_code (rc) == GPG_ERR_ELEMENT_NOT_FOUND)
1481 error_flag = err = rc;
1482 rc = 0;
1484 else
1486 xmlFree (a);
1487 return rc;
1492 xmlFree (a);
1495 return error_flag == GPG_ERR_ELOOP || error_flag == GPG_ERR_EACCES
1496 ? error_flag : rc;
1499 gpg_error_t
1500 add_attribute (struct client_s *client, xmlNodePtr node, const char *name,
1501 const char *value)
1503 char *buf;
1504 gpg_error_t rc = 0;
1506 if (client && name && !strcmp (name, "target"))
1508 rc = is_element_owner (client, node);
1509 if (rc)
1510 return rc;
1513 if (name && !xmlSetProp (node, (xmlChar *) name, (xmlChar *) value))
1514 return GPG_ERR_BAD_DATA;
1516 if (client && name && !xmlStrEqual ((xmlChar *) name, (xmlChar *) "_acl"))
1518 xmlChar *acl = node_has_attribute (node, (xmlChar *) "_acl");
1520 if (!acl)
1522 char *user = create_acl_user (client);
1524 if (user)
1526 rc = add_attribute (client, node, (char *) "_acl", user);
1527 xfree (user);
1530 return rc;
1533 xmlFree (acl);
1536 if (name && xmlStrEqual ((xmlChar *) name, (xmlChar *) "_mtime"))
1537 return 0;
1539 buf = str_asprintf ("%li", time (NULL));
1540 rc = add_attribute (client, node, "_mtime", buf);
1541 xfree (buf);
1542 return rc;
1545 static xmlNodePtr
1546 list_not_found_cb (struct client_s *client, int i, xmlNodePtr node,
1547 char **req, gpg_error_t *rc, void *data)
1549 struct element_list_s *elements = data;
1551 if (*rc != GPG_ERR_EACCES)
1552 return NULL;
1554 elements->data = strv_dup (req);
1555 return NULL;
1559 * From the element path 'path', find sub-nodes and append them to the list.
1561 gpg_error_t
1562 create_path_list (struct client_s *client, xmlDocPtr doc,
1563 struct element_list_s * elements, char *path)
1565 gpg_error_t rc;
1566 char **req, **req_orig;
1567 xmlNodePtr n;
1568 int a_target = 0;
1569 int root_only = 0;
1570 int allowed = 1;
1572 req = str_split (path, "\t", 0);
1573 if (!req)
1575 req = str_split (path, " ", 0);
1576 if (!req)
1577 return GPG_ERR_SYNTAX;
1580 req_orig = strv_dup (req);
1581 if (!req_orig)
1583 rc = GPG_ERR_ENOMEM;
1584 goto fail;
1587 n = find_root_element (client, doc, &req, &rc, &a_target, 0, 0);
1588 if ((rc == GPG_ERR_ELEMENT_NOT_FOUND || rc == GPG_ERR_ELOOP
1589 || rc == GPG_ERR_EACCES) && elements->verbose && a_target)
1591 if (rc == GPG_ERR_EACCES)
1592 allowed = 0;
1594 root_only = 1;
1595 goto done;
1598 if (rc == GPG_ERR_EACCES)
1600 allowed = 0;
1601 root_only = 1;
1602 goto done;
1605 if (!n && rc == GPG_ERR_ELEMENT_NOT_FOUND && elements->resolving == 1)
1607 rc = 0;
1608 goto fail;
1610 else if (!n)
1611 goto fail;
1613 if (a_target == 1)
1615 xfree (*req);
1616 *req = str_dup (*req_orig);
1619 if (*(req + 1))
1621 int e_target = 0;
1623 n = find_elements (client, doc, n->children, req + 1, &rc, &e_target,
1624 NULL, list_not_found_cb, 1, 0, elements, 0);
1625 if (rc == GPG_ERR_ELEMENT_NOT_FOUND && elements->resolving == 1)
1627 rc = 0;
1628 goto fail;
1630 else if (rc && rc != GPG_ERR_EACCES)
1631 goto fail;
1632 else if (rc)
1633 allowed = 0;
1636 done:
1637 if (!elements->prefix)
1640 * FIXME
1642 * If any req_orig element contains no target the element should be
1643 * prefixed with the literal character. Not really crucial if the
1644 * client isn't human because child elements are prefixed for the
1645 * current path. But may be confusing if editing by hand.
1647 if (elements->data)
1649 /* This is needed to prune the original requested element path to the
1650 * length of the failed element in the path. */
1651 int x = strv_length (req_orig)-strv_length ((char **)elements->data);
1652 int i;
1653 char **tmp = NULL;
1655 for (i = 0; i <= x; i++)
1656 tmp = strv_cat (tmp, str_dup (req_orig[i]));
1658 elements->prefix = strv_join ("\t", tmp);
1659 strv_free (tmp);
1660 strv_free (elements->data);
1661 elements->data = NULL;
1663 else
1665 if (root_only)
1666 elements->prefix = str_dup (*req_orig);
1667 else
1668 elements->prefix = strv_join ("\t", req_orig);
1671 if (!elements->prefix)
1673 rc = GPG_ERR_ENOMEM;
1674 goto fail;
1677 if (elements->verbose)
1679 int ret;
1680 struct string_s *realpath = NULL;
1682 if (!rc && allowed && a_target && elements->with_target)
1684 rc = build_realpath (client, doc, path, &realpath);
1685 if (rc)
1686 goto fail;
1688 realpath = string_prepend (realpath, "T ");
1691 ret = strv_printf (&elements->elements, "%s%s%s%s%s%s%s",
1692 elements->prefix,
1693 (allowed && n && find_element_node (n->children))
1694 || realpath ? " " : "",
1695 (allowed && n && find_element_node (n->children)) ? "+" : "",
1696 allowed && realpath ? realpath->str : "",
1697 rc == GPG_ERR_ELOOP ? " O" : "",
1698 rc == GPG_ERR_ELEMENT_NOT_FOUND ? " E" : "",
1699 !allowed ? " P" : "");
1700 string_free (realpath, 1);
1701 if (!ret)
1703 rc = GPG_ERR_ENOMEM;
1704 goto fail;
1707 else
1709 if (strv_printf (&elements->elements, "%s", elements->prefix) == 0)
1711 rc = GPG_ERR_ENOMEM;
1712 goto fail;
1716 if (update_element_list (elements) == 0)
1718 rc = GPG_ERR_ENOMEM;
1719 goto fail;
1723 if (allowed)
1724 rc = path_list_recurse (client, doc, n ? n->children : n, elements);
1726 fail:
1727 strv_free (req_orig);
1728 strv_free (req);
1729 return rc;
1732 gpg_error_t
1733 recurse_xpath_nodeset (struct client_s *client, xmlDocPtr doc,
1734 xmlNodeSetPtr nodes, xmlChar * value,
1735 xmlBufferPtr * result, int cmd, const xmlChar * attr)
1737 int i = value ? nodes->nodeNr - 1 : 0;
1738 xmlBufferPtr buf;
1740 buf = xmlBufferCreate ();
1742 if (!buf)
1743 return GPG_ERR_ENOMEM;
1745 for (; value ? i >= 0 : i < nodes->nodeNr; value ? i-- : i++)
1747 xmlNodePtr n = nodes->nodeTab[i];
1748 gpg_error_t rc;
1750 if (!n)
1751 continue;
1753 if (!value && !attr)
1755 if (xmlNodeDump (buf, doc, n, 0, 0) == -1)
1757 *result = buf;
1758 return GPG_ERR_BAD_DATA;
1761 continue;
1764 if (!attr)
1766 xmlNodeSetContent (n, value);
1767 rc = update_element_mtime (client, n);
1769 if (rc)
1770 return rc;
1772 else
1774 if (!cmd)
1775 rc = add_attribute (client, n, (char *) attr, (char *) value);
1776 else
1777 rc = delete_attribute (client, n, attr);
1779 if (rc)
1780 return rc;
1784 *result = buf;
1785 return 0;
1788 static gpg_error_t
1789 convert_root_element (struct client_s *client, xmlNodePtr n)
1791 xmlChar *a = xmlGetProp (n, (xmlChar *) "_name");
1792 gpg_error_t rc;
1794 if (a)
1796 xmlFree (a);
1797 xmlChar *t = xmlGetNodePath (n);
1799 log_write (_
1800 ("An existing \"_name\" attribute already exists. Please rename this attribute before converting. Path is: %s"),
1802 xmlFree (t);
1803 return GPG_ERR_AMBIGUOUS_NAME;
1806 a = xmlGetProp (n, (xmlChar *) "name");
1808 if (a)
1810 rc = add_attribute (client, n, "_name", (char *) a);
1811 xmlFree (a);
1813 if (rc)
1814 return rc;
1816 rc = delete_attribute (client, n, (xmlChar *) "name");
1818 if (rc)
1819 return rc;
1821 xmlNodeSetName (n, (xmlChar *) "element");
1824 return 0;
1827 gpg_error_t
1828 delete_attribute (struct client_s *client, xmlNodePtr n, const xmlChar * name)
1830 xmlAttrPtr a;
1831 gpg_error_t rc = 0;
1833 if ((a = xmlHasProp (n, name)) == NULL)
1834 return GPG_ERR_NOT_FOUND;
1836 if (xmlRemoveProp (a) == -1)
1837 return GPG_ERR_BAD_DATA;
1839 if (client && xmlStrEqual (name, (xmlChar *) "_acl"))
1841 char *user = create_acl_user (client);
1843 rc = add_attribute (client, n, (char *) "_acl", user);
1844 xfree (user);
1846 if (rc)
1847 return rc;
1850 return update_element_mtime (client, n);
1853 static gpg_error_t
1854 convert_elements_recurse (struct client_s *client, xmlDocPtr doc,
1855 xmlNodePtr n, unsigned depth)
1857 gpg_error_t rc;
1859 depth++;
1861 for (n = n->children; n; n = n->next)
1863 if (n->type == XML_ELEMENT_NODE)
1865 if (depth > 1)
1867 xmlChar *a = NULL;
1869 if (xmlStrEqual (n->name, (xmlChar *) "element"))
1871 xmlChar *t = xmlGetNodePath (n);
1873 log_write (_
1874 ("An existing \"element\" already exists. Please rename this element before converting. Path is: %s"),
1876 xmlFree (t);
1877 return GPG_ERR_AMBIGUOUS_NAME;
1880 a = xmlGetProp (n, (xmlChar *) "_name");
1881 if (a)
1883 xmlFree (a);
1884 xmlChar *t = xmlGetNodePath (n);
1886 log_write (_
1887 ("An existing \"_name\" attribute already exists. Please rename this attribute before converting. Path is: %s"),
1889 xmlFree (t);
1890 return GPG_ERR_AMBIGUOUS_NAME;
1893 xmlChar *tmp = xmlStrdup (n->name);
1895 if (!tmp)
1896 return GPG_ERR_ENOMEM;
1898 xmlNodeSetName (n, (xmlChar *) "element");
1899 rc = add_attribute (client, n, "_name", (char *) tmp);
1900 xmlFree (tmp);
1902 if (rc)
1903 return rc;
1905 else
1907 rc = convert_root_element (client, n);
1909 if (rc)
1910 return rc;
1914 if (n->children)
1916 rc = convert_elements_recurse (client, doc, n, depth);
1918 if (rc)
1919 return rc;
1923 return 0;
1926 /* Renames ALL elements to the new "element" name. Existing element names are
1927 * stored as an attribute "_name". This was introduced in pwmd 2.12 so
1928 * elements can contain common characters that the XML parser barfs on (an
1929 * email address for example. */
1930 gpg_error_t
1931 convert_pre_212_elements (xmlDocPtr doc)
1933 xmlNodePtr n = xmlDocGetRootElement (doc);
1935 log_write (_("Converting pre 2.12 data file..."));
1936 return convert_elements_recurse (NULL, doc, n, 0);
1939 gpg_error_t
1940 validate_import (struct client_s *client, xmlNodePtr node)
1942 gpg_error_t rc = 0;
1944 if (!node)
1945 return 0;
1947 for (xmlNodePtr n = node; n; n = n->next)
1949 if (n->type == XML_ELEMENT_NODE)
1951 if (xmlStrEqual (n->name, (xmlChar *) "element"))
1953 xmlChar *a = xmlGetProp (n, (xmlChar *) "_name");
1955 if (!a)
1957 xmlChar *t = xmlGetNodePath (n);
1959 log_write (_("Missing attribute '_name' at %s."), t);
1960 xmlFree (t);
1961 return GPG_ERR_INV_VALUE;
1964 if (!valid_xml_element (a))
1966 xmlChar *t = xmlGetNodePath (n);
1968 log_write (_("'%s' is not a valid element name at %s."), a,
1970 xmlFree (a);
1971 xmlFree (t);
1972 return GPG_ERR_INV_VALUE;
1975 xmlFree (a);
1976 a = xmlGetProp (n, (xmlChar *) "_ctime");
1977 if (!a)
1978 attr_ctime (client, n);
1980 xmlFree (a);
1981 a = xmlGetProp (n, (xmlChar *) "_mtime");
1982 if (!a)
1983 update_element_mtime (client, n);
1984 xmlFree (a);
1986 else
1988 xmlChar *t = xmlGetNodePath (n);
1990 log_write (_("Warning: unknown element '%s' at %s. Ignoring."),
1991 n->name, t);
1992 xmlFree (t);
1993 continue;
1997 if (n->children)
1999 rc = validate_import (client, n->children);
2001 if (rc)
2002 return rc;
2006 return rc;
2009 gpg_error_t
2010 update_element_mtime (struct client_s *client, xmlNodePtr n)
2012 return add_attribute (client, n, NULL, NULL);
2015 gpg_error_t
2016 unlink_node (struct client_s *client, xmlNodePtr n)
2018 gpg_error_t rc = 0;
2020 if (!n)
2021 return rc;
2023 if (n->parent)
2024 rc = update_element_mtime (client, n->parent);
2026 xmlUnlinkNode (n);
2027 return rc;
2030 gpg_error_t
2031 parse_doc (const char *xml, size_t len, xmlDocPtr *result)
2033 xmlDocPtr doc;
2035 xmlResetLastError ();
2036 doc = xmlReadMemory (xml, len, NULL, "UTF-8", XML_PARSE_NOBLANKS);
2037 if (!doc && xmlGetLastError ())
2038 return GPG_ERR_BAD_DATA;
2040 *result = doc;
2041 return !doc ? GPG_ERR_ENOMEM : 0;
2044 static xmlNodePtr
2045 realpath_elements_cb (struct client_s *client, xmlNodePtr node, char **target,
2046 gpg_error_t * rc, char **req_orig, void *data)
2048 char *path = *(char **) data;
2049 char *tmp = NULL, *result;
2051 if (path)
2053 xfree (path);
2054 *(char **) data = NULL;
2057 path = strv_join ("\t", target);
2059 if (!path)
2061 *rc = GPG_ERR_ENOMEM;
2062 return NULL;
2065 if (req_orig)
2067 tmp = strv_join ("\t", req_orig);
2069 if (!tmp)
2071 xfree (path);
2072 *rc = GPG_ERR_ENOMEM;
2073 return NULL;
2077 if (tmp && *tmp)
2078 result = str_asprintf ("%s\t%s", path, tmp);
2079 else
2080 result = str_dup (path);
2082 if (!result)
2084 *rc = GPG_ERR_ENOMEM;
2085 xfree (path);
2086 xfree (tmp);
2087 return NULL;
2090 xfree (path);
2091 xfree (tmp);
2092 *(char **) data = result;
2093 return node;
2096 gpg_error_t
2097 build_realpath (struct client_s *client, xmlDocPtr doc, char *line,
2098 struct string_s ** result)
2100 gpg_error_t rc;
2101 char **req;
2102 char *t;
2103 int i;
2104 xmlNodePtr n;
2105 struct string_s *string;
2106 char *rp = NULL;
2108 if (strchr (line, '\t') != NULL)
2110 if ((req = str_split (line, "\t", 0)) == NULL)
2111 return GPG_ERR_SYNTAX;
2113 else
2115 if ((req = str_split (line, " ", 0)) == NULL)
2116 return GPG_ERR_SYNTAX;
2119 n = find_root_element (client, doc, &req, &rc, NULL, 0, 0);
2120 if (rc)
2122 strv_free (req);
2123 return rc;
2126 rp = strv_join ("\t", req);
2127 if (!rp)
2129 strv_free (req);
2130 return GPG_ERR_ENOMEM;
2133 if (req[1])
2135 n = find_elements (client, doc, n->children, req + 1, &rc, NULL,
2136 realpath_elements_cb, NULL, 0, 0, &rp, 0);
2137 if (!n)
2139 xfree (rp);
2140 strv_free (req);
2141 return rc;
2145 string = string_new (rp);
2146 xfree (rp);
2147 strv_free (req);
2148 if (!string)
2149 return GPG_ERR_ENOMEM;
2151 again:
2152 for (i = 0, t = string->str + i; *t; t++, i++)
2154 if ((!i && *t != '!') || (*t == '\t' && *(t + 1) && *(t + 1) != '!'))
2156 struct string_s *s = string_insert_c (string, !i ? i++ : ++i, '!');
2158 if (!s)
2160 string_free (string, 1);
2161 return GPG_ERR_ENOMEM;
2164 string = s;
2165 goto again;
2169 *result = string;
2170 return rc;
2173 #if 0
2174 static char *
2175 node_to_element_path (xmlNodePtr node)
2177 xmlNodePtr n;
2178 struct string_s *str = string_new ("");
2179 char *result;
2181 for (n = node; n; n = n->parent)
2183 xmlNodePtr child;
2185 for (child = n; child; child = child->next)
2187 if (child->type != XML_ELEMENT_NODE)
2188 continue;
2190 xmlChar *name = node_has_attribute (n, (xmlChar *) "_name");
2191 if (name)
2193 str = string_prepend (str, (char *) name);
2194 xmlFree (name);
2195 name = node_has_attribute (n, (xmlChar *) "target");
2196 if (name)
2197 str = string_prepend (str, "\t");
2198 else
2199 str = string_prepend (str, "\t!");
2200 xmlFree (name);
2202 break;
2206 str = string_erase (str, 0, 1);
2207 result = str->str;
2208 string_free (str, 0);
2209 return result;
2211 #endif
2214 * Recurse the element tree beginning at 'node' and find elements who point
2215 * back to 'src' or 'dst'. Also follows target attributes.
2217 static gpg_error_t
2218 find_child_to_target (struct client_s *client, xmlDocPtr doc, xmlNodePtr node,
2219 xmlNodePtr src, xmlNodePtr dst, unsigned depth,
2220 int is_target)
2222 xmlNodePtr n;
2223 gpg_error_t rc = 0;
2225 if (max_recursion_depth >= 1 && depth > max_recursion_depth)
2226 return gpg_error (GPG_ERR_ELOOP);
2228 for (n = node; n; n = n->next)
2230 xmlChar *target;
2232 if (n->type != XML_ELEMENT_NODE)
2233 continue;
2235 if (n == src || n == dst)
2236 return GPG_ERR_ELOOP;
2238 target = node_has_attribute (n, (xmlChar *) "target");
2239 if (target)
2241 xmlNodePtr tmp;
2242 char **result = NULL;
2244 tmp = resolve_path (client, doc, target, &result, &rc);
2245 xmlFree (target);
2246 strv_free (result);
2247 if (!rc)
2249 rc = find_child_to_target (client, doc, tmp, src, dst, ++depth,
2251 depth--;
2254 if (rc && gpg_err_code (rc) != GPG_ERR_ELEMENT_NOT_FOUND)
2255 return rc;
2257 if (is_target)
2258 break;
2260 continue;
2263 if (n->children)
2265 rc = find_child_to_target (client, doc, n->children, src, dst,
2266 ++depth,0);
2267 depth--;
2268 if (rc)
2269 return rc;
2272 if (is_target)
2273 break;
2276 return rc;
2279 static gpg_error_t
2280 find_child_of_parent (xmlDocPtr doc, xmlNodePtr src, xmlNodePtr dst)
2282 xmlNodePtr n;
2283 gpg_error_t rc = 0;
2285 for (n = src; n; n = n->next)
2287 if (n->type != XML_ELEMENT_NODE)
2288 continue;
2290 if (n == dst)
2292 rc = GPG_ERR_ELOOP;
2293 break;
2296 rc = find_child_of_parent (doc, n->children, dst);
2299 return rc;
2302 static gpg_error_t
2303 find_parent_of_child (xmlDocPtr doc, xmlNodePtr node, xmlNodePtr dst)
2305 xmlNodePtr n;
2306 gpg_error_t rc = 0;
2308 for (n = node; n; n = n->parent)
2310 if (n->type != XML_ELEMENT_NODE)
2312 xmlNodePtr tmp;
2314 for (tmp = n->next; tmp; n = n->next)
2316 if (n->type != XML_ELEMENT_NODE)
2317 continue;
2319 if (tmp == dst)
2320 return GPG_ERR_ELOOP;
2324 if (n == dst)
2325 return GPG_ERR_ELOOP;
2328 return rc;
2331 gpg_error_t
2332 validate_target_attribute (struct client_s *client, xmlDocPtr doc,
2333 const char *src, xmlNodePtr dst_node)
2335 gpg_error_t rc;
2336 xmlNodePtr src_node;
2337 char **src_req = NULL;
2339 src_node = resolve_path (client, doc, (xmlChar *) src, &src_req, &rc);
2340 if (rc)
2341 goto fail;
2343 client->flags |= FLAG_ACL_IGNORE;
2344 /* A destination element is a child of the source element. */
2345 rc = find_child_of_parent (doc, src_node->children, dst_node);
2346 if (rc)
2347 goto fail;
2349 /* The destination element is a parent of the source element. */
2350 rc = find_parent_of_child (doc, src_node->parent, dst_node);
2351 if (rc)
2352 goto fail;
2354 /* A destination child element contains a target to the source element. */
2355 if (dst_node)
2356 rc = find_child_to_target (client, doc, dst_node->children, src_node,
2357 dst_node, 0, 0);
2358 if (rc)
2359 goto fail;
2361 fail:
2362 strv_free (src_req);
2363 client->flags &= ~(FLAG_ACL_IGNORE | FLAG_ACL_ERROR);
2364 return rc;
2367 /* The owner of the element is the first user listed in the _acl attribute
2368 * list. acl_check() should be called before calling this function. An empty
2369 * ACL is an error if the client is not invoking_user.
2371 gpg_error_t
2372 is_element_owner (struct client_s *client, xmlNodePtr n)
2374 xmlChar *acl = node_has_attribute (n, (xmlChar *) "_acl");
2375 char **users;
2376 gpg_error_t rc = GPG_ERR_EACCES;
2378 if (!acl || !*acl)
2380 xmlFree (acl);
2381 return peer_is_invoker (client);
2384 users = str_split((char *)acl, ",", 0);
2385 if (users && *users)
2387 char *user;
2389 #ifdef WITH_GNUTLS
2390 if (client->thd->remote)
2391 user = str_asprintf ("#%s", client->thd->tls->fp);
2392 else
2393 user = get_username (client->thd->peer->uid);
2394 #else
2395 user = get_username (client->thd->peer->uid);
2396 #endif
2398 if (*user == '#')
2399 rc = !strcasecmp (*users, user) ? 0 : GPG_ERR_EACCES;
2400 else
2401 rc = !strcmp (*users, user) ? 0 : GPG_ERR_EACCES;
2403 if (rc)
2404 rc = peer_is_invoker (client);
2406 xfree (user);
2409 xmlFree (acl);
2410 strv_free (users);
2411 return rc;