Get and use a password with special characters in Bash shell
Asked Answered
S

2

5

I'm getting some troubles to use a password with special characters such as $ in a bash shell script.

My shell script is :

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

And the password could be something like $Something18$.

Well, the command

ldapadd -H ldap://localhost -x -W -D "dn=cn=Admin" -f /tmp/file.ldif` 

asks for my $Something18$, and works fine.

But if I try

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

it doesn't work. I guess it's trying to resolve the variable $Something18, so I tried with \$Something18$, \$Something18\$, \\\$Something18$, ... but it keeps on failing...

How can I do? (Without changing my password...)

Selfsown answered 21/1, 2017 at 17:16 Comment(2)
Just to make sure I understand your question, is it your script that fails and you want to get working, or your manual statement, or both?Ironwood
Well... Finally, this solution works, but didn't solve my problem. I mean, to allow a password in linux with special characters, it works. But if you're using OpenDJ, it doesn't. I finally installed OpenLDAP and everything is fine now. I don't know what they did with the ldaputilities implementation to make it fail with such a password :(Selfsown
D
3

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.

Diastase answered 21/1, 2017 at 18:38 Comment(0)
D
7

Put it in double-quotes and escape the $ symbol avoid special interpretation from the shell,

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

(or) [more recommended]

Enclose it within single-quote to let the shell treat it as a literal string without expanding it,

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

From the man bash page,

Enclosing characters in double quotes preserves the literal value of all characters within the quotes, with the exception of $, , \, and, when history expansion is enabled, !. The characters $ and retain their special meaning within double quotes. The backslash retains its special meaning only when followed by one of the following characters: $, `, ", \, or . A double quote may be quoted within double quotes by preceding it with a backslash. If enabled, history expansion will be performed unless an ! appearing in double quotes is escaped using a backslash. The backslash preceding the ! is not removed.

Dewain answered 21/1, 2017 at 17:17 Comment(1)
Single quotes would be preferable, since it doesn't require escaping the $ separately. Escaping the final $ is optional, since there is no following character to trigger a parameter expansion.Hunkers
D
3

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.

Diastase answered 21/1, 2017 at 18:38 Comment(0)

© 2022 - 2024 — McMap. All rights reserved.