Set the TLS audit log callback.
[pwmd.git] / src / xml.c
blobfce76e741806b16d8755b8e479bbbf02819b2478
1 /*
2 Copyright (C) 2006, 2007, 2008, 2009, 2010, 2011, 2012, 2013, 2014, 2015
3 Ben Kibbey <bjk@luxsci.net>
5 This file is part of pwmd.
7 Pwmd is free software: you can redistribute it and/or modify
8 it under the terms of the GNU General Public License as published by
9 the Free Software Foundation, either version 2 of the License, or
10 (at your option) any later version.
12 Pwmd is distributed in the hope that it will be useful,
13 but WITHOUT ANY WARRANTY; without even the implied warranty of
14 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
15 GNU General Public License for more details.
17 You should have received a copy of the GNU General Public License
18 along with Pwmd. If not, see <http://www.gnu.org/licenses/>.
20 #ifdef HAVE_CONFIG_H
21 #include <config.h>
22 #endif
24 #include <stdio.h>
25 #include <stdlib.h>
26 #include <unistd.h>
27 #include <err.h>
28 #include <string.h>
29 #include <sys/stat.h>
30 #include <fcntl.h>
31 #include <ctype.h>
32 #include <libxml/xmlwriter.h>
33 #include <wctype.h>
34 #include <sys/types.h>
35 #include <pwd.h>
37 #ifndef _
38 #include "gettext.h"
39 #define _(msgid) gettext(msgid)
40 #endif
42 #include "pwmd-error.h"
43 #include "util-misc.h"
44 #include "xml.h"
45 #include "mem.h"
46 #include "rcfile.h"
47 #include "commands.h"
49 extern void log_write (const char *fmt, ...);
52 * 'element' must be allocated.
54 int
55 is_literal_element (char **element)
57 char *p;
59 if (!element || !*element)
60 return 0;
62 if (*(*element) == '!')
64 char *c;
66 for (p = *element, c = p + 1; *c; c++)
67 *p++ = *c;
69 *p = 0;
70 return 1;
73 return 0;
76 int
77 valid_xml_attribute (const char *str)
79 wchar_t *wc;
80 size_t len, c;
81 int ret = valid_xml_element ((xmlChar *)str);
83 if (!ret)
84 return ret;
86 wc = str_to_wchar ((const char *)str);
87 if (!wc)
88 return 0;
90 len = wcslen (wc);
91 for (c = 0; c < len; c++)
93 switch (wc[c])
95 case '-':
96 case '.':
97 case '0' ... '9':
98 case 0xB7:
99 case 0x0300 ... 0x036F:
100 case 0x203F ... 0x2040:
101 if (!c)
103 xfree (wc);
104 return 0;
106 case ':': break;
107 case '_': break;
108 case 'A' ... 'Z': break;
109 case 'a' ... 'z': break;
110 case 0xC0 ... 0xD6: break;
111 case 0xD8 ... 0xF6: break;
112 case 0xF8 ... 0x2FF: break;
113 case 0x370 ... 0x37D: break;
114 case 0x37F ... 0x1FFF: break;
115 case 0x200C ... 0x200D: break;
116 case 0x2070 ... 0x218F: break;
117 case 0x2C00 ... 0x2FEF: break;
118 case 0x3001 ... 0xD7FF: break;
119 case 0xF900 ... 0xFDCF: break;
120 case 0xFDF0 ... 0xFFFD: break;
121 case 0x10000 ... 0xEFFFF: break;
122 default:
123 xfree (wc);
124 return 0;
128 xfree (wc);
129 return 1;
133 valid_xml_element (xmlChar *str)
135 wchar_t *wc;
136 size_t len, c;
138 if (!str || !*str || *str == '!')
139 return 0;
141 wc = str_to_wchar ((const char *)str);
142 if (!wc)
143 return 0;
145 len = wcslen (wc);
146 for (c = 0; c < len; c++)
148 if (iswspace(wc[c]))
150 xfree (wc);
151 return 0;
155 xfree (wc);
156 return 1;
160 valid_element_path (char **path, int with_content)
162 char **dup = NULL, **p;
164 if (!path || !*path)
165 return 0;
167 /* Save some memory by not duplicating the element content. */
168 if (with_content)
170 int i, t = strv_length (path);
172 for (i = 0; i < t - 1; i++)
174 char **tmp = xrealloc (dup, (i + 2) * sizeof (char *));
176 if (!tmp)
178 strv_free (dup);
179 return 0;
182 dup = tmp;
183 dup[i] = str_dup (path[i]);
184 dup[i + 1] = NULL;
187 else
188 dup = strv_dup (path);
190 if (!dup)
191 return 0;
193 for (p = dup; *p && *(*p); p++)
195 is_literal_element (&(*p));
196 if (!valid_xml_element ((xmlChar *) * p))
198 strv_free (dup);
199 return 0;
203 strv_free (dup);
204 return 1;
207 gpg_error_t
208 attr_ctime (struct client_s *client, xmlNodePtr n)
210 char *buf = str_asprintf ("%li", time (NULL));
211 gpg_error_t rc;
213 if (!buf)
214 return GPG_ERR_ENOMEM;
216 rc = add_attribute (client, n, "_ctime", buf);
217 xfree (buf);
218 return rc;
221 static gpg_error_t
222 acl_check (struct client_s *client, xmlNodePtr n)
224 gpg_error_t rc = GPG_ERR_EACCES;
225 xmlChar *acl = node_has_attribute (n, (xmlChar *) "_acl");
226 char **users = acl ? str_split((char *)acl, ",", 0) : NULL;
227 char **p;
228 int allowed = 0;
230 if (!acl || !*acl || !users || !*users)
232 xmlFree (acl);
233 strv_free(users);
234 return peer_is_invoker(client);
237 if (!peer_is_invoker(client))
238 return 0;
240 for (p = users; *p; p++)
242 #ifdef WITH_GNUTLS
243 rc = acl_check_common (client, *p,
244 client->thd->remote ? 0 : client->thd->peer->uid,
245 client->thd->remote ? 0 : client->thd->peer->gid,
246 &allowed);
247 #else
248 rc = acl_check_common (client, *p, client->thd->peer->uid,
249 client->thd->peer->gid, &allowed);
250 #endif
253 xmlFree(acl);
254 strv_free(users);
256 // ATTR LIST makes use of FLAG_ACL_IGNORE to allow listing of element
257 // attributes that the client is not normally allowed access to.
258 if ((rc == GPG_ERR_EACCES || !allowed) && client->flags & FLAG_ACL_IGNORE)
260 rc = 0;
261 client->flags &= ~FLAG_ACL_IGNORE;
263 // This flag is used in ATTR LIST to prevent listing attributes of
264 // children whose parent ACL does not allow access to the client.
265 client->flags |= FLAG_ACL_ERROR;
266 allowed = 1;
269 if (rc)
270 return rc;
272 return allowed ? 0 : GPG_ERR_EACCES;
275 static char *
276 create_acl_user (struct client_s *client)
278 #ifdef WITH_GNUTLS
279 if (client->thd->remote)
280 return str_asprintf ("#%s", client->thd->tls->fp);
281 #endif
283 return get_username (client->thd->peer->uid);
286 static gpg_error_t
287 create_new_element (struct client_s *client, int verify, xmlNodePtr parent,
288 const char *name, xmlNodePtr * result)
290 xmlNodePtr n;
291 gpg_error_t rc;
293 // Allow any client to create a non-existing root element.
294 if (parent->parent->type != XML_DOCUMENT_NODE)
296 rc = acl_check(client, parent);
297 if (rc)
298 return rc;
301 n = xmlNewNode (NULL, (xmlChar *) "element");
302 if (!n)
303 return GPG_ERR_ENOMEM;
305 rc = add_attribute (client, n, "_name", name);
306 if (!rc)
307 rc = attr_ctime (client, n);
309 if (!rc && verify && parent->parent->type != XML_DOCUMENT_NODE)
310 rc = is_element_owner (client, parent);
312 if (!rc)
314 xmlNodePtr p = xmlAddChild (parent, n);
315 char *user = create_acl_user (client);
317 if (result)
318 *result = p;
320 rc = add_attribute(client, p, "_acl", user);
321 xfree (user);
323 else
324 xmlFreeNode (n);
326 return rc;
329 gpg_error_t
330 new_root_element (struct client_s *client, xmlDocPtr doc, char *name)
332 xmlNodePtr root = xmlDocGetRootElement (doc);
333 char *p = name;
335 if (!p || !root)
336 return GPG_ERR_BAD_DATA;
338 if (*p == '!')
339 p++;
341 if (!valid_xml_element ((xmlChar *) p))
342 return GPG_ERR_INV_VALUE;
344 return create_new_element (client, 0, root, p, NULL);
347 static xmlDocPtr
348 create_dtd ()
350 xmlDocPtr doc;
351 xmlTextWriterPtr wr = xmlNewTextWriterDoc (&doc, 0);
353 if (!wr)
354 return NULL;
356 if (xmlTextWriterStartDocument (wr, NULL, "UTF-8", "yes"))
357 goto fail;
359 if (xmlTextWriterStartDTD (wr, (xmlChar *) "pwmd", NULL, NULL) == -1)
360 goto fail;
362 if (xmlTextWriterWriteDTDElement (wr, (xmlChar *) "pwmd",
363 (xmlChar *) "(element)") == -1)
364 goto fail;
366 xmlTextWriterEndDTDElement (wr);
368 if (xmlTextWriterWriteDTDAttlist (wr, (xmlChar *) "element",
369 (xmlChar *) "_name CDATA #REQUIRED") ==
371 goto fail;
373 xmlTextWriterEndDTDAttlist (wr);
374 xmlTextWriterEndDTD (wr);
376 if (xmlTextWriterStartElement (wr, (xmlChar *) "pwmd"))
377 goto fail;
379 xmlTextWriterEndElement (wr);
380 xmlTextWriterEndDocument (wr);
381 xmlFreeTextWriter (wr);
382 return doc;
384 fail:
385 xmlTextWriterEndDocument (wr);
386 xmlFreeTextWriter (wr);
387 xmlFreeDoc (doc);
388 return NULL;
391 xmlDocPtr
392 new_document ()
394 return create_dtd ();
397 xmlNodePtr
398 find_element_node (xmlNodePtr node)
400 xmlNodePtr n = node;
402 if (n && n->type == XML_ELEMENT_NODE)
403 return n;
405 for (n = node; n; n = n->next)
407 if (n->type == XML_ELEMENT_NODE)
408 return n;
411 return NULL;
414 static xmlNodePtr
415 resolve_path (struct client_s *client, xmlDocPtr doc, xmlChar * path,
416 char ***result, gpg_error_t * rc)
418 xmlNodePtr n;
419 char **req;
421 req = str_split ((char *) path, "\t", 0);
422 if (!req)
424 *rc = GPG_ERR_ENOMEM;
425 return NULL;
428 n = find_root_element (client, doc, &req, rc, NULL, 0, 0);
429 if (*rc)
431 strv_free (req);
432 return n;
435 if (req[1])
436 n = find_elements (client, doc, n->children, req + 1, rc, NULL, NULL, NULL,
437 0, 0, NULL, 0);
439 if (*rc)
440 strv_free (req);
441 else
442 *result = req;
444 return n;
448 * Lists root element names; the value of the attribute "_name" of an element
449 * "element". If there's a target attribute both literal and non-literal
450 * element names will be added. This is the primary reason why XML entities
451 * cannot be used. There wouldn't be a way to get the literal an non-literal
452 * element paths.
454 gpg_error_t
455 list_root_elements (struct client_s *client, xmlDocPtr doc,
456 struct string_s ** result, int verbose, int with_target)
458 xmlNodePtr n = NULL;
459 struct slist_s *list = NULL;
460 int total, i;
461 struct string_s *string;
462 gpg_error_t rc = 0;
464 n = xmlDocGetRootElement (doc);
465 if (!n || !n->children)
466 return GPG_ERR_NO_DATA;
468 for (n = n->children; n; n = n->next)
470 xmlAttrPtr a;
471 xmlChar *val, *target;
472 struct slist_s *tlist;
473 char *tmp;
475 if (n->type != XML_ELEMENT_NODE)
476 continue;
478 a = xmlHasProp (n, (xmlChar *) "_name");
479 if (!a || !a->children->content)
480 continue;
482 val = xmlNodeGetContent (a->children);
483 if (!val)
485 rc = GPG_ERR_ENOMEM;
486 goto fail;
489 tmp = str_asprintf ("!%s%s", (char *) val,
490 verbose ? find_element_node (n->children) ? " +"
491 : "" : "");
493 if (!tmp)
495 xmlFree (val);
496 rc = GPG_ERR_ENOMEM;
497 goto fail;
500 tlist = slist_append (list, tmp);
501 if (!tlist)
503 xmlFree (val);
504 rc = GPG_ERR_ENOMEM;
505 goto fail;
508 list = tlist;
509 target = node_has_attribute (n, (xmlChar *) "target");
510 if (target)
512 char *t = NULL;
514 if (verbose)
516 char **req = NULL;
517 xmlNodePtr tnode = resolve_path (client, doc, target, &req, &rc);
519 if (rc == GPG_ERR_ELEMENT_NOT_FOUND || rc == GPG_ERR_ELOOP
520 || rc == GPG_ERR_EACCES)
522 t = str_asprintf ("%s %s%s%s", (char *) val,
523 rc == GPG_ERR_ELOOP ? "O" :
524 rc == GPG_ERR_EACCES ? "P" : "E",
525 with_target ? "T " : "",
526 with_target ? (char *)target : "");
527 rc = 0;
529 else if (!rc)
531 struct string_s *realpath = NULL;
533 if (with_target)
535 rc = build_realpath (client, doc, (char *) target,
536 &realpath);
537 if (rc)
539 strv_free (req);
540 xmlFree (val);
541 xmlFree (target);
542 goto fail;
545 realpath = string_prepend (realpath, "T ");
548 t = str_asprintf ("%s%s%s%s", (char *) val,
549 (tnode
550 && find_element_node (tnode->children))
551 || realpath ? " " : "", tnode
552 && find_element_node (tnode->children) ?
553 "+" : "", realpath ? realpath->str : "");
555 if (realpath)
556 string_free (realpath, 1);
559 if (req)
560 strv_free (req);
562 else
563 t = str_dup ((char *) val);
565 if (!t || rc)
567 xmlFree (val);
568 xmlFree (target);
569 rc = rc ? rc : GPG_ERR_ENOMEM;
570 goto fail;
573 tlist = slist_append (list, t);
574 if (!tlist)
576 xmlFree (val);
577 xfree (t);
578 xmlFree (target);
579 rc = GPG_ERR_ENOMEM;
580 goto fail;
583 list = tlist;
586 xmlFree (val);
587 xmlFree (target);
590 total = slist_length (list);
591 if (!total)
592 return GPG_ERR_NO_DATA;
594 string = string_new (NULL);
595 if (!string)
597 rc = GPG_ERR_ENOMEM;
598 goto fail;
601 for (i = 0; i < total; i++)
603 char *val = slist_nth_data (list, i);
605 string_append_printf (string, "%s\n", val);
608 string = string_truncate (string, string->len - 1);
609 *result = string;
611 fail:
612 total = slist_length (list);
613 for (i = 0; i < total; i++)
614 xfree (slist_nth_data (list, i));
616 slist_free (list);
617 return rc;
621 * Prevents a sibling element past the current element path with the same
622 * element name.
624 static xmlNodePtr
625 find_stop_node (xmlNodePtr node)
627 xmlNodePtr n;
629 for (n = node->parent->children; n; n = n->next)
631 if (n == node)
632 return n->next;
635 return NULL;
638 xmlNodePtr
639 create_target_elements_cb (struct client_s *client, int verify,
640 xmlNodePtr node, char **path, gpg_error_t *rc,
641 void *data)
643 int i;
644 char **req = path;
645 xmlNodePtr parent = data;
647 for (i = 0; req[i] && *req[i]; i++)
649 xmlNodePtr n;
651 if (parent && node == parent)
653 *rc = GPG_ERR_CONFLICT;
654 return NULL;
657 is_literal_element (&req[i]);
659 if ((n = find_element (client, node, req[i],
660 find_stop_node (node), rc)) == NULL ||
661 (n && n->parent == node->parent))
664 if (!*rc)
665 *rc = create_new_element (client, verify, node, req[i], &node);
667 if (*rc)
668 return NULL;
670 else
671 node = n;
674 return node;
677 xmlNodePtr
678 find_text_node (xmlNodePtr node)
680 xmlNodePtr n = node;
682 if (n && n->type == XML_TEXT_NODE)
683 return n;
685 for (n = node; n; n = n->next)
687 if (n->type == XML_TEXT_NODE)
688 return n;
691 return NULL;
694 xmlNodePtr
695 create_elements_cb (struct client_s *client, int verify, xmlNodePtr node,
696 char **elements, gpg_error_t * rc, void *data)
698 int i;
699 char **req = elements;
701 if (*rc && *rc != GPG_ERR_ELEMENT_NOT_FOUND)
702 return NULL;
704 if (node->type == XML_TEXT_NODE)
705 node = node->parent;
707 for (i = 0; req[i] && *req[i]; i++)
709 xmlNodePtr n;
712 * Strip the first '!' if needed. If there's another, it's an
713 * rc. The syntax has already been checked before calling this
714 * function.
716 is_literal_element (&req[i]);
717 n = find_element (client, node, req[i], find_stop_node (node), rc);
718 if (*rc)
719 return NULL;
722 * If the found element has the same parent as the current element,
723 * they are siblings and the new element needs to be created as a
724 * child of the current element (node).
726 if (n && n->parent == node->parent)
727 n = NULL;
729 if (!n)
731 *rc = create_new_element (client, 0, node, req[i], &node);
732 if (*rc)
733 return NULL;
735 else
736 node = n;
739 return node;
742 /* The root element is really req[0]. It is need as a pointer in case there is
743 * a target attribute so it can be updated. */
744 xmlNodePtr
745 find_root_element (struct client_s *client, xmlDocPtr doc, char ***req,
746 gpg_error_t * rc, int *target, int recursion_depth,
747 int stop)
749 xmlNodePtr n = xmlDocGetRootElement (doc);
750 int depth = 0;
751 char *root = str_dup (*req[0]);
752 int literal = is_literal_element (&root);
754 if (!root)
756 *rc = GPG_ERR_ENOMEM;
757 return NULL;
760 *rc = 0;
761 recursion_depth++;
763 if (max_recursion_depth >= 1 && recursion_depth > max_recursion_depth)
765 xmlChar *t = xmlGetNodePath (n);
767 log_write ("%s: %s", pwmd_strerror (GPG_ERR_ELOOP), t);
768 xmlFree (t);
769 xfree (root);
770 *rc = GPG_ERR_ELOOP;
771 return NULL;
774 while (n)
776 if (n->type == XML_ELEMENT_NODE)
778 if (depth == 0 && xmlStrEqual (n->name, (xmlChar *) "pwmd"))
780 n = n->children;
781 depth++;
782 continue;
785 if (depth == 1 && xmlStrEqual (n->name, (xmlChar *) "element"))
787 xmlChar *content = node_has_attribute (n, (xmlChar *) "_name");
789 if (!content)
790 continue;
792 if (xmlStrEqual (content, (xmlChar *) root))
794 char **nreq, **tmp = NULL;
795 int acl = client->flags & FLAG_ACL_IGNORE;
797 *rc = acl_check(client, n);
798 if ((*rc && *rc != GPG_ERR_EACCES)
799 || (*rc == GPG_ERR_EACCES && !acl))
801 xmlFree (content);
802 xfree (root);
803 return n;
806 if (acl)
808 *rc = 0;
809 // This flag is cleared in acl_check() but we always
810 // allow ATTR LIST of root elements.
811 client->flags |= FLAG_ACL_IGNORE;
814 if (literal == 1)
816 xmlFree (content);
817 xfree (root);
818 return n;
821 xmlFree (content);
822 content = node_has_attribute (n, (xmlChar *) "target");
824 if (content && target)
825 *target = 1;
827 if (!content || stop)
829 if (content)
830 xmlFree (content);
832 xfree (root);
833 return n;
836 if (strchr ((char *) content, '\t'))
838 nreq = str_split ((char *) content, "\t", 0);
839 xmlFree (content);
841 #if 0
843 * FIXME ENOMEM
845 if (!nreq)
847 *rc = GPG_ERR_ENOMEM;
848 return NULL;
850 #endif
852 tmp = *req;
853 tmp = strv_catv (nreq, tmp + 1);
854 strv_free (nreq);
856 if (!tmp)
858 xfree (root);
859 *rc = GPG_ERR_ENOMEM;
860 return NULL;
863 strv_free (*req);
864 *req = tmp;
866 else
868 if (strv_printf (&tmp, "%s", content) == 0)
870 xmlFree (content);
871 xfree (root);
872 *rc = GPG_ERR_ENOMEM;
873 return NULL;
876 xmlFree (content);
877 nreq = *req;
878 nreq = strv_catv (tmp, nreq + 1);
879 strv_free (tmp);
881 if (!nreq)
883 *rc = GPG_ERR_ENOMEM;
884 xfree (root);
885 return NULL;
888 strv_free (*req);
889 *req = nreq;
892 xfree (root);
893 return find_root_element (client, doc, req, rc, target,
894 recursion_depth, 0);
897 xmlFree (content);
901 n = n->next;
904 xfree (root);
905 *rc = GPG_ERR_ELEMENT_NOT_FOUND;
906 return NULL;
909 xmlNodePtr
910 find_element (struct client_s *client, xmlNodePtr node, char *element,
911 xmlNodePtr stop, gpg_error_t *rc)
913 xmlNodePtr n;
915 *rc = 0;
917 if (!node || !element)
918 return NULL;
920 for (n = node; n; n = n->next)
922 if (n->type != XML_ELEMENT_NODE)
923 continue;
925 if (n == stop)
926 break;
928 xmlChar *a = node_has_attribute (n, (xmlChar *) "_name");
930 if (a && xmlStrEqual (a, (xmlChar *) element))
932 xmlFree (a);
934 // Prevent ATTR LIST showing child element attributes for a parent
935 // whos ACL denies the client.
936 if (client->flags & FLAG_ACL_ERROR)
938 *rc = GPG_ERR_EACCES;
939 return NULL;
942 *rc = acl_check(client, n);
943 if (*rc)
944 n = NULL;
946 return n;
949 xmlFree (a);
952 return NULL;
955 xmlChar *
956 node_has_attribute (xmlNodePtr n, xmlChar * attr)
958 xmlAttrPtr a = xmlHasProp (n, attr);
960 if (!a)
961 return NULL;
963 if (!a->children || !a->children->content)
964 return NULL;
966 return xmlGetProp (n, attr);
969 static int
970 element_to_literal (char **element)
972 char *p = str_asprintf ("!%s", *element);
974 if (!p)
975 return 0;
977 xfree (*element);
978 *element = p;
979 return 1;
982 /* Resolves elements in 'req' one at a time. It's recursive in case of
983 * "target" attributes. */
984 xmlNodePtr
985 find_elements (struct client_s *client, xmlDocPtr doc, xmlNodePtr node,
986 char **req, gpg_error_t * rc, int *target,
987 xmlNodePtr (*found_fn) (struct client_s *, xmlNodePtr, char **,
988 gpg_error_t *, char **, void *),
989 xmlNodePtr (*not_found_fn) (struct client_s *, int, xmlNodePtr,
990 char **, gpg_error_t *, void *),
991 int is_list_command, int recursion_depth, void *data, int stop)
993 xmlNodePtr n, last, last_node;
994 char **p;
995 int found = 0;
997 *rc = 0;
998 recursion_depth++;
1000 if (max_recursion_depth >= 1 && recursion_depth > max_recursion_depth)
1002 xmlChar *t = xmlGetNodePath (node);
1004 log_write ("%s: %s", pwmd_strerror (GPG_ERR_ELOOP), t);
1005 xmlFree (t);
1006 recursion_depth--;
1007 *rc = GPG_ERR_ELOOP;
1008 return NULL;
1011 for (last_node = last = n = node, p = req; *p; p++)
1013 xmlNodePtr tmp;
1014 char *t;
1015 int literal;
1017 if (!*(*p))
1019 *rc = GPG_ERR_ELEMENT_NOT_FOUND;
1020 return NULL;
1023 t = str_dup (*p);
1024 if (!t)
1026 *rc = GPG_ERR_ENOMEM;
1027 return NULL;
1030 literal = is_literal_element (&t);
1031 n = find_element (client, last, t, NULL, rc);
1032 xfree (t);
1033 if (!n)
1035 if (!*rc)
1036 *rc = GPG_ERR_ELEMENT_NOT_FOUND;
1038 if (not_found_fn)
1039 return not_found_fn (client, 0,
1040 found ? last_node : last_node->parent, p,
1041 rc, data);
1042 return NULL;
1045 last = n->children;
1046 last_node = n;
1047 found = 1;
1049 if (literal == 0)
1051 xmlChar *content = node_has_attribute (n, (xmlChar *) "target");
1052 char **nreq = NULL, **nnreq;
1054 if (!content)
1056 if (is_list_command == 1)
1058 if (element_to_literal (&(*p)) == 0)
1060 *rc = GPG_ERR_ENOMEM;
1061 return NULL;
1065 continue;
1068 if (target)
1069 *target = 1;
1071 if (!*(p + 1) && stop)
1073 xmlFree (content);
1074 return n;
1077 if (strchr ((char *) content, '\t') != NULL)
1079 if ((nreq = str_split ((char *) content, "\t", 0)) == NULL)
1081 xmlFree (content);
1082 *rc = GPG_ERR_INV_VALUE;
1083 return NULL;
1086 else
1088 if ((nreq = str_split ((char *) content, " ", 0)) == NULL)
1090 xmlFree (content);
1091 *rc = GPG_ERR_INV_VALUE;
1092 return NULL;
1096 xmlFree (content);
1097 tmp = find_root_element (client, doc, &nreq, rc, target, 0, 0);
1098 if (*rc)
1100 strv_free (nreq);
1101 if (not_found_fn && *rc == GPG_ERR_EACCES)
1102 return not_found_fn (client, 0, NULL, p, rc, data);
1103 return tmp;
1106 if (found_fn)
1108 found_fn (client, tmp, nreq, rc, p + 1, data);
1110 if (*rc)
1112 strv_free (nreq);
1113 return NULL;
1117 if (!*(nreq + 1) && !*(p + 1))
1119 strv_free (nreq);
1120 return tmp;
1123 nnreq = strv_catv (nreq + 1, p + 1);
1124 strv_free (nreq);
1126 // FIXME ENOMEM
1127 if (!nnreq || !*nnreq)
1129 strv_free (nnreq);
1130 return tmp;
1133 if (tmp->children)
1135 n = find_elements (client, doc, tmp->children, nnreq, rc, NULL,
1136 found_fn, not_found_fn, is_list_command,
1137 recursion_depth, data, stop);
1138 if (!n)
1140 strv_free (nnreq);
1141 return NULL;
1144 else
1146 strv_free (nnreq);
1147 if (not_found_fn)
1148 return not_found_fn (client, 0, tmp, p, rc, data);
1150 *rc = GPG_ERR_ELEMENT_NOT_FOUND;
1151 return NULL;
1154 if (*(p + 1))
1156 char **zz = p + 1, **qq = nnreq;
1158 if (strv_length (nnreq) > strv_length (p + 1))
1159 qq = nnreq + 1;
1161 for (; *qq && *zz; zz++)
1163 xfree (*zz);
1164 *zz = str_dup (*qq++);
1166 if (!*zz)
1168 *rc = GPG_ERR_ENOMEM;
1169 n = NULL;
1170 break;
1175 strv_free (nnreq);
1176 return n;
1180 return n;
1183 static int
1184 update_element_list (struct element_list_s *elements)
1186 char *line;
1187 struct slist_s *l;
1189 if (!elements || !elements->elements)
1190 return 1;
1192 line = strv_join ("\t", elements->elements);
1194 if (!line)
1195 return 0;
1197 strv_free (elements->elements);
1198 elements->elements = NULL;
1199 l = slist_append (elements->list, line);
1201 if (!l)
1202 return 0;
1204 elements->list = l;
1205 return 1;
1208 static gpg_error_t
1209 path_list_recurse (struct client_s *client, xmlDocPtr doc, xmlNodePtr node,
1210 struct element_list_s *elements)
1212 gpg_error_t rc = 0;
1213 xmlNodePtr n;
1214 gpg_error_t error_flag = 0;
1216 for (n = node; n; n = n->next)
1218 xmlChar *target = NULL;
1219 xmlChar *a = node_has_attribute (n, (xmlChar *) "_name");
1220 gpg_error_t err = 0;
1221 char *path = NULL;
1223 rc = 0;
1224 if (!a)
1225 continue;
1227 if (n->type != XML_ELEMENT_NODE)
1228 goto children;
1230 rc = acl_check(client, n);
1232 if (elements->verbose)
1234 if (strv_printf
1235 (&elements->elements, "%s\t!%s%s%s", elements->prefix, a,
1236 !rc && find_element_node (n->children) ? " +" : "",
1237 rc == GPG_ERR_EACCES ? " P" : rc ? " E" : "") == 0)
1239 xmlFree (a);
1240 return GPG_ERR_ENOMEM;
1243 else
1244 if (strv_printf (&elements->elements, "%s\t!%s", elements->prefix, a)
1245 == 0)
1247 xmlFree (a);
1248 return GPG_ERR_ENOMEM;
1251 if (update_element_list (elements) == 0)
1253 xmlFree (a);
1254 return GPG_ERR_ENOMEM;
1257 if (rc == GPG_ERR_EACCES)
1259 xmlFree(a);
1260 error_flag = rc;
1261 continue;
1263 else if (rc)
1265 xmlFree (a);
1266 return rc;
1269 target = node_has_attribute (n, (xmlChar *) "target");
1270 if (target)
1272 char *tmp;
1273 char *save = elements->prefix;
1274 int r = elements->resolving;
1275 char **req = NULL;
1276 xmlNodePtr tnode;
1277 struct string_s *realpath = NULL;
1279 tnode = resolve_path (client, doc, target, &req, &rc);
1280 if (rc == GPG_ERR_ELOOP || rc == GPG_ERR_ELEMENT_NOT_FOUND
1281 || rc == GPG_ERR_EACCES)
1283 if (rc == GPG_ERR_ELOOP)
1285 xmlChar *t = xmlGetNodePath (n);
1287 log_write ("%s: %s", pwmd_strerror (GPG_ERR_ELOOP), t);
1288 xmlFree (t);
1291 if (elements->verbose)
1293 error_flag = err = rc;
1294 rc = 0;
1297 else if (!elements->verbose && rc)
1299 xmlFree (a);
1300 xmlFree (target);
1301 return rc;
1304 path = str_asprintf("%s\t%s", elements->prefix, a);
1305 rc = validate_target_attribute (client, client->doc, path, tnode);
1306 xfree (path);
1307 if (rc == GPG_ERR_ELOOP || rc == GPG_ERR_EACCES
1308 || rc == GPG_ERR_ELEMENT_NOT_FOUND)
1310 if (rc != GPG_ERR_ELEMENT_NOT_FOUND)
1311 error_flag = err = rc;
1313 rc = 0;
1315 else if (rc)
1317 xmlFree (a);
1318 xmlFree (target);
1319 return rc;
1322 if (err)
1324 strv_printf (&elements->elements, "%s\t%s %s%s%s",
1325 elements->prefix, a,
1326 err == GPG_ERR_ELOOP ? "O" :
1327 err == GPG_ERR_EACCES ? "P" : "E",
1328 elements->with_target ? "T " : "",
1329 elements->with_target ? (char *)target : "");
1331 else if (!err && elements->with_target)
1333 rc = build_realpath (client, doc, (char *) target, &realpath);
1334 if (rc)
1336 xmlFree (a);
1337 xmlFree (target);
1338 return rc;
1341 realpath = string_prepend (realpath, "T ");
1344 if (!err && elements->verbose)
1346 if (!strv_printf (&elements->elements, "%s\t%s%s%s%s",
1347 elements->prefix, a,
1348 (tnode && find_element_node (tnode->children))
1349 || realpath ? " " : "", tnode
1350 && find_element_node (tnode->children) ? "+" :
1351 "", realpath ? realpath->str : ""))
1353 xmlFree (a);
1354 xmlFree (target);
1355 return GPG_ERR_ENOMEM;
1358 else if (!err)
1359 if (!strv_printf
1360 (&elements->elements, "%s\t%s", elements->prefix, a))
1362 xmlFree (a);
1363 xmlFree (target);
1364 return GPG_ERR_ENOMEM;
1367 if (realpath)
1368 string_free (realpath, 1);
1370 tmp = strv_join ("\t", elements->elements);
1371 if (!tmp)
1373 xmlFree (a);
1374 xmlFree (target);
1375 return GPG_ERR_ENOMEM;
1378 if (update_element_list (elements) == 0)
1380 xfree (tmp);
1381 xmlFree (a);
1382 xmlFree (target);
1383 return GPG_ERR_ENOMEM;
1386 if (!err && elements->recurse)
1388 /* Prune element flags. */
1389 if (elements->verbose && strchr (tmp, ' '))
1391 char *p;
1393 for (p = tmp; *p; p++)
1395 if (*p == ' ')
1397 *p = 0;
1398 break;
1403 elements->prefix = tmp;
1404 elements->resolving = 1;
1405 rc = create_path_list (client, doc, elements, (char *) target);
1406 elements->resolving = r;
1407 elements->prefix = save;
1409 if (rc && gpg_err_code (rc) != GPG_ERR_ELOOP
1410 && gpg_err_code(rc) != GPG_ERR_EACCES)
1412 xfree (tmp);
1413 xmlFree (target);
1414 xmlFree (a);
1415 return rc;
1418 error_flag = err = rc;
1419 rc = 0;
1422 xfree (tmp);
1423 xmlFree (target);
1426 children:
1427 if (n->children && elements->recurse)
1429 char *tmp = str_asprintf ("%s\t!%s", elements->prefix, a);
1430 char *save = elements->prefix;
1432 if (!tmp)
1434 xmlFree (a);
1435 return GPG_ERR_ENOMEM;
1438 elements->prefix = tmp;
1439 rc = path_list_recurse (client, doc, n->children, elements);
1440 xfree (elements->prefix);
1441 elements->prefix = save;
1443 if (rc)
1445 if (gpg_err_code(rc) == GPG_ERR_ELOOP
1446 || gpg_err_code (rc) == GPG_ERR_EACCES
1447 || gpg_err_code (rc) == GPG_ERR_ELEMENT_NOT_FOUND)
1449 error_flag = err = rc;
1450 rc = 0;
1452 else
1454 xmlFree (a);
1455 return rc;
1460 xmlFree (a);
1463 return error_flag == GPG_ERR_ELOOP || error_flag == GPG_ERR_EACCES
1464 ? error_flag : rc;
1467 gpg_error_t
1468 add_attribute (struct client_s *client, xmlNodePtr node, const char *name,
1469 const char *value)
1471 char *buf;
1472 gpg_error_t rc = 0;
1474 if (client && name && !strcmp (name, "target"))
1476 rc = is_element_owner (client, node);
1477 if (rc)
1478 return rc;
1481 if (name && !xmlSetProp (node, (xmlChar *) name, (xmlChar *) value))
1482 return GPG_ERR_BAD_DATA;
1484 if (client && name && !xmlStrEqual ((xmlChar *) name, (xmlChar *) "_acl"))
1486 xmlChar *acl = node_has_attribute (node, (xmlChar *) "_acl");
1488 if (!acl)
1490 char *user = create_acl_user (client);
1492 if (user)
1494 rc = add_attribute (client, node, (char *) "_acl", user);
1495 xfree (user);
1498 return rc;
1501 xmlFree (acl);
1504 if (name && xmlStrEqual ((xmlChar *) name, (xmlChar *) "_mtime"))
1505 return 0;
1507 buf = str_asprintf ("%li", time (NULL));
1508 rc = add_attribute (client, node, "_mtime", buf);
1509 xfree (buf);
1510 return rc;
1513 static xmlNodePtr
1514 list_not_found_cb (struct client_s *client, int i, xmlNodePtr node,
1515 char **req, gpg_error_t *rc, void *data)
1517 struct element_list_s *elements = data;
1519 if (*rc != GPG_ERR_EACCES)
1520 return NULL;
1522 elements->data = strv_dup (req);
1523 return NULL;
1527 * From the element path 'path', find sub-nodes and append them to the list.
1529 gpg_error_t
1530 create_path_list (struct client_s *client, xmlDocPtr doc,
1531 struct element_list_s * elements, char *path)
1533 gpg_error_t rc;
1534 char **req, **req_orig;
1535 xmlNodePtr n;
1536 int a_target = 0;
1537 int root_only = 0;
1538 int allowed = 1;
1540 req = str_split (path, "\t", 0);
1541 if (!req)
1543 req = str_split (path, " ", 0);
1544 if (!req)
1545 return GPG_ERR_SYNTAX;
1548 req_orig = strv_dup (req);
1549 if (!req_orig)
1551 rc = GPG_ERR_ENOMEM;
1552 goto fail;
1555 n = find_root_element (client, doc, &req, &rc, &a_target, 0, 0);
1556 if ((rc == GPG_ERR_ELEMENT_NOT_FOUND || rc == GPG_ERR_ELOOP
1557 || rc == GPG_ERR_EACCES) && elements->verbose && a_target)
1559 if (rc == GPG_ERR_EACCES)
1560 allowed = 0;
1562 root_only = 1;
1563 goto done;
1566 if (rc == GPG_ERR_EACCES)
1568 allowed = 0;
1569 root_only = 1;
1570 goto done;
1573 if (!n && rc == GPG_ERR_ELEMENT_NOT_FOUND && elements->resolving == 1)
1575 rc = 0;
1576 goto fail;
1578 else if (!n)
1579 goto fail;
1581 if (a_target == 1)
1583 xfree (*req);
1584 *req = str_dup (*req_orig);
1587 if (*(req + 1))
1589 int e_target = 0;
1591 n = find_elements (client, doc, n->children, req + 1, &rc, &e_target,
1592 NULL, list_not_found_cb, 1, 0, elements, 0);
1593 if (rc == GPG_ERR_ELEMENT_NOT_FOUND && elements->resolving == 1)
1595 rc = 0;
1596 goto fail;
1598 else if (rc && rc != GPG_ERR_EACCES)
1599 goto fail;
1600 else if (rc)
1601 allowed = 0;
1604 done:
1605 if (!elements->prefix)
1608 * FIXME
1610 * If any req_orig element contains no target the element should be
1611 * prefixed with the literal character. Not really crucial if the
1612 * client isn't human because child elements are prefixed for the
1613 * current path. But may be confusing if editing by hand.
1615 if (elements->data)
1617 /* This is needed to prune the original requested element path to the
1618 * length of the failed element in the path. */
1619 int x = strv_length (req_orig)-strv_length ((char **)elements->data);
1620 int i;
1621 char **tmp = NULL;
1623 for (i = 0; i <= x; i++)
1624 tmp = strv_cat (tmp, str_dup (req_orig[i]));
1626 elements->prefix = strv_join ("\t", tmp);
1627 strv_free (tmp);
1628 strv_free (elements->data);
1629 elements->data = NULL;
1631 else
1633 if (root_only)
1634 elements->prefix = str_dup (*req_orig);
1635 else
1636 elements->prefix = strv_join ("\t", req_orig);
1639 if (!elements->prefix)
1641 rc = GPG_ERR_ENOMEM;
1642 goto fail;
1645 if (elements->verbose)
1647 int ret;
1648 struct string_s *realpath = NULL;
1650 if (!rc && allowed && a_target && elements->with_target)
1652 rc = build_realpath (client, doc, path, &realpath);
1653 if (rc)
1654 goto fail;
1656 realpath = string_prepend (realpath, "T ");
1659 ret = strv_printf (&elements->elements, "%s%s%s%s%s%s%s",
1660 elements->prefix,
1661 (allowed && n && find_element_node (n->children))
1662 || realpath ? " " : "",
1663 (allowed && n && find_element_node (n->children)) ? "+" : "",
1664 allowed && realpath ? realpath->str : "",
1665 rc == GPG_ERR_ELOOP ? " O" : "",
1666 rc == GPG_ERR_ELEMENT_NOT_FOUND ? " E" : "",
1667 !allowed ? " P" : "");
1668 string_free (realpath, 1);
1669 if (!ret)
1671 rc = GPG_ERR_ENOMEM;
1672 goto fail;
1675 else
1677 if (strv_printf (&elements->elements, "%s", elements->prefix) == 0)
1679 rc = GPG_ERR_ENOMEM;
1680 goto fail;
1684 if (update_element_list (elements) == 0)
1686 rc = GPG_ERR_ENOMEM;
1687 goto fail;
1691 if (allowed)
1692 rc = path_list_recurse (client, doc, n ? n->children : n, elements);
1694 fail:
1695 strv_free (req_orig);
1696 strv_free (req);
1697 return rc;
1700 gpg_error_t
1701 recurse_xpath_nodeset (struct client_s *client, xmlDocPtr doc,
1702 xmlNodeSetPtr nodes, xmlChar * value,
1703 xmlBufferPtr * result, int cmd, const xmlChar * attr)
1705 int i = value ? nodes->nodeNr - 1 : 0;
1706 xmlBufferPtr buf;
1708 buf = xmlBufferCreate ();
1710 if (!buf)
1711 return GPG_ERR_ENOMEM;
1713 for (; value ? i >= 0 : i < nodes->nodeNr; value ? i-- : i++)
1715 xmlNodePtr n = nodes->nodeTab[i];
1716 gpg_error_t rc;
1718 if (!n)
1719 continue;
1721 if (!value && !attr)
1723 if (xmlNodeDump (buf, doc, n, 0, 0) == -1)
1725 *result = buf;
1726 return GPG_ERR_BAD_DATA;
1729 continue;
1732 if (!attr)
1734 xmlNodeSetContent (n, value);
1735 rc = update_element_mtime (client, n);
1737 if (rc)
1738 return rc;
1740 else
1742 if (!cmd)
1743 rc = add_attribute (client, n, (char *) attr, (char *) value);
1744 else
1745 rc = delete_attribute (client, n, attr);
1747 if (rc)
1748 return rc;
1752 *result = buf;
1753 return 0;
1756 static gpg_error_t
1757 convert_root_element (struct client_s *client, xmlNodePtr n)
1759 xmlChar *a = xmlGetProp (n, (xmlChar *) "_name");
1760 gpg_error_t rc;
1762 if (a)
1764 xmlFree (a);
1765 xmlChar *t = xmlGetNodePath (n);
1767 log_write (_
1768 ("An existing \"_name\" attribute already exists. Please rename this attribute before converting. Path is: %s"),
1770 xmlFree (t);
1771 return GPG_ERR_AMBIGUOUS_NAME;
1774 a = xmlGetProp (n, (xmlChar *) "name");
1776 if (a)
1778 rc = add_attribute (client, n, "_name", (char *) a);
1779 xmlFree (a);
1781 if (rc)
1782 return rc;
1784 rc = delete_attribute (client, n, (xmlChar *) "name");
1786 if (rc)
1787 return rc;
1789 xmlNodeSetName (n, (xmlChar *) "element");
1792 return 0;
1795 gpg_error_t
1796 delete_attribute (struct client_s *client, xmlNodePtr n, const xmlChar * name)
1798 xmlAttrPtr a;
1799 gpg_error_t rc = 0;
1801 if ((a = xmlHasProp (n, name)) == NULL)
1802 return GPG_ERR_NOT_FOUND;
1804 if (xmlRemoveProp (a) == -1)
1805 return GPG_ERR_BAD_DATA;
1807 if (client && xmlStrEqual (name, (xmlChar *) "_acl"))
1809 char *user = create_acl_user (client);
1811 rc = add_attribute (client, n, (char *) "_acl", user);
1812 xfree (user);
1814 if (rc)
1815 return rc;
1818 return update_element_mtime (client, n);
1821 static gpg_error_t
1822 convert_elements_recurse (struct client_s *client, xmlDocPtr doc,
1823 xmlNodePtr n, unsigned depth)
1825 gpg_error_t rc;
1827 depth++;
1829 for (n = n->children; n; n = n->next)
1831 if (n->type == XML_ELEMENT_NODE)
1833 if (depth > 1)
1835 xmlChar *a = NULL;
1837 if (xmlStrEqual (n->name, (xmlChar *) "element"))
1839 xmlChar *t = xmlGetNodePath (n);
1841 log_write (_
1842 ("An existing \"element\" already exists. Please rename this element before converting. Path is: %s"),
1844 xmlFree (t);
1845 return GPG_ERR_AMBIGUOUS_NAME;
1848 a = xmlGetProp (n, (xmlChar *) "_name");
1849 if (a)
1851 xmlFree (a);
1852 xmlChar *t = xmlGetNodePath (n);
1854 log_write (_
1855 ("An existing \"_name\" attribute already exists. Please rename this attribute before converting. Path is: %s"),
1857 xmlFree (t);
1858 return GPG_ERR_AMBIGUOUS_NAME;
1861 xmlChar *tmp = xmlStrdup (n->name);
1863 if (!tmp)
1864 return GPG_ERR_ENOMEM;
1866 xmlNodeSetName (n, (xmlChar *) "element");
1867 rc = add_attribute (client, n, "_name", (char *) tmp);
1868 xmlFree (tmp);
1870 if (rc)
1871 return rc;
1873 else
1875 rc = convert_root_element (client, n);
1877 if (rc)
1878 return rc;
1882 if (n->children)
1884 rc = convert_elements_recurse (client, doc, n, depth);
1886 if (rc)
1887 return rc;
1891 return 0;
1894 /* Renames ALL elements to the new "element" name. Existing element names are
1895 * stored as an attribute "_name". This was introduced in pwmd 2.12 so
1896 * elements can contain common characters that the XML parser barfs on (an
1897 * email address for example. */
1898 gpg_error_t
1899 convert_pre_212_elements (xmlDocPtr doc)
1901 xmlNodePtr n = xmlDocGetRootElement (doc);
1903 log_write (_("Converting pre 2.12 data file..."));
1904 return convert_elements_recurse (NULL, doc, n, 0);
1907 gpg_error_t
1908 validate_import (struct client_s *client, xmlNodePtr node)
1910 gpg_error_t rc = 0;
1912 if (!node)
1913 return 0;
1915 for (xmlNodePtr n = node; n; n = n->next)
1917 if (n->type == XML_ELEMENT_NODE)
1919 if (xmlStrEqual (n->name, (xmlChar *) "element"))
1921 xmlChar *a = xmlGetProp (n, (xmlChar *) "_name");
1923 if (!a)
1925 xmlChar *t = xmlGetNodePath (n);
1927 log_write (_("Missing attribute '_name' at %s."), t);
1928 xmlFree (t);
1929 return GPG_ERR_INV_VALUE;
1932 if (!valid_xml_element (a))
1934 xmlChar *t = xmlGetNodePath (n);
1936 log_write (_("'%s' is not a valid element name at %s."), a,
1938 xmlFree (a);
1939 xmlFree (t);
1940 return GPG_ERR_INV_VALUE;
1943 xmlFree (a);
1944 a = xmlGetProp (n, (xmlChar *) "_ctime");
1945 if (!a)
1946 attr_ctime (client, n);
1948 xmlFree (a);
1949 a = xmlGetProp (n, (xmlChar *) "_mtime");
1950 if (!a)
1951 update_element_mtime (client, n);
1952 xmlFree (a);
1954 else
1956 xmlChar *t = xmlGetNodePath (n);
1958 log_write (_("Warning: unknown element '%s' at %s. Ignoring."),
1959 n->name, t);
1960 xmlFree (t);
1961 continue;
1965 if (n->children)
1967 rc = validate_import (client, n->children);
1969 if (rc)
1970 return rc;
1974 return rc;
1977 gpg_error_t
1978 update_element_mtime (struct client_s *client, xmlNodePtr n)
1980 return add_attribute (client, n, NULL, NULL);
1983 gpg_error_t
1984 unlink_node (struct client_s *client, xmlNodePtr n)
1986 gpg_error_t rc = 0;
1988 if (!n)
1989 return rc;
1991 if (n->parent)
1992 rc = update_element_mtime (client, n->parent);
1994 xmlUnlinkNode (n);
1995 return rc;
1998 gpg_error_t
1999 parse_doc (const char *xml, size_t len, xmlDocPtr *result)
2001 xmlDocPtr doc;
2003 xmlResetLastError ();
2004 doc = xmlReadMemory (xml, len, NULL, "UTF-8", XML_PARSE_NOBLANKS);
2005 if (!doc && xmlGetLastError ())
2006 return GPG_ERR_BAD_DATA;
2008 *result = doc;
2009 return !doc ? GPG_ERR_ENOMEM : 0;
2012 static xmlNodePtr
2013 realpath_elements_cb (struct client_s *client, xmlNodePtr node, char **target,
2014 gpg_error_t * rc, char **req_orig, void *data)
2016 char *path = *(char **) data;
2017 char *tmp = NULL, *result;
2019 if (path)
2021 xfree (path);
2022 *(char **) data = NULL;
2025 path = strv_join ("\t", target);
2027 if (!path)
2029 *rc = GPG_ERR_ENOMEM;
2030 return NULL;
2033 if (req_orig)
2035 tmp = strv_join ("\t", req_orig);
2037 if (!tmp)
2039 xfree (path);
2040 *rc = GPG_ERR_ENOMEM;
2041 return NULL;
2045 if (tmp && *tmp)
2046 result = str_asprintf ("%s\t%s", path, tmp);
2047 else
2048 result = str_dup (path);
2050 if (!result)
2052 *rc = GPG_ERR_ENOMEM;
2053 xfree (path);
2054 xfree (tmp);
2055 return NULL;
2058 xfree (path);
2059 xfree (tmp);
2060 *(char **) data = result;
2061 return node;
2064 gpg_error_t
2065 build_realpath (struct client_s *client, xmlDocPtr doc, char *line,
2066 struct string_s ** result)
2068 gpg_error_t rc;
2069 char **req;
2070 char *t;
2071 int i;
2072 xmlNodePtr n;
2073 struct string_s *string;
2074 char *rp = NULL;
2076 if (strchr (line, '\t') != NULL)
2078 if ((req = str_split (line, "\t", 0)) == NULL)
2079 return GPG_ERR_SYNTAX;
2081 else
2083 if ((req = str_split (line, " ", 0)) == NULL)
2084 return GPG_ERR_SYNTAX;
2087 n = find_root_element (client, doc, &req, &rc, NULL, 0, 0);
2088 if (rc)
2090 strv_free (req);
2091 return rc;
2094 rp = strv_join ("\t", req);
2095 if (!rp)
2097 strv_free (req);
2098 return GPG_ERR_ENOMEM;
2101 if (req[1])
2103 n = find_elements (client, doc, n->children, req + 1, &rc, NULL,
2104 realpath_elements_cb, NULL, 0, 0, &rp, 0);
2105 if (!n)
2107 xfree (rp);
2108 strv_free (req);
2109 return rc;
2113 string = string_new (rp);
2114 xfree (rp);
2115 strv_free (req);
2116 if (!string)
2117 return GPG_ERR_ENOMEM;
2119 again:
2120 for (i = 0, t = string->str + i; *t; t++, i++)
2122 if ((!i && *t != '!') || (*t == '\t' && *(t + 1) && *(t + 1) != '!'))
2124 struct string_s *s = string_insert_c (string, !i ? i++ : ++i, '!');
2126 if (!s)
2128 string_free (string, 1);
2129 return GPG_ERR_ENOMEM;
2132 string = s;
2133 goto again;
2137 *result = string;
2138 return rc;
2141 #if 0
2142 static char *
2143 node_to_element_path (xmlNodePtr node)
2145 xmlNodePtr n;
2146 struct string_s *str = string_new ("");
2147 char *result;
2149 for (n = node; n; n = n->parent)
2151 xmlNodePtr child;
2153 for (child = n; child; child = child->next)
2155 if (child->type != XML_ELEMENT_NODE)
2156 continue;
2158 xmlChar *name = node_has_attribute (n, (xmlChar *) "_name");
2159 if (name)
2161 str = string_prepend (str, (char *) name);
2162 xmlFree (name);
2163 name = node_has_attribute (n, (xmlChar *) "target");
2164 if (name)
2165 str = string_prepend (str, "\t");
2166 else
2167 str = string_prepend (str, "\t!");
2168 xmlFree (name);
2170 break;
2174 str = string_erase (str, 0, 1);
2175 result = str->str;
2176 string_free (str, 0);
2177 return result;
2179 #endif
2182 * Recurse the element tree beginning at 'node' and find elements who point
2183 * back to 'src' or 'dst'. Also follows target attributes.
2185 static gpg_error_t
2186 find_child_to_target (struct client_s *client, xmlDocPtr doc, xmlNodePtr node,
2187 xmlNodePtr src, xmlNodePtr dst, unsigned depth,
2188 int is_target)
2190 xmlNodePtr n;
2191 gpg_error_t rc = 0;
2193 if (max_recursion_depth >= 1 && depth > max_recursion_depth)
2194 return gpg_error (GPG_ERR_ELOOP);
2196 for (n = node; n; n = n->next)
2198 xmlChar *target;
2200 if (n->type != XML_ELEMENT_NODE)
2201 continue;
2203 if (n == src || n == dst)
2204 return GPG_ERR_ELOOP;
2206 target = node_has_attribute (n, (xmlChar *) "target");
2207 if (target)
2209 xmlNodePtr tmp;
2210 char **result = NULL;
2212 tmp = resolve_path (client, doc, target, &result, &rc);
2213 xmlFree (target);
2214 strv_free (result);
2215 if (!rc)
2217 rc = find_child_to_target (client, doc, tmp, src, dst, ++depth,
2219 depth--;
2222 if (rc && gpg_err_code (rc) != GPG_ERR_ELEMENT_NOT_FOUND)
2223 return rc;
2225 if (is_target)
2226 break;
2228 continue;
2231 if (n->children)
2233 rc = find_child_to_target (client, doc, n->children, src, dst,
2234 ++depth,0);
2235 depth--;
2236 if (rc)
2237 return rc;
2240 if (is_target)
2241 break;
2244 return rc;
2247 static gpg_error_t
2248 find_child_of_parent (xmlDocPtr doc, xmlNodePtr src, xmlNodePtr dst)
2250 xmlNodePtr n;
2251 gpg_error_t rc = 0;
2253 for (n = src; n; n = n->next)
2255 if (n->type != XML_ELEMENT_NODE)
2256 continue;
2258 if (n == dst)
2260 rc = GPG_ERR_ELOOP;
2261 break;
2264 rc = find_child_of_parent (doc, n->children, dst);
2267 return rc;
2270 static gpg_error_t
2271 find_parent_of_child (xmlDocPtr doc, xmlNodePtr node, xmlNodePtr dst)
2273 xmlNodePtr n;
2274 gpg_error_t rc = 0;
2276 for (n = node; n; n = n->parent)
2278 if (n->type != XML_ELEMENT_NODE)
2280 xmlNodePtr tmp;
2282 for (tmp = n->next; tmp; n = n->next)
2284 if (n->type != XML_ELEMENT_NODE)
2285 continue;
2287 if (tmp == dst)
2288 return GPG_ERR_ELOOP;
2292 if (n == dst)
2293 return GPG_ERR_ELOOP;
2296 return rc;
2299 gpg_error_t
2300 validate_target_attribute (struct client_s *client, xmlDocPtr doc,
2301 const char *src, xmlNodePtr dst_node)
2303 gpg_error_t rc;
2304 xmlNodePtr src_node;
2305 char **src_req = NULL;
2307 src_node = resolve_path (client, doc, (xmlChar *) src, &src_req, &rc);
2308 if (rc)
2309 goto fail;
2311 client->flags |= FLAG_ACL_IGNORE;
2312 /* A destination element is a child of the source element. */
2313 rc = find_child_of_parent (doc, src_node->children, dst_node);
2314 if (rc)
2315 goto fail;
2317 /* The destination element is a parent of the source element. */
2318 rc = find_parent_of_child (doc, src_node->parent, dst_node);
2319 if (rc)
2320 goto fail;
2322 /* A destination child element contains a target to the source element. */
2323 rc = find_child_to_target (client, doc, dst_node->children, src_node,
2324 dst_node, 0, 0);
2325 if (rc)
2326 goto fail;
2328 fail:
2329 strv_free (src_req);
2330 client->flags &= ~(FLAG_ACL_IGNORE | FLAG_ACL_ERROR);
2331 return rc;
2334 /* The owner of the element is the first user listed in the _acl attribute
2335 * list. acl_check() should be called before calling this function. An empty
2336 * ACL is an error if the client is not invoking_user.
2338 gpg_error_t
2339 is_element_owner (struct client_s *client, xmlNodePtr n)
2341 xmlChar *acl = node_has_attribute (n, (xmlChar *) "_acl");
2342 char **users;
2343 gpg_error_t rc = GPG_ERR_EACCES;
2345 if (!acl || !*acl)
2347 xmlFree (acl);
2348 return peer_is_invoker (client);
2351 users = str_split((char *)acl, ",", 0);
2352 if (users && *users)
2354 char *user;
2356 #ifdef WITH_GNUTLS
2357 if (client->thd->remote)
2358 user = str_asprintf ("#%s", client->thd->tls->fp);
2359 else
2360 user = get_username (client->thd->peer->uid);
2361 #else
2362 user = get_username (client->thd->peer->uid);
2363 #endif
2365 if (*user == '#')
2366 rc = !strcasecmp (*users, user) ? 0 : GPG_ERR_EACCES;
2367 else
2368 rc = !strcmp (*users, user) ? 0 : GPG_ERR_EACCES;
2370 if (rc)
2371 rc = peer_is_invoker (client);
2373 xfree (user);
2376 strv_free (users);
2377 return rc;