Changeset View
Changeset View
Standalone View
Standalone View
lib/libpam/modules/pam_unix/pam_unix.c
Context not available. | |||||
#include <netinet/in.h> | #include <netinet/in.h> | ||||
#include <arpa/inet.h> | #include <arpa/inet.h> | ||||
#include <errno.h> | |||||
#include <login_cap.h> | #include <login_cap.h> | ||||
#include <netdb.h> | #include <netdb.h> | ||||
#include <pwd.h> | #include <pwd.h> | ||||
Context not available. | |||||
#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" | ||||
Context not available. | |||||
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; | ||||
size_t salt_sz; | |||||
int salt_err; | |||||
int i; | |||||
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(); | ||||
Context not available. | |||||
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) | passwd_format = login_getcapstr(lc, "passwd_format", "", NULL); | ||||
openpam_log(PAM_LOG_ERROR, | |||||
"can't set password cipher, relying on default"); | salt_err = 0; | ||||
salt_sz = 64 * sizeof(char); | |||||
/* We might need more memory than we guessed at initialization. | |||||
* Let's retry up to one time with new information. | |||||
*/ | |||||
for (i = 0; i < 2 && salt_err == 0; i++ ) { | |||||
if ((salt = malloc(salt_sz)) == NULL) { | |||||
return (PAM_BUF_ERR); | |||||
} | |||||
salt_err = crypt_makesalt(salt, passwd_format, &salt_sz); | |||||
switch(salt_err) { | |||||
case ENOMEM: | |||||
/* Try allocating a larger amount if this is | |||||
* the first time trying | |||||
*/ | |||||
if (i == 0) | |||||
salt_err = 0; | |||||
free(salt); | |||||
break; | |||||
case EINVAL: | |||||
/* terminate loop */ | |||||
break; | |||||
} | |||||
} | |||||
if (salt_err != 0) { | |||||
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); | ||||
Context not available. | |||||
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) { | ||||
Context not available. | |||||
} | } | ||||
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"); | ||||
Context not available. |