You cannot select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

291 lines
9.1 KiB
C

/*
* Copyright (c) 2016 The ZLToolKit project authors. All Rights Reserved.
*
* This file is part of ZLToolKit(https://github.com/ZLMediaKit/ZLToolKit).
*
* Use of this source code is governed by MIT license that can be found in the
* LICENSE file in the root of the source tree. All contributing project authors
* may be found in the AUTHORS file in the root of the source tree.
*/
#ifndef CRYPTO_SSLBOX_H_
#define CRYPTO_SSLBOX_H_
#include <mutex>
#include <string>
#include <functional>
#include "logger.h"
#include "List.h"
#include "util.h"
#include "Network/Buffer.h"
#include "ResourcePool.h"
typedef struct x509_st X509;
typedef struct evp_pkey_st EVP_PKEY;
typedef struct ssl_ctx_st SSL_CTX;
typedef struct ssl_st SSL;
typedef struct bio_st BIO;
namespace toolkit {
class SSL_Initor {
public:
friend class SSL_Box;
static SSL_Initor &Instance();
/**
*
* (cer使)
* ()
* @param pem_or_p12 pemp12
* @param server_mode
* @param password
* @param is_file pem_or_p12
* @param is_default
* Load public and private keys from a file or string
* The certificate file must contain both public and private keys (cer format certificates only include public keys, use the following method to load)
* The client can load the certificate by default (unless the server requires the client to provide a certificate)
* @param pem_or_p12 pem or p12 file path or file content string
* @param server_mode Whether it is in server mode
* @param password Private key encryption password
* @param is_file Whether the parameter pem_or_p12 is a file path
* @param is_default Whether it is the default certificate
* [AUTO-TRANSLATED:18cec755]
*/
bool loadCertificate(const std::string &pem_or_p12, bool server_mode = true, const std::string &password = "",
bool is_file = true, bool is_default = true);
/**
*
*
* @param ignore
* Whether to ignore invalid certificates
* Ignore by default, strongly not recommended!
* @param ignore Flag
* [AUTO-TRANSLATED:fd45125a]
*/
void ignoreInvalidCertificate(bool ignore = true);
/**
* ,CA使
*
* @param pem_p12_cer pemp12cer
* @param server_mode
* @param password pemp12
* @param is_file
* @return
* Trust a certain certificate, generally used for clients to trust self-signed certificates or certificates signed by self-signed CAs
* For example, if my client wants to trust a certificate I issued myself, we can only trust this certificate
* @param pem_p12_cer pem file or p12 file or cer file path or content
* @param server_mode Whether it is in server mode
* @param password pem or p12 certificate password
* @param is_file Whether it is a file path
* @return Whether the loading is successful
* [AUTO-TRANSLATED:9ace5400]
*/
bool trustCertificate(const std::string &pem_p12_cer, bool server_mode = false, const std::string &password = "",
bool is_file = true);
/**
*
* @param cer
* @param server_mode
* @return
* Trust a certain certificate
* @param cer Certificate public key
* @param server_mode Whether it is in server mode
* @return Whether the loading is successful
* [AUTO-TRANSLATED:557120dd]
*/
bool trustCertificate(X509 *cer, bool server_mode = false);
/**
* SSL_CTX
* @param vhost
* @param server_mode
* @return SSL_CTX
* Get the SSL_CTX object based on the virtual host
* @param vhost Virtual host name
* @param server_mode Whether it is in server mode
* @return SSL_CTX object
* [AUTO-TRANSLATED:4d771109]
*/
std::shared_ptr<SSL_CTX> getSSLCtx(const std::string &vhost, bool server_mode);
private:
SSL_Initor();
~SSL_Initor();
/**
* SSL
* Create an SSL object
* [AUTO-TRANSLATED:047a0b4c]
*/
std::shared_ptr<SSL> makeSSL(bool server_mode);
/**
* ssl context
* @param vhost
* @param ctx ssl context
* @param server_mode ssl context
* @param is_default
* Set the ssl context
* @param vhost Virtual host name
* @param ctx ssl context
* @param server_mode ssl context
* @param is_default Whether it is the default certificate
* [AUTO-TRANSLATED:265f3049]
*/
bool setContext(const std::string &vhost, const std::shared_ptr<SSL_CTX> &ctx, bool server_mode, bool is_default = true);
/**
* SSL_CTX
* @param ctx
* Set the default configuration for SSL_CTX
* @param ctx Object pointer
* [AUTO-TRANSLATED:1b3438d0]
*/
static void setupCtx(SSL_CTX *ctx);
std::shared_ptr<SSL_CTX> getSSLCtx_l(const std::string &vhost, bool server_mode);
std::shared_ptr<SSL_CTX> getSSLCtxWildcards(const std::string &vhost, bool server_mode);
/**
*
* Get the default virtual host
* [AUTO-TRANSLATED:e2430399]
*/
std::string defaultVhost(bool server_mode);
/**
* vhost name
* Callback function for completing vhost name matching
* [AUTO-TRANSLATED:f9973cfa]
*/
static int findCertificate(SSL *ssl, int *ad, void *arg);
private:
struct less_nocase {
bool operator()(const std::string &x, const std::string &y) const {
return strcasecmp(x.data(), y.data()) < 0;
}
};
private:
std::recursive_mutex _mtx;
std::string _default_vhost[2];
std::shared_ptr<SSL_CTX> _ctx_empty[2];
std::map<std::string, std::shared_ptr<SSL_CTX>, less_nocase> _ctxs[2];
std::map<std::string, std::shared_ptr<SSL_CTX>, less_nocase> _ctxs_wildcards[2];
};
////////////////////////////////////////////////////////////////////////////////////
class SSL_Box {
public:
SSL_Box(bool server_mode = true, bool enable = true, int buff_size = 32 * 1024);
~SSL_Box();
/**
*
* @param buffer
* Decrypts the received ciphertext after calling this function
* @param buffer Received ciphertext data
* [AUTO-TRANSLATED:7e8b1fc6]
*/
void onRecv(const Buffer::Ptr &buffer);
/**
*
* @param buffer
* Calls this function to encrypt the plaintext that needs to be encrypted
* @param buffer Plaintext data that needs to be encrypted
* [AUTO-TRANSLATED:9d386695]
*/
void onSend(Buffer::Ptr buffer);
/**
*
* @param cb
* Sets the callback to get the plaintext after decryption
* @param cb Callback object
* [AUTO-TRANSLATED:897359bc]
*/
void setOnDecData(const std::function<void(const Buffer::Ptr &)> &cb);
/**
*
* @param cb
* Sets the callback to get the ciphertext after encryption
* @param cb Callback object
* [AUTO-TRANSLATED:bb31b34b]
*/
void setOnEncData(const std::function<void(const Buffer::Ptr &)> &cb);
/**
* ssl
* Terminates SSL
* [AUTO-TRANSLATED:2ab06469]
*/
void shutdown();
/**
*
* Clears data
* [AUTO-TRANSLATED:62d4f400]
*/
void flush();
/**
*
* @param host
* @return
* Sets the virtual host name
* @param host Virtual host name
* @return Whether the operation was successful
* [AUTO-TRANSLATED:eebc1e2f]
*/
bool setHost(const char *host);
private:
void flushWriteBio();
void flushReadBio();
private:
bool _server_mode;
bool _send_handshake;
bool _is_flush = false;
int _buff_size;
BIO *_read_bio;
BIO *_write_bio;
std::shared_ptr<SSL> _ssl;
List <Buffer::Ptr> _buffer_send;
ResourcePool <BufferRaw> _buffer_pool;
std::function<void(const Buffer::Ptr &)> _on_dec;
std::function<void(const Buffer::Ptr &)> _on_enc;
};
} /* namespace toolkit */
#endif /* CRYPTO_SSLBOX_H_ */