Back to home page

EIC code displayed by LXR

 
 

    


File indexing completed on 2026-04-17 08:35:03

0001 /*
0002  * Licensed to the Apache Software Foundation (ASF) under one
0003  * or more contributor license agreements. See the NOTICE file
0004  * distributed with this work for additional information
0005  * regarding copyright ownership. The ASF licenses this file
0006  * to you under the Apache License, Version 2.0 (the
0007  * "License"); you may not use this file except in compliance
0008  * with the License. You may obtain a copy of the License at
0009  *
0010  *   http://www.apache.org/licenses/LICENSE-2.0
0011  *
0012  * Unless required by applicable law or agreed to in writing,
0013  * software distributed under the License is distributed on an
0014  * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
0015  * KIND, either express or implied. See the License for the
0016  * specific language governing permissions and limitations
0017  * under the License.
0018  */
0019 
0020 #ifndef _THRIFT_TRANSPORT_TSSLSOCKET_H_
0021 #define _THRIFT_TRANSPORT_TSSLSOCKET_H_ 1
0022 
0023 // Put this first to avoid WIN32 build failure
0024 #include <thrift/transport/TSocket.h>
0025 
0026 #include <openssl/ssl.h>
0027 #include <string>
0028 #include <thrift/concurrency/Mutex.h>
0029 
0030 namespace apache {
0031 namespace thrift {
0032 namespace transport {
0033 
0034 class AccessManager;
0035 class SSLContext;
0036 
0037 enum SSLProtocol {
0038   SSLTLS  = 0,  // Supports SSLv2 and SSLv3 handshake but only negotiates at TLSv1_0 or later.
0039 //SSLv2   = 1,  // HORRIBLY INSECURE!
0040   SSLv3   = 2,  // Supports SSLv3 only - also horribly insecure!
0041   TLSv1_0 = 3,  // Supports TLSv1_0 or later.
0042   TLSv1_1 = 4,  // Supports TLSv1_1 or later.
0043   TLSv1_2 = 5,  // Supports TLSv1_2 or later.
0044   LATEST  = TLSv1_2
0045 };
0046 
0047 #define TSSL_EINTR 0
0048 #define TSSL_DATA 1
0049 
0050 /**
0051  * Initialize OpenSSL library.  This function, or some other
0052  * equivalent function to initialize OpenSSL, must be called before
0053  * TSSLSocket is used.  If you set TSSLSocketFactory to use manual
0054  * OpenSSL initialization, you should call this function or otherwise
0055  * ensure OpenSSL is initialized yourself.
0056  */
0057 void initializeOpenSSL();
0058 /**
0059  * Cleanup OpenSSL library.  This function should be called to clean
0060  * up OpenSSL after use of OpenSSL functionality is finished.  If you
0061  * set TSSLSocketFactory to use manual OpenSSL initialization, you
0062  * should call this function yourself or ensure that whatever
0063  * initialized OpenSSL cleans it up too.
0064  */
0065 void cleanupOpenSSL();
0066 
0067 /**
0068  * OpenSSL implementation for SSL socket interface.
0069  */
0070 class TSSLSocket : public TSocket {
0071 public:
0072   ~TSSLSocket() override;
0073   /**
0074    * TTransport interface.
0075    */
0076   bool isOpen() const override;
0077   bool peek() override;
0078   void open() override;
0079   void close() override;
0080   bool hasPendingDataToRead() override;
0081   uint32_t read(uint8_t* buf, uint32_t len) override;
0082   void write(const uint8_t* buf, uint32_t len) override;
0083   uint32_t write_partial(const uint8_t* buf, uint32_t len) override;
0084   void flush() override;
0085   /**
0086   * Set whether to use client or server side SSL handshake protocol.
0087   *
0088   * @param flag  Use server side handshake protocol if true.
0089   */
0090   void server(bool flag) { server_ = flag; }
0091   /**
0092    * Determine whether the SSL socket is server or client mode.
0093    */
0094   bool server() const { return server_; }
0095   /**
0096    * Set AccessManager.
0097    *
0098    * @param manager  Instance of AccessManager
0099    */
0100   virtual void access(std::shared_ptr<AccessManager> manager) { access_ = manager; }
0101   /**
0102    * Set eventSafe flag if libevent is used.
0103    */
0104   void setLibeventSafe() { eventSafe_ = true; }
0105   /**
0106    * Determines whether SSL Socket is libevent safe or not.
0107    */
0108   bool isLibeventSafe() const { return eventSafe_; }
0109 
0110 protected:
0111   /**
0112    * Constructor.
0113    */
0114   TSSLSocket(std::shared_ptr<SSLContext> ctx, std::shared_ptr<TConfiguration> config = nullptr);
0115   /**
0116    * Constructor with an interrupt signal.
0117    */
0118   TSSLSocket(std::shared_ptr<SSLContext> ctx, std::shared_ptr<THRIFT_SOCKET> interruptListener,
0119             std::shared_ptr<TConfiguration> config = nullptr);
0120   /**
0121    * Constructor, create an instance of TSSLSocket given an existing socket.
0122    *
0123    * @param socket An existing socket
0124    */
0125   TSSLSocket(std::shared_ptr<SSLContext> ctx, THRIFT_SOCKET socket, std::shared_ptr<TConfiguration> config = nullptr);
0126   /**
0127    * Constructor, create an instance of TSSLSocket given an existing socket that can be interrupted.
0128    *
0129    * @param socket An existing socket
0130    */
0131   TSSLSocket(std::shared_ptr<SSLContext> ctx, THRIFT_SOCKET socket, std::shared_ptr<THRIFT_SOCKET> interruptListener,
0132             std::shared_ptr<TConfiguration> config = nullptr);
0133    /**
0134    * Constructor.
0135    *
0136    * @param host  Remote host name
0137    * @param port  Remote port number
0138    */
0139   TSSLSocket(std::shared_ptr<SSLContext> ctx, std::string host, int port, std::shared_ptr<TConfiguration> config = nullptr);
0140     /**
0141   * Constructor with an interrupt signal.
0142   *
0143   * @param host  Remote host name
0144   * @param port  Remote port number
0145   */
0146     TSSLSocket(std::shared_ptr<SSLContext> ctx, std::string host, int port, std::shared_ptr<THRIFT_SOCKET> interruptListener,
0147               std::shared_ptr<TConfiguration> config = nullptr);
0148   /**
0149    * Authorize peer access after SSL handshake completes.
0150    */
0151   virtual void authorize();
0152   /**
0153    * Initiate SSL handshake if not already initiated.
0154    */
0155   void initializeHandshake();
0156   /**
0157    * Initiate SSL handshake params.
0158    */
0159   void initializeHandshakeParams();
0160   /**
0161    * Check if  SSL handshake is completed or not.
0162    */
0163   bool checkHandshake();
0164   /**
0165    * Waits for an socket or shutdown event.
0166    *
0167    * @throw TTransportException::INTERRUPTED if interrupted is signaled.
0168    *
0169    * @return TSSL_EINTR if EINTR happened on the underlying socket
0170    *         TSSL_DATA  if data is available on the socket.
0171    */
0172   unsigned int waitForEvent(bool wantRead);
0173 
0174   bool server_;
0175   SSL* ssl_;
0176   std::shared_ptr<SSLContext> ctx_;
0177   std::shared_ptr<AccessManager> access_;
0178   friend class TSSLSocketFactory;
0179 
0180 private:
0181   bool handshakeCompleted_;
0182   int readRetryCount_;
0183   bool eventSafe_;
0184 
0185   void init();
0186 };
0187 
0188 /**
0189  * SSL socket factory. SSL sockets should be created via SSL factory.
0190  * The factory will automatically initialize and cleanup openssl as long as
0191  * there is a TSSLSocketFactory instantiated, and as long as the static
0192  * boolean manualOpenSSLInitialization_ is set to false, the default.
0193  *
0194  * If you would like to initialize and cleanup openssl yourself, set
0195  * manualOpenSSLInitialization_ to true and TSSLSocketFactory will no
0196  * longer be responsible for openssl initialization and teardown.
0197  *
0198  * It is the responsibility of the code using TSSLSocketFactory to
0199  * ensure that the factory lifetime exceeds the lifetime of any sockets
0200  * it might create.  If this is not guaranteed, a socket may call into
0201  * openssl after the socket factory has cleaned up openssl!  This
0202  * guarantee is unnecessary if manualOpenSSLInitialization_ is true,
0203  * however, since it would be up to the consuming application instead.
0204  */
0205 class TSSLSocketFactory {
0206 public:
0207   /**
0208    * Constructor/Destructor
0209    *
0210    * @param protocol The SSL/TLS protocol to use.
0211    */
0212   TSSLSocketFactory(SSLProtocol protocol = SSLTLS);
0213   virtual ~TSSLSocketFactory();
0214   /**
0215    * Create an instance of TSSLSocket with a fresh new socket.
0216    */
0217   virtual std::shared_ptr<TSSLSocket> createSocket();
0218   /**
0219    * Create an instance of TSSLSocket with a fresh new socket, which is interruptable.
0220    */
0221   virtual std::shared_ptr<TSSLSocket> createSocket(std::shared_ptr<THRIFT_SOCKET> interruptListener);
0222   /**
0223    * Create an instance of TSSLSocket with the given socket.
0224    *
0225    * @param socket An existing socket.
0226    */
0227   virtual std::shared_ptr<TSSLSocket> createSocket(THRIFT_SOCKET socket);
0228   /**
0229    * Create an instance of TSSLSocket with the given socket which is interruptable.
0230    *
0231    * @param socket An existing socket.
0232    */
0233   virtual std::shared_ptr<TSSLSocket> createSocket(THRIFT_SOCKET socket, std::shared_ptr<THRIFT_SOCKET> interruptListener);
0234   /**
0235   * Create an instance of TSSLSocket.
0236   *
0237   * @param host  Remote host to be connected to
0238   * @param port  Remote port to be connected to
0239   */
0240   virtual std::shared_ptr<TSSLSocket> createSocket(const std::string& host, int port);
0241   /**
0242   * Create an instance of TSSLSocket.
0243   *
0244   * @param host  Remote host to be connected to
0245   * @param port  Remote port to be connected to
0246   */
0247   virtual std::shared_ptr<TSSLSocket> createSocket(const std::string& host, int port, std::shared_ptr<THRIFT_SOCKET> interruptListener);
0248   /**
0249    * Set ciphers to be used in SSL handshake process.
0250    *
0251    * @param ciphers  A list of ciphers
0252    */
0253   virtual void ciphers(const std::string& enable);
0254   /**
0255    * Enable/Disable authentication.
0256    *
0257    * @param required Require peer to present valid certificate if true
0258    */
0259   virtual void authenticate(bool required);
0260   /**
0261    * Load server certificate.
0262    *
0263    * @param path   Path to the certificate file
0264    * @param format Certificate file format
0265    */
0266   virtual void loadCertificate(const char* path, const char* format = "PEM");
0267   virtual void loadCertificateFromBuffer(const char* aCertificate, const char* format = "PEM");
0268   /**
0269    * Load private key.
0270    *
0271    * @param path   Path to the private key file
0272    * @param format Private key file format
0273    */
0274   virtual void loadPrivateKey(const char* path, const char* format = "PEM");
0275   virtual void loadPrivateKeyFromBuffer(const char* aPrivateKey, const char* format = "PEM");
0276   /**
0277    * Load trusted certificates from specified file.
0278    *
0279    * @param path Path to trusted certificate file
0280    */
0281   virtual void loadTrustedCertificates(const char* path, const char* capath = nullptr);
0282   virtual void loadTrustedCertificatesFromBuffer(const char* aCertificate, const char* aChain = nullptr);
0283   /**
0284    * Default randomize method.
0285    */
0286   virtual void randomize();
0287   /**
0288    * Override default OpenSSL password callback with getPassword().
0289    */
0290   void overrideDefaultPasswordCallback();
0291   /**
0292    * Set/Unset server mode.
0293    *
0294    * @param flag  Server mode if true
0295    */
0296   virtual void server(bool flag) { server_ = flag; }
0297   /**
0298    * Determine whether the socket is in server or client mode.
0299    *
0300    * @return true, if server mode, or, false, if client mode
0301    */
0302   virtual bool server() const { return server_; }
0303   /**
0304    * Set AccessManager.
0305    *
0306    * @param manager  The AccessManager instance
0307    */
0308   virtual void access(std::shared_ptr<AccessManager> manager) { access_ = manager; }
0309   static void setManualOpenSSLInitialization(bool manualOpenSSLInitialization) {
0310     manualOpenSSLInitialization_ = manualOpenSSLInitialization;
0311   }
0312 
0313 protected:
0314   std::shared_ptr<SSLContext> ctx_;
0315 
0316   /**
0317    * Override this method for custom password callback. It may be called
0318    * multiple times at any time during a session as necessary.
0319    *
0320    * @param password Pass collected password to OpenSSL
0321    * @param size     Maximum length of password including NULL character
0322    */
0323   virtual void getPassword(std::string& /* password */, int /* size */) {}
0324 
0325 private:
0326   bool server_;
0327   std::shared_ptr<AccessManager> access_;
0328   static concurrency::Mutex mutex_;
0329   static uint64_t count_;
0330   THRIFT_EXPORT static bool manualOpenSSLInitialization_;
0331   void setup(std::shared_ptr<TSSLSocket> ssl);
0332   static int passwordCallback(char* password, int size, int, void* data);
0333 };
0334 
0335 /**
0336  * SSL exception.
0337  */
0338 class TSSLException : public TTransportException {
0339 public:
0340   TSSLException(const std::string& message)
0341     : TTransportException(TTransportException::INTERNAL_ERROR, message) {}
0342 
0343   const char* what() const noexcept override {
0344     if (message_.empty()) {
0345       return "TSSLException";
0346     } else {
0347       return message_.c_str();
0348     }
0349   }
0350 };
0351 
0352 /**
0353  * Wrap OpenSSL SSL_CTX into a class.
0354  */
0355 class SSLContext {
0356 public:
0357   SSLContext(const SSLProtocol& protocol = SSLTLS);
0358   virtual ~SSLContext();
0359   SSL* createSSL();
0360   SSL_CTX* get() { return ctx_; }
0361 
0362 private:
0363   SSL_CTX* ctx_;
0364 };
0365 
0366 /**
0367  * Callback interface for access control. It's meant to verify the remote host.
0368  * It's constructed when application starts and set to TSSLSocketFactory
0369  * instance. It's passed onto all TSSLSocket instances created by this factory
0370  * object.
0371  */
0372 class AccessManager {
0373 public:
0374   enum Decision {
0375     DENY = -1, // deny access
0376     SKIP = 0,  // cannot make decision, move on to next (if any)
0377     ALLOW = 1  // allow access
0378   };
0379   /**
0380    * Destructor
0381    */
0382   virtual ~AccessManager() = default;
0383   /**
0384    * Determine whether the peer should be granted access or not. It's called
0385    * once after the SSL handshake completes successfully, before peer certificate
0386    * is examined.
0387    *
0388    * If a valid decision (ALLOW or DENY) is returned, the peer certificate is
0389    * not to be verified.
0390    *
0391    * @param  sa Peer IP address
0392    * @return True if the peer is trusted, false otherwise
0393    */
0394   virtual Decision verify(const sockaddr_storage& /* sa */) noexcept { return DENY; }
0395   /**
0396    * Determine whether the peer should be granted access or not. It's called
0397    * every time a DNS subjectAltName/common name is extracted from peer's
0398    * certificate.
0399    *
0400    * @param  host Client mode: host name returned by TSocket::getHost()
0401    *              Server mode: host name returned by TSocket::getPeerHost()
0402    * @param  name SubjectAltName or common name extracted from peer certificate
0403    * @param  size Length of name
0404    * @return True if the peer is trusted, false otherwise
0405    *
0406    * Note: The "name" parameter may be UTF8 encoded.
0407    */
0408   virtual Decision verify(const std::string& /* host */,
0409                           const char* /* name */,
0410                           int /* size */) noexcept {
0411     return DENY;
0412   }
0413   /**
0414    * Determine whether the peer should be granted access or not. It's called
0415    * every time an IP subjectAltName is extracted from peer's certificate.
0416    *
0417    * @param  sa   Peer IP address retrieved from the underlying socket
0418    * @param  data IP address extracted from certificate
0419    * @param  size Length of the IP address
0420    * @return True if the peer is trusted, false otherwise
0421    */
0422   virtual Decision verify(const sockaddr_storage& /* sa */,
0423                           const char* /* data */,
0424                           int /* size */) noexcept {
0425     return DENY;
0426   }
0427 };
0428 
0429 typedef AccessManager::Decision Decision;
0430 
0431 class DefaultClientAccessManager : public AccessManager {
0432 public:
0433   // AccessManager interface
0434   Decision verify(const sockaddr_storage& sa) noexcept override;
0435   Decision verify(const std::string& host, const char* name, int size) noexcept override;
0436   Decision verify(const sockaddr_storage& sa, const char* data, int size) noexcept override;
0437 };
0438 }
0439 }
0440 }
0441 
0442 #endif