diff options
author | Sergey Poznyakoff <gray@gnu.org.ua> | 2017-12-22 15:22:14 +0200 |
---|---|---|
committer | Sergey Poznyakoff <gray@gnu.org.ua> | 2017-12-22 15:25:58 +0200 |
commit | 55620228a87786860e5eeabbab146a835e9830cf (patch) | |
tree | 3692518804feccff77aae50cf1ea3614ccb639be /pam_fshadow | |
parent | fc8bf4028f468848ab00efb41e6c2a76be2174c9 (diff) | |
download | pam-modules-55620228a87786860e5eeabbab146a835e9830cf.tar.gz pam-modules-55620228a87786860e5eeabbab146a835e9830cf.tar.bz2 |
pam_fshadow: allow the user to use arbitrary group numbers for username and domain parts.
New options username-index and domain-index are used to indicate
indices of the parenthesized groups used to extract the user and
the domain name. The default corresponds to 'user-index=1 domain-index=1'.
Additionally, change the behavior in case if the user name doesn't
match the regexp. Previous versions would fall back to plain authentication
in this case. New behavior is to reject access.
* pam_fshadow/pam_fshadow.c (pam_opt): New options
username-index and domain-index.
(pam_sm_authenticate): Move username splitting into a separate
function.
* doc/pam_fshadow.8in: Document the new options.
Diffstat (limited to 'pam_fshadow')
-rw-r--r-- | pam_fshadow/pam_fshadow.c | 120 |
1 files changed, 79 insertions, 41 deletions
diff --git a/pam_fshadow/pam_fshadow.c b/pam_fshadow/pam_fshadow.c index 058dd44..3dd07f5 100644 --- a/pam_fshadow/pam_fshadow.c +++ b/pam_fshadow/pam_fshadow.c @@ -103,15 +103,15 @@ fgetpwent(FILE *fp) #define CNTL_REGEX 0x0080 #define CNTL_REVERT_INDEX 0x0100 -char *sysconfdir = SYSCONFDIR; +static regex_t rexp; +static char *sysconfdir = SYSCONFDIR; static int cntl_flags = CNTL_PASSWD|CNTL_SHADOW; static long debug_level = 0; -static regex_t rexp; static const char *regex_str = NULL; static int regex_flags = REG_EXTENDED; -static int username_index = 1; -static int domain_index = 2; +static long username_index = 1; +static long domain_index = 2; struct pam_opt pam_opt[] = { { PAM_OPTSTR(debug), pam_opt_long, &debug_level }, @@ -139,6 +139,8 @@ struct pam_opt pam_opt[] = { { .value = CNTL_SHADOW } }, { PAM_OPTSTR(revert-index), pam_opt_bool, &cntl_flags, { .value = CNTL_REVERT_INDEX } }, + { PAM_OPTSTR(username-index), pam_opt_long, &username_index }, + { PAM_OPTSTR(domain-index), pam_opt_long, &domain_index }, { NULL } }; @@ -162,13 +164,23 @@ _pam_parse(pam_handle_t *pamh, int argc, const char **argv) "either passwd or shadow must be true"); return PAM_AUTHINFO_UNAVAIL; } + if (username_index <= 0) { + _pam_log(LOG_CRIT, "username-index out of range"); + return PAM_AUTHINFO_UNAVAIL; + } + if (domain_index <= 0) { + _pam_log(LOG_CRIT, "domain-index out of range"); + return PAM_AUTHINFO_UNAVAIL; + } + if (cntl_flags & CNTL_REVERT_INDEX) { - username_index = 2; - domain_index = 1; + long t = username_index; + username_index = domain_index; + domain_index = t; } if (regex_str) { int rc; - if (rc = regcomp(&rexp, regex_str, regex_flags)) { + if ((rc = regcomp(&rexp, regex_str, regex_flags))) { size_t s = regerror(rc, &rexp, NULL, 0); char *buf = malloc (s); if (buf) { @@ -182,11 +194,16 @@ _pam_parse(pam_handle_t *pamh, int argc, const char **argv) "cannot compile regex `%s'", regex_str); retval = PAM_AUTHINFO_UNAVAIL; - } else if (rexp.re_nsub != 2) { - _pam_log(LOG_NOTICE, - "invalid regular expression `%s': " - "must contain two reference groups", - regex_str); + } else if (!(username_index <= rexp.re_nsub + && domain_index <= rexp.re_nsub)) { + if (username_index > rexp.re_nsub) + _pam_log(LOG_NOTICE, + "not enough parenthesized groups" + " to satisfy username-index"); + if (domain_index > rexp.re_nsub) + _pam_log(LOG_NOTICE, + "not enough parenthesized groups" + " to satisfy domain-index"); regfree(&rexp); retval = PAM_AUTHINFO_UNAVAIL; } else @@ -438,11 +455,50 @@ copy_backref (pam_handle_t *pamh, const char *name, /* --- authentication management functions (only) --- */ +static int +translate(pam_handle_t *pamh, char const *input, + char **ret_username, char **ret_confdir) +{ + size_t nmatch = (domain_index > username_index + ? domain_index : username_index) + 1; + regmatch_t *rmatch; + int rc; + + rmatch = calloc(nmatch, sizeof(rmatch[0])); + if (!rmatch) { + _pam_log(LOG_ERR, "out of memory"); + return PAM_SERVICE_ERR; + } + + if (regexec(&rexp, input, nmatch, rmatch, 0) == 0) { + char *domain; + + if ((rc = copy_backref(pamh, "DOMAIN", input, rmatch, + domain_index, &domain)) == PAM_SUCCESS + && ((rc = copy_backref(pamh, "USERNAME", input, rmatch, + username_index, ret_username)) + == PAM_SUCCESS)) { + *ret_confdir = mkfilename(sysconfdir, domain); + pam_set_data(pamh, "CONFDIR", + (void *)*ret_confdir, gray_cleanup_string); + } + } else { + DEBUG(1,("user name `%s' does not match regular " + "expression `%s'", + input, + regex_str)); + rc = PAM_AUTH_ERR; + } + free(rmatch); + return rc; +} + PAM_EXTERN int pam_sm_authenticate(pam_handle_t *pamh, int flags, int argc, const char **argv) { - const char *username; + const char *input_username; + char *username; char *password; int retval = PAM_AUTH_ERR; int rc; @@ -455,8 +511,8 @@ pam_sm_authenticate(pam_handle_t *pamh, int flags, confdir = sysconfdir; /* Get the username */ - retval = pam_get_user(pamh, &username, NULL); - if (retval != PAM_SUCCESS || !username) { + retval = pam_get_user(pamh, &input_username, NULL); + if (retval != PAM_SUCCESS || !input_username) { DEBUG(1,("can not get the username")); if (cntl_flags & CNTL_REGEX) regfree(&rexp); @@ -464,39 +520,21 @@ pam_sm_authenticate(pam_handle_t *pamh, int flags, } if (cntl_flags & CNTL_REGEX) { - regmatch_t rmatch[3]; - if (regexec(&rexp, username, 3, rmatch, 0) == 0) { - char *domain; - - rc = copy_backref(pamh, "DOMAIN", username, rmatch, - domain_index, &domain); - if (rc != PAM_SUCCESS) - return rc; - rc = copy_backref(pamh, "USERNAME", username, rmatch, - username_index, (char **) &username); - if (rc != PAM_SUCCESS) - return rc; - confdir = mkfilename(sysconfdir, domain); - pam_set_data(pamh, "CONFDIR", - (void *)confdir, gray_cleanup_string); - } else { - DEBUG(1,("user name `%s' does not match regular " - "expression `%s'", - username, - regex_str)); - } + retval = translate(pamh, input_username, &username, &confdir); regfree(&rexp); + } else { + retval = PAM_SUCCESS; + username = (char *) input_username; + confdir = sysconfdir; } + + if (retval != PAM_SUCCESS) + return retval; /* Get the password */ if (_pam_get_password(pamh, &password, "Password:")) return PAM_SERVICE_ERR; - if (retval != PAM_SUCCESS) { - _pam_log(LOG_ERR, "Could not retrive user's password"); - return -2; - } - if (cntl_flags & CNTL_PASSWD) retval = verify_user_acct(confdir, username, &pwstr); else |