1 /* 2 * Copyright (c) 1999, 2011, Oracle and/or its affiliates. All rights reserved. 3 * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. 4 * 5 * This code is free software; you can redistribute it and/or modify it 6 * under the terms of the GNU General Public License version 2 only, as 7 * published by the Free Software Foundation. Oracle designates this 8 * particular file as subject to the "Classpath" exception as provided 9 * by Oracle in the LICENSE file that accompanied this code. 10 * 11 * This code is distributed in the hope that it will be useful, but WITHOUT 12 * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or 13 * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License 14 * version 2 for more details (a copy is included in the LICENSE file that 15 * accompanied this code). 16 * 17 * You should have received a copy of the GNU General Public License version 18 * 2 along with this work; if not, write to the Free Software Foundation, 19 * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. 20 * 21 * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA 22 * or visit www.oracle.com if you need additional information or have any 23 * questions. 24 */ 25 26 package com.sun.jndi.url.ldap; 27 28 import javax.naming.spi.ResolveResult; 29 import javax.naming.*; 30 import javax.naming.directory.*; 31 import java.util.Hashtable; 32 import java.util.StringTokenizer; 33 import com.sun.jndi.ldap.LdapURL; 34 35 /** 36 * An LDAP URL context. 37 * 38 * @author Rosanna Lee 39 * @author Scott Seligman 40 */ 41 42 final public class ldapURLContext 43 extends com.sun.jndi.toolkit.url.GenericURLDirContext { 44 45 ldapURLContext(Hashtable<?,?> env) { 46 super(env); 47 } 48 49 /** 50 * Resolves 'name' into a target context with remaining name. 51 * It only resolves the hostname/port number. The remaining name 52 * contains the root DN. 53 * 54 * For example, with a LDAP URL "ldap://localhost:389/o=widget,c=us", 55 * this method resolves "ldap://localhost:389/" to the root LDAP 56 * context on the server 'localhost' on port 389, 57 * and returns as the remaining name "o=widget, c=us". 58 */ 59 protected ResolveResult getRootURLContext(String name, Hashtable<?,?> env) 60 throws NamingException { 61 return ldapURLContextFactory.getUsingURLIgnoreRootDN(name, env); 62 } 63 64 /** 65 * Return the suffix of an ldap url. 66 * prefix parameter is ignored. 67 */ 68 protected Name getURLSuffix(String prefix, String url) 69 throws NamingException { 70 71 LdapURL ldapUrl = new LdapURL(url); 72 String dn = (ldapUrl.getDN() != null? ldapUrl.getDN() : ""); 73 74 // Represent DN as empty or single-component composite name. 75 CompositeName remaining = new CompositeName(); 76 if (!"".equals(dn)) { 77 // if nonempty, add component 78 remaining.add(dn); 79 } 80 return remaining; 81 } 82 83 /* 84 * Override context operations. 85 * Test for presence of LDAP URL query components in the name argument. 86 * Query components are permitted only for search operations and only 87 * when the name has a single component. 88 */ 89 90 public Object lookup(String name) throws NamingException { 91 if (LdapURL.hasQueryComponents(name)) { 92 throw new InvalidNameException(name); 93 } else { 94 return super.lookup(name); 95 } 96 } 97 98 public Object lookup(Name name) throws NamingException { 99 if (LdapURL.hasQueryComponents(name.get(0))) { 100 throw new InvalidNameException(name.toString()); 101 } else { 102 return super.lookup(name); 103 } 104 } 105 106 public void bind(String name, Object obj) throws NamingException { 107 if (LdapURL.hasQueryComponents(name)) { 108 throw new InvalidNameException(name); 109 } else { 110 super.bind(name, obj); 111 } 112 } 113 114 public void bind(Name name, Object obj) throws NamingException { 115 if (LdapURL.hasQueryComponents(name.get(0))) { 116 throw new InvalidNameException(name.toString()); 117 } else { 118 super.bind(name, obj); 119 } 120 } 121 122 public void rebind(String name, Object obj) throws NamingException { 123 if (LdapURL.hasQueryComponents(name)) { 124 throw new InvalidNameException(name); 125 } else { 126 super.rebind(name, obj); 127 } 128 } 129 130 public void rebind(Name name, Object obj) throws NamingException { 131 if (LdapURL.hasQueryComponents(name.get(0))) { 132 throw new InvalidNameException(name.toString()); 133 } else { 134 super.rebind(name, obj); 135 } 136 } 137 138 public void unbind(String name) throws NamingException { 139 if (LdapURL.hasQueryComponents(name)) { 140 throw new InvalidNameException(name); 141 } else { 142 super.unbind(name); 143 } 144 } 145 146 public void unbind(Name name) throws NamingException { 147 if (LdapURL.hasQueryComponents(name.get(0))) { 148 throw new InvalidNameException(name.toString()); 149 } else { 150 super.unbind(name); 151 } 152 } 153 154 public void rename(String oldName, String newName) throws NamingException { 155 if (LdapURL.hasQueryComponents(oldName)) { 156 throw new InvalidNameException(oldName); 157 } else if (LdapURL.hasQueryComponents(newName)) { 158 throw new InvalidNameException(newName); 159 } else { 160 super.rename(oldName, newName); 161 } 162 } 163 164 public void rename(Name oldName, Name newName) throws NamingException { 165 if (LdapURL.hasQueryComponents(oldName.get(0))) { 166 throw new InvalidNameException(oldName.toString()); 167 } else if (LdapURL.hasQueryComponents(newName.get(0))) { 168 throw new InvalidNameException(newName.toString()); 169 } else { 170 super.rename(oldName, newName); 171 } 172 } 173 174 public NamingEnumeration<NameClassPair> list(String name) 175 throws NamingException { 176 if (LdapURL.hasQueryComponents(name)) { 177 throw new InvalidNameException(name); 178 } else { 179 return super.list(name); 180 } 181 } 182 183 public NamingEnumeration<NameClassPair> list(Name name) 184 throws NamingException { 185 if (LdapURL.hasQueryComponents(name.get(0))) { 186 throw new InvalidNameException(name.toString()); 187 } else { 188 return super.list(name); 189 } 190 } 191 192 public NamingEnumeration<Binding> listBindings(String name) 193 throws NamingException { 194 if (LdapURL.hasQueryComponents(name)) { 195 throw new InvalidNameException(name); 196 } else { 197 return super.listBindings(name); 198 } 199 } 200 201 public NamingEnumeration<Binding> listBindings(Name name) 202 throws NamingException { 203 if (LdapURL.hasQueryComponents(name.get(0))) { 204 throw new InvalidNameException(name.toString()); 205 } else { 206 return super.listBindings(name); 207 } 208 } 209 210 public void destroySubcontext(String name) throws NamingException { 211 if (LdapURL.hasQueryComponents(name)) { 212 throw new InvalidNameException(name); 213 } else { 214 super.destroySubcontext(name); 215 } 216 } 217 218 public void destroySubcontext(Name name) throws NamingException { 219 if (LdapURL.hasQueryComponents(name.get(0))) { 220 throw new InvalidNameException(name.toString()); 221 } else { 222 super.destroySubcontext(name); 223 } 224 } 225 226 public Context createSubcontext(String name) throws NamingException { 227 if (LdapURL.hasQueryComponents(name)) { 228 throw new InvalidNameException(name); 229 } else { 230 return super.createSubcontext(name); 231 } 232 } 233 234 public Context createSubcontext(Name name) throws NamingException { 235 if (LdapURL.hasQueryComponents(name.get(0))) { 236 throw new InvalidNameException(name.toString()); 237 } else { 238 return super.createSubcontext(name); 239 } 240 } 241 242 public Object lookupLink(String name) throws NamingException { 243 if (LdapURL.hasQueryComponents(name)) { 244 throw new InvalidNameException(name); 245 } else { 246 return super.lookupLink(name); 247 } 248 } 249 250 public Object lookupLink(Name name) throws NamingException { 251 if (LdapURL.hasQueryComponents(name.get(0))) { 252 throw new InvalidNameException(name.toString()); 253 } else { 254 return super.lookupLink(name); 255 } 256 } 257 258 public NameParser getNameParser(String name) throws NamingException { 259 if (LdapURL.hasQueryComponents(name)) { 260 throw new InvalidNameException(name); 261 } else { 262 return super.getNameParser(name); 263 } 264 } 265 266 public NameParser getNameParser(Name name) throws NamingException { 267 if (LdapURL.hasQueryComponents(name.get(0))) { 268 throw new InvalidNameException(name.toString()); 269 } else { 270 return super.getNameParser(name); 271 } 272 } 273 274 public String composeName(String name, String prefix) 275 throws NamingException { 276 if (LdapURL.hasQueryComponents(name)) { 277 throw new InvalidNameException(name); 278 } else if (LdapURL.hasQueryComponents(prefix)) { 279 throw new InvalidNameException(prefix); 280 } else { 281 return super.composeName(name, prefix); 282 } 283 } 284 285 public Name composeName(Name name, Name prefix) throws NamingException { 286 if (LdapURL.hasQueryComponents(name.get(0))) { 287 throw new InvalidNameException(name.toString()); 288 } else if (LdapURL.hasQueryComponents(prefix.get(0))) { 289 throw new InvalidNameException(prefix.toString()); 290 } else { 291 return super.composeName(name, prefix); 292 } 293 } 294 295 public Attributes getAttributes(String name) throws NamingException { 296 if (LdapURL.hasQueryComponents(name)) { 297 throw new InvalidNameException(name); 298 } else { 299 return super.getAttributes(name); 300 } 301 } 302 303 public Attributes getAttributes(Name name) throws NamingException { 304 if (LdapURL.hasQueryComponents(name.get(0))) { 305 throw new InvalidNameException(name.toString()); 306 } else { 307 return super.getAttributes(name); 308 } 309 } 310 311 public Attributes getAttributes(String name, String[] attrIds) 312 throws NamingException { 313 if (LdapURL.hasQueryComponents(name)) { 314 throw new InvalidNameException(name); 315 } else { 316 return super.getAttributes(name, attrIds); 317 } 318 } 319 320 public Attributes getAttributes(Name name, String[] attrIds) 321 throws NamingException { 322 if (LdapURL.hasQueryComponents(name.get(0))) { 323 throw new InvalidNameException(name.toString()); 324 } else { 325 return super.getAttributes(name, attrIds); 326 } 327 } 328 329 public void modifyAttributes(String name, int mod_op, Attributes attrs) 330 throws NamingException { 331 if (LdapURL.hasQueryComponents(name)) { 332 throw new InvalidNameException(name); 333 } else { 334 super.modifyAttributes(name, mod_op, attrs); 335 } 336 } 337 338 public void modifyAttributes(Name name, int mod_op, Attributes attrs) 339 throws NamingException { 340 if (LdapURL.hasQueryComponents(name.get(0))) { 341 throw new InvalidNameException(name.toString()); 342 } else { 343 super.modifyAttributes(name, mod_op, attrs); 344 } 345 } 346 347 public void modifyAttributes(String name, ModificationItem[] mods) 348 throws NamingException { 349 if (LdapURL.hasQueryComponents(name)) { 350 throw new InvalidNameException(name); 351 } else { 352 super.modifyAttributes(name, mods); 353 } 354 } 355 356 public void modifyAttributes(Name name, ModificationItem[] mods) 357 throws NamingException { 358 if (LdapURL.hasQueryComponents(name.get(0))) { 359 throw new InvalidNameException(name.toString()); 360 } else { 361 super.modifyAttributes(name, mods); 362 } 363 } 364 365 public void bind(String name, Object obj, Attributes attrs) 366 throws NamingException { 367 if (LdapURL.hasQueryComponents(name)) { 368 throw new InvalidNameException(name); 369 } else { 370 super.bind(name, obj, attrs); 371 } 372 } 373 374 public void bind(Name name, Object obj, Attributes attrs) 375 throws NamingException { 376 if (LdapURL.hasQueryComponents(name.get(0))) { 377 throw new InvalidNameException(name.toString()); 378 } else { 379 super.bind(name, obj, attrs); 380 } 381 } 382 383 public void rebind(String name, Object obj, Attributes attrs) 384 throws NamingException { 385 if (LdapURL.hasQueryComponents(name)) { 386 throw new InvalidNameException(name); 387 } else { 388 super.rebind(name, obj, attrs); 389 } 390 } 391 392 public void rebind(Name name, Object obj, Attributes attrs) 393 throws NamingException { 394 if (LdapURL.hasQueryComponents(name.get(0))) { 395 throw new InvalidNameException(name.toString()); 396 } else { 397 super.rebind(name, obj, attrs); 398 } 399 } 400 401 public DirContext createSubcontext(String name, Attributes attrs) 402 throws NamingException { 403 if (LdapURL.hasQueryComponents(name)) { 404 throw new InvalidNameException(name); 405 } else { 406 return super.createSubcontext(name, attrs); 407 } 408 } 409 410 public DirContext createSubcontext(Name name, Attributes attrs) 411 throws NamingException { 412 if (LdapURL.hasQueryComponents(name.get(0))) { 413 throw new InvalidNameException(name.toString()); 414 } else { 415 return super.createSubcontext(name, attrs); 416 } 417 } 418 419 public DirContext getSchema(String name) throws NamingException { 420 if (LdapURL.hasQueryComponents(name)) { 421 throw new InvalidNameException(name); 422 } else { 423 return super.getSchema(name); 424 } 425 } 426 427 public DirContext getSchema(Name name) throws NamingException { 428 if (LdapURL.hasQueryComponents(name.get(0))) { 429 throw new InvalidNameException(name.toString()); 430 } else { 431 return super.getSchema(name); 432 } 433 } 434 435 public DirContext getSchemaClassDefinition(String name) 436 throws NamingException { 437 if (LdapURL.hasQueryComponents(name)) { 438 throw new InvalidNameException(name); 439 } else { 440 return super.getSchemaClassDefinition(name); 441 } 442 } 443 444 public DirContext getSchemaClassDefinition(Name name) 445 throws NamingException { 446 if (LdapURL.hasQueryComponents(name.get(0))) { 447 throw new InvalidNameException(name.toString()); 448 } else { 449 return super.getSchemaClassDefinition(name); 450 } 451 } 452 453 // divert the search operation when the LDAP URL has query components 454 public NamingEnumeration<SearchResult> search(String name, 455 Attributes matchingAttributes) 456 throws NamingException { 457 458 if (LdapURL.hasQueryComponents(name)) { 459 return searchUsingURL(name); 460 } else { 461 return super.search(name, matchingAttributes); 462 } 463 } 464 465 // divert the search operation when name has a single component 466 public NamingEnumeration<SearchResult> search(Name name, 467 Attributes matchingAttributes) 468 throws NamingException { 469 if (name.size() == 1) { 470 return search(name.get(0), matchingAttributes); 471 } else if (LdapURL.hasQueryComponents(name.get(0))) { 472 throw new InvalidNameException(name.toString()); 473 } else { 474 return super.search(name, matchingAttributes); 475 } 476 } 477 478 // divert the search operation when the LDAP URL has query components 479 public NamingEnumeration<SearchResult> search(String name, 480 Attributes matchingAttributes, 481 String[] attributesToReturn) 482 throws NamingException { 483 484 if (LdapURL.hasQueryComponents(name)) { 485 return searchUsingURL(name); 486 } else { 487 return super.search(name, matchingAttributes, attributesToReturn); 488 } 489 } 490 491 // divert the search operation when name has a single component 492 public NamingEnumeration<SearchResult> search(Name name, 493 Attributes matchingAttributes, 494 String[] attributesToReturn) 495 throws NamingException { 496 497 if (name.size() == 1) { 498 return search(name.get(0), matchingAttributes, attributesToReturn); 499 } else if (LdapURL.hasQueryComponents(name.get(0))) { 500 throw new InvalidNameException(name.toString()); 501 } else { 502 return super.search(name, matchingAttributes, attributesToReturn); 503 } 504 } 505 506 // divert the search operation when the LDAP URL has query components 507 public NamingEnumeration<SearchResult> search(String name, 508 String filter, 509 SearchControls cons) 510 throws NamingException { 511 512 if (LdapURL.hasQueryComponents(name)) { 513 return searchUsingURL(name); 514 } else { 515 return super.search(name, filter, cons); 516 } 517 } 518 519 // divert the search operation when name has a single component 520 public NamingEnumeration<SearchResult> search(Name name, 521 String filter, 522 SearchControls cons) 523 throws NamingException { 524 525 if (name.size() == 1) { 526 return search(name.get(0), filter, cons); 527 } else if (LdapURL.hasQueryComponents(name.get(0))) { 528 throw new InvalidNameException(name.toString()); 529 } else { 530 return super.search(name, filter, cons); 531 } 532 } 533 534 // divert the search operation when the LDAP URL has query components 535 public NamingEnumeration<SearchResult> search(String name, 536 String filterExpr, 537 Object[] filterArgs, 538 SearchControls cons) 539 throws NamingException { 540 541 if (LdapURL.hasQueryComponents(name)) { 542 return searchUsingURL(name); 543 } else { 544 return super.search(name, filterExpr, filterArgs, cons); 545 } 546 } 547 548 // divert the search operation when name has a single component 549 public NamingEnumeration<SearchResult> search(Name name, 550 String filterExpr, 551 Object[] filterArgs, 552 SearchControls cons) 553 throws NamingException { 554 555 if (name.size() == 1) { 556 return search(name.get(0), filterExpr, filterArgs, cons); 557 } else if (LdapURL.hasQueryComponents(name.get(0))) { 558 throw new InvalidNameException(name.toString()); 559 } else { 560 return super.search(name, filterExpr, filterArgs, cons); 561 } 562 } 563 564 // Search using the LDAP URL in name. 565 // LDAP URL query components override the search arguments. 566 private NamingEnumeration<SearchResult> searchUsingURL(String name) 567 throws NamingException { 568 569 LdapURL url = new LdapURL(name); 570 571 ResolveResult res = getRootURLContext(name, myEnv); 572 DirContext ctx = (DirContext)res.getResolvedObj(); 573 try { 574 return ctx.search(res.getRemainingName(), 575 setFilterUsingURL(url), 576 setSearchControlsUsingURL(url)); 577 } finally { 578 ctx.close(); 579 } 580 } 581 582 /* 583 * Initialize a String filter using the LDAP URL filter component. 584 * If filter is not present in the URL it is initialized to its default 585 * value as specified in RFC-2255. 586 */ 587 private static String setFilterUsingURL(LdapURL url) { 588 589 String filter = url.getFilter(); 590 591 if (filter == null) { 592 filter = "(objectClass=*)"; //default value 593 } 594 return filter; 595 } 596 597 /* 598 * Initialize a SearchControls object using LDAP URL query components. 599 * Components not present in the URL are initialized to their default 600 * values as specified in RFC-2255. 601 */ 602 private static SearchControls setSearchControlsUsingURL(LdapURL url) { 603 604 SearchControls cons = new SearchControls(); 605 String scope = url.getScope(); 606 String attributes = url.getAttributes(); 607 608 if (scope == null) { 609 cons.setSearchScope(SearchControls.OBJECT_SCOPE); //default value 610 } else { 611 if (scope.equals("sub")) { 612 cons.setSearchScope(SearchControls.SUBTREE_SCOPE); 613 } else if (scope.equals("one")) { 614 cons.setSearchScope(SearchControls.ONELEVEL_SCOPE); 615 } else if (scope.equals("base")) { 616 cons.setSearchScope(SearchControls.OBJECT_SCOPE); 617 } 618 } 619 620 if (attributes == null) { 621 cons.setReturningAttributes(null); //default value 622 } else { 623 StringTokenizer tokens = new StringTokenizer(attributes, ","); 624 int count = tokens.countTokens(); 625 String[] attrs = new String[count]; 626 for (int i = 0; i < count; i ++) { 627 attrs[i] = tokens.nextToken(); 628 } 629 cons.setReturningAttributes(attrs); 630 } 631 return cons; 632 } 633 }