AMQ-7137 - Implement abort() properly in the LoginModules. Also fix a bug in LdapLoginModule relating to Logout

This commit is contained in:
Colm O hEigeartaigh 2019-01-16 14:10:02 +00:00
parent c3714457f1
commit 042cad9e93
4 changed files with 137 additions and 49 deletions

View File

@ -49,10 +49,13 @@ public abstract class CertificateLoginModule extends PropertiesLoader implements
private CallbackHandler callbackHandler; private CallbackHandler callbackHandler;
private Subject subject; private Subject subject;
private X509Certificate certificates[];
private String username; private String username;
private Set<Principal> principals = new HashSet<Principal>(); private Set<Principal> principals = new HashSet<Principal>();
/** the authentication status*/
private boolean succeeded = false;
private boolean commitSucceeded = false;
/** /**
* Overriding to allow for proper initialization. Standard JAAS. * Overriding to allow for proper initialization. Standard JAAS.
*/ */
@ -78,7 +81,7 @@ public abstract class CertificateLoginModule extends PropertiesLoader implements
} catch (UnsupportedCallbackException uce) { } catch (UnsupportedCallbackException uce) {
throw new LoginException(uce.getMessage() + " Unable to obtain client certificates."); throw new LoginException(uce.getMessage() + " Unable to obtain client certificates.");
} }
certificates = ((CertificateCallback)callbacks[0]).getCertificates(); X509Certificate[] certificates = ((CertificateCallback)callbacks[0]).getCertificates();
username = getUserNameForCertificates(certificates); username = getUserNameForCertificates(certificates);
if (username == null) { if (username == null) {
@ -88,6 +91,7 @@ public abstract class CertificateLoginModule extends PropertiesLoader implements
if (debug) { if (debug) {
LOG.debug("Certificate for user: " + username); LOG.debug("Certificate for user: " + username);
} }
succeeded = true;
return true; return true;
} }
@ -96,6 +100,15 @@ public abstract class CertificateLoginModule extends PropertiesLoader implements
*/ */
@Override @Override
public boolean commit() throws LoginException { public boolean commit() throws LoginException {
if (debug) {
LOG.debug("commit");
}
if (!succeeded) {
clear();
return false;
}
principals.add(new UserPrincipal(username)); principals.add(new UserPrincipal(username));
for (String group : getUserGroups(username)) { for (String group : getUserGroups(username)) {
@ -104,11 +117,8 @@ public abstract class CertificateLoginModule extends PropertiesLoader implements
subject.getPrincipals().addAll(principals); subject.getPrincipals().addAll(principals);
clear(); username = null;
commitSucceeded = true;
if (debug) {
LOG.debug("commit");
}
return true; return true;
} }
@ -117,11 +127,19 @@ public abstract class CertificateLoginModule extends PropertiesLoader implements
*/ */
@Override @Override
public boolean abort() throws LoginException { public boolean abort() throws LoginException {
clear();
if (debug) { if (debug) {
LOG.debug("abort"); LOG.debug("abort");
} }
if (!succeeded) {
return false;
} else if (succeeded && commitSucceeded) {
// we succeeded, but another required module failed
logout();
} else {
// our commit failed
clear();
succeeded = false;
}
return true; return true;
} }
@ -131,11 +149,14 @@ public abstract class CertificateLoginModule extends PropertiesLoader implements
@Override @Override
public boolean logout() { public boolean logout() {
subject.getPrincipals().removeAll(principals); subject.getPrincipals().removeAll(principals);
principals.clear(); clear();
if (debug) { if (debug) {
LOG.debug("logout"); LOG.debug("logout");
} }
succeeded = false;
commitSucceeded = false;
return true; return true;
} }
@ -143,8 +164,8 @@ public abstract class CertificateLoginModule extends PropertiesLoader implements
* Helper method. * Helper method.
*/ */
private void clear() { private void clear() {
certificates = null;
username = null; username = null;
principals.clear();
} }
/** /**

View File

@ -54,7 +54,10 @@ public class GuestLoginModule implements LoginModule {
private boolean credentialsInvalidate; private boolean credentialsInvalidate;
private Set<Principal> principals = new HashSet<Principal>(); private Set<Principal> principals = new HashSet<Principal>();
private CallbackHandler callbackHandler; private CallbackHandler callbackHandler;
private boolean loginSucceeded;
/** the authentication status*/
private boolean succeeded = false;
private boolean commitSucceeded = false;
@Override @Override
public void initialize(Subject subject, CallbackHandler callbackHandler, Map sharedState, Map options) { public void initialize(Subject subject, CallbackHandler callbackHandler, Map sharedState, Map options) {
@ -79,7 +82,7 @@ public class GuestLoginModule implements LoginModule {
@Override @Override
public boolean login() throws LoginException { public boolean login() throws LoginException {
loginSucceeded = true; succeeded = true;
if (credentialsInvalidate) { if (credentialsInvalidate) {
PasswordCallback passwordCallback = new PasswordCallback("Password: ", false); PasswordCallback passwordCallback = new PasswordCallback("Password: ", false);
try { try {
@ -88,7 +91,7 @@ public class GuestLoginModule implements LoginModule {
if (debug) { if (debug) {
LOG.debug("Guest login failing (credentialsInvalidate=true) on presence of a password"); LOG.debug("Guest login failing (credentialsInvalidate=true) on presence of a password");
} }
loginSucceeded = false; succeeded = false;
passwordCallback.clearPassword(); passwordCallback.clearPassword();
}; };
} catch (IOException ioe) { } catch (IOException ioe) {
@ -96,21 +99,24 @@ public class GuestLoginModule implements LoginModule {
} }
} }
if (debug) { if (debug) {
LOG.debug("Guest login " + loginSucceeded); LOG.debug("Guest login " + succeeded);
} }
return loginSucceeded; return succeeded;
} }
@Override @Override
public boolean commit() throws LoginException { public boolean commit() throws LoginException {
if (loginSucceeded) {
subject.getPrincipals().addAll(principals);
}
if (debug) { if (debug) {
LOG.debug("commit"); LOG.debug("commit");
} }
return loginSucceeded;
if (!succeeded) {
return false;
}
subject.getPrincipals().addAll(principals);
commitSucceeded = true;
return true;
} }
@Override @Override
@ -119,6 +125,15 @@ public class GuestLoginModule implements LoginModule {
if (debug) { if (debug) {
LOG.debug("abort"); LOG.debug("abort");
} }
if (!succeeded) {
return false;
} else if (succeeded && commitSucceeded) {
// we succeeded, but another required module failed
logout();
} else {
// our commit failed
succeeded = false;
}
return true; return true;
} }
@ -129,6 +144,9 @@ public class GuestLoginModule implements LoginModule {
if (debug) { if (debug) {
LOG.debug("logout"); LOG.debug("logout");
} }
succeeded = false;
commitSucceeded = false;
return true; return true;
} }
} }

View File

@ -72,9 +72,13 @@ public class LDAPLoginModule implements LoginModule {
private Subject subject; private Subject subject;
private CallbackHandler handler; private CallbackHandler handler;
private LDAPLoginProperty [] config; private LDAPLoginProperty [] config;
private String username; private Principal user;
private Set<GroupPrincipal> groups = new HashSet<GroupPrincipal>(); private Set<GroupPrincipal> groups = new HashSet<GroupPrincipal>();
/** the authentication status*/
private boolean succeeded = false;
private boolean commitSucceeded = false;
@Override @Override
public void initialize(Subject subject, CallbackHandler callbackHandler, Map sharedState, Map options) { public void initialize(Subject subject, CallbackHandler callbackHandler, Map sharedState, Map options) {
this.subject = subject; this.subject = subject;
@ -118,7 +122,7 @@ public class LDAPLoginModule implements LoginModule {
String password; String password;
username = ((NameCallback)callbacks[0]).getName(); String username = ((NameCallback)callbacks[0]).getName();
if (username == null) if (username == null)
return false; return false;
@ -130,28 +134,56 @@ public class LDAPLoginModule implements LoginModule {
// authenticate will throw LoginException // authenticate will throw LoginException
// in case of failed authentication // in case of failed authentication
authenticate(username, password); authenticate(username, password);
user = new UserPrincipal(username);
succeeded = true;
return true; return true;
} }
@Override @Override
public boolean logout() throws LoginException { public boolean logout() throws LoginException {
username = null; subject.getPrincipals().remove(user);
subject.getPrincipals().removeAll(groups);
user = null;
groups.clear();
succeeded = false;
commitSucceeded = false;
return true; return true;
} }
@Override @Override
public boolean commit() throws LoginException { public boolean commit() throws LoginException {
if (!succeeded) {
user = null;
groups.clear();
return false;
}
Set<Principal> principals = subject.getPrincipals(); Set<Principal> principals = subject.getPrincipals();
principals.add(new UserPrincipal(username)); principals.add(user);
for (GroupPrincipal gp : groups) { for (GroupPrincipal gp : groups) {
principals.add(gp); principals.add(gp);
} }
commitSucceeded = true;
return true; return true;
} }
@Override @Override
public boolean abort() throws LoginException { public boolean abort() throws LoginException {
username = null; if (!succeeded) {
return false;
} else if (succeeded && commitSucceeded) {
// we succeeded, but another required module failed
logout();
} else {
// our commit failed
user = null;
groups.clear();
succeeded = false;
}
return true; return true;
} }

View File

@ -50,13 +50,16 @@ public class PropertiesLoginModule extends PropertiesLoader implements LoginModu
private Map<String,Set<String>> groups; private Map<String,Set<String>> groups;
private String user; private String user;
private final Set<Principal> principals = new HashSet<Principal>(); private final Set<Principal> principals = new HashSet<Principal>();
private boolean loginSucceeded;
/** the authentication status*/
private boolean succeeded = false;
private boolean commitSucceeded = false;
@Override @Override
public void initialize(Subject subject, CallbackHandler callbackHandler, Map sharedState, Map options) { public void initialize(Subject subject, CallbackHandler callbackHandler, Map sharedState, Map options) {
this.subject = subject; this.subject = subject;
this.callbackHandler = callbackHandler; this.callbackHandler = callbackHandler;
loginSucceeded = false; succeeded = false;
init(options); init(options);
users = load(USER_FILE_PROP_NAME, "user", options).getProps(); users = load(USER_FILE_PROP_NAME, "user", options).getProps();
groups = load(GROUP_FILE_PROP_NAME, "group", options).invertedPropertiesValuesMap(); groups = load(GROUP_FILE_PROP_NAME, "group", options).invertedPropertiesValuesMap();
@ -91,63 +94,77 @@ public class PropertiesLoginModule extends PropertiesLoader implements LoginModu
if (!password.equals(new String(tmpPassword))) { if (!password.equals(new String(tmpPassword))) {
throw new FailedLoginException("Password does not match"); throw new FailedLoginException("Password does not match");
} }
loginSucceeded = true; succeeded = true;
if (debug) { if (debug) {
LOG.debug("login " + user); LOG.debug("login " + user);
} }
return loginSucceeded; return succeeded;
} }
@Override @Override
public boolean commit() throws LoginException { public boolean commit() throws LoginException {
boolean result = loginSucceeded; if (!succeeded) {
if (result) { clear();
principals.add(new UserPrincipal(user)); if (debug) {
LOG.debug("commit, result: false");
Set<String> matchedGroups = groups.get(user);
if (matchedGroups != null) {
for (String entry : matchedGroups) {
principals.add(new GroupPrincipal(entry));
}
} }
return false;
subject.getPrincipals().addAll(principals);
} }
// will whack loginSucceeded principals.add(new UserPrincipal(user));
clear();
Set<String> matchedGroups = groups.get(user);
if (matchedGroups != null) {
for (String entry : matchedGroups) {
principals.add(new GroupPrincipal(entry));
}
}
subject.getPrincipals().addAll(principals);
if (debug) { if (debug) {
LOG.debug("commit, result: " + result); LOG.debug("commit, result: true");
} }
return result;
commitSucceeded = true;
return true;
} }
@Override @Override
public boolean abort() throws LoginException { public boolean abort() throws LoginException {
clear();
if (debug) { if (debug) {
LOG.debug("abort"); LOG.debug("abort");
} }
if (!succeeded) {
return false;
} else if (succeeded && commitSucceeded) {
// we succeeded, but another required module failed
logout();
} else {
// our commit failed
clear();
succeeded = false;
}
return true; return true;
} }
@Override @Override
public boolean logout() throws LoginException { public boolean logout() throws LoginException {
subject.getPrincipals().removeAll(principals); subject.getPrincipals().removeAll(principals);
principals.clear();
clear(); clear();
if (debug) { if (debug) {
LOG.debug("logout"); LOG.debug("logout");
} }
succeeded = false;
commitSucceeded = false;
return true; return true;
} }
private void clear() { private void clear() {
user = null; user = null;
loginSucceeded = false; principals.clear();
} }
} }