Changeset View
Changeset View
Standalone View
Standalone View
lib/libpam/modules/pam_unix/pam_unix.c
Show First 20 Lines • Show All 63 Lines • ▼ Show 20 Lines | |||||
#define PAM_SM_AUTH | #define PAM_SM_AUTH | ||||
#define PAM_SM_ACCOUNT | #define PAM_SM_ACCOUNT | ||||
#define PAM_SM_PASSWORD | #define PAM_SM_PASSWORD | ||||
#include <security/pam_appl.h> | #include <security/pam_appl.h> | ||||
#include <security/pam_modules.h> | #include <security/pam_modules.h> | ||||
#include <security/pam_mod_misc.h> | #include <security/pam_mod_misc.h> | ||||
#define PASSWORD_HASH "md5" | |||||
#define DEFAULT_WARN (2L * 7L * 86400L) /* Two weeks */ | #define DEFAULT_WARN (2L * 7L * 86400L) /* Two weeks */ | ||||
#define SALTSIZE 32 | |||||
#define LOCKED_PREFIX "*LOCKED*" | #define LOCKED_PREFIX "*LOCKED*" | ||||
#define LOCKED_PREFIX_LEN (sizeof(LOCKED_PREFIX) - 1) | #define LOCKED_PREFIX_LEN (sizeof(LOCKED_PREFIX) - 1) | ||||
static void makesalt(char []); | |||||
static char password_hash[] = PASSWORD_HASH; | |||||
#define PAM_OPT_LOCAL_PASS "local_pass" | #define PAM_OPT_LOCAL_PASS "local_pass" | ||||
#define PAM_OPT_NIS_PASS "nis_pass" | #define PAM_OPT_NIS_PASS "nis_pass" | ||||
/* | /* | ||||
* authentication management | * authentication management | ||||
*/ | */ | ||||
PAM_EXTERN int | PAM_EXTERN int | ||||
pam_sm_authenticate(pam_handle_t *pamh, int flags __unused, | pam_sm_authenticate(pam_handle_t *pamh, int flags __unused, | ||||
▲ Show 20 Lines • Show All 180 Lines • ▼ Show 20 Lines | |||||
PAM_EXTERN int | PAM_EXTERN int | ||||
pam_sm_chauthtok(pam_handle_t *pamh, int flags, | pam_sm_chauthtok(pam_handle_t *pamh, int flags, | ||||
int argc __unused, const char *argv[] __unused) | int argc __unused, const char *argv[] __unused) | ||||
{ | { | ||||
#ifdef YP | #ifdef YP | ||||
struct ypclnt *ypclnt; | struct ypclnt *ypclnt; | ||||
const void *yp_domain, *yp_server; | const void *yp_domain, *yp_server; | ||||
#endif | #endif | ||||
char salt[SALTSIZE + 1]; | char salt[256]; | ||||
size_t salt_sz; | |||||
login_cap_t *lc; | login_cap_t *lc; | ||||
struct passwd *pwd, *old_pwd; | struct passwd *pwd, *old_pwd; | ||||
const char *user, *old_pass, *new_pass; | const char *user, *old_pass, *new_pass; | ||||
char *encrypted; | char *encrypted; | ||||
time_t passwordtime; | time_t passwordtime; | ||||
int pfd, tfd, retval; | int pfd, tfd, retval; | ||||
const char *passwd_format; | |||||
if (openpam_get_option(pamh, PAM_OPT_AUTH_AS_SELF)) | if (openpam_get_option(pamh, PAM_OPT_AUTH_AS_SELF)) | ||||
user = getlogin(); | user = getlogin(); | ||||
else { | else { | ||||
retval = pam_get_user(pamh, &user, NULL); | retval = pam_get_user(pamh, &user, NULL); | ||||
if (retval != PAM_SUCCESS) | if (retval != PAM_SUCCESS) | ||||
return (retval); | return (retval); | ||||
} | } | ||||
▲ Show 20 Lines • Show All 87 Lines • ▼ Show 20 Lines | else if (flags & PAM_UPDATE_AUTHTOK) { | ||||
if (getuid() != 0 && new_pass[0] == '\0' && | if (getuid() != 0 && new_pass[0] == '\0' && | ||||
!openpam_get_option(pamh, PAM_OPT_NULLOK)) | !openpam_get_option(pamh, PAM_OPT_NULLOK)) | ||||
return (PAM_PERM_DENIED); | return (PAM_PERM_DENIED); | ||||
if ((old_pwd = pw_dup(pwd)) == NULL) | if ((old_pwd = pw_dup(pwd)) == NULL) | ||||
return (PAM_BUF_ERR); | return (PAM_BUF_ERR); | ||||
lc = login_getclass(pwd->pw_class); | lc = login_getclass(pwd->pw_class); | ||||
if (login_setcryptfmt(lc, password_hash, NULL) == NULL) | |||||
openpam_log(PAM_LOG_ERROR, | |||||
"can't set password cipher, relying on default"); | |||||
salt_sz = sizeof(salt); | |||||
passwd_format = login_getcapstr(lc, "passwd_format", "", NULL); | |||||
if (crypt_makesalt(salt, passwd_format, &salt_sz)) { | |||||
login_close(lc); | |||||
PAM_LOG("Unable to create salt for crypt(3) format: %s", | |||||
passwd_format); | |||||
return (PAM_SERVICE_ERR); | |||||
} | |||||
/* set password expiry date */ | /* set password expiry date */ | ||||
pwd->pw_change = 0; | pwd->pw_change = 0; | ||||
passwordtime = login_getcaptime(lc, "passwordtime", 0, 0); | passwordtime = login_getcaptime(lc, "passwordtime", 0, 0); | ||||
if (passwordtime > 0) | if (passwordtime > 0) | ||||
pwd->pw_change = time(NULL) + passwordtime; | pwd->pw_change = time(NULL) + passwordtime; | ||||
login_close(lc); | login_close(lc); | ||||
makesalt(salt); | |||||
pwd->pw_passwd = crypt(new_pass, salt); | pwd->pw_passwd = crypt(new_pass, salt); | ||||
#ifdef YP | #ifdef YP | ||||
switch (old_pwd->pw_fields & _PWF_SOURCE) { | switch (old_pwd->pw_fields & _PWF_SOURCE) { | ||||
case _PWF_FILES: | case _PWF_FILES: | ||||
#endif | #endif | ||||
retval = PAM_SERVICE_ERR; | retval = PAM_SERVICE_ERR; | ||||
if (pw_init(NULL, NULL)) | if (pw_init(NULL, NULL)) | ||||
openpam_log(PAM_LOG_ERROR, "pw_init() failed"); | openpam_log(PAM_LOG_ERROR, "pw_init() failed"); | ||||
Show All 37 Lines | #endif | ||||
} | } | ||||
else { | else { | ||||
/* Very bad juju */ | /* Very bad juju */ | ||||
retval = PAM_ABORT; | retval = PAM_ABORT; | ||||
PAM_LOG("Illegal 'flags'"); | PAM_LOG("Illegal 'flags'"); | ||||
} | } | ||||
return (retval); | return (retval); | ||||
} | |||||
/* Mostly stolen from passwd(1)'s local_passwd.c - markm */ | |||||
static unsigned char itoa64[] = /* 0 ... 63 => ascii - 64 */ | |||||
"./0123456789ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz"; | |||||
static void | |||||
to64(char *s, long v, int n) | |||||
{ | |||||
while (--n >= 0) { | |||||
*s++ = itoa64[v&0x3f]; | |||||
v >>= 6; | |||||
} | |||||
} | |||||
/* Salt suitable for traditional DES and MD5 */ | |||||
static void | |||||
makesalt(char salt[SALTSIZE + 1]) | |||||
{ | |||||
int i; | |||||
/* These are not really random numbers, they are just | |||||
* numbers that change to thwart construction of a | |||||
* dictionary. | |||||
*/ | |||||
for (i = 0; i < SALTSIZE; i += 4) | |||||
to64(&salt[i], arc4random(), 4); | |||||
salt[SALTSIZE] = '\0'; | |||||
} | } | ||||
PAM_MODULE_ENTRY("pam_unix"); | PAM_MODULE_ENTRY("pam_unix"); |