Add optional digest auth to mOS HTTP server

If http.auth_{domain,file} are configured, all HTTP requests require valid digest authorization header.
This applies to files served by mg_http_serve as well as synamic endpoints such as /update and /rpc.

mongoose-os#229

PUBLISHED_FROM=824d594147cfeb2428b463d24478b207839aa5e2
This commit is contained in:
Deomid Ryabkov 2017-04-11 11:32:19 +01:00 committed by Cesanta Bot
parent 8ce34af9f3
commit 7f259f2a79
2 changed files with 430 additions and 373 deletions

View File

@ -777,7 +777,7 @@ double cs_time(void) {
#endif /* CS_COMMON_CS_ENDIAN_H_ */
#ifdef MG_MODULE_LINES
#line 1 "common/md5.c"
#line 1 "common/cs_md5.c"
#endif
/*
* This code implements the MD5 message-digest algorithm.
@ -796,7 +796,7 @@ double cs_time(void) {
* will fill a supplied 16-byte array with the digest.
*/
/* Amalgamated: #include "common/md5.h" */
/* Amalgamated: #include "common/cs_md5.h" */
/* Amalgamated: #include "common/str_util.h" */
#if !defined(EXCLUDE_COMMON)
@ -831,7 +831,7 @@ static void byteReverse(unsigned char *buf, unsigned longs) {
* Start MD5 accumulation. Set bit count to 0 and buffer to mysterious
* initialization constants.
*/
void MD5_Init(MD5_CTX *ctx) {
void cs_md5_init(cs_md5_ctx *ctx) {
ctx->buf[0] = 0x67452301;
ctx->buf[1] = 0xefcdab89;
ctx->buf[2] = 0x98badcfe;
@ -841,7 +841,7 @@ void MD5_Init(MD5_CTX *ctx) {
ctx->bits[1] = 0;
}
static void MD5Transform(uint32_t buf[4], uint32_t const in[16]) {
static void cs_md5_transform(uint32_t buf[4], uint32_t const in[16]) {
register uint32_t a, b, c, d;
a = buf[0];
@ -923,7 +923,7 @@ static void MD5Transform(uint32_t buf[4], uint32_t const in[16]) {
buf[3] += d;
}
void MD5_Update(MD5_CTX *ctx, const unsigned char *buf, size_t len) {
void cs_md5_update(cs_md5_ctx *ctx, const unsigned char *buf, size_t len) {
uint32_t t;
t = ctx->bits[0];
@ -942,7 +942,7 @@ void MD5_Update(MD5_CTX *ctx, const unsigned char *buf, size_t len) {
}
memcpy(p, buf, t);
byteReverse(ctx->in, 16);
MD5Transform(ctx->buf, (uint32_t *) ctx->in);
cs_md5_transform(ctx->buf, (uint32_t *) ctx->in);
buf += t;
len -= t;
}
@ -950,7 +950,7 @@ void MD5_Update(MD5_CTX *ctx, const unsigned char *buf, size_t len) {
while (len >= 64) {
memcpy(ctx->in, buf, 64);
byteReverse(ctx->in, 16);
MD5Transform(ctx->buf, (uint32_t *) ctx->in);
cs_md5_transform(ctx->buf, (uint32_t *) ctx->in);
buf += 64;
len -= 64;
}
@ -958,7 +958,7 @@ void MD5_Update(MD5_CTX *ctx, const unsigned char *buf, size_t len) {
memcpy(ctx->in, buf, len);
}
void MD5_Final(unsigned char digest[16], MD5_CTX *ctx) {
void cs_md5_final(unsigned char digest[16], cs_md5_ctx *ctx) {
unsigned count;
unsigned char *p;
uint32_t *a;
@ -971,7 +971,7 @@ void MD5_Final(unsigned char digest[16], MD5_CTX *ctx) {
if (count < 8) {
memset(p, 0, count);
byteReverse(ctx->in, 16);
MD5Transform(ctx->buf, (uint32_t *) ctx->in);
cs_md5_transform(ctx->buf, (uint32_t *) ctx->in);
memset(ctx->in, 0, 56);
} else {
memset(p, 0, count - 8);
@ -982,234 +982,21 @@ void MD5_Final(unsigned char digest[16], MD5_CTX *ctx) {
a[14] = ctx->bits[0];
a[15] = ctx->bits[1];
MD5Transform(ctx->buf, (uint32_t *) ctx->in);
cs_md5_transform(ctx->buf, (uint32_t *) ctx->in);
byteReverse((unsigned char *) ctx->buf, 4);
memcpy(digest, ctx->buf, 16);
memset((char *) ctx, 0, sizeof(*ctx));
}
char *cs_md5(char buf[33], ...) {
unsigned char hash[16];
const unsigned char *p;
va_list ap;
MD5_CTX ctx;
MD5_Init(&ctx);
va_start(ap, buf);
while ((p = va_arg(ap, const unsigned char *) ) != NULL) {
size_t len = va_arg(ap, size_t);
MD5_Update(&ctx, p, len);
}
va_end(ap);
MD5_Final(hash, &ctx);
cs_to_hex(buf, hash, sizeof(hash));
return buf;
}
#endif /* CS_DISABLE_MD5 */
#endif /* EXCLUDE_COMMON */
#ifdef MG_MODULE_LINES
#line 1 "common/mbuf.c"
#endif
/*
* Copyright (c) 2014 Cesanta Software Limited
* All rights reserved
*/
#ifndef EXCLUDE_COMMON
#include <assert.h>
#include <string.h>
/* Amalgamated: #include "common/mbuf.h" */
#ifndef MBUF_REALLOC
#define MBUF_REALLOC realloc
#endif
#ifndef MBUF_FREE
#define MBUF_FREE free
#endif
void mbuf_init(struct mbuf *mbuf, size_t initial_size) WEAK;
void mbuf_init(struct mbuf *mbuf, size_t initial_size) {
mbuf->len = mbuf->size = 0;
mbuf->buf = NULL;
mbuf_resize(mbuf, initial_size);
}
void mbuf_free(struct mbuf *mbuf) WEAK;
void mbuf_free(struct mbuf *mbuf) {
if (mbuf->buf != NULL) {
MBUF_FREE(mbuf->buf);
mbuf_init(mbuf, 0);
}
}
void mbuf_resize(struct mbuf *a, size_t new_size) WEAK;
void mbuf_resize(struct mbuf *a, size_t new_size) {
if (new_size > a->size || (new_size < a->size && new_size >= a->len)) {
char *buf = (char *) MBUF_REALLOC(a->buf, new_size);
/*
* In case realloc fails, there's not much we can do, except keep things as
* they are. Note that NULL is a valid return value from realloc when
* size == 0, but that is covered too.
*/
if (buf == NULL && new_size != 0) return;
a->buf = buf;
a->size = new_size;
}
}
void mbuf_trim(struct mbuf *mbuf) WEAK;
void mbuf_trim(struct mbuf *mbuf) {
mbuf_resize(mbuf, mbuf->len);
}
size_t mbuf_insert(struct mbuf *a, size_t off, const void *buf, size_t) WEAK;
size_t mbuf_insert(struct mbuf *a, size_t off, const void *buf, size_t len) {
char *p = NULL;
assert(a != NULL);
assert(a->len <= a->size);
assert(off <= a->len);
/* check overflow */
if (~(size_t) 0 - (size_t) a->buf < len) return 0;
if (a->len + len <= a->size) {
memmove(a->buf + off + len, a->buf + off, a->len - off);
if (buf != NULL) {
memcpy(a->buf + off, buf, len);
}
a->len += len;
} else {
size_t new_size = (size_t)((a->len + len) * MBUF_SIZE_MULTIPLIER);
if ((p = (char *) MBUF_REALLOC(a->buf, new_size)) != NULL) {
a->buf = p;
memmove(a->buf + off + len, a->buf + off, a->len - off);
if (buf != NULL) memcpy(a->buf + off, buf, len);
a->len += len;
a->size = new_size;
} else {
len = 0;
}
}
return len;
}
size_t mbuf_append(struct mbuf *a, const void *buf, size_t len) WEAK;
size_t mbuf_append(struct mbuf *a, const void *buf, size_t len) {
return mbuf_insert(a, a->len, buf, len);
}
void mbuf_remove(struct mbuf *mb, size_t n) WEAK;
void mbuf_remove(struct mbuf *mb, size_t n) {
if (n > 0 && n <= mb->len) {
memmove(mb->buf, mb->buf + n, mb->len - n);
mb->len -= n;
}
}
#endif /* EXCLUDE_COMMON */
#ifdef MG_MODULE_LINES
#line 1 "common/mg_str.c"
#endif
/*
* Copyright (c) 2014-2016 Cesanta Software Limited
* All rights reserved
*/
/* Amalgamated: #include "common/mg_mem.h" */
/* Amalgamated: #include "common/mg_str.h" */
#include <stdlib.h>
#include <string.h>
int mg_ncasecmp(const char *s1, const char *s2, size_t len) WEAK;
struct mg_str mg_mk_str(const char *s) WEAK;
struct mg_str mg_mk_str(const char *s) {
struct mg_str ret = {s, 0};
if (s != NULL) ret.len = strlen(s);
return ret;
}
struct mg_str mg_mk_str_n(const char *s, size_t len) WEAK;
struct mg_str mg_mk_str_n(const char *s, size_t len) {
struct mg_str ret = {s, len};
return ret;
}
int mg_vcmp(const struct mg_str *str1, const char *str2) WEAK;
int mg_vcmp(const struct mg_str *str1, const char *str2) {
size_t n2 = strlen(str2), n1 = str1->len;
int r = strncmp(str1->p, str2, (n1 < n2) ? n1 : n2);
if (r == 0) {
return n1 - n2;
}
return r;
}
int mg_vcasecmp(const struct mg_str *str1, const char *str2) WEAK;
int mg_vcasecmp(const struct mg_str *str1, const char *str2) {
size_t n2 = strlen(str2), n1 = str1->len;
int r = mg_ncasecmp(str1->p, str2, (n1 < n2) ? n1 : n2);
if (r == 0) {
return n1 - n2;
}
return r;
}
struct mg_str mg_strdup(const struct mg_str s) WEAK;
struct mg_str mg_strdup(const struct mg_str s) {
struct mg_str r = {NULL, 0};
if (s.len > 0 && s.p != NULL) {
r.p = (char *) MG_MALLOC(s.len);
if (r.p != NULL) {
memcpy((char *) r.p, s.p, s.len);
r.len = s.len;
}
}
return r;
}
int mg_strcmp(const struct mg_str str1, const struct mg_str str2) WEAK;
int mg_strcmp(const struct mg_str str1, const struct mg_str str2) {
size_t i = 0;
while (i < str1.len && i < str2.len) {
if (str1.p[i] < str2.p[i]) return -1;
if (str1.p[i] > str2.p[i]) return 1;
i++;
}
if (i < str1.len) return 1;
if (i < str2.len) return -1;
return 0;
}
int mg_strncmp(const struct mg_str, const struct mg_str, size_t n) WEAK;
int mg_strncmp(const struct mg_str str1, const struct mg_str str2, size_t n) {
struct mg_str s1 = str1;
struct mg_str s2 = str2;
if (s1.len > n) {
s1.len = n;
}
if (s2.len > n) {
s2.len = n;
}
return mg_strcmp(s1, s2);
}
#ifdef MG_MODULE_LINES
#line 1 "common/sha1.c"
#line 1 "common/cs_sha1.c"
#endif
/* Copyright(c) By Steve Reid <steve@edmweb.com> */
/* 100% Public Domain */
/* Amalgamated: #include "common/sha1.h" */
/* Amalgamated: #include "common/cs_sha1.h" */
#if !CS_DISABLE_SHA1 && !defined(EXCLUDE_COMMON)
@ -1460,6 +1247,198 @@ void cs_hmac_sha1(const unsigned char *key, size_t keylen,
#endif /* EXCLUDE_COMMON */
#ifdef MG_MODULE_LINES
#line 1 "common/mbuf.c"
#endif
/*
* Copyright (c) 2014 Cesanta Software Limited
* All rights reserved
*/
#ifndef EXCLUDE_COMMON
#include <assert.h>
#include <string.h>
/* Amalgamated: #include "common/mbuf.h" */
#ifndef MBUF_REALLOC
#define MBUF_REALLOC realloc
#endif
#ifndef MBUF_FREE
#define MBUF_FREE free
#endif
void mbuf_init(struct mbuf *mbuf, size_t initial_size) WEAK;
void mbuf_init(struct mbuf *mbuf, size_t initial_size) {
mbuf->len = mbuf->size = 0;
mbuf->buf = NULL;
mbuf_resize(mbuf, initial_size);
}
void mbuf_free(struct mbuf *mbuf) WEAK;
void mbuf_free(struct mbuf *mbuf) {
if (mbuf->buf != NULL) {
MBUF_FREE(mbuf->buf);
mbuf_init(mbuf, 0);
}
}
void mbuf_resize(struct mbuf *a, size_t new_size) WEAK;
void mbuf_resize(struct mbuf *a, size_t new_size) {
if (new_size > a->size || (new_size < a->size && new_size >= a->len)) {
char *buf = (char *) MBUF_REALLOC(a->buf, new_size);
/*
* In case realloc fails, there's not much we can do, except keep things as
* they are. Note that NULL is a valid return value from realloc when
* size == 0, but that is covered too.
*/
if (buf == NULL && new_size != 0) return;
a->buf = buf;
a->size = new_size;
}
}
void mbuf_trim(struct mbuf *mbuf) WEAK;
void mbuf_trim(struct mbuf *mbuf) {
mbuf_resize(mbuf, mbuf->len);
}
size_t mbuf_insert(struct mbuf *a, size_t off, const void *buf, size_t) WEAK;
size_t mbuf_insert(struct mbuf *a, size_t off, const void *buf, size_t len) {
char *p = NULL;
assert(a != NULL);
assert(a->len <= a->size);
assert(off <= a->len);
/* check overflow */
if (~(size_t) 0 - (size_t) a->buf < len) return 0;
if (a->len + len <= a->size) {
memmove(a->buf + off + len, a->buf + off, a->len - off);
if (buf != NULL) {
memcpy(a->buf + off, buf, len);
}
a->len += len;
} else {
size_t new_size = (size_t)((a->len + len) * MBUF_SIZE_MULTIPLIER);
if ((p = (char *) MBUF_REALLOC(a->buf, new_size)) != NULL) {
a->buf = p;
memmove(a->buf + off + len, a->buf + off, a->len - off);
if (buf != NULL) memcpy(a->buf + off, buf, len);
a->len += len;
a->size = new_size;
} else {
len = 0;
}
}
return len;
}
size_t mbuf_append(struct mbuf *a, const void *buf, size_t len) WEAK;
size_t mbuf_append(struct mbuf *a, const void *buf, size_t len) {
return mbuf_insert(a, a->len, buf, len);
}
void mbuf_remove(struct mbuf *mb, size_t n) WEAK;
void mbuf_remove(struct mbuf *mb, size_t n) {
if (n > 0 && n <= mb->len) {
memmove(mb->buf, mb->buf + n, mb->len - n);
mb->len -= n;
}
}
#endif /* EXCLUDE_COMMON */
#ifdef MG_MODULE_LINES
#line 1 "common/mg_str.c"
#endif
/*
* Copyright (c) 2014-2016 Cesanta Software Limited
* All rights reserved
*/
/* Amalgamated: #include "common/mg_mem.h" */
/* Amalgamated: #include "common/mg_str.h" */
#include <stdlib.h>
#include <string.h>
int mg_ncasecmp(const char *s1, const char *s2, size_t len) WEAK;
struct mg_str mg_mk_str(const char *s) WEAK;
struct mg_str mg_mk_str(const char *s) {
struct mg_str ret = {s, 0};
if (s != NULL) ret.len = strlen(s);
return ret;
}
struct mg_str mg_mk_str_n(const char *s, size_t len) WEAK;
struct mg_str mg_mk_str_n(const char *s, size_t len) {
struct mg_str ret = {s, len};
return ret;
}
int mg_vcmp(const struct mg_str *str1, const char *str2) WEAK;
int mg_vcmp(const struct mg_str *str1, const char *str2) {
size_t n2 = strlen(str2), n1 = str1->len;
int r = strncmp(str1->p, str2, (n1 < n2) ? n1 : n2);
if (r == 0) {
return n1 - n2;
}
return r;
}
int mg_vcasecmp(const struct mg_str *str1, const char *str2) WEAK;
int mg_vcasecmp(const struct mg_str *str1, const char *str2) {
size_t n2 = strlen(str2), n1 = str1->len;
int r = mg_ncasecmp(str1->p, str2, (n1 < n2) ? n1 : n2);
if (r == 0) {
return n1 - n2;
}
return r;
}
struct mg_str mg_strdup(const struct mg_str s) WEAK;
struct mg_str mg_strdup(const struct mg_str s) {
struct mg_str r = {NULL, 0};
if (s.len > 0 && s.p != NULL) {
r.p = (char *) MG_MALLOC(s.len);
if (r.p != NULL) {
memcpy((char *) r.p, s.p, s.len);
r.len = s.len;
}
}
return r;
}
int mg_strcmp(const struct mg_str str1, const struct mg_str str2) WEAK;
int mg_strcmp(const struct mg_str str1, const struct mg_str str2) {
size_t i = 0;
while (i < str1.len && i < str2.len) {
if (str1.p[i] < str2.p[i]) return -1;
if (str1.p[i] > str2.p[i]) return 1;
i++;
}
if (i < str1.len) return 1;
if (i < str2.len) return -1;
return 0;
}
int mg_strncmp(const struct mg_str, const struct mg_str, size_t n) WEAK;
int mg_strncmp(const struct mg_str str1, const struct mg_str str2, size_t n) {
struct mg_str s1 = str1;
struct mg_str s2 = str2;
if (s1.len > n) {
s1.len = n;
}
if (s2.len > n) {
s2.len = n;
}
return mg_strcmp(s1, s2);
}
#ifdef MG_MODULE_LINES
#line 1 "common/str_util.c"
#endif
/*
@ -5032,7 +5011,6 @@ int mg_normalize_uri_path(const struct mg_str *in, struct mg_str *out) {
#if MG_ENABLE_HTTP
/* Amalgamated: #include "common/md5.h" */
/* Amalgamated: #include "common/sha1.h" */
/* Amalgamated: #include "mongoose/src/internal.h" */
/* Amalgamated: #include "mongoose/src/util.h" */
@ -5060,8 +5038,10 @@ struct mg_http_proto_data_chuncked {
struct mg_http_endpoint {
struct mg_http_endpoint *next;
const char *name;
size_t name_len;
struct mg_str uri_pattern; /* owned */
char *auth_domain; /* owned */
char *auth_file; /* owned */
mg_event_handler_t handler;
#if MG_ENABLE_CALLBACK_USERDATA
void *user_data;
@ -5151,7 +5131,9 @@ static void mg_http_free_proto_data_endpoints(struct mg_http_endpoint **ep) {
while (current != NULL) {
struct mg_http_endpoint *tmp = current->next;
MG_FREE((void *) current->name);
MG_FREE((void *) current->uri_pattern.p);
MG_FREE((void *) current->auth_domain);
MG_FREE((void *) current->auth_file);
MG_FREE(current);
current = tmp;
}
@ -5583,8 +5565,7 @@ struct mg_http_endpoint *mg_http_get_endpoint_handler(struct mg_connection *nc,
ep = pd->endpoints;
while (ep != NULL) {
const struct mg_str name_s = {ep->name, ep->name_len};
if ((matched = mg_match_prefix_n(name_s, *uri_path)) != -1) {
if ((matched = mg_match_prefix_n(ep->uri_pattern, *uri_path)) != -1) {
if (matched > matched_max) {
/* Looking for the longest suitable handler */
ret = ep;
@ -5598,25 +5579,6 @@ struct mg_http_endpoint *mg_http_get_endpoint_handler(struct mg_connection *nc,
return ret;
}
static void mg_http_call_endpoint_handler(struct mg_connection *nc, int ev,
struct http_message *hm) {
struct mg_http_proto_data *pd = mg_http_get_proto_data(nc);
void *user_data = nc->user_data;
if (ev == MG_EV_HTTP_REQUEST) {
struct mg_http_endpoint *ep =
mg_http_get_endpoint_handler(nc->listener, &hm->uri);
if (ep != NULL) {
pd->endpoint_handler = ep->handler;
#if MG_ENABLE_CALLBACK_USERDATA
user_data = ep->user_data;
#endif
}
}
mg_call(nc, pd->endpoint_handler ? pd->endpoint_handler : nc->handler,
user_data, ev, hm);
}
#if MG_ENABLE_HTTP_STREAMING_MULTIPART
static void mg_http_multipart_continue(struct mg_connection *nc);
@ -5625,6 +5587,9 @@ static void mg_http_multipart_begin(struct mg_connection *nc,
#endif
static void mg_http_call_endpoint_handler(struct mg_connection *nc, int ev,
struct http_message *hm);
/*
* lx106 compiler has a bug (TODO(mkm) report and insert tracking bug here)
* If a big structure is declared in a big function, lx106 gcc will make it
@ -6691,6 +6656,42 @@ static int mg_is_file_hidden(const char *path,
}
#if !MG_DISABLE_HTTP_DIGEST_AUTH
#ifndef MG_EXT_MD5
void mg_hash_md5_v(size_t num_msgs, const uint8_t *msgs[],
const size_t *msg_lens, uint8_t *digest) {
size_t i;
cs_md5_ctx md5_ctx;
cs_md5_init(&md5_ctx);
for (i = 0; i < num_msgs; i++) {
cs_md5_update(&md5_ctx, msgs[i], msg_lens[i]);
}
cs_md5_final(digest, &md5_ctx);
}
#else
extern void mg_hash_md5_v(size_t num_msgs, const uint8_t *msgs[],
const size_t *msg_lens, uint8_t *digest);
#endif
void cs_md5(char buf[33], ...) {
unsigned char hash[16];
const uint8_t *msgs[20], *p;
size_t msg_lens[20];
size_t num_msgs = 0;
va_list ap;
va_start(ap, buf);
while ((p = va_arg(ap, const unsigned char *) ) != NULL) {
msgs[num_msgs] = p;
msg_lens[num_msgs] = va_arg(ap, size_t);
num_msgs++;
}
va_end(ap);
mg_hash_md5_v(num_msgs, msgs, msg_lens, hash);
cs_to_hex(buf, hash, sizeof(hash));
}
static void mg_mkmd5resp(const char *method, size_t method_len, const char *uri,
size_t uri_len, const char *ha1, size_t ha1_len,
const char *nonce, size_t nonce_len, const char *nc,
@ -6699,7 +6700,6 @@ static void mg_mkmd5resp(const char *method, size_t method_len, const char *uri,
static const char colon[] = ":";
static const size_t one = 1;
char ha2[33];
cs_md5(ha2, method, method_len, colon, one, uri, uri_len, NULL);
cs_md5(resp, ha1, ha1_len, colon, one, nonce, nonce_len, colon, one, nc,
nc_len, colon, one, cnonce, cnonce_len, colon, one, qop, qop_len,
@ -6744,7 +6744,7 @@ int mg_http_check_digest_auth(struct http_message *hm, const char *auth_domain,
FILE *fp) {
struct mg_str *hdr;
char buf[128], f_user[sizeof(buf)], f_ha1[sizeof(buf)], f_domain[sizeof(buf)];
char user[50], cnonce[33], response[40], uri[200], qop[20], nc[20], nonce[30];
char user[50], cnonce[64], response[40], uri[200], qop[20], nc[20], nonce[30];
char expected_response[33];
/* Parse "Authorization:" header, fail fast on parse error */
@ -6777,6 +6777,8 @@ int mg_http_check_digest_auth(struct http_message *hm, const char *auth_domain,
hm->uri.len + (hm->query_string.len ? hm->query_string.len + 1 : 0),
f_ha1, strlen(f_ha1), nonce, strlen(nonce), nc, strlen(nc), cnonce,
strlen(cnonce), qop, strlen(qop), expected_response);
LOG(LL_DEBUG,
("%s %s %s %s", user, f_domain, response, expected_response));
return mg_casecmp(response, expected_response) == 0;
}
}
@ -6785,10 +6787,10 @@ int mg_http_check_digest_auth(struct http_message *hm, const char *auth_domain,
return 0;
}
static int mg_is_authorized(struct http_message *hm, const char *path,
int is_directory, const char *domain,
const char *passwords_file,
int is_global_pass_file) {
static int mg_http_is_authorized(struct http_message *hm, struct mg_str path,
int is_directory, const char *domain,
const char *passwords_file,
int is_global_pass_file) {
char buf[MG_MAX_PATH];
const char *p;
FILE *fp;
@ -6798,12 +6800,13 @@ static int mg_is_authorized(struct http_message *hm, const char *path,
if (is_global_pass_file) {
fp = mg_fopen(passwords_file, "r");
} else if (is_directory) {
snprintf(buf, sizeof(buf), "%s%c%s", path, DIRSEP, passwords_file);
snprintf(buf, sizeof(buf), "%.*s%c%s", (int) path.len, path.p, DIRSEP,
passwords_file);
fp = mg_fopen(buf, "r");
} else {
p = strrchr(path, DIRSEP);
if (p == NULL) p = path;
snprintf(buf, sizeof(buf), "%.*s%c%s", (int) (p - path), path, DIRSEP,
p = strrchr(path.p, DIRSEP);
if (p == NULL) p = path.p;
snprintf(buf, sizeof(buf), "%.*s%c%s", (int) (p - path.p), path.p, DIRSEP,
passwords_file);
fp = mg_fopen(buf, "r");
}
@ -6814,15 +6817,16 @@ static int mg_is_authorized(struct http_message *hm, const char *path,
}
}
LOG(LL_DEBUG, ("%s '%s' %d %d", path, passwords_file ? passwords_file : "",
is_global_pass_file, authorized));
LOG(LL_DEBUG,
("%.*s %s %d %d", (int) path.len, path.p,
passwords_file ? passwords_file : "", is_global_pass_file, authorized));
return authorized;
}
#else
static int mg_is_authorized(struct http_message *hm, const char *path,
int is_directory, const char *domain,
const char *passwords_file,
int is_global_pass_file) {
static int mg_http_is_authorized(struct http_message *hm,
const struct mg_str path, int is_directory,
const char *domain, const char *passwords_file,
int is_global_pass_file) {
(void) hm;
(void) path;
(void) is_directory;
@ -7169,7 +7173,7 @@ static int mg_http_handle_forwarding(struct mg_connection *nc,
return 0;
}
#endif
#endif /* MG_ENABLE_FILESYSTEM */
MG_INTERNAL int mg_uri_to_local_path(struct http_message *hm,
const struct mg_serve_http_opts *opts,
@ -7453,10 +7457,12 @@ MG_INTERNAL void mg_send_http_file(struct mg_connection *nc, char *path,
if (is_dav && opts->dav_document_root == NULL) {
mg_http_send_error(nc, 501, NULL);
} else if (!mg_is_authorized(hm, path, is_directory, opts->auth_domain,
opts->global_auth_file, 1) ||
!mg_is_authorized(hm, path, is_directory, opts->auth_domain,
opts->per_directory_auth_file, 0)) {
} else if (!mg_http_is_authorized(hm, mg_mk_str(path), is_directory,
opts->auth_domain, opts->global_auth_file,
1) ||
!mg_http_is_authorized(hm, mg_mk_str(path), is_directory,
opts->auth_domain,
opts->per_directory_auth_file, 0)) {
mg_http_send_digest_auth_request(nc, opts->auth_domain);
} else if (is_cgi) {
#if MG_ENABLE_HTTP_CGI
@ -7472,11 +7478,11 @@ MG_INTERNAL void mg_send_http_file(struct mg_connection *nc, char *path,
} else if (!mg_vcmp(&hm->method, "PROPFIND")) {
mg_handle_propfind(nc, path, &st, hm, opts);
#if !MG_DISABLE_DAV_AUTH
} else if (is_dav &&
(opts->dav_auth_file == NULL ||
(strcmp(opts->dav_auth_file, "-") != 0 &&
!mg_is_authorized(hm, path, is_directory, opts->auth_domain,
opts->dav_auth_file, 1)))) {
} else if (is_dav && (opts->dav_auth_file == NULL ||
(strcmp(opts->dav_auth_file, "-") != 0 &&
!mg_http_is_authorized(hm, mg_mk_str(path),
is_directory, opts->auth_domain,
opts->dav_auth_file, 1)))) {
mg_http_send_digest_auth_request(nc, opts->auth_domain);
#endif
} else if (!mg_vcmp(&hm->method, "MKCOL")) {
@ -7910,9 +7916,10 @@ size_t mg_parse_multipart(const char *buf, size_t buf_len, char *var_name,
return 0;
}
void mg_register_http_endpoint(struct mg_connection *nc, const char *uri_path,
MG_CB(mg_event_handler_t handler,
void *user_data)) {
void mg_register_http_endpoint_opt(struct mg_connection *nc,
const char *uri_path,
mg_event_handler_t handler,
struct mg_http_endpoint_opts opts) {
struct mg_http_proto_data *pd = NULL;
struct mg_http_endpoint *new_ep = NULL;
@ -7921,16 +7928,57 @@ void mg_register_http_endpoint(struct mg_connection *nc, const char *uri_path,
if (new_ep == NULL) return;
pd = mg_http_get_proto_data(nc);
new_ep->name = strdup(uri_path);
new_ep->name_len = strlen(new_ep->name);
new_ep->uri_pattern = mg_strdup(mg_mk_str(uri_path));
if (opts.auth_domain != NULL && opts.auth_file != NULL) {
new_ep->auth_domain = strdup(opts.auth_domain);
new_ep->auth_file = strdup(opts.auth_file);
}
new_ep->handler = handler;
#if MG_ENABLE_CALLBACK_USERDATA
new_ep->user_data = user_data;
new_ep->user_data = opts.user_data;
#endif
new_ep->next = pd->endpoints;
pd->endpoints = new_ep;
}
static void mg_http_call_endpoint_handler(struct mg_connection *nc, int ev,
struct http_message *hm) {
struct mg_http_proto_data *pd = mg_http_get_proto_data(nc);
void *user_data = nc->user_data;
if (ev == MG_EV_HTTP_REQUEST) {
struct mg_http_endpoint *ep =
mg_http_get_endpoint_handler(nc->listener, &hm->uri);
if (ep != NULL) {
#if MG_ENABLE_FILESYSTEM && !MG_DISABLE_HTTP_DIGEST_AUTH
if (!mg_http_is_authorized(hm, hm->uri, 0 /* is_directory */,
ep->auth_domain, ep->auth_file,
1 /* is_global_pass_file */)) {
mg_http_send_digest_auth_request(nc, ep->auth_domain);
return;
}
#endif
pd->endpoint_handler = ep->handler;
#if MG_ENABLE_CALLBACK_USERDATA
user_data = ep->user_data;
#endif
}
}
mg_call(nc, pd->endpoint_handler ? pd->endpoint_handler : nc->handler,
user_data, ev, hm);
}
void mg_register_http_endpoint(struct mg_connection *nc, const char *uri_path,
MG_CB(mg_event_handler_t handler,
void *user_data)) {
struct mg_http_endpoint_opts opts;
memset(&opts, 0, sizeof(opts));
#if MG_ENABLE_CALLBACK_USERDATA
opts.user_data = user_data;
#endif
mg_register_http_endpoint_opt(nc, uri_path, handler, opts);
}
#endif /* MG_ENABLE_HTTP */
#ifdef MG_MODULE_LINES
#line 1 "mongoose/src/http_cgi.c"
@ -8919,6 +8967,8 @@ MG_INTERNAL void mg_handle_put(struct mg_connection *nc, const char *path,
#if MG_ENABLE_HTTP && MG_ENABLE_HTTP_WEBSOCKET
/* Amalgamated: #include "common/sha1.h" */
#ifndef MG_WEBSOCKET_PING_INTERVAL_SECONDS
#define MG_WEBSOCKET_PING_INTERVAL_SECONDS 5
#endif
@ -9187,8 +9237,8 @@ MG_INTERNAL void mg_ws_handler(struct mg_connection *nc, int ev,
}
#ifndef MG_EXT_SHA1
static void mg_hash_sha1_v(size_t num_msgs, const uint8_t *msgs[],
const size_t *msg_lens, uint8_t *digest) {
void mg_hash_sha1_v(size_t num_msgs, const uint8_t *msgs[],
const size_t *msg_lens, uint8_t *digest) {
size_t i;
cs_sha1_ctx sha_ctx;
cs_sha1_init(&sha_ctx);
@ -9650,7 +9700,7 @@ int mg_match_prefix_n(const struct mg_str pattern, const struct mg_str str) {
return j == str.len ? (int) j : -1;
} else if (pattern.p[i] == '*') {
i++;
if (pattern.p[i] == '*') {
if (i < pattern.len && pattern.p[i] == '*') {
i++;
len = str.len - j;
} else {

View File

@ -1629,6 +1629,84 @@ void mg_lwip_set_keepalive_params(struct mg_connection *nc, int idle,
#endif /* CS_COMMON_PLATFORMS_LWIP_MG_LWIP_H_ */
#ifdef MG_MODULE_LINES
#line 1 "common/cs_md5.h"
#endif
/*
* Copyright (c) 2014 Cesanta Software Limited
* All rights reserved
*/
#ifndef CS_COMMON_MD5_H_
#define CS_COMMON_MD5_H_
/* Amalgamated: #include "common/platform.h" */
#ifndef CS_DISABLE_MD5
#define CS_DISABLE_MD5 0
#endif
#ifdef __cplusplus
extern "C" {
#endif /* __cplusplus */
typedef struct {
uint32_t buf[4];
uint32_t bits[2];
unsigned char in[64];
} cs_md5_ctx;
void cs_md5_init(cs_md5_ctx *c);
void cs_md5_update(cs_md5_ctx *c, const unsigned char *data, size_t len);
void cs_md5_final(unsigned char *md, cs_md5_ctx *c);
#ifdef __cplusplus
}
#endif /* __cplusplus */
#endif /* CS_COMMON_MD5_H_ */
#ifdef MG_MODULE_LINES
#line 1 "common/cs_sha1.h"
#endif
/*
* Copyright (c) 2014 Cesanta Software Limited
* All rights reserved
*/
#ifndef CS_COMMON_SHA1_H_
#define CS_COMMON_SHA1_H_
#ifndef CS_DISABLE_SHA1
#define CS_DISABLE_SHA1 0
#endif
#if !CS_DISABLE_SHA1
/* Amalgamated: #include "common/platform.h" */
#ifdef __cplusplus
extern "C" {
#endif /* __cplusplus */
typedef struct {
uint32_t state[5];
uint32_t count[2];
unsigned char buffer[64];
} cs_sha1_ctx;
void cs_sha1_init(cs_sha1_ctx *);
void cs_sha1_update(cs_sha1_ctx *, const unsigned char *data, uint32_t len);
void cs_sha1_final(unsigned char digest[20], cs_sha1_ctx *);
void cs_hmac_sha1(const unsigned char *key, size_t key_len,
const unsigned char *text, size_t text_len,
unsigned char out[20]);
#ifdef __cplusplus
}
#endif /* __cplusplus */
#endif /* CS_DISABLE_SHA1 */
#endif /* CS_COMMON_SHA1_H_ */
#ifdef MG_MODULE_LINES
#line 1 "common/cs_time.h"
#endif
/*
@ -1793,94 +1871,6 @@ void mbuf_trim(struct mbuf *);
#endif /* CS_COMMON_MBUF_H_ */
#ifdef MG_MODULE_LINES
#line 1 "common/sha1.h"
#endif
/*
* Copyright (c) 2014 Cesanta Software Limited
* All rights reserved
*/
#ifndef CS_COMMON_SHA1_H_
#define CS_COMMON_SHA1_H_
#ifndef CS_DISABLE_SHA1
#define CS_DISABLE_SHA1 0
#endif
#if !CS_DISABLE_SHA1
/* Amalgamated: #include "common/platform.h" */
#ifdef __cplusplus
extern "C" {
#endif /* __cplusplus */
typedef struct {
uint32_t state[5];
uint32_t count[2];
unsigned char buffer[64];
} cs_sha1_ctx;
void cs_sha1_init(cs_sha1_ctx *);
void cs_sha1_update(cs_sha1_ctx *, const unsigned char *data, uint32_t len);
void cs_sha1_final(unsigned char digest[20], cs_sha1_ctx *);
void cs_hmac_sha1(const unsigned char *key, size_t key_len,
const unsigned char *text, size_t text_len,
unsigned char out[20]);
#ifdef __cplusplus
}
#endif /* __cplusplus */
#endif /* CS_DISABLE_SHA1 */
#endif /* CS_COMMON_SHA1_H_ */
#ifdef MG_MODULE_LINES
#line 1 "common/md5.h"
#endif
/*
* Copyright (c) 2014 Cesanta Software Limited
* All rights reserved
*/
#ifndef CS_COMMON_MD5_H_
#define CS_COMMON_MD5_H_
/* Amalgamated: #include "common/platform.h" */
#ifndef CS_DISABLE_MD5
#define CS_DISABLE_MD5 0
#endif
#ifdef __cplusplus
extern "C" {
#endif /* __cplusplus */
typedef struct MD5Context {
uint32_t buf[4];
uint32_t bits[2];
unsigned char in[64];
} MD5_CTX;
void MD5_Init(MD5_CTX *c);
void MD5_Update(MD5_CTX *c, const unsigned char *data, size_t len);
void MD5_Final(unsigned char *md, MD5_CTX *c);
/*
* Return stringified MD5 hash for NULL terminated list of pointer/length pairs.
* A length should be specified as size_t variable.
* Example:
*
* char buf[33];
* cs_md5(buf, "foo", (size_t) 3, "bar", (size_t) 3, NULL);
*/
char *cs_md5(char buf[33], ...);
#ifdef __cplusplus
}
#endif /* __cplusplus */
#endif /* CS_COMMON_MD5_H_ */
#ifdef MG_MODULE_LINES
#line 1 "common/base64.h"
#endif
/*
@ -4394,6 +4384,11 @@ void mg_printf_websocket_frame(struct mg_connection *nc, int op_and_flags,
int mg_url_decode(const char *src, int src_len, char *dst, int dst_len,
int is_form_url_encoded);
extern void mg_hash_md5_v(size_t num_msgs, const uint8_t *msgs[],
const size_t *msg_lens, uint8_t *digest);
extern void mg_hash_sha1_v(size_t num_msgs, const uint8_t *msgs[],
const size_t *msg_lens, uint8_t *digest);
#ifdef __cplusplus
}
#endif /* __cplusplus */
@ -4805,6 +4800,18 @@ void mg_register_http_endpoint(struct mg_connection *nc, const char *uri_path,
MG_CB(mg_event_handler_t handler,
void *user_data));
struct mg_http_endpoint_opts {
void *user_data;
/* Authorization domain (realm) */
const char *auth_domain;
const char *auth_file;
};
void mg_register_http_endpoint_opt(struct mg_connection *nc,
const char *uri_path,
mg_event_handler_t handler,
struct mg_http_endpoint_opts opts);
/*
* Authenticates a HTTP request against an opened password file.
* Returns 1 if authenticated, 0 otherwise.