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    package org.apache.geronimo.security.jaas;
018    
019    import java.io.IOException;
020    import java.util.Map;
021    import java.util.Set;
022    import javax.security.auth.DestroyFailedException;
023    import javax.security.auth.Subject;
024    import javax.security.auth.callback.Callback;
025    import javax.security.auth.callback.CallbackHandler;
026    import javax.security.auth.callback.NameCallback;
027    import javax.security.auth.callback.PasswordCallback;
028    import javax.security.auth.callback.UnsupportedCallbackException;
029    import javax.security.auth.login.LoginException;
030    import javax.security.auth.spi.LoginModule;
031    
032    
033    /**
034     * Inserts named Username/Password credential into private credentials of Subject.
035     * <p/>
036     * If either the username or password is not passed in the callback handler,
037     * then the credential is not placed into the Subject.
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 $Revision: 565912 $ $Date: 2007-08-14 17:03:11 -0400 (Tue, 14 Aug 2007) $
043     */
044    public class NamedUPCredentialLoginModule implements LoginModule {
045    
046        public static final String CREDENTIAL_NAME = "org.apache.geronimo.jaas.NamedUPCredentialLoginModule.Name";
047    
048        private String name;
049        private Subject subject;
050        private CallbackHandler callbackHandler;
051        private NamedUsernamePasswordCredential nupCredential;
052    
053        public void initialize(Subject subject, CallbackHandler callbackHandler, Map sharedState, Map options) {
054    
055            this.subject = subject;
056            this.callbackHandler = callbackHandler;
057            this.name = (String) options.get(CREDENTIAL_NAME);
058        }
059    
060        public boolean login() throws LoginException {
061    
062            Callback[] callbacks = new Callback[2];
063    
064            callbacks[0] = new NameCallback("User name");
065            callbacks[1] = new PasswordCallback("Password", false);
066            try {
067                callbackHandler.handle(callbacks);
068            } catch (IOException ioe) {
069                throw (LoginException) new LoginException().initCause(ioe);
070            } catch (UnsupportedCallbackException uce) {
071                throw (LoginException) new LoginException().initCause(uce);
072            }
073    
074            String username = ((NameCallback) callbacks[0]).getName();
075            char[] password = ((PasswordCallback) callbacks[1]).getPassword();
076    
077            if (username == null || password == null) return false;
078    
079            nupCredential = new NamedUsernamePasswordCredential(username, password, name);
080    
081            return false;
082        }
083    
084        public boolean commit() throws LoginException {
085    
086            if (subject.isReadOnly()) {
087                throw new LoginException("Subject is ReadOnly");
088            }
089    
090            Set pvtCreds = subject.getPrivateCredentials();
091            if (nupCredential != null && !pvtCreds.contains(nupCredential)) {
092                pvtCreds.add(nupCredential);
093            }
094    
095            return false;
096        }
097    
098        public boolean abort() throws LoginException {
099    
100            return logout();
101        }
102    
103        public boolean logout() throws LoginException {
104    
105            if (nupCredential == null) return false;
106    
107            Set pvtCreds = subject.getPrivateCredentials(NamedUsernamePasswordCredential.class);
108            if (pvtCreds.contains(nupCredential)) {
109                pvtCreds.remove(nupCredential);
110            }
111    
112            try {
113                nupCredential.destroy();
114            } catch (DestroyFailedException e) {
115                // do nothing
116            }
117            nupCredential = null;
118    
119            return false;
120        }
121    
122    }