You are viewing a plain text version of this content. The canonical link for it is here.
Posted to scm@geronimo.apache.org by ad...@apache.org on 2005/02/16 20:48:06 UTC
svn commit: r154075 - in geronimo/trunk/modules/security/src:
java/org/apache/geronimo/security/jaas/UPCredentialLoginModule.java
java/org/apache/geronimo/security/jaas/UsernamePasswordCredential.java
test/org/apache/geronimo/security/jaas/ConfigurationEntryTest.java
Author: adc
Date: Wed Feb 16 11:48:03 2005
New Revision: 154075
URL: http://svn.apache.org/viewcvs?view=rev&rev=154075
Log:
Simple login module that scrapes the username/password and places the information into a private credential.
Added:
geronimo/trunk/modules/security/src/java/org/apache/geronimo/security/jaas/UPCredentialLoginModule.java
geronimo/trunk/modules/security/src/java/org/apache/geronimo/security/jaas/UsernamePasswordCredential.java
Modified:
geronimo/trunk/modules/security/src/test/org/apache/geronimo/security/jaas/ConfigurationEntryTest.java
Added: geronimo/trunk/modules/security/src/java/org/apache/geronimo/security/jaas/UPCredentialLoginModule.java
URL: http://svn.apache.org/viewcvs/geronimo/trunk/modules/security/src/java/org/apache/geronimo/security/jaas/UPCredentialLoginModule.java?view=auto&rev=154075
==============================================================================
--- geronimo/trunk/modules/security/src/java/org/apache/geronimo/security/jaas/UPCredentialLoginModule.java (added)
+++ geronimo/trunk/modules/security/src/java/org/apache/geronimo/security/jaas/UPCredentialLoginModule.java Wed Feb 16 11:48:03 2005
@@ -0,0 +1,108 @@
+/**
+ *
+ * Copyright 2005 The Apache Software Foundation
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package org.apache.geronimo.security.jaas;
+
+import java.io.IOException;
+import java.util.Map;
+import java.util.Set;
+import javax.security.auth.Subject;
+import javax.security.auth.callback.Callback;
+import javax.security.auth.callback.CallbackHandler;
+import javax.security.auth.callback.NameCallback;
+import javax.security.auth.callback.PasswordCallback;
+import javax.security.auth.callback.UnsupportedCallbackException;
+import javax.security.auth.login.LoginException;
+import javax.security.auth.spi.LoginModule;
+
+
+/**
+ * Inserts Username/Password credential into private credentials of Subject.
+ * <p/>
+ * If either the username or password is not passed in the callback handler,
+ * then the credential is not placed into the Subject.
+ *
+ * @version $Revision: $ $Date: $
+ */
+public class UPCredentialLoginModule implements LoginModule {
+
+ private Subject subject;
+ private CallbackHandler callbackHandler;
+ private UsernamePasswordCredential upCredential;
+
+ public boolean abort() throws LoginException {
+
+ return logout();
+ }
+
+ public boolean commit() throws LoginException {
+
+ if (subject.isReadOnly()) {
+ throw new LoginException("Subject is ReadOnly");
+ }
+
+ Set pvtCreds = subject.getPrivateCredentials();
+ if (upCredential != null && !pvtCreds.contains(upCredential)) {
+ pvtCreds.add(upCredential);
+ }
+
+ return true;
+ }
+
+ public boolean login() throws LoginException {
+
+ Callback[] callbacks = new Callback[2];
+
+ callbacks[0] = new NameCallback("User name");
+ callbacks[1] = new PasswordCallback("Password", false);
+ try {
+ callbackHandler.handle(callbacks);
+ } catch (IOException ioe) {
+ throw (LoginException) new LoginException().initCause(ioe);
+ } catch (UnsupportedCallbackException uce) {
+ throw (LoginException) new LoginException().initCause(uce);
+ }
+
+ String username = ((NameCallback) callbacks[0]).getName();
+ char[] password = ((PasswordCallback) callbacks[1]).getPassword();
+
+ if (username == null || password == null) return true;
+
+ upCredential = new UsernamePasswordCredential(username, new String(password));
+
+ return true;
+ }
+
+ public boolean logout() throws LoginException {
+
+ if (upCredential == null) return true;
+
+ Set pvtCreds = subject.getPrivateCredentials(UsernamePasswordCredential.class);
+ if (pvtCreds.contains(upCredential)) {
+ pvtCreds.remove(upCredential);
+ }
+
+ upCredential = null;
+
+ return true;
+ }
+
+ public void initialize(Subject subject, CallbackHandler callbackHandler, Map sharedState, Map options) {
+
+ this.subject = subject;
+ this.callbackHandler = callbackHandler;
+ }
+}
Added: geronimo/trunk/modules/security/src/java/org/apache/geronimo/security/jaas/UsernamePasswordCredential.java
URL: http://svn.apache.org/viewcvs/geronimo/trunk/modules/security/src/java/org/apache/geronimo/security/jaas/UsernamePasswordCredential.java?view=auto&rev=154075
==============================================================================
--- geronimo/trunk/modules/security/src/java/org/apache/geronimo/security/jaas/UsernamePasswordCredential.java (added)
+++ geronimo/trunk/modules/security/src/java/org/apache/geronimo/security/jaas/UsernamePasswordCredential.java Wed Feb 16 11:48:03 2005
@@ -0,0 +1,91 @@
+/**
+ *
+ * Copyright 2005 The Apache Software Foundation
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package org.apache.geronimo.security.jaas;
+
+import java.io.Serializable;
+import javax.security.auth.DestroyFailedException;
+import javax.security.auth.Destroyable;
+import javax.security.auth.RefreshFailedException;
+import javax.security.auth.Refreshable;
+
+
+/**
+ * A username/password credential. Used to store the username/password in the
+ * Subject's private credentials.
+ *
+ * @version $Revision: $ $Date: $
+ */
+public class UsernamePasswordCredential implements Destroyable, Refreshable, Serializable {
+
+ private String username;
+ private String password;
+ private boolean destroyed;
+
+ public UsernamePasswordCredential(String username, String password) {
+ assert username != null;
+ assert password != null;
+
+ this.username = username;
+ this.password = password;
+ }
+
+ public String getUsername() {
+ return username;
+ }
+
+ public String getPassword() {
+ return password;
+ }
+
+ public void destroy() throws DestroyFailedException {
+ username = null;
+ password = null;
+ destroyed = true;
+ }
+
+ public boolean isDestroyed() {
+ return destroyed;
+ }
+
+ public void refresh() throws RefreshFailedException {
+ }
+
+ public boolean isCurrent() {
+ return !destroyed;
+ }
+
+ public boolean equals(Object o) {
+ if (this == o) return true;
+ if (!(o instanceof UsernamePasswordCredential)) return false;
+
+ final UsernamePasswordCredential usernamePasswordCredential = (UsernamePasswordCredential) o;
+
+ if (destroyed != usernamePasswordCredential.destroyed) return false;
+ if (!password.equals(usernamePasswordCredential.password)) return false;
+ if (!username.equals(usernamePasswordCredential.username)) return false;
+
+ return true;
+ }
+
+ public int hashCode() {
+ int result;
+ result = username.hashCode();
+ result = 29 * result + password.hashCode();
+ result = 29 * result + (destroyed ? 1 : 0);
+ return result;
+ }
+}
Modified: geronimo/trunk/modules/security/src/test/org/apache/geronimo/security/jaas/ConfigurationEntryTest.java
URL: http://svn.apache.org/viewcvs/geronimo/trunk/modules/security/src/test/org/apache/geronimo/security/jaas/ConfigurationEntryTest.java?view=diff&r1=154074&r2=154075
==============================================================================
--- geronimo/trunk/modules/security/src/test/org/apache/geronimo/security/jaas/ConfigurationEntryTest.java (original)
+++ geronimo/trunk/modules/security/src/test/org/apache/geronimo/security/jaas/ConfigurationEntryTest.java Wed Feb 16 11:48:03 2005
@@ -48,6 +48,7 @@
protected ObjectName loginConfiguration;
protected ObjectName loginService;
protected ObjectName clientCE;
+ protected ObjectName testUPCred;
protected ObjectName testCE;
protected ObjectName testRealm;
protected ObjectName serverStub;
@@ -79,6 +80,7 @@
assertTrue("server subject should be associated with remote id", ContextManager.getRegisteredSubject(remote.getId()) != null);
assertTrue("server subject should have two realm principals ("+subject.getPrincipals(RealmPrincipal.class).size()+")", subject.getPrincipals(RealmPrincipal.class).size() == 2);
assertTrue("server subject should have five principals ("+subject.getPrincipals().size()+")", subject.getPrincipals().size() == 5);
+ assertTrue("server subject should have one private credential ("+subject.getPrivateCredentials().size()+")", subject.getPrivateCredentials().size() == 1);
RealmPrincipal principal = (RealmPrincipal) subject.getPrincipals(RealmPrincipal.class).iterator().next();
assertTrue("id of principal should be non-zero", principal.getId() != 0);
@@ -108,6 +110,7 @@
assertTrue("server subject should be associated with remote id", ContextManager.getRegisteredSubject(remote.getId()) != null);
assertTrue("server subject should have two realm principals ("+subject.getPrincipals(RealmPrincipal.class).size()+")", subject.getPrincipals(RealmPrincipal.class).size() == 2);
assertTrue("server subject should have five principals ("+subject.getPrincipals().size()+")", subject.getPrincipals().size() == 5);
+ assertTrue("server subject should have one private credential ("+subject.getPrivateCredentials().size()+")", subject.getPrivateCredentials().size() == 1);
principal = (RealmPrincipal) subject.getPrincipals(RealmPrincipal.class).iterator().next();
assertTrue("id of principal should be non-zero", principal.getId() != 0);
@@ -166,6 +169,13 @@
kernel.loadGBean(testCE, gbean);
gbean = new GBeanMBean("org.apache.geronimo.security.jaas.LoginModuleGBean");
+ testUPCred = new ObjectName("geronimo.security:type=LoginModule,name=UPCred");
+ gbean.setAttribute("loginModuleClass", "org.apache.geronimo.security.jaas.UPCredentialLoginModule");
+ gbean.setAttribute("serverSide", new Boolean(true));
+ gbean.setAttribute("options", new Properties());
+ kernel.loadGBean(testUPCred, gbean);
+
+ gbean = new GBeanMBean("org.apache.geronimo.security.jaas.LoginModuleGBean");
testCE = new ObjectName("geronimo.security:type=LoginModule,name=audit");
gbean.setAttribute("loginModuleClass", "org.apache.geronimo.security.realm.providers.FileAuditLoginModule");
gbean.setAttribute("serverSide", new Boolean(true));
@@ -178,7 +188,8 @@
testRealm = new ObjectName("geronimo.security:type=SecurityRealm,realm=properties-realm");
gbean.setAttribute("realmName", "properties-realm");
props = new Properties();
- props.setProperty("LoginModule.2.OPTIONAL","geronimo.security:type=LoginModule,name=audit");
+ props.setProperty("LoginModule.3.REQUIRED","geronimo.security:type=LoginModule,name=UPCred");
+ props.setProperty("LoginModule.2.REQUIRED","geronimo.security:type=LoginModule,name=audit");
props.setProperty("LoginModule.1.REQUIRED","geronimo.security:type=LoginModule,name=properties");
gbean.setAttribute("loginModuleConfiguration", props);
gbean.setReferencePatterns("ServerInfo", Collections.singleton(serverInfo));
@@ -194,6 +205,7 @@
kernel.startGBean(loginService);
kernel.startGBean(clientCE);
kernel.startGBean(testCE);
+ kernel.startGBean(testUPCred);
kernel.startGBean(testRealm);
kernel.startGBean(serverStub);
}
@@ -201,6 +213,7 @@
protected void tearDown() throws Exception {
kernel.stopGBean(serverStub);
kernel.stopGBean(testRealm);
+ kernel.stopGBean(testUPCred);
kernel.stopGBean(testCE);
kernel.stopGBean(clientCE);
kernel.stopGBean(loginService);
@@ -209,6 +222,7 @@
kernel.unloadGBean(loginService);
kernel.unloadGBean(testCE);
+ kernel.unloadGBean(testUPCred);
kernel.unloadGBean(testRealm);
kernel.unloadGBean(clientCE);
kernel.unloadGBean(serverStub);
Re: svn commit: r154075 - in geronimo/trunk/modules/security/src:
java/org/apache/geronimo/security/jaas/UPCredentialLoginModule.java java/org/apache/geronimo/security/jaas/UsernamePasswordCredential.java
test/org/apache/geronimo/security/jaas/ConfigurationEntryTest.java
Posted by "Alan D. Cabrera" <ad...@toolazydogs.com>.
Thanks for the hads-up. I fixed the bug and included the security
enhancement that you suggested on IRC, blanking out the pw when destroying.
Regards,
Alan
David Jencks wrote:
> There are a couple problems with this:
>
> 1. it essentially duplicates the intended functionality of the
> existing o.a.g.security.realm.GeronimoPasswordCredential/LoginModule
>
> 2. The inclusion of the destroy method and implementation breaks the
> contracts for equals and hashcode for use in a Collection. In other
> words, after destroying UserPasswordCredential you won't be able to
> remove it from a collection. I think throwing an
> IllegalStateException from equals and hashcode after destroy might be
> reasonable. Currently, calling hashCode after destroy will have
> undesirable effects (npe)
>
> I propose we fix the equals/hashcode problem somehow and replace the
> use of GeronimoPasswordCredential[LoginModule] with the new classes.
>
> thanks
> david jencks
>
> On Feb 16, 2005, at 11:48 AM, adc@apache.org wrote:
>
>> Author: adc
>> Date: Wed Feb 16 11:48:03 2005
>> New Revision: 154075
>>
>> URL: http://svn.apache.org/viewcvs?view=rev&rev=154075
>> Log:
>> Simple login module that scrapes the username/password and places
>> the information into a private credential.
>>
>> Added:
>>
>> geronimo/trunk/modules/security/src/java/org/apache/geronimo/security/
>> jaas/UPCredentialLoginModule.java
>>
>> geronimo/trunk/modules/security/src/java/org/apache/geronimo/security/
>> jaas/UsernamePasswordCredential.java
>> Modified:
>>
>> geronimo/trunk/modules/security/src/test/org/apache/geronimo/security/
>> jaas/ConfigurationEntryTest.java
>>
>> Added:
>> geronimo/trunk/modules/security/src/java/org/apache/geronimo/security/
>> jaas/UPCredentialLoginModule.java
>> URL:
>> http://svn.apache.org/viewcvs/geronimo/trunk/modules/security/src/
>> java/org/apache/geronimo/security/jaas/UPCredentialLoginModule.java?
>> view=auto&rev=154075
>> =======================================================================
>> =======
>> ---
>> geronimo/trunk/modules/security/src/java/org/apache/geronimo/security/
>> jaas/UPCredentialLoginModule.java (added)
>> +++
>> geronimo/trunk/modules/security/src/java/org/apache/geronimo/security/
>> jaas/UPCredentialLoginModule.java Wed Feb 16 11:48:03 2005
>> @@ -0,0 +1,108 @@
>> +/**
>> + *
>> + * Copyright 2005 The Apache Software Foundation
>> + *
>> + * Licensed under the Apache License, Version 2.0 (the "License");
>> + * you may not use this file except in compliance with the License.
>> + * You may obtain a copy of the License at
>> + *
>> + * http://www.apache.org/licenses/LICENSE-2.0
>> + *
>> + * Unless required by applicable law or agreed to in writing,
>> software
>> + * distributed under the License is distributed on an "AS IS" BASIS,
>> + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or
>> implied.
>> + * See the License for the specific language governing permissions
>> and
>> + * limitations under the License.
>> + */
>> +package org.apache.geronimo.security.jaas;
>> +
>> +import java.io.IOException;
>> +import java.util.Map;
>> +import java.util.Set;
>> +import javax.security.auth.Subject;
>> +import javax.security.auth.callback.Callback;
>> +import javax.security.auth.callback.CallbackHandler;
>> +import javax.security.auth.callback.NameCallback;
>> +import javax.security.auth.callback.PasswordCallback;
>> +import javax.security.auth.callback.UnsupportedCallbackException;
>> +import javax.security.auth.login.LoginException;
>> +import javax.security.auth.spi.LoginModule;
>> +
>> +
>> +/**
>> + * Inserts Username/Password credential into private credentials of
>> Subject.
>> + * <p/>
>> + * If either the username or password is not passed in the callback
>> handler,
>> + * then the credential is not placed into the Subject.
>> + *
>> + * @version $Revision: $ $Date: $
>> + */
>> +public class UPCredentialLoginModule implements LoginModule {
>> +
>> + private Subject subject;
>> + private CallbackHandler callbackHandler;
>> + private UsernamePasswordCredential upCredential;
>> +
>> + public boolean abort() throws LoginException {
>> +
>> + return logout();
>> + }
>> +
>> + public boolean commit() throws LoginException {
>> +
>> + if (subject.isReadOnly()) {
>> + throw new LoginException("Subject is ReadOnly");
>> + }
>> +
>> + Set pvtCreds = subject.getPrivateCredentials();
>> + if (upCredential != null &&
>> !pvtCreds.contains(upCredential)) {
>> + pvtCreds.add(upCredential);
>> + }
>> +
>> + return true;
>> + }
>> +
>> + public boolean login() throws LoginException {
>> +
>> + Callback[] callbacks = new Callback[2];
>> +
>> + callbacks[0] = new NameCallback("User name");
>> + callbacks[1] = new PasswordCallback("Password", false);
>> + try {
>> + callbackHandler.handle(callbacks);
>> + } catch (IOException ioe) {
>> + throw (LoginException) new
>> LoginException().initCause(ioe);
>> + } catch (UnsupportedCallbackException uce) {
>> + throw (LoginException) new
>> LoginException().initCause(uce);
>> + }
>> +
>> + String username = ((NameCallback) callbacks[0]).getName();
>> + char[] password = ((PasswordCallback)
>> callbacks[1]).getPassword();
>> +
>> + if (username == null || password == null) return true;
>> +
>> + upCredential = new UsernamePasswordCredential(username, new
>> String(password));
>> +
>> + return true;
>> + }
>> +
>> + public boolean logout() throws LoginException {
>> +
>> + if (upCredential == null) return true;
>> +
>> + Set pvtCreds =
>> subject.getPrivateCredentials(UsernamePasswordCredential.class);
>> + if (pvtCreds.contains(upCredential)) {
>> + pvtCreds.remove(upCredential);
>> + }
>> +
>> + upCredential = null;
>> +
>> + return true;
>> + }
>> +
>> + public void initialize(Subject subject, CallbackHandler
>> callbackHandler, Map sharedState, Map options) {
>> +
>> + this.subject = subject;
>> + this.callbackHandler = callbackHandler;
>> + }
>> +}
>>
>> Added:
>> geronimo/trunk/modules/security/src/java/org/apache/geronimo/security/
>> jaas/UsernamePasswordCredential.java
>> URL:
>> http://svn.apache.org/viewcvs/geronimo/trunk/modules/security/src/
>> java/org/apache/geronimo/security/jaas/
>> UsernamePasswordCredential.java?view=auto&rev=154075
>> =======================================================================
>> =======
>> ---
>> geronimo/trunk/modules/security/src/java/org/apache/geronimo/security/
>> jaas/UsernamePasswordCredential.java (added)
>> +++
>> geronimo/trunk/modules/security/src/java/org/apache/geronimo/security/
>> jaas/UsernamePasswordCredential.java Wed Feb 16 11:48:03 2005
>> @@ -0,0 +1,91 @@
>> +/**
>> + *
>> + * Copyright 2005 The Apache Software Foundation
>> + *
>> + * Licensed under the Apache License, Version 2.0 (the "License");
>> + * you may not use this file except in compliance with the License.
>> + * You may obtain a copy of the License at
>> + *
>> + * http://www.apache.org/licenses/LICENSE-2.0
>> + *
>> + * Unless required by applicable law or agreed to in writing,
>> software
>> + * distributed under the License is distributed on an "AS IS" BASIS,
>> + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or
>> implied.
>> + * See the License for the specific language governing permissions
>> and
>> + * limitations under the License.
>> + */
>> +package org.apache.geronimo.security.jaas;
>> +
>> +import java.io.Serializable;
>> +import javax.security.auth.DestroyFailedException;
>> +import javax.security.auth.Destroyable;
>> +import javax.security.auth.RefreshFailedException;
>> +import javax.security.auth.Refreshable;
>> +
>> +
>> +/**
>> + * A username/password credential. Used to store the
>> username/password in the
>> + * Subject's private credentials.
>> + *
>> + * @version $Revision: $ $Date: $
>> + */
>> +public class UsernamePasswordCredential implements Destroyable,
>> Refreshable, Serializable {
>> +
>> + private String username;
>> + private String password;
>> + private boolean destroyed;
>> +
>> + public UsernamePasswordCredential(String username, String
>> password) {
>> + assert username != null;
>> + assert password != null;
>> +
>> + this.username = username;
>> + this.password = password;
>> + }
>> +
>> + public String getUsername() {
>> + return username;
>> + }
>> +
>> + public String getPassword() {
>> + return password;
>> + }
>> +
>> + public void destroy() throws DestroyFailedException {
>> + username = null;
>> + password = null;
>> + destroyed = true;
>> + }
>> +
>> + public boolean isDestroyed() {
>> + return destroyed;
>> + }
>> +
>> + public void refresh() throws RefreshFailedException {
>> + }
>> +
>> + public boolean isCurrent() {
>> + return !destroyed;
>> + }
>> +
>> + public boolean equals(Object o) {
>> + if (this == o) return true;
>> + if (!(o instanceof UsernamePasswordCredential)) return false;
>> +
>> + final UsernamePasswordCredential usernamePasswordCredential
>> = (UsernamePasswordCredential) o;
>> +
>> + if (destroyed != usernamePasswordCredential.destroyed)
>> return false;
>> + if (!password.equals(usernamePasswordCredential.password))
>> return false;
>> + if (!username.equals(usernamePasswordCredential.username))
>> return false;
>> +
>> + return true;
>> + }
>> +
>> + public int hashCode() {
>> + int result;
>> + result = username.hashCode();
>> + result = 29 * result + password.hashCode();
>> + result = 29 * result + (destroyed ? 1 : 0);
>> + return result;
>> + }
>> +}
>>
>> Modified:
>> geronimo/trunk/modules/security/src/test/org/apache/geronimo/security/
>> jaas/ConfigurationEntryTest.java
>> URL:
>> http://svn.apache.org/viewcvs/geronimo/trunk/modules/security/src/
>> test/org/apache/geronimo/security/jaas/ConfigurationEntryTest.java?
>> view=diff&r1=154074&r2=154075
>> =======================================================================
>> =======
>> ---
>> geronimo/trunk/modules/security/src/test/org/apache/geronimo/security/
>> jaas/ConfigurationEntryTest.java (original)
>> +++
>> geronimo/trunk/modules/security/src/test/org/apache/geronimo/security/
>> jaas/ConfigurationEntryTest.java Wed Feb 16 11:48:03 2005
>> @@ -48,6 +48,7 @@
>> protected ObjectName loginConfiguration;
>> protected ObjectName loginService;
>> protected ObjectName clientCE;
>> + protected ObjectName testUPCred;
>> protected ObjectName testCE;
>> protected ObjectName testRealm;
>> protected ObjectName serverStub;
>> @@ -79,6 +80,7 @@
>> assertTrue("server subject should be associated with remote
>> id", ContextManager.getRegisteredSubject(remote.getId()) != null);
>> assertTrue("server subject should have two realm principals
>> ("+subject.getPrincipals(RealmPrincipal.class).size()+")",
>> subject.getPrincipals(RealmPrincipal.class).size() == 2);
>> assertTrue("server subject should have five principals
>> ("+subject.getPrincipals().size()+")",
>> subject.getPrincipals().size() == 5);
>> + assertTrue("server subject should have one private
>> credential ("+subject.getPrivateCredentials().size()+")",
>> subject.getPrivateCredentials().size() == 1);
>> RealmPrincipal principal = (RealmPrincipal)
>> subject.getPrincipals(RealmPrincipal.class).iterator().next();
>> assertTrue("id of principal should be non-zero",
>> principal.getId() != 0);
>>
>> @@ -108,6 +110,7 @@
>> assertTrue("server subject should be associated with remote
>> id", ContextManager.getRegisteredSubject(remote.getId()) != null);
>> assertTrue("server subject should have two realm principals
>> ("+subject.getPrincipals(RealmPrincipal.class).size()+")",
>> subject.getPrincipals(RealmPrincipal.class).size() == 2);
>> assertTrue("server subject should have five principals
>> ("+subject.getPrincipals().size()+")",
>> subject.getPrincipals().size() == 5);
>> + assertTrue("server subject should have one private
>> credential ("+subject.getPrivateCredentials().size()+")",
>> subject.getPrivateCredentials().size() == 1);
>> principal = (RealmPrincipal)
>> subject.getPrincipals(RealmPrincipal.class).iterator().next();
>> assertTrue("id of principal should be non-zero",
>> principal.getId() != 0);
>>
>> @@ -166,6 +169,13 @@
>> kernel.loadGBean(testCE, gbean);
>>
>> gbean = new
>> GBeanMBean("org.apache.geronimo.security.jaas.LoginModuleGBean");
>> + testUPCred = new
>> ObjectName("geronimo.security:type=LoginModule,name=UPCred");
>> + gbean.setAttribute("loginModuleClass",
>> "org.apache.geronimo.security.jaas.UPCredentialLoginModule");
>> + gbean.setAttribute("serverSide", new Boolean(true));
>> + gbean.setAttribute("options", new Properties());
>> + kernel.loadGBean(testUPCred, gbean);
>> +
>> + gbean = new
>> GBeanMBean("org.apache.geronimo.security.jaas.LoginModuleGBean");
>> testCE = new
>> ObjectName("geronimo.security:type=LoginModule,name=audit");
>> gbean.setAttribute("loginModuleClass",
>> "org.apache.geronimo.security.realm.providers.FileAuditLoginModule");
>> gbean.setAttribute("serverSide", new Boolean(true));
>> @@ -178,7 +188,8 @@
>> testRealm = new
>> ObjectName("geronimo.security:type=SecurityRealm,realm=properties-
>> realm");
>> gbean.setAttribute("realmName", "properties-realm");
>> props = new Properties();
>> -
>> props.setProperty("LoginModule.2.OPTIONAL","geronimo.security:
>> type=LoginModule,name=audit");
>> +
>> props.setProperty("LoginModule.3.REQUIRED","geronimo.security:
>> type=LoginModule,name=UPCred");
>> +
>> props.setProperty("LoginModule.2.REQUIRED","geronimo.security:
>> type=LoginModule,name=audit");
>>
>> props.setProperty("LoginModule.1.REQUIRED","geronimo.security:
>> type=LoginModule,name=properties");
>> gbean.setAttribute("loginModuleConfiguration", props);
>> gbean.setReferencePatterns("ServerInfo",
>> Collections.singleton(serverInfo));
>> @@ -194,6 +205,7 @@
>> kernel.startGBean(loginService);
>> kernel.startGBean(clientCE);
>> kernel.startGBean(testCE);
>> + kernel.startGBean(testUPCred);
>> kernel.startGBean(testRealm);
>> kernel.startGBean(serverStub);
>> }
>> @@ -201,6 +213,7 @@
>> protected void tearDown() throws Exception {
>> kernel.stopGBean(serverStub);
>> kernel.stopGBean(testRealm);
>> + kernel.stopGBean(testUPCred);
>> kernel.stopGBean(testCE);
>> kernel.stopGBean(clientCE);
>> kernel.stopGBean(loginService);
>> @@ -209,6 +222,7 @@
>>
>> kernel.unloadGBean(loginService);
>> kernel.unloadGBean(testCE);
>> + kernel.unloadGBean(testUPCred);
>> kernel.unloadGBean(testRealm);
>> kernel.unloadGBean(clientCE);
>> kernel.unloadGBean(serverStub);
>>
>>
Re: svn commit: r154075 - in geronimo/trunk/modules/security/src: java/org/apache/geronimo/security/jaas/UPCredentialLoginModule.java java/org/apache/geronimo/security/jaas/UsernamePasswordCredential.java test/org/apache/geronimo/security/jaas/ConfigurationEntryTest.java
Posted by David Jencks <dj...@gluecode.com>.
There are a couple problems with this:
1. it essentially duplicates the intended functionality of the existing
o.a.g.security.realm.GeronimoPasswordCredential/LoginModule
2. The inclusion of the destroy method and implementation breaks the
contracts for equals and hashcode for use in a Collection. In other
words, after destroying UserPasswordCredential you won't be able to
remove it from a collection. I think throwing an IllegalStateException
from equals and hashcode after destroy might be reasonable. Currently,
calling hashCode after destroy will have undesirable effects (npe)
I propose we fix the equals/hashcode problem somehow and replace the
use of GeronimoPasswordCredential[LoginModule] with the new classes.
thanks
david jencks
On Feb 16, 2005, at 11:48 AM, adc@apache.org wrote:
> Author: adc
> Date: Wed Feb 16 11:48:03 2005
> New Revision: 154075
>
> URL: http://svn.apache.org/viewcvs?view=rev&rev=154075
> Log:
> Simple login module that scrapes the username/password and places the
> information into a private credential.
>
> Added:
>
> geronimo/trunk/modules/security/src/java/org/apache/geronimo/security/
> jaas/UPCredentialLoginModule.java
>
> geronimo/trunk/modules/security/src/java/org/apache/geronimo/security/
> jaas/UsernamePasswordCredential.java
> Modified:
>
> geronimo/trunk/modules/security/src/test/org/apache/geronimo/security/
> jaas/ConfigurationEntryTest.java
>
> Added:
> geronimo/trunk/modules/security/src/java/org/apache/geronimo/security/
> jaas/UPCredentialLoginModule.java
> URL:
> http://svn.apache.org/viewcvs/geronimo/trunk/modules/security/src/
> java/org/apache/geronimo/security/jaas/UPCredentialLoginModule.java?
> view=auto&rev=154075
> =======================================================================
> =======
> ---
> geronimo/trunk/modules/security/src/java/org/apache/geronimo/security/
> jaas/UPCredentialLoginModule.java (added)
> +++
> geronimo/trunk/modules/security/src/java/org/apache/geronimo/security/
> jaas/UPCredentialLoginModule.java Wed Feb 16 11:48:03 2005
> @@ -0,0 +1,108 @@
> +/**
> + *
> + * Copyright 2005 The Apache Software Foundation
> + *
> + * Licensed under the Apache License, Version 2.0 (the "License");
> + * you may not use this file except in compliance with the License.
> + * You may obtain a copy of the License at
> + *
> + * http://www.apache.org/licenses/LICENSE-2.0
> + *
> + * Unless required by applicable law or agreed to in writing,
> software
> + * distributed under the License is distributed on an "AS IS" BASIS,
> + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or
> implied.
> + * See the License for the specific language governing permissions
> and
> + * limitations under the License.
> + */
> +package org.apache.geronimo.security.jaas;
> +
> +import java.io.IOException;
> +import java.util.Map;
> +import java.util.Set;
> +import javax.security.auth.Subject;
> +import javax.security.auth.callback.Callback;
> +import javax.security.auth.callback.CallbackHandler;
> +import javax.security.auth.callback.NameCallback;
> +import javax.security.auth.callback.PasswordCallback;
> +import javax.security.auth.callback.UnsupportedCallbackException;
> +import javax.security.auth.login.LoginException;
> +import javax.security.auth.spi.LoginModule;
> +
> +
> +/**
> + * Inserts Username/Password credential into private credentials of
> Subject.
> + * <p/>
> + * If either the username or password is not passed in the callback
> handler,
> + * then the credential is not placed into the Subject.
> + *
> + * @version $Revision: $ $Date: $
> + */
> +public class UPCredentialLoginModule implements LoginModule {
> +
> + private Subject subject;
> + private CallbackHandler callbackHandler;
> + private UsernamePasswordCredential upCredential;
> +
> + public boolean abort() throws LoginException {
> +
> + return logout();
> + }
> +
> + public boolean commit() throws LoginException {
> +
> + if (subject.isReadOnly()) {
> + throw new LoginException("Subject is ReadOnly");
> + }
> +
> + Set pvtCreds = subject.getPrivateCredentials();
> + if (upCredential != null && !pvtCreds.contains(upCredential))
> {
> + pvtCreds.add(upCredential);
> + }
> +
> + return true;
> + }
> +
> + public boolean login() throws LoginException {
> +
> + Callback[] callbacks = new Callback[2];
> +
> + callbacks[0] = new NameCallback("User name");
> + callbacks[1] = new PasswordCallback("Password", false);
> + try {
> + callbackHandler.handle(callbacks);
> + } catch (IOException ioe) {
> + throw (LoginException) new
> LoginException().initCause(ioe);
> + } catch (UnsupportedCallbackException uce) {
> + throw (LoginException) new
> LoginException().initCause(uce);
> + }
> +
> + String username = ((NameCallback) callbacks[0]).getName();
> + char[] password = ((PasswordCallback)
> callbacks[1]).getPassword();
> +
> + if (username == null || password == null) return true;
> +
> + upCredential = new UsernamePasswordCredential(username, new
> String(password));
> +
> + return true;
> + }
> +
> + public boolean logout() throws LoginException {
> +
> + if (upCredential == null) return true;
> +
> + Set pvtCreds =
> subject.getPrivateCredentials(UsernamePasswordCredential.class);
> + if (pvtCreds.contains(upCredential)) {
> + pvtCreds.remove(upCredential);
> + }
> +
> + upCredential = null;
> +
> + return true;
> + }
> +
> + public void initialize(Subject subject, CallbackHandler
> callbackHandler, Map sharedState, Map options) {
> +
> + this.subject = subject;
> + this.callbackHandler = callbackHandler;
> + }
> +}
>
> Added:
> geronimo/trunk/modules/security/src/java/org/apache/geronimo/security/
> jaas/UsernamePasswordCredential.java
> URL:
> http://svn.apache.org/viewcvs/geronimo/trunk/modules/security/src/
> java/org/apache/geronimo/security/jaas/
> UsernamePasswordCredential.java?view=auto&rev=154075
> =======================================================================
> =======
> ---
> geronimo/trunk/modules/security/src/java/org/apache/geronimo/security/
> jaas/UsernamePasswordCredential.java (added)
> +++
> geronimo/trunk/modules/security/src/java/org/apache/geronimo/security/
> jaas/UsernamePasswordCredential.java Wed Feb 16 11:48:03 2005
> @@ -0,0 +1,91 @@
> +/**
> + *
> + * Copyright 2005 The Apache Software Foundation
> + *
> + * Licensed under the Apache License, Version 2.0 (the "License");
> + * you may not use this file except in compliance with the License.
> + * You may obtain a copy of the License at
> + *
> + * http://www.apache.org/licenses/LICENSE-2.0
> + *
> + * Unless required by applicable law or agreed to in writing,
> software
> + * distributed under the License is distributed on an "AS IS" BASIS,
> + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or
> implied.
> + * See the License for the specific language governing permissions
> and
> + * limitations under the License.
> + */
> +package org.apache.geronimo.security.jaas;
> +
> +import java.io.Serializable;
> +import javax.security.auth.DestroyFailedException;
> +import javax.security.auth.Destroyable;
> +import javax.security.auth.RefreshFailedException;
> +import javax.security.auth.Refreshable;
> +
> +
> +/**
> + * A username/password credential. Used to store the
> username/password in the
> + * Subject's private credentials.
> + *
> + * @version $Revision: $ $Date: $
> + */
> +public class UsernamePasswordCredential implements Destroyable,
> Refreshable, Serializable {
> +
> + private String username;
> + private String password;
> + private boolean destroyed;
> +
> + public UsernamePasswordCredential(String username, String
> password) {
> + assert username != null;
> + assert password != null;
> +
> + this.username = username;
> + this.password = password;
> + }
> +
> + public String getUsername() {
> + return username;
> + }
> +
> + public String getPassword() {
> + return password;
> + }
> +
> + public void destroy() throws DestroyFailedException {
> + username = null;
> + password = null;
> + destroyed = true;
> + }
> +
> + public boolean isDestroyed() {
> + return destroyed;
> + }
> +
> + public void refresh() throws RefreshFailedException {
> + }
> +
> + public boolean isCurrent() {
> + return !destroyed;
> + }
> +
> + public boolean equals(Object o) {
> + if (this == o) return true;
> + if (!(o instanceof UsernamePasswordCredential)) return false;
> +
> + final UsernamePasswordCredential usernamePasswordCredential =
> (UsernamePasswordCredential) o;
> +
> + if (destroyed != usernamePasswordCredential.destroyed) return
> false;
> + if (!password.equals(usernamePasswordCredential.password))
> return false;
> + if (!username.equals(usernamePasswordCredential.username))
> return false;
> +
> + return true;
> + }
> +
> + public int hashCode() {
> + int result;
> + result = username.hashCode();
> + result = 29 * result + password.hashCode();
> + result = 29 * result + (destroyed ? 1 : 0);
> + return result;
> + }
> +}
>
> Modified:
> geronimo/trunk/modules/security/src/test/org/apache/geronimo/security/
> jaas/ConfigurationEntryTest.java
> URL:
> http://svn.apache.org/viewcvs/geronimo/trunk/modules/security/src/
> test/org/apache/geronimo/security/jaas/ConfigurationEntryTest.java?
> view=diff&r1=154074&r2=154075
> =======================================================================
> =======
> ---
> geronimo/trunk/modules/security/src/test/org/apache/geronimo/security/
> jaas/ConfigurationEntryTest.java (original)
> +++
> geronimo/trunk/modules/security/src/test/org/apache/geronimo/security/
> jaas/ConfigurationEntryTest.java Wed Feb 16 11:48:03 2005
> @@ -48,6 +48,7 @@
> protected ObjectName loginConfiguration;
> protected ObjectName loginService;
> protected ObjectName clientCE;
> + protected ObjectName testUPCred;
> protected ObjectName testCE;
> protected ObjectName testRealm;
> protected ObjectName serverStub;
> @@ -79,6 +80,7 @@
> assertTrue("server subject should be associated with remote
> id", ContextManager.getRegisteredSubject(remote.getId()) != null);
> assertTrue("server subject should have two realm principals
> ("+subject.getPrincipals(RealmPrincipal.class).size()+")",
> subject.getPrincipals(RealmPrincipal.class).size() == 2);
> assertTrue("server subject should have five principals
> ("+subject.getPrincipals().size()+")", subject.getPrincipals().size()
> == 5);
> + assertTrue("server subject should have one private credential
> ("+subject.getPrivateCredentials().size()+")",
> subject.getPrivateCredentials().size() == 1);
> RealmPrincipal principal = (RealmPrincipal)
> subject.getPrincipals(RealmPrincipal.class).iterator().next();
> assertTrue("id of principal should be non-zero",
> principal.getId() != 0);
>
> @@ -108,6 +110,7 @@
> assertTrue("server subject should be associated with remote
> id", ContextManager.getRegisteredSubject(remote.getId()) != null);
> assertTrue("server subject should have two realm principals
> ("+subject.getPrincipals(RealmPrincipal.class).size()+")",
> subject.getPrincipals(RealmPrincipal.class).size() == 2);
> assertTrue("server subject should have five principals
> ("+subject.getPrincipals().size()+")", subject.getPrincipals().size()
> == 5);
> + assertTrue("server subject should have one private credential
> ("+subject.getPrivateCredentials().size()+")",
> subject.getPrivateCredentials().size() == 1);
> principal = (RealmPrincipal)
> subject.getPrincipals(RealmPrincipal.class).iterator().next();
> assertTrue("id of principal should be non-zero",
> principal.getId() != 0);
>
> @@ -166,6 +169,13 @@
> kernel.loadGBean(testCE, gbean);
>
> gbean = new
> GBeanMBean("org.apache.geronimo.security.jaas.LoginModuleGBean");
> + testUPCred = new
> ObjectName("geronimo.security:type=LoginModule,name=UPCred");
> + gbean.setAttribute("loginModuleClass",
> "org.apache.geronimo.security.jaas.UPCredentialLoginModule");
> + gbean.setAttribute("serverSide", new Boolean(true));
> + gbean.setAttribute("options", new Properties());
> + kernel.loadGBean(testUPCred, gbean);
> +
> + gbean = new
> GBeanMBean("org.apache.geronimo.security.jaas.LoginModuleGBean");
> testCE = new
> ObjectName("geronimo.security:type=LoginModule,name=audit");
> gbean.setAttribute("loginModuleClass",
> "org.apache.geronimo.security.realm.providers.FileAuditLoginModule");
> gbean.setAttribute("serverSide", new Boolean(true));
> @@ -178,7 +188,8 @@
> testRealm = new
> ObjectName("geronimo.security:type=SecurityRealm,realm=properties-
> realm");
> gbean.setAttribute("realmName", "properties-realm");
> props = new Properties();
> -
> props.setProperty("LoginModule.2.OPTIONAL","geronimo.security:
> type=LoginModule,name=audit");
> +
> props.setProperty("LoginModule.3.REQUIRED","geronimo.security:
> type=LoginModule,name=UPCred");
> +
> props.setProperty("LoginModule.2.REQUIRED","geronimo.security:
> type=LoginModule,name=audit");
>
> props.setProperty("LoginModule.1.REQUIRED","geronimo.security:
> type=LoginModule,name=properties");
> gbean.setAttribute("loginModuleConfiguration", props);
> gbean.setReferencePatterns("ServerInfo",
> Collections.singleton(serverInfo));
> @@ -194,6 +205,7 @@
> kernel.startGBean(loginService);
> kernel.startGBean(clientCE);
> kernel.startGBean(testCE);
> + kernel.startGBean(testUPCred);
> kernel.startGBean(testRealm);
> kernel.startGBean(serverStub);
> }
> @@ -201,6 +213,7 @@
> protected void tearDown() throws Exception {
> kernel.stopGBean(serverStub);
> kernel.stopGBean(testRealm);
> + kernel.stopGBean(testUPCred);
> kernel.stopGBean(testCE);
> kernel.stopGBean(clientCE);
> kernel.stopGBean(loginService);
> @@ -209,6 +222,7 @@
>
> kernel.unloadGBean(loginService);
> kernel.unloadGBean(testCE);
> + kernel.unloadGBean(testUPCred);
> kernel.unloadGBean(testRealm);
> kernel.unloadGBean(clientCE);
> kernel.unloadGBean(serverStub);
>
>