* lib/prototypes.h, libmisc/salt.c: Add parameters to

crypt_make_salt to force the crypt method and number of rounds.
* libmisc/salt.c: Add parameter to SHA_salt_rounds to force the
  number of rounds.
* libmisc/salt.c, lib/getdef.c: ENCRYPT_METHOD and MD5_CRYPT_ENAB
  are needed also when USE_PAM (e.g. for chpasswd).
* src/newusers.c, src/gpasswd.c: Use the new crypt_make_salt prototype.
* src/chpasswd.c, src/chgpasswd.c: Add option -c, --crypt-method
  and -s, --sha-rounds to specify the crypt method and number of
  rounds in case of one of the SHA methods. The new prototype of
  crypt_make_salt simplifies the handling of -m, --md5.
This commit is contained in:
nekral-guest 2007-11-20 09:33:52 +00:00
parent eb23bbfd98
commit 0b695f5a76
8 changed files with 233 additions and 82 deletions

View File

@ -1,3 +1,17 @@
2007-11-20 Nicolas François <nicolas.francois@centraliens.net>
* lib/prototypes.h, libmisc/salt.c: Add parameters to
crypt_make_salt to force the crypt method and number of rounds.
* libmisc/salt.c: Add parameter to SHA_salt_rounds to force the
number of rounds.
* libmisc/salt.c, lib/getdef.c: ENCRYPT_METHOD and MD5_CRYPT_ENAB
are needed also when USE_PAM (e.g. for chpasswd).
* src/newusers.c, src/gpasswd.c: Use the new crypt_make_salt prototype
* src/chpasswd.c, src/chgpasswd.c: Add option -c, --crypt-method
and -s, --sha-rounds to specify the crypt method and number of
rounds in case of one of the SHA methods. The new prototype of
crypt_make_salt simplifies the handling of -m, --md5.
2007-11-19 Nicolas François <nicolas.francois@centraliens.net> 2007-11-19 Nicolas François <nicolas.francois@centraliens.net>
* libmisc/salt.c: The salt has a random size (between 8 and 16 * libmisc/salt.c: The salt has a random size (between 8 and 16

View File

@ -52,6 +52,7 @@ static struct itemdef def_table[] = {
{"CONSOLE", NULL}, {"CONSOLE", NULL},
{"CREATE_HOME", NULL}, {"CREATE_HOME", NULL},
{"DEFAULT_HOME", NULL}, {"DEFAULT_HOME", NULL},
{"ENCRYPT_METHOD", NULL},
{"ENV_PATH", NULL}, {"ENV_PATH", NULL},
{"ENV_SUPATH", NULL}, {"ENV_SUPATH", NULL},
{"ERASECHAR", NULL}, {"ERASECHAR", NULL},
@ -67,9 +68,12 @@ static struct itemdef def_table[] = {
{"LOG_UNKFAIL_ENAB", NULL}, {"LOG_UNKFAIL_ENAB", NULL},
{"MAIL_DIR", NULL}, {"MAIL_DIR", NULL},
{"MAIL_FILE", NULL}, {"MAIL_FILE", NULL},
{"MD5_CRYPT_ENAB", NULL},
{"PASS_MAX_DAYS", NULL}, {"PASS_MAX_DAYS", NULL},
{"PASS_MIN_DAYS", NULL}, {"PASS_MIN_DAYS", NULL},
{"PASS_WARN_AGE", NULL}, {"PASS_WARN_AGE", NULL},
{"SHA_CRYPT_MAX_ROUNDS", NULL},
{"SHA_CRYPT_MIN_ROUNDS", NULL},
{"SULOG_FILE", NULL}, {"SULOG_FILE", NULL},
{"SU_NAME", NULL}, {"SU_NAME", NULL},
{"TTYGROUP", NULL}, {"TTYGROUP", NULL},
@ -84,7 +88,6 @@ static struct itemdef def_table[] = {
{"CHFN_AUTH", NULL}, {"CHFN_AUTH", NULL},
{"CHSH_AUTH", NULL}, {"CHSH_AUTH", NULL},
{"CRACKLIB_DICTPATH", NULL}, {"CRACKLIB_DICTPATH", NULL},
{"ENCRYPT_METHOD", NULL},
{"ENV_HZ", NULL}, {"ENV_HZ", NULL},
{"ENVIRON_FILE", NULL}, {"ENVIRON_FILE", NULL},
{"ENV_TZ", NULL}, {"ENV_TZ", NULL},
@ -94,7 +97,6 @@ static struct itemdef def_table[] = {
{"LASTLOG_ENAB", NULL}, {"LASTLOG_ENAB", NULL},
{"LOGIN_STRING", NULL}, {"LOGIN_STRING", NULL},
{"MAIL_CHECK_ENAB", NULL}, {"MAIL_CHECK_ENAB", NULL},
{"MD5_CRYPT_ENAB", NULL},
{"MOTD_FILE", NULL}, {"MOTD_FILE", NULL},
{"NOLOGINS_FILE", NULL}, {"NOLOGINS_FILE", NULL},
{"OBSCURE_CHECKS_ENAB", NULL}, {"OBSCURE_CHECKS_ENAB", NULL},
@ -104,8 +106,6 @@ static struct itemdef def_table[] = {
{"PASS_MIN_LEN", NULL}, {"PASS_MIN_LEN", NULL},
{"PORTTIME_CHECKS_ENAB", NULL}, {"PORTTIME_CHECKS_ENAB", NULL},
{"QUOTAS_ENAB", NULL}, {"QUOTAS_ENAB", NULL},
{"SHA_CRYPT_MAX_ROUNDS", NULL},
{"SHA_CRYPT_MIN_ROUNDS", NULL},
{"SU_WHEEL_ONLY", NULL}, {"SU_WHEEL_ONLY", NULL},
{"ULIMIT", NULL}, {"ULIMIT", NULL},
#endif #endif

View File

@ -132,7 +132,7 @@ extern void pwd_init (void);
extern int do_rlogin (const char *, char *, int, char *, int); extern int do_rlogin (const char *, char *, int, char *, int);
/* salt.c */ /* salt.c */
extern char *crypt_make_salt (void); extern char *crypt_make_salt (char *meth, void *arg);
/* setugid.c */ /* setugid.c */
extern int setup_groups (const struct passwd *); extern int setup_groups (const struct passwd *);

View File

@ -85,29 +85,33 @@ static unsigned int SHA_salt_size (void)
/* /*
* Return a salt prefix specifying the rounds number for the SHA crypt methods. * Return a salt prefix specifying the rounds number for the SHA crypt methods.
*/ */
static char *SHA_salt_rounds (void) static char *SHA_salt_rounds (int *prefered_rounds)
{ {
static char *rounds_prefix[18]; static char rounds_prefix[18];
long min_rounds = getdef_long ("SHA_CRYPT_MIN_ROUNDS", -1);
long max_rounds = getdef_long ("SHA_CRYPT_MAX_ROUNDS", -1);
long rounds; long rounds;
if (-1 == min_rounds && -1 == max_rounds) if (NULL == prefered_rounds) {
long min_rounds = getdef_long ("SHA_CRYPT_MIN_ROUNDS", -1);
long max_rounds = getdef_long ("SHA_CRYPT_MAX_ROUNDS", -1);
if (-1 == min_rounds && -1 == max_rounds)
return "";
if (-1 == min_rounds)
min_rounds = max_rounds;
if (-1 == max_rounds)
max_rounds = min_rounds;
if (min_rounds > max_rounds)
max_rounds = min_rounds;
srand (time (NULL));
rounds = min_rounds +
(double)rand () * (max_rounds-min_rounds+1)/RAND_MAX;
} else if (0 == *prefered_rounds)
return ""; return "";
if (-1 == min_rounds)
min_rounds = max_rounds;
if (-1 == max_rounds)
max_rounds = min_rounds;
if (min_rounds > max_rounds)
max_rounds = min_rounds;
srand (time (NULL));
rounds = min_rounds +
(double)rand () * (max_rounds-min_rounds+1)/RAND_MAX;
/* Sanity checks. The libc should also check this, but this /* Sanity checks. The libc should also check this, but this
* protects against a rounds_prefix overflow. */ * protects against a rounds_prefix overflow. */
if (rounds < ROUNDS_MIN) if (rounds < ROUNDS_MIN)
@ -133,8 +137,16 @@ static char *SHA_salt_rounds (void)
* (magic) and pw_encrypt() will execute the MD5-based FreeBSD-compatible * (magic) and pw_encrypt() will execute the MD5-based FreeBSD-compatible
* version of crypt() instead of the standard one. * version of crypt() instead of the standard one.
* Other methods can be set with ENCRYPT_METHOD * Other methods can be set with ENCRYPT_METHOD
*
* The method can be forced with the meth parameter.
* If NULL, the method will be defined according to the MD5_CRYPT_ENAB and
* ENCRYPT_METHOD login.defs variables.
*
* If meth is specified, an additional parameter can be provided.
* * For the SHA256 and SHA512 method, this specifies the number of rounds
* (if not NULL).
*/ */
char *crypt_make_salt (void) char *crypt_make_salt (char *meth, void *arg)
{ {
struct timeval tv; struct timeval tv;
/* Max result size for the SHA methods: /* Max result size for the SHA methods:
@ -145,41 +157,39 @@ char *crypt_make_salt (void)
*/ */
static char result[40]; static char result[40];
int max_salt_len = 8; int max_salt_len = 8;
char *method; char *method = "DES";
result[0] = '\0'; result[0] = '\0';
#ifndef USE_PAM if (NULL != meth)
method = meth;
else
#ifdef ENCRYPTMETHOD_SELECT #ifdef ENCRYPTMETHOD_SELECT
if ((method = getdef_str ("ENCRYPT_METHOD")) == NULL) { if ((method = getdef_str ("ENCRYPT_METHOD")) == NULL)
#endif #endif
if (getdef_bool ("MD5_CRYPT_ENAB")) { if (getdef_bool ("MD5_CRYPT_ENAB"))
MAGNUM(result,'1'); method = "MD5";
max_salt_len = 11;
} if (!strncmp (method, "MD5", 3)) {
MAGNUM(result, '1');
max_salt_len = 11;
#ifdef ENCRYPTMETHOD_SELECT #ifdef ENCRYPTMETHOD_SELECT
} else { } else if (!strncmp (method, "SHA256", 6)) {
if (!strncmp (method, "MD5", 3)) { MAGNUM(result, '5');
MAGNUM(result, '1'); strcat(result, SHA_salt_rounds((int *)arg));
max_salt_len = 11; max_salt_len = strlen(result) + SHA_salt_size();
} else if (!strncmp (method, "SHA256", 6)) { } else if (!strncmp (method, "SHA512", 6)) {
MAGNUM(result, '5'); MAGNUM(result, '6');
strcat(result, SHA_salt_rounds()); strcat(result, SHA_salt_rounds((int *)arg));
max_salt_len = strlen(result) + SHA_salt_size(); max_salt_len = strlen(result) + SHA_salt_size();
} else if (!strncmp (method, "SHA512", 6)) { #endif
MAGNUM(result, '6'); } else if (0 != strncmp (method, "DES", 3)) {
strcat(result, SHA_salt_rounds()); fprintf (stderr,
max_salt_len = strlen(result) + SHA_salt_size(); _("Invalid ENCRYPT_METHOD value: '%s'.\n"
} else if (0 != strncmp (method, "DES", 3)) { "Defaulting to DES.\n"),
fprintf (stderr, method);
_("Invalid ENCRYPT_METHOD value: '%s'.\n" result[0] = '\0';
"Defaulting to DES.\n"),
method);
result[0] = '\0';
}
} }
#endif /* ENCRYPTMETHOD_SELECT */
#endif /* USE_PAM */
/* /*
* Concatenate a pseudo random salt. * Concatenate a pseudo random salt.

View File

@ -50,8 +50,13 @@
* Global variables * Global variables
*/ */
static char *Prog; static char *Prog;
static int cflg = 0;
static int eflg = 0; static int eflg = 0;
static int md5flg = 0; static int md5flg = 0;
static int sflg = 0;
static char *crypt_method = NULL;
static int sha_rounds = 5000;
#ifdef SHADOWGRP #ifdef SHADOWGRP
static int is_shadow_grp; static int is_shadow_grp;
@ -68,14 +73,36 @@ static void usage (void)
fprintf (stderr, _("Usage: chgpasswd [options]\n" fprintf (stderr, _("Usage: chgpasswd [options]\n"
"\n" "\n"
"Options:\n" "Options:\n"
" -c, --crypt-method the crypt method (one of %s)\n"
" -e, --encrypted supplied passwords are encrypted\n" " -e, --encrypted supplied passwords are encrypted\n"
" -h, --help display this help message and exit\n" " -h, --help display this help message and exit\n"
" -m, --md5 use MD5 encryption instead DES when the supplied\n" " -m, --md5 use MD5 encryption instead DES when the supplied\n"
" passwords are not encrypted\n" " passwords are not encrypted\n"
"\n")); "\n"),
#ifndef ENCRYPTMETHOD_SELECT
"DES MD5"
#else
"DES MD5 SHA256 SHA512"
#endif
);
exit (1); exit (1);
} }
static long getnumber (const char *numstr)
{
long val;
char *errptr;
val = strtol (numstr, &errptr, 10);
if (*errptr || errno == ERANGE) {
fprintf (stderr, _("%s: invalid numeric argument '%s'\n"), Prog,
numstr);
exit (1);
}
return val;
}
int main (int argc, char **argv) int main (int argc, char **argv)
{ {
char buf[BUFSIZ]; char buf[BUFSIZ];
@ -111,16 +138,22 @@ int main (int argc, char **argv)
int option_index = 0; int option_index = 0;
int c; int c;
static struct option long_options[] = { static struct option long_options[] = {
{"crypt-method", required_argument, NULL, 'c'},
{"encrypted", no_argument, NULL, 'e'}, {"encrypted", no_argument, NULL, 'e'},
{"help", no_argument, NULL, 'h'}, {"help", no_argument, NULL, 'h'},
{"md5", no_argument, NULL, 'm'}, {"md5", no_argument, NULL, 'm'},
{"sha-rounds", required_argument, NULL, 's'},
{NULL, 0, NULL, '\0'} {NULL, 0, NULL, '\0'}
}; };
while ((c = while ((c =
getopt_long (argc, argv, "ehm", long_options, getopt_long (argc, argv, "c:ehms:", long_options,
&option_index)) != -1) { &option_index)) != -1) {
switch (c) { switch (c) {
case 'c':
cflg = 1;
crypt_method = optarg;
break;
case 'e': case 'e':
eflg = 1; eflg = 1;
break; break;
@ -130,6 +163,10 @@ int main (int argc, char **argv)
case 'm': case 'm':
md5flg = 1; md5flg = 1;
break; break;
case 's':
sflg = 1;
sha_rounds = getnumber(optarg);
break;
case 0: case 0:
/* long option */ /* long option */
break; break;
@ -140,6 +177,34 @@ int main (int argc, char **argv)
} }
} }
/* validate options */
if (sflg && !cflg) {
fprintf (stderr,
_("%s: %s flag is ONLY allowed with the %s flag\n"),
Prog, "-s", "-c");
usage ();
}
if (md5flg && cflg) {
fprintf (stderr,
_("%s: the -m and -c flags are exclusive\n"),
Prog);
usage ();
}
if (cflg) {
if (0 != strcmp (method, "DES") &&
0 != strcmp (method, "MD5") &&
#ifdef ENCRYPTMETHOD_SELECT
0 != strcmp (method, "SHA256") &&
0 != strcmp (method, "SHA512")
#endif
) {
fprintf (stderr,
_("%s: unsupported crypt method: %s\n"),
Prog, method);
usage ();
}
}
#ifdef USE_PAM #ifdef USE_PAM
retval = PAM_SUCCESS; retval = PAM_SUCCESS;
@ -245,18 +310,16 @@ int main (int argc, char **argv)
} }
newpwd = cp; newpwd = cp;
if (!eflg) { if (!eflg) {
if (md5flg) { void *arg = NULL;
char md5salt[12] = "$1$"; if (md5flg)
char *salt = crypt_make_salt (); crypt_method = "MD5";
else if (crypt_method != NULL) {
if (strncmp (salt, "$1$", 3) == 0) { if (sflg)
strncpy (md5salt, salt, 11); arg = &sha_rounds;
} else {
strncat (md5salt, salt, 8);
}
cp = pw_encrypt (newpwd, md5salt);
} else } else
cp = pw_encrypt (newpwd, crypt_make_salt ()); crypt_method = "DES";
cp = pw_encrypt (newpwd,
crypt_make_salt(crypt_method, arg));
} }
/* /*

View File

@ -49,8 +49,13 @@
* Global variables * Global variables
*/ */
static char *Prog; static char *Prog;
static int cflg = 0;
static int eflg = 0; static int eflg = 0;
static int md5flg = 0; static int md5flg = 0;
static int sflg = 0;
static char *crypt_method = NULL;
static int sha_rounds = 5000;
static int is_shadow_pwd; static int is_shadow_pwd;
@ -65,14 +70,36 @@ static void usage (void)
fprintf (stderr, _("Usage: chpasswd [options]\n" fprintf (stderr, _("Usage: chpasswd [options]\n"
"\n" "\n"
"Options:\n" "Options:\n"
" -c, --crypt-method the crypt method (one of %s)\n"
" -e, --encrypted supplied passwords are encrypted\n" " -e, --encrypted supplied passwords are encrypted\n"
" -h, --help display this help message and exit\n" " -h, --help display this help message and exit\n"
" -m, --md5 use MD5 encryption instead DES when the supplied\n" " -m, --md5 use MD5 encryption instead DES when the supplied\n"
" passwords are not encrypted\n" " passwords are not encrypted\n"
"\n")); "\n"),
#ifndef ENCRYPTMETHOD_SELECT
"DES MD5"
#else
"DES MD5 SHA256 SHA512"
#endif
);
exit (E_USAGE); exit (E_USAGE);
} }
static long getnumber (const char *numstr)
{
long val;
char *errptr;
val = strtol (numstr, &errptr, 10);
if (*errptr || errno == ERANGE) {
fprintf (stderr, _("%s: invalid numeric argument '%s'\n"), Prog,
numstr);
exit (1);
}
return val;
}
int main (int argc, char **argv) int main (int argc, char **argv)
{ {
char buf[BUFSIZ]; char buf[BUFSIZ];
@ -105,16 +132,22 @@ int main (int argc, char **argv)
int option_index = 0; int option_index = 0;
int c; int c;
static struct option long_options[] = { static struct option long_options[] = {
{"crypt-method", required_argument, NULL, 'c'},
{"encrypted", no_argument, NULL, 'e'}, {"encrypted", no_argument, NULL, 'e'},
{"help", no_argument, NULL, 'h'}, {"help", no_argument, NULL, 'h'},
{"md5", no_argument, NULL, 'm'}, {"md5", no_argument, NULL, 'm'},
{"sha-rounds", required_argument, NULL, 's'},
{NULL, 0, NULL, '\0'} {NULL, 0, NULL, '\0'}
}; };
while ((c = while ((c =
getopt_long (argc, argv, "ehm", long_options, getopt_long (argc, argv, "c:ehms:", long_options,
&option_index)) != -1) { &option_index)) != -1) {
switch (c) { switch (c) {
case 'c':
cflg = 1;
crypt_method = optarg;
break;
case 'e': case 'e':
eflg = 1; eflg = 1;
break; break;
@ -124,6 +157,10 @@ int main (int argc, char **argv)
case 'm': case 'm':
md5flg = 1; md5flg = 1;
break; break;
case 's':
sflg = 1;
sha_rounds = getnumber(optarg);
break;
case 0: case 0:
/* long option */ /* long option */
break; break;
@ -134,6 +171,34 @@ int main (int argc, char **argv)
} }
} }
/* validate options */
if (sflg && !cflg) {
fprintf (stderr,
_("%s: %s flag is ONLY allowed with the %s flag\n"),
Prog, "-s", "-c");
usage ();
}
if (md5flg && cflg) {
fprintf (stderr,
_("%s: the -m and -c flags are exclusive\n"),
Prog);
usage ();
}
if (cflg) {
if (0 != strcmp (method, "DES") &&
0 != strcmp (method, "MD5") &&
#ifdef ENCRYPTMETHOD_SELECT
0 != strcmp (method, "SHA256") &&
0 != strcmp (method, "SHA512")
#endif
) {
fprintf (stderr,
_("%s: unsupported crypt method: %s\n"),
Prog, method);
usage ();
}
}
#ifdef USE_PAM #ifdef USE_PAM
retval = PAM_SUCCESS; retval = PAM_SUCCESS;
@ -241,18 +306,16 @@ int main (int argc, char **argv)
} }
newpwd = cp; newpwd = cp;
if (!eflg) { if (!eflg) {
if (md5flg) { void *arg = NULL;
char md5salt[12] = "$1$"; if (md5flg)
char *salt = crypt_make_salt (); crypt_method = "MD5";
else if (crypt_method != NULL) {
if (strncmp (salt, "$1$", 3) == 0) { if (sflg)
strncpy (md5salt, salt, 11); arg = &sha_rounds;
} else {
strncat (md5salt, salt, 8);
}
cp = pw_encrypt (newpwd, salt);
} else } else
cp = pw_encrypt (newpwd, crypt_make_salt ()); crypt_method = "DES";
cp = pw_encrypt (newpwd,
crypt_make_salt(crypt_method, arg));
} }
/* /*

View File

@ -607,7 +607,7 @@ int main (int argc, char **argv)
exit (1); exit (1);
} }
cp = pw_encrypt (pass, crypt_make_salt ()); cp = pw_encrypt (pass, crypt_make_salt (NULL, NULL));
memzero (pass, sizeof pass); memzero (pass, sizeof pass);
#ifdef SHADOWGRP #ifdef SHADOWGRP
if (is_shadowgrp) if (is_shadowgrp)

View File

@ -214,7 +214,7 @@ static int add_user (const char *name, const char *uid, uid_t * nuid, gid_t gid)
static void update_passwd (struct passwd *pwd, const char *passwd) static void update_passwd (struct passwd *pwd, const char *passwd)
{ {
pwd->pw_passwd = pw_encrypt (passwd, crypt_make_salt ()); pwd->pw_passwd = pw_encrypt (passwd, crypt_make_salt (NULL, NULL));
} }
/* /*
@ -241,7 +241,8 @@ static int add_passwd (struct passwd *pwd, const char *passwd)
*/ */
if ((sp = spw_locate (pwd->pw_name))) { if ((sp = spw_locate (pwd->pw_name))) {
spent = *sp; spent = *sp;
spent.sp_pwdp = pw_encrypt (passwd, crypt_make_salt ()); spent.sp_pwdp = pw_encrypt (passwd,
crypt_make_salt (NULL, NULL));
return !spw_update (&spent); return !spw_update (&spent);
} }
@ -261,7 +262,7 @@ static int add_passwd (struct passwd *pwd, const char *passwd)
* shadow password file entry. * shadow password file entry.
*/ */
spent.sp_namp = pwd->pw_name; spent.sp_namp = pwd->pw_name;
spent.sp_pwdp = pw_encrypt (passwd, crypt_make_salt ()); spent.sp_pwdp = pw_encrypt (passwd, crypt_make_salt (NULL, NULL));
spent.sp_lstchg = time ((time_t *) 0) / SCALE; spent.sp_lstchg = time ((time_t *) 0) / SCALE;
spent.sp_min = getdef_num ("PASS_MIN_DAYS", 0); spent.sp_min = getdef_num ("PASS_MIN_DAYS", 0);
/* 10000 is infinity this week */ /* 10000 is infinity this week */