Why does LDAP requires a two step "login" (connect and then bind) - ldap

There's this thing I don't understand concerning LDAP (conceptually speaking, and - at least so I think - not tied to a particular implementation).
I noticed that a typical LDAP client library(for example apache DS) does a connect() first (for which some servers might require username/password), and then executes a bind() operation (which also requires username and password).
Questions:
What is the point of this two step operation in LDAP?
Does it add extra security?
Why not just a single step ?
What is the conceptual signification of these two steps ?

When an LDAP client connects to an LDAP server, that connection is unauthenticated. Clients use the BIND operation to authenticate the connection. The server then processes requests on the connection using the authorization state of the connection with the privileges and access control thereto.
Some (if not most) LDAP APIs offer a single-step connection and BIND, for which one must provide the credentials of the user, or a pre-constructed BIND request (there are different types of BIND requests, simple and SASL). In the case you describe, the API is most likely establishing a connection to the server and then issuing the BIND request to the server. If this is successful, then the connection's authorization state is set. This would be a "convenience" method for clients.
Separating the connection from the BIND (the two steps you mention), is done so that the same connection can be used with different authorization states. Each BIND resets the authorization state of the connection. The LDAP client can connect, then BIND using one user and credentials, perform some operations as that user, then send another BIND request on the same connection to change the authorization state to that of a different user. This enables the client and server to be more efficient since the connection need not be made more than once. This is supported by LDAPv3.
The UNBIND request's name is a relic of LDAPv2, which did not allow multiple authorization states per connection. UNBIND is not the opposite of BIND, and it does disconnect as you discovered. LDAP clients using LDAPv3 can transmit a BIND request to change the authorization state of the connection. The misnamed UNBIND request does not "un-authorize" a state, it merely disconnects the LDAP client from the LDAP server.
see also:
LDAP: Programming Practices
LDAP: Authentication Best Practices

Actually, there is a difference!
Connect() refers to the connection to a LDAP server on a specified hostname and port, as the bind () binds to the LDAP directory with specified RDN and password.
Hope this is helpful!

Related

Using socket io over http, is a secure log in procedure possible?

I have built a game server in nodejs using socket io.
I am planning to remove express and cookies from the authentication procedure and instead use webstorage and a client which attempts to log in during the socket io handshake.
However, I am using http and sending the user id and password in cleartext. Please, have mercy on me! I believe using https for the entire socket connection would add a huge overhead since updates are sent every 100ms. My current solution has worked for development, but I am sure it is insecure.
I should mention I have never set up/used https, so correct me if I am wrong regarding the overhead, which I know is a very debated topic. An ideal solution appears to be authenticating users over a https connection and then transmitting game state stuff over http, but I have no idea if or how this could be achieved.
Finally, I have 2 options for logging users in. I could allow the socket io connection on the server and just emit the log in credentials from the client. Then disconnect them if they are incorrect.
However, a cleaner solution would be to send the user id and pw in the http header for the handshake, and then authenticate the user from a socket.io middleware, but I am not sure if sending the data this way would be safe.
I do not think this is such a niche problem that a standard practice does not exist, however it may be to just use https. I believe there is no advantage to encrypting the users credentials as the data can still be snooped between the client and server. Any information on how I can achieve this is appreciated,
Or just point me in the right direction :)
Use one https connection for the login authentication and reply back to the client with a unique security token if the username/password is valid.
Use ordinary http connections for the rest of the dialog between client and server. Include the security token in the dialog if the client is requesting something that requires validation. Your client can store the security token in a cookie if you find that convenient, as the token can only be used for one session.
Have the server purge session tokens once a client signs off, or after the token has been idle for some period of time.
This is cheap and effective for medium-security applications. Variations on this scheme get used in many applications. It is not foolproof - a packet sniffer may be able to grab the security token in transit.
If the security token is constructed from a hash of the client IP address and a server timestamp, then it is easy for the server to validate the token in every message and very difficult for a 3rd-party to hijack the session.

LDAP connections using BIND authentication mechanism

