File: | src/libexec/login_ldap/aldap.c |
Warning: | line 967, column 8 Although the value stored to 'elm' is used in the enclosing expression, the value is never actually read from 'elm' |
Press '?' to see keyboard shortcuts
Keyboard shortcuts:
1 | /* $OpenBSD: aldap.c,v 1.2 2022/03/31 09:05:15 martijn Exp $ */ |
2 | |
3 | /* |
4 | * Copyright (c) 2008 Alexander Schrijver <aschrijver@openbsd.org> |
5 | * Copyright (c) 2006, 2007 Marc Balmer <mbalmer@openbsd.org> |
6 | * |
7 | * Permission to use, copy, modify, and distribute this software for any |
8 | * purpose with or without fee is hereby granted, provided that the above |
9 | * copyright notice and this permission notice appear in all copies. |
10 | * |
11 | * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES |
12 | * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF |
13 | * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR |
14 | * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES |
15 | * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN |
16 | * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF |
17 | * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. |
18 | */ |
19 | |
20 | #include <arpa/inet.h> |
21 | #include <ctype.h> |
22 | #include <errno(*__errno()).h> |
23 | #include <inttypes.h> |
24 | #include <string.h> |
25 | #include <stdlib.h> |
26 | #include <unistd.h> |
27 | |
28 | #include <event.h> |
29 | |
30 | #include "aldap.h" |
31 | |
32 | #if 0 |
33 | #define DEBUG |
34 | #endif |
35 | #define VERSION3 3 |
36 | |
37 | static struct ber_element *ldap_parse_search_filter(struct ber_element *, |
38 | char *); |
39 | static struct ber_element *ldap_do_parse_search_filter( |
40 | struct ber_element *, char **); |
41 | struct aldap_stringset *aldap_get_stringset(struct ber_element *); |
42 | char *utoa(char *); |
43 | static int isu8cont(unsigned char); |
44 | char *parseval(char *, size_t); |
45 | int aldap_create_page_control(struct ber_element *, |
46 | int, struct aldap_page_control *); |
47 | int aldap_send(struct aldap *, |
48 | struct ber_element *); |
49 | unsigned int aldap_application(struct ber_element *); |
50 | |
51 | #ifdef DEBUG |
52 | void ldap_debug_elements(struct ber_element *); |
53 | #endif |
54 | |
55 | #ifdef DEBUG |
56 | #define DPRINTF(x...)do { } while (0) printf(x) |
57 | #define LDAP_DEBUG(x, y)do { } while (0) do { fprintf(stderr(&__sF[2]), "*** " x "\n"); ldap_debug_elements(y); } while (0) |
58 | #else |
59 | #define DPRINTF(x...)do { } while (0) do { } while (0) |
60 | #define LDAP_DEBUG(x, y)do { } while (0) do { } while (0) |
61 | #endif |
62 | |
63 | unsigned int |
64 | aldap_application(struct ber_element *elm) |
65 | { |
66 | return BER_TYPE_OCTETSTRING4; |
67 | } |
68 | |
69 | int |
70 | aldap_close(struct aldap *al) |
71 | { |
72 | if (al->tls != NULL((void *)0)) { |
73 | tls_close(al->tls); |
74 | tls_free(al->tls); |
75 | } |
76 | close(al->fd); |
77 | ober_free(&al->ber); |
78 | evbuffer_free(al->buf); |
79 | free(al); |
80 | |
81 | return (0); |
82 | } |
83 | |
84 | struct aldap * |
85 | aldap_init(int fd) |
86 | { |
87 | struct aldap *a; |
88 | |
89 | if ((a = calloc(1, sizeof(*a))) == NULL((void *)0)) |
90 | return NULL((void *)0); |
91 | a->buf = evbuffer_new(); |
92 | a->fd = fd; |
93 | ober_set_application(&a->ber, aldap_application); |
94 | |
95 | return a; |
96 | } |
97 | |
98 | int |
99 | aldap_tls(struct aldap *ldap, struct tls_config *cfg, const char *name) |
100 | { |
101 | ldap->tls = tls_client(); |
102 | if (ldap->tls == NULL((void *)0)) { |
103 | ldap->err = ALDAP_ERR_OPERATION_FAILED3; |
104 | return (-1); |
105 | } |
106 | |
107 | if (tls_configure(ldap->tls, cfg) == -1) { |
108 | ldap->err = ALDAP_ERR_TLS_ERROR4; |
109 | return (-1); |
110 | } |
111 | |
112 | if (tls_connect_socket(ldap->tls, ldap->fd, name) == -1) { |
113 | ldap->err = ALDAP_ERR_TLS_ERROR4; |
114 | return (-1); |
115 | } |
116 | |
117 | if (tls_handshake(ldap->tls) == -1) { |
118 | ldap->err = ALDAP_ERR_TLS_ERROR4; |
119 | return (-1); |
120 | } |
121 | |
122 | return (0); |
123 | } |
124 | |
125 | int |
126 | aldap_send(struct aldap *ldap, struct ber_element *root) |
127 | { |
128 | void *ptr; |
129 | char *data; |
130 | size_t len, done; |
131 | ssize_t error, wrote; |
132 | |
133 | len = ober_calc_len(root); |
134 | error = ober_write_elements(&ldap->ber, root); |
135 | ober_free_elements(root); |
136 | if (error == -1) |
137 | return -1; |
138 | |
139 | ober_get_writebuf(&ldap->ber, &ptr); |
140 | done = 0; |
141 | data = ptr; |
142 | while (len > 0) { |
143 | if (ldap->tls != NULL((void *)0)) { |
144 | wrote = tls_write(ldap->tls, data + done, len); |
145 | if (wrote == TLS_WANT_POLLIN-2 || |
146 | wrote == TLS_WANT_POLLOUT-3) |
147 | continue; |
148 | } else |
149 | wrote = write(ldap->fd, data + done, len); |
150 | |
151 | if (wrote == -1) |
152 | return -1; |
153 | |
154 | len -= wrote; |
155 | done += wrote; |
156 | } |
157 | |
158 | return 0; |
159 | } |
160 | |
161 | int |
162 | aldap_req_starttls(struct aldap *ldap) |
163 | { |
164 | struct ber_element *root = NULL((void *)0), *ber; |
165 | |
166 | if ((root = ober_add_sequence(NULL((void *)0))) == NULL((void *)0)) |
167 | goto fail; |
168 | |
169 | ber = ober_printf_elements(root, "d{tst", ++ldap->msgid, BER_CLASS_APP0x1, |
170 | LDAP_REQ_EXTENDED, LDAP_STARTTLS_OID"1.3.6.1.4.1.1466.20037", BER_CLASS_CONTEXT0x2, 0); |
171 | if (ber == NULL((void *)0)) { |
172 | ldap->err = ALDAP_ERR_OPERATION_FAILED3; |
173 | goto fail; |
174 | } |
175 | |
176 | if (aldap_send(ldap, root) == -1) |
177 | goto fail; |
178 | |
179 | return (ldap->msgid); |
180 | fail: |
181 | if (root != NULL((void *)0)) |
182 | ober_free_elements(root); |
183 | |
184 | ldap->err = ALDAP_ERR_OPERATION_FAILED3; |
185 | return (-1); |
186 | } |
187 | |
188 | int |
189 | aldap_bind(struct aldap *ldap, char *binddn, char *bindcred) |
190 | { |
191 | struct ber_element *root = NULL((void *)0), *elm; |
192 | |
193 | if (binddn == NULL((void *)0)) |
194 | binddn = ""; |
195 | if (bindcred == NULL((void *)0)) |
196 | bindcred = ""; |
197 | |
198 | if ((root = ober_add_sequence(NULL((void *)0))) == NULL((void *)0)) |
199 | goto fail; |
200 | |
201 | elm = ober_printf_elements(root, "d{tdsst", ++ldap->msgid, BER_CLASS_APP0x1, |
202 | LDAP_REQ_BIND, VERSION3, binddn, bindcred, BER_CLASS_CONTEXT0x2, |
203 | LDAP_AUTH_SIMPLE); |
204 | if (elm == NULL((void *)0)) |
205 | goto fail; |
206 | |
207 | LDAP_DEBUG("aldap_bind", root)do { } while (0); |
208 | |
209 | if (aldap_send(ldap, root) == -1) { |
210 | root = NULL((void *)0); |
211 | goto fail; |
212 | } |
213 | return (ldap->msgid); |
214 | fail: |
215 | if (root != NULL((void *)0)) |
216 | ober_free_elements(root); |
217 | |
218 | ldap->err = ALDAP_ERR_OPERATION_FAILED3; |
219 | return (-1); |
220 | } |
221 | |
222 | int |
223 | aldap_unbind(struct aldap *ldap) |
224 | { |
225 | struct ber_element *root = NULL((void *)0), *elm; |
226 | |
227 | if ((root = ober_add_sequence(NULL((void *)0))) == NULL((void *)0)) |
228 | goto fail; |
229 | elm = ober_printf_elements(root, "d{t", ++ldap->msgid, BER_CLASS_APP0x1, |
230 | LDAP_REQ_UNBIND_30); |
231 | if (elm == NULL((void *)0)) |
232 | goto fail; |
233 | |
234 | LDAP_DEBUG("aldap_unbind", root)do { } while (0); |
235 | |
236 | if (aldap_send(ldap, root) == -1) { |
237 | root = NULL((void *)0); |
238 | goto fail; |
239 | } |
240 | return (ldap->msgid); |
241 | fail: |
242 | if (root != NULL((void *)0)) |
243 | ober_free_elements(root); |
244 | |
245 | ldap->err = ALDAP_ERR_OPERATION_FAILED3; |
246 | |
247 | return (-1); |
248 | } |
249 | |
250 | int |
251 | aldap_search(struct aldap *ldap, char *basedn, enum scope scope, char *filter, |
252 | char **attrs, int typesonly, int sizelimit, int timelimit, |
253 | struct aldap_page_control *page) |
254 | { |
255 | struct ber_element *root = NULL((void *)0), *ber, *c; |
256 | int i; |
257 | |
258 | if ((root = ober_add_sequence(NULL((void *)0))) == NULL((void *)0)) |
259 | goto fail; |
260 | |
261 | ber = ober_printf_elements(root, "d{t", ++ldap->msgid, BER_CLASS_APP0x1, |
262 | LDAP_REQ_SEARCH); |
263 | if (ber == NULL((void *)0)) { |
264 | ldap->err = ALDAP_ERR_OPERATION_FAILED3; |
265 | goto fail; |
266 | } |
267 | |
268 | c = ber; |
269 | ber = ober_printf_elements(ber, "sEEddb", basedn, (long long)scope, |
270 | (long long)LDAP_DEREF_NEVER, sizelimit, |
271 | timelimit, typesonly); |
272 | if (ber == NULL((void *)0)) { |
273 | ldap->err = ALDAP_ERR_OPERATION_FAILED3; |
274 | goto fail; |
275 | } |
276 | |
277 | if ((ber = ldap_parse_search_filter(ber, filter)) == NULL((void *)0)) { |
278 | ldap->err = ALDAP_ERR_PARSER_ERROR1; |
279 | goto fail; |
280 | } |
281 | |
282 | if ((ber = ober_add_sequence(ber)) == NULL((void *)0)) |
283 | goto fail; |
284 | if (attrs != NULL((void *)0)) |
285 | for (i = 0; attrs[i] != NULL((void *)0); i++) { |
286 | if ((ber = ober_add_string(ber, attrs[i])) == NULL((void *)0)) |
287 | goto fail; |
288 | } |
289 | |
290 | aldap_create_page_control(c, 100, page); |
291 | |
292 | LDAP_DEBUG("aldap_search", root)do { } while (0); |
293 | |
294 | if (aldap_send(ldap, root) == -1) { |
295 | root = NULL((void *)0); |
296 | ldap->err = ALDAP_ERR_OPERATION_FAILED3; |
297 | goto fail; |
298 | } |
299 | |
300 | return (ldap->msgid); |
301 | |
302 | fail: |
303 | if (root != NULL((void *)0)) |
304 | ober_free_elements(root); |
305 | |
306 | return (-1); |
307 | } |
308 | |
309 | int |
310 | aldap_create_page_control(struct ber_element *elm, int size, |
311 | struct aldap_page_control *page) |
312 | { |
313 | ssize_t len; |
314 | struct ber c; |
315 | struct ber_element *ber = NULL((void *)0); |
316 | |
317 | c.br_wbuf = NULL((void *)0); |
318 | |
319 | ber = ober_add_sequence(NULL((void *)0)); |
320 | |
321 | if (page == NULL((void *)0)) { |
322 | if (ober_printf_elements(ber, "ds", 50, "") == NULL((void *)0)) |
323 | goto fail; |
324 | } else { |
325 | if (ober_printf_elements(ber, "dx", 50, page->cookie, |
326 | page->cookie_len) == NULL((void *)0)) |
327 | goto fail; |
328 | } |
329 | |
330 | if ((len = ober_write_elements(&c, ber)) < 1) |
331 | goto fail; |
332 | if (ober_printf_elements(elm, "{t{sx", 2, 0, LDAP_PAGED_OID"1.2.840.113556.1.4.319", |
333 | c.br_wbuf, (size_t)len) == NULL((void *)0)) |
334 | goto fail; |
335 | |
336 | ober_free_elements(ber); |
337 | ober_free(&c); |
338 | return len; |
339 | fail: |
340 | if (ber != NULL((void *)0)) |
341 | ober_free_elements(ber); |
342 | ober_free(&c); |
343 | |
344 | return (-1); |
345 | } |
346 | |
347 | struct aldap_message * |
348 | aldap_parse(struct aldap *ldap) |
349 | { |
350 | int class; |
351 | unsigned int type; |
352 | long long msgid = 0; |
353 | struct aldap_message *m; |
354 | struct ber_element *a = NULL((void *)0), *ep; |
355 | char rbuf[512]; |
356 | int ret, retry; |
357 | |
358 | if ((m = calloc(1, sizeof(struct aldap_message))) == NULL((void *)0)) |
359 | return NULL((void *)0); |
360 | |
361 | retry = 0; |
362 | while (m->msg == NULL((void *)0)) { |
363 | if (retry || EVBUFFER_LENGTH(ldap->buf)(ldap->buf)->off == 0) { |
364 | if (ldap->tls) { |
365 | ret = tls_read(ldap->tls, rbuf, sizeof(rbuf)); |
366 | if (ret == TLS_WANT_POLLIN-2 || |
367 | ret == TLS_WANT_POLLOUT-3) |
368 | continue; |
369 | } else |
370 | ret = read(ldap->fd, rbuf, sizeof(rbuf)); |
371 | |
372 | if (ret == -1) { |
373 | goto parsefail; |
374 | } |
375 | |
376 | evbuffer_add(ldap->buf, rbuf, ret); |
377 | } |
378 | |
379 | if (EVBUFFER_LENGTH(ldap->buf)(ldap->buf)->off > 0) { |
380 | ober_set_readbuf(&ldap->ber, EVBUFFER_DATA(ldap->buf)(ldap->buf)->buffer, |
381 | EVBUFFER_LENGTH(ldap->buf)(ldap->buf)->off); |
382 | errno(*__errno()) = 0; |
383 | m->msg = ober_read_elements(&ldap->ber, NULL((void *)0)); |
384 | if (errno(*__errno()) != 0 && errno(*__errno()) != ECANCELED88) { |
385 | goto parsefail; |
386 | } |
387 | |
388 | retry = 1; |
389 | } |
390 | } |
391 | |
392 | evbuffer_drain(ldap->buf, ldap->ber.br_rptr - ldap->ber.br_rbuf); |
393 | |
394 | LDAP_DEBUG("message", m->msg)do { } while (0); |
395 | |
396 | if (ober_scanf_elements(m->msg, "{ite", &msgid, &class, &type, &a) != 0) |
397 | goto parsefail; |
398 | m->msgid = msgid; |
399 | m->message_type = type; |
400 | m->protocol_op = a; |
401 | |
402 | switch (m->message_type) { |
403 | case LDAP_RES_BIND: |
404 | case LDAP_RES_MODIFY: |
405 | case LDAP_RES_ADD: |
406 | case LDAP_RES_DELETE: |
407 | case LDAP_RES_MODRDN: |
408 | case LDAP_RES_COMPARE: |
409 | case LDAP_RES_SEARCH_RESULT: |
410 | if (ober_scanf_elements(m->protocol_op, "{EeSe", |
411 | &m->body.res.rescode, &m->dn, &m->body.res.diagmsg) != 0) |
412 | goto parsefail; |
413 | if (m->body.res.rescode == LDAP_REFERRAL) { |
414 | a = m->body.res.diagmsg->be_next; |
415 | if (ober_scanf_elements(a, "{e", &m->references) != 0) |
416 | goto parsefail; |
417 | } |
418 | if (m->msg->be_subbe_union.bv_sub) { |
419 | for (ep = m->msg->be_subbe_union.bv_sub; ep != NULL((void *)0); ep = ep->be_next) { |
420 | ober_scanf_elements(ep, "t", &class, &type); |
421 | if (class == 2 && type == 0) |
422 | m->page = aldap_parse_page_control(ep->be_subbe_union.bv_sub->be_subbe_union.bv_sub, |
423 | ep->be_subbe_union.bv_sub->be_subbe_union.bv_sub->be_len); |
424 | } |
425 | } else |
426 | m->page = NULL((void *)0); |
427 | break; |
428 | case LDAP_RES_SEARCH_ENTRY: |
429 | if (ober_scanf_elements(m->protocol_op, "{eS{e", &m->dn, |
430 | &m->body.search.attrs) != 0) |
431 | goto parsefail; |
432 | break; |
433 | case LDAP_RES_SEARCH_REFERENCE: |
434 | if (ober_scanf_elements(m->protocol_op, "{e", &m->references) != 0) |
435 | goto parsefail; |
436 | break; |
437 | case LDAP_RES_EXTENDED: |
438 | if (ober_scanf_elements(m->protocol_op, "{E", |
439 | &m->body.res.rescode) != 0) { |
440 | goto parsefail; |
441 | } |
442 | break; |
443 | } |
444 | |
445 | return m; |
446 | parsefail: |
447 | evbuffer_drain(ldap->buf, EVBUFFER_LENGTH(ldap->buf)(ldap->buf)->off); |
448 | ldap->err = ALDAP_ERR_PARSER_ERROR1; |
449 | aldap_freemsg(m); |
450 | return NULL((void *)0); |
451 | } |
452 | |
453 | struct aldap_page_control * |
454 | aldap_parse_page_control(struct ber_element *control, size_t len) |
455 | { |
456 | char *oid, *s; |
457 | char *encoded; |
458 | struct ber b; |
459 | struct ber_element *elm; |
460 | struct aldap_page_control *page; |
461 | |
462 | b.br_wbuf = NULL((void *)0); |
463 | ober_scanf_elements(control, "ss", &oid, &encoded); |
464 | ober_set_readbuf(&b, encoded, control->be_next->be_len); |
465 | elm = ober_read_elements(&b, NULL((void *)0)); |
466 | |
467 | if ((page = malloc(sizeof(struct aldap_page_control))) == NULL((void *)0)) { |
468 | if (elm != NULL((void *)0)) |
469 | ober_free_elements(elm); |
470 | ober_free(&b); |
471 | return NULL((void *)0); |
472 | } |
473 | |
474 | ober_scanf_elements(elm->be_subbe_union.bv_sub, "is", &page->size, &s); |
475 | page->cookie_len = elm->be_subbe_union.bv_sub->be_next->be_len; |
476 | |
477 | if ((page->cookie = malloc(page->cookie_len)) == NULL((void *)0)) { |
478 | if (elm != NULL((void *)0)) |
479 | ober_free_elements(elm); |
480 | ober_free(&b); |
481 | free(page); |
482 | return NULL((void *)0); |
483 | } |
484 | memcpy(page->cookie, s, page->cookie_len); |
485 | |
486 | ober_free_elements(elm); |
487 | ober_free(&b); |
488 | return page; |
489 | } |
490 | |
491 | void |
492 | aldap_freepage(struct aldap_page_control *page) |
493 | { |
494 | free(page->cookie); |
495 | free(page); |
496 | } |
497 | |
498 | void |
499 | aldap_freemsg(struct aldap_message *msg) |
500 | { |
501 | if (msg->msg) |
502 | ober_free_elements(msg->msg); |
503 | free(msg); |
504 | } |
505 | |
506 | int |
507 | aldap_get_resultcode(struct aldap_message *msg) |
508 | { |
509 | return msg->body.res.rescode; |
510 | } |
511 | |
512 | char * |
513 | aldap_get_dn(struct aldap_message *msg) |
514 | { |
515 | char *dn; |
516 | |
517 | if (msg->dn == NULL((void *)0)) |
518 | return NULL((void *)0); |
519 | |
520 | if (ober_get_string(msg->dn, &dn) == -1) |
521 | return NULL((void *)0); |
522 | |
523 | return utoa(dn); |
524 | } |
525 | |
526 | struct aldap_stringset * |
527 | aldap_get_references(struct aldap_message *msg) |
528 | { |
529 | if (msg->references == NULL((void *)0)) |
530 | return NULL((void *)0); |
531 | return aldap_get_stringset(msg->references); |
532 | } |
533 | |
534 | void |
535 | aldap_free_references(char **values) |
536 | { |
537 | int i; |
538 | |
539 | if (values == NULL((void *)0)) |
540 | return; |
541 | |
542 | for (i = 0; values[i] != NULL((void *)0); i++) |
543 | free(values[i]); |
544 | |
545 | free(values); |
546 | } |
547 | |
548 | char * |
549 | aldap_get_diagmsg(struct aldap_message *msg) |
550 | { |
551 | char *s; |
552 | |
553 | if (msg->body.res.diagmsg == NULL((void *)0)) |
554 | return NULL((void *)0); |
555 | |
556 | if (ober_get_string(msg->body.res.diagmsg, &s) == -1) |
557 | return NULL((void *)0); |
558 | |
559 | return utoa(s); |
560 | } |
561 | |
562 | int |
563 | aldap_count_attrs(struct aldap_message *msg) |
564 | { |
565 | int i; |
566 | struct ber_element *a; |
567 | |
568 | if (msg->body.search.attrs == NULL((void *)0)) |
569 | return (-1); |
570 | |
571 | for (i = 0, a = msg->body.search.attrs; |
572 | a != NULL((void *)0) && ober_get_eoc(a) != 0; |
573 | i++, a = a->be_next) |
574 | ; |
575 | |
576 | return i; |
577 | } |
578 | |
579 | int |
580 | aldap_first_attr(struct aldap_message *msg, char **outkey, |
581 | struct aldap_stringset **outvalues) |
582 | { |
583 | struct ber_element *b; |
584 | char *key; |
585 | struct aldap_stringset *ret; |
586 | |
587 | if (msg->body.search.attrs == NULL((void *)0)) |
588 | goto fail; |
589 | |
590 | if (ober_scanf_elements(msg->body.search.attrs, "{s(e)}", |
591 | &key, &b) != 0) |
592 | goto fail; |
593 | |
594 | msg->body.search.iter = msg->body.search.attrs->be_next; |
595 | |
596 | if ((ret = aldap_get_stringset(b)) == NULL((void *)0)) |
597 | goto fail; |
598 | |
599 | (*outvalues) = ret; |
600 | (*outkey) = utoa(key); |
601 | |
602 | return (1); |
603 | fail: |
604 | (*outkey) = NULL((void *)0); |
605 | (*outvalues) = NULL((void *)0); |
606 | return (-1); |
607 | } |
608 | |
609 | int |
610 | aldap_next_attr(struct aldap_message *msg, char **outkey, |
611 | struct aldap_stringset **outvalues) |
612 | { |
613 | struct ber_element *a; |
614 | char *key; |
615 | struct aldap_stringset *ret; |
616 | |
617 | if (msg->body.search.iter == NULL((void *)0)) |
618 | goto notfound; |
619 | |
620 | LDAP_DEBUG("attr", msg->body.search.iter)do { } while (0); |
621 | |
622 | if (ober_get_eoc(msg->body.search.iter) == 0) |
623 | goto notfound; |
624 | |
625 | if (ober_scanf_elements(msg->body.search.iter, "{s(e)}", &key, &a) != 0) |
626 | goto fail; |
627 | |
628 | msg->body.search.iter = msg->body.search.iter->be_next; |
629 | |
630 | if ((ret = aldap_get_stringset(a)) == NULL((void *)0)) |
631 | goto fail; |
632 | |
633 | (*outvalues) = ret; |
634 | (*outkey) = utoa(key); |
635 | |
636 | return (1); |
637 | fail: |
638 | notfound: |
639 | (*outkey) = NULL((void *)0); |
640 | (*outvalues) = NULL((void *)0); |
641 | return (-1); |
642 | } |
643 | |
644 | int |
645 | aldap_match_attr(struct aldap_message *msg, char *inkey, |
646 | struct aldap_stringset **outvalues) |
647 | { |
648 | struct ber_element *a, *b; |
649 | char *descr = NULL((void *)0); |
650 | struct aldap_stringset *ret; |
651 | |
652 | if (msg->body.search.attrs == NULL((void *)0)) |
653 | goto fail; |
654 | |
655 | LDAP_DEBUG("attr", msg->body.search.attrs)do { } while (0); |
656 | |
657 | for (a = msg->body.search.attrs;;) { |
658 | if (a == NULL((void *)0)) |
659 | goto notfound; |
660 | if (ober_get_eoc(a) == 0) |
661 | goto notfound; |
662 | if (ober_scanf_elements(a, "{s(e", &descr, &b) != 0) |
663 | goto fail; |
664 | if (strcasecmp(descr, inkey) == 0) |
665 | goto attrfound; |
666 | a = a->be_next; |
667 | } |
668 | |
669 | attrfound: |
670 | if ((ret = aldap_get_stringset(b)) == NULL((void *)0)) |
671 | goto fail; |
672 | |
673 | (*outvalues) = ret; |
674 | |
675 | return (1); |
676 | fail: |
677 | notfound: |
678 | (*outvalues) = NULL((void *)0); |
679 | return (-1); |
680 | } |
681 | |
682 | int |
683 | aldap_free_attr(struct aldap_stringset *values) |
684 | { |
685 | if (values == NULL((void *)0)) |
686 | return -1; |
687 | |
688 | free(values->str); |
689 | free(values); |
690 | |
691 | return (1); |
692 | } |
693 | |
694 | void |
695 | aldap_free_url(struct aldap_url *lu) |
696 | { |
697 | free(lu->buffer); |
698 | } |
699 | |
700 | int |
701 | aldap_parse_url(const char *url, struct aldap_url *lu) |
702 | { |
703 | char *p, *forward, *forward2; |
704 | const char *errstr = NULL((void *)0); |
705 | int i; |
706 | |
707 | if ((lu->buffer = p = strdup(url)) == NULL((void *)0)) |
708 | return (-1); |
709 | |
710 | /* protocol */ |
711 | if (strncasecmp(LDAP_URL"ldap://", p, strlen(LDAP_URL"ldap://")) == 0) { |
712 | lu->protocol = LDAP; |
713 | p += strlen(LDAP_URL"ldap://"); |
714 | } else if (strncasecmp(LDAPS_URL"ldaps://", p, strlen(LDAPS_URL"ldaps://")) == 0) { |
715 | lu->protocol = LDAPS; |
716 | p += strlen(LDAPS_URL"ldaps://"); |
717 | } else if (strncasecmp(LDAPTLS_URL"ldap+tls://", p, strlen(LDAPTLS_URL"ldap+tls://")) == 0) { |
718 | lu->protocol = LDAPTLS; |
719 | p += strlen(LDAPTLS_URL"ldap+tls://"); |
720 | } else if (strncasecmp(LDAPI_URL"ldapi://", p, strlen(LDAPI_URL"ldapi://")) == 0) { |
721 | lu->protocol = LDAPI; |
722 | p += strlen(LDAPI_URL"ldapi://"); |
723 | } else |
724 | lu->protocol = -1; |
725 | |
726 | /* host and optional port */ |
727 | if ((forward = strchr(p, '/')) != NULL((void *)0)) |
728 | *forward = '\0'; |
729 | /* find the optional port */ |
730 | if ((forward2 = strchr(p, ':')) != NULL((void *)0)) { |
731 | *forward2 = '\0'; |
732 | /* if a port is given */ |
733 | if (*(forward2+1) != '\0') { |
734 | #define PORT_MAX0xffff UINT16_MAX0xffff |
735 | lu->port = strtonum(++forward2, 0, PORT_MAX0xffff, &errstr); |
736 | if (errstr) |
737 | goto fail; |
738 | } |
739 | } |
740 | /* fail if no host is given */ |
741 | if (strlen(p) == 0) |
742 | goto fail; |
743 | lu->host = p; |
744 | if (forward == NULL((void *)0)) |
745 | goto done; |
746 | /* p is assigned either a pointer to a character or to '\0' */ |
747 | p = ++forward; |
748 | if (strlen(p) == 0) |
749 | goto done; |
750 | |
751 | /* dn */ |
752 | if ((forward = strchr(p, '?')) != NULL((void *)0)) |
753 | *forward = '\0'; |
754 | lu->dn = p; |
755 | if (forward == NULL((void *)0)) |
756 | goto done; |
757 | /* p is assigned either a pointer to a character or to '\0' */ |
758 | p = ++forward; |
759 | if (strlen(p) == 0) |
760 | goto done; |
761 | |
762 | /* attributes */ |
763 | if ((forward = strchr(p, '?')) != NULL((void *)0)) |
764 | *forward = '\0'; |
765 | for (i = 0; i < MAXATTR1024; i++) { |
766 | if ((forward2 = strchr(p, ',')) == NULL((void *)0)) { |
767 | if (strlen(p) == 0) |
768 | break; |
769 | lu->attributes[i] = p; |
770 | break; |
771 | } |
772 | *forward2 = '\0'; |
773 | lu->attributes[i] = p; |
774 | p = ++forward2; |
775 | } |
776 | if (forward == NULL((void *)0)) |
777 | goto done; |
778 | /* p is assigned either a pointer to a character or to '\0' */ |
779 | p = ++forward; |
780 | if (strlen(p) == 0) |
781 | goto done; |
782 | |
783 | /* scope */ |
784 | if ((forward = strchr(p, '?')) != NULL((void *)0)) |
785 | *forward = '\0'; |
786 | if (strcmp(p, "base") == 0) |
787 | lu->scope = LDAP_SCOPE_BASE; |
788 | else if (strcmp(p, "one") == 0) |
789 | lu->scope = LDAP_SCOPE_ONELEVEL; |
790 | else if (strcmp(p, "sub") == 0) |
791 | lu->scope = LDAP_SCOPE_SUBTREE; |
792 | else |
793 | goto fail; |
794 | if (forward == NULL((void *)0)) |
795 | goto done; |
796 | p = ++forward; |
797 | if (strlen(p) == 0) |
798 | goto done; |
799 | |
800 | /* filter */ |
801 | if (p) |
802 | lu->filter = p; |
803 | done: |
804 | return (1); |
805 | fail: |
806 | free(lu->buffer); |
807 | lu->buffer = NULL((void *)0); |
808 | return (-1); |
809 | } |
810 | |
811 | int |
812 | aldap_search_url(struct aldap *ldap, char *url, int typesonly, int sizelimit, |
813 | int timelimit, struct aldap_page_control *page) |
814 | { |
815 | struct aldap_url *lu; |
816 | |
817 | if ((lu = calloc(1, sizeof(*lu))) == NULL((void *)0)) |
818 | return (-1); |
819 | |
820 | if (aldap_parse_url(url, lu)) |
821 | goto fail; |
822 | |
823 | if (aldap_search(ldap, lu->dn, lu->scope, lu->filter, lu->attributes, |
824 | typesonly, sizelimit, timelimit, page) == -1) |
825 | goto fail; |
826 | |
827 | aldap_free_url(lu); |
828 | return (ldap->msgid); |
829 | fail: |
830 | aldap_free_url(lu); |
831 | return (-1); |
832 | } |
833 | |
834 | /* |
835 | * internal functions |
836 | */ |
837 | |
838 | struct aldap_stringset * |
839 | aldap_get_stringset(struct ber_element *elm) |
840 | { |
841 | struct ber_element *a; |
842 | int i; |
843 | struct aldap_stringset *ret; |
844 | |
845 | if (elm->be_type != BER_TYPE_OCTETSTRING4) |
846 | return NULL((void *)0); |
847 | |
848 | if ((ret = malloc(sizeof(*ret))) == NULL((void *)0)) |
849 | return NULL((void *)0); |
850 | for (a = elm, ret->len = 0; a != NULL((void *)0) && a->be_type == |
851 | BER_TYPE_OCTETSTRING4; a = a->be_next, ret->len++) |
852 | ; |
853 | if (ret->len == 0) { |
854 | free(ret); |
855 | return NULL((void *)0); |
856 | } |
857 | |
858 | if ((ret->str = reallocarray(NULL((void *)0), ret->len, |
859 | sizeof(*(ret->str)))) == NULL((void *)0)) { |
860 | free(ret); |
861 | return NULL((void *)0); |
862 | } |
863 | |
864 | for (a = elm, i = 0; a != NULL((void *)0) && a->be_type == BER_TYPE_OCTETSTRING4; |
865 | a = a->be_next, i++) |
866 | (void) ober_get_ostring(a, &(ret->str[i])); |
867 | |
868 | return ret; |
869 | } |
870 | |
871 | /* |
872 | * Base case for ldap_do_parse_search_filter |
873 | * |
874 | * returns: |
875 | * struct ber_element *, ber_element tree |
876 | * NULL, parse failed |
877 | */ |
878 | static struct ber_element * |
879 | ldap_parse_search_filter(struct ber_element *ber, char *filter) |
880 | { |
881 | struct ber_element *elm; |
882 | char *cp; |
883 | |
884 | cp = filter; |
885 | |
886 | if (cp == NULL((void *)0) || *cp == '\0') { |
887 | errno(*__errno()) = EINVAL22; |
888 | return (NULL((void *)0)); |
889 | } |
890 | |
891 | if ((elm = ldap_do_parse_search_filter(ber, &cp)) == NULL((void *)0)) |
892 | return (NULL((void *)0)); |
893 | |
894 | if (*cp != '\0') { |
895 | ober_free_elements(elm); |
896 | ober_link_elements(ber, NULL((void *)0)); |
897 | errno(*__errno()) = EINVAL22; |
898 | return (NULL((void *)0)); |
899 | } |
900 | |
901 | return (elm); |
902 | } |
903 | |
904 | /* |
905 | * Translate RFC4515 search filter string into ber_element tree |
906 | * |
907 | * returns: |
908 | * struct ber_element *, ber_element tree |
909 | * NULL, parse failed |
910 | * |
911 | * notes: |
912 | * when cp is passed to a recursive invocation, it is updated |
913 | * to point one character beyond the filter that was passed |
914 | * i.e., cp jumps to "(filter)" upon return |
915 | * ^ |
916 | * goto's used to discriminate error-handling based on error type |
917 | * doesn't handle extended filters (yet) |
918 | * |
919 | */ |
920 | static struct ber_element * |
921 | ldap_do_parse_search_filter(struct ber_element *prev, char **cpp) |
922 | { |
923 | struct ber_element *elm, *root = NULL((void *)0); |
924 | char *attr_desc, *attr_val, *parsed_val, *cp; |
925 | size_t len; |
926 | unsigned long type; |
927 | |
928 | root = NULL((void *)0); |
929 | |
930 | /* cpp should pass in pointer to opening parenthesis of "(filter)" */ |
931 | cp = *cpp; |
932 | if (*cp != '(') |
933 | goto syntaxfail; |
934 | |
935 | switch (*++cp) { |
936 | case '&': /* AND */ |
937 | case '|': /* OR */ |
938 | if (*cp == '&') |
939 | type = LDAP_FILT_AND; |
940 | else |
941 | type = LDAP_FILT_OR; |
942 | |
943 | if ((elm = ober_add_set(prev)) == NULL((void *)0)) |
944 | goto callfail; |
945 | root = elm; |
946 | ober_set_header(elm, BER_CLASS_CONTEXT0x2, type); |
947 | |
948 | if (*++cp != '(') /* opening `(` of filter */ |
949 | goto syntaxfail; |
950 | |
951 | while (*cp == '(') { |
952 | if ((elm = |
953 | ldap_do_parse_search_filter(elm, &cp)) == NULL((void *)0)) |
954 | goto bad; |
955 | } |
956 | |
957 | if (*cp != ')') /* trailing `)` of filter */ |
958 | goto syntaxfail; |
959 | break; |
960 | |
961 | case '!': /* NOT */ |
962 | if ((root = ober_add_sequence(prev)) == NULL((void *)0)) |
963 | goto callfail; |
964 | ober_set_header(root, BER_CLASS_CONTEXT0x2, LDAP_FILT_NOT); |
965 | |
966 | cp++; /* now points to sub-filter */ |
967 | if ((elm = ldap_do_parse_search_filter(root, &cp)) == NULL((void *)0)) |
Although the value stored to 'elm' is used in the enclosing expression, the value is never actually read from 'elm' | |
968 | goto bad; |
969 | |
970 | if (*cp != ')') /* trailing `)` of filter */ |
971 | goto syntaxfail; |
972 | break; |
973 | |
974 | default: /* SIMPLE || PRESENCE */ |
975 | attr_desc = cp; |
976 | |
977 | len = strcspn(cp, "()<>~="); |
978 | cp += len; |
979 | switch (*cp) { |
980 | case '~': |
981 | type = LDAP_FILT_APPR; |
982 | cp++; |
983 | break; |
984 | case '<': |
985 | type = LDAP_FILT_LE; |
986 | cp++; |
987 | break; |
988 | case '>': |
989 | type = LDAP_FILT_GE; |
990 | cp++; |
991 | break; |
992 | case '=': |
993 | type = LDAP_FILT_EQ; /* assume EQ until disproven */ |
994 | break; |
995 | case '(': |
996 | case ')': |
997 | default: |
998 | goto syntaxfail; |
999 | } |
1000 | attr_val = ++cp; |
1001 | |
1002 | /* presence filter */ |
1003 | if (strncmp(attr_val, "*)", 2) == 0) { |
1004 | cp++; /* point to trailing `)` */ |
1005 | if ((root = |
1006 | ober_add_nstring(prev, attr_desc, len)) == NULL((void *)0)) |
1007 | goto bad; |
1008 | |
1009 | ober_set_header(root, BER_CLASS_CONTEXT0x2, LDAP_FILT_PRES); |
1010 | break; |
1011 | } |
1012 | |
1013 | if ((root = ober_add_sequence(prev)) == NULL((void *)0)) |
1014 | goto callfail; |
1015 | ober_set_header(root, BER_CLASS_CONTEXT0x2, type); |
1016 | |
1017 | if ((elm = ober_add_nstring(root, attr_desc, len)) == NULL((void *)0)) |
1018 | goto callfail; |
1019 | |
1020 | len = strcspn(attr_val, "*)"); |
1021 | if (len == 0 && *cp != '*') |
1022 | goto syntaxfail; |
1023 | cp += len; |
1024 | if (*cp == '\0') |
1025 | goto syntaxfail; |
1026 | |
1027 | if (*cp == '*') { /* substring filter */ |
1028 | int initial; |
1029 | |
1030 | cp = attr_val; |
1031 | |
1032 | ober_set_header(root, BER_CLASS_CONTEXT0x2, LDAP_FILT_SUBS); |
1033 | |
1034 | if ((elm = ober_add_sequence(elm)) == NULL((void *)0)) |
1035 | goto callfail; |
1036 | |
1037 | for (initial = 1;; cp++, initial = 0) { |
1038 | attr_val = cp; |
1039 | |
1040 | len = strcspn(attr_val, "*)"); |
1041 | if (len == 0) { |
1042 | if (*cp == ')') |
1043 | break; |
1044 | else |
1045 | continue; |
1046 | } |
1047 | cp += len; |
1048 | if (*cp == '\0') |
1049 | goto syntaxfail; |
1050 | |
1051 | if (initial) |
1052 | type = LDAP_FILT_SUBS_INIT; |
1053 | else if (*cp == ')') |
1054 | type = LDAP_FILT_SUBS_FIN; |
1055 | else |
1056 | type = LDAP_FILT_SUBS_ANY; |
1057 | |
1058 | if ((parsed_val = parseval(attr_val, len)) == |
1059 | NULL((void *)0)) |
1060 | goto callfail; |
1061 | elm = ober_add_nstring(elm, parsed_val, |
1062 | strlen(parsed_val)); |
1063 | free(parsed_val); |
1064 | if (elm == NULL((void *)0)) |
1065 | goto callfail; |
1066 | ober_set_header(elm, BER_CLASS_CONTEXT0x2, type); |
1067 | if (type == LDAP_FILT_SUBS_FIN) |
1068 | break; |
1069 | } |
1070 | break; |
1071 | } |
1072 | |
1073 | if ((parsed_val = parseval(attr_val, len)) == NULL((void *)0)) |
1074 | goto callfail; |
1075 | elm = ober_add_nstring(elm, parsed_val, strlen(parsed_val)); |
1076 | free(parsed_val); |
1077 | if (elm == NULL((void *)0)) |
1078 | goto callfail; |
1079 | break; |
1080 | } |
1081 | |
1082 | cp++; /* now points one char beyond the trailing `)` */ |
1083 | |
1084 | *cpp = cp; |
1085 | return (root); |
1086 | |
1087 | syntaxfail: /* XXX -- error reporting */ |
1088 | callfail: |
1089 | bad: |
1090 | if (root != NULL((void *)0)) |
1091 | ober_free_elements(root); |
1092 | ober_link_elements(prev, NULL((void *)0)); |
1093 | return (NULL((void *)0)); |
1094 | } |
1095 | |
1096 | #ifdef DEBUG |
1097 | /* |
1098 | * Display a list of ber elements. |
1099 | * |
1100 | */ |
1101 | void |
1102 | ldap_debug_elements(struct ber_element *root) |
1103 | { |
1104 | static int indent = 0; |
1105 | long long v; |
1106 | int d; |
1107 | char *buf; |
1108 | size_t len; |
1109 | u_int i; |
1110 | int constructed; |
1111 | struct ber_oid o; |
1112 | |
1113 | /* calculate lengths */ |
1114 | ober_calc_len(root); |
1115 | |
1116 | switch (root->be_encoding) { |
1117 | case BER_TYPE_SEQUENCE16: |
1118 | case BER_TYPE_SET17: |
1119 | constructed = root->be_encoding; |
1120 | break; |
1121 | default: |
1122 | constructed = 0; |
1123 | break; |
1124 | } |
1125 | |
1126 | fprintf(stderr(&__sF[2]), "%*slen %lu ", indent, "", root->be_len); |
1127 | switch (root->be_class) { |
1128 | case BER_CLASS_UNIVERSAL0x0: |
1129 | fprintf(stderr(&__sF[2]), "class: universal(%u) type: ", root->be_class); |
1130 | switch (root->be_type) { |
1131 | case BER_TYPE_EOC0: |
1132 | fprintf(stderr(&__sF[2]), "end-of-content"); |
1133 | break; |
1134 | case BER_TYPE_BOOLEAN1: |
1135 | fprintf(stderr(&__sF[2]), "boolean"); |
1136 | break; |
1137 | case BER_TYPE_INTEGER2: |
1138 | fprintf(stderr(&__sF[2]), "integer"); |
1139 | break; |
1140 | case BER_TYPE_BITSTRING3: |
1141 | fprintf(stderr(&__sF[2]), "bit-string"); |
1142 | break; |
1143 | case BER_TYPE_OCTETSTRING4: |
1144 | fprintf(stderr(&__sF[2]), "octet-string"); |
1145 | break; |
1146 | case BER_TYPE_NULL5: |
1147 | fprintf(stderr(&__sF[2]), "null"); |
1148 | break; |
1149 | case BER_TYPE_OBJECT6: |
1150 | fprintf(stderr(&__sF[2]), "object"); |
1151 | break; |
1152 | case BER_TYPE_ENUMERATED10: |
1153 | fprintf(stderr(&__sF[2]), "enumerated"); |
1154 | break; |
1155 | case BER_TYPE_SEQUENCE16: |
1156 | fprintf(stderr(&__sF[2]), "sequence"); |
1157 | break; |
1158 | case BER_TYPE_SET17: |
1159 | fprintf(stderr(&__sF[2]), "set"); |
1160 | break; |
1161 | } |
1162 | break; |
1163 | case BER_CLASS_APPLICATION0x1: |
1164 | fprintf(stderr(&__sF[2]), "class: application(%u) type: ", |
1165 | root->be_class); |
1166 | switch (root->be_type) { |
1167 | case LDAP_REQ_BIND: |
1168 | fprintf(stderr(&__sF[2]), "bind"); |
1169 | break; |
1170 | case LDAP_RES_BIND: |
1171 | fprintf(stderr(&__sF[2]), "bind"); |
1172 | break; |
1173 | case LDAP_REQ_UNBIND_30: |
1174 | break; |
1175 | case LDAP_REQ_SEARCH: |
1176 | fprintf(stderr(&__sF[2]), "search"); |
1177 | break; |
1178 | case LDAP_RES_SEARCH_ENTRY: |
1179 | fprintf(stderr(&__sF[2]), "search_entry"); |
1180 | break; |
1181 | case LDAP_RES_SEARCH_RESULT: |
1182 | fprintf(stderr(&__sF[2]), "search_result"); |
1183 | break; |
1184 | case LDAP_REQ_MODIFY: |
1185 | fprintf(stderr(&__sF[2]), "modify"); |
1186 | break; |
1187 | case LDAP_RES_MODIFY: |
1188 | fprintf(stderr(&__sF[2]), "modify"); |
1189 | break; |
1190 | case LDAP_REQ_ADD: |
1191 | fprintf(stderr(&__sF[2]), "add"); |
1192 | break; |
1193 | case LDAP_RES_ADD: |
1194 | fprintf(stderr(&__sF[2]), "add"); |
1195 | break; |
1196 | case LDAP_REQ_DELETE_30: |
1197 | fprintf(stderr(&__sF[2]), "delete"); |
1198 | break; |
1199 | case LDAP_RES_DELETE: |
1200 | fprintf(stderr(&__sF[2]), "delete"); |
1201 | break; |
1202 | case LDAP_REQ_MODRDN: |
1203 | fprintf(stderr(&__sF[2]), "modrdn"); |
1204 | break; |
1205 | case LDAP_RES_MODRDN: |
1206 | fprintf(stderr(&__sF[2]), "modrdn"); |
1207 | break; |
1208 | case LDAP_REQ_COMPARE: |
1209 | fprintf(stderr(&__sF[2]), "compare"); |
1210 | break; |
1211 | case LDAP_RES_COMPARE: |
1212 | fprintf(stderr(&__sF[2]), "compare"); |
1213 | break; |
1214 | case LDAP_REQ_ABANDON_30: |
1215 | fprintf(stderr(&__sF[2]), "abandon"); |
1216 | break; |
1217 | } |
1218 | break; |
1219 | case BER_CLASS_PRIVATE0x3: |
1220 | fprintf(stderr(&__sF[2]), "class: private(%u) type: ", root->be_class); |
1221 | fprintf(stderr(&__sF[2]), "encoding (%u) type: ", root->be_encoding); |
1222 | break; |
1223 | case BER_CLASS_CONTEXT0x2: |
1224 | /* XXX: this is not correct */ |
1225 | fprintf(stderr(&__sF[2]), "class: context(%u) type: ", root->be_class); |
1226 | switch(root->be_type) { |
1227 | case LDAP_AUTH_SIMPLE: |
1228 | fprintf(stderr(&__sF[2]), "auth simple"); |
1229 | break; |
1230 | } |
1231 | break; |
1232 | default: |
1233 | fprintf(stderr(&__sF[2]), "class: <INVALID>(%u) type: ", root->be_class); |
1234 | break; |
1235 | } |
1236 | fprintf(stderr(&__sF[2]), "(%u) encoding %u ", |
1237 | root->be_type, root->be_encoding); |
1238 | |
1239 | if (constructed) |
1240 | root->be_encoding = constructed; |
1241 | |
1242 | switch (root->be_encoding) { |
1243 | case BER_TYPE_BOOLEAN1: |
1244 | if (ober_get_boolean(root, &d) == -1) { |
1245 | fprintf(stderr(&__sF[2]), "<INVALID>\n"); |
1246 | break; |
1247 | } |
1248 | fprintf(stderr(&__sF[2]), "%s(%d)\n", d ? "true" : "false", d); |
1249 | break; |
1250 | case BER_TYPE_INTEGER2: |
1251 | if (ober_get_integer(root, &v) == -1) { |
1252 | fprintf(stderr(&__sF[2]), "<INVALID>\n"); |
1253 | break; |
1254 | } |
1255 | fprintf(stderr(&__sF[2]), "value %lld\n", v); |
1256 | break; |
1257 | case BER_TYPE_ENUMERATED10: |
1258 | if (ober_get_enumerated(root, &v) == -1) { |
1259 | fprintf(stderr(&__sF[2]), "<INVALID>\n"); |
1260 | break; |
1261 | } |
1262 | fprintf(stderr(&__sF[2]), "value %lld\n", v); |
1263 | break; |
1264 | case BER_TYPE_BITSTRING3: |
1265 | if (ober_get_bitstring(root, (void *)&buf, &len) == -1) { |
1266 | fprintf(stderr(&__sF[2]), "<INVALID>\n"); |
1267 | break; |
1268 | } |
1269 | fprintf(stderr(&__sF[2]), "hexdump "); |
1270 | for (i = 0; i < len; i++) |
1271 | fprintf(stderr(&__sF[2]), "%02x", buf[i]); |
1272 | fprintf(stderr(&__sF[2]), "\n"); |
1273 | break; |
1274 | case BER_TYPE_OBJECT6: |
1275 | if (ober_get_oid(root, &o) == -1) { |
1276 | fprintf(stderr(&__sF[2]), "<INVALID>\n"); |
1277 | break; |
1278 | } |
1279 | fprintf(stderr(&__sF[2]), "\n"); |
1280 | break; |
1281 | case BER_TYPE_OCTETSTRING4: |
1282 | if (ober_get_nstring(root, (void *)&buf, &len) == -1) { |
1283 | fprintf(stderr(&__sF[2]), "<INVALID>\n"); |
1284 | break; |
1285 | } |
1286 | fprintf(stderr(&__sF[2]), "string \"%.*s\"\n", (int)len, buf); |
1287 | break; |
1288 | case BER_TYPE_NULL5: /* no payload */ |
1289 | case BER_TYPE_EOC0: |
1290 | case BER_TYPE_SEQUENCE16: |
1291 | case BER_TYPE_SET17: |
1292 | default: |
1293 | fprintf(stderr(&__sF[2]), "\n"); |
1294 | break; |
1295 | } |
1296 | |
1297 | if (constructed && root->be_subbe_union.bv_sub) { |
1298 | indent += 2; |
1299 | ldap_debug_elements(root->be_subbe_union.bv_sub); |
1300 | indent -= 2; |
1301 | } |
1302 | if (root->be_next) |
1303 | ldap_debug_elements(root->be_next); |
1304 | } |
1305 | #endif |
1306 | |
1307 | /* |
1308 | * Strip UTF-8 down to ASCII without validation. |
1309 | * notes: |
1310 | * non-ASCII characters are displayed as '?' |
1311 | * the argument u should be a NULL terminated sequence of UTF-8 bytes. |
1312 | */ |
1313 | char * |
1314 | utoa(char *u) |
1315 | { |
1316 | int len, i, j; |
1317 | char *str; |
1318 | |
1319 | /* calculate the length to allocate */ |
1320 | for (len = 0, i = 0; u[i] != '\0'; i++) |
1321 | if (!isu8cont(u[i])) |
1322 | len++; |
1323 | |
1324 | if ((str = calloc(len + 1, sizeof(char))) == NULL((void *)0)) |
1325 | return NULL((void *)0); |
1326 | |
1327 | /* copy the ASCII characters to the newly allocated string */ |
1328 | for (i = 0, j = 0; u[i] != '\0'; i++) |
1329 | if (!isu8cont(u[i])) |
1330 | str[j++] = isascii((unsigned char)u[i]) ? u[i] : '?'; |
1331 | |
1332 | return str; |
1333 | } |
1334 | |
1335 | static int |
1336 | isu8cont(unsigned char c) |
1337 | { |
1338 | return (c & (0x80 | 0x40)) == 0x80; |
1339 | } |
1340 | |
1341 | /* |
1342 | * Parse a LDAP value |
1343 | * notes: |
1344 | * the argument p should be a NUL-terminated sequence of ASCII bytes |
1345 | */ |
1346 | char * |
1347 | parseval(char *p, size_t len) |
1348 | { |
1349 | char hex[3]; |
1350 | char *buffer; |
1351 | size_t i, j; |
1352 | |
1353 | if ((buffer = calloc(1, len + 1)) == NULL((void *)0)) |
1354 | return NULL((void *)0); |
1355 | |
1356 | for (i = j = 0; j < len; i++) { |
1357 | if (p[j] == '\\') { |
1358 | strlcpy(hex, p + j + 1, sizeof(hex)); |
1359 | buffer[i] = (char)strtoumax(hex, NULL((void *)0), 16); |
1360 | j += 3; |
1361 | } else { |
1362 | buffer[i] = p[j]; |
1363 | j++; |
1364 | } |
1365 | } |
1366 | |
1367 | return buffer; |
1368 | } |
1369 | |
1370 | int |
1371 | aldap_get_errno(struct aldap *a, const char **estr) |
1372 | { |
1373 | switch (a->err) { |
1374 | case ALDAP_ERR_SUCCESS0: |
1375 | *estr = "success"; |
1376 | break; |
1377 | case ALDAP_ERR_PARSER_ERROR1: |
1378 | *estr = "parser failed"; |
1379 | break; |
1380 | case ALDAP_ERR_INVALID_FILTER2: |
1381 | *estr = "invalid filter"; |
1382 | break; |
1383 | case ALDAP_ERR_OPERATION_FAILED3: |
1384 | *estr = "operation failed"; |
1385 | break; |
1386 | case ALDAP_ERR_TLS_ERROR4: |
1387 | *estr = tls_error(a->tls); |
1388 | break; |
1389 | default: |
1390 | *estr = "unknown"; |
1391 | break; |
1392 | } |
1393 | return (a->err); |
1394 | } |