mirror of
https://github.com/proxytunnel/proxytunnel.git
synced 2026-01-23 02:34:59 +00:00
Merge pull request #17 from ExtraHop/master
New features (Add IPv6 and SSL cert verification support, make SSLv3 optional)
This commit is contained in:
commit
cb8e792052
7 changed files with 276 additions and 43 deletions
54
cmdline.c
54
cmdline.c
|
|
@ -60,9 +60,14 @@ void cmdline_parser_print_help (void) {
|
|||
" -E, --encrypt-proxy SSL encrypt data between client and local proxy\n"
|
||||
" -X, --encrypt-remproxy SSL encrypt data between local and remote proxy\n"
|
||||
" -L (legacy) enforce TLSv1 connection\n"
|
||||
" -T, --no-ssl3 Do not connect using SSLv3\n"
|
||||
#endif
|
||||
"\n"
|
||||
"Additional options for specific features:\n"
|
||||
#ifdef USE_SSL
|
||||
" -z, --no-check-certficate Don't verify server SSL certificate\n"
|
||||
" -C, --cacert=STRING Path to trusted CA certificate or directory\n"
|
||||
#endif
|
||||
" -F, --passfile=STRING File with credentials for proxy authentication\n"
|
||||
" -P, --proxyauth=STRING Proxy auth credentials user:pass combination\n"
|
||||
" -R, --remproxyauth=STRING Remote proxy auth credentials user:pass combination\n"
|
||||
|
|
@ -136,6 +141,7 @@ int cmdline_parser( int argc, char * const *argv, struct gengetopt_args_info *ar
|
|||
args_info->proctitle_given = 0;
|
||||
args_info->enforcetls1_given = 0;
|
||||
args_info->host_given = 0;
|
||||
args_info->cacert_given = 0;
|
||||
|
||||
/* No... we can't make this a function... -- Maniac */
|
||||
#define clear_args() \
|
||||
|
|
@ -160,9 +166,12 @@ int cmdline_parser( int argc, char * const *argv, struct gengetopt_args_info *ar
|
|||
args_info->encrypt_flag = 0; \
|
||||
args_info->encryptproxy_flag = 0; \
|
||||
args_info->encryptremproxy_flag = 0; \
|
||||
args_info->no_ssl3_flag = 0; \
|
||||
args_info->proctitle_arg = NULL; \
|
||||
args_info->enforcetls1_flag = 0; \
|
||||
args_info->host_arg = NULL; \
|
||||
args_info->no_check_cert_flag = 0; \
|
||||
args_info->cacert_arg = NULL; \
|
||||
}
|
||||
|
||||
clear_args();
|
||||
|
|
@ -206,12 +215,15 @@ int cmdline_parser( int argc, char * const *argv, struct gengetopt_args_info *ar
|
|||
{ "encrypt", 0, NULL, 'e' },
|
||||
{ "encrypt-proxy", 0, NULL, 'E' },
|
||||
{ "encrypt-remproxy",0,NULL, 'X' },
|
||||
{ "no-ssl3", 0, NULL, 'T' },
|
||||
{ "no-check-certificate",0,NULL,'z' },
|
||||
{ "cacert", 1, NULL, 'C' },
|
||||
{ NULL, 0, NULL, 0 }
|
||||
};
|
||||
|
||||
c = getopt_long (argc, argv, "hVia:u:s:t:F:p:P:r:R:d:H:x:nvNeEXqLo:", long_options, &option_index);
|
||||
c = getopt_long (argc, argv, "hVia:u:s:t:F:p:P:r:R:d:H:x:nvNeEXqLo:TzC:", long_options, &option_index);
|
||||
#else
|
||||
c = getopt( argc, argv, "hVia:u:s:t:F:p:P:r:R:d:H:x:nvNeEXqLo:" );
|
||||
c = getopt( argc, argv, "hVia:u:s:t:F:p:P:r:R:d:H:x:nvNeEXqLo:TzC:" );
|
||||
#endif
|
||||
|
||||
if (c == -1)
|
||||
|
|
@ -390,6 +402,11 @@ int cmdline_parser( int argc, char * const *argv, struct gengetopt_args_info *ar
|
|||
message("SSL local to remote proxy enabled\n");
|
||||
break;
|
||||
|
||||
case 'T': /* Turn off SSLv3 */
|
||||
args_info->no_ssl3_flag = !(args_info->no_ssl3_flag);
|
||||
if( args_info->verbose_flag )
|
||||
message("SSLv3 disabled\n");
|
||||
break;
|
||||
|
||||
case 'd': /* Destination host to built the tunnel to. */
|
||||
if (args_info->dest_given) {
|
||||
|
|
@ -423,6 +440,22 @@ int cmdline_parser( int argc, char * const *argv, struct gengetopt_args_info *ar
|
|||
args_info->quiet_flag = !(args_info->quiet_flag);
|
||||
break;
|
||||
|
||||
case 'z': /* Don't verify server SSL certificate */
|
||||
args_info->no_check_cert_flag = 1;
|
||||
if( args_info->verbose_flag )
|
||||
message("Server SSL certificate verification disabled\n");
|
||||
break;
|
||||
|
||||
case 'C': /* Trusted CA certificate (or directory) for server SSL certificate verification */
|
||||
if (args_info->cacert_given) {
|
||||
fprintf (stderr, "%s: `--cacert' (`-C') option given more than once\n", PACKAGE);
|
||||
clear_args ();
|
||||
exit(1);
|
||||
}
|
||||
args_info->cacert_given = 1;
|
||||
args_info->cacert_arg = gengetopt_strdup (optarg);
|
||||
break;
|
||||
|
||||
case 0: /* Long option with no short option */
|
||||
|
||||
case '?': /* Invalid option. */
|
||||
|
|
@ -503,12 +536,23 @@ int cmdline_parser( int argc, char * const *argv, struct gengetopt_args_info *ar
|
|||
}
|
||||
|
||||
if (args_info->proxy_given ) {
|
||||
char proxy_arg_fmt[32];
|
||||
size_t proxy_arg_len;
|
||||
char * phost;
|
||||
int pport;
|
||||
|
||||
phost = malloc( 50+1 );
|
||||
|
||||
r = sscanf( args_info->proxy_arg, "%50[^:]:%5u", phost, &pport );
|
||||
proxy_arg_len = strlen( args_info->proxy_arg );
|
||||
if ( (phost = malloc( proxy_arg_len + 1 )) == NULL ) {
|
||||
message( "Out of memory\n" );
|
||||
exit(1);
|
||||
}
|
||||
snprintf( proxy_arg_fmt, sizeof(proxy_arg_fmt), "%%%zu[^:]:%%5u", proxy_arg_len - 1 );
|
||||
r = sscanf( args_info->proxy_arg, proxy_arg_fmt, phost, &pport );
|
||||
if ( r != 2 ) {
|
||||
/* try bracket-enclosed IPv6 literal */
|
||||
snprintf( proxy_arg_fmt, sizeof(proxy_arg_fmt), "[%%%zu[^]]]:%%5u", proxy_arg_len - 1 );
|
||||
r = sscanf( args_info->proxy_arg, proxy_arg_fmt, phost, &pport );
|
||||
}
|
||||
if ( r == 2 ) {
|
||||
args_info->proxyhost_arg = phost;
|
||||
args_info->proxyport_arg = pport;
|
||||
|
|
|
|||
|
|
@ -47,9 +47,12 @@ struct gengetopt_args_info {
|
|||
int encrypt_flag; /* Turn on SSL encryption (default=off). */
|
||||
int encryptproxy_flag; /* Turn on client to proxy SSL encryption (def=off).*/
|
||||
int encryptremproxy_flag; /* Turn on local to remote proxy SSL encryption (def=off).*/
|
||||
int no_ssl3_flag; /* Turn off SSLv3 (default=on) */
|
||||
char *proctitle_arg; /* Override process title (default=off). */
|
||||
int enforcetls1_flag; /* Override default and enforce TLSv1 */
|
||||
char *host_arg; /* Optional Host Header */
|
||||
int no_check_cert_flag; /* Turn off server SSL certificate verification (default=on) */
|
||||
char *cacert_arg; /* Trusted CA certificate (or directory) for server SSL certificate verification */
|
||||
int help_given; /* Whether help was given. */
|
||||
int version_given; /* Whether version was given. */
|
||||
int user_given; /* Whether user was given. */
|
||||
|
|
@ -75,6 +78,7 @@ struct gengetopt_args_info {
|
|||
int proctitle_given; /* Whether to override process title */
|
||||
int enforcetls1_given; /* Wheter to enforce TLSv1 */
|
||||
int host_given; /* Wheter we override the Host Header */
|
||||
int cacert_given; /* Whether cacert was given */
|
||||
};
|
||||
|
||||
int cmdline_parser( int argc, char * const *argv, struct gengetopt_args_info *args_info );
|
||||
|
|
|
|||
|
|
@ -49,6 +49,20 @@ also be used for other proxy-traversing purposes like proxy bouncing.
|
|||
|
||||
== ADDITIONAL OPTIONS
|
||||
|
||||
*-T*, *--no-ssl3*::
|
||||
Prevent the use of SSLv3 in encrypted connections (default: enabled)
|
||||
|
||||
*-z*, *--no-check-certificate*::
|
||||
Do not verify server SSL certificate when establishing an SSL connection.
|
||||
By default, the server SSL certficate is verified and the target host name
|
||||
is checked against the server certificate's subject alternative names if
|
||||
any are present, or common name if there are no subject alternative names.
|
||||
|
||||
*-C*, *--cacert*=_filename/directory_::
|
||||
Specify a CA certificate file (or directory containing CA certificate(s))
|
||||
to trust when verifying a server SSL certificate. If a directory is provided,
|
||||
it must be prepared with OpenSSL's c_rehash tool. (default: /etc/ssl/certs)
|
||||
|
||||
*-F*, *--passfile*=_filename_::
|
||||
Use _filename_ for reading username and password for HTTPS proxy
|
||||
authentication, the file uses the same format as .wgetrc and can be shared
|
||||
|
|
|
|||
2
http.c
2
http.c
|
|
@ -159,7 +159,7 @@ void proxy_protocol(PTSTREAM *pts) {
|
|||
|
||||
/* If --encrypt-remproxy is specified, connect to the remote proxy using SSL */
|
||||
if ( args_info.encryptremproxy_flag )
|
||||
stream_enable_ssl(stunnel);
|
||||
stream_enable_ssl(stunnel, args_info.remproxy_arg);
|
||||
|
||||
if( args_info.verbose_flag )
|
||||
message( "\nTunneling to %s (destination)\n", args_info.dest_arg );
|
||||
|
|
|
|||
|
|
@ -66,45 +66,44 @@ void signal_handler( int signal ) {
|
|||
* the socket that is connected to the proxy
|
||||
*/
|
||||
int tunnel_connect() {
|
||||
struct sockaddr_in sa;
|
||||
struct hostent *he;
|
||||
struct addrinfo hints = {
|
||||
.ai_family = AF_UNSPEC,
|
||||
.ai_socktype = SOCK_STREAM,
|
||||
.ai_flags = AI_ADDRCONFIG | AI_NUMERICSERV,
|
||||
.ai_protocol = 0
|
||||
};
|
||||
struct addrinfo * result, * rp;
|
||||
int rc;
|
||||
char service[6];
|
||||
int sd;
|
||||
|
||||
/* Create the socket */
|
||||
if( ( sd = socket( AF_INET, SOCK_STREAM, 0 ) ) < 0 ) {
|
||||
my_perror("Can not create socket");
|
||||
rc = snprintf( service, sizeof(service), "%d", args_info.proxyport_arg );
|
||||
if( ( rc < 0 ) || ( rc >= sizeof(service) ) ) {
|
||||
/* this should never happen */
|
||||
message( "snprintf() failed" );
|
||||
exit(1);
|
||||
}
|
||||
|
||||
/* Lookup the IP address of the proxy */
|
||||
if( ! ( he = gethostbyname( args_info.proxyhost_arg ) ) ) {
|
||||
// FIXME: my_perror("Local proxy %s could not be resolved", args_info.proxyhost_arg);
|
||||
my_perror("Local proxy could not be resolved." );
|
||||
rc = getaddrinfo( args_info.proxyhost_arg, service, &hints, &result );
|
||||
if( rc != 0 ) {
|
||||
message( "getaddrinfo() failed to resolve local proxy: %s\n",
|
||||
gai_strerror( rc ) );
|
||||
exit(1);
|
||||
}
|
||||
|
||||
char ip[16];
|
||||
snprintf(ip, 16, "%d.%d.%d.%d", he->h_addr[0] & 255, he->h_addr[1] & 255, he->h_addr[2] & 255, he->h_addr[3] & 255);
|
||||
if( args_info.verbose_flag && strcmp(args_info.proxyhost_arg, ip)) {
|
||||
message( "Local proxy %s resolves to %d.%d.%d.%d\n",
|
||||
args_info.proxyhost_arg,
|
||||
he->h_addr[0] & 255,
|
||||
he->h_addr[1] & 255,
|
||||
he->h_addr[2] & 255,
|
||||
he->h_addr[3] & 255 );
|
||||
for (rp = result; rp != NULL; rp = rp->ai_next) {
|
||||
sd = socket( rp->ai_family, rp->ai_socktype, rp->ai_protocol );
|
||||
if( sd < 0 ) {
|
||||
continue;
|
||||
}
|
||||
if( connect( sd, rp->ai_addr, rp->ai_addrlen ) == 0 ) {
|
||||
break;
|
||||
}
|
||||
close(sd);
|
||||
}
|
||||
|
||||
/* Set up the structure to connect to the proxy port of the proxy host */
|
||||
memset( &sa, '\0', sizeof( sa ) );
|
||||
sa.sin_family = AF_INET;
|
||||
memcpy( &sa.sin_addr.s_addr, he->h_addr, 4);
|
||||
sa.sin_port = htons( args_info.proxyport_arg );
|
||||
|
||||
/* Connect the socket */
|
||||
if( connect( sd, (struct sockaddr*) &sa, sizeof( sa ) ) < 0 ) {
|
||||
my_perror("connect() failed");
|
||||
if( rp == NULL ) {
|
||||
my_perror( "failed to connect to local proxy" );
|
||||
exit(1);
|
||||
}
|
||||
freeaddrinfo(result);
|
||||
|
||||
/* Increase interactivity of tunnel, patch by Ingo Molnar */
|
||||
int flag = 1;
|
||||
|
|
@ -266,7 +265,7 @@ void do_daemon()
|
|||
#ifdef USE_SSL
|
||||
/* If --encrypt-proxy is specified, connect to the proxy using SSL */
|
||||
if ( args_info.encryptproxy_flag )
|
||||
stream_enable_ssl(stunnel);
|
||||
stream_enable_ssl(stunnel, args_info.proxy_arg);
|
||||
#endif /* USE_SSL */
|
||||
|
||||
/* Open the tunnel */
|
||||
|
|
@ -275,7 +274,7 @@ void do_daemon()
|
|||
#ifdef USE_SSL
|
||||
/* If --encrypt is specified, wrap all traffic after the proxy handoff in SSL */
|
||||
if( args_info.encrypt_flag )
|
||||
stream_enable_ssl(stunnel);
|
||||
stream_enable_ssl(stunnel, args_info.dest_arg);
|
||||
#endif /* USE_SSL */
|
||||
|
||||
#ifdef SETPROCTITLE
|
||||
|
|
@ -388,7 +387,7 @@ int main( int argc, char *argv[] ) {
|
|||
/* If --encrypt-proxy is specified, connect to the proxy using SSL */
|
||||
#ifdef USE_SSL
|
||||
if ( args_info.encryptproxy_flag )
|
||||
stream_enable_ssl(stunnel);
|
||||
stream_enable_ssl(stunnel, args_info.proxy_arg);
|
||||
#endif /* USE_SSL */
|
||||
|
||||
/* Open the tunnel */
|
||||
|
|
@ -397,7 +396,7 @@ int main( int argc, char *argv[] ) {
|
|||
/* If --encrypt is specified, wrap all traffic after the proxy handoff in SSL */
|
||||
#ifdef USE_SSL
|
||||
if( args_info.encrypt_flag )
|
||||
stream_enable_ssl(stunnel);
|
||||
stream_enable_ssl(stunnel, args_info.dest_arg);
|
||||
#endif /* USE_SSL */
|
||||
|
||||
#ifdef SETPROCTITLE
|
||||
|
|
|
|||
176
ptstream.c
176
ptstream.c
|
|
@ -19,12 +19,15 @@
|
|||
|
||||
/* ptstream.c */
|
||||
|
||||
#include <arpa/inet.h>
|
||||
#include <openssl/x509v3.h>
|
||||
#include <stdio.h>
|
||||
#include <stdlib.h>
|
||||
#include <string.h>
|
||||
#include <unistd.h>
|
||||
#include <sys/types.h>
|
||||
#include <sys/socket.h>
|
||||
#include <sys/stat.h>
|
||||
|
||||
#include "proxytunnel.h"
|
||||
|
||||
|
|
@ -142,14 +145,112 @@ int stream_copy(PTSTREAM *pts_from, PTSTREAM *pts_to) {
|
|||
}
|
||||
|
||||
|
||||
/* Check the certificate host name against the expected host name */
|
||||
/* Return 1 if peer hostname is valid, any other value indicates failure */
|
||||
int check_cert_valid_host(const char *cert_host, const char *peer_host) {
|
||||
if (cert_host == NULL || peer_host == NULL) {
|
||||
return 0;
|
||||
}
|
||||
if (cert_host[0] == '*') {
|
||||
if (strncmp(cert_host, "*.", 2) != 0) {
|
||||
/* Invalid wildcard hostname */
|
||||
return 0;
|
||||
}
|
||||
/* Skip "*." */
|
||||
cert_host += 2;
|
||||
/* Wildcards can only match the first subdomain component */
|
||||
while (*peer_host++ != '.' && *peer_host != '\0')
|
||||
;;
|
||||
}
|
||||
if (strlen(cert_host) == 0 || strlen(peer_host) == 0) {
|
||||
return 0;
|
||||
}
|
||||
return strcmp(cert_host, peer_host) == 0;
|
||||
}
|
||||
|
||||
|
||||
int check_cert_valid_ip6(const unsigned char *cert_ip_data, const int cert_ip_len, const struct in6_addr *addr6) {
|
||||
int i;
|
||||
for (i = 0; i < cert_ip_len; i++) {
|
||||
if (cert_ip_data[i] != addr6->s6_addr[i]) {
|
||||
return 0;
|
||||
}
|
||||
}
|
||||
return 1;
|
||||
}
|
||||
|
||||
|
||||
int check_cert_valid_ip(const unsigned char *cert_ip_data, const int cert_ip_len, const struct in_addr *addr) {
|
||||
int i;
|
||||
for (i = 0; i < cert_ip_len; i++) {
|
||||
if (cert_ip_data[i] != ((addr->s_addr >> (i * 8)) & 0xFF)) {
|
||||
return 0;
|
||||
}
|
||||
}
|
||||
return 1;
|
||||
}
|
||||
|
||||
|
||||
int check_cert_names(X509 *cert, char *peer_host) {
|
||||
char peer_cn[256];
|
||||
const GENERAL_NAME *gn;
|
||||
STACK_OF(GENERAL_NAME) *gen_names;
|
||||
struct in_addr addr;
|
||||
struct in6_addr addr6;
|
||||
int peer_host_is_ipv4 = 0, peer_host_is_ipv6 = 0;
|
||||
int i, san_count;
|
||||
|
||||
gen_names = X509_get_ext_d2i(cert, NID_subject_alt_name, NULL, NULL);
|
||||
san_count = sk_GENERAL_NAME_num(gen_names);
|
||||
if (san_count > 0) {
|
||||
peer_host_is_ipv4 = (inet_pton(AF_INET, peer_host, &addr) == 1);
|
||||
peer_host_is_ipv6 = (peer_host_is_ipv4 ? 0 : inet_pton(AF_INET6, peer_host, &addr6) == 1);
|
||||
for (i = 0; i < san_count; i++) {
|
||||
gn = sk_GENERAL_NAME_value(gen_names, i);
|
||||
if (gn->type == GEN_DNS && !(peer_host_is_ipv4 || peer_host_is_ipv6)) {
|
||||
if (check_cert_valid_host((char*)ASN1_STRING_data(gn->d.ia5), peer_host)) {
|
||||
return 1;
|
||||
}
|
||||
} else if (gn->type == GEN_IPADD) {
|
||||
if (gn->d.ip->length == 4 && peer_host_is_ipv4) {
|
||||
if (check_cert_valid_ip(gn->d.ip->data, gn->d.ip->length, &addr)) {
|
||||
return 1;
|
||||
}
|
||||
} else if (gn->d.ip->length == 16 && peer_host_is_ipv6) {
|
||||
if (check_cert_valid_ip6(gn->d.ip->data, gn->d.ip->length, &addr6)) {
|
||||
return 1;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
message("Host name %s does not match certificate subject alternative names\n", peer_host);
|
||||
} else {
|
||||
X509_NAME_get_text_by_NID(X509_get_subject_name(cert), NID_commonName, peer_cn, sizeof(peer_cn));
|
||||
message("Host name %s does not match certificate common name %s or any subject alternative names\n", peer_host, peer_cn);
|
||||
return check_cert_valid_host(peer_cn, peer_host);
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
/* Initiate an SSL handshake on this stream and encrypt all subsequent data */
|
||||
int stream_enable_ssl(PTSTREAM *pts) {
|
||||
int stream_enable_ssl(PTSTREAM *pts, const char *proxy_arg) {
|
||||
#ifdef USE_SSL
|
||||
const SSL_METHOD *meth;
|
||||
SSL *ssl;
|
||||
SSL_CTX *ctx;
|
||||
long res = 1;
|
||||
|
||||
long ssl_options = 0;
|
||||
|
||||
X509* cert = NULL;
|
||||
int status;
|
||||
struct stat st_buf;
|
||||
const char *ca_file = NULL;
|
||||
const char *ca_dir = "/etc/ssl/certs/"; /* Default cert directory if none given */
|
||||
long vresult;
|
||||
char *peer_host = NULL;
|
||||
char proxy_arg_fmt[32];
|
||||
size_t proxy_arg_len;
|
||||
|
||||
/* Initialise the connection */
|
||||
SSLeay_add_ssl_algorithms();
|
||||
if (args_info.enforcetls1_flag) {
|
||||
|
|
@ -160,6 +261,30 @@ int stream_enable_ssl(PTSTREAM *pts) {
|
|||
SSL_load_error_strings();
|
||||
|
||||
ctx = SSL_CTX_new (meth);
|
||||
if (args_info.no_ssl3_flag) {
|
||||
ssl_options |= SSL_OP_NO_SSLv3;
|
||||
}
|
||||
SSL_CTX_set_options (ctx, ssl_options);
|
||||
|
||||
if ( !args_info.no_check_cert_flag ) {
|
||||
if ( args_info.cacert_given ) {
|
||||
if ((status = stat(args_info.cacert_arg, &st_buf)) != 0) {
|
||||
message("Error reading certificate path %s\n", args_info.cacert_arg);
|
||||
goto fail;
|
||||
}
|
||||
if (S_ISDIR(st_buf.st_mode)) {
|
||||
ca_dir = args_info.cacert_arg;
|
||||
} else {
|
||||
ca_dir = NULL;
|
||||
ca_file = args_info.cacert_arg;
|
||||
}
|
||||
}
|
||||
if (!SSL_CTX_load_verify_locations(ctx, ca_file, ca_dir)) {
|
||||
message("Error loading certificate(s) from %s\n", args_info.cacert_arg);
|
||||
goto fail;
|
||||
}
|
||||
}
|
||||
|
||||
ssl = SSL_new (ctx);
|
||||
|
||||
SSL_set_rfd (ssl, stream_get_incoming_fd(pts));
|
||||
|
|
@ -177,6 +302,42 @@ int stream_enable_ssl(PTSTREAM *pts) {
|
|||
|
||||
SSL_connect (ssl);
|
||||
|
||||
if ( !args_info.no_check_cert_flag ) {
|
||||
/* Make sure peer presented a certificate */
|
||||
cert = SSL_get_peer_certificate(ssl);
|
||||
if (cert == NULL) {
|
||||
message("No certificate presented\n");
|
||||
goto fail;
|
||||
}
|
||||
|
||||
/* Check that the certificate is valid */
|
||||
vresult = SSL_get_verify_result(ssl);
|
||||
if (vresult != X509_V_OK) {
|
||||
message("Certificate verification failed (%s)\n",
|
||||
X509_verify_cert_error_string(vresult));
|
||||
goto fail;
|
||||
}
|
||||
|
||||
/* Determine the host name we are connecting to */
|
||||
proxy_arg_len = strlen(proxy_arg);
|
||||
if ((peer_host = malloc(proxy_arg_len + 1)) == NULL) {
|
||||
message("Out of memory\n");
|
||||
goto fail;
|
||||
}
|
||||
snprintf( proxy_arg_fmt, sizeof(proxy_arg_fmt), proxy_arg[0] == '[' ? "[%%%zu[^]]]" : "%%%zu[^:]", proxy_arg_len - 1 );
|
||||
if ( sscanf( proxy_arg, proxy_arg_fmt, peer_host ) != 1 ) {
|
||||
goto fail;
|
||||
}
|
||||
|
||||
/* Verify the certificate name matches the host we are connecting to */
|
||||
if (!check_cert_names(cert, peer_host)) {
|
||||
goto fail;
|
||||
}
|
||||
|
||||
free(peer_host);
|
||||
X509_free(cert);
|
||||
}
|
||||
|
||||
/* Store ssl and ctx parameters */
|
||||
pts->ssl = ssl;
|
||||
pts->ctx = ctx;
|
||||
|
|
@ -185,6 +346,17 @@ int stream_enable_ssl(PTSTREAM *pts) {
|
|||
#endif /* USE_SSL */
|
||||
|
||||
return 1;
|
||||
|
||||
fail:
|
||||
#ifdef USE_SSL
|
||||
if (cert != NULL) {
|
||||
X509_free(cert);
|
||||
}
|
||||
if (peer_host != NULL) {
|
||||
free(peer_host);
|
||||
}
|
||||
#endif /* USE_SSL */
|
||||
exit(1);
|
||||
}
|
||||
|
||||
|
||||
|
|
|
|||
|
|
@ -44,7 +44,7 @@ int stream_close(PTSTREAM *pts);
|
|||
int stream_read(PTSTREAM *pts, void *buf, size_t len);
|
||||
int stream_write(PTSTREAM *pts, void *buf, size_t len);
|
||||
int stream_copy(PTSTREAM *pts_from, PTSTREAM *pts_to);
|
||||
int stream_enable_ssl(PTSTREAM *pts);
|
||||
int stream_enable_ssl(PTSTREAM *pts, const char *proxy_arg);
|
||||
int stream_get_incoming_fd(PTSTREAM *pts);
|
||||
int stream_get_outgoing_fd(PTSTREAM *pts);
|
||||
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue