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