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