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