001 /**
002 * Licensed to the Apache Software Foundation (ASF) under one or more
003 * contributor license agreements. See the NOTICE file distributed with
004 * this work for additional information regarding copyright ownership.
005 * The ASF licenses this file to You under the Apache License, Version 2.0
006 * (the "License"); you may not use this file except in compliance with
007 * the License. You may obtain a copy of the License at
008 *
009 * http://www.apache.org/licenses/LICENSE-2.0
010 *
011 * Unless required by applicable law or agreed to in writing, software
012 * distributed under the License is distributed on an "AS IS" BASIS,
013 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
014 * See the License for the specific language governing permissions and
015 * limitations under the License.
016 */
017
018 package org.apache.geronimo.connector.outbound.security;
019
020 import java.io.IOException;
021 import java.util.Map;
022
023 import javax.resource.spi.ManagedConnectionFactory;
024 import javax.resource.spi.security.PasswordCredential;
025 import javax.security.auth.Subject;
026 import javax.security.auth.callback.Callback;
027 import javax.security.auth.callback.CallbackHandler;
028 import javax.security.auth.callback.NameCallback;
029 import javax.security.auth.callback.PasswordCallback;
030 import javax.security.auth.callback.UnsupportedCallbackException;
031 import javax.security.auth.login.LoginException;
032 import javax.security.auth.spi.LoginModule;
033
034 /**
035 * CallerIdentityPasswordCredentialLoginModule uses the username and password from the CallbackHandler
036 * and a ManagedConnectionFactory from the Options to construct a j2ca PasswordCredential that can be
037 * used for j2ca container managed security.
038 *
039 * This login module does not check credentials so it should never be able to cause a login to succeed.
040 * Therefore the lifecycle methods must return false to indicate success or throw a LoginException to indicate failure.
041 *
042 * @version $Rev: 706640 $ $Date: 2008-10-21 14:44:05 +0000 (Tue, 21 Oct 2008) $
043 *
044 * */
045 public class CallerIdentityPasswordCredentialLoginModule implements LoginModule {
046
047 private Subject subject;
048 private CallbackHandler callbackHandler;
049
050 private ManagedConnectionFactory managedConnectionFactory;
051
052 private String resourcePrincipalName;
053 private String userName;
054 private char[] password;
055 private ResourcePrincipal resourcePrincipal;
056 private PasswordCredential passwordCredential;
057
058 public void initialize(Subject subject, CallbackHandler callbackHandler,
059 Map sharedState, Map options) {
060 this.subject = subject;
061 this.callbackHandler = callbackHandler;
062 managedConnectionFactory = (ManagedConnectionFactory) options.get(PasswordCredentialLoginModuleWrapper.MANAGED_CONNECTION_FACTORY_OPTION);
063 if (managedConnectionFactory == null) {
064 throw new IllegalArgumentException("No ManagedConnectionFactory supplied in options");
065 }
066 }
067
068 public boolean login() throws LoginException {
069 if (managedConnectionFactory == null) {
070 return false;
071 }
072 Callback[] callbacks = new Callback[2];
073
074 callbacks[0] = new NameCallback("User name");
075 callbacks[1] = new PasswordCallback("Password", false);
076 try {
077 callbackHandler.handle(callbacks);
078 } catch (IOException ioe) {
079 throw (LoginException) new LoginException().initCause(ioe);
080 } catch (UnsupportedCallbackException uce) {
081 throw (LoginException) new LoginException().initCause(uce);
082 }
083 resourcePrincipalName = ((NameCallback) callbacks[0]).getName();
084 userName = ((NameCallback) callbacks[0]).getName();
085 password = ((PasswordCallback) callbacks[1]).getPassword();
086 return false;
087 }
088
089 public boolean commit() throws LoginException {
090 if (resourcePrincipalName == null || userName == null || password == null) {
091 return false;
092 }
093 resourcePrincipal = new ResourcePrincipal(resourcePrincipalName);
094 subject.getPrincipals().add(resourcePrincipal);
095 passwordCredential = new PasswordCredential(userName, password);
096 passwordCredential.setManagedConnectionFactory(managedConnectionFactory);
097 subject.getPrivateCredentials().add(passwordCredential);
098
099 // Clear private state
100 resourcePrincipalName = null;
101 userName = null;
102 password = null;
103 return false;
104 }
105
106 public boolean abort() throws LoginException {
107 resourcePrincipalName = null;
108 userName = null;
109 password = null;
110 return false;
111 }
112
113 public boolean logout() throws LoginException {
114 if(!subject.isReadOnly()) {
115 subject.getPrincipals().remove(resourcePrincipal);
116 subject.getPrivateCredentials().remove(passwordCredential);
117 }
118
119 // TODO: Destroy the credential when subject is read-only.
120 resourcePrincipal = null;
121 passwordCredential = null;
122
123 // Clear private state
124 resourcePrincipalName = null;
125 userName = null;
126 password = null;
127 return false;
128 }
129 }