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>
This commit is contained in:
parent
7e8218f9b2
commit
9f8eb1ee76
@ -926,16 +926,16 @@ static void log_and_exit(void)
|
|||||||
static void send_headers(int responseNum)
|
static void send_headers(int responseNum)
|
||||||
{
|
{
|
||||||
static const char RFC1123FMT[] ALIGN1 = "%a, %d %b %Y %H:%M:%S GMT";
|
static const char RFC1123FMT[] ALIGN1 = "%a, %d %b %Y %H:%M:%S GMT";
|
||||||
|
/* Fixed size 29-byte string. Example: Sun, 06 Nov 1994 08:49:37 GMT */
|
||||||
|
char date_str[40]; /* using a bit larger buffer to paranoia reasons */
|
||||||
|
|
||||||
const char *responseString = "";
|
const char *responseString = "";
|
||||||
const char *infoString = NULL;
|
const char *infoString = NULL;
|
||||||
const char *mime_type;
|
|
||||||
#if ENABLE_FEATURE_HTTPD_ERROR_PAGES
|
#if ENABLE_FEATURE_HTTPD_ERROR_PAGES
|
||||||
const char *error_page = NULL;
|
const char *error_page = NULL;
|
||||||
#endif
|
#endif
|
||||||
unsigned i;
|
unsigned i;
|
||||||
time_t timer = time(NULL);
|
time_t timer = time(NULL);
|
||||||
char tmp_str[80];
|
|
||||||
int len;
|
int len;
|
||||||
|
|
||||||
for (i = 0; i < ARRAY_SIZE(http_response_type); i++) {
|
for (i = 0; i < ARRAY_SIZE(http_response_type); i++) {
|
||||||
@ -948,25 +948,33 @@ static void send_headers(int responseNum)
|
|||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
/* error message is HTML */
|
|
||||||
mime_type = responseNum == HTTP_OK ?
|
|
||||||
found_mime_type : "text/html";
|
|
||||||
|
|
||||||
if (verbose)
|
if (verbose)
|
||||||
bb_error_msg("response:%u", responseNum);
|
bb_error_msg("response:%u", responseNum);
|
||||||
|
|
||||||
/* emit the current date */
|
/* We use sprintf, not snprintf (it's less code).
|
||||||
strftime(tmp_str, sizeof(tmp_str), RFC1123FMT, gmtime(&timer));
|
* iobuf[] is several kbytes long and all headers we generate
|
||||||
|
* always fit into those kbytes.
|
||||||
|
*/
|
||||||
|
|
||||||
|
strftime(date_str, sizeof(date_str), RFC1123FMT, gmtime(&timer));
|
||||||
len = sprintf(iobuf,
|
len = sprintf(iobuf,
|
||||||
"HTTP/1.0 %d %s\r\nContent-type: %s\r\n"
|
"HTTP/1.0 %d %s\r\n"
|
||||||
"Date: %s\r\nConnection: close\r\n",
|
"Content-type: %s\r\n"
|
||||||
responseNum, responseString, mime_type, tmp_str);
|
"Date: %s\r\n"
|
||||||
|
"Connection: close\r\n",
|
||||||
|
responseNum, responseString,
|
||||||
|
/* if it's error message, then it's HTML */
|
||||||
|
(responseNum == HTTP_OK ? found_mime_type : "text/html"),
|
||||||
|
date_str
|
||||||
|
);
|
||||||
|
|
||||||
#if ENABLE_FEATURE_HTTPD_BASIC_AUTH
|
#if ENABLE_FEATURE_HTTPD_BASIC_AUTH
|
||||||
if (responseNum == HTTP_UNAUTHORIZED) {
|
if (responseNum == HTTP_UNAUTHORIZED) {
|
||||||
len += sprintf(iobuf + len,
|
len += sprintf(iobuf + len,
|
||||||
"WWW-Authenticate: Basic realm=\"%s\"\r\n",
|
"WWW-Authenticate: Basic realm=\"%.999s\"\r\n",
|
||||||
g_realm);
|
g_realm /* %.999s protects from overflowing iobuf[] */
|
||||||
|
);
|
||||||
}
|
}
|
||||||
#endif
|
#endif
|
||||||
if (responseNum == HTTP_MOVED_TEMPORARILY) {
|
if (responseNum == HTTP_MOVED_TEMPORARILY) {
|
||||||
@ -981,7 +989,8 @@ static void send_headers(int responseNum)
|
|||||||
"Location: %s/%s%s\r\n",
|
"Location: %s/%s%s\r\n",
|
||||||
found_moved_temporarily,
|
found_moved_temporarily,
|
||||||
(g_query ? "?" : ""),
|
(g_query ? "?" : ""),
|
||||||
(g_query ? g_query : ""));
|
(g_query ? g_query : "")
|
||||||
|
);
|
||||||
if (len > IOBUF_SIZE-3)
|
if (len > IOBUF_SIZE-3)
|
||||||
len = IOBUF_SIZE-3;
|
len = IOBUF_SIZE-3;
|
||||||
}
|
}
|
||||||
@ -1002,13 +1011,15 @@ static void send_headers(int responseNum)
|
|||||||
#endif
|
#endif
|
||||||
|
|
||||||
if (file_size != -1) { /* file */
|
if (file_size != -1) { /* file */
|
||||||
strftime(tmp_str, sizeof(tmp_str), RFC1123FMT, gmtime(&last_mod));
|
strftime(date_str, sizeof(date_str), RFC1123FMT, gmtime(&last_mod));
|
||||||
#if ENABLE_FEATURE_HTTPD_RANGES
|
#if ENABLE_FEATURE_HTTPD_RANGES
|
||||||
if (responseNum == HTTP_PARTIAL_CONTENT) {
|
if (responseNum == HTTP_PARTIAL_CONTENT) {
|
||||||
len += sprintf(iobuf + len, "Content-Range: bytes %"OFF_FMT"u-%"OFF_FMT"u/%"OFF_FMT"u\r\n",
|
len += sprintf(iobuf + len,
|
||||||
|
"Content-Range: bytes %"OFF_FMT"u-%"OFF_FMT"u/%"OFF_FMT"u\r\n",
|
||||||
range_start,
|
range_start,
|
||||||
range_end,
|
range_end,
|
||||||
file_size);
|
file_size
|
||||||
|
);
|
||||||
file_size = range_end - range_start + 1;
|
file_size = range_end - range_start + 1;
|
||||||
}
|
}
|
||||||
#endif
|
#endif
|
||||||
@ -1016,8 +1027,9 @@ static void send_headers(int responseNum)
|
|||||||
#if ENABLE_FEATURE_HTTPD_RANGES
|
#if ENABLE_FEATURE_HTTPD_RANGES
|
||||||
"Accept-Ranges: bytes\r\n"
|
"Accept-Ranges: bytes\r\n"
|
||||||
#endif
|
#endif
|
||||||
"Last-Modified: %s\r\n%s %"OFF_FMT"u\r\n",
|
"Last-Modified: %s\r\n"
|
||||||
tmp_str,
|
"%s %"OFF_FMT"u\r\n",
|
||||||
|
date_str,
|
||||||
content_gzip ? "Transfer-length:" : "Content-length:",
|
content_gzip ? "Transfer-length:" : "Content-length:",
|
||||||
file_size
|
file_size
|
||||||
);
|
);
|
||||||
@ -1031,9 +1043,13 @@ static void send_headers(int responseNum)
|
|||||||
if (infoString) {
|
if (infoString) {
|
||||||
len += sprintf(iobuf + len,
|
len += sprintf(iobuf + len,
|
||||||
"<HTML><HEAD><TITLE>%d %s</TITLE></HEAD>\n"
|
"<HTML><HEAD><TITLE>%d %s</TITLE></HEAD>\n"
|
||||||
"<BODY><H1>%d %s</H1>\n%s\n</BODY></HTML>\n",
|
"<BODY><H1>%d %s</H1>\n"
|
||||||
|
"%s\n"
|
||||||
|
"</BODY></HTML>\n",
|
||||||
responseNum, responseString,
|
responseNum, responseString,
|
||||||
responseNum, responseString, infoString);
|
responseNum, responseString,
|
||||||
|
infoString
|
||||||
|
);
|
||||||
}
|
}
|
||||||
if (DEBUG) {
|
if (DEBUG) {
|
||||||
iobuf[len] = '\0';
|
iobuf[len] = '\0';
|
||||||
|
Loading…
x
Reference in New Issue
Block a user