[mod_auth] HTTP Basic auth backends also do authz (#1817)

HTTP Basic auth backends now do both authn and authz
in order to allow provide a means to extend backends to optionally
support group authz

x-ref:
  "LDAP-Group support for HTTP-Authentication"
  https://redmine.lighttpd.net/issues/1817
This commit is contained in:
Glenn Strauss 2016-09-28 06:36:38 -04:00
parent d4f812550c
commit a401c9469a
6 changed files with 38 additions and 33 deletions

View File

@ -23,7 +23,7 @@ int http_auth_match_rules (const http_auth_require_t *require, const char *user,
typedef struct http_auth_backend_t {
const char *name;
handler_t(*basic)(server *srv, connection *con, void *p_d, const buffer *username, const buffer *realm, const char *pw);
handler_t(*basic)(server *srv, connection *con, void *p_d, const http_auth_require_t *require, const buffer *username, const char *pw);
handler_t(*digest)(server *srv, connection *con, void *p_d, const char *username, const char *realm, unsigned char HA1[16]);
void *p_d;
} http_auth_backend_t;

View File

@ -486,14 +486,10 @@ static handler_t mod_auth_check_basic(server *srv, connection *con, void *p_d, c
buffer_string_set_length(username, pw - username->ptr);
pw++;
rc = backend->basic(srv, con, backend->p_d, username, require->realm, pw);
rc = backend->basic(srv, con, backend->p_d, require, username, pw);
switch (rc) {
case HANDLER_GO_ON:
if (http_auth_match_rules(require, username->ptr, NULL, NULL)) {
http_auth_setenv(con->environment, CONST_BUF_LEN(username), CONST_STR_LEN("Basic"));
} else {
rc = HANDLER_UNSET;
}
http_auth_setenv(con->environment, CONST_BUF_LEN(username), CONST_STR_LEN("Basic"));
break;
case HANDLER_WAIT_FOR_EVENT:
case HANDLER_FINISHED:

View File

@ -62,10 +62,10 @@ typedef struct {
} plugin_data;
static handler_t mod_authn_file_htdigest_digest(server *srv, connection *con, void *p_d, const char *username, const char *realm, unsigned char HA1[16]);
static handler_t mod_authn_file_htdigest_basic(server *srv, connection *con, void *p_d, const buffer *username, const buffer *realm, const char *pw);
static handler_t mod_authn_file_htdigest_basic(server *srv, connection *con, void *p_d, const http_auth_require_t *require, const buffer *username, const char *pw);
static handler_t mod_authn_file_plain_digest(server *srv, connection *con, void *p_d, const char *username, const char *realm, unsigned char HA1[16]);
static handler_t mod_authn_file_plain_basic(server *srv, connection *con, void *p_d, const buffer *username, const buffer *realm, const char *pw);
static handler_t mod_authn_file_htpasswd_basic(server *srv, connection *con, void *p_d, const buffer *username, const buffer *realm, const char *pw);
static handler_t mod_authn_file_plain_basic(server *srv, connection *con, void *p_d, const http_auth_require_t *require, const buffer *username, const char *pw);
static handler_t mod_authn_file_htpasswd_basic(server *srv, connection *con, void *p_d, const http_auth_require_t *require, const buffer *username, const char *pw);
INIT_FUNC(mod_authn_file_init) {
static http_auth_backend_t http_auth_backend_htdigest =
@ -280,25 +280,26 @@ static handler_t mod_authn_file_htdigest_digest(server *srv, connection *con, vo
return (0 == rc) ? HANDLER_GO_ON : HANDLER_ERROR;
}
static handler_t mod_authn_file_htdigest_basic(server *srv, connection *con, void *p_d, const buffer *username, const buffer *realm, const char *pw) {
static handler_t mod_authn_file_htdigest_basic(server *srv, connection *con, void *p_d, const http_auth_require_t *require, const buffer *username, const char *pw) {
plugin_data *p = (plugin_data *)p_d;
li_MD5_CTX Md5Ctx;
unsigned char HA1[16];
unsigned char htdigest[16];
mod_authn_file_patch_connection(srv, con, p);
if (mod_authn_file_htdigest_get(srv, p->conf.auth_htdigest_userfile, username, realm, htdigest)) return HANDLER_ERROR;
if (mod_authn_file_htdigest_get(srv, p->conf.auth_htdigest_userfile, username, require->realm, htdigest)) return HANDLER_ERROR;
li_MD5_Init(&Md5Ctx);
li_MD5_Update(&Md5Ctx, CONST_BUF_LEN(username));
li_MD5_Update(&Md5Ctx, CONST_STR_LEN(":"));
li_MD5_Update(&Md5Ctx, CONST_BUF_LEN(realm));
li_MD5_Update(&Md5Ctx, CONST_BUF_LEN(require->realm));
li_MD5_Update(&Md5Ctx, CONST_STR_LEN(":"));
li_MD5_Update(&Md5Ctx, (unsigned char *)pw, strlen(pw));
li_MD5_Final(HA1, &Md5Ctx);
UNUSED(con);
return (0 == memcmp(HA1, htdigest, sizeof(HA1)))
return (0 == memcmp(HA1, htdigest, sizeof(HA1))
&& http_auth_match_rules(require, username->ptr, NULL, NULL))
? HANDLER_GO_ON
: HANDLER_ERROR;
}
@ -388,7 +389,7 @@ static handler_t mod_authn_file_plain_digest(server *srv, connection *con, void
return (0 == rc) ? HANDLER_GO_ON : HANDLER_ERROR;
}
static handler_t mod_authn_file_plain_basic(server *srv, connection *con, void *p_d, const buffer *username, const buffer *realm, const char *pw) {
static handler_t mod_authn_file_plain_basic(server *srv, connection *con, void *p_d, const http_auth_require_t *require, const buffer *username, const char *pw) {
plugin_data *p = (plugin_data *)p_d;
buffer *password_buf = buffer_init();/* password-string from auth-backend */
int rc;
@ -399,8 +400,9 @@ static handler_t mod_authn_file_plain_basic(server *srv, connection *con, void *
}
buffer_free(password_buf);
UNUSED(con);
UNUSED(realm);
return (0 == rc) ? HANDLER_GO_ON : HANDLER_ERROR;
return 0 == rc && http_auth_match_rules(require, username->ptr, NULL, NULL)
? HANDLER_GO_ON
: HANDLER_ERROR;
}
@ -611,7 +613,7 @@ static void apr_sha_encode(const char *pw, char *result, size_t nbytes) {
}
#endif
static handler_t mod_authn_file_htpasswd_basic(server *srv, connection *con, void *p_d, const buffer *username, const buffer *realm, const char *pw) {
static handler_t mod_authn_file_htpasswd_basic(server *srv, connection *con, void *p_d, const http_auth_require_t *require, const buffer *username, const char *pw) {
plugin_data *p = (plugin_data *)p_d;
buffer *password = buffer_init();/* password-string from auth-backend */
int rc;
@ -709,8 +711,9 @@ static handler_t mod_authn_file_htpasswd_basic(server *srv, connection *con, voi
}
buffer_free(password);
UNUSED(con);
UNUSED(realm);
return (0 == rc) ? HANDLER_GO_ON : HANDLER_ERROR;
return 0 == rc && http_auth_match_rules(require, username->ptr, NULL, NULL)
? HANDLER_GO_ON
: HANDLER_ERROR;
}

View File

@ -53,7 +53,7 @@ typedef struct {
} plugin_data;
static handler_t mod_authn_gssapi_check(server *srv, connection *con, void *p_d, const struct http_auth_require_t *require, const struct http_auth_backend_t *backend);
static handler_t mod_authn_gssapi_basic(server *srv, connection *con, void *p_d, const buffer *username, const buffer *realm, const char *pw);
static handler_t mod_authn_gssapi_basic(server *srv, connection *con, void *p_d, const http_auth_require_t *require, const buffer *username, const char *pw);
static plugin_data *plugin_data_singleton;
@ -622,7 +622,7 @@ static handler_t mod_authn_gssapi_send_401_unauthorized_basic (server *srv, conn
return HANDLER_FINISHED;
}
static handler_t mod_authn_gssapi_basic(server *srv, connection *con, void *p_d, const buffer *username, const buffer *realm, const char *pw)
static handler_t mod_authn_gssapi_basic(server *srv, connection *con, void *p_d, const http_auth_require_t *require, const buffer *username, const char *pw)
{
krb5_context kcontext = NULL;
krb5_keytab keytab = NULL;
@ -676,7 +676,7 @@ static handler_t mod_authn_gssapi_basic(server *srv, connection *con, void *p_d,
if (strchr(username->ptr, '@') == NULL) {
user_at_realm = buffer_init_buffer(username);
BUFFER_APPEND_STRING_CONST(user_at_realm, "@");
buffer_append_string_buffer(user_at_realm, realm);
buffer_append_string_buffer(user_at_realm, require->realm);
}
ret = krb5_parse_name(kcontext, (user_at_realm ? user_at_realm->ptr : username->ptr), &c_princ);
@ -758,12 +758,12 @@ static handler_t mod_authn_gssapi_basic(server *srv, connection *con, void *p_d,
krb5_free_context(kcontext);
if (0 == ret) {
if (0 == ret && http_auth_match_rules(require,username->ptr,NULL,NULL)){
return HANDLER_GO_ON;
}
else {
/* ret == KRB5KDC_ERR_C_PRINCIPAL_UNKNOWN */
log_error_write(srv, __FILE__, __LINE__, "sbsb", "password doesn't match for user:", username, "uri:", con->uri.path);
/* ret == KRB5KDC_ERR_C_PRINCIPAL_UNKNOWN or no authz rules match */
log_error_write(srv, __FILE__, __LINE__, "sbsBss", "password doesn't match for", con->uri.path, "username:", username, ", IP:", con->dst_addr_buf);
return mod_authn_gssapi_send_401_unauthorized_basic(srv, con);
}
}

View File

@ -39,7 +39,7 @@ typedef struct {
buffer *ldap_filter;
} plugin_data;
static handler_t mod_authn_ldap_basic(server *srv, connection *con, void *p_d, const buffer *username, const buffer *realm, const char *pw);
static handler_t mod_authn_ldap_basic(server *srv, connection *con, void *p_d, const http_auth_require_t *require, const buffer *username, const char *pw);
INIT_FUNC(mod_authn_ldap_init) {
static http_auth_backend_t http_auth_backend_ldap =
@ -401,11 +401,10 @@ static char * mod_authn_ldap_get_dn(server *srv, plugin_config *s, char *base, c
return dn;
}
static handler_t mod_authn_ldap_basic(server *srv, connection *con, void *p_d, const buffer *username, const buffer *realm, const char *pw) {
static handler_t mod_authn_ldap_basic(server *srv, connection *con, void *p_d, const http_auth_require_t *require, const buffer *username, const char *pw) {
plugin_data *p = (plugin_data *)p_d;
LDAP *ld;
char *dn;
UNUSED(realm);
mod_authn_ldap_patch_connection(srv, con, p);
@ -467,7 +466,9 @@ static handler_t mod_authn_ldap_basic(server *srv, connection *con, void *p_d, c
ldap_unbind_ext_s(ld, NULL, NULL); /* disconnect */
ldap_memfree(dn);
return HANDLER_GO_ON; /* access granted */
return http_auth_match_rules(require, username->ptr, NULL, NULL)
? HANDLER_GO_ON /* access granted */
: HANDLER_ERROR;
}
int mod_authn_ldap_plugin_init(plugin *p);

View File

@ -133,7 +133,7 @@ static void mod_authn_mysql_sock_error(server *srv, plugin_config *pconf) {
mod_authn_mysql_sock_close(pconf);
}
static handler_t mod_authn_mysql_basic(server *srv, connection *con, void *p_d, const buffer *username, const buffer *realm, const char *pw);
static handler_t mod_authn_mysql_basic(server *srv, connection *con, void *p_d, const http_auth_require_t *require, const buffer *username, const char *pw);
static handler_t mod_authn_mysql_digest(server *srv, connection *con, void *p_d, const char *username, const char *realm, unsigned char HA1[16]);
INIT_FUNC(mod_authn_mysql_init) {
@ -514,11 +514,16 @@ static handler_t mod_authn_mysql_query(server *srv, connection *con, void *p_d,
return (0 == rc) ? HANDLER_GO_ON : HANDLER_ERROR;
}
static handler_t mod_authn_mysql_basic(server *srv, connection *con, void *p_d, const buffer *username, const buffer *realm, const char *pw) {
static handler_t mod_authn_mysql_basic(server *srv, connection *con, void *p_d, const http_auth_require_t *require, const buffer *username, const char *pw) {
/*(HA1 is not written since pw passed should not be NULL;
* avoid passing NULL since subroutine expects unsigned char HA1[16] arg)*/
static unsigned char HA1[16];
return mod_authn_mysql_query(srv,con,p_d,username->ptr,realm->ptr,pw,HA1);
char *realm = require->realm->ptr;
handler_t rc =mod_authn_mysql_query(srv,con,p_d,username->ptr,realm,pw,HA1);
if (HANDLER_GO_ON != rc) return rc;
return http_auth_match_rules(require, username->ptr, NULL, NULL)
? HANDLER_GO_ON /* access granted */
: HANDLER_ERROR;
}
static handler_t mod_authn_mysql_digest(server *srv, connection *con, void *p_d, const char *username, const char *realm, unsigned char HA1[16]) {