2012-04-13 12:47:30 +00:00
|
|
|
/*
|
2015-02-24 18:19:20 +00:00
|
|
|
* SSLsplit - transparent SSL/TLS interception
|
2018-01-18 00:18:53 +00:00
|
|
|
* Copyright (c) 2009-2018, Daniel Roethlisberger <daniel@roe.ch>
|
|
|
|
* Copyright (c) 2017-2018, Soner Tari <sonertari@gmail.com>
|
2012-04-13 12:47:30 +00:00
|
|
|
* All rights reserved.
|
|
|
|
* http://www.roe.ch/SSLsplit
|
|
|
|
*
|
|
|
|
* Redistribution and use in source and binary forms, with or without
|
|
|
|
* modification, are permitted provided that the following conditions
|
|
|
|
* are met:
|
|
|
|
* 1. Redistributions of source code must retain the above copyright
|
2015-02-24 18:19:20 +00:00
|
|
|
* notice, this list of conditions, and the following disclaimer.
|
2012-04-13 12:47:30 +00:00
|
|
|
* 2. Redistributions in binary form must reproduce the above copyright
|
|
|
|
* notice, this list of conditions and the following disclaimer in the
|
|
|
|
* documentation and/or other materials provided with the distribution.
|
|
|
|
*
|
|
|
|
* THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
|
|
|
|
* IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
|
|
|
|
* OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
|
|
|
|
* IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
|
|
|
|
* INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
|
|
|
|
* NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
|
|
|
|
* DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
|
|
|
|
* THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
|
|
|
|
* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
|
|
|
|
* THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
|
|
|
*/
|
|
|
|
|
|
|
|
#include "opts.h"
|
|
|
|
|
|
|
|
#include "sys.h"
|
2014-11-05 20:18:53 +00:00
|
|
|
#include "log.h"
|
2012-04-13 12:47:30 +00:00
|
|
|
|
|
|
|
#include <string.h>
|
|
|
|
#include <sys/types.h>
|
|
|
|
#include <sys/socket.h>
|
|
|
|
|
|
|
|
#ifndef OPENSSL_NO_DH
|
|
|
|
#include <openssl/dh.h>
|
|
|
|
#endif /* !OPENSSL_NO_DH */
|
|
|
|
#include <openssl/x509.h>
|
|
|
|
|
|
|
|
opts_t *
|
|
|
|
opts_new(void)
|
|
|
|
{
|
|
|
|
opts_t *opts;
|
|
|
|
|
|
|
|
opts = malloc(sizeof(opts_t));
|
|
|
|
memset(opts, 0, sizeof(opts_t));
|
|
|
|
|
|
|
|
opts->sslcomp = 1;
|
|
|
|
opts->chain = sk_X509_new_null();
|
2014-11-05 19:06:11 +00:00
|
|
|
opts->sslmethod = SSLv23_method;
|
2012-04-13 12:47:30 +00:00
|
|
|
|
|
|
|
return opts;
|
|
|
|
}
|
|
|
|
|
|
|
|
void
|
|
|
|
opts_free(opts_t *opts)
|
|
|
|
{
|
|
|
|
sk_X509_pop_free(opts->chain, X509_free);
|
|
|
|
if (opts->cacrt) {
|
|
|
|
X509_free(opts->cacrt);
|
|
|
|
}
|
|
|
|
if (opts->cakey) {
|
|
|
|
EVP_PKEY_free(opts->cakey);
|
|
|
|
}
|
|
|
|
if (opts->key) {
|
|
|
|
EVP_PKEY_free(opts->key);
|
|
|
|
}
|
|
|
|
#ifndef OPENSSL_NO_DH
|
|
|
|
if (opts->dh) {
|
|
|
|
DH_free(opts->dh);
|
|
|
|
}
|
|
|
|
#endif /* !OPENSSL_NO_DH */
|
|
|
|
#ifndef OPENSSL_NO_ECDH
|
|
|
|
if (opts->ecdhcurve) {
|
|
|
|
free(opts->ecdhcurve);
|
|
|
|
}
|
|
|
|
#endif /* !OPENSSL_NO_ECDH */
|
|
|
|
if (opts->spec) {
|
|
|
|
proxyspec_free(opts->spec);
|
|
|
|
}
|
|
|
|
if (opts->ciphers) {
|
|
|
|
free(opts->ciphers);
|
|
|
|
}
|
|
|
|
if (opts->tgcrtdir) {
|
|
|
|
free(opts->tgcrtdir);
|
|
|
|
}
|
2018-01-18 00:18:53 +00:00
|
|
|
if (opts->crlurl) {
|
|
|
|
free(opts->crlurl);
|
|
|
|
}
|
2012-04-13 12:47:30 +00:00
|
|
|
if (opts->dropuser) {
|
|
|
|
free(opts->dropuser);
|
|
|
|
}
|
2014-10-18 06:34:51 +00:00
|
|
|
if (opts->dropgroup) {
|
|
|
|
free(opts->dropgroup);
|
|
|
|
}
|
2012-04-13 12:47:30 +00:00
|
|
|
if (opts->jaildir) {
|
|
|
|
free(opts->jaildir);
|
|
|
|
}
|
|
|
|
if (opts->pidfile) {
|
|
|
|
free(opts->pidfile);
|
|
|
|
}
|
|
|
|
if (opts->connectlog) {
|
|
|
|
free(opts->connectlog);
|
|
|
|
}
|
|
|
|
if (opts->contentlog) {
|
|
|
|
free(opts->contentlog);
|
|
|
|
}
|
2014-12-09 20:02:25 +00:00
|
|
|
if (opts->certgendir) {
|
|
|
|
free(opts->certgendir);
|
|
|
|
}
|
2014-11-24 21:01:52 +00:00
|
|
|
if (opts->contentlog_basedir) {
|
|
|
|
free(opts->contentlog_basedir);
|
|
|
|
}
|
2012-04-13 12:47:30 +00:00
|
|
|
memset(opts, 0, sizeof(opts_t));
|
|
|
|
free(opts);
|
|
|
|
}
|
|
|
|
|
|
|
|
/*
|
2015-04-21 14:00:55 +00:00
|
|
|
* Return 1 if opts_t contains a proxyspec that (eventually) uses SSL/TLS,
|
|
|
|
* 0 otherwise. When 0, it is safe to assume that no SSL/TLS operations
|
|
|
|
* will take place with this configuration.
|
2012-04-13 12:47:30 +00:00
|
|
|
*/
|
|
|
|
int
|
|
|
|
opts_has_ssl_spec(opts_t *opts)
|
|
|
|
{
|
|
|
|
proxyspec_t *p = opts->spec;
|
|
|
|
|
|
|
|
while (p) {
|
2015-04-21 14:00:55 +00:00
|
|
|
if (p->ssl || p->upgrade)
|
2012-04-13 12:47:30 +00:00
|
|
|
return 1;
|
|
|
|
p = p->next;
|
|
|
|
}
|
|
|
|
|
|
|
|
return 0;
|
|
|
|
}
|
|
|
|
|
2015-09-27 14:39:24 +00:00
|
|
|
/*
|
|
|
|
* Return 1 if opts_t contains a proxyspec with dns, 0 otherwise.
|
|
|
|
*/
|
|
|
|
int
|
|
|
|
opts_has_dns_spec(opts_t *opts)
|
|
|
|
{
|
|
|
|
proxyspec_t *p = opts->spec;
|
|
|
|
|
|
|
|
while (p) {
|
|
|
|
if (p->dns)
|
|
|
|
return 1;
|
|
|
|
p = p->next;
|
|
|
|
}
|
|
|
|
|
|
|
|
return 0;
|
|
|
|
}
|
|
|
|
|
2014-11-05 19:06:11 +00:00
|
|
|
/*
|
|
|
|
* Parse SSL proto string in optarg and look up the corresponding SSL method.
|
|
|
|
* Calls exit() on failure.
|
|
|
|
*/
|
|
|
|
void
|
|
|
|
opts_proto_force(opts_t *opts, const char *optarg, const char *argv0)
|
|
|
|
{
|
|
|
|
if (opts->sslmethod != SSLv23_method) {
|
|
|
|
fprintf(stderr, "%s: cannot use -r multiple times\n", argv0);
|
|
|
|
exit(EXIT_FAILURE);
|
|
|
|
}
|
|
|
|
|
2015-07-28 21:23:53 +00:00
|
|
|
#ifdef HAVE_SSLV2
|
2014-11-05 19:06:11 +00:00
|
|
|
if (!strcmp(optarg, "ssl2")) {
|
|
|
|
opts->sslmethod = SSLv2_method;
|
|
|
|
} else
|
2015-07-28 21:23:53 +00:00
|
|
|
#endif /* HAVE_SSLV2 */
|
|
|
|
#ifdef HAVE_SSLV3
|
2014-11-05 19:06:11 +00:00
|
|
|
if (!strcmp(optarg, "ssl3")) {
|
|
|
|
opts->sslmethod = SSLv3_method;
|
|
|
|
} else
|
2015-07-28 21:23:53 +00:00
|
|
|
#endif /* HAVE_SSLV3 */
|
|
|
|
#ifdef HAVE_TLSV10
|
2014-11-05 19:06:11 +00:00
|
|
|
if (!strcmp(optarg, "tls10") || !strcmp(optarg, "tls1")) {
|
|
|
|
opts->sslmethod = TLSv1_method;
|
|
|
|
} else
|
2015-07-28 21:23:53 +00:00
|
|
|
#endif /* HAVE_TLSV10 */
|
|
|
|
#ifdef HAVE_TLSV11
|
2014-11-05 19:06:11 +00:00
|
|
|
if (!strcmp(optarg, "tls11")) {
|
|
|
|
opts->sslmethod = TLSv1_1_method;
|
|
|
|
} else
|
2015-07-28 21:23:53 +00:00
|
|
|
#endif /* HAVE_TLSV11 */
|
|
|
|
#ifdef HAVE_TLSV12
|
2014-11-05 19:06:11 +00:00
|
|
|
if (!strcmp(optarg, "tls12")) {
|
|
|
|
opts->sslmethod = TLSv1_2_method;
|
|
|
|
} else
|
2015-07-28 21:23:53 +00:00
|
|
|
#endif /* HAVE_TLSV12 */
|
2014-11-05 19:06:11 +00:00
|
|
|
{
|
|
|
|
fprintf(stderr, "%s: Unsupported SSL/TLS protocol '%s'\n",
|
|
|
|
argv0, optarg);
|
|
|
|
exit(EXIT_FAILURE);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
/*
|
|
|
|
* Parse SSL proto string in optarg and set the corresponding no_foo bit.
|
|
|
|
* Calls exit() on failure.
|
|
|
|
*/
|
|
|
|
void
|
|
|
|
opts_proto_disable(opts_t *opts, const char *optarg, const char *argv0)
|
|
|
|
{
|
2015-07-28 21:23:53 +00:00
|
|
|
#ifdef HAVE_SSLV2
|
2014-11-05 19:06:11 +00:00
|
|
|
if (!strcmp(optarg, "ssl2")) {
|
|
|
|
opts->no_ssl2 = 1;
|
|
|
|
} else
|
2015-07-28 21:23:53 +00:00
|
|
|
#endif /* HAVE_SSLV2 */
|
|
|
|
#ifdef HAVE_SSLV3
|
2014-11-05 19:06:11 +00:00
|
|
|
if (!strcmp(optarg, "ssl3")) {
|
|
|
|
opts->no_ssl3 = 1;
|
|
|
|
} else
|
2015-07-28 21:23:53 +00:00
|
|
|
#endif /* HAVE_SSLV3 */
|
|
|
|
#ifdef HAVE_TLSV10
|
2014-11-05 19:06:11 +00:00
|
|
|
if (!strcmp(optarg, "tls10") || !strcmp(optarg, "tls1")) {
|
|
|
|
opts->no_tls10 = 1;
|
|
|
|
} else
|
2015-07-28 21:23:53 +00:00
|
|
|
#endif /* HAVE_TLSV10 */
|
|
|
|
#ifdef HAVE_TLSV11
|
2014-11-05 19:06:11 +00:00
|
|
|
if (!strcmp(optarg, "tls11")) {
|
|
|
|
opts->no_tls11 = 1;
|
|
|
|
} else
|
2015-07-28 21:23:53 +00:00
|
|
|
#endif /* HAVE_TLSV11 */
|
|
|
|
#ifdef HAVE_TLSV12
|
2014-11-05 19:06:11 +00:00
|
|
|
if (!strcmp(optarg, "tls12")) {
|
|
|
|
opts->no_tls12 = 1;
|
|
|
|
} else
|
2015-07-28 21:23:53 +00:00
|
|
|
#endif /* HAVE_TLSV12 */
|
2014-11-05 19:06:11 +00:00
|
|
|
{
|
|
|
|
fprintf(stderr, "%s: Unsupported SSL/TLS protocol '%s'\n",
|
|
|
|
argv0, optarg);
|
|
|
|
exit(EXIT_FAILURE);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2014-11-05 20:18:53 +00:00
|
|
|
/*
|
|
|
|
* Dump the SSL/TLS protocol related configuration to the debug log.
|
|
|
|
*/
|
|
|
|
void
|
|
|
|
opts_proto_dbg_dump(opts_t *opts)
|
|
|
|
{
|
|
|
|
log_dbg_printf("SSL/TLS protocol: %s%s%s%s%s%s\n",
|
2015-07-28 21:23:53 +00:00
|
|
|
#ifdef HAVE_SSLV2
|
2014-11-05 20:18:53 +00:00
|
|
|
(opts->sslmethod == SSLv2_method) ? "nossl2" :
|
2015-07-28 21:23:53 +00:00
|
|
|
#endif /* HAVE_SSLV2 */
|
|
|
|
#ifdef HAVE_SSLV3
|
2014-11-05 20:18:53 +00:00
|
|
|
(opts->sslmethod == SSLv3_method) ? "ssl3" :
|
2015-07-28 21:23:53 +00:00
|
|
|
#endif /* HAVE_SSLV3 */
|
|
|
|
#ifdef HAVE_TLSV10
|
2014-11-05 20:18:53 +00:00
|
|
|
(opts->sslmethod == TLSv1_method) ? "tls10" :
|
2015-07-28 21:23:53 +00:00
|
|
|
#endif /* HAVE_TLSV10 */
|
|
|
|
#ifdef HAVE_TLSV11
|
2014-11-05 20:18:53 +00:00
|
|
|
(opts->sslmethod == TLSv1_1_method) ? "tls11" :
|
2015-07-28 21:23:53 +00:00
|
|
|
#endif /* HAVE_TLSV11 */
|
|
|
|
#ifdef HAVE_TLSV12
|
2014-11-05 20:18:53 +00:00
|
|
|
(opts->sslmethod == TLSv1_2_method) ? "tls12" :
|
2015-07-28 21:23:53 +00:00
|
|
|
#endif /* HAVE_TLSV12 */
|
2014-11-05 20:18:53 +00:00
|
|
|
"negotiate",
|
2015-07-28 21:23:53 +00:00
|
|
|
#ifdef HAVE_SSLV2
|
2014-11-05 20:18:53 +00:00
|
|
|
opts->no_ssl2 ? " -ssl2" :
|
2015-07-28 21:23:53 +00:00
|
|
|
#endif /* HAVE_SSLV2 */
|
2014-11-05 20:18:53 +00:00
|
|
|
"",
|
2015-07-28 21:23:53 +00:00
|
|
|
#ifdef HAVE_SSLV3
|
2014-11-05 20:18:53 +00:00
|
|
|
opts->no_ssl3 ? " -ssl3" :
|
2015-07-28 21:23:53 +00:00
|
|
|
#endif /* HAVE_SSLV3 */
|
2014-11-05 20:18:53 +00:00
|
|
|
"",
|
2015-07-28 21:23:53 +00:00
|
|
|
#ifdef HAVE_TLSV10
|
2014-11-05 20:18:53 +00:00
|
|
|
opts->no_tls10 ? " -tls10" :
|
2015-07-28 21:23:53 +00:00
|
|
|
#endif /* HAVE_TLSV10 */
|
2014-11-05 20:18:53 +00:00
|
|
|
"",
|
2015-07-28 21:23:53 +00:00
|
|
|
#ifdef HAVE_TLSV11
|
2014-11-05 20:18:53 +00:00
|
|
|
opts->no_tls11 ? " -tls11" :
|
2015-07-28 21:23:53 +00:00
|
|
|
#endif /* HAVE_TLSV11 */
|
2014-11-05 20:18:53 +00:00
|
|
|
"",
|
2015-07-28 21:23:53 +00:00
|
|
|
#ifdef HAVE_TLSV12
|
2014-11-05 20:18:53 +00:00
|
|
|
opts->no_tls12 ? " -tls12" :
|
2015-07-28 21:23:53 +00:00
|
|
|
#endif /* HAVE_TLSV12 */
|
2014-11-05 20:18:53 +00:00
|
|
|
"");
|
|
|
|
}
|
|
|
|
|
2018-01-18 00:18:53 +00:00
|
|
|
|
2012-04-13 12:47:30 +00:00
|
|
|
/*
|
|
|
|
* Parse proxyspecs using a simple state machine.
|
|
|
|
*/
|
2017-08-16 13:01:52 +00:00
|
|
|
void
|
|
|
|
proxyspec_parse(int *argc, char **argv[], const char *natengine, opts_t *opts)
|
2012-04-13 12:47:30 +00:00
|
|
|
{
|
2017-08-21 23:02:30 +00:00
|
|
|
proxyspec_t *curspec = NULL;
|
2015-03-02 09:23:48 +00:00
|
|
|
char *addr = NULL;
|
|
|
|
int af = AF_UNSPEC;
|
2012-04-13 12:47:30 +00:00
|
|
|
int state = 0;
|
|
|
|
|
|
|
|
while ((*argc)--) {
|
|
|
|
switch (state) {
|
|
|
|
default:
|
|
|
|
case 0:
|
2017-08-19 22:46:57 +00:00
|
|
|
/* tcp | ssl | http | https | autossl | pop3 | pop3s | smtp | smtps */
|
2012-04-13 12:47:30 +00:00
|
|
|
curspec = malloc(sizeof(proxyspec_t));
|
|
|
|
memset(curspec, 0, sizeof(proxyspec_t));
|
2017-08-16 13:01:52 +00:00
|
|
|
|
|
|
|
curspec->next = opts->spec;
|
|
|
|
opts->spec = curspec;
|
|
|
|
|
2017-08-03 11:55:57 +00:00
|
|
|
// Defaults
|
2017-08-16 13:01:52 +00:00
|
|
|
curspec->ssl = 0;
|
|
|
|
curspec->http = 0;
|
|
|
|
curspec->upgrade = 0;
|
|
|
|
curspec->mail = 0;
|
2017-08-19 22:46:57 +00:00
|
|
|
curspec->pop3 = 0;
|
|
|
|
curspec->smtp = 0;
|
2012-04-13 12:47:30 +00:00
|
|
|
if (!strcmp(**argv, "tcp")) {
|
2017-08-03 11:55:57 +00:00
|
|
|
// use defaults
|
2012-04-13 12:47:30 +00:00
|
|
|
} else
|
|
|
|
if (!strcmp(**argv, "ssl")) {
|
2017-08-16 13:01:52 +00:00
|
|
|
curspec->ssl = 1;
|
2012-04-13 12:47:30 +00:00
|
|
|
} else
|
|
|
|
if (!strcmp(**argv, "http")) {
|
2017-08-16 13:01:52 +00:00
|
|
|
curspec->http = 1;
|
2012-04-13 12:47:30 +00:00
|
|
|
} else
|
|
|
|
if (!strcmp(**argv, "https")) {
|
2017-08-16 13:01:52 +00:00
|
|
|
curspec->ssl = 1;
|
|
|
|
curspec->http = 1;
|
2015-04-18 12:26:03 +00:00
|
|
|
} else
|
2015-04-21 14:00:55 +00:00
|
|
|
if (!strcmp(**argv, "autossl")) {
|
2017-08-16 13:01:52 +00:00
|
|
|
curspec->upgrade = 1;
|
2017-08-03 11:55:57 +00:00
|
|
|
} else
|
2017-08-19 22:46:57 +00:00
|
|
|
if (!strcmp(**argv, "pop3")) {
|
2017-08-16 13:01:52 +00:00
|
|
|
curspec->mail = 1;
|
2017-08-19 22:46:57 +00:00
|
|
|
curspec->pop3 = 1;
|
2017-08-03 11:55:57 +00:00
|
|
|
} else
|
2017-08-19 22:46:57 +00:00
|
|
|
if (!strcmp(**argv, "pop3s")) {
|
2017-08-16 13:01:52 +00:00
|
|
|
curspec->ssl = 1;
|
|
|
|
curspec->mail = 1;
|
2017-08-19 22:46:57 +00:00
|
|
|
curspec->pop3 = 1;
|
|
|
|
} else
|
|
|
|
if (!strcmp(**argv, "smtp")) {
|
|
|
|
curspec->mail = 1;
|
|
|
|
curspec->smtp = 1;
|
|
|
|
} else
|
|
|
|
if (!strcmp(**argv, "smtps")) {
|
|
|
|
curspec->ssl = 1;
|
|
|
|
curspec->mail = 1;
|
|
|
|
curspec->smtp = 1;
|
2012-04-13 12:47:30 +00:00
|
|
|
} else {
|
|
|
|
fprintf(stderr, "Unknown connection "
|
|
|
|
"type '%s'\n", **argv);
|
|
|
|
exit(EXIT_FAILURE);
|
|
|
|
}
|
|
|
|
state++;
|
|
|
|
break;
|
|
|
|
case 1:
|
|
|
|
/* listenaddr */
|
2017-07-25 13:07:39 +00:00
|
|
|
addr = **argv;
|
2012-04-13 12:47:30 +00:00
|
|
|
state++;
|
|
|
|
break;
|
|
|
|
case 2:
|
|
|
|
/* listenport */
|
|
|
|
if (strstr(addr, ":"))
|
|
|
|
af = AF_INET6;
|
|
|
|
else if (!strpbrk(addr, "abcdefghijklmnopqrstu"
|
|
|
|
"vwxyzABCDEFGHIJKLMNOP"
|
|
|
|
"QRSTUVWXYZ-"))
|
|
|
|
af = AF_INET;
|
|
|
|
else
|
|
|
|
af = AF_UNSPEC;
|
2017-08-16 13:01:52 +00:00
|
|
|
af = sys_sockaddr_parse(&curspec->listen_addr,
|
|
|
|
&curspec->listen_addrlen,
|
2012-04-13 12:47:30 +00:00
|
|
|
addr, **argv, af,
|
|
|
|
EVUTIL_AI_PASSIVE);
|
|
|
|
if (af == -1) {
|
|
|
|
exit(EXIT_FAILURE);
|
|
|
|
}
|
2014-10-18 01:35:44 +00:00
|
|
|
if (natengine) {
|
2017-08-16 13:01:52 +00:00
|
|
|
curspec->natengine = strdup(natengine);
|
|
|
|
if (!curspec->natengine) {
|
2014-10-23 10:49:12 +00:00
|
|
|
fprintf(stderr,
|
|
|
|
"Out of memory"
|
|
|
|
"\n");
|
|
|
|
exit(EXIT_FAILURE);
|
|
|
|
}
|
2014-10-18 01:35:44 +00:00
|
|
|
} else {
|
2017-08-16 13:01:52 +00:00
|
|
|
curspec->natengine = NULL;
|
2014-10-18 01:35:44 +00:00
|
|
|
}
|
2012-04-13 12:47:30 +00:00
|
|
|
state++;
|
|
|
|
break;
|
|
|
|
case 3:
|
2017-08-19 22:46:57 +00:00
|
|
|
// UTM port is mandatory
|
2017-07-22 13:30:40 +00:00
|
|
|
// The UTM port is set/used in pf and UTM service config.
|
|
|
|
// @todo Need IPv6?
|
|
|
|
if (strstr(**argv, "up:")) {
|
2017-08-16 13:01:52 +00:00
|
|
|
af = sys_sockaddr_parse(&curspec->parent_dst_addr,
|
|
|
|
&curspec->parent_dst_addrlen,
|
|
|
|
"127.0.0.1", **argv + 3, AF_INET, EVUTIL_AI_PASSIVE);
|
2017-07-22 13:30:40 +00:00
|
|
|
if (af == -1) {
|
|
|
|
exit(EXIT_FAILURE);
|
|
|
|
}
|
2017-08-16 13:01:52 +00:00
|
|
|
af = sys_sockaddr_parse(&curspec->child_src_addr,
|
|
|
|
&curspec->child_src_addrlen,
|
2017-07-22 13:30:40 +00:00
|
|
|
"127.0.0.1", "0", AF_INET, EVUTIL_AI_PASSIVE);
|
|
|
|
if (af == -1) {
|
|
|
|
exit(EXIT_FAILURE);
|
|
|
|
}
|
|
|
|
state++;
|
|
|
|
}
|
|
|
|
break;
|
|
|
|
case 4:
|
2012-04-13 12:47:30 +00:00
|
|
|
/* [ natengine | dstaddr ] */
|
|
|
|
if (!strcmp(**argv, "tcp") ||
|
|
|
|
!strcmp(**argv, "ssl") ||
|
|
|
|
!strcmp(**argv, "http") ||
|
2016-03-27 12:38:06 +00:00
|
|
|
!strcmp(**argv, "https") ||
|
2017-08-03 11:55:57 +00:00
|
|
|
!strcmp(**argv, "autossl") ||
|
2017-08-19 22:46:57 +00:00
|
|
|
!strcmp(**argv, "pop3") ||
|
|
|
|
!strcmp(**argv, "pop3s") ||
|
|
|
|
!strcmp(**argv, "smtp") ||
|
|
|
|
!strcmp(**argv, "smtps")) {
|
2012-04-13 12:47:30 +00:00
|
|
|
/* implicit default natengine */
|
|
|
|
(*argv)--; (*argc)++; /* rewind */
|
|
|
|
state = 0;
|
|
|
|
} else
|
|
|
|
if (!strcmp(**argv, "sni")) {
|
2017-08-16 13:01:52 +00:00
|
|
|
free(curspec->natengine);
|
|
|
|
curspec->natengine = NULL;
|
|
|
|
if (!curspec->ssl) {
|
2012-04-13 12:47:30 +00:00
|
|
|
fprintf(stderr,
|
|
|
|
"SNI hostname lookup "
|
|
|
|
"only works for ssl "
|
|
|
|
"and https proxyspecs"
|
|
|
|
"\n");
|
|
|
|
exit(EXIT_FAILURE);
|
|
|
|
}
|
2017-07-22 13:30:40 +00:00
|
|
|
state = 6;
|
2012-04-13 12:47:30 +00:00
|
|
|
} else
|
|
|
|
if (nat_exist(**argv)) {
|
|
|
|
/* natengine */
|
2017-08-16 13:01:52 +00:00
|
|
|
free(curspec->natengine);
|
|
|
|
curspec->natengine = strdup(**argv);
|
|
|
|
if (!curspec->natengine) {
|
2014-10-23 10:49:12 +00:00
|
|
|
fprintf(stderr,
|
|
|
|
"Out of memory"
|
|
|
|
"\n");
|
|
|
|
exit(EXIT_FAILURE);
|
|
|
|
}
|
2012-04-13 12:47:30 +00:00
|
|
|
state = 0;
|
|
|
|
} else {
|
|
|
|
/* explicit target address */
|
2017-08-16 13:01:52 +00:00
|
|
|
free(curspec->natengine);
|
|
|
|
curspec->natengine = NULL;
|
2012-04-13 12:47:30 +00:00
|
|
|
addr = **argv;
|
|
|
|
state++;
|
|
|
|
}
|
|
|
|
break;
|
2017-07-22 13:30:40 +00:00
|
|
|
case 5:
|
2012-04-13 12:47:30 +00:00
|
|
|
/* dstport */
|
2017-08-16 13:01:52 +00:00
|
|
|
af = sys_sockaddr_parse(&curspec->connect_addr,
|
|
|
|
&curspec->connect_addrlen,
|
2012-04-13 12:47:30 +00:00
|
|
|
addr, **argv, af, 0);
|
|
|
|
if (af == -1) {
|
|
|
|
exit(EXIT_FAILURE);
|
|
|
|
}
|
|
|
|
state = 0;
|
|
|
|
break;
|
2017-07-22 13:30:40 +00:00
|
|
|
case 6:
|
2012-04-13 12:47:30 +00:00
|
|
|
/* SNI dstport */
|
2017-08-16 13:01:52 +00:00
|
|
|
curspec->sni_port = atoi(**argv);
|
|
|
|
if (!curspec->sni_port) {
|
2012-04-13 12:47:30 +00:00
|
|
|
fprintf(stderr, "Invalid port '%s'\n",
|
|
|
|
**argv);
|
|
|
|
exit(EXIT_FAILURE);
|
|
|
|
}
|
2017-08-16 13:01:52 +00:00
|
|
|
curspec->dns = 1;
|
2012-04-13 12:47:30 +00:00
|
|
|
state = 0;
|
|
|
|
break;
|
|
|
|
}
|
|
|
|
(*argv)++;
|
|
|
|
}
|
2017-07-22 13:30:40 +00:00
|
|
|
if (state != 0 && state != 4) {
|
2012-04-13 12:47:30 +00:00
|
|
|
fprintf(stderr, "Incomplete proxyspec!\n");
|
|
|
|
exit(EXIT_FAILURE);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
/*
|
|
|
|
* Clear and free a proxy spec.
|
|
|
|
*/
|
|
|
|
void
|
|
|
|
proxyspec_free(proxyspec_t *spec)
|
|
|
|
{
|
2016-03-25 15:44:05 +00:00
|
|
|
do {
|
2012-04-13 12:47:30 +00:00
|
|
|
proxyspec_t *next = spec->next;
|
|
|
|
if (spec->natengine)
|
|
|
|
free(spec->natengine);
|
|
|
|
memset(spec, 0, sizeof(proxyspec_t));
|
|
|
|
free(spec);
|
|
|
|
spec = next;
|
2016-03-25 15:44:05 +00:00
|
|
|
} while (spec);
|
2012-04-13 12:47:30 +00:00
|
|
|
}
|
|
|
|
|
2015-03-15 21:55:34 +00:00
|
|
|
/*
|
|
|
|
* Return text representation of proxy spec for display to the user.
|
|
|
|
* Returned string must be freed by caller.
|
|
|
|
*/
|
|
|
|
char *
|
|
|
|
proxyspec_str(proxyspec_t *spec)
|
|
|
|
{
|
|
|
|
char *s;
|
|
|
|
char *lhbuf, *lpbuf;
|
|
|
|
char *cbuf = NULL;
|
2017-07-12 21:45:12 +00:00
|
|
|
char *pdstbuf = NULL;
|
|
|
|
char *csrcbuf = NULL;
|
2015-03-15 21:55:34 +00:00
|
|
|
if (sys_sockaddr_str((struct sockaddr *)&spec->listen_addr,
|
|
|
|
spec->listen_addrlen, &lhbuf, &lpbuf) != 0) {
|
|
|
|
return NULL;
|
|
|
|
}
|
|
|
|
if (spec->connect_addrlen) {
|
|
|
|
char *chbuf, *cpbuf;
|
|
|
|
if (sys_sockaddr_str((struct sockaddr *)&spec->connect_addr,
|
|
|
|
spec->connect_addrlen,
|
|
|
|
&chbuf, &cpbuf) != 0) {
|
|
|
|
return NULL;
|
|
|
|
}
|
2017-05-29 09:22:23 +00:00
|
|
|
if (asprintf(&cbuf, "\nconnect= [%s]:%s", chbuf, cpbuf) < 0) {
|
|
|
|
return NULL;
|
|
|
|
}
|
|
|
|
free(chbuf);
|
|
|
|
free(cpbuf);
|
|
|
|
}
|
2017-07-12 21:45:12 +00:00
|
|
|
if (spec->parent_dst_addrlen) {
|
2017-05-29 09:22:23 +00:00
|
|
|
char *chbuf, *cpbuf;
|
2017-07-12 21:45:12 +00:00
|
|
|
if (sys_sockaddr_str((struct sockaddr *)&spec->parent_dst_addr,
|
|
|
|
spec->parent_dst_addrlen,
|
2017-05-29 09:22:23 +00:00
|
|
|
&chbuf, &cpbuf) != 0) {
|
|
|
|
return NULL;
|
|
|
|
}
|
2017-07-12 21:45:12 +00:00
|
|
|
if (asprintf(&pdstbuf, "\nparent dst addr= [%s]:%s", chbuf, cpbuf) < 0) {
|
2017-05-29 09:22:23 +00:00
|
|
|
return NULL;
|
|
|
|
}
|
|
|
|
free(chbuf);
|
|
|
|
free(cpbuf);
|
|
|
|
}
|
2017-07-12 21:45:12 +00:00
|
|
|
if (spec->child_src_addrlen) {
|
2017-05-29 09:22:23 +00:00
|
|
|
char *chbuf, *cpbuf;
|
2017-07-12 21:45:12 +00:00
|
|
|
if (sys_sockaddr_str((struct sockaddr *)&spec->child_src_addr,
|
|
|
|
spec->child_src_addrlen,
|
2017-05-29 09:22:23 +00:00
|
|
|
&chbuf, &cpbuf) != 0) {
|
|
|
|
return NULL;
|
|
|
|
}
|
2017-07-12 21:45:12 +00:00
|
|
|
if (asprintf(&csrcbuf, "\nchild src addr= [%s]:%s", chbuf, cpbuf) < 0) {
|
2015-03-15 21:55:34 +00:00
|
|
|
return NULL;
|
|
|
|
}
|
|
|
|
free(chbuf);
|
|
|
|
free(cpbuf);
|
|
|
|
}
|
|
|
|
if (spec->sni_port) {
|
2017-05-29 09:22:23 +00:00
|
|
|
if (asprintf(&cbuf, "\nsni %i", spec->sni_port) < 0) {
|
2015-03-15 21:55:34 +00:00
|
|
|
return NULL;
|
|
|
|
}
|
|
|
|
}
|
2017-08-03 11:55:57 +00:00
|
|
|
if (asprintf(&s, "listen=[%s]:%s %s%s%s%s %s%s%s", lhbuf, lpbuf,
|
2015-03-15 21:55:34 +00:00
|
|
|
(spec->ssl ? "ssl" : "tcp"),
|
2015-04-21 14:00:55 +00:00
|
|
|
(spec->upgrade ? "|upgrade" : ""),
|
|
|
|
(spec->http ? "|http" : ""),
|
2017-08-03 11:55:57 +00:00
|
|
|
(spec->mail ? "|mail" : ""),
|
2017-05-29 09:22:23 +00:00
|
|
|
(spec->natengine ? spec->natengine : cbuf),
|
2017-07-12 21:45:12 +00:00
|
|
|
(pdstbuf),
|
|
|
|
(csrcbuf)) < 0) {
|
2015-03-15 21:55:34 +00:00
|
|
|
s = NULL;
|
|
|
|
}
|
|
|
|
free(lhbuf);
|
|
|
|
free(lpbuf);
|
|
|
|
if (cbuf)
|
|
|
|
free(cbuf);
|
2017-07-12 21:45:12 +00:00
|
|
|
if (pdstbuf)
|
|
|
|
free(pdstbuf);
|
|
|
|
if (csrcbuf)
|
|
|
|
free(csrcbuf);
|
2015-03-15 21:55:34 +00:00
|
|
|
return s;
|
|
|
|
}
|
|
|
|
|
2012-04-13 12:47:30 +00:00
|
|
|
/* vim: set noet ft=c: */
|