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 *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);
|
|
||||||
}
|
|
||||||
|
@ -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__
|
@ -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;}
|
||||||
|
Loading…
Reference in New Issue
Block a user