Source Code Cross Referenced for LDAPAuthenticationSchemeImpl.java in  » Database-DBMS » db-derby-10.2 » org » apache » derby » impl » jdbc » authentication » 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 » Database DBMS » db derby 10.2 » org.apache.derby.impl.jdbc.authentication 
Source Cross Referenced  Class Diagram Java Document (Java Doc) 


001:        /*
002:
003:           Derby - Class org.apache.derby.impl.jdbc.authentication.LDAPAuthenticationSchemeImpl
004:
005:           Licensed to the Apache Software Foundation (ASF) under one or more
006:           contributor license agreements.  See the NOTICE file distributed with
007:           this work for additional information regarding copyright ownership.
008:           The ASF licenses this file to you under the Apache License, Version 2.0
009:           (the "License"); you may not use this file except in compliance with
010:           the License.  You may obtain a copy of the License at
011:
012:              http://www.apache.org/licenses/LICENSE-2.0
013:
014:           Unless required by applicable law or agreed to in writing, software
015:           distributed under the License is distributed on an "AS IS" BASIS,
016:           WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
017:           See the License for the specific language governing permissions and
018:           limitations under the License.
019:
020:         */
021:
022:        package org.apache.derby.impl.jdbc.authentication;
023:
024:        import org.apache.derby.iapi.reference.MessageId;
025:        import org.apache.derby.iapi.services.monitor.Monitor;
026:        import org.apache.derby.iapi.error.StandardException;
027:        import org.apache.derby.iapi.services.i18n.MessageService;
028:        import org.apache.derby.iapi.jdbc.AuthenticationService;
029:
030:        import org.apache.derby.authentication.UserAuthenticator;
031:
032:        import org.apache.derby.iapi.services.sanity.SanityManager;
033:        import org.apache.derby.iapi.util.StringUtil;
034:
035:        import javax.naming.*;
036:        import javax.naming.directory.*;
037:
038:        import java.util.Properties;
039:        import java.sql.SQLException;
040:
041:        /**
042:         * This is the Cloudscape LDAP authentication scheme implementation.
043:         *
044:         * JNDI system/environment properties can be set at the database
045:         * level as database properties. They will be picked-up and set in
046:         * the JNDI initial context if any are found.
047:         *
048:         * We do connect first to the LDAP server in order to retrieve the
049:         * user's distinguished name (DN) and then we reconnect and try to
050:         * authenticate with the user's DN and passed-in password.
051:         *
052:         * In 2.0 release, we first connect to do a search (user full DN lookup).
053:         * This initial lookup can be done through anonymous bind or using special
054:         * LDAP search credentials that the user may have configured on the
055:         * LDAP settings for the database or the system.
056:         * It is a typical operation with LDAP servers where sometimes it is
057:         * hard to tell/guess in advance a users' full DN's.
058:         *
059:         * NOTE: In a future release, we will cache/maintain the user DN within
060:         * the the cloudscape database or system to avoid the initial lookup.
061:         * Also note that LDAP search/retrieval operations are usually very fast.
062:         *
063:         * The default LDAP url is ldap:/// (ldap://localhost:389/)
064:         *
065:         * @see org.apache.derby.authentication.UserAuthenticator 
066:         *
067:         */
068:
069:        public final class LDAPAuthenticationSchemeImpl extends
070:                JNDIAuthenticationSchemeBase {
071:            private static final String dfltLDAPURL = "ldap://";
072:
073:            private String searchBaseDN;
074:
075:            private String leftSearchFilter; // stick in uid in between
076:            private String rightSearchFilter;
077:            private boolean useUserPropertyAsDN;
078:
079:            // Search Auth DN & Password if anonymous search not allowed
080:            private String searchAuthDN;
081:            private String searchAuthPW;
082:            // we only want the user's full DN in return
083:            private static final String[] attrDN = { "dn" };;
084:
085:            //
086:            // Cloudscape LDAP Configuration properties
087:            //
088:            private static final String LDAP_SEARCH_BASE = "derby.authentication.ldap.searchBase";
089:            private static final String LDAP_SEARCH_FILTER = "derby.authentication.ldap.searchFilter";
090:            private static final String LDAP_SEARCH_AUTH_DN = "derby.authentication.ldap.searchAuthDN";
091:            private static final String LDAP_SEARCH_AUTH_PW = "derby.authentication.ldap.searchAuthPW";
092:            private static final String LDAP_LOCAL_USER_DN = "derby.user";
093:            private static final String LDAP_SEARCH_FILTER_USERNAME = "%USERNAME%";
094:
095:            public LDAPAuthenticationSchemeImpl(JNDIAuthenticationService as,
096:                    Properties dbProperties) {
097:
098:                super (as, dbProperties);
099:            }
100:
101:            /**
102:             * Authenticate the passed-in user's credentials.
103:             *
104:             * We authenticate against a LDAP Server.
105:             *
106:             *
107:             * @param userName		The user's name used to connect to JBMS system
108:             * @param userPassword	The user's password used to connect to JBMS system
109:             * @param databaseName	The database which the user wants to connect to.
110:             * @param info			Additional jdbc connection info.
111:             */
112:            public boolean authenticateUser(String userName,
113:                    String userPassword, String databaseName, Properties info)
114:                    throws java.sql.SQLException {
115:                if (((userName == null) || (userName.length() == 0))
116:                        || ((userPassword == null) || (userPassword.length() == 0))) {
117:                    // We don't tolerate 'guest' user for now as well as
118:                    // null password.
119:                    // If a null password is passed upon authenticating a user
120:                    // through LDAP, then the LDAP server might consider this as
121:                    // anonymous bind and therefore no authentication will be done
122:                    // at all.
123:                    return false;
124:                }
125:
126:                Exception e;
127:                try {
128:                    Properties env = (Properties) initDirContextEnv.clone();
129:                    String userDN = null;
130:                    //
131:                    // Retrieve the user's DN (Distinguished Name)
132:                    // If we're asked to look it up locally, do it first
133:                    // and if we don't find it, we go against the LDAP
134:                    // server for a look-up (search)
135:                    //
136:                    if (useUserPropertyAsDN)
137:                        userDN = authenticationService
138:                                .getProperty(org.apache.derby.iapi.reference.Property.USER_PROPERTY_PREFIX);
139:
140:                    if (userDN == (String) null) {
141:                        userDN = getDNFromUID(userName);
142:                    }
143:
144:                    if (SanityManager.DEBUG) {
145:                        if (SanityManager
146:                                .DEBUG_ON(AuthenticationServiceBase.AuthenticationTrace)) {
147:                            SanityManager
148:                                    .DEBUG(
149:                                            AuthenticationServiceBase.AuthenticationTrace,
150:                                            "User DN = [" + userDN + "]\n");
151:                        }
152:                    }
153:
154:                    env.put(Context.SECURITY_PRINCIPAL, userDN);
155:                    env.put(Context.SECURITY_CREDENTIALS, userPassword);
156:
157:                    // Connect & authenticate (bind) to the LDAP server now
158:
159:                    // it is happening right here
160:                    DirContext ctx = new InitialDirContext(env);
161:
162:                    // if the above was successfull, then username and
163:                    // password must be correct
164:                    return true;
165:
166:                } catch (javax.naming.AuthenticationException jndiae) {
167:                    return false;
168:
169:                } catch (javax.naming.NameNotFoundException jndinnfe) {
170:                    return false;
171:
172:                } catch (javax.naming.NamingException jndine) {
173:                    e = jndine;
174:                }
175:
176:                throw getLoginSQLException(e);
177:            }
178:
179:            /**
180:             * This method basically tests and sets default/expected JNDI properties
181:             * for the JNDI provider scheme (here it is LDAP).
182:             *
183:             **/
184:            protected void setJNDIProviderProperties() {
185:
186:                // check if we're told to use a different initial context factory
187:                if (initDirContextEnv
188:                        .getProperty(Context.INITIAL_CONTEXT_FACTORY) == (String) null) {
189:                    initDirContextEnv.put(Context.INITIAL_CONTEXT_FACTORY,
190:                            "com.sun.jndi.ldap.LdapCtxFactory");
191:                }
192:
193:                // retrieve LDAP server name/port# and construct LDAP url
194:                if (initDirContextEnv.getProperty(Context.PROVIDER_URL) == (String) null) {
195:                    // Now we construct the LDAP url and expect to find the LDAP Server
196:                    // name.
197:                    //
198:                    String ldapServer = authenticationService
199:                            .getProperty(org.apache.derby.iapi.reference.Property.AUTHENTICATION_SERVER_PARAMETER);
200:
201:                    if (ldapServer == (String) null) {
202:
203:                        // we do expect a LDAP Server name to be configured
204:                        Monitor
205:                                .logTextMessage(
206:                                        MessageId.AUTH_NO_LDAP_HOST_MENTIONED,
207:                                        org.apache.derby.iapi.reference.Property.AUTHENTICATION_SERVER_PARAMETER);
208:
209:                        this .providerURL = dfltLDAPURL + "/";
210:
211:                    } else {
212:
213:                        if (ldapServer.startsWith(dfltLDAPURL)
214:                                || ldapServer.startsWith("ldaps://"))
215:                            this .providerURL = ldapServer;
216:                        else if (ldapServer.startsWith("//"))
217:                            this .providerURL = "ldap:" + ldapServer;
218:                        else
219:                            this .providerURL = dfltLDAPURL + ldapServer;
220:                    }
221:                    initDirContextEnv.put(Context.PROVIDER_URL, providerURL);
222:                }
223:
224:                // check if we should we use a particular authentication method
225:                // we assume the ldap server supports this authentication method
226:                // (Netscape DS 3.1.1 does not support CRAM-MD5 for instance)
227:                if (initDirContextEnv
228:                        .getProperty(Context.SECURITY_AUTHENTICATION) == (String) null) {
229:                    // set the default to be clear userName/Password as not of all the
230:                    // LDAP server(s) support CRAM-MD5 (especially ldap v2 ones)
231:                    // Netscape Directory Server 3.1.1 does not support CRAM-MD5
232:                    // (told by Sun JNDI engineering). Netscape DS 4.0 allows SASL
233:                    // plug-ins to be installed and that can be used as authentication
234:                    // method.
235:                    //
236:                    initDirContextEnv.put(Context.SECURITY_AUTHENTICATION,
237:                            "simple");
238:                }
239:
240:                // Retrieve and set the search base (root) DN to use on the ldap
241:                // server.
242:                String ldapSearchBase = authenticationService
243:                        .getProperty(LDAP_SEARCH_BASE);
244:                if (ldapSearchBase != (String) null)
245:                    this .searchBaseDN = ldapSearchBase;
246:                else
247:                    this .searchBaseDN = "";
248:
249:                // retrieve principal and credentials for the search bind as the
250:                // user may not want to allow anonymous binds (for searches)
251:                this .searchAuthDN = authenticationService
252:                        .getProperty(LDAP_SEARCH_AUTH_DN);
253:                this .searchAuthPW = authenticationService
254:                        .getProperty(LDAP_SEARCH_AUTH_PW);
255:
256:                //
257:                // Construct the LDAP search filter:
258:                //
259:                // If we were told to use a special search filther, we do so;
260:                // otherwise we use our default search filter.
261:                // The user may have set the search filter 3 different ways:
262:                //
263:                // - if %USERNAME% was found in the search filter, then we
264:                // will substitute this with the passed-in uid at runtime.
265:                //
266:                // - if "derby.user" is the search filter value, then we
267:                // will assume the user's DN can be found in the system or
268:                // database property "derby.user.<uid>" . If the property
269:                // does not exist, then we will do a normal lookup with our
270:                // default search filter; otherwise we will perform an
271:                // authenticated bind to the LDAP server using the found DN.
272:                //
273:                // - if neither of the 2 previous values were found, then we use
274:                // our default search filter and we will substitute insert the
275:                // uid passed at runtime into our default search filter.
276:                //
277:                String searchFilterProp = authenticationService
278:                        .getProperty(LDAP_SEARCH_FILTER);
279:
280:                if (searchFilterProp == (String) null) {
281:                    // use our default search filter
282:                    this .leftSearchFilter = "(&(objectClass=inetOrgPerson)(uid=";
283:                    this .rightSearchFilter = "))";
284:
285:                } else if (StringUtil.SQLEqualsIgnoreCase(searchFilterProp,
286:                        LDAP_LOCAL_USER_DN)) {
287:
288:                    // use local user DN in derby.user.<uid>
289:                    this .leftSearchFilter = "(&(objectClass=inetOrgPerson)(uid=";
290:                    this .rightSearchFilter = "))";
291:                    this .useUserPropertyAsDN = true;
292:
293:                } else if (searchFilterProp
294:                        .indexOf(LDAP_SEARCH_FILTER_USERNAME) != -1) {
295:
296:                    // user has set %USERNAME% in the search filter
297:                    this .leftSearchFilter = searchFilterProp.substring(0,
298:                            searchFilterProp
299:                                    .indexOf(LDAP_SEARCH_FILTER_USERNAME));
300:                    this .rightSearchFilter = searchFilterProp
301:                            .substring(searchFilterProp
302:                                    .indexOf(LDAP_SEARCH_FILTER_USERNAME)
303:                                    + (int) LDAP_SEARCH_FILTER_USERNAME
304:                                            .length());
305:
306:                } else { // add this search filter to ours
307:
308:                    // complement this search predicate to ours
309:                    this .leftSearchFilter = "(&(" + searchFilterProp + ")"
310:                            + "(objectClass=inetOrgPerson)(uid=";
311:                    this .rightSearchFilter = "))";
312:
313:                }
314:
315:                if (SanityManager.DEBUG) {
316:                    if (SanityManager
317:                            .DEBUG_ON(AuthenticationServiceBase.AuthenticationTrace)) {
318:
319:                        java.io.PrintWriter iDbgStream = SanityManager
320:                                .GET_DEBUG_STREAM();
321:
322:                        iDbgStream
323:                                .println("\n\n+ LDAP Authentication Configuration:\n"
324:                                        + "   - provider URL ["
325:                                        + this .providerURL
326:                                        + "]\n"
327:                                        + "   - search base ["
328:                                        + this .searchBaseDN
329:                                        + "]\n"
330:                                        + "   - search filter to be ["
331:                                        + this .leftSearchFilter
332:                                        + "<uid>"
333:                                        + this .rightSearchFilter
334:                                        + "]\n"
335:                                        + "   - use local DN ["
336:                                        + (useUserPropertyAsDN ? "true"
337:                                                : "false") + "]\n");
338:                    }
339:                }
340:
341:                if (SanityManager.DEBUG) {
342:                    if (SanityManager
343:                            .DEBUG_ON(AuthenticationServiceBase.AuthenticationTrace)) {
344:                        try {
345:                            initDirContextEnv.put(
346:                                    "com.sun.naming.ldap.trace.ber",
347:                                    new java.io.FileOutputStream(
348:                                            "CloudLDAP.out"));
349:                        } catch (java.io.IOException ie) {
350:                        }
351:                    }
352:                }
353:            }
354:
355:            /**
356:             * Search for the full user's DN in the LDAP server.
357:             * LDAP server bind may or not be anonymous.
358:             *
359:             * If the admin does not want us to do anonymous bind/search, then we
360:             * must have been given principal/credentials in order to successfully
361:             * bind to perform the user's DN search.
362:             *
363:             * @exception NamingException if could not retrieve the user DN.
364:             **/
365:            private String getDNFromUID(String uid)
366:                    throws javax.naming.NamingException {
367:                //
368:                // We bind to the LDAP server here
369:                // Note that this bind might be anonymous (if anonymous searches
370:                // are allowed in the LDAP server, or authenticated if we were
371:                // told/configured to.
372:                //
373:                Properties env = null;
374:                if (this .searchAuthDN != (String) null) {
375:                    env = (Properties) initDirContextEnv.clone();
376:                    env.put(Context.SECURITY_PRINCIPAL, this .searchAuthDN);
377:                    env.put(Context.SECURITY_CREDENTIALS, this .searchAuthPW);
378:                } else
379:                    env = initDirContextEnv;
380:
381:                DirContext ctx = new InitialDirContext(env);
382:
383:                // Construct Search Filter
384:                SearchControls ctls = new SearchControls();
385:                // Set-up a LDAP subtree search scope
386:                ctls.setSearchScope(SearchControls.SUBTREE_SCOPE);
387:
388:                // Just retrieve the DN
389:                ctls.setReturningAttributes(attrDN);
390:
391:                String searchFilter = this .leftSearchFilter + uid
392:                        + this .rightSearchFilter;
393:                NamingEnumeration results = ctx.search(searchBaseDN,
394:                        searchFilter, ctls);
395:
396:                // If we did not find anything then login failed
397:                if (results == null || !results.hasMore())
398:                    throw new NameNotFoundException();
399:
400:                SearchResult result = (SearchResult) results.next();
401:
402:                if (results.hasMore()) {
403:                    // This is a login failure as we cannot assume the first one
404:                    // is the valid one.
405:                    if (SanityManager.DEBUG) {
406:                        if (SanityManager
407:                                .DEBUG_ON(AuthenticationServiceBase.AuthenticationTrace)) {
408:
409:                            java.io.PrintWriter iDbgStream = SanityManager
410:                                    .GET_DEBUG_STREAM();
411:
412:                            iDbgStream
413:                                    .println(" - LDAP Authentication request failure: "
414:                                            + "search filter ["
415:                                            + searchFilter
416:                                            + "]"
417:                                            + ", retrieve more than one occurence in "
418:                                            + "LDAP server ["
419:                                            + this .providerURL + "]");
420:                        }
421:                    }
422:                    throw new NameNotFoundException();
423:                }
424:
425:                NameParser parser = ctx.getNameParser(searchBaseDN);
426:                Name userDN = parser.parse(searchBaseDN);
427:
428:                if (userDN == (Name) null)
429:                    // This should not happen in theory
430:                    throw new NameNotFoundException();
431:                else
432:                    userDN.addAll(parser.parse(result.getName()));
433:
434:                // Return the full user's DN
435:                return userDN.toString();
436:            }
437:        }
www.java2java.com | Contact Us
Copyright 2009 - 12 Demo Source and Support. All rights reserved.
All other trademarks are property of their respective owners.