1 /* $OpenBSD: ldape.c,v 1.33 2019/10/26 17:52:55 martijn 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 int 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 int type, 73 long long result_code, const char *extended_oid) 74 { 75 ssize_t 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 = ober_add_sequence(NULL)) == NULL) 82 goto fail; 83 84 elm = ober_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 (ober_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 = ober_write_elements(&conn->ber, root); 96 ober_free_elements(root); 97 98 if (rc < 0) 99 log_warn("failed to create ldap result"); 100 else { 101 ober_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 ober_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 int type; 120 ssize_t 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 = ober_add_sequence(NULL)) == NULL) 140 goto fail; 141 142 if ((elm = ref_root = ober_add_sequence(NULL)) == NULL) 143 goto fail; 144 ober_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 = ober_add_string(elm, url); 157 free(url); 158 if (elm == NULL) 159 goto fail; 160 } 161 162 elm = ober_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 = ober_write_elements(&req->conn->ber, root); 169 ober_free_elements(root); 170 171 if (rc < 0) 172 log_warn("failed to create ldap result"); 173 else { 174 ober_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 ober_free_elements(root); 185 if (ref_root != NULL) 186 ober_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 int 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 (ober_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", 233 req->conn->binddn == NULL ? "" : req->conn->binddn); 234 conn_disconnect(req->conn); 235 request_free(req); 236 return -1; /* don't send any response */ 237 } 238 239 int 240 ldap_compare(struct request *req) 241 { 242 struct ber_element *entry, *elm, *attr; 243 struct namespace *ns; 244 struct referrals *refs; 245 struct attr_type *at; 246 char *dn, *aname, *value, *s; 247 248 if (ober_scanf_elements(req->op, "{s{ss", &dn, &aname, &value) != 0) { 249 log_debug("%s: protocol error", __func__); 250 request_free(req); 251 return -1; 252 } 253 254 if ((at = lookup_attribute(conf->schema, aname)) == NULL) 255 return ldap_respond(req, LDAP_UNDEFINED_TYPE); 256 257 if ((ns = namespace_for_base(dn)) == NULL) { 258 refs = namespace_referrals(dn); 259 if (refs == NULL) 260 return ldap_respond(req, LDAP_NO_SUCH_OBJECT); 261 else 262 return ldap_refer(req, dn, NULL, refs); 263 } 264 265 if ((entry = namespace_get(ns, dn)) == NULL) 266 return ldap_respond(req, LDAP_NO_SUCH_OBJECT); 267 268 if ((attr = ldap_find_attribute(entry, at)) == NULL) 269 return ldap_respond(req, LDAP_NO_SUCH_ATTRIBUTE); 270 271 if ((attr = attr->be_next) == NULL) /* skip attribute name */ 272 return ldap_respond(req, LDAP_OTHER); 273 274 for (elm = attr->be_sub; elm != NULL; elm = elm->be_next) { 275 if (ober_get_string(elm, &s) != 0) 276 return ldap_respond(req, LDAP_OTHER); 277 if (strcasecmp(value, s) == 0) 278 return ldap_respond(req, LDAP_COMPARE_TRUE); 279 } 280 281 return ldap_respond(req, LDAP_COMPARE_FALSE); 282 } 283 284 int 285 ldap_starttls(struct request *req) 286 { 287 if ((req->conn->listener->flags & F_STARTTLS) == 0) { 288 log_debug("StartTLS not configured for this connection"); 289 return LDAP_OPERATIONS_ERROR; 290 } 291 292 req->conn->s_flags |= F_STARTTLS; 293 return LDAP_SUCCESS; 294 } 295 296 int 297 ldap_extended(struct request *req) 298 { 299 int i, rc = LDAP_PROTOCOL_ERROR; 300 char *oid = 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 (ober_scanf_elements(req->op, "{s", &oid) != 0) 310 goto done; 311 312 log_debug("got extended operation %s", oid); 313 req->op = req->op->be_sub->be_next; 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 TAILQ_INIT(&conn_list); 350 351 ldap_loginit("ldap server", debug, verbose); 352 setproctitle("ldap server"); 353 event_init(); 354 355 signal_set(&ev_sigint, SIGINT, ldape_sig_handler, NULL); 356 signal_set(&ev_sigterm, SIGTERM, ldape_sig_handler, NULL); 357 signal_set(&ev_sigchld, SIGCHLD, ldape_sig_handler, NULL); 358 signal_set(&ev_sighup, SIGHUP, ldape_sig_handler, NULL); 359 signal_add(&ev_sigint, NULL); 360 signal_add(&ev_sigterm, NULL); 361 signal_add(&ev_sigchld, NULL); 362 signal_add(&ev_sighup, NULL); 363 signal(SIGPIPE, SIG_IGN); 364 365 /* Initialize parent imsg events. */ 366 if ((iev_ldapd = calloc(1, sizeof(struct imsgev))) == NULL) 367 fatal("calloc"); 368 imsgev_init(iev_ldapd, PROC_PARENT_SOCK_FILENO, NULL, ldape_imsgev, 369 ldape_needfd); 370 371 /* Initialize control socket. */ 372 memset(&csock, 0, sizeof(csock)); 373 csock.cs_name = csockpath; 374 control_init(&csock); 375 control_listen(&csock); 376 TAILQ_INIT(&ctl_conns); 377 378 /* Initialize LDAP listeners. 379 */ 380 TAILQ_FOREACH(l, &conf->listeners, entry) { 381 l->fd = socket(l->ss.ss_family, SOCK_STREAM | SOCK_NONBLOCK, 382 0); 383 if (l->fd == -1) 384 fatal("ldape: socket"); 385 386 setsockopt(l->fd, SOL_SOCKET, SO_REUSEADDR, &on, sizeof(on)); 387 388 if (l->ss.ss_family == AF_UNIX) { 389 sun = (struct sockaddr_un *)&l->ss; 390 log_info("listening on %s", sun->sun_path); 391 if (unlink(sun->sun_path) == -1 && errno != ENOENT) 392 fatal("ldape: unlink"); 393 } else { 394 print_host(&l->ss, host, sizeof(host)); 395 log_info("listening on %s:%d", host, ntohs(l->port)); 396 } 397 398 if (l->ss.ss_family == AF_UNIX) { 399 old_umask = umask(S_IXUSR|S_IXGRP|S_IXOTH); 400 } 401 402 if (bind(l->fd, (struct sockaddr *)&l->ss, l->ss.ss_len) != 0) 403 fatal("ldape: bind"); 404 405 if (l->ss.ss_family == AF_UNIX) { 406 mode_t mode = S_IRUSR|S_IWUSR|S_IRGRP|S_IWGRP|S_IROTH|S_IWOTH; 407 408 (void)umask(old_umask); 409 if (chmod(sun->sun_path, mode) == -1) { 410 unlink(sun->sun_path); 411 fatal("ldape: chmod"); 412 } 413 } 414 415 if (listen(l->fd, 20) != 0) 416 fatal("ldape: listen"); 417 418 event_set(&l->ev, l->fd, EV_READ, conn_accept, l); 419 event_add(&l->ev, NULL); 420 evtimer_set(&l->evt, conn_accept, l); 421 422 if (l->flags & F_SSL) { 423 if (strlcpy(key.ssl_name, l->ssl_cert_name, 424 sizeof(key.ssl_name)) >= sizeof(key.ssl_name)) 425 fatal("ldape: certificate name truncated"); 426 427 l->ssl = SPLAY_FIND(ssltree, conf->sc_ssl, &key); 428 if (l->ssl == NULL) 429 fatal("ldape: certificate tree corrupted"); 430 431 l->tls = tls_server(); 432 if (l->tls == NULL) 433 fatal("ldape: couldn't allocate tls context"); 434 435 if (tls_configure(l->tls, l->ssl->config)) { 436 log_warn("ldape: %s", tls_error(l->tls)); 437 fatal("ldape: couldn't configure tls"); 438 } 439 } 440 } 441 442 TAILQ_FOREACH(ns, &conf->namespaces, next) { 443 if (!namespace_has_referrals(ns) && namespace_open(ns) != 0) 444 fatal("%s", ns->suffix); 445 } 446 447 if ((pw = getpwnam(LDAPD_USER)) == NULL) 448 fatal("getpwnam"); 449 450 if (pw != NULL) { 451 if (chroot(pw->pw_dir) == -1) 452 fatal("chroot"); 453 if (chdir("/") == -1) 454 fatal("chdir(\"/\")"); 455 456 if (setgroups(1, &pw->pw_gid) || 457 setresgid(pw->pw_gid, pw->pw_gid, pw->pw_gid) || 458 setresuid(pw->pw_uid, pw->pw_uid, pw->pw_uid)) 459 fatal("cannot drop privileges"); 460 } 461 462 if (pledge("stdio flock inet unix recvfd", NULL) == -1) 463 fatal("pledge"); 464 465 log_debug("ldape: entering event loop"); 466 event_dispatch(); 467 468 while ((ns = TAILQ_FIRST(&conf->namespaces)) != NULL) 469 namespace_remove(ns); 470 471 control_cleanup(&csock); 472 473 log_info("ldape: exiting"); 474 exit(0); 475 } 476 477 static void 478 ldape_imsgev(struct imsgev *iev, int code, struct imsg *imsg) 479 { 480 switch (code) { 481 case IMSGEV_IMSG: 482 log_debug("%s: got imsg %d on fd %d", 483 __func__, imsg->hdr.type, iev->ibuf.fd); 484 switch (imsg->hdr.type) { 485 case IMSG_LDAPD_AUTH_RESULT: 486 ldape_auth_result(imsg); 487 break; 488 case IMSG_LDAPD_OPEN_RESULT: 489 ldape_open_result(imsg); 490 break; 491 default: 492 log_debug("%s: unexpected imsg %d", 493 __func__, imsg->hdr.type); 494 break; 495 } 496 break; 497 case IMSGEV_EREAD: 498 case IMSGEV_EWRITE: 499 case IMSGEV_EIMSG: 500 fatal("imsgev read/write error"); 501 break; 502 case IMSGEV_DONE: 503 event_loopexit(NULL); 504 break; 505 } 506 } 507 508 static void 509 ldape_needfd(struct imsgev *iev) 510 { 511 /* Try to close a control connection first */ 512 if (control_close_any(&csock) == 0) { 513 log_warn("closed a control connection"); 514 return; 515 } 516 517 if (conn_close_any() == 0) { 518 log_warn("closed a client connection"); 519 return; 520 } 521 522 fatal("unable to free an fd"); 523 } 524 525 static void 526 ldape_auth_result(struct imsg *imsg) 527 { 528 struct conn *conn; 529 struct auth_res *ares = imsg->data; 530 531 log_debug("authentication on conn %d/%lld = %d", ares->fd, ares->msgid, 532 ares->ok); 533 conn = conn_by_fd(ares->fd); 534 if (conn->bind_req != NULL && conn->bind_req->msgid == ares->msgid) 535 ldap_bind_continue(conn, ares->ok); 536 else 537 log_warnx("spurious auth result"); 538 } 539 540 static void 541 ldape_open_result(struct imsg *imsg) 542 { 543 struct namespace *ns; 544 struct open_req *oreq = imsg->data; 545 546 if (imsg->hdr.len != sizeof(*oreq) + IMSG_HEADER_SIZE) 547 fatal("invalid size of open result"); 548 549 /* make sure path is null-terminated */ 550 oreq->path[PATH_MAX] = '\0'; 551 552 log_debug("open(%s) returned fd %d", oreq->path, imsg->fd); 553 554 TAILQ_FOREACH(ns, &conf->namespaces, next) { 555 if (namespace_has_referrals(ns)) 556 continue; 557 if (strcmp(oreq->path, ns->data_path) == 0) { 558 namespace_set_data_fd(ns, imsg->fd); 559 break; 560 } 561 if (strcmp(oreq->path, ns->indx_path) == 0) { 562 namespace_set_indx_fd(ns, imsg->fd); 563 break; 564 } 565 } 566 567 if (ns == NULL) { 568 log_warnx("spurious open result"); 569 close(imsg->fd); 570 } else 571 namespace_queue_schedule(ns, 0); 572 } 573 574