1 /* $OpenBSD: ldape.c,v 1.17 2012/06/16 00:08:32 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 %i", type, req->msgid); 136 137 if ((root = ber_add_sequence(NULL)) == NULL) 138 goto fail; 139 140 if ((elm = ref_root = ber_add_sequence(NULL)) == NULL) 141 goto fail; 142 ber_set_header(ref_root, BER_CLASS_CONTEXT, LDAP_REQ_SEARCH); 143 SLIST_FOREACH(ref, refs, next) { 144 if (search != NULL) 145 asprintf(&url, "%s/%s??%s", ref->url, basedn, 146 scope_str); 147 else 148 asprintf(&url, "%s/%s", ref->url, basedn); 149 if (url == NULL) { 150 log_warn("asprintf"); 151 goto fail; 152 } 153 log_debug("adding referral '%s'", url); 154 elm = ber_add_string(elm, url); 155 free(url); 156 if (elm == NULL) 157 goto fail; 158 } 159 160 elm = ber_printf_elements(root, "d{tEsse", 161 req->msgid, BER_CLASS_APP, type, result_code, "", "", ref_root); 162 if (elm == NULL) 163 goto fail; 164 ref_root = NULL; 165 166 rc = ber_write_elements(&req->conn->ber, root); 167 ber_free_elements(root); 168 169 if (rc < 0) 170 log_warn("failed to create ldap result"); 171 else { 172 ber_get_writebuf(&req->conn->ber, &buf); 173 if (bufferevent_write(req->conn->bev, buf, rc) != 0) 174 log_warn("failed to send ldap result"); 175 } 176 177 request_free(req); 178 return LDAP_REFERRAL; 179 180 fail: 181 if (root != NULL) 182 ber_free_elements(root); 183 if (ref_root != NULL) 184 ber_free_elements(ref_root); 185 request_free(req); 186 return LDAP_REFERRAL; 187 } 188 189 void 190 send_ldap_result(struct conn *conn, int msgid, unsigned long type, 191 long long result_code) 192 { 193 send_ldap_extended_response(conn, msgid, type, result_code, NULL); 194 } 195 196 int 197 ldap_respond(struct request *req, int code) 198 { 199 if (code >= 0) 200 send_ldap_result(req->conn, req->msgid, req->type + 1, code); 201 request_free(req); 202 return code; 203 } 204 205 int 206 ldap_abandon(struct request *req) 207 { 208 long long msgid; 209 struct search *search; 210 211 if (ber_scanf_elements(req->op, "i", &msgid) != 0) { 212 request_free(req); 213 return -1; /* protocol error, but don't respond */ 214 } 215 216 TAILQ_FOREACH(search, &req->conn->searches, next) { 217 if (search->req->msgid == msgid) { 218 /* unlinks the search from conn->searches */ 219 search_close(search); 220 break; 221 } 222 } 223 request_free(req); 224 return -1; 225 } 226 227 int 228 ldap_unbind(struct request *req) 229 { 230 log_debug("current bind dn = %s", req->conn->binddn); 231 conn_disconnect(req->conn); 232 request_free(req); 233 return -1; /* don't send any response */ 234 } 235 236 int 237 ldap_compare(struct request *req) 238 { 239 struct ber_element *entry, *elm, *attr; 240 struct namespace *ns; 241 struct referrals *refs; 242 struct attr_type *at; 243 char *dn, *aname, *value, *s; 244 245 if (ber_scanf_elements(req->op, "{s{ss", &dn, &aname, &value) != 0) { 246 log_debug("%s: protocol error", __func__); 247 request_free(req); 248 return -1; 249 } 250 251 if ((at = lookup_attribute(conf->schema, aname)) == NULL) 252 return ldap_respond(req, LDAP_UNDEFINED_TYPE); 253 254 if ((ns = namespace_for_base(dn)) == NULL) { 255 refs = namespace_referrals(dn); 256 if (refs == NULL) 257 return ldap_respond(req, LDAP_NO_SUCH_OBJECT); 258 else 259 return ldap_refer(req, dn, NULL, refs); 260 } 261 262 if ((entry = namespace_get(ns, dn)) == NULL) 263 return ldap_respond(req, LDAP_NO_SUCH_OBJECT); 264 265 if ((attr = ldap_find_attribute(entry, at)) == NULL) 266 return ldap_respond(req, LDAP_NO_SUCH_ATTRIBUTE); 267 268 if ((attr = attr->be_next) == NULL) /* skip attribute name */ 269 return ldap_respond(req, LDAP_OTHER); 270 271 for (elm = attr->be_sub; elm != NULL; elm = elm->be_next) { 272 if (ber_get_string(elm, &s) != 0) 273 return ldap_respond(req, LDAP_OTHER); 274 if (strcasecmp(value, s) == 0) 275 return ldap_respond(req, LDAP_COMPARE_TRUE); 276 } 277 278 return ldap_respond(req, LDAP_COMPARE_FALSE); 279 } 280 281 int 282 ldap_starttls(struct request *req) 283 { 284 if ((req->conn->listener->flags & F_STARTTLS) == 0) { 285 log_debug("StartTLS not configured for this connection"); 286 return LDAP_OPERATIONS_ERROR; 287 } 288 289 req->conn->s_flags |= F_STARTTLS; 290 return LDAP_SUCCESS; 291 } 292 293 int 294 ldap_extended(struct request *req) 295 { 296 int i, rc = LDAP_PROTOCOL_ERROR; 297 char *oid = NULL; 298 struct ber_element *ext_val = NULL; 299 struct { 300 const char *oid; 301 int (*fn)(struct request *); 302 } extended_ops[] = { 303 { "1.3.6.1.4.1.1466.20037", ldap_starttls }, 304 { NULL } 305 }; 306 307 if (ber_scanf_elements(req->op, "{se", &oid, &ext_val) != 0) 308 goto done; 309 310 log_debug("got extended operation %s", oid); 311 req->op = ext_val; 312 313 for (i = 0; extended_ops[i].oid != NULL; i++) { 314 if (strcmp(oid, extended_ops[i].oid) == 0) { 315 rc = extended_ops[i].fn(req); 316 break; 317 } 318 } 319 320 if (extended_ops[i].fn == NULL) 321 log_warnx("unimplemented extended operation %s", oid); 322 323 done: 324 send_ldap_extended_response(req->conn, req->msgid, LDAP_RES_EXTENDED, 325 rc, oid); 326 327 request_free(req); 328 return 0; 329 } 330 331 pid_t 332 ldape(struct passwd *pw, char *csockpath, int pipe_parent2ldap[2]) 333 { 334 int on = 1; 335 pid_t pid; 336 struct namespace *ns; 337 struct listener *l; 338 struct sockaddr_un *sun = NULL; 339 struct event ev_sigint; 340 struct event ev_sigterm; 341 struct event ev_sigchld; 342 struct event ev_sighup; 343 char host[128]; 344 mode_t old_umask = 0; 345 346 TAILQ_INIT(&conn_list); 347 348 pid = fork(); 349 if (pid < 0) 350 fatal("ldape: fork"); 351 if (pid > 0) 352 return pid; 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 close(pipe_parent2ldap[0]); 368 369 /* Initialize parent imsg events. */ 370 if ((iev_ldapd = calloc(1, sizeof(struct imsgev))) == NULL) 371 fatal("calloc"); 372 imsgev_init(iev_ldapd, pipe_parent2ldap[1], NULL, ldape_imsgev, 373 ldape_needfd); 374 375 /* Initialize control socket. */ 376 bzero(&csock, sizeof(csock)); 377 csock.cs_name = csockpath; 378 control_init(&csock); 379 control_listen(&csock); 380 TAILQ_INIT(&ctl_conns); 381 382 /* Initialize LDAP listeners. 383 */ 384 TAILQ_FOREACH(l, &conf->listeners, entry) { 385 l->fd = socket(l->ss.ss_family, SOCK_STREAM, 0); 386 if (l->fd < 0) 387 fatal("ldape: socket"); 388 389 setsockopt(l->fd, SOL_SOCKET, SO_REUSEADDR, &on, sizeof(on)); 390 391 if (l->ss.ss_family == AF_UNIX) { 392 sun = (struct sockaddr_un *)&l->ss; 393 log_info("listening on %s", sun->sun_path); 394 if (unlink(sun->sun_path) == -1 && errno != ENOENT) 395 fatal("ldape: unlink"); 396 } else { 397 print_host(&l->ss, host, sizeof(host)); 398 log_info("listening on %s:%d", host, ntohs(l->port)); 399 } 400 401 if (l->ss.ss_family == AF_UNIX) { 402 old_umask = umask(S_IXUSR|S_IXGRP|S_IXOTH); 403 } 404 405 if (bind(l->fd, (struct sockaddr *)&l->ss, l->ss.ss_len) != 0) 406 fatal("ldape: bind"); 407 408 if (l->ss.ss_family == AF_UNIX) { 409 mode_t mode = S_IRUSR|S_IWUSR|S_IRGRP|S_IWGRP|S_IROTH|S_IWOTH; 410 411 (void)umask(old_umask); 412 if (chmod(sun->sun_path, mode) == -1) { 413 unlink(sun->sun_path); 414 fatal("ldape: chmod"); 415 } 416 } 417 418 if (listen(l->fd, 20) != 0) 419 fatal("ldape: listen"); 420 421 fd_nonblock(l->fd); 422 423 event_set(&l->ev, l->fd, EV_READ, conn_accept, l); 424 event_add(&l->ev, NULL); 425 evtimer_set(&l->evt, conn_accept, l); 426 427 ssl_setup(conf, l); 428 } 429 430 TAILQ_FOREACH(ns, &conf->namespaces, next) { 431 if (!namespace_has_referrals(ns) && namespace_open(ns) != 0) 432 fatal(ns->suffix); 433 } 434 435 if (pw != NULL) { 436 if (chroot(pw->pw_dir) == -1) 437 fatal("chroot"); 438 if (chdir("/") == -1) 439 fatal("chdir(\"/\")"); 440 441 if (setgroups(1, &pw->pw_gid) || 442 setresgid(pw->pw_gid, pw->pw_gid, pw->pw_gid) || 443 setresuid(pw->pw_uid, pw->pw_uid, pw->pw_uid)) 444 fatal("cannot drop privileges"); 445 } 446 447 log_debug("ldape: entering event loop"); 448 event_dispatch(); 449 450 while ((ns = TAILQ_FIRST(&conf->namespaces)) != NULL) 451 namespace_remove(ns); 452 453 control_cleanup(&csock); 454 455 log_info("ldape: exiting"); 456 _exit(0); 457 } 458 459 static void 460 ldape_imsgev(struct imsgev *iev, int code, struct imsg *imsg) 461 { 462 switch (code) { 463 case IMSGEV_IMSG: 464 log_debug("%s: got imsg %i on fd %i", 465 __func__, imsg->hdr.type, iev->ibuf.fd); 466 switch (imsg->hdr.type) { 467 case IMSG_LDAPD_AUTH_RESULT: 468 ldape_auth_result(imsg); 469 break; 470 case IMSG_LDAPD_OPEN_RESULT: 471 ldape_open_result(imsg); 472 break; 473 default: 474 log_debug("%s: unexpected imsg %d", 475 __func__, imsg->hdr.type); 476 break; 477 } 478 break; 479 case IMSGEV_EREAD: 480 case IMSGEV_EWRITE: 481 case IMSGEV_EIMSG: 482 fatal("imsgev read/write error"); 483 break; 484 case IMSGEV_DONE: 485 event_loopexit(NULL); 486 break; 487 } 488 } 489 490 static void 491 ldape_needfd(struct imsgev *iev) 492 { 493 /* Try to close a control connection first */ 494 if (control_close_any(&csock) == 0) { 495 log_warn("closed a control connection"); 496 return; 497 } 498 499 if (conn_close_any() == 0) { 500 log_warn("closed a client connection"); 501 return; 502 } 503 504 fatal("unable to free an fd"); 505 } 506 507 static void 508 ldape_auth_result(struct imsg *imsg) 509 { 510 struct conn *conn; 511 struct auth_res *ares = imsg->data; 512 513 log_debug("authentication on conn %i/%lld = %d", ares->fd, ares->msgid, 514 ares->ok); 515 conn = conn_by_fd(ares->fd); 516 if (conn->bind_req != NULL && conn->bind_req->msgid == ares->msgid) 517 ldap_bind_continue(conn, ares->ok); 518 else 519 log_warnx("spurious auth result"); 520 } 521 522 static void 523 ldape_open_result(struct imsg *imsg) 524 { 525 struct namespace *ns; 526 struct open_req *oreq = imsg->data; 527 528 if (imsg->hdr.len != sizeof(*oreq) + IMSG_HEADER_SIZE) 529 fatal("invalid size of open result"); 530 531 /* make sure path is null-terminated */ 532 oreq->path[MAXPATHLEN] = '\0'; 533 534 log_debug("open(%s) returned fd %i", oreq->path, imsg->fd); 535 536 TAILQ_FOREACH(ns, &conf->namespaces, next) { 537 if (namespace_has_referrals(ns)) 538 continue; 539 if (strcmp(oreq->path, ns->data_path) == 0) { 540 namespace_set_data_fd(ns, imsg->fd); 541 break; 542 } 543 if (strcmp(oreq->path, ns->indx_path) == 0) { 544 namespace_set_indx_fd(ns, imsg->fd); 545 break; 546 } 547 } 548 549 if (ns == NULL) { 550 log_warnx("spurious open result"); 551 close(imsg->fd); 552 } else 553 namespace_queue_schedule(ns, 0); 554 } 555 556