diff options
Diffstat (limited to 'modules/pam_userdb/pam_userdb.c')
-rw-r--r-- | modules/pam_userdb/pam_userdb.c | 110 |
1 files changed, 89 insertions, 21 deletions
diff --git a/modules/pam_userdb/pam_userdb.c b/modules/pam_userdb/pam_userdb.c index 297403b0..71012e57 100644 --- a/modules/pam_userdb/pam_userdb.c +++ b/modules/pam_userdb/pam_userdb.c @@ -25,6 +25,8 @@ #ifdef HAVE_NDBM_H # include <ndbm.h> +#elif defined(HAVE_GDBM_H) +# include <gdbm.h> #else # ifdef HAVE_DB_H # define DB_DBM_HSEARCH 1 /* use the dbm interface */ @@ -39,6 +41,13 @@ #include <security/pam_ext.h> #include <security/_pam_macros.h> #include "pam_inline.h" +#include "pam_i18n.h" + +#ifndef HAVE_GDBM_H +# define COND_UNUSED UNUSED +#else +# define COND_UNUSED +#endif /* HAVE_GDBM_H */ /* * Conversation function to obtain the user's password @@ -129,6 +138,65 @@ _pam_parse (pam_handle_t *pamh, int argc, const char **argv, return ctrl; } +/* + * Database abstraction functions + */ +static void * +db_open(const char *database, mode_t file_mode) +{ +#ifdef HAVE_GDBM_H + return gdbm_open(database, 4096, GDBM_READER, file_mode, NULL); +#else + return dbm_open(database, O_RDONLY, file_mode); +#endif /* HAVE_GDBM_H */ +} + +static datum +db_firstkey(void *dbm) +{ +#ifdef HAVE_GDBM_H + return gdbm_firstkey(dbm); +#else + return dbm_firstkey(dbm); +#endif /* HAVE_GDBM_H */ +} + +static datum +db_nextkey(void *dbm, datum key COND_UNUSED) +{ +#ifdef HAVE_GDBM_H + return gdbm_nextkey(dbm, key); +#else + return dbm_nextkey(dbm); +#endif /* HAVE_GDBM_H */ +} + +static datum +db_fetch(void *dbm, datum key) +{ +#ifdef HAVE_GDBM_H + return gdbm_fetch(dbm, key); +#else + return dbm_fetch(dbm, key); +#endif /* HAVE_GDBM_H */ +} + +static int +db_close(void *dbm) +{ +#ifdef HAVE_GDBM_H +# ifdef GDBM_CLOSE_RETURNS_INT + return gdbm_close(dbm); +# else + gdbm_close(dbm); + return 0; +# endif +#else + dbm_close(dbm); + return 0; +#endif /* HAVE_GDBM_H */ +} + /* * Looks up a user name in a database and checks the password @@ -143,11 +211,15 @@ static int user_lookup (pam_handle_t *pamh, const char *database, const char *cryptmode, const char *user, const char *pass, int ctrl) { +#ifdef HAVE_GDBM_H + GDBM_FILE *dbm; +#else DBM *dbm; +#endif datum key, data; /* Open the DB file. */ - dbm = dbm_open(database, O_RDONLY, 0644); + dbm = db_open(database, 0644); if (dbm == NULL) { pam_syslog(pamh, LOG_ERR, "user_lookup: could not open database `%s': %m", database); @@ -157,9 +229,9 @@ user_lookup (pam_handle_t *pamh, const char *database, const char *cryptmode, /* dump out the database contents for debugging */ if (ctrl & PAM_DUMP_ARG) { pam_syslog(pamh, LOG_INFO, "Database dump:"); - for (key = dbm_firstkey(dbm); key.dptr != NULL; - key = dbm_nextkey(dbm)) { - data = dbm_fetch(dbm, key); + for (key = db_firstkey(dbm); key.dptr != NULL; + key = db_nextkey(dbm, key)) { + data = db_fetch(dbm, key); pam_syslog(pamh, LOG_INFO, "key[len=%d] = `%s', data[len=%d] = `%s'", key.dsize, key.dptr, data.dsize, data.dptr); @@ -180,7 +252,7 @@ user_lookup (pam_handle_t *pamh, const char *database, const char *cryptmode, } if (key.dptr) { - data = dbm_fetch(dbm, key); + data = db_fetch(dbm, key); pam_overwrite_n(key.dptr, key.dsize); free(key.dptr); } @@ -196,16 +268,11 @@ user_lookup (pam_handle_t *pamh, const char *database, const char *cryptmode, if (ctrl & PAM_KEY_ONLY_ARG) { - dbm_close (dbm); + db_close (dbm); return 0; /* found it, data contents don't matter */ } if (cryptmode && pam_str_skip_icase_prefix(cryptmode, "crypt") != NULL) { - - /* crypt(3) password storage */ - - char *cryptpw = NULL; - if (data.dsize < 13) { /* hash is too short */ pam_syslog(pamh, LOG_INFO, "password hash in database is too short"); @@ -219,13 +286,13 @@ user_lookup (pam_handle_t *pamh, const char *database, const char *cryptmode, if (pwhash == NULL) { pam_syslog(pamh, LOG_CRIT, "strndup failed: data.dptr"); } else { + char *cryptpw = NULL; #ifdef HAVE_CRYPT_R struct crypt_data *cdata = NULL; - cdata = malloc(sizeof(*cdata)); + cdata = calloc(1, sizeof(*cdata)); if (cdata == NULL) { pam_syslog(pamh, LOG_CRIT, "malloc failed: struct crypt_data"); } else { - cdata->initialized = 0; cryptpw = crypt_r(pass, pwhash, cdata); } #else @@ -244,14 +311,15 @@ user_lookup (pam_handle_t *pamh, const char *database, const char *cryptmode, } } #ifdef HAVE_CRYPT_R + pam_overwrite_object(cdata); free(cdata); +#else + pam_overwrite_string(cryptpw); #endif } pam_overwrite_string(pwhash); free(pwhash); } - - pam_overwrite_string(cryptpw); } else { /* Unknown password encryption method - @@ -275,7 +343,7 @@ user_lookup (pam_handle_t *pamh, const char *database, const char *cryptmode, } - dbm_close(dbm); + db_close(dbm); if (compare == 0) return 0; /* match */ else @@ -290,14 +358,14 @@ user_lookup (pam_handle_t *pamh, const char *database, const char *cryptmode, /* probably we should check dbm_error() here */ if ((ctrl & PAM_KEY_ONLY_ARG) == 0) { - dbm_close(dbm); + db_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); + for (key = db_firstkey(dbm); key.dptr != NULL; - key = dbm_nextkey(dbm)) { + key = db_nextkey(dbm, key)) { int compare; /* first compare the user portion (case sensitive) */ compare = strncmp(key.dptr, user, strlen(user)); @@ -322,12 +390,12 @@ user_lookup (pam_handle_t *pamh, const char *database, const char *cryptmode, } } if (compare == 0) { - dbm_close(dbm); + db_close(dbm); return 0; /* match */ } } } - dbm_close(dbm); + db_close(dbm); if (saw_user) return -1; /* saw the user, but password mismatch */ else |