KickJava   Java API By Example, From Geeks To Geeks.

Java > Open Source Codes > com > sun > security > auth > module > UnixLoginModule


1 /*
2  * @(#)UnixLoginModule.java 1.7 04/05/05
3  *
4  * Copyright 2004 Sun Microsystems, Inc. All rights reserved.
5  * SUN PROPRIETARY/CONFIDENTIAL. Use is subject to license terms.
6  */

7
8 package com.sun.security.auth.module;
9
10 import java.util.*;
11 import java.io.IOException JavaDoc;
12 import javax.security.auth.*;
13 import javax.security.auth.callback.*;
14 import javax.security.auth.login.*;
15 import javax.security.auth.spi.*;
16 import com.sun.security.auth.UnixPrincipal;
17 import com.sun.security.auth.UnixNumericUserPrincipal;
18 import com.sun.security.auth.UnixNumericGroupPrincipal;
19
20 /**
21  * <p> This <code>LoginModule</code> imports a user's Unix
22  * <code>Principal</code> information (<code>UnixPrincipal</code>,
23  * <code>UnixNumericUserPrincipal</code>,
24  * and <code>UnixNumericGroupPrincipal</code>)
25  * and associates them with the current <code>Subject</code>.
26  *
27  * <p> This LoginModule recognizes the debug option.
28  * If set to true in the login Configuration,
29  * debug messages will be output to the output stream, System.out.
30  *
31  * @version 1.7, 05/05/04
32  */

