/** contact the ldap server and attempt to authenticate */ protected boolean ldapAuthenticate(String netid, String password, Context context) { if (!password.equals("")) { LdapContext ctx = null; StartTlsResponse startTLSResponse = null; // Set up environment for creating initial context Hashtable<String, String> env = new Hashtable<String, String>(); env.put(javax.naming.Context.INITIAL_CONTEXT_FACTORY, "com.sun.jndi.ldap.LdapCtxFactory"); env.put(javax.naming.Context.PROVIDER_URL, ldap_provider_url); try { if (useTLS) { ctx = new InitialLdapContext(env, null); // start TLS startTLSResponse = (StartTlsResponse) ctx.extendedOperation(new StartTlsRequest()); startTLSResponse.negotiate(); // perform simple client authentication ctx.addToEnvironment(javax.naming.Context.SECURITY_AUTHENTICATION, "simple"); ctx.addToEnvironment(javax.naming.Context.SECURITY_PRINCIPAL, netid); ctx.addToEnvironment(javax.naming.Context.SECURITY_CREDENTIALS, password); ctx.addToEnvironment(javax.naming.Context.AUTHORITATIVE, "true"); ctx.addToEnvironment(javax.naming.Context.REFERRAL, "follow"); // dummy operation to check if authentication has succeeded ctx.getAttributes(""); } else if (!useTLS) { // Authenticate env.put(javax.naming.Context.SECURITY_AUTHENTICATION, "Simple"); env.put(javax.naming.Context.SECURITY_PRINCIPAL, netid); env.put(javax.naming.Context.SECURITY_CREDENTIALS, password); env.put(javax.naming.Context.AUTHORITATIVE, "true"); env.put(javax.naming.Context.REFERRAL, "follow"); // Try to bind ctx = new InitialLdapContext(env, null); } } catch (NamingException | IOException e) { // something went wrong (like wrong password) so return false log.warn(LogManager.getHeader(context, "ldap_authentication", "type=failed_auth " + e)); return false; } finally { // Close the context when we're done try { if (startTLSResponse != null) { startTLSResponse.close(); } if (ctx != null) { ctx.close(); } } catch (NamingException | IOException e) { } } } else { return false; } return true; }
/** * Method authenticate. * * @param username String * @param password String * @return boolean * @throws Exception */ public boolean authenticate(String username, String password) throws Exception { try { ctx.addToEnvironment(Context.SECURITY_PRINCIPAL, username); ctx.addToEnvironment(Context.SECURITY_CREDENTIALS, password); ctx.reconnect(connCtls); } catch (AuthenticationException e) { throw e; } catch (NamingException e) { throw e; } return true; }
@Override public LdapContext getLdapContext(Object principal, Object credentials) throws NamingException { LdapContext ctx = getSystemLdapContext(); ctx.addToEnvironment(Context.SECURITY_PRINCIPAL, principal); ctx.addToEnvironment(Context.SECURITY_CREDENTIALS, credentials); try { // AUTHENTICATE CREDENTIALS BY CREATING AN INITIAL LDAP CONTEXT new InitialLdapContext(ctx.getEnvironment(), null); } catch (AuthenticationException ex) { throw new AuthenticationException("Access denied: " + principal); } return ctx; }
private ProxyLdapContext(Hashtable env) throws NamingException { final Map<String, Object> savedEnv = new HashMap<String, Object>(); for (final String key : Arrays.asList( Context.SECURITY_AUTHENTICATION, Context.SECURITY_CREDENTIALS, Context.SECURITY_PRINCIPAL, Context.SECURITY_PROTOCOL)) { final Object entry = env.remove(key); if (entry != null) { savedEnv.put(key, entry); } } delegate = new InitialLdapContext(env, null); tls = (StartTlsResponse) delegate.extendedOperation(new StartTlsRequest()); tls.setHostnameVerifier( new HostnameVerifier() { @Override public boolean verify(String hostname, SSLSession session) { return true; } }); try { final SSLSession negotiate = tls.negotiate(); Logger.getLogger(this.getClass().getCanonicalName()) .fine("LDAP is now using " + negotiate.getProtocol()); } catch (final IOException e) { throw new NamingException(e.getMessage()); } for (final Map.Entry<String, Object> savedEntry : savedEnv.entrySet()) { delegate.addToEnvironment(savedEntry.getKey(), savedEntry.getValue()); } }
@Override public LdapContext getSystemLdapContext() throws NamingException { try { InitialLdapContext ictx = new InitialLdapContext(); LdapContext ctx = (LdapContext) ictx.lookup(getLdapJndi()); /* Glassfish does not pass through these properties, even though it is aware of them? * Without com.sun.jndi.ldap.LdapCtxFactory, authentication is NOT carried out */ ctx.addToEnvironment(Context.INITIAL_CONTEXT_FACTORY, "com.sun.jndi.ldap.LdapCtxFactory"); ctx.addToEnvironment("java.naming.ldap.attributes.binary", "userPKCS12"); if (logger.isDebugEnabled()) { String providerURL = (String) ctx.getEnvironment().get(Context.PROVIDER_URL); logger.debug("LDAP providerURL=" + providerURL); } return ctx; } catch (Exception ex) { throw new RuntimeException("Failed to lookup " + getLdapJndi(), ex); } }
/** * Attempt authentication * * @param getPasswdFromSharedState boolean that tells this method whether to retrieve the password * from the sharedState. * @exception LoginException if the authentication attempt fails. */ private void attemptAuthentication(boolean getPasswdFromSharedState) throws LoginException { // first get the username and password getUsernamePassword(getPasswdFromSharedState); if (password == null || password.length == 0) { throw (LoginException) new FailedLoginException("No password was supplied"); } String dn = ""; if (authFirst || authOnly) { String id = replaceUsernameToken(identityMatcher, authcIdentity); // Prepare to bind using user's username and password ldapEnvironment.put(Context.SECURITY_CREDENTIALS, password); ldapEnvironment.put(Context.SECURITY_PRINCIPAL, id); if (debug) { System.out.println( "\t\t[LdapLoginModule] " + "attempting to authenticate user: "******"Cannot bind to LDAP server").initCause(e); } // Authentication has succeeded // Locate the user's distinguished name if (userFilter != null) { dn = findUserDN(ctx); } else { dn = id; } } else { try { // Connect to the LDAP server (using anonymous bind) ctx = new InitialLdapContext(ldapEnvironment, null); } catch (NamingException e) { throw (LoginException) new FailedLoginException("Cannot connect to LDAP server").initCause(e); } // Locate the user's distinguished name dn = findUserDN(ctx); try { // Prepare to bind using user's distinguished name and password ctx.addToEnvironment(Context.SECURITY_AUTHENTICATION, "simple"); ctx.addToEnvironment(Context.SECURITY_PRINCIPAL, dn); ctx.addToEnvironment(Context.SECURITY_CREDENTIALS, password); if (debug) { System.out.println( "\t\t[LdapLoginModule] " + "attempting to authenticate user: "******"Cannot bind to LDAP server").initCause(e); } } // Save input as shared state only if authentication succeeded if (storePass && !sharedState.containsKey(USERNAME_KEY) && !sharedState.containsKey(PASSWORD_KEY)) { sharedState.put(USERNAME_KEY, username); sharedState.put(PASSWORD_KEY, password); } // Create the user principals userPrincipal = new UserPrincipal(username); if (authzIdentity != null) { authzPrincipal = new UserPrincipal(authzIdentity); } try { ldapPrincipal = new LdapPrincipal(dn); } catch (InvalidNameException e) { if (debug) { System.out.println("\t\t[LdapLoginModule] " + "cannot create LdapPrincipal: bad DN"); } throw (LoginException) new FailedLoginException("Cannot create LdapPrincipal").initCause(e); } }
private LdapContext bind( String principalName, String password, SocketInfo server, Hashtable<String, String> props) throws NamingException { String ldapUrl = (FORCE_LDAPS ? "ldaps://" : "ldap://") + server + '/'; String oldName = Thread.currentThread().getName(); Thread.currentThread().setName("Connecting to " + ldapUrl + " : " + oldName); LOGGER.fine("Connecting to " + ldapUrl); try { props.put(Context.PROVIDER_URL, ldapUrl); props.put("java.naming.ldap.version", "3"); customizeLdapProperties(props); LdapContext context = (LdapContext) LdapCtxFactory.getLdapCtxInstance(ldapUrl, props); if (!FORCE_LDAPS) { // try to upgrade to TLS if we can, but failing to do so isn't fatal // see http://download.oracle.com/javase/jndi/tutorial/ldap/ext/starttls.html try { StartTlsResponse rsp = (StartTlsResponse) context.extendedOperation(new StartTlsRequest()); rsp.negotiate((SSLSocketFactory) TrustAllSocketFactory.getDefault()); LOGGER.fine("Connection upgraded to TLS"); } catch (NamingException e) { LOGGER.log( Level.FINE, "Failed to start TLS. Authentication will be done via plain-text LDAP", e); context.removeFromEnvironment("java.naming.ldap.factory.socket"); } catch (IOException e) { LOGGER.log( Level.FINE, "Failed to start TLS. Authentication will be done via plain-text LDAP", e); context.removeFromEnvironment("java.naming.ldap.factory.socket"); } } if (principalName == null || password == null || password.equals("")) { // anonymous bind. LDAP uses empty password as a signal to anonymous bind (RFC 2829 5.1), // which means it can never be the actual user password. context.addToEnvironment(Context.SECURITY_AUTHENTICATION, "none"); LOGGER.fine("Binding anonymously to " + ldapUrl); } else { // authenticate after upgrading to TLS, so that the credential won't go in clear text context.addToEnvironment(Context.SECURITY_PRINCIPAL, principalName); context.addToEnvironment(Context.SECURITY_CREDENTIALS, password); LOGGER.fine("Binding as " + principalName + " to " + ldapUrl); } // this is supposed to cause the LDAP bind operation with the server, // but I notice that AD may still accept this and yet fail to search later, // when I tried anonymous bind. // if I do specify a wrong credential, this seems to fail. context.reconnect(null); return context; // worked } finally { Thread.currentThread().setName(oldName); } }
protected String getDNOfUser( String adminUser, String adminPassword, Context context, String netid) { // The resultant DN String resultDN; // The search scope to use (default to 0) int ldap_search_scope_value = 0; try { ldap_search_scope_value = Integer.parseInt(ldap_search_scope.trim()); } catch (NumberFormatException e) { // Log the error if it has been set but is invalid if (ldap_search_scope != null) { log.warn( LogManager.getHeader( context, "ldap_authentication", "invalid search scope: " + ldap_search_scope)); } } // Set up environment for creating initial context Hashtable<String, String> env = new Hashtable<String, String>(); env.put(javax.naming.Context.INITIAL_CONTEXT_FACTORY, "com.sun.jndi.ldap.LdapCtxFactory"); env.put(javax.naming.Context.PROVIDER_URL, ldap_provider_url); LdapContext ctx = null; StartTlsResponse startTLSResponse = null; try { if ((adminUser != null) && (!adminUser.trim().equals("")) && (adminPassword != null) && (!adminPassword.trim().equals(""))) { if (useTLS) { ctx = new InitialLdapContext(env, null); // start TLS startTLSResponse = (StartTlsResponse) ctx.extendedOperation(new StartTlsRequest()); startTLSResponse.negotiate(); // perform simple client authentication ctx.addToEnvironment(javax.naming.Context.SECURITY_AUTHENTICATION, "simple"); ctx.addToEnvironment(javax.naming.Context.SECURITY_PRINCIPAL, adminUser); ctx.addToEnvironment(javax.naming.Context.SECURITY_CREDENTIALS, adminPassword); } else { // Use admin credentials for search// Authenticate env.put(javax.naming.Context.SECURITY_AUTHENTICATION, "simple"); env.put(javax.naming.Context.SECURITY_PRINCIPAL, adminUser); env.put(javax.naming.Context.SECURITY_CREDENTIALS, adminPassword); // Create initial context ctx = new InitialLdapContext(env, null); } } else { // Use anonymous authentication env.put(javax.naming.Context.SECURITY_AUTHENTICATION, "none"); } Attributes matchAttrs = new BasicAttributes(true); matchAttrs.put(new BasicAttribute(ldap_id_field, netid)); // look up attributes try { SearchControls ctrls = new SearchControls(); ctrls.setSearchScope(ldap_search_scope_value); String searchName = ""; if (useTLS) { searchName = ldap_search_context; } else { searchName = ldap_provider_url + ldap_search_context; } NamingEnumeration<SearchResult> answer = ctx.search(searchName, "(&({0}={1}))", new Object[] {ldap_id_field, netid}, ctrls); while (answer.hasMoreElements()) { SearchResult sr = answer.next(); if (StringUtils.isEmpty(ldap_search_context)) { resultDN = sr.getName(); } else { resultDN = (sr.getName() + "," + ldap_search_context); } String attlist[] = { ldap_email_field, ldap_givenname_field, ldap_surname_field, ldap_phone_field, ldap_group_field }; Attributes atts = sr.getAttributes(); Attribute att; if (attlist[0] != null) { att = atts.get(attlist[0]); if (att != null) { ldapEmail = (String) att.get(); } } if (attlist[1] != null) { att = atts.get(attlist[1]); if (att != null) { ldapGivenName = (String) att.get(); } } if (attlist[2] != null) { att = atts.get(attlist[2]); if (att != null) { ldapSurname = (String) att.get(); } } if (attlist[3] != null) { att = atts.get(attlist[3]); if (att != null) { ldapPhone = (String) att.get(); } } if (attlist[4] != null) { att = atts.get(attlist[4]); if (att != null) { ldapGroup = (String) att.get(); } } if (answer.hasMoreElements()) { // Oh dear - more than one match // Ambiguous user, can't continue } else { log.debug(LogManager.getHeader(context, "got DN", resultDN)); return resultDN; } } } catch (NamingException e) { // if the lookup fails go ahead and create a new record for them because the // authentication // succeeded log.warn( LogManager.getHeader(context, "ldap_attribute_lookup", "type=failed_search " + e)); } } catch (NamingException | IOException e) { log.warn(LogManager.getHeader(context, "ldap_authentication", "type=failed_auth " + e)); } finally { // Close the context when we're done try { if (startTLSResponse != null) { startTLSResponse.close(); } if (ctx != null) { ctx.close(); } } catch (NamingException | IOException e) { } } // No DN match found return null; }