Bug Summary

File:src/libexec/login_ldap/util.c
Warning:line 362, column 10
The left operand of '==' is a garbage value

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 util.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/util.c
1/*
2 * $OpenBSD: util.c,v 1.3 2021/09/02 20:57:58 deraadt Exp $
3 * Copyright (c) 2002 Institute for Open Systems Technology Australia (IFOST)
4 * Copyright (c) 2007 Michael Erdely <merdely@openbsd.org>
5 * Copyright (c) 2019 Martijn van Duren <martijn@openbsd.org>
6 *
7 * All rights reserved.
8 *
9 * Redistribution and use in source and binary forms, with or without
10 * modification, are permitted provided that the following conditions
11 * are met:
12 * 1. Redistributions of source code must retain the above copyright
13 * notice, this list of conditions and the following disclaimer.
14 * 2. Redistributions in binary form must reproduce the above copyright
15 * notice, this list of conditions and the following disclaimer in the
16 * documentation and/or other materials provided with the distribution.
17 * 3. The name of the author may not be used to endorse or promote products
18 * derived from this software without specific prior written permission.
19 *
20 * THIS SOFTWARE IS PROVIDED ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES,
21 * INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY
22 * AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL
23 * THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
24 * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
25 * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS;
26 * OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY,
27 * WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR
28 * OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF
29 * ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
30 */
31
32#include <sys/socket.h>
33#include <limits.h>
34#include <sys/time.h>
35#include <sys/types.h>
36#include <sys/stat.h>
37#include <sys/un.h>
38#include <netinet/in.h>
39
40#include <ctype.h>
41#include <grp.h>
42#include <unistd.h>
43#include <stdio.h>
44#include <stdarg.h>
45#include <stdlib.h>
46#include <string.h>
47#include <limits.h>
48#include <errno(*__errno()).h>
49#include <syslog.h>
50#include <tls.h>
51#include <netdb.h>
52#include <login_cap.h>
53
54#include "aldap.h"
55#include "login_ldap.h"
56
57int debug = 0;
58
59static int getscope(char *);
60
61void
62dlog(int d, char *fmt, ...)
63{
64 va_list ap;
65
66 /*
67 * if debugging is on, print everthing to stderr
68 * otherwise, syslog it if d = 0. messing with
69 * newlines means there wont be newlines in stuff
70 * that goes to syslog.
71 */
72
73 va_start(ap, fmt)__builtin_va_start(ap, fmt);
74 if (debug) {
75 vfprintf(stderr(&__sF[2]), fmt, ap);
76 fputc('\n', stderr(&__sF[2]));
77 } else if (d == 0)
78 vsyslog(LOG_WARNING4, fmt, ap);
79
80 va_end(ap)__builtin_va_end(ap);
81}
82
83const char *
84ldap_resultcode(enum result_code code)
85{
86#define CODE(_X)case 0x40:return ("_X") case _X0x40:return (#_X0x40)
87 switch (code) {
88 CODE(LDAP_SUCCESS)case LDAP_SUCCESS:return ("LDAP_SUCCESS");
89 CODE(LDAP_OPERATIONS_ERROR)case LDAP_OPERATIONS_ERROR:return ("LDAP_OPERATIONS_ERROR");
90 CODE(LDAP_PROTOCOL_ERROR)case LDAP_PROTOCOL_ERROR:return ("LDAP_PROTOCOL_ERROR");
91 CODE(LDAP_TIMELIMIT_EXCEEDED)case LDAP_TIMELIMIT_EXCEEDED:return ("LDAP_TIMELIMIT_EXCEEDED"
)
;
92 CODE(LDAP_SIZELIMIT_EXCEEDED)case LDAP_SIZELIMIT_EXCEEDED:return ("LDAP_SIZELIMIT_EXCEEDED"
)
;
93 CODE(LDAP_COMPARE_FALSE)case LDAP_COMPARE_FALSE:return ("LDAP_COMPARE_FALSE");
94 CODE(LDAP_COMPARE_TRUE)case LDAP_COMPARE_TRUE:return ("LDAP_COMPARE_TRUE");
95 CODE(LDAP_STRONG_AUTH_NOT_SUPPORTED)case LDAP_STRONG_AUTH_NOT_SUPPORTED:return ("LDAP_STRONG_AUTH_NOT_SUPPORTED"
)
;
96 CODE(LDAP_STRONG_AUTH_REQUIRED)case LDAP_STRONG_AUTH_REQUIRED:return ("LDAP_STRONG_AUTH_REQUIRED"
)
;
97 CODE(LDAP_REFERRAL)case LDAP_REFERRAL:return ("LDAP_REFERRAL");
98 CODE(LDAP_ADMINLIMIT_EXCEEDED)case LDAP_ADMINLIMIT_EXCEEDED:return ("LDAP_ADMINLIMIT_EXCEEDED"
)
;
99 CODE(LDAP_UNAVAILABLE_CRITICAL_EXTENSION)case LDAP_UNAVAILABLE_CRITICAL_EXTENSION:return ("LDAP_UNAVAILABLE_CRITICAL_EXTENSION"
)
;
100 CODE(LDAP_CONFIDENTIALITY_REQUIRED)case LDAP_CONFIDENTIALITY_REQUIRED:return ("LDAP_CONFIDENTIALITY_REQUIRED"
)
;
101 CODE(LDAP_SASL_BIND_IN_PROGRESS)case LDAP_SASL_BIND_IN_PROGRESS:return ("LDAP_SASL_BIND_IN_PROGRESS"
)
;
102 CODE(LDAP_NO_SUCH_ATTRIBUTE)case LDAP_NO_SUCH_ATTRIBUTE:return ("LDAP_NO_SUCH_ATTRIBUTE");
103 CODE(LDAP_UNDEFINED_TYPE)case LDAP_UNDEFINED_TYPE:return ("LDAP_UNDEFINED_TYPE");
104 CODE(LDAP_INAPPROPRIATE_MATCHING)case LDAP_INAPPROPRIATE_MATCHING:return ("LDAP_INAPPROPRIATE_MATCHING"
)
;
105 CODE(LDAP_CONSTRAINT_VIOLATION)case LDAP_CONSTRAINT_VIOLATION:return ("LDAP_CONSTRAINT_VIOLATION"
)
;
106 CODE(LDAP_TYPE_OR_VALUE_EXISTS)case LDAP_TYPE_OR_VALUE_EXISTS:return ("LDAP_TYPE_OR_VALUE_EXISTS"
)
;
107 CODE(LDAP_INVALID_SYNTAX)case LDAP_INVALID_SYNTAX:return ("LDAP_INVALID_SYNTAX");
108 CODE(LDAP_NO_SUCH_OBJECT)case LDAP_NO_SUCH_OBJECT:return ("LDAP_NO_SUCH_OBJECT");
109 CODE(LDAP_ALIAS_PROBLEM)case LDAP_ALIAS_PROBLEM:return ("LDAP_ALIAS_PROBLEM");
110 CODE(LDAP_INVALID_DN_SYNTAX)case LDAP_INVALID_DN_SYNTAX:return ("LDAP_INVALID_DN_SYNTAX");
111 CODE(LDAP_ALIAS_DEREF_PROBLEM)case LDAP_ALIAS_DEREF_PROBLEM:return ("LDAP_ALIAS_DEREF_PROBLEM"
)
;
112 CODE(LDAP_INAPPROPRIATE_AUTH)case LDAP_INAPPROPRIATE_AUTH:return ("LDAP_INAPPROPRIATE_AUTH"
)
;
113 CODE(LDAP_INVALID_CREDENTIALS)case LDAP_INVALID_CREDENTIALS:return ("LDAP_INVALID_CREDENTIALS"
)
;
114 CODE(LDAP_INSUFFICIENT_ACCESS)case LDAP_INSUFFICIENT_ACCESS:return ("LDAP_INSUFFICIENT_ACCESS"
)
;
115 CODE(LDAP_BUSY)case LDAP_BUSY:return ("LDAP_BUSY");
116 CODE(LDAP_UNAVAILABLE)case LDAP_UNAVAILABLE:return ("LDAP_UNAVAILABLE");
117 CODE(LDAP_UNWILLING_TO_PERFORM)case LDAP_UNWILLING_TO_PERFORM:return ("LDAP_UNWILLING_TO_PERFORM"
)
;
118 CODE(LDAP_LOOP_DETECT)case LDAP_LOOP_DETECT:return ("LDAP_LOOP_DETECT");
119 CODE(LDAP_NAMING_VIOLATION)case LDAP_NAMING_VIOLATION:return ("LDAP_NAMING_VIOLATION");
120 CODE(LDAP_OBJECT_CLASS_VIOLATION)case LDAP_OBJECT_CLASS_VIOLATION:return ("LDAP_OBJECT_CLASS_VIOLATION"
)
;
121 CODE(LDAP_NOT_ALLOWED_ON_NONLEAF)case LDAP_NOT_ALLOWED_ON_NONLEAF:return ("LDAP_NOT_ALLOWED_ON_NONLEAF"
)
;
122 CODE(LDAP_NOT_ALLOWED_ON_RDN)case LDAP_NOT_ALLOWED_ON_RDN:return ("LDAP_NOT_ALLOWED_ON_RDN"
)
;
123 CODE(LDAP_ALREADY_EXISTS)case LDAP_ALREADY_EXISTS:return ("LDAP_ALREADY_EXISTS");
124 CODE(LDAP_NO_OBJECT_CLASS_MODS)case LDAP_NO_OBJECT_CLASS_MODS:return ("LDAP_NO_OBJECT_CLASS_MODS"
)
;
125 CODE(LDAP_AFFECTS_MULTIPLE_DSAS)case LDAP_AFFECTS_MULTIPLE_DSAS:return ("LDAP_AFFECTS_MULTIPLE_DSAS"
)
;
126 CODE(LDAP_OTHER)case LDAP_OTHER:return ("LDAP_OTHER");
127 }
128
129 return ("UNKNOWN_ERROR");
130};
131
132
133static int
134parse_server_line(char *buf, struct aldap_url *s)
135{
136 /**
137 * host=[<protocol>://]<hostname>[:port]
138 *
139 * must have a hostname
140 * protocol can be "ldap", "ldaps", "ldap+tls" or "ldapi"
141 * for ldap and ldap+tls, port defaults to 389
142 * for ldaps, port defaults to 636
143 */
144
145 if (buf == NULL((void*)0)) {
146 dlog(1, "%s got NULL buf!", __func__);
147 return 0;
148 }
149
150 dlog(1, "parse_server_line buf = %s", buf);
151
152 memset(s, 0, sizeof(*s));
153
154 if (aldap_parse_url(buf, s) == -1) {
155 dlog(0, "failed to parse host %s", buf);
156 return 0;
157 }
158
159 if (s->protocol == -1)
160 s->protocol = LDAP;
161 if (s->protocol != LDAPI && s->port == 0) {
162 if (s->protocol == LDAPS)
163 s->port = 636;
164 else
165 s->port = 389;
166 }
167
168 return 1;
169}
170
171int
172parse_conf(struct auth_ctx *ctx, const char *path)
173{
174 FILE *cf;
175 struct stat sb;
176 struct group *grp;
177 struct aldap_urlq *url;
178 char *buf = NULL((void*)0), *key, *value, *tail;
179 const char *errstr;
180 size_t buflen = 0;
181 ssize_t linelen;
182
183 dlog(1, "Parsing config file '%s'", path);
184
185 if ((cf = fopen(path, "r")) == NULL((void*)0)) {
186 dlog(0, "Can't open config file: %s", strerror(errno(*__errno())));
187 return 0;
188 }
189 if (fstat(fileno(cf)(!__isthreaded ? ((cf)->_file) : (fileno)(cf)), &sb) == -1) {
190 dlog(0, "Can't stat config file: %s", strerror(errno(*__errno())));
191 return 0;
192 }
193 if ((grp = getgrnam("auth")) == NULL((void*)0)) {
194 dlog(0, "Can't find group auth");
195 return 0;
196 }
197 if (sb.st_uid != 0 ||
198 sb.st_gid != grp->gr_gid ||
199 (sb.st_mode & S_IRWXU0000700) != (S_IRUSR0000400 | S_IWUSR0000200) ||
200 (sb.st_mode & S_IRWXG0000070) != S_IRGRP0000040 ||
201 (sb.st_mode & S_IRWXO0000007) != 0) {
202 dlog(0, "Wrong permissions for config file");
203 return 0;
204 }
205
206 /* We need a default scope */
207 ctx->gscope = ctx->scope = getscope(NULL((void*)0));
208
209 while ((linelen = getline(&buf, &buflen, cf)) != -1) {
210 if (buf[linelen - 1] == '\n')
211 buf[linelen -1] = '\0';
212 /* Allow leading spaces */
213 for (key = buf; key[0] != '\0' && isspace(key[0]); key++)
214 continue;
215 /* Comment or white lines */
216 if (key[0] == '#' || key[0] == '\0')
217 continue;
218 if ((tail = value = strchr(key, '=')) == NULL((void*)0)) {
219 dlog(0, "Missing value for option '%s'", key);
220 return 0;
221 }
222 value++;
223 /* Don't fail over trailing key spaces */
224 for (tail--; isspace(tail[0]); tail--)
225 continue;
226 tail[1] = '\0';
227 if (strcmp(key, "host") == 0) {
228 if ((url = calloc(1, sizeof(*url))) == NULL((void*)0)) {
229 dlog(0, "Failed to add %s: %s", value,
230 strerror(errno(*__errno())));
231 continue;
232 }
233 if (parse_server_line(value, &(url->s)) == 0) {
234 free(url);
235 return 0;
236 }
237 TAILQ_INSERT_TAIL(&(ctx->s), url, entries)do { (url)->entries.tqe_next = ((void*)0); (url)->entries
.tqe_prev = (&(ctx->s))->tqh_last; *(&(ctx->
s))->tqh_last = (url); (&(ctx->s))->tqh_last = &
(url)->entries.tqe_next; } while (0)
;
238 } else if (strcmp(key, "basedn") == 0) {
239 free(ctx->basedn);
240 if ((ctx->basedn = strdup(value)) == NULL((void*)0)) {
241 dlog(0, "%s", strerror(errno(*__errno())));
242 return 0;
243 }
244 } else if (strcmp(key, "binddn") == 0) {
245 free(ctx->binddn);
246 if ((ctx->binddn = parse_filter(ctx, value)) == NULL((void*)0))
247 return 0;
248 } else if (strcmp(key, "bindpw") == 0) {
249 free(ctx->bindpw);
250 if ((ctx->bindpw = strdup(value)) == NULL((void*)0)) {
251 dlog(0, "%s", strerror(errno(*__errno())));
252 return 0;
253 }
254 } else if (strcmp(key, "timeout") == 0) {
255 ctx->timeout = strtonum(value, 0, INT_MAX2147483647, &errstr);
256 if (ctx->timeout == 0 && errstr != NULL((void*)0)) {
257 dlog(0, "timeout %s", errstr);
258 return 0;
259 }
260 } else if (strcmp(key, "filter") == 0) {
261 free(ctx->filter);
262 if ((ctx->filter = parse_filter(ctx, value)) == NULL((void*)0))
263 return 0;
264 } else if (strcmp(key, "scope") == 0) {
265 if ((ctx->scope = getscope(value)) == -1)
266 return 0;
267 } else if (strcmp(key, "cacert") == 0) {
268 free(ctx->cacert);
269 if ((ctx->cacert = strdup(value)) == NULL((void*)0)) {
270 dlog(0, "%s", strerror(errno(*__errno())));
271 return 0;
272 }
273 } else if (strcmp(key, "cacertdir") == 0) {
274 free(ctx->cacertdir);
275 if ((ctx->cacertdir = strdup(value)) == NULL((void*)0)) {
276 dlog(0, "%s", strerror(errno(*__errno())));
277 return 0;
278 }
279 } else if (strcmp(key, "gbasedn") == 0) {
280 free(ctx->gbasedn);
281 if ((ctx->gbasedn = strdup(value)) == NULL((void*)0)) {
282 dlog(0, "%s", strerror(errno(*__errno())));
283 return 0;
284 }
285 } else if (strcmp(key, "gfilter") == 0) {
286 free(ctx->gfilter);
287 if ((ctx->gfilter = strdup(value)) == NULL((void*)0)) {
288 dlog(0, "%s", strerror(errno(*__errno())));
289 return 0;
290 }
291 } else if (strcmp(key, "gscope") == 0) {
292 if ((ctx->scope = getscope(value)) == -1)
293 return 0;
294 } else {
295 dlog(0, "Unknown option '%s'", key);
296 return 0;
297 }
298 }
299 if (ferror(cf)(!__isthreaded ? (((cf)->_flags & 0x0040) != 0) : (ferror
)(cf))
) {
300 dlog(0, "Can't read config file: %s", strerror(errno(*__errno())));
301 return 0;
302 }
303 if (TAILQ_EMPTY(&(ctx->s))(((&(ctx->s))->tqh_first) == ((void*)0))) {
304 dlog(0, "Missing host");
305 return 0;
306 }
307 if (ctx->basedn == NULL((void*)0) && ctx->binddn == NULL((void*)0)) {
308 dlog(0, "Missing basedn or binddn");
309 return 0;
310 }
311 return 1;
312}
313
314int
315do_conn(struct auth_ctx *ctx, struct aldap_url *url)
316{
317 struct addrinfo ai, *res, *res0;
318 struct sockaddr_un un;
319 struct aldap_message *m;
320 struct tls_config *tls_config;
321 const char *errstr;
322 char port[6];
323 int fd, code;
4
'fd' declared without an initial value
324
325 dlog(1, "host %s, port %d", url->host, url->port);
326
327 if (url->protocol == LDAPI) {
5
Assuming field 'protocol' is not equal to LDAPI
6
Taking false branch
328 memset(&un, 0, sizeof(un));
329 un.sun_family = AF_UNIX1;
330 if (strlcpy(un.sun_path, url->host,
331 sizeof(un.sun_path)) >= sizeof(un.sun_path)) {
332 dlog(0, "socket '%s' too long", url->host);
333 return 0;
334 }
335 if ((fd = socket(AF_UNIX1, SOCK_STREAM1, 0)) == -1 ||
336 connect(fd, (struct sockaddr *)&un, sizeof(un)) == -1) {
337 dlog(0, "can't create socket '%s'", url->host);
338 return 0;
339 }
340 } else {
341 memset(&ai, 0, sizeof(ai));
342 ai.ai_family = AF_UNSPEC0;
343 ai.ai_socktype = SOCK_STREAM1;
344 ai.ai_protocol = IPPROTO_TCP6;
345 (void)snprintf(port, sizeof(port), "%u", url->port);
346 if ((code = getaddrinfo(url->host, port,
7
Assuming the condition is false
8
Taking false branch
347 &ai, &res0)) != 0) {
348 dlog(0, "%s", gai_strerror(code));
349 return 0;
350 }
351 for (res = res0; res; res = res->ai_next, fd = -1) {
9
Loop condition is false. Execution continues on line 361
352 if ((fd = socket(res->ai_family, res->ai_socktype,
353 res->ai_protocol)) == -1)
354 continue;
355
356 if (connect(fd, res->ai_addr, res->ai_addrlen) >= 0)
357 break;
358
359 close(fd);
360 }
361 freeaddrinfo(res0);
362 if (fd == -1)
10
The left operand of '==' is a garbage value
363 return 0;
364 }
365
366 ctx->ld = aldap_init(fd);
367 if (ctx->ld == NULL((void*)0)) {
368 dlog(0, "aldap_open(%s:%hd) failed", url->host, url->port);
369 return 0;
370 }
371
372 dlog(1, "connect success!");
373
374 if (url->protocol == LDAPTLS) {
375 dlog(1, "starttls!");
376 if (aldap_req_starttls(ctx->ld) == -1) {
377 dlog(0, "failed to request STARTTLS");
378 goto fail;
379 }
380
381 if ((m = aldap_parse(ctx->ld)) == NULL((void*)0)) {
382 dlog(0, "failed to parse STARTTLS response");
383 goto fail;
384 }
385
386 if (ctx->ld->msgid != m->msgid ||
387 (code = aldap_get_resultcode(m)) != LDAP_SUCCESS) {
388 dlog(0, "STARTTLS failed: %s(%d)",
389 ldap_resultcode(code), code);
390 aldap_freemsg(m);
391 goto fail;
392 }
393 aldap_freemsg(m);
394 }
395 if (url->protocol == LDAPTLS || url->protocol == LDAPS) {
396 dlog(1, "%s: starting TLS", __func__);
397
398 if ((tls_config = tls_config_new()) == NULL((void*)0)) {
399 dlog(0, "TLS config failed");
400 goto fail;
401 }
402
403 if (ctx->cacert != NULL((void*)0) &&
404 tls_config_set_ca_file(tls_config, ctx->cacert) == -1) {
405 dlog(0, "Failed to set ca file %s", ctx->cacert);
406 goto fail;
407 }
408 if (ctx->cacertdir != NULL((void*)0) &&
409 tls_config_set_ca_path(tls_config, ctx->cacertdir) == -1) {
410 dlog(0, "Failed to set ca dir %s", ctx->cacertdir);
411 goto fail;
412 }
413
414 if (aldap_tls(ctx->ld, tls_config, url->host) < 0) {
415 aldap_get_errno(ctx->ld, &errstr);
416 dlog(0, "TLS failed: %s", errstr);
417 goto fail;
418 }
419 }
420 return 1;
421fail:
422 aldap_close(ctx->ld);
423 return 0;
424}
425
426int
427conn(struct auth_ctx *ctx)
428{
429 struct aldap_urlq *url;
430
431 TAILQ_FOREACH(url, &(ctx->s), entries)for((url) = ((&(ctx->s))->tqh_first); (url) != ((void
*)0); (url) = ((url)->entries.tqe_next))
{
1
Assuming 'url' is not equal to null
2
Loop condition is true. Entering loop body
432 if (do_conn(ctx, &(url->s)))
3
Calling 'do_conn'
433 return 1;
434 }
435
436 /* all the urls have failed */
437 return 0;
438}
439
440static int
441getscope(char *scope)
442{
443 if (scope == NULL((void*)0) || scope[0] == '\0')
444 return LDAP_SCOPE_SUBTREE;
445
446 if (strcmp(scope, "base") == 0)
447 return LDAP_SCOPE_BASE;
448 else if (strcmp(scope, "one") == 0)
449 return LDAP_SCOPE_ONELEVEL;
450 else if (strcmp(scope, "sub") == 0)
451 return LDAP_SCOPE_SUBTREE;
452
453 dlog(0, "Invalid scope");
454 return -1;
455}
456
457/*
458 * Convert format specifiers from the filter in login.conf to their
459 * real values. return the new filter in the filter argument.
460 */
461char *
462parse_filter(struct auth_ctx *ctx, const char *str)
463{
464 char tmp[PATH_MAX1024];
465 char hostname[HOST_NAME_MAX255+1];
466 const char *p;
467 char *q;
468
469 if (str == NULL((void*)0))
470 return NULL((void*)0);
471
472 /*
473 * copy over from str to q, if we hit a %, substitute the real value,
474 * if we hit a NULL, its the end of the filter string
475 */
476 for (p = str, q = tmp; p[0] != '\0' &&
477 ((size_t)(q - tmp) < sizeof(tmp)); p++) {
478 if (p[0] == '%') {
479 p++;
480
481 /* Make sure we can find the end of tmp for strlcat */
482 q[0] = '\0';
483
484 /*
485 * Don't need to check strcat for truncation, since we
486 * will bail on the next iteration
487 */
488 switch (p[0]) {
489 case 'u': /* username */
490 q = tmp + strlcat(tmp, ctx->user, sizeof(tmp));
491 break;
492 case 'h': /* hostname */
493 if (gethostname(hostname, sizeof(hostname)) ==
494 -1) {
495 dlog(0, "couldn't get host name for "
496 "%%h %s", strerror(errno(*__errno())));
497 return NULL((void*)0);
498 }
499 q = tmp + strlcat(tmp, hostname, sizeof(tmp));
500 break;
501 case 'd': /* user dn */
502 if (ctx->userdn == NULL((void*)0)) {
503 dlog(0, "no userdn has been recorded");
504 return 0;
505 }
506 q = tmp + strlcat(tmp, ctx->userdn,
507 sizeof(tmp));
508 break;
509 case '%': /* literal % */
510 q[0] = p[0];
511 q++;
512 break;
513 default:
514 dlog(0, "%s: invalid filter specifier",
515 __func__);
516 return NULL((void*)0);
517 }
518 } else {
519 q[0] = p[0];
520 q++;
521 }
522 }
523 if ((size_t) (q - tmp) >= sizeof(tmp)) {
524 dlog(0, "filter string too large, unable to process: %s", str);
525 return NULL((void*)0);
526 }
527
528 q[0] = '\0';
529 q = strdup(tmp);
530 if (q == NULL((void*)0)) {
531 dlog(0, "%s", strerror(errno(*__errno())));
532 return NULL((void*)0);
533 }
534
535 return q;
536}