xref: /openbsd-src/usr.sbin/ldapd/attributes.c (revision 91f110e064cd7c194e59e019b83bb7496c1c84d4)
1 /*	$OpenBSD: attributes.c,v 1.3 2010/10/19 09:34:41 martinh 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 
28 struct ber_element *
29 ldap_get_attribute(struct ber_element *entry, const char *attr)
30 {
31 	char			*s;
32 	struct ber_element	*elm, *a;
33 
34 	assert(entry);
35 	assert(attr);
36 	if (entry->be_encoding != BER_TYPE_SEQUENCE)
37 		return NULL;
38 
39 	for (elm = entry->be_sub; elm != NULL; elm = elm->be_next) {
40 		a = elm->be_sub;
41 		if (a && ber_get_string(a, &s) == 0 && strcasecmp(s, attr) == 0)
42 			return a;
43 	}
44 
45 	return NULL;
46 }
47 
48 struct ber_element *
49 ldap_find_attribute(struct ber_element *entry, struct attr_type *at)
50 {
51 	struct ber_element	*elm = NULL;
52 	struct name		*an;
53 
54 	SLIST_FOREACH(an, at->names, next) {
55 		if ((elm = ldap_get_attribute(entry, an->name)) != NULL)
56 			return elm;
57 	}
58 	if (an == NULL)
59 		elm = ldap_get_attribute(entry, at->oid);
60 
61 	return elm;
62 }
63 
64 struct ber_element *
65 ldap_find_value(struct ber_element *elm, const char *value)
66 {
67 	char			*s;
68 	struct ber_element	*a;
69 
70 	if (elm == NULL)
71 		return NULL;
72 
73 	for (a = elm->be_sub; a != NULL; a = a->be_next) {
74 		if (ber_get_string(a, &s) == 0 && strcasecmp(s, value) == 0)
75 			return a;
76 	}
77 
78 	return NULL;
79 }
80 
81 struct ber_element *
82 ldap_add_attribute(struct ber_element *entry, const char *attr,
83 	struct ber_element *value_set)
84 {
85 	struct ber_element	*elm, *a, *last;
86 
87 	assert(entry);
88 	assert(attr);
89 	assert(value_set);
90 
91 	if (entry->be_encoding != BER_TYPE_SEQUENCE) {
92 		log_warnx("entries should be a sequence");
93 		return NULL;
94 	}
95 
96 	if (value_set->be_type != BER_TYPE_SET) {
97 		log_warnx("values should be a set");
98 		return NULL;
99 	}
100 
101 	last = entry->be_sub;
102 	if (last == NULL)
103 		last = entry;
104 	else while (last != NULL && last->be_next != NULL)
105 		last = last->be_next;
106 
107 	if ((elm = ber_add_sequence(last)) == NULL)
108 		return NULL;
109 	if ((a = ber_add_string(elm, attr)) == NULL) {
110 		ber_free_elements(elm);
111 		return NULL;
112 	}
113 	ber_link_elements(a, value_set);
114 
115 	return elm;
116 }
117 
118 int
119 ldap_set_values(struct ber_element *elm, struct ber_element *vals)
120 {
121 	char			*attr;
122 	struct ber_element	*old_vals;
123 
124 	assert(elm);
125 	assert(vals);
126 	assert(vals->be_sub);
127 
128 	if (ber_scanf_elements(elm, "se(", &attr, &old_vals) != 0) {
129 		log_warnx("failed to parse element");
130 		return -1;
131 	}
132 
133 	ber_free_elements(old_vals->be_sub);
134 	old_vals->be_sub = NULL;
135 	ber_link_elements(old_vals, vals->be_sub);
136 
137 	vals->be_sub = NULL;
138 	ber_free_elements(vals);
139 
140 	return 0;
141 }
142 
143 int
144 ldap_merge_values(struct ber_element *elm, struct ber_element *vals)
145 {
146 	char			*attr;
147 	struct ber_element	*old_vals, *last;
148 
149 	assert(elm);
150 	assert(vals);
151 	assert(vals->be_type == BER_TYPE_SET);
152 	assert(vals->be_sub);
153 
154 	if (ber_scanf_elements(elm, "se(", &attr, &old_vals) != 0) {
155 		log_warnx("failed to parse element");
156 		return -1;
157 	}
158 
159 	last = old_vals->be_sub;
160 	while (last && last->be_next)
161 		last = last->be_next;
162 
163 	ber_link_elements(last, vals->be_sub);
164 
165 	vals->be_sub = NULL;
166 	ber_free_elements(vals);
167 
168 	return 0;
169 }
170 
171 
172 int
173 ldap_del_attribute(struct ber_element *entry, const char *attrdesc)
174 {
175 	struct ber_element	*attr, *prev = NULL;
176 	char			*s;
177 
178 	assert(entry);
179 	assert(attrdesc);
180 
181 	attr = entry->be_sub;
182 	while (attr) {
183 		if (ber_scanf_elements(attr, "{s(", &s) != 0) {
184 			log_warnx("failed to parse attribute");
185 			return -1;
186 		}
187 
188 		if (strcasecmp(s, attrdesc) == 0) {
189 			if (prev == NULL)
190 				entry->be_sub = attr->be_next;
191 			else
192 				prev->be_next = attr->be_next;
193 			attr->be_next = NULL;
194 			ber_free_elements(attr);
195 			break;
196 		}
197 
198 		prev = attr;
199 		attr = attr->be_next;
200 	}
201 
202 	return 0;
203 }
204 
205 int
206 ldap_del_values(struct ber_element *elm, struct ber_element *vals)
207 {
208 	char			*attr;
209 	struct ber_element	*old_vals, *v, *x, *vk, *xk, *prev;
210 	struct ber_element	*removed;
211 
212 	assert(elm);
213 	assert(vals);
214 	assert(vals->be_sub);
215 
216 	if (ber_scanf_elements(elm, "se(", &attr, &old_vals) != 0) {
217 		log_warnx("failed to parse element");
218 		return -1;
219 	}
220 
221 	prev = old_vals;
222 	for (v = old_vals->be_sub; v; v = v->be_next) {
223 		vk = v->be_sub;
224 		for (x = vals->be_sub; x; x = x->be_next) {
225 			xk = x->be_sub;
226 			if (xk && vk->be_len == xk->be_len &&
227 			    memcmp(vk->be_val, xk->be_val, xk->be_len) == 0) {
228 				removed = ber_unlink_elements(prev);
229 				ber_link_elements(prev, removed->be_next);
230 				ber_free_elements(removed);
231 				break;
232 			}
233 		}
234 		prev = v;
235 	}
236 
237 	return 0;
238 }
239 
240 char *
241 ldap_strftime(time_t tm)
242 {
243 	static char	 tmbuf[16];
244 	struct tm	*gmt = gmtime(&tm);
245 
246 	strftime(tmbuf, sizeof(tmbuf), "%Y%m%d%H%M%SZ", gmt);
247 	return tmbuf;
248 }
249 
250 char *
251 ldap_now(void)
252 {
253 	return ldap_strftime(time(0));
254 }
255 
256