| @@ -1,14 +1,14 @@ | | | @@ -1,14 +1,14 @@ |
1 | /* $NetBSD: cgi-bozo.c,v 1.42 2018/11/22 08:54:08 mrg Exp $ */ | | 1 | /* $NetBSD: cgi-bozo.c,v 1.43 2018/11/22 18:42:06 mrg Exp $ */ |
2 | | | 2 | |
3 | /* $eterna: cgi-bozo.c,v 1.40 2011/11/18 09:21:15 mrg Exp $ */ | | 3 | /* $eterna: cgi-bozo.c,v 1.40 2011/11/18 09:21:15 mrg Exp $ */ |
4 | | | 4 | |
5 | /* | | 5 | /* |
6 | * Copyright (c) 1997-2018 Matthew R. Green | | 6 | * Copyright (c) 1997-2018 Matthew R. Green |
7 | * All rights reserved. | | 7 | * All rights reserved. |
8 | * | | 8 | * |
9 | * Redistribution and use in source and binary forms, with or without | | 9 | * Redistribution and use in source and binary forms, with or without |
10 | * modification, are permitted provided that the following conditions | | 10 | * modification, are permitted provided that the following conditions |
11 | * are met: | | 11 | * are met: |
12 | * 1. Redistributions of source code must retain the above copyright | | 12 | * 1. Redistributions of source code must retain the above copyright |
13 | * notice, this list of conditions and the following disclaimer. | | 13 | * notice, this list of conditions and the following disclaimer. |
14 | * 2. Redistributions in binary form must reproduce the above copyright | | 14 | * 2. Redistributions in binary form must reproduce the above copyright |
| @@ -35,26 +35,27 @@ | | | @@ -35,26 +35,27 @@ |
35 | #ifndef NO_CGIBIN_SUPPORT | | 35 | #ifndef NO_CGIBIN_SUPPORT |
36 | | | 36 | |
37 | #include <sys/param.h> | | 37 | #include <sys/param.h> |
38 | #include <sys/socket.h> | | 38 | #include <sys/socket.h> |
39 | | | 39 | |
40 | #include <ctype.h> | | 40 | #include <ctype.h> |
41 | #include <errno.h> | | 41 | #include <errno.h> |
42 | #include <paths.h> | | 42 | #include <paths.h> |
43 | #include <signal.h> | | 43 | #include <signal.h> |
44 | #include <stdlib.h> | | 44 | #include <stdlib.h> |
45 | #include <string.h> | | 45 | #include <string.h> |
46 | #include <syslog.h> | | 46 | #include <syslog.h> |
47 | #include <unistd.h> | | 47 | #include <unistd.h> |
| | | 48 | #include <assert.h> |
48 | | | 49 | |
49 | #include <netinet/in.h> | | 50 | #include <netinet/in.h> |
50 | | | 51 | |
51 | #include "bozohttpd.h" | | 52 | #include "bozohttpd.h" |
52 | | | 53 | |
53 | #define CGIBIN_PREFIX "cgi-bin/" | | 54 | #define CGIBIN_PREFIX "cgi-bin/" |
54 | #define CGIBIN_PREFIX_LEN (sizeof(CGIBIN_PREFIX)-1) | | 55 | #define CGIBIN_PREFIX_LEN (sizeof(CGIBIN_PREFIX)-1) |
55 | | | 56 | |
56 | #ifndef USE_ARG | | 57 | #ifndef USE_ARG |
57 | #define USE_ARG(x) /*LINTED*/(void)&(x) | | 58 | #define USE_ARG(x) /*LINTED*/(void)&(x) |
58 | #endif | | 59 | #endif |
59 | | | 60 | |
60 | /* | | 61 | /* |
| @@ -370,26 +371,27 @@ bozo_setenv(bozohttpd_t *httpd, const ch | | | @@ -370,26 +371,27 @@ bozo_setenv(bozohttpd_t *httpd, const ch |
370 | * process the cgi, otherwise just return. Returns 0 if it did not handle | | 371 | * process the cgi, otherwise just return. Returns 0 if it did not handle |
371 | * the request. | | 372 | * the request. |
372 | */ | | 373 | */ |
373 | int | | 374 | int |
374 | bozo_process_cgi(bozo_httpreq_t *request) | | 375 | bozo_process_cgi(bozo_httpreq_t *request) |
375 | { | | 376 | { |
376 | bozohttpd_t *httpd = request->hr_httpd; | | 377 | bozohttpd_t *httpd = request->hr_httpd; |
377 | char buf[BOZO_WRSZ]; | | 378 | char buf[BOZO_WRSZ]; |
378 | char date[40]; | | 379 | char date[40]; |
379 | bozoheaders_t *headp; | | 380 | bozoheaders_t *headp; |
380 | const char *type, *clen, *info, *cgihandler; | | 381 | const char *type, *clen, *info, *cgihandler; |
381 | char *query, *s, *t, *path, *env, *command, *file, *url; | | 382 | char *query, *s, *t, *path, *env, *command, *file, *url; |
382 | char **envp, **curenvp, **argv, **search_string_argv = NULL; | | 383 | char **envp, **curenvp, **argv, **search_string_argv = NULL; |
| | | 384 | char **lastenvp; |
383 | char *uri; | | 385 | char *uri; |
384 | size_t i, len, search_string_argc = 0; | | 386 | size_t i, len, search_string_argc = 0; |
385 | ssize_t rbytes; | | 387 | ssize_t rbytes; |
386 | pid_t pid; | | 388 | pid_t pid; |
387 | int envpsize, ix, nph; | | 389 | int envpsize, ix, nph; |
388 | int sv[2]; | | 390 | int sv[2]; |
389 | | | 391 | |
390 | if (!httpd->cgibin && !httpd->process_cgi) | | 392 | if (!httpd->cgibin && !httpd->process_cgi) |
391 | return 0; | | 393 | return 0; |
392 | | | 394 | |
393 | #ifndef NO_USER_SUPPORT | | 395 | #ifndef NO_USER_SUPPORT |
394 | if (request->hr_user && !httpd->enable_cgi_users) | | 396 | if (request->hr_user && !httpd->enable_cgi_users) |
395 | return 0; | | 397 | return 0; |
| @@ -496,26 +498,27 @@ bozo_process_cgi(bozo_httpreq_t *request | | | @@ -496,26 +498,27 @@ bozo_process_cgi(bozo_httpreq_t *request |
496 | bozo_auth_cgi_count(request) + | | 498 | bozo_auth_cgi_count(request) + |
497 | (request->hr_serverport && *request->hr_serverport ? 1 : 0); | | 499 | (request->hr_serverport && *request->hr_serverport ? 1 : 0); |
498 | | | 500 | |
499 | debug((httpd, DEBUG_FAT, | | 501 | debug((httpd, DEBUG_FAT, |
500 | "%s: path `%s', cmd `%s', info `%s', " | | 502 | "%s: path `%s', cmd `%s', info `%s', " |
501 | "query `%s', nph `%d', envpsize `%d'", __func__, | | 503 | "query `%s', nph `%d', envpsize `%d'", __func__, |
502 | path, command, strornull(info), | | 504 | path, command, strornull(info), |
503 | strornull(query), nph, envpsize)); | | 505 | strornull(query), nph, envpsize)); |
504 | | | 506 | |
505 | envp = bozomalloc(httpd, sizeof(*envp) * envpsize); | | 507 | envp = bozomalloc(httpd, sizeof(*envp) * envpsize); |
506 | for (ix = 0; ix < envpsize; ix++) | | 508 | for (ix = 0; ix < envpsize; ix++) |
507 | envp[ix] = NULL; | | 509 | envp[ix] = NULL; |
508 | curenvp = envp; | | 510 | curenvp = envp; |
| | | 511 | lastenvp = envp + envpsize; |
509 | | | 512 | |
510 | SIMPLEQ_FOREACH(headp, &request->hr_headers, h_next) { | | 513 | SIMPLEQ_FOREACH(headp, &request->hr_headers, h_next) { |
511 | const char *s2; | | 514 | const char *s2; |
512 | env = bozomalloc(httpd, 6 + strlen(headp->h_header) + 1 + | | 515 | env = bozomalloc(httpd, 6 + strlen(headp->h_header) + 1 + |
513 | strlen(headp->h_value)); | | 516 | strlen(headp->h_value)); |
514 | | | 517 | |
515 | t = env; | | 518 | t = env; |
516 | strcpy(t, "HTTP_"); | | 519 | strcpy(t, "HTTP_"); |
517 | t += strlen(t); | | 520 | t += strlen(t); |
518 | for (s2 = headp->h_header; *s2; t++, s2++) | | 521 | for (s2 = headp->h_header; *s2; t++, s2++) |
519 | if (islower((unsigned)*s2)) | | 522 | if (islower((unsigned)*s2)) |
520 | *t = toupper((unsigned)*s2); | | 523 | *t = toupper((unsigned)*s2); |
521 | else if (*s2 == '-') | | 524 | else if (*s2 == '-') |
| @@ -577,26 +580,27 @@ bozo_process_cgi(bozo_httpreq_t *request | | | @@ -577,26 +580,27 @@ bozo_process_cgi(bozo_httpreq_t *request |
577 | debug((httpd, DEBUG_FAT, "%s: going exec %s with args:", __func__, | | 580 | debug((httpd, DEBUG_FAT, "%s: going exec %s with args:", __func__, |
578 | path)); | | 581 | path)); |
579 | | | 582 | |
580 | for (i = 0; argv[i] != NULL; i++) { | | 583 | for (i = 0; argv[i] != NULL; i++) { |
581 | debug((httpd, DEBUG_FAT, "%s: argv[%zu] = `%s'", __func__, | | 584 | debug((httpd, DEBUG_FAT, "%s: argv[%zu] = `%s'", __func__, |
582 | i, argv[i])); | | 585 | i, argv[i])); |
583 | } | | 586 | } |
584 | | | 587 | |
585 | if (socketpair(AF_UNIX, SOCK_STREAM, PF_UNSPEC, sv) == -1) | | 588 | if (socketpair(AF_UNIX, SOCK_STREAM, PF_UNSPEC, sv) == -1) |
586 | bozoerr(httpd, 1, "child socketpair failed: %s", | | 589 | bozoerr(httpd, 1, "child socketpair failed: %s", |
587 | strerror(errno)); | | 590 | strerror(errno)); |
588 | | | 591 | |
589 | *curenvp = 0; | | 592 | *curenvp = 0; |
| | | 593 | assert(lastenvp > curenvp); |
590 | | | 594 | |
591 | /* | | 595 | /* |
592 | * We create 2 procs: one to become the CGI, one read from | | 596 | * We create 2 procs: one to become the CGI, one read from |
593 | * the CGI and output to the network, and this parent will | | 597 | * the CGI and output to the network, and this parent will |
594 | * continue reading from the network and writing to the | | 598 | * continue reading from the network and writing to the |
595 | * CGI procsss. | | 599 | * CGI procsss. |
596 | */ | | 600 | */ |
597 | switch (fork()) { | | 601 | switch (fork()) { |
598 | case -1: /* eep, failure */ | | 602 | case -1: /* eep, failure */ |
599 | bozoerr(httpd, 1, "child fork failed: %s", strerror(errno)); | | 603 | bozoerr(httpd, 1, "child fork failed: %s", strerror(errno)); |
600 | /*NOTREACHED*/ | | 604 | /*NOTREACHED*/ |
601 | case 0: | | 605 | case 0: |
602 | close(sv[0]); | | 606 | close(sv[0]); |