xref: /openbsd-src/usr.sbin/ldapd/attributes.c (revision 5387241f8527ff37ae50356167c4e1c0a1937311)
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