xz: omit explicit \0 from HEADER_MAGIC
[oweals/busybox.git] / networking / httpd.c
index 3f4e6aab7c9f4c8881f563d95fe8e4035ac4b8d2..1934bb27eb71fcae437cd46193ba515bc89b4b6e 100644 (file)
@@ -348,7 +348,7 @@ struct globals {
 #define range_len         (G.range_len        )
 #else
 enum {
-       range_start = 0,
+       range_start = -1,
        range_end = MAXINT(off_t) - 1,
        range_len = MAXINT(off_t),
 };
@@ -370,6 +370,7 @@ enum {
 #define INIT_G() do { \
        SET_PTR_TO_GLOBALS(xzalloc(sizeof(G))); \
        IF_FEATURE_HTTPD_BASIC_AUTH(g_realm = "Web Server Authentication";) \
+       IF_FEATURE_HTTPD_RANGES(range_start = -1;) \
        bind_addr_or_port = "80"; \
        index_page = index_html; \
        file_size = -1; \
@@ -795,9 +796,9 @@ static void parse_conf(const char *path, int flag)
                /* the line is not recognized */
  config_error:
                bb_error_msg("config error '%s' in '%s'", buf, filename);
-        } /* while (fgets) */
+       } /* while (fgets) */
 
-        fclose(f);
+       fclose(f);
 }
 
 #if ENABLE_FEATURE_HTTPD_ENCODE_URL_STR
