How to convert Domain Name to Distinguished Name (DN) in LDAP? - java

I am creating a java application that able to login to LDAP server with OpenDJ Client SDK, but I only has Domain Name, User Name (also known as SAMAccountName), and Password. If you don't know domain login, see this image:
You enter the user name field in format: DOMAIN_NAME\USER_NAME instead of just plain USER_NAME. Example of Domain Name is: corp.fabrikam.com.
Now I need to know how to convert Domain Name to Distinguished Name (DN)? Because OpenDJ requires Distinguished Name to connect to LDAP.
For example: Distinguished Name from corp.fabrikam.com is: dc=corp, dc=fabrikam, dc=com.
It seems I just need to split it by ".", but I heard there is thing called Disjoint Domain:
http://technet.microsoft.com/en-us/library/cc731125%28v=ws.10%29.aspx
So splitting trick might not reliable here.
Also, user in LDAP can be under an Organizational Unit (OU). Let's say user john is belong to manager OU, so the full user DN of john would become like this:
uid=john, ou=manager, dc=corp, dc=fabrikam, dc=com

You should always refer to the RootDSE entry of the ldap server to get information about the environment you are connecting to. The RootDSE entry is readable by anyone upon an anonymous bind ( or a particular user, it does not really matter, as long as you are bound ). It contains a lot of interesting stuff, the one you are looking for is defaultNamingContext.
Once bound, perform an ldap read operation on the DN of an empty string: ''. If the framework of your choice provides some API to read the rootDSE, try to use that. It might be much more simple.
This might help you to get a kickstart:
http://opendj.forgerock.org/opendj-ldap-sdk/apidocs/index.html
I did not find any mention of the defaultNamingContext on the opendj documentation pages, but you might just get the information you are looking for via getNamingContexts() method.
Note that rootDSE is an ldap feature, it's not implementation-specific.

Related

Get AD Groups with kerberos ticket in Java

I am obtaining a kerberos ticket with the following code:
String client = "com.sun.security.jgss.krb5.initiate";
LoginContext lc = new LoginContext(client, new CallbackHandler() {
#Override
public void handle(Callback[] arg0) throws IOException, UnsupportedCallbackException {
System.out.println("CB: " + arg0);
}
});
lc.login();
System.out.println("SUBJ: " + lc.getSubject());
This code works fine, I get a subject that shows my user ID. The problem I'm having is now I need to know whether the user belongs to a certain group in AD. Is there a way to do this from here?
I've seen code to get user groups using LDAP but it requires logging in with a user/password, I need to do it the SSO way.
You cannot actually do this with the kind of ticket you get at login. The problem is that the Windows PAC (which contains the group membership information) is in the encrypted part of the ticket. Only the domain controller knows how to decrypt that initial ticket.
It is possible to do with a service ticket.
So, you could set up a keytab, use jgss to authenticate to yourself and then decrypt the ticket, find the PAC, decode the PAC and then process the SIDs. I wasn't able to find code for most of that in Java, although it is available in C. Take a look at this for how to decrypt the ticket.
Now, at this point you're talking about writing or finding an NDR decoder, reading all the specs about how the PAC and sids are put together, or porting the C code to Java.
My recommendation would be to take a different approach.
Instead, use Kerberos to sign into LDAP. Find an LDAP library that supports Java SASL and you should be able to use a Kerberos ticket to log in.
If your application wants to know the groups the user belongs to in order to populate menus and stuff like that, you can just log in as the user.
However, if you're going to decide what access the user has, don't log in as the user to gain access to LDAP. The problem is that with Kerberos, an attacker can cooperate with the user to impersonate the entire infrastructure to your application unless you confirm that your ticket comes from the infrastructure.
That is, because the user knows their password, and because that's the only secret your application knows about, the user can cooperate with someone to pretend to be the LDAP server and claim to have any access they want.
Instead, your application should have its own account to use when accessing LDAP. If you do that, you can just look up the group list.
I do realize this is all kind of complex.

valid ( existing ) email address verification

