My real question is simple.

How you can allow customers to alter their passwords saved in certain htpasswd file in linux without revealing the files content or allow customers to change other passwords?

I attempted to create a script to achieve that job using ssh and specialy-designed user however it leads noway.

Help. I'm using Debian server "Lenny".

The Apache htpasswd file doesn't support any shadow functionality. Because of this you need to avoid the customers being able to access your internet server to be able to have them from the password file. Therefore the only option would be your SSH based approach or other remote solution. The next description will show you crafting a SSH command script to alter the password only when the consumer knows his old password. The issue is, that Apache doesn't give a command line tool to ensure your password inside a htpasswd file. But you can do this manually.

The next description assumes the web server user is www-data which the house directory from the user is /var/www.

First you need to produce a htpasswd file, that's writable through the web server user:

# ls -la .htpasswd
-rw-r--r-- 1 www-data root 18 10. Mai 16:30 .htpasswd

Then you've to include the secrets of your customers towards the authorized_keys file from the web server user. You need to prefix each line using the command option.

# cat .ssh/authorized_keys 
command="/var/www/" ssh-rsa AAAA... user@host

Each time a user connects together with his key just the will get performed. The customers have no spend accessibility web server.

This is actually the script to alter the password:

#! /bin/bash


die () { echo "$*" >&2 ; exit 1 ; }

read -p 'Enter user name: ' USER
read -s -p 'Old password: ' OLDPW ; echo
read -s -p 'New password: ' NEWPW0 ; echo
read -s -p 'Re-type new password: ' NEWPW1 ; echo

if LINE=$(grep ^"$USER": "$HTPASSWD")
    echo "$LINE" | sed 's/.*:\(..\)\(.\+\)/\1 \2/' | { 
        read SALT CRYPT
        if [[ "$SALT$CRYPT" = $(echo "$OLDPW" | mkpasswd -sS "$SALT") ]] ; then
            if [ "$NEWPW0" != "$NEWPW1" ] ; then
                die "Password verification error!"
            PWS=$(grep -v ^"$USER:" "$HTPASSWD")
                echo "$PWS"
                echo -n "$USER:"
                echo "$NEWPW0" | mkpasswd -s
            } > "$HTPASSWD"
            echo "Updating password for user $USER."
            die "Password verification error!"
    die "Password verification error!"

The tricky part may be the password verification. To control your emotions by reading through that old salt and encrypting that old password using the old salt. It makes sense in comparison using the old encoded password within the htpasswd file.

The user can connect to the net server to be able to alter the password:

$ ssh www-data@localhost
Enter user name: szi
Old password: 
New password: 
Re-type new password: 
Updating password for user szi.
Connection to localhost closed.

Everyone can alter only their own password and nobody can access the encoded passwords from the other customers. This solution has another advantage about while using original htpasswd enter in a spend script, since the passwords will never be used like a command line argument. This wouldn't be possible with htpasswd, because it cannot browse the password from stdin like mkpasswd.