xref: /openbsd-src/usr.sbin/ldapd/ldape.c (revision f2da64fbbbf1b03f09f390ab01267c93dfd77c4c)
1 /*	$OpenBSD: ldape.c,v 1.24 2016/05/01 00:32:37 jmatthew Exp $ */
2 
3 /*
4  * Copyright (c) 2009, 2010 Martin Hedenfalk <martin@bzero.se>
5  *
6  * Permission to use, copy, modify, and distribute this software for any
7  * purpose with or without fee is hereby granted, provided that the above
8  * copyright notice and this permission notice appear in all copies.
9  *
10  * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
11  * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
12  * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
13  * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
14  * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
15  * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
16  * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
17  */
18 
19 #include <sys/queue.h>
20 #include <sys/types.h>
21 #include <sys/socket.h>
22 #include <sys/stat.h>
23 #include <sys/un.h>
24 #include <sys/wait.h>
25 
26 #include <err.h>
27 #include <errno.h>
28 #include <signal.h>
29 #include <stdlib.h>
30 #include <string.h>
31 #include <unistd.h>
32 
33 #include "ldapd.h"
34 
35 void			 ldape_sig_handler(int fd, short why, void *data);
36 static void		 ldape_auth_result(struct imsg *imsg);
37 static void		 ldape_open_result(struct imsg *imsg);
38 static void		 ldape_imsgev(struct imsgev *iev, int code,
39 			    struct imsg *imsg);
40 static void		 ldape_needfd(struct imsgev *iev);
41 
42 int			 ldap_starttls(struct request *req);
43 void			 send_ldap_extended_response(struct conn *conn,
44 				int msgid, unsigned long type,
45 				long long result_code,
46 				const char *extended_oid);
47 
48 struct imsgev		*iev_ldapd;
49 struct control_sock	 csock;
50 
51 void
52 ldape_sig_handler(int sig, short why, void *data)
53 {
54 	log_debug("ldape: got signal %d", sig);
55 	if (sig == SIGCHLD) {
56 		for (;;) {
57 			pid_t	 pid;
58 			int	 status;
59 
60 			pid = waitpid(WAIT_ANY, &status, WNOHANG);
61 			if (pid <= 0)
62 				break;
63 		}
64 		return;
65 	}
66 
67 	event_loopexit(NULL);
68 }
69 
70 void
71 send_ldap_extended_response(struct conn *conn, int msgid, unsigned long type,
72     long long result_code, const char *extended_oid)
73 {
74 	int			 rc;
75 	struct ber_element	*root, *elm;
76 	void			*buf;
77 
78 	log_debug("sending response %u with result %lld", type, result_code);
79 
80 	if ((root = ber_add_sequence(NULL)) == NULL)
81 		goto fail;
82 
83 	elm = ber_printf_elements(root, "d{tEss",
84 	    msgid, BER_CLASS_APP, type, result_code, "", "");
85 	if (elm == NULL)
86 		goto fail;
87 
88 	if (extended_oid)
89 		if (ber_add_string(elm, extended_oid) == NULL)
90 			goto fail;
91 
92 	ldap_debug_elements(root, type, "sending response on fd %d", conn->fd);
93 
94 	rc = ber_write_elements(&conn->ber, root);
95 	ber_free_elements(root);
96 
97 	if (rc < 0)
98 		log_warn("failed to create ldap result");
99 	else {
100 		ber_get_writebuf(&conn->ber, &buf);
101 		if (bufferevent_write(conn->bev, buf, rc) != 0)
102 			log_warn("failed to send ldap result");
103 	}
104 
105 	return;
106 fail:
107 	if (root)
108 		ber_free_elements(root);
109 }
110 
111 int
112 ldap_refer(struct request *req, const char *basedn, struct search *search,
113     struct referrals *refs)
114 {
115 	struct ber_element	*root, *elm, *ref_root = NULL;
116 	struct referral		*ref;
117 	long long		 result_code = LDAP_REFERRAL;
118 	unsigned long		 type;
119 	int			 rc;
120 	void			*buf;
121 	char			*url, *scope_str = NULL;
122 
123 	if (req->type == LDAP_REQ_SEARCH)
124 		type = LDAP_RES_SEARCH_RESULT;
125 	else
126 		type = req->type + 1;
127 
128 	if (search != NULL) {
129 		if (search->scope != LDAP_SCOPE_SUBTREE)
130 			scope_str = "base";
131 		else
132 			scope_str = "sub";
133 	}
134 
135 	log_debug("sending referral in response %u on msgid %lld",
136 	    type, req->msgid);
137 
138 	if ((root = ber_add_sequence(NULL)) == NULL)
139 		goto fail;
140 
141 	if ((elm = ref_root = ber_add_sequence(NULL)) == NULL)
142 		goto fail;
143 	ber_set_header(ref_root, BER_CLASS_CONTEXT, LDAP_REQ_SEARCH);
144 	SLIST_FOREACH(ref, refs, next) {
145 		if (search != NULL)
146 			rc = asprintf(&url, "%s/%s??%s", ref->url, basedn,
147 			    scope_str);
148 		else
149 			rc = asprintf(&url, "%s/%s", ref->url, basedn);
150 		if (rc == -1) {
151 			log_warn("asprintf");
152 			goto fail;
153 		}
154 		log_debug("adding referral '%s'", url);
155 		elm = ber_add_string(elm, url);
156 		free(url);
157 		if (elm == NULL)
158 			goto fail;
159 	}
160 
161 	elm = ber_printf_elements(root, "d{tEsse",
162 	    req->msgid, BER_CLASS_APP, type, result_code, "", "", ref_root);
163 	if (elm == NULL)
164 		goto fail;
165 	ref_root = NULL;
166 
167 	rc = ber_write_elements(&req->conn->ber, root);
168 	ber_free_elements(root);
169 
170 	if (rc < 0)
171 		log_warn("failed to create ldap result");
172 	else {
173 		ber_get_writebuf(&req->conn->ber, &buf);
174 		if (bufferevent_write(req->conn->bev, buf, rc) != 0)
175 			log_warn("failed to send ldap result");
176 	}
177 
178 	request_free(req);
179 	return LDAP_REFERRAL;
180 
181 fail:
182 	if (root != NULL)
183 		ber_free_elements(root);
184 	if (ref_root != NULL)
185 		ber_free_elements(ref_root);
186 	request_free(req);
187 	return LDAP_REFERRAL;
188 }
189 
190 void
191 send_ldap_result(struct conn *conn, int msgid, unsigned long type,
192     long long result_code)
193 {
194 	send_ldap_extended_response(conn, msgid, type, result_code, NULL);
195 }
196 
197 int
198 ldap_respond(struct request *req, int code)
199 {
200 	if (code >= 0)
201 		send_ldap_result(req->conn, req->msgid, req->type + 1, code);
202 	request_free(req);
203 	return code;
204 }
205 
206 int
207 ldap_abandon(struct request *req)
208 {
209 	long long	 msgid;
210 	struct search	*search;
211 
212 	if (ber_scanf_elements(req->op, "i", &msgid) != 0) {
213 		request_free(req);
214 		return -1;	/* protocol error, but don't respond */
215 	}
216 
217 	TAILQ_FOREACH(search, &req->conn->searches, next) {
218 		if (search->req->msgid == msgid) {
219 			/* unlinks the search from conn->searches */
220 			search_close(search);
221 			break;
222 		}
223 	}
224 	request_free(req);
225 	return -1;
226 }
227 
228 int
229 ldap_unbind(struct request *req)
230 {
231 	log_debug("current bind dn = %s", req->conn->binddn);
232 	conn_disconnect(req->conn);
233 	request_free(req);
234 	return -1;		/* don't send any response */
235 }
236 
237 int
238 ldap_compare(struct request *req)
239 {
240 	struct ber_element	*entry, *elm, *attr;
241 	struct namespace	*ns;
242 	struct referrals	*refs;
243 	struct attr_type	*at;
244 	char			*dn, *aname, *value, *s;
245 
246 	if (ber_scanf_elements(req->op, "{s{ss", &dn, &aname, &value) != 0) {
247 		log_debug("%s: protocol error", __func__);
248 		request_free(req);
249 		return -1;
250 	}
251 
252 	if ((at = lookup_attribute(conf->schema, aname)) == NULL)
253 		return ldap_respond(req, LDAP_UNDEFINED_TYPE);
254 
255 	if ((ns = namespace_for_base(dn)) == NULL) {
256 		refs = namespace_referrals(dn);
257 		if (refs == NULL)
258 			return ldap_respond(req, LDAP_NO_SUCH_OBJECT);
259 		else
260 			return ldap_refer(req, dn, NULL, refs);
261 	}
262 
263 	if ((entry = namespace_get(ns, dn)) == NULL)
264 		return ldap_respond(req, LDAP_NO_SUCH_OBJECT);
265 
266 	if ((attr = ldap_find_attribute(entry, at)) == NULL)
267 		return ldap_respond(req, LDAP_NO_SUCH_ATTRIBUTE);
268 
269 	if ((attr = attr->be_next) == NULL)	/* skip attribute name */
270 		return ldap_respond(req, LDAP_OTHER);
271 
272 	for (elm = attr->be_sub; elm != NULL; elm = elm->be_next) {
273 		if (ber_get_string(elm, &s) != 0)
274 			return ldap_respond(req, LDAP_OTHER);
275 		if (strcasecmp(value, s) == 0)
276 			return ldap_respond(req, LDAP_COMPARE_TRUE);
277 	}
278 
279 	return ldap_respond(req, LDAP_COMPARE_FALSE);
280 }
281 
282 int
283 ldap_starttls(struct request *req)
284 {
285 	if ((req->conn->listener->flags & F_STARTTLS) == 0) {
286 		log_debug("StartTLS not configured for this connection");
287 		return LDAP_OPERATIONS_ERROR;
288 	}
289 
290 	req->conn->s_flags |= F_STARTTLS;
291 	return LDAP_SUCCESS;
292 }
293 
294 int
295 ldap_extended(struct request *req)
296 {
297 	int			 i, rc = LDAP_PROTOCOL_ERROR;
298 	char			*oid = NULL;
299 	struct ber_element	*ext_val = NULL;
300 	struct {
301 		const char	*oid;
302 		int (*fn)(struct request *);
303 	} extended_ops[] = {
304 		{ "1.3.6.1.4.1.1466.20037", ldap_starttls },
305 		{ NULL }
306 	};
307 
308 	if (ber_scanf_elements(req->op, "{se", &oid, &ext_val) != 0)
309 		goto done;
310 
311 	log_debug("got extended operation %s", oid);
312 	req->op = ext_val;
313 
314 	for (i = 0; extended_ops[i].oid != NULL; i++) {
315 		if (strcmp(oid, extended_ops[i].oid) == 0) {
316 			rc = extended_ops[i].fn(req);
317 			break;
318 		}
319 	}
320 
321 	if (extended_ops[i].fn == NULL)
322 		log_warnx("unimplemented extended operation %s", oid);
323 
324 done:
325 	send_ldap_extended_response(req->conn, req->msgid, LDAP_RES_EXTENDED,
326 	    rc, oid);
327 
328 	request_free(req);
329 	return 0;
330 }
331 
332 pid_t
333 ldape(struct passwd *pw, char *csockpath, int pipe_parent2ldap[2])
334 {
335 	int			 on = 1;
336 	pid_t			 pid;
337 	struct namespace	*ns;
338 	struct listener		*l;
339 	struct sockaddr_un	*sun = NULL;
340 	struct event		 ev_sigint;
341 	struct event		 ev_sigterm;
342 	struct event		 ev_sigchld;
343 	struct event		 ev_sighup;
344 	struct ssl		 key;
345 	char			 host[128];
346 	mode_t			old_umask = 0;
347 
348 	TAILQ_INIT(&conn_list);
349 
350 	pid = fork();
351 	if (pid < 0)
352 		fatal("ldape: fork");
353 	if (pid > 0)
354 		return pid;
355 
356 	setproctitle("ldap server");
357 	event_init();
358 
359 	signal_set(&ev_sigint, SIGINT, ldape_sig_handler, NULL);
360 	signal_set(&ev_sigterm, SIGTERM, ldape_sig_handler, NULL);
361 	signal_set(&ev_sigchld, SIGCHLD, ldape_sig_handler, NULL);
362 	signal_set(&ev_sighup, SIGHUP, ldape_sig_handler, NULL);
363 	signal_add(&ev_sigint, NULL);
364 	signal_add(&ev_sigterm, NULL);
365 	signal_add(&ev_sigchld, NULL);
366 	signal_add(&ev_sighup, NULL);
367 	signal(SIGPIPE, SIG_IGN);
368 
369 	close(pipe_parent2ldap[0]);
370 
371 	/* Initialize parent imsg events. */
372 	if ((iev_ldapd = calloc(1, sizeof(struct imsgev))) == NULL)
373 		fatal("calloc");
374 	imsgev_init(iev_ldapd, pipe_parent2ldap[1], NULL, ldape_imsgev,
375 	    ldape_needfd);
376 
377 	/* Initialize control socket. */
378 	memset(&csock, 0, sizeof(csock));
379 	csock.cs_name = csockpath;
380 	control_init(&csock);
381 	control_listen(&csock);
382 	TAILQ_INIT(&ctl_conns);
383 
384 	/* Initialize LDAP listeners.
385 	 */
386 	TAILQ_FOREACH(l, &conf->listeners, entry) {
387 		l->fd = socket(l->ss.ss_family, SOCK_STREAM | SOCK_NONBLOCK,
388 		    0);
389 		if (l->fd < 0)
390 			fatal("ldape: socket");
391 
392 		setsockopt(l->fd, SOL_SOCKET, SO_REUSEADDR, &on, sizeof(on));
393 
394 		if (l->ss.ss_family == AF_UNIX) {
395 			sun = (struct sockaddr_un *)&l->ss;
396 			log_info("listening on %s", sun->sun_path);
397 			if (unlink(sun->sun_path) == -1 && errno != ENOENT)
398 				fatal("ldape: unlink");
399 		} else {
400 			print_host(&l->ss, host, sizeof(host));
401 			log_info("listening on %s:%d", host, ntohs(l->port));
402 		}
403 
404 		if (l->ss.ss_family == AF_UNIX) {
405 			old_umask = umask(S_IXUSR|S_IXGRP|S_IXOTH);
406 		}
407 
408 		if (bind(l->fd, (struct sockaddr *)&l->ss, l->ss.ss_len) != 0)
409 			fatal("ldape: bind");
410 
411 		if (l->ss.ss_family == AF_UNIX) {
412 			mode_t mode = S_IRUSR|S_IWUSR|S_IRGRP|S_IWGRP|S_IROTH|S_IWOTH;
413 
414 			(void)umask(old_umask);
415 			if (chmod(sun->sun_path, mode) == -1) {
416 				unlink(sun->sun_path);
417 				fatal("ldape: chmod");
418 			}
419 		}
420 
421 		if (listen(l->fd, 20) != 0)
422 			fatal("ldape: listen");
423 
424 		event_set(&l->ev, l->fd, EV_READ, conn_accept, l);
425 		event_add(&l->ev, NULL);
426 		evtimer_set(&l->evt, conn_accept, l);
427 
428 		if (l->flags & F_SSL) {
429 			if (strlcpy(key.ssl_name, l->ssl_cert_name,
430 			    sizeof(key.ssl_name)) >= sizeof(key.ssl_name))
431 				fatal("ldape: certificate name truncated");
432 
433 			l->ssl = SPLAY_FIND(ssltree, conf->sc_ssl, &key);
434 			if (l->ssl == NULL)
435 				fatal("ldape: certificate tree corrupted");
436 
437 			l->tls = tls_server();
438 			if (l->tls == NULL)
439 				fatal("ldape: couldn't allocate tls context");
440 
441 			if (tls_configure(l->tls, l->ssl->config)) {
442 				log_warn("ldape: %s", tls_error(l->tls));
443 				fatal("ldape: couldn't configure tls");
444 			}
445 		}
446 	}
447 
448 	TAILQ_FOREACH(ns, &conf->namespaces, next) {
449 		if (!namespace_has_referrals(ns) && namespace_open(ns) != 0)
450 			fatal(ns->suffix);
451 	}
452 
453 	if (pw != NULL) {
454 		if (chroot(pw->pw_dir) == -1)
455 			fatal("chroot");
456 		if (chdir("/") == -1)
457 			fatal("chdir(\"/\")");
458 
459 		if (setgroups(1, &pw->pw_gid) ||
460 		    setresgid(pw->pw_gid, pw->pw_gid, pw->pw_gid) ||
461 		    setresuid(pw->pw_uid, pw->pw_uid, pw->pw_uid))
462 			fatal("cannot drop privileges");
463 	}
464 
465 	if (pledge("stdio flock inet unix recvfd", NULL) == -1)
466 		fatal("pledge");
467 
468 	log_debug("ldape: entering event loop");
469 	event_dispatch();
470 
471 	while ((ns = TAILQ_FIRST(&conf->namespaces)) != NULL)
472 		namespace_remove(ns);
473 
474 	control_cleanup(&csock);
475 
476 	log_info("ldape: exiting");
477 	_exit(0);
478 }
479 
480 static void
481 ldape_imsgev(struct imsgev *iev, int code, struct imsg *imsg)
482 {
483 	switch (code) {
484 	case IMSGEV_IMSG:
485 		log_debug("%s: got imsg %d on fd %d",
486 		    __func__, imsg->hdr.type, iev->ibuf.fd);
487 		switch (imsg->hdr.type) {
488 		case IMSG_LDAPD_AUTH_RESULT:
489 			ldape_auth_result(imsg);
490 			break;
491 		case IMSG_LDAPD_OPEN_RESULT:
492 			ldape_open_result(imsg);
493 			break;
494 		default:
495 			log_debug("%s: unexpected imsg %d",
496 			    __func__, imsg->hdr.type);
497 			break;
498 		}
499 		break;
500 	case IMSGEV_EREAD:
501 	case IMSGEV_EWRITE:
502 	case IMSGEV_EIMSG:
503 		fatal("imsgev read/write error");
504 		break;
505 	case IMSGEV_DONE:
506 		event_loopexit(NULL);
507 		break;
508 	}
509 }
510 
511 static void
512 ldape_needfd(struct imsgev *iev)
513 {
514 	/* Try to close a control connection first */
515 	if (control_close_any(&csock) == 0) {
516 		log_warn("closed a control connection");
517 		return;
518 	}
519 
520 	if (conn_close_any() == 0) {
521 		log_warn("closed a client connection");
522 		return;
523 	}
524 
525 	fatal("unable to free an fd");
526 }
527 
528 static void
529 ldape_auth_result(struct imsg *imsg)
530 {
531 	struct conn		*conn;
532 	struct auth_res		*ares = imsg->data;
533 
534 	log_debug("authentication on conn %d/%lld = %d", ares->fd, ares->msgid,
535 	    ares->ok);
536 	conn = conn_by_fd(ares->fd);
537 	if (conn->bind_req != NULL && conn->bind_req->msgid == ares->msgid)
538 		ldap_bind_continue(conn, ares->ok);
539 	else
540 		log_warnx("spurious auth result");
541 }
542 
543 static void
544 ldape_open_result(struct imsg *imsg)
545 {
546 	struct namespace	*ns;
547 	struct open_req		*oreq = imsg->data;
548 
549 	if (imsg->hdr.len != sizeof(*oreq) + IMSG_HEADER_SIZE)
550 		fatal("invalid size of open result");
551 
552 	/* make sure path is null-terminated */
553 	oreq->path[PATH_MAX] = '\0';
554 
555 	log_debug("open(%s) returned fd %d", oreq->path, imsg->fd);
556 
557 	TAILQ_FOREACH(ns, &conf->namespaces, next) {
558 		if (namespace_has_referrals(ns))
559 			continue;
560 		if (strcmp(oreq->path, ns->data_path) == 0) {
561 			namespace_set_data_fd(ns, imsg->fd);
562 			break;
563 		}
564 		if (strcmp(oreq->path, ns->indx_path) == 0) {
565 			namespace_set_indx_fd(ns, imsg->fd);
566 			break;
567 		}
568 	}
569 
570 	if (ns == NULL) {
571 		log_warnx("spurious open result");
572 		close(imsg->fd);
573 	} else
574 		namespace_queue_schedule(ns, 0);
575 }
576 
577