xref: /openbsd-src/usr.sbin/ldapd/ldape.c (revision 50b7afb2c2c0993b0894d4e34bf857cb13ed9c80)
1 /*	$OpenBSD: ldape.c,v 1.18 2013/11/02 13:31:51 deraadt 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 			asprintf(&url, "%s/%s??%s", ref->url, basedn,
147 			    scope_str);
148 		else
149 			asprintf(&url, "%s/%s", ref->url, basedn);
150 		if (url == NULL) {
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 	char			 host[128];
345 	mode_t			old_umask = 0;
346 
347 	TAILQ_INIT(&conn_list);
348 
349 	pid = fork();
350 	if (pid < 0)
351 		fatal("ldape: fork");
352 	if (pid > 0)
353 		return pid;
354 
355 	setproctitle("ldap server");
356 	event_init();
357 
358 	signal_set(&ev_sigint, SIGINT, ldape_sig_handler, NULL);
359 	signal_set(&ev_sigterm, SIGTERM, ldape_sig_handler, NULL);
360 	signal_set(&ev_sigchld, SIGCHLD, ldape_sig_handler, NULL);
361 	signal_set(&ev_sighup, SIGHUP, ldape_sig_handler, NULL);
362 	signal_add(&ev_sigint, NULL);
363 	signal_add(&ev_sigterm, NULL);
364 	signal_add(&ev_sigchld, NULL);
365 	signal_add(&ev_sighup, NULL);
366 	signal(SIGPIPE, SIG_IGN);
367 
368 	close(pipe_parent2ldap[0]);
369 
370 	/* Initialize parent imsg events. */
371 	if ((iev_ldapd = calloc(1, sizeof(struct imsgev))) == NULL)
372 		fatal("calloc");
373 	imsgev_init(iev_ldapd, pipe_parent2ldap[1], NULL, ldape_imsgev,
374 	    ldape_needfd);
375 
376 	/* Initialize control socket. */
377 	bzero(&csock, sizeof(csock));
378 	csock.cs_name = csockpath;
379 	control_init(&csock);
380 	control_listen(&csock);
381 	TAILQ_INIT(&ctl_conns);
382 
383 	/* Initialize LDAP listeners.
384 	 */
385 	TAILQ_FOREACH(l, &conf->listeners, entry) {
386 		l->fd = socket(l->ss.ss_family, SOCK_STREAM, 0);
387 		if (l->fd < 0)
388 			fatal("ldape: socket");
389 
390 		setsockopt(l->fd, SOL_SOCKET, SO_REUSEADDR, &on, sizeof(on));
391 
392 		if (l->ss.ss_family == AF_UNIX) {
393 			sun = (struct sockaddr_un *)&l->ss;
394 			log_info("listening on %s", sun->sun_path);
395 			if (unlink(sun->sun_path) == -1 && errno != ENOENT)
396 				fatal("ldape: unlink");
397 		} else {
398 			print_host(&l->ss, host, sizeof(host));
399 			log_info("listening on %s:%d", host, ntohs(l->port));
400 		}
401 
402 		if (l->ss.ss_family == AF_UNIX) {
403 			old_umask = umask(S_IXUSR|S_IXGRP|S_IXOTH);
404 		}
405 
406 		if (bind(l->fd, (struct sockaddr *)&l->ss, l->ss.ss_len) != 0)
407 			fatal("ldape: bind");
408 
409 		if (l->ss.ss_family == AF_UNIX) {
410 			mode_t mode = S_IRUSR|S_IWUSR|S_IRGRP|S_IWGRP|S_IROTH|S_IWOTH;
411 
412 			(void)umask(old_umask);
413 			if (chmod(sun->sun_path, mode) == -1) {
414 				unlink(sun->sun_path);
415 				fatal("ldape: chmod");
416 			}
417 		}
418 
419 		if (listen(l->fd, 20) != 0)
420 			fatal("ldape: listen");
421 
422 		fd_nonblock(l->fd);
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 		ssl_setup(conf, l);
429 	}
430 
431 	TAILQ_FOREACH(ns, &conf->namespaces, next) {
432 		if (!namespace_has_referrals(ns) && namespace_open(ns) != 0)
433 			fatal(ns->suffix);
434 	}
435 
436 	if (pw != NULL) {
437 		if (chroot(pw->pw_dir) == -1)
438 			fatal("chroot");
439 		if (chdir("/") == -1)
440 			fatal("chdir(\"/\")");
441 
442 		if (setgroups(1, &pw->pw_gid) ||
443 		    setresgid(pw->pw_gid, pw->pw_gid, pw->pw_gid) ||
444 		    setresuid(pw->pw_uid, pw->pw_uid, pw->pw_uid))
445 			fatal("cannot drop privileges");
446 	}
447 
448 	log_debug("ldape: entering event loop");
449 	event_dispatch();
450 
451 	while ((ns = TAILQ_FIRST(&conf->namespaces)) != NULL)
452 		namespace_remove(ns);
453 
454 	control_cleanup(&csock);
455 
456 	log_info("ldape: exiting");
457 	_exit(0);
458 }
459 
460 static void
461 ldape_imsgev(struct imsgev *iev, int code, struct imsg *imsg)
462 {
463 	switch (code) {
464 	case IMSGEV_IMSG:
465 		log_debug("%s: got imsg %d on fd %d",
466 		    __func__, imsg->hdr.type, iev->ibuf.fd);
467 		switch (imsg->hdr.type) {
468 		case IMSG_LDAPD_AUTH_RESULT:
469 			ldape_auth_result(imsg);
470 			break;
471 		case IMSG_LDAPD_OPEN_RESULT:
472 			ldape_open_result(imsg);
473 			break;
474 		default:
475 			log_debug("%s: unexpected imsg %d",
476 			    __func__, imsg->hdr.type);
477 			break;
478 		}
479 		break;
480 	case IMSGEV_EREAD:
481 	case IMSGEV_EWRITE:
482 	case IMSGEV_EIMSG:
483 		fatal("imsgev read/write error");
484 		break;
485 	case IMSGEV_DONE:
486 		event_loopexit(NULL);
487 		break;
488 	}
489 }
490 
491 static void
492 ldape_needfd(struct imsgev *iev)
493 {
494 	/* Try to close a control connection first */
495 	if (control_close_any(&csock) == 0) {
496 		log_warn("closed a control connection");
497 		return;
498 	}
499 
500 	if (conn_close_any() == 0) {
501 		log_warn("closed a client connection");
502 		return;
503 	}
504 
505 	fatal("unable to free an fd");
506 }
507 
508 static void
509 ldape_auth_result(struct imsg *imsg)
510 {
511 	struct conn		*conn;
512 	struct auth_res		*ares = imsg->data;
513 
514 	log_debug("authentication on conn %d/%lld = %d", ares->fd, ares->msgid,
515 	    ares->ok);
516 	conn = conn_by_fd(ares->fd);
517 	if (conn->bind_req != NULL && conn->bind_req->msgid == ares->msgid)
518 		ldap_bind_continue(conn, ares->ok);
519 	else
520 		log_warnx("spurious auth result");
521 }
522 
523 static void
524 ldape_open_result(struct imsg *imsg)
525 {
526 	struct namespace	*ns;
527 	struct open_req		*oreq = imsg->data;
528 
529 	if (imsg->hdr.len != sizeof(*oreq) + IMSG_HEADER_SIZE)
530 		fatal("invalid size of open result");
531 
532 	/* make sure path is null-terminated */
533 	oreq->path[MAXPATHLEN] = '\0';
534 
535 	log_debug("open(%s) returned fd %d", oreq->path, imsg->fd);
536 
537 	TAILQ_FOREACH(ns, &conf->namespaces, next) {
538 		if (namespace_has_referrals(ns))
539 			continue;
540 		if (strcmp(oreq->path, ns->data_path) == 0) {
541 			namespace_set_data_fd(ns, imsg->fd);
542 			break;
543 		}
544 		if (strcmp(oreq->path, ns->indx_path) == 0) {
545 			namespace_set_indx_fd(ns, imsg->fd);
546 			break;
547 		}
548 	}
549 
550 	if (ns == NULL) {
551 		log_warnx("spurious open result");
552 		close(imsg->fd);
553 	} else
554 		namespace_queue_schedule(ns, 0);
555 }
556 
557