initial commit to TLS refactoring

This commit is contained in:
Vladimir Dubrovin 2024-02-18 19:07:09 +03:00
parent d162ad5c38
commit 6dc145b16b
3 changed files with 210 additions and 208 deletions

View File

@ -32,11 +32,6 @@ typedef struct _ssl_conn {
SSL *ssl; SSL *ssl;
} ssl_conn; } ssl_conn;
static X509 *CA_cert = NULL;
static EVP_PKEY *CA_key = NULL;
static EVP_PKEY *server_key = NULL;
static X509_NAME *name = NULL;
pthread_mutex_t ssl_file_mutex; pthread_mutex_t ssl_file_mutex;
@ -91,8 +86,6 @@ static int add_ext(X509 *cert, int nid, char *value)
return 1; return 1;
} }
extern char *cert_path;
void del_ext(X509 *dst_cert, int nid, int where){ void del_ext(X509 *dst_cert, int nid, int where){
int ex; int ex;
@ -104,7 +97,7 @@ void del_ext(X509 *dst_cert, int nid, int where){
} }
SSL_CERT ssl_copy_cert(SSL_CERT cert) SSL_CERT ssl_copy_cert(SSL_CERT cert, SSL_CONFIG *config)
{ {
int err = -1; int err = -1;
BIO *fcache; BIO *fcache;
@ -114,12 +107,8 @@ SSL_CERT ssl_copy_cert(SSL_CERT cert)
EVP_PKEY *pk = NULL; EVP_PKEY *pk = NULL;
RSA *rsa = NULL; RSA *rsa = NULL;
unsigned char p1[] = "RU";
unsigned char p2[] = "3proxy";
unsigned char p3[] = "3proxy CA";
int hash_size = 20; int hash_size = 20;
char hash_sha1[20]; unsigned char hash_sha1[20];
char hash_name_sha1[(20*2) + 1]; char hash_name_sha1[(20*2) + 1];
char cache_name[256]; char cache_name[256];
@ -130,7 +119,7 @@ SSL_CERT ssl_copy_cert(SSL_CERT cert)
} }
bin2hex(hash_sha1, 20, hash_name_sha1, sizeof(hash_name_sha1)); bin2hex(hash_sha1, 20, hash_name_sha1, sizeof(hash_name_sha1));
sprintf(cache_name, "%s%s.pem", cert_path, hash_name_sha1); sprintf(cache_name, "%s%s.pem", config->certcache, hash_name_sha1);
/* check if certificate is already cached */ /* check if certificate is already cached */
fcache = BIO_new_file(cache_name, "rb"); fcache = BIO_new_file(cache_name, "rb");
if ( fcache != NULL ) { if ( fcache != NULL ) {
@ -157,19 +146,19 @@ SSL_CERT ssl_copy_cert(SSL_CERT cert)
del_ext(dst_cert, NID_authority_key_identifier, -1); del_ext(dst_cert, NID_authority_key_identifier, -1);
del_ext(dst_cert, NID_certificate_policies, 0); del_ext(dst_cert, NID_certificate_policies, 0);
err = X509_set_pubkey(dst_cert, server_key); err = X509_set_pubkey(dst_cert, config->server_key);
if ( err == 0 ) { if ( err == 0 ) {
X509_free(dst_cert); X509_free(dst_cert);
return NULL; return NULL;
} }
err = X509_set_issuer_name(dst_cert, name); err = X509_set_issuer_name(dst_cert, config->name);
if(!err){ if(!err){
X509_free(dst_cert); X509_free(dst_cert);
return NULL; return NULL;
} }
err = X509_sign(dst_cert, CA_key, EVP_sha256()); err = X509_sign(dst_cert, config->CA_key, EVP_sha256());
if(!err){ if(!err){
X509_free(dst_cert); X509_free(dst_cert);
return NULL; return NULL;
@ -247,7 +236,7 @@ SSL_CONN ssl_handshake_to_server(SOCKET s, char * hostname, SSL_CERT *server_cer
return conn; return conn;
} }
SSL_CONN ssl_handshake_to_client(SOCKET s, SSL_CERT server_cert, char** errSSL) SSL_CONN ssl_handshake_to_client(SOCKET s, SSL_CERT server_cert, EVP_PKEY *server_key, char** errSSL)
{ {
int err = 0; int err = 0;
X509 *cert; X509 *cert;
@ -414,89 +403,17 @@ int thread_cleanup(void)
int ssl_file_init = 0; int ssl_file_init = 0;
int ssl_init_done = 0;
void ssl_init(void) void ssl_init()
{ {
BIO *f; if(!ssl_init_done){
static char fname[200]; ssl_init_done = 1;
thread_setup();
if(!ssl_file_init++)pthread_mutex_init(&ssl_file_mutex, NULL); SSLeay_add_ssl_algorithms();
SSL_load_error_strings();
pthread_mutex_lock(&ssl_file_mutex); pthread_mutex_init(&ssl_file_mutex, NULL);
thread_setup(); bio_err=BIO_new_fp(stderr,BIO_NOCLOSE);
SSLeay_add_ssl_algorithms();
SSL_load_error_strings();
sprintf(fname, "%.128s3proxy.pem", cert_path);
f = BIO_new_file(fname, "r");
if ( f != NULL ) {
if(!(CA_cert=PEM_read_bio_X509(f, NULL, NULL, NULL))){
unsigned long err;
err=ERR_get_error();
fprintf(stderr, "failed to read: %s: [%lu] %s\n", fname, err, ERR_error_string(err, NULL));
return;
}
BIO_free(f);
} }
else {
fprintf(stderr, "failed to open: %s\n", fname);
return;
}
name = X509_get_subject_name(CA_cert);
sprintf(fname, "%.128s3proxy.key", cert_path);
f = BIO_new_file(fname, "rb");
if ( f != NULL ) {
CA_key = PEM_read_bio_PrivateKey(f, NULL, NULL, NULL);
if(!CA_key){
unsigned long err;
err=ERR_get_error();
fprintf(stderr, "failed to read: %s: [%lu] %s\n", fname, err, ERR_error_string(err, NULL));
return;
}
BIO_free(f);
}
else {
fprintf(stderr, "failed to open: %s\n", fname);
return;
}
sprintf(fname, "%.128sserver.key", cert_path);
f = BIO_new_file(fname, "rb");
if ( f != NULL ) {
server_key = PEM_read_bio_PrivateKey(f, &server_key, NULL, NULL);
if(!server_key){
unsigned long err;
err=ERR_get_error();
fprintf(stderr, "failed to read: %s: [%lu] %s\n", fname, err, ERR_error_string(err, NULL));
return;
}
BIO_free(f);
}
else {
fprintf(stderr, "failed to open: %s\n", fname);
}
bio_err=BIO_new_fp(stderr,BIO_NOCLOSE);
pthread_mutex_unlock(&ssl_file_mutex);
} }
void ssl_release(void)
{
pthread_mutex_lock(&ssl_file_mutex);
if ( CA_cert != NULL ) {
X509_free(CA_cert);
CA_cert = NULL;
}
if ( CA_key != NULL ) {
EVP_PKEY_free(CA_key);
CA_key = NULL;
}
if ( server_key != NULL ) {
EVP_PKEY_free(server_key);
server_key = NULL;
}
thread_cleanup();
pthread_mutex_unlock(&ssl_file_mutex);
}

View File

@ -10,16 +10,28 @@ typedef void *SSL_CONN;
// //
typedef void *SSL_CERT; typedef void *SSL_CERT;
struct ssl_config {
int transparent;
char *certcache;
X509 *CA_cert;
EVP_PKEY *CA_key;
EVP_PKEY *server_key;
X509_NAME *name;
};
typedef struct ssl_config SSL_CONFIG;
// //
// Create copy of certificate signed by "other" CA // Create copy of certificate signed by "other" CA
// //
SSL_CERT ssl_copy_cert(SSL_CERT cert); SSL_CERT ssl_copy_cert(SSL_CERT cert, SSL_CONFIG *config);
// //
// SSL/TLS handshakes // SSL/TLS handshakes
// //
SSL_CONN ssl_handshake_to_server(SOCKET s, char * hostname, SSL_CERT *server_cert, char **errSSL); SSL_CONN ssl_handshake_to_server(SOCKET s, char * hostname, SSL_CERT *server_cert, char **errSSL);
SSL_CONN ssl_handshake_to_client(SOCKET s, SSL_CERT server_cert, char **errSSL); SSL_CONN ssl_handshake_to_client(SOCKET s, SSL_CERT server_cert, EVP_PKEY *server_key, char **errSSL);
// //
// SSL/TLS Read/Write // SSL/TLS Read/Write
@ -38,6 +50,6 @@ void _ssl_cert_free(SSL_CERT cert);
// Global (de)initialization // Global (de)initialization
// //
void ssl_init(void); void ssl_init(void);
void ssl_release(void);
#endif // __my_ssl_h__ #endif // __my_ssl_h__

View File

@ -11,6 +11,7 @@
#include <openssl/x509.h> #include <openssl/x509.h>
#include <openssl/pem.h> #include <openssl/pem.h>
#include <openssl/ssl.h> #include <openssl/ssl.h>
#include <openssl/err.h>
#include "../../proxy.h" #include "../../proxy.h"
#include "my_ssl.h" #include "my_ssl.h"
@ -30,79 +31,68 @@ PROXYFUNC tcppmfunc, proxyfunc, smtppfunc, ftpprfunc;
static struct pluginlink * pl; static struct pluginlink * pl;
pthread_mutex_t ssl_mutex;
static int ssl_loaded = 0; static int ssl_loaded = 0;
static int ssl_connect_timeout = 0; static int ssl_connect_timeout = 0;
char *cert_path = ""; char *certcache = NULL;
int mitm = 0;
int ssl_inited = 0;
typedef struct _ssl_conn { typedef struct _ssl_conn {
struct SSL_CTX *ctx; struct SSL_CTX *ctx;
struct SSL *ssl; struct SSL *ssl;
} ssl_conn; } ssl_conn;
struct SSLqueue {
struct SSLqueue *next; struct SSLsock {
SOCKET s; SOCKET s;
SSL_CERT cert;
SSL_CONN conn; SSL_CONN conn;
};
struct SSLstate {
struct SSLsock cli, srv;
struct clientparam* param; struct clientparam* param;
} *SSLq = NULL; SSL_CONFIG *config;
};
/* /*
TO DO: use hashtable TO DO: use hashtable
*/ */
static struct SSLqueue *searchSSL(SOCKET s){
struct SSLqueue *sslq = NULL;
pthread_mutex_lock(&ssl_mutex); #define STATE ((struct SSLstate *)(state))
for(sslq = SSLq; sslq; sslq = sslq->next)
if(sslq->s == s) break; static struct SSLsock *searchSSL(void* state, SOCKET s){
pthread_mutex_unlock(&ssl_mutex); if(!state || s == INVALID_SOCKET) return NULL;
return sslq; if(STATE->cli.s == s) return &STATE->cli;
if(STATE->srv.s == s) return &STATE->srv;
return NULL;
} }
static void addSSL(SOCKET s, SSL_CERT cert, SSL_CONN conn, struct clientparam* param){ #define SOSTATE ((struct SSLstate *)(param->sostate))
struct SSLqueue *sslq;
sslq = (struct SSLqueue *) malloc(sizeof(struct SSLqueue)); static void addSSL(
sslq->s = s; SOCKET cli_s, SSL_CONN cli_conn,
sslq->cert = cert; SOCKET srv_s, SSL_CONN srv_conn,
sslq->conn = conn; struct clientparam* param){
sslq->param = param; if(!param->sostate) return;
pthread_mutex_lock(&ssl_mutex); SOSTATE->cli.s = cli_s;
sslq->next = SSLq; SOSTATE->cli.conn = cli_conn;
SSLq = sslq; SOSTATE->srv.s = srv_s;
pthread_mutex_unlock(&ssl_mutex); SOSTATE->srv.conn = srv_conn;
} }
int delSSL(SOCKET s){ void delSSL(void *state, SOCKET s){
struct SSLqueue *sqi, *sqt = NULL; if(!state || s == INVALID_SOCKET) return;
if(STATE->cli.s == s) {
if(!SSLq) return 0; ssl_conn_free(STATE->cli.conn);
pthread_mutex_lock(&ssl_mutex); STATE->cli.conn = NULL;
if(SSLq){ STATE->cli.s = INVALID_SOCKET;
if(SSLq->s == s){ }
sqt = SSLq; else if(STATE->srv.s == s) {
SSLq = SSLq->next; ssl_conn_free(STATE->cli.conn);
} STATE->cli.conn = NULL;
else for(sqi = SSLq; sqi->next; sqi = sqi->next){ STATE->cli.s = INVALID_SOCKET;
if (sqi->next->s == s){ }
sqt = sqi->next;
sqi->next = sqt->next;
break;
}
}
}
pthread_mutex_unlock(&ssl_mutex);
if(sqt) {
_ssl_cert_free(sqt->cert);
ssl_conn_free(sqt->conn);
free(sqt);
return 1;
}
return 0;
} }
struct sockfuncs sso; struct sockfuncs sso;
@ -112,9 +102,9 @@ static int WINAPI ssl_send(void *state, SOCKET s, const void *msg, int len, int
#else #else
static ssize_t ssl_send(void *state, SOCKET s, const void *msg, size_t len, int flags){ static ssize_t ssl_send(void *state, SOCKET s, const void *msg, size_t len, int flags){
#endif #endif
struct SSLqueue *sslq; struct SSLsock *sslq;
if ((sslq = searchSSL(s))){ if ((sslq = searchSSL(state, s))){
int res, err; int res, err;
if((res = ssl_write(sslq->conn, (void *)msg, len)) <= 0){ if((res = ssl_write(sslq->conn, (void *)msg, len)) <= 0){
err = SSL_get_error((SSL *)((ssl_conn*)sslq->conn)->ssl, res); err = SSL_get_error((SSL *)((ssl_conn*)sslq->conn)->ssl, res);
@ -136,9 +126,9 @@ static int WINAPI ssl_sendto(void *state, SOCKET s, const void *msg, int len, in
#else #else
static ssize_t ssl_sendto(void *state, SOCKET s, const void *msg, size_t len, int flags, const struct sockaddr *to, SASIZETYPE tolen){ static ssize_t ssl_sendto(void *state, SOCKET s, const void *msg, size_t len, int flags, const struct sockaddr *to, SASIZETYPE tolen){
#endif #endif
struct SSLqueue *sslq; struct SSLsock *sslq;
if ((sslq = searchSSL(s))){ if ((sslq = searchSSL(state, s))){
int res, err; int res, err;
if((res = ssl_write(sslq->conn, (void *)msg, len)) <= 0) { if((res = ssl_write(sslq->conn, (void *)msg, len)) <= 0) {
err = SSL_get_error((SSL *)((ssl_conn*)sslq->conn)->ssl, res); err = SSL_get_error((SSL *)((ssl_conn*)sslq->conn)->ssl, res);
@ -159,9 +149,9 @@ static int WINAPI ssl_recvfrom(void *state, SOCKET s, void *msg, int len, int fl
#else #else
static ssize_t ssl_recvfrom(void *state, SOCKET s, void *msg, size_t len, int flags, struct sockaddr *from, SASIZETYPE *fromlen){ static ssize_t ssl_recvfrom(void *state, SOCKET s, void *msg, size_t len, int flags, struct sockaddr *from, SASIZETYPE *fromlen){
#endif #endif
struct SSLqueue *sslq; struct SSLsock *sslq;
if ((sslq = searchSSL(s))){ if ((sslq = searchSSL(state, s))){
int res, err; int res, err;
if((res = ssl_read(sslq->conn, (void *)msg, len)) <= 0) { if((res = ssl_read(sslq->conn, (void *)msg, len)) <= 0) {
err = SSL_get_error((SSL *)((ssl_conn*)sslq->conn)->ssl, res); err = SSL_get_error((SSL *)((ssl_conn*)sslq->conn)->ssl, res);
@ -181,9 +171,9 @@ static int WINAPI ssl_recv(void *state, SOCKET s, void *msg, int len, int flags)
#else #else
static ssize_t ssl_recv(void *state, SOCKET s, void *msg, size_t len, int flags){ static ssize_t ssl_recv(void *state, SOCKET s, void *msg, size_t len, int flags){
#endif #endif
struct SSLqueue *sslq; struct SSLsock *sslq;
if ((sslq = searchSSL(s))){ if ((sslq = searchSSL(state,s))){
int res, err; int res, err;
if((res = ssl_read(sslq->conn, (void *)msg, len)) <= 0) { if((res = ssl_read(sslq->conn, (void *)msg, len)) <= 0) {
err = SSL_get_error((SSL *)((ssl_conn*)sslq->conn)->ssl, res); err = SSL_get_error((SSL *)((ssl_conn*)sslq->conn)->ssl, res);
@ -200,16 +190,16 @@ static ssize_t ssl_recv(void *state, SOCKET s, void *msg, size_t len, int flags)
} }
static int WINAPI ssl_closesocket(void *state, SOCKET s){ static int WINAPI ssl_closesocket(void *state, SOCKET s){
delSSL(s); delSSL(state, s);
return sso._closesocket(sso.state, s); return sso._closesocket(sso.state, s);
} }
static int WINAPI ssl_poll(void *state, struct pollfd *fds, unsigned int nfds, int timeout){ static int WINAPI ssl_poll(void *state, struct pollfd *fds, unsigned int nfds, int timeout){
struct SSLqueue *sslq = NULL; struct SSLsock *sslq = NULL;
unsigned int i; unsigned int i;
int ret = 0; int ret = 0;
for(i = 0; i < nfds; i++){ for(i = 0; i < nfds; i++){
if((fds[i].events & POLLIN) && (sslq = searchSSL(fds[i].fd)) && ssl_pending(sslq->conn)){ if((fds[i].events & POLLIN) && (sslq = searchSSL(state, fds[i].fd)) && ssl_pending(sslq->conn)){
fds[i].revents = POLLIN; fds[i].revents = POLLIN;
ret++; ret++;
} }
@ -221,6 +211,7 @@ static int WINAPI ssl_poll(void *state, struct pollfd *fds, unsigned int nfds, i
return ret; return ret;
} }
#define PCONF (((struct SSLstate *)param->sostate)->config)
int dossl(struct clientparam* param, SSL_CONN* ServerConnp, SSL_CONN* ClientConnp){ int dossl(struct clientparam* param, SSL_CONN* ServerConnp, SSL_CONN* ClientConnp){
SSL_CERT ServerCert=NULL, FakeCert=NULL; SSL_CERT ServerCert=NULL, FakeCert=NULL;
@ -253,23 +244,22 @@ int dossl(struct clientparam* param, SSL_CONN* ServerConnp, SSL_CONN* ClientConn
if(errSSL)param->srv->logfunc(param, (unsigned char *)errSSL); if(errSSL)param->srv->logfunc(param, (unsigned char *)errSSL);
return 1; return 1;
} }
FakeCert = ssl_copy_cert(ServerCert); FakeCert = ssl_copy_cert(ServerCert, PCONF);
_ssl_cert_free(ServerCert);
if ( FakeCert == NULL ) { if ( FakeCert == NULL ) {
param->res = 8012; param->res = 8012;
_ssl_cert_free(ServerCert);
param->srv->logfunc(param, (unsigned char *)"Failed to create certificate copy"); param->srv->logfunc(param, (unsigned char *)"Failed to create certificate copy");
ssl_conn_free(ServerConn); ssl_conn_free(ServerConn);
return 2; return 2;
} }
ClientConn = ssl_handshake_to_client(param->clisock, FakeCert, &errSSL); ClientConn = ssl_handshake_to_client(param->clisock, FakeCert, PCONF->server_key, &errSSL);
_ssl_cert_free(FakeCert);
if ( ClientConn == NULL ) { if ( ClientConn == NULL ) {
param->res = 8012; param->res = 8012;
param->srv->logfunc(param, (unsigned char *)"Handshake to client failed"); param->srv->logfunc(param, (unsigned char *)"Handshake to client failed");
if(errSSL)param->srv->logfunc(param, (unsigned char *)errSSL); if(errSSL)param->srv->logfunc(param, (unsigned char *)errSSL);
_ssl_cert_free(ServerCert);
_ssl_cert_free(FakeCert);
ssl_conn_free(ServerConn); ssl_conn_free(ServerConn);
return 3; return 3;
} }
@ -289,8 +279,7 @@ int dossl(struct clientparam* param, SSL_CONN* ServerConnp, SSL_CONN* ClientConn
SSL_set_mode((SSL *)((ssl_conn *)ClientConn)->ssl, SSL_MODE_ENABLE_PARTIAL_WRITE|SSL_MODE_AUTO_RETRY); SSL_set_mode((SSL *)((ssl_conn *)ClientConn)->ssl, SSL_MODE_ENABLE_PARTIAL_WRITE|SSL_MODE_AUTO_RETRY);
SSL_set_read_ahead((SSL *)((ssl_conn *)ServerConn)->ssl, 0); SSL_set_read_ahead((SSL *)((ssl_conn *)ServerConn)->ssl, 0);
SSL_set_read_ahead((SSL *)((ssl_conn *)ClientConn)->ssl, 0); SSL_set_read_ahead((SSL *)((ssl_conn *)ClientConn)->ssl, 0);
addSSL(param->remsock, ServerCert, ServerConn, param); addSSL(param->clisock, ClientConn, param->remsock, ServerConn, param);
addSSL(param->clisock, FakeCert, ClientConn, param);
if(ServerConnp)*ServerConnp = ServerConn; if(ServerConnp)*ServerConnp = ServerConn;
if(ClientConnp)*ClientConnp = ClientConn; if(ClientConnp)*ClientConnp = ClientConn;
@ -299,13 +288,95 @@ int dossl(struct clientparam* param, SSL_CONN* ServerConnp, SSL_CONN* ClientConn
} }
static void* ssl_filter_open(void * idata, struct srvparam * param){
return idata; static void* ssl_filter_open(void * idata, struct srvparam * srv){
struct ssl_config *sc;
sc = malloc(sizeof(struct ssl_config));
if(!sc) return NULL;
memset(sc, 0, sizeof(struct ssl_config));
if(certcache) sc->certcache = strdup(certcache);
if(mitm){
BIO *f;
char fname[256];
if(!certcache) {
free(sc);
return NULL;
}
sprintf(fname, "%.240s3proxy.pem", certcache);
f = BIO_new_file(fname, "r");
if ( f != NULL ) {
sc->CA_cert=PEM_read_bio_X509(f, NULL, NULL, NULL);
BIO_free(f);
if(!sc->CA_cert){
unsigned long err;
err=ERR_get_error();
fprintf(stderr, "failed to read: %s: [%lu] %s\n", fname, err, ERR_error_string(err, NULL));
free(sc);
return NULL;
}
}
else {
fprintf(stderr, "failed to open: %s\n", fname);
free(sc);
return NULL;
}
sc->name = X509_get_subject_name(sc->CA_cert);
sprintf(fname, "%.240s3proxy.key", sc->certcache);
f = BIO_new_file(fname, "rb");
if ( f != NULL ) {
sc->CA_key = PEM_read_bio_PrivateKey(f, NULL, NULL, NULL);
BIO_free(f);
if(!sc->CA_key){
unsigned long err;
err=ERR_get_error();
fprintf(stderr, "failed to read: %s: [%lu] %s\n", fname, err, ERR_error_string(err, NULL));
return NULL;
}
}
else {
fprintf(stderr, "failed to open: %s\n", fname);
return NULL;
}
sprintf(fname, "%.128sserver.key", sc->certcache);
f = BIO_new_file(fname, "rb");
if ( f != NULL ) {
sc->server_key = PEM_read_bio_PrivateKey(f, &sc->server_key, NULL, NULL);
BIO_free(f);
if(!sc->server_key){
unsigned long err;
err=ERR_get_error();
fprintf(stderr, "failed to read: %s: [%lu] %s\n", fname, err, ERR_error_string(err, NULL));
return NULL;
}
}
else {
fprintf(stderr, "failed to open: %s\n", fname);
}
sc->transparent = 1;
srv->so._send = ssl_send;
srv->so._recv = ssl_recv;
srv->so._sendto = ssl_sendto;
srv->so._recvfrom = ssl_recvfrom;
srv->so._closesocket = ssl_closesocket;
srv->so._poll = ssl_poll;
}
return sc;
} }
static FILTER_ACTION ssl_filter_client(void *fo, struct clientparam * param, void** fc){ static FILTER_ACTION ssl_filter_client(void *fo, struct clientparam * param, void** fc){
struct SSLstate *ssls;
ssls = (struct SSLstate *) malloc(sizeof(struct SSLstate));
memset(ssls, 0, sizeof(struct SSLstate));
ssls->config = fo;
ssls->param = param;
param->sostate = ssls;
*fc = ssls;
return CONTINUE; return CONTINUE;
} }
@ -319,16 +390,35 @@ static FILTER_ACTION ssl_filter_predata(void *fo, struct clientparam * param){
} }
static void ssl_filter_clear(void *fo){ static void ssl_filter_clear(void *fc){
free(fc);
} }
#define CONFIG ((SSL_CONFIG *)fo)
static void ssl_filter_close(void *fo){ static void ssl_filter_close(void *fo){
free(CONFIG->certcache);
if ( CONFIG->CA_cert != NULL ) {
X509_free(CONFIG->CA_cert);
CONFIG->CA_cert = NULL;
}
if ( CONFIG->CA_key != NULL ) {
EVP_PKEY_free(CONFIG->CA_key);
CONFIG->CA_key = NULL;
}
if ( CONFIG->server_key != NULL ) {
EVP_PKEY_free(CONFIG->server_key);
CONFIG->server_key = NULL;
}
free(fo);
} }
static struct filter ssl_filter = { static struct filter ssl_filter_mitm = {
NULL, NULL,
"ssl filter", "ssl filter",
"ssl filter", "mitm",
ssl_filter_open, ssl_filter_open,
ssl_filter_client, ssl_filter_client,
NULL, NULL, NULL, ssl_filter_predata, NULL, NULL, NULL, NULL, NULL, ssl_filter_predata, NULL, NULL,
@ -336,50 +426,44 @@ static struct filter ssl_filter = {
ssl_filter_close ssl_filter_close
}; };
int mitm = 0;
int ssl_inited = 0;
static int h_mitm(int argc, unsigned char **argv){ static int h_mitm(int argc, unsigned char **argv){
if(!ssl_inited) {
ssl_init();
ssl_inited = 1;
}
if((mitm&1)) return 1; if((mitm&1)) return 1;
if(mitm) usleep(100*SLEEPTIME); if(mitm) usleep(100*SLEEPTIME);
ssl_filter.next = pl->conf->filters; ssl_filter_mitm.next = pl->conf->filters;
pl->conf->filters = &ssl_filter; pl->conf->filters = &ssl_filter_mitm;
mitm++; sso = *pl->so;
mitm = 1;
return 0; return 0;
} }
static int h_nomitm(int argc, unsigned char **argv){ static int h_nomitm(int argc, unsigned char **argv){
struct filter * sf; struct filter * sf;
if(!(mitm&1)) return 1; if(!mitm) return 1;
if(mitm) usleep(100*SLEEPTIME); if(pl->conf->filters == &ssl_filter_mitm) pl->conf->filters = ssl_filter_mitm.next;
if(pl->conf->filters == &ssl_filter) pl->conf->filters = ssl_filter.next;
else for(sf = pl->conf->filters; sf && sf->next; sf=sf->next){ else for(sf = pl->conf->filters; sf && sf->next; sf=sf->next){
if(sf->next == &ssl_filter) { if(sf->next == &ssl_filter_mitm) {
sf->next = ssl_filter.next; sf->next = ssl_filter_mitm.next;
break; break;
} }
} }
mitm++; mitm = 0;
return 0; return 0;
} }
static int h_certpath(int argc, unsigned char **argv){ static int h_certcache(int argc, unsigned char **argv){
size_t len; size_t len;
len = strlen(argv[1]); len = strlen((char *)argv[1]);
if(!len || (argv[1][len - 1] != '/' && argv[1][len - 1] != '\\')) return 1; if(!len || (argv[1][len - 1] != '/' && argv[1][len - 1] != '\\')) return 1;
if(cert_path && *cert_path) free(cert_path); if(certcache) free(certcache);
cert_path = strdup(argv[1]); certcache = strdup((char *)argv[1]);
return 0; return 0;
} }
static struct commands ssl_commandhandlers[] = { static struct commands ssl_commandhandlers[] = {
{ssl_commandhandlers+1, "ssl_mitm", h_mitm, 1, 1}, {ssl_commandhandlers+1, "ssl_mitm", h_mitm, 1, 1},
{ssl_commandhandlers+2, "ssl_nomitm", h_nomitm, 1, 1}, {ssl_commandhandlers+2, "ssl_nomitm", h_nomitm, 1, 1},
{NULL, "ssl_certcache", h_certpath, 2, 2}, {NULL, "ssl_certcache", h_certcache, 2, 2},
}; };
@ -395,21 +479,10 @@ PLUGINAPI int PLUGINCALL ssl_plugin (struct pluginlink * pluginlink,
pl = pluginlink; pl = pluginlink;
if(!ssl_loaded){ if(!ssl_loaded){
ssl_loaded = 1; ssl_loaded = 1;
pthread_mutex_init(&ssl_mutex, NULL); ssl_init();
memcpy(&sso, pl->so, sizeof(struct sockfuncs));
pl->so->_send = ssl_send;
pl->so->_recv = ssl_recv;
pl->so->_sendto = ssl_sendto;
pl->so->_recvfrom = ssl_recvfrom;
pl->so->_closesocket = ssl_closesocket;
pl->so->_poll = ssl_poll;
ssl_commandhandlers[2].next = pl->commandhandlers->next; ssl_commandhandlers[2].next = pl->commandhandlers->next;
pl->commandhandlers->next = ssl_commandhandlers; pl->commandhandlers->next = ssl_commandhandlers;
} }
else {
ssl_release();
ssl_inited = 0;
}
tcppmfunc = (PROXYFUNC)pl->findbyname("tcppm"); tcppmfunc = (PROXYFUNC)pl->findbyname("tcppm");
if(!tcppmfunc){return 13;} if(!tcppmfunc){return 13;}