1 /* $OpenBSD: slowcgi.c,v 1.48 2015/11/20 09:04:01 tb Exp $ */ 2 /* 3 * Copyright (c) 2013 David Gwynne <dlg@openbsd.org> 4 * Copyright (c) 2013 Florian Obser <florian@openbsd.org> 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/types.h> 20 #include <sys/ioctl.h> 21 #include <sys/queue.h> 22 #include <sys/socket.h> 23 #include <sys/stat.h> 24 #include <sys/time.h> 25 #include <sys/un.h> 26 #include <sys/wait.h> 27 #include <arpa/inet.h> 28 #include <err.h> 29 #include <fcntl.h> 30 #include <errno.h> 31 #include <event.h> 32 #include <limits.h> 33 #include <pwd.h> 34 #include <signal.h> 35 #include <stdarg.h> 36 #include <stdio.h> 37 #include <stdlib.h> 38 #include <string.h> 39 #include <syslog.h> 40 #include <unistd.h> 41 42 #define TIMEOUT_DEFAULT 120 43 #define SLOWCGI_USER "www" 44 45 #define FCGI_CONTENT_SIZE 65535 46 #define FCGI_PADDING_SIZE 255 47 #define FCGI_RECORD_SIZE \ 48 (sizeof(struct fcgi_record_header) + FCGI_CONTENT_SIZE + FCGI_PADDING_SIZE) 49 50 #define STDOUT_DONE 1 51 #define STDERR_DONE 2 52 #define SCRIPT_DONE 4 53 54 #define FCGI_BEGIN_REQUEST 1 55 #define FCGI_ABORT_REQUEST 2 56 #define FCGI_END_REQUEST 3 57 #define FCGI_PARAMS 4 58 #define FCGI_STDIN 5 59 #define FCGI_STDOUT 6 60 #define FCGI_STDERR 7 61 #define FCGI_DATA 8 62 #define FCGI_GET_VALUES 9 63 #define FCGI_GET_VALUES_RESULT 10 64 #define FCGI_UNKNOWN_TYPE 11 65 #define FCGI_MAXTYPE (FCGI_UNKNOWN_TYPE) 66 67 #define FCGI_REQUEST_COMPLETE 0 68 #define FCGI_CANT_MPX_CONN 1 69 #define FCGI_OVERLOADED 2 70 #define FCGI_UNKNOWN_ROLE 3 71 72 #define FD_RESERVE 5 73 #define FD_NEEDED 6 74 int cgi_inflight = 0; 75 76 struct listener { 77 struct event ev, pause; 78 }; 79 80 struct env_val { 81 SLIST_ENTRY(env_val) entry; 82 char *val; 83 }; 84 SLIST_HEAD(env_head, env_val); 85 86 struct fcgi_record_header { 87 uint8_t version; 88 uint8_t type; 89 uint16_t id; 90 uint16_t content_len; 91 uint8_t padding_len; 92 uint8_t reserved; 93 }__packed; 94 95 struct fcgi_response { 96 TAILQ_ENTRY(fcgi_response) entry; 97 uint8_t data[FCGI_RECORD_SIZE]; 98 size_t data_pos; 99 size_t data_len; 100 }; 101 TAILQ_HEAD(fcgi_response_head, fcgi_response); 102 103 struct fcgi_stdin { 104 TAILQ_ENTRY(fcgi_stdin) entry; 105 uint8_t data[FCGI_RECORD_SIZE]; 106 size_t data_pos; 107 size_t data_len; 108 }; 109 TAILQ_HEAD(fcgi_stdin_head, fcgi_stdin); 110 111 struct request { 112 struct event ev; 113 struct event resp_ev; 114 struct event tmo; 115 int fd; 116 uint8_t buf[FCGI_RECORD_SIZE]; 117 size_t buf_pos; 118 size_t buf_len; 119 struct fcgi_response_head response_head; 120 struct fcgi_stdin_head stdin_head; 121 uint16_t id; 122 char script_name[PATH_MAX]; 123 struct env_head env; 124 int env_count; 125 pid_t script_pid; 126 int script_status; 127 struct event script_ev; 128 struct event script_err_ev; 129 struct event script_stdin_ev; 130 int stdin_fd_closed; 131 int stdout_fd_closed; 132 int stderr_fd_closed; 133 uint8_t script_flags; 134 uint8_t request_started; 135 int inflight_fds_accounted; 136 }; 137 138 struct requests { 139 SLIST_ENTRY(requests) entry; 140 struct request *request; 141 }; 142 SLIST_HEAD(requests_head, requests); 143 144 struct slowcgi_proc { 145 struct requests_head requests; 146 struct event ev_sigchld; 147 struct event ev_sigpipe; 148 }; 149 150 struct fcgi_begin_request_body { 151 uint16_t role; 152 uint8_t flags; 153 uint8_t reserved[5]; 154 }__packed; 155 156 struct fcgi_end_request_body { 157 uint32_t app_status; 158 uint8_t protocol_status; 159 uint8_t reserved[3]; 160 }__packed; 161 162 __dead void usage(void); 163 int slowcgi_listen(char *, struct passwd *); 164 void slowcgi_paused(int, short, void *); 165 int accept_reserve(int, struct sockaddr *, socklen_t *, int, 166 volatile int *); 167 void slowcgi_accept(int, short, void *); 168 void slowcgi_request(int, short, void *); 169 void slowcgi_response(int, short, void *); 170 void slowcgi_add_response(struct request *, struct fcgi_response *); 171 void slowcgi_timeout(int, short, void *); 172 void slowcgi_sig_handler(int, short, void *); 173 size_t parse_record(uint8_t * , size_t, struct request *); 174 void parse_begin_request(uint8_t *, uint16_t, struct request *, 175 uint16_t); 176 void parse_params(uint8_t *, uint16_t, struct request *, uint16_t); 177 void parse_stdin(uint8_t *, uint16_t, struct request *, uint16_t); 178 void exec_cgi(struct request *); 179 void script_in(int, struct event *, struct request *, uint8_t); 180 void script_std_in(int, short, void *); 181 void script_err_in(int, short, void *); 182 void script_out(int, short, void *); 183 void create_end_record(struct request *); 184 void dump_fcgi_record(const char *, 185 struct fcgi_record_header *); 186 void dump_fcgi_record_header(const char *, 187 struct fcgi_record_header *); 188 void dump_fcgi_begin_request_body(const char *, 189 struct fcgi_begin_request_body *); 190 void dump_fcgi_end_request_body(const char *, 191 struct fcgi_end_request_body *); 192 void cleanup_request(struct request *); 193 194 struct loggers { 195 __dead void (*err)(int, const char *, ...); 196 __dead void (*errx)(int, const char *, ...); 197 void (*warn)(const char *, ...); 198 void (*warnx)(const char *, ...); 199 void (*info)(const char *, ...); 200 void (*debug)(const char *, ...); 201 }; 202 203 const struct loggers conslogger = { 204 err, 205 errx, 206 warn, 207 warnx, 208 warnx, /* info */ 209 warnx /* debug */ 210 }; 211 212 __dead void syslog_err(int, const char *, ...); 213 __dead void syslog_errx(int, const char *, ...); 214 void syslog_warn(const char *, ...); 215 void syslog_warnx(const char *, ...); 216 void syslog_info(const char *, ...); 217 void syslog_debug(const char *, ...); 218 void syslog_vstrerror(int, int, const char *, va_list); 219 220 const struct loggers syslogger = { 221 syslog_err, 222 syslog_errx, 223 syslog_warn, 224 syslog_warnx, 225 syslog_info, 226 syslog_debug 227 }; 228 229 const struct loggers *logger = &conslogger; 230 231 #define lerr(_e, _f...) logger->err((_e), _f) 232 #define lerrx(_e, _f...) logger->errx((_e), _f) 233 #define lwarn(_f...) logger->warn(_f) 234 #define lwarnx(_f...) logger->warnx(_f) 235 #define linfo(_f...) logger->info(_f) 236 #define ldebug(_f...) logger->debug(_f) 237 238 __dead void 239 usage(void) 240 { 241 extern char *__progname; 242 fprintf(stderr, "usage: %s [-d] [-p path] [-s socket] [-u user]\n", 243 __progname); 244 exit(1); 245 } 246 247 struct timeval timeout = { TIMEOUT_DEFAULT, 0 }; 248 struct slowcgi_proc slowcgi_proc; 249 int debug = 0; 250 int on = 1; 251 char *fcgi_socket = "/var/www/run/slowcgi.sock"; 252 253 int 254 main(int argc, char *argv[]) 255 { 256 extern char *__progname; 257 struct listener *l = NULL; 258 struct passwd *pw; 259 struct stat sb; 260 int c, fd; 261 const char *chrootpath = NULL; 262 const char *slowcgi_user = SLOWCGI_USER; 263 264 /* 265 * Ensure we have fds 0-2 open so that we have no fd overlaps 266 * in exec_cgi() later. Just exit on error, we don't have enough 267 * fds open to output an error message anywhere. 268 */ 269 for (c=0; c < 3; c++) { 270 if (fstat(c, &sb) == -1) { 271 if ((fd = open("/dev/null", O_RDWR)) != -1) { 272 if (dup2(fd, c) == -1) 273 exit(1); 274 if (fd > c) 275 close(fd); 276 } else 277 exit(1); 278 } 279 } 280 281 while ((c = getopt(argc, argv, "dp:s:u:")) != -1) { 282 switch (c) { 283 case 'd': 284 debug = 1; 285 break; 286 case 'p': 287 chrootpath = optarg; 288 break; 289 case 's': 290 fcgi_socket = optarg; 291 break; 292 case 'u': 293 slowcgi_user = optarg; 294 break; 295 default: 296 usage(); 297 /* NOTREACHED */ 298 } 299 } 300 301 if (geteuid() != 0) 302 errx(1, "need root privileges"); 303 304 if (!debug && daemon(1, 0) == -1) 305 err(1, "daemon"); 306 307 if (!debug) { 308 openlog(__progname, LOG_PID|LOG_NDELAY, LOG_DAEMON); 309 logger = &syslogger; 310 } 311 312 pw = getpwnam(SLOWCGI_USER); 313 if (pw == NULL) 314 lerrx(1, "no %s user", SLOWCGI_USER); 315 316 fd = slowcgi_listen(fcgi_socket, pw); 317 318 lwarnx("slowcgi_user: %s", slowcgi_user); 319 pw = getpwnam(slowcgi_user); 320 if (pw == NULL) 321 lerrx(1, "no %s user", slowcgi_user); 322 323 if (chrootpath == NULL) 324 chrootpath = pw->pw_dir; 325 326 if (chroot(chrootpath) == -1) 327 lerr(1, "chroot(%s)", chrootpath); 328 329 ldebug("chroot: %s", chrootpath); 330 331 if (chdir("/") == -1) 332 lerr(1, "chdir(/)"); 333 334 if (setgroups(1, &pw->pw_gid) || 335 setresgid(pw->pw_gid, pw->pw_gid, pw->pw_gid) || 336 setresuid(pw->pw_uid, pw->pw_uid, pw->pw_uid)) 337 lerr(1, "unable to revoke privs"); 338 339 if (pledge("stdio rpath unix proc exec", NULL) == -1) 340 lerr(1, "pledge"); 341 342 SLIST_INIT(&slowcgi_proc.requests); 343 event_init(); 344 345 l = calloc(1, sizeof(*l)); 346 if (l == NULL) 347 lerr(1, "listener ev alloc"); 348 349 event_set(&l->ev, fd, EV_READ | EV_PERSIST, slowcgi_accept, l); 350 event_add(&l->ev, NULL); 351 evtimer_set(&l->pause, slowcgi_paused, l); 352 353 signal_set(&slowcgi_proc.ev_sigchld, SIGCHLD, slowcgi_sig_handler, 354 &slowcgi_proc); 355 signal_set(&slowcgi_proc.ev_sigpipe, SIGPIPE, slowcgi_sig_handler, 356 &slowcgi_proc); 357 358 signal_add(&slowcgi_proc.ev_sigchld, NULL); 359 signal_add(&slowcgi_proc.ev_sigpipe, NULL); 360 361 event_dispatch(); 362 return (0); 363 } 364 365 int 366 slowcgi_listen(char *path, struct passwd *pw) 367 { 368 struct sockaddr_un sun; 369 mode_t old_umask; 370 int fd; 371 372 if ((fd = socket(AF_UNIX, SOCK_STREAM | SOCK_NONBLOCK | SOCK_CLOEXEC, 373 0)) == -1) 374 lerr(1, "slowcgi_listen: socket"); 375 376 bzero(&sun, sizeof(sun)); 377 sun.sun_family = AF_UNIX; 378 if (strlcpy(sun.sun_path, path, sizeof(sun.sun_path)) >= 379 sizeof(sun.sun_path)) 380 lerrx(1, "socket path too long"); 381 382 if (unlink(path) == -1) 383 if (errno != ENOENT) 384 lerr(1, "slowcgi_listen: unlink %s", path); 385 386 old_umask = umask(S_IXUSR|S_IXGRP|S_IWOTH|S_IROTH| 387 S_IXOTH); 388 389 if (bind(fd, (struct sockaddr *)&sun, sizeof(sun)) == -1) 390 lerr(1,"slowcgi_listen: bind: %s", path); 391 392 umask(old_umask); 393 394 if (chown(path, pw->pw_uid, pw->pw_gid) == -1) 395 lerr(1, "slowcgi_listen: chown: %s", path); 396 397 if (listen(fd, 5) == -1) 398 lerr(1, "listen"); 399 400 ldebug("socket: %s", path); 401 return fd; 402 } 403 404 void 405 slowcgi_paused(int fd, short events, void *arg) 406 { 407 struct listener *l = arg; 408 event_add(&l->ev, NULL); 409 } 410 411 int 412 accept_reserve(int sockfd, struct sockaddr *addr, socklen_t *addrlen, 413 int reserve, volatile int *counter) 414 { 415 int ret; 416 if (getdtablecount() + reserve + 417 (*counter * FD_NEEDED) >= getdtablesize()) { 418 ldebug("inflight fds exceeded"); 419 errno = EMFILE; 420 return -1; 421 } 422 423 if ((ret = accept4(sockfd, addr, addrlen, SOCK_NONBLOCK | SOCK_CLOEXEC)) 424 > -1) { 425 (*counter)++; 426 ldebug("inflight incremented, now %d", *counter); 427 } 428 return ret; 429 } 430 431 void 432 slowcgi_accept(int fd, short events, void *arg) 433 { 434 struct listener *l; 435 struct sockaddr_storage ss; 436 struct timeval backoff; 437 struct request *c; 438 struct requests *requests; 439 socklen_t len; 440 int s; 441 442 l = arg; 443 backoff.tv_sec = 1; 444 backoff.tv_usec = 0; 445 c = NULL; 446 447 len = sizeof(ss); 448 if ((s = accept_reserve(fd, (struct sockaddr *)&ss, 449 &len, FD_RESERVE, &cgi_inflight)) == -1) { 450 switch (errno) { 451 case EINTR: 452 case EWOULDBLOCK: 453 case ECONNABORTED: 454 return; 455 case EMFILE: 456 case ENFILE: 457 event_del(&l->ev); 458 evtimer_add(&l->pause, &backoff); 459 return; 460 default: 461 lerr(1, "accept"); 462 } 463 } 464 465 c = calloc(1, sizeof(*c)); 466 if (c == NULL) { 467 lwarn("cannot calloc request"); 468 close(s); 469 cgi_inflight--; 470 return; 471 } 472 requests = calloc(1, sizeof(*requests)); 473 if (requests == NULL) { 474 lwarn("cannot calloc requests"); 475 close(s); 476 cgi_inflight--; 477 free(c); 478 return; 479 } 480 c->fd = s; 481 c->buf_pos = 0; 482 c->buf_len = 0; 483 c->request_started = 0; 484 c->stdin_fd_closed = c->stdout_fd_closed = c->stderr_fd_closed = 0; 485 c->inflight_fds_accounted = 0; 486 TAILQ_INIT(&c->response_head); 487 TAILQ_INIT(&c->stdin_head); 488 489 event_set(&c->ev, s, EV_READ | EV_PERSIST, slowcgi_request, c); 490 event_add(&c->ev, NULL); 491 event_set(&c->resp_ev, s, EV_WRITE | EV_PERSIST, slowcgi_response, c); 492 event_set(&c->tmo, s, 0, slowcgi_timeout, c); 493 event_add(&c->tmo, &timeout); 494 requests->request = c; 495 SLIST_INSERT_HEAD(&slowcgi_proc.requests, requests, entry); 496 } 497 498 void 499 slowcgi_timeout(int fd, short events, void *arg) 500 { 501 cleanup_request((struct request*) arg); 502 } 503 504 void 505 slowcgi_sig_handler(int sig, short event, void *arg) 506 { 507 struct request *c; 508 struct requests *ncs; 509 struct slowcgi_proc *p; 510 pid_t pid; 511 int status; 512 513 p = arg; 514 515 switch (sig) { 516 case SIGCHLD: 517 while ((pid = waitpid(WAIT_ANY, &status, WNOHANG)) > 0) { 518 c = NULL; 519 SLIST_FOREACH(ncs, &p->requests, entry) 520 if (ncs->request->script_pid == pid) { 521 c = ncs->request; 522 break; 523 } 524 if (c == NULL) { 525 lwarnx("caught exit of unknown child %i", pid); 526 continue; 527 } 528 529 if (WIFSIGNALED(status)) 530 c->script_status = WTERMSIG(status); 531 else 532 c->script_status = WEXITSTATUS(status); 533 534 if (c->script_flags == (STDOUT_DONE | STDERR_DONE)) 535 create_end_record(c); 536 c->script_flags |= SCRIPT_DONE; 537 538 ldebug("wait: %s", c->script_name); 539 } 540 if (pid == -1 && errno != ECHILD) 541 lwarn("waitpid"); 542 break; 543 case SIGPIPE: 544 /* ignore */ 545 break; 546 default: 547 lerr(1, "unexpected signal: %d", sig); 548 break; 549 } 550 } 551 552 void 553 slowcgi_add_response(struct request *c, struct fcgi_response *resp) 554 { 555 TAILQ_INSERT_TAIL(&c->response_head, resp, entry); 556 event_add(&c->resp_ev, NULL); 557 } 558 559 void 560 slowcgi_response(int fd, short events, void *arg) 561 { 562 struct request *c; 563 struct fcgi_record_header *header; 564 struct fcgi_response *resp; 565 ssize_t n; 566 567 c = arg; 568 569 while ((resp = TAILQ_FIRST(&c->response_head))) { 570 header = (struct fcgi_record_header*) resp->data; 571 if (debug) 572 dump_fcgi_record("resp ", header); 573 574 n = write(fd, resp->data + resp->data_pos, resp->data_len); 575 if (n == -1) { 576 if (errno == EAGAIN || errno == EINTR) 577 return; 578 cleanup_request(c); 579 return; 580 } 581 resp->data_pos += n; 582 resp->data_len -= n; 583 if (resp->data_len == 0) { 584 TAILQ_REMOVE(&c->response_head, resp, entry); 585 free(resp); 586 } 587 } 588 589 if (TAILQ_EMPTY(&c->response_head)) { 590 if (c->script_flags == (STDOUT_DONE | STDERR_DONE | 591 SCRIPT_DONE)) 592 cleanup_request(c); 593 else 594 event_del(&c->resp_ev); 595 } 596 } 597 598 void 599 slowcgi_request(int fd, short events, void *arg) 600 { 601 struct request *c; 602 ssize_t n; 603 size_t parsed; 604 605 c = arg; 606 607 n = read(fd, c->buf + c->buf_pos + c->buf_len, 608 FCGI_RECORD_SIZE - c->buf_pos-c->buf_len); 609 610 switch (n) { 611 case -1: 612 switch (errno) { 613 case EINTR: 614 case EAGAIN: 615 return; 616 default: 617 goto fail; 618 } 619 break; 620 621 case 0: 622 ldebug("closed connection"); 623 goto fail; 624 default: 625 break; 626 } 627 628 c->buf_len += n; 629 630 /* 631 * Parse the records as they are received. Per the FastCGI 632 * specification, the server need only receive the FastCGI 633 * parameter records in full; it is free to begin execution 634 * at that point, which is what happens here. 635 */ 636 do { 637 parsed = parse_record(c->buf + c->buf_pos, c->buf_len, c); 638 c->buf_pos += parsed; 639 c->buf_len -= parsed; 640 } while (parsed > 0 && c->buf_len > 0); 641 642 /* Make space for further reads */ 643 if (c->buf_len > 0) { 644 bcopy(c->buf + c->buf_pos, c->buf, c->buf_len); 645 c->buf_pos = 0; 646 } 647 return; 648 fail: 649 cleanup_request(c); 650 } 651 652 void 653 parse_begin_request(uint8_t *buf, uint16_t n, struct request *c, uint16_t id) 654 { 655 /* XXX -- FCGI_CANT_MPX_CONN */ 656 if (c->request_started) { 657 lwarnx("unexpected FCGI_BEGIN_REQUEST, ignoring"); 658 return; 659 } 660 661 if (n != sizeof(struct fcgi_begin_request_body)) { 662 lwarnx("wrong size %d != %d", n, 663 sizeof(struct fcgi_begin_request_body)); 664 return; 665 } 666 667 c->request_started = 1; 668 669 c->id = id; 670 SLIST_INIT(&c->env); 671 c->env_count = 0; 672 } 673 void 674 parse_params(uint8_t *buf, uint16_t n, struct request *c, uint16_t id) 675 { 676 struct env_val *env_entry; 677 uint32_t name_len, val_len; 678 679 if (!c->request_started) { 680 lwarnx("FCGI_PARAMS without FCGI_BEGIN_REQUEST, ignoring"); 681 return; 682 } 683 684 if (c->id != id) { 685 lwarnx("unexpected id, ignoring"); 686 return; 687 } 688 689 /* 690 * If this is the last FastCGI parameter record, 691 * begin execution of the CGI script. 692 */ 693 if (n == 0) { 694 exec_cgi(c); 695 return; 696 } 697 698 while (n > 0) { 699 if (buf[0] >> 7 == 0) { 700 name_len = buf[0]; 701 n--; 702 buf++; 703 } else { 704 if (n > 3) { 705 name_len = ((buf[0] & 0x7f) << 24) + 706 (buf[1] << 16) + (buf[2] << 8) + buf[3]; 707 n -= 4; 708 buf += 4; 709 } else 710 return; 711 } 712 713 if (n > 0) { 714 if (buf[0] >> 7 == 0) { 715 val_len = buf[0]; 716 n--; 717 buf++; 718 } else { 719 if (n > 3) { 720 val_len = ((buf[0] & 0x7f) << 24) + 721 (buf[1] << 16) + (buf[2] << 8) + 722 buf[3]; 723 n -= 4; 724 buf += 4; 725 } else 726 return; 727 } 728 } else 729 return; 730 731 if (n < name_len + val_len) 732 return; 733 734 if ((env_entry = malloc(sizeof(struct env_val))) == NULL) { 735 lwarnx("cannot allocate env_entry"); 736 return; 737 } 738 739 if ((env_entry->val = calloc(sizeof(char), name_len + val_len + 740 2)) == NULL) { 741 lwarnx("cannot allocate env_entry->val"); 742 free(env_entry); 743 return; 744 } 745 746 bcopy(buf, env_entry->val, name_len); 747 buf += name_len; 748 n -= name_len; 749 750 env_entry->val[name_len] = '\0'; 751 if (val_len < PATH_MAX && strcmp(env_entry->val, 752 "SCRIPT_NAME") == 0 && c->script_name[0] == '\0') { 753 bcopy(buf, c->script_name, val_len); 754 c->script_name[val_len] = '\0'; 755 } else if (val_len < PATH_MAX && strcmp(env_entry->val, 756 "SCRIPT_FILENAME") == 0) { 757 bcopy(buf, c->script_name, val_len); 758 c->script_name[val_len] = '\0'; 759 } 760 env_entry->val[name_len] = '='; 761 762 bcopy(buf, (env_entry->val) + name_len + 1, val_len); 763 buf += val_len; 764 n -= val_len; 765 766 SLIST_INSERT_HEAD(&c->env, env_entry, entry); 767 ldebug("env[%d], %s", c->env_count, env_entry->val); 768 c->env_count++; 769 } 770 } 771 772 void 773 parse_stdin(uint8_t *buf, uint16_t n, struct request *c, uint16_t id) 774 { 775 struct fcgi_stdin *node; 776 777 if (c->id != id) { 778 lwarnx("unexpected id, ignoring"); 779 return; 780 } 781 782 if ((node = calloc(1, sizeof(struct fcgi_stdin))) == NULL) { 783 lwarnx("cannot calloc stdin node"); 784 return; 785 } 786 787 bcopy(buf, node->data, n); 788 node->data_pos = 0; 789 node->data_len = n; 790 791 TAILQ_INSERT_TAIL(&c->stdin_head, node, entry); 792 793 if (event_initialized(&c->script_stdin_ev)) 794 event_add(&c->script_stdin_ev, NULL); 795 } 796 797 size_t 798 parse_record(uint8_t *buf, size_t n, struct request *c) 799 { 800 struct fcgi_record_header *h; 801 802 if (n < sizeof(struct fcgi_record_header)) 803 return (0); 804 805 h = (struct fcgi_record_header*) buf; 806 807 if (debug) 808 dump_fcgi_record("", h); 809 810 if (n < sizeof(struct fcgi_record_header) + ntohs(h->content_len) 811 + h->padding_len) 812 return (0); 813 814 if (h->version != 1) 815 lerrx(1, "wrong version"); 816 817 switch (h->type) { 818 case FCGI_BEGIN_REQUEST: 819 parse_begin_request(buf + sizeof(struct fcgi_record_header), 820 ntohs(h->content_len), c, ntohs(h->id)); 821 break; 822 case FCGI_PARAMS: 823 parse_params(buf + sizeof(struct fcgi_record_header), 824 ntohs(h->content_len), c, ntohs(h->id)); 825 break; 826 case FCGI_STDIN: 827 parse_stdin(buf + sizeof(struct fcgi_record_header), 828 ntohs(h->content_len), c, ntohs(h->id)); 829 break; 830 default: 831 lwarnx("unimplemented type %d", h->type); 832 break; 833 } 834 835 return (sizeof(struct fcgi_record_header) + ntohs(h->content_len) 836 + h->padding_len); 837 } 838 839 /* 840 * Fork a new CGI process to handle the request, translating 841 * between FastCGI parameter records and CGI's environment variables, 842 * as well as between the CGI process' stdin/stdout and the 843 * corresponding FastCGI records. 844 */ 845 void 846 exec_cgi(struct request *c) 847 { 848 struct env_val *env_entry; 849 int s_in[2], s_out[2], s_err[2], i; 850 pid_t pid; 851 char *argv[2]; 852 char **env; 853 char *path; 854 855 i = 0; 856 857 if (socketpair(AF_UNIX, SOCK_STREAM, PF_UNSPEC, s_in) == -1) 858 lerr(1, "socketpair"); 859 if (socketpair(AF_UNIX, SOCK_STREAM, PF_UNSPEC, s_out) == -1) 860 lerr(1, "socketpair"); 861 if (socketpair(AF_UNIX, SOCK_STREAM, PF_UNSPEC, s_err) == -1) 862 lerr(1, "socketpair"); 863 cgi_inflight--; 864 c->inflight_fds_accounted = 1; 865 ldebug("fork: %s", c->script_name); 866 867 switch (pid = fork()) { 868 case -1: 869 c->script_status = errno; 870 871 lwarn("fork"); 872 873 close(s_in[0]); 874 close(s_out[0]); 875 close(s_err[0]); 876 877 close(s_in[1]); 878 close(s_out[1]); 879 close(s_err[1]); 880 881 c->stdin_fd_closed = c->stdout_fd_closed = 882 c->stderr_fd_closed = 1; 883 c->script_flags = (STDOUT_DONE | STDERR_DONE | SCRIPT_DONE); 884 885 create_end_record(c); 886 return; 887 case 0: 888 /* Child process */ 889 if (pledge("stdio rpath exec", NULL) == -1) 890 lerr(1, "pledge"); 891 close(s_in[0]); 892 close(s_out[0]); 893 close(s_err[0]); 894 895 if (dup2(s_in[1], STDIN_FILENO) == -1) 896 _exit(1); 897 if (dup2(s_out[1], STDOUT_FILENO) == -1) 898 _exit(1); 899 if (dup2(s_err[1], STDERR_FILENO) == -1) 900 _exit(1); 901 902 close(s_in[1]); 903 close(s_out[1]); 904 close(s_err[1]); 905 906 path = strrchr(c->script_name, '/'); 907 if (path != NULL) { 908 if (path != c->script_name) { 909 *path = '\0'; 910 if (chdir(c->script_name) == -1) 911 lwarn("cannot chdir to %s", 912 c->script_name); 913 *path = '/'; 914 } else 915 if (chdir("/") == -1) 916 lwarn("cannot chdir to /"); 917 } 918 919 argv[0] = c->script_name; 920 argv[1] = NULL; 921 if ((env = calloc(c->env_count + 1, sizeof(char*))) == NULL) 922 _exit(1); 923 SLIST_FOREACH(env_entry, &c->env, entry) 924 env[i++] = env_entry->val; 925 env[i++] = NULL; 926 execve(c->script_name, argv, env); 927 lwarn("execve %s", c->script_name); 928 _exit(1); 929 930 } 931 932 /* Parent process*/ 933 close(s_in[1]); 934 close(s_out[1]); 935 close(s_err[1]); 936 937 fcntl(s_in[0], F_SETFD, FD_CLOEXEC); 938 fcntl(s_out[0], F_SETFD, FD_CLOEXEC); 939 fcntl(s_err[0], F_SETFD, FD_CLOEXEC); 940 941 if (ioctl(s_in[0], FIONBIO, &on) == -1) 942 lerr(1, "script ioctl(FIONBIO)"); 943 if (ioctl(s_out[0], FIONBIO, &on) == -1) 944 lerr(1, "script ioctl(FIONBIO)"); 945 if (ioctl(s_err[0], FIONBIO, &on) == -1) 946 lerr(1, "script ioctl(FIONBIO)"); 947 948 c->script_pid = pid; 949 event_set(&c->script_stdin_ev, s_in[0], EV_WRITE | EV_PERSIST, 950 script_out, c); 951 event_add(&c->script_stdin_ev, NULL); 952 event_set(&c->script_ev, s_out[0], EV_READ | EV_PERSIST, 953 script_std_in, c); 954 event_add(&c->script_ev, NULL); 955 event_set(&c->script_err_ev, s_err[0], EV_READ | EV_PERSIST, 956 script_err_in, c); 957 event_add(&c->script_err_ev, NULL); 958 } 959 960 void 961 create_end_record(struct request *c) 962 { 963 struct fcgi_response *resp; 964 struct fcgi_record_header *header; 965 struct fcgi_end_request_body *end_request; 966 967 if ((resp = malloc(sizeof(struct fcgi_response))) == NULL) { 968 lwarnx("cannot malloc fcgi_response"); 969 return; 970 } 971 header = (struct fcgi_record_header*) resp->data; 972 header->version = 1; 973 header->type = FCGI_END_REQUEST; 974 header->id = htons(c->id); 975 header->content_len = htons(sizeof(struct 976 fcgi_end_request_body)); 977 header->padding_len = 0; 978 header->reserved = 0; 979 end_request = (struct fcgi_end_request_body *) (resp->data + 980 sizeof(struct fcgi_record_header)); 981 end_request->app_status = htonl(c->script_status); 982 end_request->protocol_status = FCGI_REQUEST_COMPLETE; 983 end_request->reserved[0] = 0; 984 end_request->reserved[1] = 0; 985 end_request->reserved[2] = 0; 986 resp->data_pos = 0; 987 resp->data_len = sizeof(struct fcgi_end_request_body) + 988 sizeof(struct fcgi_record_header); 989 slowcgi_add_response(c, resp); 990 } 991 992 void 993 script_in(int fd, struct event *ev, struct request *c, uint8_t type) 994 { 995 struct fcgi_response *resp; 996 struct fcgi_record_header *header; 997 ssize_t n; 998 999 if ((resp = malloc(sizeof(struct fcgi_response))) == NULL) { 1000 lwarnx("cannot malloc fcgi_response"); 1001 return; 1002 } 1003 header = (struct fcgi_record_header*) resp->data; 1004 header->version = 1; 1005 header->type = type; 1006 header->id = htons(c->id); 1007 header->padding_len = 0; 1008 header->reserved = 0; 1009 1010 n = read(fd, resp->data + sizeof(struct fcgi_record_header), 1011 FCGI_CONTENT_SIZE); 1012 1013 if (n == -1) { 1014 switch (errno) { 1015 case EINTR: 1016 case EAGAIN: 1017 free(resp); 1018 return; 1019 default: 1020 n = 0; /* fake empty FCGI_STD{OUT,ERR} response */ 1021 } 1022 } 1023 header->content_len = htons(n); 1024 resp->data_pos = 0; 1025 resp->data_len = n + sizeof(struct fcgi_record_header); 1026 slowcgi_add_response(c, resp); 1027 1028 if (n == 0) { 1029 if (type == FCGI_STDOUT) 1030 c->script_flags |= STDOUT_DONE; 1031 else 1032 c->script_flags |= STDERR_DONE; 1033 1034 if (c->script_flags == (STDOUT_DONE | STDERR_DONE | 1035 SCRIPT_DONE)) { 1036 create_end_record(c); 1037 } 1038 event_del(ev); 1039 close(fd); 1040 if (type == FCGI_STDOUT) 1041 c->stdout_fd_closed = 1; 1042 else 1043 c->stderr_fd_closed = 1; 1044 } 1045 } 1046 1047 void 1048 script_std_in(int fd, short events, void *arg) 1049 { 1050 struct request *c = arg; 1051 script_in(fd, &c->script_ev, c, FCGI_STDOUT); 1052 } 1053 1054 void 1055 script_err_in(int fd, short events, void *arg) 1056 { 1057 struct request *c = arg; 1058 script_in(fd, &c->script_err_ev, c, FCGI_STDERR); 1059 } 1060 1061 void 1062 script_out(int fd, short events, void *arg) 1063 { 1064 struct request *c; 1065 struct fcgi_stdin *node; 1066 ssize_t n; 1067 1068 c = arg; 1069 1070 while ((node = TAILQ_FIRST(&c->stdin_head))) { 1071 if (node->data_len == 0) { /* end of stdin marker */ 1072 close(fd); 1073 c->stdin_fd_closed = 1; 1074 break; 1075 } 1076 n = write(fd, node->data + node->data_pos, node->data_len); 1077 if (n == -1) { 1078 if (errno == EAGAIN || errno == EINTR) 1079 return; 1080 event_del(&c->script_stdin_ev); 1081 return; 1082 } 1083 node->data_pos += n; 1084 node->data_len -= n; 1085 if (node->data_len == 0) { 1086 TAILQ_REMOVE(&c->stdin_head, node, entry); 1087 free(node); 1088 } 1089 } 1090 event_del(&c->script_stdin_ev); 1091 } 1092 1093 void 1094 cleanup_request(struct request *c) 1095 { 1096 struct fcgi_response *resp; 1097 struct fcgi_stdin *stdin_node; 1098 struct env_val *env_entry; 1099 struct requests *ncs, *tcs; 1100 1101 evtimer_del(&c->tmo); 1102 if (event_initialized(&c->ev)) 1103 event_del(&c->ev); 1104 if (event_initialized(&c->resp_ev)) 1105 event_del(&c->resp_ev); 1106 if (event_initialized(&c->script_ev)) { 1107 if (!c->stdout_fd_closed) 1108 close(EVENT_FD(&c->script_ev)); 1109 event_del(&c->script_ev); 1110 } 1111 if (event_initialized(&c->script_err_ev)) { 1112 if (!c->stderr_fd_closed) 1113 close(EVENT_FD(&c->script_err_ev)); 1114 event_del(&c->script_err_ev); 1115 } 1116 if (event_initialized(&c->script_stdin_ev)) { 1117 if (!c->stdin_fd_closed) 1118 close(EVENT_FD(&c->script_stdin_ev)); 1119 event_del(&c->script_stdin_ev); 1120 } 1121 close(c->fd); 1122 while (!SLIST_EMPTY(&c->env)) { 1123 env_entry = SLIST_FIRST(&c->env); 1124 SLIST_REMOVE_HEAD(&c->env, entry); 1125 free(env_entry->val); 1126 free(env_entry); 1127 } 1128 1129 while ((resp = TAILQ_FIRST(&c->response_head))) { 1130 TAILQ_REMOVE(&c->response_head, resp, entry); 1131 free(resp); 1132 } 1133 while ((stdin_node = TAILQ_FIRST(&c->stdin_head))) { 1134 TAILQ_REMOVE(&c->stdin_head, stdin_node, entry); 1135 free(stdin_node); 1136 } 1137 SLIST_FOREACH_SAFE(ncs, &slowcgi_proc.requests, entry, tcs) { 1138 if (ncs->request == c) { 1139 SLIST_REMOVE(&slowcgi_proc.requests, ncs, requests, 1140 entry); 1141 free(ncs); 1142 break; 1143 } 1144 } 1145 if (! c->inflight_fds_accounted) 1146 cgi_inflight--; 1147 free(c); 1148 } 1149 1150 void 1151 dump_fcgi_record(const char *p, struct fcgi_record_header *h) 1152 { 1153 dump_fcgi_record_header(p, h); 1154 1155 if (h->type == FCGI_BEGIN_REQUEST) 1156 dump_fcgi_begin_request_body(p, 1157 (struct fcgi_begin_request_body *)(h + 1)); 1158 else if (h->type == FCGI_END_REQUEST) 1159 dump_fcgi_end_request_body(p, 1160 (struct fcgi_end_request_body *)(h + 1)); 1161 } 1162 1163 void 1164 dump_fcgi_record_header(const char* p, struct fcgi_record_header *h) 1165 { 1166 ldebug("%sversion: %d", p, h->version); 1167 ldebug("%stype: %d", p, h->type); 1168 ldebug("%srequestId: %d", p, ntohs(h->id)); 1169 ldebug("%scontentLength: %d", p, ntohs(h->content_len)); 1170 ldebug("%spaddingLength: %d", p, h->padding_len); 1171 ldebug("%sreserved: %d", p, h->reserved); 1172 } 1173 1174 void 1175 dump_fcgi_begin_request_body(const char *p, struct fcgi_begin_request_body *b) 1176 { 1177 ldebug("%srole %d", p, ntohs(b->role)); 1178 ldebug("%sflags %d", p, b->flags); 1179 } 1180 1181 void 1182 dump_fcgi_end_request_body(const char *p, struct fcgi_end_request_body *b) 1183 { 1184 ldebug("%sappStatus: %d", p, ntohl(b->app_status)); 1185 ldebug("%sprotocolStatus: %d", p, b->protocol_status); 1186 } 1187 1188 void 1189 syslog_vstrerror(int e, int priority, const char *fmt, va_list ap) 1190 { 1191 char *s; 1192 1193 if (vasprintf(&s, fmt, ap) == -1) { 1194 syslog(LOG_EMERG, "unable to alloc in syslog_vstrerror"); 1195 exit(1); 1196 } 1197 syslog(priority, "%s: %s", s, strerror(e)); 1198 free(s); 1199 } 1200 1201 __dead void 1202 syslog_err(int ecode, const char *fmt, ...) 1203 { 1204 va_list ap; 1205 1206 va_start(ap, fmt); 1207 syslog_vstrerror(errno, LOG_EMERG, fmt, ap); 1208 va_end(ap); 1209 exit(ecode); 1210 } 1211 1212 __dead void 1213 syslog_errx(int ecode, const char *fmt, ...) 1214 { 1215 va_list ap; 1216 1217 va_start(ap, fmt); 1218 vsyslog(LOG_WARNING, fmt, ap); 1219 va_end(ap); 1220 exit(ecode); 1221 } 1222 1223 void 1224 syslog_warn(const char *fmt, ...) 1225 { 1226 va_list ap; 1227 1228 va_start(ap, fmt); 1229 syslog_vstrerror(errno, LOG_WARNING, fmt, ap); 1230 va_end(ap); 1231 } 1232 1233 void 1234 syslog_warnx(const char *fmt, ...) 1235 { 1236 va_list ap; 1237 1238 va_start(ap, fmt); 1239 vsyslog(LOG_WARNING, fmt, ap); 1240 va_end(ap); 1241 } 1242 1243 void 1244 syslog_info(const char *fmt, ...) 1245 { 1246 va_list ap; 1247 1248 va_start(ap, fmt); 1249 vsyslog(LOG_INFO, fmt, ap); 1250 va_end(ap); 1251 } 1252 1253 void 1254 syslog_debug(const char *fmt, ...) 1255 { 1256 va_list ap; 1257 1258 if (!debug) 1259 return; 1260 1261 va_start(ap, fmt); 1262 vsyslog(LOG_DEBUG, fmt, ap); 1263 va_end(ap); 1264 } 1265