Added multiple TLS configuration parameters for SSLPlugin

ssl_client_ciphersuites - TLS client ciphers for TLS 1.3, e.g. ssl_client_ciphersuites TLS_AES_128_GCM_SHA256
ssl_server_ciphersuites - TLS server ciphers for TLS 1.3
ssl_client_cipher_list - TLS client ciphers for TLS 1.2 and below , e.g. ssl_client_cipher_list ECDHE-ECDSA-AES128-GCM-SHA256:ECDHE-RSA-AES128-GCM-SHA256:ECDHE-ECDSA-AES256-GCM-SHA384:ECDHE-RSA-AES256-GCM-SHA384:ECDHE-ECDSA-CHACHA20-POLY1305:ECDHE-RSA-CHACHA20-POLY1305:DHE-RSA-AES128-GCM-SHA256:DHE-RSA-AES256-GCM-SHA384:DHE-RSA-CHACHA20-POLY1305
ssl_server_cipher_list - TLS server ciphers for TLS 1.2 and below
ssl_client_min_proto_version - TLS client min TLS version (e.g. TLSv1.2)
ssl_server_min_proto_version - TLS server min TLS version (e.g. TLSv1.2)
ssl_client_max_proto_version - TLS client max TLS version (e.g. TLSv1.2)
ssl_server_max_proto_version - TLS server max TLS version (e.g. TLSv1.2)
ssl_client_verify - verify certificate for upstream server in TLS client functionality
ssl_client_no_verify - do not verify certificate for upstream server in TLS client functionality (default)
This commit is contained in:
Vladimir Dubrovin 2024-03-10 13:36:40 +03:00
parent d87241c487
commit a316622a85
3 changed files with 196 additions and 21 deletions

View File

