1
0
Fork 0
mirror of https://github.com/warmcat/libwebsockets.git synced 2025-03-09 00:00:04 +01:00

basic auth: add callback option

Allow an http mount to specify it wants to check Basic Auth
requests via a protocol callback instead of a text file.
This commit is contained in:
Dane 2019-12-12 18:45:00 +00:00 committed by Andy Green
parent 6879574d8d
commit 10290048b0
5 changed files with 49 additions and 12 deletions

View file

@ -280,6 +280,15 @@ enum lws_callback_reasons {
* break;
*/
LWS_CALLBACK_VERIFY_BASIC_AUTHORIZATION = 102,
/**< This gives the user code a chance to accept or reject credentials
* provided HTTP to basic authorization. It will only be called if the
* http mount's authentication_mode is set to LWSAUTHM_BASIC_AUTH_CALLBACK
* `in` points to a credential string of the form `username:password` If
* the callback returns zero (the default if unhandled), then the
* transaction ends with HTTP_STATUS_UNAUTHORIZED, otherwise the request
* will be processed */
LWS_CALLBACK_CHECK_ACCESS_RIGHTS = 51,
/**< This gives the user code a chance to forbid an http access.
* `in` points to a `struct lws_process_html_args`, which

View file

@ -1040,6 +1040,18 @@ enum lws_mount_protocols {
LWSMPRO_CALLBACK = 6, /**< hand by named protocol's callback */
};
/** enum lws_authentication_mode
* This specifies the authentication mode of the mount. The basic_auth_login_file mount parameter
* is ignored unless LWSAUTHM_DEFAULT is set.
*/
enum lws_authentication_mode {
LWSAUTHM_DEFAULT = 0, /**< default authenticate only if basic_auth_login_file is provided */
LWSAUTHM_BASIC_AUTH_CALLBACK = 1 << 28 /**< Basic auth with a custom verifier */
};
/** The authentication mode is stored in the top 4 bits of lws_http_mount.auth_mask */
#define AUTH_MODE_MASK 0xF0000000
/** struct lws_http_mount
*
* arguments for mounting something in a vhost's url namespace
@ -1080,7 +1092,7 @@ struct lws_http_mount {
unsigned char mountpoint_len; /**< length of mountpoint string */
const char *basic_auth_login_file;
/**<NULL, or filepath to use to check basic auth logins against */
/**<NULL, or filepath to use to check basic auth logins against. (requires LWSAUTHM_DEFAULT) */
/* Add new things just above here ---^
* This is part of the ABI, don't needlessly break compatibility

View file

@ -300,7 +300,7 @@ enum lws_check_basic_auth_results {
};
enum lws_check_basic_auth_results
lws_check_basic_auth(struct lws *wsi, const char *basic_auth_login_file);
lws_check_basic_auth(struct lws *wsi, const char *basic_auth_login_file, unsigned int auth_mode);
int
lws_unauthorised_basic_auth(struct lws *wsi);

View file

@ -946,16 +946,15 @@ lws_http_get_uri_and_method(struct lws *wsi, char **puri_ptr, int *puri_len)
return -1;
}
enum lws_check_basic_auth_results
lws_check_basic_auth(struct lws *wsi, const char *basic_auth_login_file)
lws_check_basic_auth(struct lws *wsi, const char *basic_auth_login_file,
unsigned int auth_mode)
{
#if defined(LWS_WITH_FILE_OPS)
char b64[160], plain[(sizeof(b64) * 3) / 4], *pcolon;
int m, ml, fi;
int m, ml, fi, bar;
if (!basic_auth_login_file)
if (!basic_auth_login_file && auth_mode == LWSAUTHM_DEFAULT)
return LCBA_CONTINUE;
/* Did he send auth? */
@ -998,8 +997,23 @@ lws_check_basic_auth(struct lws *wsi, const char *basic_auth_login_file)
lwsl_err("basic auth format broken\n");
return LCBA_END_TRANSACTION;
}
if (!lws_find_string_in_file(basic_auth_login_file, plain, m)) {
lwsl_err("basic auth lookup failed\n");
switch (auth_mode) {
case LWSAUTHM_DEFAULT:
if (lws_find_string_in_file(basic_auth_login_file, plain, m))
break;
lwsl_err("%s: basic auth lookup failed\n", __func__);
return LCBA_FAILED_AUTH;
case LWSAUTHM_BASIC_AUTH_CALLBACK:
bar = wsi->protocol->callback(wsi,
LWS_CALLBACK_VERIFY_BASIC_AUTHORIZATION,
wsi->user_space, plain, m);
if (!bar)
return LCBA_FAILED_AUTH;
break;
default:
/* Invalid auth mode so lets fail all authentication attempts */
return LCBA_FAILED_AUTH;
}
@ -1468,7 +1482,8 @@ lws_http_action(struct lws *wsi)
/* basic auth? */
switch(lws_check_basic_auth(wsi, hit->basic_auth_login_file)) {
switch (lws_check_basic_auth(wsi, hit->basic_auth_login_file,
hit->auth_mask & AUTH_MODE_MASK)) {
case LCBA_CONTINUE:
break;
case LCBA_FAILED_AUTH:
@ -1527,7 +1542,7 @@ lws_http_action(struct lws *wsi)
args.p = uri_ptr;
args.len = uri_len;
args.max_len = hit->auth_mask;
args.max_len = hit->auth_mask & ~AUTH_MODE_MASK;
args.final = 0; /* used to signal callback dealt with it */
args.chunked = 0;

View file

@ -271,7 +271,8 @@ lws_process_ws_upgrade2(struct lws *wsi)
!lws_pvo_get_str((void *)pvos->options, "basic-auth",
&ws_prot_basic_auth)) {
lwsl_info("%s: ws upgrade requires basic auth\n", __func__);
switch(lws_check_basic_auth(wsi, ws_prot_basic_auth)) {
switch (lws_check_basic_auth(wsi, ws_prot_basic_auth, LWSAUTHM_DEFAULT
/* no callback based auth here */)) {
case LCBA_CONTINUE:
break;
case LCBA_FAILED_AUTH: