#1217: libt/shttpd: "shttpd crash in decide_what_to_do()"
This commit is contained in:
parent
dcaf1f16ef
commit
56736ca883
|
@ -15,6 +15,7 @@
|
||||||
#define CONFIG_FILE "shttpd.conf" /* Configuration file */
|
#define CONFIG_FILE "shttpd.conf" /* Configuration file */
|
||||||
#define HTPASSWD ".htpasswd" /* Passwords file name */
|
#define HTPASSWD ".htpasswd" /* Passwords file name */
|
||||||
#define URI_MAX 16384 /* Default max request size */
|
#define URI_MAX 16384 /* Default max request size */
|
||||||
|
#define IO_BUFSIZE 65536 /* IO buffer size */
|
||||||
#define LISTENING_PORTS "80" /* Default listening ports */
|
#define LISTENING_PORTS "80" /* Default listening ports */
|
||||||
#define INDEX_FILES "index.html,index.htm,index.php,index.cgi"
|
#define INDEX_FILES "index.html,index.htm,index.php,index.cgi"
|
||||||
#define CGI_EXT "cgi,pl,php" /* Default CGI extensions */
|
#define CGI_EXT "cgi,pl,php" /* Default CGI extensions */
|
||||||
|
|
|
@ -16,8 +16,6 @@
|
||||||
void
|
void
|
||||||
_shttpd_elog(int flags, struct conn *c, const char *fmt, ...)
|
_shttpd_elog(int flags, struct conn *c, const char *fmt, ...)
|
||||||
{
|
{
|
||||||
char date[64], buf[URI_MAX];
|
|
||||||
int len;
|
|
||||||
FILE *fp = c == NULL ? NULL : c->ctx->error_log;
|
FILE *fp = c == NULL ? NULL : c->ctx->error_log;
|
||||||
va_list ap;
|
va_list ap;
|
||||||
|
|
||||||
|
@ -29,23 +27,29 @@ _shttpd_elog(int flags, struct conn *c, const char *fmt, ...)
|
||||||
va_end(ap);
|
va_end(ap);
|
||||||
}
|
}
|
||||||
|
|
||||||
strftime(date, sizeof(date), "%a %b %d %H:%M:%S %Y",
|
|
||||||
localtime(&_shttpd_current_time));
|
|
||||||
|
|
||||||
len = _shttpd_snprintf(buf, sizeof(buf),
|
|
||||||
"[%s] [error] [client %s] \"%s\" ",
|
|
||||||
date, c ? inet_ntoa(c->sa.u.sin.sin_addr) : "-",
|
|
||||||
c && c->request ? c->request : "-");
|
|
||||||
|
|
||||||
va_start(ap, fmt);
|
|
||||||
(void) vsnprintf(buf + len, sizeof(buf) - len, fmt, ap);
|
|
||||||
va_end(ap);
|
|
||||||
|
|
||||||
buf[sizeof(buf) - 1] = '\0';
|
|
||||||
|
|
||||||
if (fp != NULL && (flags & (E_FATAL | E_LOG))) {
|
if (fp != NULL && (flags & (E_FATAL | E_LOG))) {
|
||||||
|
char date[64];
|
||||||
|
char *buf = malloc( URI_MAX );
|
||||||
|
int len;
|
||||||
|
|
||||||
|
strftime(date, sizeof(date), "%a %b %d %H:%M:%S %Y",
|
||||||
|
localtime(&_shttpd_current_time));
|
||||||
|
|
||||||
|
len = _shttpd_snprintf(buf, URI_MAX,
|
||||||
|
"[%s] [error] [client %s] \"%s\" ",
|
||||||
|
date, c ? inet_ntoa(c->sa.u.sin.sin_addr) : "-",
|
||||||
|
c && c->request ? c->request : "-");
|
||||||
|
|
||||||
|
va_start(ap, fmt);
|
||||||
|
(void) vsnprintf(buf + len, URI_MAX - len, fmt, ap);
|
||||||
|
va_end(ap);
|
||||||
|
|
||||||
|
buf[URI_MAX - 1] = '\0';
|
||||||
|
|
||||||
(void) fprintf(fp, "%s\n", buf);
|
(void) fprintf(fp, "%s\n", buf);
|
||||||
(void) fflush(fp);
|
(void) fflush(fp);
|
||||||
|
|
||||||
|
free(buf);
|
||||||
}
|
}
|
||||||
|
|
||||||
if (flags & E_FATAL)
|
if (flags & E_FATAL)
|
||||||
|
@ -57,10 +61,18 @@ _shttpd_log_access(FILE *fp, const struct conn *c)
|
||||||
{
|
{
|
||||||
static const struct vec dash = {"-", 1};
|
static const struct vec dash = {"-", 1};
|
||||||
|
|
||||||
const struct vec *user = &c->ch.user.v_vec;
|
const struct vec *user;
|
||||||
const struct vec *referer = &c->ch.referer.v_vec;
|
const struct vec *referer;
|
||||||
const struct vec *user_agent = &c->ch.useragent.v_vec;
|
const struct vec *user_agent;
|
||||||
char date[64], buf[URI_MAX], *q1 = "\"", *q2 = "\"";
|
char date[64], *buf, *q1, *q2;
|
||||||
|
|
||||||
|
if (fp == NULL)
|
||||||
|
return;
|
||||||
|
|
||||||
|
user = &c->ch.user.v_vec;
|
||||||
|
referer = &c->ch.referer.v_vec;
|
||||||
|
user_agent = &c->ch.useragent.v_vec;
|
||||||
|
q1 = q2 = "\"";
|
||||||
|
|
||||||
if (user->len == 0)
|
if (user->len == 0)
|
||||||
user = ‐
|
user = ‐
|
||||||
|
@ -78,7 +90,9 @@ _shttpd_log_access(FILE *fp, const struct conn *c)
|
||||||
(void) strftime(date, sizeof(date), "%d/%b/%Y:%H:%M:%S",
|
(void) strftime(date, sizeof(date), "%d/%b/%Y:%H:%M:%S",
|
||||||
localtime(&c->birth_time));
|
localtime(&c->birth_time));
|
||||||
|
|
||||||
(void) _shttpd_snprintf(buf, sizeof(buf),
|
buf = malloc(URI_MAX);
|
||||||
|
|
||||||
|
(void) _shttpd_snprintf(buf, URI_MAX,
|
||||||
"%s - %.*s [%s %+05d] \"%s\" %d %lu %s%.*s%s %s%.*s%s",
|
"%s - %.*s [%s %+05d] \"%s\" %d %lu %s%.*s%s %s%.*s%s",
|
||||||
inet_ntoa(c->sa.u.sin.sin_addr), user->len, user->ptr,
|
inet_ntoa(c->sa.u.sin.sin_addr), user->len, user->ptr,
|
||||||
date, _shttpd_tz_offset, c->request ? c->request : "-",
|
date, _shttpd_tz_offset, c->request ? c->request : "-",
|
||||||
|
@ -86,8 +100,8 @@ _shttpd_log_access(FILE *fp, const struct conn *c)
|
||||||
q1, referer->len, referer->ptr, q1,
|
q1, referer->len, referer->ptr, q1,
|
||||||
q2, user_agent->len, user_agent->ptr, q2);
|
q2, user_agent->len, user_agent->ptr, q2);
|
||||||
|
|
||||||
if (fp != NULL) {
|
(void) fprintf(fp, "%s\n", buf);
|
||||||
(void) fprintf(fp, "%s\n", buf);
|
(void) fflush(fp);
|
||||||
(void) fflush(fp);
|
|
||||||
}
|
free(buf);
|
||||||
}
|
}
|
||||||
|
|
|
@ -533,7 +533,8 @@ get_path_info(struct conn *c, char *path, struct stat *stp)
|
||||||
static void
|
static void
|
||||||
decide_what_to_do(struct conn *c)
|
decide_what_to_do(struct conn *c)
|
||||||
{
|
{
|
||||||
char path[URI_MAX], buf[1024], *root;
|
char *path;
|
||||||
|
const char *root;
|
||||||
struct vec alias_uri, alias_path;
|
struct vec alias_uri, alias_path;
|
||||||
struct stat st;
|
struct stat st;
|
||||||
int rc;
|
int rc;
|
||||||
|
@ -548,16 +549,17 @@ decide_what_to_do(struct conn *c)
|
||||||
remove_double_dots(c->uri);
|
remove_double_dots(c->uri);
|
||||||
|
|
||||||
root = c->ctx->options[OPT_ROOT];
|
root = c->ctx->options[OPT_ROOT];
|
||||||
if (strlen(c->uri) + strlen(root) >= sizeof(path)) {
|
if (strlen(c->uri) + strlen(root) >= URI_MAX) {
|
||||||
_shttpd_send_server_error(c, 400, "URI is too long");
|
_shttpd_send_server_error(c, 400, "URI is too long");
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
(void) _shttpd_snprintf(path, sizeof(path), "%s%s", root, c->uri);
|
path = malloc( URI_MAX );
|
||||||
|
(void) _shttpd_snprintf(path, URI_MAX, "%s%s", root, c->uri);
|
||||||
|
|
||||||
/* User may use the aliases - check URI for mount point */
|
/* User may use the aliases - check URI for mount point */
|
||||||
if (is_alias(c->ctx, c->uri, &alias_uri, &alias_path) != NULL) {
|
if (is_alias(c->ctx, c->uri, &alias_uri, &alias_path) != NULL) {
|
||||||
(void) _shttpd_snprintf(path, sizeof(path), "%.*s%s",
|
(void) _shttpd_snprintf(path, URI_MAX, "%.*s%s",
|
||||||
alias_path.len, alias_path.ptr, c->uri + alias_uri.len);
|
alias_path.len, alias_path.ptr, c->uri + alias_uri.len);
|
||||||
DBG(("using alias %.*s -> %.*s", alias_uri.len, alias_uri.ptr,
|
DBG(("using alias %.*s -> %.*s", alias_uri.len, alias_uri.ptr,
|
||||||
alias_path.len, alias_path.ptr));
|
alias_path.len, alias_path.ptr));
|
||||||
|
@ -612,11 +614,12 @@ decide_what_to_do(struct conn *c)
|
||||||
} else if (get_path_info(c, path, &st) != 0) {
|
} else if (get_path_info(c, path, &st) != 0) {
|
||||||
_shttpd_send_server_error(c, 404, "Not Found");
|
_shttpd_send_server_error(c, 404, "Not Found");
|
||||||
} else if (S_ISDIR(st.st_mode) && path[strlen(path) - 1] != '/') {
|
} else if (S_ISDIR(st.st_mode) && path[strlen(path) - 1] != '/') {
|
||||||
|
char buf[1024];
|
||||||
(void) _shttpd_snprintf(buf, sizeof(buf),
|
(void) _shttpd_snprintf(buf, sizeof(buf),
|
||||||
"Moved Permanently\r\nLocation: %s/", c->uri);
|
"Moved Permanently\r\nLocation: %s/", c->uri);
|
||||||
_shttpd_send_server_error(c, 301, buf);
|
_shttpd_send_server_error(c, 301, buf);
|
||||||
} else if (S_ISDIR(st.st_mode) &&
|
} else if (S_ISDIR(st.st_mode) &&
|
||||||
find_index_file(c, path, sizeof(path) - 1, &st) == -1 &&
|
find_index_file(c, path, URI_MAX - 1, &st) == -1 &&
|
||||||
!IS_TRUE(c->ctx, OPT_DIR_LIST)) {
|
!IS_TRUE(c->ctx, OPT_DIR_LIST)) {
|
||||||
_shttpd_send_server_error(c, 403, "Directory Listing Denied");
|
_shttpd_send_server_error(c, 403, "Directory Listing Denied");
|
||||||
} else if (S_ISDIR(st.st_mode) && IS_TRUE(c->ctx, OPT_DIR_LIST)) {
|
} else if (S_ISDIR(st.st_mode) && IS_TRUE(c->ctx, OPT_DIR_LIST)) {
|
||||||
|
@ -655,6 +658,8 @@ decide_what_to_do(struct conn *c)
|
||||||
} else {
|
} else {
|
||||||
_shttpd_send_server_error(c, 500, "Internal Error");
|
_shttpd_send_server_error(c, 500, "Internal Error");
|
||||||
}
|
}
|
||||||
|
|
||||||
|
free(path);
|
||||||
}
|
}
|
||||||
|
|
||||||
static int
|
static int
|
||||||
|
@ -781,7 +786,7 @@ add_socket(struct worker *worker, int sock, int is_ssl)
|
||||||
(void) closesocket(sock);
|
(void) closesocket(sock);
|
||||||
SSL_free(ssl);
|
SSL_free(ssl);
|
||||||
#endif /* NO_SSL */
|
#endif /* NO_SSL */
|
||||||
} else if ((c = calloc(1, sizeof(*c) + 2 * URI_MAX)) == NULL) {
|
} else if ((c = calloc(1, sizeof(*c) + 2 * IO_BUFSIZE)) == NULL) {
|
||||||
#if !defined(NO_SSL)
|
#if !defined(NO_SSL)
|
||||||
if (ssl)
|
if (ssl)
|
||||||
SSL_free(ssl);
|
SSL_free(ssl);
|
||||||
|
@ -808,8 +813,8 @@ add_socket(struct worker *worker, int sock, int is_ssl)
|
||||||
|
|
||||||
/* Set IO buffers */
|
/* Set IO buffers */
|
||||||
c->loc.io.buf = (char *) (c + 1);
|
c->loc.io.buf = (char *) (c + 1);
|
||||||
c->rem.io.buf = c->loc.io.buf + URI_MAX;
|
c->rem.io.buf = c->loc.io.buf + IO_BUFSIZE;
|
||||||
c->loc.io.size = c->rem.io.size = URI_MAX;
|
c->loc.io.size = c->rem.io.size = IO_BUFSIZE;
|
||||||
|
|
||||||
#if !defined(NO_SSL)
|
#if !defined(NO_SSL)
|
||||||
if (is_ssl) {
|
if (is_ssl) {
|
||||||
|
|
Loading…
Reference in New Issue