aboutsummaryrefslogtreecommitdiff
path: root/pam_fshadow
diff options
context:
space:
mode:
authorSergey Poznyakoff <gray@gnu.org.ua>2017-12-22 15:22:14 +0200
committerSergey Poznyakoff <gray@gnu.org.ua>2017-12-22 15:25:58 +0200
commit55620228a87786860e5eeabbab146a835e9830cf (patch)
tree3692518804feccff77aae50cf1ea3614ccb639be /pam_fshadow
parentfc8bf4028f468848ab00efb41e6c2a76be2174c9 (diff)
downloadpam-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.c120
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

Return to:

Send suggestions and report system problems to the System administrator.