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