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