[PATCH] correct_password: Handle NULL from crypt

Tito farmatito at tiscali.it
Mon Feb 3 21:25:44 UTC 2014


On Monday 03 February 2014 17:50:00 Lauri Kasanen wrote:
> Hi,
> 
> As with many other software, busybox was also broken by the glibc >=
> 2.17 behavior change. Now crypt() returns NULL if either salt or
> password is invalid.
> 
> This causes busybox 1.21, 1.22, and git su to segfault, when you just
> press enter at the password prompt (configured to use system crypt() of
> course).
> 
> Program terminated with signal 11, Segmentation fault.
> #0  0xb760cb84 in strcmp () from /lib/libc.so.6
> (gdb) bt full
> #0  0xb760cb84 in strcmp () from /lib/libc.so.6
> No symbol table info available.
> #1  0x080493d3 in ask_and_check_password_extended ()
> No symbol table info available.
> 
> The attached patch fixes su. You may want to check every other call to
> crypt() in busybox.
> 
> - Lauri
> 
> 
Hi,
other users of crypt():

1) call pw_encrypt directly:

busybox/loginutils/chpasswd.c
busybox/loginutils/cryptpw.c
busybox/loginutils/passwd.c

these 3 could be fixed by adding a new pw_encrypt_or_die() function like:

char* FAST_FUNC pw_encrypt_or_die(const char *clear, const char *salt, int cleanup)
{
	char * s = crypt(clear, salt);
	if (! s)
		 bb_simple_perror_msg_and_die("crypt");
	return xstrdup(s);
}

in case we use bb internal crypt function erroring out maybe is not
needed so in this case we could define pw_encrypt_or_die = pw_encrypt.

2) using ask_and_check_password or ask_and_check_password_extended fixed by Lauri's patch
busybox/loginutils/login.c
busybox/loginutils/su.c
busybox/loginutils/sulogin.c
busybox/loginutils/vlock.c

3) needs separate fix (as daemon could not be killed) (untested): 

busybox/networking/httpd.c   at line 1874

			if (passwd[0] == '$' && isdigit(passwd[1])) {
				char *encrypted;
# if !ENABLE_PAM
 check_encrypted:
# endif
				/* encrypt pwd from peer and check match with local one */
				encrypted = pw_encrypt(
					/* pwd (from peer): */  colon_after_user + 1,
					/* salt: */ passwd,
					/* cleanup: */ 0
				);
+                             if (!encrypted)
+					r = 1;
+				else {
					r = strcmp(encrypted, passwd);
					free(encrypted);
+				}
			} else {
				/* local passwd is from httpd.conf and it's plaintext */
				r = strcmp(colon_after_user + 1, passwd);
			}
			goto end_check_passwd;
		}


Hope this helps.

Ciao,
Tito










More information about the busybox mailing list