@ -180,7 +180,7 @@ SSL_CERT ssl_copy_cert(SSL_CERT cert, SSL_CONFIG *config)
}
SSL_CONN ssl_handshake_to_server(SOCKET s, char * hostname, SSL_CTX *srv_ctx, SSL_CERT *server_cert, char **errSSL)
SSL_CONN ssl_handshake_to_server(SOCKET s, char * hostname, SSL_CONFIG *config, SSL_CERT *server_cert, char **errSSL)
{
int err = 0;
X509 *cert;
@ -193,11 +193,17 @@ SSL_CONN ssl_handshake_to_server(SOCKET s, char * hostname, SSL_CTX *srv_ctx, SS
return NULL;
}
conn->ctx = NULL;
conn->ssl = SSL_new(srv_ctx);
conn->ssl = SSL_new(config->srv_ctx);
if ( conn->ssl == NULL ) {
free(conn);
return NULL;
}
if(config->client_verify){
X509_VERIFY_PARAM *param;
param = SSL_get0_param(conn->ssl);
X509_VERIFY_PARAM_set1_host(param, hostname, strlen(hostname));
}
if(!SSL_set_fd(conn->ssl, s)){
ssl_conn_free(conn);
@ -226,7 +232,7 @@ SSL_CONN ssl_handshake_to_server(SOCKET s, char * hostname, SSL_CTX *srv_ctx, SS
}
SSL_CTX * ssl_cli_ctx(SSL_CERT server_cert, EVP_PKEY *server_key, char** errSSL){
SSL_CTX * ssl_cli_ctx(SSL_CONFIG *config, X509 *server_cert, EVP_PKEY *server_key, char** errSSL){
SSL_CTX *ctx;
int err = 0;
@ -254,10 +260,14 @@ SSL_CTX * ssl_cli_ctx(SSL_CERT server_cert, EVP_PKEY *server_key, char** errSSL)
SSL_CTX_free(ctx);
return NULL;
}
if(config->server_min_proto_version)SSL_CTX_set_min_proto_version(ctx, config->server_min_proto_version);
if(config->server_max_proto_version)SSL_CTX_set_max_proto_version(ctx, config->server_max_proto_version);
if(config->server_cipher_list)SSL_CTX_set_cipher_list(ctx, config->server_cipher_list);
if(config->server_ciphersuites)SSL_CTX_set_ciphersuites(ctx, config->server_ciphersuites);
return ctx;
}
SSL_CONN ssl_handshake_to_client(SOCKET s, SSL_CTX *cli_ctx, SSL_CERT server_cert, EVP_PKEY *server_key, char** errSSL){
SSL_CONN ssl_handshake_to_client(SOCKET s, SSL_CONFIG *config, X509 *server_cert, EVP_PKEY *server_key, char** errSSL){
int err = 0;
X509 *cert;
ssl_conn *conn;
@ -270,15 +280,15 @@ SSL_CONN ssl_handshake_to_client(SOCKET s, SSL_CTX *cli_ctx, SSL_CERT server_cer
conn->ctx = NULL;
conn->ssl = NULL;
if(!cli_ctx){
conn->ctx = ssl_cli_ctx(server_cert, server_key, errSSL);
if(!config->cli_ctx){
conn->ctx = ssl_cli_ctx(config, server_cert, server_key, errSSL);
if(!conn->ctx){
ssl_conn_free(conn);
return NULL;
}
}
conn->ssl = SSL_new(cli_ctx?cli_ctx : conn->ctx);
conn->ssl = SSL_new(config->cli_ctx?config->cli_ctx : conn->ctx);
if ( conn->ssl == NULL ) {
*errSSL = ERR_error_string(ERR_get_error(), errbuf);
if(conn->ctx)SSL_CTX_free(conn->ctx);

View File

@ -20,6 +20,15 @@ struct ssl_config {
EVP_PKEY *server_key;
SSL_CTX *cli_ctx;
SSL_CTX *srv_ctx;
int client_min_proto_version;
int client_max_proto_version;
int server_min_proto_version;
int server_max_proto_version;
int client_verify;
char * client_ciphersuites;
char * server_ciphersuites;
char * client_cipher_list;
char * server_cipher_list;
};
typedef struct ssl_config SSL_CONFIG;
@ -33,9 +42,9 @@ SSL_CERT ssl_copy_cert(SSL_CERT cert, SSL_CONFIG *config);
//
// SSL/TLS handshakes
//
SSL_CTX * ssl_cli_ctx(SSL_CERT server_cert, EVP_PKEY *server_key, char** errSSL);
SSL_CONN ssl_handshake_to_server(SOCKET s, char * hostname, SSL_CTX *srv_ctx, SSL_CERT *server_cert, char **errSSL);
SSL_CONN ssl_handshake_to_client(SOCKET s, SSL_CTX *cli_ctx, SSL_CERT server_cert, EVP_PKEY *server_key, char **errSSL);
SSL_CTX * ssl_cli_ctx(SSL_CONFIG *config, X509 *server_cert, EVP_PKEY *server_key,char** errSSL);
SSL_CONN ssl_handshake_to_client(SOCKET s, SSL_CONFIG *config, X509 *server_cert, EVP_PKEY *server_key, char **errSSL);
SSL_CONN ssl_handshake_to_server(SOCKET s, char * hostname, SSL_CONFIG *config, SSL_CERT *server_cert, char **errSSL);
//
// SSL/TLS Read/Write

View File

@ -34,11 +34,20 @@ static struct pluginlink * pl;
static int ssl_loaded = 0;
static int ssl_connect_timeout = 0;
char *certcache = NULL;
char *srvcert;
char *srvkey;
char *srvcert = NULL;
char *srvkey = NULL;
int mitm = 0;
int serv = 0;
int ssl_inited = 0;
int client_min_proto_version = 0;
int client_max_proto_version = 0;
int server_min_proto_version = 0;
int server_max_proto_version = 0;
int client_verify = 0;
char * client_ciphersuites = NULL;
char * server_ciphersuites = NULL;
char * client_cipher_list = NULL;
char * server_cipher_list = NULL;
typedef struct _ssl_conn {
struct SSL_CTX *ctx;
@ -238,7 +247,7 @@ int domitm(struct clientparam* param){
ul = ((unsigned long)ssl_connect_timeout)*1000;
setsockopt(param->remsock, SOL_SOCKET, SO_SNDTIMEO, (char *)&ul, 4);
}
ServerConn = ssl_handshake_to_server(param->remsock, (char *)param->hostname, PCONF->srv_ctx, &ServerCert, &errSSL);
ServerConn = ssl_handshake_to_server(param->remsock, (char *)param->hostname, PCONF, &ServerCert, &errSSL);
if ( ServerConn == NULL || ServerCert == NULL ) {
if(ServerConn) ssl_conn_free(ServerConn);
param->res = 8011;
@ -257,7 +266,7 @@ int domitm(struct clientparam* param){
return 2;
}
ClientConn = ssl_handshake_to_client(param->clisock, NULL, FakeCert, PCONF->server_key?PCONF->server_key:PCONF->CA_key, &errSSL);
ClientConn = ssl_handshake_to_client(param->clisock, PCONF, FakeCert, PCONF->server_key?PCONF->server_key:PCONF->CA_key, &errSSL);
_ssl_cert_free(FakeCert);
if ( ClientConn == NULL ) {
@ -311,6 +320,10 @@ EVP_PKEY * getKey(const char *fname){
return key;
}
static int verify_callback(int preverify_ok, X509_STORE_CTX *ctx){
return preverify_ok;
}
static void* ssl_filter_open(void * idata, struct srvparam * srv){
char fname[256];
char *errSSL;
@ -319,6 +332,16 @@ static void* ssl_filter_open(void * idata, struct srvparam * srv){
if(!sc) return NULL;
memset(sc, 0, sizeof(struct ssl_config));
if(certcache) sc->certcache = strdup(certcache);
sc->client_min_proto_version = client_min_proto_version;
sc->client_max_proto_version = client_max_proto_version;
sc->server_min_proto_version = server_min_proto_version;
sc->server_max_proto_version = server_max_proto_version;
sc->client_verify = client_verify;
if(client_ciphersuites) sc->client_ciphersuites = strdup(client_ciphersuites);
if(server_ciphersuites) sc->server_ciphersuites = strdup(server_ciphersuites);
if(client_cipher_list) sc->client_cipher_list = strdup(client_cipher_list);
if(server_cipher_list) sc->server_cipher_list = strdup(server_cipher_list);
if(mitm){
if(!certcache) {
return sc;
@ -360,7 +383,7 @@ static void* ssl_filter_open(void * idata, struct srvparam * srv){
fprintf(stderr, "failed to read: %s\n", srvkey);
return sc;
}
if(!(sc->cli_ctx = ssl_cli_ctx(sc->server_cert, sc->server_key, &errSSL))){
if(!(sc->cli_ctx = ssl_cli_ctx(sc, sc->server_cert, sc->server_key, &errSSL))){
fprintf(stderr, "failed to create context: %s\n", errSSL);
return sc;
}
@ -384,6 +407,14 @@ static void* ssl_filter_open(void * idata, struct srvparam * srv){
if ( sc->srv_ctx == NULL ) {
sc->mitm = 0;
}
if(sc->client_min_proto_version)SSL_CTX_set_min_proto_version(sc->srv_ctx, sc->client_min_proto_version);
if(sc->client_max_proto_version)SSL_CTX_set_max_proto_version(sc->srv_ctx, sc->client_max_proto_version);
if(sc->client_cipher_list)SSL_CTX_set_cipher_list(sc->srv_ctx, sc->client_cipher_list);
if(sc->client_ciphersuites)SSL_CTX_set_ciphersuites(sc->srv_ctx, sc->client_ciphersuites);
if(sc->client_verify){
SSL_CTX_set_verify(sc->srv_ctx, SSL_VERIFY_PEER, verify_callback);
SSL_CTX_set_default_verify_paths(sc->srv_ctx);
}
}
return sc;
}
@ -410,7 +441,7 @@ static FILTER_ACTION ssl_filter_client(void *fo, struct clientparam * param, voi
fcntl(param->clisock,F_SETFL,0);
#endif
ClientConn = ssl_handshake_to_client(param->clisock, ssls->config->cli_ctx, NULL, NULL, &err);
ClientConn = ssl_handshake_to_client(param->clisock, ssls->config, NULL, NULL, &err);
if ( ClientConn == NULL ) {
param->res = 8013;
param->srv->logfunc(param, (unsigned char *)"Handshake to client failed");
@ -469,6 +500,10 @@ static void ssl_filter_close(void *fo){
if ( CONFIG->cli_ctx != NULL ) {
SSL_CTX_free(CONFIG->cli_ctx);
}
free(CONFIG->client_ciphersuites);
free(CONFIG->server_ciphersuites);
free(CONFIG->client_cipher_list);
free(CONFIG->server_cipher_list);
free(fo);
}
@ -555,13 +590,103 @@ static int h_certcache(int argc, unsigned char **argv){
static int h_srvcert(int argc, unsigned char **argv){
free(srvcert);
srvcert = strdup((char *)argv[1]);
srvcert = argc > 1? strdup((char *)argv[1]) : NULL;
return 0;
}
static int h_srvkey(int argc, unsigned char **argv){
free(srvkey);
srvkey = strdup((char *)argv[1]);
srvkey = argc > 1? strdup((char *)argv[1]) : NULL;
return 0;
}
static int h_client_cipher_list(int argc, unsigned char **argv){
free(client_cipher_list);
client_cipher_list = argc > 1? strdup((char *)argv[1]) : NULL;
return 0;
}
static int h_server_cipher_list(int argc, unsigned char **argv){
free(server_cipher_list);
server_cipher_list = argc > 1? strdup((char *)argv[1]) : NULL;
return 0;
}
static int h_client_ciphersuites(int argc, unsigned char **argv){
free(client_ciphersuites);
client_ciphersuites = argc > 1? strdup((char *)argv[1]) : NULL;
return 0;
}
static int h_server_ciphersuites(int argc, unsigned char **argv){
free(server_ciphersuites);
server_ciphersuites = argc > 1? strdup((char *)argv[1]) : NULL;
return 0;
}
struct vermap{
char *sver;
int iver;
} versions[] = {
#ifdef SSL3_VERSION
{"SSLv3",SSL3_VERSION},
#endif
#ifdef TLS1_VERSION
{"TLSv1",TLS1_VERSION},
#endif
#ifdef TLS1_1_VERSION
{"TLSv1.1",TLS1_1_VERSION},
#endif
#ifdef TLS1_2_VERSION
{"TLSv1.2",TLS1_2_VERSION},
#endif
#ifdef TLS1_3_VERSION
{"TLSv1.3",TLS1_3_VERSION},
#endif
{NULL, 0}
};
int string_to_version(unsigned char *ver){
struct vermap *v;
int i;
int res;
for (i=0; versions[i].sver; i++){
if(!strcasecmp(versions[i].sver, (char *)ver)) return versions[i].iver;
}
return 0;
}
static int h_client_min_proto_version(int argc, unsigned char **argv){
client_min_proto_version = argc>1? string_to_version(argv[1]) : 0;
return 0;
}
static int h_client_max_proto_version(int argc, unsigned char **argv){
client_max_proto_version = argc>1? string_to_version(argv[1]) : 0;
return 0;
}
static int h_server_min_proto_version(int argc, unsigned char **argv){
server_min_proto_version = argc>1? string_to_version(argv[1]) : 0;
return 0;
}
static int h_server_max_proto_version(int argc, unsigned char **argv){
server_max_proto_version = argc>1? string_to_version(argv[1]) : 0;
return 0;
}
static int h_client_verify(int argc, unsigned char **argv){
client_verify = 1;
return 0;
}
static int h_no_client_verify(int argc, unsigned char **argv){
client_verify = 0;
return 0;
}
@ -570,8 +695,18 @@ static struct commands ssl_commandhandlers[] = {
{ssl_commandhandlers+2, "ssl_nomitm", h_nomitm, 1, 1},
{ssl_commandhandlers+3, "ssl_serv", h_serv, 1, 1},
{ssl_commandhandlers+4, "ssl_noserv", h_serv, 1, 1},
{ssl_commandhandlers+5, "ssl_srvcert", h_srvcert, 2, 2},
{ssl_commandhandlers+6, "ssl_srvkey", h_srvkey, 2, 2},
{ssl_commandhandlers+5, "ssl_srvcert", h_srvcert, 1, 2},
{ssl_commandhandlers+6, "ssl_srvkey", h_srvkey, 1, 2},
{ssl_commandhandlers+7, "ssl_client_ciphersuites", h_client_ciphersuites, 1, 2},
{ssl_commandhandlers+8, "ssl_server_ciphersuites", h_server_ciphersuites, 1, 2},
{ssl_commandhandlers+9, "ssl_client_cipher_list", h_client_cipher_list, 1, 2},
{ssl_commandhandlers+10, "ssl_server_cipher_list", h_server_cipher_list, 1, 2},
{ssl_commandhandlers+11, "ssl_client_min_proto_version", h_client_min_proto_version, 1, 2},
{ssl_commandhandlers+12, "ssl_server_min_proto_version", h_server_min_proto_version, 1, 2},
{ssl_commandhandlers+13, "ssl_client_max_proto_version", h_client_max_proto_version, 1, 2},
{ssl_commandhandlers+14, "ssl_server_max_proto_version", h_server_max_proto_version, 1, 2},
{ssl_commandhandlers+15, "ssl_client_verify", h_client_verify, 1, 1},
{ssl_commandhandlers+16, "ssl_client_no_verify", h_no_client_verify, 1, 1},
{NULL, "ssl_certcache", h_certcache, 2, 2},
};
@ -586,10 +721,31 @@ PLUGINAPI int PLUGINCALL ssl_plugin (struct pluginlink * pluginlink,
int argc, char** argv){
pl = pluginlink;
ssl_connect_timeout = 0;
free(certcache);
certcache = NULL;
free(srvcert);
srvcert = NULL;
free(srvkey);
srvkey = NULL;
mitm = 0;
serv = 0;
client_min_proto_version = 0;
client_max_proto_version = 0;
server_min_proto_version = 0;
server_max_proto_version = 0;
client_verify = 0;
client_ciphersuites = NULL;
server_ciphersuites = NULL;
client_cipher_list = NULL;
server_cipher_list = NULL;
if(!ssl_loaded){
ssl_loaded = 1;
ssl_init();
ssl_commandhandlers[6].next = pl->commandhandlers->next;
ssl_commandhandlers[(sizeof(ssl_commandhandlers)/sizeof(struct commands))-1].next = pl->commandhandlers->next;
pl->commandhandlers->next = ssl_commandhandlers;
}