File: | src/usr.sbin/ypldap/ldapclient.c |
Warning: | line 385, column 2 Value stored to 'dns_pid' is never read |
Press '?' to see keyboard shortcuts
Keyboard shortcuts:
1 | /* $OpenBSD: ldapclient.c,v 1.43 2019/06/28 13:32:52 deraadt Exp $ */ |
2 | |
3 | /* |
4 | * Copyright (c) 2008 Alexander Schrijver <aschrijver@openbsd.org> |
5 | * Copyright (c) 2008 Pierre-Yves Ritschard <pyr@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 <sys/types.h> |
21 | #include <sys/queue.h> |
22 | #include <sys/socket.h> |
23 | #include <sys/tree.h> |
24 | |
25 | #include <netinet/in.h> |
26 | #include <arpa/inet.h> |
27 | |
28 | #include <netdb.h> |
29 | #include <errno(*__errno()).h> |
30 | #include <err.h> |
31 | #include <signal.h> |
32 | #include <event.h> |
33 | #include <fcntl.h> |
34 | #include <unistd.h> |
35 | #include <pwd.h> |
36 | #include <stdio.h> |
37 | #include <stdlib.h> |
38 | #include <string.h> |
39 | #include <limits.h> |
40 | |
41 | #include "aldap.h" |
42 | #include "log.h" |
43 | #include "ypldap.h" |
44 | |
45 | void client_sig_handler(int, short, void *); |
46 | void client_dispatch_dns(int, short, void *); |
47 | void client_dispatch_parent(int, short, void *); |
48 | void client_shutdown(void); |
49 | void client_connect(int, short, void *); |
50 | void client_configure(struct env *); |
51 | void client_periodic_update(int, short, void *); |
52 | int client_build_req(struct idm *, struct idm_req *, struct aldap_message *, |
53 | int, int); |
54 | int client_search_idm(struct env *, struct idm *, struct aldap *, |
55 | char **, char *, int, int, enum imsg_type); |
56 | int client_try_idm(struct env *, struct idm *); |
57 | void client_addr_init(struct idm *); |
58 | int client_addr_free(struct idm *); |
59 | |
60 | struct aldap *client_aldap_open(struct ypldap_addr_list *); |
61 | |
62 | /* |
63 | * dummy wrapper to provide aldap_init with its fd's. |
64 | */ |
65 | struct aldap * |
66 | client_aldap_open(struct ypldap_addr_list *addr) |
67 | { |
68 | int fd = -1; |
69 | struct ypldap_addr *p; |
70 | struct aldap *al; |
71 | |
72 | TAILQ_FOREACH(p, addr, next)for((p) = ((addr)->tqh_first); (p) != ((void*)0); (p) = (( p)->next.tqe_next)) { |
73 | char hbuf[NI_MAXHOST256], sbuf[NI_MAXSERV32]; |
74 | struct sockaddr *sa = (struct sockaddr *)&p->ss; |
75 | |
76 | if (getnameinfo(sa, SA_LEN(sa)((sa)->sa_len), hbuf, sizeof(hbuf), sbuf, |
77 | sizeof(sbuf), NI_NUMERICHOST1 | NI_NUMERICSERV2)) |
78 | errx(1, "could not get numeric hostname"); |
79 | |
80 | if ((fd = socket(sa->sa_family, SOCK_STREAM1, 0)) == -1) |
81 | return NULL((void*)0); |
82 | |
83 | if (connect(fd, sa, SA_LEN(sa)((sa)->sa_len)) == 0) |
84 | break; |
85 | |
86 | warn("connect to %s port %s (%s) failed", hbuf, sbuf, "tcp"); |
87 | close(fd); |
88 | fd = -1; |
89 | } |
90 | |
91 | if (fd == -1) |
92 | return NULL((void*)0); |
93 | |
94 | al = aldap_init(fd); |
95 | if (al == NULL((void*)0)) |
96 | close(fd); |
97 | return al; |
98 | } |
99 | |
100 | void |
101 | client_addr_init(struct idm *idm) |
102 | { |
103 | struct sockaddr_in *sa_in; |
104 | struct sockaddr_in6 *sa_in6; |
105 | struct ypldap_addr *h; |
106 | int defport; |
107 | |
108 | if (idm->idm_port != 0) |
109 | defport = idm->idm_port; |
110 | else if (idm->idm_flags & F_SSL0x00100000) |
111 | defport = LDAPS_PORT636; |
112 | else |
113 | defport = LDAP_PORT389; |
114 | |
115 | TAILQ_FOREACH(h, &idm->idm_addr, next)for((h) = ((&idm->idm_addr)->tqh_first); (h) != ((void *)0); (h) = ((h)->next.tqe_next)) { |
116 | switch (h->ss.ss_family) { |
117 | case AF_INET2: |
118 | sa_in = (struct sockaddr_in *)&h->ss; |
119 | if (ntohs(sa_in->sin_port)(__uint16_t)(__builtin_constant_p(sa_in->sin_port) ? (__uint16_t )(((__uint16_t)(sa_in->sin_port) & 0xffU) << 8 | ((__uint16_t)(sa_in->sin_port) & 0xff00U) >> 8) : __swap16md(sa_in->sin_port)) == 0) |
120 | sa_in->sin_port = htons(defport)(__uint16_t)(__builtin_constant_p(defport) ? (__uint16_t)(((__uint16_t )(defport) & 0xffU) << 8 | ((__uint16_t)(defport) & 0xff00U) >> 8) : __swap16md(defport)); |
121 | idm->idm_state = STATE_DNS_DONE; |
122 | break; |
123 | case AF_INET624: |
124 | sa_in6 = (struct sockaddr_in6 *)&h->ss; |
125 | if (ntohs(sa_in6->sin6_port)(__uint16_t)(__builtin_constant_p(sa_in6->sin6_port) ? (__uint16_t )(((__uint16_t)(sa_in6->sin6_port) & 0xffU) << 8 | ((__uint16_t)(sa_in6->sin6_port) & 0xff00U) >> 8) : __swap16md(sa_in6->sin6_port)) == 0) |
126 | sa_in6->sin6_port = htons(defport)(__uint16_t)(__builtin_constant_p(defport) ? (__uint16_t)(((__uint16_t )(defport) & 0xffU) << 8 | ((__uint16_t)(defport) & 0xff00U) >> 8) : __swap16md(defport)); |
127 | idm->idm_state = STATE_DNS_DONE; |
128 | break; |
129 | default: |
130 | fatalx("king bula sez: wrong AF in client_addr_init"); |
131 | /* not reached */ |
132 | } |
133 | } |
134 | } |
135 | |
136 | int |
137 | client_addr_free(struct idm *idm) |
138 | { |
139 | struct ypldap_addr *h; |
140 | |
141 | while (!TAILQ_EMPTY(&idm->idm_addr)(((&idm->idm_addr)->tqh_first) == ((void*)0))) { |
142 | h = TAILQ_FIRST(&idm->idm_addr)((&idm->idm_addr)->tqh_first); |
143 | TAILQ_REMOVE(&idm->idm_addr, h, next)do { if (((h)->next.tqe_next) != ((void*)0)) (h)->next. tqe_next->next.tqe_prev = (h)->next.tqe_prev; else (& idm->idm_addr)->tqh_last = (h)->next.tqe_prev; *(h)-> next.tqe_prev = (h)->next.tqe_next; ; ; } while (0); |
144 | free(h); |
145 | } |
146 | |
147 | return (0); |
148 | } |
149 | |
150 | void |
151 | client_sig_handler(int sig, short event, void *p) |
152 | { |
153 | switch (sig) { |
154 | case SIGINT2: |
155 | case SIGTERM15: |
156 | client_shutdown(); |
157 | break; |
158 | default: |
159 | fatalx("unexpected signal"); |
160 | } |
161 | } |
162 | |
163 | void |
164 | client_dispatch_dns(int fd, short events, void *p) |
165 | { |
166 | struct imsg imsg; |
167 | u_int16_t dlen; |
168 | u_char *data; |
169 | struct ypldap_addr *h; |
170 | int n, wait_cnt = 0; |
171 | struct idm *idm; |
172 | int shut = 0; |
173 | |
174 | struct env *env = p; |
175 | struct imsgev *iev = env->sc_iev_dns; |
176 | struct imsgbuf *ibuf = &iev->ibuf; |
177 | |
178 | if ((events & (EV_READ0x02 | EV_WRITE0x04)) == 0) |
179 | fatalx("unknown event"); |
180 | |
181 | if (events & EV_READ0x02) { |
182 | if ((n = imsg_read(ibuf)) == -1 && errno(*__errno()) != EAGAIN35) |
183 | fatal("imsg_read error"); |
184 | if (n == 0) |
185 | shut = 1; |
186 | } |
187 | if (events & EV_WRITE0x04) { |
188 | if ((n = msgbuf_write(&ibuf->w)) == -1 && errno(*__errno()) != EAGAIN35) |
189 | fatal("msgbuf_write"); |
190 | if (n == 0) |
191 | shut = 1; |
192 | goto done; |
193 | } |
194 | |
195 | for (;;) { |
196 | if ((n = imsg_get(ibuf, &imsg)) == -1) |
197 | fatal("client_dispatch_dns: imsg_get error"); |
198 | if (n == 0) |
199 | break; |
200 | |
201 | switch (imsg.hdr.type) { |
202 | case IMSG_HOST_DNS: |
203 | TAILQ_FOREACH(idm, &env->sc_idms, idm_entry)for((idm) = ((&env->sc_idms)->tqh_first); (idm) != ( (void*)0); (idm) = ((idm)->idm_entry.tqe_next)) |
204 | if (idm->idm_id == imsg.hdr.peerid) |
205 | break; |
206 | if (idm == NULL((void*)0)) { |
207 | log_warnx("IMSG_HOST_DNS with invalid peerID"); |
208 | break; |
209 | } |
210 | if (!TAILQ_EMPTY(&idm->idm_addr)(((&idm->idm_addr)->tqh_first) == ((void*)0))) { |
211 | log_warnx("IMSG_HOST_DNS but addrs set!"); |
212 | break; |
213 | } |
214 | |
215 | dlen = imsg.hdr.len - IMSG_HEADER_SIZEsizeof(struct imsg_hdr); |
216 | if (dlen == 0) { /* no data -> temp error */ |
217 | idm->idm_state = STATE_DNS_TEMPFAIL; |
218 | break; |
219 | } |
220 | |
221 | data = (u_char *)imsg.data; |
222 | while (dlen >= sizeof(struct sockaddr_storage)) { |
223 | if ((h = calloc(1, sizeof(*h))) == NULL((void*)0)) |
224 | fatal(NULL((void*)0)); |
225 | memcpy(&h->ss, data, sizeof(h->ss)); |
226 | TAILQ_INSERT_HEAD(&idm->idm_addr, h, next)do { if (((h)->next.tqe_next = (&idm->idm_addr)-> tqh_first) != ((void*)0)) (&idm->idm_addr)->tqh_first ->next.tqe_prev = &(h)->next.tqe_next; else (&idm ->idm_addr)->tqh_last = &(h)->next.tqe_next; (& idm->idm_addr)->tqh_first = (h); (h)->next.tqe_prev = &(&idm->idm_addr)->tqh_first; } while (0); |
227 | |
228 | data += sizeof(h->ss); |
229 | dlen -= sizeof(h->ss); |
230 | } |
231 | if (dlen != 0) |
232 | fatalx("IMSG_HOST_DNS: dlen != 0"); |
233 | |
234 | client_addr_init(idm); |
235 | |
236 | break; |
237 | default: |
238 | break; |
239 | } |
240 | imsg_free(&imsg); |
241 | } |
242 | |
243 | TAILQ_FOREACH(idm, &env->sc_idms, idm_entry)for((idm) = ((&env->sc_idms)->tqh_first); (idm) != ( (void*)0); (idm) = ((idm)->idm_entry.tqe_next)) { |
244 | if (client_try_idm(env, idm) == -1) |
245 | idm->idm_state = STATE_LDAP_FAIL; |
246 | |
247 | if (idm->idm_state < STATE_LDAP_DONE) |
248 | wait_cnt++; |
249 | } |
250 | if (wait_cnt == 0) |
251 | imsg_compose_event(env->sc_iev, IMSG_END_UPDATE, 0, 0, -1, |
252 | NULL((void*)0), 0); |
253 | |
254 | done: |
255 | if (!shut) |
256 | imsg_event_add(iev); |
257 | else { |
258 | /* this pipe is dead, so remove the event handler */ |
259 | event_del(&iev->ev); |
260 | event_loopexit(NULL((void*)0)); |
261 | } |
262 | } |
263 | |
264 | void |
265 | client_dispatch_parent(int fd, short events, void *p) |
266 | { |
267 | int n; |
268 | int shut = 0; |
269 | struct imsg imsg; |
270 | struct env *env = p; |
271 | struct imsgev *iev = env->sc_iev; |
272 | struct imsgbuf *ibuf = &iev->ibuf; |
273 | |
274 | if ((events & (EV_READ0x02 | EV_WRITE0x04)) == 0) |
275 | fatalx("unknown event"); |
276 | |
277 | if (events & EV_READ0x02) { |
278 | if ((n = imsg_read(ibuf)) == -1 && errno(*__errno()) != EAGAIN35) |
279 | fatal("imsg_read error"); |
280 | if (n == 0) |
281 | shut = 1; |
282 | } |
283 | if (events & EV_WRITE0x04) { |
284 | if ((n = msgbuf_write(&ibuf->w)) == -1 && errno(*__errno()) != EAGAIN35) |
285 | fatal("msgbuf_write"); |
286 | if (n == 0) |
287 | shut = 1; |
288 | goto done; |
289 | } |
290 | |
291 | for (;;) { |
292 | if ((n = imsg_get(ibuf, &imsg)) == -1) |
293 | fatal("client_dispatch_parent: imsg_get error"); |
294 | if (n == 0) |
295 | break; |
296 | |
297 | switch (imsg.hdr.type) { |
298 | case IMSG_CONF_START: { |
299 | struct env params; |
300 | |
301 | if (env->sc_flags & F_CONFIGURING0x00200000) { |
302 | log_warnx("configuration already in progress"); |
303 | break; |
304 | } |
305 | memcpy(¶ms, imsg.data, sizeof(params)); |
306 | log_debug("configuration starting"); |
307 | env->sc_flags |= F_CONFIGURING0x00200000; |
308 | purge_config(env); |
309 | memcpy(&env->sc_conf_tv, ¶ms.sc_conf_tv, |
310 | sizeof(env->sc_conf_tv)); |
311 | env->sc_flags |= params.sc_flags; |
312 | break; |
313 | } |
314 | case IMSG_CONF_IDM: { |
315 | struct idm *idm; |
316 | |
317 | if (!(env->sc_flags & F_CONFIGURING0x00200000)) |
318 | break; |
319 | if ((idm = calloc(1, sizeof(*idm))) == NULL((void*)0)) |
320 | fatal(NULL((void*)0)); |
321 | memcpy(idm, imsg.data, sizeof(*idm)); |
322 | idm->idm_env = env; |
323 | TAILQ_INSERT_TAIL(&env->sc_idms, idm, idm_entry)do { (idm)->idm_entry.tqe_next = ((void*)0); (idm)->idm_entry .tqe_prev = (&env->sc_idms)->tqh_last; *(&env-> sc_idms)->tqh_last = (idm); (&env->sc_idms)->tqh_last = &(idm)->idm_entry.tqe_next; } while (0); |
324 | break; |
325 | } |
326 | case IMSG_CONF_END: |
327 | env->sc_flags &= ~F_CONFIGURING0x00200000; |
328 | log_debug("applying configuration"); |
329 | client_configure(env); |
330 | break; |
331 | default: |
332 | log_debug("client_dispatch_parent: unexpect imsg %d", |
333 | imsg.hdr.type); |
334 | |
335 | break; |
336 | } |
337 | imsg_free(&imsg); |
338 | } |
339 | |
340 | done: |
341 | if (!shut) |
342 | imsg_event_add(iev); |
343 | else { |
344 | /* this pipe is dead, so remove the event handler */ |
345 | event_del(&iev->ev); |
346 | event_loopexit(NULL((void*)0)); |
347 | } |
348 | } |
349 | |
350 | void |
351 | client_shutdown(void) |
352 | { |
353 | log_info("ldap client exiting"); |
354 | _exit(0); |
355 | } |
356 | |
357 | pid_t |
358 | ldapclient(int pipe_main2client[2]) |
359 | { |
360 | pid_t pid, dns_pid; |
361 | int pipe_dns[2]; |
362 | struct passwd *pw; |
363 | struct event ev_sigint; |
364 | struct event ev_sigterm; |
365 | struct env env; |
366 | |
367 | switch (pid = fork()) { |
368 | case -1: |
369 | fatal("cannot fork"); |
370 | break; |
371 | case 0: |
372 | break; |
373 | default: |
374 | return (pid); |
375 | } |
376 | |
377 | memset(&env, 0, sizeof(env)); |
378 | TAILQ_INIT(&env.sc_idms)do { (&env.sc_idms)->tqh_first = ((void*)0); (&env .sc_idms)->tqh_last = &(&env.sc_idms)->tqh_first ; } while (0); |
379 | |
380 | if ((pw = getpwnam(YPLDAP_USER"_ypldap")) == NULL((void*)0)) |
381 | fatal("getpwnam"); |
382 | |
383 | if (socketpair(AF_UNIX1, SOCK_STREAM1, PF_UNSPEC0, pipe_dns) == -1) |
384 | fatal("socketpair"); |
385 | dns_pid = ypldap_dns(pipe_dns, pw); |
Value stored to 'dns_pid' is never read | |
386 | close(pipe_dns[1]); |
387 | |
388 | #ifndef DEBUG |
389 | if (chroot(pw->pw_dir) == -1) |
390 | fatal("chroot"); |
391 | if (chdir("/") == -1) |
392 | fatal("chdir"); |
393 | #else |
394 | #warning disabling chrooting in DEBUG mode |
395 | #endif |
396 | setproctitle("ldap client"); |
397 | ypldap_process = PROC_CLIENT; |
398 | log_procname = log_procnames[ypldap_process]; |
399 | |
400 | #ifndef DEBUG |
401 | if (setgroups(1, &pw->pw_gid) || |
402 | setresgid(pw->pw_gid, pw->pw_gid, pw->pw_gid) || |
403 | setresuid(pw->pw_uid, pw->pw_uid, pw->pw_uid)) |
404 | fatal("cannot drop privileges"); |
405 | #else |
406 | #warning disabling privilege revocation in DEBUG mode |
407 | #endif |
408 | |
409 | if (pledge("stdio inet", NULL((void*)0)) == -1) |
410 | fatal("pledge"); |
411 | |
412 | event_init(); |
413 | signal(SIGPIPE13, SIG_IGN(void (*)(int))1); |
414 | signal_set(&ev_sigint, SIGINT, client_sig_handler, NULL)event_set(&ev_sigint, 2, 0x08|0x10, client_sig_handler, ( (void*)0)); |
415 | signal_set(&ev_sigterm, SIGTERM, client_sig_handler, NULL)event_set(&ev_sigterm, 15, 0x08|0x10, client_sig_handler, ((void*)0)); |
416 | signal_add(&ev_sigint, NULL)event_add(&ev_sigint, ((void*)0)); |
417 | signal_add(&ev_sigterm, NULL)event_add(&ev_sigterm, ((void*)0)); |
418 | |
419 | close(pipe_main2client[0]); |
420 | if ((env.sc_iev = calloc(1, sizeof(*env.sc_iev))) == NULL((void*)0)) |
421 | fatal(NULL((void*)0)); |
422 | if ((env.sc_iev_dns = calloc(1, sizeof(*env.sc_iev_dns))) == NULL((void*)0)) |
423 | fatal(NULL((void*)0)); |
424 | |
425 | env.sc_iev->events = EV_READ0x02; |
426 | env.sc_iev->data = &env; |
427 | imsg_init(&env.sc_iev->ibuf, pipe_main2client[1]); |
428 | env.sc_iev->handler = client_dispatch_parent; |
429 | event_set(&env.sc_iev->ev, env.sc_iev->ibuf.fd, env.sc_iev->events, |
430 | env.sc_iev->handler, &env); |
431 | event_add(&env.sc_iev->ev, NULL((void*)0)); |
432 | |
433 | env.sc_iev_dns->events = EV_READ0x02; |
434 | env.sc_iev_dns->data = &env; |
435 | imsg_init(&env.sc_iev_dns->ibuf, pipe_dns[0]); |
436 | env.sc_iev_dns->handler = client_dispatch_dns; |
437 | event_set(&env.sc_iev_dns->ev, env.sc_iev_dns->ibuf.fd, |
438 | env.sc_iev_dns->events, env.sc_iev_dns->handler, &env); |
439 | event_add(&env.sc_iev_dns->ev, NULL((void*)0)); |
440 | |
441 | event_dispatch(); |
442 | client_shutdown(); |
443 | |
444 | return (0); |
445 | |
446 | } |
447 | |
448 | int |
449 | client_build_req(struct idm *idm, struct idm_req *ir, struct aldap_message *m, |
450 | int min_attr, int max_attr) |
451 | { |
452 | struct aldap_stringset *ldap_attrs; |
453 | int i; |
454 | size_t k; |
455 | |
456 | memset(ir, 0, sizeof(*ir)); |
457 | for (i = min_attr; i < max_attr; i++) { |
458 | if (idm->idm_flags & F_FIXED_ATTR(i)(1<<i)) { |
459 | if (strlcat(ir->ir_line, idm->idm_attrs[i], |
460 | sizeof(ir->ir_line)) >= sizeof(ir->ir_line)) |
461 | /* |
462 | * entry yields a line > 1024, trash it. |
463 | */ |
464 | return (-1); |
465 | |
466 | if (i == ATTR_UID2) { |
467 | ir->ir_key.ik_uid = strtonum( |
468 | idm->idm_attrs[i], 0, |
469 | UID_MAX(2147483647 *2U +1U), NULL((void*)0)); |
470 | } else if (i == ATTR_GR_GID12) { |
471 | ir->ir_key.ik_gid = strtonum( |
472 | idm->idm_attrs[i], 0, |
473 | GID_MAX(2147483647 *2U +1U), NULL((void*)0)); |
474 | } |
475 | } else if (idm->idm_list & F_LIST(i)(1<<i)) { |
476 | aldap_match_attr(m, idm->idm_attrs[i], &ldap_attrs); |
477 | for (k = 0; k >= 0 && ldap_attrs && k < ldap_attrs->len; k++) { |
478 | /* XXX: Fail when attributes have illegal characters e.g. ',' */ |
479 | if (strlcat(ir->ir_line, |
480 | ldap_attrs->str[k].ostr_val, |
481 | sizeof(ir->ir_line)) >= sizeof(ir->ir_line)) |
482 | continue; |
483 | if (k + 1 < ldap_attrs->len) |
484 | if (strlcat(ir->ir_line, ",", |
485 | sizeof(ir->ir_line)) |
486 | >= sizeof(ir->ir_line)) { |
487 | aldap_free_attr(ldap_attrs); |
488 | return (-1); |
489 | } |
490 | } |
491 | aldap_free_attr(ldap_attrs); |
492 | } else { |
493 | if (aldap_match_attr(m, idm->idm_attrs[i], &ldap_attrs) == -1) |
494 | return (-1); |
495 | if (strlcat(ir->ir_line, ldap_attrs->str[0].ostr_val, |
496 | sizeof(ir->ir_line)) >= sizeof(ir->ir_line)) { |
497 | aldap_free_attr(ldap_attrs); |
498 | return (-1); |
499 | } |
500 | if (i == ATTR_UID2) { |
501 | ir->ir_key.ik_uid = strtonum( |
502 | ldap_attrs->str[0].ostr_val, 0, UID_MAX(2147483647 *2U +1U), |
503 | NULL((void*)0)); |
504 | } else if (i == ATTR_GR_GID12) { |
505 | ir->ir_key.ik_uid = strtonum( |
506 | ldap_attrs->str[0].ostr_val, 0, GID_MAX(2147483647 *2U +1U), |
507 | NULL((void*)0)); |
508 | } |
509 | aldap_free_attr(ldap_attrs); |
510 | } |
511 | |
512 | if (i + 1 != max_attr) |
513 | if (strlcat(ir->ir_line, ":", |
514 | sizeof(ir->ir_line)) >= sizeof(ir->ir_line)) |
515 | return (-1); |
516 | } |
517 | |
518 | return (0); |
519 | } |
520 | |
521 | int |
522 | client_search_idm(struct env *env, struct idm *idm, struct aldap *al, |
523 | char **attrs, char *filter, int min_attr, int max_attr, |
524 | enum imsg_type type) |
525 | { |
526 | struct idm_req ir; |
527 | struct aldap_message *m; |
528 | struct aldap_page_control *pg = NULL((void*)0); |
529 | const char *errstr; |
530 | char *dn; |
531 | |
532 | dn = idm->idm_basedn; |
533 | if (type == IMSG_GRP_ENTRY && idm->idm_groupdn[0] != '\0') |
534 | dn = idm->idm_groupdn; |
535 | |
536 | do { |
537 | if (aldap_search(al, dn, LDAP_SCOPE_SUBTREE, |
538 | filter, attrs, 0, 0, 0, pg) == -1) { |
539 | aldap_get_errno(al, &errstr); |
540 | log_debug("%s", errstr); |
541 | return (-1); |
542 | } |
543 | |
544 | if (pg != NULL((void*)0)) { |
545 | aldap_freepage(pg); |
546 | pg = NULL((void*)0); |
547 | } |
548 | |
549 | while ((m = aldap_parse(al)) != NULL((void*)0)) { |
550 | if (al->msgid != m->msgid) { |
551 | goto fail; |
552 | } |
553 | |
554 | if (m->message_type == LDAP_RES_SEARCH_RESULT) { |
555 | if (m->page != NULL((void*)0) && m->page->cookie_len != 0) |
556 | pg = m->page; |
557 | else |
558 | pg = NULL((void*)0); |
559 | |
560 | aldap_freemsg(m); |
561 | break; |
562 | } |
563 | |
564 | if (m->message_type != LDAP_RES_SEARCH_ENTRY) { |
565 | goto fail; |
566 | } |
567 | |
568 | if (client_build_req(idm, &ir, m, min_attr, max_attr) == 0) |
569 | imsg_compose_event(env->sc_iev, type, 0, 0, -1, |
570 | &ir, sizeof(ir)); |
571 | |
572 | aldap_freemsg(m); |
573 | } |
574 | } while (pg != NULL((void*)0)); |
575 | |
576 | return (0); |
577 | |
578 | fail: |
579 | aldap_freemsg(m); |
580 | if (pg != NULL((void*)0)) { |
581 | aldap_freepage(pg); |
582 | } |
583 | |
584 | return (-1); |
585 | } |
586 | |
587 | int |
588 | client_try_idm(struct env *env, struct idm *idm) |
589 | { |
590 | const char *where; |
591 | char *attrs[ATTR_MAX10+1]; |
592 | int i, j; |
593 | struct aldap_message *m; |
594 | struct aldap *al; |
595 | |
596 | where = "connect"; |
597 | if ((al = client_aldap_open(&idm->idm_addr)) == NULL((void*)0)) |
598 | return (-1); |
599 | |
600 | if (idm->idm_flags & F_STARTTLS0x00800000) { |
601 | log_debug("requesting starttls"); |
602 | where = "starttls"; |
603 | if (aldap_req_starttls(al) == -1) |
604 | goto bad; |
605 | |
606 | where = "parsing"; |
607 | if ((m = aldap_parse(al)) == NULL((void*)0)) |
608 | goto bad; |
609 | where = "verifying msgid"; |
610 | if (al->msgid != m->msgid) { |
611 | aldap_freemsg(m); |
612 | goto bad; |
613 | } |
614 | where = "starttls result"; |
615 | if (aldap_get_resultcode(m) != LDAP_SUCCESS) { |
616 | aldap_freemsg(m); |
617 | goto bad; |
618 | } |
619 | aldap_freemsg(m); |
620 | } |
621 | |
622 | if (idm->idm_flags & (F_STARTTLS0x00800000 | F_SSL0x00100000)) { |
623 | log_debug("starting tls"); |
624 | where = "enabling tls"; |
625 | if (aldap_tls(al, idm->idm_tls_config, idm->idm_name) < 0) { |
626 | const char *err; |
627 | aldap_get_errno(al, &err); |
628 | log_debug("tls failed: %s", err); |
629 | goto bad; |
630 | } |
631 | } |
632 | |
633 | if (idm->idm_flags & F_NEEDAUTH0x00400000) { |
634 | where = "binding"; |
635 | if (aldap_bind(al, idm->idm_binddn, idm->idm_bindcred) == -1) |
636 | goto bad; |
637 | |
638 | where = "parsing"; |
639 | if ((m = aldap_parse(al)) == NULL((void*)0)) |
640 | goto bad; |
641 | where = "verifying msgid"; |
642 | if (al->msgid != m->msgid) { |
643 | aldap_freemsg(m); |
644 | goto bad; |
645 | } |
646 | aldap_freemsg(m); |
647 | } |
648 | |
649 | memset(attrs, 0, sizeof(attrs)); |
650 | for (i = 0, j = 0; i < ATTR_MAX10; i++) { |
651 | if (idm->idm_flags & F_FIXED_ATTR(i)(1<<i)) |
652 | continue; |
653 | attrs[j++] = idm->idm_attrs[i]; |
654 | } |
655 | attrs[j] = NULL((void*)0); |
656 | |
657 | /* |
658 | * build password line. |
659 | */ |
660 | where = "search"; |
661 | log_debug("searching password entries"); |
662 | if (client_search_idm(env, idm, al, attrs, |
663 | idm->idm_filters[FILTER_USER1], 0, ATTR_MAX10, IMSG_PW_ENTRY) == -1) |
664 | goto bad; |
665 | |
666 | memset(attrs, 0, sizeof(attrs)); |
667 | for (i = ATTR_GR_MIN10, j = 0; i < ATTR_GR_MAX14; i++) { |
668 | if (idm->idm_flags & F_FIXED_ATTR(i)(1<<i)) |
669 | continue; |
670 | attrs[j++] = idm->idm_attrs[i]; |
671 | } |
672 | attrs[j] = NULL((void*)0); |
673 | |
674 | /* |
675 | * build group line. |
676 | */ |
677 | where = "search"; |
678 | log_debug("searching group entries"); |
679 | if (client_search_idm(env, idm, al, attrs, |
680 | idm->idm_filters[FILTER_GROUP0], ATTR_GR_MIN10, ATTR_GR_MAX14, |
681 | IMSG_GRP_ENTRY) == -1) |
682 | goto bad; |
683 | |
684 | aldap_close(al); |
685 | |
686 | idm->idm_state = STATE_LDAP_DONE; |
687 | |
688 | return (0); |
689 | bad: |
690 | aldap_close(al); |
691 | log_debug("directory %s errored out in %s", idm->idm_name, where); |
692 | return (-1); |
693 | } |
694 | |
695 | void |
696 | client_periodic_update(int fd, short event, void *p) |
697 | { |
698 | struct env *env = p; |
699 | |
700 | struct idm *idm; |
701 | int fail_cnt = 0; |
702 | |
703 | /* If LDAP isn't finished, notify the master process to trash the |
704 | * update. */ |
705 | TAILQ_FOREACH(idm, &env->sc_idms, idm_entry)for((idm) = ((&env->sc_idms)->tqh_first); (idm) != ( (void*)0); (idm) = ((idm)->idm_entry.tqe_next)) { |
706 | if (idm->idm_state < STATE_LDAP_DONE) |
707 | fail_cnt++; |
708 | |
709 | idm->idm_state = STATE_NONE; |
710 | |
711 | client_addr_free(idm); |
712 | } |
713 | if (fail_cnt > 0) { |
714 | log_debug("trash the update"); |
715 | imsg_compose_event(env->sc_iev, IMSG_TRASH_UPDATE, 0, 0, -1, |
716 | NULL((void*)0), 0); |
717 | } |
718 | |
719 | client_configure(env); |
720 | } |
721 | |
722 | void |
723 | client_configure(struct env *env) |
724 | { |
725 | struct timeval tv; |
726 | struct idm *idm; |
727 | u_int16_t dlen; |
728 | |
729 | log_debug("connecting to directories"); |
730 | |
731 | imsg_compose_event(env->sc_iev, IMSG_START_UPDATE, 0, 0, -1, NULL((void*)0), 0); |
732 | |
733 | /* Start the DNS lookups */ |
734 | TAILQ_FOREACH(idm, &env->sc_idms, idm_entry)for((idm) = ((&env->sc_idms)->tqh_first); (idm) != ( (void*)0); (idm) = ((idm)->idm_entry.tqe_next)) { |
735 | dlen = strlen(idm->idm_name) + 1; |
736 | imsg_compose_event(env->sc_iev_dns, IMSG_HOST_DNS, idm->idm_id, |
737 | 0, -1, idm->idm_name, dlen); |
738 | } |
739 | |
740 | tv.tv_sec = env->sc_conf_tv.tv_sec; |
741 | tv.tv_usec = env->sc_conf_tv.tv_usec; |
742 | evtimer_set(&env->sc_conf_ev, client_periodic_update, env)event_set(&env->sc_conf_ev, -1, 0, client_periodic_update , env); |
743 | evtimer_add(&env->sc_conf_ev, &tv)event_add(&env->sc_conf_ev, &tv); |
744 | } |