Source Code Cross Referenced for JndiLoginModule.java in  » 6.0-JDK-Modules-com.sun » security » com » sun » security » auth » module » Java Source Code / Java DocumentationJava Source Code and Java Documentation

Java Source Code / Java Documentation
1. 6.0 JDK Core
2. 6.0 JDK Modules
3. 6.0 JDK Modules com.sun
4. 6.0 JDK Modules com.sun.java
5. 6.0 JDK Modules sun
6. 6.0 JDK Platform
7. Ajax
8. Apache Harmony Java SE
9. Aspect oriented
10. Authentication Authorization
11. Blogger System
12. Build
13. Byte Code
14. Cache
15. Chart
16. Chat
17. Code Analyzer
18. Collaboration
19. Content Management System
20. Database Client
21. Database DBMS
22. Database JDBC Connection Pool
23. Database ORM
24. Development
25. EJB Server geronimo
26. EJB Server GlassFish
27. EJB Server JBoss 4.2.1
28. EJB Server resin 3.1.5
29. ERP CRM Financial
30. ESB
31. Forum
32. GIS
33. Graphic Library
34. Groupware
35. HTML Parser
36. IDE
37. IDE Eclipse
38. IDE Netbeans
39. Installer
40. Internationalization Localization
41. Inversion of Control
42. Issue Tracking
43. J2EE
44. JBoss
45. JMS
46. JMX
47. Library
48. Mail Clients
49. Net
50. Parser
51. PDF
52. Portal
53. Profiler
54. Project Management
55. Report
56. RSS RDF
57. Rule Engine
58. Science
59. Scripting
60. Search Engine
61. Security
62. Sevlet Container
63. Source Control
64. Swing Library
65. Template Engine
66. Test Coverage
67. Testing
68. UML
69. Web Crawler
70. Web Framework
71. Web Mail
72. Web Server
73. Web Services
74. Web Services apache cxf 2.0.1
75. Web Services AXIS2
76. Wiki Engine
77. Workflow Engines
78. XML
79. XML UI
Java
Java Tutorial
Java Open Source
Jar File Download
Java Articles
Java Products
Java by API
Photoshop Tutorials
Maya Tutorials
Flash Tutorials
3ds-Max Tutorials
Illustrator Tutorials
GIMP Tutorials
C# / C Sharp
C# / CSharp Tutorial
C# / CSharp Open Source
ASP.Net
ASP.NET Tutorial
JavaScript DHTML
JavaScript Tutorial
JavaScript Reference
HTML / CSS
HTML CSS Reference
C / ANSI-C
C Tutorial
C++
C++ Tutorial
Ruby
PHP
Python
Python Tutorial
Python Open Source
SQL Server / T-SQL
SQL Server / T-SQL Tutorial
Oracle PL / SQL
Oracle PL/SQL Tutorial
PostgreSQL
SQL / MySQL
MySQL Tutorial
VB.Net
VB.Net Tutorial
Flash / Flex / ActionScript
VBA / Excel / Access / Word
XML
XML Tutorial
Microsoft Office PowerPoint 2007 Tutorial
Microsoft Office Excel 2007 Tutorial
Microsoft Office Word 2007 Tutorial
Java Source Code / Java Documentation » 6.0 JDK Modules com.sun » security » com.sun.security.auth.module 
Source Cross Referenced  Class Diagram Java Document (Java Doc) 


