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