libbb: make pw_encrypt() die if supplied salt is bad (e.g. emply)

Fished from 520-loginutils-handle-crypt-failures.patch in openwrt

function                                             old     new   delta
pw_encrypt                                           913     927     +14
des_crypt                                           1327    1318      -9
------------------------------------------------------------------------------
(add/remove: 0/0 grow/shrink: 1/1 up/down: 14/-9)               Total: 5 bytes

Signed-off-by: Denys Vlasenko <vda.linux@googlemail.com>
This commit is contained in:
Denys Vlasenko 2020-12-15 23:19:22 +01:00
parent f3d6711c97
commit 73d93d9f83
2 changed files with 19 additions and 17 deletions

View File

@ -120,6 +120,7 @@ static char *my_crypt(const char *key, const char *salt)
if (!des_cctx) if (!des_cctx)
des_cctx = const_des_init(); des_cctx = const_des_init();
des_ctx = des_init(des_ctx, des_cctx); des_ctx = des_init(des_ctx, des_cctx);
/* Can return NULL if salt is bad ("" or "<one_char>") */
return des_crypt(des_ctx, xzalloc(DES_OUT_BUFSIZE), (unsigned char*)key, (unsigned char*)salt); return des_crypt(des_ctx, xzalloc(DES_OUT_BUFSIZE), (unsigned char*)key, (unsigned char*)salt);
} }
@ -137,6 +138,8 @@ char* FAST_FUNC pw_encrypt(const char *clear, const char *salt, int cleanup)
char *encrypted; char *encrypted;
encrypted = my_crypt(clear, salt); encrypted = my_crypt(clear, salt);
if (!encrypted)
bb_simple_error_msg_and_die("bad salt");
if (cleanup) if (cleanup)
my_crypt_cleanup(); my_crypt_cleanup();
@ -148,14 +151,16 @@ char* FAST_FUNC pw_encrypt(const char *clear, const char *salt, int cleanup)
char* FAST_FUNC pw_encrypt(const char *clear, const char *salt, int cleanup) char* FAST_FUNC pw_encrypt(const char *clear, const char *salt, int cleanup)
{ {
char *s; char *encrypted;
s = crypt(clear, salt); encrypted = crypt(clear, salt);
/* /*
* glibc used to return "" on malformed salts (for example, ""), * glibc used to return "" on malformed salts (for example, ""),
* but since 2.17 it returns NULL. * but since 2.17 it returns NULL.
*/ */
return xstrdup(s ? s : ""); if (!encrypted || !encrypted[0])
bb_simple_error_msg_and_die("bad salt");
return xstrdup(encrypted);
} }
#endif #endif

View File

@ -713,11 +713,15 @@ to64_msb_first(char *s, unsigned v)
static char * static char *
NOINLINE NOINLINE
des_crypt(struct des_ctx *ctx, char output[DES_OUT_BUFSIZE], des_crypt(struct des_ctx *ctx, char output[DES_OUT_BUFSIZE],
const unsigned char *key, const unsigned char *setting) const unsigned char *key, const unsigned char *salt_str)
{ {
uint32_t salt, r0, r1, keybuf[2]; uint32_t salt, r0, r1, keybuf[2];
uint8_t *q; uint8_t *q;
/* Bad salt? Mimic crypt() API - return NULL */
if (!salt_str[0] || !salt_str[1])
return NULL;
/* /*
* Copy the key, shifting each character up by one bit * Copy the key, shifting each character up by one bit
* and padding with zeros. * and padding with zeros.
@ -732,22 +736,15 @@ des_crypt(struct des_ctx *ctx, char output[DES_OUT_BUFSIZE],
des_setkey(ctx, (char *)keybuf); des_setkey(ctx, (char *)keybuf);
/* /*
* setting - 2 bytes of salt * salt_str - 2 bytes of salt
* key - up to 8 characters * key - up to 8 characters
*/ */
salt = (ascii_to_bin(setting[1]) << 6) output[0] = salt_str[0];
| ascii_to_bin(setting[0]); output[1] = salt_str[1];
salt = (ascii_to_bin(salt_str[1]) << 6)
output[0] = setting[0]; | ascii_to_bin(salt_str[0]);
/*
* If the encrypted password that the salt was extracted from
* is only 1 character long, the salt will be corrupted. We
* need to ensure that the output string doesn't have an extra
* NUL in it!
*/
output[1] = setting[1] ? setting[1] : output[0];
setup_salt(ctx, salt); setup_salt(ctx, salt);
/* Do it. */ /* Do it. */
do_des(ctx, /*0, 0,*/ &r0, &r1, 25 /* count */); do_des(ctx, /*0, 0,*/ &r0, &r1, 25 /* count */);