If LDAPv3 is being used with BIND authentication mechanism, then are multiple connections created between client and ldap server? Or just multiple sessions?
As per my understanding,
using ldapv3, for a deployed application, only a single connection will be created from client to LDAP server using manager dn and password. Every BIND request from the client using user's login credentials does not create a connection. It just creates a new session - rebinding happens with different credentials over a single connection created using manager dn and password.
Can BIND requests be sent concurrently to the LDAP server over a single connection?
I think we need some context.
LDAP uses TCP as a transport protocol. Once the transport connection over TCP is made, LDAP can then perform a LDAP requests within the TCP Connection.
You can establish a TCP Connection and bind as one user and then bind as a different user of the same TCP Connection.
Of course, TCP connections do die typically when not used based on the TCP Timeout values and maybe closed by either the Client or server. (Or a load balancer in the middle)
ONLY talking about LDAPv3 RFC 4511 (section 4.2.1) states that bind operations cannot be processed on a connection that has any other outstanding operations. In particular "Before processing a Bind Request, all uncompleted operations MUST either complete or be "abandoned" and "After sending a Bind Request, clients MUST NOT send further LDAP PDUs until receiving the Bind Response."
LDAP is an inherently asynchronous protocol, EXCEPT for BindRequests, meaning that, in most cases, you can issue multiple concurrent requests over the same connection and the client will be able to correlate the responses with their appropriate requests.
Most of the JAVA LDAP SDKs and other LDAP API function calls have both Synchronous Operation and Asynchronous Operation versions.
-jim
This is all completely confused. Bind requests are created over an existing connection. They either succeed or fail. They create an LDAP session of sorts, if successful, but it only lasts as long as the connection it was established with, or until another BIND request. LDAP connections are shortlived in general: they are only there to authenticate the user, or retrieve information about him from the DIT. They are not long-lived or persistent: at least they shouldn't be, if correctly programmed.
Can BIND request be sent concurrently to the LDAP server over a single connection?
Nothing can be sent concurrently to anything over a single connection. The question doesn't make sense. [Multiplexed protocols excluded, but LDAP is not one of them.]

Delegation in WCF not working - First hop is NTLM?

I'm working on a project which requires delegation in a double-hop scenario. We have a desktop client, connecting to a WCF service using a net.tcp binding, connecting to a SQL database on another server. Our goal is to use the user's credentials to access the SQL database.
Both the WCF service and SQL database are running under the same domain user, which has delegation enabled for the SQL database. The instructions here have been followed, with no success.
Now, some details recorded in our logs:
The login used on the SQL database appears as the user the WCF service is running under, and uses Kerberos.
The login used on the WCF server appears as the client's user, but uses NTLM.
Using either [OperationBehavior(Impersonation = ImpersonationOption.Allowed)] or using (ServiceSecurityContext.Current.WindowsIdentity.Impersonate()) results in commands being run as the client, on the WCF server. This leads me to believe impersonation is working fine.
So, what could be causing the first hop to fall back to NTLM? We suspect it's a SPN issue, but we've registered the SPNs of both the WCF service and SQL service to the shared domain user. Also, as per the instructions listed above, we've set the SQL service as trusted for delegation on the domain user.
We've used EndpointIdentity.CreateSpnIdentity on the WCF service to set the SPN, and this is the SPN we've registered to the domain user.
Any suggestions? Thanks in advance!
Edit:
We've found something that may have been an issue - We had not used EndpointIdentity.CreateSpnIdentity on the client. After setting this we receive the error
“call to SSPI failed” with an inner exception of “target principle name is incorrect”. But the SPN we've set in the client and the server match, and both match the hostname of the service. If we set both the client and the server SPN to something completely different, or if the client's specified SPN does not match the server's SPN, authentication falls back to NTLM as it did before. We've done research into the error, but cannot find its cause. Any suggestions?
We've also performed packet captures of both cases - falling back to NTLM and when we receive the "call to SSPI failed" error. In both cases, similar packets are sent and received until, on one, NTLM is mentioned. On the other, a "TURN CHANNEL" packet is sent from the client to the server. The packets contain nothing human readable except the IP address of the server until either NTLM is mentioned, and the username and computer names are sent, or the "TURN CHANNEL" packet is sent, which contains what appears to be the SPN, and possibly the hostname. There doesn't appear to be any human readable error codes or error messages. Any suggestions on what to look for in the packets?
We found our error - the client was creating the connection using the IP address of the server. After switching the IP to a fully qualified domain name, the first hop consistently authenticates using Kerberos.
The IP address resolves to the same string we used in both SPNs, but I suppose the client checks if the connection string matches the portion of the SPN following the slash before performing any other checks.
We tested our results using both Network Service and our domain user, and as long as the SPN was registered to the computer or user respectively, there were no issues.
Hopefully this answer will save others some time and hassle!
Additional Note: While this enabled Kerberos authentication for all connections, we later discovered that this was unnecessary in our situation. Part of our connection to the database was not inside the impersonation using block, which was causing the table read to fail. We have since removed all delegation and SPN related code, and the database connection continued to work correctly. Our first hop is using NTLM. We're not exactly sure how the credentials are being used at the SQL server, as our connection appears to be exactly what is described as the double hop scenario, which should require Kerberos and delegation, but it's hard to argue with what's working. I suspect it may have something to do with the note located under delegation in this document:
When a client authenticates to the front-end service using a user name and password that correspond to a Windows account on the back-end service, the front-end service can authenticate to the back-end service by reusing the client’s user name and password. This is a particularly powerful form of identity flow, because passing user name and password to the back-end service enables the back-end service to perform impersonation, but it does not constitute delegation because Kerberos is not used. Active Directory controls on delegation do not apply to user name and password authentication.
If anyone has any other suggestions for the reason it's working, I'd love to hear them. However, I don't feel it's worth opening another question for.

