Source Code Cross Referenced for JNDIAuthenticatorImpl.java in  » Project-Management » XPlanner-0.7b7 » com » sabre » security » jndi » 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 » Project Management » XPlanner 0.7b7 » com.sabre.security.jndi 
Source Cross Referenced  Class Diagram Java Document (Java Doc) 


001:        package com.sabre.security.jndi;
002:
003:        import java.security.Principal;
004:        import java.security.MessageDigest;
005:        import java.security.NoSuchAlgorithmException;
006:        import java.text.MessageFormat;
007:        import java.util.*;
008:        import javax.security.auth.Subject;
009:        import javax.naming.directory.*;
010:        import javax.naming.*;
011:
012:        import org.apache.log4j.Logger;
013:        import org.apache.commons.beanutils.BeanUtils;
014:        import com.sabre.security.jndi.util.Base64;
015:        import com.sabre.security.jndi.util.HexUtils;
016:
017:        public class JNDIAuthenticatorImpl implements  JNDIAuthenticator {
018:
019:            /**
020:             * Debug level
021:             */
022:            private int debug = 10;
023:            /**
024:             * Logger.
025:             */
026:            public static final Logger log = Logger
027:                    .getLogger(JNDIAuthenticatorImpl.class);
028:            /**
029:             * Should we search the entire subtree for matching users?
030:             */
031:            private boolean userSubtree;
032:            /**
033:             * Should we search the entire subtree for matching memberships?
034:             */
035:            private boolean roleSubtree;
036:            /**
037:             * Descriptive information about this Realm implementation.
038:             */
039:            protected static final String info = "org.apache.catalina.realm.JNDIRealm/1.0";
040:            /**
041:             * The JNDI context factory used to acquire our InitialContext.  By
042:             * default, assumes use of an LDAP server using the standard JNDI LDAP
043:             * provider.
044:             */
045:            protected String contextFactory = "com.sun.jndi.ldap.LdapCtxFactory";
046:            /**
047:             * The type of authentication to use
048:             */
049:            private String authentication;
050:            /**
051:             * The connection username for the server we will contact.
052:             */
053:            private String connectionUser;
054:            /**
055:             * The connection password for the server we will contact.
056:             */
057:            private String connectionPassword;
058:            /**
059:             * The connection URL for the server we will contact.
060:             */
061:            private String connectionURL;
062:            /**
063:             * The protocol that will be used in the communication with the directory server.
064:             */
065:            private String protocol;
066:            /**
067:             * How should we handle referrals?  Microsoft Active Directory can't handle
068:             * the default case, so an application authenticating against AD must
069:             * set referrals to "follow".
070:             */
071:            private String referrals;
072:            /**
073:             * The base element for user searches.
074:             */
075:            private String userBase = "";
076:            /**
077:             * The message format used to search for a user, with "{0}" marking
078:             * the spot where the username goes.
079:             */
080:            private String userSearch;
081:            /**
082:             * The attribute name used to retrieve the user password.
083:             */
084:            private String userPassword;
085:            /**
086:             * The message format used to form the distinguished name of a
087:             * user, with "{0}" marking the spot where the specified username
088:             * goes.
089:             */
090:            private String userPattern;
091:            /**
092:             * The base element for role searches.
093:             */
094:            private String roleBase = "";
095:            /**
096:             * The name of an attribute in the user's entry containing
097:             * roles for that user
098:             */
099:            private String userRoleName;
100:            /**
101:             * The name of the attribute containing roles held elsewhere
102:             */
103:            private String roleName;
104:            /**
105:             * The directory context linking us to our directory server.
106:             */
107:            protected DirContext context;
108:            /**
109:             * The MessageDigest
110:             */
111:            private MessageDigest messageDigest;
112:            /**
113:             * The MessageFormat object associated with the current
114:             * <code>userSearch</code>.
115:             */
116:            protected MessageFormat userSearchFormat;
117:            /**
118:             * The MessageFormat object associated with the current
119:             * <code>userPattern</code>.
120:             */
121:            protected MessageFormat userPatternFormat;
122:            /**
123:             * The MessageFormat object associated with the current
124:             * <code>roleSearch</code>.
125:             */
126:            protected MessageFormat roleFormat;
127:
128:            public void setDigest(String algorithm)
129:                    throws NoSuchAlgorithmException {
130:                messageDigest = MessageDigest.getInstance(algorithm);
131:            }
132:
133:            public void setDebug(String debug) {
134:                this .debug = Integer.parseInt(debug);
135:            }
136:
137:            public void setUserSubtree(String userSubtree) {
138:                this .userSubtree = Boolean.getBoolean(userSubtree);
139:            }
140:
141:            public void setRoleSubtree(String roleSubtree) {
142:                this .roleSubtree = Boolean.getBoolean(roleSubtree);
143:            }
144:
145:            public void setContextFactory(String contextFactory) {
146:                this .contextFactory = contextFactory;
147:            }
148:
149:            public void setAuthentication(String authentication) {
150:                this .authentication = authentication;
151:            }
152:
153:            public void setConnectionUser(String connectionUser) {
154:                this .connectionUser = connectionUser;
155:            }
156:
157:            public void setConnectionPassword(String connectionPassword) {
158:                this .connectionPassword = connectionPassword;
159:            }
160:
161:            public void setConnectionURL(String connectionURL) {
162:                this .connectionURL = connectionURL;
163:            }
164:
165:            public void setProtocol(String protocol) {
166:                this .protocol = protocol;
167:            }
168:
169:            public void setReferrals(String referrals) {
170:                this .referrals = referrals;
171:            }
172:
173:            public void setUserBase(String userBase) {
174:                this .userBase = userBase;
175:            }
176:
177:            public void setUserSearch(String userSearch) {
178:                this .userSearch = userSearch;
179:                if (userSearch == null) {
180:                    userSearchFormat = null;
181:                } else {
182:                    userSearchFormat = new MessageFormat(userSearch);
183:                }
184:            }
185:
186:            public void setUserPassword(String userPassword) {
187:                this .userPassword = userPassword;
188:            }
189:
190:            public void setUserPattern(String userPattern) {
191:                this .userPattern = userPattern;
192:                if (userPattern == null) {
193:                    userPatternFormat = null;
194:                } else {
195:                    userPatternFormat = new MessageFormat(userPattern);
196:                }
197:            }
198:
199:            public void setRoleBase(String roleBase) {
200:                this .roleBase = roleBase;
201:            }
202:
203:            public void setUserRoleName(String userRoleName) {
204:                this .userRoleName = userRoleName;
205:            }
206:
207:            public void setRoleName(String roleName) {
208:                this .roleName = roleName;
209:            }
210:
211:            public void setRoleSearch(String roleSearch) {
212:                if (roleSearch == null) {
213:                    roleFormat = null;
214:                } else {
215:                    roleFormat = new MessageFormat(roleSearch);
216:                }
217:            }
218:
219:            public void logMap(Map options) {
220:                for (Iterator iterator = options.keySet().iterator(); iterator
221:                        .hasNext();) {
222:                    Object key = iterator.next();
223:                    log.debug("option: " + key + "=" + options.get(key));
224:                }
225:            }
226:
227:            /**
228:             * Return the Principal associated with the specified username and
229:             * credentials, if there is one; otherwise return <code>null</code>.
230:             * <p/>
231:             * If there are any errors with the JDBC connection, executing
232:             * the query or anything we return null (don't authenticate). This
233:             * event is also logged, and the connection will be closed so that
234:             * a subsequent request will automatically re-open it.
235:             *
236:             * @param username    Username of the Principal to look up
237:             * @param credentials Password or other credentials to use in
238:             *                    authenticating this username
239:             */
240:            public synchronized Subject authenticate(String username,
241:                    String credentials) throws AuthenticationException {
242:
243:                openConnectionCheckCredentials(username, credentials);
244:                return getSubject(username, credentials);
245:
246:            }
247:
248:            private void openConnectionCheckCredentials(String username,
249:                    String credentials) throws AuthenticationException {
250:
251:                try {
252:                    if (isAnonymousConnection()) {
253:
254:                        log.debug("Anonymous connection");
255:                        open();
256:                        checkCredentials(username, credentials);
257:
258:                    } else if (isFixedUserConnection()) {
259:
260:                        log.debug("Fixed user connection");
261:                        open(connectionUser, connectionPassword);
262:                        checkCredentials(username, credentials);
263:
264:                    } else {
265:
266:                        if (userPattern != null) {
267:                            String formattedUsername = MessageFormat.format(
268:                                    userPattern, new Object[] { username });
269:                            log.debug("Connection with " + formattedUsername
270:                                    + " user");
271:                            open(formattedUsername, credentials);
272:                        }
273:
274:                    }
275:                } finally {
276:                    closeContext();
277:                }
278:
279:            }
280:
281:            public void setOptions(Map options) {
282:                try {
283:                    BeanUtils.copyProperties(this , options);
284:                    if (this .debug >= 2) {
285:                        logMap(options);
286:                    }
287:                } catch (Exception e) {
288:                    // Don't care about not assignable fields
289:                }
290:
291:            }
292:
293:            private Subject getSubject(final String username, String credentials)
294:                    throws AuthenticationException {
295:                if (username == null || username.equals("")
296:                        || credentials == null || credentials.equals("")) {
297:                    throw new AuthenticationException(
298:                            JNDIAuthenticator.MESSAGE_AUTHENTICATION_FAILED_KEY);
299:                }
300:                Subject subject = new Subject();
301:                Principal principal = new Principal() {
302:
303:                    public String getName() {
304:                        return username;
305:                    }
306:                };
307:                subject.getPrincipals().add(principal);
308:                return subject;
309:            }
310:
311:            /**
312:             * Return a User object containing information about the user
313:             * with the specified username, if found in the directory;
314:             * otherwise return <code>null</code>.
315:             * <p/>
316:             * If the <code>userPassword</code> configuration attribute is
317:             * specified, the value of that attribute is retrieved from the
318:             * user's directory entry. If the <code>userRoleName</code>
319:             * configuration attribute is specified, all values of that
320:             * attribute are retrieved from the directory entry.
321:             *
322:             * @param username Username to be looked up
323:             * @throws javax.naming.NamingException if a directory server error occurs
324:             */
325:            protected User getUser(String username) throws NamingException {
326:
327:                User user = null;
328:
329:                // Get attributes to retrieve from user entry
330:                ArrayList list = new ArrayList();
331:                if (userPassword != null) {
332:                    list.add(userPassword);
333:                }
334:                if (userRoleName != null) {
335:                    list.add(userRoleName);
336:                }
337:                String[] attrIds = new String[list.size()];
338:                list.toArray(attrIds);
339:
340:                // Use pattern or search for user entry
341:                if (userPatternFormat != null) {
342:                    log("Finding user by pattern.");
343:                    user = getUserByPattern(username, attrIds);
344:                } else {
345:                    log("Finding user by search. Subtree is " + userSubtree);
346:                    user = getUserBySearch(username, attrIds);
347:                }
348:
349:                return user;
350:            }
351:
352:            /**
353:             * Use the <code>UserPattern</code> configuration attribute to
354:             * locate the directory entry for the user with the specified
355:             * username and return a User object; otherwise return
356:             * <code>null</code>.
357:             *
358:             * @param username The username
359:             * @param attrIds  String[]containing names of attributes to
360:             *                 retrieve.
361:             * @throws javax.naming.NamingException if a directory server error occurs
362:             */
363:            protected User getUserByPattern(String username, String[] attrIds)
364:                    throws NamingException {
365:
366:                if (debug >= 2) {
367:                    log("lookupUser(" + username + ")");
368:                }
369:
370:                if (username == null || userPatternFormat == null)
371:                    return null;
372:
373:                // Form the dn from the user pattern
374:                String dn = userPatternFormat.format(new String[] { username });
375:                if (debug >= 3) {
376:                    log("  dn=" + dn);
377:                }
378:
379:                // Return if no attributes to retrieve
380:                if (attrIds == null || attrIds.length == 0) {
381:                    return new User(username, dn, null, null);
382:                }
383:
384:                // Get required attributes from user entry
385:                Attributes attrs = null;
386:                try {
387:                    attrs = context.getAttributes(dn, attrIds);
388:                } catch (NameNotFoundException e) {
389:                    return null;
390:                }
391:                if (attrs == null)
392:                    return null;
393:
394:                // Retrieve value of userPassword
395:                String password = null;
396:                if (userPassword != null) {
397:                    password = getAttributeValue(userPassword, attrs);
398:                }
399:
400:                // Retrieve values of userRoleName attribute
401:                List roles = null;
402:                if (userRoleName != null) {
403:                    roles = addAttributeValues(userRoleName, attrs, roles);
404:                }
405:
406:                return new User(username, dn, password, roles);
407:            }
408:
409:            /**
410:             * Search the directory to return a User object containing
411:             * information about the user with the specified username, if
412:             * found in the directory; otherwise return <code>null</code>.
413:             *
414:             * @param username The username
415:             * @param attrIds  String[]containing names of attributes to retrieve.
416:             * @throws javax.naming.NamingException if a directory server error occurs
417:             */
418:            protected User getUserBySearch(String username, String[] attrIds)
419:                    throws NamingException {
420:
421:                if (username == null || userSearchFormat == null) {
422:                    if (username == null) {
423:                        log("getUserBySearch impossible - username is null.");
424:                    }
425:                    if (userSearchFormat == null) {
426:                        log("getUserBySearch impossible - userSearchFormat is null.");
427:                    }
428:                    return null;
429:                }
430:
431:                // Form the search filter
432:                String filter = userSearchFormat
433:                        .format(new String[] { username });
434:
435:                // Set up the search controls
436:                SearchControls constraints = new SearchControls();
437:
438:                if (userSubtree) {
439:                    constraints.setSearchScope(SearchControls.SUBTREE_SCOPE);
440:                } else {
441:                    constraints.setSearchScope(SearchControls.ONELEVEL_SCOPE);
442:                }
443:
444:                // Specify the attributes to be retrieved
445:                if (attrIds == null) {
446:                    attrIds = new String[0];
447:                }
448:                constraints.setReturningAttributes(attrIds);
449:
450:                if (debug > 3) {
451:                    log("  Searching for " + username);
452:                    log("  base: " + userBase + "  filter: " + filter);
453:                }
454:
455:                NamingEnumeration results = context.search(userBase, filter,
456:                        constraints);
457:
458:                // Fail if no entries found
459:                if (results == null || !results.hasMore()) {
460:                    if (debug > 2) {
461:                        log("  username not found");
462:                    }
463:                    return null;
464:                }
465:
466:                // Get result for the first entry found
467:                SearchResult result = (SearchResult) results.next();
468:
469:                // Check no further entries were found
470:                if (results.hasMore()) {
471:                    log("username " + username + " has multiple entries");
472:                    return null;
473:                }
474:
475:                // Get the entry's distinguished name
476:                NameParser parser = context.getNameParser("");
477:                Name contextName = parser.parse(context.getNameInNamespace());
478:                Name baseName = parser.parse(userBase);
479:                Name entryName = parser.parse(result.getName());
480:                Name name = contextName.addAll(baseName);
481:                name = name.addAll(entryName);
482:                String dn = name.toString();
483:
484:                if (debug > 2) {
485:                    log("  entry found for " + username + " with dn " + dn);
486:                }
487:
488:                // Get the entry's attributes
489:                Attributes attrs = result.getAttributes();
490:                if (attrs == null) {
491:                    return null;
492:                }
493:
494:                // Retrieve value of userPassword
495:                String password = null;
496:                if (userPassword != null) {
497:                    password = getAttributeValue(userPassword, attrs);
498:                }
499:
500:                // Retrieve values of userRoleName attribute
501:                List roles = null;
502:                if (userRoleName != null) {
503:                    roles = addAttributeValues(userRoleName, attrs, roles);
504:                }
505:
506:                return new User(username, dn, password, roles);
507:            }
508:
509:            public boolean isAnonymousConnection() {
510:                return userPattern == null && connectionUser == null;
511:            }
512:
513:            /**
514:             * Check credentials by binding to the directory as the user
515:             *
516:             * @param user        The User to be authenticated
517:             * @param credentials Authentication credentials
518:             * @throws javax.naming.NamingException if a directory server error occurs
519:             */
520:            protected boolean bindAsUser(User user, String credentials)
521:                    throws NamingException {
522:
523:                if (credentials == null || user == null) {
524:                    return false;
525:                }
526:
527:                String dn = user.dn;
528:                if (dn == null) {
529:                    return false;
530:                }
531:
532:                // Validate the credentials
533:                if (debug >= 3) {
534:                    log("  validating credentials by binding as the user");
535:                }
536:
537:                // Set up security environment to bind as the user
538:                context.addToEnvironment(Context.SECURITY_PRINCIPAL, dn);
539:                context.addToEnvironment(Context.SECURITY_CREDENTIALS,
540:                        credentials);
541:
542:                // Elicit an LDAP bind operation
543:                boolean validated = false;
544:                try {
545:                    if (debug > 2) {
546:                        log("  binding as " + dn);
547:                    }
548:                    context.getAttributes("", null);
549:                    validated = true;
550:                } catch (javax.naming.AuthenticationException e) {
551:                    if (debug > 2) {
552:                        log("  bind attempt failed");
553:                    }
554:                }
555:
556:                // Restore the original security environment
557:                if (connectionUser != null) {
558:                    context.addToEnvironment(Context.SECURITY_PRINCIPAL,
559:                            connectionUser);
560:                } else {
561:                    context.removeFromEnvironment(Context.SECURITY_PRINCIPAL);
562:                }
563:
564:                if (connectionPassword != null) {
565:                    context.addToEnvironment(Context.SECURITY_CREDENTIALS,
566:                            connectionPassword);
567:                } else {
568:                    context.removeFromEnvironment(Context.SECURITY_CREDENTIALS);
569:                }
570:
571:                return validated;
572:            }
573:
574:            /**
575:             * Return a List of roles associated with the given User.  Any
576:             * roles present in the user's directory entry are supplemented by
577:             * a directory search. If no roles are associated with this user,
578:             * a zero-length List is returned.
579:             *
580:             * @param user    The User to be checked
581:             * @throws javax.naming.NamingException if a directory server error occurs
582:             */
583:            public List getRoles(User user) throws NamingException {
584:
585:                if (user == null)
586:                    return null;
587:
588:                String dn = user.dn;
589:                String username = user.username;
590:
591:                if (dn == null || username == null)
592:                    return null;
593:
594:                if (debug >= 2) {
595:                    log("  getRoles(" + dn + ")");
596:                }
597:
598:                // Start with roles retrieved from the user entry
599:                List list = user.roles;
600:                if (list == null) {
601:                    list = new ArrayList();
602:                }
603:
604:                // Are we configured to do role searches?
605:                if (roleFormat == null || roleName == null)
606:                    return list;
607:
608:                // Set up parameters for an appropriate search
609:                String filter = roleFormat
610:                        .format(new String[] { dn, username });
611:                SearchControls controls = new SearchControls();
612:                if (roleSubtree) {
613:                    controls.setSearchScope(SearchControls.SUBTREE_SCOPE);
614:                } else {
615:                    controls.setSearchScope(SearchControls.ONELEVEL_SCOPE);
616:                }
617:                controls.setReturningAttributes(new String[] { roleName });
618:
619:                // Perform the configured search and process the results
620:                if (debug >= 3) {
621:                    log("  Searching role base '" + roleBase
622:                            + "' for attribute '" + roleName + "'");
623:                    log("  With filter expression '" + filter + "'");
624:                }
625:                NamingEnumeration results = context.search(roleBase, filter,
626:                        controls);
627:                if (results == null) {
628:                    return list; // Should never happen, but just in case ...
629:                }
630:                while (results.hasMore()) {
631:                    SearchResult result = (SearchResult) results.next();
632:                    Attributes attrs = result.getAttributes();
633:                    if (attrs == null) {
634:                        continue;
635:                    }
636:                    list = addAttributeValues(roleName, attrs, list);
637:                }
638:
639:                // Return the augmented list of roles
640:                if (debug >= 2) {
641:                    log("  Returning " + list.size() + " roles");
642:                    for (int i = 0; i < list.size(); i++) {
643:                        log("  Found role " + list.get(i));
644:                    }
645:                }
646:
647:                return list;
648:            }
649:
650:            /**
651:             * Return a String representing the value of the specified attribute.
652:             *
653:             * @param attrId Attribute name
654:             * @param attrs  Attributes containing the required value
655:             * @throws javax.naming.NamingException if a directory server error occurs
656:             */
657:            private String getAttributeValue(String attrId, Attributes attrs)
658:                    throws NamingException {
659:
660:                if (debug >= 3) {
661:                    log("  retrieving attribute " + attrId);
662:                }
663:
664:                if (attrId == null || attrs == null) {
665:                    return null;
666:                }
667:
668:                Attribute attr = attrs.get(attrId);
669:                if (attr == null)
670:                    return null;
671:
672:                Object value = attr.get();
673:                if (value == null)
674:                    return null;
675:                String valueString = null;
676:                if (value instanceof  byte[]) {
677:                    valueString = new String((byte[]) value);
678:                } else {
679:                    valueString = value.toString();
680:                }
681:
682:                return valueString;
683:            }
684:
685:            /**
686:             * Add values of a specified attribute to a list
687:             *
688:             * @param attrId Attribute name
689:             * @param attrs  Attributes containing the new values
690:             * @param values ArrayList containing values found so far
691:             * @throws javax.naming.NamingException if a directory server error occurs
692:             */
693:            private List addAttributeValues(String attrId, Attributes attrs,
694:                    List values) throws NamingException {
695:
696:                if (debug >= 3) {
697:                    log("  retrieving values for attribute " + attrId);
698:                }
699:                if (attrId == null || attrs == null) {
700:                    return null;
701:                }
702:                if (values == null) {
703:                    values = new ArrayList();
704:                }
705:                Attribute attr = attrs.get(attrId);
706:                if (attr == null) {
707:                    return null;
708:                }
709:                NamingEnumeration e = attr.getAll();
710:                while (e.hasMore()) {
711:                    String value = (String) e.next();
712:                    values.add(value);
713:                }
714:                return values;
715:            }
716:
717:            /**
718:             * Create our directory context configuration.
719:             *
720:             * @return java.util.Hashtable the configuration for the directory context.
721:             */
722:            protected Hashtable getDirectoryContextEnvironment(String username,
723:                    String credentials) {
724:
725:                Hashtable env = new Hashtable();
726:
727:                setAttributeIfValueNotNull(env, Context.PROVIDER_URL,
728:                        connectionURL);
729:                setAttributeIfValueNotNull(env,
730:                        Context.INITIAL_CONTEXT_FACTORY, contextFactory);
731:                setAttributeIfValueNotNull(env, Context.SECURITY_PRINCIPAL,
732:                        username);
733:                setAttributeIfValueNotNull(env, Context.SECURITY_CREDENTIALS,
734:                        credentials);
735:                setAttributeIfValueNotNull(env,
736:                        Context.SECURITY_AUTHENTICATION, authentication);
737:                setAttributeIfValueNotNull(env, Context.SECURITY_PROTOCOL,
738:                        protocol);
739:                setAttributeIfValueNotNull(env, Context.REFERRAL, referrals);
740:
741:                return env;
742:            }
743:
744:            private void setAttributeIfValueNotNull(Hashtable env,
745:                    String attribute, String value) {
746:                if (value != null)
747:                    env.put(attribute, value);
748:            }
749:
750:            /**
751:             * Check whether the given User can be authenticated with the
752:             * given credentials. If the <code>userPassword</code>
753:             * configuration attribute is specified, the credentials
754:             * previously retrieved from the directory are compared explicitly
755:             * with those presented by the user. Otherwise the presented
756:             * credentials are checked by binding to the directory as the
757:             * user.
758:             *
759:             * @param userName    The UserName to be authenticated
760:             * @param credentials The credentials presented by the user
761:             * @throws com.sabre.security.jndi.AuthenticationException if a directory server error occurs
762:             *                                      if authentication fails
763:             */
764:            public void checkCredentials(String userName, String credentials)
765:                    throws com.sabre.security.jndi.AuthenticationException {
766:
767:                boolean validated = false;
768:                try {
769:                    User user = this .getUser(userName);
770:
771:                    if (userPassword == null) {
772:                        validated = bindAsUser(user, credentials);
773:                        if (user != null) {
774:                            log("bindAsUser(user, credentials) '"
775:                                    + user.username + "'");
776:                        } else {
777:                            log("bindAsUser(user, credentials)");
778:                        }
779:                    } else {
780:                        validated = compareCredentials(user, credentials);
781:                        if (user != null) {
782:                            log("compareCredentials(user, credentials) '"
783:                                    + user.username + "'");
784:                        } else {
785:                            log("compareCredentials(user, credentials)");
786:                        }
787:                    }
788:
789:                    if (debug >= 2) {
790:                        if (user != null) {
791:                            log("jndiRealm.authenticate"
792:                                    + (validated ? "Success" : "Failure" + " "
793:                                            + user.username));
794:                        } else {
795:                            log("jndiRealm.authenticate"
796:                                    + (validated ? "Success" : "Failure"));
797:                        }
798:                    }
799:                } catch (CommunicationException ex) {
800:                    log("jndiRealm.exception", ex);
801:                    closeContext();
802:                    throw new com.sabre.security.jndi.AuthenticationException(
803:                            JNDIAuthenticator.MESSAGE_COMMUNICATION_ERROR_KEY);
804:                } catch (NamingException ne) {
805:                    throw new com.sabre.security.jndi.AuthenticationException(
806:                            JNDIAuthenticator.MESSAGE_AUTHENTICATION_FAILED_KEY);
807:                }
808:                if (!validated) {
809:                    throw new com.sabre.security.jndi.AuthenticationException(
810:                            JNDIAuthenticator.MESSAGE_AUTHENTICATION_FAILED_KEY);
811:                }
812:            }
813:
814:            /**
815:             * Check whether the credentials presented by the user match those
816:             * retrieved from the directory.
817:             *
818:             * @param info        The User to be authenticated
819:             * @param credentials Authentication credentials
820:             * @throws javax.naming.NamingException if a directory server error occurs
821:             */
822:            protected boolean compareCredentials(User info, String credentials)
823:                    throws NamingException {
824:
825:                if (info == null || credentials == null) {
826:                    return false;
827:                }
828:
829:                String password = info.password;
830:                if (password == null) {
831:                    return false;
832:                }
833:
834:                // Validate the credentials specified by the user
835:                if (debug >= 3) {
836:                    log("  validating credentials");
837:                }
838:
839:                boolean validated = false;
840:                if (hasMessageDigest()) {
841:                    // Hex hashes should be compared case-insensitive
842:                    if (Base64.isBase64(password.substring(5))) {
843:                        password = HexUtils.convert(Base64.decode(password
844:                                .substring(5).getBytes()));
845:                    }
846:                    validated = digest(credentials).equalsIgnoreCase(password);
847:                } else {
848:                    validated = digest(credentials).equals(password);
849:                }
850:                return validated;
851:            }
852:
853:            protected String digest(String credentials) {
854:                // If no MessageDigest instance is specified, return unchanged
855:                if (!hasMessageDigest()) {
856:                    return credentials;
857:                }
858:
859:                // Digest the user credentials and return as hexadecimal
860:                synchronized (this ) {
861:                    try {
862:                        messageDigest.reset();
863:                        messageDigest.update(credentials.getBytes());
864:                        return HexUtils.convert(messageDigest.digest());
865:                    } catch (Exception e) {
866:                        log("realmBase.digest", e);
867:                        return credentials;
868:                    }
869:                }
870:            }
871:
872:            /**
873:             * Close any open connection to the directory server for this Realm.
874:             */
875:            public void closeContext() {
876:
877:                // Do nothing if there is no opened connection
878:                if (context == null) {
879:                    return;
880:                }
881:
882:                // Close our opened connection
883:                try {
884:                    if (debug >= 1) {
885:                        log("Closing directory context");
886:                    }
887:                    context.close();
888:                } catch (NamingException e) {
889:                    log("jndiRealm.close", e);
890:                }
891:                //      this.context = null;
892:
893:            }
894:
895:            /**
896:             * Open (if necessary) and return a connection to the configured
897:             * directory server for this Realm.
898:             *
899:             * @throws com.sabre.security.jndi.AuthenticationException if a directory server error occurs
900:             */
901:            public void open()
902:                    throws com.sabre.security.jndi.AuthenticationException {
903:
904:                open(null, null);
905:
906:            }
907:
908:            public void open(String username, String credentials)
909:                    throws com.sabre.security.jndi.AuthenticationException {
910:
911:                try {
912:
913:                    // Ensure that we have a directory context available
914:                    context = new InitialDirContext(
915:                            getDirectoryContextEnvironment(username,
916:                                    credentials));
917:
918:                } catch (NamingException e) {
919:
920:                    try {
921:
922:                        // log the first exception.
923:                        log("jndiRealm.exception", e);
924:
925:                        // Try connecting once more.
926:                        context = new InitialDirContext(
927:                                getDirectoryContextEnvironment(username,
928:                                        credentials));
929:
930:                    } catch (CommunicationException ex) {
931:                        log("jndiRealm.exception", ex);
932:                        closeContext();
933:                        throw new com.sabre.security.jndi.AuthenticationException(
934:                                JNDIAuthenticator.MESSAGE_COMMUNICATION_ERROR_KEY);
935:                    } catch (NamingException ne) {
936:                        throw new com.sabre.security.jndi.AuthenticationException(
937:                                JNDIAuthenticator.MESSAGE_AUTHENTICATION_FAILED_KEY);
938:                    }
939:                }
940:
941:            }
942:
943:            public boolean isFixedUserConnection() {
944:                return connectionUser != null && connectionPassword != null;
945:            }
946:
947:            private boolean hasMessageDigest() {
948:                return messageDigest != null;
949:            }
950:
951:            private void log(String s) {
952:                log.info(s);
953:            }
954:
955:            private void log(String s, Throwable ex) {
956:                log.info(s, ex);
957:            }
958:
959:        }
www.java2java.com | Contact Us
Copyright 2009 - 12 Demo Source and Support. All rights reserved.
All other trademarks are property of their respective owners.