Ignore:
Timestamp:
Jan 1, 2014, 12:47:38 AM (10 years ago)
Author:
Bruno Cornec
Message:
  • Update mindi-busybox to 1.21.1
File:
1 edited

Legend:

Unmodified
Added
Removed
  • branches/3.2/mindi-busybox/networking/httpd.c

    r2725 r3232  
    2121 * The server changes directory to the location of the script and executes it
    2222 * after setting QUERY_STRING and other environment variables.
     23 *
     24 * If directory URL is given, no index.html is found and CGI support is enabled,
     25 * cgi-bin/index.cgi will be run. Directory to list is ../$QUERY_STRING.
     26 * See httpd_indexcgi.c for an example GCI code.
    2327 *
    2428 * Doc:
     
    5155 * /adm:admin:setup  # Require user admin, pwd setup on urls starting with /adm/
    5256 * /adm:toor:PaSsWd  # or user toor, pwd PaSsWd on urls starting with /adm/
     57 * /adm:root:*       # or user root, pwd from /etc/passwd on urls starting with /adm/
     58 * /wiki:*:*         # or any user from /etc/passwd with according pwd on urls starting with /wiki/
    5359 * .au:audio/basic   # additional mime type for audio.au files
    5460 * *.php:/path/php   # run xxx.php through an interpreter
     
    7278 *     A:*             # (optional line added for clarity)
    7379 *
    74  * If a sub directory contains a config file it is parsed and merged with
     80 * If a sub directory contains config file, it is parsed and merged with
    7581 * any existing settings as if it was appended to the original configuration.
    7682 *
     
    94100 /* TODO: use TCP_CORK, parse_config() */
    95101
     102//usage:#define httpd_trivial_usage
     103//usage:       "[-ifv[v]]"
     104//usage:       " [-c CONFFILE]"
     105//usage:       " [-p [IP:]PORT]"
     106//usage:    IF_FEATURE_HTTPD_SETUID(" [-u USER[:GRP]]")
     107//usage:    IF_FEATURE_HTTPD_BASIC_AUTH(" [-r REALM]")
     108//usage:       " [-h HOME]\n"
     109//usage:       "or httpd -d/-e" IF_FEATURE_HTTPD_AUTH_MD5("/-m") " STRING"
     110//usage:#define httpd_full_usage "\n\n"
     111//usage:       "Listen for incoming HTTP requests\n"
     112//usage:     "\n    -i      Inetd mode"
     113//usage:     "\n    -f      Don't daemonize"
     114//usage:     "\n    -v[v]       Verbose"
     115//usage:     "\n    -p [IP:]PORT    Bind to IP:PORT (default *:80)"
     116//usage:    IF_FEATURE_HTTPD_SETUID(
     117//usage:     "\n    -u USER[:GRP]   Set uid/gid after binding to port")
     118//usage:    IF_FEATURE_HTTPD_BASIC_AUTH(
     119//usage:     "\n    -r REALM    Authentication Realm for Basic Authentication")
     120//usage:     "\n    -h HOME     Home directory (default .)"
     121//usage:     "\n    -c FILE     Configuration file (default {/etc,HOME}/httpd.conf)"
     122//usage:    IF_FEATURE_HTTPD_AUTH_MD5(
     123//usage:     "\n    -m STRING   MD5 crypt STRING")
     124//usage:     "\n    -e STRING   HTML encode STRING"
     125//usage:     "\n    -d STRING   URL decode STRING"
     126
    96127#include "libbb.h"
     128#if ENABLE_PAM
     129/* PAM may include <locale.h>. We may need to undefine bbox's stub define: */
     130# undef setlocale
     131/* For some obscure reason, PAM is not in pam/xxx, but in security/xxx.
     132 * Apparently they like to confuse people. */
     133# include <security/pam_appl.h>
     134# include <security/pam_misc.h>
     135#endif
    97136#if ENABLE_FEATURE_HTTPD_USE_SENDFILE
    98137# include <sys/sendfile.h>
     
    310349#else
    311350enum {
    312     range_start = 0,
     351    range_start = -1,
    313352    range_end = MAXINT(off_t) - 1,
    314353    range_len = MAXINT(off_t),
     
    332371    SET_PTR_TO_GLOBALS(xzalloc(sizeof(G))); \
    333372    IF_FEATURE_HTTPD_BASIC_AUTH(g_realm = "Web Server Authentication";) \
     373    IF_FEATURE_HTTPD_RANGES(range_start = -1;) \
    334374    bind_addr_or_port = "80"; \
    335375    index_page = index_html; \
     
    757797 config_error:
    758798        bb_error_msg("config error '%s' in '%s'", buf, filename);
    759      } /* while (fgets) */
    760 
    761      fclose(f);
     799    } /* while (fgets) */
     800
     801    fclose(f);
    762802}
    763803
     
    791831}
    792832#endif
    793 
    794 /*
    795  * Given a URL encoded string, convert it to plain ascii.
    796  * Since decoding always makes strings smaller, the decode is done in-place.
    797  * Thus, callers should xstrdup() the argument if they do not want the
    798  * argument modified.  The return is the original pointer, allowing this
    799  * function to be easily used as arguments to other functions.
    800  *
    801  * string    The first string to decode.
    802  * option_d  1 if called for httpd -d
    803  *
    804  * Returns a pointer to the decoded string (same as input).
    805  */
    806 static unsigned hex_to_bin(unsigned char c)
    807 {
    808     unsigned v;
    809 
    810     v = c - '0';
    811     if (v <= 9)
    812         return v;
    813     /* c | 0x20: letters to lower case, non-letters
    814      * to (potentially different) non-letters */
    815     v = (unsigned)(c | 0x20) - 'a';
    816     if (v <= 5)
    817         return v + 10;
    818     return ~0;
    819 /* For testing:
    820 void t(char c) { printf("'%c'(%u) %u\n", c, c, hex_to_bin(c)); }
    821 int main() { t(0x10); t(0x20); t('0'); t('9'); t('A'); t('F'); t('a'); t('f');
    822 t('0'-1); t('9'+1); t('A'-1); t('F'+1); t('a'-1); t('f'+1); return 0; }
    823 */
    824 }
    825 static char *decodeString(char *orig, int option_d)
    826 {
    827     /* note that decoded string is always shorter than original */
    828     char *string = orig;
    829     char *ptr = string;
    830     char c;
    831 
    832     while ((c = *ptr++) != '\0') {
    833         unsigned v;
    834 
    835         if (option_d && c == '+') {
    836             *string++ = ' ';
    837             continue;
    838         }
    839         if (c != '%') {
    840             *string++ = c;
    841             continue;
    842         }
    843         v = hex_to_bin(ptr[0]);
    844         if (v > 15) {
    845  bad_hex:
    846             if (!option_d)
    847                 return NULL;
    848             *string++ = '%';
    849             continue;
    850         }
    851         v = (v * 16) | hex_to_bin(ptr[1]);
    852         if (v > 255)
    853             goto bad_hex;
    854         if (!option_d && (v == '/' || v == '\0')) {
    855             /* caller takes it as indication of invalid
    856              * (dangerous wrt exploits) chars */
    857             return orig + 1;
    858         }
    859         *string++ = v;
    860         ptr += 2;
    861     }
    862     *string = '\0';
    863     return orig;
    864 }
    865833
    866834#if ENABLE_FEATURE_HTTPD_BASIC_AUTH
     
    10661034static void send_headers_and_exit(int responseNum)
    10671035{
     1036    IF_FEATURE_HTTPD_GZIP(content_gzip = 0;)
    10681037    send_headers(responseNum);
    10691038    log_and_exit();
     
    12981267 * Parameters:
    12991268 * const char *url              The requested URL (with leading /).
     1269 * const char *orig_uri         The original URI before rewriting (if any)
    13001270 * int post_len                 Length of the POST body.
    13011271 * const char *cookie           For set HTTP_COOKIE.
     
    13041274static void send_cgi_and_exit(
    13051275        const char *url,
     1276        const char *orig_uri,
    13061277        const char *request,
    13071278        int post_len,
     
    13101281static void send_cgi_and_exit(
    13111282        const char *url,
     1283        const char *orig_uri,
    13121284        const char *request,
    13131285        int post_len,
     
    13171289    struct fd_pair fromCgi;  /* CGI -> httpd pipe */
    13181290    struct fd_pair toCgi;    /* httpd -> CGI pipe */
    1319     char *script;
     1291    char *script, *last_slash;
    13201292    int pid;
    13211293
     
    13311303
    13321304    /* Check for [dirs/]script.cgi/PATH_INFO */
    1333     script = (char*)url;
     1305    last_slash = script = (char*)url;
    13341306    while ((script = strchr(script + 1, '/')) != NULL) {
     1307        int dir;
    13351308        *script = '\0';
    1336         if (!is_directory(url + 1, 1, NULL)) {
     1309        dir = is_directory(url + 1, /*followlinks:*/ 1);
     1310        *script = '/';
     1311        if (!dir) {
    13371312            /* not directory, found script.cgi/PATH_INFO */
    1338             *script = '/';
    13391313            break;
    13401314        }
    1341         *script = '/'; /* is directory, find next '/' */
     1315        /* is directory, find next '/' */
     1316        last_slash = script;
    13421317    }
    13431318    setenv1("PATH_INFO", script);   /* set to /PATH_INFO or "" */
    13441319    setenv1("REQUEST_METHOD", request);
    13451320    if (g_query) {
    1346         putenv(xasprintf("%s=%s?%s", "REQUEST_URI", url, g_query));
     1321        putenv(xasprintf("%s=%s?%s", "REQUEST_URI", orig_uri, g_query));
    13471322    } else {
    1348         setenv1("REQUEST_URI", url);
     1323        setenv1("REQUEST_URI", orig_uri);
    13491324    }
    13501325    if (script != NULL)
     
    14201395    }
    14211396
    1422     if (!pid) {
     1397    if (pid == 0) {
    14231398        /* Child process */
    14241399        char *argv[3];
     
    14361411
    14371412        /* Chdiring to script's dir */
    1438         script = strrchr(url, '/');
     1413        script = last_slash;
    14391414        if (script != url) { /* paranoia */
    14401415            *script = '\0';
    14411416            if (chdir(url + 1) != 0) {
    1442                 bb_perror_msg("chdir(%s)", url + 1);
     1417                bb_perror_msg("can't change directory to '%s'", url + 1);
    14431418                goto error_execing_cgi;
    14441419            }
     
    16161591     || content_gzip /* we are sending compressed page: can't do ranges */  ///why?
    16171592    ) {
    1618         range_start = 0;
     1593        range_start = -1;
    16191594    }
    16201595    range_len = MAXINT(off_t);
    1621     if (range_start) {
    1622         if (!range_end) {
     1596    if (range_start >= 0) {
     1597        if (!range_end || range_end > file_size - 1) {
    16231598            range_end = file_size - 1;
    16241599        }
     
    16271602        ) {
    16281603            lseek(fd, 0, SEEK_SET);
    1629             range_start = 0;
     1604            range_start = -1;
    16301605        } else {
    16311606            range_len = range_end - range_start + 1;
     
    16501625                goto fin;
    16511626            }
    1652             IF_FEATURE_HTTPD_RANGES(range_len -= sz;)
     1627            IF_FEATURE_HTTPD_RANGES(range_len -= count;)
    16531628            if (count == 0 || range_len == 0)
    16541629                log_and_exit();
     
    17011676
    17021677#if ENABLE_FEATURE_HTTPD_BASIC_AUTH
     1678
     1679# if ENABLE_PAM
     1680struct pam_userinfo {
     1681    const char *name;
     1682    const char *pw;
     1683};
     1684
     1685static int pam_talker(int num_msg,
     1686        const struct pam_message **msg,
     1687        struct pam_response **resp,
     1688        void *appdata_ptr)
     1689{
     1690    int i;
     1691    struct pam_userinfo *userinfo = (struct pam_userinfo *) appdata_ptr;
     1692    struct pam_response *response;
     1693
     1694    if (!resp || !msg || !userinfo)
     1695        return PAM_CONV_ERR;
     1696
     1697    /* allocate memory to store response */
     1698    response = xzalloc(num_msg * sizeof(*response));
     1699
     1700    /* copy values */
     1701    for (i = 0; i < num_msg; i++) {
     1702        const char *s;
     1703
     1704        switch (msg[i]->msg_style) {
     1705        case PAM_PROMPT_ECHO_ON:
     1706            s = userinfo->name;
     1707            break;
     1708        case PAM_PROMPT_ECHO_OFF:
     1709            s = userinfo->pw;
     1710            break;
     1711        case PAM_ERROR_MSG:
     1712            case PAM_TEXT_INFO:
     1713                s = "";
     1714            break;
     1715        default:
     1716            free(response);
     1717            return PAM_CONV_ERR;
     1718        }
     1719        response[i].resp = xstrdup(s);
     1720        if (PAM_SUCCESS != 0)
     1721            response[i].resp_retcode = PAM_SUCCESS;
     1722    }
     1723    *resp = response;
     1724    return PAM_SUCCESS;
     1725}
     1726# endif
     1727
    17031728/*
    17041729 * Config file entries are of the form "/<path>:<user>:<passwd>".
     
    17101735 * Returns 1 if user_and_passwd is OK.
    17111736 */
    1712 static int check_user_passwd(const char *path, const char *user_and_passwd)
     1737static int check_user_passwd(const char *path, char *user_and_passwd)
    17131738{
    17141739    Htaccess *cur;
     
    17181743        const char *dir_prefix;
    17191744        size_t len;
     1745        int r;
    17201746
    17211747        dir_prefix = cur->before_colon;
     
    17331759        if (len != 1 /* dir_prefix "/" matches all, don't need to check */
    17341760         && (strncmp(dir_prefix, path, len) != 0
    1735             || (path[len] != '/' && path[len] != '\0'))
     1761            || (path[len] != '/' && path[len] != '\0')
     1762            )
    17361763        ) {
    17371764            continue;
     
    17421769
    17431770        if (ENABLE_FEATURE_HTTPD_AUTH_MD5) {
    1744             char *md5_passwd;
    1745 
    1746             md5_passwd = strchr(cur->after_colon, ':');
    1747             if (md5_passwd && md5_passwd[1] == '$' && md5_passwd[2] == '1'
    1748              && md5_passwd[3] == '$' && md5_passwd[4]
     1771            char *colon_after_user;
     1772            const char *passwd;
     1773# if ENABLE_FEATURE_SHADOWPASSWDS && !ENABLE_PAM
     1774            char sp_buf[256];
     1775# endif
     1776
     1777            colon_after_user = strchr(user_and_passwd, ':');
     1778            if (!colon_after_user)
     1779                goto bad_input;
     1780
     1781            /* compare "user:" */
     1782            if (cur->after_colon[0] != '*'
     1783             && strncmp(cur->after_colon, user_and_passwd,
     1784                    colon_after_user - user_and_passwd + 1) != 0
    17491785            ) {
     1786                continue;
     1787            }
     1788            /* this cfg entry is '*' or matches username from peer */
     1789
     1790            passwd = strchr(cur->after_colon, ':');
     1791            if (!passwd)
     1792                goto bad_input;
     1793            passwd++;
     1794            if (passwd[0] == '*') {
     1795# if ENABLE_PAM
     1796                struct pam_userinfo userinfo;
     1797                struct pam_conv conv_info = { &pam_talker, (void *) &userinfo };
     1798                pam_handle_t *pamh;
     1799
     1800                *colon_after_user = '\0';
     1801                userinfo.name = user_and_passwd;
     1802                userinfo.pw = colon_after_user + 1;
     1803                r = pam_start("httpd", user_and_passwd, &conv_info, &pamh) != PAM_SUCCESS;
     1804                if (r == 0) {
     1805                    r = pam_authenticate(pamh, PAM_DISALLOW_NULL_AUTHTOK) != PAM_SUCCESS
     1806                     || pam_acct_mgmt(pamh, PAM_DISALLOW_NULL_AUTHTOK)    != PAM_SUCCESS
     1807                    ;
     1808                    pam_end(pamh, PAM_SUCCESS);
     1809                }
     1810                *colon_after_user = ':';
     1811                goto end_check_passwd;
     1812# else
     1813#  if ENABLE_FEATURE_SHADOWPASSWDS
     1814                /* Using _r function to avoid pulling in static buffers */
     1815                struct spwd spw;
     1816#  endif
     1817                struct passwd *pw;
     1818
     1819                *colon_after_user = '\0';
     1820                pw = getpwnam(user_and_passwd);
     1821                *colon_after_user = ':';
     1822                if (!pw || !pw->pw_passwd)
     1823                    continue;
     1824                passwd = pw->pw_passwd;
     1825#  if ENABLE_FEATURE_SHADOWPASSWDS
     1826                if ((passwd[0] == 'x' || passwd[0] == '*') && !passwd[1]) {
     1827                    /* getspnam_r may return 0 yet set result to NULL.
     1828                     * At least glibc 2.4 does this. Be extra paranoid here. */
     1829                    struct spwd *result = NULL;
     1830                    r = getspnam_r(pw->pw_name, &spw, sp_buf, sizeof(sp_buf), &result);
     1831                    if (r == 0 && result)
     1832                        passwd = result->sp_pwdp;
     1833                }
     1834#  endif
     1835                /* In this case, passwd is ALWAYS encrypted:
     1836                 * it came from /etc/passwd or /etc/shadow!
     1837                 */
     1838                goto check_encrypted;
     1839# endif /* ENABLE_PAM */
     1840            }
     1841            /* Else: passwd is from httpd.conf, it is either plaintext or encrypted */
     1842
     1843            if (passwd[0] == '$' && isdigit(passwd[1])) {
    17501844                char *encrypted;
    1751                 int r, user_len_p1;
    1752 
    1753                 md5_passwd++;
    1754                 user_len_p1 = md5_passwd - cur->after_colon;
    1755                 /* comparing "user:" */
    1756                 if (strncmp(cur->after_colon, user_and_passwd, user_len_p1) != 0) {
    1757                     continue;
    1758                 }
    1759 
     1845# if !ENABLE_PAM
     1846 check_encrypted:
     1847# endif
     1848                /* encrypt pwd from peer and check match with local one */
    17601849                encrypted = pw_encrypt(
    1761                     user_and_passwd + user_len_p1 /* cleartext pwd from user */,
    1762                     md5_passwd /*salt */, 1 /* cleanup */);
    1763                 r = strcmp(encrypted, md5_passwd);
     1850                    /* pwd (from peer): */  colon_after_user + 1,
     1851                    /* salt: */ passwd,
     1852                    /* cleanup: */ 0
     1853                );
     1854                r = strcmp(encrypted, passwd);
    17641855                free(encrypted);
    1765                 if (r == 0)
    1766                     goto set_remoteuser_var; /* Ok */
    1767                 continue;
    1768             }
    1769         }
    1770 
     1856            } else {
     1857                /* local passwd is from httpd.conf and it's plaintext */
     1858                r = strcmp(colon_after_user + 1, passwd);
     1859            }
     1860            goto end_check_passwd;
     1861        }
     1862 bad_input:
    17711863        /* Comparing plaintext "user:pass" in one go */
    1772         if (strcmp(cur->after_colon, user_and_passwd) == 0) {
    1773  set_remoteuser_var:
     1864        r = strcmp(cur->after_colon, user_and_passwd);
     1865 end_check_passwd:
     1866        if (r == 0) {
    17741867            remoteuser = xstrndup(user_and_passwd,
    1775                     strchrnul(user_and_passwd, ':') - user_and_passwd);
     1868                strchrnul(user_and_passwd, ':') - user_and_passwd
     1869            );
    17761870            return 1; /* Ok */
    17771871        }
     
    19122006
    19132007    /* Extract url args if present */
    1914     g_query = NULL;
     2008    /* g_query = NULL; - already is */
    19152009    tptr = strchr(urlcopy, '?');
    19162010    if (tptr) {
     
    19202014
    19212015    /* Decode URL escape sequences */
    1922     tptr = decodeString(urlcopy, 0);
     2016    tptr = percent_decode_in_place(urlcopy, /*strict:*/ 1);
    19232017    if (tptr == NULL)
    19242018        send_headers_and_exit(HTTP_BAD_REQUEST);
     
    19322026     * but don't strdup, retain trailing slash, protect root */
    19332027    urlp = tptr = urlcopy;
    1934     do {
     2028    for (;;) {
    19352029        if (*urlp == '/') {
    19362030            /* skip duplicate (or initial) slash */
    19372031            if (*tptr == '/') {
    1938                 continue;
     2032                goto next_char;
    19392033            }
    19402034            if (*tptr == '.') {
    1941                 /* skip extra "/./" */
    1942                 if (tptr[1] == '/' || !tptr[1]) {
    1943                     continue;
     2035                if (tptr[1] == '.' && (tptr[2] == '/' || tptr[2] == '\0')) {
     2036                    /* "..": be careful */
     2037                    /* protect root */
     2038                    if (urlp == urlcopy)
     2039                        send_headers_and_exit(HTTP_BAD_REQUEST);
     2040                    /* omit previous dir */
     2041                    while (*--urlp != '/')
     2042                        continue;
     2043                    /* skip to "./" or ".<NUL>" */
     2044                    tptr++;
    19442045                }
    1945                 /* "..": be careful */
    1946                 if (tptr[1] == '.' && (tptr[2] == '/' || !tptr[2])) {
    1947                     ++tptr;
    1948                     if (urlp == urlcopy) /* protect root */
    1949                         send_headers_and_exit(HTTP_BAD_REQUEST);
    1950                     while (*--urlp != '/') /* omit previous dir */;
    1951                         continue;
     2046                if (tptr[1] == '/' || tptr[1] == '\0') {
     2047                    /* skip extra "/./" */
     2048                    goto next_char;
    19522049                }
    19532050            }
    19542051        }
    19552052        *++urlp = *tptr;
    1956     } while (*++tptr);
    1957     *++urlp = '\0';       /* terminate after last character */
     2053        if (*urlp == '\0')
     2054            break;
     2055 next_char:
     2056        tptr++;
     2057    }
    19582058
    19592059    /* If URL is a directory, add '/' */
    19602060    if (urlp[-1] != '/') {
    1961         if (is_directory(urlcopy + 1, 1, NULL)) {
     2061        if (is_directory(urlcopy + 1, /*followlinks:*/ 1)) {
    19622062            found_moved_temporarily = urlcopy;
    19632063        }
     
    19732073        /* have path1/path2 */
    19742074        *tptr = '\0';
    1975         if (is_directory(urlcopy + 1, 1, NULL)) {
     2075        if (is_directory(urlcopy + 1, /*followlinks:*/ 1)) {
    19762076            /* may have subdir config */
    19772077            parse_conf(urlcopy + 1, SUBDIR_PARSE);
     
    20722172                    range_start = BB_STRTOOFF(s, &s, 10);
    20732173                    if (s[0] != '-' || range_start < 0) {
    2074                         range_start = 0;
     2174                        range_start = -1;
    20752175                    } else if (s[1]) {
    20762176                        range_end = BB_STRTOOFF(s+1, NULL, 10);
    20772177                        if (errno || range_end < range_start)
    2078                             range_start = 0;
     2178                            range_start = -1;
    20792179                    }
    20802180                }
     
    21102210
    21112211#if ENABLE_FEATURE_HTTPD_BASIC_AUTH
    2112     /* Case: no "Authorization:" was seen, but page does require passwd.
     2212    /* Case: no "Authorization:" was seen, but page might require passwd.
    21132213     * Check that with dummy user:pass */
    21142214    if (authorized < 0)
    2115         authorized = check_user_passwd(urlcopy, ":");
     2215        authorized = check_user_passwd(urlcopy, (char *) "");
    21162216    if (!authorized)
    21172217        send_headers_and_exit(HTTP_UNAUTHORIZED);
     
    21592259            send_headers_and_exit(HTTP_FORBIDDEN);
    21602260        }
    2161         send_cgi_and_exit(urlcopy, prequest, length, cookie, content_type);
    2162     }
    2163 #endif
    2164 
    2165     if (urlp[-1] == '/')
     2261        send_cgi_and_exit(urlcopy, urlcopy, prequest, length, cookie, content_type);
     2262    }
     2263#endif
     2264
     2265    if (urlp[-1] == '/') {
     2266        /* When index_page string is appended to <dir>/ URL, it overwrites
     2267         * the query string. If we fall back to call /cgi-bin/index.cgi,
     2268         * query string would be lost and not available to the CGI.
     2269         * Work around it by making a deep copy.
     2270         */
     2271        if (ENABLE_FEATURE_HTTPD_CGI)
     2272            g_query = xstrdup(g_query); /* ok for NULL too */
    21662273        strcpy(urlp, index_page);
     2274    }
    21672275    if (stat(tptr, &sb) == 0) {
    21682276#if ENABLE_FEATURE_HTTPD_CONFIG_WITH_SCRIPT_INTERPR
     
    21722280            for (cur = script_i; cur; cur = cur->next) {
    21732281                if (strcmp(cur->before_colon + 1, suffix) == 0) {
    2174                     send_cgi_and_exit(urlcopy, prequest, length, cookie, content_type);
     2282                    send_cgi_and_exit(urlcopy, urlcopy, prequest, length, cookie, content_type);
    21752283                }
    21762284            }
     
    21852293         * Try cgi-bin/index.cgi */
    21862294        if (access("/cgi-bin/index.cgi"+1, X_OK) == 0) {
    2187             urlp[0] = '\0';
    2188             g_query = urlcopy;
    2189             send_cgi_and_exit("/cgi-bin/index.cgi", prequest, length, cookie, content_type);
     2295            urlp[0] = '\0'; /* remove index_page */
     2296            send_cgi_and_exit("/cgi-bin/index.cgi", urlcopy, prequest, length, cookie, content_type);
    21902297        }
    21912298    }
     
    22862393            re_exec(argv_copy);
    22872394        }
     2395        argv_copy[0][0] &= 0x7f;
    22882396        /* parent, or vfork failed */
    22892397        close(n);
     
    23792487        );
    23802488    if (opt & OPT_DECODE_URL) {
    2381         fputs(decodeString(url_for_decode, 1), stdout);
     2489        fputs(percent_decode_in_place(url_for_decode, /*strict:*/ 0), stdout);
    23822490        return 0;
    23832491    }
     
    23942502        salt[1] = '1';
    23952503        salt[2] = '$';
    2396         crypt_make_salt(salt + 3, 4, 0);
    2397         puts(pw_encrypt(pass, salt, 1));
     2504        crypt_make_salt(salt + 3, 4);
     2505        puts(pw_encrypt(pass, salt, /*cleanup:*/ 0));
    23982506        return 0;
    23992507    }
Note: See TracChangeset for help on using the changeset viewer.