xref: /openbsd/usr.sbin/ldapd/attributes.c (revision 5387241f)
1 /*	$OpenBSD: attributes.c,v 1.7 2021/12/20 13:26:11 claudio Exp $ */
2 
3 /*
4  * Copyright (c) 2009 Martin Hedenfalk <martin@bzero.se>
5  *
6  * Permission to use, copy, modify, and distribute this software for any
7  * purpose with or without fee is hereby granted, provided that the above
8  * copyright notice and this permission notice appear in all copies.
9  *
10  * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
11  * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
12  * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
13  * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
14  * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
15  * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
16  * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
17  */
18 
19 #include <sys/queue.h>
20 #include <sys/types.h>
21 
22 #include <assert.h>
23 #include <string.h>
24 #include <time.h>
25 
26 #include "ldapd.h"
27 #include "log.h"
28 
29 struct ber_element *
ldap_get_attribute(struct ber_element * entry,const char * attr)30 ldap_get_attribute(struct ber_element *entry, const char *attr)
31 {
32 	char			*s;
33 	struct ber_element	*elm, *a;
34 
35 	assert(entry);
36 	assert(attr);
37 	if (entry->be_encoding != BER_TYPE_SEQUENCE)
38 		return NULL;
39 
40 	for (elm = entry->be_sub; elm != NULL; elm = elm->be_next) {
41 		a = elm->be_sub;
42 		if (a && ober_get_string(a, &s) == 0 && strcasecmp(s, attr) == 0)
43 			return a;
44 	}
45 
46 	return NULL;
47 }
48 
49 struct ber_element *
ldap_find_attribute(struct ber_element * entry,struct attr_type * at)50 ldap_find_attribute(struct ber_element *entry, struct attr_type *at)
51 {
52 	struct ber_element	*elm = NULL;
53 	struct name		*an;
54 
55 	SLIST_FOREACH(an, at->names, next) {
56 		if ((elm = ldap_get_attribute(entry, an->name)) != NULL)
57 			return elm;
58 	}
59 	if (an == NULL)
60 		elm = ldap_get_attribute(entry, at->oid);
61 
62 	return elm;
63 }
64 
65 struct ber_element *
ldap_find_value(struct ber_element * elm,const char * value)66 ldap_find_value(struct ber_element *elm, const char *value)
67 {
68 	char			*s;
69 	struct ber_element	*a;
70 
71 	if (elm == NULL)
72 		return NULL;
73 
74 	for (a = elm->be_sub; a != NULL; a = a->be_next) {
75 		if (ober_get_string(a, &s) == 0 && strcasecmp(s, value) == 0)
76 			return a;
77 	}
78 
79 	return NULL;
80 }
81 
82 struct ber_element *
ldap_add_attribute(struct ber_element * entry,const char * attr,struct ber_element * value_set)83 ldap_add_attribute(struct ber_element *entry, const char *attr,
84 	struct ber_element *value_set)
85 {
86 	struct ber_element	*elm, *a, *last;
87 
88 	assert(entry);
89 	assert(attr);
90 	assert(value_set);
91 
92 	if (entry->be_encoding != BER_TYPE_SEQUENCE) {
93 		log_warnx("entries should be a sequence");
94 		return NULL;
95 	}
96 
97 	if (value_set->be_type != BER_TYPE_SET) {
98 		log_warnx("values should be a set");
99 		return NULL;
100 	}
101 
102 	last = entry->be_sub;
103 	if (last == NULL)
104 		last = entry;
105 	else while (last != NULL && last->be_next != NULL)
106 		last = last->be_next;
107 
108 	if ((elm = ober_add_sequence(last)) == NULL)
109 		return NULL;
110 	if ((a = ober_add_string(elm, attr)) == NULL) {
111 		ober_free_elements(elm);
112 		return NULL;
113 	}
114 	ober_link_elements(a, value_set);
115 
116 	return elm;
117 }
118 
119 int
ldap_set_values(struct ber_element * elm,struct ber_element * vals)120 ldap_set_values(struct ber_element *elm, struct ber_element *vals)
121 {
122 	char			*attr;
123 	struct ber_element	*old_vals;
124 
125 	assert(elm);
126 	assert(vals);
127 	assert(vals->be_sub);
128 
129 	if (ober_scanf_elements(elm, "se(", &attr, &old_vals) != 0) {
130 		log_warnx("failed to parse element");
131 		return -1;
132 	}
133 
134 	ober_free_elements(old_vals->be_sub);
135 	old_vals->be_sub = NULL;
136 	ober_link_elements(old_vals, vals->be_sub);
137 
138 	vals->be_sub = NULL;
139 	ober_free_elements(vals);
140 
141 	return 0;
142 }
143 
144 int
ldap_merge_values(struct ber_element * elm,struct ber_element * vals)145 ldap_merge_values(struct ber_element *elm, struct ber_element *vals)
146 {
147 	char			*attr;
148 	struct ber_element	*old_vals, *last;
149 
150 	assert(elm);
151 	assert(vals);
152 	assert(vals->be_type == BER_TYPE_SET);
153 	assert(vals->be_sub);
154 
155 	if (ober_scanf_elements(elm, "se(", &attr, &old_vals) != 0) {
156 		log_warnx("failed to parse element");
157 		return -1;
158 	}
159 
160 	last = old_vals->be_sub;
161 	while (last && last->be_next)
162 		last = last->be_next;
163 
164 	ober_link_elements(last, vals->be_sub);
165 
166 	vals->be_sub = NULL;
167 	ober_free_elements(vals);
168 
169 	return 0;
170 }
171 
172 
173 int
ldap_del_attribute(struct ber_element * entry,const char * attrdesc)174 ldap_del_attribute(struct ber_element *entry, const char *attrdesc)
175 {
176 	struct ber_element	*attr, *prev = NULL;
177 	char			*s;
178 
179 	assert(entry);
180 	assert(attrdesc);
181 
182 	attr = entry->be_sub;
183 	while (attr) {
184 		if (ober_scanf_elements(attr, "{s", &s) != 0) {
185 			log_warnx("failed to parse attribute");
186 			return -1;
187 		}
188 
189 		if (strcasecmp(s, attrdesc) == 0) {
190 			if (prev == NULL)
191 				entry->be_sub = attr->be_next;
192 			else
193 				prev->be_next = attr->be_next;
194 			attr->be_next = NULL;
195 			ober_free_elements(attr);
196 			break;
197 		}
198 
199 		prev = attr;
200 		attr = attr->be_next;
201 	}
202 
203 	return 0;
204 }
205 
206 int
ldap_del_values(struct ber_element * elm,struct ber_element * vals)207 ldap_del_values(struct ber_element *elm, struct ber_element *vals)
208 {
209 	char			*attr;
210 	struct ber_element	*old_vals, *v, *x, *prev, *next;
211 	struct ber_element	*removed;
212 	int			removed_p;
213 	assert(elm);
214 	assert(vals);
215 	assert(vals->be_sub);
216 
217 	if (ober_scanf_elements(elm, "se(", &attr, &old_vals) != 0) {
218 		log_warnx("failed to parse element");
219 		return -1;
220 	}
221 
222 	prev = old_vals;
223 	removed_p = 0;
224 	for (v = old_vals->be_sub; v; v = next) {
225 		next = v->be_next;
226 
227 		for (x = vals->be_sub; x; x = x->be_next) {
228 			if (x && v->be_len == x->be_len &&
229 			    memcmp(v->be_val, x->be_val, x->be_len) == 0) {
230 				removed = ober_unlink_elements(prev);
231 				ober_link_elements(prev, removed->be_next);
232 				ober_free_element(removed);
233 				removed_p = 1;
234 				break;
235 			}
236 		}
237 		if (removed_p) {
238 			removed_p = 0;
239 		} else {
240 			prev = v;
241 		}
242 	}
243 
244 	if (old_vals->be_sub == NULL)
245 		return 1;
246 
247 	return 0;
248 }
249 
250 char *
ldap_strftime(time_t tm)251 ldap_strftime(time_t tm)
252 {
253 	static char	 tmbuf[16];
254 	struct tm	*gmt = gmtime(&tm);
255 
256 	strftime(tmbuf, sizeof(tmbuf), "%Y%m%d%H%M%SZ", gmt);
257 	return tmbuf;
258 }
259 
260 char *
ldap_now(void)261 ldap_now(void)
262 {
263 	return ldap_strftime(time(0));
264 }
265 
266