Move connection oriented options to a new conn_opts struct

pull/48/head
Soner Tari 3 years ago
parent 396db70a87
commit 14c8d417c9

@ -1397,7 +1397,7 @@ filter_rule_dbg_print(filter_rule_t *rule)
#define MAX_SITE_LEN 200 #define MAX_SITE_LEN 200
int int
filter_passsite_set(opts_t *opts, char *value, int line_num) filter_passsite_set(opts_t *opts, unsigned int user_auth, char *value, int line_num)
{ {
#define MAX_PASSSITE_TOKENS 3 #define MAX_PASSSITE_TOKENS 3
@ -1467,7 +1467,7 @@ filter_passsite_set(opts_t *opts, char *value, int line_num)
rule->action.precedence++; rule->action.precedence++;
rule->all_users = 1; rule->all_users = 1;
} else if (sys_isuser(argv[1])) { } else if (sys_isuser(argv[1])) {
if (!opts->user_auth) { if (!user_auth) {
fprintf(stderr, "User filter requires user auth on line %d\n", line_num); fprintf(stderr, "User filter requires user auth on line %d\n", line_num);
return -1; return -1;
} }
@ -1501,7 +1501,7 @@ filter_passsite_set(opts_t *opts, char *value, int line_num)
return -1; return -1;
} }
#ifndef WITHOUT_USERAUTH #ifndef WITHOUT_USERAUTH
if (!opts->user_auth) { if (!user_auth) {
fprintf(stderr, "Keyword filter requires user auth on line %d\n", line_num); fprintf(stderr, "Keyword filter requires user auth on line %d\n", line_num);
return -1; return -1;
} }
@ -1975,12 +1975,12 @@ filter_rule_translate(opts_t *opts, const char *name, int argc, char **argv, int
} }
static int WUNRES static int WUNRES
filter_rule_parse(opts_t *opts, const char *name, int argc, char **argv, int line_num); filter_rule_parse(opts_t *opts, unsigned int user_auth, const char *name, int argc, char **argv, int line_num);
#define MAX_FILTER_RULE_TOKENS 17 #define MAX_FILTER_RULE_TOKENS 17
static int WUNRES static int WUNRES
filter_rule_macro_expand(opts_t *opts, const char *name, int argc, char **argv, int i, int line_num) filter_rule_macro_expand(opts_t *opts, unsigned int user_auth, const char *name, int argc, char **argv, int i, int line_num)
{ {
if (argv[i][0] == '$') { if (argv[i][0] == '$') {
macro_t *macro; macro_t *macro;
@ -1998,7 +1998,7 @@ filter_rule_macro_expand(opts_t *opts, const char *name, int argc, char **argv,
expanded_argv[i] = value->value; expanded_argv[i] = value->value;
if (filter_rule_parse(opts, name, argc, expanded_argv, line_num) == -1) if (filter_rule_parse(opts, user_auth, name, argc, expanded_argv, line_num) == -1)
return -1; return -1;
value = value->next; value = value->next;
@ -2015,7 +2015,7 @@ filter_rule_macro_expand(opts_t *opts, const char *name, int argc, char **argv,
} }
static int WUNRES static int WUNRES
filter_rule_parse(opts_t *opts, const char *name, int argc, char **argv, int line_num) filter_rule_parse(opts_t *opts, unsigned int user_auth, const char *name, int argc, char **argv, int line_num)
{ {
int done_all = 0; int done_all = 0;
int done_from = 0; int done_from = 0;
@ -2046,7 +2046,7 @@ filter_rule_parse(opts_t *opts, const char *name, int argc, char **argv, int lin
#ifndef WITHOUT_USERAUTH #ifndef WITHOUT_USERAUTH
if (equal(argv[i], "user") || equal(argv[i], "desc")) { if (equal(argv[i], "user") || equal(argv[i], "desc")) {
if (equal(argv[i], "user")) { if (equal(argv[i], "user")) {
if (!opts->user_auth) { if (!user_auth) {
fprintf(stderr, "User filter requires user auth on line %d\n", line_num); fprintf(stderr, "User filter requires user auth on line %d\n", line_num);
return -1; return -1;
} }
@ -2057,7 +2057,7 @@ filter_rule_parse(opts_t *opts, const char *name, int argc, char **argv, int lin
if (argv[i][strlen(argv[i]) - 1] == '*') { if (argv[i][strlen(argv[i]) - 1] == '*') {
// Nothing to do for '*' or substring search for 'user*' // Nothing to do for '*' or substring search for 'user*'
} }
else if ((rv = filter_rule_macro_expand(opts, name, argc, argv, i, line_num)) != 0) { else if ((rv = filter_rule_macro_expand(opts, user_auth, name, argc, argv, i, line_num)) != 0) {
return rv; return rv;
} }
else if (!sys_isuser(argv[i])) { else if (!sys_isuser(argv[i])) {
@ -2069,7 +2069,7 @@ filter_rule_parse(opts_t *opts, const char *name, int argc, char **argv, int lin
// It is possible to define desc without user (i.e. * or all_users), hence no 'else' here // It is possible to define desc without user (i.e. * or all_users), hence no 'else' here
if (i < argc && equal(argv[i], "desc")) { if (i < argc && equal(argv[i], "desc")) {
if (!opts->user_auth) { if (!user_auth) {
fprintf(stderr, "Desc filter requires user auth on line %d\n", line_num); fprintf(stderr, "Desc filter requires user auth on line %d\n", line_num);
return -1; return -1;
} }
@ -2080,7 +2080,7 @@ filter_rule_parse(opts_t *opts, const char *name, int argc, char **argv, int lin
if (argv[i][strlen(argv[i]) - 1] == '*') { if (argv[i][strlen(argv[i]) - 1] == '*') {
// Nothing to do for '*' or substring search for 'desc*' // Nothing to do for '*' or substring search for 'desc*'
} }
else if ((rv = filter_rule_macro_expand(opts, name, argc, argv, i, line_num)) != 0) { else if ((rv = filter_rule_macro_expand(opts, user_auth, name, argc, argv, i, line_num)) != 0) {
return rv; return rv;
} }
i++; i++;
@ -2097,7 +2097,7 @@ filter_rule_parse(opts_t *opts, const char *name, int argc, char **argv, int lin
if (argv[i][strlen(argv[i]) - 1] == '*') { if (argv[i][strlen(argv[i]) - 1] == '*') {
// Nothing to do for '*' or substring search for 'ip*' // Nothing to do for '*' or substring search for 'ip*'
} }
else if ((rv = filter_rule_macro_expand(opts, name, argc, argv, i, line_num)) != 0) { else if ((rv = filter_rule_macro_expand(opts, user_auth, name, argc, argv, i, line_num)) != 0) {
return rv; return rv;
} }
i++; i++;
@ -2126,7 +2126,7 @@ filter_rule_parse(opts_t *opts, const char *name, int argc, char **argv, int lin
if ((i = filter_arg_index_inc(i, argc, argv[i], line_num)) == -1) if ((i = filter_arg_index_inc(i, argc, argv[i], line_num)) == -1)
return -1; return -1;
if ((rv = filter_rule_macro_expand(opts, name, argc, argv, i, line_num)) != 0) { if ((rv = filter_rule_macro_expand(opts, user_auth, name, argc, argv, i, line_num)) != 0) {
return rv; return rv;
} }
i++; i++;
@ -2137,7 +2137,7 @@ filter_rule_parse(opts_t *opts, const char *name, int argc, char **argv, int lin
if ((i = filter_arg_index_inc(i, argc, argv[i], line_num)) == -1) if ((i = filter_arg_index_inc(i, argc, argv[i], line_num)) == -1)
return -1; return -1;
if ((rv = filter_rule_macro_expand(opts, name, argc, argv, i, line_num)) != 0) { if ((rv = filter_rule_macro_expand(opts, user_auth, name, argc, argv, i, line_num)) != 0) {
return rv; return rv;
} }
i++; i++;
@ -2168,7 +2168,7 @@ filter_rule_parse(opts_t *opts, const char *name, int argc, char **argv, int lin
#endif /* !WITHOUT_MIRROR */ #endif /* !WITHOUT_MIRROR */
|| argv[i][0] == '$') { || argv[i][0] == '$') {
do { do {
if ((rv = filter_rule_macro_expand(opts, name, argc, argv, i, line_num)) != 0) { if ((rv = filter_rule_macro_expand(opts, user_auth, name, argc, argv, i, line_num)) != 0) {
return rv; return rv;
} }
if (++i == argc) if (++i == argc)
@ -2206,7 +2206,7 @@ filter_rule_parse(opts_t *opts, const char *name, int argc, char **argv, int lin
} }
int int
filter_rule_set(opts_t *opts, const char *name, char *value, int line_num) filter_rule_set(opts_t *opts, unsigned int user_auth, const char *name, char *value, int line_num)
{ {
char *argv[sizeof(char *) * MAX_FILTER_RULE_TOKENS]; char *argv[sizeof(char *) * MAX_FILTER_RULE_TOKENS];
int argc = 0; int argc = 0;
@ -2223,7 +2223,7 @@ filter_rule_set(opts_t *opts, const char *name, char *value, int line_num)
} }
} }
return filter_rule_parse(opts, name, argc, argv, line_num); return filter_rule_parse(opts, user_auth, name, argc, argv, line_num);
} }
static filter_port_t * static filter_port_t *

@ -277,7 +277,7 @@ char *filter_macro_str(macro_t *);
char *filter_rule_str(filter_rule_t *); char *filter_rule_str(filter_rule_t *);
char *filter_str(filter_t *); char *filter_str(filter_t *);
int filter_passsite_set(opts_t *, char *, int) NONNULL(1,2) WUNRES; int filter_passsite_set(opts_t *, unsigned int, char *, int) NONNULL(1,3) WUNRES;
int filter_macro_set(opts_t *, char *, int) NONNULL(1,2) WUNRES; int filter_macro_set(opts_t *, char *, int) NONNULL(1,2) WUNRES;
filter_port_t *filter_port_find(filter_site_t *, char *) NONNULL(1,2); filter_port_t *filter_port_find(filter_site_t *, char *) NONNULL(1,2);
@ -296,7 +296,7 @@ filter_desc_t *filter_desc_substring_match(ACMachine(char) *, char *) NONNULL(2)
filter_user_t *filter_user_exact_match(kbtree_t(user) *, char *) NONNULL(2) WUNRES; filter_user_t *filter_user_exact_match(kbtree_t(user) *, char *) NONNULL(2) WUNRES;
filter_user_t *filter_user_substring_match(ACMachine(char) *, char *) NONNULL(2) WUNRES; filter_user_t *filter_user_substring_match(ACMachine(char) *, char *) NONNULL(2) WUNRES;
#endif /* !WITHOUT_USERAUTH */ #endif /* !WITHOUT_USERAUTH */
int filter_rule_set(opts_t *, const char *, char *, int) NONNULL(1,2,3) WUNRES; int filter_rule_set(opts_t *, unsigned int, const char *, char *, int) NONNULL(1,3,4) WUNRES;
filter_t *filter_set(filter_rule_t *) WUNRES; filter_t *filter_set(filter_rule_t *) WUNRES;
#endif /* !FILTER_H */ #endif /* !FILTER_H */

@ -328,26 +328,26 @@ main_load_leafcert(const char *filename, void *arg)
} }
static void static void
main_check_opts(opts_t *opts, const char *argv0) main_check_opts(opts_t *opts, conn_opts_t *conn_opts, const char *argv0)
{ {
if (opts->cacrt && !opts->cakey) { if (conn_opts->cacrt && !conn_opts->cakey) {
fprintf(stderr, "%s: no CA key specified (-k).\n", fprintf(stderr, "%s: no CA key specified (-k).\n",
argv0); argv0);
exit(EXIT_FAILURE); exit(EXIT_FAILURE);
} }
if (opts->cakey && !opts->cacrt) { if (conn_opts->cakey && !conn_opts->cacrt) {
fprintf(stderr, "%s: no CA cert specified (-c).\n", fprintf(stderr, "%s: no CA cert specified (-c).\n",
argv0); argv0);
exit(EXIT_FAILURE); exit(EXIT_FAILURE);
} }
if (opts->cakey && opts->cacrt && if (conn_opts->cakey && conn_opts->cacrt &&
(X509_check_private_key(opts->cacrt, opts->cakey) != 1)) { (X509_check_private_key(conn_opts->cacrt, conn_opts->cakey) != 1)) {
fprintf(stderr, "%s: CA cert does not match key.\n", fprintf(stderr, "%s: CA cert does not match key.\n",
argv0); argv0);
ERR_print_errors_fp(stderr); ERR_print_errors_fp(stderr);
exit(EXIT_FAILURE); exit(EXIT_FAILURE);
} }
if (!opts->cakey && if (!conn_opts->cakey &&
!opts->global->leafcertdir && !opts->global->leafcertdir &&
!opts->global->defaultleafcert) { !opts->global->defaultleafcert) {
fprintf(stderr, "%s: at least one of -c/-k, -t or -A " fprintf(stderr, "%s: at least one of -c/-k, -t or -A "
@ -410,15 +410,15 @@ main(int argc, char *argv[])
exit(EXIT_FAILURE); exit(EXIT_FAILURE);
break; break;
case 'c': case 'c':
if (opts_set_cacrt(global->opts, argv0, optarg, global_tmp_opts) == -1) if (opts_set_cacrt(global->conn_opts, argv0, optarg, global_tmp_opts) == -1)
exit(EXIT_FAILURE); exit(EXIT_FAILURE);
break; break;
case 'k': case 'k':
if (opts_set_cakey(global->opts, argv0, optarg, global_tmp_opts) == -1) if (opts_set_cakey(global->conn_opts, argv0, optarg, global_tmp_opts) == -1)
exit(EXIT_FAILURE); exit(EXIT_FAILURE);
break; break;
case 'C': case 'C':
if (opts_set_chain(global->opts, argv0, optarg, global_tmp_opts) == -1) if (opts_set_chain(global->conn_opts, argv0, optarg, global_tmp_opts) == -1)
exit(EXIT_FAILURE); exit(EXIT_FAILURE);
break; break;
case 'K': case 'K':
@ -434,54 +434,54 @@ main(int argc, char *argv[])
exit(EXIT_FAILURE); exit(EXIT_FAILURE);
break; break;
case 'q': case 'q':
if (opts_set_leafcrlurl(global->opts, argv0, optarg, global_tmp_opts) == -1) if (opts_set_leafcrlurl(global->conn_opts, argv0, optarg, global_tmp_opts) == -1)
exit(EXIT_FAILURE); exit(EXIT_FAILURE);
break; break;
case 'O': case 'O':
opts_set_deny_ocsp(global->opts); opts_set_deny_ocsp(global->conn_opts);
break; break;
case 'P': case 'P':
opts_set_passthrough(global->opts); opts_set_passthrough(global->conn_opts);
break; break;
case 'a': case 'a':
if (opts_set_clientcrt(global->opts, argv0, optarg, global_tmp_opts) == -1) if (opts_set_clientcrt(global->conn_opts, argv0, optarg, global_tmp_opts) == -1)
exit(EXIT_FAILURE); exit(EXIT_FAILURE);
break; break;
case 'b': case 'b':
if (opts_set_clientkey(global->opts, argv0, optarg, global_tmp_opts) == -1) if (opts_set_clientkey(global->conn_opts, argv0, optarg, global_tmp_opts) == -1)
exit(EXIT_FAILURE); exit(EXIT_FAILURE);
break; break;
#ifndef OPENSSL_NO_DH #ifndef OPENSSL_NO_DH
case 'g': case 'g':
if (opts_set_dh(global->opts, argv0, optarg, global_tmp_opts) == -1) if (opts_set_dh(global->conn_opts, argv0, optarg, global_tmp_opts) == -1)
exit(EXIT_FAILURE); exit(EXIT_FAILURE);
break; break;
#endif /* !OPENSSL_NO_DH */ #endif /* !OPENSSL_NO_DH */
#ifndef OPENSSL_NO_ECDH #ifndef OPENSSL_NO_ECDH
case 'G': case 'G':
if (opts_set_ecdhcurve(global->opts, argv0, optarg) == -1) if (opts_set_ecdhcurve(global->conn_opts, argv0, optarg) == -1)
exit(EXIT_FAILURE); exit(EXIT_FAILURE);
break; break;
#endif /* !OPENSSL_NO_ECDH */ #endif /* !OPENSSL_NO_ECDH */
#ifdef SSL_OP_NO_COMPRESSION #ifdef SSL_OP_NO_COMPRESSION
case 'Z': case 'Z':
opts_unset_sslcomp(global->opts); opts_unset_sslcomp(global->conn_opts);
break; break;
#endif /* SSL_OP_NO_COMPRESSION */ #endif /* SSL_OP_NO_COMPRESSION */
case 's': case 's':
if (opts_set_ciphers(global->opts, argv0, optarg) == -1) if (opts_set_ciphers(global->conn_opts, argv0, optarg) == -1)
exit(EXIT_FAILURE); exit(EXIT_FAILURE);
break; break;
case 'U': case 'U':
if (opts_set_ciphersuites(global->opts, argv0, optarg) == -1) if (opts_set_ciphersuites(global->conn_opts, argv0, optarg) == -1)
exit(EXIT_FAILURE); exit(EXIT_FAILURE);
break; break;
case 'r': case 'r':
if (opts_force_proto(global->opts, argv0, optarg) == -1) if (opts_force_proto(global->conn_opts, argv0, optarg) == -1)
exit(EXIT_FAILURE); exit(EXIT_FAILURE);
break; break;
case 'R': case 'R':
if (opts_disable_proto(global->opts, argv0, optarg) == -1) if (opts_disable_proto(global->conn_opts, argv0, optarg) == -1)
exit(EXIT_FAILURE); exit(EXIT_FAILURE);
break; break;
#ifndef OPENSSL_NO_ENGINE #ifndef OPENSSL_NO_ENGINE
@ -671,10 +671,10 @@ main(int argc, char *argv[])
exit(EXIT_FAILURE); exit(EXIT_FAILURE);
} }
#endif /* !OPENSSL_NO_ENGINE */ #endif /* !OPENSSL_NO_ENGINE */
main_check_opts(global->opts, argv0); main_check_opts(global->opts, global->conn_opts, argv0);
for (proxyspec_t *spec = global->spec; spec; spec = spec->next) { for (proxyspec_t *spec = global->spec; spec; spec = spec->next) {
if (spec->ssl || spec->upgrade) if (spec->ssl || spec->upgrade)
main_check_opts(spec->opts, argv0); main_check_opts(spec->opts, spec->conn_opts, argv0);
} }
} }
#ifdef __APPLE__ #ifdef __APPLE__
@ -698,7 +698,7 @@ main(int argc, char *argv[])
} }
#ifndef WITHOUT_USERAUTH #ifndef WITHOUT_USERAUTH
if (global->opts->user_auth || global_has_userauth_spec(global)) { if (global->conn_opts->user_auth || global_has_userauth_spec(global)) {
if (!global->userdb_path) { if (!global->userdb_path) {
fprintf(stderr, "User auth requires a userdb path\n"); fprintf(stderr, "User auth requires a userdb path\n");
exit(EXIT_FAILURE); exit(EXIT_FAILURE);
@ -720,25 +720,25 @@ main(int argc, char *argv[])
#endif /* !WITHOUT_USERAUTH */ #endif /* !WITHOUT_USERAUTH */
/* dynamic defaults */ /* dynamic defaults */
if (!global->opts->ciphers) { if (!global->conn_opts->ciphers) {
global->opts->ciphers = strdup(DFLT_CIPHERS); global->conn_opts->ciphers = strdup(DFLT_CIPHERS);
if (!global->opts->ciphers) if (!global->conn_opts->ciphers)
oom_die(argv0); oom_die(argv0);
} }
if (!global->opts->ciphersuites) { if (!global->conn_opts->ciphersuites) {
global->opts->ciphersuites = strdup(DFLT_CIPHERSUITES); global->conn_opts->ciphersuites = strdup(DFLT_CIPHERSUITES);
if (!global->opts->ciphersuites) if (!global->conn_opts->ciphersuites)
oom_die(argv0); oom_die(argv0);
} }
for (proxyspec_t *spec = global->spec; spec; spec = spec->next) { for (proxyspec_t *spec = global->spec; spec; spec = spec->next) {
if (!spec->opts->ciphers) { if (!spec->conn_opts->ciphers) {
spec->opts->ciphers = strdup(DFLT_CIPHERS); spec->conn_opts->ciphers = strdup(DFLT_CIPHERS);
if (!spec->opts->ciphers) if (!spec->conn_opts->ciphers)
oom_die(argv0); oom_die(argv0);
} }
if (!spec->opts->ciphersuites) { if (!spec->conn_opts->ciphersuites) {
spec->opts->ciphersuites = strdup(DFLT_CIPHERSUITES); spec->conn_opts->ciphersuites = strdup(DFLT_CIPHERSUITES);
if (!spec->opts->ciphersuites) if (!spec->conn_opts->ciphersuites)
oom_die(argv0); oom_die(argv0);
} }
} }
@ -867,7 +867,7 @@ main(int argc, char *argv[])
/* debug log, part 2 */ /* debug log, part 2 */
if (OPTS_DEBUG(global)) { if (OPTS_DEBUG(global)) {
char *s = opts_proto_dbg_dump(global->opts); char *s = opts_proto_dbg_dump(global->conn_opts);
if (!s) if (!s)
oom_die(argv0); oom_die(argv0);
@ -889,20 +889,20 @@ main(int argc, char *argv[])
global->openssl_engine); global->openssl_engine);
} }
#endif /* !OPENSSL_NO_ENGINE */ #endif /* !OPENSSL_NO_ENGINE */
if (global->opts->cacrt) { if (global->conn_opts->cacrt) {
char *subj = ssl_x509_subject(global->opts->cacrt); char *subj = ssl_x509_subject(global->conn_opts->cacrt);
log_dbg_printf("Loaded CA: '%s'\n", subj); log_dbg_printf("Loaded CA: '%s'\n", subj);
free(subj); free(subj);
#ifdef DEBUG_CERTIFICATE #ifdef DEBUG_CERTIFICATE
log_dbg_print_free(ssl_x509_to_str(global->opts->cacrt)); log_dbg_print_free(ssl_x509_to_str(global->conn_opts->cacrt));
log_dbg_print_free(ssl_x509_to_pem(global->opts->cacrt)); log_dbg_print_free(ssl_x509_to_pem(global->conn_opts->cacrt));
#endif /* DEBUG_CERTIFICATE */ #endif /* DEBUG_CERTIFICATE */
} else { } else {
log_dbg_printf("No CA loaded.\n"); log_dbg_printf("No CA loaded.\n");
} }
for (proxyspec_t *spec = global->spec; spec; spec = spec->next) { for (proxyspec_t *spec = global->spec; spec; spec = spec->next) {
if (spec->opts->cacrt) { if (spec->conn_opts->cacrt) {
char *subj = ssl_x509_subject(spec->opts->cacrt); char *subj = ssl_x509_subject(spec->conn_opts->cacrt);
log_dbg_printf("Loaded ProxySpec CA: '%s'\n", subj); log_dbg_printf("Loaded ProxySpec CA: '%s'\n", subj);
free(subj); free(subj);
#ifdef DEBUG_CERTIFICATE #ifdef DEBUG_CERTIFICATE
@ -921,9 +921,9 @@ main(int argc, char *argv[])
if (global->defaultleafcert) { if (global->defaultleafcert) {
log_dbg_printf("- Default leaf key\n"); log_dbg_printf("- Default leaf key\n");
// @todo Debug print the cakey and passthrough opts for proxspecs too? // @todo Debug print the cakey and passthrough opts for proxspecs too?
} else if (global->opts->cakey) { } else if (global->conn_opts->cakey) {
log_dbg_printf("- Global generated on the fly\n"); log_dbg_printf("- Global generated on the fly\n");
} else if (global->opts->passthrough) { } else if (global->conn_opts->passthrough) {
log_dbg_printf("- Global passthrough without decryption\n"); log_dbg_printf("- Global passthrough without decryption\n");
} else { } else {
log_dbg_printf("- Global connection drop\n"); log_dbg_printf("- Global connection drop\n");

File diff suppressed because it is too large Load Diff

@ -81,11 +81,7 @@ typedef struct userlist {
typedef struct global global_t; typedef struct global global_t;
typedef struct opts { typedef struct conn_opts {
// Set to 1 to divert to lp, set to 0 for split mode
// Defaults to 1
unsigned int divert : 1;
unsigned int sslcomp : 1; unsigned int sslcomp : 1;
#ifdef HAVE_SSLV2 #ifdef HAVE_SSLV2
unsigned int no_ssl2 : 1; unsigned int no_ssl2 : 1;
@ -135,11 +131,21 @@ typedef struct opts {
unsigned int user_auth: 1; unsigned int user_auth: 1;
char *user_auth_url; char *user_auth_url;
unsigned int user_timeout; unsigned int user_timeout;
userlist_t *divertusers;
userlist_t *passusers;
#endif /* !WITHOUT_USERAUTH */ #endif /* !WITHOUT_USERAUTH */
unsigned int validate_proto : 1; unsigned int validate_proto : 1;
unsigned int max_http_header_size; unsigned int max_http_header_size;
} conn_opts_t;
typedef struct opts {
// Set to 1 to divert to lp, set to 0 for split mode
// Defaults to 1
unsigned int divert : 1;
#ifndef WITHOUT_USERAUTH
userlist_t *divertusers;
userlist_t *passusers;
#endif /* !WITHOUT_USERAUTH */
// Used to store filter rules and to create filter // Used to store filter rules and to create filter
// Freed during startup after filter is created and debug printed // Freed during startup after filter is created and debug printed
struct filter_rule *filter_rules; struct filter_rule *filter_rules;
@ -176,6 +182,7 @@ typedef struct proxyspec {
// Each proxyspec has its own opts // Each proxyspec has its own opts
opts_t *opts; opts_t *opts;
conn_opts_t *conn_opts;
} proxyspec_t; } proxyspec_t;
// Temporary global options // Temporary global options
@ -237,6 +244,8 @@ struct global {
sqlite3 *userdb; sqlite3 *userdb;
struct sqlite3_stmt *update_user_atime; struct sqlite3_stmt *update_user_atime;
#endif /* !WITHOUT_USERAUTH */ #endif /* !WITHOUT_USERAUTH */
conn_opts_t *conn_opts;
proxyspec_t *spec; proxyspec_t *spec;
opts_t *opts; opts_t *opts;
@ -279,26 +288,26 @@ char *proxyspec_str(proxyspec_t *) NONNULL(1) MALLOC WUNRES;
opts_t *opts_new(void) MALLOC WUNRES; opts_t *opts_new(void) MALLOC WUNRES;
void opts_free(opts_t *) NONNULL(1); void opts_free(opts_t *) NONNULL(1);
char *opts_proto_dbg_dump(opts_t *) NONNULL(1); char *opts_proto_dbg_dump(conn_opts_t *) NONNULL(1);
int opts_set_cacrt(opts_t *, const char *, const char *, global_tmp_opts_t *) NONNULL(1,2,3) WUNRES; int opts_set_cacrt(conn_opts_t *, const char *, const char *, global_tmp_opts_t *) NONNULL(1,2,3) WUNRES;
int opts_set_cakey(opts_t *, const char *, const char *, global_tmp_opts_t *) NONNULL(1,2,3) WUNRES; int opts_set_cakey(conn_opts_t *, const char *, const char *, global_tmp_opts_t *) NONNULL(1,2,3) WUNRES;
int opts_set_chain(opts_t *, const char *, const char *, global_tmp_opts_t *) NONNULL(1,2,3) WUNRES; int opts_set_chain(conn_opts_t *, const char *, const char *, global_tmp_opts_t *) NONNULL(1,2,3) WUNRES;
int opts_set_leafcrlurl(opts_t *, const char *, const char *, global_tmp_opts_t *) NONNULL(1,2,3) WUNRES; int opts_set_leafcrlurl(conn_opts_t *, const char *, const char *, global_tmp_opts_t *) NONNULL(1,2,3) WUNRES;
void opts_set_deny_ocsp(opts_t *) NONNULL(1); void opts_set_deny_ocsp(conn_opts_t *) NONNULL(1);
void opts_set_passthrough(opts_t *) NONNULL(1); void opts_set_passthrough(conn_opts_t *) NONNULL(1);
int opts_set_clientcrt(opts_t *, const char *, const char *, global_tmp_opts_t *) NONNULL(1,2,3) WUNRES; int opts_set_clientcrt(conn_opts_t *, const char *, const char *, global_tmp_opts_t *) NONNULL(1,2,3) WUNRES;
int opts_set_clientkey(opts_t *, const char *, const char *, global_tmp_opts_t *) NONNULL(1,2,3) WUNRES; int opts_set_clientkey(conn_opts_t *, const char *, const char *, global_tmp_opts_t *) NONNULL(1,2,3) WUNRES;
#ifndef OPENSSL_NO_DH #ifndef OPENSSL_NO_DH
int opts_set_dh(opts_t *, const char *, const char *, global_tmp_opts_t *) NONNULL(1,2,3) WUNRES; int opts_set_dh(conn_opts_t *, const char *, const char *, global_tmp_opts_t *) NONNULL(1,2,3) WUNRES;
#endif /* !OPENSSL_NO_DH */ #endif /* !OPENSSL_NO_DH */
#ifndef OPENSSL_NO_ECDH #ifndef OPENSSL_NO_ECDH
int opts_set_ecdhcurve(opts_t *, const char *, const char *) NONNULL(1,2,3) WUNRES; int opts_set_ecdhcurve(conn_opts_t *, const char *, const char *) NONNULL(1,2,3) WUNRES;
#endif /* !OPENSSL_NO_ECDH */ #endif /* !OPENSSL_NO_ECDH */
void opts_unset_sslcomp(opts_t *) NONNULL(1); void opts_unset_sslcomp(conn_opts_t *) NONNULL(1);
int opts_force_proto(opts_t *, const char *, const char *) NONNULL(1,2,3) WUNRES; int opts_force_proto(conn_opts_t *, const char *, const char *) NONNULL(1,2,3) WUNRES;
int opts_disable_proto(opts_t *, const char *, const char *) NONNULL(1,2,3) WUNRES; int opts_disable_proto(conn_opts_t *, const char *, const char *) NONNULL(1,2,3) WUNRES;
int opts_set_ciphers(opts_t *, const char *, const char *) NONNULL(1,2,3) WUNRES; int opts_set_ciphers(conn_opts_t *, const char *, const char *) NONNULL(1,2,3) WUNRES;
int opts_set_ciphersuites(opts_t *, const char *, const char *) NONNULL(1,2,3) WUNRES; int opts_set_ciphersuites(conn_opts_t *, const char *, const char *) NONNULL(1,2,3) WUNRES;
#define OPTS_DEBUG(global) unlikely((global)->debug) #define OPTS_DEBUG(global) unlikely((global)->debug)

@ -349,10 +349,10 @@ protohttp_filter_request_header_line(const char *line, protohttp_ctx_t *http_ctx
http_ctx->seen_keyword_count++; http_ctx->seen_keyword_count++;
return newhdr; return newhdr;
// @attention Always use conn ctx for opts, child ctx does not have opts, see the comments in pxy_conn_child_ctx // @attention Always use conn ctx for opts, child ctx does not have opts, see the comments in pxy_conn_child_ctx
} else if (ctx->spec->opts->remove_http_accept_encoding && !strncasecmp(line, "Accept-Encoding:", 16)) { } else if (ctx->conn_opts->remove_http_accept_encoding && !strncasecmp(line, "Accept-Encoding:", 16)) {
http_ctx->seen_keyword_count++; http_ctx->seen_keyword_count++;
return NULL; return NULL;
} else if (ctx->spec->opts->remove_http_referer && !strncasecmp(line, "Referer:", 8)) { } else if (ctx->conn_opts->remove_http_referer && !strncasecmp(line, "Referer:", 8)) {
http_ctx->seen_keyword_count++; http_ctx->seen_keyword_count++;
return NULL; return NULL;
/* Suppress upgrading to SSL/TLS, WebSockets or HTTP/2 and keep-alive */ /* Suppress upgrading to SSL/TLS, WebSockets or HTTP/2 and keep-alive */
@ -630,7 +630,7 @@ protohttp_filter_request_header(struct evbuffer *inbuf, struct evbuffer *outbuf,
} }
/* request header complete */ /* request header complete */
if (ctx->spec->opts->deny_ocsp) { if (ctx->conn_opts->deny_ocsp) {
protohttp_ocsp_deny(ctx, http_ctx); protohttp_ocsp_deny(ctx, http_ctx);
} }
} }
@ -764,7 +764,7 @@ protohttp_validate(pxy_conn_ctx_t *ctx)
log_finest("Passed validation"); log_finest("Passed validation");
return 0; return 0;
} }
if (http_ctx->seen_bytes > ctx->spec->opts->max_http_header_size) { if (http_ctx->seen_bytes > ctx->conn_opts->max_http_header_size) {
// Fail validation if still cannot pass as http after reaching max header size // Fail validation if still cannot pass as http after reaching max header size
http_ctx->not_valid = 1; http_ctx->not_valid = 1;
log_finest_va("Reached max header size, size=%llu", http_ctx->seen_bytes); log_finest_va("Reached max header size, size=%llu", http_ctx->seen_bytes);
@ -805,22 +805,22 @@ protohttp_bev_readcb_src(struct bufferevent *bev, pxy_conn_ctx_t *ctx)
struct evbuffer *outbuf = bufferevent_get_output(ctx->dst.bev); struct evbuffer *outbuf = bufferevent_get_output(ctx->dst.bev);
#ifndef WITHOUT_USERAUTH #ifndef WITHOUT_USERAUTH
if (ctx->spec->opts->user_auth && !ctx->user) { if (ctx->conn_opts->user_auth && !ctx->user) {
log_finest("Redirecting conn"); log_finest("Redirecting conn");
char *url = protohttp_get_url(inbuf, ctx); char *url = protohttp_get_url(inbuf, ctx);
pxy_discard_inbuf(bev); pxy_discard_inbuf(bev);
if (url) { if (url) {
evbuffer_add_printf(bufferevent_get_output(bev), redirect_url, ctx->spec->opts->user_auth_url, url); evbuffer_add_printf(bufferevent_get_output(bev), redirect_url, ctx->conn_opts->user_auth_url, url);
free(url); free(url);
} else { } else {
evbuffer_add_printf(bufferevent_get_output(bev), redirect, ctx->spec->opts->user_auth_url); evbuffer_add_printf(bufferevent_get_output(bev), redirect, ctx->conn_opts->user_auth_url);
} }
ctx->sent_userauth_msg = 1; ctx->sent_userauth_msg = 1;
return; return;
} }
#endif /* !WITHOUT_USERAUTH */ #endif /* !WITHOUT_USERAUTH */
if (ctx->spec->opts->validate_proto && !ctx->protoctx->is_valid) { if (ctx->conn_opts->validate_proto && !ctx->protoctx->is_valid) {
http_ctx->seen_bytes += evbuffer_get_length(inbuf); http_ctx->seen_bytes += evbuffer_get_length(inbuf);
} }
@ -843,7 +843,7 @@ protohttp_bev_readcb_src(struct bufferevent *bev, pxy_conn_ctx_t *ctx)
evbuffer_add_buffer(outbuf, inbuf); evbuffer_add_buffer(outbuf, inbuf);
} }
if (ctx->spec->opts->validate_proto && !ctx->protoctx->is_valid) { if (ctx->conn_opts->validate_proto && !ctx->protoctx->is_valid) {
if (protohttp_validate(ctx) == -1) { if (protohttp_validate(ctx) == -1) {
evbuffer_add(bufferevent_get_output(bev), proto_error, strlen(proto_error)); evbuffer_add(bufferevent_get_output(bev), proto_error, strlen(proto_error));
ctx->sent_protoerror_msg = 1; ctx->sent_protoerror_msg = 1;

@ -118,7 +118,7 @@ protosmtp_validate_response(pxy_conn_ctx_t *ctx, char *packet, size_t packet_siz
static int NONNULL(1,2,3,4) static int NONNULL(1,2,3,4)
protosmtp_try_validate_response(struct bufferevent *bev, pxy_conn_ctx_t *ctx, struct evbuffer *inbuf, struct evbuffer *outbuf) protosmtp_try_validate_response(struct bufferevent *bev, pxy_conn_ctx_t *ctx, struct evbuffer *inbuf, struct evbuffer *outbuf)
{ {
if (ctx->spec->opts->validate_proto) { if (ctx->conn_opts->validate_proto) {
size_t packet_size = evbuffer_get_length(inbuf); size_t packet_size = evbuffer_get_length(inbuf);
char *packet = (char *)pxy_malloc_packet(packet_size, ctx); char *packet = (char *)pxy_malloc_packet(packet_size, ctx);
if (!packet) { if (!packet) {

@ -287,7 +287,7 @@ protossl_sslctx_setoptions(SSL_CTX *sslctx, pxy_conn_ctx_t *ctx)
#ifdef SSL_OP_NO_SSLv2 #ifdef SSL_OP_NO_SSLv2
#ifdef HAVE_SSLV2 #ifdef HAVE_SSLV2
if (ctx->spec->opts->no_ssl2) { if (ctx->conn_opts->no_ssl2) {
#endif /* HAVE_SSLV2 */ #endif /* HAVE_SSLV2 */
SSL_CTX_set_options(sslctx, SSL_OP_NO_SSLv2); SSL_CTX_set_options(sslctx, SSL_OP_NO_SSLv2);
#ifdef HAVE_SSLV2 #ifdef HAVE_SSLV2
@ -295,40 +295,40 @@ protossl_sslctx_setoptions(SSL_CTX *sslctx, pxy_conn_ctx_t *ctx)
#endif /* HAVE_SSLV2 */ #endif /* HAVE_SSLV2 */
#endif /* !SSL_OP_NO_SSLv2 */ #endif /* !SSL_OP_NO_SSLv2 */
#ifdef HAVE_SSLV3 #ifdef HAVE_SSLV3
if (ctx->spec->opts->no_ssl3) { if (ctx->conn_opts->no_ssl3) {
SSL_CTX_set_options(sslctx, SSL_OP_NO_SSLv3); SSL_CTX_set_options(sslctx, SSL_OP_NO_SSLv3);
} }
#endif /* HAVE_SSLV3 */ #endif /* HAVE_SSLV3 */
#ifdef HAVE_TLSV10 #ifdef HAVE_TLSV10
if (ctx->spec->opts->no_tls10) { if (ctx->conn_opts->no_tls10) {
SSL_CTX_set_options(sslctx, SSL_OP_NO_TLSv1); SSL_CTX_set_options(sslctx, SSL_OP_NO_TLSv1);
} }
#endif /* HAVE_TLSV10 */ #endif /* HAVE_TLSV10 */
#ifdef HAVE_TLSV11 #ifdef HAVE_TLSV11
if (ctx->spec->opts->no_tls11) { if (ctx->conn_opts->no_tls11) {
SSL_CTX_set_options(sslctx, SSL_OP_NO_TLSv1_1); SSL_CTX_set_options(sslctx, SSL_OP_NO_TLSv1_1);
} }
#endif /* HAVE_TLSV11 */ #endif /* HAVE_TLSV11 */
#ifdef HAVE_TLSV12 #ifdef HAVE_TLSV12
if (ctx->spec->opts->no_tls12) { if (ctx->conn_opts->no_tls12) {
SSL_CTX_set_options(sslctx, SSL_OP_NO_TLSv1_2); SSL_CTX_set_options(sslctx, SSL_OP_NO_TLSv1_2);
} }
#endif /* HAVE_TLSV12 */ #endif /* HAVE_TLSV12 */
#ifdef HAVE_TLSV13 #ifdef HAVE_TLSV13
if (ctx->spec->opts->no_tls13) { if (ctx->conn_opts->no_tls13) {
SSL_CTX_set_options(sslctx, SSL_OP_NO_TLSv1_3); SSL_CTX_set_options(sslctx, SSL_OP_NO_TLSv1_3);
} }
#endif /* HAVE_TLSV13 */ #endif /* HAVE_TLSV13 */
#ifdef SSL_OP_NO_COMPRESSION #ifdef SSL_OP_NO_COMPRESSION
if (!ctx->spec->opts->sslcomp) { if (!ctx->conn_opts->sslcomp) {
SSL_CTX_set_options(sslctx, SSL_OP_NO_COMPRESSION); SSL_CTX_set_options(sslctx, SSL_OP_NO_COMPRESSION);
} }
#endif /* SSL_OP_NO_COMPRESSION */ #endif /* SSL_OP_NO_COMPRESSION */
SSL_CTX_set_cipher_list(sslctx, ctx->spec->opts->ciphers); SSL_CTX_set_cipher_list(sslctx, ctx->conn_opts->ciphers);
#ifdef HAVE_TLSV13 #ifdef HAVE_TLSV13
SSL_CTX_set_ciphersuites(sslctx, ctx->spec->opts->ciphersuites); SSL_CTX_set_ciphersuites(sslctx, ctx->conn_opts->ciphersuites);
#endif /* HAVE_TLSV13 */ #endif /* HAVE_TLSV13 */
#if (OPENSSL_VERSION_NUMBER >= 0x10100000L) && !defined(LIBRESSL_VERSION_NUMBER) #if (OPENSSL_VERSION_NUMBER >= 0x10100000L) && !defined(LIBRESSL_VERSION_NUMBER)
@ -346,7 +346,7 @@ static SSL_CTX *
protossl_srcsslctx_create(pxy_conn_ctx_t *ctx, X509 *crt, STACK_OF(X509) *chain, protossl_srcsslctx_create(pxy_conn_ctx_t *ctx, X509 *crt, STACK_OF(X509) *chain,
EVP_PKEY *key) EVP_PKEY *key)
{ {
SSL_CTX *sslctx = SSL_CTX_new(ctx->spec->opts->sslmethod()); SSL_CTX *sslctx = SSL_CTX_new(ctx->conn_opts->sslmethod());
if (!sslctx) { if (!sslctx) {
ctx->enomem = 1; ctx->enomem = 1;
return NULL; return NULL;
@ -355,22 +355,22 @@ protossl_srcsslctx_create(pxy_conn_ctx_t *ctx, X509 *crt, STACK_OF(X509) *chain,
protossl_sslctx_setoptions(sslctx, ctx); protossl_sslctx_setoptions(sslctx, ctx);
#if (OPENSSL_VERSION_NUMBER >= 0x10100000L && !defined(LIBRESSL_VERSION_NUMBER)) || (defined(LIBRESSL_VERSION_NUMBER) && LIBRESSL_VERSION_NUMBER >= 0x20702000L) #if (OPENSSL_VERSION_NUMBER >= 0x10100000L && !defined(LIBRESSL_VERSION_NUMBER)) || (defined(LIBRESSL_VERSION_NUMBER) && LIBRESSL_VERSION_NUMBER >= 0x20702000L)
if (ctx->spec->opts->minsslversion) { if (ctx->conn_opts->minsslversion) {
if (SSL_CTX_set_min_proto_version(sslctx, ctx->spec->opts->minsslversion) == 0) { if (SSL_CTX_set_min_proto_version(sslctx, ctx->conn_opts->minsslversion) == 0) {
SSL_CTX_free(sslctx); SSL_CTX_free(sslctx);
return NULL; return NULL;
} }
} }
if (ctx->spec->opts->maxsslversion) { if (ctx->conn_opts->maxsslversion) {
if (SSL_CTX_set_max_proto_version(sslctx, ctx->spec->opts->maxsslversion) == 0) { if (SSL_CTX_set_max_proto_version(sslctx, ctx->conn_opts->maxsslversion) == 0) {
SSL_CTX_free(sslctx); SSL_CTX_free(sslctx);
return NULL; return NULL;
} }
} }
// ForceSSLproto has precedence // ForceSSLproto has precedence
if (ctx->spec->opts->sslversion) { if (ctx->conn_opts->sslversion) {
if (SSL_CTX_set_min_proto_version(sslctx, ctx->spec->opts->sslversion) == 0 || if (SSL_CTX_set_min_proto_version(sslctx, ctx->conn_opts->sslversion) == 0 ||
SSL_CTX_set_max_proto_version(sslctx, ctx->spec->opts->sslversion) == 0) { SSL_CTX_set_max_proto_version(sslctx, ctx->conn_opts->sslversion) == 0) {
SSL_CTX_free(sslctx); SSL_CTX_free(sslctx);
return NULL; return NULL;
} }
@ -391,15 +391,15 @@ protossl_srcsslctx_create(pxy_conn_ctx_t *ctx, X509 *crt, STACK_OF(X509) *chain,
SSL_CTX_set_tlsext_servername_arg(sslctx, ctx); SSL_CTX_set_tlsext_servername_arg(sslctx, ctx);
#endif /* !OPENSSL_NO_TLSEXT */ #endif /* !OPENSSL_NO_TLSEXT */
#ifndef OPENSSL_NO_DH #ifndef OPENSSL_NO_DH
if (ctx->spec->opts->dh) { if (ctx->conn_opts->dh) {
SSL_CTX_set_tmp_dh(sslctx, ctx->spec->opts->dh); SSL_CTX_set_tmp_dh(sslctx, ctx->conn_opts->dh);
} else { } else {
SSL_CTX_set_tmp_dh_callback(sslctx, ssl_tmp_dh_callback); SSL_CTX_set_tmp_dh_callback(sslctx, ssl_tmp_dh_callback);
} }
#endif /* !OPENSSL_NO_DH */ #endif /* !OPENSSL_NO_DH */
#ifndef OPENSSL_NO_ECDH #ifndef OPENSSL_NO_ECDH
if (ctx->spec->opts->ecdhcurve) { if (ctx->conn_opts->ecdhcurve) {
EC_KEY *ecdh = ssl_ec_by_name(ctx->spec->opts->ecdhcurve); EC_KEY *ecdh = ssl_ec_by_name(ctx->conn_opts->ecdhcurve);
SSL_CTX_set_tmp_ecdh(sslctx, ecdh); SSL_CTX_set_tmp_ecdh(sslctx, ecdh);
EC_KEY_free(ecdh); EC_KEY_free(ecdh);
} else { } else {
@ -562,16 +562,16 @@ protossl_srccert_create(pxy_conn_ctx_t *ctx)
} else { } else {
if (OPTS_DEBUG(ctx->global)) if (OPTS_DEBUG(ctx->global))
log_dbg_printf("Certificate cache: MISS\n"); log_dbg_printf("Certificate cache: MISS\n");
cert->crt = ssl_x509_forge(ctx->spec->opts->cacrt, cert->crt = ssl_x509_forge(ctx->conn_opts->cacrt,
ctx->spec->opts->cakey, ctx->conn_opts->cakey,
ctx->sslctx->origcrt, ctx->sslctx->origcrt,
ctx->global->leafkey, ctx->global->leafkey,
NULL, NULL,
ctx->spec->opts->leafcrlurl); ctx->conn_opts->leafcrlurl);
cachemgr_fkcrt_set(ctx->sslctx->origcrt, cert->crt); cachemgr_fkcrt_set(ctx->sslctx->origcrt, cert->crt);
} }
cert_set_key(cert, ctx->global->leafkey); cert_set_key(cert, ctx->global->leafkey);
cert_set_chain(cert, ctx->spec->opts->chain); cert_set_chain(cert, ctx->conn_opts->chain);
ctx->sslctx->generated_cert = 1; ctx->sslctx->generated_cert = 1;
} }
@ -940,7 +940,7 @@ protossl_ossl_servername_cb(SSL *ssl, UNUSED int *al, void *arg)
/* generate a new certificate with sn as additional altSubjectName /* generate a new certificate with sn as additional altSubjectName
* and replace it both in the current SSL ctx and in the cert cache */ * and replace it both in the current SSL ctx and in the cert cache */
if (ctx->spec->opts->allow_wrong_host && !ctx->sslctx->immutable_cert && if (ctx->conn_opts->allow_wrong_host && !ctx->sslctx->immutable_cert &&
!ssl_x509_names_match((sslcrt = SSL_get_certificate(ssl)), sn)) { !ssl_x509_names_match((sslcrt = SSL_get_certificate(ssl)), sn)) {
X509 *newcrt; X509 *newcrt;
SSL_CTX *newsslctx; SSL_CTX *newsslctx;
@ -949,9 +949,9 @@ protossl_ossl_servername_cb(SSL *ssl, UNUSED int *al, void *arg)
log_dbg_printf("Certificate cache: UPDATE " log_dbg_printf("Certificate cache: UPDATE "
"(SNI mismatch)\n"); "(SNI mismatch)\n");
} }
newcrt = ssl_x509_forge(ctx->spec->opts->cacrt, ctx->spec->opts->cakey, newcrt = ssl_x509_forge(ctx->conn_opts->cacrt, ctx->conn_opts->cakey,
sslcrt, ctx->global->leafkey, sslcrt, ctx->global->leafkey,
sn, ctx->spec->opts->leafcrlurl); sn, ctx->conn_opts->leafcrlurl);
if (!newcrt) { if (!newcrt) {
ctx->enomem = 1; ctx->enomem = 1;
return SSL_TLSEXT_ERR_NOACK; return SSL_TLSEXT_ERR_NOACK;
@ -982,7 +982,7 @@ protossl_ossl_servername_cb(SSL *ssl, UNUSED int *al, void *arg)
} }
} }
newsslctx = protossl_srcsslctx_create(ctx, newcrt, ctx->spec->opts->chain, newsslctx = protossl_srcsslctx_create(ctx, newcrt, ctx->conn_opts->chain,
ctx->global->leafkey); ctx->global->leafkey);
if (!newsslctx) { if (!newsslctx) {
X509_free(newcrt); X509_free(newcrt);
@ -1011,7 +1011,7 @@ protossl_dstssl_create(pxy_conn_ctx_t *ctx)
SSL *ssl; SSL *ssl;
SSL_SESSION *sess; SSL_SESSION *sess;
sslctx = SSL_CTX_new(ctx->spec->opts->sslmethod()); sslctx = SSL_CTX_new(ctx->conn_opts->sslmethod());
if (!sslctx) { if (!sslctx) {
ctx->enomem = 1; ctx->enomem = 1;
return NULL; return NULL;
@ -1020,43 +1020,43 @@ protossl_dstssl_create(pxy_conn_ctx_t *ctx)
protossl_sslctx_setoptions(sslctx, ctx); protossl_sslctx_setoptions(sslctx, ctx);
#if (OPENSSL_VERSION_NUMBER >= 0x10100000L && !defined(LIBRESSL_VERSION_NUMBER)) || (defined(LIBRESSL_VERSION_NUMBER) && LIBRESSL_VERSION_NUMBER >= 0x20702000L) #if (OPENSSL_VERSION_NUMBER >= 0x10100000L && !defined(LIBRESSL_VERSION_NUMBER)) || (defined(LIBRESSL_VERSION_NUMBER) && LIBRESSL_VERSION_NUMBER >= 0x20702000L)
if (ctx->spec->opts->minsslversion) { if (ctx->conn_opts->minsslversion) {
if (SSL_CTX_set_min_proto_version(sslctx, ctx->spec->opts->minsslversion) == 0) { if (SSL_CTX_set_min_proto_version(sslctx, ctx->conn_opts->minsslversion) == 0) {
SSL_CTX_free(sslctx); SSL_CTX_free(sslctx);
return NULL; return NULL;
} }
} }
if (ctx->spec->opts->maxsslversion) { if (ctx->conn_opts->maxsslversion) {
if (SSL_CTX_set_max_proto_version(sslctx, ctx->spec->opts->maxsslversion) == 0) { if (SSL_CTX_set_max_proto_version(sslctx, ctx->conn_opts->maxsslversion) == 0) {
SSL_CTX_free(sslctx); SSL_CTX_free(sslctx);
return NULL; return NULL;
} }
} }
// ForceSSLproto has precedence // ForceSSLproto has precedence
if (ctx->spec->opts->sslversion) { if (ctx->conn_opts->sslversion) {
if (SSL_CTX_set_min_proto_version(sslctx, ctx->spec->opts->sslversion) == 0 || if (SSL_CTX_set_min_proto_version(sslctx, ctx->conn_opts->sslversion) == 0 ||
SSL_CTX_set_max_proto_version(sslctx, ctx->spec->opts->sslversion) == 0) { SSL_CTX_set_max_proto_version(sslctx, ctx->conn_opts->sslversion) == 0) {
SSL_CTX_free(sslctx); SSL_CTX_free(sslctx);
return NULL; return NULL;
} }
} }
#endif /* OPENSSL_VERSION_NUMBER >= 0x10100000L */ #endif /* OPENSSL_VERSION_NUMBER >= 0x10100000L */
if (ctx->spec->opts->verify_peer) { if (ctx->conn_opts->verify_peer) {
SSL_CTX_set_verify(sslctx, SSL_VERIFY_PEER, NULL); SSL_CTX_set_verify(sslctx, SSL_VERIFY_PEER, NULL);
SSL_CTX_set_default_verify_paths(sslctx); SSL_CTX_set_default_verify_paths(sslctx);
} else { } else {
SSL_CTX_set_verify(sslctx, SSL_VERIFY_NONE, NULL); SSL_CTX_set_verify(sslctx, SSL_VERIFY_NONE, NULL);
} }
if (ctx->spec->opts->clientcrt && if (ctx->conn_opts->clientcrt &&
(SSL_CTX_use_certificate(sslctx, ctx->spec->opts->clientcrt) != 1)) { (SSL_CTX_use_certificate(sslctx, ctx->conn_opts->clientcrt) != 1)) {
log_dbg_printf("loading dst client certificate failed\n"); log_dbg_printf("loading dst client certificate failed\n");
SSL_CTX_free(sslctx); SSL_CTX_free(sslctx);
return NULL; return NULL;
} }
if (ctx->spec->opts->clientkey && if (ctx->conn_opts->clientkey &&
(SSL_CTX_use_PrivateKey(sslctx, ctx->spec->opts->clientkey) != 1)) { (SSL_CTX_use_PrivateKey(sslctx, ctx->conn_opts->clientkey) != 1)) {
log_dbg_printf("loading dst client key failed\n"); log_dbg_printf("loading dst client key failed\n");
SSL_CTX_free(sslctx); SSL_CTX_free(sslctx);
return NULL; return NULL;
@ -1527,7 +1527,7 @@ protossl_setup_src_ssl(pxy_conn_ctx_t *ctx)
else if (ctx->term) { else if (ctx->term) {
return -1; return -1;
} }
else if (!ctx->enomem && (ctx->pass || ctx->spec->opts->passthrough)) { else if (!ctx->enomem && (ctx->pass || ctx->conn_opts->passthrough)) {
log_err_level_printf(LOG_WARNING, "Falling back to passthrough\n"); log_err_level_printf(LOG_WARNING, "Falling back to passthrough\n");
protopassthrough_engage(ctx); protopassthrough_engage(ctx);
// report protocol change by returning 1 // report protocol change by returning 1
@ -1719,7 +1719,7 @@ protossl_bev_eventcb_error_srvdst(UNUSED struct bufferevent *bev, pxy_conn_ctx_t
/* the callout to the original destination failed, /* the callout to the original destination failed,
* e.g. because it asked for client cert auth, so * e.g. because it asked for client cert auth, so
* close the accepted socket and clean up */ * close the accepted socket and clean up */
if (((ctx->spec->opts->passthrough && ctx->sslctx->have_sslerr) || (ctx->pass && !ctx->sslctx->have_sslerr))) { if (((ctx->conn_opts->passthrough && ctx->sslctx->have_sslerr) || (ctx->pass && !ctx->sslctx->have_sslerr))) {
/* ssl callout failed, fall back to plain TCP passthrough of SSL connection */ /* ssl callout failed, fall back to plain TCP passthrough of SSL connection */
log_err_level_printf(LOG_WARNING, "SSL srvdst connection failed; falling back to passthrough\n"); log_err_level_printf(LOG_WARNING, "SSL srvdst connection failed; falling back to passthrough\n");
ctx->sslctx->have_sslerr = 0; ctx->sslctx->have_sslerr = 0;

@ -226,10 +226,10 @@ prototcp_init_conn(UNUSED evutil_socket_t fd, UNUSED short what, void *arg)
int int
prototcp_try_send_userauth_msg(struct bufferevent *bev, pxy_conn_ctx_t *ctx) prototcp_try_send_userauth_msg(struct bufferevent *bev, pxy_conn_ctx_t *ctx)
{ {
if (ctx->spec->opts->user_auth && !ctx->user) { if (ctx->conn_opts->user_auth && !ctx->user) {
log_finest("Sending userauth message"); log_finest("Sending userauth message");
pxy_discard_inbuf(bev); pxy_discard_inbuf(bev);
evbuffer_add_printf(bufferevent_get_output(bev), USERAUTH_MSG, ctx->spec->opts->user_auth_url); evbuffer_add_printf(bufferevent_get_output(bev), USERAUTH_MSG, ctx->conn_opts->user_auth_url);
ctx->sent_userauth_msg = 1; ctx->sent_userauth_msg = 1;
return 1; return 1;
} }
@ -240,7 +240,7 @@ prototcp_try_send_userauth_msg(struct bufferevent *bev, pxy_conn_ctx_t *ctx)
static int NONNULL(1,2,3,4) static int NONNULL(1,2,3,4)
prototcp_try_validate_proto(struct bufferevent *bev, pxy_conn_ctx_t *ctx, struct evbuffer *inbuf, struct evbuffer *outbuf) prototcp_try_validate_proto(struct bufferevent *bev, pxy_conn_ctx_t *ctx, struct evbuffer *inbuf, struct evbuffer *outbuf)
{ {
if (ctx->spec->opts->validate_proto && ctx->protoctx->validatecb && !ctx->protoctx->is_valid) { if (ctx->conn_opts->validate_proto && ctx->protoctx->validatecb && !ctx->protoctx->is_valid) {
size_t packet_size = evbuffer_get_length(inbuf); size_t packet_size = evbuffer_get_length(inbuf);
char *packet = (char *)pxy_malloc_packet(packet_size, ctx); char *packet = (char *)pxy_malloc_packet(packet_size, ctx);
if (!packet) { if (!packet) {
@ -371,7 +371,7 @@ prototcp_bev_readcb_dst_child(struct bufferevent *bev, pxy_conn_child_ctx_t *ctx
int int
prototcp_try_close_unauth_conn(struct bufferevent *bev, pxy_conn_ctx_t *ctx) prototcp_try_close_unauth_conn(struct bufferevent *bev, pxy_conn_ctx_t *ctx)
{ {
if (ctx->spec->opts->user_auth && !ctx->user) { if (ctx->conn_opts->user_auth && !ctx->user) {
size_t outbuflen = evbuffer_get_length(bufferevent_get_output(bev)); size_t outbuflen = evbuffer_get_length(bufferevent_get_output(bev));
if (outbuflen > 0) { if (outbuflen > 0) {
log_finest_va("Not closing unauth conn, outbuflen=%zu", outbuflen); log_finest_va("Not closing unauth conn, outbuflen=%zu", outbuflen);
@ -390,7 +390,7 @@ prototcp_try_close_unauth_conn(struct bufferevent *bev, pxy_conn_ctx_t *ctx)
int int
prototcp_try_close_protoerror_conn(struct bufferevent *bev, pxy_conn_ctx_t *ctx) prototcp_try_close_protoerror_conn(struct bufferevent *bev, pxy_conn_ctx_t *ctx)
{ {
if (ctx->spec->opts->validate_proto && ctx->sent_protoerror_msg) { if (ctx->conn_opts->validate_proto && ctx->sent_protoerror_msg) {
size_t outbuflen = evbuffer_get_length(bufferevent_get_output(bev)); size_t outbuflen = evbuffer_get_length(bufferevent_get_output(bev));
if (outbuflen > 0) { if (outbuflen > 0) {
log_finest_va("Not closing protoerror conn, outbuflen=%zu", outbuflen); log_finest_va("Not closing protoerror conn, outbuflen=%zu", outbuflen);

@ -170,6 +170,7 @@ proxy_conn_ctx_new(evutil_socket_t fd,
ctx->fd = fd; ctx->fd = fd;
ctx->thrmgr = thrmgr; ctx->thrmgr = thrmgr;
ctx->spec = spec; ctx->spec = spec;
ctx->conn_opts = spec->conn_opts;
ctx->divert = spec->opts->divert; ctx->divert = spec->opts->divert;
// Enable all logging for conn if proxyspec does not have any filter // Enable all logging for conn if proxyspec does not have any filter

@ -328,10 +328,10 @@ pxy_conn_ctx_free(pxy_conn_ctx_t *ctx, int by_requestor)
} }
#ifndef WITHOUT_USERAUTH #ifndef WITHOUT_USERAUTH
if (ctx->spec->opts->user_auth && ctx->srchost_str && ctx->user && ctx->ether) { if (ctx->conn_opts->user_auth && ctx->srchost_str && ctx->user && ctx->ether) {
// Update userdb atime if idle time is more than 50% of user timeout, which is expected to reduce update frequency // Update userdb atime if idle time is more than 50% of user timeout, which is expected to reduce update frequency
unsigned int idletime = ctx->idletime + (time(NULL) - ctx->ctime); unsigned int idletime = ctx->idletime + (time(NULL) - ctx->ctime);
if (idletime > (ctx->spec->opts->user_timeout / 2)) { if (idletime > (ctx->conn_opts->user_timeout / 2)) {
userdbkeys_t keys; userdbkeys_t keys;
// Zero out for NULL termination // Zero out for NULL termination
memset(&keys, 0, sizeof(userdbkeys_t)); memset(&keys, 0, sizeof(userdbkeys_t));
@ -1270,7 +1270,7 @@ pxy_setup_child_listener(pxy_conn_ctx_t *ctx)
#ifndef WITHOUT_USERAUTH #ifndef WITHOUT_USERAUTH
int user_len = 0; int user_len = 0;
if (ctx->spec->opts->user_auth && ctx->user) { if (ctx->conn_opts->user_auth && ctx->user) {
// +1 for comma // +1 for comma
user_len = strlen(ctx->user) + 1; user_len = strlen(ctx->user) + 1;
} }
@ -1773,7 +1773,7 @@ identify_user(UNUSED evutil_socket_t fd, UNUSED short what, void *arg)
log_finest_va("Passed ethernet address test, %s", ether); log_finest_va("Passed ethernet address test, %s", ether);
ctx->idletime = time(NULL) - sqlite3_column_int(ctx->thr->get_user, 2); ctx->idletime = time(NULL) - sqlite3_column_int(ctx->thr->get_user, 2);
if (ctx->idletime > ctx->spec->opts->user_timeout) { if (ctx->idletime > ctx->conn_opts->user_timeout) {
log_finest_va("User entry timed out, idletime=%u", ctx->idletime); log_finest_va("User entry timed out, idletime=%u", ctx->idletime);
goto redirect; goto redirect;
} }
@ -1969,7 +1969,7 @@ out:
void void
pxy_userauth(pxy_conn_ctx_t *ctx) pxy_userauth(pxy_conn_ctx_t *ctx)
{ {
if (ctx->spec->opts->user_auth && !ctx->user) { if (ctx->conn_opts->user_auth && !ctx->user) {
#if defined(__OpenBSD__) || defined(__linux__) #if defined(__OpenBSD__) || defined(__linux__)
int ec = get_client_ether( int ec = get_client_ether(
#if defined(__OpenBSD__) #if defined(__OpenBSD__)

@ -255,6 +255,7 @@ struct pxy_conn_ctx {
pxy_thr_ctx_t *thr; pxy_thr_ctx_t *thr;
pxy_thrmgr_ctx_t *thrmgr; pxy_thrmgr_ctx_t *thrmgr;
conn_opts_t *conn_opts;
proxyspec_t *spec; proxyspec_t *spec;
global_t *global; global_t *global;

@ -107,7 +107,7 @@ pxy_thrmgr_run(pxy_thrmgr_ctx_t *ctx)
ctx->thr[i]->thrmgr = ctx; ctx->thr[i]->thrmgr = ctx;
#ifndef WITHOUT_USERAUTH #ifndef WITHOUT_USERAUTH
if ((ctx->global->opts->user_auth || global_has_userauth_spec(ctx->global)) && if ((ctx->global->conn_opts->user_auth || global_has_userauth_spec(ctx->global)) &&
sqlite3_prepare_v2(ctx->global->userdb, "SELECT user,ether,atime,desc FROM users WHERE ip = ?1", 100, &ctx->thr[i]->get_user, NULL)) { sqlite3_prepare_v2(ctx->global->userdb, "SELECT user,ether,atime,desc FROM users WHERE ip = ?1", 100, &ctx->thr[i]->get_user, NULL)) {
log_err_level_printf(LOG_CRIT, "Error preparing get_user sql stmt: %s\n", sqlite3_errmsg(ctx->global->userdb)); log_err_level_printf(LOG_CRIT, "Error preparing get_user sql stmt: %s\n", sqlite3_errmsg(ctx->global->userdb));
goto leave; goto leave;

File diff suppressed because it is too large Load Diff

@ -636,7 +636,7 @@ START_TEST(opts_set_passsite_01)
opts_t *opts = opts_new(); opts_t *opts = opts_new();
char *s = strdup("example.com"); char *s = strdup("example.com");
UNUSED int rv = filter_passsite_set(opts, s, 0); UNUSED int rv = filter_passsite_set(opts, 0, s, 0);
free(s); free(s);
fail_unless(!strcmp(opts->filter_rules->site, "example.com"), "site not example.com"); fail_unless(!strcmp(opts->filter_rules->site, "example.com"), "site not example.com");
@ -666,7 +666,7 @@ START_TEST(opts_set_passsite_02)
opts_t *opts = opts_new(); opts_t *opts = opts_new();
char *s = strdup("example.com 192.168.0.1"); char *s = strdup("example.com 192.168.0.1");
UNUSED int rv = filter_passsite_set(opts, s, 0); UNUSED int rv = filter_passsite_set(opts, 0, s, 0);
free(s); free(s);
fail_unless(!strcmp(opts->filter_rules->site, "example.com"), "site not example.com"); fail_unless(!strcmp(opts->filter_rules->site, "example.com"), "site not example.com");
@ -696,10 +696,8 @@ START_TEST(opts_set_passsite_03)
char *ps; char *ps;
opts_t *opts = opts_new(); opts_t *opts = opts_new();
opts->user_auth = 1;
char *s = strdup("example.com root"); char *s = strdup("example.com root");
UNUSED int rv = filter_passsite_set(opts, s, 0); UNUSED int rv = filter_passsite_set(opts, 1, s, 0);
free(s); free(s);
fail_unless(!strcmp(opts->filter_rules->site, "example.com"), "site not example.com"); fail_unless(!strcmp(opts->filter_rules->site, "example.com"), "site not example.com");
@ -722,10 +720,8 @@ START_TEST(opts_set_passsite_04)
char *ps; char *ps;
opts_t *opts = opts_new(); opts_t *opts = opts_new();
opts->user_auth = 1;
char *s = strdup("*.google.com * android"); char *s = strdup("*.google.com * android");
UNUSED int rv = filter_passsite_set(opts, s, 0); UNUSED int rv = filter_passsite_set(opts, 1, s, 0);
free(s); free(s);
fail_unless(!strcmp(opts->filter_rules->site, "*.google.com"), "site not *.google.com"); fail_unless(!strcmp(opts->filter_rules->site, "*.google.com"), "site not *.google.com");
@ -753,28 +749,27 @@ START_TEST(opts_set_passsite_05)
// Dup string using strdup(), otherwise strtok_r() in opts_set_passsite() will cause segmentation fault // Dup string using strdup(), otherwise strtok_r() in opts_set_passsite() will cause segmentation fault
s = strdup("example.com"); s = strdup("example.com");
UNUSED int rv = filter_passsite_set(opts, s, 0); UNUSED int rv = filter_passsite_set(opts, 0, s, 0);
free(s); free(s);
fail_unless(!opts->filter_rules->next, "next set"); fail_unless(!opts->filter_rules->next, "next set");
s = strdup("example.com *"); s = strdup("example.com *");
rv = filter_passsite_set(opts, s, 1); rv = filter_passsite_set(opts, 0, s, 1);
free(s); free(s);
fail_unless(opts->filter_rules->next, "next not set"); fail_unless(opts->filter_rules->next, "next not set");
fail_unless(!opts->filter_rules->next->next, "next->next set"); fail_unless(!opts->filter_rules->next->next, "next->next set");
s = strdup("example.com 192.168.0.1"); s = strdup("example.com 192.168.0.1");
rv = filter_passsite_set(opts, s, 2); rv = filter_passsite_set(opts, 0, s, 2);
free(s); free(s);
fail_unless(opts->filter_rules->next, "next not set"); fail_unless(opts->filter_rules->next, "next not set");
fail_unless(opts->filter_rules->next->next, "next->next not set"); fail_unless(opts->filter_rules->next->next, "next->next not set");
fail_unless(!opts->filter_rules->next->next->next, "next->next->next set"); fail_unless(!opts->filter_rules->next->next->next, "next->next->next set");
#ifndef WITHOUT_USERAUTH #ifndef WITHOUT_USERAUTH
opts->user_auth = 1;
// Use root user, opts_set_passsite() calls sys_isuser() to validate the user // Use root user, opts_set_passsite() calls sys_isuser() to validate the user
s = strdup("example.com root"); s = strdup("example.com root");
rv = filter_passsite_set(opts, s, 3); rv = filter_passsite_set(opts, 1, s, 3);
free(s); free(s);
fail_unless(opts->filter_rules->next, "next not set"); fail_unless(opts->filter_rules->next, "next not set");
fail_unless(opts->filter_rules->next->next, "next->next not set"); fail_unless(opts->filter_rules->next->next, "next->next not set");
@ -782,7 +777,7 @@ START_TEST(opts_set_passsite_05)
fail_unless(!opts->filter_rules->next->next->next->next, "next->next->next->next set"); fail_unless(!opts->filter_rules->next->next->next->next, "next->next->next->next set");
s = strdup("*.google.com * android"); s = strdup("*.google.com * android");
rv = filter_passsite_set(opts, s, 4); rv = filter_passsite_set(opts, 1, s, 4);
free(s); free(s);
#endif /* !WITHOUT_USERAUTH */ #endif /* !WITHOUT_USERAUTH */
ps = filter_rule_str(opts->filter_rules); ps = filter_rule_str(opts->filter_rules);

Loading…
Cancel
Save