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