1 23 24 package com.sun.enterprise.security.auth.login; 25 26 import java.util.*; 27 import java.util.logging.Logger ; 28 import java.util.logging.Level ; 29 import com.sun.logging.LogDomains; 30 31 import javax.security.auth.*; 32 import javax.security.auth.callback.*; 33 import javax.security.auth.login.*; 34 import javax.security.auth.spi.*; 35 36 import javax.naming.*; 37 import javax.naming.directory.*; 38 39 import com.sun.enterprise.security.auth.realm.ldap.LDAPRealm; 40 import java.security.acl.Group ; 42 import java.security.Principal ; 43 import javax.security.auth.x500.X500Principal ; 44 import com.sun.jndi.ldap.obj.GroupOfURLs; 46 import javax.security.auth.login.LoginException ; 47 48 81 public class LDAPLoginModule extends PasswordLoginModule 82 { 83 private String _userDNbase; 84 private String _searchFilter; 85 private String _grpDNbase; 86 private String _grpSearchFilter; 87 private String _grpTarget; 88 private LDAPRealm _ldapRealm; 89 private String [] _dnOnly = {"dn"}; 90 91 95 protected void authenticate () 96 throws LoginException 97 { 98 if (!(_currentRealm instanceof LDAPRealm)) { 99 String msg = sm.getString("ldaplm.badrealm"); 100 throw new LoginException (msg); 101 } 102 _ldapRealm = (LDAPRealm)_currentRealm; 103 104 if (_password == null || _password.length() == 0) { 107 String msg = sm.getString("ldaplm.emptypassword", _username); 108 throw new LoginException (msg); 109 } 110 111 _userDNbase = _currentRealm.getProperty(LDAPRealm.PARAM_USERDN); 113 _searchFilter = 114 _currentRealm.getProperty(LDAPRealm.PARAM_SEARCH_FILTER); 115 _grpDNbase = _currentRealm.getProperty(LDAPRealm.PARAM_GRPDN); 116 _grpSearchFilter = 117 _currentRealm.getProperty(LDAPRealm.PARAM_GRP_SEARCH_FILTER); 118 _grpTarget = 119 _currentRealm.getProperty(LDAPRealm.PARAM_GRP_TARGET); 120 121 String mode = _currentRealm.getProperty(LDAPRealm.PARAM_MODE); 122 123 if (LDAPRealm.MODE_FIND_BIND.equals(mode)) { 124 findAndBind(); 125 126 } else { 127 String msg = sm.getString("ldaplm.badmode", mode); 128 throw new LoginException (msg); 129 } 130 } 131 132 133 137 private void findAndBind() 138 throws LoginException 139 { 140 StringBuffer sb = new StringBuffer (_searchFilter); 142 substitute(sb, LDAPRealm.SUBST_SUBJECT_NAME, _username); 143 String userid = sb.toString(); 144 145 DirContext ctx = null; 147 String srcFilter = null; 148 String [] grpList = null; 149 try { 150 ctx = new InitialDirContext(_ldapRealm.getLdapBindProps()); 151 String realUserDN = userSearch(ctx,_userDNbase, userid); 152 if (realUserDN == null) { 153 String msg = sm.getString("ldaplm.usernotfound", _username); 154 throw new LoginException (msg); 155 } 156 157 boolean bindSuccessful = bindAsUser(realUserDN, _password); 158 if (bindSuccessful == false) { 159 String msg = sm.getString("ldaplm.bindfailed", realUserDN); 160 throw new LoginException (msg); 161 } 162 163 sb = new StringBuffer (_grpSearchFilter); 165 substitute(sb, LDAPRealm.SUBST_SUBJECT_NAME, _username); 166 substitute(sb, LDAPRealm.SUBST_SUBJECT_DN, realUserDN); 167 168 srcFilter = sb.toString(); 169 ArrayList groupsList = new ArrayList(); 170 groupsList.addAll(groupSearch(ctx, _grpDNbase, srcFilter, _grpTarget)); 171 groupsList.addAll(dynamicGroupSearch(ctx, _grpDNbase, _grpTarget, 174 realUserDN)); 175 grpList = new String [groupsList.size()]; 176 groupsList.toArray(grpList); 177 } catch (Exception e) { 178 throw new LoginException (e.toString() ); 179 } finally { 180 if (ctx != null) { 181 try { 182 ctx.close(); 183 } catch (NamingException e) {}; 184 } 185 } 186 187 if (_logger.isLoggable(Level.FINE)) { 188 _logger.log(Level.FINE, "LDAP:Group search filter: " + srcFilter); 189 StringBuffer gb = new StringBuffer (); 190 gb.append("Group memberships found: "); 191 if (grpList != null) { 192 for (int i=0; i<grpList.length; i++) { 193 gb.append(" "+grpList[i]); 194 } 195 } else { 196 gb.append("(null)"); 197 } 198 _logger.log(Level.FINE, "LDAP: "+ gb.toString()); 199 } 200 _ldapRealm.setGroupNames(_username, grpList); 201 202 if(_logger.isLoggable(Level.FINE)){ 203 _logger.log(Level.FINE, "LDAP: login succeeded for: " + _username); 204 } 205 206 commitAuthentication(_username, _password, 209 _currentRealm, grpList); 210 } 211 212 213 217 private String userSearch(DirContext ctx, String baseDN, String filter) 218 { 219 if (_logger.isLoggable(Level.FINEST)) { 220 _logger.log(Level.FINE, "search: baseDN: "+ baseDN + 221 " filter: " + filter); 222 } 223 224 String foundDN = null; 225 NamingEnumeration namingEnum = null; 226 227 SearchControls ctls = new SearchControls(); 228 ctls.setReturningAttributes(_dnOnly); 229 ctls.setSearchScope(SearchControls.SUBTREE_SCOPE); 230 ctls.setCountLimit(1); 231 232 try { 233 namingEnum = ctx.search(baseDN, filter, ctls); 234 if (namingEnum.hasMore()) { 235 SearchResult res = (SearchResult)namingEnum.next(); 236 237 StringBuffer sb = new StringBuffer (); 238 CompositeName compDN = new CompositeName(res.getName()); 240 String ldapDN = compDN.get(0); 241 sb.append(ldapDN); 242 243 if (res.isRelative()) { 244 sb.append(","); 245 sb.append(baseDN); 246 } 247 foundDN = sb.toString(); 248 if (_logger.isLoggable(Level.FINEST)) { 249 _logger.log(Level.FINE, "Found user DN: " + foundDN); 250 } 251 } 252 } catch (Exception e) { 253 _logger.log(Level.WARNING, "ldaplm.searcherror", filter); 254 _logger.log(Level.WARNING, "security.exception", e); 255 } finally { 256 if (namingEnum != null) { 257 try { 258 namingEnum.close(); 259 } catch(Exception ex) { 260 } 261 } 262 } 263 264 return foundDN; 265 } 266 267 268 272 private boolean bindAsUser(String bindDN, String password) 273 { 274 boolean bindSuccessful=false; 275 276 Properties p = _ldapRealm.getLdapBindProps(); 277 278 p.put(Context.SECURITY_PRINCIPAL, bindDN); 279 p.put(Context.SECURITY_CREDENTIALS, password); 280 281 DirContext ctx = null; 282 try { 283 ctx = new InitialDirContext(p); 284 bindSuccessful = true; 285 } catch (Exception e) { 286 if (_logger.isLoggable(Level.FINEST)) { 287 _logger.finest("Error binding to directory as: " + bindDN); 288 _logger.finest("Exception from JNDI: " + e.toString()); 289 } 290 } finally { 291 if (ctx != null) { 292 try { 293 ctx.close(); 294 } catch (NamingException e) {}; 295 } 296 } 297 return bindSuccessful; 298 } 299 300 304 private List dynamicGroupSearch(DirContext ctx, String baseDN, 305 String target, String userDN) 306 { 307 List groupList = new ArrayList(); 308 String filter = LDAPRealm.DYNAMIC_GROUP_FILTER; 309 310 String [] targets = new String [] { target, "memberUrl" }; 311 312 try { 313 SearchControls ctls = new SearchControls(); 314 ctls.setReturningAttributes(targets); 315 ctls.setSearchScope(SearchControls.SUBTREE_SCOPE); 316 ctls.setReturningObjFlag(true); 317 318 NamingEnumeration e = ctx.search(baseDN, filter, ctls); 319 320 while(e.hasMore()) { 321 SearchResult res = (SearchResult)e.next(); 322 Object searchedObject = res.getObject(); 323 if(searchedObject instanceof com.sun.jndi.ldap.obj.GroupOfURLs){ com.sun.jndi.ldap.obj.GroupOfURLs gurls = (com.sun.jndi.ldap.obj.GroupOfURLs) searchedObject; 325 Principal x500principal = new X500Principal (userDN); 326 if (gurls.isMember(x500principal)) { 327 328 Attribute grpAttr = res.getAttributes().get(target); 329 int sz = grpAttr.size(); 330 for (int i=0; i<sz; i++) { 331 String s = (String )grpAttr.get(i); 332 groupList.add(s); 333 } 334 } 335 } 336 if (searchedObject instanceof Context) { 338 ((Context)searchedObject).close(); 339 } 340 } 341 } catch (Exception e) { 342 _logger.log(Level.WARNING, "ldaplm.searcherror", filter); 343 _logger.log(Level.WARNING, "security.exception", e); 344 } 345 return groupList; 346 } 347 348 352 private List groupSearch(DirContext ctx, String baseDN, 353 String filter, String target) 354 { 355 List groupList = new ArrayList(); 356 357 try { 358 String [] targets = new String [1]; 359 targets[0] = target; 360 361 SearchControls ctls = new SearchControls(); 362 ctls.setReturningAttributes(targets); 363 ctls.setSearchScope(SearchControls.SUBTREE_SCOPE); 364 365 NamingEnumeration e = ctx.search(baseDN, filter, ctls); 366 367 while(e.hasMore()) { 368 SearchResult res = (SearchResult)e.next(); 369 Attribute grpAttr = res.getAttributes().get(target); 370 int sz = grpAttr.size(); 371 for (int i=0; i<sz; i++) { 372 String s = (String )grpAttr.get(i); 373 groupList.add(s); 374 } 375 } 376 377 } catch (Exception e) { 378 _logger.log(Level.WARNING, "ldaplm.searcherror", filter); 379 _logger.log(Level.WARNING, "security.exception", e); 380 } 381 382 return groupList; 383 } 384 385 390 private static void substitute(StringBuffer sb, 391 String target, String value) 392 { 393 int i = sb.indexOf(target); 394 while (i >= 0) { 395 sb.replace(i, i+target.length(), value); 396 i = sb.indexOf(target); 397 } 398 } 399 400 } 401 | Popular Tags |