Access control for the _acl attribute.
[pwmd.git] / src / xml.c
blob3547612bf8ad8b13578f6404e44580d325911632
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_self(client);
184 if (!peer_is_self(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, xmlNodePtr parent,
221 const char *name, xmlNodePtr * result)
223 xmlNodePtr n;
224 gpg_error_t rc;
226 rc = acl_check(client, parent);
227 if (rc)
228 return rc;
230 n = xmlNewNode (NULL, (xmlChar *) "element");
231 if (!n)
232 return GPG_ERR_ENOMEM;
234 rc = add_attribute (n, "_name", name);
235 if (!rc)
236 rc = attr_ctime (n);
238 if (!rc)
240 xmlNodePtr p = xmlAddChild (parent, n);
241 char *user = create_acl_user (client);
243 if (result)
244 *result = p;
246 rc = add_attribute(p, "_acl", user);
247 xfree (user);
249 else
250 xmlFreeNode (n);
252 return rc;
255 gpg_error_t
256 new_root_element (struct client_s *client, xmlDocPtr doc, char *name)
258 xmlNodePtr root = xmlDocGetRootElement (doc);
259 char *p = name;
261 if (!p || !root)
262 return GPG_ERR_BAD_DATA;
264 if (*p == '!')
265 p++;
267 if (!valid_xml_element ((xmlChar *) p))
268 return GPG_ERR_INV_VALUE;
270 return create_new_element (client, root, p, NULL);
273 static xmlDocPtr
274 create_dtd ()
276 xmlDocPtr doc;
277 xmlTextWriterPtr wr = xmlNewTextWriterDoc (&doc, 0);
279 if (!wr)
280 return NULL;
282 if (xmlTextWriterStartDocument (wr, NULL, "UTF-8", "yes"))
283 goto fail;
285 if (xmlTextWriterStartDTD (wr, (xmlChar *) "pwmd", NULL, NULL) == -1)
286 goto fail;
288 if (xmlTextWriterWriteDTDElement (wr, (xmlChar *) "pwmd",
289 (xmlChar *) "(element)") == -1)
290 goto fail;
292 xmlTextWriterEndDTDElement (wr);
294 if (xmlTextWriterWriteDTDAttlist (wr, (xmlChar *) "element",
295 (xmlChar *) "_name CDATA #REQUIRED") ==
297 goto fail;
299 xmlTextWriterEndDTDAttlist (wr);
300 xmlTextWriterEndDTD (wr);
302 if (xmlTextWriterStartElement (wr, (xmlChar *) "pwmd"))
303 goto fail;
305 xmlTextWriterEndElement (wr);
306 xmlTextWriterEndDocument (wr);
307 xmlFreeTextWriter (wr);
308 return doc;
310 fail:
311 xmlTextWriterEndDocument (wr);
312 xmlFreeTextWriter (wr);
313 xmlFreeDoc (doc);
314 return NULL;
317 xmlDocPtr
318 new_document ()
320 return create_dtd ();
323 xmlNodePtr
324 find_element_node (xmlNodePtr node)
326 xmlNodePtr n = node;
328 if (n && n->type == XML_ELEMENT_NODE)
329 return n;
331 for (n = node; n; n = n->next)
333 if (n->type == XML_ELEMENT_NODE)
334 return n;
337 return NULL;
340 static xmlNodePtr
341 resolve_path (struct client_s *client, xmlDocPtr doc, xmlChar * path,
342 char ***result, gpg_error_t * rc)
344 xmlNodePtr n;
345 char **req;
347 req = str_split ((char *) path, "\t", 0);
348 if (!req)
350 *rc = GPG_ERR_ENOMEM;
351 return NULL;
354 n = find_root_element (client, doc, &req, rc, NULL, 0, 0);
355 if (!n)
357 strv_free (req);
358 return NULL;
361 if (req[1])
362 n = find_elements (client, doc, n->children, req + 1, rc, NULL, NULL, NULL,
363 0, 0, NULL, 0);
365 if (*rc)
366 strv_free (req);
367 else
368 *result = req;
370 return n;
374 * Lists root element names; the value of the attribute "_name" of an element
375 * "element". If there's a target attribute both literal and non-literal
376 * element names will be added. This is the primary reason why XML entities
377 * cannot be used. There wouldn't be a way to get the literal an non-literal
378 * element paths.
380 gpg_error_t
381 list_root_elements (struct client_s *client, xmlDocPtr doc,
382 struct string_s ** result, int verbose, int with_target)
384 xmlNodePtr n = NULL;
385 struct slist_s *list = NULL;
386 int total, i;
387 struct string_s *string;
388 gpg_error_t rc = 0;
390 n = xmlDocGetRootElement (doc);
391 if (!n || !n->children)
392 return GPG_ERR_NO_DATA;
394 for (n = n->children; n; n = n->next)
396 xmlAttrPtr a;
397 xmlChar *val, *target;
398 struct slist_s *tlist;
399 char *tmp;
401 if (n->type != XML_ELEMENT_NODE)
402 continue;
404 a = xmlHasProp (n, (xmlChar *) "_name");
405 if (!a || !a->children->content)
406 continue;
408 val = xmlNodeGetContent (a->children);
409 if (!val)
411 rc = GPG_ERR_ENOMEM;
412 goto fail;
415 tmp =
416 str_asprintf ("!%s%s", (char *) val,
417 verbose ? find_element_node (n->children) ? " +" : "" :
418 "");
420 if (!tmp)
422 xmlFree (val);
423 rc = GPG_ERR_ENOMEM;
424 goto fail;
427 tlist = slist_append (list, tmp);
428 if (!tlist)
430 xmlFree (val);
431 rc = GPG_ERR_ENOMEM;
432 goto fail;
435 list = tlist;
436 target = node_has_attribute (n, (xmlChar *) "target");
437 if (target)
439 char *t = NULL;
441 if (verbose)
443 char **req = NULL;
444 xmlNodePtr tnode = resolve_path (client, doc, target, &req, &rc);
446 if (rc == GPG_ERR_ELEMENT_NOT_FOUND || rc == GPG_ERR_ELOOP
447 || rc == GPG_ERR_EPERM)
449 t = str_asprintf ("%s %s", (char *) val,
450 rc == GPG_ERR_ELOOP ? "O" :
451 rc == GPG_ERR_EPERM ? "P" : "E");
452 rc = 0;
454 else if (!rc)
456 struct string_s *realpath = NULL;
458 if (with_target)
460 rc = build_realpath (client, doc, (char *) target,
461 &realpath);
462 if (rc)
464 strv_free (req);
465 xmlFree (val);
466 xmlFree (target);
467 goto fail;
470 realpath = string_prepend (realpath, "T ");
473 t = str_asprintf ("%s%s%s%s", (char *) val,
474 (tnode
475 && find_element_node (tnode->children))
476 || realpath ? " " : "", tnode
477 && find_element_node (tnode->children) ?
478 "+" : "", realpath ? realpath->str : "");
480 if (realpath)
481 string_free (realpath, 1);
484 if (req)
485 strv_free (req);
487 else
488 t = str_dup ((char *) val);
490 if (!t || rc)
492 xmlFree (val);
493 xmlFree (target);
494 rc = rc ? rc : GPG_ERR_ENOMEM;
495 goto fail;
498 tlist = slist_append (list, t);
499 if (!tlist)
501 xmlFree (val);
502 xfree (t);
503 xmlFree (target);
504 rc = GPG_ERR_ENOMEM;
505 goto fail;
508 list = tlist;
511 xmlFree (val);
512 xmlFree (target);
515 total = slist_length (list);
516 if (!total)
517 return GPG_ERR_NO_DATA;
519 string = string_new (NULL);
520 if (!string)
522 rc = GPG_ERR_ENOMEM;
523 goto fail;
526 for (i = 0; i < total; i++)
528 char *val = slist_nth_data (list, i);
530 string_append_printf (string, "%s\n", val);
533 string = string_truncate (string, string->len - 1);
534 *result = string;
536 fail:
537 total = slist_length (list);
538 for (i = 0; i < total; i++)
539 xfree (slist_nth_data (list, i));
541 slist_free (list);
542 return rc;
546 * Prevents a sibling element past the current element path with the same
547 * element name.
549 static xmlNodePtr
550 find_stop_node (xmlNodePtr node)
552 xmlNodePtr n;
554 for (n = node->parent->children; n; n = n->next)
556 if (n == node)
557 return n->next;
560 return NULL;
563 xmlNodePtr
564 create_target_elements_cb (struct client_s *client,
565 xmlNodePtr node, char **path, gpg_error_t *rc,
566 void *data)
568 int i;
569 char **req = path;
570 xmlNodePtr parent = data;
572 for (i = 0; req[i] && *req[i]; i++)
574 xmlNodePtr n;
576 if (parent && node == parent)
578 *rc = GPG_ERR_CONFLICT;
579 return NULL;
582 is_literal_element (&req[i]);
584 if ((n = find_element (client, node, req[i],
585 find_stop_node (node), rc)) == NULL ||
586 (n && n->parent == node->parent))
589 if (!*rc)
590 *rc = create_new_element (client, node, req[i], &node);
592 if (*rc)
593 return NULL;
595 else
596 node = n;
599 return node;
602 xmlNodePtr
603 find_text_node (xmlNodePtr node)
605 xmlNodePtr n = node;
607 if (n && n->type == XML_TEXT_NODE)
608 return n;
610 for (n = node; n; n = n->next)
612 if (n->type == XML_TEXT_NODE)
613 return n;
616 return NULL;
619 xmlNodePtr
620 create_elements_cb (struct client_s *client, xmlNodePtr node, char **elements,
621 gpg_error_t * rc, void *data)
623 int i;
624 char **req = elements;
626 if (node->type == XML_TEXT_NODE)
627 node = node->parent;
629 for (i = 0; req[i] && *req[i]; i++)
631 xmlNodePtr n;
634 * Strip the first '!' if needed. If there's another, it's an
635 * rc. The syntax has already been checked before calling this
636 * function.
638 is_literal_element (&req[i]);
639 n = find_element (client, node, req[i], find_stop_node (node), rc);
640 if (*rc)
641 return NULL;
644 * If the found element has the same parent as the current element,
645 * they are siblings and the new element needs to be created as a
646 * child of the current element (node).
648 if (n && n->parent == node->parent)
649 n = NULL;
651 if (!n)
653 *rc = create_new_element (client, node, req[i], &node);
654 if (*rc)
655 return NULL;
657 else
658 node = n;
661 return node;
664 /* The root element is really req[0]. It is need as a pointer in case there is
665 * a target attribute so it can be updated. */
666 xmlNodePtr
667 find_root_element (struct client_s *client, xmlDocPtr doc, char ***req,
668 gpg_error_t * rc, int *target, int recursion_depth,
669 int stop)
671 xmlNodePtr n = xmlDocGetRootElement (doc);
672 int depth = 0;
673 char *root = str_dup (*req[0]);
674 int literal = is_literal_element (&root);
676 if (!root)
678 *rc = GPG_ERR_ENOMEM;
679 return NULL;
682 *rc = 0;
683 recursion_depth++;
685 if (max_recursion_depth >= 1 && recursion_depth > max_recursion_depth)
687 xmlChar *t = xmlGetNodePath (n);
689 log_write ("%s: %s", pwmd_strerror (GPG_ERR_ELOOP), t);
690 xmlFree (t);
691 xfree (root);
692 *rc = GPG_ERR_ELOOP;
693 return NULL;
696 while (n)
698 if (n->type == XML_ELEMENT_NODE)
700 if (depth == 0 && xmlStrEqual (n->name, (xmlChar *) "pwmd"))
702 n = n->children;
703 depth++;
704 continue;
707 if (depth == 1 && xmlStrEqual (n->name, (xmlChar *) "element"))
709 xmlChar *content = node_has_attribute (n, (xmlChar *) "_name");
711 if (!content)
712 continue;
714 if (xmlStrEqual (content, (xmlChar *) root))
716 char **nreq, **tmp = NULL;
718 *rc = acl_check(client, n);
719 if (*rc)
721 xmlFree (content);
722 xfree (root);
723 return NULL;
726 if (literal == 1)
728 xmlFree (content);
729 xfree (root);
730 return n;
733 xmlFree (content);
734 content = node_has_attribute (n, (xmlChar *) "target");
736 if (target)
737 *target = 1;
739 if (!content || stop)
741 if (content)
742 xmlFree (content);
744 xfree (root);
745 return n;
748 if (strchr ((char *) content, '\t'))
750 nreq = str_split ((char *) content, "\t", 0);
751 xmlFree (content);
753 #if 0
755 * FIXME ENOMEM
757 if (!nreq)
759 *rc = GPG_ERR_ENOMEM;
760 return NULL;
762 #endif
764 tmp = *req;
765 tmp = strv_catv (nreq, tmp + 1);
766 strv_free (nreq);
768 if (!tmp)
770 xfree (root);
771 *rc = GPG_ERR_ENOMEM;
772 return NULL;
775 strv_free (*req);
776 *req = tmp;
778 else
780 if (strv_printf (&tmp, "%s", content) == 0)
782 xmlFree (content);
783 xfree (root);
784 *rc = GPG_ERR_ENOMEM;
785 return NULL;
788 xmlFree (content);
789 nreq = *req;
790 nreq = strv_catv (tmp, nreq + 1);
791 strv_free (tmp);
793 if (!nreq)
795 *rc = GPG_ERR_ENOMEM;
796 xfree (root);
797 return NULL;
800 strv_free (*req);
801 *req = nreq;
804 xfree (root);
806 find_root_element (client, doc, req, rc, target,
807 recursion_depth, 0);
808 return n;
811 xmlFree (content);
815 n = n->next;
818 xfree (root);
819 *rc = GPG_ERR_ELEMENT_NOT_FOUND;
820 return NULL;
823 xmlNodePtr
824 find_element (struct client_s *client, xmlNodePtr node, char *element,
825 xmlNodePtr stop, gpg_error_t *rc)
827 xmlNodePtr n;
829 *rc = 0;
831 if (!node || !element)
832 return NULL;
834 for (n = node; n; n = n->next)
836 if (n->type != XML_ELEMENT_NODE)
837 continue;
839 if (n == stop)
840 break;
842 xmlChar *a = node_has_attribute (n, (xmlChar *) "_name");
844 if (a && xmlStrEqual (a, (xmlChar *) element))
846 xmlFree (a);
848 *rc = acl_check(client, n);
849 if (*rc)
850 n = NULL;
852 return n;
855 xmlFree (a);
858 return NULL;
861 xmlChar *
862 node_has_attribute (xmlNodePtr n, xmlChar * attr)
864 xmlAttrPtr a = xmlHasProp (n, attr);
866 if (!a)
867 return NULL;
869 if (!a->children || !a->children->content)
870 return NULL;
872 return xmlGetProp (n, attr);
875 static int
876 element_to_literal (char **element)
878 char *p = str_asprintf ("!%s", *element);
880 if (!p)
881 return 0;
883 xfree (*element);
884 *element = p;
885 return 1;
888 /* Resolves elements in 'req' one at a time. It's recursive in case of
889 * "target" attributes. */
890 xmlNodePtr
891 find_elements (struct client_s *client, xmlDocPtr doc, xmlNodePtr node,
892 char **req, gpg_error_t * rc, int *target,
893 xmlNodePtr (*found_fn) (struct client_s *, xmlNodePtr, char **,
894 gpg_error_t *, char **, void *),
895 xmlNodePtr (*not_found_fn) (struct client_s *, xmlNodePtr,
896 char **, gpg_error_t *, void *),
897 int is_list_command, int recursion_depth, void *data, int stop)
899 xmlNodePtr n, last, last_node;
900 char **p;
901 int found = 0;
903 *rc = 0;
904 recursion_depth++;
906 if (max_recursion_depth >= 1 && recursion_depth > max_recursion_depth)
908 xmlChar *t = xmlGetNodePath (node);
910 log_write ("%s: %s", pwmd_strerror (GPG_ERR_ELOOP), t);
911 xmlFree (t);
912 recursion_depth--;
913 *rc = GPG_ERR_ELOOP;
914 return NULL;
917 for (last_node = last = n = node, p = req; *p; p++)
919 xmlNodePtr tmp;
920 char *t;
921 int literal;
923 if (!*(*p))
925 *rc = GPG_ERR_ELEMENT_NOT_FOUND;
926 return NULL;
929 t = str_dup (*p);
930 if (!t)
932 *rc = GPG_ERR_ENOMEM;
933 return NULL;
936 literal = is_literal_element (&t);
937 n = find_element (client, last, t, NULL, rc);
938 xfree (t);
940 if (*rc && *rc != GPG_ERR_ELEMENT_NOT_FOUND)
941 return NULL;
943 if (!n)
945 if (not_found_fn)
946 return not_found_fn (client, found ? last_node : last_node->parent,
947 p, rc, data);
949 if (!*rc)
950 *rc = GPG_ERR_ELEMENT_NOT_FOUND;
952 return NULL;
955 last = n->children;
956 last_node = n;
957 found = 1;
959 if (literal == 0)
961 xmlChar *content = node_has_attribute (n, (xmlChar *) "target");
962 char **nreq = NULL, **nnreq;
964 if (!content)
966 if (is_list_command == 1)
968 if (element_to_literal (&(*p)) == 0)
970 *rc = GPG_ERR_ENOMEM;
971 return NULL;
975 continue;
978 if (target)
979 *target = 1;
981 if (!*(p + 1) && stop)
983 xmlFree (content);
984 return n;
987 if (strchr ((char *) content, '\t') != NULL)
989 if ((nreq = str_split ((char *) content, "\t", 0)) == NULL)
991 xmlFree (content);
992 *rc = GPG_ERR_INV_VALUE;
993 return NULL;
996 else
998 if ((nreq = str_split ((char *) content, " ", 0)) == NULL)
1000 xmlFree (content);
1001 *rc = GPG_ERR_INV_VALUE;
1002 return NULL;
1006 xmlFree (content);
1007 tmp = find_root_element (client, doc, &nreq, rc, target, 0, 0);
1009 if (!tmp)
1011 strv_free (nreq);
1012 return NULL;
1015 if (found_fn)
1017 found_fn (client, tmp, nreq, rc, p + 1, data);
1019 if (*rc)
1021 strv_free (nreq);
1022 return NULL;
1026 if (!*(nreq + 1) && !*(p + 1))
1028 strv_free (nreq);
1029 return tmp;
1032 nnreq = strv_catv (nreq + 1, p + 1);
1033 strv_free (nreq);
1035 // FIXME ENOMEM
1036 if (!nnreq || !*nnreq)
1038 if (nnreq)
1039 strv_free (nnreq);
1041 return tmp;
1044 if (tmp->children)
1045 n = find_elements (client, doc, tmp->children, nnreq, rc, NULL,
1046 found_fn, not_found_fn, is_list_command,
1047 recursion_depth, data, stop);
1048 else
1050 strv_free (nnreq);
1052 if (not_found_fn)
1053 return not_found_fn (client, tmp, p + 1, rc, data);
1055 *rc = GPG_ERR_ELEMENT_NOT_FOUND;
1056 return NULL;
1059 if (*(p + 1))
1061 char **zz = p + 1, **qq = nnreq;
1063 if (strv_length (nnreq) > strv_length (p + 1))
1064 qq = nnreq + 1;
1066 for (; *qq && *zz; zz++)
1068 xfree (*zz);
1069 *zz = str_dup (*qq++);
1071 if (!*zz)
1073 *rc = GPG_ERR_ENOMEM;
1074 n = NULL;
1075 break;
1080 strv_free (nnreq);
1081 return n;
1085 return n;
1088 static int
1089 update_element_list (struct element_list_s *elements)
1091 char *line;
1092 struct slist_s *l;
1094 if (!elements || !elements->elements)
1095 return 1;
1097 line = strv_join ("\t", elements->elements);
1099 if (!line)
1100 return 0;
1102 strv_free (elements->elements);
1103 elements->elements = NULL;
1104 l = slist_append (elements->list, line);
1106 if (!l)
1107 return 0;
1109 elements->list = l;
1110 return 1;
1113 static gpg_error_t
1114 path_list_recurse (struct client_s *client, xmlDocPtr doc, xmlNodePtr node,
1115 struct element_list_s *elements)
1117 gpg_error_t rc = 0;
1118 xmlNodePtr n;
1119 gpg_error_t error_flag = 0;
1121 for (n = node; n; n = n->next)
1123 xmlChar *target = NULL;
1124 xmlChar *a = node_has_attribute (n, (xmlChar *) "_name");
1125 int err = 0;
1127 rc = 0;
1128 if (!a)
1129 continue;
1131 if (n->type != XML_ELEMENT_NODE)
1132 goto children;
1134 rc = acl_check(client, n);
1136 if (elements->verbose)
1138 if (strv_printf
1139 (&elements->elements, "%s\t!%s%s%s", elements->prefix, a,
1140 !rc && find_element_node (n->children) ? " +" : "",
1141 rc == GPG_ERR_EPERM ? " P" : "") == 0)
1143 xmlFree (a);
1144 return GPG_ERR_ENOMEM;
1147 else
1148 if (strv_printf (&elements->elements, "%s\t!%s", elements->prefix, a)
1149 == 0)
1151 xmlFree (a);
1152 return GPG_ERR_ENOMEM;
1155 if (update_element_list (elements) == 0)
1157 xmlFree (a);
1158 return GPG_ERR_ENOMEM;
1162 if (rc)
1164 xmlFree (a);
1165 return rc == GPG_ERR_EPERM ? 0 : rc;
1168 target = node_has_attribute (n, (xmlChar *) "target");
1169 if (target)
1171 char *tmp;
1172 char *save = elements->prefix;
1173 int r = elements->resolving;
1174 char **req = NULL;
1175 xmlNodePtr tnode;
1176 struct string_s *realpath = NULL;
1178 tnode = resolve_path (client, doc, target, &req, &rc);
1179 if (rc == GPG_ERR_ELOOP || rc == GPG_ERR_ELEMENT_NOT_FOUND
1180 || rc == GPG_ERR_EPERM)
1182 if (rc == GPG_ERR_ELOOP)
1184 xmlChar *t = xmlGetNodePath (n);
1186 log_write ("%s: %s", pwmd_strerror (GPG_ERR_ELOOP), t);
1187 xmlFree (t);
1190 if (elements->verbose)
1192 strv_printf (&elements->elements, "%s\t%s %s",
1193 elements->prefix, a,
1194 rc == GPG_ERR_ELOOP ? "O" :
1195 rc == GPG_ERR_EPERM ? "P" : "E");
1196 error_flag = err = rc;
1197 rc = 0;
1198 goto update;
1202 if (!elements->verbose && rc)
1204 xmlFree (a);
1205 xmlFree (target);
1206 return rc;
1209 if (elements->with_target)
1211 rc = build_realpath (client, doc, (char *) target, &realpath);
1212 if (rc)
1214 xmlFree (a);
1215 xmlFree (target);
1216 return rc;
1219 realpath = string_prepend (realpath, "T ");
1222 if (elements->verbose)
1224 if (!strv_printf (&elements->elements, "%s\t%s%s%s%s",
1225 elements->prefix, a,
1226 (tnode && find_element_node (tnode->children))
1227 || realpath ? " " : "", tnode
1228 && find_element_node (tnode->children) ? "+" :
1229 "", realpath ? realpath->str : ""))
1231 xmlFree (a);
1232 xmlFree (target);
1233 return GPG_ERR_ENOMEM;
1236 else
1237 if (!strv_printf
1238 (&elements->elements, "%s\t%s", elements->prefix, a))
1240 xmlFree (a);
1241 xmlFree (target);
1242 return GPG_ERR_ENOMEM;
1245 update:
1246 if (realpath)
1247 string_free (realpath, 1);
1249 tmp = strv_join ("\t", elements->elements);
1251 if (!tmp)
1253 xmlFree (a);
1254 xmlFree (target);
1255 return GPG_ERR_ENOMEM;
1258 if (update_element_list (elements) == 0)
1260 xfree (tmp);
1261 xmlFree (a);
1262 xmlFree (target);
1263 return GPG_ERR_ENOMEM;
1266 if (!err && elements->recurse)
1268 /* Prune element flags. */
1269 if (elements->verbose && strchr (tmp, ' '))
1271 char *p;
1273 for (p = tmp; *p; p++)
1275 if (*p == ' ')
1277 *p = 0;
1278 break;
1283 elements->prefix = tmp;
1284 elements->resolving = 1;
1285 rc = create_path_list (client, doc, elements, (char *) target);
1286 elements->resolving = r;
1287 elements->prefix = save;
1289 if (rc && gpg_err_code (rc) != GPG_ERR_ELOOP)
1291 xfree (tmp);
1292 xmlFree (target);
1293 xmlFree (a);
1294 return rc;
1297 error_flag = err = rc;
1298 rc = 0;
1301 xfree (tmp);
1302 xmlFree (target);
1305 children:
1306 if (n->children && elements->recurse && err != GPG_ERR_ELOOP)
1308 char *tmp = str_asprintf ("%s\t!%s", elements->prefix, a);
1309 char *save = elements->prefix;
1311 if (!tmp)
1313 xmlFree (a);
1314 return GPG_ERR_ENOMEM;
1317 elements->prefix = tmp;
1318 rc = path_list_recurse (client, doc, n->children, elements);
1319 xfree (elements->prefix);
1320 elements->prefix = save;
1322 if (rc)
1324 xmlFree (a);
1325 return rc;
1329 xmlFree (a);
1332 return error_flag == GPG_ERR_ELOOP ? error_flag : rc;
1335 gpg_error_t
1336 add_attribute (xmlNodePtr node, const char *name, const char *value)
1338 char *buf;
1339 gpg_error_t rc;
1341 if (name && !xmlSetProp (node, (xmlChar *) name, (xmlChar *) value))
1342 return GPG_ERR_BAD_DATA;
1344 if (name && xmlStrEqual ((xmlChar *) name, (xmlChar *) "_mtime"))
1345 return 0;
1347 buf = str_asprintf ("%li", time (NULL));
1348 rc = add_attribute (node, "_mtime", buf);
1349 xfree (buf);
1350 return rc;
1354 * From the element path 'path', find sub-nodes and append them to the list.
1356 gpg_error_t
1357 create_path_list (struct client_s *client, xmlDocPtr doc,
1358 struct element_list_s * elements, char *path)
1360 gpg_error_t rc;
1361 char **req, **req_orig;
1362 xmlNodePtr n;
1363 int a_target = 0;
1365 req = str_split (path, "\t", 0);
1366 if (!req)
1368 req = str_split (path, " ", 0);
1369 if (!req)
1370 return GPG_ERR_SYNTAX;
1373 req_orig = strv_dup (req);
1374 if (!req_orig)
1376 rc = GPG_ERR_ENOMEM;
1377 goto fail;
1380 n = find_root_element (client, doc, &req, &rc, &a_target, 0, 0);
1381 if ((rc == GPG_ERR_ELEMENT_NOT_FOUND || rc == GPG_ERR_ELOOP
1382 || rc == GPG_ERR_EPERM)
1383 && elements->verbose && a_target)
1385 if (rc != GPG_ERR_EPERM)
1386 rc = 0;
1388 goto done;
1391 if (rc == GPG_ERR_EPERM)
1392 goto done;
1394 if (!n && rc == GPG_ERR_ELEMENT_NOT_FOUND && elements->resolving == 1)
1396 rc = 0;
1397 goto fail;
1399 else if (!n)
1400 goto fail;
1402 if (a_target == 1)
1404 xfree (*req);
1405 *req = str_dup (*req_orig);
1408 if (*(req + 1))
1410 int e_target = 0;
1413 find_elements (client, doc, n->children, req + 1, &rc, &e_target,
1414 NULL, NULL, 1, 0, NULL, 0);
1416 if (!n && rc == GPG_ERR_ELEMENT_NOT_FOUND && elements->resolving == 1)
1418 rc = 0;
1419 goto fail;
1421 else if (!n)
1422 goto fail;
1425 done:
1426 if (!elements->prefix)
1429 * FIXME
1431 * If any req_orig element contains no target the element should be
1432 * prefixed with the literal character. Not really crucial if the
1433 * client isn't human because child elements are prefixed for the
1434 * current path. But may be confusing if editing by hand.
1436 elements->prefix = strv_join ("\t", req_orig);
1438 if (!elements->prefix)
1440 rc = GPG_ERR_ENOMEM;
1441 goto fail;
1444 if (elements->verbose)
1446 int ret;
1447 struct string_s *realpath = NULL;
1448 gpg_error_t allowed = rc;
1450 rc = 0;
1452 if (!allowed && a_target && elements->with_target)
1454 rc = build_realpath (client, doc, path, &realpath);
1455 if (rc)
1456 goto fail;
1458 realpath = string_prepend (realpath, "T ");
1461 ret = strv_printf (&elements->elements, "%s%s%s%s%s",
1462 elements->prefix,
1463 (!allowed && n && find_element_node (n->children))
1464 || realpath ? " " : "",
1465 (!allowed && n && find_element_node (n->children)) ? "+" : "",
1466 !allowed && realpath ? realpath->str : "",
1467 allowed ? " P" : "");
1468 string_free (realpath, 1);
1469 if (!ret)
1471 rc = GPG_ERR_ENOMEM;
1472 goto fail;
1475 else if (strv_printf (&elements->elements, "%s", elements->prefix) == 0)
1477 rc = GPG_ERR_ENOMEM;
1478 goto fail;
1481 if (update_element_list (elements) == 0)
1483 rc = GPG_ERR_ENOMEM;
1484 goto fail;
1488 rc = path_list_recurse (client, doc, n ? n->children : n, elements);
1490 fail:
1491 if (req_orig)
1492 strv_free (req_orig);
1494 strv_free (req);
1495 return rc;
1498 gpg_error_t
1499 recurse_xpath_nodeset (struct client_s *client, xmlDocPtr doc,
1500 xmlNodeSetPtr nodes, xmlChar * value,
1501 xmlBufferPtr * result, int cmd, const xmlChar * attr)
1503 int i = value ? nodes->nodeNr - 1 : 0;
1504 xmlBufferPtr buf;
1506 buf = xmlBufferCreate ();
1508 if (!buf)
1509 return GPG_ERR_ENOMEM;
1511 for (; value ? i >= 0 : i < nodes->nodeNr; value ? i-- : i++)
1513 xmlNodePtr n = nodes->nodeTab[i];
1514 gpg_error_t rc;
1516 if (!n)
1517 continue;
1519 if (!value && !attr)
1521 if (xmlNodeDump (buf, doc, n, 0, 0) == -1)
1523 *result = buf;
1524 return GPG_ERR_BAD_DATA;
1527 continue;
1530 if (!attr)
1532 xmlNodeSetContent (n, value);
1533 rc = update_element_mtime (n);
1535 if (rc)
1536 return rc;
1538 else
1540 if (!cmd)
1541 rc = add_attribute (n, (char *) attr, (char *) value);
1542 else
1543 rc = delete_attribute (client, n, attr);
1545 if (rc)
1546 return rc;
1550 *result = buf;
1551 return 0;
1554 static gpg_error_t
1555 convert_root_element (struct client_s *client, xmlNodePtr n)
1557 xmlChar *a = xmlGetProp (n, (xmlChar *) "_name");
1558 gpg_error_t rc;
1560 if (a)
1562 xmlFree (a);
1563 xmlChar *t = xmlGetNodePath (n);
1565 log_write (_
1566 ("An existing \"_name\" attribute already exists. Please rename this attribute before converting. Path is: %s"),
1568 xmlFree (t);
1569 return GPG_ERR_AMBIGUOUS_NAME;
1572 a = xmlGetProp (n, (xmlChar *) "name");
1574 if (a)
1576 rc = add_attribute (n, "_name", (char *) a);
1577 xmlFree (a);
1579 if (rc)
1580 return rc;
1582 rc = delete_attribute (client, n, (xmlChar *) "name");
1584 if (rc)
1585 return rc;
1587 xmlNodeSetName (n, (xmlChar *) "element");
1590 return 0;
1593 gpg_error_t
1594 delete_attribute (struct client_s *client, xmlNodePtr n, const xmlChar * name)
1596 xmlAttrPtr a;
1597 gpg_error_t rc = 0;
1599 if ((a = xmlHasProp (n, name)) == NULL)
1600 return GPG_ERR_NOT_FOUND;
1602 if (xmlRemoveProp (a) == -1)
1603 return GPG_ERR_BAD_DATA;
1605 if (client && xmlStrEqual (name, (xmlChar *) "_acl"))
1607 char *user = create_acl_user (client);
1609 rc = add_attribute (n, (char *) "_acl", user);
1610 xfree (user);
1612 if (rc)
1613 return rc;
1616 return update_element_mtime (n);
1619 static gpg_error_t
1620 convert_elements_recurse (struct client_s *client, xmlDocPtr doc,
1621 xmlNodePtr n, unsigned depth)
1623 gpg_error_t rc;
1625 depth++;
1627 for (n = n->children; n; n = n->next)
1629 if (n->type == XML_ELEMENT_NODE)
1631 if (depth > 1)
1633 xmlChar *a = NULL;
1635 if (xmlStrEqual (n->name, (xmlChar *) "element"))
1637 xmlChar *t = xmlGetNodePath (n);
1639 log_write (_
1640 ("An existing \"element\" already exists. Please rename this element before converting. Path is: %s"),
1642 xmlFree (t);
1643 return GPG_ERR_AMBIGUOUS_NAME;
1646 a = xmlGetProp (n, (xmlChar *) "_name");
1647 if (a)
1649 xmlFree (a);
1650 xmlChar *t = xmlGetNodePath (n);
1652 log_write (_
1653 ("An existing \"_name\" attribute already exists. Please rename this attribute before converting. Path is: %s"),
1655 xmlFree (t);
1656 return GPG_ERR_AMBIGUOUS_NAME;
1659 xmlChar *tmp = xmlStrdup (n->name);
1661 if (!tmp)
1662 return GPG_ERR_ENOMEM;
1664 xmlNodeSetName (n, (xmlChar *) "element");
1665 rc = add_attribute (n, "_name", (char *) tmp);
1666 xmlFree (tmp);
1668 if (rc)
1669 return rc;
1671 else
1673 rc = convert_root_element (client, n);
1675 if (rc)
1676 return rc;
1680 if (n->children)
1682 rc = convert_elements_recurse (client, doc, n, depth);
1684 if (rc)
1685 return rc;
1689 return 0;
1692 /* Renames ALL elements to the new "element" name. Existing element names are
1693 * stored as an attribute "_name". This was introduced in pwmd 2.12 so
1694 * elements can contain common characters that the XML parser barfs on (an
1695 * email address for example. */
1696 gpg_error_t
1697 convert_pre_212_elements (xmlDocPtr doc)
1699 xmlNodePtr n = xmlDocGetRootElement (doc);
1701 log_write (_("Converting pre 2.12 data file..."));
1702 return convert_elements_recurse (NULL, doc, n, 0);
1705 gpg_error_t
1706 validate_import (xmlNodePtr node)
1708 gpg_error_t rc = 0;
1710 if (!node)
1711 return 0;
1713 for (xmlNodePtr n = node; n; n = n->next)
1715 if (n->type == XML_ELEMENT_NODE)
1717 if (xmlStrEqual (n->name, (xmlChar *) "element"))
1719 xmlChar *a = xmlGetProp (n, (xmlChar *) "_name");
1721 if (!a)
1723 xmlChar *t = xmlGetNodePath (n);
1725 log_write (_("Missing attribute '_name' at %s."), t);
1726 xmlFree (t);
1727 return GPG_ERR_INV_VALUE;
1730 if (!valid_xml_element (a))
1732 xmlChar *t = xmlGetNodePath (n);
1734 log_write (_("'%s' is not a valid element name at %s."), a,
1736 xmlFree (a);
1737 xmlFree (t);
1738 return GPG_ERR_INV_VALUE;
1741 xmlFree (a);
1742 a = xmlGetProp (n, (xmlChar *) "_ctime");
1743 if (!a)
1744 attr_ctime (n);
1746 xmlFree (a);
1747 a = xmlGetProp (n, (xmlChar *) "_mtime");
1748 if (!a)
1749 update_element_mtime (n);
1750 xmlFree (a);
1752 else
1754 xmlChar *t = xmlGetNodePath (n);
1756 log_write (_("Warning: unknown element '%s' at %s. Ignoring."),
1757 n->name, t);
1758 xmlFree (t);
1759 continue;
1763 if (n->children)
1765 rc = validate_import (n->children);
1767 if (rc)
1768 return rc;
1772 return rc;
1775 gpg_error_t
1776 update_element_mtime (xmlNodePtr n)
1778 return add_attribute (n, NULL, NULL);
1781 gpg_error_t
1782 unlink_node (xmlNodePtr n)
1784 gpg_error_t rc = 0;
1786 if (!n)
1787 return rc;
1789 if (n->parent)
1790 rc = update_element_mtime (n->parent);
1792 xmlUnlinkNode (n);
1793 return rc;
1796 gpg_error_t
1797 parse_doc (const char *xml, size_t len, xmlDocPtr *result)
1799 xmlDocPtr doc;
1801 xmlResetLastError ();
1802 doc = xmlReadMemory (xml, len, NULL, "UTF-8", XML_PARSE_NOBLANKS);
1803 if (!doc && xmlGetLastError ())
1804 return GPG_ERR_BAD_DATA;
1806 *result = doc;
1807 return !doc ? GPG_ERR_ENOMEM : 0;
1810 static xmlNodePtr
1811 realpath_elements_cb (struct client_s *client, xmlNodePtr node, char **target,
1812 gpg_error_t * rc, char **req_orig, void *data)
1814 char *path = *(char **) data;
1815 char *tmp = NULL, *result;
1817 if (path)
1819 xfree (path);
1820 *(char **) data = NULL;
1823 path = strv_join ("\t", target);
1825 if (!path)
1827 *rc = GPG_ERR_ENOMEM;
1828 return NULL;
1831 if (req_orig)
1833 tmp = strv_join ("\t", req_orig);
1835 if (!tmp)
1837 xfree (path);
1838 *rc = GPG_ERR_ENOMEM;
1839 return NULL;
1843 if (tmp && *tmp)
1844 result = str_asprintf ("%s\t%s", path, tmp);
1845 else
1846 result = str_dup (path);
1848 if (!result)
1850 *rc = GPG_ERR_ENOMEM;
1851 xfree (path);
1852 xfree (tmp);
1853 return NULL;
1856 xfree (path);
1857 xfree (tmp);
1858 *(char **) data = result;
1859 return node;
1862 gpg_error_t
1863 build_realpath (struct client_s *client, xmlDocPtr doc, char *line,
1864 struct string_s ** result)
1866 gpg_error_t rc;
1867 char **req;
1868 char *t;
1869 int i;
1870 xmlNodePtr n;
1871 struct string_s *string;
1872 char *rp = NULL;
1874 if (strchr (line, '\t') != NULL)
1876 if ((req = str_split (line, "\t", 0)) == NULL)
1877 return GPG_ERR_SYNTAX;
1879 else
1881 if ((req = str_split (line, " ", 0)) == NULL)
1882 return GPG_ERR_SYNTAX;
1885 n = find_root_element (client, doc, &req, &rc, NULL, 0, 0);
1886 if (!n)
1888 strv_free (req);
1889 return rc;
1892 rp = strv_join ("\t", req);
1893 if (!rp)
1895 strv_free (req);
1896 return GPG_ERR_ENOMEM;
1899 if (req[1])
1901 n = find_elements (client, doc, n->children, req + 1, &rc, NULL,
1902 realpath_elements_cb, NULL, 0, 0, &rp, 0);
1903 if (!n)
1905 xfree (rp);
1906 strv_free (req);
1907 return rc;
1911 string = string_new (rp);
1912 xfree (rp);
1913 strv_free (req);
1914 if (!string)
1915 return GPG_ERR_ENOMEM;
1917 again:
1918 for (i = 0, t = string->str + i; *t; t++, i++)
1920 if ((!i && *t != '!') || (*t == '\t' && *(t + 1) && *(t + 1) != '!'))
1922 struct string_s *s = string_insert_c (string, !i ? i++ : ++i, '!');
1924 if (!s)
1926 string_free (string, 1);
1927 return GPG_ERR_ENOMEM;
1930 string = s;
1931 goto again;
1935 *result = string;
1936 return rc;
1939 #if 0
1940 static char *
1941 node_to_element_path (xmlNodePtr node)
1943 xmlNodePtr n;
1944 struct string_s *str = string_new ("");
1945 char *result;
1947 for (n = node; n; n = n->parent)
1949 xmlNodePtr child;
1951 for (child = n; child; child = child->next)
1953 if (child->type != XML_ELEMENT_NODE)
1954 continue;
1956 xmlChar *name = node_has_attribute (n, (xmlChar *) "_name");
1957 if (name)
1959 str = string_prepend (str, (char *) name);
1960 xmlFree (name);
1961 name = node_has_attribute (n, (xmlChar *) "target");
1962 if (name)
1963 str = string_prepend (str, "\t");
1964 else
1965 str = string_prepend (str, "\t!");
1966 xmlFree (name);
1968 break;
1972 str = string_erase (str, 0, 1);
1973 result = str->str;
1974 string_free (str, 0);
1975 return result;
1977 #endif
1980 * Recurse the element tree beginning at 'node' and find elements who point
1981 * back to 'src' or 'dst'. Also follows target attributes.
1983 static gpg_error_t
1984 find_child_to_target (struct client_s *client, xmlDocPtr doc, xmlNodePtr node,
1985 xmlNodePtr src, xmlNodePtr dst, unsigned depth,
1986 int is_target)
1988 xmlNodePtr n;
1989 gpg_error_t rc = 0;
1991 if (max_recursion_depth >= 1 && depth > max_recursion_depth)
1992 return gpg_error (GPG_ERR_ELOOP);
1994 for (n = node; n; n = n->next)
1996 xmlChar *target;
1998 if (n->type != XML_ELEMENT_NODE)
1999 continue;
2001 if (n == src || n == dst)
2002 return GPG_ERR_ELOOP;
2004 target = node_has_attribute (n, (xmlChar *) "target");
2005 if (target)
2007 xmlNodePtr tmp;
2008 char **result = NULL;
2010 tmp = resolve_path (client, doc, target, &result, &rc);
2011 xmlFree (target);
2012 strv_free (result);
2013 if (!rc)
2015 rc = find_child_to_target (client, doc, tmp, src, dst, ++depth,
2017 depth--;
2020 if (rc && gpg_err_code (rc) != GPG_ERR_ELEMENT_NOT_FOUND)
2021 return rc;
2023 if (is_target)
2024 break;
2026 continue;
2029 if (n->children)
2031 rc = find_child_to_target (client, doc, n->children, src, dst,
2032 ++depth,0);
2033 depth--;
2034 if (rc)
2035 return rc;
2038 if (is_target)
2039 break;
2042 return rc;
2045 static gpg_error_t
2046 find_child_of_parent (xmlDocPtr doc, xmlNodePtr src, xmlNodePtr dst)
2048 xmlNodePtr n;
2049 gpg_error_t rc = 0;
2051 for (n = src; n; n = n->next)
2053 if (n->type != XML_ELEMENT_NODE)
2054 continue;
2056 if (n == dst)
2058 rc = GPG_ERR_ELOOP;
2059 break;
2062 rc = find_child_of_parent (doc, n->children, dst);
2065 return rc;
2068 static gpg_error_t
2069 find_parent_of_child (xmlDocPtr doc, xmlNodePtr node, xmlNodePtr dst)
2071 xmlNodePtr n;
2072 gpg_error_t rc = 0;
2074 for (n = node; n; n = n->parent)
2076 if (n->type != XML_ELEMENT_NODE)
2078 xmlNodePtr tmp;
2080 for (tmp = n->next; tmp; n = n->next)
2082 if (n->type != XML_ELEMENT_NODE)
2083 continue;
2085 if (tmp == dst)
2086 return GPG_ERR_ELOOP;
2090 if (n == dst)
2091 return GPG_ERR_ELOOP;
2094 return rc;
2097 gpg_error_t
2098 validate_target_attribute (struct client_s *client, xmlDocPtr doc,
2099 const char *src, xmlNodePtr dst_node)
2101 gpg_error_t rc;
2102 xmlNodePtr src_node;
2103 char **src_req = NULL;
2105 src_node = resolve_path (client, doc, (xmlChar *) src, &src_req, &rc);
2106 if (rc)
2107 goto fail;
2109 /* A destination element is a child of the source element. */
2110 rc = find_child_of_parent (doc, src_node->children, dst_node);
2111 if (rc)
2112 goto fail;
2114 /* The destination element is a parent of the source element. */
2115 rc = find_parent_of_child (doc, src_node->parent, dst_node);
2116 if (rc)
2117 goto fail;
2119 /* A destination child element contains a target to the source element. */
2120 rc = find_child_to_target (client, doc, dst_node->children, src_node,
2121 dst_node, 0, 0);
2122 if (rc)
2123 goto fail;
2125 fail:
2126 strv_free (src_req);
2127 return rc;
2130 /* The owner of the element is the first user listed in the _acl attribute
2131 * list. acl_check() should be called before calling this function. An empty
2132 * ACL is an error if the client is not invoking_user.
2134 gpg_error_t
2135 is_element_owner (struct client_s *client, xmlNodePtr n)
2137 xmlChar *acl = node_has_attribute (n, (xmlChar *) "_acl");
2138 char **users;
2139 gpg_error_t rc = GPG_ERR_EPERM;
2141 if (!acl || !*acl)
2143 xmlFree (acl);
2144 return 0;
2147 users = str_split((char *)acl, ",", 0);
2148 if (users && *users)
2150 char *user;
2152 #ifdef WITH_GNUTLS
2153 if (client->thd->remote)
2154 user = str_asprintf ("#%s", client->thd->tls->fp);
2155 else
2156 user = get_username (client->thd->peer->uid);
2157 #else
2158 user = get_username (client->thd->peer->uid);
2159 #endif
2161 rc = !strcmp (*users, user) ? 0 : GPG_ERR_EPERM;
2162 xfree (user);
2165 strv_free (users);
2166 return rc;