Get and Use a Password with Special Characters in Bash Shell

Get and use a password with special characters in Bash shell

I see two potential problems with how you're reading and using the password:

  • When you use the read command without the -r option, it'll try to interpret escape (backslash) sequences, which may cause trouble.
  • When you use a variable without wrapping it in double-quotes, it'll try to split the value into separate words and also try to expand any wildcards into a list of matching filenames. This can cause massive confusion, so you should almost always double-quote variable references.

Fixing these potential problems gives this script snippet:

read -rs -p "Password : " bindDNPass
ldapadd -H ldap://localhost -x -w "$bindDNPass" -D "dn=cn=Admin" -f /tmp/file.ldif

...But, while you should do both of these mods to make your script more robust, neither of these will change how it handles the password $Something18$. In fact, when I tried your original snippet with that password, it got passed to ldapadd correctly. If your actual password has some other special characters in it (or you've played with the value of IFS), these might help; otherwise, there's something else going on.

If your password still doesn't work after these fixes, try putting set -x before the ldapadd command (and set +x after) so it'll print what's actually being passed to ldapadd. Well, it'll print it in a possibly confusing form: it'll print an equivalent command to what's actually being executed, which means it'll add quotes and/or escapes to the password parameter as necessary so that you could run that command and it'll do the same thing. When I tried it with $Something18$, it printed:

+ ldapadd -H ldap://localhost -x -w '$Something18$' -D dn=cn=Admin -f /tmp/file.ldif

...where the single-quotes mean that what's inside them is passed directly, with no parsing. It could also have printed any of the following equivalent commands:

+ ldapadd -H ldap://localhost -x -w \$Something18\$ -D dn=cn=Admin -f /tmp/file.ldif
+ ldapadd -H ldap://localhost -x -w "\$Something18\$" -D dn=cn=Admin -f /tmp/file.ldif
+ ldapadd -H ldap://localhost -x -w $'$Something18$' -D dn=cn=Admin -f /tmp/file.ldif

so you have to take what it prints, and figure out how that'd be parsed by bash, in order to figure out what's actually being passed to ldapadd. But at least it'll give you some information about what's actually happening.

Oh, and you may notice that the DN argument isn't being double-quoted. That's because it doesn't contain any special characters, so the double-quotes aren't doing anything, so it just left them off.

curl request for login with password having special character in bash script?

  1. You should always quote variable expansions
  2. Use single-quotes to disable variable expansions and other special characters

Some issues with your current code:

  • echo $line is not properly quoted, and will break on whitespace and other special characters; use echo "$line"
    • As @GordonDavisson suggested in the comments, printf '%s\n' "$line" would actually be safer than echo, which may not work correctly depending on the contents of $line
  • admin:'$pass' will resolve to the literal characters admin:$pass being passed to curl; use "admin:${pass}"
  • https://$ip:443/admin is also not properly quoted, use "https://${ip}:443/admin"
  • If $line is being set with a literal password in the script you'll want single-quotes to have the shell ignore special characters; line='...,sbxy$sT_i7d6I*7'

pass special characters from input to bash script

The problem is probably not in your script at all, but rather on how you call it. At least from the snippets you provide, it doesn't seem like the password field is being evaluated.

So, when you call the script, if an argument contains something like $a, bash will replace it with the value of the variable a, or an empty string if it is unset.

If $ needs to be in the password, then it needs to be in single quotes.

./adduser_script username 'password$@aaa'

Special Characters in MySQL bash statement causing fail

This is a shell issue. In the example you show, the characters !! are being processed by shell history expansion before they are sent to the mysql client. So you are setting the password:

1234cd srcABC^@DEFGH

Assuming cd src was the command you ran before this one. !! is replaced with the previous command in your shell history.

There are lots of special characters in the shell that cause various expansion effects inside double-quoted strings.

You can read man bash:

There are seven kinds of expansion performed: brace expansion, tilde expansion, parameter and variable expansion, command substitution, arithmetic expansion, word splitting, and pathname expansion.

The order of expansions is: brace expansion, tilde expansion, parameter, variable and arithmetic expansion and command substitution (done in a left-to-right fashion), word splitting, and pathname expansion.

On systems that can support it, there is an additional expansion available: process substitution.

To master shell programming, you basically need to study all of these and understand which ones work inside different types of quotes.

Simple solution for handling special characters in shell script input

Hm.. Double quotes are not enough. Must use single quotes, because the rare situation, for example

mycommand --password "AAA$PWD" #is worng for any exported environment varname
mycommand --password 'AAA$PWD' #ok

Here is no way avoid this, because your users using a sort of shell, what have variable expansions and metachar-globbing. Your command getting already expanded args, so here is no way catch this in your script.

The only way - as @Bohemian told above - reading the password from a tty. You can write a simple wrapper around your current script, what will read the password from a tty and after will execute your script with properly escaped --pasword argument.



Related Topics



Leave a reply



Submit