Skip to content
This repository has been archived by the owner on Nov 5, 2023. It is now read-only.

Commit

Permalink
Accept HTTP basic authentication
Browse files Browse the repository at this point in the history
  • Loading branch information
bel2125 committed Apr 6, 2022
1 parent 4d42a5f commit e1bcce1
Showing 1 changed file with 85 additions and 30 deletions.
115 changes: 85 additions & 30 deletions src/civetweb.c
Original file line number Diff line number Diff line change
Expand Up @@ -3763,8 +3763,7 @@ skip_quoted(char **buf,
if (end_word > begin_word) {
p = end_word - 1;
while (*p == quotechar) {
/* While the delimiter is quoted, look for the next delimiter.
*/
/* While the delimiter is quoted, look for the next delimiter. */
/* This happens, e.g., in calls from parse_auth_header,
* if the user name contains a " character. */

Expand Down Expand Up @@ -8366,14 +8365,14 @@ mg_md5(char buf[33], ...)

/* Check the user's password, return 1 if OK */
static int
check_password(const char *method,
const char *ha1,
const char *uri,
const char *nonce,
const char *nc,
const char *cnonce,
const char *qop,
const char *response)
check_password_digest(const char *method,
const char *ha1,
const char *uri,
const char *nonce,
const char *nc,
const char *cnonce,
const char *qop,
const char *response)
{
char ha2[32 + 1], expected_response[32 + 1];

Expand Down Expand Up @@ -8485,7 +8484,10 @@ open_auth_file(struct mg_connection *conn,

/* Parsed Authorization header */
struct ah {
char *user, *uri, *cnonce, *response, *qop, *nc, *nonce;
char *user;
int type; /* 1 = basic, 2 = digest */
char *plain_password; /* Basic only */
char *uri, *cnonce, *response, *qop, *nc, *nonce; /* Digest only */
};


Expand All @@ -8505,8 +8507,43 @@ parse_auth_header(struct mg_connection *conn,
}

(void)memset(ah, 0, sizeof(*ah));
if (((auth_header = mg_get_header(conn, "Authorization")) == NULL)
|| mg_strncasecmp(auth_header, "Digest ", 7) != 0) {
auth_header = mg_get_header(conn, "Authorization");

if (auth_header == NULL) {
/* No Authorization header at all */
return 0;
}
if (0 == mg_strncasecmp(auth_header, "Basic ", 6)) {
/* Basic Auth (we never asked for this, but some client may send it) */
char *split;
const char *userpw_b64 = auth_header + 6;
size_t userpw_b64_len = strlen(userpw_b64);
size_t buf_len_r = buf_size;
if (mg_base64_decode(userpw_b64, userpw_b64_len, buf, &buf_len_r)
!= -1) {
return 0; /* decode error */
}
split = strchr(buf, ':');
if (!split) {
return 0; /* Format error */
}

/* Separate string at ':' */
*split = 0;

/* User name is before ':', Password is after ':' */
ah->user = buf;
ah->type = 1;
ah->plain_password = split + 1;

return 1;

} else if (0 == mg_strncasecmp(auth_header, "Digest ", 7)) {
/* Digest Auth ... implemented below */
ah->type = 2;

} else {
/* Unknown or invalid Auth method */
return 0;
}

Expand Down Expand Up @@ -8591,15 +8628,7 @@ parse_auth_header(struct mg_connection *conn,
(void)nonce;
#endif

/* CGI needs it as REMOTE_USER */
if (ah->user != NULL) {
conn->request_info.remote_user =
mg_strdup_ctx(ah->user, conn->phys_ctx);
} else {
return 0;
}

return 1;
return (ah->user != NULL);
}


Expand Down Expand Up @@ -8734,14 +8763,36 @@ read_auth_file(struct mg_file *filep,

if (!strcmp(workdata->ah.user, workdata->f_user)
&& !strcmp(workdata->domain, workdata->f_domain)) {
return check_password(workdata->conn->request_info.request_method,
workdata->f_ha1,
workdata->ah.uri,
workdata->ah.nonce,
workdata->ah.nc,
workdata->ah.cnonce,
workdata->ah.qop,
workdata->ah.response);
switch (workdata->ah.type) {
case 1: /* Basic */
{
size_t mlen = strlen(workdata->f_user)
+ strlen(workdata->domain)
+ strlen(workdata->ah.plain_password) + 3;
char md5[33];

mg_md5(md5,
workdata->f_user,
":",
workdata->domain,
":",
workdata->ah.plain_password,
NULL);
return 0 == memcmp(workdata->f_ha1, md5, 33);
}
case 2: /* Digest */
return check_password_digest(
workdata->conn->request_info.request_method,
workdata->f_ha1,
workdata->ah.uri,
workdata->ah.nonce,
workdata->ah.nc,
workdata->ah.cnonce,
workdata->ah.qop,
workdata->ah.response);
default: /* None/Other/Unknown */
return 0;
}
}
}

Expand All @@ -8767,6 +8818,10 @@ authorize(struct mg_connection *conn, struct mg_file *filep, const char *realm)
return 0;
}

/* CGI needs it as REMOTE_USER */
conn->request_info.remote_user =
mg_strdup_ctx(workdata.ah.user, conn->phys_ctx);

if (realm) {
workdata.domain = realm;
} else {
Expand Down

0 comments on commit e1bcce1

Please sign in to comment.