diff --git a/src/plugins/SSLPlugin/my_ssl.c b/src/plugins/SSLPlugin/my_ssl.c index 5ffb11c..ee472c0 100644 --- a/src/plugins/SSLPlugin/my_ssl.c +++ b/src/plugins/SSLPlugin/my_ssl.c @@ -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); diff --git a/src/plugins/SSLPlugin/my_ssl.h b/src/plugins/SSLPlugin/my_ssl.h index c87f43b..14d174a 100644 --- a/src/plugins/SSLPlugin/my_ssl.h +++ b/src/plugins/SSLPlugin/my_ssl.h @@ -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 diff --git a/src/plugins/SSLPlugin/ssl_plugin.c b/src/plugins/SSLPlugin/ssl_plugin.c index cd6590f..f3f644f 100644 --- a/src/plugins/SSLPlugin/ssl_plugin.c +++ b/src/plugins/SSLPlugin/ssl_plugin.c @@ -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; }