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 legal-notices/CDDLv1_0.txt
010 * or http://forgerock.org/license/CDDLv1.0.html.
011 * See the License for the specific language governing permissions
012 * and limitations under the License.
013 *
014 * When distributing Covered Code, include this CDDL HEADER in each
015 * file and include the License file at legal-notices/CDDLv1_0.txt.
016 * If applicable, add the following below this CDDL HEADER, with the
017 * fields enclosed by brackets "[]" replaced with your own identifying
018 * information:
019 *      Portions Copyright [yyyy] [name of copyright owner]
020 *
021 * CDDL HEADER END
022 *
023 *
024 *      Copyright 2006-2009 Sun Microsystems, Inc.
025 *      Portions Copyright 2013-2014 ForgeRock AS
026 */
027package org.opends.server.extensions;
028
029import org.forgerock.i18n.LocalizableMessageBuilder;
030import org.opends.server.admin.std.server.StartTLSExtendedOperationHandlerCfg;
031import org.opends.server.api.ClientConnection;
032import org.opends.server.api.ExtendedOperationHandler;
033import org.forgerock.opendj.config.server.ConfigException;
034import org.opends.server.core.ExtendedOperation;
035import org.opends.server.types.InitializationException;
036import org.forgerock.opendj.ldap.ResultCode;
037
038import static org.opends.messages.ExtensionMessages.*;
039import static org.opends.server.util.ServerConstants.*;
040
041/**
042 * This class provides an implementation of the StartTLS extended operation as
043 * defined in RFC 2830.  It can enable the TLS connection security provider on
044 * an established connection upon receiving an appropriate request from a
045 * client.
046 */
047public class StartTLSExtendedOperation
048       extends ExtendedOperationHandler<StartTLSExtendedOperationHandlerCfg>
049{
050
051  /**
052   * Create an instance of this StartTLS extended operation handler.  All
053   * initialization should be performed in the
054   * <CODE>initializeExtendedOperationHandler</CODE> method.
055   */
056  public StartTLSExtendedOperation()
057  {
058    super();
059  }
060
061  /** {@inheritDoc} */
062  @Override
063  public void initializeExtendedOperationHandler(
064                   StartTLSExtendedOperationHandlerCfg config)
065         throws ConfigException, InitializationException
066  {
067    super.initializeExtendedOperationHandler(config);
068  }
069
070  /**
071   * Processes the provided extended operation.
072   *
073   * @param  operation  The extended operation to be processed.
074   */
075  @Override
076  public void processExtendedOperation(ExtendedOperation operation)
077  {
078    // We should always include the StartTLS OID in the response (the same OID
079    // is used for both the request and the response), so make sure that it will
080    // happen.
081    operation.setResponseOID(OID_START_TLS_REQUEST);
082
083
084    // Get the reference to the client connection.  If there is none, then fail.
085    ClientConnection clientConnection = operation.getClientConnection();
086    if (clientConnection == null)
087    {
088      operation.setResultCode(ResultCode.UNAVAILABLE);
089      operation.appendErrorMessage(ERR_STARTTLS_NO_CLIENT_CONNECTION.get());
090      return;
091    }
092
093
094    // Make sure that the client connection is capable of enabling TLS.  If not,
095    // then fail.
096    TLSCapableConnection tlsCapableConnection;
097    if (clientConnection instanceof TLSCapableConnection)
098    {
099      tlsCapableConnection = (TLSCapableConnection) clientConnection;
100    }
101    else
102    {
103      operation.setResultCode(ResultCode.UNAVAILABLE);
104      operation.appendErrorMessage(ERR_STARTTLS_NOT_TLS_CAPABLE.get());
105      return;
106    }
107
108    LocalizableMessageBuilder unavailableReason = new LocalizableMessageBuilder();
109    if (! tlsCapableConnection.prepareTLS(unavailableReason))
110    {
111      operation.setResultCode(ResultCode.UNAVAILABLE);
112      operation.setErrorMessage(unavailableReason);
113      return;
114    }
115
116    // TLS was successfully enabled on the client connection, but we need to
117    // send the response in the clear.
118    operation.setResultCode(ResultCode.SUCCESS);
119  }
120
121  /** {@inheritDoc} */
122  @Override
123  public String getExtendedOperationOID()
124  {
125    return OID_START_TLS_REQUEST;
126  }
127
128  /** {@inheritDoc} */
129  @Override
130  public String getExtendedOperationName()
131  {
132    return "StartTLS";
133  }
134}