001    /*
002     * $Id: JAASLoginService.java 3342 2009-05-22 19:47:38Z kschaefe $
003     *
004     * Copyright 2004 Sun Microsystems, Inc., 4150 Network Circle,
005     * Santa Clara, California 95054, U.S.A. All rights reserved.
006     *
007     * This library is free software; you can redistribute it and/or
008     * modify it under the terms of the GNU Lesser General Public
009     * License as published by the Free Software Foundation; either
010     * version 2.1 of the License, or (at your option) any later version.
011     * 
012     * This library is distributed in the hope that it will be useful,
013     * but WITHOUT ANY WARRANTY; without even the implied warranty of
014     * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
015     * Lesser General Public License for more details.
016     * 
017     * You should have received a copy of the GNU Lesser General Public
018     * License along with this library; if not, write to the Free Software
019     * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA  02110-1301  USA
020     */
021    package org.jdesktop.swingx.auth;
022    
023    import java.util.logging.Level;
024    import java.util.logging.Logger;
025    
026    import javax.security.auth.Subject;
027    import javax.security.auth.callback.Callback;
028    import javax.security.auth.callback.CallbackHandler;
029    import javax.security.auth.callback.NameCallback;
030    import javax.security.auth.callback.PasswordCallback;
031    import javax.security.auth.login.AccountExpiredException;
032    import javax.security.auth.login.CredentialExpiredException;
033    import javax.security.auth.login.FailedLoginException;
034    import javax.security.auth.login.LoginContext;
035    import javax.security.auth.login.LoginException;
036    
037    /**
038     * <b>JAASLoginService</b> implements a <b>LoginService</b>
039     * that uses JAAS for authentication. <b>JAASLoginService</b> uses the 
040     * server name as name of the configuration for JAAS.
041     * 
042     * @author Bino George
043     */
044    public class JAASLoginService extends LoginService {
045        private static final Logger LOG = Logger.getLogger(JAASLoginService.class
046                .getName());
047    
048        protected LoginContext loginContext;
049    
050        /**
051         * Constructor for <b>JAASLoginService</b>
052         * @param server server name that is also used for the JAAS config name
053         */
054        public JAASLoginService(String server) {
055            super(server);
056        }
057        
058            /**
059             * Default JavaBeans constructor
060             */
061            public JAASLoginService() {
062                super();
063            }
064            
065        
066        /**
067         * @inheritDoc
068         *      
069         */
070        public boolean authenticate(String name, char[] password, String server) throws Exception {
071            // If user has selected a different server, update the login service
072            if (server != null) {
073                if (!server.equals(getServer())) {
074                    setServer(server);
075                }
076            }
077            // Clear the login context before attempting authentication
078            loginContext = null;
079            // Create a login context for the appropriate server and attempt to
080            // authenticate the user.
081            try {
082                loginContext = new LoginContext(getServer(),
083                        new JAASCallbackHandler(name, password));
084                loginContext.login();
085                return true;
086            } catch (AccountExpiredException e) {
087                // TODO add explanation?
088                LOG.log(Level.WARNING, "", e);
089                return false;
090            } catch (CredentialExpiredException e) {
091                            // TODO add explanation?
092                            LOG.log(Level.WARNING, "", e);
093                return false;
094            } catch (FailedLoginException e) {
095                            // TODO add explanation?
096                            LOG.log(Level.WARNING, "", e);
097                return false;
098            } catch (LoginException e) {
099                            // TODO add explanation?
100                            LOG.log(Level.WARNING, "", e);
101                return false;
102            } catch (Throwable e) {
103                            // TODO add explanation?
104                            LOG.log(Level.WARNING, "", e);
105                return false;
106            }
107        }
108    
109        /**
110         * Returns the <code>LoginContext</code> used during the authentication
111         * process.
112         */
113        public LoginContext getLoginContext()
114        {
115            return loginContext;
116        }
117    
118        /**
119         * Returns the <code>Subject</code> representing the authenticated 
120         * individual, or <code>null</code> if the user has not yet been 
121         * successfully authenticated.
122         */
123        public Subject getSubject()
124        {
125            if (loginContext == null)
126                return null;
127            return loginContext.getSubject();
128        }
129    
130        class JAASCallbackHandler implements CallbackHandler {
131    
132            private String name;
133    
134            private char[] password;
135    
136            public JAASCallbackHandler(String name, char[] passwd) {
137                this.name = name;
138                this.password = passwd;
139            }
140    
141            public void handle(Callback[] callbacks) throws java.io.IOException {
142                for (int i = 0; i < callbacks.length; i++) {
143                    if (callbacks[i] instanceof NameCallback) {
144                        NameCallback cb = (NameCallback) callbacks[i];
145                        cb.setName(name);
146                    } else if (callbacks[i] instanceof PasswordCallback) {
147                        PasswordCallback cb = (PasswordCallback) callbacks[i];
148                        cb.setPassword(password);
149                    }
150                }
151            }
152    
153        }
154    }