|
@@ -891,6 +891,115 @@ static void mg_fclose(struct file *filep)
|
|
|
}
|
|
|
}
|
|
|
|
|
|
+static void mg_strlcpy(register char *dst, register const char *src, size_t n)
|
|
|
+{
|
|
|
+ for (; *src != '\0' && n > 1; n--) {
|
|
|
+ *dst++ = *src++;
|
|
|
+ }
|
|
|
+ *dst = '\0';
|
|
|
+}
|
|
|
+
|
|
|
+static int lowercase(const char *s)
|
|
|
+{
|
|
|
+ return tolower(* (const unsigned char *) s);
|
|
|
+}
|
|
|
+
|
|
|
+int mg_strncasecmp(const char *s1, const char *s2, size_t len)
|
|
|
+{
|
|
|
+ int diff = 0;
|
|
|
+
|
|
|
+ if (len > 0)
|
|
|
+ do {
|
|
|
+ diff = lowercase(s1++) - lowercase(s2++);
|
|
|
+ } while (diff == 0 && s1[-1] != '\0' && --len > 0);
|
|
|
+
|
|
|
+ return diff;
|
|
|
+}
|
|
|
+
|
|
|
+static int mg_strcasecmp(const char *s1, const char *s2)
|
|
|
+{
|
|
|
+ int diff;
|
|
|
+
|
|
|
+ do {
|
|
|
+ diff = lowercase(s1++) - lowercase(s2++);
|
|
|
+ } while (diff == 0 && s1[-1] != '\0');
|
|
|
+
|
|
|
+ return diff;
|
|
|
+}
|
|
|
+
|
|
|
+static char * mg_strndup(const char *ptr, size_t len)
|
|
|
+{
|
|
|
+ char *p;
|
|
|
+
|
|
|
+ if ((p = (char *) mg_malloc(len + 1)) != NULL) {
|
|
|
+ mg_strlcpy(p, ptr, len + 1);
|
|
|
+ }
|
|
|
+
|
|
|
+ return p;
|
|
|
+}
|
|
|
+
|
|
|
+static char * mg_strdup(const char *str)
|
|
|
+{
|
|
|
+ return mg_strndup(str, strlen(str));
|
|
|
+}
|
|
|
+
|
|
|
+static const char *mg_strcasestr(const char *big_str, const char *small_str)
|
|
|
+{
|
|
|
+ int i, big_len = (int)strlen(big_str), small_len = (int)strlen(small_str);
|
|
|
+
|
|
|
+ for (i = 0; i <= big_len - small_len; i++) {
|
|
|
+ if (mg_strncasecmp(big_str + i, small_str, small_len) == 0) {
|
|
|
+ return big_str + i;
|
|
|
+ }
|
|
|
+ }
|
|
|
+
|
|
|
+ return NULL;
|
|
|
+}
|
|
|
+
|
|
|
+/* Like snprintf(), but never returns negative value, or a value
|
|
|
+ that is larger than a supplied buffer.
|
|
|
+ Thanks to Adam Zeldis to pointing snprintf()-caused vulnerability
|
|
|
+ in his audit report. */
|
|
|
+static int mg_vsnprintf(struct mg_connection *conn, char *buf, size_t buflen,
|
|
|
+ const char *fmt, va_list ap)
|
|
|
+{
|
|
|
+ int n;
|
|
|
+
|
|
|
+ if (buflen == 0)
|
|
|
+ return 0;
|
|
|
+
|
|
|
+ n = vsnprintf(buf, buflen, fmt, ap);
|
|
|
+
|
|
|
+ if (n < 0) {
|
|
|
+ mg_cry(conn, "vsnprintf error");
|
|
|
+ n = 0;
|
|
|
+ } else if (n >= (int) buflen) {
|
|
|
+ mg_cry(conn, "truncating vsnprintf buffer: [%.*s]",
|
|
|
+ n > 200 ? 200 : n, buf);
|
|
|
+ n = (int) buflen - 1;
|
|
|
+ }
|
|
|
+ buf[n] = '\0';
|
|
|
+
|
|
|
+ return n;
|
|
|
+}
|
|
|
+
|
|
|
+static int mg_snprintf(struct mg_connection *conn, char *buf, size_t buflen,
|
|
|
+ PRINTF_FORMAT_STRING(const char *fmt), ...)
|
|
|
+PRINTF_ARGS(4, 5);
|
|
|
+
|
|
|
+static int mg_snprintf(struct mg_connection *conn, char *buf, size_t buflen,
|
|
|
+ const char *fmt, ...)
|
|
|
+{
|
|
|
+ va_list ap;
|
|
|
+ int n;
|
|
|
+
|
|
|
+ va_start(ap, fmt);
|
|
|
+ n = mg_vsnprintf(conn, buf, buflen, fmt, ap);
|
|
|
+ va_end(ap);
|
|
|
+
|
|
|
+ return n;
|
|
|
+}
|
|
|
+
|
|
|
static int get_option_index(const char *name)
|
|
|
{
|
|
|
int i;
|
|
@@ -936,7 +1045,7 @@ static void sockaddr_to_string(char *buf, size_t len,
|
|
|
(void *) &usa->sin6.sin6_addr, buf, len);
|
|
|
#elif defined(_WIN32)
|
|
|
/* Only Windows Vista (and newer) have inet_ntop() */
|
|
|
- strncpy(buf, inet_ntoa(usa->sin.sin_addr), len);
|
|
|
+ mg_strlcpy(buf, inet_ntoa(usa->sin.sin_addr), len);
|
|
|
#else
|
|
|
inet_ntop(usa->sa.sa_family, (void *) &usa->sin.sin_addr, buf, len);
|
|
|
#endif
|
|
@@ -951,7 +1060,7 @@ static void gmt_time_string(char *buf, size_t buf_len, time_t *t)
|
|
|
if (tm != NULL) {
|
|
|
strftime(buf, buf_len, "%a, %d %b %Y %H:%M:%S GMT", tm);
|
|
|
} else {
|
|
|
- strncpy(buf, "Thu, 01 Jan 1970 00:00:00 GMT", buf_len);
|
|
|
+ mg_strlcpy(buf, "Thu, 01 Jan 1970 00:00:00 GMT", buf_len);
|
|
|
buf[buf_len - 1] = '\0';
|
|
|
}
|
|
|
}
|
|
@@ -1016,115 +1125,6 @@ struct mg_request_info *mg_get_request_info(struct mg_connection *conn)
|
|
|
return &conn->request_info;
|
|
|
}
|
|
|
|
|
|
-static void mg_strlcpy(register char *dst, register const char *src, size_t n)
|
|
|
-{
|
|
|
- for (; *src != '\0' && n > 1; n--) {
|
|
|
- *dst++ = *src++;
|
|
|
- }
|
|
|
- *dst = '\0';
|
|
|
-}
|
|
|
-
|
|
|
-static int lowercase(const char *s)
|
|
|
-{
|
|
|
- return tolower(* (const unsigned char *) s);
|
|
|
-}
|
|
|
-
|
|
|
-int mg_strncasecmp(const char *s1, const char *s2, size_t len)
|
|
|
-{
|
|
|
- int diff = 0;
|
|
|
-
|
|
|
- if (len > 0)
|
|
|
- do {
|
|
|
- diff = lowercase(s1++) - lowercase(s2++);
|
|
|
- } while (diff == 0 && s1[-1] != '\0' && --len > 0);
|
|
|
-
|
|
|
- return diff;
|
|
|
-}
|
|
|
-
|
|
|
-static int mg_strcasecmp(const char *s1, const char *s2)
|
|
|
-{
|
|
|
- int diff;
|
|
|
-
|
|
|
- do {
|
|
|
- diff = lowercase(s1++) - lowercase(s2++);
|
|
|
- } while (diff == 0 && s1[-1] != '\0');
|
|
|
-
|
|
|
- return diff;
|
|
|
-}
|
|
|
-
|
|
|
-static char * mg_strndup(const char *ptr, size_t len)
|
|
|
-{
|
|
|
- char *p;
|
|
|
-
|
|
|
- if ((p = (char *) mg_malloc(len + 1)) != NULL) {
|
|
|
- mg_strlcpy(p, ptr, len + 1);
|
|
|
- }
|
|
|
-
|
|
|
- return p;
|
|
|
-}
|
|
|
-
|
|
|
-static char * mg_strdup(const char *str)
|
|
|
-{
|
|
|
- return mg_strndup(str, strlen(str));
|
|
|
-}
|
|
|
-
|
|
|
-static const char *mg_strcasestr(const char *big_str, const char *small_str)
|
|
|
-{
|
|
|
- int i, big_len = (int)strlen(big_str), small_len = (int)strlen(small_str);
|
|
|
-
|
|
|
- for (i = 0; i <= big_len - small_len; i++) {
|
|
|
- if (mg_strncasecmp(big_str + i, small_str, small_len) == 0) {
|
|
|
- return big_str + i;
|
|
|
- }
|
|
|
- }
|
|
|
-
|
|
|
- return NULL;
|
|
|
-}
|
|
|
-
|
|
|
-/* Like snprintf(), but never returns negative value, or a value
|
|
|
- that is larger than a supplied buffer.
|
|
|
- Thanks to Adam Zeldis to pointing snprintf()-caused vulnerability
|
|
|
- in his audit report. */
|
|
|
-static int mg_vsnprintf(struct mg_connection *conn, char *buf, size_t buflen,
|
|
|
- const char *fmt, va_list ap)
|
|
|
-{
|
|
|
- int n;
|
|
|
-
|
|
|
- if (buflen == 0)
|
|
|
- return 0;
|
|
|
-
|
|
|
- n = vsnprintf(buf, buflen, fmt, ap);
|
|
|
-
|
|
|
- if (n < 0) {
|
|
|
- mg_cry(conn, "vsnprintf error");
|
|
|
- n = 0;
|
|
|
- } else if (n >= (int) buflen) {
|
|
|
- mg_cry(conn, "truncating vsnprintf buffer: [%.*s]",
|
|
|
- n > 200 ? 200 : n, buf);
|
|
|
- n = (int) buflen - 1;
|
|
|
- }
|
|
|
- buf[n] = '\0';
|
|
|
-
|
|
|
- return n;
|
|
|
-}
|
|
|
-
|
|
|
-static int mg_snprintf(struct mg_connection *conn, char *buf, size_t buflen,
|
|
|
- PRINTF_FORMAT_STRING(const char *fmt), ...)
|
|
|
-PRINTF_ARGS(4, 5);
|
|
|
-
|
|
|
-static int mg_snprintf(struct mg_connection *conn, char *buf, size_t buflen,
|
|
|
- const char *fmt, ...)
|
|
|
-{
|
|
|
- va_list ap;
|
|
|
- int n;
|
|
|
-
|
|
|
- va_start(ap, fmt);
|
|
|
- n = mg_vsnprintf(conn, buf, buflen, fmt, ap);
|
|
|
- va_end(ap);
|
|
|
-
|
|
|
- return n;
|
|
|
-}
|
|
|
-
|
|
|
/* Skip the characters until one of the delimiters characters found.
|
|
|
0-terminate resulting word. Skip the delimiter and following whitespaces.
|
|
|
Advance pointer to buffer to the next word. Return found 0-terminated word.
|
|
@@ -3006,7 +3006,7 @@ static int parse_auth_header(struct mg_connection *conn, char *buf,
|
|
|
/* Convert the nonce from the client to a number and check it. */
|
|
|
/* Server side nonce check is valuable in all situations but one: if the server restarts frequently,
|
|
|
but the client should not see that, so the server should accept nonces from previous starts. */
|
|
|
- íf (ah->nonce == NULL) {
|
|
|
+ if (ah->nonce == NULL) {
|
|
|
return 0;
|
|
|
}
|
|
|
nonce = strtoul(ah->nonce, &s, 10);
|
|
@@ -3311,7 +3311,7 @@ static void print_dir_entry(struct de *de)
|
|
|
if (tm != NULL) {
|
|
|
strftime(mod, sizeof(mod), "%d-%b-%Y %H:%M", tm);
|
|
|
} else {
|
|
|
- strncpy(mod, "01-Jan-1970 00:00", sizeof(mod));
|
|
|
+ mg_strlcpy(mod, "01-Jan-1970 00:00", sizeof(mod));
|
|
|
mod[sizeof(mod) - 1] = '\0';
|
|
|
}
|
|
|
mg_url_encode(de->file_name, href, sizeof(href));
|
|
@@ -5338,7 +5338,7 @@ static void redirect_to_https_port(struct mg_connection *conn, int ssl_index)
|
|
|
if (host_header != NULL) {
|
|
|
char *pos;
|
|
|
|
|
|
- strncpy(host, host_header, hostlen);
|
|
|
+ mg_strlcpy(host, host_header, hostlen);
|
|
|
host[hostlen - 1] = '\0';
|
|
|
pos = strchr(host, ':');
|
|
|
if (pos != NULL) {
|
|
@@ -5747,7 +5747,7 @@ static void log_access(const struct mg_connection *conn)
|
|
|
if (tm != NULL) {
|
|
|
strftime(date, sizeof(date), "%d/%b/%Y:%H:%M:%S %z", tm);
|
|
|
} else {
|
|
|
- strncpy(date, "01/Jan/1970:00:00:00 +0000", sizeof(date));
|
|
|
+ mg_strlcpy(date, "01/Jan/1970:00:00:00 +0000", sizeof(date));
|
|
|
date[sizeof(date) - 1] = '\0';
|
|
|
}
|
|
|
|