Merge pull request #12392 from poettering/firstboot-salt
generalize crypt_r() salt generation code
This commit is contained in:
@@ -22,6 +22,7 @@
|
||||
#include "missing.h"
|
||||
#include "parse-util.h"
|
||||
#include "path-util.h"
|
||||
#include "random-util.h"
|
||||
#include "string-util.h"
|
||||
#include "strv.h"
|
||||
#include "user-util.h"
|
||||
@@ -870,3 +871,40 @@ int fgetsgent_sane(FILE *stream, struct sgrp **sg) {
|
||||
return !!s;
|
||||
}
|
||||
#endif
|
||||
|
||||
int make_salt(char **ret) {
|
||||
static const char table[] =
|
||||
"abcdefghijklmnopqrstuvwxyz"
|
||||
"ABCDEFGHIJKLMNOPQRSTUVWXYZ"
|
||||
"0123456789"
|
||||
"./";
|
||||
|
||||
uint8_t raw[16];
|
||||
char *salt, *j;
|
||||
size_t i;
|
||||
int r;
|
||||
|
||||
/* This is a bit like crypt_gensalt_ra(), but doesn't require libcrypt, and doesn't do anything but
|
||||
* SHA512, i.e. is legacy-free and minimizes our deps. */
|
||||
|
||||
assert_cc(sizeof(table) == 64U + 1U);
|
||||
|
||||
/* Insist on the best randomness by setting RANDOM_BLOCK, this is about keeping passwords secret after all. */
|
||||
r = genuine_random_bytes(raw, sizeof(raw), RANDOM_BLOCK);
|
||||
if (r < 0)
|
||||
return r;
|
||||
|
||||
salt = new(char, 3+sizeof(raw)+1+1);
|
||||
if (!salt)
|
||||
return -ENOMEM;
|
||||
|
||||
/* We only bother with SHA512 hashed passwords, the rest is legacy, and we don't do legacy. */
|
||||
j = stpcpy(salt, "$6$");
|
||||
for (i = 0; i < sizeof(raw); i++)
|
||||
j[i] = table[raw[i] & 63];
|
||||
j[i++] = '$';
|
||||
j[i] = 0;
|
||||
|
||||
*ret = salt;
|
||||
return 0;
|
||||
}
|
||||
|
||||
@@ -113,3 +113,5 @@ int putgrent_sane(const struct group *gr, FILE *stream);
|
||||
int fgetsgent_sane(FILE *stream, struct sgrp **sg);
|
||||
int putsgent_sane(const struct sgrp *sg, FILE *stream);
|
||||
#endif
|
||||
|
||||
int make_salt(char **ret);
|
||||
|
||||
@@ -595,12 +595,6 @@ static int write_root_shadow(const char *path, const struct spwd *p) {
|
||||
|
||||
static int process_root_password(void) {
|
||||
|
||||
static const char table[] =
|
||||
"abcdefghijklmnopqrstuvwxyz"
|
||||
"ABCDEFGHIJKLMNOPQRSTUVWXYZ"
|
||||
"0123456789"
|
||||
"./";
|
||||
|
||||
struct spwd item = {
|
||||
.sp_namp = (char*) "root",
|
||||
.sp_min = -1,
|
||||
@@ -610,12 +604,9 @@ static int process_root_password(void) {
|
||||
.sp_expire = -1,
|
||||
.sp_flag = (unsigned long) -1, /* this appears to be what everybody does ... */
|
||||
};
|
||||
|
||||
_cleanup_free_ char *salt = NULL;
|
||||
_cleanup_close_ int lock = -1;
|
||||
char salt[3+16+1+1];
|
||||
uint8_t raw[16];
|
||||
unsigned i;
|
||||
char *j;
|
||||
struct crypt_data cd = {};
|
||||
|
||||
const char *etc_shadow;
|
||||
int r;
|
||||
@@ -659,27 +650,15 @@ static int process_root_password(void) {
|
||||
if (!arg_root_password)
|
||||
return 0;
|
||||
|
||||
/* Insist on the best randomness by setting RANDOM_BLOCK, this is about keeping passwords secret after all. */
|
||||
r = genuine_random_bytes(raw, 16, RANDOM_BLOCK);
|
||||
r = make_salt(&salt);
|
||||
if (r < 0)
|
||||
return log_error_errno(r, "Failed to get salt: %m");
|
||||
|
||||
/* We only bother with SHA512 hashed passwords, the rest is legacy, and we don't do legacy. */
|
||||
assert_cc(sizeof(table) == 64 + 1);
|
||||
j = stpcpy(salt, "$6$");
|
||||
for (i = 0; i < 16; i++)
|
||||
j[i] = table[raw[i] & 63];
|
||||
j[i++] = '$';
|
||||
j[i] = 0;
|
||||
|
||||
errno = 0;
|
||||
item.sp_pwdp = crypt(arg_root_password, salt);
|
||||
if (!item.sp_pwdp) {
|
||||
if (!errno)
|
||||
errno = EINVAL;
|
||||
|
||||
return log_error_errno(errno, "Failed to encrypt password: %m");
|
||||
}
|
||||
item.sp_pwdp = crypt_r(arg_root_password, salt, &cd);
|
||||
if (!item.sp_pwdp)
|
||||
return log_error_errno(errno == 0 ? SYNTHETIC_ERRNO(EINVAL) : errno,
|
||||
"Failed to encrypt password: %m");
|
||||
|
||||
item.sp_lstchg = (long) (now(CLOCK_REALTIME) / USEC_PER_DAY);
|
||||
|
||||
|
||||
Reference in New Issue
Block a user