aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorDenys Vlasenko <vda.linux@googlemail.com>2016-11-22 02:23:35 +0100
committerDenys Vlasenko <vda.linux@googlemail.com>2016-11-22 02:23:35 +0100
commit9f8eb1ee7620020e01b3596ac7259d51ebca7a7b (patch)
treef3b597df15aa26a5aea3f45c788c7239217586ad
parent7e8218f9b26946ec3b411bc25a62b6b4278f2386 (diff)
downloadbusybox-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.c56
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)
926static void send_headers(int responseNum) 926static 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';