Using the passwd command from within a shell script
Asked Answered
M

16

92

I'm writing a shell script to automatically add a new user and update their password. I don't know how to get passwd to read from the shell script instead of interactively prompting me for the new password. My code is below.

adduser $1
passwd $1
$2
$2
Melba answered 3/4, 2009 at 17:34 Comment(1)
Similar question to: askubuntu.com/questions/94060/run-adduser-non-interactively/…Emileeemili
M
114

from "man 1 passwd":

   --stdin
          This option is used to indicate that passwd should read the new
          password from standard input, which can be a pipe.

So in your case

adduser "$1"
echo "$2" | passwd "$1" --stdin

Your passwd command may not have a --stdin option: use the chpasswd utility instead, as suggested by ashawley.

If you use a shell other than bash, echo might not be a builtin command, and the shell will call /bin/echo. This is insecure because the password will show up in the process table and can be seen with tools like ps.

In this case, you should use another scripting language. Here is an example in Perl:

#!/usr/bin/perl -w
open my $pipe, '|chpasswd' or die "can't open pipe: $!";
print {$pipe} "$username:$password";
close $pipe
Mahone answered 3/4, 2009 at 17:41 Comment(3)
if bash then passwd "$1" <<< "$2"Eyeopening
@glennjackman please note that here strings implicitly create temporary files that may be readable by outside sources.Cassandracassandre
@Mahone Relying on echo keeping its arguments out of the public process tree as a side-effect of it being a built-in probably isn't the best practice. The side-effect may not hold true on all systems, echo isn't always a built-in and seeing passwords passed as arguments should just be a big red flag you should aim to avoid.Cassandracassandre
T
81

The only solution works on Ubuntu 12.04:

echo -e "new_password\nnew_password" | (passwd user)

But the second option only works when I change from:

echo "password:name" | chpasswd

To:

echo "user:password" | chpasswd

See explanations in original post: Changing password via a script

Trinitroglycerin answered 3/8, 2012 at 0:56 Comment(3)
echo 'user:newpassword' | sudo chpasswd, or without sudo as root.Emileeemili
What if the password contains a "\n" in the first case? There is a way to handle this? Such as my@secret\npasword123Jackijackie
Similar to the first but automatically repeats the password. Also, use sudo otherwise it will ask for current password first and mess this up. echo password | sed 's/.*/\0\n\0/' | sudo passwd -q $USER 2> /dev/nullMejias
R
44

Nowadays, you can use this command as root:

echo "user:pass" | chpasswd

or with sudo as permitted user:

echo "user:pass" | sudo chpasswd
Ringnecked answered 2/11, 2013 at 19:8 Comment(2)
For some reason I received the following error when trying your command: "Authentication token manipulation error". Adding sudo before chpasswd fixed this for me.Albertype
@LaurentVanWinckel - chpasswd only works with sudo/root rights. Therefore, to execute it as an user other than root, that user has to be in the sudo group: echo 'user:pass' | sudo chpasswd . When executing this one-liner on a prompt, make sure to prepend it with an additional space. Otherwise the command including the sensitive password will likely be written to the user's prompt history file, e.g. ~/.bash_history.Szechwan
C
27

Read the wise words from:

I quote:

Nothing you can do in bash can possibly work. passwd(1) does not read from standard input. This is intentional. It is for your protection. Passwords were never intended to be put into programs, or generated by programs. They were intended to be entered only by the fingers of an actual human being, with a functional brain, and never, ever written down anywhere.

Nonetheless, we get hordes of users asking how they can circumvent 35 years of Unix security.

It goes on to explain how you can set your shadow(5) password properly, and shows you the GNU-I-only-care-about-security-if-it-doesn't-make-me-think-too-much-way of abusing passwd(1).

Lastly, if you ARE going to use the silly GNU passwd(1) extension --stdin, do not pass the password putting it on the command line.

echo $mypassword | passwd --stdin # Eternal Sin.
echo "$mypassword" | passwd --stdin # Eternal Sin, but at least you remembered to quote your PE.
passwd --stdin <<< "$mypassword" # A little less insecure, still pretty insecure, though.
passwd --stdin < "passwordfile" # With a password file that was created with a secure `umask(1)`, a little bit secure.

The last is the best you can do with GNU passwd. Though I still wouldn't recommend it.

Putting the password on the command line means anyone with even the remotest hint of access to the box can be monitoring ps or such and steal the password. Even if you think your box is safe; it's something you should really get in the habit of avoiding at all cost (yes, even the cost of doing a bit more trouble getting the job done).

Cassandracassandre answered 3/4, 2009 at 20:48 Comment(2)
may I ask why this is 'still pretty insecure'? $ passwd --stdin <<< $(pass somehost/someuser)Tribasic
@JackTang You need quotes on your parameter expansion. The reason why <<< is less secure than < with a file that has good permissions is because <<< may implicitly create a temporary file that's readable by outsiders.Cassandracassandre
B
7

