I have a problem adding an entry in LDAP, precisely I want to add a user.
class AddUser {
public static void main(String[] args) {
String userName = "manager";
String password = "pass";
Hashtable env = new Hashtable();
env.put(Context.INITIAL_CONTEXT_FACTORY, "com.sun.jndi.ldap.LdapCtxFactory");
env.put(Context.PROVIDER_URL, "ldap://192.168.10.45:389/dc=mydc,dc=local");
env.put(Context.SECURITY_AUTHENTICATION, "simple");
env.put(Context.SECURITY_PRINCIPAL, new String("mydc" + "\\" + userName));
env.put(Context.SECURITY_CREDENTIALS, password);
// env.put(Context.REFERRAL, "follow");
// entry's DN
String entryDN = "cn=NewUser, dc=mydc, dc=local";
// entry's attributes
Attribute cn = new BasicAttribute("cn", "NewUser");
Attribute sn = new BasicAttribute("sn", "Smith");
Attribute mail = new BasicAttribute("mail", "newuser#foo.com");
Attribute phone = new BasicAttribute("telephoneNumber", "+1 222 3334444");
Attribute uid = new BasicAttribute("uid", "nsmith");
Attribute userPassword = new BasicAttribute("userPassword", "pwd1");
Attribute oc = new BasicAttribute("objectClass");
oc.add("dcObject");
oc.add("person");
oc.add("inetOrgPerson");
DirContext ctx = null;
try {
// get a handle to an Initial DirContext
ctx = new InitialDirContext(env);
// build the entry
Attributes entry = new BasicAttributes();
entry.put(cn);
entry.put(sn);
entry.put(mail);
entry.put(phone);
entry.put(uid);
entry.put(userPassword);
entry.put(oc);
// Add the entry
ctx.createSubcontext(entryDN, entry);
System.out.println("AddUser: added entry " + entryDN + ".");
} catch (NamingException e) {
System.err.println("AddUser: error adding entry." + e);
}
}
}
I got the following error:
AddUser: error adding
entry.javax.naming.directory.NoSuchAttributeException: [LDAP: error code 16 - 00000057: LdapErr: DSID-0C090C3E, comment: Error in attribute conversion operation, data 0, v1db1 ]; remaining name cn=NewUser, dc=mydc, dc=local
I don't know where is the error. Can be only a bad input about the attributes?
The right code is the following:
public static void main(String[] args) {
String userName = "admin";
String password = "s3cret";
Hashtable env = new Hashtable();
env.put(Context.INITIAL_CONTEXT_FACTORY, "com.sun.jndi.ldap.LdapCtxFactory");
env.put(Context.PROVIDER_URL, "ldap://192.168.10.10:389/DC=SOFTWAREDEV,DC=LOCAL");
env.put(Context.SECURITY_AUTHENTICATION, "simple");
env.put(Context.SECURITY_PRINCIPAL, new String("softwaredev" + "\\" + userName));
env.put(Context.SECURITY_CREDENTIALS, password);
String path = "OU=SoftwareV3,OU=SOFTWARE";
String newUser = "myUser"; // insert user here
String entryDN = "CN=" + newUser + "," + path;
Attribute cn = new BasicAttribute("cn", newUser);
Attribute oc = new BasicAttribute("objectClass");
oc.add("top");
oc.add("person");
oc.add("organizationalPerson");
oc.add("user");
DirContext ctx = null;
try {
ctx = new InitialDirContext(env);
Attributes entry = new BasicAttributes();
entry.put(cn);
entry.put(oc);
ctx.createSubcontext(entryDN, entry);
System.out.println("AddUser: added entry " + entryDN + ".");
} catch (NamingException e) {
System.err.println("AddUser: error adding entry." + e);
}
}
Related
I am new to LDAP. And I did the authentication part using LDAP INITIAL_CONTEXT_FACTORY ("com.sun.jndi.ldap.LdapCtxFactory"). Code of what I did is as follows.
String url = ldap_url;
String uname = request.getUsername();
String pwd = request.getPassword();
boolean authentication = false;
boolean error = true;
String msg, attributes, search;
String ldapDn = String.format("%s%s", searchFilter,uname);
// create env for initial context
Hashtable env = new Hashtable();
env.put(Context.INITIAL_CONTEXT_FACTORY, "com.sun.jndi.ldap.LdapCtxFactory");
env.put(Context.PROVIDER_URL, url);
env.put(Context.SECURITY_AUTHENTICATION, "simple");
env.put(Context.SECURITY_PRINCIPAL, ldapDn);
env.put(Context.SECURITY_CREDENTIALS, pwd);
try {
DirContext ctx = new InitialDirContext(env);
authentication = true;
error = false;
ctx.close();
} catch (Exception e) {
} finally {
if (!error) {
msg = "Login success!!!";
} else {
msg = "Authentication failed!";
}
}
Now I need to fetch the "employee_id" which returns with the LDAP result. I went through few examples in the internet and I could not make it happen. It will be great if anyone can suggest me a better way to search this attribute.
I'm trying to do an LDAP authentication using Java but this always return a null result and usrNamespace. Also was able to confirm that the username and password passed are correct.
With the username I use cn, i tried changing (uid=" + username + ") to cn but still gives me the same result
If anyone can help me that would be greatly appreciated. Thank you!
public class LdapAuthenticationAdapter implements AuthenticationAdapter {
#Override
public boolean authenticate(String username, String password) throws Exception {
Properties prop = new Properties();
//set the property value
SECURITY_AUTHENTICATION = prop.getProperty("eq.SECURITY_AUTHENTICATION");
SECURITY_PRINCIPAL = prop.getProperty("eq.SECURITY_PRINCIPAL");
SECURITY_CREDENTIALS = prop.getProperty("eq.SECURITY_CREDENTIALS");
PROVIDER_URL = prop.getProperty("eq.PROVIDER_URL");
// Get admin user, password(encrypted), host, port and other LDAP parameters
// from equationConfiguration.properties
Hashtable<String, Object> env = new Hashtable<String, Object>();
env.put(Context.SECURITY_AUTHENTICATION, "simple");
env.put(Context.SECURITY_PRINCIPAL, "uid=admin,ou=system");
env.put(Context.SECURITY_CREDENTIALS, "secret");
env.put(Context.INITIAL_CONTEXT_FACTORY, "com.sun.jndi.ldap.LdapCtxFactory");
env.put(Context.PROVIDER_URL, "ldap://localhost:10389/dc=main,dc=com");
// env.put("java.naming.ldap.attributes.binary", "objectSID"); // validate this line if applicable
InitialDirContext context = new InitialDirContext(env);
SearchControls ctrls = new SearchControls();
ctrls.setReturningAttributes(new String[] { "givenName", "sn","memberOf" });
ctrls.setSearchScope(SearchControls.SUBTREE_SCOPE);
NamingEnumeration<javax.naming.directory.SearchResult> answers = null;
SearchResult result = null;
String usrNamespace = null;
try {
answers = context.search("ou=bankfusionusers", "(uid=" + username + ")", ctrls); // Get directory context
result = answers.nextElement();
usrNamespace = result.getNameInNamespace();
Properties props = new Properties();
props.put(Context.INITIAL_CONTEXT_FACTORY, "com.sun.jndi.ldap.LdapCtxFactory");
props.put(Context.PROVIDER_URL, "ldap://localhost:10389/dc=main,dc=com");
props.put(Context.SECURITY_PRINCIPAL, usrNamespace);
props.put(Context.SECURITY_CREDENTIALS, password);
System.err.println("Entry 1");
context = new InitialDirContext(props);
}catch(NullPointerException e){
System.err.println("Unsuccessful authenticated bind " + e + "\n");
return false;
}
return true;
}//end method
}
I changed your code a little bit, and it works on mine.
public static void main(String[] args) throws NamingException {
Properties initialProperties = new Properties();
initialProperties.put(Context.INITIAL_CONTEXT_FACTORY, "com.sun.jndi.ldap.LdapCtxFactory");
initialProperties.put(Context.PROVIDER_URL, "ldap://192.168.0.179:389");
initialProperties.put(Context.SECURITY_PRINCIPAL, "cn=Directory Manager");
initialProperties.put(Context.SECURITY_CREDENTIALS, "dirmanager");
initialProperties.put(Context.SECURITY_AUTHENTICATION, "simple");
InitialDirContext context = new InitialDirContext(initialProperties);
SearchControls ctrls = new SearchControls();
ctrls.setReturningAttributes(new String[] { "cn", "sn","givenname" });
ctrls.setSearchScope(SearchControls.SUBTREE_SCOPE);
NamingEnumeration<javax.naming.directory.SearchResult> answers = null;
SearchResult result = null;
String usrNamespace = null;
try {
String username = "user.997"; // I added this, I removed some of your code as well
answers = context.search("dc=example,dc=com", "(uid=" + username + ")", ctrls); // Get directory context
result = answers.nextElement();
usrNamespace = result.getNameInNamespace();
System.out.println("result variable shows : " + result);
System.out.println("usrNamespace variable shows: " + usrNamespace);
}catch(NullPointerException e){
System.err.println("Unsuccessful authenticated bind " + e + "\n");
}
}
}
In my console, I see
Is their any way to fetch duplicates from AD using java ? I see we can do it in power shell by grouping all usernames and then checking count >1.
https://gallery.technet.microsoft.com/scriptcenter/Find-Active-Directory-c8789b42
Please help :).
you should get all objects of a special type(such as user, group , ...) and their attributes. then check duplicate attributes of all objects. for do this, you can insert each attributes in a hasp map as a key, and insert all value of attribute per each object and check is duplicated or not ?
use JAVA JNDI to access AD server as follow:
/**
* retrieve all attributes of a named object.
*
*/
class GetAllAttrs {
static void printAttrs(Attributes attrs) {
if (attrs == null) {
System.out.println("No attributes");
} else {
/* Print each attribute */
try {
for (NamingEnumeration ae = attrs.getAll(); ae.hasMore();) {
Attribute attr = (Attribute) ae.next();
System.out.println("attribute: " + attr.getID());
/* print each value */
for (NamingEnumeration e = attr.getAll(); e.hasMore(); System.out
.println("value: " + e.next()))
;
}
} catch (NamingException e) {
e.printStackTrace();
}
}
}
public static void main(String[] args) {
// Set up the environment for creating the initial context
Hashtable<String, Object> env = new Hashtable<String, Object>(11);
env
.put(Context.INITIAL_CONTEXT_FACTORY,
"com.sun.jndi.ldap.LdapCtxFactory");
env.put(Context.PROVIDER_URL, "ldap://localhost:389/o=JNDITutorial");
try {
// Create the initial context
DirContext ctx = new InitialDirContext(env);
// Get all the attributes of named object
Attributes answer = ctx.getAttributes("cn=Ted Geisel, ou=People");
// Print the answer
printAttrs(answer);
// Close the context when we're done
ctx.close();
} catch (Exception e) {
e.printStackTrace();
}
}
}
also you can use search filter to limit your outputs:
public class LdapSearch {
public static void main(String[] args) throws Exception {
Hashtable env = new Hashtable();
String sp = "com.sun.jndi.ldap.LdapCtxFactory";
env.put(Context.INITIAL_CONTEXT_FACTORY, sp);
String ldapUrl = "ldap://localhost:389/dc=yourName, dc=com";
env.put(Context.PROVIDER_URL, ldapUrl);
DirContext dctx = new InitialDirContext(env);
String base = "ou=People";
SearchControls sc = new SearchControls();
String[] attributeFilter = { "cn", "mail" };
sc.setReturningAttributes(attributeFilter);
sc.setSearchScope(SearchControls.SUBTREE_SCOPE);
String filter = "(&(sn=W*)(l=Criteria*))";
NamingEnumeration results = dctx.search(base, filter, sc);
while (results.hasMore()) {
SearchResult sr = (SearchResult) results.next();
Attributes attrs = sr.getAttributes();
Attribute attr = attrs.get("cn");
System.out.print(attr.get() + ": ");
attr = attrs.get("mail");
System.out.println(attr.get());
}
dctx.close();
}
}
I want to query my ldap to give me all users where sn contains a specific value (maier). However I always get a single result.
public LdapContext getLdapContext(){
LdapContext ctx = null;
try{
Hashtable<String, String> env = new Hashtable<String, String>();
env.put(Context.INITIAL_CONTEXT_FACTORY, "com.sun.jndi.ldap.LdapCtxFactory");
env.put(Context.PROVIDER_URL, "ldap://ldap.url:389");
ctx = new InitialLdapContext(env, null);
System.out.println("Connection Successful.");
}catch(NamingException nex){
System.out.println("LDAP Connection: FAILED");
nex.printStackTrace();
}
return ctx;
}
private User getUserBasicAttributes(String username, LdapContext ctx) {
User user=null;
try {
SearchControls constraints = new SearchControls();
constraints.setSearchScope(SearchControls.SUBTREE_SCOPE);
String[] attrIDs = { "distinguishedName",
"sn",
"givenname",
"mail",
"telephonenumber"};
constraints.setReturningAttributes(attrIDs);
constraints.setCountLimit(200);
NamingEnumeration answer = ctx.search("DC=myDc,DC=com", "sn=*maier*", constraints);
if (answer.hasMore()) {
Attributes attrs = ((SearchResult) answer.next()).getAttributes();
System.out.println("distinguishedName "+ attrs.get("distinguishedName"));
System.out.println("givenname "+ attrs.get("givenname"));
System.out.println("sn "+ attrs.get("sn"));
System.out.println("mail "+ attrs.get("mail"));
System.out.println("telephonenumber "+ attrs.get("telephonenumber"));
}else{
throw new Exception("Invalid User");
}
} catch (Exception ex) {
ex.printStackTrace();
}
return user;
}
Did I do anything wrong?
You're not looping, so of course you're only getting one result. Change if (answer.hasMore()) to while (answer.hasMore()).
I'm trying to change the mail and password attributes of Active Directory using java. To do this, it was generated a security certificate and imported into the certificate store of the jvm (carcerts). The connection is made using ssl successfully however when trying to change any field, eg mail,I get the following error message:
javax.naming.OperationNotSupportedException: [LDAP: error code 53 - 00002035: LdapErr: DSID-0C090B3E, comment: Operation not allowed through GC port, data 0, v1db1
source code:
// change mail
private void salvarEmailESenhaNoAd() throws IOException, NamingException {
Properties mudaSenhaProperties = new PropertiesFactory().propertiesByJndi("mudaSenha");
ADUtil adUtil = null;
try
{
adUtil = new ADUtil(mudaSenhaProperties);
adUtil.changeEmail("CN=018061671627,OU=SDS,OU=CS,OU=STI,OU=DG,OU=PRES,OU=TRERN,DC=tre-rn,DC=jus,DC=br", dadosUsuario.getEmail());
}
finally
{
if (adUtil != null)
{
adUtil.close();
}
}
}
public class ADUtil {
private LdapContext ldapContext = null;
public ADUtil(Properties properties) throws NamingException
{
ldapContext = createUserContext(properties);
}
private LdapContext createUserContext(Properties properties) throws NamingException {
String javaNamingFactoryInitial = properties.getProperty("java.naming.factory.initial");
String javaNamingProviderUrl = properties.getProperty("java.naming.provider.url");
String javaNamingSecurityAuthentication = properties.getProperty("java.naming.security.authentication");
String javaNamingSecurityPrincipal = properties.getProperty("java.naming.security.principal");
String javaNamingSecurityCredentials = properties.getProperty("java.naming.security.credentials");
String javaNamingSecurityProtocol = properties.getProperty("java.naming.security.protocol");
String javaNamingReferral = properties.getProperty("java.naming.referral");
String javaNetSslTrustStore = properties.getProperty("javax.net.ssl.trustStore");
String javaNetSslTrustStorePassword = properties.getProperty("javax.net.ssl.trustStorePassword");
Hashtable<String, String> env = new Hashtable<String, String>();
System.setProperty("javax.net.ssl.trustStore", javaNetSslTrustStore);
System.setProperty("javax.net.ssl.trustStorePassword", javaNetSslTrustStorePassword);
env.put(Context.INITIAL_CONTEXT_FACTORY, javaNamingFactoryInitial);
env.put(Context.SECURITY_AUTHENTICATION, javaNamingSecurityAuthentication);
env.put(Context.SECURITY_PRINCIPAL, javaNamingSecurityPrincipal);
env.put(Context.SECURITY_CREDENTIALS, javaNamingSecurityCredentials);
env.put(Context.SECURITY_PROTOCOL, javaNamingSecurityProtocol); // para poder modificar password y grupos del usuario.
env.put(Context.PROVIDER_URL, javaNamingProviderUrl);
env.put(Context.REFERRAL, javaNamingReferral);
return new InitialLdapContext(env, null);
}
public void changePassword(String userCN, String newPassword) throws NamingException, UnsupportedEncodingException, IOException {
modifyAdAttribute(userCN, "unicodePwd", converteString(newPassword));
System.out.println("Password changed for " + userCN);
}
public void changeEmail(String userDN, String newEmail) throws NamingException, UnsupportedEncodingException, IOException {
modifyAdAttribute(userDN, "mail", converteString(newEmail));
System.out.println("Email changed for " + newEmail);
}
private void modifyAdAttribute(String userCN, String attribute, Object value) throws NamingException{
ModificationItem[] modificationItem = new ModificationItem[1];
modificationItem[0] = new ModificationItem(DirContext.REPLACE_ATTRIBUTE,
new BasicAttribute(attribute, value));
ldapContext.modifyAttributes(userCN, modificationItem);
}
private static byte[] converteString(String password) throws UnsupportedEncodingException{
String newQuotedPassword = "\"" + password + "\"";
return newQuotedPassword.getBytes("UTF-16LE");
}
public void close() throws NamingException
{
if (ldapContext != null)
{
ldapContext.close();
}
}
Reading the attributes is usually done with the code below:
public class TesteLdap {
/**
* #param args the command line arguments
*/
private static SearchControls getSimpleSearchControls() {
SearchControls searchControls = new SearchControls();
searchControls.setSearchScope(SearchControls.SUBTREE_SCOPE);
searchControls.setTimeLimit(30000);
//String[] attrIDs = {"objectGUID"};
//searchControls.setReturningAttributes(attrIDs);
return searchControls;
}
public static void main(String[] args) throws NamingException {
try {
Hashtable env = new Hashtable();
env.put(Context.INITIAL_CONTEXT_FACTORY, "com.sun.jndi.ldap.LdapCtxFactory");
env.put(Context.PROVIDER_URL, "ldap://rndc10.tre-rn.jus.br:3269");
env.put(Context.SECURITY_AUTHENTICATION, "simple");
env.put(Context.SECURITY_PRINCIPAL, "user");
env.put(Context.SECURITY_CREDENTIALS, "password");
env.put(Context.SECURITY_PROTOCOL, "ssl");
env.put(Context.REFERRAL, "ignore");
String filter = "(&(objectClass=user)(CN=018061671627))";
LdapContext ctx = new InitialLdapContext(env, null);
ctx.setRequestControls(null);
NamingEnumeration<?> namingEnum = ctx.search("OU=DG,OU=PRES,OU=TRERN,DC=tre-rn,DC=jus,DC=br", filter, getSimpleSearchControls());
while (namingEnum.hasMore()) {
SearchResult result = (SearchResult) namingEnum.next();
Attributes attrs = result.getAttributes();
System.out.println(attrs.get("cn"));
System.out.println(attrs.get("displayname"));
System.out.println(attrs.get("mail"));
System.out.println(attrs.get("distinguishedName"));
}
namingEnum.close();
} catch (Exception e) {
e.printStackTrace();
My environment: Active Directory on Windows 2008R2 Standart, Open JDK 7 running on unbutu 12.10.
I would be grateful if someone help me because I've tried everything but I can not make it work.
The error seems to be self-explanatory. You should perform this operation over LDAPS using port 636.
Have you tried to use
env.put(Context.PROVIDER_URL, "ldaps://rndc10.tre-rn.jus.br:636");
(Note that ldaps:// is not mandatory if you specify ssl separately).
Do you have RODCs (Read only DCs) in your environment? And if so, is rndc10.tre-rn.jus.br a RODC?
Perhaps you should be pointing to a DC that is writeable?
Have you tried updating this string:
env.put(Context.PROVIDER_URL, "ldap://rndc10.tre-rn.jus.br:3269");
to:
env.put(Context.PROVIDER_URL, "ldaps://rndc10.tre-rn.jus.br:3269");
^