From 6fb01537462a326a139f0c2d975145b26cd54bbe Mon Sep 17 00:00:00 2001 From: Thorsten Kukuk Date: Tue, 28 Sep 2004 13:48:45 +0000 Subject: Relevant BUGIDs: Purpose of commit: Commit summary: --------------- bugfix: * Merge patches from Red Hat (Bug 477000 and other - kukuk) * Fix pam_rhosts option parsing (Bug 922648 - kukuk) --- modules/Makefile | 2 +- modules/Simple.Rules | 2 + modules/pam_filter/pam_filter.c | 8 +- modules/pam_limits/Makefile | 3 + modules/pam_pwdb/Makefile | 5 +- modules/pam_rhosts/pam_rhosts_auth.c | 20 +-- modules/pam_unix/Makefile | 23 +++- modules/pam_unix/bigcrypt_main.c | 18 +++ modules/pam_userdb/README | 29 +++- modules/pam_userdb/conv.c | 2 - modules/pam_userdb/create.pl | 2 +- modules/pam_userdb/pam_userdb.c | 258 ++++++++++++++++++++++++++--------- modules/pam_userdb/pam_userdb.h | 3 + 13 files changed, 289 insertions(+), 86 deletions(-) create mode 100644 modules/pam_unix/bigcrypt_main.c (limited to 'modules') diff --git a/modules/Makefile b/modules/Makefile index 93891029..d16dedcf 100644 --- a/modules/Makefile +++ b/modules/Makefile @@ -8,7 +8,7 @@ include ../Make.Rules -MODDIRS=$(shell /bin/ls -d pam_*) +MODDIRS=$(shell /bin/ls -d pam_*/Makefile | cut -f1 -d/) all: @echo building the static modutil library diff --git a/modules/Simple.Rules b/modules/Simple.Rules index 97f419a8..c12ede3a 100644 --- a/modules/Simple.Rules +++ b/modules/Simple.Rules @@ -13,6 +13,8 @@ # $(MODULE_SIMPLE_EXTRAFILES) - other files to build (no .c suffix) # +-include ../Make.Rules + LIBFILES = $(TITLE) $(MODULE_SIMPLE_EXTRAFILES) LIBSRC = $(addsuffix .c,$(LIBFILES)) LIBOBJ = $(addsuffix .o,$(LIBFILES)) diff --git a/modules/pam_filter/pam_filter.c b/modules/pam_filter/pam_filter.c index e9a0494b..d3462f40 100644 --- a/modules/pam_filter/pam_filter.c +++ b/modules/pam_filter/pam_filter.c @@ -150,7 +150,7 @@ static int process_args(pam_handle_t *pamh /* the "ARGS" variable */ -#define ARGS_OFFSET 5 /* sizeof('ARGS='); */ +#define ARGS_OFFSET 5 /* strlen('ARGS='); */ #define ARGS_NAME "ARGS=" size += ARGS_OFFSET; @@ -174,7 +174,7 @@ static int process_args(pam_handle_t *pamh /* the "SERVICE" variable */ -#define SERVICE_OFFSET 8 /* sizeof('SERVICE='); */ +#define SERVICE_OFFSET 8 /* strlen('SERVICE='); */ #define SERVICE_NAME "SERVICE=" retval = pam_get_item(pamh, PAM_SERVICE, (const void **)&tmp); @@ -204,7 +204,7 @@ static int process_args(pam_handle_t *pamh /* the "USER" variable */ -#define USER_OFFSET 5 /* sizeof('USER='); */ +#define USER_OFFSET 5 /* strlen('USER='); */ #define USER_NAME "USER=" tmp = NULL; @@ -231,7 +231,7 @@ static int process_args(pam_handle_t *pamh /* the "USER" variable */ -#define TYPE_OFFSET 5 /* sizeof('TYPE='); */ +#define TYPE_OFFSET 5 /* strlen('TYPE='); */ #define TYPE_NAME "TYPE=" size = TYPE_OFFSET+strlen(type); diff --git a/modules/pam_limits/Makefile b/modules/pam_limits/Makefile index 0a481fe8..5aeb73ce 100644 --- a/modules/pam_limits/Makefile +++ b/modules/pam_limits/Makefile @@ -27,6 +27,9 @@ endif include ../Simple.Rules +#else +#include ../dont_makefile +#endif else include ../dont_makefile diff --git a/modules/pam_pwdb/Makefile b/modules/pam_pwdb/Makefile index 2b581dcd..fa0e1b02 100644 --- a/modules/pam_pwdb/Makefile +++ b/modules/pam_pwdb/Makefile @@ -17,6 +17,9 @@ EXTRAS += -DCHKPWD_HELPER=\"$(SUPLEMENTED)/$(CHKPWD)\" ifeq ($(HAVE_LIBCRYPT),yes) EXTRALS += -lcrypt endif +ifeq ($(HAVE_LIBNSL),yes) + EXTRALS += -lnsl +endif TITLE=pam_pwdb CHKPWD=pwdb_chkpwd @@ -53,7 +56,7 @@ info: $(CHKPWD): pwdb_chkpwd.o md5_good.o md5_broken.o \ md5_crypt_good.o md5_crypt_broken.o - $(CC) -o $(CHKPWD) $^ -lpwdb + $(CC) $(CFLAGS) -o $(CHKPWD) $^ $(LDFLAGS) -lpwdb $(EXTRALS) pwdb_chkpwd.o: pwdb_chkpwd.c pam_unix_md.-c bigcrypt.-c diff --git a/modules/pam_rhosts/pam_rhosts_auth.c b/modules/pam_rhosts/pam_rhosts_auth.c index 374318dc..b41b708d 100644 --- a/modules/pam_rhosts/pam_rhosts_auth.c +++ b/modules/pam_rhosts/pam_rhosts_auth.c @@ -178,7 +178,7 @@ static void set_option (struct _options *opts, const char *arg) return; } - if (strcmp(arg, "superuser=") == 0) { + if (strncmp(arg, "superuser=", sizeof("superuser=")-1) == 0) { opts->superuser = arg+sizeof("superuser=")-1; return; } @@ -293,7 +293,7 @@ __icheckhost (pam_handle_t *pamh, struct _options *opts, U32 raddr hp = gethostbyname(lhost); if (hp == NULL) return (0); - + /* Spin through ip addresses. */ for (pp = hp->h_addr_list; *pp; ++pp) if (!memcmp (&raddr, *pp, sizeof (U32))) @@ -408,7 +408,7 @@ __ivaliduser (pam_handle_t *pamh, struct _options *opts, user = p; /* this is the user's name */ while (*p && !isspace(*p)) ++p; /* find end of user's name */ - } else + } else user = p; *p = '\0'; /* terminate username (+host?) */ @@ -480,7 +480,7 @@ pam_iruserok(pam_handle_t *pamh, No hosts.equiv file on system. } */ } - + if ( opts->opt_no_rhosts ) return 1; @@ -490,10 +490,10 @@ pam_iruserok(pam_handle_t *pamh, pwd = _pammodutil_getpwnam(pamh, luser); if (pwd == NULL) { - /* + /* * luser is assumed to be valid because of an earlier check for uid = 0 * we don't log this error twice. However, this shouldn't happen ! - * --cristiang + * --cristiang */ return(1); } @@ -652,9 +652,9 @@ pam_ruserok (pam_handle_t *pamh, */ static int _pam_auth_rhosts (pam_handle_t *pamh, - int flags, + int flags, int argc, - const char **argv) + const char **argv) { int retval; const char *luser = NULL; @@ -745,9 +745,9 @@ static int _pam_auth_rhosts (pam_handle_t *pamh, /* --- authentication management functions --- */ PAM_EXTERN -int pam_sm_authenticate (pam_handle_t *pamh, +int pam_sm_authenticate (pam_handle_t *pamh, int flags, - int argc, + int argc, const char **argv) { int retval; diff --git a/modules/pam_unix/Makefile b/modules/pam_unix/Makefile index 3fe0e8ae..24ffd4b5 100644 --- a/modules/pam_unix/Makefile +++ b/modules/pam_unix/Makefile @@ -18,6 +18,19 @@ include ../../Make.Rules #USE_CRACKLIB=-D"USE_CRACKLIB" #endif +ifeq ($(shell if [ -f /usr/lib/cracklib_dict.hwm ]; then echo yes ; fi),yes) + CRACKLIB_DICTPATH=/usr/lib/cracklib_dict +else + CRACKLIB_DICTPATH=/usr/share/dict/cracklib_dict +endif +EXTRAS += -DCRACKLIB_DICTS=\"$(CRACKLIB_DICTPATH)\" + +ifeq ($(HAVE_LIBCRYPT),yes) + EXTRALS += -lcrypt +endif +ifeq ($(HAVE_LIBNSL),yes) + EXTRALS += -lnsl +endif # do you want to use lckpwdf? ifeq ($(WITH_LCKPWDF),yes) USE_LCKPWDF=-D"USE_LCKPWDF" @@ -37,6 +50,8 @@ endif CHKPWD=unix_chkpwd +BIGCRYPT=bigcrypt + EXTRAS += -DCHKPWD_HELPER=\"$(SUPLEMENTED)/$(CHKPWD)\" LINK_PAMMODUTILS = -L../pammodutil -lpammodutil @@ -74,7 +89,8 @@ endif ########################### don't edit below ####################### -all: dirs info $(PLUS) $(LIBSHARED) $(LIBSTATIC) $(CHKPWD) register +all: dirs info $(PLUS) $(LIBSHARED) $(LIBSTATIC) $(CHKPWD) $(BIGCRYPT) \ + register dynamic/%.o : %.c $(CC) $(CFLAGS) $(DYNAMIC) $(CPPFLAGS) $(TARGET_ARCH) -c $< -o $@ @@ -125,7 +141,10 @@ endif $(CHKPWD): unix_chkpwd.o md5_good.o md5_broken.o \ md5_crypt_good.o md5_crypt_broken.o \ bigcrypt.o - $(CC) -o $(CHKPWD) $^ $(LDLIBS) $(LIBCRYPT) + $(CC) $(CFLAGS) -o $(CHKPWD) $^ $(LDLIBS) $(LIBCRYPT) + +$(BIGCRYPT): bigcrypt_main.o bigcrypt.o + $(CC) -o $(BIGCRYPT) $^ $(LDLIBS) $(LIBCRYPT) unix_chkpwd.o: unix_chkpwd.c $(CC) $(CFLAGS) $(CPPFLAGS) $(TARGET_ARCH) -c $< -o $@ diff --git a/modules/pam_unix/bigcrypt_main.c b/modules/pam_unix/bigcrypt_main.c new file mode 100644 index 00000000..70819072 --- /dev/null +++ b/modules/pam_unix/bigcrypt_main.c @@ -0,0 +1,18 @@ +#include +#include + +extern const char *bigcrypt(const char *password, const char *salt); + +int +main(int argc, char **argv) +{ + if (argc < 3) { + fprintf(stderr, "Usage: %s password salt\n", + strchr(argv[0], '/') ? + (strchr(argv[0], '/') + 1) : + argv[0]); + return 0; + } + fprintf(stdout, "%s\n", bigcrypt(argv[1], argv[2])); + return 0; +} diff --git a/modules/pam_userdb/README b/modules/pam_userdb/README index 9fa6519d..fc56cfa0 100644 --- a/modules/pam_userdb/README +++ b/modules/pam_userdb/README @@ -1,6 +1,7 @@ pam_userdb: Look up users in a .db database and verify their password against - what is contained in that database. + what is contained in that database. The database will have been + created using db_load. RECOGNIZED ARGUMENTS: debug write a message to syslog indicating success or @@ -8,7 +9,9 @@ RECOGNIZED ARGUMENTS: db=[path] use the [path] database for performing lookup. There is no default; the module will return PAM_IGNORE if - no database is provided. + no database is provided. Some versions of DB will + automatically append ".db" to whatever pathname you + supply here. crypt=[mode] indicates whether encrypted or plaintext passwords are stored in the database. If [mode] is "crypt", @@ -24,8 +27,28 @@ RECOGNIZED ARGUMENTS: dump dump all the entries in the database to the log (eek, don't do this by default!) + use_authtok use the authentication token previously obtained by + another module that did the conversation with the + application. If this token can not be obtained then + the module will try to converse again. This option can + be used for stacking different modules that need to + deal with the authentication tokens. + + unknown_ok do not return error when checking for a user that is + not in the database. This can be used to stack more + than one pam_userdb module that will check a + username/password pair in more than a database. + + key_only the username and password are concatenated together + in the database hash as 'username-password' with a + random value. if the concatenation of the username and + password with a dash in the middle returns any result, + the user is valid. this is useful in cases where + the username may not be unique but the username and + password pair are. + MODULE SERVICES PROVIDED: - auth _authetication and _setcred (blank) + auth _authentication and _setcred (blank) EXAMPLE USE: auth sufficient pam_userdb.so icase db=/tmp/dbtest.db diff --git a/modules/pam_userdb/conv.c b/modules/pam_userdb/conv.c index 0f13d03a..de5d12f2 100644 --- a/modules/pam_userdb/conv.c +++ b/modules/pam_userdb/conv.c @@ -5,8 +5,6 @@ /* $Id */ /* Copyright at the end of the file */ -#define _BSD_SOURCE - #include #include diff --git a/modules/pam_userdb/create.pl b/modules/pam_userdb/create.pl index 046b55f0..224204b7 100644 --- a/modules/pam_userdb/create.pl +++ b/modules/pam_userdb/create.pl @@ -7,7 +7,7 @@ use DB_File; my $database = $ARGV[0]; -die "Use: check,pl \n" unless ($database); +die "Use: create.pl \n" unless ($database); print "Using database: $database\n"; my %lusers = (); diff --git a/modules/pam_userdb/pam_userdb.c b/modules/pam_userdb/pam_userdb.c index 30f1e578..a0a5b8b5 100644 --- a/modules/pam_userdb/pam_userdb.c +++ b/modules/pam_userdb/pam_userdb.c @@ -1,5 +1,5 @@ /* pam_userdb module */ - + /* * $Id$ * Written by Cristian Gafton 1996/09/10 @@ -8,6 +8,7 @@ #include +#include #include #include #include @@ -56,39 +57,53 @@ static void _pam_log(int err, const char *format, ...) closelog(); } -char * database = NULL; -char * cryptmode = NULL; -static int ctrl = 0; - -static int _pam_parse(int argc, const char **argv) +static int +_pam_parse (int argc, const char **argv, + char **database, char **cryptmode) { - /* step through arguments */ - for (ctrl = 0; argc-- > 0; ++argv) { - - /* generic options */ - - if (!strcmp(*argv,"debug")) - ctrl |= PAM_DEBUG_ARG; - else if (!strcasecmp(*argv, "icase")) - ctrl |= PAM_ICASE_ARG; - else if (!strcasecmp(*argv, "dump")) - ctrl |= PAM_DUMP_ARG; - else if (!strncasecmp(*argv,"db=", 3)) { - database = strdup((*argv) + 3); - if (database == NULL) - _pam_log(LOG_ERR, "pam_parse: could not parse argument \"%s\"", - *argv); - } else if (!strncasecmp(*argv,"crypt=", 6)) { - cryptmode = strdup((*argv) + 6); - if (cryptmode == NULL) - _pam_log(LOG_ERR, "pam_parse: could not parse argument \"%s\"", - *argv); - } else { - _pam_log(LOG_ERR, "pam_parse: unknown option; %s", *argv); - } - } + int ctrl; + + *database = NULL; + *cryptmode = NULL; + + /* step through arguments */ + for (ctrl = 0; argc-- > 0; ++argv) + { + /* generic options */ + + if (!strcmp(*argv,"debug")) + ctrl |= PAM_DEBUG_ARG; + else if (!strcasecmp(*argv, "icase")) + ctrl |= PAM_ICASE_ARG; + else if (!strcasecmp(*argv, "dump")) + ctrl |= PAM_DUMP_ARG; + else if (!strcasecmp(*argv, "unknown_ok")) + ctrl |= PAM_UNKNOWN_OK_ARG; + else if (!strcasecmp(*argv, "key_only")) + ctrl |= PAM_KEY_ONLY_ARG; + else if (!strncasecmp(*argv,"db=", 3)) + { + *database = strdup((*argv) + 3); + if ((*database == NULL) || (strlen (*database) == 0)) + _pam_log(LOG_ERR, + "pam_parse: could not parse argument \"%s\"", + *argv); + } + else if (!strncasecmp(*argv,"crypt=", 6)) + { + *cryptmode = strdup((*argv) + 6); + if ((*cryptmode == NULL) || (strlen (*cryptmode) == 0)) + _pam_log(LOG_ERR, + "pam_parse: could not parse argument \"%s\"", + *argv); + } + else + { + _pam_log(LOG_ERR, "pam_parse: unknown option; %s", *argv); + } + } - return ctrl; + return ctrl; } @@ -101,7 +116,9 @@ static int _pam_parse(int argc, const char **argv) * -1 = Password incorrect * -2 = System error */ -static int user_lookup(const char *user, const char *pass) +static int +user_lookup (const char *database, const char *cryptmode, + const char *user, const char *pass, int ctrl) { DBM *dbm; datum key, data; @@ -114,7 +131,8 @@ static int user_lookup(const char *user, const char *pass) return -2; } - if (ctrl &PAM_DUMP_ARG) { + /* dump out the database contents for debugging */ + if (ctrl & PAM_DUMP_ARG) { _pam_log(LOG_INFO, "Database dump:"); for (key = dbm_firstkey(dbm); key.dptr != NULL; key = dbm_nextkey(dbm)) { @@ -122,14 +140,19 @@ static int user_lookup(const char *user, const char *pass) _pam_log(LOG_INFO, "key[len=%d] = `%s', data[len=%d] = `%s'", key.dsize, key.dptr, data.dsize, data.dptr); } - } - /* do some more init work */ + } + /* do some more init work */ memset(&key, 0, sizeof(key)); memset(&data, 0, sizeof(data)); - key.dptr = x_strdup(user); - key.dsize = strlen(user); - user = NULL; + if (ctrl & PAM_KEY_ONLY_ARG) { + key.dptr = malloc(strlen(user) + 1 + strlen(pass) + 1); + sprintf(key.dptr, "%s-%s", user, pass); + key.dsize = strlen(key.dptr); + } else { + key.dptr = x_strdup(user); + key.dsize = strlen(user); + } if (key.dptr) { data = dbm_fetch(dbm, key); @@ -144,7 +167,13 @@ static int user_lookup(const char *user, const char *pass) if (data.dptr != NULL) { int compare = 0; - + + if (ctrl & PAM_KEY_ONLY_ARG) + { + dbm_close (dbm); + return 0; /* found it, data contents don't matter */ + } + if (strncasecmp(cryptmode, "crypt", 5) == 0) { /* crypt(3) password storage */ @@ -166,7 +195,7 @@ static int user_lookup(const char *user, const char *pass) compare = strncasecmp (data.dptr, cryptpw, data.dsize); } else { compare = -2; - if (ctrl & PAM_DEBUG_ARG) { + if (ctrl & PAM_DEBUG_ARG) { _pam_log(LOG_INFO, "crypt() returned NULL"); } }; @@ -174,20 +203,20 @@ static int user_lookup(const char *user, const char *pass) }; } else { - + /* Unknown password encryption method - * default to plaintext password storage */ if (strlen(pass) != data.dsize) { - compare = 1; + compare = 1; /* wrong password len -> wrong password */ } else if (ctrl & PAM_ICASE_ARG) { compare = strncasecmp(data.dptr, pass, data.dsize); } else { compare = strncmp(data.dptr, pass, data.dsize); } - if (strncasecmp(cryptmode, "none", 4) && ctrl & PAM_DEBUG_ARG) { + if (strncasecmp(cryptmode, "none", 4) && ctrl & PAM_DEBUG_ARG) { _pam_log(LOG_INFO, "invalid value for crypt parameter: %s", cryptmode); _pam_log(LOG_INFO, "defaulting to plaintext password mode"); @@ -201,13 +230,58 @@ static int user_lookup(const char *user, const char *pass) else return -1; /* wrong */ } else { - if (ctrl & PAM_DEBUG_ARG) { + int saw_user = 0; + + if (ctrl & PAM_DEBUG_ARG) { _pam_log(LOG_INFO, "error returned by dbm_fetch: %s", strerror(errno)); } - dbm_close(dbm); + /* probably we should check dbm_error() here */ - return 1; /* not found */ + + if ((ctrl & PAM_KEY_ONLY_ARG) == 0) { + dbm_close(dbm); + return 1; /* not key_only, so no entry => no entry for the user */ + } + + /* now handle the key_only case */ + for (key = dbm_firstkey(dbm); + key.dptr != NULL; + key = dbm_nextkey(dbm)) { + int compare; + /* first compare the user portion (case sensitive) */ + compare = strncmp(key.dptr, user, strlen(user)); + if (compare == 0) { + /* assume failure */ + compare = -1; + /* if we have the divider where we expect it to be... */ + if (key.dptr[strlen(user)] == '-') { + saw_user = 1; + if (key.dsize == strlen(user) + 1 + strlen(pass)) { + if (ctrl & PAM_ICASE_ARG) { + /* compare the password portion (case insensitive)*/ + compare = strncasecmp(key.dptr + strlen(user) + 1, + pass, + strlen(pass)); + } else { + /* compare the password portion (case sensitive) */ + compare = strncmp(key.dptr + strlen(user) + 1, + pass, + strlen(pass)); + } + } + } + if (compare == 0) { + dbm_close(dbm); + return 0; /* match */ + } + } + } + dbm_close(dbm); + if (saw_user) + return -1; /* saw the user, but password mismatch */ + else + return 1; /* not found */ } /* NOT REACHED */ @@ -222,10 +296,17 @@ int pam_sm_authenticate(pam_handle_t *pamh, int flags, { const char *username; const char *password; - int retval = PAM_AUTH_ERR; - + char *database = NULL; + char *cryptmode = NULL; + int retval = PAM_AUTH_ERR, ctrl; + /* parse arguments */ - ctrl = _pam_parse(argc, argv); + ctrl = _pam_parse(argc, argv, &database, &cryptmode); + if ((database == NULL) || (strlen(database) == 0)) { + if (ctrl & PAM_DEBUG_ARG) + _pam_log(LOG_DEBUG,"can not get the database name"); + return PAM_SERVICE_ERR; + } /* Get the username */ retval = pam_get_user(pamh, &username, NULL); @@ -234,32 +315,47 @@ int pam_sm_authenticate(pam_handle_t *pamh, int flags, _pam_log(LOG_DEBUG,"can not get the username"); return PAM_SERVICE_ERR; } - - /* Converse just to be sure we have the password */ + + /* Converse just to be sure we have a password */ retval = conversation(pamh); if (retval != PAM_SUCCESS) { _pam_log(LOG_ERR, "could not obtain password for `%s'", username); - return -2; + return PAM_CONV_ERR; + } + + /* Check if we got a password. The docs say that if we didn't have one, + * and use_authtok was specified as an argument, that we converse with the + * user anyway, so check for one and handle a failure for that case. If + * use_authtok wasn't specified, then we've already asked once and needn't + * do so again. */ + retval = pam_get_item(pamh, PAM_AUTHTOK, (const void **) &password); + if ((retval != PAM_SUCCESS) && ((ctrl & PAM_USE_AUTHTOK_ARG) != 0)) { + retval = conversation(pamh); + if (retval != PAM_SUCCESS) { + _pam_log(LOG_ERR, "could not obtain password for `%s'", + username); + return PAM_CONV_ERR; + } } - + /* Get the password */ retval = pam_get_item(pamh, PAM_AUTHTOK, (const void **)&password); if (retval != PAM_SUCCESS) { - _pam_log(LOG_ERR, "Could not retrive user's password"); + _pam_log(LOG_ERR, "Could not retrieve user's password"); return -2; } - + if (ctrl & PAM_DEBUG_ARG) _pam_log(LOG_INFO, "Verify user `%s' with password `%s'", username, password); - + /* Now use the username to look up password in the database file */ - retval = user_lookup(username, password); + retval = user_lookup(database, cryptmode, username, password, ctrl); switch (retval) { case -2: /* some sort of system error. The log was already printed */ - return PAM_SERVICE_ERR; + return PAM_SERVICE_ERR; case -1: /* incorrect password */ _pam_log(LOG_WARNING, @@ -296,9 +392,47 @@ int pam_sm_setcred(pam_handle_t *pamh, int flags, } PAM_EXTERN -int pam_sm_acct_mgmt(pam_handle_t *pamh, int flags, - int argc, const char **argv) +int pam_sm_acct_mgmt(pam_handle_t *pamh, int flags, int argc, const char **argv) { + const char *username; + char *database = NULL; + char *cryptmode = NULL; + int retval = PAM_AUTH_ERR, ctrl; + + /* parse arguments */ + ctrl = _pam_parse(argc, argv, &database, &cryptmode); + + /* Get the username */ + retval = pam_get_user(pamh, &username, NULL); + if ((retval != PAM_SUCCESS) || (!username)) { + if (ctrl & PAM_DEBUG_ARG) + _pam_log(LOG_DEBUG,"can not get the username"); + return PAM_SERVICE_ERR; + } + + /* Now use the username to look up password in the database file */ + retval = user_lookup(database, cryptmode, username, "", ctrl); + switch (retval) { + case -2: + /* some sort of system error. The log was already printed */ + return PAM_SERVICE_ERR; + case -1: + /* incorrect password, but we don't care */ + /* FALL THROUGH */ + case 0: + /* authentication succeeded. dumbest password ever. */ + return PAM_SUCCESS; + case 1: + /* the user does not exist in the database */ + return PAM_USER_UNKNOWN; + default: + /* we don't know anything about this return value */ + _pam_log(LOG_ERR, + "internal module error (retval = %d, user = `%s'", + retval, username); + return PAM_SERVICE_ERR; + } + return PAM_SUCCESS; } @@ -311,7 +445,7 @@ struct pam_module _pam_userdb_modstruct = { "pam_userdb", pam_sm_authenticate, pam_sm_setcred, - NULL, + pam_sm_acct_mgmt, NULL, NULL, NULL, diff --git a/modules/pam_userdb/pam_userdb.h b/modules/pam_userdb/pam_userdb.h index 911a7622..a371fa9f 100644 --- a/modules/pam_userdb/pam_userdb.h +++ b/modules/pam_userdb/pam_userdb.h @@ -10,6 +10,9 @@ #define PAM_DEBUG_ARG 0x0001 #define PAM_ICASE_ARG 0x0002 #define PAM_DUMP_ARG 0x0004 +#define PAM_USE_AUTHTOK_ARG 0x0008 +#define PAM_UNKNOWN_OK_ARG 0x0010 +#define PAM_KEY_ONLY_ARG 0x0020 /* Useful macros */ #define x_strdup(s) ( (s) ? strdup(s):NULL ) -- cgit v1.2.3