Bug Summary

File:src/libexec/login_ldap/aldap.c
Warning:line 832, column 2
Potential leak of memory pointed to by 'lu'

Annotated Source Code

Press '?' to see keyboard shortcuts

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