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-2014 ForgeRock AS.
016 */
017package org.opends.server.extensions;
018
019import org.forgerock.i18n.LocalizableMessageBuilder;
020import org.opends.server.admin.std.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  /**
042   * Create an instance of this StartTLS extended operation handler.  All
043   * initialization should be performed in the
044   * <CODE>initializeExtendedOperationHandler</CODE> method.
045   */
046  public StartTLSExtendedOperation()
047  {
048    super();
049  }
050
051  /** {@inheritDoc} */
052  @Override
053  public void initializeExtendedOperationHandler(
054                   StartTLSExtendedOperationHandlerCfg config)
055         throws ConfigException, InitializationException
056  {
057    super.initializeExtendedOperationHandler(config);
058  }
059
060  /**
061   * Processes the provided extended operation.
062   *
063   * @param  operation  The extended operation to be processed.
064   */
065  @Override
066  public void processExtendedOperation(ExtendedOperation operation)
067  {
068    // We should always include the StartTLS OID in the response (the same OID
069    // is used for both the request and the response), so make sure that it will
070    // happen.
071    operation.setResponseOID(OID_START_TLS_REQUEST);
072
073
074    // Get the reference to the client connection.  If there is none, then fail.
075    ClientConnection clientConnection = operation.getClientConnection();
076    if (clientConnection == null)
077    {
078      operation.setResultCode(ResultCode.UNAVAILABLE);
079      operation.appendErrorMessage(ERR_STARTTLS_NO_CLIENT_CONNECTION.get());
080      return;
081    }
082
083
084    // Make sure that the client connection is capable of enabling TLS.  If not,
085    // then fail.
086    TLSCapableConnection tlsCapableConnection;
087    if (clientConnection instanceof TLSCapableConnection)
088    {
089      tlsCapableConnection = (TLSCapableConnection) clientConnection;
090    }
091    else
092    {
093      operation.setResultCode(ResultCode.UNAVAILABLE);
094      operation.appendErrorMessage(ERR_STARTTLS_NOT_TLS_CAPABLE.get());
095      return;
096    }
097
098    LocalizableMessageBuilder unavailableReason = new LocalizableMessageBuilder();
099    if (! tlsCapableConnection.prepareTLS(unavailableReason))
100    {
101      operation.setResultCode(ResultCode.UNAVAILABLE);
102      operation.setErrorMessage(unavailableReason);
103      return;
104    }
105
106    // TLS was successfully enabled on the client connection, but we need to
107    // send the response in the clear.
108    operation.setResultCode(ResultCode.SUCCESS);
109  }
110
111  /** {@inheritDoc} */
112  @Override
113  public String getExtendedOperationOID()
114  {
115    return OID_START_TLS_REQUEST;
116  }
117
118  /** {@inheritDoc} */
119  @Override
120  public String getExtendedOperationName()
121  {
122    return "StartTLS";
123  }
124}