Docjar: A Java Source and Docuemnt Enginecom.*    java.*    javax.*    org.*    all    new    plug-in

Quick Search    Search Deep

Source code: com/xpn/xwiki/user/impl/LDAP/LDAPAuthServiceImpl.java


1   package com.xpn.xwiki.user.impl.LDAP;
2   
3   import com.xpn.xwiki.user.api.XWikiAuthService;
4   import com.xpn.xwiki.user.api.XWikiUser;
5   import com.xpn.xwiki.user.impl.xwiki.*;
6   import com.xpn.xwiki.XWikiContext;
7   import com.xpn.xwiki.XWikiException;
8   import com.xpn.xwiki.XWiki;
9   import com.xpn.xwiki.objects.classes.BaseClass;
10  import com.xpn.xwiki.objects.BaseObject;
11  import com.xpn.xwiki.doc.XWikiDocument;
12  import com.novell.ldap.*;
13  import com.novell.ldap.util.Base64;
14  import org.apache.commons.logging.Log;
15  import org.apache.commons.logging.LogFactory;
16  import org.apache.commons.lang.StringUtils;
17  import org.apache.ecs.xhtml.fieldset;
18  import org.securityfilter.authenticator.Authenticator;
19  import org.securityfilter.config.SecurityConfig;
20  import org.securityfilter.filter.SecurityRequestWrapper;
21  import org.securityfilter.realm.SimplePrincipal;
22  
23  import javax.servlet.http.HttpServletRequest;
24  import javax.servlet.http.HttpServletResponse;
25  import java.security.Principal;
26  import java.io.IOException;
27  import java.io.UnsupportedEncodingException;
28  import java.util.*;
29  import java.text.Format;
30  import java.text.MessageFormat;
31  
32  /**
33   * Created by IntelliJ IDEA.
34   * User: Alex
35   * Date: 18 avr. 2005
36   * Time: 16:18:50
37   * To change this template use File | Settings | File Templates.
38   */
39  public class LDAPAuthServiceImpl extends XWikiAuthServiceImpl {
40      private static final Log log = LogFactory.getLog(LDAPAuthServiceImpl.class);
41  
42      public Principal authenticate(String username, String password, XWikiContext context) throws XWikiException {
43          Principal principal = null;
44  
45          if ((username==null)||(username.trim().equals("")))
46              return null;
47  
48          if ((password==null)||(password.trim().equals("")))
49              return null;
50  
51          String superadmin = <font color=red>"superadmin"font>;
52          if (username.equals(superadmin)) {
53              String superadminpassword = context.getWiki().Param(<font color=red>"xwiki.superadminpassword"font>);
54              if ((superadminpassword!=null)&&(superadminpassword.equals(password))) {
55                  principal = new SimplePrincipal(<font color=red>"XWiki.superadmin"font>);
56                  return principal;
57              } else {
58                  return null;
59              }
60          }
61  
62          // If we have the context then we are using direct mode
63          // then we should specify the database
64          // This is needed for virtual mode to work
65          if (context!=null) {
66              String susername = username;
67              int i = username.indexOf(<font color=red>"."font>);
68              if (i!=-1)
69                  susername = username.substring(i+1);
70  
71             String DN = getLDAP_DN(susername, context);
72  
73             if (DN != null && DN.length()!=0)
74             {
75                 if (checkDNPassword(DN, susername, password, context))
76                 {
77                     principal = GetUserPrincipal(susername, context);
78                 }
79             }
80             else
81              {
82                 HashMap attributes = new HashMap();
83                 if (checkUserPassword(susername, password, attributes, context))
84                 {
85                     principal = GetUserPrincipal(susername, context);
86                     if (principal == null && attributes.size() > 0)
87                     {
88                         CreateUserFromLDAP(susername, attributes, context);
89                         principal = GetUserPrincipal(susername, context);
90                     }
91                 }
92              }
93          }
94          return principal;
95      }
96  
97      private void CreateUserFromLDAP(String susername, HashMap attributes, XWikiContext context) throws XWikiException {
98          String ldapFieldMapping = getParam(<font color=red>"ldap_fields_mapping"font>,context);
99          if (ldapFieldMapping != null && ldapFieldMapping.length() > 0)
100         {
101             String[] fields = ldapFieldMapping.split(<font color=red>","font>);
102             BaseClass bclass = context.getWiki().getUserClass(context);
103             BaseObject bobj = new BaseObject();
104             bobj.setClassName(bclass.getName());
105             String name = null;
106             String fullwikiname = null;
107             for(int i = 0; i < fields.length; i++ )
108             {
109                 String[] field = fields[i].split(<font color=red>"="font>);
110                 if (2 == field.length)
111                 {
112                    String fieldName = field[0];
113                    if (attributes.containsKey(field[1]))
114                    {
115                        String fieldValue;
116                        fieldValue = (String)attributes.get(field[1]);
117                        if (fieldName.equals(<font color=red>"name"font>))
118                        {
119                            name = fieldValue;
120                            fullwikiname = <font color=red>"XWiki."font> + name;
121                            bobj.setName(fullwikiname);
122                        }
123                        else
124                        {
125                            bobj.setStringValue(fieldName, fieldValue);
126                        }
127                    }
128                 }
129             }
130 
131             if (name != null && name.length() > 0)
132             {
133                 XWikiDocument doc = context.getWiki().getDocument(fullwikiname, context);
134                 doc.setParent("");
135                 doc.addObject(bclass.getName(), bobj);
136                 doc.setContent(<font color=red>"#includeForm(\"XWiki.XWikiUserTemplate\")"font>);
137 
138                 context.getWiki().ProtectUserPage(context, fullwikiname, <font color=red>"edit"font>, doc);
139 
140                 context.getWiki().saveDocument(doc, null, context);
141 
142                 context.getWiki().SetUserDefaultGroup(context, fullwikiname);
143             }
144         }
145     }
146 
147     protected Principal GetUserPrincipal(String susername, XWikiContext context) {
148         Principal principal = null;
149 
150         // First we check in the local database
151         try {
152             String user = findUser(susername, context);
153             if (user!=null) {
154                 principal = new SimplePrincipal(user);
155             }
156         } catch (Exception e) {}
157 
158         if (context.isVirtual()) {
159             if (principal==null) {
160                 // Then we check in the main database
161                 String db = context.getDatabase();
162                 try {
163                     context.setDatabase(context.getWiki().getDatabase());
164                     try {
165                         String user = findUser(susername, context);
166                         if (user!=null)
167                             principal = new SimplePrincipal(context.getDatabase() + <font color=red>":"font> + user);
168                     } catch (Exception e) {}
169                 } finally {
170                     context.setDatabase(db);
171                 }
172             }
173         }
174         return principal;
175     }
176 
177     public String getLDAP_DN(String susername, XWikiContext context)
178     {
179         String DN=null;
180         if (context!=null) {
181             // First we check in the local database
182             try {
183                 String user = findUser(susername, context);
184                 if (user!=null && user.length()!=0) {
185                     DN = readLDAP_DN(user, context);
186                 }
187             } catch (Exception e) {}
188 
189             if (context.isVirtual()) {
190                 if (DN==null && DN.length()!=0) {
191                     // Then we check in the main database
192                     String db = context.getDatabase();
193                     try {
194                         context.setDatabase(context.getWiki().getDatabase());
195                         try {
196                             String user = findUser(susername, context);
197                             if (user!=null && user.length()!=0)
198                                 DN = readLDAP_DN(user, context);
199                         } catch (Exception e) {}
200                     } finally {
201                         context.setDatabase(db);
202                     }
203                 }
204             }
205         }
206         return DN;
207     }
208 
209     private String readLDAP_DN(String username, XWikiContext context) {
210         String DN = null;
211         try {
212             XWikiDocument doc = context.getWiki().getDocument(username, context);
213             // We only allow empty password from users having a XWikiUsers object.
214             if (doc.getObject(<font color=red>"XWiki.XWikiUsers"font>)!=null) {
215               DN = doc.getStringValue(<font color=red>"XWiki.XWikiUsers"font>, <font color=red>"ldap_dn"font>);
216             }
217 
218         } catch (Throwable e) {}
219         return DN;
220     }
221 
222     protected boolean checkUserPassword(String username, String password, HashMap attributes, XWikiContext context) throws XWikiException {
223         LDAPConnection lc = new LDAPConnection();
224         boolean result = false;
225         boolean notinLDAP = false;
226         String foundDN = null;
227 
228         try {
229 
230             int ldapPort = getLDAPPort(context);
231             int ldapVersion = LDAPConnection.LDAP_V3;
232             String ldapHost = getParam(<font color=red>"ldap_server"font>, context);
233             String bindDNFormat = getParam(<font color=red>"ldap_bind_DN"font>,context);
234             String bindPasswordFormat = getParam(<font color=red>"ldap_bind_pass"font>,context);
235 
236             int checkLevel = GetCheckLevel(context);
237 
238             Object[] arguments = {
239                 username,
240                 password
241              };
242             String bindDN = MessageFormat.format(bindDNFormat, arguments);
243             String bindPassword =  MessageFormat.format(bindPasswordFormat, arguments);
244 
245             String baseDN = getParam(<font color=red>"ldap_base_DN"font>,context);
246 
247 
248             lc.connect( ldapHost, ldapPort );
249 
250             // authenticate to the server
251             result = Bind(bindDN, bindPassword, lc, ldapVersion);
252 
253             if (result && checkLevel > 0)
254             {
255                 LDAPSearchResults searchResults =
256                     lc.search(  baseDN,
257                                 LDAPConnection.SCOPE_SUB ,
258                                 <font color=red>"("font>+ getParam(<font color=red>"ldap_UID_attr"font>,context) +
259                                    <font color=red>"="font> + username + <font color=red>")"font>,
260                                 null,          // return all attributes
261                                 false);        // return attrs and values
262 
263                 if (searchResults.hasMore())
264                 {
265                     LDAPEntry nextEntry = searchResults.next();
266 
267                     foundDN = nextEntry.getDN();
268 
269                     if (checkLevel > 1)
270                     {
271                         LDAPAttribute attr = new LDAPAttribute(
272                                                         <font color=red>"userPassword"font>, password );
273                         result = lc.compare( foundDN, attr );
274                     }
275                     if (result)
276                     {
277                         LDAPAttributeSet attributeSet = nextEntry.getAttributeSet();
278                         Iterator allAttributes = attributeSet.iterator();
279 
280                         while(allAttributes.hasNext()) {
281                             LDAPAttribute attribute =
282                                         (LDAPAttribute)allAttributes.next();
283                             String attributeName = attribute.getName();
284 
285                             Enumeration allValues = attribute.getStringValues();
286 
287                             if( allValues != null) {
288                                 while(allValues.hasMoreElements()) {
289                                     String Value = (String) allValues.nextElement();
290                                     attributes.put(attributeName, Value);
291                                 }
292                             }
293                         }
294                         attributes.put(<font color=red>"dn"font>, foundDN);
295                     }
296                 }
297                 else
298                     notinLDAP = true;
299 
300                 if (log.isDebugEnabled()) {
301                     if (result)
302                      log.debug(<font color=red>"(debug) Password check for user "font> + username + <font color=red>" successfull"font>);
303                     else
304                      log.debug(<font color=red>"(debug) Password check for user "font> + username + <font color=red>" failed"font>);
305                 }
306             }
307         }
308         catch( LDAPException e ) {
309             if ( e.getResultCode() == LDAPException.NO_SUCH_OBJECT ) {
310                 notinLDAP = true;
311             } else if ( e.getResultCode() ==
312                                         LDAPException.NO_SUCH_ATTRIBUTE ) {
313                 notinLDAP = true;
314             }
315         }
316         catch (Throwable e) {
317             e.printStackTrace();
318         }
319         finally
320         {
321             try {
322                 lc.disconnect();
323             } catch (LDAPException e) {
324                 e.printStackTrace();
325             }
326         }
327         if (notinLDAP)
328         {
329             // Use XWiki password if user not in LDAP
330             result = checkPassword(username, password, context);
331             foundDN = null;
332         }
333 
334         return result;
335     }
336 
337     private String getParam(String name, XWikiContext context) {
338         String param = "";
339         try {
340          param = context.getWiki().getXWikiPreference(name,context);
341         } catch (Exception e) {}
342         if (param == null || "".equals(param))
343         {
344             try{
345              param = context.getWiki().Param(<font color=red>"xwiki.authentication."font> + StringUtils.replace(name, <font color=red>"ldap_"font>,<font color=red>"ldap."font>));
346             } catch (Exception e) {}
347         }
348         if (param == null)
349             param = "";
350         return param;
351     }
352 
353     protected int GetCheckLevel(XWikiContext context)
354     {
355         String checkLevel = getParam(<font color=red>"ldap_check_level"font>,  context);
356         int val = 2;
357         if (<font color=red>"1"font>.equals(checkLevel))
358             val = 1;
359         else if (<font color=red>"0"font>.equals(checkLevel))
360             val = 0;
361         return val;
362     }
363 
364     private int getLDAPPort(XWikiContext context) {
365         try {
366          return context.getWiki().getXWikiPreferenceAsInt(<font color=red>"ldap_port"font>, context);
367         } catch (Exception e) {
368          return (int)context.getWiki().ParamAsLong(<font color=red>"xwiki.authentication.ldap.port"font>, LDAPConnection.DEFAULT_PORT);
369         }
370     }
371 
372     protected boolean checkDNPassword(String DN, String username, String password, XWikiContext context) throws XWikiException {
373         LDAPConnection lc = new LDAPConnection();
374         boolean result = false;
375         boolean notinLDAP = false;
376         try {
377 
378             int ldapPort = getLDAPPort(context);
379             int ldapVersion = LDAPConnection.LDAP_V3;
380             String ldapHost = getParam(<font color=red>"ldap_server"font>, context);
381             String bindDN = getParam(<font color=red>"ldap_bind_DN"font>,context);
382             String bindPassword = getParam(<font color=red>"ldap_bind_pass"font>,context);
383             String baseDN = getParam(<font color=red>"ldap_base_DN"font>,context);
384 
385             lc.connect( ldapHost, ldapPort );
386 
387             // authenticate to the server
388             result = Bind(DN, password, lc, ldapVersion);
389 
390             if (log.isDebugEnabled()) {
391                 if (result)
392                  log.debug(<font color=red>"(debug) Password check for user "font> + DN + <font color=red>" successfull"font>);
393                 else
394                  log.debug(<font color=red>"(debug) Password check for user "font> + DN + <font color=red>" failed"font>);
395             }
396         }
397         catch( LDAPException e ) {
398             if ( e.getResultCode() == LDAPException.NO_SUCH_OBJECT ) {
399                 notinLDAP = true;
400             } else if ( e.getResultCode() ==
401                                         LDAPException.NO_SUCH_ATTRIBUTE ) {
402                 notinLDAP = true;
403             }
404         }
405         catch (Throwable e) {
406             e.printStackTrace();
407         }
408         finally
409         {
410             try {
411                 lc.disconnect();
412             } catch (LDAPException e) {
413                 e.printStackTrace();
414             }
415         }
416         if (notinLDAP)
417         {
418             // Use XWiki password if user not in LDAP
419             result = checkPassword(username, password, context);
420         }
421         return result;
422     }
423 
424 
425     private boolean Bind(String bindDN, String bindPassword, LDAPConnection lc, int ldapVersion) throws UnsupportedEncodingException {
426         boolean bound = false;
427         if (bindDN != null && bindDN.length() > 0 && bindPassword != null)
428         {
429             try
430             {
431                 lc.bind( ldapVersion, bindDN, bindPassword.getBytes(<font color=red>"UTF8"font>) );
432                 bound = true;
433             }
434             catch(LDAPException e) { };
435         }
436         return bound;
437     }
438 }