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