Mercurial > dovecot > core-2.2
changeset 22008:700d5e6f041d
auth: Add username_filter for passdb block
username_filter lets you specify one or more pattern(s) for
including or excluding users. exclusion patterns are denoted
with ! prefix.
if any exclude matches the username, passdb will be skipped.
if any inclusions is specified, and the username does not match
one of them, passdb will be skipped.
author | Aki Tuomi <aki.tuomi@dovecot.fi> |
---|---|
date | Fri, 28 Apr 2017 12:51:20 +0300 |
parents | 5849b30422cc |
children | 2d5018651d64 |
files | src/auth/auth-request.c src/auth/auth-request.h src/auth/auth-settings.c src/auth/auth-settings.h src/auth/passdb.c src/auth/passdb.h |
diffstat | 6 files changed, 51 insertions(+), 0 deletions(-) [+] |
line wrap: on
line diff
--- a/src/auth/auth-request.c Thu Apr 27 11:53:13 2017 +0300 +++ b/src/auth/auth-request.c Fri Apr 28 12:51:20 2017 +0300 @@ -27,6 +27,7 @@ #include "userdb-blocking.h" #include "userdb-template.h" #include "password-scheme.h" +#include "wildcard-match.h" #include <sys/stat.h> @@ -630,16 +631,55 @@ return str_array_icase_find(mechs, mech->mech_name); } +/** + +Check if username is included in the filter. Logic is that if the username +is not excluded by anything, and is included by something, it will be accepted. +By default, all usernames are included, unless there is a inclusion item, when +username will be excluded if there is no inclusion for it. + +Exclusions are denoted with a ! in front of the pattern. +*/ +bool auth_request_username_accepted(const char *const *filter, const char *username) +{ + bool have_includes = FALSE; + bool matched_inc = FALSE; + + for(;*filter != NULL; filter++) { + /* if filter has ! it means the pattern will be refused */ + bool exclude = (**filter == '!'); + if (!exclude) + have_includes = TRUE; + if (wildcard_match(username, (*filter)+(exclude?1:0))) { + if (exclude) { + return FALSE; + } else { + matched_inc = TRUE; + } + } + } + + return matched_inc || !have_includes; +} + static bool auth_request_want_skip_passdb(struct auth_request *request, struct auth_passdb *passdb) { /* if mechanism is not supported, skip */ const char *const *mechs = passdb->passdb->mechanisms; + const char *const *username_filter = passdb->passdb->username_filter; + const char *username; + + username = request->user; if (!auth_request_mechanism_accepted(mechs, request->mech)) return TRUE; + if (passdb->passdb->username_filter != NULL && + !auth_request_username_accepted(username_filter, username)) + return TRUE; + /* skip_password_check basically specifies if authentication is finished */ bool authenticated = request->skip_password_check;
--- a/src/auth/auth-request.h Thu Apr 27 11:53:13 2017 +0300 +++ b/src/auth/auth-request.h Fri Apr 28 12:51:20 2017 +0300 @@ -268,5 +268,6 @@ void auth_request_refresh_last_access(struct auth_request *request); void auth_str_append(string_t *dest, const char *key, const char *value); +bool auth_request_username_accepted(const char *const *filter, const char *username); #endif
--- a/src/auth/auth-settings.c Thu Apr 27 11:53:13 2017 +0300 +++ b/src/auth/auth-settings.c Fri Apr 28 12:51:20 2017 +0300 @@ -114,6 +114,7 @@ DEF(SET_STR, default_fields), DEF(SET_STR, override_fields), DEF(SET_STR, mechanisms), + DEF(SET_STR, username_filter), DEF(SET_ENUM, skip), DEF(SET_ENUM, result_success), @@ -135,6 +136,7 @@ .default_fields = "", .override_fields = "", .mechanisms = "", + .username_filter = "", .skip = "never:authenticated:unauthenticated", .result_success = "return-ok:return:return-fail:continue:continue-ok:continue-fail",
--- a/src/auth/auth-settings.h Thu Apr 27 11:53:13 2017 +0300 +++ b/src/auth/auth-settings.h Fri Apr 28 12:51:20 2017 +0300 @@ -11,6 +11,7 @@ const char *default_fields; const char *override_fields; const char *mechanisms; + const char *username_filter; const char *skip; const char *result_success;
--- a/src/auth/passdb.c Thu Apr 27 11:53:13 2017 +0300 +++ b/src/auth/passdb.c Fri Apr 28 12:51:20 2017 +0300 @@ -231,6 +231,11 @@ passdb->mechanisms = (const char* const*)p_strsplit_spaces(pool, set->mechanisms, " ,"); } + if (*set->username_filter == '\0') { + passdb->username_filter = NULL; + } else { + passdb->username_filter = (const char* const*)p_strsplit_spaces(pool, set->username_filter, " ,"); + } array_append(&passdb_modules, &passdb, 1); return passdb; }
--- a/src/auth/passdb.h Thu Apr 27 11:53:13 2017 +0300 +++ b/src/auth/passdb.h Fri Apr 28 12:51:20 2017 +0300 @@ -64,6 +64,8 @@ const char *default_pass_scheme; /* Supported authentication mechanisms, NULL is all, [NULL] is none*/ const char *const *mechanisms; + /* Username filter, NULL is no filter */ + const char *const *username_filter; /* If blocking is set to TRUE, use child processes to access this passdb. */