@@ -1413,7 +1414,7 @@ static void send_cgi_and_exit(
                if (script != url) { /* paranoia */
                        *script = '\0';
                        if (chdir(url + 1) != 0) {
-                               bb_perror_msg("chdir(%s)", url + 1);
+                               bb_perror_msg("can't change directory to '%s'", url + 1);
                                goto error_execing_cgi;
                        }
                        // not needed: *script = '/';
@@ -1589,18 +1590,18 @@ static NOINLINE void send_file_and_exit(const char *url, int what)
        if (what == SEND_BODY /* err pages and ranges don't mix */
         || content_gzip /* we are sending compressed page: can't do ranges */  ///why?
        ) {
-               range_start = 0;
+               range_start = -1;
        }
        range_len = MAXINT(off_t);
-       if (range_start) {
-               if (!range_end) {
+       if (range_start >= 0) {
+               if (!range_end || range_end > file_size - 1) {
                        range_end = file_size - 1;
                }
                if (range_end < range_start
                 || lseek(fd, range_start, SEEK_SET) != range_start
                ) {
                        lseek(fd, 0, SEEK_SET);
-                       range_start = 0;
+                       range_start = -1;
                } else {
                        range_len = range_end - range_start + 1;
                        send_headers(HTTP_PARTIAL_CONTENT);
@@ -1623,7 +1624,7 @@ static NOINLINE void send_file_and_exit(const char *url, int what)
                                        break; /* fall back to read/write loop */
                                goto fin;
                        }
-                       IF_FEATURE_HTTPD_RANGES(range_len -= sz;)
+                       IF_FEATURE_HTTPD_RANGES(range_len -= count;)
                        if (count == 0 || range_len == 0)
                                log_and_exit();
                }
@@ -1675,7 +1676,7 @@ static int checkPermIP(void)
 
 #if ENABLE_FEATURE_HTTPD_BASIC_AUTH
 
-# if ENABLE_FEATURE_HTTPD_AUTH_MD5 && ENABLE_PAM
+# if ENABLE_PAM
 struct pam_userinfo {
        const char *name;
        const char *pw;
@@ -1707,7 +1708,7 @@ static int pam_talker(int num_msg,
                case PAM_PROMPT_ECHO_OFF:
                        s = userinfo->pw;
                        break;
-               case PAM_ERROR_MSG:
+               case PAM_ERROR_MSG:
                case PAM_TEXT_INFO:
                        s = "";
                        break;
@@ -1776,6 +1777,16 @@ static int check_user_passwd(const char *path, char *user_and_passwd)
                        colon_after_user = strchr(user_and_passwd, ':');
                        if (!colon_after_user)
                                goto bad_input;
+
+                       /* compare "user:" */
+                       if (cur->after_colon[0] != '*'
+                        && strncmp(cur->after_colon, user_and_passwd,
+                                       colon_after_user - user_and_passwd + 1) != 0
+                       ) {
+                               continue;
+                       }
+                       /* this cfg entry is '*' or matches username from peer */
+
                        passwd = strchr(cur->after_colon, ':');
                        if (!passwd)
                                goto bad_input;
@@ -1786,13 +1797,6 @@ static int check_user_passwd(const char *path, char *user_and_passwd)
                                struct pam_conv conv_info = { &pam_talker, (void *) &userinfo };
                                pam_handle_t *pamh;
 
-                               /* compare "user:" */
-                               if (cur->after_colon[0] != '*'
-                                && strncmp(cur->after_colon, user_and_passwd, colon_after_user - user_and_passwd + 1) != 0
-                               ) {
-                                       continue;
-                               }
-                               /* this cfg entry is '*' or matches username from peer */
                                *colon_after_user = '\0';
                                userinfo.name = user_and_passwd;
                                userinfo.pw = colon_after_user + 1;
@@ -1828,31 +1832,34 @@ static int check_user_passwd(const char *path, char *user_and_passwd)
                                                passwd = result->sp_pwdp;
                                }
 #  endif
+                               /* In this case, passwd is ALWAYS encrypted:
+                                * it came from /etc/passwd or /etc/shadow!
+                                */
+                               goto check_encrypted;
 # endif /* ENABLE_PAM */
                        }
+                       /* Else: passwd is from httpd.conf, it is either plaintext or encrypted */
 
-                       /* compare "user:" */
-                       if (cur->after_colon[0] != '*'
-                        && strncmp(cur->after_colon, user_and_passwd, colon_after_user - user_and_passwd + 1) != 0
-                       ) {
-                               continue;
-                       }
-                       /* this cfg entry is '*' or matches username from peer */
-
-                       /* encrypt pwd from peer and check match with local one */
-                       {
-                               char *encrypted = pw_encrypt(
-                                       /* pwd: */  colon_after_user + 1,
+                       if (passwd[0] == '$' && isdigit(passwd[1])) {
+                               char *encrypted;
+# if !ENABLE_PAM
+ check_encrypted:
+# endif
+                               /* encrypt pwd from peer and check match with local one */
+                               encrypted = pw_encrypt(
+                                       /* pwd (from peer): */  colon_after_user + 1,
                                        /* salt: */ passwd,
                                        /* cleanup: */ 0
                                );
                                r = strcmp(encrypted, passwd);
                                free(encrypted);
-                               goto end_check_passwd;
+                       } else {
+                               /* local passwd is from httpd.conf and it's plaintext */
+                               r = strcmp(colon_after_user + 1, passwd);
                        }
bad_input: ;
                      goto end_check_passwd;
                }
-
+ bad_input:
                /* Comparing plaintext "user:pass" in one go */
                r = strcmp(cur->after_colon, user_and_passwd);
  end_check_passwd:
@@ -2164,11 +2171,11 @@ static void handle_incoming_and_exit(const len_and_sockaddr *fromAddr)
                                        s += sizeof("bytes=")-1;
                                        range_start = BB_STRTOOFF(s, &s, 10);
                                        if (s[0] != '-' || range_start < 0) {
-                                               range_start = 0;
+                                               range_start = -1;
                                        } else if (s[1]) {
                                                range_end = BB_STRTOOFF(s+1, NULL, 10);
                                                if (errno || range_end < range_start)
-                                                       range_start = 0;
+                                                       range_start = -1;
                                        }
                                }
                        }