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