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