OSDN Git Service

Imported GNU Classpath 0.20
[pf3gnuchains/gcc-fork.git] / libjava / classpath / javax / security / auth / login / LoginContext.java
1 /* LoginContext.java
2    Copyright (C) 2004 Free Software Foundation, Inc.
3
4 This file is part of GNU Classpath.
5
6 GNU Classpath is free software; you can redistribute it and/or modify
7 it under the terms of the GNU General Public License as published by
8 the Free Software Foundation; either version 2, or (at your option)
9 any later version.
10
11 GNU Classpath is distributed in the hope that it will be useful, but
12 WITHOUT ANY WARRANTY; without even the implied warranty of
13 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
14 General Public License for more details.
15
16 You should have received a copy of the GNU General Public License
17 along with GNU Classpath; see the file COPYING.  If not, write to the
18 Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
19 02110-1301 USA.
20
21 Linking this library statically or dynamically with other modules is
22 making a combined work based on this library.  Thus, the terms and
23 conditions of the GNU General Public License cover the whole
24 combination.
25
26 As a special exception, the copyright holders of this library give you
27 permission to link this library with independent modules to produce an
28 executable, regardless of the license terms of these independent
29 modules, and to copy and distribute the resulting executable under
30 terms of your choice, provided that you also meet, for each linked
31 independent module, the terms and conditions of the license of that
32 module.  An independent module is a module which is not derived from
33 or based on this library.  If you modify this library, you may extend
34 this exception to your version of the library, but you are not
35 obligated to do so.  If you do not wish to do so, delete this
36 exception statement from your version. */
37
38
39 package javax.security.auth.login;
40
41 import gnu.java.security.action.GetSecurityPropertyAction;
42
43 import java.security.AccessController;
44
45 import java.util.HashMap;
46 import java.util.Map;
47
48 import javax.security.auth.Subject;
49 import javax.security.auth.callback.CallbackHandler;
50 import javax.security.auth.spi.LoginModule;
51
52 public class LoginContext
53 {
54
55   private static final String OTHER = "other";
56
57   private final String name;
58   private final CallbackHandler cbHandler;
59   private final Subject subject;
60   private final AppConfigurationEntry[] entries;
61   private final LoginModule[] modules;
62   private final Map sharedState;
63
64   public LoginContext (final String name) throws LoginException
65   {
66     this (name, new Subject(), defaultHandler());
67   }
68
69   public LoginContext (final String name, final CallbackHandler cbHandler)
70     throws LoginException
71   {
72     this (name, new Subject(), cbHandler);
73   }
74
75   public LoginContext (final String name, final Subject subject)
76     throws LoginException
77   {
78     this (name, subject, defaultHandler());
79   }
80
81   public LoginContext (final String name, final Subject subject,
82                        final CallbackHandler cbHandler)
83     throws LoginException
84   {
85     this (name, subject, cbHandler, null);
86   }
87
88   /** @since 1.5 */
89   public LoginContext (final String name, final Subject subject,
90                        final CallbackHandler cbHandler,
91                        Configuration config)
92     throws LoginException
93   {
94     if (config == null)
95       config = Configuration.getConfig();
96     AppConfigurationEntry[] entries = config.getAppConfigurationEntry (name);
97     if (entries == null)
98       entries = config.getAppConfigurationEntry (OTHER);
99     if (entries == null)
100       throw new LoginException ("no configured modules for application "
101                                 + name);
102     this.entries = entries;
103     modules = new LoginModule[entries.length];
104     sharedState = new HashMap();
105     for (int i = 0; i < entries.length; i++)
106       modules[i] = lookupModule (entries[i], subject, sharedState);
107     this.name = name;
108     this.subject = subject;
109     this.cbHandler = cbHandler;
110   }
111
112   /**
113    * Returns the authenticated subject, or the parameter passed to one
114    * of the constructors. <code>null</code> is returned if the previous
115    * login attempt failed and there was no subject provided.
116    *
117    * @return The subject, or null.
118    */
119   public Subject getSubject()
120   {
121     return subject;
122   }
123
124   /**
125    * Logs a subject in, using all login modules configured for this
126    * application. This method will call the {@link LoginModule#login()}
127    * method of each module configured for this application, stopping
128    * if a REQUISITE module fails or if a SUFFICIENT module succeeds. If
129    * the overall login attempt fails, a {@link LoginException} will be
130    * thrown.
131    *
132    * @throws LoginException If logging in fails.
133    */
134   public void login() throws LoginException
135   {
136     boolean failure = false;
137     for (int i = 0; i < modules.length; i++)
138       {
139         try
140           {
141             boolean result = modules[i].login();
142             if (!result)
143               {
144                 if (entries[i].getControlFlag() ==
145                     AppConfigurationEntry.LoginModuleControlFlag.REQUISITE)
146                   throw new LoginException ("REQUISITE module " + entries[i].getLoginModuleName()
147                                             + " failed");
148                 else if (entries[i].getControlFlag() ==
149                          AppConfigurationEntry.LoginModuleControlFlag.REQUIRED)
150                   failure = true;
151               }
152             else
153               {
154                 if (entries[i].getControlFlag() ==
155                     AppConfigurationEntry.LoginModuleControlFlag.SUFFICIENT)
156                   break;
157               }
158           }
159         catch (LoginException le)
160           {
161             if (entries[i].getControlFlag() !=
162                 AppConfigurationEntry.LoginModuleControlFlag.REQUISITE)
163               continue;
164             for (int j = 0; j < modules.length; j++)
165               modules[i].abort();
166             throw le;
167           }
168       }
169     if (failure)
170       throw new LoginException ("not all REQUIRED modules succeeded");
171
172     for (int i = 0; i < modules.length; i++)
173       modules[i].commit();
174   }
175
176   /**
177    * Logs a subject out, cleaning up any state that may be in memory.
178    *
179    * @throws LoginException If logging out fails.
180    */
181   public void logout() throws LoginException
182   {
183     for (int i = 0; i < modules.length; i++)
184       modules[i].logout();
185   }
186
187   // Own methods.
188
189   /**
190    * Fetch the default callback handler, based on the
191    * auth.login.defaultCallbackHandler property, or null if it is not
192    * set.
193    */
194   private static CallbackHandler defaultHandler()
195   {
196     GetSecurityPropertyAction act =
197       new GetSecurityPropertyAction ("auth.login.defaultCallbackHandler");
198     String classname = (String) AccessController.doPrivileged (act);
199     if (classname != null)
200       {
201         try
202           {
203             return (CallbackHandler) Class.forName (classname).newInstance();
204           }
205         catch (ClassNotFoundException cnfe)
206           {
207             return null;
208           }
209         catch (ClassCastException cce)
210           {
211             return null;
212           }
213         catch (IllegalAccessException iae)
214           {
215             return null;
216           }
217         catch (InstantiationException ie)
218           {
219             return null;
220           }
221       }
222     return null;
223   }
224
225   private LoginModule lookupModule (AppConfigurationEntry entry,
226                                     Subject subject, Map sharedState)
227     throws LoginException
228   {
229     LoginModule module = null;
230     Exception cause = null;
231     try
232       {
233         ClassLoader cl = Thread.currentThread().getContextClassLoader();
234         Class c = Class.forName(entry.getLoginModuleName(), true, cl);
235         module = (LoginModule) c.newInstance();
236       }
237     catch (ClassNotFoundException cnfe)
238       {
239         cause = cnfe;
240       }
241     catch (ClassCastException cce)
242       {
243         cause = cce;
244       }
245     catch (IllegalAccessException iae)
246       {
247         cause = iae;
248       }
249     catch (InstantiationException ie)
250       {
251         cause = ie;
252       }
253
254     if (cause != null)
255       {
256         LoginException le = new LoginException ("could not load module "
257                                                 + entry.getLoginModuleName());
258         le.initCause (cause);
259         throw le;
260       }
261
262     module.initialize (subject, cbHandler, sharedState, entry.getOptions());
263     return module;
264   }
265 }