Allow creating a "target" to visible restricted element.
[libpwmd.git] / src / xml.c
blobe8200211df7bab0096dbf98752bed3ffea212e55
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", (char *) val,
523 rc == GPG_ERR_ELOOP ? "O" :
524 rc == GPG_ERR_EACCES ? "P" : "E");
525 rc = 0;
527 else if (!rc)
529 struct string_s *realpath = NULL;
531 if (with_target)
533 rc = build_realpath (client, doc, (char *) target,
534 &realpath);
535 if (rc)
537 strv_free (req);
538 xmlFree (val);
539 xmlFree (target);
540 goto fail;
543 realpath = string_prepend (realpath, "T ");
546 t = str_asprintf ("%s%s%s%s", (char *) val,
547 (tnode
548 && find_element_node (tnode->children))
549 || realpath ? " " : "", tnode
550 && find_element_node (tnode->children) ?
551 "+" : "", realpath ? realpath->str : "");
553 if (realpath)
554 string_free (realpath, 1);
557 if (req)
558 strv_free (req);
560 else
561 t = str_dup ((char *) val);
563 if (!t || rc)
565 xmlFree (val);
566 xmlFree (target);
567 rc = rc ? rc : GPG_ERR_ENOMEM;
568 goto fail;
571 tlist = slist_append (list, t);
572 if (!tlist)
574 xmlFree (val);
575 xfree (t);
576 xmlFree (target);
577 rc = GPG_ERR_ENOMEM;
578 goto fail;
581 list = tlist;
584 xmlFree (val);
585 xmlFree (target);
588 total = slist_length (list);
589 if (!total)
590 return GPG_ERR_NO_DATA;
592 string = string_new (NULL);
593 if (!string)
595 rc = GPG_ERR_ENOMEM;
596 goto fail;
599 for (i = 0; i < total; i++)
601 char *val = slist_nth_data (list, i);
603 string_append_printf (string, "%s\n", val);
606 string = string_truncate (string, string->len - 1);
607 *result = string;
609 fail:
610 total = slist_length (list);
611 for (i = 0; i < total; i++)
612 xfree (slist_nth_data (list, i));
614 slist_free (list);
615 return rc;
619 * Prevents a sibling element past the current element path with the same
620 * element name.
622 static xmlNodePtr
623 find_stop_node (xmlNodePtr node)
625 xmlNodePtr n;
627 for (n = node->parent->children; n; n = n->next)
629 if (n == node)
630 return n->next;
633 return NULL;
636 xmlNodePtr
637 create_target_elements_cb (struct client_s *client, int verify,
638 xmlNodePtr node, char **path, gpg_error_t *rc,
639 void *data)
641 int i;
642 char **req = path;
643 xmlNodePtr parent = data;
645 for (i = 0; req[i] && *req[i]; i++)
647 xmlNodePtr n;
649 if (parent && node == parent)
651 *rc = GPG_ERR_CONFLICT;
652 return NULL;
655 is_literal_element (&req[i]);
657 if ((n = find_element (client, node, req[i],
658 find_stop_node (node), rc)) == NULL ||
659 (n && n->parent == node->parent))
662 if (!*rc)
663 *rc = create_new_element (client, verify, node, req[i], &node);
665 if (*rc)
666 return NULL;
668 else
669 node = n;
672 return node;
675 xmlNodePtr
676 find_text_node (xmlNodePtr node)
678 xmlNodePtr n = node;
680 if (n && n->type == XML_TEXT_NODE)
681 return n;
683 for (n = node; n; n = n->next)
685 if (n->type == XML_TEXT_NODE)
686 return n;
689 return NULL;
692 xmlNodePtr
693 create_elements_cb (struct client_s *client, int verify, xmlNodePtr node,
694 char **elements, gpg_error_t * rc, void *data)
696 int i;
697 char **req = elements;
699 if (node->type == XML_TEXT_NODE)
700 node = node->parent;
702 for (i = 0; req[i] && *req[i]; i++)
704 xmlNodePtr n;
707 * Strip the first '!' if needed. If there's another, it's an
708 * rc. The syntax has already been checked before calling this
709 * function.
711 is_literal_element (&req[i]);
712 n = find_element (client, node, req[i], find_stop_node (node), rc);
713 if (*rc)
714 return NULL;
717 * If the found element has the same parent as the current element,
718 * they are siblings and the new element needs to be created as a
719 * child of the current element (node).
721 if (n && n->parent == node->parent)
722 n = NULL;
724 if (!n)
726 *rc = create_new_element (client, 0, node, req[i], &node);
727 if (*rc)
728 return NULL;
730 else
731 node = n;
734 return node;
737 /* The root element is really req[0]. It is need as a pointer in case there is
738 * a target attribute so it can be updated. */
739 xmlNodePtr
740 find_root_element (struct client_s *client, xmlDocPtr doc, char ***req,
741 gpg_error_t * rc, int *target, int recursion_depth,
742 int stop)
744 xmlNodePtr n = xmlDocGetRootElement (doc);
745 int depth = 0;
746 char *root = str_dup (*req[0]);
747 int literal = is_literal_element (&root);
749 if (!root)
751 *rc = GPG_ERR_ENOMEM;
752 return NULL;
755 *rc = 0;
756 recursion_depth++;
758 if (max_recursion_depth >= 1 && recursion_depth > max_recursion_depth)
760 xmlChar *t = xmlGetNodePath (n);
762 log_write ("%s: %s", pwmd_strerror (GPG_ERR_ELOOP), t);
763 xmlFree (t);
764 xfree (root);
765 *rc = GPG_ERR_ELOOP;
766 return NULL;
769 while (n)
771 if (n->type == XML_ELEMENT_NODE)
773 if (depth == 0 && xmlStrEqual (n->name, (xmlChar *) "pwmd"))
775 n = n->children;
776 depth++;
777 continue;
780 if (depth == 1 && xmlStrEqual (n->name, (xmlChar *) "element"))
782 xmlChar *content = node_has_attribute (n, (xmlChar *) "_name");
784 if (!content)
785 continue;
787 if (xmlStrEqual (content, (xmlChar *) root))
789 char **nreq, **tmp = NULL;
790 int acl = client->flags & FLAG_ACL_IGNORE;
792 *rc = acl_check(client, n);
793 if ((*rc && *rc != GPG_ERR_EACCES)
794 || (*rc == GPG_ERR_EACCES && !acl))
796 xmlFree (content);
797 xfree (root);
798 return n;
801 if (acl)
803 *rc = 0;
804 // This flag is cleared in acl_check() but we always
805 // allow ATTR LIST of root elements.
806 client->flags |= FLAG_ACL_IGNORE;
809 if (literal == 1)
811 xmlFree (content);
812 xfree (root);
813 return n;
816 xmlFree (content);
817 content = node_has_attribute (n, (xmlChar *) "target");
819 if (content && target)
820 *target = 1;
822 if (!content || stop)
824 if (content)
825 xmlFree (content);
827 xfree (root);
828 return n;
831 if (strchr ((char *) content, '\t'))
833 nreq = str_split ((char *) content, "\t", 0);
834 xmlFree (content);
836 #if 0
838 * FIXME ENOMEM
840 if (!nreq)
842 *rc = GPG_ERR_ENOMEM;
843 return NULL;
845 #endif
847 tmp = *req;
848 tmp = strv_catv (nreq, tmp + 1);
849 strv_free (nreq);
851 if (!tmp)
853 xfree (root);
854 *rc = GPG_ERR_ENOMEM;
855 return NULL;
858 strv_free (*req);
859 *req = tmp;
861 else
863 if (strv_printf (&tmp, "%s", content) == 0)
865 xmlFree (content);
866 xfree (root);
867 *rc = GPG_ERR_ENOMEM;
868 return NULL;
871 xmlFree (content);
872 nreq = *req;
873 nreq = strv_catv (tmp, nreq + 1);
874 strv_free (tmp);
876 if (!nreq)
878 *rc = GPG_ERR_ENOMEM;
879 xfree (root);
880 return NULL;
883 strv_free (*req);
884 *req = nreq;
887 xfree (root);
888 return find_root_element (client, doc, req, rc, target,
889 recursion_depth, 0);
892 xmlFree (content);
896 n = n->next;
899 xfree (root);
900 *rc = GPG_ERR_ELEMENT_NOT_FOUND;
901 return NULL;
904 xmlNodePtr
905 find_element (struct client_s *client, xmlNodePtr node, char *element,
906 xmlNodePtr stop, gpg_error_t *rc)
908 xmlNodePtr n;
910 *rc = 0;
912 if (!node || !element)
913 return NULL;
915 for (n = node; n; n = n->next)
917 if (n->type != XML_ELEMENT_NODE)
918 continue;
920 if (n == stop)
921 break;
923 xmlChar *a = node_has_attribute (n, (xmlChar *) "_name");
925 if (a && xmlStrEqual (a, (xmlChar *) element))
927 xmlFree (a);
929 // Prevent ATTR LIST showing child element attributes for a parent
930 // whos ACL denies the client.
931 if (client->flags & FLAG_ACL_ERROR)
933 *rc = GPG_ERR_EACCES;
934 return NULL;
937 *rc = acl_check(client, n);
938 if (*rc)
939 n = NULL;
941 return n;
944 xmlFree (a);
947 return NULL;
950 xmlChar *
951 node_has_attribute (xmlNodePtr n, xmlChar * attr)
953 xmlAttrPtr a = xmlHasProp (n, attr);
955 if (!a)
956 return NULL;
958 if (!a->children || !a->children->content)
959 return NULL;
961 return xmlGetProp (n, attr);
964 static int
965 element_to_literal (char **element)
967 char *p = str_asprintf ("!%s", *element);
969 if (!p)
970 return 0;
972 xfree (*element);
973 *element = p;
974 return 1;
977 /* Resolves elements in 'req' one at a time. It's recursive in case of
978 * "target" attributes. */
979 xmlNodePtr
980 find_elements (struct client_s *client, xmlDocPtr doc, xmlNodePtr node,
981 char **req, gpg_error_t * rc, int *target,
982 xmlNodePtr (*found_fn) (struct client_s *, xmlNodePtr, char **,
983 gpg_error_t *, char **, void *),
984 xmlNodePtr (*not_found_fn) (struct client_s *, int, xmlNodePtr,
985 char **, gpg_error_t *, void *),
986 int is_list_command, int recursion_depth, void *data, int stop)
988 xmlNodePtr n, last, last_node;
989 char **p;
990 int found = 0;
992 *rc = 0;
993 recursion_depth++;
995 if (max_recursion_depth >= 1 && recursion_depth > max_recursion_depth)
997 xmlChar *t = xmlGetNodePath (node);
999 log_write ("%s: %s", pwmd_strerror (GPG_ERR_ELOOP), t);
1000 xmlFree (t);
1001 recursion_depth--;
1002 *rc = GPG_ERR_ELOOP;
1003 return NULL;
1006 for (last_node = last = n = node, p = req; *p; p++)
1008 xmlNodePtr tmp;
1009 char *t;
1010 int literal;
1012 if (!*(*p))
1014 *rc = GPG_ERR_ELEMENT_NOT_FOUND;
1015 return NULL;
1018 t = str_dup (*p);
1019 if (!t)
1021 *rc = GPG_ERR_ENOMEM;
1022 return NULL;
1025 literal = is_literal_element (&t);
1026 n = find_element (client, last, t, NULL, rc);
1027 xfree (t);
1028 if (!n)
1030 if (!*rc)
1031 *rc = GPG_ERR_ELEMENT_NOT_FOUND;
1033 if (not_found_fn)
1034 return not_found_fn (client, 0,
1035 found ? last_node : last_node->parent, p,
1036 rc, data);
1037 return NULL;
1040 last = n->children;
1041 last_node = n;
1042 found = 1;
1044 if (literal == 0)
1046 xmlChar *content = node_has_attribute (n, (xmlChar *) "target");
1047 char **nreq = NULL, **nnreq;
1049 if (!content)
1051 if (is_list_command == 1)
1053 if (element_to_literal (&(*p)) == 0)
1055 *rc = GPG_ERR_ENOMEM;
1056 return NULL;
1060 continue;
1063 if (target)
1064 *target = 1;
1066 if (!*(p + 1) && stop)
1068 xmlFree (content);
1069 return n;
1072 if (strchr ((char *) content, '\t') != NULL)
1074 if ((nreq = str_split ((char *) content, "\t", 0)) == NULL)
1076 xmlFree (content);
1077 *rc = GPG_ERR_INV_VALUE;
1078 return NULL;
1081 else
1083 if ((nreq = str_split ((char *) content, " ", 0)) == NULL)
1085 xmlFree (content);
1086 *rc = GPG_ERR_INV_VALUE;
1087 return NULL;
1091 xmlFree (content);
1092 tmp = find_root_element (client, doc, &nreq, rc, target, 0, 0);
1093 if (*rc)
1095 strv_free (nreq);
1096 if (not_found_fn && *rc == GPG_ERR_EACCES)
1097 return not_found_fn (client, 0, NULL, p, rc, data);
1098 return tmp;
1101 if (found_fn)
1103 found_fn (client, tmp, nreq, rc, p + 1, data);
1105 if (*rc)
1107 strv_free (nreq);
1108 return NULL;
1112 if (!*(nreq + 1) && !*(p + 1))
1114 strv_free (nreq);
1115 return tmp;
1118 nnreq = strv_catv (nreq + 1, p + 1);
1119 strv_free (nreq);
1121 // FIXME ENOMEM
1122 if (!nnreq || !*nnreq)
1124 strv_free (nnreq);
1125 return tmp;
1128 if (tmp->children)
1130 n = find_elements (client, doc, tmp->children, nnreq, rc, NULL,
1131 found_fn, not_found_fn, is_list_command,
1132 recursion_depth, data, stop);
1133 if (!n)
1135 strv_free (nnreq);
1136 return NULL;
1139 else
1141 strv_free (nnreq);
1142 if (not_found_fn)
1143 return not_found_fn (client, 0, tmp, p, rc, data);
1145 *rc = GPG_ERR_ELEMENT_NOT_FOUND;
1146 return NULL;
1149 if (*(p + 1))
1151 char **zz = p + 1, **qq = nnreq;
1153 if (strv_length (nnreq) > strv_length (p + 1))
1154 qq = nnreq + 1;
1156 for (; *qq && *zz; zz++)
1158 xfree (*zz);
1159 *zz = str_dup (*qq++);
1161 if (!*zz)
1163 *rc = GPG_ERR_ENOMEM;
1164 n = NULL;
1165 break;
1170 strv_free (nnreq);
1171 return n;
1175 return n;
1178 static int
1179 update_element_list (struct element_list_s *elements)
1181 char *line;
1182 struct slist_s *l;
1184 if (!elements || !elements->elements)
1185 return 1;
1187 line = strv_join ("\t", elements->elements);
1189 if (!line)
1190 return 0;
1192 strv_free (elements->elements);
1193 elements->elements = NULL;
1194 l = slist_append (elements->list, line);
1196 if (!l)
1197 return 0;
1199 elements->list = l;
1200 return 1;
1203 static gpg_error_t
1204 path_list_recurse (struct client_s *client, xmlDocPtr doc, xmlNodePtr node,
1205 struct element_list_s *elements)
1207 gpg_error_t rc = 0;
1208 xmlNodePtr n;
1209 gpg_error_t error_flag = 0;
1211 for (n = node; n; n = n->next)
1213 xmlChar *target = NULL;
1214 xmlChar *a = node_has_attribute (n, (xmlChar *) "_name");
1215 gpg_error_t err = 0;
1216 char *path = NULL;
1218 rc = 0;
1219 if (!a)
1220 continue;
1222 if (n->type != XML_ELEMENT_NODE)
1223 goto children;
1225 rc = acl_check(client, n);
1227 if (elements->verbose)
1229 if (strv_printf
1230 (&elements->elements, "%s\t!%s%s%s", elements->prefix, a,
1231 !rc && find_element_node (n->children) ? " +" : "",
1232 rc == GPG_ERR_EACCES ? " P" : rc ? " E" : "") == 0)
1234 xmlFree (a);
1235 return GPG_ERR_ENOMEM;
1238 else
1239 if (strv_printf (&elements->elements, "%s\t!%s", elements->prefix, a)
1240 == 0)
1242 xmlFree (a);
1243 return GPG_ERR_ENOMEM;
1246 if (update_element_list (elements) == 0)
1248 xmlFree (a);
1249 return GPG_ERR_ENOMEM;
1252 if (rc == GPG_ERR_EACCES)
1254 xmlFree(a);
1255 error_flag = rc;
1256 continue;
1258 else if (rc)
1260 xmlFree (a);
1261 return rc;
1264 target = node_has_attribute (n, (xmlChar *) "target");
1265 if (target)
1267 char *tmp;
1268 char *save = elements->prefix;
1269 int r = elements->resolving;
1270 char **req = NULL;
1271 xmlNodePtr tnode;
1272 struct string_s *realpath = NULL;
1274 tnode = resolve_path (client, doc, target, &req, &rc);
1275 if (rc == GPG_ERR_ELOOP || rc == GPG_ERR_ELEMENT_NOT_FOUND
1276 || rc == GPG_ERR_EACCES)
1278 if (rc == GPG_ERR_ELOOP)
1280 xmlChar *t = xmlGetNodePath (n);
1282 log_write ("%s: %s", pwmd_strerror (GPG_ERR_ELOOP), t);
1283 xmlFree (t);
1286 if (elements->verbose)
1288 error_flag = err = rc;
1289 rc = 0;
1292 else if (!elements->verbose && rc)
1294 xmlFree (a);
1295 xmlFree (target);
1296 return rc;
1299 path = str_asprintf("%s\t%s", elements->prefix, a);
1300 rc = validate_target_attribute (client, client->doc, path, tnode);
1301 xfree (path);
1302 if (rc == GPG_ERR_ELOOP || rc == GPG_ERR_EACCES
1303 || rc == GPG_ERR_ELEMENT_NOT_FOUND)
1305 if (rc != GPG_ERR_ELEMENT_NOT_FOUND)
1306 error_flag = err = rc;
1308 rc = 0;
1310 else if (rc)
1312 xmlFree (a);
1313 xmlFree (target);
1314 return rc;
1317 if (err)
1319 strv_printf (&elements->elements, "%s\t%s %s", elements->prefix,
1321 err == GPG_ERR_ELOOP ? "O" :
1322 err == GPG_ERR_EACCES ? "P" : "E");
1325 if (!err && elements->with_target)
1327 rc = build_realpath (client, doc, (char *) target, &realpath);
1328 if (rc)
1330 xmlFree (a);
1331 xmlFree (target);
1332 return rc;
1335 realpath = string_prepend (realpath, "T ");
1338 if (!err && elements->verbose)
1340 if (!strv_printf (&elements->elements, "%s\t%s%s%s%s",
1341 elements->prefix, a,
1342 (tnode && find_element_node (tnode->children))
1343 || realpath ? " " : "", tnode
1344 && find_element_node (tnode->children) ? "+" :
1345 "", realpath ? realpath->str : ""))
1347 xmlFree (a);
1348 xmlFree (target);
1349 return GPG_ERR_ENOMEM;
1352 else if (!err)
1353 if (!strv_printf
1354 (&elements->elements, "%s\t%s", elements->prefix, a))
1356 xmlFree (a);
1357 xmlFree (target);
1358 return GPG_ERR_ENOMEM;
1361 if (realpath)
1362 string_free (realpath, 1);
1364 tmp = strv_join ("\t", elements->elements);
1365 if (!tmp)
1367 xmlFree (a);
1368 xmlFree (target);
1369 return GPG_ERR_ENOMEM;
1372 if (update_element_list (elements) == 0)
1374 xfree (tmp);
1375 xmlFree (a);
1376 xmlFree (target);
1377 return GPG_ERR_ENOMEM;
1380 if (!err && elements->recurse)
1382 /* Prune element flags. */
1383 if (elements->verbose && strchr (tmp, ' '))
1385 char *p;
1387 for (p = tmp; *p; p++)
1389 if (*p == ' ')
1391 *p = 0;
1392 break;
1397 elements->prefix = tmp;
1398 elements->resolving = 1;
1399 rc = create_path_list (client, doc, elements, (char *) target);
1400 elements->resolving = r;
1401 elements->prefix = save;
1403 if (rc && gpg_err_code (rc) != GPG_ERR_ELOOP
1404 && gpg_err_code(rc) != GPG_ERR_EACCES)
1406 xfree (tmp);
1407 xmlFree (target);
1408 xmlFree (a);
1409 return rc;
1412 error_flag = err = rc;
1413 rc = 0;
1416 xfree (tmp);
1417 xmlFree (target);
1420 children:
1421 if (n->children && elements->recurse)
1423 char *tmp = str_asprintf ("%s\t!%s", elements->prefix, a);
1424 char *save = elements->prefix;
1426 if (!tmp)
1428 xmlFree (a);
1429 return GPG_ERR_ENOMEM;
1432 elements->prefix = tmp;
1433 rc = path_list_recurse (client, doc, n->children, elements);
1434 xfree (elements->prefix);
1435 elements->prefix = save;
1437 if (rc)
1439 if (gpg_err_code(rc) == GPG_ERR_ELOOP
1440 || gpg_err_code (rc) == GPG_ERR_EACCES
1441 || gpg_err_code (rc) == GPG_ERR_ELEMENT_NOT_FOUND)
1443 error_flag = err = rc;
1444 rc = 0;
1446 else
1448 xmlFree (a);
1449 return rc;
1454 xmlFree (a);
1457 return error_flag == GPG_ERR_ELOOP || error_flag == GPG_ERR_EACCES
1458 ? error_flag : rc;
1461 gpg_error_t
1462 add_attribute (struct client_s *client, xmlNodePtr node, const char *name,
1463 const char *value)
1465 char *buf;
1466 gpg_error_t rc = 0;
1468 if (client && name && !strcmp (name, "target"))
1470 rc = is_element_owner (client, node);
1471 if (rc)
1472 return rc;
1475 if (name && !xmlSetProp (node, (xmlChar *) name, (xmlChar *) value))
1476 return GPG_ERR_BAD_DATA;
1478 if (client && name && !xmlStrEqual ((xmlChar *) name, (xmlChar *) "_acl"))
1480 xmlChar *acl = node_has_attribute (node, (xmlChar *) "_acl");
1482 if (!acl)
1484 char *user = create_acl_user (client);
1486 if (user)
1488 rc = add_attribute (client, node, (char *) "_acl", user);
1489 xfree (user);
1492 return rc;
1495 xmlFree (acl);
1498 if (name && xmlStrEqual ((xmlChar *) name, (xmlChar *) "_mtime"))
1499 return 0;
1501 buf = str_asprintf ("%li", time (NULL));
1502 rc = add_attribute (client, node, "_mtime", buf);
1503 xfree (buf);
1504 return rc;
1507 static xmlNodePtr
1508 list_not_found_cb (struct client_s *client, int i, xmlNodePtr node,
1509 char **req, gpg_error_t *rc, void *data)
1511 struct element_list_s *elements = data;
1513 if (*rc != GPG_ERR_EACCES)
1514 return NULL;
1516 elements->data = strv_dup (req);
1517 return NULL;
1521 * From the element path 'path', find sub-nodes and append them to the list.
1523 gpg_error_t
1524 create_path_list (struct client_s *client, xmlDocPtr doc,
1525 struct element_list_s * elements, char *path)
1527 gpg_error_t rc;
1528 char **req, **req_orig;
1529 xmlNodePtr n;
1530 int a_target = 0;
1531 int root_only = 0;
1532 gpg_error_t allowed = 0;
1534 req = str_split (path, "\t", 0);
1535 if (!req)
1537 req = str_split (path, " ", 0);
1538 if (!req)
1539 return GPG_ERR_SYNTAX;
1542 req_orig = strv_dup (req);
1543 if (!req_orig)
1545 rc = GPG_ERR_ENOMEM;
1546 goto fail;
1549 n = find_root_element (client, doc, &req, &rc, &a_target, 0, 0);
1550 if ((rc == GPG_ERR_ELEMENT_NOT_FOUND || rc == GPG_ERR_ELOOP)
1551 && elements->verbose && a_target)
1553 if (rc != GPG_ERR_EACCES)
1555 rc = 0;
1556 goto done;
1560 if (rc == GPG_ERR_EACCES)
1562 allowed = rc;
1563 root_only = 1;
1564 goto done;
1567 if (!n && rc == GPG_ERR_ELEMENT_NOT_FOUND && elements->resolving == 1)
1569 rc = 0;
1570 goto fail;
1572 else if (!n)
1573 goto fail;
1575 if (a_target == 1)
1577 xfree (*req);
1578 *req = str_dup (*req_orig);
1581 if (*(req + 1))
1583 int e_target = 0;
1585 n = find_elements (client, doc, n->children, req + 1, &rc, &e_target,
1586 NULL, list_not_found_cb, 1, 0, elements, 0);
1587 if (rc == GPG_ERR_ELEMENT_NOT_FOUND && elements->resolving == 1)
1589 rc = 0;
1590 goto fail;
1592 else if (rc && rc != GPG_ERR_EACCES)
1593 goto fail;
1594 else
1595 allowed = rc;
1598 done:
1599 if (!elements->prefix)
1602 * FIXME
1604 * If any req_orig element contains no target the element should be
1605 * prefixed with the literal character. Not really crucial if the
1606 * client isn't human because child elements are prefixed for the
1607 * current path. But may be confusing if editing by hand.
1609 if (elements->data)
1611 /* This is needed to prune the original requested element path to the
1612 * length of the failed element in the path. */
1613 int x = strv_length (req_orig)-strv_length ((char **)elements->data);
1614 int i;
1615 char **tmp = NULL;
1617 for (i = 0; i <= x; i++)
1618 tmp = strv_cat (tmp, str_dup (req_orig[i]));
1620 elements->prefix = strv_join ("\t", tmp);
1621 strv_free (tmp);
1622 strv_free (elements->data);
1623 elements->data = NULL;
1625 else
1627 if (root_only)
1628 elements->prefix = str_dup (*req_orig);
1629 else
1630 elements->prefix = strv_join ("\t", req_orig);
1633 if (!elements->prefix)
1635 rc = GPG_ERR_ENOMEM;
1636 goto fail;
1639 if (elements->verbose)
1641 int ret;
1642 struct string_s *realpath = NULL;
1644 rc = 0;
1646 if (!allowed && a_target && elements->with_target)
1648 rc = build_realpath (client, doc, path, &realpath);
1649 if (rc)
1650 goto fail;
1652 realpath = string_prepend (realpath, "T ");
1655 ret = strv_printf (&elements->elements, "%s%s%s%s%s",
1656 elements->prefix,
1657 (!allowed && n && find_element_node (n->children))
1658 || realpath ? " " : "",
1659 (!allowed && n && find_element_node (n->children)) ? "+" : "",
1660 !allowed && realpath ? realpath->str : "",
1661 allowed ? " P" : "");
1662 string_free (realpath, 1);
1663 if (!ret)
1665 rc = GPG_ERR_ENOMEM;
1666 goto fail;
1669 else if (strv_printf (&elements->elements, "%s", elements->prefix) == 0)
1671 rc = GPG_ERR_ENOMEM;
1672 goto fail;
1675 if (update_element_list (elements) == 0)
1677 rc = GPG_ERR_ENOMEM;
1678 goto fail;
1682 if (!allowed)
1683 rc = path_list_recurse (client, doc, n ? n->children : n, elements);
1685 fail:
1686 strv_free (req_orig);
1687 strv_free (req);
1688 return rc;
1691 gpg_error_t
1692 recurse_xpath_nodeset (struct client_s *client, xmlDocPtr doc,
1693 xmlNodeSetPtr nodes, xmlChar * value,
1694 xmlBufferPtr * result, int cmd, const xmlChar * attr)
1696 int i = value ? nodes->nodeNr - 1 : 0;
1697 xmlBufferPtr buf;
1699 buf = xmlBufferCreate ();
1701 if (!buf)
1702 return GPG_ERR_ENOMEM;
1704 for (; value ? i >= 0 : i < nodes->nodeNr; value ? i-- : i++)
1706 xmlNodePtr n = nodes->nodeTab[i];
1707 gpg_error_t rc;
1709 if (!n)
1710 continue;
1712 if (!value && !attr)
1714 if (xmlNodeDump (buf, doc, n, 0, 0) == -1)
1716 *result = buf;
1717 return GPG_ERR_BAD_DATA;
1720 continue;
1723 if (!attr)
1725 xmlNodeSetContent (n, value);
1726 rc = update_element_mtime (client, n);
1728 if (rc)
1729 return rc;
1731 else
1733 if (!cmd)
1734 rc = add_attribute (client, n, (char *) attr, (char *) value);
1735 else
1736 rc = delete_attribute (client, n, attr);
1738 if (rc)
1739 return rc;
1743 *result = buf;
1744 return 0;
1747 static gpg_error_t
1748 convert_root_element (struct client_s *client, xmlNodePtr n)
1750 xmlChar *a = xmlGetProp (n, (xmlChar *) "_name");
1751 gpg_error_t rc;
1753 if (a)
1755 xmlFree (a);
1756 xmlChar *t = xmlGetNodePath (n);
1758 log_write (_
1759 ("An existing \"_name\" attribute already exists. Please rename this attribute before converting. Path is: %s"),
1761 xmlFree (t);
1762 return GPG_ERR_AMBIGUOUS_NAME;
1765 a = xmlGetProp (n, (xmlChar *) "name");
1767 if (a)
1769 rc = add_attribute (client, n, "_name", (char *) a);
1770 xmlFree (a);
1772 if (rc)
1773 return rc;
1775 rc = delete_attribute (client, n, (xmlChar *) "name");
1777 if (rc)
1778 return rc;
1780 xmlNodeSetName (n, (xmlChar *) "element");
1783 return 0;
1786 gpg_error_t
1787 delete_attribute (struct client_s *client, xmlNodePtr n, const xmlChar * name)
1789 xmlAttrPtr a;
1790 gpg_error_t rc = 0;
1792 if ((a = xmlHasProp (n, name)) == NULL)
1793 return GPG_ERR_NOT_FOUND;
1795 if (xmlRemoveProp (a) == -1)
1796 return GPG_ERR_BAD_DATA;
1798 if (client && xmlStrEqual (name, (xmlChar *) "_acl"))
1800 char *user = create_acl_user (client);
1802 rc = add_attribute (client, n, (char *) "_acl", user);
1803 xfree (user);
1805 if (rc)
1806 return rc;
1809 return update_element_mtime (client, n);
1812 static gpg_error_t
1813 convert_elements_recurse (struct client_s *client, xmlDocPtr doc,
1814 xmlNodePtr n, unsigned depth)
1816 gpg_error_t rc;
1818 depth++;
1820 for (n = n->children; n; n = n->next)
1822 if (n->type == XML_ELEMENT_NODE)
1824 if (depth > 1)
1826 xmlChar *a = NULL;
1828 if (xmlStrEqual (n->name, (xmlChar *) "element"))
1830 xmlChar *t = xmlGetNodePath (n);
1832 log_write (_
1833 ("An existing \"element\" already exists. Please rename this element before converting. Path is: %s"),
1835 xmlFree (t);
1836 return GPG_ERR_AMBIGUOUS_NAME;
1839 a = xmlGetProp (n, (xmlChar *) "_name");
1840 if (a)
1842 xmlFree (a);
1843 xmlChar *t = xmlGetNodePath (n);
1845 log_write (_
1846 ("An existing \"_name\" attribute already exists. Please rename this attribute before converting. Path is: %s"),
1848 xmlFree (t);
1849 return GPG_ERR_AMBIGUOUS_NAME;
1852 xmlChar *tmp = xmlStrdup (n->name);
1854 if (!tmp)
1855 return GPG_ERR_ENOMEM;
1857 xmlNodeSetName (n, (xmlChar *) "element");
1858 rc = add_attribute (client, n, "_name", (char *) tmp);
1859 xmlFree (tmp);
1861 if (rc)
1862 return rc;
1864 else
1866 rc = convert_root_element (client, n);
1868 if (rc)
1869 return rc;
1873 if (n->children)
1875 rc = convert_elements_recurse (client, doc, n, depth);
1877 if (rc)
1878 return rc;
1882 return 0;
1885 /* Renames ALL elements to the new "element" name. Existing element names are
1886 * stored as an attribute "_name". This was introduced in pwmd 2.12 so
1887 * elements can contain common characters that the XML parser barfs on (an
1888 * email address for example. */
1889 gpg_error_t
1890 convert_pre_212_elements (xmlDocPtr doc)
1892 xmlNodePtr n = xmlDocGetRootElement (doc);
1894 log_write (_("Converting pre 2.12 data file..."));
1895 return convert_elements_recurse (NULL, doc, n, 0);
1898 gpg_error_t
1899 validate_import (struct client_s *client, xmlNodePtr node)
1901 gpg_error_t rc = 0;
1903 if (!node)
1904 return 0;
1906 for (xmlNodePtr n = node; n; n = n->next)
1908 if (n->type == XML_ELEMENT_NODE)
1910 if (xmlStrEqual (n->name, (xmlChar *) "element"))
1912 xmlChar *a = xmlGetProp (n, (xmlChar *) "_name");
1914 if (!a)
1916 xmlChar *t = xmlGetNodePath (n);
1918 log_write (_("Missing attribute '_name' at %s."), t);
1919 xmlFree (t);
1920 return GPG_ERR_INV_VALUE;
1923 if (!valid_xml_element (a))
1925 xmlChar *t = xmlGetNodePath (n);
1927 log_write (_("'%s' is not a valid element name at %s."), a,
1929 xmlFree (a);
1930 xmlFree (t);
1931 return GPG_ERR_INV_VALUE;
1934 xmlFree (a);
1935 a = xmlGetProp (n, (xmlChar *) "_ctime");
1936 if (!a)
1937 attr_ctime (client, n);
1939 xmlFree (a);
1940 a = xmlGetProp (n, (xmlChar *) "_mtime");
1941 if (!a)
1942 update_element_mtime (client, n);
1943 xmlFree (a);
1945 else
1947 xmlChar *t = xmlGetNodePath (n);
1949 log_write (_("Warning: unknown element '%s' at %s. Ignoring."),
1950 n->name, t);
1951 xmlFree (t);
1952 continue;
1956 if (n->children)
1958 rc = validate_import (client, n->children);
1960 if (rc)
1961 return rc;
1965 return rc;
1968 gpg_error_t
1969 update_element_mtime (struct client_s *client, xmlNodePtr n)
1971 return add_attribute (client, n, NULL, NULL);
1974 gpg_error_t
1975 unlink_node (struct client_s *client, xmlNodePtr n)
1977 gpg_error_t rc = 0;
1979 if (!n)
1980 return rc;
1982 if (n->parent)
1983 rc = update_element_mtime (client, n->parent);
1985 xmlUnlinkNode (n);
1986 return rc;
1989 gpg_error_t
1990 parse_doc (const char *xml, size_t len, xmlDocPtr *result)
1992 xmlDocPtr doc;
1994 xmlResetLastError ();
1995 doc = xmlReadMemory (xml, len, NULL, "UTF-8", XML_PARSE_NOBLANKS);
1996 if (!doc && xmlGetLastError ())
1997 return GPG_ERR_BAD_DATA;
1999 *result = doc;
2000 return !doc ? GPG_ERR_ENOMEM : 0;
2003 static xmlNodePtr
2004 realpath_elements_cb (struct client_s *client, xmlNodePtr node, char **target,
2005 gpg_error_t * rc, char **req_orig, void *data)
2007 char *path = *(char **) data;
2008 char *tmp = NULL, *result;
2010 if (path)
2012 xfree (path);
2013 *(char **) data = NULL;
2016 path = strv_join ("\t", target);
2018 if (!path)
2020 *rc = GPG_ERR_ENOMEM;
2021 return NULL;
2024 if (req_orig)
2026 tmp = strv_join ("\t", req_orig);
2028 if (!tmp)
2030 xfree (path);
2031 *rc = GPG_ERR_ENOMEM;
2032 return NULL;
2036 if (tmp && *tmp)
2037 result = str_asprintf ("%s\t%s", path, tmp);
2038 else
2039 result = str_dup (path);
2041 if (!result)
2043 *rc = GPG_ERR_ENOMEM;
2044 xfree (path);
2045 xfree (tmp);
2046 return NULL;
2049 xfree (path);
2050 xfree (tmp);
2051 *(char **) data = result;
2052 return node;
2055 gpg_error_t
2056 build_realpath (struct client_s *client, xmlDocPtr doc, char *line,
2057 struct string_s ** result)
2059 gpg_error_t rc;
2060 char **req;
2061 char *t;
2062 int i;
2063 xmlNodePtr n;
2064 struct string_s *string;
2065 char *rp = NULL;
2067 if (strchr (line, '\t') != NULL)
2069 if ((req = str_split (line, "\t", 0)) == NULL)
2070 return GPG_ERR_SYNTAX;
2072 else
2074 if ((req = str_split (line, " ", 0)) == NULL)
2075 return GPG_ERR_SYNTAX;
2078 n = find_root_element (client, doc, &req, &rc, NULL, 0, 0);
2079 if (rc)
2081 strv_free (req);
2082 return rc;
2085 rp = strv_join ("\t", req);
2086 if (!rp)
2088 strv_free (req);
2089 return GPG_ERR_ENOMEM;
2092 if (req[1])
2094 n = find_elements (client, doc, n->children, req + 1, &rc, NULL,
2095 realpath_elements_cb, NULL, 0, 0, &rp, 0);
2096 if (!n)
2098 xfree (rp);
2099 strv_free (req);
2100 return rc;
2104 string = string_new (rp);
2105 xfree (rp);
2106 strv_free (req);
2107 if (!string)
2108 return GPG_ERR_ENOMEM;
2110 again:
2111 for (i = 0, t = string->str + i; *t; t++, i++)
2113 if ((!i && *t != '!') || (*t == '\t' && *(t + 1) && *(t + 1) != '!'))
2115 struct string_s *s = string_insert_c (string, !i ? i++ : ++i, '!');
2117 if (!s)
2119 string_free (string, 1);
2120 return GPG_ERR_ENOMEM;
2123 string = s;
2124 goto again;
2128 *result = string;
2129 return rc;
2132 #if 0
2133 static char *
2134 node_to_element_path (xmlNodePtr node)
2136 xmlNodePtr n;
2137 struct string_s *str = string_new ("");
2138 char *result;
2140 for (n = node; n; n = n->parent)
2142 xmlNodePtr child;
2144 for (child = n; child; child = child->next)
2146 if (child->type != XML_ELEMENT_NODE)
2147 continue;
2149 xmlChar *name = node_has_attribute (n, (xmlChar *) "_name");
2150 if (name)
2152 str = string_prepend (str, (char *) name);
2153 xmlFree (name);
2154 name = node_has_attribute (n, (xmlChar *) "target");
2155 if (name)
2156 str = string_prepend (str, "\t");
2157 else
2158 str = string_prepend (str, "\t!");
2159 xmlFree (name);
2161 break;
2165 str = string_erase (str, 0, 1);
2166 result = str->str;
2167 string_free (str, 0);
2168 return result;
2170 #endif
2173 * Recurse the element tree beginning at 'node' and find elements who point
2174 * back to 'src' or 'dst'. Also follows target attributes.
2176 static gpg_error_t
2177 find_child_to_target (struct client_s *client, xmlDocPtr doc, xmlNodePtr node,
2178 xmlNodePtr src, xmlNodePtr dst, unsigned depth,
2179 int is_target)
2181 xmlNodePtr n;
2182 gpg_error_t rc = 0;
2184 if (max_recursion_depth >= 1 && depth > max_recursion_depth)
2185 return gpg_error (GPG_ERR_ELOOP);
2187 for (n = node; n; n = n->next)
2189 xmlChar *target;
2191 if (n->type != XML_ELEMENT_NODE)
2192 continue;
2194 if (n == src || n == dst)
2195 return GPG_ERR_ELOOP;
2197 target = node_has_attribute (n, (xmlChar *) "target");
2198 if (target)
2200 xmlNodePtr tmp;
2201 char **result = NULL;
2203 tmp = resolve_path (client, doc, target, &result, &rc);
2204 xmlFree (target);
2205 strv_free (result);
2206 if (!rc)
2208 rc = find_child_to_target (client, doc, tmp, src, dst, ++depth,
2210 depth--;
2213 if (rc && gpg_err_code (rc) != GPG_ERR_ELEMENT_NOT_FOUND)
2214 return rc;
2216 if (is_target)
2217 break;
2219 continue;
2222 if (n->children)
2224 rc = find_child_to_target (client, doc, n->children, src, dst,
2225 ++depth,0);
2226 depth--;
2227 if (rc)
2228 return rc;
2231 if (is_target)
2232 break;
2235 return rc;
2238 static gpg_error_t
2239 find_child_of_parent (xmlDocPtr doc, xmlNodePtr src, xmlNodePtr dst)
2241 xmlNodePtr n;
2242 gpg_error_t rc = 0;
2244 for (n = src; n; n = n->next)
2246 if (n->type != XML_ELEMENT_NODE)
2247 continue;
2249 if (n == dst)
2251 rc = GPG_ERR_ELOOP;
2252 break;
2255 rc = find_child_of_parent (doc, n->children, dst);
2258 return rc;
2261 static gpg_error_t
2262 find_parent_of_child (xmlDocPtr doc, xmlNodePtr node, xmlNodePtr dst)
2264 xmlNodePtr n;
2265 gpg_error_t rc = 0;
2267 for (n = node; n; n = n->parent)
2269 if (n->type != XML_ELEMENT_NODE)
2271 xmlNodePtr tmp;
2273 for (tmp = n->next; tmp; n = n->next)
2275 if (n->type != XML_ELEMENT_NODE)
2276 continue;
2278 if (tmp == dst)
2279 return GPG_ERR_ELOOP;
2283 if (n == dst)
2284 return GPG_ERR_ELOOP;
2287 return rc;
2290 gpg_error_t
2291 validate_target_attribute (struct client_s *client, xmlDocPtr doc,
2292 const char *src, xmlNodePtr dst_node)
2294 gpg_error_t rc;
2295 xmlNodePtr src_node;
2296 char **src_req = NULL;
2298 src_node = resolve_path (client, doc, (xmlChar *) src, &src_req, &rc);
2299 if (rc)
2300 goto fail;
2302 client->flags |= FLAG_ACL_IGNORE;
2303 /* A destination element is a child of the source element. */
2304 rc = find_child_of_parent (doc, src_node->children, dst_node);
2305 if (rc)
2306 goto fail;
2308 /* The destination element is a parent of the source element. */
2309 rc = find_parent_of_child (doc, src_node->parent, dst_node);
2310 if (rc)
2311 goto fail;
2313 /* A destination child element contains a target to the source element. */
2314 rc = find_child_to_target (client, doc, dst_node->children, src_node,
2315 dst_node, 0, 0);
2316 if (rc)
2317 goto fail;
2319 fail:
2320 strv_free (src_req);
2321 client->flags &= ~(FLAG_ACL_IGNORE | FLAG_ACL_ERROR);
2322 return rc;
2325 /* The owner of the element is the first user listed in the _acl attribute
2326 * list. acl_check() should be called before calling this function. An empty
2327 * ACL is an error if the client is not invoking_user.
2329 gpg_error_t
2330 is_element_owner (struct client_s *client, xmlNodePtr n)
2332 xmlChar *acl = node_has_attribute (n, (xmlChar *) "_acl");
2333 char **users;
2334 gpg_error_t rc = GPG_ERR_EACCES;
2336 if (!acl || !*acl)
2338 xmlFree (acl);
2339 return peer_is_invoker (client);
2342 users = str_split((char *)acl, ",", 0);
2343 if (users && *users)
2345 char *user;
2347 #ifdef WITH_GNUTLS
2348 if (client->thd->remote)
2349 user = str_asprintf ("#%s", client->thd->tls->fp);
2350 else
2351 user = get_username (client->thd->peer->uid);
2352 #else
2353 user = get_username (client->thd->peer->uid);
2354 #endif
2356 if (*user == '#')
2357 rc = !strcasecmp (*users, user) ? 0 : GPG_ERR_EACCES;
2358 else
2359 rc = !strcmp (*users, user) ? 0 : GPG_ERR_EACCES;
2361 if (rc)
2362 rc = peer_is_invoker (client);
2364 xfree (user);
2367 strv_free (users);
2368 return rc;