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