Here-document works if your passwd doesn't support --stdin and you don't want to (or can't) use chpasswd for some reason.

Example:

#!/usr/bin/env bash

username="user"
password="pass"

passwd ${username} << EOD
${password}
${password}
EOD

Tested under Arch Linux. This passwd is an element of shadow-utils and installed from the core/filesystem package, which you usually have by default since the package is required by core/base.

Bine answered 31/5, 2020 at 5:32 Comment(1)
Super-evil, but it's the only thing that actually worked for me :)Expression
P
2

You could use chpasswd

echo $1:$2 | chpasswd

Prokofiev answered 8/4, 2013 at 10:18 Comment(0)
E
2

I stumbled upon the same problem and for some reason the --stdin option was not available on the version of passwd I was using (shipped in Ubuntu 14.04).

If any of you happen to experience the same issue, you can work it around as I did, by using the chpasswd command like this:

echo "<user>:<password>" | chpasswd
Ellswerth answered 12/3, 2015 at 22:16 Comment(0)
E
2

For those who need to 'run as root' remotely through a script logging into a user account in the sudoers file, I found an evil horrible hack, that is no doubt very insecure:

sshpass -p 'userpass' ssh -T -p port user@server << EOSSH
sudo -S su - << RROOT
userpass
echo ""
echo "*** Got Root ***"
echo ""
#[root commands go here]
useradd -m newuser
echo "newuser:newpass" | chpasswd
RROOT
EOSSH
Euchology answered 4/5, 2017 at 21:39 Comment(0)
R
1

Tested this on a CentOS VMWare image that I keep around for this sort of thing. Note that you probably want to avoid putting passwords as command-line arguments, because anybody on the entire machine can read them out of 'ps -ef'.

That said, this will work:

user="$1"
password="$2"
adduser $user
echo $password | passwd --stdin $user
Robomb answered 3/4, 2009 at 17:49 Comment(0)
A
1

This is the definitive answer for a teradata node admin.

Go to your /etc/hosts file and create a list of IP's or node names in a text file.

SMP007-1
SMP007-2
SMP007-3

Put the following script in a file.

#set a password across all nodes
printf "User ID: "
read MYUSERID
printf "New Password: "
read MYPASS

while read -r i; do
    echo changing password on "$i"
    ssh root@"$i" sudo echo "$MYUSERID":"$MYPASS" | chpasswd
    echo password changed on "$i"
done< /usr/bin/setpwd.srvrs

Okay I know I've broken a cardinal security rule with ssh and root but I'll let you security folks deal with it.

Now put this in your /usr/bin subdir along with your setpwd.srvrs config file.

When you run the command it prompts you one time for the User ID then one time for the password. Then the script traverses all nodes in the setpwd.srvrs file and does a passwordless ssh to each node, then sets the password without any user interaction or secondary password validation.

Alexis answered 2/6, 2016 at 23:6 Comment(1)
I fixed the most egregious errors in this but this really isn't best practice at all. Hardcoding a local data file in /usr/bin is just a horrible idea.Silicate
R
1

For me on Raspbian it works only this way (old password added):

#!/usr/bin/env bash

username="pi"
password="Szevasz123"
new_ps="Szevasz1234"

passwd ${username} << EOD
${password}
${new_ps}
${new_ps}
EOD
Riella answered 3/1, 2021 at 11:57 Comment(0)
B
0

Have you looked at the -p option of adduser (which AFAIK is just another name for useradd)? You may also want to look at the -P option of luseradd which takes a plaintext password, but I don't know if luseradd is a standard command (it may be part of SE Linux or perhaps just an oddity of Fedora).

Berton answered 3/4, 2009 at 17:43 Comment(0)
I
0

Sometimes it is useful to set a password which nobody knows. This seems to work:

tr -dc A-Za-z0-9 < /dev/urandom | head -c44 | passwd --stdin $user
Islam answered 7/7, 2014 at 9:33 Comment(2)
It's better to disable an account / disable its login than giving it an unknown password but leaving its login active.Epaulet
passwd --delete or --lockIrradiance
S
0

echo 'yourPassword' | sudo -S yourCommand

if -S doesnt work try with -kS

Salve answered 21/8, 2021 at 20:35 Comment(0)
P
0

Auto-generated random password from all graphical characters

The top answer by @fernando-kosh could not easily be used when the password may contain \ character because echo -e would interpret \ as having special meaing.

Since I am auto-generating password from graphical character set which may also contain \, I a different way to send new password twice to stdout with newline in between. Here is a solution with yes command:

NEW_PASSWORD=$(tr -dc '[:graph:]' </dev/urandom | head -c "${PASSWORD_LENGTH:-30}")

yes "$NEW_PASSWORD" | \
  head -n 2 | \
  sudo passwd "$TARGET_USERNAME"

This will generate 30-character random password by default if PASSWORD_LENGTH is not set.

Pewit answered 15/3 at 14:7 Comment(0)
P
-1

You can use the expect utility to drive all programs that read from a tty (as opposed to stdin, which is what passwd does). Expect comes with ready to run examples for all sorts of interactive problems, like passwd entry.

Profiterole answered 2/6, 2012 at 8:21 Comment(0)

© 2022 - 2024 — McMap. All rights reserved.