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