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