diff options
author | Denys Vlasenko <vda.linux@googlemail.com> | 2016-11-22 02:23:35 +0100 |
---|---|---|
committer | Denys Vlasenko <vda.linux@googlemail.com> | 2016-11-22 02:23:35 +0100 |
commit | 9f8eb1ee7620020e01b3596ac7259d51ebca7a7b (patch) | |
tree | f3b597df15aa26a5aea3f45c788c7239217586ad | |
parent | 7e8218f9b26946ec3b411bc25a62b6b4278f2386 (diff) | |
download | busybox-w32-9f8eb1ee7620020e01b3596ac7259d51ebca7a7b.tar.gz busybox-w32-9f8eb1ee7620020e01b3596ac7259d51ebca7a7b.tar.bz2 busybox-w32-9f8eb1ee7620020e01b3596ac7259d51ebca7a7b.zip |
httpd: explain why we use sprintf and why it should be fine
While at it, fix a pathological case where it is not fine:
-r REALM with some 8-kbyte long REALM would overflow the buffer.
Signed-off-by: Denys Vlasenko <vda.linux@googlemail.com>
-rw-r--r-- | networking/httpd.c | 56 |
1 files changed, 36 insertions, 20 deletions
diff --git a/networking/httpd.c b/networking/httpd.c index abe83a458..c20642e11 100644 --- a/networking/httpd.c +++ b/networking/httpd.c | |||
@@ -926,16 +926,16 @@ static void log_and_exit(void) | |||
926 | static void send_headers(int responseNum) | 926 | static void send_headers(int responseNum) |
927 | { | 927 | { |
928 | static const char RFC1123FMT[] ALIGN1 = "%a, %d %b %Y %H:%M:%S GMT"; | 928 | static const char RFC1123FMT[] ALIGN1 = "%a, %d %b %Y %H:%M:%S GMT"; |
929 | /* Fixed size 29-byte string. Example: Sun, 06 Nov 1994 08:49:37 GMT */ | ||
930 | char date_str[40]; /* using a bit larger buffer to paranoia reasons */ | ||
929 | 931 | ||
930 | const char *responseString = ""; | 932 | const char *responseString = ""; |
931 | const char *infoString = NULL; | 933 | const char *infoString = NULL; |
932 | const char *mime_type; | ||
933 | #if ENABLE_FEATURE_HTTPD_ERROR_PAGES | 934 | #if ENABLE_FEATURE_HTTPD_ERROR_PAGES |
934 | const char *error_page = NULL; | 935 | const char *error_page = NULL; |
935 | #endif | 936 | #endif |
936 | unsigned i; | 937 | unsigned i; |
937 | time_t timer = time(NULL); | 938 | time_t timer = time(NULL); |
938 | char tmp_str[80]; | ||
939 | int len; | 939 | int len; |
940 | 940 | ||
941 | for (i = 0; i < ARRAY_SIZE(http_response_type); i++) { | 941 | for (i = 0; i < ARRAY_SIZE(http_response_type); i++) { |
@@ -948,25 +948,33 @@ static void send_headers(int responseNum) | |||
948 | break; | 948 | break; |
949 | } | 949 | } |
950 | } | 950 | } |
951 | /* error message is HTML */ | ||
952 | mime_type = responseNum == HTTP_OK ? | ||
953 | found_mime_type : "text/html"; | ||
954 | 951 | ||
955 | if (verbose) | 952 | if (verbose) |
956 | bb_error_msg("response:%u", responseNum); | 953 | bb_error_msg("response:%u", responseNum); |
957 | 954 | ||
958 | /* emit the current date */ | 955 | /* We use sprintf, not snprintf (it's less code). |
959 | strftime(tmp_str, sizeof(tmp_str), RFC1123FMT, gmtime(&timer)); | 956 | * iobuf[] is several kbytes long and all headers we generate |
957 | * always fit into those kbytes. | ||
958 | */ | ||
959 | |||
960 | strftime(date_str, sizeof(date_str), RFC1123FMT, gmtime(&timer)); | ||
960 | len = sprintf(iobuf, | 961 | len = sprintf(iobuf, |
961 | "HTTP/1.0 %d %s\r\nContent-type: %s\r\n" | 962 | "HTTP/1.0 %d %s\r\n" |
962 | "Date: %s\r\nConnection: close\r\n", | 963 | "Content-type: %s\r\n" |
963 | responseNum, responseString, mime_type, tmp_str); | 964 | "Date: %s\r\n" |
965 | "Connection: close\r\n", | ||
966 | responseNum, responseString, | ||
967 | /* if it's error message, then it's HTML */ | ||
968 | (responseNum == HTTP_OK ? found_mime_type : "text/html"), | ||
969 | date_str | ||
970 | ); | ||
964 | 971 | ||
965 | #if ENABLE_FEATURE_HTTPD_BASIC_AUTH | 972 | #if ENABLE_FEATURE_HTTPD_BASIC_AUTH |
966 | if (responseNum == HTTP_UNAUTHORIZED) { | 973 | if (responseNum == HTTP_UNAUTHORIZED) { |
967 | len += sprintf(iobuf + len, | 974 | len += sprintf(iobuf + len, |
968 | "WWW-Authenticate: Basic realm=\"%s\"\r\n", | 975 | "WWW-Authenticate: Basic realm=\"%.999s\"\r\n", |
969 | g_realm); | 976 | g_realm /* %.999s protects from overflowing iobuf[] */ |
977 | ); | ||
970 | } | 978 | } |
971 | #endif | 979 | #endif |
972 | if (responseNum == HTTP_MOVED_TEMPORARILY) { | 980 | if (responseNum == HTTP_MOVED_TEMPORARILY) { |
@@ -981,7 +989,8 @@ static void send_headers(int responseNum) | |||
981 | "Location: %s/%s%s\r\n", | 989 | "Location: %s/%s%s\r\n", |
982 | found_moved_temporarily, | 990 | found_moved_temporarily, |
983 | (g_query ? "?" : ""), | 991 | (g_query ? "?" : ""), |
984 | (g_query ? g_query : "")); | 992 | (g_query ? g_query : "") |
993 | ); | ||
985 | if (len > IOBUF_SIZE-3) | 994 | if (len > IOBUF_SIZE-3) |
986 | len = IOBUF_SIZE-3; | 995 | len = IOBUF_SIZE-3; |
987 | } | 996 | } |
@@ -1002,13 +1011,15 @@ static void send_headers(int responseNum) | |||
1002 | #endif | 1011 | #endif |
1003 | 1012 | ||
1004 | if (file_size != -1) { /* file */ | 1013 | if (file_size != -1) { /* file */ |
1005 | strftime(tmp_str, sizeof(tmp_str), RFC1123FMT, gmtime(&last_mod)); | 1014 | strftime(date_str, sizeof(date_str), RFC1123FMT, gmtime(&last_mod)); |
1006 | #if ENABLE_FEATURE_HTTPD_RANGES | 1015 | #if ENABLE_FEATURE_HTTPD_RANGES |
1007 | if (responseNum == HTTP_PARTIAL_CONTENT) { | 1016 | if (responseNum == HTTP_PARTIAL_CONTENT) { |
1008 | len += sprintf(iobuf + len, "Content-Range: bytes %"OFF_FMT"u-%"OFF_FMT"u/%"OFF_FMT"u\r\n", | 1017 | len += sprintf(iobuf + len, |
1018 | "Content-Range: bytes %"OFF_FMT"u-%"OFF_FMT"u/%"OFF_FMT"u\r\n", | ||
1009 | range_start, | 1019 | range_start, |
1010 | range_end, | 1020 | range_end, |
1011 | file_size); | 1021 | file_size |
1022 | ); | ||
1012 | file_size = range_end - range_start + 1; | 1023 | file_size = range_end - range_start + 1; |
1013 | } | 1024 | } |
1014 | #endif | 1025 | #endif |
@@ -1016,8 +1027,9 @@ static void send_headers(int responseNum) | |||
1016 | #if ENABLE_FEATURE_HTTPD_RANGES | 1027 | #if ENABLE_FEATURE_HTTPD_RANGES |
1017 | "Accept-Ranges: bytes\r\n" | 1028 | "Accept-Ranges: bytes\r\n" |
1018 | #endif | 1029 | #endif |
1019 | "Last-Modified: %s\r\n%s %"OFF_FMT"u\r\n", | 1030 | "Last-Modified: %s\r\n" |
1020 | tmp_str, | 1031 | "%s %"OFF_FMT"u\r\n", |
1032 | date_str, | ||
1021 | content_gzip ? "Transfer-length:" : "Content-length:", | 1033 | content_gzip ? "Transfer-length:" : "Content-length:", |
1022 | file_size | 1034 | file_size |
1023 | ); | 1035 | ); |
@@ -1031,9 +1043,13 @@ static void send_headers(int responseNum) | |||
1031 | if (infoString) { | 1043 | if (infoString) { |
1032 | len += sprintf(iobuf + len, | 1044 | len += sprintf(iobuf + len, |
1033 | "<HTML><HEAD><TITLE>%d %s</TITLE></HEAD>\n" | 1045 | "<HTML><HEAD><TITLE>%d %s</TITLE></HEAD>\n" |
1034 | "<BODY><H1>%d %s</H1>\n%s\n</BODY></HTML>\n", | 1046 | "<BODY><H1>%d %s</H1>\n" |
1047 | "%s\n" | ||
1048 | "</BODY></HTML>\n", | ||
1035 | responseNum, responseString, | 1049 | responseNum, responseString, |
1036 | responseNum, responseString, infoString); | 1050 | responseNum, responseString, |
1051 | infoString | ||
1052 | ); | ||
1037 | } | 1053 | } |
1038 | if (DEBUG) { | 1054 | if (DEBUG) { |
1039 | iobuf[len] = '\0'; | 1055 | iobuf[len] = '\0'; |