xref: /openbsd-src/usr.sbin/ypldap/aldap.c (revision 40c942665e2a6e73653062386b61f09373477e3d)
1*40c94266Sjmatthew /*	$OpenBSD: aldap.c,v 1.49 2022/10/13 04:55:33 jmatthew Exp $ */
2af720893Saschrijver 
3af720893Saschrijver /*
4af720893Saschrijver  * Copyright (c) 2008 Alexander Schrijver <aschrijver@openbsd.org>
5af720893Saschrijver  * Copyright (c) 2006, 2007 Marc Balmer <mbalmer@openbsd.org>
6af720893Saschrijver  *
7af720893Saschrijver  * Permission to use, copy, modify, and distribute this software for any
8af720893Saschrijver  * purpose with or without fee is hereby granted, provided that the above
9af720893Saschrijver  * copyright notice and this permission notice appear in all copies.
10af720893Saschrijver  *
11af720893Saschrijver  * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
12af720893Saschrijver  * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
13af720893Saschrijver  * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
14af720893Saschrijver  * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
15af720893Saschrijver  * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
16af720893Saschrijver  * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
17af720893Saschrijver  * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
18af720893Saschrijver  */
19af720893Saschrijver 
2012e5c931Sguenther #include <arpa/inet.h>
216c9ae825Sschwarze #include <ctype.h>
227e3b263bSaschrijver #include <errno.h>
237e3b263bSaschrijver #include <inttypes.h>
24af720893Saschrijver #include <string.h>
25af720893Saschrijver #include <stdlib.h>
2608aaee68Spyr #include <unistd.h>
27af720893Saschrijver 
2832814761Sjmatthew #include <event.h>
2932814761Sjmatthew 
30af720893Saschrijver #include "aldap.h"
31af720893Saschrijver 
32f021e556Spyr #if 0
33f021e556Spyr #define DEBUG
34f021e556Spyr #endif
35af720893Saschrijver #define VERSION 3
36af720893Saschrijver 
37c89bbd07Sjmatthew static struct ber_element	*ldap_parse_search_filter(struct ber_element *,
38c89bbd07Sjmatthew 				    char *);
39c89bbd07Sjmatthew static struct ber_element	*ldap_do_parse_search_filter(
40c89bbd07Sjmatthew 				    struct ber_element *, char **);
41d464d0deSmartijn struct aldap_stringset		*aldap_get_stringset(struct ber_element *);
429ae551f8Saschrijver char				*utoa(char *);
436c9ae825Sschwarze static int			 isu8cont(unsigned char);
449ae551f8Saschrijver char				*parseval(char *, size_t);
45c89bbd07Sjmatthew int				aldap_create_page_control(struct ber_element *,
46c89bbd07Sjmatthew 				    int, struct aldap_page_control *);
4732814761Sjmatthew int				aldap_send(struct aldap *,
4832814761Sjmatthew 				    struct ber_element *);
498defa1f3Sclaudio unsigned int			aldap_application(struct ber_element *);
50af720893Saschrijver 
51af720893Saschrijver #ifdef DEBUG
52af720893Saschrijver void			 ldap_debug_elements(struct ber_element *);
53af720893Saschrijver #endif
54af720893Saschrijver 
55af720893Saschrijver #ifdef DEBUG
56af720893Saschrijver #define DPRINTF(x...)	printf(x)
57af720893Saschrijver #define LDAP_DEBUG(x, y)	do { fprintf(stderr, "*** " x "\n"); ldap_debug_elements(y); } while (0)
58af720893Saschrijver #else
59af720893Saschrijver #define DPRINTF(x...)	do { } while (0)
60af720893Saschrijver #define LDAP_DEBUG(x, y)	do { } while (0)
61af720893Saschrijver #endif
62af720893Saschrijver 
638defa1f3Sclaudio unsigned int
aldap_application(struct ber_element * elm)6432814761Sjmatthew aldap_application(struct ber_element *elm)
6532814761Sjmatthew {
6632814761Sjmatthew 	return BER_TYPE_OCTETSTRING;
6732814761Sjmatthew }
6832814761Sjmatthew 
6908aaee68Spyr int
aldap_close(struct aldap * al)7008aaee68Spyr aldap_close(struct aldap *al)
7108aaee68Spyr {
725efa5574Sjmatthew 	if (al->tls != NULL) {
735efa5574Sjmatthew 		tls_close(al->tls);
745efa5574Sjmatthew 		tls_free(al->tls);
755efa5574Sjmatthew 	}
765efa5574Sjmatthew 	close(al->fd);
77696b5899Stb 	ober_free(&al->ber);
7832814761Sjmatthew 	evbuffer_free(al->buf);
7908aaee68Spyr 	free(al);
8008aaee68Spyr 
8108aaee68Spyr 	return (0);
8208aaee68Spyr }
8308aaee68Spyr 
84af720893Saschrijver struct aldap *
aldap_init(int fd)85af720893Saschrijver aldap_init(int fd)
86af720893Saschrijver {
87af720893Saschrijver 	struct aldap *a;
88af720893Saschrijver 
891e34b618Sderaadt 	if ((a = calloc(1, sizeof(*a))) == NULL)
90af720893Saschrijver 		return NULL;
9132814761Sjmatthew 	a->buf = evbuffer_new();
9232814761Sjmatthew 	a->fd = fd;
93696b5899Stb 	ober_set_application(&a->ber, aldap_application);
94af720893Saschrijver 
95af720893Saschrijver 	return a;
96af720893Saschrijver }
97af720893Saschrijver 
98af720893Saschrijver int
aldap_tls(struct aldap * ldap,struct tls_config * cfg,const char * name)9932814761Sjmatthew aldap_tls(struct aldap *ldap, struct tls_config *cfg, const char *name)
10032814761Sjmatthew {
10132814761Sjmatthew 	ldap->tls = tls_client();
10232814761Sjmatthew 	if (ldap->tls == NULL) {
10332814761Sjmatthew 		ldap->err = ALDAP_ERR_OPERATION_FAILED;
10432814761Sjmatthew 		return (-1);
10532814761Sjmatthew 	}
10632814761Sjmatthew 
10732814761Sjmatthew 	if (tls_configure(ldap->tls, cfg) == -1) {
10832814761Sjmatthew 		ldap->err = ALDAP_ERR_TLS_ERROR;
10932814761Sjmatthew 		return (-1);
11032814761Sjmatthew 	}
11132814761Sjmatthew 
11232814761Sjmatthew 	if (tls_connect_socket(ldap->tls, ldap->fd, name) == -1) {
11332814761Sjmatthew 		ldap->err = ALDAP_ERR_TLS_ERROR;
11432814761Sjmatthew 		return (-1);
11532814761Sjmatthew 	}
11632814761Sjmatthew 
11732814761Sjmatthew 	if (tls_handshake(ldap->tls) == -1) {
11832814761Sjmatthew 		ldap->err = ALDAP_ERR_TLS_ERROR;
11932814761Sjmatthew 		return (-1);
12032814761Sjmatthew 	}
12132814761Sjmatthew 
12232814761Sjmatthew 	return (0);
12332814761Sjmatthew }
12432814761Sjmatthew 
12532814761Sjmatthew int
aldap_send(struct aldap * ldap,struct ber_element * root)12632814761Sjmatthew aldap_send(struct aldap *ldap, struct ber_element *root)
12732814761Sjmatthew {
12832814761Sjmatthew 	void *ptr;
12932814761Sjmatthew 	char *data;
13032814761Sjmatthew 	size_t len, done;
13173774627Srob 	ssize_t	error, wrote;
13232814761Sjmatthew 
133696b5899Stb 	len = ober_calc_len(root);
134696b5899Stb 	error = ober_write_elements(&ldap->ber, root);
135696b5899Stb 	ober_free_elements(root);
13632814761Sjmatthew 	if (error == -1)
13732814761Sjmatthew 		return -1;
13832814761Sjmatthew 
139696b5899Stb 	ober_get_writebuf(&ldap->ber, &ptr);
14032814761Sjmatthew 	done = 0;
14132814761Sjmatthew 	data = ptr;
14232814761Sjmatthew 	while (len > 0) {
14332814761Sjmatthew 		if (ldap->tls != NULL) {
14432814761Sjmatthew 			wrote = tls_write(ldap->tls, data + done, len);
14532814761Sjmatthew 			if (wrote == TLS_WANT_POLLIN ||
14632814761Sjmatthew 			    wrote == TLS_WANT_POLLOUT)
14732814761Sjmatthew 				continue;
14832814761Sjmatthew 		} else
14932814761Sjmatthew 			wrote = write(ldap->fd, data + done, len);
15032814761Sjmatthew 
15132814761Sjmatthew 		if (wrote == -1)
15232814761Sjmatthew 			return -1;
15332814761Sjmatthew 
15432814761Sjmatthew 		len -= wrote;
15532814761Sjmatthew 		done += wrote;
15632814761Sjmatthew 	}
15732814761Sjmatthew 
15832814761Sjmatthew 	return 0;
15932814761Sjmatthew }
16032814761Sjmatthew 
16132814761Sjmatthew int
aldap_req_starttls(struct aldap * ldap)16232814761Sjmatthew aldap_req_starttls(struct aldap *ldap)
16332814761Sjmatthew {
16432814761Sjmatthew 	struct ber_element *root = NULL, *ber;
16532814761Sjmatthew 
166696b5899Stb 	if ((root = ober_add_sequence(NULL)) == NULL)
16732814761Sjmatthew 		goto fail;
16832814761Sjmatthew 
169696b5899Stb 	ber = ober_printf_elements(root, "d{tst", ++ldap->msgid, BER_CLASS_APP,
1708defa1f3Sclaudio 	    LDAP_REQ_EXTENDED, LDAP_STARTTLS_OID, BER_CLASS_CONTEXT, 0);
17132814761Sjmatthew 	if (ber == NULL) {
17232814761Sjmatthew 		ldap->err = ALDAP_ERR_OPERATION_FAILED;
17332814761Sjmatthew 		goto fail;
17432814761Sjmatthew 	}
17532814761Sjmatthew 
17632814761Sjmatthew 	if (aldap_send(ldap, root) == -1)
17732814761Sjmatthew 		goto fail;
17832814761Sjmatthew 
17932814761Sjmatthew 	return (ldap->msgid);
18032814761Sjmatthew fail:
18132814761Sjmatthew 	if (root != NULL)
182696b5899Stb 		ober_free_elements(root);
18332814761Sjmatthew 
18432814761Sjmatthew 	ldap->err = ALDAP_ERR_OPERATION_FAILED;
18532814761Sjmatthew 	return (-1);
18632814761Sjmatthew }
18732814761Sjmatthew 
18832814761Sjmatthew int
aldap_bind(struct aldap * ldap,char * binddn,char * bindcred)189af720893Saschrijver aldap_bind(struct aldap *ldap, char *binddn, char *bindcred)
190af720893Saschrijver {
191b89a6dc6Saschrijver 	struct ber_element *root = NULL, *elm;
192af720893Saschrijver 
193a5a5011eSaschrijver 	if (binddn == NULL)
194a5a5011eSaschrijver 		binddn = "";
195a5a5011eSaschrijver 	if (bindcred == NULL)
196a5a5011eSaschrijver 		bindcred = "";
197a5a5011eSaschrijver 
198696b5899Stb 	if ((root = ober_add_sequence(NULL)) == NULL)
199b89a6dc6Saschrijver 		goto fail;
200b89a6dc6Saschrijver 
201696b5899Stb 	elm = ober_printf_elements(root, "d{tdsst", ++ldap->msgid, BER_CLASS_APP,
2028defa1f3Sclaudio 	    LDAP_REQ_BIND, VERSION, binddn, bindcred,
2038defa1f3Sclaudio 	    BER_CLASS_CONTEXT, LDAP_AUTH_SIMPLE);
204b89a6dc6Saschrijver 	if (elm == NULL)
205b89a6dc6Saschrijver 		goto fail;
206af720893Saschrijver 
207af720893Saschrijver 	LDAP_DEBUG("aldap_bind", root);
208af720893Saschrijver 
20932814761Sjmatthew 	if (aldap_send(ldap, root) == -1) {
210b89a6dc6Saschrijver 		root = NULL;
211b89a6dc6Saschrijver 		goto fail;
21232814761Sjmatthew 	}
213af720893Saschrijver 	return (ldap->msgid);
214b89a6dc6Saschrijver fail:
215b89a6dc6Saschrijver 	if (root != NULL)
216696b5899Stb 		ober_free_elements(root);
21742013679Saschrijver 
21842013679Saschrijver 	ldap->err = ALDAP_ERR_OPERATION_FAILED;
219b89a6dc6Saschrijver 	return (-1);
220af720893Saschrijver }
221af720893Saschrijver 
222af720893Saschrijver int
aldap_bind_sasl_external(struct aldap * ldap,char * bindid)223*40c94266Sjmatthew aldap_bind_sasl_external(struct aldap *ldap, char *bindid)
224*40c94266Sjmatthew {
225*40c94266Sjmatthew 	struct ber_element *root = NULL, *elm;
226*40c94266Sjmatthew 
227*40c94266Sjmatthew 	if ((root = ober_add_sequence(NULL)) == NULL)
228*40c94266Sjmatthew 		goto fail;
229*40c94266Sjmatthew 
230*40c94266Sjmatthew 	elm = ober_printf_elements(root, "d{tds{ts", ++ldap->msgid,
231*40c94266Sjmatthew 	    BER_CLASS_APP, LDAP_REQ_BIND, VERSION, "",
232*40c94266Sjmatthew 	    BER_CLASS_CONTEXT, LDAP_AUTH_SASL, LDAP_SASL_MECH_EXTERNAL);
233*40c94266Sjmatthew 	if (elm == NULL)
234*40c94266Sjmatthew 		goto fail;
235*40c94266Sjmatthew 
236*40c94266Sjmatthew 	if (bindid == NULL)
237*40c94266Sjmatthew 		elm = ober_add_null(elm);
238*40c94266Sjmatthew 	else
239*40c94266Sjmatthew 		elm = ober_add_string(elm, bindid);
240*40c94266Sjmatthew 
241*40c94266Sjmatthew 	if (elm == NULL)
242*40c94266Sjmatthew 		goto fail;
243*40c94266Sjmatthew 
244*40c94266Sjmatthew 	LDAP_DEBUG("aldap_bind_sasl_external", root);
245*40c94266Sjmatthew 
246*40c94266Sjmatthew 	if (aldap_send(ldap, root) == -1) {
247*40c94266Sjmatthew 		root = NULL;
248*40c94266Sjmatthew 		goto fail;
249*40c94266Sjmatthew 	}
250*40c94266Sjmatthew 	return (ldap->msgid);
251*40c94266Sjmatthew fail:
252*40c94266Sjmatthew 	ober_free_elements(root);
253*40c94266Sjmatthew 
254*40c94266Sjmatthew 	ldap->err = ALDAP_ERR_OPERATION_FAILED;
255*40c94266Sjmatthew 	return (-1);
256*40c94266Sjmatthew }
257*40c94266Sjmatthew 
258*40c94266Sjmatthew int
aldap_unbind(struct aldap * ldap)259af720893Saschrijver aldap_unbind(struct aldap *ldap)
260af720893Saschrijver {
261b89a6dc6Saschrijver 	struct ber_element *root = NULL, *elm;
262af720893Saschrijver 
263696b5899Stb 	if ((root = ober_add_sequence(NULL)) == NULL)
264b89a6dc6Saschrijver 		goto fail;
265696b5899Stb 	elm = ober_printf_elements(root, "d{t", ++ldap->msgid, BER_CLASS_APP,
266af720893Saschrijver 	    LDAP_REQ_UNBIND_30);
267b89a6dc6Saschrijver 	if (elm == NULL)
268b89a6dc6Saschrijver 		goto fail;
269af720893Saschrijver 
270af720893Saschrijver 	LDAP_DEBUG("aldap_unbind", root);
271af720893Saschrijver 
27232814761Sjmatthew 	if (aldap_send(ldap, root) == -1) {
273b89a6dc6Saschrijver 		root = NULL;
274b89a6dc6Saschrijver 		goto fail;
27532814761Sjmatthew 	}
276af720893Saschrijver 	return (ldap->msgid);
277b89a6dc6Saschrijver fail:
278b89a6dc6Saschrijver 	if (root != NULL)
279696b5899Stb 		ober_free_elements(root);
280b89a6dc6Saschrijver 
28142013679Saschrijver 	ldap->err = ALDAP_ERR_OPERATION_FAILED;
28242013679Saschrijver 
283b89a6dc6Saschrijver 	return (-1);
284af720893Saschrijver }
285af720893Saschrijver 
286af720893Saschrijver 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)287af720893Saschrijver aldap_search(struct aldap *ldap, char *basedn, enum scope scope, char *filter,
288c89bbd07Sjmatthew     char **attrs, int typesonly, int sizelimit, int timelimit,
289c89bbd07Sjmatthew     struct aldap_page_control *page)
290af720893Saschrijver {
291c89bbd07Sjmatthew 	struct ber_element *root = NULL, *ber, *c;
29232814761Sjmatthew 	int i;
293af720893Saschrijver 
294696b5899Stb 	if ((root = ober_add_sequence(NULL)) == NULL)
295b89a6dc6Saschrijver 		goto fail;
296b89a6dc6Saschrijver 
297696b5899Stb 	ber = ober_printf_elements(root, "d{t", ++ldap->msgid, BER_CLASS_APP,
2988defa1f3Sclaudio 	    LDAP_REQ_SEARCH);
299c89bbd07Sjmatthew 	if (ber == NULL) {
300c89bbd07Sjmatthew 		ldap->err = ALDAP_ERR_OPERATION_FAILED;
301c89bbd07Sjmatthew 		goto fail;
302c89bbd07Sjmatthew 	}
303c89bbd07Sjmatthew 
304c89bbd07Sjmatthew 	c = ber;
305696b5899Stb 	ber = ober_printf_elements(ber, "sEEddb", basedn, (long long)scope,
306c89bbd07Sjmatthew 	                         (long long)LDAP_DEREF_NEVER, sizelimit,
307c89bbd07Sjmatthew 				 timelimit, typesonly);
3083b316f64Saschrijver 	if (ber == NULL) {
3093b316f64Saschrijver 		ldap->err = ALDAP_ERR_OPERATION_FAILED;
310b89a6dc6Saschrijver 		goto fail;
3113b316f64Saschrijver 	}
312af720893Saschrijver 
3133b316f64Saschrijver 	if ((ber = ldap_parse_search_filter(ber, filter)) == NULL) {
3143b316f64Saschrijver 		ldap->err = ALDAP_ERR_PARSER_ERROR;
3153b316f64Saschrijver 		goto fail;
3163b316f64Saschrijver 	}
317af720893Saschrijver 
318696b5899Stb 	if ((ber = ober_add_sequence(ber)) == NULL)
319b89a6dc6Saschrijver 		goto fail;
320af720893Saschrijver 	if (attrs != NULL)
321a2d4139bSblambert 		for (i = 0; attrs[i] != NULL; i++) {
322696b5899Stb 			if ((ber = ober_add_string(ber, attrs[i])) == NULL)
323b89a6dc6Saschrijver 				goto fail;
324b89a6dc6Saschrijver 		}
325af720893Saschrijver 
326c89bbd07Sjmatthew 	aldap_create_page_control(c, 100, page);
327c89bbd07Sjmatthew 
328af720893Saschrijver 	LDAP_DEBUG("aldap_search", root);
329af720893Saschrijver 
33032814761Sjmatthew 	if (aldap_send(ldap, root) == -1) {
331b89a6dc6Saschrijver 		root = NULL;
3323b316f64Saschrijver 		ldap->err = ALDAP_ERR_OPERATION_FAILED;
333b89a6dc6Saschrijver 		goto fail;
3343b316f64Saschrijver 	}
335b2f0a52bSaschrijver 
336af720893Saschrijver 	return (ldap->msgid);
337b89a6dc6Saschrijver 
338b89a6dc6Saschrijver fail:
339b89a6dc6Saschrijver 	if (root != NULL)
340696b5899Stb 		ober_free_elements(root);
341b89a6dc6Saschrijver 
342b89a6dc6Saschrijver 	return (-1);
343af720893Saschrijver }
344af720893Saschrijver 
345c89bbd07Sjmatthew int
aldap_create_page_control(struct ber_element * elm,int size,struct aldap_page_control * page)346c89bbd07Sjmatthew aldap_create_page_control(struct ber_element *elm, int size,
347c89bbd07Sjmatthew     struct aldap_page_control *page)
348c89bbd07Sjmatthew {
34973774627Srob 	ssize_t len;
350c89bbd07Sjmatthew 	struct ber c;
351c89bbd07Sjmatthew 	struct ber_element *ber = NULL;
352c89bbd07Sjmatthew 
353c89bbd07Sjmatthew 	c.br_wbuf = NULL;
354c89bbd07Sjmatthew 
355696b5899Stb 	ber = ober_add_sequence(NULL);
356c89bbd07Sjmatthew 
357c89bbd07Sjmatthew 	if (page == NULL) {
358696b5899Stb 		if (ober_printf_elements(ber, "ds", 50, "") == NULL)
359c89bbd07Sjmatthew 			goto fail;
360c89bbd07Sjmatthew 	} else {
361696b5899Stb 		if (ober_printf_elements(ber, "dx", 50, page->cookie,
362c89bbd07Sjmatthew 			    page->cookie_len) == NULL)
363c89bbd07Sjmatthew 			goto fail;
364c89bbd07Sjmatthew 	}
365c89bbd07Sjmatthew 
366696b5899Stb 	if ((len = ober_write_elements(&c, ber)) < 1)
367c89bbd07Sjmatthew 		goto fail;
368696b5899Stb 	if (ober_printf_elements(elm, "{t{sx", 2, 0, LDAP_PAGED_OID,
369c89bbd07Sjmatthew 		                c.br_wbuf, (size_t)len) == NULL)
370c89bbd07Sjmatthew 		goto fail;
371c89bbd07Sjmatthew 
372696b5899Stb 	ober_free_elements(ber);
373696b5899Stb 	ober_free(&c);
374c89bbd07Sjmatthew 	return len;
375c89bbd07Sjmatthew fail:
376c89bbd07Sjmatthew 	if (ber != NULL)
377696b5899Stb 		ober_free_elements(ber);
378696b5899Stb 	ober_free(&c);
379c89bbd07Sjmatthew 
380c89bbd07Sjmatthew 	return (-1);
381c89bbd07Sjmatthew }
382c89bbd07Sjmatthew 
383af720893Saschrijver struct aldap_message *
aldap_parse(struct aldap * ldap)384af720893Saschrijver aldap_parse(struct aldap *ldap)
385af720893Saschrijver {
386c89bbd07Sjmatthew 	int			 class;
3878defa1f3Sclaudio 	unsigned int		 type;
388af720893Saschrijver 	long long		 msgid = 0;
389af720893Saschrijver 	struct aldap_message	*m;
390c89bbd07Sjmatthew 	struct ber_element	*a = NULL, *ep;
39132814761Sjmatthew 	char			 rbuf[512];
39232814761Sjmatthew 	int			 ret, retry;
393af720893Saschrijver 
3941e34b618Sderaadt 	if ((m = calloc(1, sizeof(struct aldap_message))) == NULL)
395af720893Saschrijver 		return NULL;
396af720893Saschrijver 
39732814761Sjmatthew 	retry = 0;
39832814761Sjmatthew 	while (m->msg == NULL) {
39932814761Sjmatthew 		if (retry || EVBUFFER_LENGTH(ldap->buf) == 0) {
40032814761Sjmatthew 			if (ldap->tls) {
40132814761Sjmatthew 				ret = tls_read(ldap->tls, rbuf, sizeof(rbuf));
40232814761Sjmatthew 				if (ret == TLS_WANT_POLLIN ||
40332814761Sjmatthew 				    ret == TLS_WANT_POLLOUT)
40432814761Sjmatthew 					continue;
40532814761Sjmatthew 			} else
40632814761Sjmatthew 				ret = read(ldap->fd, rbuf, sizeof(rbuf));
40732814761Sjmatthew 
40832814761Sjmatthew 			if (ret == -1) {
409c6a2e645Sblambert 				goto parsefail;
41032814761Sjmatthew 			}
41132814761Sjmatthew 
41232814761Sjmatthew 			evbuffer_add(ldap->buf, rbuf, ret);
41332814761Sjmatthew 		}
41432814761Sjmatthew 
41532814761Sjmatthew 		if (EVBUFFER_LENGTH(ldap->buf) > 0) {
416696b5899Stb 			ober_set_readbuf(&ldap->ber, EVBUFFER_DATA(ldap->buf),
41732814761Sjmatthew 			    EVBUFFER_LENGTH(ldap->buf));
41832814761Sjmatthew 			errno = 0;
419696b5899Stb 			m->msg = ober_read_elements(&ldap->ber, NULL);
42032814761Sjmatthew 			if (errno != 0 && errno != ECANCELED) {
42132814761Sjmatthew 				goto parsefail;
42232814761Sjmatthew 			}
42332814761Sjmatthew 
42432814761Sjmatthew 			retry = 1;
42532814761Sjmatthew 		}
42632814761Sjmatthew 	}
42732814761Sjmatthew 
42832814761Sjmatthew 	evbuffer_drain(ldap->buf, ldap->ber.br_rptr - ldap->ber.br_rbuf);
429af720893Saschrijver 
430af720893Saschrijver 	LDAP_DEBUG("message", m->msg);
431af720893Saschrijver 
432696b5899Stb 	if (ober_scanf_elements(m->msg, "{ite", &msgid, &class, &type, &a) != 0)
433af720893Saschrijver 		goto parsefail;
434af720893Saschrijver 	m->msgid = msgid;
435af720893Saschrijver 	m->message_type = type;
436af720893Saschrijver 	m->protocol_op = a;
437af720893Saschrijver 
438af720893Saschrijver 	switch (m->message_type) {
439af720893Saschrijver 	case LDAP_RES_BIND:
440af720893Saschrijver 	case LDAP_RES_MODIFY:
441af720893Saschrijver 	case LDAP_RES_ADD:
442af720893Saschrijver 	case LDAP_RES_DELETE:
443af720893Saschrijver 	case LDAP_RES_MODRDN:
444af720893Saschrijver 	case LDAP_RES_COMPARE:
445af720893Saschrijver 	case LDAP_RES_SEARCH_RESULT:
446696b5899Stb 		if (ober_scanf_elements(m->protocol_op, "{EeSe",
44792748799Smartijn 		    &m->body.res.rescode, &m->dn, &m->body.res.diagmsg) != 0)
448af720893Saschrijver 			goto parsefail;
44992748799Smartijn 		if (m->body.res.rescode == LDAP_REFERRAL) {
45092748799Smartijn 			a = m->body.res.diagmsg->be_next;
451696b5899Stb 			if (ober_scanf_elements(a, "{e", &m->references) != 0)
452af720893Saschrijver 				goto parsefail;
45392748799Smartijn 		}
454c89bbd07Sjmatthew 		if (m->msg->be_sub) {
455c89bbd07Sjmatthew 			for (ep = m->msg->be_sub; ep != NULL; ep = ep->be_next) {
456696b5899Stb 				ober_scanf_elements(ep, "t", &class, &type);
457c89bbd07Sjmatthew 				if (class == 2 && type == 0)
458c89bbd07Sjmatthew 					m->page = aldap_parse_page_control(ep->be_sub->be_sub,
459c89bbd07Sjmatthew 					    ep->be_sub->be_sub->be_len);
460c89bbd07Sjmatthew 			}
461c89bbd07Sjmatthew 		} else
462c89bbd07Sjmatthew 			m->page = NULL;
463af720893Saschrijver 		break;
464af720893Saschrijver 	case LDAP_RES_SEARCH_ENTRY:
465696b5899Stb 		if (ober_scanf_elements(m->protocol_op, "{eS{e", &m->dn,
466e971cb85Saschrijver 		    &m->body.search.attrs) != 0)
467af720893Saschrijver 			goto parsefail;
468af720893Saschrijver 		break;
469af720893Saschrijver 	case LDAP_RES_SEARCH_REFERENCE:
470696b5899Stb 		if (ober_scanf_elements(m->protocol_op, "{e", &m->references) != 0)
471af720893Saschrijver 			goto parsefail;
472af720893Saschrijver 		break;
47332814761Sjmatthew 	case LDAP_RES_EXTENDED:
474696b5899Stb 		if (ober_scanf_elements(m->protocol_op, "{E",
47532814761Sjmatthew 		    &m->body.res.rescode) != 0) {
47632814761Sjmatthew 			goto parsefail;
47732814761Sjmatthew 		}
47832814761Sjmatthew 		break;
479af720893Saschrijver 	}
480af720893Saschrijver 
481af720893Saschrijver 	return m;
482af720893Saschrijver parsefail:
48332814761Sjmatthew 	evbuffer_drain(ldap->buf, EVBUFFER_LENGTH(ldap->buf));
48442013679Saschrijver 	ldap->err = ALDAP_ERR_PARSER_ERROR;
485c6a2e645Sblambert 	aldap_freemsg(m);
486af720893Saschrijver 	return NULL;
487af720893Saschrijver }
488af720893Saschrijver 
489c89bbd07Sjmatthew struct aldap_page_control *
aldap_parse_page_control(struct ber_element * control,size_t len)490c89bbd07Sjmatthew aldap_parse_page_control(struct ber_element *control, size_t len)
491c89bbd07Sjmatthew {
492c89bbd07Sjmatthew 	char *oid, *s;
493c89bbd07Sjmatthew 	char *encoded;
494c89bbd07Sjmatthew 	struct ber b;
495c89bbd07Sjmatthew 	struct ber_element *elm;
496c89bbd07Sjmatthew 	struct aldap_page_control *page;
497c89bbd07Sjmatthew 
498c89bbd07Sjmatthew 	b.br_wbuf = NULL;
499696b5899Stb 	ober_scanf_elements(control, "ss", &oid, &encoded);
500696b5899Stb 	ober_set_readbuf(&b, encoded, control->be_next->be_len);
501696b5899Stb 	elm = ober_read_elements(&b, NULL);
502c89bbd07Sjmatthew 
503c89bbd07Sjmatthew 	if ((page = malloc(sizeof(struct aldap_page_control))) == NULL) {
504c89bbd07Sjmatthew 		if (elm != NULL)
505696b5899Stb 			ober_free_elements(elm);
506696b5899Stb 		ober_free(&b);
507c89bbd07Sjmatthew 		return NULL;
508c89bbd07Sjmatthew 	}
509c89bbd07Sjmatthew 
510696b5899Stb 	ober_scanf_elements(elm->be_sub, "is", &page->size, &s);
511c89bbd07Sjmatthew 	page->cookie_len = elm->be_sub->be_next->be_len;
512c89bbd07Sjmatthew 
513c89bbd07Sjmatthew 	if ((page->cookie = malloc(page->cookie_len)) == NULL) {
514c89bbd07Sjmatthew 		if (elm != NULL)
515696b5899Stb 			ober_free_elements(elm);
516696b5899Stb 		ober_free(&b);
517c89bbd07Sjmatthew 		free(page);
518c89bbd07Sjmatthew 		return NULL;
519c89bbd07Sjmatthew 	}
520c89bbd07Sjmatthew 	memcpy(page->cookie, s, page->cookie_len);
521c89bbd07Sjmatthew 
522696b5899Stb 	ober_free_elements(elm);
523696b5899Stb 	ober_free(&b);
524c89bbd07Sjmatthew 	return page;
525c89bbd07Sjmatthew }
526c89bbd07Sjmatthew 
527c89bbd07Sjmatthew void
aldap_freepage(struct aldap_page_control * page)528c89bbd07Sjmatthew aldap_freepage(struct aldap_page_control *page)
529c89bbd07Sjmatthew {
530c89bbd07Sjmatthew 	free(page->cookie);
531c89bbd07Sjmatthew 	free(page);
532c89bbd07Sjmatthew }
533c89bbd07Sjmatthew 
534af720893Saschrijver void
aldap_freemsg(struct aldap_message * msg)535af720893Saschrijver aldap_freemsg(struct aldap_message *msg)
536af720893Saschrijver {
537c6a2e645Sblambert 	if (msg->msg)
538696b5899Stb 		ober_free_elements(msg->msg);
539af720893Saschrijver 	free(msg);
540af720893Saschrijver }
541af720893Saschrijver 
542af720893Saschrijver int
aldap_get_resultcode(struct aldap_message * msg)543af720893Saschrijver aldap_get_resultcode(struct aldap_message *msg)
544af720893Saschrijver {
545af720893Saschrijver 	return msg->body.res.rescode;
546af720893Saschrijver }
547af720893Saschrijver 
548af720893Saschrijver char *
aldap_get_dn(struct aldap_message * msg)549af720893Saschrijver aldap_get_dn(struct aldap_message *msg)
550af720893Saschrijver {
551af720893Saschrijver 	char *dn;
552af720893Saschrijver 
553af720893Saschrijver 	if (msg->dn == NULL)
554af720893Saschrijver 		return NULL;
555af720893Saschrijver 
556696b5899Stb 	if (ober_get_string(msg->dn, &dn) == -1)
557af720893Saschrijver 		return NULL;
558af720893Saschrijver 
559af720893Saschrijver 	return utoa(dn);
560af720893Saschrijver }
561af720893Saschrijver 
562d464d0deSmartijn struct aldap_stringset *
aldap_get_references(struct aldap_message * msg)563af720893Saschrijver aldap_get_references(struct aldap_message *msg)
564af720893Saschrijver {
565ec4ad443Saschrijver 	if (msg->references == NULL)
566ec4ad443Saschrijver 		return NULL;
567ec4ad443Saschrijver 	return aldap_get_stringset(msg->references);
568af720893Saschrijver }
569af720893Saschrijver 
570af720893Saschrijver void
aldap_free_references(char ** values)571af720893Saschrijver aldap_free_references(char **values)
572af720893Saschrijver {
573af720893Saschrijver 	int i;
574af720893Saschrijver 
575af720893Saschrijver 	if (values == NULL)
576af720893Saschrijver 		return;
577af720893Saschrijver 
578a2d4139bSblambert 	for (i = 0; values[i] != NULL; i++)
579af720893Saschrijver 		free(values[i]);
580af720893Saschrijver 
581af720893Saschrijver 	free(values);
582af720893Saschrijver }
583af720893Saschrijver 
584af720893Saschrijver char *
aldap_get_diagmsg(struct aldap_message * msg)585af720893Saschrijver aldap_get_diagmsg(struct aldap_message *msg)
586af720893Saschrijver {
587af720893Saschrijver 	char *s;
588af720893Saschrijver 
589af720893Saschrijver 	if (msg->body.res.diagmsg == NULL)
590af720893Saschrijver 		return NULL;
591af720893Saschrijver 
592696b5899Stb 	if (ober_get_string(msg->body.res.diagmsg, &s) == -1)
593af720893Saschrijver 		return NULL;
594af720893Saschrijver 
595af720893Saschrijver 	return utoa(s);
596af720893Saschrijver }
597af720893Saschrijver 
598af720893Saschrijver int
aldap_count_attrs(struct aldap_message * msg)599e971cb85Saschrijver aldap_count_attrs(struct aldap_message *msg)
600af720893Saschrijver {
601af720893Saschrijver 	int i;
602af720893Saschrijver 	struct ber_element *a;
603af720893Saschrijver 
604e971cb85Saschrijver 	if (msg->body.search.attrs == NULL)
605af720893Saschrijver 		return (-1);
606af720893Saschrijver 
607e971cb85Saschrijver 	for (i = 0, a = msg->body.search.attrs;
608696b5899Stb 	    a != NULL && ober_get_eoc(a) != 0;
609af720893Saschrijver 	    i++, a = a->be_next)
610af720893Saschrijver 		;
611af720893Saschrijver 
612af720893Saschrijver 	return i;
613af720893Saschrijver }
614af720893Saschrijver 
615af720893Saschrijver int
aldap_first_attr(struct aldap_message * msg,char ** outkey,struct aldap_stringset ** outvalues)616d464d0deSmartijn aldap_first_attr(struct aldap_message *msg, char **outkey,
617d464d0deSmartijn     struct aldap_stringset **outvalues)
618af720893Saschrijver {
61976549c4aSmartijn 	struct ber_element *b;
620af720893Saschrijver 	char *key;
621d464d0deSmartijn 	struct aldap_stringset *ret;
622af720893Saschrijver 
623e971cb85Saschrijver 	if (msg->body.search.attrs == NULL)
624db474592Saschrijver 		goto fail;
625af720893Saschrijver 
62676549c4aSmartijn 	if (ober_scanf_elements(msg->body.search.attrs, "{s(e)}",
62776549c4aSmartijn 	    &key, &b) != 0)
628db474592Saschrijver 		goto fail;
629af720893Saschrijver 
630e971cb85Saschrijver 	msg->body.search.iter = msg->body.search.attrs->be_next;
631af720893Saschrijver 
632db474592Saschrijver 	if ((ret = aldap_get_stringset(b)) == NULL)
633db474592Saschrijver 		goto fail;
634db474592Saschrijver 
635db474592Saschrijver 	(*outvalues) = ret;
636af720893Saschrijver 	(*outkey) = utoa(key);
637af720893Saschrijver 
638af720893Saschrijver 	return (1);
639db474592Saschrijver fail:
640db474592Saschrijver 	(*outkey) = NULL;
641db474592Saschrijver 	(*outvalues) = NULL;
642db474592Saschrijver 	return (-1);
643af720893Saschrijver }
644af720893Saschrijver 
645af720893Saschrijver int
aldap_next_attr(struct aldap_message * msg,char ** outkey,struct aldap_stringset ** outvalues)646d464d0deSmartijn aldap_next_attr(struct aldap_message *msg, char **outkey,
647d464d0deSmartijn     struct aldap_stringset **outvalues)
648af720893Saschrijver {
64976549c4aSmartijn 	struct ber_element *a;
650af720893Saschrijver 	char *key;
651d464d0deSmartijn 	struct aldap_stringset *ret;
652af720893Saschrijver 
653af720893Saschrijver 	if (msg->body.search.iter == NULL)
654af720893Saschrijver 		goto notfound;
655a04825e0Saschrijver 
656e971cb85Saschrijver 	LDAP_DEBUG("attr", msg->body.search.iter);
657a04825e0Saschrijver 
658696b5899Stb 	if (ober_get_eoc(msg->body.search.iter) == 0)
659af720893Saschrijver 		goto notfound;
660af720893Saschrijver 
66176549c4aSmartijn 	if (ober_scanf_elements(msg->body.search.iter, "{s(e)}", &key, &a) != 0)
662af720893Saschrijver 		goto fail;
663af720893Saschrijver 
664af720893Saschrijver 	msg->body.search.iter = msg->body.search.iter->be_next;
665af720893Saschrijver 
666db474592Saschrijver 	if ((ret = aldap_get_stringset(a)) == NULL)
667db474592Saschrijver 		goto fail;
668db474592Saschrijver 
669db474592Saschrijver 	(*outvalues) = ret;
670af720893Saschrijver 	(*outkey) = utoa(key);
671af720893Saschrijver 
672af720893Saschrijver 	return (1);
673af720893Saschrijver fail:
674af720893Saschrijver notfound:
675af720893Saschrijver 	(*outkey) = NULL;
676af720893Saschrijver 	(*outvalues) = NULL;
677af720893Saschrijver 	return (-1);
678af720893Saschrijver }
679af720893Saschrijver 
680af720893Saschrijver int
aldap_match_attr(struct aldap_message * msg,char * inkey,struct aldap_stringset ** outvalues)681d464d0deSmartijn aldap_match_attr(struct aldap_message *msg, char *inkey,
682d464d0deSmartijn     struct aldap_stringset **outvalues)
683af720893Saschrijver {
684af720893Saschrijver 	struct ber_element *a, *b;
685af720893Saschrijver 	char *descr = NULL;
686d464d0deSmartijn 	struct aldap_stringset *ret;
687af720893Saschrijver 
688e971cb85Saschrijver 	if (msg->body.search.attrs == NULL)
6890099bae5Sjmatthew 		goto fail;
690af720893Saschrijver 
691e971cb85Saschrijver 	LDAP_DEBUG("attr", msg->body.search.attrs);
692a04825e0Saschrijver 
693e971cb85Saschrijver 	for (a = msg->body.search.attrs;;) {
694af720893Saschrijver 		if (a == NULL)
695af720893Saschrijver 			goto notfound;
696696b5899Stb 		if (ober_get_eoc(a) == 0)
697af720893Saschrijver 			goto notfound;
698696b5899Stb 		if (ober_scanf_elements(a, "{s(e", &descr, &b) != 0)
699af720893Saschrijver 			goto fail;
700af720893Saschrijver 		if (strcasecmp(descr, inkey) == 0)
701af720893Saschrijver 			goto attrfound;
702af720893Saschrijver 		a = a->be_next;
703af720893Saschrijver 	}
704af720893Saschrijver 
705af720893Saschrijver attrfound:
706db474592Saschrijver 	if ((ret = aldap_get_stringset(b)) == NULL)
707db474592Saschrijver 		goto fail;
708db474592Saschrijver 
709db474592Saschrijver 	(*outvalues) = ret;
710af720893Saschrijver 
711af720893Saschrijver 	return (1);
712af720893Saschrijver fail:
713af720893Saschrijver notfound:
714af720893Saschrijver 	(*outvalues) = NULL;
715af720893Saschrijver 	return (-1);
716af720893Saschrijver }
717af720893Saschrijver 
718af720893Saschrijver int
aldap_free_attr(struct aldap_stringset * values)719d464d0deSmartijn aldap_free_attr(struct aldap_stringset *values)
720af720893Saschrijver {
721af720893Saschrijver 	if (values == NULL)
722af720893Saschrijver 		return -1;
723af720893Saschrijver 
724d464d0deSmartijn 	free(values->str);
725af720893Saschrijver 	free(values);
726af720893Saschrijver 
727af720893Saschrijver 	return (1);
728af720893Saschrijver }
729af720893Saschrijver 
730af720893Saschrijver void
aldap_free_url(struct aldap_url * lu)731af720893Saschrijver aldap_free_url(struct aldap_url *lu)
732af720893Saschrijver {
733bc9dda0eSblambert 	free(lu->buffer);
734af720893Saschrijver }
735af720893Saschrijver 
736af720893Saschrijver int
aldap_parse_url(const char * url,struct aldap_url * lu)73760f5961dSreyk aldap_parse_url(const char *url, struct aldap_url *lu)
738af720893Saschrijver {
739bc9dda0eSblambert 	char		*p, *forward, *forward2;
7407e3b263bSaschrijver 	const char	*errstr = NULL;
741af720893Saschrijver 	int		 i;
742af720893Saschrijver 
743bc9dda0eSblambert 	if ((lu->buffer = p = strdup(url)) == NULL)
744bc9dda0eSblambert 		return (-1);
745af720893Saschrijver 
746af720893Saschrijver 	/* protocol */
74760f5961dSreyk 	if (strncasecmp(LDAP_URL, p, strlen(LDAP_URL)) == 0) {
748af720893Saschrijver 		lu->protocol = LDAP;
749af720893Saschrijver 		p += strlen(LDAP_URL);
75060f5961dSreyk 	} else if (strncasecmp(LDAPS_URL, p, strlen(LDAPS_URL)) == 0) {
75160f5961dSreyk 		lu->protocol = LDAPS;
75260f5961dSreyk 		p += strlen(LDAPS_URL);
75360f5961dSreyk 	} else if (strncasecmp(LDAPTLS_URL, p, strlen(LDAPTLS_URL)) == 0) {
75460f5961dSreyk 		lu->protocol = LDAPTLS;
75560f5961dSreyk 		p += strlen(LDAPTLS_URL);
75660f5961dSreyk 	} else if (strncasecmp(LDAPI_URL, p, strlen(LDAPI_URL)) == 0) {
75760f5961dSreyk 		lu->protocol = LDAPI;
75860f5961dSreyk 		p += strlen(LDAPI_URL);
75960f5961dSreyk 	} else
76060f5961dSreyk 		lu->protocol = -1;
761af720893Saschrijver 
762af720893Saschrijver 	/* host and optional port */
763af720893Saschrijver 	if ((forward = strchr(p, '/')) != NULL)
764af720893Saschrijver 		*forward = '\0';
765af720893Saschrijver 	/* find the optional port */
766af720893Saschrijver 	if ((forward2 = strchr(p, ':')) != NULL) {
767af720893Saschrijver 		*forward2 = '\0';
768af720893Saschrijver 		/* if a port is given */
7697e3b263bSaschrijver 		if (*(forward2+1) != '\0') {
770ec4ad443Saschrijver #define PORT_MAX UINT16_MAX
771ec4ad443Saschrijver 			lu->port = strtonum(++forward2, 0, PORT_MAX, &errstr);
7727e3b263bSaschrijver 			if (errstr)
7737e3b263bSaschrijver 				goto fail;
7747e3b263bSaschrijver 		}
775af720893Saschrijver 	}
776af720893Saschrijver 	/* fail if no host is given */
777af720893Saschrijver 	if (strlen(p) == 0)
778af720893Saschrijver 		goto fail;
779bc9dda0eSblambert 	lu->host = p;
780af720893Saschrijver 	if (forward == NULL)
781af720893Saschrijver 		goto done;
782af720893Saschrijver 	/* p is assigned either a pointer to a character or to '\0' */
783af720893Saschrijver 	p = ++forward;
784af720893Saschrijver 	if (strlen(p) == 0)
785af720893Saschrijver 		goto done;
786af720893Saschrijver 
787af720893Saschrijver 	/* dn */
788af720893Saschrijver 	if ((forward = strchr(p, '?')) != NULL)
789af720893Saschrijver 		*forward = '\0';
790bc9dda0eSblambert 	lu->dn = p;
791af720893Saschrijver 	if (forward == NULL)
792af720893Saschrijver 		goto done;
793af720893Saschrijver 	/* p is assigned either a pointer to a character or to '\0' */
794af720893Saschrijver 	p = ++forward;
795af720893Saschrijver 	if (strlen(p) == 0)
796af720893Saschrijver 		goto done;
797af720893Saschrijver 
798af720893Saschrijver 	/* attributes */
799af720893Saschrijver 	if ((forward = strchr(p, '?')) != NULL)
800af720893Saschrijver 		*forward = '\0';
801af720893Saschrijver 	for (i = 0; i < MAXATTR; i++) {
802af720893Saschrijver 		if ((forward2 = strchr(p, ',')) == NULL) {
803af720893Saschrijver 			if (strlen(p) == 0)
804af720893Saschrijver 				break;
805bc9dda0eSblambert 			lu->attributes[i] = p;
806af720893Saschrijver 			break;
807af720893Saschrijver 		}
808af720893Saschrijver 		*forward2 = '\0';
809bc9dda0eSblambert 		lu->attributes[i] = p;
810af720893Saschrijver 		p = ++forward2;
811af720893Saschrijver 	}
812af720893Saschrijver 	if (forward == NULL)
813af720893Saschrijver 		goto done;
814af720893Saschrijver 	/* p is assigned either a pointer to a character or to '\0' */
815af720893Saschrijver 	p = ++forward;
816af720893Saschrijver 	if (strlen(p) == 0)
817af720893Saschrijver 		goto done;
818af720893Saschrijver 
819af720893Saschrijver 	/* scope */
820af720893Saschrijver 	if ((forward = strchr(p, '?')) != NULL)
821af720893Saschrijver 		*forward = '\0';
822af720893Saschrijver 	if (strcmp(p, "base") == 0)
823af720893Saschrijver 		lu->scope = LDAP_SCOPE_BASE;
824af720893Saschrijver 	else if (strcmp(p, "one") == 0)
825af720893Saschrijver 		lu->scope = LDAP_SCOPE_ONELEVEL;
826af720893Saschrijver 	else if (strcmp(p, "sub") == 0)
827af720893Saschrijver 		lu->scope = LDAP_SCOPE_SUBTREE;
828bc9dda0eSblambert 	else
829bc9dda0eSblambert 		goto fail;
830af720893Saschrijver 	if (forward == NULL)
831af720893Saschrijver 		goto done;
832af720893Saschrijver 	p = ++forward;
833af720893Saschrijver 	if (strlen(p) == 0)
834af720893Saschrijver 		goto done;
835af720893Saschrijver 
836af720893Saschrijver 	/* filter */
837bc9dda0eSblambert 	if (p)
838bc9dda0eSblambert 		lu->filter = p;
839af720893Saschrijver done:
840af720893Saschrijver 	return (1);
841af720893Saschrijver fail:
842bc9dda0eSblambert 	free(lu->buffer);
843bc9dda0eSblambert 	lu->buffer = NULL;
844af720893Saschrijver 	return (-1);
845af720893Saschrijver }
846af720893Saschrijver 
847bc9dda0eSblambert int
aldap_search_url(struct aldap * ldap,char * url,int typesonly,int sizelimit,int timelimit,struct aldap_page_control * page)848bc9dda0eSblambert aldap_search_url(struct aldap *ldap, char *url, int typesonly, int sizelimit,
84960f5961dSreyk     int timelimit, struct aldap_page_control *page)
850bc9dda0eSblambert {
851bc9dda0eSblambert 	struct aldap_url *lu;
852bc9dda0eSblambert 
853bc9dda0eSblambert 	if ((lu = calloc(1, sizeof(*lu))) == NULL)
854bc9dda0eSblambert 		return (-1);
855bc9dda0eSblambert 
856bc9dda0eSblambert 	if (aldap_parse_url(url, lu))
857bc9dda0eSblambert 		goto fail;
858bc9dda0eSblambert 
859bc9dda0eSblambert 	if (aldap_search(ldap, lu->dn, lu->scope, lu->filter, lu->attributes,
86060f5961dSreyk 	    typesonly, sizelimit, timelimit, page) == -1)
861bc9dda0eSblambert 		goto fail;
862bc9dda0eSblambert 
863bc9dda0eSblambert 	aldap_free_url(lu);
864bc9dda0eSblambert 	return (ldap->msgid);
865bc9dda0eSblambert fail:
866bc9dda0eSblambert 	aldap_free_url(lu);
867bc9dda0eSblambert 	return (-1);
868bc9dda0eSblambert }
869bc9dda0eSblambert 
870af720893Saschrijver /*
871af720893Saschrijver  * internal functions
872af720893Saschrijver  */
873af720893Saschrijver 
874d464d0deSmartijn struct aldap_stringset *
aldap_get_stringset(struct ber_element * elm)875af720893Saschrijver aldap_get_stringset(struct ber_element *elm)
876af720893Saschrijver {
877af720893Saschrijver 	struct ber_element *a;
878af720893Saschrijver 	int i;
879d464d0deSmartijn 	struct aldap_stringset *ret;
880af720893Saschrijver 
881af720893Saschrijver 	if (elm->be_type != BER_TYPE_OCTETSTRING)
882af720893Saschrijver 		return NULL;
883af720893Saschrijver 
884d464d0deSmartijn 	if ((ret = malloc(sizeof(*ret))) == NULL)
885d464d0deSmartijn 		return NULL;
886d464d0deSmartijn 	for (a = elm, ret->len = 0; a != NULL && a->be_type ==
887d464d0deSmartijn 	    BER_TYPE_OCTETSTRING; a = a->be_next, ret->len++)
888af720893Saschrijver 		;
889d464d0deSmartijn 	if (ret->len == 0) {
890d464d0deSmartijn 		free(ret);
891ec4ad443Saschrijver 		return NULL;
892d464d0deSmartijn 	}
893af720893Saschrijver 
894d464d0deSmartijn 	if ((ret->str = reallocarray(NULL, ret->len,
895d464d0deSmartijn 	    sizeof(*(ret->str)))) == NULL) {
896d464d0deSmartijn 		free(ret);
897af720893Saschrijver 		return NULL;
898d464d0deSmartijn 	}
899af720893Saschrijver 
9005344c61fSgilles 	for (a = elm, i = 0; a != NULL && a->be_type == BER_TYPE_OCTETSTRING;
901d464d0deSmartijn 	    a = a->be_next, i++)
902696b5899Stb 		(void) ober_get_ostring(a, &(ret->str[i]));
903af720893Saschrijver 
904af720893Saschrijver 	return ret;
905af720893Saschrijver }
906af720893Saschrijver 
907af720893Saschrijver /*
9089ae551f8Saschrijver  * Base case for ldap_do_parse_search_filter
909af720893Saschrijver  *
910af720893Saschrijver  * returns:
911af720893Saschrijver  *	struct ber_element *, ber_element tree
912af720893Saschrijver  *	NULL, parse failed
913af720893Saschrijver  */
914af720893Saschrijver static struct ber_element *
ldap_parse_search_filter(struct ber_element * ber,char * filter)915af720893Saschrijver ldap_parse_search_filter(struct ber_element *ber, char *filter)
916af720893Saschrijver {
917af720893Saschrijver 	struct ber_element *elm;
918af720893Saschrijver 	char *cp;
919af720893Saschrijver 
920af720893Saschrijver 	cp = filter;
921af720893Saschrijver 
922af720893Saschrijver 	if (cp == NULL || *cp == '\0') {
923af720893Saschrijver 		errno = EINVAL;
924af720893Saschrijver 		return (NULL);
925af720893Saschrijver 	}
926af720893Saschrijver 
927af720893Saschrijver 	if ((elm = ldap_do_parse_search_filter(ber, &cp)) == NULL)
928af720893Saschrijver 		return (NULL);
929af720893Saschrijver 
930af720893Saschrijver 	if (*cp != '\0') {
931696b5899Stb 		ober_free_elements(elm);
932696b5899Stb 		ober_link_elements(ber, NULL);
933af720893Saschrijver 		errno = EINVAL;
934af720893Saschrijver 		return (NULL);
935af720893Saschrijver 	}
936af720893Saschrijver 
937af720893Saschrijver 	return (elm);
938af720893Saschrijver }
939af720893Saschrijver 
940af720893Saschrijver /*
9419ae551f8Saschrijver  * Translate RFC4515 search filter string into ber_element tree
942af720893Saschrijver  *
943af720893Saschrijver  * returns:
944af720893Saschrijver  *	struct ber_element *, ber_element tree
945af720893Saschrijver  *	NULL, parse failed
946af720893Saschrijver  *
947af720893Saschrijver  * notes:
948af720893Saschrijver  *	when cp is passed to a recursive invocation, it is updated
949af720893Saschrijver  *	    to point one character beyond the filter that was passed
950a2d4139bSblambert  *	    i.e., cp jumps to "(filter)" upon return
951af720893Saschrijver  *	                               ^
952af720893Saschrijver  *	goto's used to discriminate error-handling based on error type
953af720893Saschrijver  *	doesn't handle extended filters (yet)
954af720893Saschrijver  *
955af720893Saschrijver  */
956af720893Saschrijver static struct ber_element *
ldap_do_parse_search_filter(struct ber_element * prev,char ** cpp)957af720893Saschrijver ldap_do_parse_search_filter(struct ber_element *prev, char **cpp)
958af720893Saschrijver {
959b89a6dc6Saschrijver 	struct ber_element *elm, *root = NULL;
9609ae551f8Saschrijver 	char *attr_desc, *attr_val, *parsed_val, *cp;
961af720893Saschrijver 	size_t len;
962af720893Saschrijver 	unsigned long type;
963af720893Saschrijver 
964af720893Saschrijver 	root = NULL;
965af720893Saschrijver 
966af720893Saschrijver 	/* cpp should pass in pointer to opening parenthesis of "(filter)" */
967af720893Saschrijver 	cp = *cpp;
968af720893Saschrijver 	if (*cp != '(')
969af720893Saschrijver 		goto syntaxfail;
970af720893Saschrijver 
971af720893Saschrijver 	switch (*++cp) {
972af720893Saschrijver 	case '&':		/* AND */
973af720893Saschrijver 	case '|':		/* OR */
974af720893Saschrijver 		if (*cp == '&')
975af720893Saschrijver 			type = LDAP_FILT_AND;
976af720893Saschrijver 		else
977af720893Saschrijver 			type = LDAP_FILT_OR;
978af720893Saschrijver 
979696b5899Stb 		if ((elm = ober_add_set(prev)) == NULL)
980af720893Saschrijver 			goto callfail;
981af720893Saschrijver 		root = elm;
982696b5899Stb 		ober_set_header(elm, BER_CLASS_CONTEXT, type);
983af720893Saschrijver 
984af720893Saschrijver 		if (*++cp != '(')		/* opening `(` of filter */
985af720893Saschrijver 			goto syntaxfail;
986af720893Saschrijver 
987af720893Saschrijver 		while (*cp == '(') {
988af720893Saschrijver 			if ((elm =
989af720893Saschrijver 			    ldap_do_parse_search_filter(elm, &cp)) == NULL)
990af720893Saschrijver 				goto bad;
991af720893Saschrijver 		}
992af720893Saschrijver 
993af720893Saschrijver 		if (*cp != ')')			/* trailing `)` of filter */
994af720893Saschrijver 			goto syntaxfail;
995af720893Saschrijver 		break;
996af720893Saschrijver 
997af720893Saschrijver 	case '!':		/* NOT */
998696b5899Stb 		if ((root = ober_add_sequence(prev)) == NULL)
999af720893Saschrijver 			goto callfail;
1000696b5899Stb 		ober_set_header(root, BER_CLASS_CONTEXT, LDAP_FILT_NOT);
1001af720893Saschrijver 
1002af720893Saschrijver 		cp++;				/* now points to sub-filter */
1003af720893Saschrijver 		if ((elm = ldap_do_parse_search_filter(root, &cp)) == NULL)
1004af720893Saschrijver 			goto bad;
1005af720893Saschrijver 
1006af720893Saschrijver 		if (*cp != ')')			/* trailing `)` of filter */
1007af720893Saschrijver 			goto syntaxfail;
1008af720893Saschrijver 		break;
1009af720893Saschrijver 
1010af720893Saschrijver 	default:	/* SIMPLE || PRESENCE */
1011af720893Saschrijver 		attr_desc = cp;
1012af720893Saschrijver 
1013af720893Saschrijver 		len = strcspn(cp, "()<>~=");
1014af720893Saschrijver 		cp += len;
1015af720893Saschrijver 		switch (*cp) {
1016af720893Saschrijver 		case '~':
1017af720893Saschrijver 			type = LDAP_FILT_APPR;
1018af720893Saschrijver 			cp++;
1019af720893Saschrijver 			break;
1020af720893Saschrijver 		case '<':
1021af720893Saschrijver 			type = LDAP_FILT_LE;
1022af720893Saschrijver 			cp++;
1023af720893Saschrijver 			break;
1024af720893Saschrijver 		case '>':
1025af720893Saschrijver 			type = LDAP_FILT_GE;
1026af720893Saschrijver 			cp++;
1027af720893Saschrijver 			break;
1028af720893Saschrijver 		case '=':
1029af720893Saschrijver 			type = LDAP_FILT_EQ;	/* assume EQ until disproven */
1030af720893Saschrijver 			break;
1031af720893Saschrijver 		case '(':
1032af720893Saschrijver 		case ')':
1033af720893Saschrijver 		default:
1034af720893Saschrijver 			goto syntaxfail;
1035af720893Saschrijver 		}
1036af720893Saschrijver 		attr_val = ++cp;
1037af720893Saschrijver 
1038af720893Saschrijver 		/* presence filter */
1039af720893Saschrijver 		if (strncmp(attr_val, "*)", 2) == 0) {
1040af720893Saschrijver 			cp++;			/* point to trailing `)` */
1041af720893Saschrijver 			if ((root =
1042696b5899Stb 			    ober_add_nstring(prev, attr_desc, len)) == NULL)
1043af720893Saschrijver 				goto bad;
1044af720893Saschrijver 
1045696b5899Stb 			ober_set_header(root, BER_CLASS_CONTEXT, LDAP_FILT_PRES);
1046af720893Saschrijver 			break;
1047af720893Saschrijver 		}
1048af720893Saschrijver 
1049696b5899Stb 		if ((root = ober_add_sequence(prev)) == NULL)
1050af720893Saschrijver 			goto callfail;
1051696b5899Stb 		ober_set_header(root, BER_CLASS_CONTEXT, type);
1052af720893Saschrijver 
1053696b5899Stb 		if ((elm = ober_add_nstring(root, attr_desc, len)) == NULL)
1054af720893Saschrijver 			goto callfail;
1055af720893Saschrijver 
1056af720893Saschrijver 		len = strcspn(attr_val, "*)");
1057af720893Saschrijver 		if (len == 0 && *cp != '*')
1058af720893Saschrijver 			goto syntaxfail;
1059af720893Saschrijver 		cp += len;
1060af720893Saschrijver 		if (*cp == '\0')
1061af720893Saschrijver 			goto syntaxfail;
1062af720893Saschrijver 
1063af720893Saschrijver 		if (*cp == '*') {	/* substring filter */
1064af720893Saschrijver 			int initial;
1065af720893Saschrijver 
1066af720893Saschrijver 			cp = attr_val;
1067af720893Saschrijver 
1068696b5899Stb 			ober_set_header(root, BER_CLASS_CONTEXT, LDAP_FILT_SUBS);
1069af720893Saschrijver 
1070696b5899Stb 			if ((elm = ober_add_sequence(elm)) == NULL)
1071af720893Saschrijver 				goto callfail;
1072af720893Saschrijver 
1073af720893Saschrijver 			for (initial = 1;; cp++, initial = 0) {
1074af720893Saschrijver 				attr_val = cp;
1075af720893Saschrijver 
1076af720893Saschrijver 				len = strcspn(attr_val, "*)");
1077af720893Saschrijver 				if (len == 0) {
1078af720893Saschrijver 					if (*cp == ')')
1079af720893Saschrijver 						break;
1080af720893Saschrijver 					else
1081af720893Saschrijver 						continue;
1082af720893Saschrijver 				}
1083af720893Saschrijver 				cp += len;
1084af720893Saschrijver 				if (*cp == '\0')
1085af720893Saschrijver 					goto syntaxfail;
1086af720893Saschrijver 
1087af720893Saschrijver 				if (initial)
1088af720893Saschrijver 					type = LDAP_FILT_SUBS_INIT;
1089af720893Saschrijver 				else if (*cp == ')')
1090af720893Saschrijver 					type = LDAP_FILT_SUBS_FIN;
1091af720893Saschrijver 				else
1092af720893Saschrijver 					type = LDAP_FILT_SUBS_ANY;
1093af720893Saschrijver 
10949ae551f8Saschrijver 				if ((parsed_val = parseval(attr_val, len)) ==
10959ae551f8Saschrijver 				    NULL)
1096af720893Saschrijver 					goto callfail;
1097696b5899Stb 				elm = ober_add_nstring(elm, parsed_val,
1098f62ce581Sblambert 				    strlen(parsed_val));
10999ae551f8Saschrijver 				free(parsed_val);
1100f62ce581Sblambert 				if (elm == NULL)
1101f62ce581Sblambert 					goto callfail;
1102696b5899Stb 				ober_set_header(elm, BER_CLASS_CONTEXT, type);
1103af720893Saschrijver 				if (type == LDAP_FILT_SUBS_FIN)
1104af720893Saschrijver 					break;
1105af720893Saschrijver 			}
1106af720893Saschrijver 			break;
1107af720893Saschrijver 		}
1108af720893Saschrijver 
1109b89a6dc6Saschrijver 		if ((parsed_val = parseval(attr_val, len)) == NULL)
1110af720893Saschrijver 			goto callfail;
1111696b5899Stb 		elm = ober_add_nstring(elm, parsed_val, strlen(parsed_val));
11129ae551f8Saschrijver 		free(parsed_val);
1113f62ce581Sblambert 		if (elm == NULL)
1114f62ce581Sblambert 			goto callfail;
1115af720893Saschrijver 		break;
1116af720893Saschrijver 	}
1117af720893Saschrijver 
1118af720893Saschrijver 	cp++;		/* now points one char beyond the trailing `)` */
1119af720893Saschrijver 
1120af720893Saschrijver 	*cpp = cp;
1121af720893Saschrijver 	return (root);
1122af720893Saschrijver 
1123af720893Saschrijver syntaxfail:		/* XXX -- error reporting */
1124af720893Saschrijver callfail:
1125af720893Saschrijver bad:
1126b89a6dc6Saschrijver 	if (root != NULL)
1127696b5899Stb 		ober_free_elements(root);
1128696b5899Stb 	ober_link_elements(prev, NULL);
1129af720893Saschrijver 	return (NULL);
1130af720893Saschrijver }
1131af720893Saschrijver 
1132af720893Saschrijver #ifdef DEBUG
1133af720893Saschrijver /*
1134af720893Saschrijver  * Display a list of ber elements.
1135af720893Saschrijver  *
1136af720893Saschrijver  */
1137af720893Saschrijver void
ldap_debug_elements(struct ber_element * root)1138af720893Saschrijver ldap_debug_elements(struct ber_element *root)
1139af720893Saschrijver {
1140af720893Saschrijver 	static int	 indent = 0;
1141af720893Saschrijver 	long long	 v;
1142af720893Saschrijver 	int		 d;
1143af720893Saschrijver 	char		*buf;
1144af720893Saschrijver 	size_t		 len;
1145af720893Saschrijver 	u_int		 i;
1146af720893Saschrijver 	int		 constructed;
1147af720893Saschrijver 	struct ber_oid	 o;
1148af720893Saschrijver 
1149af720893Saschrijver 	/* calculate lengths */
1150696b5899Stb 	ober_calc_len(root);
1151af720893Saschrijver 
1152af720893Saschrijver 	switch (root->be_encoding) {
1153af720893Saschrijver 	case BER_TYPE_SEQUENCE:
1154af720893Saschrijver 	case BER_TYPE_SET:
1155af720893Saschrijver 		constructed = root->be_encoding;
1156af720893Saschrijver 		break;
1157af720893Saschrijver 	default:
1158af720893Saschrijver 		constructed = 0;
1159af720893Saschrijver 		break;
1160af720893Saschrijver 	}
1161af720893Saschrijver 
1162af720893Saschrijver 	fprintf(stderr, "%*slen %lu ", indent, "", root->be_len);
1163af720893Saschrijver 	switch (root->be_class) {
1164af720893Saschrijver 	case BER_CLASS_UNIVERSAL:
1165af720893Saschrijver 		fprintf(stderr, "class: universal(%u) type: ", root->be_class);
1166af720893Saschrijver 		switch (root->be_type) {
1167af720893Saschrijver 		case BER_TYPE_EOC:
1168af720893Saschrijver 			fprintf(stderr, "end-of-content");
1169af720893Saschrijver 			break;
1170af720893Saschrijver 		case BER_TYPE_BOOLEAN:
1171af720893Saschrijver 			fprintf(stderr, "boolean");
1172af720893Saschrijver 			break;
1173af720893Saschrijver 		case BER_TYPE_INTEGER:
1174af720893Saschrijver 			fprintf(stderr, "integer");
1175af720893Saschrijver 			break;
1176af720893Saschrijver 		case BER_TYPE_BITSTRING:
1177af720893Saschrijver 			fprintf(stderr, "bit-string");
1178af720893Saschrijver 			break;
1179af720893Saschrijver 		case BER_TYPE_OCTETSTRING:
1180af720893Saschrijver 			fprintf(stderr, "octet-string");
1181af720893Saschrijver 			break;
1182af720893Saschrijver 		case BER_TYPE_NULL:
1183af720893Saschrijver 			fprintf(stderr, "null");
1184af720893Saschrijver 			break;
1185af720893Saschrijver 		case BER_TYPE_OBJECT:
1186af720893Saschrijver 			fprintf(stderr, "object");
1187af720893Saschrijver 			break;
1188af720893Saschrijver 		case BER_TYPE_ENUMERATED:
1189af720893Saschrijver 			fprintf(stderr, "enumerated");
1190af720893Saschrijver 			break;
1191af720893Saschrijver 		case BER_TYPE_SEQUENCE:
1192af720893Saschrijver 			fprintf(stderr, "sequence");
1193af720893Saschrijver 			break;
1194af720893Saschrijver 		case BER_TYPE_SET:
1195af720893Saschrijver 			fprintf(stderr, "set");
1196af720893Saschrijver 			break;
1197af720893Saschrijver 		}
1198af720893Saschrijver 		break;
1199af720893Saschrijver 	case BER_CLASS_APPLICATION:
1200af720893Saschrijver 		fprintf(stderr, "class: application(%u) type: ",
1201af720893Saschrijver 		    root->be_class);
1202af720893Saschrijver 		switch (root->be_type) {
1203af720893Saschrijver 		case LDAP_REQ_BIND:
1204af720893Saschrijver 			fprintf(stderr, "bind");
1205af720893Saschrijver 			break;
1206af720893Saschrijver 		case LDAP_RES_BIND:
1207af720893Saschrijver 			fprintf(stderr, "bind");
1208af720893Saschrijver 			break;
1209af720893Saschrijver 		case LDAP_REQ_UNBIND_30:
1210af720893Saschrijver 			break;
1211af720893Saschrijver 		case LDAP_REQ_SEARCH:
1212af720893Saschrijver 			fprintf(stderr, "search");
1213af720893Saschrijver 			break;
1214af720893Saschrijver 		case LDAP_RES_SEARCH_ENTRY:
1215af720893Saschrijver 			fprintf(stderr, "search_entry");
1216af720893Saschrijver 			break;
1217af720893Saschrijver 		case LDAP_RES_SEARCH_RESULT:
1218af720893Saschrijver 			fprintf(stderr, "search_result");
1219af720893Saschrijver 			break;
1220af720893Saschrijver 		case LDAP_REQ_MODIFY:
1221af720893Saschrijver 			fprintf(stderr, "modify");
1222af720893Saschrijver 			break;
1223af720893Saschrijver 		case LDAP_RES_MODIFY:
1224af720893Saschrijver 			fprintf(stderr, "modify");
1225af720893Saschrijver 			break;
1226af720893Saschrijver 		case LDAP_REQ_ADD:
1227af720893Saschrijver 			fprintf(stderr, "add");
1228af720893Saschrijver 			break;
1229af720893Saschrijver 		case LDAP_RES_ADD:
1230af720893Saschrijver 			fprintf(stderr, "add");
1231af720893Saschrijver 			break;
1232af720893Saschrijver 		case LDAP_REQ_DELETE_30:
1233af720893Saschrijver 			fprintf(stderr, "delete");
1234af720893Saschrijver 			break;
1235af720893Saschrijver 		case LDAP_RES_DELETE:
1236af720893Saschrijver 			fprintf(stderr, "delete");
1237af720893Saschrijver 			break;
1238af720893Saschrijver 		case LDAP_REQ_MODRDN:
1239af720893Saschrijver 			fprintf(stderr, "modrdn");
1240af720893Saschrijver 			break;
1241af720893Saschrijver 		case LDAP_RES_MODRDN:
1242af720893Saschrijver 			fprintf(stderr, "modrdn");
1243af720893Saschrijver 			break;
1244af720893Saschrijver 		case LDAP_REQ_COMPARE:
1245af720893Saschrijver 			fprintf(stderr, "compare");
1246af720893Saschrijver 			break;
1247af720893Saschrijver 		case LDAP_RES_COMPARE:
1248af720893Saschrijver 			fprintf(stderr, "compare");
1249af720893Saschrijver 			break;
1250af720893Saschrijver 		case LDAP_REQ_ABANDON_30:
1251af720893Saschrijver 			fprintf(stderr, "abandon");
1252af720893Saschrijver 			break;
1253af720893Saschrijver 		}
1254af720893Saschrijver 		break;
1255af720893Saschrijver 	case BER_CLASS_PRIVATE:
1256af720893Saschrijver 		fprintf(stderr, "class: private(%u) type: ", root->be_class);
125779c62c2aSrob 		fprintf(stderr, "encoding (%u) type: ", root->be_encoding);
1258af720893Saschrijver 		break;
1259af720893Saschrijver 	case BER_CLASS_CONTEXT:
1260af720893Saschrijver 		/* XXX: this is not correct */
1261af720893Saschrijver 		fprintf(stderr, "class: context(%u) type: ", root->be_class);
1262af720893Saschrijver 		switch(root->be_type) {
1263af720893Saschrijver 		case LDAP_AUTH_SIMPLE:
1264af720893Saschrijver 			fprintf(stderr, "auth simple");
1265af720893Saschrijver 			break;
1266af720893Saschrijver 		}
1267af720893Saschrijver 		break;
1268af720893Saschrijver 	default:
1269af720893Saschrijver 		fprintf(stderr, "class: <INVALID>(%u) type: ", root->be_class);
1270af720893Saschrijver 		break;
1271af720893Saschrijver 	}
127279c62c2aSrob 	fprintf(stderr, "(%u) encoding %u ",
1273af720893Saschrijver 	    root->be_type, root->be_encoding);
1274af720893Saschrijver 
1275af720893Saschrijver 	if (constructed)
1276af720893Saschrijver 		root->be_encoding = constructed;
1277af720893Saschrijver 
1278af720893Saschrijver 	switch (root->be_encoding) {
1279af720893Saschrijver 	case BER_TYPE_BOOLEAN:
1280696b5899Stb 		if (ober_get_boolean(root, &d) == -1) {
1281af720893Saschrijver 			fprintf(stderr, "<INVALID>\n");
1282af720893Saschrijver 			break;
1283af720893Saschrijver 		}
1284af720893Saschrijver 		fprintf(stderr, "%s(%d)\n", d ? "true" : "false", d);
1285af720893Saschrijver 		break;
1286af720893Saschrijver 	case BER_TYPE_INTEGER:
1287696b5899Stb 		if (ober_get_integer(root, &v) == -1) {
1288af720893Saschrijver 			fprintf(stderr, "<INVALID>\n");
1289af720893Saschrijver 			break;
1290af720893Saschrijver 		}
1291af720893Saschrijver 		fprintf(stderr, "value %lld\n", v);
1292af720893Saschrijver 		break;
1293af720893Saschrijver 	case BER_TYPE_ENUMERATED:
1294696b5899Stb 		if (ober_get_enumerated(root, &v) == -1) {
1295af720893Saschrijver 			fprintf(stderr, "<INVALID>\n");
1296af720893Saschrijver 			break;
1297af720893Saschrijver 		}
1298af720893Saschrijver 		fprintf(stderr, "value %lld\n", v);
1299af720893Saschrijver 		break;
1300af720893Saschrijver 	case BER_TYPE_BITSTRING:
1301696b5899Stb 		if (ober_get_bitstring(root, (void *)&buf, &len) == -1) {
1302af720893Saschrijver 			fprintf(stderr, "<INVALID>\n");
1303af720893Saschrijver 			break;
1304af720893Saschrijver 		}
1305af720893Saschrijver 		fprintf(stderr, "hexdump ");
1306af720893Saschrijver 		for (i = 0; i < len; i++)
1307af720893Saschrijver 			fprintf(stderr, "%02x", buf[i]);
1308af720893Saschrijver 		fprintf(stderr, "\n");
1309af720893Saschrijver 		break;
1310af720893Saschrijver 	case BER_TYPE_OBJECT:
1311696b5899Stb 		if (ober_get_oid(root, &o) == -1) {
1312af720893Saschrijver 			fprintf(stderr, "<INVALID>\n");
1313af720893Saschrijver 			break;
1314af720893Saschrijver 		}
1315af720893Saschrijver 		fprintf(stderr, "\n");
1316af720893Saschrijver 		break;
1317af720893Saschrijver 	case BER_TYPE_OCTETSTRING:
1318696b5899Stb 		if (ober_get_nstring(root, (void *)&buf, &len) == -1) {
1319af720893Saschrijver 			fprintf(stderr, "<INVALID>\n");
1320af720893Saschrijver 			break;
1321af720893Saschrijver 		}
132260f5961dSreyk 		fprintf(stderr, "string \"%.*s\"\n",  (int)len, buf);
1323af720893Saschrijver 		break;
1324af720893Saschrijver 	case BER_TYPE_NULL:	/* no payload */
1325af720893Saschrijver 	case BER_TYPE_EOC:
1326af720893Saschrijver 	case BER_TYPE_SEQUENCE:
1327af720893Saschrijver 	case BER_TYPE_SET:
1328af720893Saschrijver 	default:
1329af720893Saschrijver 		fprintf(stderr, "\n");
1330af720893Saschrijver 		break;
1331af720893Saschrijver 	}
1332af720893Saschrijver 
1333af720893Saschrijver 	if (constructed && root->be_sub) {
1334af720893Saschrijver 		indent += 2;
1335af720893Saschrijver 		ldap_debug_elements(root->be_sub);
1336af720893Saschrijver 		indent -= 2;
1337af720893Saschrijver 	}
1338af720893Saschrijver 	if (root->be_next)
1339af720893Saschrijver 		ldap_debug_elements(root->be_next);
1340af720893Saschrijver }
1341af720893Saschrijver #endif
1342af720893Saschrijver 
1343af720893Saschrijver /*
13446c9ae825Sschwarze  * Strip UTF-8 down to ASCII without validation.
1345af720893Saschrijver  * notes:
1346af720893Saschrijver  *	non-ASCII characters are displayed as '?'
1347af720893Saschrijver  *	the argument u should be a NULL terminated sequence of UTF-8 bytes.
1348af720893Saschrijver  */
1349af720893Saschrijver char *
utoa(char * u)1350af720893Saschrijver utoa(char *u)
1351af720893Saschrijver {
1352af720893Saschrijver 	int	 len, i, j;
1353af720893Saschrijver 	char	*str;
1354af720893Saschrijver 
1355af720893Saschrijver 	/* calculate the length to allocate */
13566c9ae825Sschwarze 	for (len = 0, i = 0; u[i] != '\0'; i++)
13576c9ae825Sschwarze 		if (!isu8cont(u[i]))
1358af720893Saschrijver 			len++;
1359af720893Saschrijver 
13609ae551f8Saschrijver 	if ((str = calloc(len + 1, sizeof(char))) == NULL)
13619ae551f8Saschrijver 		return NULL;
1362af720893Saschrijver 
1363af720893Saschrijver 	/* copy the ASCII characters to the newly allocated string */
13646c9ae825Sschwarze 	for (i = 0, j = 0; u[i] != '\0'; i++)
13656c9ae825Sschwarze 		if (!isu8cont(u[i]))
13666c9ae825Sschwarze 			str[j++] = isascii((unsigned char)u[i]) ? u[i] : '?';
1367af720893Saschrijver 
1368af720893Saschrijver 	return str;
1369af720893Saschrijver }
13709ae551f8Saschrijver 
13716c9ae825Sschwarze static int
isu8cont(unsigned char c)13726c9ae825Sschwarze isu8cont(unsigned char c)
13736c9ae825Sschwarze {
13746c9ae825Sschwarze 	return (c & (0x80 | 0x40)) == 0x80;
13756c9ae825Sschwarze }
13766c9ae825Sschwarze 
13779ae551f8Saschrijver /*
13789ae551f8Saschrijver  * Parse a LDAP value
13799ae551f8Saschrijver  * notes:
138008529037Sderaadt  *	the argument p should be a NUL-terminated sequence of ASCII bytes
13819ae551f8Saschrijver  */
13829ae551f8Saschrijver char *
parseval(char * p,size_t len)13839ae551f8Saschrijver parseval(char *p, size_t len)
13849ae551f8Saschrijver {
13859ae551f8Saschrijver 	char	 hex[3];
138670281e88Sjmatthew 	char	*buffer;
138770281e88Sjmatthew 	size_t	 i, j;
13889ae551f8Saschrijver 
138970281e88Sjmatthew 	if ((buffer = calloc(1, len + 1)) == NULL)
13909ae551f8Saschrijver 		return NULL;
13919ae551f8Saschrijver 
1392a2d4139bSblambert 	for (i = j = 0; j < len; i++) {
139370281e88Sjmatthew 		if (p[j] == '\\') {
139470281e88Sjmatthew 			strlcpy(hex, p + j + 1, sizeof(hex));
13959ae551f8Saschrijver 			buffer[i] = (char)strtoumax(hex, NULL, 16);
13969ae551f8Saschrijver 			j += 3;
13979ae551f8Saschrijver 		} else {
139870281e88Sjmatthew 			buffer[i] = p[j];
13999ae551f8Saschrijver 			j++;
14009ae551f8Saschrijver 		}
14019ae551f8Saschrijver 	}
14029ae551f8Saschrijver 
14039ae551f8Saschrijver 	return buffer;
14049ae551f8Saschrijver }
1405bc9dda0eSblambert 
140642013679Saschrijver int
aldap_get_errno(struct aldap * a,const char ** estr)140742013679Saschrijver aldap_get_errno(struct aldap *a, const char **estr)
140842013679Saschrijver {
140942013679Saschrijver 	switch (a->err) {
141042013679Saschrijver 	case ALDAP_ERR_SUCCESS:
141142013679Saschrijver 		*estr = "success";
141242013679Saschrijver 		break;
141342013679Saschrijver 	case ALDAP_ERR_PARSER_ERROR:
141442013679Saschrijver 		*estr = "parser failed";
141542013679Saschrijver 		break;
141642013679Saschrijver 	case ALDAP_ERR_INVALID_FILTER:
141742013679Saschrijver 		*estr = "invalid filter";
141842013679Saschrijver 		break;
141942013679Saschrijver 	case ALDAP_ERR_OPERATION_FAILED:
142042013679Saschrijver 		*estr = "operation failed";
142142013679Saschrijver 		break;
142232814761Sjmatthew 	case ALDAP_ERR_TLS_ERROR:
142332814761Sjmatthew 		*estr = tls_error(a->tls);
142432814761Sjmatthew 		break;
142542013679Saschrijver 	default:
142642013679Saschrijver 		*estr = "unknown";
142742013679Saschrijver 		break;
142842013679Saschrijver 	}
142942013679Saschrijver 	return (a->err);
143042013679Saschrijver }
1431