LDAP bind associations with subsequent requests

I'm wondering how LDAP associates requests with a previous BIND request on a technical level.
For example you issue a BIND request to LDAP that authenticates you to do searches or whatever then you UNBIND.
How does LDAP associate your subsequent SEARCH/ADD etc. requests after the BIND?
I'm currently digging through a packet capture of a bunch of LDAP requests and I don't see the bindResponses returning a session token or anything like that ... does it just consider an IP authenticated or something?
Thanks if anyone can shed some light on the internal mechanism here!
edit: using SIMPLE auth BINDs
Are you talking to the LDAP server using UDP or TCP?
With TCP, it's simple - you do a BIND, then that TCP connection remains authenticated for any subsequent operations issued on the connection, until the connection closes or you issue an UNBIND.

Using HTTPS for the client-server communication

I would like to use the HTTPS to secure the communication between my client and the server. The first encrypted communication will be used to authenticate the user - i.e. checking his/her user name and password.
After the user credentials will be successfully checked by server I would like to start getting some data in subsequent requests. BUT how the server will determine that the subsequent request is send by the user, whose credentials were already checked?
Since the TCP connection might be closed between login and subsequent HTTPS requests, (I think) this means that the SSL context must be released by the server, so with the new GET request, the new TCP connection must be established and the new SSL(TLS) handshake must be done (i.e. new shared password for the encryption must be exchanged by both sides, etc.)
For this I think server needs to send back to the client in 200 OK response for the initial authentication request some randomly generated nonce (which is valid for a certain time), which I will include in every subsequent request, so the server will be able to detect, based on this randomly generated nonce, which user name is behind the request and check that this user is already logged in. Is my understanding correct?
Thanks a lot for the reply
BR
STeN
The simplest method is to require all communication to go via HTTPS (so the data is confidential; nobody other than the client and the server can see it) and to use simple username and password on every request inside that secure connection. This is dead simple to do in practice (the username and password actually go over the connection as an HTTP header, which is OK here because we're using HTTPS) and the server can check every time that the user is allowed. You don't need to worry about the SSL handshakes; that's the SSL/HTTPS layer's responsibility (and that's why HTTPS/SSL is nice).
Alternatively, the login can be done with any method and generate some kind of magic number (e.g., a UUID or a cryptographic hash of a random number and the user's name) that is stored in a session cookie. Subsequent requests can just check that the magic number is one that it recognizes from session start (and that not too much time has passed since it was issued); logout just becomes forgetting the magic number on the server side (and asking the client to forget too). It's a bit more work to implement this, but still isn't hard and there are libraries for server-side to handle the donkey work.
The first option is particularly good for where you're writing something to be used by other programs, as it is really easy to implement. The second option is better where the client is a web browser as it gives users more control over when their browser is authorized (program APIs don't tend to need that sort of thing). Whenever the client is going to be a browser, you need to take care to armor against other types of attack too (e.g., various types of request forgery) but that's pretty much independent of everything else.
Inventing custom authentication mechanism in your case is very risky - it's easy to make a mistake that will let lots of wrong doing. So the right approach, as for me, would be to use HTTPS and pass user credentials with each request.