mirror of
https://github.com/3proxy/3proxy.git
synced 2025-02-23 02:25:40 +08:00
initial commit to TLS refactoring
This commit is contained in:
parent
d162ad5c38
commit
6dc145b16b
@ -32,11 +32,6 @@ typedef struct _ssl_conn {
|
||||
SSL *ssl;
|
||||
} 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;
|
||||
|
||||
|
||||
@ -91,8 +86,6 @@ static int add_ext(X509 *cert, int nid, char *value)
|
||||
return 1;
|
||||
}
|
||||
|
||||
extern char *cert_path;
|
||||
|
||||
void del_ext(X509 *dst_cert, int nid, int where){
|
||||
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;
|
||||
BIO *fcache;
|
||||
@ -114,12 +107,8 @@ SSL_CERT ssl_copy_cert(SSL_CERT cert)
|
||||
EVP_PKEY *pk = NULL;
|
||||
RSA *rsa = NULL;
|
||||
|
||||
unsigned char p1[] = "RU";
|
||||
unsigned char p2[] = "3proxy";
|
||||
unsigned char p3[] = "3proxy CA";
|
||||
|
||||
int hash_size = 20;
|
||||
char hash_sha1[20];
|
||||
unsigned char hash_sha1[20];
|
||||
char hash_name_sha1[(20*2) + 1];
|
||||
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));
|
||||
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 */
|
||||
fcache = BIO_new_file(cache_name, "rb");
|
||||
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_certificate_policies, 0);
|
||||
|
||||
err = X509_set_pubkey(dst_cert, server_key);
|
||||
err = X509_set_pubkey(dst_cert, config->server_key);
|
||||
if ( err == 0 ) {
|
||||
X509_free(dst_cert);
|
||||
return NULL;
|
||||
}
|
||||
|
||||
|
||||
err = X509_set_issuer_name(dst_cert, name);
|
||||
err = X509_set_issuer_name(dst_cert, config->name);
|
||||
if(!err){
|
||||
X509_free(dst_cert);
|
||||
return NULL;
|
||||
}
|
||||
err = X509_sign(dst_cert, CA_key, EVP_sha256());
|
||||
err = X509_sign(dst_cert, config->CA_key, EVP_sha256());
|
||||
if(!err){
|
||||
X509_free(dst_cert);
|
||||
return NULL;
|
||||
@ -247,7 +236,7 @@ SSL_CONN ssl_handshake_to_server(SOCKET s, char * hostname, SSL_CERT *server_cer
|
||||
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;
|
||||
X509 *cert;
|
||||
@ -414,89 +403,17 @@ int thread_cleanup(void)
|
||||
|
||||
int ssl_file_init = 0;
|
||||
|
||||
int ssl_init_done = 0;
|
||||
|
||||
void ssl_init(void)
|
||||
void ssl_init()
|
||||
{
|
||||
BIO *f;
|
||||
static char fname[200];
|
||||
|
||||
if(!ssl_file_init++)pthread_mutex_init(&ssl_file_mutex, NULL);
|
||||
|
||||
pthread_mutex_lock(&ssl_file_mutex);
|
||||
if(!ssl_init_done){
|
||||
ssl_init_done = 1;
|
||||
thread_setup();
|
||||
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);
|
||||
}
|
||||
|
||||
pthread_mutex_init(&ssl_file_mutex, NULL);
|
||||
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);
|
||||
}
|
||||
|
@ -10,16 +10,28 @@ typedef void *SSL_CONN;
|
||||
//
|
||||
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
|
||||
//
|
||||
SSL_CERT ssl_copy_cert(SSL_CERT cert);
|
||||
SSL_CERT ssl_copy_cert(SSL_CERT cert, SSL_CONFIG *config);
|
||||
|
||||
//
|
||||
// SSL/TLS handshakes
|
||||
//
|
||||
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
|
||||
@ -38,6 +50,6 @@ void _ssl_cert_free(SSL_CERT cert);
|
||||
// Global (de)initialization
|
||||
//
|
||||
void ssl_init(void);
|
||||
void ssl_release(void);
|
||||
|
||||
|
||||
#endif // __my_ssl_h__
|
@ -11,6 +11,7 @@
|
||||
#include <openssl/x509.h>
|
||||
#include <openssl/pem.h>
|
||||
#include <openssl/ssl.h>
|
||||
#include <openssl/err.h>
|
||||
#include "../../proxy.h"
|
||||
#include "my_ssl.h"
|
||||
|
||||
@ -30,79 +31,68 @@ PROXYFUNC tcppmfunc, proxyfunc, smtppfunc, ftpprfunc;
|
||||
|
||||
static struct pluginlink * pl;
|
||||
|
||||
pthread_mutex_t ssl_mutex;
|
||||
|
||||
static int ssl_loaded = 0;
|
||||
static int ssl_connect_timeout = 0;
|
||||
char *cert_path = "";
|
||||
char *certcache = NULL;
|
||||
int mitm = 0;
|
||||
int ssl_inited = 0;
|
||||
|
||||
typedef struct _ssl_conn {
|
||||
struct SSL_CTX *ctx;
|
||||
struct SSL *ssl;
|
||||
} ssl_conn;
|
||||
|
||||
struct SSLqueue {
|
||||
struct SSLqueue *next;
|
||||
|
||||
struct SSLsock {
|
||||
SOCKET s;
|
||||
SSL_CERT cert;
|
||||
SSL_CONN conn;
|
||||
};
|
||||
|
||||
struct SSLstate {
|
||||
struct SSLsock cli, srv;
|
||||
struct clientparam* param;
|
||||
} *SSLq = NULL;
|
||||
SSL_CONFIG *config;
|
||||
};
|
||||
|
||||
|
||||
/*
|
||||
TO DO: use hashtable
|
||||
*/
|
||||
static struct SSLqueue *searchSSL(SOCKET s){
|
||||
struct SSLqueue *sslq = NULL;
|
||||
|
||||
pthread_mutex_lock(&ssl_mutex);
|
||||
for(sslq = SSLq; sslq; sslq = sslq->next)
|
||||
if(sslq->s == s) break;
|
||||
pthread_mutex_unlock(&ssl_mutex);
|
||||
return sslq;
|
||||
#define STATE ((struct SSLstate *)(state))
|
||||
|
||||
static struct SSLsock *searchSSL(void* state, SOCKET s){
|
||||
if(!state || s == INVALID_SOCKET) return NULL;
|
||||
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){
|
||||
struct SSLqueue *sslq;
|
||||
#define SOSTATE ((struct SSLstate *)(param->sostate))
|
||||
|
||||
sslq = (struct SSLqueue *) malloc(sizeof(struct SSLqueue));
|
||||
sslq->s = s;
|
||||
sslq->cert = cert;
|
||||
sslq->conn = conn;
|
||||
sslq->param = param;
|
||||
pthread_mutex_lock(&ssl_mutex);
|
||||
sslq->next = SSLq;
|
||||
SSLq = sslq;
|
||||
pthread_mutex_unlock(&ssl_mutex);
|
||||
static void addSSL(
|
||||
SOCKET cli_s, SSL_CONN cli_conn,
|
||||
SOCKET srv_s, SSL_CONN srv_conn,
|
||||
struct clientparam* param){
|
||||
if(!param->sostate) return;
|
||||
SOSTATE->cli.s = cli_s;
|
||||
SOSTATE->cli.conn = cli_conn;
|
||||
SOSTATE->srv.s = srv_s;
|
||||
SOSTATE->srv.conn = srv_conn;
|
||||
}
|
||||
|
||||
int delSSL(SOCKET s){
|
||||
struct SSLqueue *sqi, *sqt = NULL;
|
||||
|
||||
if(!SSLq) return 0;
|
||||
pthread_mutex_lock(&ssl_mutex);
|
||||
if(SSLq){
|
||||
if(SSLq->s == s){
|
||||
sqt = SSLq;
|
||||
SSLq = SSLq->next;
|
||||
void delSSL(void *state, SOCKET s){
|
||||
if(!state || s == INVALID_SOCKET) return;
|
||||
if(STATE->cli.s == s) {
|
||||
ssl_conn_free(STATE->cli.conn);
|
||||
STATE->cli.conn = NULL;
|
||||
STATE->cli.s = INVALID_SOCKET;
|
||||
}
|
||||
else for(sqi = SSLq; sqi->next; sqi = sqi->next){
|
||||
if (sqi->next->s == s){
|
||||
sqt = sqi->next;
|
||||
sqi->next = sqt->next;
|
||||
break;
|
||||
else if(STATE->srv.s == s) {
|
||||
ssl_conn_free(STATE->cli.conn);
|
||||
STATE->cli.conn = NULL;
|
||||
STATE->cli.s = INVALID_SOCKET;
|
||||
}
|
||||
}
|
||||
}
|
||||
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;
|
||||
@ -112,9 +102,9 @@ static int WINAPI ssl_send(void *state, SOCKET s, const void *msg, int len, int
|
||||
#else
|
||||
static ssize_t ssl_send(void *state, SOCKET s, const void *msg, size_t len, int flags){
|
||||
#endif
|
||||
struct SSLqueue *sslq;
|
||||
struct SSLsock *sslq;
|
||||
|
||||
if ((sslq = searchSSL(s))){
|
||||
if ((sslq = searchSSL(state, s))){
|
||||
int res, err;
|
||||
if((res = ssl_write(sslq->conn, (void *)msg, len)) <= 0){
|
||||
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
|
||||
static ssize_t ssl_sendto(void *state, SOCKET s, const void *msg, size_t len, int flags, const struct sockaddr *to, SASIZETYPE tolen){
|
||||
#endif
|
||||
struct SSLqueue *sslq;
|
||||
struct SSLsock *sslq;
|
||||
|
||||
if ((sslq = searchSSL(s))){
|
||||
if ((sslq = searchSSL(state, s))){
|
||||
int res, err;
|
||||
if((res = ssl_write(sslq->conn, (void *)msg, len)) <= 0) {
|
||||
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
|
||||
static ssize_t ssl_recvfrom(void *state, SOCKET s, void *msg, size_t len, int flags, struct sockaddr *from, SASIZETYPE *fromlen){
|
||||
#endif
|
||||
struct SSLqueue *sslq;
|
||||
struct SSLsock *sslq;
|
||||
|
||||
if ((sslq = searchSSL(s))){
|
||||
if ((sslq = searchSSL(state, s))){
|
||||
int res, err;
|
||||
if((res = ssl_read(sslq->conn, (void *)msg, len)) <= 0) {
|
||||
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
|
||||
static ssize_t ssl_recv(void *state, SOCKET s, void *msg, size_t len, int flags){
|
||||
#endif
|
||||
struct SSLqueue *sslq;
|
||||
struct SSLsock *sslq;
|
||||
|
||||
if ((sslq = searchSSL(s))){
|
||||
if ((sslq = searchSSL(state,s))){
|
||||
int res, err;
|
||||
if((res = ssl_read(sslq->conn, (void *)msg, len)) <= 0) {
|
||||
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){
|
||||
delSSL(s);
|
||||
delSSL(state, s);
|
||||
return sso._closesocket(sso.state, s);
|
||||
}
|
||||
|
||||
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;
|
||||
int ret = 0;
|
||||
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;
|
||||
ret++;
|
||||
}
|
||||
@ -221,6 +211,7 @@ static int WINAPI ssl_poll(void *state, struct pollfd *fds, unsigned int nfds, i
|
||||
return ret;
|
||||
}
|
||||
|
||||
#define PCONF (((struct SSLstate *)param->sostate)->config)
|
||||
|
||||
int dossl(struct clientparam* param, SSL_CONN* ServerConnp, SSL_CONN* ClientConnp){
|
||||
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);
|
||||
return 1;
|
||||
}
|
||||
FakeCert = ssl_copy_cert(ServerCert);
|
||||
FakeCert = ssl_copy_cert(ServerCert, PCONF);
|
||||
_ssl_cert_free(ServerCert);
|
||||
if ( FakeCert == NULL ) {
|
||||
param->res = 8012;
|
||||
_ssl_cert_free(ServerCert);
|
||||
param->srv->logfunc(param, (unsigned char *)"Failed to create certificate copy");
|
||||
ssl_conn_free(ServerConn);
|
||||
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 ) {
|
||||
param->res = 8012;
|
||||
param->srv->logfunc(param, (unsigned char *)"Handshake to client failed");
|
||||
if(errSSL)param->srv->logfunc(param, (unsigned char *)errSSL);
|
||||
_ssl_cert_free(ServerCert);
|
||||
_ssl_cert_free(FakeCert);
|
||||
ssl_conn_free(ServerConn);
|
||||
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_read_ahead((SSL *)((ssl_conn *)ServerConn)->ssl, 0);
|
||||
SSL_set_read_ahead((SSL *)((ssl_conn *)ClientConn)->ssl, 0);
|
||||
addSSL(param->remsock, ServerCert, ServerConn, param);
|
||||
addSSL(param->clisock, FakeCert, ClientConn, param);
|
||||
addSSL(param->clisock, ClientConn, param->remsock, ServerConn, param);
|
||||
if(ServerConnp)*ServerConnp = ServerConn;
|
||||
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){
|
||||
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;
|
||||
}
|
||||
|
||||
@ -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){
|
||||
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,
|
||||
"ssl filter",
|
||||
"ssl filter",
|
||||
"mitm",
|
||||
ssl_filter_open,
|
||||
ssl_filter_client,
|
||||
NULL, NULL, NULL, ssl_filter_predata, NULL, NULL,
|
||||
@ -336,50 +426,44 @@ static struct filter ssl_filter = {
|
||||
ssl_filter_close
|
||||
};
|
||||
|
||||
int mitm = 0;
|
||||
int ssl_inited = 0;
|
||||
|
||||
static int h_mitm(int argc, unsigned char **argv){
|
||||
if(!ssl_inited) {
|
||||
ssl_init();
|
||||
ssl_inited = 1;
|
||||
}
|
||||
if((mitm&1)) return 1;
|
||||
if(mitm) usleep(100*SLEEPTIME);
|
||||
ssl_filter.next = pl->conf->filters;
|
||||
pl->conf->filters = &ssl_filter;
|
||||
mitm++;
|
||||
ssl_filter_mitm.next = pl->conf->filters;
|
||||
pl->conf->filters = &ssl_filter_mitm;
|
||||
sso = *pl->so;
|
||||
mitm = 1;
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int h_nomitm(int argc, unsigned char **argv){
|
||||
struct filter * sf;
|
||||
if(!(mitm&1)) return 1;
|
||||
if(mitm) usleep(100*SLEEPTIME);
|
||||
if(pl->conf->filters == &ssl_filter) pl->conf->filters = ssl_filter.next;
|
||||
if(!mitm) return 1;
|
||||
if(pl->conf->filters == &ssl_filter_mitm) pl->conf->filters = ssl_filter_mitm.next;
|
||||
else for(sf = pl->conf->filters; sf && sf->next; sf=sf->next){
|
||||
if(sf->next == &ssl_filter) {
|
||||
sf->next = ssl_filter.next;
|
||||
if(sf->next == &ssl_filter_mitm) {
|
||||
sf->next = ssl_filter_mitm.next;
|
||||
break;
|
||||
}
|
||||
}
|
||||
mitm++;
|
||||
mitm = 0;
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int h_certpath(int argc, unsigned char **argv){
|
||||
static int h_certcache(int argc, unsigned char **argv){
|
||||
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(cert_path && *cert_path) free(cert_path);
|
||||
cert_path = strdup(argv[1]);
|
||||
if(certcache) free(certcache);
|
||||
certcache = strdup((char *)argv[1]);
|
||||
return 0;
|
||||
}
|
||||
|
||||
static struct commands ssl_commandhandlers[] = {
|
||||
{ssl_commandhandlers+1, "ssl_mitm", h_mitm, 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;
|
||||
if(!ssl_loaded){
|
||||
ssl_loaded = 1;
|
||||
pthread_mutex_init(&ssl_mutex, NULL);
|
||||
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_init();
|
||||
ssl_commandhandlers[2].next = pl->commandhandlers->next;
|
||||
pl->commandhandlers->next = ssl_commandhandlers;
|
||||
}
|
||||
else {
|
||||
ssl_release();
|
||||
ssl_inited = 0;
|
||||
}
|
||||
|
||||
tcppmfunc = (PROXYFUNC)pl->findbyname("tcppm");
|
||||
if(!tcppmfunc){return 13;}
|
||||
|
Loading…
Reference in New Issue
Block a user