001:        /*
002:         * Copyright 2000-2006 Sun Microsystems, Inc.  All Rights Reserved.
003:         * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
004:         *
005:         * This code is free software; you can redistribute it and/or modify it
006:         * under the terms of the GNU General Public License version 2 only, as
007:         * published by the Free Software Foundation.  Sun designates this
008:         * particular file as subject to the "Classpath" exception as provided
009:         * by Sun in the LICENSE file that accompanied this code.
010:         *
011:         * This code is distributed in the hope that it will be useful, but WITHOUT
012:         * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
013:         * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
014:         * version 2 for more details (a copy is included in the LICENSE file that
015:         * accompanied this code).
016:         *
017:         * You should have received a copy of the GNU General Public License version
018:         * 2 along with this work; if not, write to the Free Software Foundation,
019:         * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
020:         *
021:         * Please contact Sun Microsystems, Inc., 4150 Network Circle, Santa Clara,
022:         * CA 95054 USA or visit www.sun.com if you need additional information or
023:         * have any questions.
024:         */
025:
026:        package com.sun.security.auth.module;
027:
028:        import javax.security.auth.*;
029:        import javax.security.auth.callback.*;
030:        import javax.security.auth.login.*;
031:        import javax.security.auth.spi.*;
032:        import javax.naming.*;
033:        import javax.naming.directory.*;
034:
035:        import java.io.IOException;
036:        import java.util.Map;
037:        import java.util.LinkedList;
038:        import java.util.ResourceBundle;
039:
040:        import com.sun.security.auth.UnixPrincipal;
041:        import com.sun.security.auth.UnixNumericUserPrincipal;
042:        import com.sun.security.auth.UnixNumericGroupPrincipal;
043:
044:        import sun.security.util.AuthResources;
045:
046:        /**
047:         * <p> The module prompts for a username and password
048:         * and then verifies the password against the password stored in
049:         * a directory service configured under JNDI.
050:         *
051:         * <p> This <code>LoginModule</code> interoperates with
052:         * any conformant JNDI service provider.  To direct this
053:         * <code>LoginModule</code> to use a specific JNDI service provider,
054:         * two options must be specified in the login <code>Configuration</code>
055:         * for this <code>LoginModule</code>.
056:         * <pre>
057:         *	user.provider.url=<b>name_service_url</b>
058:         *	group.provider.url=<b>name_service_url</b>
059:         * </pre>
060:         *
061:         * <b>name_service_url</b> specifies
062:         * the directory service and path where this <code>LoginModule</code>
063:         * can access the relevant user and group information.  Because this
064:         * <code>LoginModule</code> only performs one-level searches to
065:         * find the relevant user information, the <code>URL</code>
066:         * must point to a directory one level above where the user and group
067:         * information is stored in the directory service.
068:         * For example, to instruct this <code>LoginModule</code>
069:         * to contact a NIS server, the following URLs must be specified:
070:         * <pre>
071:         *    user.provider.url="nis://<b>NISServerHostName</b>/<b>NISDomain</b>/user"
072:         *    group.provider.url="nis://<b>NISServerHostName</b>/<b>NISDomain</b>/system/group"
073:         * </pre>
074:         *
075:         * <b>NISServerHostName</b> specifies the server host name of the
076:         * NIS server (for example, <i>nis.sun.com</i>, and <b>NISDomain</b>
077:         * specifies the domain for that NIS server (for example, <i>jaas.sun.com</i>.
078:         * To contact an LDAP server, the following URLs must be specified:
079:         * <pre>
080:         *    user.provider.url="ldap://<b>LDAPServerHostName</b>/<b>LDAPName</b>"
081:         *    group.provider.url="ldap://<b>LDAPServerHostName</b>/<b>LDAPName</b>"
082:         * </pre>
083:         *
084:         * <b>LDAPServerHostName</b> specifies the server host name of the
085:         * LDAP server, which may include a port number
086:         * (for example, <i>ldap.sun.com:389</i>),
087:         * and <b>LDAPName</b> specifies the entry name in the LDAP directory
088:         * (for example, <i>ou=People,o=Sun,c=US</i> and <i>ou=Groups,o=Sun,c=US</i>
089:         * for user and group information, respectively).
090:         *
091:         * <p> The format in which the user's information must be stored in
092:         * the directory service is specified in RFC 2307.  Specifically,
093:         * this <code>LoginModule</code> will search for the user's entry in the
094:         * directory service using the user's <i>uid</i> attribute,
095:         * where <i>uid=<b>username</b></i>.  If the search succeeds,
096:         * this <code>LoginModule</code> will then
097:         * obtain the user's encrypted password from the retrieved entry
098:         * using the <i>userPassword</i> attribute.
099:         * This <code>LoginModule</code> assumes that the password is stored
100:         * as a byte array, which when converted to a <code>String</code>,
101:         * has the following format:
102:         * <pre>
103:         *	"{crypt}<b>encrypted_password</b>"
104:         * </pre>
105:         * 
106:         * The LDAP directory server must be configured
107:         * to permit read access to the userPassword attribute.
108:         * If the user entered a valid username and password,
109:         * this <code>LoginModule</code> associates a
110:         * <code>UnixPrincipal</code>, <code>UnixNumericUserPrincipal</code>,
111:         * and the relevant UnixNumericGroupPrincipals with the
112:         * <code>Subject</code>.
113:         * 
114:         * <p> This LoginModule also recognizes the following <code>Configuration</code>
115:         * options:
116:         * <pre>
117:         *    debug          if, true, debug messages are output to System.out.
118:         *
119:         *    useFirstPass   if, true, this LoginModule retrieves the
120:         *                   username and password from the module's shared state,
121:         *                   using "javax.security.auth.login.name" and
122:         *                   "javax.security.auth.login.password" as the respective
123:         *                   keys.  The retrieved values are used for authentication.
124:         *                   If authentication fails, no attempt for a retry is made,
125:         *                   and the failure is reported back to the calling
126:         *                   application.
127:         *
128:         *    tryFirstPass   if, true, this LoginModule retrieves the
129:         *                   the username and password from the module's shared state,
130:         *                   using "javax.security.auth.login.name" and
131:         *                   "javax.security.auth.login.password" as the respective
132:         *                   keys.  The retrieved values are used for authentication.
133:         *                   If authentication fails, the module uses the
134:         *                   CallbackHandler to retrieve a new username and password,
135:         *                   and another attempt to authenticate is made.
136:         *                   If the authentication fails, the failure is reported
137:         *                   back to the calling application.
138:         *
139:         *    storePass      if, true, this LoginModule stores the username and password
140:         *                   obtained from the CallbackHandler in the module's
141:         *                   shared state, using "javax.security.auth.login.name" and
142:         *                   "javax.security.auth.login.password" as the respective
143:         *                   keys.  This is not performed if existing values already
144:         *                   exist for the username and password in the shared state,
145:         *                   or if authentication fails.
146:         *
147:         *    clearPass     if, true, this <code>LoginModule</code> clears the
148:         *                  username and password stored in the module's shared state
149:         *                  after both phases of authentication (login and commit)
150:         *                  have completed.
151:         * </pre>
152:         *
153:         * @version 1.19, 05/05/07
154:         */
155:        public class JndiLoginModule implements  LoginModule {
156:
157:            static final java.util.ResourceBundle rb = java.util.ResourceBundle
158:                    .getBundle("sun.security.util.AuthResources");
159:
160:            /** JNDI Provider */
161:            public final String USER_PROVIDER = "user.provider.url";
162:            public final String GROUP_PROVIDER = "group.provider.url";
163:
164:            // configurable options
165:            private boolean debug = false;
166:            private boolean strongDebug = false;
167:            private String userProvider;
168:            private String groupProvider;
169:            private boolean useFirstPass = false;
170:            private boolean tryFirstPass = false;
171:            private boolean storePass = false;
172:            private boolean clearPass = false;
173:
174:            // the authentication status
175:            private boolean succeeded = false;
176:            private boolean commitSucceeded = false;
177:
178:            // username, password, and JNDI context
179:            private String username;
180:            private char[] password;
181:            DirContext ctx;
182:
183:            // the user (assume it is a UnixPrincipal)
184:            private UnixPrincipal userPrincipal;
185:            private UnixNumericUserPrincipal UIDPrincipal;
186:            private UnixNumericGroupPrincipal GIDPrincipal;
187:            private LinkedList<UnixNumericGroupPrincipal> supplementaryGroups = new LinkedList<UnixNumericGroupPrincipal>();
188:
189:            // initial state
190:            private Subject subject;
191:            private CallbackHandler callbackHandler;
192:            private Map sharedState;
193:            private Map<String, ?> options;
194:
195:            private static final String CRYPT = "{crypt}";
196:            private static final String USER_PWD = "userPassword";
197:            private static final String USER_UID = "uidNumber";
198:            private static final String USER_GID = "gidNumber";
199:            private static final String GROUP_ID = "gidNumber";
200:            private static final String NAME = "javax.security.auth.login.name";
201:            private static final String PWD = "javax.security.auth.login.password";
202:
203:            /**
204:             * Initialize this <code>LoginModule</code>.
205:             *
206:             * <p>
207:             *
208:             * @param subject the <code>Subject</code> to be authenticated. <p>
209:             *
210:             * @param callbackHandler a <code>CallbackHandler</code> for communicating
211:             *			with the end user (prompting for usernames and
212:             *			passwords, for example). <p>
213:             *
214:             * @param sharedState shared <code>LoginModule</code> state. <p>
215:             *
216:             * @param options options specified in the login
217:             *			<code>Configuration</code> for this particular
218:             *			<code>LoginModule</code>.
219:             */
220:            public void initialize(Subject subject,
221:                    CallbackHandler callbackHandler,
222:                    Map<String, ?> sharedState, Map<String, ?> options) {
223:
224:                this .subject = subject;
225:                this .callbackHandler = callbackHandler;
226:                this .sharedState = sharedState;
227:                this .options = options;
228:
229:                // initialize any configured options
230:                debug = "true".equalsIgnoreCase((String) options.get("debug"));
231:                strongDebug = "true".equalsIgnoreCase((String) options
232:                        .get("strongDebug"));
233:                userProvider = (String) options.get(USER_PROVIDER);
234:                groupProvider = (String) options.get(GROUP_PROVIDER);
235:                tryFirstPass = "true".equalsIgnoreCase((String) options
236:                        .get("tryFirstPass"));
237:                useFirstPass = "true".equalsIgnoreCase((String) options
238:                        .get("useFirstPass"));
239:                storePass = "true".equalsIgnoreCase((String) options
240:                        .get("storePass"));
241:                clearPass = "true".equalsIgnoreCase((String) options
242:                        .get("clearPass"));
243:            }
244:
245:            /**
246:             * <p> Prompt for username and password.
247:             * Verify the password against the relevant name service.
248:             *
249:             * <p>
250:             *
251:             * @return true always, since this <code>LoginModule</code>
252:             *		should not be ignored.
253:             *
254:             * @exception FailedLoginException if the authentication fails. <p>
255:             *
256:             * @exception LoginException if this <code>LoginModule</code>
257:             *		is unable to perform the authentication.
258:             */
259:            public boolean login() throws LoginException {
260:
261:                if (userProvider == null) {
262:                    throw new LoginException(
263:                            "Error: Unable to locate JNDI user provider");
264:                }
265:                if (groupProvider == null) {
266:                    throw new LoginException(
267:                            "Error: Unable to locate JNDI group provider");
268:                }
269:
270:                if (debug) {
271:                    System.out.println("\t\t[JndiLoginModule] user provider: "
272:                            + userProvider);
273:                    System.out.println("\t\t[JndiLoginModule] group provider: "
274:                            + groupProvider);
275:                }
276:
277:                // attempt the authentication
278:                if (tryFirstPass) {
279:
280:                    try {
281:                        // attempt the authentication by getting the
282:                        // username and password from shared state
283:                        attemptAuthentication(true);
284:
285:                        // authentication succeeded
286:                        succeeded = true;
287:                        if (debug) {
288:                            System.out.println("\t\t[JndiLoginModule] "
289:                                    + "tryFirstPass succeeded");
290:                        }
291:                        return true;
292:                    } catch (LoginException le) {
293:                        // authentication failed -- try again below by prompting
294:                        cleanState();
295:                        if (debug) {
296:                            System.out.println("\t\t[JndiLoginModule] "
297:                                    + "tryFirstPass failed with:"
298:                                    + le.toString());
299:                        }
300:                    }
301:
302:                } else if (useFirstPass) {
303:
304:                    try {
305:                        // attempt the authentication by getting the
306:                        // username and password from shared state
307:                        attemptAuthentication(true);
308:
309:                        // authentication succeeded
310:                        succeeded = true;
311:                        if (debug) {
312:                            System.out.println("\t\t[JndiLoginModule] "
313:                                    + "useFirstPass succeeded");
314:                        }
315:                        return true;
316:                    } catch (LoginException le) {
317:                        // authentication failed
318:                        cleanState();
319:                        if (debug) {
320:                            System.out.println("\t\t[JndiLoginModule] "
321:                                    + "useFirstPass failed");
322:                        }
323:                        throw le;
324:                    }
325:                }
326:
327:                // attempt the authentication by prompting for the username and pwd
328:                try {
329:                    attemptAuthentication(false);
330:
331:                    // authentication succeeded
332:                    succeeded = true;
333:                    if (debug) {
334:                        System.out.println("\t\t[JndiLoginModule] "
335:                                + "regular authentication succeeded");
336:                    }
337:                    return true;
338:                } catch (LoginException le) {
339:                    cleanState();
340:                    if (debug) {
341:                        System.out.println("\t\t[JndiLoginModule] "
342:                                + "regular authentication failed");
343:                    }
344:                    throw le;
345:                }
346:            }
347:
348:            /**
349:             * Abstract method to commit the authentication process (phase 2).
350:             *
351:             * <p> This method is called if the LoginContext's
352:             * overall authentication succeeded
353:             * (the relevant REQUIRED, REQUISITE, SUFFICIENT and OPTIONAL LoginModules
354:             * succeeded).
355:             *
356:             * <p> If this LoginModule's own authentication attempt
357:             * succeeded (checked by retrieving the private state saved by the
358:             * <code>login</code> method), then this method associates a
359:             * <code>UnixPrincipal</code>
360:             * with the <code>Subject</code> located in the
361:             * <code>LoginModule</code>.  If this LoginModule's own
362:             * authentication attempted failed, then this method removes
363:             * any state that was originally saved.
364:             *
365:             * <p>
366:             *
367:             * @exception LoginException if the commit fails
368:             *
369:             * @return true if this LoginModule's own login and commit
370:             *		attempts succeeded, or false otherwise.
371:             */
372:            public boolean commit() throws LoginException {
373:
374:                if (succeeded == false) {
375:                    return false;
376:                } else {
377:                    if (subject.isReadOnly()) {
378:                        cleanState();
379:                        throw new LoginException("Subject is Readonly");
380:                    }
381:                    // add Principals to the Subject
382:                    if (!subject.getPrincipals().contains(userPrincipal))
383:                        subject.getPrincipals().add(userPrincipal);
384:                    if (!subject.getPrincipals().contains(UIDPrincipal))
385:                        subject.getPrincipals().add(UIDPrincipal);
386:                    if (!subject.getPrincipals().contains(GIDPrincipal))
387:                        subject.getPrincipals().add(GIDPrincipal);
388:                    for (int i = 0; i < supplementaryGroups.size(); i++) {
389:                        if (!subject.getPrincipals().contains(
390:                                supplementaryGroups.get(i)))
391:                            subject.getPrincipals().add(
392:                                    supplementaryGroups.get(i));
393:                    }
394:
395:                    if (debug) {
396:                        System.out.println("\t\t[JndiLoginModule]: "
397:                                + "added UnixPrincipal,");
398:                        System.out.println("\t\t\t\tUnixNumericUserPrincipal,");
399:                        System.out
400:                                .println("\t\t\t\tUnixNumericGroupPrincipal(s),");
401:                        System.out.println("\t\t\t to Subject");
402:                    }
403:                }
404:                // in any case, clean out state
405:                cleanState();
406:                commitSucceeded = true;
407:                return true;
408:            }
409:
410:            /**
411:             * <p> This method is called if the LoginContext's
412:             * overall authentication failed.
413:             * (the relevant REQUIRED, REQUISITE, SUFFICIENT and OPTIONAL LoginModules
414:             * did not succeed).
415:             *
416:             * <p> If this LoginModule's own authentication attempt
417:             * succeeded (checked by retrieving the private state saved by the
418:             * <code>login</code> and <code>commit</code> methods),
419:             * then this method cleans up any state that was originally saved.
420:             *
421:             * <p>
422:             *
423:             * @exception LoginException if the abort fails.
424:             *
425:             * @return false if this LoginModule's own login and/or commit attempts
426:             *		failed, and true otherwise.
427:             */
428:            public boolean abort() throws LoginException {
429:                if (debug)
430:                    System.out.println("\t\t[JndiLoginModule]: "
431:                            + "aborted authentication failed");
432:
433:                if (succeeded == false) {
434:                    return false;
435:                } else if (succeeded == true && commitSucceeded == false) {
436:
437:                    // Clean out state
438:                    succeeded = false;
439:                    cleanState();
440:
441:                    userPrincipal = null;
442:                    UIDPrincipal = null;
443:                    GIDPrincipal = null;
444:                    supplementaryGroups = new LinkedList<UnixNumericGroupPrincipal>();
445:                } else {
446:                    // overall authentication succeeded and commit succeeded,
447:                    // but someone else's commit failed
448:                    logout();
449:                }
450:                return true;
451:            }
452:
453:            /**
454:             * Logout a user.
455:             *
456:             * <p> This method removes the Principals
457:             * that were added by the <code>commit</code> method.
458:             *
459:             * <p>
460:             *
461:             * @exception LoginException if the logout fails.
462:             *
463:             * @return true in all cases since this <code>LoginModule</code>
464:             *		should not be ignored.
465:             */
466:            public boolean logout() throws LoginException {
467:                if (subject.isReadOnly()) {
468:                    cleanState();
469:                    throw new LoginException("Subject is Readonly");
470:                }
471:                subject.getPrincipals().remove(userPrincipal);
472:                subject.getPrincipals().remove(UIDPrincipal);
473:                subject.getPrincipals().remove(GIDPrincipal);
474:                for (int i = 0; i < supplementaryGroups.size(); i++) {
475:                    subject.getPrincipals().remove(supplementaryGroups.get(i));
476:                }
477:
478:                // clean out state
479:                cleanState();
480:                succeeded = false;
481:                commitSucceeded = false;
482:
483:                userPrincipal = null;
484:                UIDPrincipal = null;
485:                GIDPrincipal = null;
486:                supplementaryGroups = new LinkedList<UnixNumericGroupPrincipal>();
487:
488:                if (debug) {
489:                    System.out.println("\t\t[JndiLoginModule]: "
490:                            + "logged out Subject");
491:                }
492:                return true;
493:            }
494:
495:            /**
496:             * Attempt authentication
497:             *
498:             * <p>
499:             *
500:             * @param getPasswdFromSharedState boolean that tells this method whether
501:             *		to retrieve the password from the sharedState.
502:             */
503:            private void attemptAuthentication(boolean getPasswdFromSharedState)
504:                    throws LoginException {
505:
506:                String encryptedPassword = null;
507:
508:                // first get the username and password
509:                getUsernamePassword(getPasswdFromSharedState);
510:
511:                try {
512:
513:                    // get the user's passwd entry from the user provider URL
514:                    InitialContext iCtx = new InitialContext();
515:                    ctx = (DirContext) iCtx.lookup(userProvider);
516:
517:                    /*
518:                    SearchControls controls = new SearchControls
519:                    			(SearchControls.ONELEVEL_SCOPE,
520:                    			0,
521:                    			5000,
522:                    			new String[] { USER_PWD },
523:                    			false,
524:                    			false);
525:                     */
526:
527:                    SearchControls controls = new SearchControls();
528:                    NamingEnumeration<SearchResult> ne = ctx.search("", "(uid="
529:                            + username + ")", controls);
530:                    if (ne.hasMore()) {
531:                        SearchResult result = ne.next();
532:                        Attributes attributes = result.getAttributes();
533:
534:                        // get the password
535:
536:                        // this module works only if the LDAP directory server
537:                        // is configured to permit read access to the userPassword
538:                        // attribute. The directory administrator need to grant
539:                        // this access.
540:                        //
541:                        // A workaround would be to make the server do authentication
542:                        // by setting the Context.SECURITY_PRINCIPAL
543:                        // and Context.SECURITY_CREDENTIALS property.
544:                        // However, this would make it not work with systems that
545:                        // don't do authentication at the server (like NIS).
546:                        //
547:                        // Setting the SECURITY_* properties and using "simple"
548:                        // authentication for LDAP is recommended only for secure
549:                        // channels. For nonsecure channels, SSL is recommended.
550:
551:                        Attribute pwd = attributes.get(USER_PWD);
552:                        String encryptedPwd = new String((byte[]) pwd.get(),
553:                                "UTF8");
554:                        encryptedPassword = encryptedPwd.substring(CRYPT
555:                                .length());
556:
557:                        // check the password
558:                        if (verifyPassword(encryptedPassword, new String(
559:                                password)) == true) {
560:
561:                            // authentication succeeded
562:                            if (debug)
563:                                System.out.println("\t\t[JndiLoginModule] "
564:                                        + "attemptAuthentication() succeeded");
565:
566:                        } else {
567:                            // authentication failed
568:                            if (debug)
569:                                System.out.println("\t\t[JndiLoginModule] "
570:                                        + "attemptAuthentication() failed");
571:                            throw new FailedLoginException("Login incorrect");
572:                        }
573:
574:                        // save input as shared state only if
575:                        // authentication succeeded
576:                        if (storePass && !sharedState.containsKey(NAME)
577:                                && !sharedState.containsKey(PWD)) {
578:                            sharedState.put(NAME, username);
579:                            sharedState.put(PWD, password);
580:                        }
581:
582:                        // create the user principal
583:                        userPrincipal = new UnixPrincipal(username);
584:
585:                        // get the UID
586:                        Attribute uid = attributes.get(USER_UID);
587:                        String uidNumber = (String) uid.get();
588:                        UIDPrincipal = new UnixNumericUserPrincipal(uidNumber);
589:                        if (debug && uidNumber != null) {
590:                            System.out.println("\t\t[JndiLoginModule] "
591:                                    + "user: '" + username + "' has UID: "
592:                                    + uidNumber);
593:                        }
594:
595:                        // get the GID
596:                        Attribute gid = attributes.get(USER_GID);
597:                        String gidNumber = (String) gid.get();
598:                        GIDPrincipal = new UnixNumericGroupPrincipal(gidNumber,
599:                                true);
600:                        if (debug && gidNumber != null) {
601:                            System.out.println("\t\t[JndiLoginModule] "
602:                                    + "user: '" + username + "' has GID: "
603:                                    + gidNumber);
604:                        }
605:
606:                        // get the supplementary groups from the group provider URL
607:                        ctx = (DirContext) iCtx.lookup(groupProvider);
608:                        ne = ctx.search("", new BasicAttributes("memberUid",
609:                                username));
610:
611:                        while (ne.hasMore()) {
612:                            result = ne.next();
613:                            attributes = result.getAttributes();
614:
615:                            gid = attributes.get(GROUP_ID);
616:                            String suppGid = (String) gid.get();
617:                            if (!gidNumber.equals(suppGid)) {
618:                                UnixNumericGroupPrincipal suppPrincipal = new UnixNumericGroupPrincipal(
619:                                        suppGid, false);
620:                                supplementaryGroups.add(suppPrincipal);
621:                                if (debug && suppGid != null) {
622:                                    System.out.println("\t\t[JndiLoginModule] "
623:                                            + "user: '" + username
624:                                            + "' has Supplementary Group: "
625:                                            + suppGid);
626:                                }
627:                            }
628:                        }
629:
630:                    } else {
631:                        // bad username
632:                        if (debug) {
633:                            System.out
634:                                    .println("\t\t[JndiLoginModule]: User not found");
635:                        }
636:                        throw new FailedLoginException("User not found");
637:                    }
638:                } catch (NamingException ne) {
639:                    // bad username
640:                    if (debug) {
641:                        System.out
642:                                .println("\t\t[JndiLoginModule]:  User not found");
643:                        ne.printStackTrace();
644:                    }
645:                    throw new FailedLoginException("User not found");
646:                } catch (java.io.UnsupportedEncodingException uee) {
647:                    // password stored in incorrect format
648:                    if (debug) {
649:                        System.out.println("\t\t[JndiLoginModule]:  "
650:                                + "password incorrectly encoded");
651:                        uee.printStackTrace();
652:                    }
653:                    throw new LoginException("Login failure due to incorrect "
654:                            + "password encoding in the password database");
655:                }
656:
657:                // authentication succeeded
658:            }
659:
660:            /**
661:             * Get the username and password.
662:             * This method does not return any value.
663:             * Instead, it sets global name and password variables.
664:             *
665:             * <p> Also note that this method will set the username and password
666:             * values in the shared state in case subsequent LoginModules
667:             * want to use them via use/tryFirstPass.
668:             *
669:             * <p>
670:             *
671:             * @param getPasswdFromSharedState boolean that tells this method whether
672:             *		to retrieve the password from the sharedState.
673:             */
674:            private void getUsernamePassword(boolean getPasswdFromSharedState)
675:                    throws LoginException {
676:
677:                if (getPasswdFromSharedState) {
678:                    // use the password saved by the first module in the stack
679:                    username = (String) sharedState.get(NAME);
680:                    password = (char[]) sharedState.get(PWD);
681:                    return;
682:                }
683:
684:                // prompt for a username and password
685:                if (callbackHandler == null)
686:                    throw new LoginException(
687:                            "Error: no CallbackHandler available "
688:                                    + "to garner authentication information from the user");
689:
690:                String protocol = userProvider.substring(0, userProvider
691:                        .indexOf(":"));
692:
693:                Callback[] callbacks = new Callback[2];
694:                callbacks[0] = new NameCallback(protocol + " "
695:                        + rb.getString("username: "));
696:                callbacks[1] = new PasswordCallback(protocol + " "
697:                        + rb.getString("password: "), false);
698:
699:                try {
700:                    callbackHandler.handle(callbacks);
701:                    username = ((NameCallback) callbacks[0]).getName();
702:                    char[] tmpPassword = ((PasswordCallback) callbacks[1])
703:                            .getPassword();
704:                    password = new char[tmpPassword.length];
705:                    System.arraycopy(tmpPassword, 0, password, 0,
706:                            tmpPassword.length);
707:                    ((PasswordCallback) callbacks[1]).clearPassword();
708:
709:                } catch (java.io.IOException ioe) {
710:                    throw new LoginException(ioe.toString());
711:                } catch (UnsupportedCallbackException uce) {
712:                    throw new LoginException(
713:                            "Error: "
714:                                    + uce.getCallback().toString()
715:                                    + " not available to garner authentication information "
716:                                    + "from the user");
717:                }
718:
719:                // print debugging information
720:                if (strongDebug) {
721:                    System.out.println("\t\t[JndiLoginModule] "
722:                            + "user entered username: " + username);
723:                    System.out.print("\t\t[JndiLoginModule] "
724:                            + "user entered password: ");
725:                    for (int i = 0; i < password.length; i++)
726:                        System.out.print(password[i]);
727:                    System.out.println();
728:                }
729:            }
730:
731:            /**
732:             * Verify a password against the encrypted passwd from /etc/shadow
733:             */
734:            private boolean verifyPassword(String encryptedPassword,
735:                    String password) {
736:
737:                if (encryptedPassword == null)
738:                    return false;
739:
740:                Crypt c = new Crypt();
741:                try {
742:                    byte oldCrypt[] = encryptedPassword.getBytes("UTF8");
743:                    byte newCrypt[] = c.crypt(password.getBytes("UTF8"),
744:                            oldCrypt);
745:                    if (newCrypt.length != oldCrypt.length)
746:                        return false;
747:                    for (int i = 0; i < newCrypt.length; i++) {
748:                        if (oldCrypt[i] != newCrypt[i])
749:                            return false;
750:                    }
751:                } catch (java.io.UnsupportedEncodingException uee) {
752:                    // cannot happen, but return false just to be safe
753:                    return false;
754:                }
755:                return true;
756:            }
757:
758:            /**
759:             * Clean out state because of a failed authentication attempt
760:             */
761:            private void cleanState() {
762:                username = null;
763:                if (password != null) {
764:                    for (int i = 0; i < password.length; i++)
765:                        password[i] = ' ';
766:                    password = null;
767:                }
768:                ctx = null;
769:
770:                if (clearPass) {
771:                    sharedState.remove(NAME);
772:                    sharedState.remove(PWD);
773:                }
774:            }
775:        }
www.java2java.com | Contact Us
Copyright 2009 - 12 Demo Source and Support. All rights reserved.
All other trademarks are property of their respective owners.