1*5387241fSclaudio /* $OpenBSD: attributes.c,v 1.7 2021/12/20 13:26:11 claudio Exp $ */
25d465952Smartinh
35d465952Smartinh /*
45d465952Smartinh * Copyright (c) 2009 Martin Hedenfalk <martin@bzero.se>
55d465952Smartinh *
65d465952Smartinh * Permission to use, copy, modify, and distribute this software for any
75d465952Smartinh * purpose with or without fee is hereby granted, provided that the above
85d465952Smartinh * copyright notice and this permission notice appear in all copies.
95d465952Smartinh *
105d465952Smartinh * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
115d465952Smartinh * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
125d465952Smartinh * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
135d465952Smartinh * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
145d465952Smartinh * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
155d465952Smartinh * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
165d465952Smartinh * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
175d465952Smartinh */
185d465952Smartinh
195d465952Smartinh #include <sys/queue.h>
205d465952Smartinh #include <sys/types.h>
215d465952Smartinh
225d465952Smartinh #include <assert.h>
235d465952Smartinh #include <string.h>
245d465952Smartinh #include <time.h>
255d465952Smartinh
265d465952Smartinh #include "ldapd.h"
27fdd30f56Sbenno #include "log.h"
285d465952Smartinh
295d465952Smartinh struct ber_element *
ldap_get_attribute(struct ber_element * entry,const char * attr)305d465952Smartinh ldap_get_attribute(struct ber_element *entry, const char *attr)
315d465952Smartinh {
325d465952Smartinh char *s;
335d465952Smartinh struct ber_element *elm, *a;
345d465952Smartinh
355d465952Smartinh assert(entry);
365d465952Smartinh assert(attr);
375d465952Smartinh if (entry->be_encoding != BER_TYPE_SEQUENCE)
385d465952Smartinh return NULL;
395d465952Smartinh
405d465952Smartinh for (elm = entry->be_sub; elm != NULL; elm = elm->be_next) {
415d465952Smartinh a = elm->be_sub;
42696b5899Stb if (a && ober_get_string(a, &s) == 0 && strcasecmp(s, attr) == 0)
435d465952Smartinh return a;
445d465952Smartinh }
455d465952Smartinh
465d465952Smartinh return NULL;
475d465952Smartinh }
485d465952Smartinh
495d465952Smartinh struct ber_element *
ldap_find_attribute(struct ber_element * entry,struct attr_type * at)505d465952Smartinh ldap_find_attribute(struct ber_element *entry, struct attr_type *at)
515d465952Smartinh {
525d465952Smartinh struct ber_element *elm = NULL;
535d465952Smartinh struct name *an;
545d465952Smartinh
555d465952Smartinh SLIST_FOREACH(an, at->names, next) {
565d465952Smartinh if ((elm = ldap_get_attribute(entry, an->name)) != NULL)
575d465952Smartinh return elm;
585d465952Smartinh }
595d465952Smartinh if (an == NULL)
605d465952Smartinh elm = ldap_get_attribute(entry, at->oid);
615d465952Smartinh
625d465952Smartinh return elm;
635d465952Smartinh }
645d465952Smartinh
655d465952Smartinh struct ber_element *
ldap_find_value(struct ber_element * elm,const char * value)665d465952Smartinh ldap_find_value(struct ber_element *elm, const char *value)
675d465952Smartinh {
685d465952Smartinh char *s;
695d465952Smartinh struct ber_element *a;
705d465952Smartinh
715d465952Smartinh if (elm == NULL)
725d465952Smartinh return NULL;
735d465952Smartinh
745d465952Smartinh for (a = elm->be_sub; a != NULL; a = a->be_next) {
75696b5899Stb if (ober_get_string(a, &s) == 0 && strcasecmp(s, value) == 0)
765d465952Smartinh return a;
775d465952Smartinh }
785d465952Smartinh
795d465952Smartinh return NULL;
805d465952Smartinh }
815d465952Smartinh
825d465952Smartinh struct ber_element *
ldap_add_attribute(struct ber_element * entry,const char * attr,struct ber_element * value_set)835d465952Smartinh ldap_add_attribute(struct ber_element *entry, const char *attr,
845d465952Smartinh struct ber_element *value_set)
855d465952Smartinh {
865d465952Smartinh struct ber_element *elm, *a, *last;
875d465952Smartinh
885d465952Smartinh assert(entry);
895d465952Smartinh assert(attr);
905d465952Smartinh assert(value_set);
915d465952Smartinh
925d465952Smartinh if (entry->be_encoding != BER_TYPE_SEQUENCE) {
935d465952Smartinh log_warnx("entries should be a sequence");
945d465952Smartinh return NULL;
955d465952Smartinh }
965d465952Smartinh
975d465952Smartinh if (value_set->be_type != BER_TYPE_SET) {
985d465952Smartinh log_warnx("values should be a set");
995d465952Smartinh return NULL;
1005d465952Smartinh }
1015d465952Smartinh
1025d465952Smartinh last = entry->be_sub;
10316beda35Smartinh if (last == NULL)
10416beda35Smartinh last = entry;
10516beda35Smartinh else while (last != NULL && last->be_next != NULL)
1065d465952Smartinh last = last->be_next;
1075d465952Smartinh
108696b5899Stb if ((elm = ober_add_sequence(last)) == NULL)
1095d465952Smartinh return NULL;
110696b5899Stb if ((a = ober_add_string(elm, attr)) == NULL) {
111696b5899Stb ober_free_elements(elm);
1125d465952Smartinh return NULL;
1135d465952Smartinh }
114696b5899Stb ober_link_elements(a, value_set);
1155d465952Smartinh
1165d465952Smartinh return elm;
1175d465952Smartinh }
1185d465952Smartinh
1195d465952Smartinh int
ldap_set_values(struct ber_element * elm,struct ber_element * vals)1205d465952Smartinh ldap_set_values(struct ber_element *elm, struct ber_element *vals)
1215d465952Smartinh {
1225d465952Smartinh char *attr;
1235d465952Smartinh struct ber_element *old_vals;
1245d465952Smartinh
1255d465952Smartinh assert(elm);
1265d465952Smartinh assert(vals);
1275d465952Smartinh assert(vals->be_sub);
1285d465952Smartinh
129696b5899Stb if (ober_scanf_elements(elm, "se(", &attr, &old_vals) != 0) {
1305d465952Smartinh log_warnx("failed to parse element");
1315d465952Smartinh return -1;
1325d465952Smartinh }
1335d465952Smartinh
134696b5899Stb ober_free_elements(old_vals->be_sub);
1355d465952Smartinh old_vals->be_sub = NULL;
136696b5899Stb ober_link_elements(old_vals, vals->be_sub);
1375d465952Smartinh
138f12396bdSmartinh vals->be_sub = NULL;
139696b5899Stb ober_free_elements(vals);
140f12396bdSmartinh
1415d465952Smartinh return 0;
1425d465952Smartinh }
1435d465952Smartinh
1445d465952Smartinh int
ldap_merge_values(struct ber_element * elm,struct ber_element * vals)1455d465952Smartinh ldap_merge_values(struct ber_element *elm, struct ber_element *vals)
1465d465952Smartinh {
1475d465952Smartinh char *attr;
1485d465952Smartinh struct ber_element *old_vals, *last;
1495d465952Smartinh
1505d465952Smartinh assert(elm);
1515d465952Smartinh assert(vals);
1525d465952Smartinh assert(vals->be_type == BER_TYPE_SET);
1535d465952Smartinh assert(vals->be_sub);
1545d465952Smartinh
155696b5899Stb if (ober_scanf_elements(elm, "se(", &attr, &old_vals) != 0) {
1565d465952Smartinh log_warnx("failed to parse element");
1575d465952Smartinh return -1;
1585d465952Smartinh }
1595d465952Smartinh
1605d465952Smartinh last = old_vals->be_sub;
1615d465952Smartinh while (last && last->be_next)
1625d465952Smartinh last = last->be_next;
1635d465952Smartinh
164696b5899Stb ober_link_elements(last, vals->be_sub);
1655d465952Smartinh
166f12396bdSmartinh vals->be_sub = NULL;
167696b5899Stb ober_free_elements(vals);
168f12396bdSmartinh
1695d465952Smartinh return 0;
1705d465952Smartinh }
1715d465952Smartinh
1725d465952Smartinh
1735d465952Smartinh int
ldap_del_attribute(struct ber_element * entry,const char * attrdesc)1745d465952Smartinh ldap_del_attribute(struct ber_element *entry, const char *attrdesc)
1755d465952Smartinh {
1765d465952Smartinh struct ber_element *attr, *prev = NULL;
1775d465952Smartinh char *s;
1785d465952Smartinh
1795d465952Smartinh assert(entry);
1805d465952Smartinh assert(attrdesc);
1815d465952Smartinh
1825d465952Smartinh attr = entry->be_sub;
1835d465952Smartinh while (attr) {
184*5387241fSclaudio if (ober_scanf_elements(attr, "{s", &s) != 0) {
1855d465952Smartinh log_warnx("failed to parse attribute");
1865d465952Smartinh return -1;
1875d465952Smartinh }
1885d465952Smartinh
1895d465952Smartinh if (strcasecmp(s, attrdesc) == 0) {
1905d465952Smartinh if (prev == NULL)
1915d465952Smartinh entry->be_sub = attr->be_next;
1925d465952Smartinh else
1935d465952Smartinh prev->be_next = attr->be_next;
1945d465952Smartinh attr->be_next = NULL;
195696b5899Stb ober_free_elements(attr);
1965d465952Smartinh break;
1975d465952Smartinh }
1985d465952Smartinh
1995d465952Smartinh prev = attr;
2005d465952Smartinh attr = attr->be_next;
2015d465952Smartinh }
2025d465952Smartinh
2035d465952Smartinh return 0;
2045d465952Smartinh }
2055d465952Smartinh
2065d465952Smartinh int
ldap_del_values(struct ber_element * elm,struct ber_element * vals)2075d465952Smartinh ldap_del_values(struct ber_element *elm, struct ber_element *vals)
2085d465952Smartinh {
2095d465952Smartinh char *attr;
2107c698af4Sguenther struct ber_element *old_vals, *v, *x, *prev, *next;
2115d465952Smartinh struct ber_element *removed;
2127c698af4Sguenther int removed_p;
2135d465952Smartinh assert(elm);
2145d465952Smartinh assert(vals);
2155d465952Smartinh assert(vals->be_sub);
2165d465952Smartinh
217696b5899Stb if (ober_scanf_elements(elm, "se(", &attr, &old_vals) != 0) {
2185d465952Smartinh log_warnx("failed to parse element");
2195d465952Smartinh return -1;
2205d465952Smartinh }
2215d465952Smartinh
2225d465952Smartinh prev = old_vals;
2237c698af4Sguenther removed_p = 0;
2247c698af4Sguenther for (v = old_vals->be_sub; v; v = next) {
2257c698af4Sguenther next = v->be_next;
2267c698af4Sguenther
2275d465952Smartinh for (x = vals->be_sub; x; x = x->be_next) {
2287c698af4Sguenther if (x && v->be_len == x->be_len &&
2297c698af4Sguenther memcmp(v->be_val, x->be_val, x->be_len) == 0) {
230696b5899Stb removed = ober_unlink_elements(prev);
231696b5899Stb ober_link_elements(prev, removed->be_next);
232696b5899Stb ober_free_element(removed);
2337c698af4Sguenther removed_p = 1;
2345d465952Smartinh break;
2355d465952Smartinh }
2365d465952Smartinh }
2377c698af4Sguenther if (removed_p) {
2387c698af4Sguenther removed_p = 0;
2397c698af4Sguenther } else {
2405d465952Smartinh prev = v;
2415d465952Smartinh }
2427c698af4Sguenther }
2435d465952Smartinh
244*5387241fSclaudio if (old_vals->be_sub == NULL)
245*5387241fSclaudio return 1;
246*5387241fSclaudio
2475d465952Smartinh return 0;
2485d465952Smartinh }
2495d465952Smartinh
2505d465952Smartinh char *
ldap_strftime(time_t tm)2515d465952Smartinh ldap_strftime(time_t tm)
2525d465952Smartinh {
2535d465952Smartinh static char tmbuf[16];
2545d465952Smartinh struct tm *gmt = gmtime(&tm);
2555d465952Smartinh
2565d465952Smartinh strftime(tmbuf, sizeof(tmbuf), "%Y%m%d%H%M%SZ", gmt);
2575d465952Smartinh return tmbuf;
2585d465952Smartinh }
2595d465952Smartinh
2605d465952Smartinh char *
ldap_now(void)2615d465952Smartinh ldap_now(void)
2625d465952Smartinh {
2635d465952Smartinh return ldap_strftime(time(0));
2645d465952Smartinh }
2655d465952Smartinh
266