From 7f789a5107ee040f73c52013fee1eaa84466d09d Mon Sep 17 00:00:00 2001 From: Helton Marques Date: Sat, 15 Feb 2014 22:01:47 -0200 Subject: [PATCH] added support to basic access authentication --- examples/auth_basic.c | 29 +++++++++++++++ mongoose.c | 86 +++++++++++++++++++++++++++++++++++++++++++ mongoose.h | 5 +++ 3 files changed, 120 insertions(+) create mode 100644 examples/auth_basic.c diff --git a/examples/auth_basic.c b/examples/auth_basic.c new file mode 100644 index 0000000000..6289652d90 --- /dev/null +++ b/examples/auth_basic.c @@ -0,0 +1,29 @@ +#include +#include +#include "mongoose.h" + +static int auth_handler(struct mg_connection *conn) { + // + // md5 hash of password 'constantine': + // 2f2aa5570eb38a679d2690116090ff65 + // + // to verify: + // curl -u john:2f2aa5570eb38a679d2690116090ff65 -i localhost:8080 + // + return mg_authorize_basic(conn, "john", "constantine", MG_MD5_PASSWORD); +} + +int main(void) { + struct mg_server *server = mg_create_server(NULL); + mg_set_option(server, "listening_port", "8080"); + mg_set_option(server, "document_root", "."); + mg_set_auth_handler(server, auth_handler); + + printf("Starting on port %s\n", mg_get_option(server, "listening_port")); + for (;;) { + mg_poll_server(server, 1000); + } + mg_destroy_server(&server); + + return 0; +} diff --git a/mongoose.c b/mongoose.c index 85c1a49ee4..80a3be6b39 100644 --- a/mongoose.c +++ b/mongoose.c @@ -4297,3 +4297,89 @@ struct mg_server *mg_create_server(void *server_data) { return server; } + +static int getbyte64(char c) +{ + if(c >='A' && c <='Z') return c - 'A'; + if(c >='a' && c <='z') return c - 'a' + 26; + if(c >='0' && c <='9') return c - '0' + 52; + if(c == '+') return 62; + if(c == '/') return 63; + return -1; +} + +static int base64_decode(const unsigned char *src, int src_len, char *dst) +{ + int a, b, c, d, i, j; + int len = src_len; + + if (!src || src_len == 0 || !dst) { + return 0; + } + + //removing "==" from the end of src string + while ((src[len-1] == '=') && len) { + --len; + } + + for (i=0, j=0; (i + 3) < len; i+=4) { + a = getbyte64(src[i]); + b = getbyte64(src[i + 1]); + c = getbyte64(src[i + 2]); + d = getbyte64(src[i + 3]); + + dst[j++] = ((a << 2) | ((b & 0x30) >> 4)); + dst[j++] = (((b & 0x0F) << 4) | ((c & 0x3C) >> 2)); + dst[j++] = (((c & 0x03) << 6) | (d & 0x3F)); + } + if (i < len) { + a = getbyte64(src[i]); + b = ((i + 1) < len) ? getbyte64(src[i + 1]) : -1; + c = ((i + 2) < len) ? getbyte64(src[i + 2]) : -1; + d = -1; + + if (b != -1) { + dst[j++] = ((a << 2) | ((b & 0x30) >> 4)); + if (c != -1) { + dst[j++] = (((b & 0x0F) << 4) | ((c & 0x3C) >> 2)); + if (d != -1) { + dst[j++] = (((c & 0x03) << 6) | (d & 0x3F)); + } + } + } + } + dst[j] = '\0'; + return (j > src_len) ? 0 : 1; +} + +// Authorize using username and password, without load data from file. +// Return 1 if authorized. +int mg_authorize_basic(struct mg_connection *c, + const char *username, const char *password, int type) { + char cred[256], user[100], resp[100], ha[256]; + const char *hdr, *base; + + if (c == NULL || username == NULL || password == NULL) return 0; + if ((hdr = mg_get_header(c, "Authorization")) == NULL) return 0; + + base = strchr(hdr, ' '); + if ((base == NULL) || (base <= hdr)) return 0; + if ((mg_strncasecmp(hdr, "Basic", (base - hdr))) != 0) return 0; + if (base64_decode((const unsigned char *)(base + 1), + strlen(base + 1), cred) == 0) return 0; + + if (sscanf(cred, "%[^:]:%s", user, resp) == 2 && + !strcmp(user, username)) { + // compare with a MD5 password + if (type == MG_MD5_PASSWORD) { + mg_md5(ha, password, NULL); + return mg_strcasecmp(ha, resp) == 0 ? + MG_AUTH_OK : MG_AUTH_FAIL; + } + // or a plain password + return mg_strcasecmp(password, resp) == 0 ? + MG_AUTH_OK : MG_AUTH_FAIL; + } + return MG_AUTH_FAIL; +} + diff --git a/mongoose.h b/mongoose.h index d335c8039c..503c736141 100644 --- a/mongoose.h +++ b/mongoose.h @@ -104,6 +104,11 @@ void *mg_start_thread(void *(*func)(void *), void *param); char *mg_md5(char buf[33], ...); int mg_authorize_digest(struct mg_connection *c, FILE *fp); +// Support to basic access authentication +enum { MG_MD5_PASSWORD, MG_PLAIN_PASSWORD }; +int mg_authorize_basic(struct mg_connection *c, + const char *username, const char *password, int type); + // Callback function return codes enum { MG_REQUEST_NOT_PROCESSED, MG_REQUEST_PROCESSED, MG_REQUEST_CALL_AGAIN }; enum { MG_AUTH_FAIL, MG_AUTH_OK };