My goal is to test LDAP authentication from command line. I tried using ldapsearch for this.
I'm using Centos 6.7
Even though I'm using the correct credentials, the following command fails
[user#localhost html]# ldapsearch -x -h localhost -p 3389 -b "uid=john.martin,ou=Users,dc=company,dc=com" -W
Enter LDAP Password:
ldap_bind: Invalid credentials (49)
The following command works fine without the password field.
ldapsearch -x -h localhost -p 3389 -b "uid=john.martin,ou=Users,dc=company,dc=com"
Is there anything I'm missing while trying to supply the password? Could I request help to figure out the problem please?
UPDATED
Here's the structure of a user account
ldapsearch -x -h 127.0.0.1 -p 3389 -b "ou=Users,dc=company,dc=com" -s sub | more
# john.martin, Users, company.com
dn: uid=john.martin,ou=Users,dc=company,dc=com
uid: john.martin
objectClass: account
objectClass: posixAccount
objectClass: top
objectClass: shadowAccount
objectClass: ldapPublicKey
shadowLastChange: 13306
shadowMax: 99999
shadowWarning: 7
loginShell: /bin/bash
uidNumber: 509
homeDirectory: /home/john.martin
mail: john.martin#company.com
gecos: john martin
sshPublicKey:: some key
gidNumber: 87
cn: John Martin
Here's the query of searching a particular cn
ldapsearch -h 127.0.0.1 -p 3389 -x -b "dc=company,dc=com" "(&(objectClass=posixGroup)(cn=member_of_this_group))"
# extended LDIF
#
# LDAPv3
# base <dc=company,dc=com> with scope subtree
# filter: (&(objectClass=posixGroup)(cn=member_of_this_group))
# requesting: ALL
#
# member_of_this_group, groups, company.com
dn: cn=member_of_this_group,ou=groups,dc=company,dc=com
objectClass: posixGroup
objectClass: top
cn: member_of_this_group
description:: some characters bla bla
memberUid: john.martin
memberUid: kyle.miller
memberUid: robert.dangie
memberUid: smith.collins
memberUid: ian.bell
gidNumber: 54787
# search result
search: 2
result: 0 Success
# numResponses: 2
# numEntries: 1
When you do not prompt for password than the client will perform an anonymous bind (this is why you do not see an error in the example that does not prompt for the password field).
In the first example, bear in mind that the -b argument sets the search base and not the bind DN. You need to use the -D argument (for the bind DN). This may sound confusing, but ldapsearch command line tool essentially performs an LDAP BIND followed by an LDAP SEARCH (hence the two arguments).
Related
I'm using slapd-mdb and I'm looking for a way to programmatically update "maxsize" parameter using ldapmodify or similar: http://manpages.courier-mta.org/htmlman5/slapd-mdb.5.html
My main problem is that I have a huge dataset and I need more space.
Any suggestions on how to update OpenLDAP configuration programmatically would be appreciated.
My environment is Kubernetes and I deployed OpenLDAP as a container.
The "Quickstart" section of the OpenLDAP documentation includes a mdb sample configuration:
dn: olcDatabase=mdb,cn=config
objectClass: olcDatabaseConfig
objectClass: olcMdbConfig
olcDatabase: mdb
OlcDbMaxSize: 1073741824
olcSuffix: dc=<MY-DOMAIN>,dc=<COM>
olcRootDN: cn=Manager,dc=<MY-DOMAIN>,dc=<COM>
olcRootPW: secret
olcDbDirectory: /usr/local/var/openldap-data
olcDbIndex: objectClass eq
Replace the placeholders in olcSuffix, olcRootDN and olcRootPW with your values, change the OlcDbMaxSize value to suit your requirement.
Import your configration database:
su root -c /usr/local/sbin/slapadd -n 0 -F /usr/local/etc/slapd.d -l /usr/local/etc/openldap/slapd.ldif
Start SLAPD:
su root -c /usr/local/libexec/slapd -F /usr/local/etc/slapd.d
I use openldap slapd 2.4.40 and postgresql9.2.23 as back-sql on CentoS 6.9
user and password for LDAP uid and userPassword are stored in postgresql by DES encoding.
Original clear text is JacicFk5
DES encoded/encrypted text is IfjFxsltK/MPE which stored in DB.
I can see the user information as the result of ldapseach by stored password.
ldapsearch -x -b "dc=example,dc=com" -D uid="HDZZZ0R0N,ou=people,dc=example,dc=com" -w IfjFxsltK/MPE '(&(uid= HDZZZ0R0N)(objectClass=*))'
# extended LDIF
#
# LDAPv3
# base <dc=example,dc=com> with scope subtree
# filter: (&(uid= HDZZZ0R0N)(objectClass=*))
# requesting: ALL
#
# user01, people, example.com
dn: uid= HDZZZ0R0N,ou=people,dc=example,dc=com
objectClass: inetOrgPerson
cn:: W+aOkl3lia/nlKPnianjg6Hjg7Pjg4bjg4rjg7PjgrnvvIgzNu+8iVNURw==
sn:: W+aOkl3lia/nlKPnianjg6Hjg7Pjg4bjg4rjg7PjgrnvvIgzNu+8iVNURw==
uid: HDZZZ0R0N
userPassword:: SWZqRnhzbHRLL01QRQ==
However, I can’t do ldapsearch by original clear text password
ldapsearch -x -b "dc=example,dc=com" -D uid="HDZZZ0R0N,ou=people,dc=example,dc=com" -w JacicFk5 '(&(uid= HDZZZ0R0N)(objectClass=*))'
ldap_bind: Invalid credentials (49)
Does anyone tell me how to make ldapsearch to resolve given password by clear text and stored password by DES encoding?
I’d like to know is how to make plaintext JacicFk5 from ldapseach command-line to hash IfjFxsltK/MPE and make it match against IfjFxsltK/MPE in DB as userPassowrd.
Is there suitable directive for ldap.conf or slapd.conf?
I've checked followings .
echo "SWZqRnhzbHRLL01QRQ==" |perl -MMIME::Base64 -ne 'print decode_base64($_) . "\n"'
it returns IfjFxsltK/MPE
perl -e 'print("userPassword: {crypt}".crypt("JacicFk5","If")."\n");'
it returns userPassword: {crypt}IfjFxsltK/MPE
One more info.
my ldapseach can solve password text for users stored in AD server via ownclod.
What you want/need to have is a LDAP simple authentication. Please first note that it is unsecure to store passwords in plaintext!
First you need to test what auth mechanisms you have supported/allowed.
An example:
tukanos#localhost:~# ldapsearch -H ldap:// -x -LLL -s base -b "" supportedSASLMechanisms
dn:
supportedSASLMechanisms: DIGEST-MD5
supportedSASLMechanisms: CRAM-MD5
supportedSASLMechanisms: NTLM
Now you want to change the onfiguration via ldapmodify. You prepare a LDIF file (LDIF stands for LDAP Data Interchangable Format) with configuration.
Prepare your configuration file you can name it olcSaslSecProps.ldif:
dn: cn=config
replace: olcSaslSecProps
olcSaslSecProps: noanonymous,minssf=0,passcred
What the properties mean:
noanonymous ... no anonymous connection allowed
minssf=0 ... that defines your effective encryption strength (0 ... no encryption)
passcred ... that would allow password to work as for credentials
To quote the OpenLDAP security considerations
Security Strength Factors
The server uses Security Strength Factors (SSF) to indicate the
relative strength of protection. A SSF of zero (0) indicates no
protections are in place. A SSF of one (1) indicates integrity
protection are in place. A SSF greater than one (>1) roughly
correlates to the effective encryption key length. For example, DES is
56, 3DES is 112, and AES 128, 192, or 256.
A number of administrative controls rely on SSFs associated with TLS
and SASL protection in place on an LDAP session.
security controls disallow operations when appropriate protections are
not in place. For example:
security ssf=1 update_ssf=112
requires integrity protection for all operations and encryption
protection, 3DES equivalent, for update operations (e.g. add, delete,
modify, etc.). See slapd.conf(5) for details.
Now to apply the LDIF file:
ldapmodify -Y EXTERNAL -H ldapi:// -f ./olcSaslSecProps.ldif
Now to restart the slapd daemon:
systemctl restart slapd
If you check now your configuration you should get LOGIN and PLAIN:
ldapsearch -H ldap:// -x -LLL -s base -b "" supportedSASLMechanisms
dn:
supportedSASLMechanisms: PLAIN
supportedSASLMechanisms: LOGIN
Now your search should work with plain test password:
ldapsearch -x -b "dc=example,dc=com" -D uid="HDZZZ0R0N,ou=people,dc=example,dc=com" -w JacicFk5 '(&(uid= HDZZZ0R0N)(objectClass=*))'
I am trying to automate database creation process with a shell script and one thing I've hit a road block with passing a password to psql.
Here is a bit of code from the shell script:
psql -U $DB_USER -h localhost -c"$DB_RECREATE_SQL"
How do I pass a password to psql in a non-interactive way?
Set the PGPASSWORD environment variable inside the script before calling psql
PGPASSWORD=pass1234 psql -U MyUsername myDatabaseName
For reference, see http://www.postgresql.org/docs/current/static/libpq-envars.html
Edit
Since Postgres 9.2 there is also the option to specify a connection string or URI that can contain the username and password. Syntax is:
$ psql postgresql://[user[:password]#][host][:port][,...][/dbname][?param1=value1&...]
Using that is a security risk because the password is visible in plain text when looking at the command line of a running process e.g. using ps (Linux), ProcessExplorer (Windows) or similar tools, by other users.
See also this question on Database Administrators
From the official documentation:
It is also convenient to have a ~/.pgpass file to avoid regularly having to type in passwords. See Section 30.13 for more information.
...
This file should contain lines of the following format:
hostname:port:database:username:password
The password field from the first line that matches the current connection parameters will be used.
in one line:
export PGPASSWORD='password'; psql -h 'server name' -U 'user name' -d 'base name' -c 'command'
with command a sql command such as "select * from schema.table"
or more readable:
export PGPASSWORD='password'
psql -h 'server name' -U 'user name' -d 'base name' \
-c 'command' (eg. "select * from schema.table")
I tend to prefer passing a URL to psql:
psql "postgresql://$DB_USER:$DB_PWD#$DB_SERVER/$DB_NAME"
This gives me the freedom to name my environment variables as I wish and avoids creating unnecessary files.
This requires libpq. The documentation can be found here.
On Windows:
Assign value to PGPASSWORD: C:\>set PGPASSWORD=pass
Run command: C:\>psql -d database -U user
Ready
Or in one line,
set PGPASSWORD=pass&& psql -d database -U user
Note the lack of space before the && !
This can be done by creating a .pgpass file in the home directory of the (Linux) User.
.pgpass file format:
<databaseip>:<port>:<databasename>:<dbusername>:<password>
You can also use wild card * in place of details.
Say I wanted to run tmp.sql without prompting for a password.
With the following code you can in *.sh file
echo "192.168.1.1:*:*:postgres:postgrespwd" > $HOME/.pgpass
echo "` chmod 0600 $HOME/.pgpass `"
echo " ` psql -h 192.168.1.1 -p 5432 -U postgres postgres -f tmp.sql `
An alternative to using the PGPASSWORD environment variable is to use the conninfo string according to the documentation:
An alternative way to specify connection parameters is in a conninfo
string or a URI, which is used instead of a database name. This
mechanism give you very wide control over the connection.
$ psql "host=<server> port=5432 dbname=<db> user=<user> password=<password>"
postgres=>
If its not too late to add most of the options in one answer:
There are a couple of options:
set it in the pgpass file. link
set an environment variable and get it from there:
export PGPASSWORD='password'
and then run your psql to login or even run the command from
there:
psql -h clustername -U username -d testdb
On windows you will have to use "set" :
set PGPASSWORD=pass and then login to the psql bash.
Pass it via URL & env variable:
psql "postgresql://$USER_NAME:$PASSWORD#$HOST_NAME/$DB_NAME"
Just to add more clarity.
You can assign the password to the PGPASSWORD variable.
So instead of the below which will require you to type the password:
psql --host=aurora-postgres.cluster-fgshdjdf.eu-west-1.rds.amazonaws.com --port=5432 --user=my_master_user --password --dbname=postgres
We will replace the --password flag with PGPASSWORD=QghyumjB3ZtCQkdf. So it will be:
PGPASSWORD=QghyumjB3ZtCQkdf psql --host=aurora-postgres.cluster-fgshdjdf.eu-west-1.rds.amazonaws.com --port=5432 --user=my_master_user --dbname=postgres
This way you will not be required to type the password.
Added content of pg_env.sh to my .bashrc:
cat /opt/PostgreSQL/10/pg_env.sh
#!/bin/sh
# The script sets environment variables helpful for PostgreSQL
export PATH=/opt/PostgreSQL/10/bin:$PATH
export PGDATA=/opt/PostgreSQL/10/data
export PGDATABASE=postgres
export PGUSER=postgres
export PGPORT=5433
export PGLOCALEDIR=/opt/PostgreSQL/10/share/locale
export MANPATH=$MANPATH:/opt/PostgreSQL/10/share/man
with addition of (as per user4653174 suggestion)
export PGPASSWORD='password'
psql postgresql://myawsumuser:myPassword#127.0.0.1:5432/myawsumdb
I'm trying to find Active Directory users who are:
memberOf::Q049RG9tw6RuZW4tQWRtaW5zLENOPVVzZXJzLERDPXh4eCxEQz1pbnRlcm4=
(this base64 stands for CN=Domänen-Admins,CN=Users,DC=xxx,DC=intern)
Searching for it directly (via API or ldapsearch) yields no result (since it's a unicode DN):
ldapsearch -h ... -D Administrator#xxx.intern -x -w '...' -b dc=xxx,dc=intern '(memberof=CN=Domänen-Benutzer,CN=Users,DC=xxx,DC=intern)'
Following filters didn't work either:
(memberof=Q049RG9tw6RuZW4tQWRtaW5zLENOPVVzZXJzLERDPXh4eCxEQz1pbnRlcm4=)
(memberof=:Q049RG9tw6RuZW4tQWRtaW5zLENOPVVzZXJzLERDPXh4eCxEQz1pbnRlcm4=)
(memberof=::Q049RG9tw6RuZW4tQWRtaW5zLENOPVVzZXJzLERDPXh4eCxEQz1pbnRlcm4=)
I can't find any documentation except for RFC specifying base64 encoding in LDIF files.
UPDATE the above ldapsearch commands are for convenience only, it doesn't work with LDAP API either - using:
ldap.search_s('dc=xxx,dc=intern', ldap.SCOPE_SUBTREE, filter, ['cn'])
with filters:
filter='(memberof=CN=Domänen-Benutzer,CN=Users,DC=xxx,DC=intern)'.encode('utf-8') # raw UTF
filter='(memberof=CN=Domänen-Benutzer,CN=Users,DC=xxx,DC=intern)'.encode('cp1252') # raw 1252
filter=b'(memberof=CN=Dom\\e4nen-Benutzer,CN=Users,DC=xxx,DC=intern)' # hex
filter=b'(memberof=CN=Dom\\xe4nen-Benutzer,CN=Users,DC=xxx,DC=intern)' # python repr
I've also confirmed with Wireshark that the filter is indeed transmitted in UTF8
The attribute type cn has a Directory String syntax according to the standard. Directory Strings are encoded using UTF-8. Saying that searching via API yields no results incorrect. You are just using the incorrect encoding. The ldapsearch tool (assuming you are using OpenLDAP) may not support searching with accented characters.
The ldapsearch utility shipped with the UnboundID Data Store handles this pretty well. Here is the LDIF that I used for testing:
dn:: Q049RG9tw4PCpG5lbi1BZG1pbnMsZGM9ZXhhbXBsZSxkYz1jb20=
objectclass: organizationalPerson
sn: person
dn: cn=mygroup,dc=example,dc=com
objectclass: groupofnames
member:: Q049RG9tw4PCpG5lbi1BZG1pbnMsZGM9ZXhhbXBsZSxkYz1jb20=
Here is my command line test:
$ ldapsearch -b "dc=example,dc=com" "member=CN=Domänen-Admins,dc=example,dc=com"
dn: cn=mygroup,dc=example,dc=com
objectClass: top
objectClass: groupofnames
cn: mygroup
member:: Q049RG9tw4PCpG5lbi1BZG1pbnMsZGM9ZXhhbXBsZSxkYz1jb20=
Also, you may want to read the Directory String syntax from RFC 4517.
UPDATE
I managed to make this working with Active Directory (Windows Server 2012 R2, DataCenter edition) and using the ldapsearch utility shipped with the UnboundID Data Store. This is what I see:
$ ldapsearch --trustAll -Z -h <hostname> -p 636 -D "cn=administrator,cn=users,dc=dom-ad2,dc=local" -w <password> -b "cn=test,dc=dom-ad2,dc=local" "member=CN=Domänen-Benutzer,CN=test,DC=dom-ad2,DC=local"
dn: CN=mygroup,CN=test,DC=dom-ad2,DC=local
objectClass: top
objectClass: group
cn: mygroup
member:: Q049RG9tw4PCpG5lbi1CZW51dHplcixDTj10ZXN0LERDPWRvbS1hZDIsREM9bG9jYWw=
member: CN=Administrator,CN=Users,DC=dom-ad2,DC=local
distinguishedName: CN=mygroup,CN=test,DC=dom-ad2,DC=local
instanceType: 4
whenCreated: 20160514104531.0Z
You can also use the LDAPSearch example class from the UnboundID LDAP SDK (jar download link) to accomplish this. Here is the equivalent command-line I used with the LDAP SDK:
$ java -cp unboundid-ldapsdk-3.1.1.jar com.unboundid.ldap.sdk.examples.LDAPSearch --trustAll -Z -h <host> -p 636 -D "cn=administrator,cn=users,dc=dom-ad2,dc=local" -w <password> -b "cn=test,dc=dom-ad2,dc=local" "member=CN=Domänen-Benutzer,CN=test,DC=dom-ad2,DC=local"
It turned out that it's only impossible to fetch members for built-in AD groups (i.e. (isCriticalSystemObject=TRUE)). memberOf queries for user-created groups work just fine, independently from encoding used. No hex encoding was necessary.
Why are you trying to use the base64 encoded value? You must base64 decode the value before using it in a LDAP filter. It either needs to be the string representation name of the value or a hex escaped version of the string value when used in a LDAP filter.
Edit: After translating the group names a bit from your question it became more apparent to me what your issue actually is. The default "Domain Users" group is actually a primary group for a user. It will not show up in the memberOf list (hence the empty results on a search). To check if a user is a member of "Domain Users" you must inspect the primaryGroupId value for a user. In 99% of all cases this will always be the default "Domain Users" group.
I am trying to test a connection to AD using OpenLDAP and this is what I try on the command line:
/usr/bin/ldapsearch -h names.myorg.com \
-p 389 \
-D "cn=conapps readonly,cn=users,dc=myorg,dc=com" \
-LLL \
-x \
-b "ou=MyOrg Staff,ou=People,dc=myorg,dc=com" \
-s sub "(objectClass=*)" DN sn givenName mail userPrincipalName employeeID usertype \
-W
However, I keep getting the following error:
Operations error (1)
Additional information: 00000000: LdapErr: DSID-0C090627, comment: In order to perform this operation a successful bind must be completed on the connection., data 0, vece
Can anybody see what I am doing incorrectly?
Try port 3268 instead, see http://technet.microsoft.com/en-us/library/cc978012.aspx for more information
This command works for me:
$ ldapsearch -x -LLL -H ldap://test.com:3268 -dbc=test,dc=com -D 'DOMAIN\username' -W name=username dn
I think your password for bindDN is wrong, The bindDn which you are specifying is cn=readonly,cn=users,dc=myorg,dc=com and the password using -W is empty. It may be wrong and it is unable to authenticate you before doing a search.