Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

added support to basic access authentication #330

Closed
wants to merge 1 commit into from
Closed
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Jump to
Jump to file
Failed to load files.
Diff view
Diff view
29 changes: 29 additions & 0 deletions examples/auth_basic.c
@@ -0,0 +1,29 @@
#include <stdio.h>
#include <string.h>
#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;
}
86 changes: 86 additions & 0 deletions mongoose.c
Expand Up @@ -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;
}

5 changes: 5 additions & 0 deletions mongoose.h
Expand Up @@ -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 };
Expand Down