GCC Code Coverage Report
Directory: ./ Exec Total Coverage
File: usr.sbin/ypldap/aldap.c Lines: 0 424 0.0 %
Date: 2017-11-13 Branches: 0 314 0.0 %

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