Skip to content

Instantly share code, notes, and snippets.

@freeeve
Created August 20, 2011 00:04
Show Gist options
  • Star 0 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save freeeve/1158359 to your computer and use it in GitHub Desktop.
Save freeeve/1158359 to your computer and use it in GitHub Desktop.
A pedagogical LDAP authentication test in Java.
/* 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