Annotation of src/usr.bin/ldap/aldap.c, Revision 1.8.2.1
1.8.2.1 ! tb 1: /* $OpenBSD: aldap.c,v 1.8 2019/09/10 14:35:32 martijn Exp $ */
1.1 reyk 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.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 VERSION 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 **);
1.6 martijn 41: struct aldap_stringset *aldap_get_stringset(struct ber_element *);
1.1 reyk 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 *);
1.3 claudio 49: unsigned int aldap_application(struct ber_element *);
1.1 reyk 50:
51: #ifdef DEBUG
52: void ldap_debug_elements(struct ber_element *);
53: #endif
54:
55: #ifdef DEBUG
56: #define DPRINTF(x...) printf(x)
57: #define LDAP_DEBUG(x, y) do { fprintf(stderr, "*** " x "\n"); ldap_debug_elements(y); } while (0)
58: #else
59: #define DPRINTF(x...) do { } while (0)
60: #define LDAP_DEBUG(x, y) do { } while (0)
61: #endif
62:
1.3 claudio 63: unsigned int
1.1 reyk 64: aldap_application(struct ber_element *elm)
65: {
66: return BER_TYPE_OCTETSTRING;
67: }
68:
69: int
70: aldap_close(struct aldap *al)
71: {
72: if (al->tls != NULL) {
73: tls_close(al->tls);
74: tls_free(al->tls);
75: }
76: close(al->fd);
1.8.2.1 ! tb 77: ober_free(&al->ber);
1.1 reyk 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)
90: return NULL;
91: a->buf = evbuffer_new();
92: a->fd = fd;
1.8.2.1 ! tb 93: ober_set_application(&a->ber, aldap_application);
1.1 reyk 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) {
103: ldap->err = ALDAP_ERR_OPERATION_FAILED;
104: return (-1);
105: }
106:
107: if (tls_configure(ldap->tls, cfg) == -1) {
108: ldap->err = ALDAP_ERR_TLS_ERROR;
109: return (-1);
110: }
111:
112: if (tls_connect_socket(ldap->tls, ldap->fd, name) == -1) {
113: ldap->err = ALDAP_ERR_TLS_ERROR;
114: return (-1);
115: }
116:
117: if (tls_handshake(ldap->tls) == -1) {
118: ldap->err = ALDAP_ERR_TLS_ERROR;
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;
1.5 rob 131: ssize_t error, wrote;
1.1 reyk 132:
1.8.2.1 ! tb 133: len = ober_calc_len(root);
! 134: error = ober_write_elements(&ldap->ber, root);
! 135: ober_free_elements(root);
1.1 reyk 136: if (error == -1)
137: return -1;
138:
1.8.2.1 ! tb 139: ober_get_writebuf(&ldap->ber, &ptr);
1.1 reyk 140: done = 0;
141: data = ptr;
142: while (len > 0) {
143: if (ldap->tls != NULL) {
144: wrote = tls_write(ldap->tls, data + done, len);
145: if (wrote == TLS_WANT_POLLIN ||
146: wrote == TLS_WANT_POLLOUT)
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, *ber;
165:
1.8.2.1 ! tb 166: if ((root = ober_add_sequence(NULL)) == NULL)
1.1 reyk 167: goto fail;
168:
1.8.2.1 ! tb 169: ber = ober_printf_elements(root, "d{tst", ++ldap->msgid, BER_CLASS_APP,
1.3 claudio 170: LDAP_REQ_EXTENDED, LDAP_STARTTLS_OID, BER_CLASS_CONTEXT, 0);
1.1 reyk 171: if (ber == NULL) {
172: ldap->err = ALDAP_ERR_OPERATION_FAILED;
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)
1.8.2.1 ! tb 182: ober_free_elements(root);
1.1 reyk 183:
184: ldap->err = ALDAP_ERR_OPERATION_FAILED;
185: return (-1);
186: }
187:
188: int
189: aldap_bind(struct aldap *ldap, char *binddn, char *bindcred)
190: {
191: struct ber_element *root = NULL, *elm;
192:
193: if (binddn == NULL)
194: binddn = "";
195: if (bindcred == NULL)
196: bindcred = "";
197:
1.8.2.1 ! tb 198: if ((root = ober_add_sequence(NULL)) == NULL)
1.1 reyk 199: goto fail;
200:
1.8.2.1 ! tb 201: elm = ober_printf_elements(root, "d{tdsst", ++ldap->msgid, BER_CLASS_APP,
1.3 claudio 202: LDAP_REQ_BIND, VERSION, binddn, bindcred, BER_CLASS_CONTEXT,
203: LDAP_AUTH_SIMPLE);
1.1 reyk 204: if (elm == NULL)
205: goto fail;
206:
207: LDAP_DEBUG("aldap_bind", root);
208:
209: if (aldap_send(ldap, root) == -1) {
210: root = NULL;
211: goto fail;
212: }
213: return (ldap->msgid);
214: fail:
215: if (root != NULL)
1.8.2.1 ! tb 216: ober_free_elements(root);
1.1 reyk 217:
218: ldap->err = ALDAP_ERR_OPERATION_FAILED;
219: return (-1);
220: }
221:
222: int
223: aldap_unbind(struct aldap *ldap)
224: {
225: struct ber_element *root = NULL, *elm;
226:
1.8.2.1 ! tb 227: if ((root = ober_add_sequence(NULL)) == NULL)
1.1 reyk 228: goto fail;
1.8.2.1 ! tb 229: elm = ober_printf_elements(root, "d{t", ++ldap->msgid, BER_CLASS_APP,
1.1 reyk 230: LDAP_REQ_UNBIND_30);
231: if (elm == NULL)
232: goto fail;
233:
234: LDAP_DEBUG("aldap_unbind", root);
235:
236: if (aldap_send(ldap, root) == -1) {
237: root = NULL;
238: goto fail;
239: }
240: return (ldap->msgid);
241: fail:
242: if (root != NULL)
1.8.2.1 ! tb 243: ober_free_elements(root);
1.1 reyk 244:
245: ldap->err = ALDAP_ERR_OPERATION_FAILED;
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, *ber, *c;
256: int i;
257:
1.8.2.1 ! tb 258: if ((root = ober_add_sequence(NULL)) == NULL)
1.1 reyk 259: goto fail;
260:
1.8.2.1 ! tb 261: ber = ober_printf_elements(root, "d{t", ++ldap->msgid, BER_CLASS_APP,
1.3 claudio 262: LDAP_REQ_SEARCH);
1.1 reyk 263: if (ber == NULL) {
264: ldap->err = ALDAP_ERR_OPERATION_FAILED;
265: goto fail;
266: }
267:
268: c = ber;
1.8.2.1 ! tb 269: ber = ober_printf_elements(ber, "sEEddb", basedn, (long long)scope,
1.1 reyk 270: (long long)LDAP_DEREF_NEVER, sizelimit,
271: timelimit, typesonly);
272: if (ber == NULL) {
273: ldap->err = ALDAP_ERR_OPERATION_FAILED;
274: goto fail;
275: }
276:
277: if ((ber = ldap_parse_search_filter(ber, filter)) == NULL) {
278: ldap->err = ALDAP_ERR_PARSER_ERROR;
279: goto fail;
280: }
281:
1.8.2.1 ! tb 282: if ((ber = ober_add_sequence(ber)) == NULL)
1.1 reyk 283: goto fail;
284: if (attrs != NULL)
285: for (i = 0; attrs[i] != NULL; i++) {
1.8.2.1 ! tb 286: if ((ber = ober_add_string(ber, attrs[i])) == NULL)
1.1 reyk 287: goto fail;
288: }
289:
290: aldap_create_page_control(c, 100, page);
291:
292: LDAP_DEBUG("aldap_search", root);
293:
294: if (aldap_send(ldap, root) == -1) {
295: root = NULL;
296: ldap->err = ALDAP_ERR_OPERATION_FAILED;
297: goto fail;
298: }
299:
300: return (ldap->msgid);
301:
302: fail:
303: if (root != NULL)
1.8.2.1 ! tb 304: ober_free_elements(root);
1.1 reyk 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: {
1.5 rob 313: ssize_t len;
1.1 reyk 314: struct ber c;
315: struct ber_element *ber = NULL;
316:
317: c.br_wbuf = NULL;
318:
1.8.2.1 ! tb 319: ber = ober_add_sequence(NULL);
1.1 reyk 320:
321: if (page == NULL) {
1.8.2.1 ! tb 322: if (ober_printf_elements(ber, "ds", 50, "") == NULL)
1.1 reyk 323: goto fail;
324: } else {
1.8.2.1 ! tb 325: if (ober_printf_elements(ber, "dx", 50, page->cookie,
1.1 reyk 326: page->cookie_len) == NULL)
327: goto fail;
328: }
329:
1.8.2.1 ! tb 330: if ((len = ober_write_elements(&c, ber)) < 1)
1.1 reyk 331: goto fail;
1.8.2.1 ! tb 332: if (ober_printf_elements(elm, "{t{sx", 2, 0, LDAP_PAGED_OID,
1.1 reyk 333: c.br_wbuf, (size_t)len) == NULL)
334: goto fail;
335:
1.8.2.1 ! tb 336: ober_free_elements(ber);
! 337: ober_free(&c);
1.1 reyk 338: return len;
339: fail:
340: if (ber != NULL)
1.8.2.1 ! tb 341: ober_free_elements(ber);
! 342: ober_free(&c);
1.1 reyk 343:
344: return (-1);
345: }
346:
347: struct aldap_message *
348: aldap_parse(struct aldap *ldap)
349: {
350: int class;
1.3 claudio 351: unsigned int type;
1.1 reyk 352: long long msgid = 0;
353: struct aldap_message *m;
354: struct ber_element *a = NULL, *ep;
355: char rbuf[512];
356: int ret, retry;
357:
358: if ((m = calloc(1, sizeof(struct aldap_message))) == NULL)
359: return NULL;
360:
361: retry = 0;
362: while (m->msg == NULL) {
363: if (retry || EVBUFFER_LENGTH(ldap->buf) == 0) {
364: if (ldap->tls) {
365: ret = tls_read(ldap->tls, rbuf, sizeof(rbuf));
366: if (ret == TLS_WANT_POLLIN ||
367: ret == TLS_WANT_POLLOUT)
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) > 0) {
1.8.2.1 ! tb 380: ober_set_readbuf(&ldap->ber, EVBUFFER_DATA(ldap->buf),
1.1 reyk 381: EVBUFFER_LENGTH(ldap->buf));
382: errno = 0;
1.8.2.1 ! tb 383: m->msg = ober_read_elements(&ldap->ber, NULL);
1.1 reyk 384: if (errno != 0 && errno != ECANCELED) {
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);
395:
1.8.2.1 ! tb 396: if (ober_scanf_elements(m->msg, "{ite", &msgid, &class, &type, &a) != 0)
1.1 reyk 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:
1.8.2.1 ! tb 410: if (ober_scanf_elements(m->protocol_op, "{EeSe",
1.8 martijn 411: &m->body.res.rescode, &m->dn, &m->body.res.diagmsg) != 0)
1.1 reyk 412: goto parsefail;
1.8 martijn 413: if (m->body.res.rescode == LDAP_REFERRAL) {
414: a = m->body.res.diagmsg->be_next;
1.8.2.1 ! tb 415: if (ober_scanf_elements(a, "{e", &m->references) != 0)
1.1 reyk 416: goto parsefail;
1.8 martijn 417: }
1.1 reyk 418: if (m->msg->be_sub) {
419: for (ep = m->msg->be_sub; ep != NULL; ep = ep->be_next) {
1.8.2.1 ! tb 420: ober_scanf_elements(ep, "t", &class, &type);
1.1 reyk 421: if (class == 2 && type == 0)
422: m->page = aldap_parse_page_control(ep->be_sub->be_sub,
423: ep->be_sub->be_sub->be_len);
424: }
425: } else
426: m->page = NULL;
427: break;
428: case LDAP_RES_SEARCH_ENTRY:
1.8.2.1 ! tb 429: if (ober_scanf_elements(m->protocol_op, "{eS{e", &m->dn,
1.1 reyk 430: &m->body.search.attrs) != 0)
431: goto parsefail;
432: break;
433: case LDAP_RES_SEARCH_REFERENCE:
1.8.2.1 ! tb 434: if (ober_scanf_elements(m->protocol_op, "{e", &m->references) != 0)
1.1 reyk 435: goto parsefail;
436: break;
437: case LDAP_RES_EXTENDED:
1.8.2.1 ! tb 438: if (ober_scanf_elements(m->protocol_op, "{E",
1.1 reyk 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));
448: ldap->err = ALDAP_ERR_PARSER_ERROR;
449: aldap_freemsg(m);
450: return NULL;
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;
1.8.2.1 ! tb 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);
1.1 reyk 466:
467: if ((page = malloc(sizeof(struct aldap_page_control))) == NULL) {
468: if (elm != NULL)
1.8.2.1 ! tb 469: ober_free_elements(elm);
! 470: ober_free(&b);
1.1 reyk 471: return NULL;
472: }
473:
1.8.2.1 ! tb 474: ober_scanf_elements(elm->be_sub, "is", &page->size, &s);
1.1 reyk 475: page->cookie_len = elm->be_sub->be_next->be_len;
476:
477: if ((page->cookie = malloc(page->cookie_len)) == NULL) {
478: if (elm != NULL)
1.8.2.1 ! tb 479: ober_free_elements(elm);
! 480: ober_free(&b);
1.1 reyk 481: free(page);
482: return NULL;
483: }
484: memcpy(page->cookie, s, page->cookie_len);
485:
1.8.2.1 ! tb 486: ober_free_elements(elm);
! 487: ober_free(&b);
1.1 reyk 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)
1.8.2.1 ! tb 502: ober_free_elements(msg->msg);
1.1 reyk 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)
518: return NULL;
519:
1.8.2.1 ! tb 520: if (ober_get_string(msg->dn, &dn) == -1)
1.1 reyk 521: return NULL;
522:
523: return utoa(dn);
524: }
525:
1.6 martijn 526: struct aldap_stringset *
1.1 reyk 527: aldap_get_references(struct aldap_message *msg)
528: {
529: if (msg->references == NULL)
530: return NULL;
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)
540: return;
541:
542: for (i = 0; values[i] != NULL; 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)
554: return NULL;
555:
1.8.2.1 ! tb 556: if (ober_get_string(msg->body.res.diagmsg, &s) == -1)
1.1 reyk 557: return NULL;
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)
569: return (-1);
570:
571: for (i = 0, a = msg->body.search.attrs;
1.8.2.1 ! tb 572: a != NULL && ober_get_eoc(a) != 0;
1.1 reyk 573: i++, a = a->be_next)
574: ;
575:
576: return i;
577: }
578:
579: int
1.6 martijn 580: aldap_first_attr(struct aldap_message *msg, char **outkey,
581: struct aldap_stringset **outvalues)
1.1 reyk 582: {
583: struct ber_element *b, *c;
584: char *key;
1.6 martijn 585: struct aldap_stringset *ret;
1.1 reyk 586:
587: if (msg->body.search.attrs == NULL)
588: goto fail;
589:
1.8.2.1 ! tb 590: if (ober_scanf_elements(msg->body.search.attrs, "{s(e)}e",
1.1 reyk 591: &key, &b, &c) != 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)
597: goto fail;
598:
599: (*outvalues) = ret;
600: (*outkey) = utoa(key);
601:
602: return (1);
603: fail:
604: (*outkey) = NULL;
605: (*outvalues) = NULL;
606: return (-1);
607: }
608:
609: int
1.6 martijn 610: aldap_next_attr(struct aldap_message *msg, char **outkey,
611: struct aldap_stringset **outvalues)
1.1 reyk 612: {
613: struct ber_element *a, *b;
614: char *key;
1.6 martijn 615: struct aldap_stringset *ret;
1.1 reyk 616:
617: if (msg->body.search.iter == NULL)
618: goto notfound;
619:
620: LDAP_DEBUG("attr", msg->body.search.iter);
621:
1.8.2.1 ! tb 622: if (ober_get_eoc(msg->body.search.iter) == 0)
1.1 reyk 623: goto notfound;
624:
1.8.2.1 ! tb 625: if (ober_scanf_elements(msg->body.search.iter, "{s(e)}e", &key, &a, &b)
1.1 reyk 626: != 0)
627: goto fail;
628:
629: msg->body.search.iter = msg->body.search.iter->be_next;
630:
631: if ((ret = aldap_get_stringset(a)) == NULL)
632: goto fail;
633:
634: (*outvalues) = ret;
635: (*outkey) = utoa(key);
636:
637: return (1);
638: fail:
639: notfound:
640: (*outkey) = NULL;
641: (*outvalues) = NULL;
642: return (-1);
643: }
644:
645: int
1.6 martijn 646: aldap_match_attr(struct aldap_message *msg, char *inkey,
647: struct aldap_stringset **outvalues)
1.1 reyk 648: {
649: struct ber_element *a, *b;
650: char *descr = NULL;
1.6 martijn 651: struct aldap_stringset *ret;
1.1 reyk 652:
653: if (msg->body.search.attrs == NULL)
654: goto fail;
655:
656: LDAP_DEBUG("attr", msg->body.search.attrs);
657:
658: for (a = msg->body.search.attrs;;) {
659: if (a == NULL)
660: goto notfound;
1.8.2.1 ! tb 661: if (ober_get_eoc(a) == 0)
1.1 reyk 662: goto notfound;
1.8.2.1 ! tb 663: if (ober_scanf_elements(a, "{s(e", &descr, &b) != 0)
1.1 reyk 664: goto fail;
665: if (strcasecmp(descr, inkey) == 0)
666: goto attrfound;
667: a = a->be_next;
668: }
669:
670: attrfound:
671: if ((ret = aldap_get_stringset(b)) == NULL)
672: goto fail;
673:
674: (*outvalues) = ret;
675:
676: return (1);
677: fail:
678: notfound:
679: (*outvalues) = NULL;
680: return (-1);
681: }
682:
683: int
1.6 martijn 684: aldap_free_attr(struct aldap_stringset *values)
1.1 reyk 685: {
686: if (values == NULL)
687: return -1;
688:
1.6 martijn 689: free(values->str);
1.1 reyk 690: free(values);
691:
692: return (1);
693: }
694:
695: void
696: aldap_free_url(struct aldap_url *lu)
697: {
698: free(lu->buffer);
699: }
700:
701: int
702: aldap_parse_url(const char *url, struct aldap_url *lu)
703: {
704: char *p, *forward, *forward2;
705: const char *errstr = NULL;
706: int i;
707:
708: if ((lu->buffer = p = strdup(url)) == NULL)
709: return (-1);
710:
711: /* protocol */
712: if (strncasecmp(LDAP_URL, p, strlen(LDAP_URL)) == 0) {
713: lu->protocol = LDAP;
714: p += strlen(LDAP_URL);
715: } else if (strncasecmp(LDAPS_URL, p, strlen(LDAPS_URL)) == 0) {
716: lu->protocol = LDAPS;
717: p += strlen(LDAPS_URL);
718: } else if (strncasecmp(LDAPTLS_URL, p, strlen(LDAPTLS_URL)) == 0) {
719: lu->protocol = LDAPTLS;
720: p += strlen(LDAPTLS_URL);
721: } else if (strncasecmp(LDAPI_URL, p, strlen(LDAPI_URL)) == 0) {
722: lu->protocol = LDAPI;
723: p += strlen(LDAPI_URL);
724: } else
725: lu->protocol = -1;
726:
727: /* host and optional port */
728: if ((forward = strchr(p, '/')) != NULL)
729: *forward = '\0';
730: /* find the optional port */
731: if ((forward2 = strchr(p, ':')) != NULL) {
732: *forward2 = '\0';
733: /* if a port is given */
734: if (*(forward2+1) != '\0') {
735: #define PORT_MAX UINT16_MAX
736: lu->port = strtonum(++forward2, 0, PORT_MAX, &errstr);
737: if (errstr)
738: goto fail;
739: }
740: }
741: /* fail if no host is given */
742: if (strlen(p) == 0)
743: goto fail;
744: lu->host = p;
745: if (forward == NULL)
746: goto done;
747: /* p is assigned either a pointer to a character or to '\0' */
748: p = ++forward;
749: if (strlen(p) == 0)
750: goto done;
751:
752: /* dn */
753: if ((forward = strchr(p, '?')) != NULL)
754: *forward = '\0';
755: lu->dn = p;
756: if (forward == NULL)
757: goto done;
758: /* p is assigned either a pointer to a character or to '\0' */
759: p = ++forward;
760: if (strlen(p) == 0)
761: goto done;
762:
763: /* attributes */
764: if ((forward = strchr(p, '?')) != NULL)
765: *forward = '\0';
766: for (i = 0; i < MAXATTR; i++) {
767: if ((forward2 = strchr(p, ',')) == NULL) {
768: if (strlen(p) == 0)
769: break;
770: lu->attributes[i] = p;
771: break;
772: }
773: *forward2 = '\0';
774: lu->attributes[i] = p;
775: p = ++forward2;
776: }
777: if (forward == NULL)
778: goto done;
779: /* p is assigned either a pointer to a character or to '\0' */
780: p = ++forward;
781: if (strlen(p) == 0)
782: goto done;
783:
784: /* scope */
785: if ((forward = strchr(p, '?')) != NULL)
786: *forward = '\0';
787: if (strcmp(p, "base") == 0)
788: lu->scope = LDAP_SCOPE_BASE;
789: else if (strcmp(p, "one") == 0)
790: lu->scope = LDAP_SCOPE_ONELEVEL;
791: else if (strcmp(p, "sub") == 0)
792: lu->scope = LDAP_SCOPE_SUBTREE;
793: else
794: goto fail;
795: if (forward == NULL)
796: goto done;
797: p = ++forward;
798: if (strlen(p) == 0)
799: goto done;
800:
801: /* filter */
802: if (p)
803: lu->filter = p;
804: done:
805: return (1);
806: fail:
807: free(lu->buffer);
808: lu->buffer = NULL;
809: return (-1);
810: }
811:
812: int
813: aldap_search_url(struct aldap *ldap, char *url, int typesonly, int sizelimit,
814: int timelimit, struct aldap_page_control *page)
815: {
816: struct aldap_url *lu;
817:
818: if ((lu = calloc(1, sizeof(*lu))) == NULL)
819: return (-1);
820:
821: if (aldap_parse_url(url, lu))
822: goto fail;
823:
824: if (aldap_search(ldap, lu->dn, lu->scope, lu->filter, lu->attributes,
825: typesonly, sizelimit, timelimit, page) == -1)
826: goto fail;
827:
828: aldap_free_url(lu);
829: return (ldap->msgid);
830: fail:
831: aldap_free_url(lu);
832: return (-1);
833: }
834:
835: /*
836: * internal functions
837: */
838:
1.6 martijn 839: struct aldap_stringset *
1.1 reyk 840: aldap_get_stringset(struct ber_element *elm)
841: {
842: struct ber_element *a;
843: int i;
1.6 martijn 844: struct aldap_stringset *ret;
1.1 reyk 845:
846: if (elm->be_type != BER_TYPE_OCTETSTRING)
847: return NULL;
848:
1.6 martijn 849: if ((ret = malloc(sizeof(*ret))) == NULL)
850: return NULL;
851: for (a = elm, ret->len = 0; a != NULL && a->be_type ==
852: BER_TYPE_OCTETSTRING; a = a->be_next, ret->len++)
1.1 reyk 853: ;
1.6 martijn 854: if (ret->len == 0) {
855: free(ret);
1.1 reyk 856: return NULL;
1.6 martijn 857: }
1.1 reyk 858:
1.6 martijn 859: if ((ret->str = reallocarray(NULL, ret->len,
860: sizeof(*(ret->str)))) == NULL) {
861: free(ret);
1.1 reyk 862: return NULL;
1.6 martijn 863: }
1.1 reyk 864:
865: for (a = elm, i = 0; a != NULL && a->be_type == BER_TYPE_OCTETSTRING;
1.6 martijn 866: a = a->be_next, i++)
1.8.2.1 ! tb 867: (void) ober_get_ostring(a, &(ret->str[i]));
1.1 reyk 868:
869: return ret;
870: }
871:
872: /*
873: * Base case for ldap_do_parse_search_filter
874: *
875: * returns:
876: * struct ber_element *, ber_element tree
877: * NULL, parse failed
878: */
879: static struct ber_element *
880: ldap_parse_search_filter(struct ber_element *ber, char *filter)
881: {
882: struct ber_element *elm;
883: char *cp;
884:
885: cp = filter;
886:
887: if (cp == NULL || *cp == '\0') {
888: errno = EINVAL;
889: return (NULL);
890: }
891:
892: if ((elm = ldap_do_parse_search_filter(ber, &cp)) == NULL)
893: return (NULL);
894:
895: if (*cp != '\0') {
1.8.2.1 ! tb 896: ober_free_elements(elm);
! 897: ober_link_elements(ber, NULL);
1.1 reyk 898: errno = EINVAL;
899: return (NULL);
900: }
901:
902: return (elm);
903: }
904:
905: /*
906: * Translate RFC4515 search filter string into ber_element tree
907: *
908: * returns:
909: * struct ber_element *, ber_element tree
910: * NULL, parse failed
911: *
912: * notes:
913: * when cp is passed to a recursive invocation, it is updated
914: * to point one character beyond the filter that was passed
915: * i.e., cp jumps to "(filter)" upon return
916: * ^
917: * goto's used to discriminate error-handling based on error type
918: * doesn't handle extended filters (yet)
919: *
920: */
921: static struct ber_element *
922: ldap_do_parse_search_filter(struct ber_element *prev, char **cpp)
923: {
924: struct ber_element *elm, *root = NULL;
925: char *attr_desc, *attr_val, *parsed_val, *cp;
926: size_t len;
927: unsigned long type;
928:
929: root = NULL;
930:
931: /* cpp should pass in pointer to opening parenthesis of "(filter)" */
932: cp = *cpp;
933: if (*cp != '(')
934: goto syntaxfail;
935:
936: switch (*++cp) {
937: case '&': /* AND */
938: case '|': /* OR */
939: if (*cp == '&')
940: type = LDAP_FILT_AND;
941: else
942: type = LDAP_FILT_OR;
943:
1.8.2.1 ! tb 944: if ((elm = ober_add_set(prev)) == NULL)
1.1 reyk 945: goto callfail;
946: root = elm;
1.8.2.1 ! tb 947: ober_set_header(elm, BER_CLASS_CONTEXT, type);
1.1 reyk 948:
949: if (*++cp != '(') /* opening `(` of filter */
950: goto syntaxfail;
951:
952: while (*cp == '(') {
953: if ((elm =
954: ldap_do_parse_search_filter(elm, &cp)) == NULL)
955: goto bad;
956: }
957:
958: if (*cp != ')') /* trailing `)` of filter */
959: goto syntaxfail;
960: break;
961:
962: case '!': /* NOT */
1.8.2.1 ! tb 963: if ((root = ober_add_sequence(prev)) == NULL)
1.1 reyk 964: goto callfail;
1.8.2.1 ! tb 965: ober_set_header(root, BER_CLASS_CONTEXT, LDAP_FILT_NOT);
1.1 reyk 966:
967: cp++; /* now points to sub-filter */
968: if ((elm = ldap_do_parse_search_filter(root, &cp)) == NULL)
969: goto bad;
970:
971: if (*cp != ')') /* trailing `)` of filter */
972: goto syntaxfail;
973: break;
974:
975: default: /* SIMPLE || PRESENCE */
976: attr_desc = cp;
977:
978: len = strcspn(cp, "()<>~=");
979: cp += len;
980: switch (*cp) {
981: case '~':
982: type = LDAP_FILT_APPR;
983: cp++;
984: break;
985: case '<':
986: type = LDAP_FILT_LE;
987: cp++;
988: break;
989: case '>':
990: type = LDAP_FILT_GE;
991: cp++;
992: break;
993: case '=':
994: type = LDAP_FILT_EQ; /* assume EQ until disproven */
995: break;
996: case '(':
997: case ')':
998: default:
999: goto syntaxfail;
1000: }
1001: attr_val = ++cp;
1002:
1003: /* presence filter */
1004: if (strncmp(attr_val, "*)", 2) == 0) {
1005: cp++; /* point to trailing `)` */
1006: if ((root =
1.8.2.1 ! tb 1007: ober_add_nstring(prev, attr_desc, len)) == NULL)
1.1 reyk 1008: goto bad;
1009:
1.8.2.1 ! tb 1010: ober_set_header(root, BER_CLASS_CONTEXT, LDAP_FILT_PRES);
1.1 reyk 1011: break;
1012: }
1013:
1.8.2.1 ! tb 1014: if ((root = ober_add_sequence(prev)) == NULL)
1.1 reyk 1015: goto callfail;
1.8.2.1 ! tb 1016: ober_set_header(root, BER_CLASS_CONTEXT, type);
1.1 reyk 1017:
1.8.2.1 ! tb 1018: if ((elm = ober_add_nstring(root, attr_desc, len)) == NULL)
1.1 reyk 1019: goto callfail;
1020:
1021: len = strcspn(attr_val, "*)");
1022: if (len == 0 && *cp != '*')
1023: goto syntaxfail;
1024: cp += len;
1025: if (*cp == '\0')
1026: goto syntaxfail;
1027:
1028: if (*cp == '*') { /* substring filter */
1029: int initial;
1030:
1031: cp = attr_val;
1032:
1.8.2.1 ! tb 1033: ober_set_header(root, BER_CLASS_CONTEXT, LDAP_FILT_SUBS);
1.1 reyk 1034:
1.8.2.1 ! tb 1035: if ((elm = ober_add_sequence(elm)) == NULL)
1.1 reyk 1036: goto callfail;
1037:
1038: for (initial = 1;; cp++, initial = 0) {
1039: attr_val = cp;
1040:
1041: len = strcspn(attr_val, "*)");
1042: if (len == 0) {
1043: if (*cp == ')')
1044: break;
1045: else
1046: continue;
1047: }
1048: cp += len;
1049: if (*cp == '\0')
1050: goto syntaxfail;
1051:
1052: if (initial)
1053: type = LDAP_FILT_SUBS_INIT;
1054: else if (*cp == ')')
1055: type = LDAP_FILT_SUBS_FIN;
1056: else
1057: type = LDAP_FILT_SUBS_ANY;
1058:
1059: if ((parsed_val = parseval(attr_val, len)) ==
1060: NULL)
1061: goto callfail;
1.8.2.1 ! tb 1062: elm = ober_add_nstring(elm, parsed_val,
1.1 reyk 1063: strlen(parsed_val));
1064: free(parsed_val);
1065: if (elm == NULL)
1066: goto callfail;
1.8.2.1 ! tb 1067: ober_set_header(elm, BER_CLASS_CONTEXT, type);
1.1 reyk 1068: if (type == LDAP_FILT_SUBS_FIN)
1069: break;
1070: }
1071: break;
1072: }
1073:
1074: if ((parsed_val = parseval(attr_val, len)) == NULL)
1075: goto callfail;
1.8.2.1 ! tb 1076: elm = ober_add_nstring(elm, parsed_val, strlen(parsed_val));
1.1 reyk 1077: free(parsed_val);
1078: if (elm == NULL)
1079: goto callfail;
1080: break;
1081: }
1082:
1083: cp++; /* now points one char beyond the trailing `)` */
1084:
1085: *cpp = cp;
1086: return (root);
1087:
1088: syntaxfail: /* XXX -- error reporting */
1089: callfail:
1090: bad:
1091: if (root != NULL)
1.8.2.1 ! tb 1092: ober_free_elements(root);
! 1093: ober_link_elements(prev, NULL);
1.1 reyk 1094: return (NULL);
1095: }
1096:
1097: #ifdef DEBUG
1098: /*
1099: * Display a list of ber elements.
1100: *
1101: */
1102: void
1103: ldap_debug_elements(struct ber_element *root)
1104: {
1105: static int indent = 0;
1106: long long v;
1107: int d;
1108: char *buf;
1109: size_t len;
1110: u_int i;
1111: int constructed;
1112: struct ber_oid o;
1113:
1114: /* calculate lengths */
1.8.2.1 ! tb 1115: ober_calc_len(root);
1.1 reyk 1116:
1117: switch (root->be_encoding) {
1118: case BER_TYPE_SEQUENCE:
1119: case BER_TYPE_SET:
1120: constructed = root->be_encoding;
1121: break;
1122: default:
1123: constructed = 0;
1124: break;
1125: }
1126:
1127: fprintf(stderr, "%*slen %lu ", indent, "", root->be_len);
1128: switch (root->be_class) {
1129: case BER_CLASS_UNIVERSAL:
1130: fprintf(stderr, "class: universal(%u) type: ", root->be_class);
1131: switch (root->be_type) {
1132: case BER_TYPE_EOC:
1133: fprintf(stderr, "end-of-content");
1134: break;
1135: case BER_TYPE_BOOLEAN:
1136: fprintf(stderr, "boolean");
1137: break;
1138: case BER_TYPE_INTEGER:
1139: fprintf(stderr, "integer");
1140: break;
1141: case BER_TYPE_BITSTRING:
1142: fprintf(stderr, "bit-string");
1143: break;
1144: case BER_TYPE_OCTETSTRING:
1145: fprintf(stderr, "octet-string");
1146: break;
1147: case BER_TYPE_NULL:
1148: fprintf(stderr, "null");
1149: break;
1150: case BER_TYPE_OBJECT:
1151: fprintf(stderr, "object");
1152: break;
1153: case BER_TYPE_ENUMERATED:
1154: fprintf(stderr, "enumerated");
1155: break;
1156: case BER_TYPE_SEQUENCE:
1157: fprintf(stderr, "sequence");
1158: break;
1159: case BER_TYPE_SET:
1160: fprintf(stderr, "set");
1161: break;
1162: }
1163: break;
1164: case BER_CLASS_APPLICATION:
1165: fprintf(stderr, "class: application(%u) type: ",
1166: root->be_class);
1167: switch (root->be_type) {
1168: case LDAP_REQ_BIND:
1169: fprintf(stderr, "bind");
1170: break;
1171: case LDAP_RES_BIND:
1172: fprintf(stderr, "bind");
1173: break;
1174: case LDAP_REQ_UNBIND_30:
1175: break;
1176: case LDAP_REQ_SEARCH:
1177: fprintf(stderr, "search");
1178: break;
1179: case LDAP_RES_SEARCH_ENTRY:
1180: fprintf(stderr, "search_entry");
1181: break;
1182: case LDAP_RES_SEARCH_RESULT:
1183: fprintf(stderr, "search_result");
1184: break;
1185: case LDAP_REQ_MODIFY:
1186: fprintf(stderr, "modify");
1187: break;
1188: case LDAP_RES_MODIFY:
1189: fprintf(stderr, "modify");
1190: break;
1191: case LDAP_REQ_ADD:
1192: fprintf(stderr, "add");
1193: break;
1194: case LDAP_RES_ADD:
1195: fprintf(stderr, "add");
1196: break;
1197: case LDAP_REQ_DELETE_30:
1198: fprintf(stderr, "delete");
1199: break;
1200: case LDAP_RES_DELETE:
1201: fprintf(stderr, "delete");
1202: break;
1203: case LDAP_REQ_MODRDN:
1204: fprintf(stderr, "modrdn");
1205: break;
1206: case LDAP_RES_MODRDN:
1207: fprintf(stderr, "modrdn");
1208: break;
1209: case LDAP_REQ_COMPARE:
1210: fprintf(stderr, "compare");
1211: break;
1212: case LDAP_RES_COMPARE:
1213: fprintf(stderr, "compare");
1214: break;
1215: case LDAP_REQ_ABANDON_30:
1216: fprintf(stderr, "abandon");
1217: break;
1218: }
1219: break;
1220: case BER_CLASS_PRIVATE:
1221: fprintf(stderr, "class: private(%u) type: ", root->be_class);
1.4 rob 1222: fprintf(stderr, "encoding (%u) type: ", root->be_encoding);
1.1 reyk 1223: break;
1224: case BER_CLASS_CONTEXT:
1225: /* XXX: this is not correct */
1226: fprintf(stderr, "class: context(%u) type: ", root->be_class);
1227: switch(root->be_type) {
1228: case LDAP_AUTH_SIMPLE:
1229: fprintf(stderr, "auth simple");
1230: break;
1231: }
1232: break;
1233: default:
1234: fprintf(stderr, "class: <INVALID>(%u) type: ", root->be_class);
1235: break;
1236: }
1.4 rob 1237: fprintf(stderr, "(%u) encoding %u ",
1.1 reyk 1238: root->be_type, root->be_encoding);
1239:
1240: if (constructed)
1241: root->be_encoding = constructed;
1242:
1243: switch (root->be_encoding) {
1244: case BER_TYPE_BOOLEAN:
1.8.2.1 ! tb 1245: if (ober_get_boolean(root, &d) == -1) {
1.1 reyk 1246: fprintf(stderr, "<INVALID>\n");
1247: break;
1248: }
1249: fprintf(stderr, "%s(%d)\n", d ? "true" : "false", d);
1250: break;
1251: case BER_TYPE_INTEGER:
1.8.2.1 ! tb 1252: if (ober_get_integer(root, &v) == -1) {
1.1 reyk 1253: fprintf(stderr, "<INVALID>\n");
1254: break;
1255: }
1256: fprintf(stderr, "value %lld\n", v);
1257: break;
1258: case BER_TYPE_ENUMERATED:
1.8.2.1 ! tb 1259: if (ober_get_enumerated(root, &v) == -1) {
1.1 reyk 1260: fprintf(stderr, "<INVALID>\n");
1261: break;
1262: }
1263: fprintf(stderr, "value %lld\n", v);
1264: break;
1265: case BER_TYPE_BITSTRING:
1.8.2.1 ! tb 1266: if (ober_get_bitstring(root, (void *)&buf, &len) == -1) {
1.1 reyk 1267: fprintf(stderr, "<INVALID>\n");
1268: break;
1269: }
1270: fprintf(stderr, "hexdump ");
1271: for (i = 0; i < len; i++)
1272: fprintf(stderr, "%02x", buf[i]);
1273: fprintf(stderr, "\n");
1274: break;
1275: case BER_TYPE_OBJECT:
1.8.2.1 ! tb 1276: if (ober_get_oid(root, &o) == -1) {
1.1 reyk 1277: fprintf(stderr, "<INVALID>\n");
1278: break;
1279: }
1280: fprintf(stderr, "\n");
1281: break;
1282: case BER_TYPE_OCTETSTRING:
1.8.2.1 ! tb 1283: if (ober_get_nstring(root, (void *)&buf, &len) == -1) {
1.1 reyk 1284: fprintf(stderr, "<INVALID>\n");
1285: break;
1286: }
1.2 reyk 1287: fprintf(stderr, "string \"%.*s\"\n", (int)len, buf);
1.1 reyk 1288: break;
1289: case BER_TYPE_NULL: /* no payload */
1290: case BER_TYPE_EOC:
1291: case BER_TYPE_SEQUENCE:
1292: case BER_TYPE_SET:
1293: default:
1294: fprintf(stderr, "\n");
1295: break;
1296: }
1297:
1298: if (constructed && root->be_sub) {
1299: indent += 2;
1300: ldap_debug_elements(root->be_sub);
1301: indent -= 2;
1302: }
1303: if (root->be_next)
1304: ldap_debug_elements(root->be_next);
1305: }
1306: #endif
1307:
1308: /*
1309: * Strip UTF-8 down to ASCII without validation.
1310: * notes:
1311: * non-ASCII characters are displayed as '?'
1312: * the argument u should be a NULL terminated sequence of UTF-8 bytes.
1313: */
1314: char *
1315: utoa(char *u)
1316: {
1317: int len, i, j;
1318: char *str;
1319:
1320: /* calculate the length to allocate */
1321: for (len = 0, i = 0; u[i] != '\0'; i++)
1322: if (!isu8cont(u[i]))
1323: len++;
1324:
1325: if ((str = calloc(len + 1, sizeof(char))) == NULL)
1326: return NULL;
1327:
1328: /* copy the ASCII characters to the newly allocated string */
1329: for (i = 0, j = 0; u[i] != '\0'; i++)
1330: if (!isu8cont(u[i]))
1331: str[j++] = isascii((unsigned char)u[i]) ? u[i] : '?';
1332:
1333: return str;
1334: }
1335:
1336: static int
1337: isu8cont(unsigned char c)
1338: {
1339: return (c & (0x80 | 0x40)) == 0x80;
1340: }
1341:
1342: /*
1343: * Parse a LDAP value
1344: * notes:
1345: * the argument p should be a NUL-terminated sequence of ASCII bytes
1346: */
1347: char *
1348: parseval(char *p, size_t len)
1349: {
1350: char hex[3];
1351: char *buffer;
1352: size_t i, j;
1353:
1354: if ((buffer = calloc(1, len + 1)) == NULL)
1355: return NULL;
1356:
1357: for (i = j = 0; j < len; i++) {
1358: if (p[j] == '\\') {
1359: strlcpy(hex, p + j + 1, sizeof(hex));
1360: buffer[i] = (char)strtoumax(hex, NULL, 16);
1361: j += 3;
1362: } else {
1363: buffer[i] = p[j];
1364: j++;
1365: }
1366: }
1367:
1368: return buffer;
1369: }
1370:
1371: int
1372: aldap_get_errno(struct aldap *a, const char **estr)
1373: {
1374: switch (a->err) {
1375: case ALDAP_ERR_SUCCESS:
1376: *estr = "success";
1377: break;
1378: case ALDAP_ERR_PARSER_ERROR:
1379: *estr = "parser failed";
1380: break;
1381: case ALDAP_ERR_INVALID_FILTER:
1382: *estr = "invalid filter";
1383: break;
1384: case ALDAP_ERR_OPERATION_FAILED:
1385: *estr = "operation failed";
1386: break;
1387: case ALDAP_ERR_TLS_ERROR:
1388: *estr = tls_error(a->tls);
1389: break;
1390: default:
1391: *estr = "unknown";
1392: break;
1393: }
1394: return (a->err);
1395: }