33 public class UnixLoginModule implements LoginModule {
34
35     // initial state
36
private Subject subject;
37     private CallbackHandler callbackHandler;
38     private Map sharedState;
39     private Map options;
40
41     // configurable option
42
private boolean debug = true;
43
44     // UnixSystem to retrieve underlying system info
45
private UnixSystem ss;
46
47     // the authentication status
48
private boolean succeeded = false;
49     private boolean commitSucceeded = false;
50
51     // Underlying system info
52
private UnixPrincipal userPrincipal;
53     private UnixNumericUserPrincipal UIDPrincipal;
54     private UnixNumericGroupPrincipal GIDPrincipal;
55     private LinkedList supplementaryGroups = new LinkedList();
56
57     /**
58      * Initialize this <code>LoginModule</code>.
59      *
60      * <p>
61      *
62      * @param subject the <code>Subject</code> to be authenticated. <p>
63      *
64      * @param callbackHandler a <code>CallbackHandler</code> for communicating
65      * with the end user (prompting for usernames and
66      * passwords, for example). <p>
67      *
68      * @param sharedState shared <code>LoginModule</code> state. <p>
69      *
70      * @param options options specified in the login
71      * <code>Configuration</code> for this particular
72      * <code>LoginModule</code>.
73      */

74     public void initialize(Subject subject, CallbackHandler callbackHandler,
75                Map<String JavaDoc,?> sharedState,
76                Map<String JavaDoc,?> options) {
77
78     this.subject = subject;
79     this.callbackHandler = callbackHandler;
80     this.sharedState = sharedState;
81     this.options = options;
82
83     // initialize any configured options
84
debug = "true".equalsIgnoreCase((String JavaDoc)options.get("debug"));
85     }
86
87     /**
88      * Authenticate the user (first phase).
89      *
90      * <p> The implementation of this method attempts to retrieve the user's
91      * Unix <code>Subject</code> information by making a native Unix
92      * system call.
93      *
94      * <p>
95      *
96      * @exception FailedLoginException if attempts to retrieve the underlying
97      * system information fail.
98      *
99      * @return true in all cases (this <code>LoginModule</code>
100      * should not be ignored).
101      */

102     public boolean login() throws LoginException {
103
104     long[] unixGroups = null;
105
106     ss = new UnixSystem();
107
108     if (ss == null) {
109         succeeded = false;
110         throw new FailedLoginException
111                 ("Failed in attempt to import " +
112                 "the underlying system identity information");
113     } else {
114         userPrincipal = new UnixPrincipal(ss.getUsername());
115         UIDPrincipal = new UnixNumericUserPrincipal(ss.getUid());
116         GIDPrincipal = new UnixNumericGroupPrincipal(ss.getGid(), true);
117         if (ss.getGroups() != null && ss.getGroups().length > 0)
118         unixGroups = ss.getGroups();
119         for (int i = 0; i < unixGroups.length; i++) {
120             UnixNumericGroupPrincipal ngp =
121             new UnixNumericGroupPrincipal
122             (unixGroups[i], false);
123             if (!ngp.getName().equals(GIDPrincipal.getName()))
124             supplementaryGroups.add(ngp);
125         }
126         if (debug) {
127         System.out.println("\t\t[UnixLoginModule]: " +
128             "succeeded importing info: ");
129         System.out.println("\t\t\tuid = " + ss.getUid());
130         System.out.println("\t\t\tgid = " + ss.getGid());
131         unixGroups = ss.getGroups();
132         for (int i = 0; i < unixGroups.length; i++) {
133             System.out.println("\t\t\tsupp gid = " + unixGroups[i]);
134         }
135         }
136         succeeded = true;
137         return true;
138     }
139     }
140
141     /**
142      * Commit the authentication (second phase).
143      *
144      * <p> This method is called if the LoginContext's
145      * overall authentication succeeded
146      * (the relevant REQUIRED, REQUISITE, SUFFICIENT and OPTIONAL LoginModules
147      * succeeded).
148      *
149      * <p> If this LoginModule's own authentication attempt
150      * succeeded (the importing of the Unix authentication information
151      * succeeded), then this method associates the Unix Principals
152      * with the <code>Subject</code> currently tied to the
153      * <code>LoginModule</code>. If this LoginModule's
154      * authentication attempted failed, then this method removes
155      * any state that was originally saved.
156      *
157      * <p>
158      *
159      * @exception LoginException if the commit fails
160      *
161      * @return true if this LoginModule's own login and commit attempts
162      * succeeded, or false otherwise.
163      */

164     public boolean commit() throws LoginException {
165     if (succeeded == false) {
166         if (debug) {
167         System.out.println("\t\t[UnixLoginModule]: " +
168             "did not add any Principals to Subject " +
169             "because own authentication failed.");
170         }
171         return false;
172     } else {
173         if (subject.isReadOnly()) {
174         throw new LoginException
175             ("commit Failed: Subject is Readonly");
176         }
177         if (!subject.getPrincipals().contains(userPrincipal))
178         subject.getPrincipals().add(userPrincipal);
179         if (!subject.getPrincipals().contains(UIDPrincipal))
180         subject.getPrincipals().add(UIDPrincipal);
181         if (!subject.getPrincipals().contains(GIDPrincipal))
182         subject.getPrincipals().add(GIDPrincipal);
183         for (int i = 0; i < supplementaryGroups.size(); i++) {
184         if (!subject.getPrincipals().contains
185             ((UnixNumericGroupPrincipal)supplementaryGroups.get(i)))
186             subject.getPrincipals().add((UnixNumericGroupPrincipal)
187             supplementaryGroups.get(i));
188         }
189
190         if (debug) {
191         System.out.println("\t\t[UnixLoginModule]: " +
192             "added UnixPrincipal,");
193         System.out.println("\t\t\t\tUnixNumericUserPrincipal,");
194         System.out.println("\t\t\t\tUnixNumericGroupPrincipal(s),");
195         System.out.println("\t\t\t to Subject");
196         }
197
198         commitSucceeded = true;
199         return true;
200     }
201     }
202
203     /**
204      * Abort the authentication (second phase).
205      *
206      * <p> This method is called if the LoginContext's
207      * overall authentication failed.
208      * (the relevant REQUIRED, REQUISITE, SUFFICIENT and OPTIONAL LoginModules
209      * did not succeed).
210      *
211      * <p> This method cleans up any state that was originally saved
212      * as part of the authentication attempt from the <code>login</code>
213      * and <code>commit</code> methods.
214      *
215      * <p>
216      *
217      * @exception LoginException if the abort fails
218      *
219      * @return false if this LoginModule's own login and/or commit attempts
220      * failed, and true otherwise.
221      */

222     public boolean abort() throws LoginException {
223     if (debug) {
224         System.out.println("\t\t[UnixLoginModule]: " +
225         "aborted authentication attempt");
226     }
227
228     if (succeeded == false) {
229         return false;
230     } else if (succeeded == true && commitSucceeded == false) {
231
232         // Clean out state
233
succeeded = false;
234         ss = null;
235         userPrincipal = null;
236         UIDPrincipal = null;
237         GIDPrincipal = null;
238         supplementaryGroups = new LinkedList();
239     } else {
240         // overall authentication succeeded and commit succeeded,
241
// but someone else's commit failed
242
logout();
243     }
244     return true;
245     }
246
247     /**
248      * Logout the user
249      *
250      * <p> This method removes the Principals associated
251      * with the <code>Subject</code>.
252      *
253      * <p>
254      *
255      * @exception LoginException if the logout fails
256      *
257      * @return true in all cases (this <code>LoginModule</code>
258      * should not be ignored).
259      */

260     public boolean logout() throws LoginException {
261
262     if (subject.isReadOnly()) {
263         throw new LoginException
264             ("logout Failed: Subject is Readonly");
265         }
266     // remove the added Principals from the Subject
267
subject.getPrincipals().remove(userPrincipal);
268     subject.getPrincipals().remove(UIDPrincipal);
269     subject.getPrincipals().remove(GIDPrincipal);
270     for (int i = 0; i < supplementaryGroups.size(); i++) {
271         subject.getPrincipals().remove
272             ((UnixNumericGroupPrincipal)supplementaryGroups.get(i));
273     }
274
275     // clean out state
276
ss = null;
277     succeeded = false;
278     commitSucceeded = false;
279     userPrincipal = null;
280     UIDPrincipal = null;
281     GIDPrincipal = null;
282     supplementaryGroups = new LinkedList();
283
284     if (debug) {
285         System.out.println("\t\t[UnixLoginModule]: " +
286         "logged out Subject");
287     }
288     return true;
289     }
290 }
291
Popular Tags