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