001 /* 002 * CDDL HEADER START 003 * 004 * The contents of this file are subject to the terms of the 005 * Common Development and Distribution License, Version 1.0 only 006 * (the "License"). You may not use this file except in compliance 007 * with the License. 008 * 009 * You can obtain a copy of the license at 010 * trunk/opends/resource/legal-notices/OpenDS.LICENSE 011 * or https://OpenDS.dev.java.net/OpenDS.LICENSE. 012 * See the License for the specific language governing permissions 013 * and limitations under the License. 014 * 015 * When distributing Covered Code, include this CDDL HEADER in each 016 * file and include the License file at 017 * trunk/opends/resource/legal-notices/OpenDS.LICENSE. If applicable, 018 * add the following below this CDDL HEADER, with the fields enclosed 019 * by brackets "[]" replaced with your own identifying information: 020 * Portions Copyright [yyyy] [name of copyright owner] 021 * 022 * CDDL HEADER END 023 * 024 * 025 * Copyright 2006-2008 Sun Microsystems, Inc. 026 */ 027 package org.opends.server.protocols.ldap; 028 import org.opends.messages.Message; 029 030 031 032 import java.util.ArrayList; 033 034 import org.opends.server.protocols.asn1.ASN1Element; 035 import org.opends.server.protocols.asn1.ASN1Integer; 036 import org.opends.server.protocols.asn1.ASN1OctetString; 037 import org.opends.server.protocols.asn1.ASN1Sequence; 038 import org.opends.server.types.AuthenticationType; 039 import org.opends.server.types.DebugLogLevel; 040 import org.opends.server.types.LDAPException; 041 042 import static org.opends.server.loggers.debug.DebugLogger.*; 043 import org.opends.server.loggers.debug.DebugTracer; 044 import static org.opends.messages.ProtocolMessages.*; 045 import static org.opends.server.protocols.ldap.LDAPConstants.*; 046 import static org.opends.server.protocols.ldap.LDAPResultCode.*; 047 import static org.opends.server.util.ServerConstants.*; 048 049 050 051 /** 052 * This class defines the structures and methods for an LDAP bind request 053 * protocol op, which is used to authenticate a user to the Directory Server. 054 */ 055 public class BindRequestProtocolOp 056 extends ProtocolOp 057 { 058 /** 059 * The tracer object for the debug logger. 060 */ 061 private static final DebugTracer TRACER = getTracer(); 062 063 // The bind DN for this request. 064 private ASN1OctetString dn; 065 066 // The SASL credentials for this request. 067 private ASN1OctetString saslCredentials; 068 069 // The simple authentication password for this request. 070 private ASN1OctetString simplePassword; 071 072 // The authentication type for this request. 073 private AuthenticationType authenticationType; 074 075 // The protocol version for this bind request. 076 private int protocolVersion; 077 078 // The SASL mechanism for this request. 079 private String saslMechanism; 080 081 082 083 /** 084 * Creates a new bind request protocol op to perform simple authentication 085 * with the provided DN and password. 086 * 087 * @param dn The DN for this bind request. 088 * @param protocolVersion The LDAP protocol version for this bind request. 089 * @param simplePassword The password for this bind request. 090 */ 091 public BindRequestProtocolOp(ASN1OctetString dn, int protocolVersion, 092 ASN1OctetString simplePassword) 093 { 094 this.dn = dn; 095 this.protocolVersion = protocolVersion; 096 this.simplePassword = simplePassword; 097 098 authenticationType = AuthenticationType.SIMPLE; 099 saslMechanism = null; 100 saslCredentials = null; 101 } 102 103 104 105 /** 106 * Creates a new bind request protocol op to perform SASL authentication with 107 * the provided information. 108 * 109 * @param dn The DN for this bind request. 110 * @param saslMechanism The SASL mechanism for this bind request. 111 * @param saslCredentials The SASL credentials for this bind request. 112 */ 113 public BindRequestProtocolOp(ASN1OctetString dn, String saslMechanism, 114 ASN1OctetString saslCredentials) 115 { 116 this.dn = dn; 117 this.saslMechanism = saslMechanism; 118 this.saslCredentials = saslCredentials; 119 120 authenticationType = AuthenticationType.SASL; 121 protocolVersion = 3; 122 simplePassword = null; 123 } 124 125 126 127 /** 128 * Creates a new bind request protocol op to perform SASL authentication with 129 * the provided information. 130 * 131 * @param dn The DN for this bind request. 132 * @param protocolVersion The protocol version for this bind request. 133 * @param authenticationType The authentication type for this bind request. 134 * @param simplePassword The password for this bind request. 135 * @param saslMechanism The SASL mechanism for this bind request. 136 * @param saslCredentials The SASL credentials for this bind request. 137 */ 138 private BindRequestProtocolOp(ASN1OctetString dn, int protocolVersion, 139 AuthenticationType authenticationType, 140 ASN1OctetString simplePassword, 141 String saslMechanism, 142 ASN1OctetString saslCredentials) 143 { 144 this.dn = dn; 145 this.protocolVersion = protocolVersion; 146 this.authenticationType = authenticationType; 147 this.simplePassword = simplePassword; 148 this.saslMechanism = saslMechanism; 149 this.saslCredentials = saslCredentials; 150 } 151 152 153 154 /** 155 * Retrieves the DN for this bind request. 156 * 157 * @return The DN for this bind request. 158 */ 159 public ASN1OctetString getDN() 160 { 161 return dn; 162 } 163 164 165 166 /** 167 * Specifies the DN for this bind request. 168 * 169 * @param dn The DN for this bind request. 170 */ 171 public void setDN(ASN1OctetString dn) 172 { 173 this.dn = dn; 174 } 175 176 177 178 /** 179 * Retrieves the protocol version for this bind request. 180 * 181 * @return The protocol version for this bind request. 182 */ 183 public int getProtocolVersion() 184 { 185 return protocolVersion; 186 } 187 188 189 190 /** 191 * Specifies the protocol version for this bind request. 192 * 193 * @param protocolVersion The protocol version for this bind request. 194 */ 195 public void setProtocolVersion(int protocolVersion) 196 { 197 this.protocolVersion = protocolVersion; 198 } 199 200 201 202 /** 203 * Retrieves the authentication type for this bind request. 204 * 205 * @return The authentication type for this bind request. 206 */ 207 public AuthenticationType getAuthenticationType() 208 { 209 return authenticationType; 210 } 211 212 213 214 /** 215 * Retrieves the simple authentication password for this bind request. 216 * 217 * @return The simple authentication password for this bind request, or 218 * <CODE>null</CODE> if this is a SASL bind request. 219 */ 220 public ASN1OctetString getSimplePassword() 221 { 222 return simplePassword; 223 } 224 225 226 227 /** 228 * Indicates that this bind request should use simple authentication with the 229 * provided password. 230 * 231 * @param simplePassword The simple authentication password for this bind 232 * request. 233 */ 234 public void setSimplePassword(ASN1OctetString simplePassword) 235 { 236 this.simplePassword = simplePassword; 237 authenticationType = AuthenticationType.SIMPLE; 238 saslMechanism = null; 239 saslCredentials = null; 240 } 241 242 243 244 /** 245 * Retrieves the SASL mechanism for this bind request. 246 * 247 * @return The SASL mechanism for this bind request, or <CODE>null</CODE> if 248 * this is a simple bind request. 249 */ 250 public String getSASLMechanism() 251 { 252 return saslMechanism; 253 } 254 255 256 257 /** 258 * Retrieves the SASL credentials for this bind request. 259 * 260 * @return The SASL credentials for this bind request, or <CODE>null</CODE> 261 * if there are none or if this is a simple bind request. 262 */ 263 public ASN1OctetString getSASLCredentials() 264 { 265 return saslCredentials; 266 } 267 268 269 270 /** 271 * Indicates that this bind request should use SASL authentication with the 272 * provided information. 273 * 274 * @param saslMechanism The SASL mechanism for this bind request. 275 * @param saslCredentials The SASL credentials for this bind request. 276 */ 277 public void setSASLAuthenticationInfo(String saslMechanism, 278 ASN1OctetString saslCredentials) 279 { 280 this.saslMechanism = saslMechanism; 281 this.saslCredentials = saslCredentials; 282 authenticationType = AuthenticationType.SASL; 283 simplePassword = null; 284 } 285 286 287 288 289 /** 290 * Retrieves the BER type for this protocol op. 291 * 292 * @return The BER type for this protocol op. 293 */ 294 public byte getType() 295 { 296 return OP_TYPE_BIND_REQUEST; 297 } 298 299 300 301 /** 302 * Retrieves the name for this protocol op type. 303 * 304 * @return The name for this protocol op type. 305 */ 306 public String getProtocolOpName() 307 { 308 return "Bind Request"; 309 } 310 311 312 313 /** 314 * Encodes this protocol op to an ASN.1 element suitable for including in an 315 * LDAP message. 316 * 317 * @return The ASN.1 element containing the encoded protocol op. 318 */ 319 public ASN1Element encode() 320 { 321 ArrayList<ASN1Element> elements = new ArrayList<ASN1Element>(3); 322 323 elements.add(new ASN1Integer(protocolVersion)); 324 elements.add(dn); 325 326 if (authenticationType == AuthenticationType.SIMPLE) 327 { 328 simplePassword.setType(TYPE_AUTHENTICATION_SIMPLE); 329 elements.add(simplePassword); 330 } 331 else 332 { 333 ArrayList<ASN1Element> saslElements = new ArrayList<ASN1Element>(2); 334 saslElements.add(new ASN1OctetString(saslMechanism)); 335 if (saslCredentials != null) 336 { 337 saslElements.add(saslCredentials); 338 } 339 340 elements.add(new ASN1Sequence(TYPE_AUTHENTICATION_SASL, saslElements)); 341 } 342 343 return new ASN1Sequence(OP_TYPE_BIND_REQUEST, elements); 344 } 345 346 347 348 /** 349 * Decodes the provided ASN.1 element as an LDAP bind request protocol op. 350 * 351 * @param element The ASN.1 element to decode. 352 * 353 * @return The decoded LDAP bind request protocol op. 354 * 355 * @throws LDAPException If a problem occurs while trying to decode the 356 * provided ASN.1 element as an LDAP bind request. 357 */ 358 public static BindRequestProtocolOp decodeBindRequest(ASN1Element element) 359 throws LDAPException 360 { 361 ArrayList<ASN1Element> elements; 362 try 363 { 364 elements = element.decodeAsSequence().elements(); 365 } 366 catch (Exception e) 367 { 368 if (debugEnabled()) 369 { 370 TRACER.debugCaught(DebugLogLevel.ERROR, e); 371 } 372 373 Message message = 374 ERR_LDAP_BIND_REQUEST_DECODE_SEQUENCE.get(String.valueOf(e)); 375 throw new LDAPException(PROTOCOL_ERROR, message, e); 376 } 377 378 379 int numElements = elements.size(); 380 if (numElements != 3) 381 { 382 Message message = ERR_LDAP_BIND_REQUEST_DECODE_INVALID_ELEMENT_COUNT.get( 383 numElements); 384 throw new LDAPException(PROTOCOL_ERROR, message); 385 } 386 387 388 int protocolVersion; 389 try 390 { 391 protocolVersion = elements.get(0).decodeAsInteger().intValue(); 392 } 393 catch (Exception e) 394 { 395 if (debugEnabled()) 396 { 397 TRACER.debugCaught(DebugLogLevel.ERROR, e); 398 } 399 400 Message message = 401 ERR_LDAP_BIND_REQUEST_DECODE_VERSION.get(String.valueOf(e)); 402 throw new LDAPException(PROTOCOL_ERROR, message, e); 403 } 404 405 406 ASN1OctetString dn; 407 try 408 { 409 dn = elements.get(1).decodeAsOctetString(); 410 } 411 catch (Exception e) 412 { 413 if (debugEnabled()) 414 { 415 TRACER.debugCaught(DebugLogLevel.ERROR, e); 416 } 417 418 Message message = ERR_LDAP_BIND_REQUEST_DECODE_DN.get(String.valueOf(e)); 419 throw new LDAPException(PROTOCOL_ERROR, message, e); 420 } 421 422 423 AuthenticationType authenticationType; 424 ASN1OctetString simplePassword = null; 425 String saslMechanism = null; 426 ASN1OctetString saslCredentials = null; 427 try 428 { 429 element = elements.get(2); 430 switch (element.getType()) 431 { 432 case TYPE_AUTHENTICATION_SIMPLE: 433 authenticationType = AuthenticationType.SIMPLE; 434 435 try 436 { 437 simplePassword = element.decodeAsOctetString(); 438 } 439 catch (Exception e) 440 { 441 Message message = 442 ERR_LDAP_BIND_REQUEST_DECODE_PASSWORD.get(String.valueOf(e)); 443 throw new LDAPException(PROTOCOL_ERROR, message, e); 444 } 445 446 break; 447 case TYPE_AUTHENTICATION_SASL: 448 authenticationType = AuthenticationType.SASL; 449 450 try 451 { 452 elements = element.decodeAsSequence().elements(); 453 454 saslMechanism = elements.get(0).decodeAsOctetString().stringValue(); 455 if (elements.size() == 2) 456 { 457 saslCredentials = elements.get(1).decodeAsOctetString(); 458 } 459 } 460 catch (Exception e) 461 { 462 Message message = 463 ERR_LDAP_BIND_REQUEST_DECODE_SASL_INFO.get(String.valueOf(e)); 464 throw new LDAPException(PROTOCOL_ERROR, message, e); 465 } 466 467 break; 468 default: 469 Message message = ERR_LDAP_BIND_REQUEST_DECODE_INVALID_CRED_TYPE.get( 470 element.getType()); 471 throw new LDAPException(AUTH_METHOD_NOT_SUPPORTED, message); 472 } 473 } 474 catch (LDAPException le) 475 { 476 throw le; 477 } 478 catch (Exception e) 479 { 480 if (debugEnabled()) 481 { 482 TRACER.debugCaught(DebugLogLevel.ERROR, e); 483 } 484 485 Message message = 486 ERR_LDAP_BIND_REQUEST_DECODE_CREDENTIALS.get(String.valueOf(e)); 487 throw new LDAPException(PROTOCOL_ERROR, message, e); 488 } 489 490 491 return new BindRequestProtocolOp(dn, protocolVersion, authenticationType, 492 simplePassword, saslMechanism, 493 saslCredentials); 494 } 495 496 497 /** 498 * Appends a string representation of this LDAP protocol op to the provided 499 * buffer. 500 * 501 * @param buffer The buffer to which the string should be appended. 502 */ 503 public void toString(StringBuilder buffer) 504 { 505 buffer.append("BindRequest(version="); 506 buffer.append(protocolVersion); 507 buffer.append(", dn="); 508 509 if (dn != null) 510 { 511 dn.toString(buffer); 512 } 513 514 if (authenticationType == AuthenticationType.SIMPLE) 515 { 516 buffer.append(", password="); 517 simplePassword.toString(buffer); 518 } 519 else 520 { 521 buffer.append(", saslMechanism="); 522 buffer.append(saslMechanism); 523 524 if (saslCredentials != null) 525 { 526 buffer.append(", saslCredentials="); 527 saslCredentials.toString(buffer); 528 } 529 } 530 531 buffer.append(")"); 532 } 533 534 535 536 /** 537 * Appends a multi-line string representation of this LDAP protocol op to the 538 * provided buffer. 539 * 540 * @param buffer The buffer to which the information should be appended. 541 * @param indent The number of spaces from the margin that the lines should 542 * be indented. 543 */ 544 public void toString(StringBuilder buffer, int indent) 545 { 546 StringBuilder indentBuf = new StringBuilder(indent); 547 for (int i=0 ; i < indent; i++) 548 { 549 indentBuf.append(' '); 550 } 551 552 buffer.append(indentBuf); 553 buffer.append("Bind Request"); 554 buffer.append(EOL); 555 556 buffer.append(indentBuf); 557 buffer.append(" Protocol Version: "); 558 buffer.append(protocolVersion); 559 buffer.append(EOL); 560 561 buffer.append(indentBuf); 562 buffer.append(" DN: "); 563 if (dn != null) 564 { 565 dn.toString(buffer); 566 } 567 buffer.append(EOL); 568 569 if (authenticationType == AuthenticationType.SIMPLE) 570 { 571 buffer.append(indentBuf); 572 buffer.append(" Simple Password: "); 573 buffer.append(String.valueOf(simplePassword)); 574 buffer.append(EOL); 575 } 576 else 577 { 578 buffer.append(indentBuf); 579 buffer.append(" SASL Mechanism: "); 580 buffer.append(saslMechanism); 581 buffer.append(EOL); 582 583 if (saslCredentials != null) 584 { 585 buffer.append(indentBuf); 586 buffer.append(" SASL Credentials:"); 587 buffer.append(EOL); 588 saslCredentials.toString(buffer, indent+4); 589 } 590 } 591 } 592 } 593