Verifying user's credentials with LDAP using Net::LDAP - perl

I have an username and password and I need to verify that the username and password is found in the LDAP before letting the user into my system. I'm a newbie in LDAP and was quite confused about some terms. I know I need to bind the admin user and perform a search to check if I can find the username and password in LDAP. Then I should bind the user with the username and password.
Firstly, I don't quite understand why I need to bind the username and password at the last step.
Secondly, how do I bind the admin user? I know it should be in this format
bind("DN, OU and stuff",password=>$password)
What is the $password that I am suppose to pass?
Many thanks for your help!

The LDAP protocol is based on a request-response framework, with the exception of the unsolicited notification. The LDAP client transmits a correctly formed request to the LDAP server and then reads the response.
When an LDAP client connects to the server, the connection is not authenticated. In order to change the authentication state of a connection, the LDAP client transmits a "BIND" request to the server. A "BIND" request is either:
a simple BIND (distinguished name and credentials (password))
a SASL BIND (distinguished name or user name transmitted with other information, depending on the SASL mechanism
The server then determines whether the credentials are correct, and if they are, then the server changes the authentication state of the connection to that of the username or distinguished name and transmits a BIND response to the LDAP client. If the result code in the BIND response is 0 then the LDAP client knows that the user or distinguished name exists and the credentials are correct - there is no need to search for the user if the base object is already known.
If the connection already exists (for example, if connection pooling is used), then the client can request information about the authentication state of the connection using the authorization identity request control or the who am i? extended request. Some directory servers also support the account usable request control (which is not specified in any standards documentation but was invented by Sun Microsystems).
The base DN is the distinguished name from which a search "starts", that is, the search response would include the base DN and entries one level below the base DN if the search scope were one and all entries below the base DN if the search scope was sub or whole subtree.

Binding as the admin gives you access to search for the user. Binding as the user ensures that the password is correct.

1/ do an anonymous search if possible to lookup the dn
2/ do a bind test to verify the password
Just give you some idea, you need to fix some of the code below to match your case.
#!/usr/bin/perl
use Net::LDAP;
my $ldap = Net::LDAP->new($hostname, version => 2);
$mesg = $ldap->search(
base => $baseDN,
filter => "uid=$username",
attrs => ['dn']
);
$result = (1==0);
if ($mesg->code) {
foreach $entry ($mesg->entries) {
$dn = $entry->dn;
$bmesg = $ldap->bind($dn, $password);
$result = $bmesg->code
}
}
if ($result) {
print "Authenticated";
}

While the Perl example provided by Ken will work, its technically not the right approach. Searching is completely different versus a simple credential verification. While I won't go into the "why" on this remark, just understand that searching can behave in a misleading way, depending on how the server is configured.
As Terry mentioned, one method is the WhoAmI operation. Here's a CPAN page on the subject:
http://search.cpan.org/~marschap/perl-ldap-0.56/lib/Net/LDAP/Extension/WhoAmI.pm
As you can see, the WhoAmI operation is pretty simple when compared to a search. Only a username and password (of some kind) are needed. No filters nor search attributes are needed (nor accepted).
Basically, in laymen's terms, the WhoAmI operation would work like this (conversationally):
Client: "My name is [[insert DN here]], and my password is [[insert password here]]. Am I valid?"
Server: [[insert 'yes' or 'no' answer here]]
I hope this helps...
Max

Related

Will Directory api store my password as plain text if I dont specify hashfunction value in request body?

Will Directory api store my password as plain text if I dont specify hashfunction value in request body . kindly tell me
If we check the docs for Manage users we can see how google wants us to use the User.insert method. As far as the password goes there are a few things we can add to the body of the request.
The password itself and the hashFunction that was used to create the password
"password": "new user password",
"hashFunction": "SHA-1",
"changePasswordAtNextLogin": false,
If we read further down in the docs we will find this line.
A password is required for new user accounts. If a hashFunction is specified, the password must be a valid hash key. For more information, see the API Reference.
So you must send a password, in clear text. Then Google will hash it on their end using what ever hashing method they choose. If you then do a user.get on the ner user created the hashFunction will be filled in and google will tell you which type of hash function they used.
You do have another option you can decide yourself which hash function you want to use. By sending hashFunction as part of your request. However you then must hash the password itself. If a hashFunction is specified, the password must be a valid hash key. This option may by some be considered more secure as you are not sending a clear text password to google for hashing.
So if you want to send it clear text just let google hasht it on their end. However if your have your own favoriate hash function (dont we all) then feel free to use that as long as its one of these apparently google only supports MD5, SHA1 and crypt
resource:-user
I have added an issue request 237333031 to have some clarifications added to the documentation.

What's the easiest way to validate a username / password in Treeline?

I know this is a total novice question, but any help would be greatly appreciated.
So I'm creating my first app in Treeline and simply want to check to see if a username / password combination is valid.
What's the best way to do that given the current machines that are available? Attempted to use the Password machine with "Check Password" but wasn't immediately clear how you take the hashed password returned from "find user" and compare it to the hashed pw already stored.
Ended up figuring this out after some trial and error.
Use the Find One User machine which will return the encrypted password. Then use the Check Password machine using your unencrypted password parameter as the first value, then the FindOneUser variable as the second.
If you click the FindOneUser bubble, it will turn into a dropdown and it will allow you to choose the password key from the dictionary.

How to hide mail account password in a config file?

I have a Python3 program which sends emails. It reads variables from a config file, and one of these is the password of the email account which sends the emails. Now, it is in clear text, but it should not, so I am looking for a way to hide it.
I thought about writing directly the result of applying md5 to the password, like for example:
password = 'write_here_the_password_encrypted'
But the following code would not work:
server = smtplib.SMTP('smtp.gmail.com:587')
server.starttls()
server.login(username, password)
server.sendmail(from_email, to_emails, msg)
server.quit()
Is there anyway to make work the line server.login(username, password) if the password is encrypted?
login method from SMTP needs only plain password, not some hash of it, so the only way to make it work - unencrypt password before passing to login().
But as md5 is one way hash function (or intended to be one way), so you cannot decode the password, once you coded it into md5 hash. But even if you could, that anyone who has access to you config will also could.
What you need to do - is to separate passwords and other sensitive information to separate file, and store it in safe location, not accessible to unauthorized persons.

XMPP SASL authenfication

I want to implement a simple authentication in C++. For now I can initiate a stream, get supported mechanisms and chose one. It works fine, but now I can't read out (from http://xmpp.org/extensions/xep-0034.html#sect-id259287 ) what I have to write into the plaintext handshake. Decoding the string I get "robsecret". So how do I do it with username "user" and passsword "pass"?
PS: Response using "userpass" is "".
Thanks!
You do of course realize that this is a retracted XEP you are trying to find information in?
The relevant documents are RFC 6120 (XMPP Core) and RFC 4616 (SASL PLAIN).
Short version:
PLAIN requires you to send base64("authzid\0authcid\0password"), where authzid is usually empty and authcid is your username.

Set Active Directory password hash to a SHA1 value?

I'm syncing users from an external system into ours. I need to set the user's password in our Active Directory.
I am only provided SHA1's of the external user's passwords and setPassword will hash whatever I is input.
Is setting the User's unicodePwd the actual hash field?
If so, can I just set it to the provided hash?
If not, how/can I set the hash being stored by Active-Directory?
AD does not store just one type of hash. When you change your password, the DC receives the plaintext version of the password, checks its complexity and then generates and stores MD4, MD5, PBKDF2 (4096 * SHA1) and several other kinds of hashes. It is because each authentication mechanism (NTLM, Kerberos, Digest,...) uses a different hash function and AD needs to support them all.
The password hashes are stored in these AD attributes: unicodePwd, dBCSPwd, lmPwdHistory, ntPwdHistory and supplementalCredentials. For security reasons, you cannot read them through LDAP or ADSI. But I have recently found a way to retrieve them and created a PowerShell cmdlet that can do that:
Get-ADReplAccount -SamAccountName John -Domain Contoso -Server LON-DC1
There is also a poorly documented way to push MD4 hashes (AKA NT hashes) to workstation or AD through the legacy SAMR protocol. As there are no built-in commands that expose this functionality, I have created PowerShell cmdlets to do that, too.
To generate a NT hash, you can use this PowerShell command:
$hash = ConvertTo-NTHash (Read-Host -AsSecureString)
And finally, this command pushes the NT hash to AD:
Set-SamAccountPasswordHash -SamAccountName john -Domain ADATUM -NTHash $hash -Server dc1.adatum.com
These commands can be used to migrate passwords between local and domain accounts or between AD and Samba. But be careful, Kerberos-AES and WDigest authentication will not work with this account, only NTLM and Kerberos-RC4.
As far as I understand you can't set unicodePwd to the actual hash field. You can use the userPasswd as you want for your own check but it's not used bys Active-Directory.
As far as I know, what you want is not possible. You can change/set passwords in AD using at least three different protocols:
LDAP (actually LDAPS)
Kerberos Change Password Protocol
NTLM - I am not sure if the latest versions of AD still support it
Am 100% sure that LDAP cannot be used, but you may want to check the other two, as there may be some way to do it with them.