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








_______________________________________________
busybox mailing list
busybox@busybox.net
http://lists.busybox.net/mailman/listinfo/busybox

Reply via email to