ARTEMIS-4202 expand coverage of noCacheExceptions in LDAPLoginModule

This commit is contained in:
Justin Bertram 2023-03-09 09:09:53 -06:00
parent 294daa0ff6
commit 39b0f01ca9
1 changed files with 85 additions and 76 deletions

View File

@ -174,49 +174,52 @@ public class LDAPLoginModule implements AuditLoginModule {
@Override @Override
public boolean login() throws LoginException { public boolean login() throws LoginException {
if (!authenticateUser) {
return false;
}
Callback[] callbacks = new Callback[2];
callbacks[0] = new NameCallback("User name");
callbacks[1] = new PasswordCallback("Password", false);
try { try {
handler.handle(callbacks); if (!authenticateUser) {
} catch (IOException | UnsupportedCallbackException e) { return false;
throw (LoginException) new LoginException().initCause(e); }
Callback[] callbacks = new Callback[2];
callbacks[0] = new NameCallback("User name");
callbacks[1] = new PasswordCallback("Password", false);
try {
handler.handle(callbacks);
} catch (IOException | UnsupportedCallbackException e) {
throw (LoginException) new LoginException().initCause(e);
}
String password = null;
username = ((NameCallback) callbacks[0]).getName();
if (username == null) {
return false;
}
if (((PasswordCallback) callbacks[1]).getPassword() != null) {
password = new String(((PasswordCallback) callbacks[1]).getPassword());
}
/*
* https://tools.ietf.org/html/rfc4513#section-6.3.1
*
* Clients that use the results from a simple Bind operation to make
* authorization decisions should actively detect unauthenticated Bind
* requests (by verifying that the supplied password is not empty) and
* react appropriately.
*/
if (password == null || password.length() == 0) {
throw new FailedLoginException("Password cannot be null or empty");
}
// authenticate will throw LoginException
// in case of failed authentication
authenticate(username, password);
userAuthenticated = true;
return true;
} catch (LoginException e) {
throw handleException(e);
} }
String password = null;
username = ((NameCallback) callbacks[0]).getName();
if (username == null) {
return false;
}
if (((PasswordCallback) callbacks[1]).getPassword() != null) {
password = new String(((PasswordCallback) callbacks[1]).getPassword());
}
/*
* https://tools.ietf.org/html/rfc4513#section-6.3.1
*
* Clients that use the results from a simple Bind operation to make
* authorization decisions should actively detect unauthenticated Bind
* requests (by verifying that the supplied password is not empty) and
* react appropriately.
*/
if (password == null || password.length() == 0) {
throw new FailedLoginException("Password cannot be null or empty");
}
// authenticate will throw LoginException
// in case of failed authentication
authenticate(username, password);
userAuthenticated = true;
return true;
} }
@Override @Override
@ -227,31 +230,43 @@ public class LDAPLoginModule implements AuditLoginModule {
@Override @Override
public boolean commit() throws LoginException { public boolean commit() throws LoginException {
boolean result = userAuthenticated; try {
Set<UserPrincipal> authenticatedUsers = subject.getPrincipals(UserPrincipal.class); boolean result = userAuthenticated;
Set<Principal> principals = subject.getPrincipals(); Set<UserPrincipal> authenticatedUsers = subject.getPrincipals(UserPrincipal.class);
if (result) { Set<Principal> principals = subject.getPrincipals();
principals.add(new UserPrincipal(username)); if (result) {
} principals.add(new UserPrincipal(username));
// assign roles to any other UserPrincipal
for (UserPrincipal authenticatedUser : authenticatedUsers) {
List<String> roles = new ArrayList<>();
try {
String dn = resolveDN(authenticatedUser.getName(), roles);
resolveRolesForDN(context, dn, authenticatedUser.getName(), roles);
} catch (NamingException e) {
closeContext();
FailedLoginException ex = new FailedLoginException("Error contacting LDAP");
ex.initCause(e);
throw ex;
} }
// assign roles to any other UserPrincipal
for (UserPrincipal authenticatedUser : authenticatedUsers) {
List<String> roles = new ArrayList<>();
try {
String dn = resolveDN(authenticatedUser.getName(), roles);
resolveRolesForDN(context, dn, authenticatedUser.getName(), roles);
} catch (NamingException e) {
closeContext();
FailedLoginException ex = new FailedLoginException("Error contacting LDAP");
ex.initCause(e);
throw ex;
}
}
principals.addAll(groups);
clear();
return result;
} catch (LoginException e) {
throw handleException(e);
} }
}
principals.addAll(groups); private LoginException handleException(LoginException e) {
Throwable t = ExceptionUtil.getRootCause(e);
clear(); if (noCacheExceptions.contains(t.getClass().getName())) {
return result; t.initCause(new NoCacheLoginException());
}
return e;
} }
private void clear() { private void clear() {
@ -314,8 +329,10 @@ public class LDAPLoginModule implements AuditLoginModule {
logger.debug("Create the LDAP initial context."); logger.debug("Create the LDAP initial context.");
try { try {
openContext(); openContext();
} catch (Exception e) { } catch (Exception ne) {
return handleException(e, "Error opening LDAP connection"); FailedLoginException ex = new FailedLoginException("Error opening LDAP connection");
ex.initCause(ne);
throw ex;
} }
if (!isLoginPropertySet(ConfigKey.USER_SEARCH_MATCHING)) { if (!isLoginPropertySet(ConfigKey.USER_SEARCH_MATCHING)) {
@ -440,22 +457,14 @@ public class LDAPLoginModule implements AuditLoginModule {
} }
} catch (NamingException e) { } catch (NamingException e) {
closeContext(); closeContext();
handleException(e, "Error contacting LDAP"); FailedLoginException ex = new FailedLoginException("Error contacting LDAP");
ex.initCause(e);
throw ex;
} }
return dn; return dn;
} }
private String handleException(Exception e, String s) throws FailedLoginException {
FailedLoginException ex = new FailedLoginException(s);
if (noCacheExceptions.contains(ExceptionUtil.getRootCause(e).getClass().getName())) {
ex.initCause(new NoCacheLoginException());
} else {
ex.initCause(e);
}
throw ex;
}
protected void addRoles(DirContext context, protected void addRoles(DirContext context,
String dn, String dn,
String username, String username,