Created
August 20, 2011 00:04
-
-
Save freeeve/1158359 to your computer and use it in GitHub Desktop.
A pedagogical LDAP authentication test in Java.
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
/* Copyright 2011 Wes Freeman | |
* | |
* This program is free software: you can redistribute it and/or modify | |
* it under the terms of the GNU Lesser General Public License as published by | |
* the Free Software Foundation, either version 3 of the License, or | |
* (at your option) any later version. | |
* | |
* This program is distributed in the hope that it will be useful, | |
* but WITHOUT ANY WARRANTY; without even the implied warranty of | |
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the | |
* GNU Lesser General Public License for more details. | |
* | |
* You should have received a copy of the GNU Lesser General Public License | |
* along with this program. If not, see <http://www.gnu.org/licenses/>. | |
*/ | |
import java.io.BufferedReader; | |
import java.io.FileInputStream; | |
import java.io.FileOutputStream; | |
import java.io.IOException; | |
import java.io.InputStreamReader; | |
import java.util.HashMap; | |
import java.util.Hashtable; | |
import java.util.Properties; | |
import javax.naming.AuthenticationException; | |
import javax.naming.Context; | |
import javax.naming.NamingException; | |
import javax.naming.directory.InitialDirContext; | |
/** | |
* Wes's TestLDAP class. For testing LDAP queries, and learning how to do LDAP | |
* authentication. | |
* | |
* @author wfreeman | |
*/ | |
public class TestLDAP { | |
/** a hash map for error messages from LDAP; set statically at bottom of file. */ | |
private static HashMap<String, String> errorMap; | |
/** | |
* Prompts for domain, user, pass, and ldapURL, attempts to connect, and | |
* gives result. | |
* | |
* @param args | |
* not used. | |
* @throws IOException | |
*/ | |
public static void main(String args[]) throws IOException { | |
// load default properties, if they exist | |
Properties appProps = new Properties(); | |
try { | |
FileInputStream propFile = new FileInputStream("TestLDAP.properties"); | |
appProps.load(propFile); | |
propFile.close(); | |
} catch (IOException e) { | |
System.out | |
.println("no defaults file found; optional creation at end."); | |
} | |
BufferedReader in = new BufferedReader(new InputStreamReader(System.in)); | |
String domain = "", username = "", password = "", ldapURL = "", inStr; | |
domain = appProps.getProperty("domain"); | |
ldapURL = appProps.getProperty("ldapURL"); | |
System.out | |
.println("Welcome to the TestLDAP program." | |
+ "\nHere you can make sure your LDAP authentication is working properly." | |
+ "\n\n Note: Domain should be in the form of example: google.com\n" | |
+ " Note: LDAP URL should be in the form of ldap://<domain controller fqdn>:<port>/\n"); | |
do { | |
System.out.print("enter domain [default: " + domain | |
+ "]: "); | |
inStr = in.readLine(); | |
if (!inStr.equals("")) { | |
domain = inStr; | |
} | |
} while (domain == null || domain.equals("")); | |
do { | |
System.out.print("enter LDAP URL [default: " + ldapURL + "]: "); | |
inStr = in.readLine(); | |
if (!inStr.equals("")) { | |
ldapURL = inStr; | |
} | |
} while (ldapURL == null || ldapURL.equals("")); | |
do { | |
System.out.print("enter username: "); | |
inStr = in.readLine(); | |
if (!inStr.equals("")) { | |
username = inStr; | |
} | |
} while (username == null || username.equals("")); | |
do { | |
System.out.print("enter password: "); | |
inStr = in.readLine(); | |
if (!inStr.equals("")) { | |
password = inStr; | |
} | |
} while (password == null || password.equals("")); | |
if (!domain.equals(appProps.get("domain")) | |
|| !ldapURL.equals(appProps.get("ldapURL"))) { | |
System.out | |
.print("Do you want to remember this domain/ldapURL (NOT user/pass) for next time? y/n: "); | |
inStr = in.readLine(); | |
if (inStr.equalsIgnoreCase("y")) { | |
FileOutputStream outFile = new FileOutputStream( | |
"TestLDAP.properties"); | |
appProps.put("domain", domain); | |
appProps.put("ldapURL", ldapURL); | |
appProps.store(outFile, "no comment"); | |
outFile.close(); | |
} | |
} | |
// this is where it all happens! | |
(new TestLDAP()).testLDAP(domain, username, password, ldapURL); | |
System.out.println("... ending program."); | |
} | |
/** | |
* The actual test is here. | |
*/ | |
private void testLDAP(String domain, String username, String password, | |
String ldapURL) { | |
boolean isAuthenticated = false; | |
Hashtable<String, String> authEnv = new Hashtable<String, String>(11); | |
String dn = username + "@" + domain; | |
authEnv.put(Context.INITIAL_CONTEXT_FACTORY, | |
"com.sun.jndi.ldap.LdapCtxFactory"); | |
authEnv.put(Context.PROVIDER_URL, ldapURL); | |
authEnv.put(Context.SECURITY_PRINCIPAL, dn); | |
authEnv.put(Context.SECURITY_CREDENTIALS, password); | |
isAuthenticated = false; | |
try { | |
new InitialDirContext(authEnv); | |
isAuthenticated = true; | |
} catch (AuthenticationException authEx) { | |
String msg = authEx.getMessage(); | |
// a hack to find what the error is... (see list below) | |
for (String key : errorMap.keySet()) { | |
if (msg.contains("data " + key)) { | |
System.out.println(errorMap.get(key)); | |
} | |
} | |
System.out.println("Exception message: " + msg); | |
} catch (NamingException namEx) { | |
System.out.println("Something went wrong connecting to the server!"); | |
namEx.printStackTrace(System.out); | |
} | |
if (!isAuthenticated) { | |
System.out.println("Not authenticated!"); | |
} else { | |
System.out.println("Authenticated!"); | |
} | |
} | |
static { | |
errorMap = new HashMap<String, String>(); | |
errorMap.put("525", | |
"ERROR_NO_SUCH_USER (The specified account does not exist.)" | |
+ "\nNOTE: Returns when username is invalid."); | |
errorMap | |
.put("52e", | |
"ERROR_LOGON_FAILURE (Logon failure: unknown user name or bad password.)" | |
+ "\nNOTE: Returns when username is valid but password/credential is invalid." | |
+ "\nWill prevent most other errors from being displayed as noted."); | |
errorMap | |
.put("530", | |
"ERROR_INVALID_LOGON_HOURS (Logon failure: account logon time restriction violation.)" | |
+ "\nNOTE: Returns only when presented with valid username and password/credential."); | |
errorMap | |
.put("531", | |
"ERROR_INVALID_WORKSTATION (Logon failure: user not allowed to log on to this computer.)" | |
+ "\nLDAP[userWorkstations: <multivalued list of workstation names>]" | |
+ "\nNOTE: Returns only when presented with valid username and password/credential."); | |
errorMap | |
.put("532", | |
"ERROR_PASSWORD_EXPIRED (Logon failure: the specified account password has expired.)" | |
+ "\nLDAP[userAccountControl: <bitmask=0x00800000>] - PASSWORDEXPIRED" | |
+ "\nNOTE: Returns only when presented with valid username and password/credential."); | |
errorMap | |
.put("533", | |
"ERROR_ACCOUNT_DISABLED (Logon failure: account currently disabled.)" | |
+ "\nLDAP[userAccountControl: <bitmask=0x00000002>] - ACCOUNTDISABLE" | |
+ "\nNOTE: Returns only when presented with valid username and password/credential"); | |
errorMap | |
.put("701", | |
"ERROR_ACCOUNT_EXPIRED (The user's account has expired.)" | |
+ "\nLDAP[accountExpires: <value of -1, 0, or extemely large value indicates account will not expire>] - ACCOUNTEXPIRED" | |
+ "\nNOTE: Returns only when presented with valid username and password/credential."); | |
errorMap | |
.put("773", | |
"ERROR_PASSWORD_MUST_CHANGE (The user's password must be changed before logging on the first time.)" | |
+ "\nLDAP[pwdLastSet: <value of 0 indicates admin-required password change>] - MUST_CHANGE_PASSWD" | |
+ "\nNOTE: Returns only when presented with valid username and password/credential."); | |
errorMap | |
.put("775", | |
"ERROR_ACCOUNT_LOCKED_OUT (The referenced account is currently locked out and may not be logged on to.)" | |
+ "\nLDAP[userAccountControl: <bitmask=0x00000010>] - LOCKOUT" | |
+ "\nNOTE: Returns even if invalid password is presented"); | |
} | |
} |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment