0

I'm trying to set a users password from a shell script by passing an argument to the shell script so that the password itself is not embedded within the file, and can be updated and interchanged between systems.

Here is an example password that has all sorts of problems, and is just one of many examples of something Bash pukes on: 'my@secret\npasword123!

The way that this is being run and scripted I am going to call "semi-automation" in that there will be a user behind a keyboard having to place the argument which contains the password.

Here's an example of what that looks like from the command line to visualize

./password.sh administrator 'my@secret\npasword123!

Here's what I've currently looked up for advice but have come up short, I feel like putting them here for reference may be helpful as it's possible I overlooked something but also to get a better idea as to other users with similar problems.

Here are some various methods I've currently tried for my password.sh file but have come up short with each of them

echo -e '$2\n$2' | (passwd --stdin $1)
echo $1:$2 | sudo chpasswd
yes $2 | passwd $1
sudo passwd $1 <<EOF
$2
$2
EOF

What I'm hoping to find here, is a simple "one size fits all" catch all solution that will let me encapsulate any sort of randomly generated password that can't be escaped by any means and all edge cases are covered, backslashes, dollar signs, single and double quotes, whatever Bash pukes on. Having to manually escape every instance of a special character as mentioned is out of the question.

I would also a way to quickly programmatically turn what would be a password containing special characters into a modified escaped sequence just for Bash. I looked up things such as "Bash Escape Sequence Converter" but I couldn't find any sort of tool that I could give input and would spit out a sequence that would do the needful in making sure Bash behaved as expected once I fed it that. This would add an additional step to the process, but would be acceptable.

Lastly, if there are any other alternative methods to doing and running this I would also be interested in hearing them, as long as they're able to properly escape / ignore interpretation of special characters which are going to be expected for the password.

Since this is what I call "semi-automation", I would say a desired answer is something that I could run from a Bash shell as a one-liner like I described above ( ./password.sh administrator 'my@secret\npasword123! ) but I understand this may not be possible due to limitations with Bash. I'd also as a last ditch consider a way to prompt the user from the Shell for input after the script is run as valid, but I'm not entirely sure how some automation tools would take to that in the future so it may not be entirely future proof solution.

Thanks!

  • 1
    I think you're asking at least two things: how to `read` complicated strings (bash: `read -r`) and how to call interactive programs (like `passwd`) from another program (with `expect`). – Lorinczy Zsigmond Apr 16 '19 at 04:06
  • 2
    There are three basic rules: if you're passing the string on the command line, it must be in correct shell syntax (usually meaning it must be properly quoted and/or escaped -- this *cannot* be added later); if you're `read`ing it, use `read -r`; and when using the parameter/variable, put double-quotes around it. Depending on what you're doing with the string, there *might* be other considerations, but these are rare. Except `echo`; avoid using that. See [my answer here](https://stackoverflow.com/questions/55623092/parsing-a-string-with-quotes-in-getopts/55640063#55640063) for more details. – Gordon Davisson Apr 16 '19 at 04:38
  • You can make this difficult, complex and fragile by fighting the system, or you can make it simple, secure and predictable by working *with* it. Is the point here that you have a single `password.sh` that should work on multiple systems, and it requires a different password for each one? Can you just read the password from one of the user's dotfiles? That's simple, safe, and easy to automate. – that other guy Apr 16 '19 at 05:38
  • Use `chpasswd` for batch password changing. Use `printf` instead of `echo` (it can fail with strings like `-e`). And quote all your variables. `printf "%s:%s\n" "$1" "$2" | sudo chpasswd`. – KamilCuk Apr 16 '19 at 09:31
  • @LorinczyZsigmond After playing around with `read -r` I do see how it could be useful, but I don't really understand (and haven't used) `expect` before. Could you help me understand better how it may help in this situation and maybe how I could use it? – Keegan Jacobson Apr 16 '19 at 15:45
  • @GordonDavisson seems like `read -r` works great, and I did review your link thank you for including that. It is possible to append a string containing many special characters to my understanding, but it requires potentially a lot of modification as you've mentioned. Do you know of a way to maybe `read` some sort of input and have it output a "bash compatible" line that would escape all the special characters? Maybe I'm crazy for looking for a solution like that, but it does make me curious if there is a faster / better way to do that. – Keegan Jacobson Apr 16 '19 at 15:49
  • @OP: Well, what is your actual question? – Lorinczy Zsigmond Apr 16 '19 at 16:07
  • @LorinczyZsigmond you had mentioned that using `read -r` could be used with `passwd` - After playing around with both of them I can see the direct benefit and use regarding both of them. I'm currently using `bash` still though with similar commands to above, so I'm curious how `expect` may be used in conjuction with the solution as I'm not too familiar with it. Do you have maybe a code sample or something I could review or maybe explain further how `expect` could be used with this use-case? Thank you! – Keegan Jacobson Apr 16 '19 at 16:11
  • @KeeganJacobson In general, you shouldn't try to make output "bash compatible"; bash syntax applies to commands executed by a bash shell (either interactively or in a script); it does not apply to data stored in variables or output *from* bash. In general, you should adding syntax to your data (e.g. string variables), and just pass the data around as uninterpreted blobs. – Gordon Davisson Apr 16 '19 at 19:25

0 Answers0