Quoting Christian Perrier ([EMAIL PROTECTED]): > tags 275343 patch > tags 304343 patch > merge 305352 275343 > thanks > > Attached is the first draft of a patch that should allow preseeding > MD5 hash paasswords for both the root and the first created user > passwords.
Testing this is a little bit tricky because the relevant code actually runs only when calling "dpkg-reconfigure passwd". Also, when run on a live system, where root already has a password, it does nothing. The key is emptying the root password before manually running a modified passwd.config script where the test about $1 being "reconfigure" is removed. See attached "test" script which is such a modified version. The attached "set" script allow to set the root password hash to a hash corresponding to "r00tme". The similar code for the user password preseeding is NOT included in this test. Actually, testing this is even more tricky on a live system because the script first test about the presence of an existing unprivileged user and only proposes a user creation when such a user does not exist.
#!/bin/sh -e test -f /usr/share/debconf/confmodule || exit 0 # don't make assumptions about the umask umask 022 . /usr/share/debconf/confmodule db_capb "backup" # Remove this : not translatable and looks ugly in d-i process # db_title "Password setup" # Returns a true value if there seems to be a system user account. is_system_user () { # Assume NIS, or any uid from 1000 to 29999, means there is a user. if grep -q '^+:' /etc/passwd || \ grep -q '^[^:]*:[^:]*:[1-9][0-9][0-9][0-9]:' /etc/passwd || \ grep -q '^[^:]*:[^:]*:[12][0-9][0-9][0-9][0-9]:' /etc/passwd; then return 0 else return 1 fi } # Returns a true value if root already has a password. root_password () { # Assume there is a root password if NIS is being used. if grep -q '^+:' /etc/passwd; then return 0 fi if [ -e /etc/shadow ] && \ [ "`grep ^root: /etc/shadow | cut -d : -f 2`" ]; then return 0 fi if [ "`grep ^root: /etc/passwd | cut -d : -f 2`" ] && \ [ "`grep ^root: /etc/passwd | cut -d : -f 2`" != 'x' ]; then return 0 fi return 1 } # Set a password, via chpasswd. # Use perl rather than echo, to avoid the password # showing in the process table. (However, this is normally # only called when first booting the system, when root has no # password at all, so that should be an unnecessary precaution). # # Arguments: # 1) (mandatory) username # 2) (mandatory) password # 3) (optional) 1 for meaning "the passed password is a MD5 hash" setpassword () { SETPASSWD_PW="$2" export SETPASSWD_PW # This is very annoying. chpasswd cannot handle generating md5 # passwords as it is not PAM-aware. Thus, I have to work around # that by crypting the password myself if md5 is used. USE_MD5=1 export USE_MD5 if test "$3" ; then echo $1:${SETPASSWD_PW} | chpasswd -e else perl -e ' sub CreateCryptSalt { my $md5 = shift; my @valid = split(//, "./0123456789abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ"); my ($in, $out); my $cryptsaltlen = ($md5 ? 8 : 2); open (F, "</dev/urandom") || die "No /dev/urandom found!"; foreach (1..$cryptsaltlen) { read(F, $in, 1); $out .= $valid[ord($in) % ($#valid + 1)]; } close F; return ($md5 ? "\$1\$$out\$" : $out); } open(P,"| chpasswd -e"); print P shift().":". crypt($ENV{SETPASSWD_PW}, CreateCryptSalt($ENV{USE_MD5})). "\n"; close P; ' "$1" fi SETPASSWD_PW='' USE_MD5='' } # Main loop starts here. Use a state machine to allow jumping back to # previous questions. STATE=0 while [ "$STATE" != '10' ] && [ "$STATE" != '-1' ]; do case "$STATE" in 0) # Ask how the password files should be set up. db_input low passwd/shadow || true ;; 1) # md5 passwords are now on by default. This step is dead. : ;; 2) # Enable shadowed passwords...or not db_get passwd/shadow if [ "$RET" = true ]; then echo shadowconfig on else echo shadowconfig off fi ;; 3) # Prompt for a root password if there is none. if ! root_password; then # First check whether the root password hash was preseeded db_get passwd/root-password-hash || true if ! test $RET ; then # No preseed of the root password hash # we will prompt the user db_input critical passwd/root-password || true # Note that this runs at a slightly lower # priority, so it may not always be seen. If # it isn't, don't compare passwords. COMPARE_PW='' db_input critical passwd/root-password-again \ && COMPARE_PW=1 || true fi fi ;; 4) # Verify and set a root password. if ! root_password; then # First check whether the root password hash was preseeded db_get passwd/root-password-hash || true if ! test $RET ; then # Compare the two passwords, loop back if not # identical, or if empty. db_get passwd/root-password ROOT_PW="$RET" if [ -z "$ROOT_PW" ]; then db_fset passwd/password-empty seen false db_input critical passwd/password-empty STATE=2 continue fi db_get passwd/root-password-again if [ "$COMPARE_PW" ] && [ "$ROOT_PW" != "$RET" ]; then db_fset passwd/password-mismatch seen false db_input critical passwd/password-mismatch STATE=2 continue fi # Clear root password from the db, and set the # password. db_set passwd/root-password "" db_set passwd/root-password-again "" setpassword root "$ROOT_PW" ROOT_PW='' else # The hash for the root password was preseeded ROOT_PW=$RET setpassword root "$ROOT_PW" 1 ROOT_PW='' fi # Loop back to state #2 to make sure that there # is a root password, and if not, prompt again. STATE=2 continue fi ;; 5) # Ask if a non-root user should be made, if there is not # already one. if ! is_system_user; then db_input medium passwd/make-user || true fi ;; 6) # Prompt for user info. db_get passwd/make-user if [ "$RET" = true ] && ! is_system_user; then db_input critical passwd/user-fullname || true fi ;; 7) # Prompt for user info. db_get passwd/make-user if [ "$RET" = true ] && ! is_system_user; then LOOP="" db_get passwd/username if [ -z "$RET" ]; then db_get passwd/user-fullname # Login defaults to user's first name # Some hat off to a few d-i people case "$RET" in "Martin Michlmayr") userdefault="tbm" ;; *) userdefault=`echo $RET | sed 's/ .*//' | tr A-Z a-z` ;; esac if test -n "$userdefault"; then db_set passwd/username "$userdefault" fi fi db_input critical passwd/username || true fi ;; 8) # Verify and make user. db_get passwd/make-user if [ "$RET" = true ] && ! is_system_user; then # Verify the user name, loop with message if bad. db_get passwd/username USER="$RET" if ! expr "$USER" : '[a-z][a-z0-9]*$' >/dev/null; then db_fset passwd/username seen false db_fset passwd/username-bad seen false db_input critical passwd/username-bad STATE=5 continue fi db_input critical passwd/user-password || true COMPARE_PW='' db_input critical passwd/user-password-again \ && COMPARE_PW=1 || true fi ;; 9) db_get passwd/make-user if [ "$RET" = true ] && ! is_system_user; then # Compare the two passwords, loop with message if not # identical, or if empty. db_get passwd/user-password USER_PW="$RET" db_get passwd/user-password-again if [ "$COMPARE_PW" ] && [ "$USER_PW" != "$RET" ]; then db_set passwd/user-password "" db_set passwd/user-password-again "" db_fset passwd/password-mismatch seen false db_input critical passwd/password-mismatch db_fset passwd/user-password seen false db_fset passwd/user-password-again seen false STATE=8 continue fi if [ -z "$USER_PW" ]; then db_set passwd/user-password "" db_set passwd/user-password-again "" db_fset passwd/password-empty seen false db_input critical passwd/password-empty db_fset passwd/user-password seen false db_fset passwd/user-password-again seen false STATE=8 continue fi # Add the user to the database, using adduser in # noninteractive mode. db_get passwd/user-fullname if test -x /usr/sbin/adduser; then adduser --disabled-password --gecos "$RET" "$USER" >/dev/null || true else useradd -c "$RET" -m "$USER" >/dev/null || true fi # Clear password from the db, and set the password. db_set passwd/user-password "" db_set passwd/user-password-again "" db_get passwd/username setpassword "$USER" "$USER_PW" USER_PW='' # Loop back through to make sure the user was # added. STATE=5 continue fi ;; esac if db_go; then STATE=$(($STATE + 1)) else STATE=$(($STATE - 1)) fi # echo "ON STATE: $STATE" done if test "$STATE" = -1 then exit 30 fi
#!/bin/sh -e test -f /usr/share/debconf/confmodule || exit 0 # don't make assumptions about the umask umask 022 . /usr/share/debconf/confmodule db_capb "backup" db_set passwd/root-password-hash '$1$RdxpHJJO$74sQZ6OBQCeVBsKR3oP6V.'