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 2007-2008 Sun Microsystems, Inc.
026 */
027 package org.opends.server.core;
028 import org.opends.messages.Message;
029 import org.opends.messages.MessageBuilder;
030
031
032 import static org.opends.server.core.CoreConstants.LOG_ELEMENT_AUTH_TYPE;
033 import static org.opends.server.core.CoreConstants.LOG_ELEMENT_BIND_DN;
034 import static org.opends.server.core.CoreConstants.LOG_ELEMENT_ERROR_MESSAGE;
035 import static org.opends.server.core.CoreConstants.LOG_ELEMENT_MATCHED_DN;
036 import static org.opends.server.core.CoreConstants.LOG_ELEMENT_PROCESSING_TIME;
037 import static org.opends.server.core.CoreConstants.LOG_ELEMENT_REFERRAL_URLS;
038 import static org.opends.server.core.CoreConstants.LOG_ELEMENT_RESULT_CODE;
039 import static org.opends.server.core.CoreConstants.LOG_ELEMENT_SASL_MECHANISM;
040 import static org.opends.server.loggers.AccessLogger.logBindRequest;
041 import static org.opends.server.loggers.AccessLogger.logBindResponse;
042 import static org.opends.server.loggers.debug.DebugLogger.debugEnabled;
043 import static org.opends.messages.CoreMessages.*;
044
045 import java.util.ArrayList;
046 import java.util.Iterator;
047 import java.util.List;
048
049 import org.opends.server.api.ClientConnection;
050 import org.opends.server.api.plugin.PluginResult;
051 import org.opends.server.loggers.debug.DebugLogger;
052 import org.opends.server.loggers.debug.DebugTracer;
053 import org.opends.server.protocols.asn1.ASN1OctetString;
054 import org.opends.server.types.*;
055 import org.opends.server.types.operation.PreParseBindOperation;
056 import org.opends.server.workflowelement.localbackend.*;
057
058
059
060
061 /**
062 * This class defines an operation that may be used to authenticate a user to
063 * the Directory Server. Note that for security restrictions, response messages
064 * that may be returned to the client must be carefully cleaned to ensure that
065 * they do not provide a malicious client with information that may be useful in
066 * an attack. This does impact the debugability of the server, but that can
067 * be addressed by calling the <CODE>setAuthFailureReason</CODE> method, which
068 * can provide a reason for a failure in a form that will not be returned to the
069 * client but may be written to a log file.
070 */
071 public class BindOperationBasis
072 extends AbstractOperation
073 implements BindOperation, PreParseBindOperation
074 {
075 /**
076 * The tracer object for the debug logger.
077 */
078 private static final DebugTracer TRACER = DebugLogger.getTracer();
079
080 // The credentials used for SASL authentication.
081 private ASN1OctetString saslCredentials;
082
083 // The server SASL credentials provided to the client in the response.
084 private ASN1OctetString serverSASLCredentials;
085
086 // The authentication info for this bind operation.
087 private AuthenticationInfo authInfo = null;
088
089 // The authentication type used for this bind operation.
090 private AuthenticationType authType;
091
092 // The raw, unprocessed bind DN as contained in the client request.
093 private ByteString rawBindDN;
094
095 // The password used for simple authentication.
096 private ByteString simplePassword;
097
098 // The bind DN used for this bind operation.
099 private DN bindDN;
100
101 // The DN of the user entry that is attempting to authenticate.
102 private DN userEntryDN;
103
104 // The DN of the user as whom a SASL authentication was attempted (regardless
105 // of whether the authentication was successful) for the purpose of updating
106 // password policy state information.
107 private Entry saslAuthUserEntry;
108
109 // The set of response controls for this bind operation.
110 private List<Control> responseControls;
111
112 // A message explaining the reason for the authentication failure.
113 private Message authFailureReason;
114
115 // The SASL mechanism used for SASL authentication.
116 private String saslMechanism;
117
118 // A string representation of the protocol version for this bind operation.
119 private String protocolVersion;
120
121 /**
122 * Creates a new simple bind operation with the provided information.
123 *
124 * @param clientConnection The client connection with which this operation
125 * is associated.
126 * @param operationID The operation ID for this operation.
127 * @param messageID The message ID of the request with which this
128 * operation is associated.
129 * @param requestControls The set of controls included in the request.
130 * @param protocolVersion The string representation of the protocol version
131 * associated with this bind request.
132 * @param rawBindDN The raw, unprocessed bind DN as provided in the
133 * request from the client.
134 * @param simplePassword The password to use for the simple
135 * authentication.
136 */
137 public BindOperationBasis(ClientConnection clientConnection, long operationID,
138 int messageID, List<Control> requestControls,
139 String protocolVersion, ByteString rawBindDN,
140 ByteString simplePassword)
141 {
142 super(clientConnection, operationID, messageID, requestControls);
143
144
145 this.protocolVersion = protocolVersion;
146 this.authType = AuthenticationType.SIMPLE;
147 this.saslMechanism = null;
148 this.saslCredentials = null;
149
150 if (rawBindDN == null)
151 {
152 this.rawBindDN = new ASN1OctetString();
153 }
154 else
155 {
156 this.rawBindDN = rawBindDN;
157 }
158
159 if (simplePassword == null)
160 {
161 this.simplePassword = new ASN1OctetString();
162 }
163 else
164 {
165 this.simplePassword = simplePassword;
166 }
167
168 bindDN = null;
169 userEntryDN = null;
170 responseControls = new ArrayList<Control>(0);
171 authFailureReason = null;
172 saslAuthUserEntry = null;
173
174 cancelResult = new CancelResult(ResultCode.CANNOT_CANCEL,
175 ERR_CANNOT_CANCEL_BIND.get());
176 }
177
178
179
180 /**
181 * Creates a new SASL bind operation with the provided information.
182 *
183 * @param clientConnection The client connection with which this operation
184 * is associated.
185 * @param operationID The operation ID for this operation.
186 * @param messageID The message ID of the request with which this
187 * operation is associated.
188 * @param requestControls The set of controls included in the request.
189 * @param protocolVersion The string representation of the protocol version
190 * associated with this bind request.
191 * @param rawBindDN The raw, unprocessed bind DN as provided in the
192 * request from the client.
193 * @param saslMechanism The SASL mechanism included in the request.
194 * @param saslCredentials The optional SASL credentials included in the
195 * request.
196 */
197 public BindOperationBasis(ClientConnection clientConnection, long operationID,
198 int messageID, List<Control> requestControls,
199 String protocolVersion, ByteString rawBindDN,
200 String saslMechanism, ASN1OctetString saslCredentials)
201 {
202 super(clientConnection, operationID, messageID, requestControls);
203
204
205 this.protocolVersion = protocolVersion;
206 this.authType = AuthenticationType.SASL;
207 this.saslMechanism = saslMechanism;
208 this.saslCredentials = saslCredentials;
209 this.simplePassword = null;
210
211 if (rawBindDN == null)
212 {
213 this.rawBindDN = new ASN1OctetString();
214 }
215 else
216 {
217 this.rawBindDN = rawBindDN;
218 }
219
220 bindDN = null;
221 userEntryDN = null;
222 responseControls = new ArrayList<Control>(0);
223 authFailureReason = null;
224 saslAuthUserEntry = null;
225
226 cancelResult = new CancelResult(ResultCode.CANNOT_CANCEL,
227 ERR_CANNOT_CANCEL_BIND.get());
228 }
229
230
231
232 /**
233 * Creates a new simple bind operation with the provided information.
234 *
235 * @param clientConnection The client connection with which this operation
236 * is associated.
237 * @param operationID The operation ID for this operation.
238 * @param messageID The message ID of the request with which this
239 * operation is associated.
240 * @param requestControls The set of controls included in the request.
241 * @param protocolVersion The string representation of the protocol version
242 * associated with this bind request.
243 * @param bindDN The bind DN for this bind operation.
244 * @param simplePassword The password to use for the simple
245 * authentication.
246 */
247 public BindOperationBasis(ClientConnection clientConnection, long operationID,
248 int messageID, List<Control> requestControls,
249 String protocolVersion, DN bindDN,
250 ByteString simplePassword)
251 {
252 super(clientConnection, operationID, messageID, requestControls);
253
254
255 this.protocolVersion = protocolVersion;
256 this.authType = AuthenticationType.SIMPLE;
257 this.bindDN = bindDN;
258 this.saslMechanism = null;
259 this.saslCredentials = null;
260
261 if (bindDN == null)
262 {
263 rawBindDN = new ASN1OctetString();
264 }
265 else
266 {
267 rawBindDN = new ASN1OctetString(bindDN.toString());
268 }
269
270 if (simplePassword == null)
271 {
272 this.simplePassword = new ASN1OctetString();
273 }
274 else
275 {
276 this.simplePassword = simplePassword;
277 }
278
279 responseControls = new ArrayList<Control>(0);
280 authFailureReason = null;
281 saslAuthUserEntry = null;
282 userEntryDN = null;
283
284 cancelResult = new CancelResult(ResultCode.CANNOT_CANCEL,
285 ERR_CANNOT_CANCEL_BIND.get());
286 }
287
288
289
290 /**
291 * Creates a new SASL bind operation with the provided information.
292 *
293 * @param clientConnection The client connection with which this operation
294 * is associated.
295 * @param operationID The operation ID for this operation.
296 * @param messageID The message ID of the request with which this
297 * operation is associated.
298 * @param requestControls The set of controls included in the request.
299 * @param protocolVersion The string representation of the protocol version
300 * associated with this bind request.
301 * @param bindDN The bind DN for this bind operation.
302 * @param saslMechanism The SASL mechanism included in the request.
303 * @param saslCredentials The optional SASL credentials included in the
304 * request.
305 */
306 public BindOperationBasis(ClientConnection clientConnection, long operationID,
307 int messageID, List<Control> requestControls,
308 String protocolVersion, DN bindDN,
309 String saslMechanism, ASN1OctetString saslCredentials)
310 {
311 super(clientConnection, operationID, messageID, requestControls);
312
313
314 this.protocolVersion = protocolVersion;
315 this.authType = AuthenticationType.SASL;
316 this.bindDN = bindDN;
317 this.saslMechanism = saslMechanism;
318 this.saslCredentials = saslCredentials;
319 this.simplePassword = null;
320
321 if (bindDN == null)
322 {
323 rawBindDN = new ASN1OctetString();
324 }
325 else
326 {
327 rawBindDN = new ASN1OctetString(bindDN.toString());
328 }
329
330 responseControls = new ArrayList<Control>(0);
331 authFailureReason = null;
332 saslAuthUserEntry = null;
333 userEntryDN = null;
334
335 cancelResult = new CancelResult(ResultCode.CANNOT_CANCEL,
336 ERR_CANNOT_CANCEL_BIND.get());
337 }
338
339
340 /**
341 * {@inheritDoc}
342 */
343 public final AuthenticationType getAuthenticationType()
344 {
345 return authType;
346 }
347
348
349 /**
350 * {@inheritDoc}
351 */
352 public final ByteString getRawBindDN()
353 {
354 return rawBindDN;
355 }
356
357 /**
358 * {@inheritDoc}
359 */
360 public final void setRawBindDN(ByteString rawBindDN)
361 {
362 if (rawBindDN == null)
363 {
364 this.rawBindDN = new ASN1OctetString();
365 }
366 else
367 {
368 this.rawBindDN = rawBindDN;
369 }
370
371 bindDN = null;
372 }
373
374
375 /**
376 * {@inheritDoc}
377 */
378 public final DN getBindDN()
379 {
380 try
381 {
382 if (bindDN == null)
383 {
384 bindDN = DN.decode(rawBindDN);
385 }
386 }
387 catch (DirectoryException de)
388 {
389 if (debugEnabled())
390 {
391 TRACER.debugCaught(DebugLogLevel.ERROR, de);
392 }
393
394 setResultCode(ResultCode.INVALID_CREDENTIALS);
395 setAuthFailureReason(de.getMessageObject());
396 }
397 return bindDN;
398 }
399
400 /**
401 * {@inheritDoc}
402 */
403 public final ByteString getSimplePassword()
404 {
405 return simplePassword;
406 }
407
408 /**
409 * {@inheritDoc}
410 */
411 public final void setSimplePassword(ByteString simplePassword)
412 {
413 if (simplePassword == null)
414 {
415 this.simplePassword = new ASN1OctetString();
416 }
417 else
418 {
419 this.simplePassword = simplePassword;
420 }
421
422 authType = AuthenticationType.SIMPLE;
423 saslMechanism = null;
424 saslCredentials = null;
425 }
426
427 /**
428 * {@inheritDoc}
429 */
430 public final String getSASLMechanism()
431 {
432 return saslMechanism;
433 }
434
435 /**
436 * {@inheritDoc}
437 */
438 public final ASN1OctetString getSASLCredentials()
439 {
440 return saslCredentials;
441 }
442
443 /**
444 * {@inheritDoc}
445 */
446 public final void setSASLCredentials(String saslMechanism,
447 ASN1OctetString saslCredentials)
448 {
449 this.saslMechanism = saslMechanism;
450 this.saslCredentials = saslCredentials;
451
452 authType = AuthenticationType.SASL;
453 simplePassword = null;
454 }
455
456 /**
457 * {@inheritDoc}
458 */
459 public final ASN1OctetString getServerSASLCredentials()
460 {
461 return serverSASLCredentials;
462 }
463
464 /**
465 * {@inheritDoc}
466 */
467 public final void setServerSASLCredentials(ASN1OctetString
468 serverSASLCredentials)
469 {
470 this.serverSASLCredentials = serverSASLCredentials;
471 }
472
473 /**
474 * {@inheritDoc}
475 */
476 public final Entry getSASLAuthUserEntry()
477 {
478 return saslAuthUserEntry;
479 }
480
481 /**
482 * {@inheritDoc}
483 */
484 public final void setSASLAuthUserEntry(Entry saslAuthUserEntry)
485 {
486 this.saslAuthUserEntry = saslAuthUserEntry;
487 }
488
489 /**
490 * {@inheritDoc}
491 */
492 public final Message getAuthFailureReason()
493 {
494 return authFailureReason;
495 }
496
497 /**
498 * {@inheritDoc}
499 */
500 public final void setAuthFailureReason(Message message)
501 {
502 if (DirectoryServer.returnBindErrorMessages())
503 {
504 appendErrorMessage(message);
505 }
506 else
507 {
508 authFailureReason = message;
509 }
510 }
511
512 /**
513 * {@inheritDoc}
514 */
515 public final DN getUserEntryDN()
516 {
517 return userEntryDN;
518 }
519
520 /**
521 * {@inheritDoc}
522 */
523 public final AuthenticationInfo getAuthenticationInfo()
524 {
525 return authInfo;
526 }
527
528 /**
529 * {@inheritDoc}
530 */
531 public final void setAuthenticationInfo(AuthenticationInfo authInfo)
532 {
533 this.authInfo = authInfo;
534 }
535
536 /**
537 * {@inheritDoc}
538 */
539 @Override()
540 public final OperationType getOperationType()
541 {
542 // Note that no debugging will be done in this method because it is a likely
543 // candidate for being called by the logging subsystem.
544
545 return OperationType.BIND;
546 }
547
548 /**
549 * {@inheritDoc}
550 */
551 @Override()
552 public final String[][] getRequestLogElements()
553 {
554 // Note that no debugging will be done in this method because it is a likely
555 // candidate for being called by the logging subsystem.
556
557 if (authType == AuthenticationType.SASL)
558 {
559 return new String[][]
560 {
561 new String[] { LOG_ELEMENT_BIND_DN, String.valueOf(rawBindDN) },
562 new String[] { LOG_ELEMENT_AUTH_TYPE, authType.toString() },
563 new String[] { LOG_ELEMENT_SASL_MECHANISM, saslMechanism }
564 };
565 }
566 else
567 {
568 return new String[][]
569 {
570 new String[] { LOG_ELEMENT_BIND_DN, String.valueOf(rawBindDN) },
571 new String[] { LOG_ELEMENT_AUTH_TYPE, authType.toString() }
572 };
573 }
574 }
575
576 /**
577 * {@inheritDoc}
578 */
579 @Override()
580 public final String[][] getResponseLogElements()
581 {
582 // Note that no debugging will be done in this method because it is a likely
583 // candidate for being called by the logging subsystem.
584
585 String resultCode = String.valueOf(getResultCode().getIntValue());
586
587 String errorMessage;
588 MessageBuilder errorMessageBuffer = getErrorMessage();
589 if (errorMessageBuffer == null)
590 {
591 errorMessage = null;
592 }
593 else
594 {
595 errorMessage = errorMessageBuffer.toString();
596 }
597
598 String matchedDNStr;
599 DN matchedDN = getMatchedDN();
600 if (matchedDN == null)
601 {
602 matchedDNStr = null;
603 }
604 else
605 {
606 matchedDNStr = matchedDN.toString();
607 }
608
609 String referrals;
610 List<String> referralURLs = getReferralURLs();
611 if ((referralURLs == null) || referralURLs.isEmpty())
612 {
613 referrals = null;
614 }
615 else
616 {
617 StringBuilder buffer = new StringBuilder();
618 Iterator<String> iterator = referralURLs.iterator();
619 buffer.append(iterator.next());
620
621 while (iterator.hasNext())
622 {
623 buffer.append(", ");
624 buffer.append(iterator.next());
625 }
626
627 referrals = buffer.toString();
628 }
629
630 String processingTime =
631 String.valueOf(getProcessingTime());
632
633 return new String[][]
634 {
635 new String[] { LOG_ELEMENT_RESULT_CODE, resultCode },
636 new String[] { LOG_ELEMENT_ERROR_MESSAGE, errorMessage },
637 new String[] { LOG_ELEMENT_MATCHED_DN, matchedDNStr },
638 new String[] { LOG_ELEMENT_REFERRAL_URLS, referrals },
639 new String[] { LOG_ELEMENT_PROCESSING_TIME, processingTime }
640 };
641 }
642
643 /**
644 * {@inheritDoc}
645 */
646 @Override()
647 public final List<Control> getResponseControls()
648 {
649 return responseControls;
650 }
651
652 /**
653 * {@inheritDoc}
654 */
655 @Override()
656 public final void addResponseControl(Control control)
657 {
658 responseControls.add(control);
659 }
660
661 /**
662 * {@inheritDoc}
663 */
664 @Override()
665 public final void removeResponseControl(Control control)
666 {
667 responseControls.remove(control);
668 }
669
670
671 /**
672 * {@inheritDoc}
673 */
674 @Override()
675 public final void toString(StringBuilder buffer)
676 {
677 buffer.append("BindOperation(connID=");
678 buffer.append(clientConnection.getConnectionID());
679 buffer.append(", opID=");
680 buffer.append(operationID);
681 buffer.append(", protocol=\"");
682 buffer.append(clientConnection.getProtocol());
683 buffer.append(" ");
684 buffer.append(protocolVersion);
685 buffer.append(", dn=");
686 buffer.append(rawBindDN);
687 buffer.append(", authType=");
688 buffer.append(authType);
689 buffer.append(")");
690 }
691
692 /**
693 * {@inheritDoc}
694 */
695 public void setUserEntryDN(DN userEntryDN)
696 {
697 this.userEntryDN = userEntryDN;
698 }
699
700 /**
701 * {@inheritDoc}
702 */
703 public String getProtocolVersion()
704 {
705 return protocolVersion;
706 }
707
708 /**
709 * {@inheritDoc}
710 */
711 public void setProtocolVersion(String protocolVersion)
712 {
713 this.protocolVersion = protocolVersion;
714 }
715
716 /**
717 * {@inheritDoc}
718 */
719 public final void run()
720 {
721 setResultCode(ResultCode.UNDEFINED);
722
723 // Start the processing timer and initially set the result to indicate that
724 // the result is unknown.
725 setProcessingStartTime();
726
727 // Log the bind request message.
728 logBindRequest(this);
729
730 ClientConnection clientConnection = getClientConnection();
731
732 // Set a flag to indicate that a bind operation is in progress. This should
733 // ensure that no new operations will be accepted for this client until the
734 // bind is complete.
735 clientConnection.setBindInProgress(true);
736
737 // Wipe out any existing authentication for the client connection and create
738 // a placeholder that will be used if the bind is successful.
739 clientConnection.setUnauthenticated();
740
741 // Abandon any operations that may be in progress for the client.
742 Message cancelReason = INFO_CANCELED_BY_BIND_REQUEST.get();
743 CancelRequest cancelRequest = new CancelRequest(true, cancelReason);
744 clientConnection.cancelAllOperationsExcept(cancelRequest, getMessageID());
745
746
747 // Get the plugin config manager that will be used for invoking plugins.
748 PluginConfigManager pluginConfigManager =
749 DirectoryServer.getPluginConfigManager();
750
751
752 // This flag is set to true as soon as a workflow has been executed.
753 boolean workflowExecuted = false;
754
755
756 try
757 {
758 // Invoke the pre-parse bind plugins.
759 PluginResult.PreParse preParseResult =
760 pluginConfigManager.invokePreParseBindPlugins(this);
761 if (!preParseResult.continueProcessing())
762 {
763 setResultCode(preParseResult.getResultCode());
764 appendErrorMessage(preParseResult.getErrorMessage());
765 setMatchedDN(preParseResult.getMatchedDN());
766 setReferralURLs(preParseResult.getReferralURLs());
767 return;
768 }
769
770
771 // Process the bind DN to convert it from the raw form as provided by the
772 // client into the form required for the rest of the bind processing.
773 DN bindDN = getBindDN();
774 if (bindDN == null){
775 return;
776 }
777
778 // If this is a simple bind
779 // Then check wether the bind DN is actually one of the alternate root DNs
780 // defined in the server. If so, then replace it with the actual DN
781 // for that user.
782 switch (getAuthenticationType())
783 {
784 case SIMPLE:
785 DN actualRootDN = DirectoryServer.getActualRootBindDN(bindDN);
786 if (actualRootDN != null)
787 {
788 bindDN = actualRootDN;
789 }
790 }
791
792
793 // Retrieve the network group attached to the client connection
794 // and get a workflow to process the operation.
795 NetworkGroup ng = getClientConnection().getNetworkGroup();
796 Workflow workflow = ng.getWorkflowCandidate(bindDN);
797 if (workflow == null)
798 {
799 // We have found no workflow for the requested base DN, just return
800 // a no such entry result code and stop the processing.
801 updateOperationErrMsgAndResCode();
802 return;
803 }
804 workflow.execute(this);
805 workflowExecuted = true;
806
807 }
808 catch(CanceledOperationException coe)
809 {
810 // This shouldn't happen for bind operations. Just cancel anyways
811 if (debugEnabled())
812 {
813 TRACER.debugCaught(DebugLogLevel.ERROR, coe);
814 }
815
816 setResultCode(ResultCode.CANCELED);
817
818 appendErrorMessage(cancelRequest.getCancelReason());
819 }
820 finally
821 {
822 // If the bind processing is finished, then unset the "bind in progress"
823 // flag to allow other operations to be processed on the connection.
824 if (getResultCode() != ResultCode.SASL_BIND_IN_PROGRESS)
825 {
826 clientConnection.setBindInProgress(false);
827 }
828
829 // Stop the processing timer.
830 setProcessingStopTime();
831
832 // Send the bind response to the client.
833 clientConnection.sendResponse(this);
834
835 // Log the bind response.
836 logBindResponse(this);
837
838 // Invoke the post-response bind plugins.
839 invokePostResponsePlugins(workflowExecuted);
840 }
841 }
842
843
844 /**
845 * Invokes the post response plugins. If a workflow has been executed
846 * then invoke the post response plugins provided by the workflow
847 * elements of the worklfow, otherwise invoke the post reponse plugins
848 * that have been registered with the current operation.
849 *
850 * @param workflowExecuted <code>true</code> if a workflow has been
851 * executed
852 */
853 private void invokePostResponsePlugins(boolean workflowExecuted)
854 {
855 // Get the plugin config manager that will be used for invoking plugins.
856 PluginConfigManager pluginConfigManager =
857 DirectoryServer.getPluginConfigManager();
858
859 // Invoke the post response plugins
860 if (workflowExecuted)
861 {
862 // The post responses are provided by the workflow elements of the
863 // workflow.
864 List localOperations =
865 (List)getAttachment(Operation.LOCALBACKENDOPERATIONS);
866 if (localOperations != null)
867 {
868 for (Object localOp : localOperations)
869 {
870 LocalBackendBindOperation localOperation =
871 (LocalBackendBindOperation)localOp;
872 // Invoke the post-response bind plugins.
873 pluginConfigManager.invokePostResponseBindPlugins(localOperation);
874 }
875 }
876 else
877 {
878 // The current operation does not implement any bind post response
879 // interface so we cannot invoke any post-response plugin.
880 }
881 }
882 }
883
884
885 /**
886 * Updates the error message and the result code of the operation.
887 *
888 * This method is called because no workflows were found to process
889 * the operation.
890 */
891 private void updateOperationErrMsgAndResCode()
892 {
893 Message message = ERR_BIND_OPERATION_UNKNOWN_USER.get(
894 String.valueOf(getBindDN()));
895 setResultCode(ResultCode.INVALID_CREDENTIALS);
896 setAuthFailureReason(message);
897 }
898
899 }
900