s/peer_is_self/peer_is_invoker/.
[libpwmd.git] / src / xml.c
blobc90dd2f46a5a94b127a07fc751151d89101db291
1 /*
2 Copyright (C) 2006, 2007, 2008, 2009, 2010, 2011, 2012, 2013, 2014
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"
48 extern void log_write (const char *fmt, ...);
51 * 'element' must be allocated.
53 int
54 is_literal_element (char **element)
56 char *p;
58 if (!element || !*element)
59 return 0;
61 if (*(*element) == '!')
63 char *c;
65 for (p = *element, c = p + 1; *c; c++)
66 *p++ = *c;
68 *p = 0;
69 return 1;
72 return 0;
75 int
76 valid_xml_attribute (const char *str)
78 return valid_xml_element ((xmlChar *)str);
81 int
82 valid_xml_element (xmlChar *str)
84 wchar_t *wc;
85 size_t len, c;
87 if (!str || !*str || *str == '!')
88 return 0;
90 wc = str_to_wchar ((const char *)str);
91 len = wcslen (wc);
93 for (c = 0; c < len; c++)
95 if (iswspace(wc[c]))
97 xfree (wc);
98 return 0;
102 xfree (wc);
103 return 1;
107 valid_element_path (char **path, int with_content)
109 char **dup = NULL, **p;
111 if (!path || !*path)
112 return 0;
114 /* Save some memory by not duplicating the element content. */
115 if (with_content)
117 int i, t = strv_length (path);
119 for (i = 0; i < t - 1; i++)
121 char **tmp = xrealloc (dup, (i + 2) * sizeof (char *));
123 if (!tmp)
125 strv_free (dup);
126 return 0;
129 dup = tmp;
130 dup[i] = str_dup (path[i]);
131 dup[i + 1] = NULL;
134 else
135 dup = strv_dup (path);
137 if (!dup)
138 return 0;
140 for (p = dup; *p && *(*p); p++)
142 is_literal_element (&(*p));
143 if (!valid_xml_element ((xmlChar *) * p))
145 strv_free (dup);
146 return 0;
150 strv_free (dup);
151 return 1;
154 gpg_error_t
155 attr_ctime (xmlNodePtr n)
157 char *buf = str_asprintf ("%li", time (NULL));
158 gpg_error_t rc;
160 if (!buf)
161 return GPG_ERR_ENOMEM;
163 rc = add_attribute (n, "_ctime", buf);
164 xfree (buf);
165 return rc;
168 // FIXME add parameter to want RW or RO access to the XML node.
169 static gpg_error_t
170 acl_check (struct client_s *client, xmlNodePtr n)
172 gpg_error_t rc = GPG_ERR_EPERM;
173 xmlChar *acl = node_has_attribute (n, (xmlChar *) "_acl");
174 char **users = acl ? str_split((char *)acl, ",", 0) : NULL;
175 char **p;
176 int allowed = 0;
178 if (!acl || !users || !*users)
180 strv_free(users);
181 return peer_is_invoker(client);
184 if (!peer_is_invoker(client))
185 return 0;
187 for (p = users; *p; p++)
189 #ifdef WITH_GNUTLS
190 rc = acl_check_common (client, *p,
191 client->thd->remote ? 0 : client->thd->peer->uid,
192 client->thd->remote ? 0 : client->thd->peer->gid,
193 &allowed);
194 #else
195 rc = acl_check_common (client, *p, client->thd->peer->uid,
196 client->thd->peer->gid, &allowed);
197 #endif
200 xmlFree(acl);
201 strv_free(users);
202 if (rc)
203 return rc;
205 return allowed ? 0 : GPG_ERR_EPERM;
208 static char *
209 create_acl_user (struct client_s *client)
211 #ifdef WITH_GNUTLS
212 if (client->thd->remote)
213 return str_asprintf ("#%s", client->thd->tls->fp);
214 #endif
216 return get_username (client->thd->peer->uid);
219 static gpg_error_t
220 create_new_element (struct client_s *client, int verify, xmlNodePtr parent,
221 const char *name, xmlNodePtr * result)
223 xmlNodePtr n;
224 gpg_error_t rc;
226 // Allow any client to create a non-existing root element.
227 if (parent->parent->type != XML_DOCUMENT_NODE)
229 rc = acl_check(client, parent);
230 if (rc)
231 return rc;
234 n = xmlNewNode (NULL, (xmlChar *) "element");
235 if (!n)
236 return GPG_ERR_ENOMEM;
238 rc = add_attribute (n, "_name", name);
239 if (!rc)
240 rc = attr_ctime (n);
242 if (!rc && verify && parent->parent->type != XML_DOCUMENT_NODE)
244 rc = peer_is_invoker (client);
245 if (rc == GPG_ERR_EPERM)
246 rc = is_element_owner (client, parent);
249 if (!rc)
251 xmlNodePtr p = xmlAddChild (parent, n);
252 char *user = create_acl_user (client);
254 if (result)
255 *result = p;
257 rc = add_attribute(p, "_acl", user);
258 xfree (user);
260 else
261 xmlFreeNode (n);
263 return rc;
266 gpg_error_t
267 new_root_element (struct client_s *client, xmlDocPtr doc, char *name)
269 xmlNodePtr root = xmlDocGetRootElement (doc);
270 char *p = name;
272 if (!p || !root)
273 return GPG_ERR_BAD_DATA;
275 if (*p == '!')
276 p++;
278 if (!valid_xml_element ((xmlChar *) p))
279 return GPG_ERR_INV_VALUE;
281 return create_new_element (client, 0, root, p, NULL);
284 static xmlDocPtr
285 create_dtd ()
287 xmlDocPtr doc;
288 xmlTextWriterPtr wr = xmlNewTextWriterDoc (&doc, 0);
290 if (!wr)
291 return NULL;
293 if (xmlTextWriterStartDocument (wr, NULL, "UTF-8", "yes"))
294 goto fail;
296 if (xmlTextWriterStartDTD (wr, (xmlChar *) "pwmd", NULL, NULL) == -1)
297 goto fail;
299 if (xmlTextWriterWriteDTDElement (wr, (xmlChar *) "pwmd",
300 (xmlChar *) "(element)") == -1)
301 goto fail;
303 xmlTextWriterEndDTDElement (wr);
305 if (xmlTextWriterWriteDTDAttlist (wr, (xmlChar *) "element",
306 (xmlChar *) "_name CDATA #REQUIRED") ==
308 goto fail;
310 xmlTextWriterEndDTDAttlist (wr);
311 xmlTextWriterEndDTD (wr);
313 if (xmlTextWriterStartElement (wr, (xmlChar *) "pwmd"))
314 goto fail;
316 xmlTextWriterEndElement (wr);
317 xmlTextWriterEndDocument (wr);
318 xmlFreeTextWriter (wr);
319 return doc;
321 fail:
322 xmlTextWriterEndDocument (wr);
323 xmlFreeTextWriter (wr);
324 xmlFreeDoc (doc);
325 return NULL;
328 xmlDocPtr
329 new_document ()
331 return create_dtd ();
334 xmlNodePtr
335 find_element_node (xmlNodePtr node)
337 xmlNodePtr n = node;
339 if (n && n->type == XML_ELEMENT_NODE)
340 return n;
342 for (n = node; n; n = n->next)
344 if (n->type == XML_ELEMENT_NODE)
345 return n;
348 return NULL;
351 static xmlNodePtr
352 resolve_path (struct client_s *client, xmlDocPtr doc, xmlChar * path,
353 char ***result, gpg_error_t * rc)
355 xmlNodePtr n;
356 char **req;
358 req = str_split ((char *) path, "\t", 0);
359 if (!req)
361 *rc = GPG_ERR_ENOMEM;
362 return NULL;
365 n = find_root_element (client, doc, &req, rc, NULL, 0, 0);
366 if (!n)
368 strv_free (req);
369 return NULL;
372 if (req[1])
373 n = find_elements (client, doc, n->children, req + 1, rc, NULL, NULL, NULL,
374 0, 0, NULL, 0);
376 if (*rc)
377 strv_free (req);
378 else
379 *result = req;
381 return n;
385 * Lists root element names; the value of the attribute "_name" of an element
386 * "element". If there's a target attribute both literal and non-literal
387 * element names will be added. This is the primary reason why XML entities
388 * cannot be used. There wouldn't be a way to get the literal an non-literal
389 * element paths.
391 gpg_error_t
392 list_root_elements (struct client_s *client, xmlDocPtr doc,
393 struct string_s ** result, int verbose, int with_target)
395 xmlNodePtr n = NULL;
396 struct slist_s *list = NULL;
397 int total, i;
398 struct string_s *string;
399 gpg_error_t rc = 0;
401 n = xmlDocGetRootElement (doc);
402 if (!n || !n->children)
403 return GPG_ERR_NO_DATA;
405 for (n = n->children; n; n = n->next)
407 xmlAttrPtr a;
408 xmlChar *val, *target;
409 struct slist_s *tlist;
410 char *tmp;
412 if (n->type != XML_ELEMENT_NODE)
413 continue;
415 a = xmlHasProp (n, (xmlChar *) "_name");
416 if (!a || !a->children->content)
417 continue;
419 val = xmlNodeGetContent (a->children);
420 if (!val)
422 rc = GPG_ERR_ENOMEM;
423 goto fail;
426 tmp =
427 str_asprintf ("!%s%s", (char *) val,
428 verbose ? find_element_node (n->children) ? " +" : "" :
429 "");
431 if (!tmp)
433 xmlFree (val);
434 rc = GPG_ERR_ENOMEM;
435 goto fail;
438 tlist = slist_append (list, tmp);
439 if (!tlist)
441 xmlFree (val);
442 rc = GPG_ERR_ENOMEM;
443 goto fail;
446 list = tlist;
447 target = node_has_attribute (n, (xmlChar *) "target");
448 if (target)
450 char *t = NULL;
452 if (verbose)
454 char **req = NULL;
455 xmlNodePtr tnode = resolve_path (client, doc, target, &req, &rc);
457 if (rc == GPG_ERR_ELEMENT_NOT_FOUND || rc == GPG_ERR_ELOOP
458 || rc == GPG_ERR_EPERM)
460 t = str_asprintf ("%s %s", (char *) val,
461 rc == GPG_ERR_ELOOP ? "O" :
462 rc == GPG_ERR_EPERM ? "P" : "E");
463 rc = 0;
465 else if (!rc)
467 struct string_s *realpath = NULL;
469 if (with_target)
471 rc = build_realpath (client, doc, (char *) target,
472 &realpath);
473 if (rc)
475 strv_free (req);
476 xmlFree (val);
477 xmlFree (target);
478 goto fail;
481 realpath = string_prepend (realpath, "T ");
484 t = str_asprintf ("%s%s%s%s", (char *) val,
485 (tnode
486 && find_element_node (tnode->children))
487 || realpath ? " " : "", tnode
488 && find_element_node (tnode->children) ?
489 "+" : "", realpath ? realpath->str : "");
491 if (realpath)
492 string_free (realpath, 1);
495 if (req)
496 strv_free (req);
498 else
499 t = str_dup ((char *) val);
501 if (!t || rc)
503 xmlFree (val);
504 xmlFree (target);
505 rc = rc ? rc : GPG_ERR_ENOMEM;
506 goto fail;
509 tlist = slist_append (list, t);
510 if (!tlist)
512 xmlFree (val);
513 xfree (t);
514 xmlFree (target);
515 rc = GPG_ERR_ENOMEM;
516 goto fail;
519 list = tlist;
522 xmlFree (val);
523 xmlFree (target);
526 total = slist_length (list);
527 if (!total)
528 return GPG_ERR_NO_DATA;
530 string = string_new (NULL);
531 if (!string)
533 rc = GPG_ERR_ENOMEM;
534 goto fail;
537 for (i = 0; i < total; i++)
539 char *val = slist_nth_data (list, i);
541 string_append_printf (string, "%s\n", val);
544 string = string_truncate (string, string->len - 1);
545 *result = string;
547 fail:
548 total = slist_length (list);
549 for (i = 0; i < total; i++)
550 xfree (slist_nth_data (list, i));
552 slist_free (list);
553 return rc;
557 * Prevents a sibling element past the current element path with the same
558 * element name.
560 static xmlNodePtr
561 find_stop_node (xmlNodePtr node)
563 xmlNodePtr n;
565 for (n = node->parent->children; n; n = n->next)
567 if (n == node)
568 return n->next;
571 return NULL;
574 xmlNodePtr
575 create_target_elements_cb (struct client_s *client, int verify,
576 xmlNodePtr node, char **path, gpg_error_t *rc,
577 void *data)
579 int i;
580 char **req = path;
581 xmlNodePtr parent = data;
583 for (i = 0; req[i] && *req[i]; i++)
585 xmlNodePtr n;
587 if (parent && node == parent)
589 *rc = GPG_ERR_CONFLICT;
590 return NULL;
593 is_literal_element (&req[i]);
595 if ((n = find_element (client, node, req[i],
596 find_stop_node (node), rc)) == NULL ||
597 (n && n->parent == node->parent))
600 if (!*rc)
601 *rc = create_new_element (client, verify, node, req[i], &node);
603 if (*rc)
604 return NULL;
606 else
607 node = n;
610 return node;
613 xmlNodePtr
614 find_text_node (xmlNodePtr node)
616 xmlNodePtr n = node;
618 if (n && n->type == XML_TEXT_NODE)
619 return n;
621 for (n = node; n; n = n->next)
623 if (n->type == XML_TEXT_NODE)
624 return n;
627 return NULL;
630 xmlNodePtr
631 create_elements_cb (struct client_s *client, int verify, xmlNodePtr node,
632 char **elements, gpg_error_t * rc, void *data)
634 int i;
635 char **req = elements;
637 if (node->type == XML_TEXT_NODE)
638 node = node->parent;
640 for (i = 0; req[i] && *req[i]; i++)
642 xmlNodePtr n;
645 * Strip the first '!' if needed. If there's another, it's an
646 * rc. The syntax has already been checked before calling this
647 * function.
649 is_literal_element (&req[i]);
650 n = find_element (client, node, req[i], find_stop_node (node), rc);
651 if (*rc)
652 return NULL;
655 * If the found element has the same parent as the current element,
656 * they are siblings and the new element needs to be created as a
657 * child of the current element (node).
659 if (n && n->parent == node->parent)
660 n = NULL;
662 if (!n)
664 *rc = create_new_element (client, 0, node, req[i], &node);
665 if (*rc)
666 return NULL;
668 else
669 node = n;
672 return node;
675 /* The root element is really req[0]. It is need as a pointer in case there is
676 * a target attribute so it can be updated. */
677 xmlNodePtr
678 find_root_element (struct client_s *client, xmlDocPtr doc, char ***req,
679 gpg_error_t * rc, int *target, int recursion_depth,
680 int stop)
682 xmlNodePtr n = xmlDocGetRootElement (doc);
683 int depth = 0;
684 char *root = str_dup (*req[0]);
685 int literal = is_literal_element (&root);
687 if (!root)
689 *rc = GPG_ERR_ENOMEM;
690 return NULL;
693 *rc = 0;
694 recursion_depth++;
696 if (max_recursion_depth >= 1 && recursion_depth > max_recursion_depth)
698 xmlChar *t = xmlGetNodePath (n);
700 log_write ("%s: %s", pwmd_strerror (GPG_ERR_ELOOP), t);
701 xmlFree (t);
702 xfree (root);
703 *rc = GPG_ERR_ELOOP;
704 return NULL;
707 while (n)
709 if (n->type == XML_ELEMENT_NODE)
711 if (depth == 0 && xmlStrEqual (n->name, (xmlChar *) "pwmd"))
713 n = n->children;
714 depth++;
715 continue;
718 if (depth == 1 && xmlStrEqual (n->name, (xmlChar *) "element"))
720 xmlChar *content = node_has_attribute (n, (xmlChar *) "_name");
722 if (!content)
723 continue;
725 if (xmlStrEqual (content, (xmlChar *) root))
727 char **nreq, **tmp = NULL;
729 *rc = acl_check(client, n);
730 if (*rc)
732 xmlFree (content);
733 xfree (root);
734 return NULL;
737 if (literal == 1)
739 xmlFree (content);
740 xfree (root);
741 return n;
744 xmlFree (content);
745 content = node_has_attribute (n, (xmlChar *) "target");
747 if (target)
748 *target = 1;
750 if (!content || stop)
752 if (content)
753 xmlFree (content);
755 xfree (root);
756 return n;
759 if (strchr ((char *) content, '\t'))
761 nreq = str_split ((char *) content, "\t", 0);
762 xmlFree (content);
764 #if 0
766 * FIXME ENOMEM
768 if (!nreq)
770 *rc = GPG_ERR_ENOMEM;
771 return NULL;
773 #endif
775 tmp = *req;
776 tmp = strv_catv (nreq, tmp + 1);
777 strv_free (nreq);
779 if (!tmp)
781 xfree (root);
782 *rc = GPG_ERR_ENOMEM;
783 return NULL;
786 strv_free (*req);
787 *req = tmp;
789 else
791 if (strv_printf (&tmp, "%s", content) == 0)
793 xmlFree (content);
794 xfree (root);
795 *rc = GPG_ERR_ENOMEM;
796 return NULL;
799 xmlFree (content);
800 nreq = *req;
801 nreq = strv_catv (tmp, nreq + 1);
802 strv_free (tmp);
804 if (!nreq)
806 *rc = GPG_ERR_ENOMEM;
807 xfree (root);
808 return NULL;
811 strv_free (*req);
812 *req = nreq;
815 xfree (root);
817 find_root_element (client, doc, req, rc, target,
818 recursion_depth, 0);
819 return n;
822 xmlFree (content);
826 n = n->next;
829 xfree (root);
830 *rc = GPG_ERR_ELEMENT_NOT_FOUND;
831 return NULL;
834 xmlNodePtr
835 find_element (struct client_s *client, xmlNodePtr node, char *element,
836 xmlNodePtr stop, gpg_error_t *rc)
838 xmlNodePtr n;
840 *rc = 0;
842 if (!node || !element)
843 return NULL;
845 for (n = node; n; n = n->next)
847 if (n->type != XML_ELEMENT_NODE)
848 continue;
850 if (n == stop)
851 break;
853 xmlChar *a = node_has_attribute (n, (xmlChar *) "_name");
855 if (a && xmlStrEqual (a, (xmlChar *) element))
857 xmlFree (a);
859 *rc = acl_check(client, n);
860 if (*rc)
861 n = NULL;
863 return n;
866 xmlFree (a);
869 return NULL;
872 xmlChar *
873 node_has_attribute (xmlNodePtr n, xmlChar * attr)
875 xmlAttrPtr a = xmlHasProp (n, attr);
877 if (!a)
878 return NULL;
880 if (!a->children || !a->children->content)
881 return NULL;
883 return xmlGetProp (n, attr);
886 static int
887 element_to_literal (char **element)
889 char *p = str_asprintf ("!%s", *element);
891 if (!p)
892 return 0;
894 xfree (*element);
895 *element = p;
896 return 1;
899 /* Resolves elements in 'req' one at a time. It's recursive in case of
900 * "target" attributes. */
901 xmlNodePtr
902 find_elements (struct client_s *client, xmlDocPtr doc, xmlNodePtr node,
903 char **req, gpg_error_t * rc, int *target,
904 xmlNodePtr (*found_fn) (struct client_s *, xmlNodePtr, char **,
905 gpg_error_t *, char **, void *),
906 xmlNodePtr (*not_found_fn) (struct client_s *, int, xmlNodePtr,
907 char **, gpg_error_t *, void *),
908 int is_list_command, int recursion_depth, void *data, int stop)
910 xmlNodePtr n, last, last_node;
911 char **p;
912 int found = 0;
914 *rc = 0;
915 recursion_depth++;
917 if (max_recursion_depth >= 1 && recursion_depth > max_recursion_depth)
919 xmlChar *t = xmlGetNodePath (node);
921 log_write ("%s: %s", pwmd_strerror (GPG_ERR_ELOOP), t);
922 xmlFree (t);
923 recursion_depth--;
924 *rc = GPG_ERR_ELOOP;
925 return NULL;
928 for (last_node = last = n = node, p = req; *p; p++)
930 xmlNodePtr tmp;
931 char *t;
932 int literal;
934 if (!*(*p))
936 *rc = GPG_ERR_ELEMENT_NOT_FOUND;
937 return NULL;
940 t = str_dup (*p);
941 if (!t)
943 *rc = GPG_ERR_ENOMEM;
944 return NULL;
947 literal = is_literal_element (&t);
948 n = find_element (client, last, t, NULL, rc);
949 xfree (t);
951 if (*rc && *rc != GPG_ERR_ELEMENT_NOT_FOUND)
952 return NULL;
954 if (!n)
956 if (not_found_fn)
957 return not_found_fn (client, 1,
958 found ? last_node : last_node->parent, p,
959 rc, data);
961 if (!*rc)
962 *rc = GPG_ERR_ELEMENT_NOT_FOUND;
964 return NULL;
967 last = n->children;
968 last_node = n;
969 found = 1;
971 if (literal == 0)
973 xmlChar *content = node_has_attribute (n, (xmlChar *) "target");
974 char **nreq = NULL, **nnreq;
976 if (!content)
978 if (is_list_command == 1)
980 if (element_to_literal (&(*p)) == 0)
982 *rc = GPG_ERR_ENOMEM;
983 return NULL;
987 continue;
990 if (target)
991 *target = 1;
993 if (!*(p + 1) && stop)
995 xmlFree (content);
996 return n;
999 if (strchr ((char *) content, '\t') != NULL)
1001 if ((nreq = str_split ((char *) content, "\t", 0)) == NULL)
1003 xmlFree (content);
1004 *rc = GPG_ERR_INV_VALUE;
1005 return NULL;
1008 else
1010 if ((nreq = str_split ((char *) content, " ", 0)) == NULL)
1012 xmlFree (content);
1013 *rc = GPG_ERR_INV_VALUE;
1014 return NULL;
1018 xmlFree (content);
1019 tmp = find_root_element (client, doc, &nreq, rc, target, 0, 0);
1021 if (!tmp)
1023 strv_free (nreq);
1024 return NULL;
1027 if (found_fn)
1029 found_fn (client, tmp, nreq, rc, p + 1, data);
1031 if (*rc)
1033 strv_free (nreq);
1034 return NULL;
1038 if (!*(nreq + 1) && !*(p + 1))
1040 strv_free (nreq);
1041 return tmp;
1044 nnreq = strv_catv (nreq + 1, p + 1);
1045 strv_free (nreq);
1047 // FIXME ENOMEM
1048 if (!nnreq || !*nnreq)
1050 if (nnreq)
1051 strv_free (nnreq);
1053 return tmp;
1056 if (tmp->children)
1057 n = find_elements (client, doc, tmp->children, nnreq, rc, NULL,
1058 found_fn, not_found_fn, is_list_command,
1059 recursion_depth, data, stop);
1060 else
1062 strv_free (nnreq);
1064 if (not_found_fn)
1065 return not_found_fn (client, 1, tmp, p + 1, rc, data);
1067 *rc = GPG_ERR_ELEMENT_NOT_FOUND;
1068 return NULL;
1071 if (*(p + 1))
1073 char **zz = p + 1, **qq = nnreq;
1075 if (strv_length (nnreq) > strv_length (p + 1))
1076 qq = nnreq + 1;
1078 for (; *qq && *zz; zz++)
1080 xfree (*zz);
1081 *zz = str_dup (*qq++);
1083 if (!*zz)
1085 *rc = GPG_ERR_ENOMEM;
1086 n = NULL;
1087 break;
1092 strv_free (nnreq);
1093 return n;
1097 return n;
1100 static int
1101 update_element_list (struct element_list_s *elements)
1103 char *line;
1104 struct slist_s *l;
1106 if (!elements || !elements->elements)
1107 return 1;
1109 line = strv_join ("\t", elements->elements);
1111 if (!line)
1112 return 0;
1114 strv_free (elements->elements);
1115 elements->elements = NULL;
1116 l = slist_append (elements->list, line);
1118 if (!l)
1119 return 0;
1121 elements->list = l;
1122 return 1;
1125 static gpg_error_t
1126 path_list_recurse (struct client_s *client, xmlDocPtr doc, xmlNodePtr node,
1127 struct element_list_s *elements)
1129 gpg_error_t rc = 0;
1130 xmlNodePtr n;
1131 gpg_error_t error_flag = 0;
1133 for (n = node; n; n = n->next)
1135 xmlChar *target = NULL;
1136 xmlChar *a = node_has_attribute (n, (xmlChar *) "_name");
1137 int err = 0;
1139 rc = 0;
1140 if (!a)
1141 continue;
1143 if (n->type != XML_ELEMENT_NODE)
1144 goto children;
1146 rc = acl_check(client, n);
1148 if (elements->verbose)
1150 if (strv_printf
1151 (&elements->elements, "%s\t!%s%s%s", elements->prefix, a,
1152 !rc && find_element_node (n->children) ? " +" : "",
1153 rc == GPG_ERR_EPERM ? " P" : "") == 0)
1155 xmlFree (a);
1156 return GPG_ERR_ENOMEM;
1159 else
1160 if (strv_printf (&elements->elements, "%s\t!%s", elements->prefix, a)
1161 == 0)
1163 xmlFree (a);
1164 return GPG_ERR_ENOMEM;
1167 if (update_element_list (elements) == 0)
1169 xmlFree (a);
1170 return GPG_ERR_ENOMEM;
1174 if (rc == GPG_ERR_EPERM)
1176 xmlFree(a);
1177 error_flag = rc;
1178 continue;
1180 else if (rc)
1182 xmlFree (a);
1183 return rc;
1186 target = node_has_attribute (n, (xmlChar *) "target");
1187 if (target)
1189 char *tmp;
1190 char *save = elements->prefix;
1191 int r = elements->resolving;
1192 char **req = NULL;
1193 xmlNodePtr tnode;
1194 struct string_s *realpath = NULL;
1196 tnode = resolve_path (client, doc, target, &req, &rc);
1197 if (rc == GPG_ERR_ELOOP || rc == GPG_ERR_ELEMENT_NOT_FOUND
1198 || rc == GPG_ERR_EPERM)
1200 if (rc == GPG_ERR_ELOOP)
1202 xmlChar *t = xmlGetNodePath (n);
1204 log_write ("%s: %s", pwmd_strerror (GPG_ERR_ELOOP), t);
1205 xmlFree (t);
1208 if (elements->verbose)
1210 strv_printf (&elements->elements, "%s\t%s %s",
1211 elements->prefix, a,
1212 rc == GPG_ERR_ELOOP ? "O" :
1213 rc == GPG_ERR_EPERM ? "P" : "E");
1214 error_flag = err = rc;
1215 rc = 0;
1216 goto update;
1220 if (!elements->verbose && rc)
1222 xmlFree (a);
1223 xmlFree (target);
1224 return rc;
1227 if (elements->with_target)
1229 rc = build_realpath (client, doc, (char *) target, &realpath);
1230 if (rc)
1232 xmlFree (a);
1233 xmlFree (target);
1234 return rc;
1237 realpath = string_prepend (realpath, "T ");
1240 if (elements->verbose)
1242 if (!strv_printf (&elements->elements, "%s\t%s%s%s%s",
1243 elements->prefix, a,
1244 (tnode && find_element_node (tnode->children))
1245 || realpath ? " " : "", tnode
1246 && find_element_node (tnode->children) ? "+" :
1247 "", realpath ? realpath->str : ""))
1249 xmlFree (a);
1250 xmlFree (target);
1251 return GPG_ERR_ENOMEM;
1254 else
1255 if (!strv_printf
1256 (&elements->elements, "%s\t%s", elements->prefix, a))
1258 xmlFree (a);
1259 xmlFree (target);
1260 return GPG_ERR_ENOMEM;
1263 update:
1264 if (realpath)
1265 string_free (realpath, 1);
1267 tmp = strv_join ("\t", elements->elements);
1269 if (!tmp)
1271 xmlFree (a);
1272 xmlFree (target);
1273 return GPG_ERR_ENOMEM;
1276 if (update_element_list (elements) == 0)
1278 xfree (tmp);
1279 xmlFree (a);
1280 xmlFree (target);
1281 return GPG_ERR_ENOMEM;
1284 if (!err && elements->recurse)
1286 /* Prune element flags. */
1287 if (elements->verbose && strchr (tmp, ' '))
1289 char *p;
1291 for (p = tmp; *p; p++)
1293 if (*p == ' ')
1295 *p = 0;
1296 break;
1301 elements->prefix = tmp;
1302 elements->resolving = 1;
1303 rc = create_path_list (client, doc, elements, (char *) target);
1304 elements->resolving = r;
1305 elements->prefix = save;
1307 if (rc && gpg_err_code (rc) != GPG_ERR_ELOOP
1308 && gpg_err_code(rc) != GPG_ERR_EPERM)
1310 xfree (tmp);
1311 xmlFree (target);
1312 xmlFree (a);
1313 return rc;
1316 error_flag = err = rc;
1317 rc = 0;
1320 xfree (tmp);
1321 xmlFree (target);
1324 children:
1325 if (n->children && elements->recurse && err != GPG_ERR_ELOOP
1326 && err != GPG_ERR_EPERM)
1328 char *tmp = str_asprintf ("%s\t!%s", elements->prefix, a);
1329 char *save = elements->prefix;
1331 if (!tmp)
1333 xmlFree (a);
1334 return GPG_ERR_ENOMEM;
1337 elements->prefix = tmp;
1338 rc = path_list_recurse (client, doc, n->children, elements);
1339 xfree (elements->prefix);
1340 elements->prefix = save;
1342 if (rc)
1344 xmlFree (a);
1345 return rc;
1349 xmlFree (a);
1352 return error_flag == GPG_ERR_ELOOP || error_flag == GPG_ERR_EPERM
1353 ? error_flag : rc;
1356 gpg_error_t
1357 add_attribute (xmlNodePtr node, const char *name, const char *value)
1359 char *buf;
1360 gpg_error_t rc;
1362 if (name && !xmlSetProp (node, (xmlChar *) name, (xmlChar *) value))
1363 return GPG_ERR_BAD_DATA;
1365 if (name && xmlStrEqual ((xmlChar *) name, (xmlChar *) "_mtime"))
1366 return 0;
1368 buf = str_asprintf ("%li", time (NULL));
1369 rc = add_attribute (node, "_mtime", buf);
1370 xfree (buf);
1371 return rc;
1375 * From the element path 'path', find sub-nodes and append them to the list.
1377 gpg_error_t
1378 create_path_list (struct client_s *client, xmlDocPtr doc,
1379 struct element_list_s * elements, char *path)
1381 gpg_error_t rc;
1382 char **req, **req_orig;
1383 xmlNodePtr n;
1384 int a_target = 0;
1386 req = str_split (path, "\t", 0);
1387 if (!req)
1389 req = str_split (path, " ", 0);
1390 if (!req)
1391 return GPG_ERR_SYNTAX;
1394 req_orig = strv_dup (req);
1395 if (!req_orig)
1397 rc = GPG_ERR_ENOMEM;
1398 goto fail;
1401 n = find_root_element (client, doc, &req, &rc, &a_target, 0, 0);
1402 if ((rc == GPG_ERR_ELEMENT_NOT_FOUND || rc == GPG_ERR_ELOOP
1403 || rc == GPG_ERR_EPERM)
1404 && elements->verbose && a_target)
1406 if (rc != GPG_ERR_EPERM)
1407 rc = 0;
1409 goto done;
1412 if (rc == GPG_ERR_EPERM)
1413 goto done;
1415 if (!n && rc == GPG_ERR_ELEMENT_NOT_FOUND && elements->resolving == 1)
1417 rc = 0;
1418 goto fail;
1420 else if (!n)
1421 goto fail;
1423 if (a_target == 1)
1425 xfree (*req);
1426 *req = str_dup (*req_orig);
1429 if (*(req + 1))
1431 int e_target = 0;
1434 find_elements (client, doc, n->children, req + 1, &rc, &e_target,
1435 NULL, NULL, 1, 0, NULL, 0);
1437 if (!n && rc == GPG_ERR_ELEMENT_NOT_FOUND && elements->resolving == 1)
1439 rc = 0;
1440 goto fail;
1442 else if (!n)
1443 goto fail;
1446 done:
1447 if (!elements->prefix)
1450 * FIXME
1452 * If any req_orig element contains no target the element should be
1453 * prefixed with the literal character. Not really crucial if the
1454 * client isn't human because child elements are prefixed for the
1455 * current path. But may be confusing if editing by hand.
1457 elements->prefix = strv_join ("\t", req_orig);
1459 if (!elements->prefix)
1461 rc = GPG_ERR_ENOMEM;
1462 goto fail;
1465 if (elements->verbose)
1467 int ret;
1468 struct string_s *realpath = NULL;
1469 gpg_error_t allowed = rc;
1471 rc = 0;
1473 if (!allowed && a_target && elements->with_target)
1475 rc = build_realpath (client, doc, path, &realpath);
1476 if (rc)
1477 goto fail;
1479 realpath = string_prepend (realpath, "T ");
1482 ret = strv_printf (&elements->elements, "%s%s%s%s%s",
1483 elements->prefix,
1484 (!allowed && n && find_element_node (n->children))
1485 || realpath ? " " : "",
1486 (!allowed && n && find_element_node (n->children)) ? "+" : "",
1487 !allowed && realpath ? realpath->str : "",
1488 allowed ? " P" : "");
1489 string_free (realpath, 1);
1490 if (!ret)
1492 rc = GPG_ERR_ENOMEM;
1493 goto fail;
1496 else if (strv_printf (&elements->elements, "%s", elements->prefix) == 0)
1498 rc = GPG_ERR_ENOMEM;
1499 goto fail;
1502 if (update_element_list (elements) == 0)
1504 rc = GPG_ERR_ENOMEM;
1505 goto fail;
1509 rc = path_list_recurse (client, doc, n ? n->children : n, elements);
1511 fail:
1512 if (req_orig)
1513 strv_free (req_orig);
1515 strv_free (req);
1516 return rc;
1519 gpg_error_t
1520 recurse_xpath_nodeset (struct client_s *client, xmlDocPtr doc,
1521 xmlNodeSetPtr nodes, xmlChar * value,
1522 xmlBufferPtr * result, int cmd, const xmlChar * attr)
1524 int i = value ? nodes->nodeNr - 1 : 0;
1525 xmlBufferPtr buf;
1527 buf = xmlBufferCreate ();
1529 if (!buf)
1530 return GPG_ERR_ENOMEM;
1532 for (; value ? i >= 0 : i < nodes->nodeNr; value ? i-- : i++)
1534 xmlNodePtr n = nodes->nodeTab[i];
1535 gpg_error_t rc;
1537 if (!n)
1538 continue;
1540 if (!value && !attr)
1542 if (xmlNodeDump (buf, doc, n, 0, 0) == -1)
1544 *result = buf;
1545 return GPG_ERR_BAD_DATA;
1548 continue;
1551 if (!attr)
1553 xmlNodeSetContent (n, value);
1554 rc = update_element_mtime (n);
1556 if (rc)
1557 return rc;
1559 else
1561 if (!cmd)
1562 rc = add_attribute (n, (char *) attr, (char *) value);
1563 else
1564 rc = delete_attribute (client, n, attr);
1566 if (rc)
1567 return rc;
1571 *result = buf;
1572 return 0;
1575 static gpg_error_t
1576 convert_root_element (struct client_s *client, xmlNodePtr n)
1578 xmlChar *a = xmlGetProp (n, (xmlChar *) "_name");
1579 gpg_error_t rc;
1581 if (a)
1583 xmlFree (a);
1584 xmlChar *t = xmlGetNodePath (n);
1586 log_write (_
1587 ("An existing \"_name\" attribute already exists. Please rename this attribute before converting. Path is: %s"),
1589 xmlFree (t);
1590 return GPG_ERR_AMBIGUOUS_NAME;
1593 a = xmlGetProp (n, (xmlChar *) "name");
1595 if (a)
1597 rc = add_attribute (n, "_name", (char *) a);
1598 xmlFree (a);
1600 if (rc)
1601 return rc;
1603 rc = delete_attribute (client, n, (xmlChar *) "name");
1605 if (rc)
1606 return rc;
1608 xmlNodeSetName (n, (xmlChar *) "element");
1611 return 0;
1614 gpg_error_t
1615 delete_attribute (struct client_s *client, xmlNodePtr n, const xmlChar * name)
1617 xmlAttrPtr a;
1618 gpg_error_t rc = 0;
1620 if ((a = xmlHasProp (n, name)) == NULL)
1621 return GPG_ERR_NOT_FOUND;
1623 if (xmlRemoveProp (a) == -1)
1624 return GPG_ERR_BAD_DATA;
1626 if (client && xmlStrEqual (name, (xmlChar *) "_acl"))
1628 char *user = create_acl_user (client);
1630 rc = add_attribute (n, (char *) "_acl", user);
1631 xfree (user);
1633 if (rc)
1634 return rc;
1637 return update_element_mtime (n);
1640 static gpg_error_t
1641 convert_elements_recurse (struct client_s *client, xmlDocPtr doc,
1642 xmlNodePtr n, unsigned depth)
1644 gpg_error_t rc;
1646 depth++;
1648 for (n = n->children; n; n = n->next)
1650 if (n->type == XML_ELEMENT_NODE)
1652 if (depth > 1)
1654 xmlChar *a = NULL;
1656 if (xmlStrEqual (n->name, (xmlChar *) "element"))
1658 xmlChar *t = xmlGetNodePath (n);
1660 log_write (_
1661 ("An existing \"element\" already exists. Please rename this element before converting. Path is: %s"),
1663 xmlFree (t);
1664 return GPG_ERR_AMBIGUOUS_NAME;
1667 a = xmlGetProp (n, (xmlChar *) "_name");
1668 if (a)
1670 xmlFree (a);
1671 xmlChar *t = xmlGetNodePath (n);
1673 log_write (_
1674 ("An existing \"_name\" attribute already exists. Please rename this attribute before converting. Path is: %s"),
1676 xmlFree (t);
1677 return GPG_ERR_AMBIGUOUS_NAME;
1680 xmlChar *tmp = xmlStrdup (n->name);
1682 if (!tmp)
1683 return GPG_ERR_ENOMEM;
1685 xmlNodeSetName (n, (xmlChar *) "element");
1686 rc = add_attribute (n, "_name", (char *) tmp);
1687 xmlFree (tmp);
1689 if (rc)
1690 return rc;
1692 else
1694 rc = convert_root_element (client, n);
1696 if (rc)
1697 return rc;
1701 if (n->children)
1703 rc = convert_elements_recurse (client, doc, n, depth);
1705 if (rc)
1706 return rc;
1710 return 0;
1713 /* Renames ALL elements to the new "element" name. Existing element names are
1714 * stored as an attribute "_name". This was introduced in pwmd 2.12 so
1715 * elements can contain common characters that the XML parser barfs on (an
1716 * email address for example. */
1717 gpg_error_t
1718 convert_pre_212_elements (xmlDocPtr doc)
1720 xmlNodePtr n = xmlDocGetRootElement (doc);
1722 log_write (_("Converting pre 2.12 data file..."));
1723 return convert_elements_recurse (NULL, doc, n, 0);
1726 gpg_error_t
1727 validate_import (xmlNodePtr node)
1729 gpg_error_t rc = 0;
1731 if (!node)
1732 return 0;
1734 for (xmlNodePtr n = node; n; n = n->next)
1736 if (n->type == XML_ELEMENT_NODE)
1738 if (xmlStrEqual (n->name, (xmlChar *) "element"))
1740 xmlChar *a = xmlGetProp (n, (xmlChar *) "_name");
1742 if (!a)
1744 xmlChar *t = xmlGetNodePath (n);
1746 log_write (_("Missing attribute '_name' at %s."), t);
1747 xmlFree (t);
1748 return GPG_ERR_INV_VALUE;
1751 if (!valid_xml_element (a))
1753 xmlChar *t = xmlGetNodePath (n);
1755 log_write (_("'%s' is not a valid element name at %s."), a,
1757 xmlFree (a);
1758 xmlFree (t);
1759 return GPG_ERR_INV_VALUE;
1762 xmlFree (a);
1763 a = xmlGetProp (n, (xmlChar *) "_ctime");
1764 if (!a)
1765 attr_ctime (n);
1767 xmlFree (a);
1768 a = xmlGetProp (n, (xmlChar *) "_mtime");
1769 if (!a)
1770 update_element_mtime (n);
1771 xmlFree (a);
1773 else
1775 xmlChar *t = xmlGetNodePath (n);
1777 log_write (_("Warning: unknown element '%s' at %s. Ignoring."),
1778 n->name, t);
1779 xmlFree (t);
1780 continue;
1784 if (n->children)
1786 rc = validate_import (n->children);
1788 if (rc)
1789 return rc;
1793 return rc;
1796 gpg_error_t
1797 update_element_mtime (xmlNodePtr n)
1799 return add_attribute (n, NULL, NULL);
1802 gpg_error_t
1803 unlink_node (xmlNodePtr n)
1805 gpg_error_t rc = 0;
1807 if (!n)
1808 return rc;
1810 if (n->parent)
1811 rc = update_element_mtime (n->parent);
1813 xmlUnlinkNode (n);
1814 return rc;
1817 gpg_error_t
1818 parse_doc (const char *xml, size_t len, xmlDocPtr *result)
1820 xmlDocPtr doc;
1822 xmlResetLastError ();
1823 doc = xmlReadMemory (xml, len, NULL, "UTF-8", XML_PARSE_NOBLANKS);
1824 if (!doc && xmlGetLastError ())
1825 return GPG_ERR_BAD_DATA;
1827 *result = doc;
1828 return !doc ? GPG_ERR_ENOMEM : 0;
1831 static xmlNodePtr
1832 realpath_elements_cb (struct client_s *client, xmlNodePtr node, char **target,
1833 gpg_error_t * rc, char **req_orig, void *data)
1835 char *path = *(char **) data;
1836 char *tmp = NULL, *result;
1838 if (path)
1840 xfree (path);
1841 *(char **) data = NULL;
1844 path = strv_join ("\t", target);
1846 if (!path)
1848 *rc = GPG_ERR_ENOMEM;
1849 return NULL;
1852 if (req_orig)
1854 tmp = strv_join ("\t", req_orig);
1856 if (!tmp)
1858 xfree (path);
1859 *rc = GPG_ERR_ENOMEM;
1860 return NULL;
1864 if (tmp && *tmp)
1865 result = str_asprintf ("%s\t%s", path, tmp);
1866 else
1867 result = str_dup (path);
1869 if (!result)
1871 *rc = GPG_ERR_ENOMEM;
1872 xfree (path);
1873 xfree (tmp);
1874 return NULL;
1877 xfree (path);
1878 xfree (tmp);
1879 *(char **) data = result;
1880 return node;
1883 gpg_error_t
1884 build_realpath (struct client_s *client, xmlDocPtr doc, char *line,
1885 struct string_s ** result)
1887 gpg_error_t rc;
1888 char **req;
1889 char *t;
1890 int i;
1891 xmlNodePtr n;
1892 struct string_s *string;
1893 char *rp = NULL;
1895 if (strchr (line, '\t') != NULL)
1897 if ((req = str_split (line, "\t", 0)) == NULL)
1898 return GPG_ERR_SYNTAX;
1900 else
1902 if ((req = str_split (line, " ", 0)) == NULL)
1903 return GPG_ERR_SYNTAX;
1906 n = find_root_element (client, doc, &req, &rc, NULL, 0, 0);
1907 if (!n)
1909 strv_free (req);
1910 return rc;
1913 rp = strv_join ("\t", req);
1914 if (!rp)
1916 strv_free (req);
1917 return GPG_ERR_ENOMEM;
1920 if (req[1])
1922 n = find_elements (client, doc, n->children, req + 1, &rc, NULL,
1923 realpath_elements_cb, NULL, 0, 0, &rp, 0);
1924 if (!n)
1926 xfree (rp);
1927 strv_free (req);
1928 return rc;
1932 string = string_new (rp);
1933 xfree (rp);
1934 strv_free (req);
1935 if (!string)
1936 return GPG_ERR_ENOMEM;
1938 again:
1939 for (i = 0, t = string->str + i; *t; t++, i++)
1941 if ((!i && *t != '!') || (*t == '\t' && *(t + 1) && *(t + 1) != '!'))
1943 struct string_s *s = string_insert_c (string, !i ? i++ : ++i, '!');
1945 if (!s)
1947 string_free (string, 1);
1948 return GPG_ERR_ENOMEM;
1951 string = s;
1952 goto again;
1956 *result = string;
1957 return rc;
1960 #if 0
1961 static char *
1962 node_to_element_path (xmlNodePtr node)
1964 xmlNodePtr n;
1965 struct string_s *str = string_new ("");
1966 char *result;
1968 for (n = node; n; n = n->parent)
1970 xmlNodePtr child;
1972 for (child = n; child; child = child->next)
1974 if (child->type != XML_ELEMENT_NODE)
1975 continue;
1977 xmlChar *name = node_has_attribute (n, (xmlChar *) "_name");
1978 if (name)
1980 str = string_prepend (str, (char *) name);
1981 xmlFree (name);
1982 name = node_has_attribute (n, (xmlChar *) "target");
1983 if (name)
1984 str = string_prepend (str, "\t");
1985 else
1986 str = string_prepend (str, "\t!");
1987 xmlFree (name);
1989 break;
1993 str = string_erase (str, 0, 1);
1994 result = str->str;
1995 string_free (str, 0);
1996 return result;
1998 #endif
2001 * Recurse the element tree beginning at 'node' and find elements who point
2002 * back to 'src' or 'dst'. Also follows target attributes.
2004 static gpg_error_t
2005 find_child_to_target (struct client_s *client, xmlDocPtr doc, xmlNodePtr node,
2006 xmlNodePtr src, xmlNodePtr dst, unsigned depth,
2007 int is_target)
2009 xmlNodePtr n;
2010 gpg_error_t rc = 0;
2012 if (max_recursion_depth >= 1 && depth > max_recursion_depth)
2013 return gpg_error (GPG_ERR_ELOOP);
2015 for (n = node; n; n = n->next)
2017 xmlChar *target;
2019 if (n->type != XML_ELEMENT_NODE)
2020 continue;
2022 if (n == src || n == dst)
2023 return GPG_ERR_ELOOP;
2025 target = node_has_attribute (n, (xmlChar *) "target");
2026 if (target)
2028 xmlNodePtr tmp;
2029 char **result = NULL;
2031 tmp = resolve_path (client, doc, target, &result, &rc);
2032 xmlFree (target);
2033 strv_free (result);
2034 if (!rc)
2036 rc = find_child_to_target (client, doc, tmp, src, dst, ++depth,
2038 depth--;
2041 if (rc && gpg_err_code (rc) != GPG_ERR_ELEMENT_NOT_FOUND)
2042 return rc;
2044 if (is_target)
2045 break;
2047 continue;
2050 if (n->children)
2052 rc = find_child_to_target (client, doc, n->children, src, dst,
2053 ++depth,0);
2054 depth--;
2055 if (rc)
2056 return rc;
2059 if (is_target)
2060 break;
2063 return rc;
2066 static gpg_error_t
2067 find_child_of_parent (xmlDocPtr doc, xmlNodePtr src, xmlNodePtr dst)
2069 xmlNodePtr n;
2070 gpg_error_t rc = 0;
2072 for (n = src; n; n = n->next)
2074 if (n->type != XML_ELEMENT_NODE)
2075 continue;
2077 if (n == dst)
2079 rc = GPG_ERR_ELOOP;
2080 break;
2083 rc = find_child_of_parent (doc, n->children, dst);
2086 return rc;
2089 static gpg_error_t
2090 find_parent_of_child (xmlDocPtr doc, xmlNodePtr node, xmlNodePtr dst)
2092 xmlNodePtr n;
2093 gpg_error_t rc = 0;
2095 for (n = node; n; n = n->parent)
2097 if (n->type != XML_ELEMENT_NODE)
2099 xmlNodePtr tmp;
2101 for (tmp = n->next; tmp; n = n->next)
2103 if (n->type != XML_ELEMENT_NODE)
2104 continue;
2106 if (tmp == dst)
2107 return GPG_ERR_ELOOP;
2111 if (n == dst)
2112 return GPG_ERR_ELOOP;
2115 return rc;
2118 gpg_error_t
2119 validate_target_attribute (struct client_s *client, xmlDocPtr doc,
2120 const char *src, xmlNodePtr dst_node)
2122 gpg_error_t rc;
2123 xmlNodePtr src_node;
2124 char **src_req = NULL;
2126 src_node = resolve_path (client, doc, (xmlChar *) src, &src_req, &rc);
2127 if (rc)
2128 goto fail;
2130 /* A destination element is a child of the source element. */
2131 rc = find_child_of_parent (doc, src_node->children, dst_node);
2132 if (rc)
2133 goto fail;
2135 /* The destination element is a parent of the source element. */
2136 rc = find_parent_of_child (doc, src_node->parent, dst_node);
2137 if (rc)
2138 goto fail;
2140 /* A destination child element contains a target to the source element. */
2141 rc = find_child_to_target (client, doc, dst_node->children, src_node,
2142 dst_node, 0, 0);
2143 if (rc)
2144 goto fail;
2146 fail:
2147 strv_free (src_req);
2148 return rc;
2151 /* The owner of the element is the first user listed in the _acl attribute
2152 * list. acl_check() should be called before calling this function. An empty
2153 * ACL is an error if the client is not invoking_user.
2155 gpg_error_t
2156 is_element_owner (struct client_s *client, xmlNodePtr n)
2158 xmlChar *acl = node_has_attribute (n, (xmlChar *) "_acl");
2159 char **users;
2160 gpg_error_t rc = GPG_ERR_EPERM;
2162 if (!acl || !*acl)
2164 xmlFree (acl);
2165 return 0;
2168 users = str_split((char *)acl, ",", 0);
2169 if (users && *users)
2171 char *user;
2173 #ifdef WITH_GNUTLS
2174 if (client->thd->remote)
2175 user = str_asprintf ("#%s", client->thd->tls->fp);
2176 else
2177 user = get_username (client->thd->peer->uid);
2178 #else
2179 user = get_username (client->thd->peer->uid);
2180 #endif
2182 rc = !strcmp (*users, user) ? 0 : GPG_ERR_EPERM;
2183 xfree (user);
2186 strv_free (users);
2187 return rc;