/* * Copyright (c) Meta Platforms, Inc. and affiliates. * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. */ #pragma once #include #include #include #include #include #include namespace apache { namespace thrift { namespace detail { THRIFT_PLUGGABLE_FUNC_DECLARE( void, setSockOptStopTLS, folly::AsyncSocketTransport&); } // namespace detail class ThriftParametersContext; /** * ThriftFizzAcceptorHandshakeHelper represents a single asynchronous Fizz * handshake. It has Thrift specific functionality such as including * a Thrift extension in the handshake and managing StopTLS negotiations. * * IMPLEMENTATION NOTES: * To fulfill the AcceptorHandshakeHelper contract as documented in wangle, * we must ensure that we always send either a `connectionReady()` or * `connectionError()` during the lifetime of this helper object. * * `dropConnection()` is inherited from the parent, which will close the * underlying socket. To fulfill our promises to the Handshake Manager, we * just need to ensure that at any time while this object lives, if we close * the underlying socket, this will result in some error being propagated. * * If the socket is closed: * * During the initial TLS handshake, this results in a fizzHandshakeErr * firing, which will trigger a connectionError(). * * If we are performing StopTLS, and we receive a `dropConnection()` after * the initial TLS handshake but before the peer close_notify arrives, then * we rely on `AsyncStopTLS` to receive a `readErr()` which will fire * `stopTLSError()` which will fire `connectionError()` */ class ThriftFizzAcceptorHandshakeHelper : public wangle::FizzAcceptorHandshakeHelper, private AsyncStopTLS::Callback { public: ThriftFizzAcceptorHandshakeHelper( std::shared_ptr context, std::shared_ptr sslContextManager, const folly::SocketAddress& clientAddr, std::chrono::steady_clock::time_point acceptTime, wangle::TransportInfo& tinfo, wangle::FizzHandshakeOptions&& options, fizz::AsyncFizzBase::TransportOptions transportOptions) : wangle::FizzAcceptorHandshakeHelper::FizzAcceptorHandshakeHelper( std::move(context), std::move(sslContextManager), clientAddr, acceptTime, tinfo, std::move(options), transportOptions) {} void start( folly::AsyncSSLSocket::UniquePtr sock, wangle::AcceptorHandshakeHelper::Callback* callback) noexcept override; void setThriftParametersContext( std::shared_ptr context) { thriftParametersContext_ = std::move(context); } private: // AsyncFizzServer::HandshakeCallback API void fizzHandshakeSuccess( fizz::server::AsyncFizzServer* transport) noexcept override; // Invoked by AsyncStopTLS when StopTLS downgrade completes successfully void stopTLSSuccess(std::unique_ptr endOfData) override; // Invoked by AsyncStopTLS when StopTLS downgrade was interrupted or did // not finish successfully. void stopTLSError(const folly::exception_wrapper& ew) override { callback_->connectionError(transport_.get(), ew, sslError_); } std::shared_ptr thriftParametersContext_; std::shared_ptr thriftExtension_; AsyncStopTLS::UniquePtr stopTLSAsyncFrame_; }; /** * FizzPeeker is a specialization of the default wangle Fizz peeker that returns * a handshake helper that includes Thrift specific behavior, such as sending * custom Thrift extension and implementing StopTLS. * * TODO: This can be generalized into wangle. */ class FizzPeeker : public wangle::DefaultToFizzPeekingCallback { public: using DefaultToFizzPeekingCallback::DefaultToFizzPeekingCallback; wangle::AcceptorHandshakeHelper::UniquePtr getHelper( const std::vector& /* bytes */, const folly::SocketAddress& clientAddr, std::chrono::steady_clock::time_point acceptTime, wangle::TransportInfo& tinfo) override; folly::DelayedDestructionUniquePtr getThriftHelper( const std::vector& /* bytes */, const folly::SocketAddress& clientAddr, std::chrono::steady_clock::time_point acceptTime, wangle::TransportInfo& tinfo); }; } // namespace thrift } // namespace apache