I have this registration page which works fine ,but for the email field I need to make sure that the email is correct and valid
1 : Correct
2 : Valid
for the correct email add i am using java script validation for maintaining
abc#def.com
well that is working fine
but my question is , Is there any web service or java API to make sure whether the mail ID actually is existing and registered
Like my mail id is : hussainABCD#gmail.com
this is actually a existing ID
but i may try hussain5555#gmail.com,hussain1111#gmail.com,hussain8888#gmail.com,
these will pass the java script validation but are not existing in reality
do we have any way to make sure that the mail id exists ??
The only way to check if an email address actually exists is to send an email to it and let the user respond on that.
For example:
a confirmation code that needs to be filled in your website
a link, going to your website, that needs to be visited
And still it is uncertain whether the email is existing afterwards, as it is easy to simply create a temporary email to pass the validation and delete it afterwards.
Instead of validating email addresses you can use the Google API to let your users sign in using their account. It is also possible to use OpenID on a similar way.
This probably isn't possible using existing services and/or API's, since it could be quite a security risk. Use an email with a validation link if you want to be sure the address exists. Or OpenID, as mentioned by BalusC.

Error retrieving LDAP info with search

I am trying to setup an LDAP LoginModule (using BrowserLdapLoginModule). The user/password is correctly; it retrieves the roles from the user but when it tries to extract the CN value it cannot find the values.
I have followed the process, and in the end the failure is that I get a javax.naming.NameNotFoundException in the following line
NamingEnumeration roleAnswer = ctx.search(searchBaseDN, roleFilter, roleconstraints);
with the following values (doble quotes not included):
searchBaseDN(String) = "OU=Roles,DC=siafake,DC=aplssib"
roleFilter(String) = "(distinguishedName=CN=Urgencias,OU=Roles,DC=siafake,DC=aplssib)"
derefRoleAttribute(String[] = { "cn" };
With that data, I expect the search to return me Urgencias, yet I only get the exception. It is not a permissions issue, since with the same user/password I can browse the LDAP tree without problem.
Any idea / suggestion? Thanks in advance.
Ok, here is the answer that I found (also, some clarifications to the comments from Terry Gardner comments)
My sysadmins gave me user A ("system" user, that can connect and browse the LDAP). The user that will connect to my application would b user F (final user). When asked about samples to configure my jboss, they redirected my to the BrowserLdapModuleLogin (BLML).
Turns out, BLML works by doing an initial connection with user A, for retrieving user F data (full LDAP "name").
After that, a new connection is setup using user F connection data to validate user/password and retrieve the groups (memberOf attribute) to which it belongs. Until this point, all works as it should (at least with our setup).
The trouble began when I did setup the option to just get the "CN" value (instead of CN=value,OU=organization....). By setting up this option, the module tries again to login as user F into the roles tree to get the attribute. But it happens that F does not have permissions to do so.
As the module was provided by our IT people and I am new to LDAP, I assumed I was just setting up something wrong, and I did not want to change anything in the code. In the end, it happens that in the system that uses it, this module was used only for authentication; the roles were extracted from another DB and I have been forced to code around this issue.
Sorry for the annoyances...

Share Current User Data Between Subdomains on Google App Engine for Java

I am Using Google App Engine for Java and I want to be able to share session data between subdomains:
www.myapp.com
user1.myapp.com
user2.myapp.com
The reason I need this is that I need to be able to detect if the user was logged in on www.myapp.com when trying to access user1.myapp.com. I want to do this to give them admin abilities on their own subdomains as well as allow them to seamlessly switch between subdomains without having to login again.
I am willing to share all cookie data between the subdomains and this is possible using Tomcat as seen here: Share session data between 2 subdomains
Is this possible with App Engine in Java?
Update 1
I got a good tip that I could share information using a cookie with the domain set to ".myapp.com". This allows me to set something like the "current_user" to "4" and have access to that on all subdomains. Then my server code can be responsible for checking cookies if the user does not have an active session.
This still doesn't allow me to get access to the original session (which seems like it might not be possible).
My concern now is security. Should I allow a user to be authenticated purely on the fact that the cookie ("current_user" == user_id)? This seems very un-secure and I certainly hope I'm missing something.
Shared cookie is most optimal way for your case. But you cannot use it to share a session on appengine. Except the case when you have a 3rd party service to store sessions, like Redis deployed to Cloud Instances.
You also need to add some authentication to your cookie. In cryptography there is a special thing called Message Authentication Code (MAC), or most usually HMAC.
Basically you need to store user id + hash of this id and a secret key (known to both servers, but not to the user). So each time you could check if user have provided valid id, like:
String cookie = "6168165_4aee8fb290d94bf4ba382dc01873b5a6";
String[] pair = cookie.split('_');
assert pair.length == 2
String id = pair[0];
String sign = pair[1];
assert DigestUtils.md5Hex(id + "_mysecretkey").equals(sign);
Take a look also at TokenBasedRememberMeServices from Spring Security, you can use it as an example.

Session management between thick client and server?

My application is a Eclipse Rich Client and I would like to add authentication and authorization features to. My Users and roles are stored in a database and my application also has a web based admin console which lets me manage users and roles. I am leveraging Spring security on this admin console.
So here's my requirement:
I would like my thick client to provide users with a login dialog box. The authentication would need to be performed on the server side (it could be a webservice) and the roles have to flow in to the thick client. I would also like to manage sessions on the server side, somehow.
I really can't think of any easy way to doing this. I know that if I were to use Spring Rich Client, it would integrate pretty well with Spring Security on the server side.
But, that is not an option for me at this point.
Please share your thoughts on how to acheive this. Appreciate your help.
Since you're leaning toward web services (it sounds like you are) I'd think about taking the user information from your rich client (I assume user ID and password), using WS-Security to send the encrypted info to a web service, and having the web service do the auth stuff. Also I'd think about the web service returning any info that you want to go back to the rich client about the user (first/last name, etc).
I developed a similar application recently using the Challenge-Response-authentication. Basically you have three methods in your webservice or on your server
getChallenge(username) : challenge
getSession(username, response) : key
getData(username, action?) : data
getChallenge returns a value (some random value or a timestamp for instance) that the client hashes with his/hers password and sends back to getSession. The server stores the username and the challenge in a map for instance.
In getSession the server calculates the same hash and compares against the response from the client. If correct, a session key is generated, stored, and sent to the client encrypted with the users password. Now every call to getData could encrypt the data with the session key, and since the client is already validated in getSession, s/he doesn't have to "login" again.
The good thing about this is that the password is never sent in plain text, and if someone is listening, since the password is hashed with a random value, the call to getSession will be hard to fake (by replaying a call for instance). Since the key from getSession is sent encrypted with the users password, a perpetrator would have to know the password to decipher it. And last, you only have to validate a user once, since the call to getData would encipher the data with the users session key and then wouldn't have to "care" anymore.
I've a similar requirement I think. In our case:
user provides username and password at login
check this against a USER table (password not in plain text btw)
if valid, we want a session to last, say, 20 minutes; we don't want to check username and password every time the thick client does a retrieve-data or store-data (we could do that, and in fact it wouldn't be the end of the world, but it's an extra DB op that's unnecessary)
In our case we have many privileges to consider, not just a boolean "has or has not got access". What I am thinking of doing is generating a globally unique session token/key (e.g. a java.util.UUID) that the thick client retains in a local ThickClientSession object of some sort.
Every time the thick client initiates an operation, e.g. calls getLatestDataFromServer(), this session key gets passed to the server.
The app server (e.g. a Java webapp running under Tomcat) is essentially stateless, except for the record of this session key. If I log in at 10am, then the app server records the session key as being valid until 10:20am. If I request data at 10:05am, the session key validity extends to 10:25am. The various privilege levels accompanying the session are held in state as well. This could be done via a simple Map collection keyed on the UUID.
As to how to make these calls: I recommend Spring HTTP Invoker. It's great. You don't need a full blown Spring Rich Client infrastructure, it can be very readily integrated into any Java client technology; I'm using Swing to do so for example. This can be combined with SSL for security purposes.
Anyway that's roughly how I plan to tackle it. Hope this is of some use!
Perhaps this will help you out:
http://prajapatinilesh.wordpress.com/2009/01/14/manually-set-php-session-timeout-php-session/
Notice especially this (for forcing garbage collection):
ini_set(’session.gc_maxlifetime’,30);
ini_set(’session.gc_probability’,1);
ini_set(’session.gc_divisor’,1);
There is also another variable called session.cookie_lifetime which you may have to alter as well.
IIRC, there are at least 2, possibly more, variables that you have to set. I can't remember for the life of me what they were, but I do remember there was more than 1.

Categories