Add WITHOUT_USERAUTH switch

pull/48/head
Soner Tari 4 years ago
parent ca79405769
commit 6f5a7ceeb1

@ -75,6 +75,13 @@
#FEATURES+= -DWITH_SSLV2
### User Authentication
# Define to disable support for user authentication.
# Doing so will remove the dependency on sqlite.
#FEATURES+= -DWITHOUT_USERAUTH
### Debugging
# These flags are added to CFLAGS iff building from a git repo.
@ -281,10 +288,12 @@ PKGS+= $(shell $(PKGCONFIG) $(PCFLAGS) --exists libpcap \
&& echo libpcap)
endif
endif
ifneq ($(filter -DWITHOUT_USERAUTH,$(FEATURES)),-DWITHOUT_USERAUTH)
ifndef SQLITE_BASE
PKGS+= $(shell $(PKGCONFIG) $(PCFLAGS) --exists sqlite3 \
&& echo sqlite3)
endif
endif
TPKGS:=
ifndef CHECK_BASE
TPKGS+= $(shell $(PKGCONFIG) $(PCFLAGS) --exists check \
@ -328,6 +337,7 @@ $(error dependency 'libpcap' not found; \
endif
endif
endif
ifneq ($(filter -DWITHOUT_USERAUTH,$(FEATURES)),-DWITHOUT_USERAUTH)
ifeq (,$(filter sqlite3,$(PKGS)))
SQLITE_FOUND:=$(call locate,sqlite3,include/sqlite3.h,$(SQLITE_BASE))
ifndef SQLITE_FOUND
@ -335,6 +345,7 @@ $(error dependency 'SQLite3' not found; \
install it or point SQLITE_BASE to base path)
endif
endif
endif
ifeq (,$(filter check,$(TPKGS)))
CHECK_FOUND:= $(call locate,check,include/check.h,$(CHECK_BASE))
ifndef CHECK_FOUND
@ -385,11 +396,13 @@ PKG_LDFLAGS+= -L$(LIBPCAP_FOUND)/lib
PKG_LIBS+= -lpcap
endif
endif
ifneq ($(filter -DWITHOUT_USERAUTH,$(FEATURES)),-DWITHOUT_USERAUTH)
ifdef SQLITE_FOUND
PKG_CPPFLAGS+= -I$(SQLITE_FOUND)/include
PKG_LDFLAGS+= -L$(SQLITE_FOUND)/lib
PKG_LIBS+= -lsqlite3
endif
endif
ifdef CHECK_FOUND
TPKG_CPPFLAGS+= -I$(CHECK_FOUND)/include
TPKG_LDFLAGS+= -L$(CHECK_FOUND)/lib

@ -135,8 +135,10 @@ main_version(void)
lpv += 16;
fprintf(stderr, "rtlinked against libpcap %s\n", lpv);
#endif /* !WITHOUT_MIRROR */
#ifndef WITHOUT_USERAUTH
fprintf(stderr, "compiled against sqlite %s\n", SQLITE_VERSION);
fprintf(stderr, "rtlinked against sqlite %s\n", sqlite3_libversion());
#endif /* !WITHOUT_USERAUTH */
fprintf(stderr, "%d CPU cores detected\n", sys_get_cpu_cores());
}
@ -641,6 +643,7 @@ main(int argc, char *argv[])
}
}
#ifndef WITHOUT_USERAUTH
if (global->opts->user_auth || global_has_userauth_spec(global)) {
if (!global->userdb_path) {
fprintf(stderr, "User auth requires a userdb path\n");
@ -660,6 +663,7 @@ main(int argc, char *argv[])
exit(EXIT_FAILURE);
}
}
#endif /* !WITHOUT_USERAUTH */
/* dynamic defaults */
if (!global->opts->ciphers) {

@ -120,7 +120,9 @@ opts_new(void)
#endif /* OPENSSL_VERSION_NUMBER >= 0x10100000L */
opts->remove_http_referer = 1;
opts->verify_peer = 1;
#ifndef WITHOUT_USERAUTH
opts->user_timeout = 300;
#endif /* !WITHOUT_USERAUTH */
opts->max_http_header_size = 8192;
return opts;
}
@ -177,19 +179,23 @@ opts_free(opts_t *opts)
if (opts->ciphersuites) {
free(opts->ciphersuites);
}
#ifndef WITHOUT_USERAUTH
if (opts->user_auth_url) {
free(opts->user_auth_url);
}
#endif /* !WITHOUT_USERAUTH */
passsite_t *passsite = opts->passsites;
while (passsite) {
passsite_t *next = passsite->next;
free(passsite->site);
if (passsite->ip)
free(passsite->ip);
#ifndef WITHOUT_USERAUTH
if (passsite->user)
free(passsite->user);
if (passsite->keyword)
free(passsite->keyword);
#endif /* !WITHOUT_USERAUTH */
free(passsite);
passsite = next;
}
@ -327,6 +333,7 @@ global_free(global_t *global)
free(global->mirrortarget);
}
#endif /* !WITHOUT_MIRROR */
#ifndef WITHOUT_USERAUTH
if (global->userdb_path) {
free(global->userdb_path);
}
@ -335,6 +342,7 @@ global_free(global_t *global)
sqlite3_finalize(global->update_user_atime);
sqlite3_close(global->userdb);
}
#endif /* !WITHOUT_USERAUTH */
if (global->opts) {
opts_free(global->opts);
}
@ -387,6 +395,7 @@ global_has_dns_spec(global_t *global)
return 0;
}
#ifndef WITHOUT_USERAUTH
/*
* Return 1 if global_t contains a proxyspec with user_auth, 0 otherwise.
*/
@ -403,6 +412,7 @@ global_has_userauth_spec(global_t *global)
return 0;
}
#endif /* !WITHOUT_USERAUTH */
/*
* Return 1 if global_t contains a proxyspec with cakey defined, 0 otherwise.
@ -531,6 +541,7 @@ opts_proto_dbg_dump(opts_t *opts)
return s;
}
#ifndef WITHOUT_USERAUTH
static void
opts_set_user_auth_url(opts_t *opts, const char *optarg)
{
@ -541,6 +552,7 @@ opts_set_user_auth_url(opts_t *opts, const char *optarg)
log_dbg_printf("UserAuthURL: %s\n", opts->user_auth_url);
#endif /* DEBUG_OPTS */
}
#endif /* !WITHOUT_USERAUTH */
static opts_t *
clone_global_opts(global_t *global, const char *argv0, global_opts_str_t *global_opts_str)
@ -583,8 +595,10 @@ clone_global_opts(global_t *global, const char *argv0, global_opts_str_t *global
opts->remove_http_referer = global->opts->remove_http_referer;
opts->verify_peer = global->opts->verify_peer;
opts->allow_wrong_host = global->opts->allow_wrong_host;
#ifndef WITHOUT_USERAUTH
opts->user_auth = global->opts->user_auth;
opts->user_timeout = global->opts->user_timeout;
#endif /* !WITHOUT_USERAUTH */
opts->validate_proto = global->opts->validate_proto;
opts->max_http_header_size = global->opts->max_http_header_size;
@ -624,9 +638,11 @@ clone_global_opts(global_t *global, const char *argv0, global_opts_str_t *global
if (global->opts->ciphersuites) {
opts_set_ciphersuites(opts, argv0, global->opts->ciphersuites);
}
#ifndef WITHOUT_USERAUTH
if (global->opts->user_auth_url) {
opts_set_user_auth_url(opts, global->opts->user_auth_url);
}
#endif /* !WITHOUT_USERAUTH */
passsite_t *passsite = global->opts->passsites;
while (passsite) {
@ -637,11 +653,13 @@ clone_global_opts(global_t *global, const char *argv0, global_opts_str_t *global
ps->site = strdup(passsite->site);
if (passsite->ip)
ps->ip = strdup(passsite->ip);
#ifndef WITHOUT_USERAUTH
if (passsite->user)
ps->user = strdup(passsite->user);
if (passsite->keyword)
ps->keyword = strdup(passsite->keyword);
ps->all = passsite->all;
#endif /* !WITHOUT_USERAUTH */
ps->next = opts->passsites;
opts->passsites = ps;
@ -941,8 +959,15 @@ passsite_str(passsite_t *passsite)
int count = 0;
while (passsite) {
char *p;
if (asprintf(&p, "site=%s,ip=%s,user=%s,keyword=%s,all=%d",
passsite->site, STRORNONE(passsite->ip), STRORNONE(passsite->user), STRORNONE(passsite->keyword), passsite->all) < 0) {
if (asprintf(&p, "site=%s,ip=%s"
#ifndef WITHOUT_USERAUTH
",user=%s,keyword=%s,all=%d"
#endif /* !WITHOUT_USERAUTH */
, passsite->site, STRORNONE(passsite->ip)
#ifndef WITHOUT_USERAUTH
, STRORNONE(passsite->user), STRORNONE(passsite->keyword), passsite->all
#endif /* !WITHOUT_USERAUTH */
) < 0) {
goto err;
}
char *nps;
@ -1009,7 +1034,11 @@ opts_str(opts_t *opts)
#ifndef OPENSSL_NO_ECDH
"|%s"
#endif /* !OPENSSL_NO_ECDH */
"|%s%s%s%s%s%s|%s|%d%s|%d\n%s%s%s",
"|%s%s%s%s%s"
#ifndef WITHOUT_USERAUTH
"%s|%s|%d"
#endif /* !WITHOUT_USERAUTH */
"%s|%d\n%s%s%s",
(!opts->sslcomp ? "no sslcomp" : ""),
#ifdef HAVE_SSLV2
(opts->no_ssl2 ? "|no_ssl2" : ""),
@ -1041,9 +1070,11 @@ opts_str(opts_t *opts)
(opts->remove_http_referer ? "|remove_http_referer" : ""),
(opts->verify_peer ? "|verify_peer" : ""),
(opts->allow_wrong_host ? "|allow_wrong_host" : ""),
#ifndef WITHOUT_USERAUTH
(opts->user_auth ? "|user_auth" : ""),
(opts->user_auth_url ? opts->user_auth_url : "no user_auth_url"),
opts->user_timeout,
opts->user_timeout,
#endif /* !WITHOUT_USERAUTH */
(opts->validate_proto ? "|validate_proto" : ""),
opts->max_http_header_size,
proto_dump,
@ -1700,6 +1731,7 @@ opts_unset_allow_wrong_host(opts_t *opts)
opts->allow_wrong_host = 0;
}
#ifndef WITHOUT_USERAUTH
static void
opts_set_user_auth(UNUSED opts_t *opts)
{
@ -1714,6 +1746,7 @@ opts_unset_user_auth(opts_t *opts)
{
opts->user_auth = 0;
}
#endif /* !WITHOUT_USERAUTH */
static void
opts_set_validate_proto(opts_t *opts)
@ -1763,6 +1796,7 @@ opts_set_pass_site(opts_t *opts, char *value, int line_num)
ps->site = strdup(s);
if (argc > 1) {
#ifndef WITHOUT_USERAUTH
if (!strcmp(argv[1], "*")) {
ps->all = 1;
} else if (sys_isuser(argv[1])) {
@ -1772,8 +1806,11 @@ opts_set_pass_site(opts_t *opts, char *value, int line_num)
}
ps->user = strdup(argv[1]);
} else {
#endif /* !WITHOUT_USERAUTH */
ps->ip = strdup(argv[1]);
#ifndef WITHOUT_USERAUTH
}
#endif /* !WITHOUT_USERAUTH */
}
if (argc > 2) {
@ -1781,13 +1818,19 @@ opts_set_pass_site(opts_t *opts, char *value, int line_num)
fprintf(stderr, "PassSite client ip cannot define keyword filter on line %d\n", line_num);
exit(EXIT_FAILURE);
}
#ifndef WITHOUT_USERAUTH
ps->keyword = strdup(argv[2]);
#endif /* !WITHOUT_USERAUTH */
}
ps->next = opts->passsites;
opts->passsites = ps;
#ifdef DEBUG_OPTS
#ifndef WITHOUT_USERAUTH
log_dbg_printf("PassSite: %s, %s, %s, %s\n", ps->site, STRORDASH(ps->ip), ps->all ? "*" : STRORDASH(ps->user), STRORDASH(ps->keyword));
#else /* WITHOUT_USERAUTH */
log_dbg_printf("PassSite: %s, %s\n", ps->site, STRORDASH(ps->ip));
#endif /* WITHOUT_USERAUTH */
#endif /* DEBUG_OPTS */
}
@ -2284,6 +2327,7 @@ global_unset_statslog(global_t *global)
global->statslog = 0;
}
#ifndef WITHOUT_USERAUTH
static void
global_set_userdb_path(global_t *global, const char *optarg)
{
@ -2294,6 +2338,7 @@ global_set_userdb_path(global_t *global, const char *optarg)
log_dbg_printf("UserDBPath: %s\n", global->userdb_path);
#endif /* DEBUG_OPTS */
}
#endif /* !WITHOUT_USERAUTH */
int
check_value_yesno(const char *value, const char *name, int line_num)
@ -2393,6 +2438,7 @@ set_option(opts_t *opts, const char *argv0,
#ifdef DEBUG_OPTS
log_dbg_printf("NATEngine: %s\n", *natengine);
#endif /* DEBUG_OPTS */
#ifndef WITHOUT_USERAUTH
} else if (equal(name, "UserAuth")) {
yes = check_value_yesno(value, "UserAuth", line_num);
if (yes == -1) {
@ -2415,6 +2461,7 @@ set_option(opts_t *opts, const char *argv0,
#ifdef DEBUG_OPTS
log_dbg_printf("UserTimeout: %u\n", opts->user_timeout);
#endif /* DEBUG_OPTS */
#endif /* !WITHOUT_USERAUTH */
} else if (equal(name, "ValidateProto")) {
yes = check_value_yesno(value, "ValidateProto", line_num);
if (yes == -1) {
@ -2816,8 +2863,10 @@ set_global_option(global_t *global, const char *argv0,
#endif /* DEBUG_OPTS */
} else if (equal(name, "DebugLevel")) {
global_set_debug_level(value);
#ifndef WITHOUT_USERAUTH
} else if (equal(name, "UserDBPath")) {
global_set_userdb_path(global, value);
#endif /* !WITHOUT_USERAUTH */
} else if (equal(name, "ProxySpec")) {
if (equal(value, "{")) {
#ifdef DEBUG_OPTS

@ -36,9 +36,11 @@
#include "cert.h"
#include "attrib.h"
#ifndef WITHOUT_USERAUTH
#include <sys/types.h>
#include <sys/socket.h>
#include <sqlite3.h>
#endif /* !WITHOUT_USERAUTH */
/*
* Print helper for logging code.
@ -94,9 +96,11 @@ typedef struct opts {
unsigned int remove_http_referer: 1;
unsigned int verify_peer: 1;
unsigned int allow_wrong_host: 1;
#ifndef WITHOUT_USERAUTH
unsigned int user_auth: 1;
char *user_auth_url;
unsigned int user_timeout;
#endif /* !WITHOUT_USERAUTH */
unsigned int validate_proto : 1;
unsigned int max_http_header_size;
struct passsite *passsites;
@ -137,9 +141,11 @@ typedef struct passsite {
char *site;
// Filter definition fields
char *ip;
#ifndef WITHOUT_USERAUTH
char *user;
unsigned int all : 1; /* 1 for all users */
char *keyword;
#endif /* !WITHOUT_USERAUTH */
struct passsite *next;
} passsite_t;
@ -190,9 +196,11 @@ struct global {
unsigned int stats_period;
unsigned int statslog: 1;
unsigned int log_stats: 1;
#ifndef WITHOUT_USERAUTH
char *userdb_path;
sqlite3 *userdb;
struct sqlite3_stmt *update_user_atime;
#endif /* !WITHOUT_USERAUTH */
proxyspec_t *spec;
opts_t *opts;
@ -210,11 +218,13 @@ struct global {
#endif /* !OPENSSL_NO_ENGINE */
};
#ifndef WITHOUT_USERAUTH
typedef struct userdbkeys {
char ip[46];
char user[32];
char ether[18];
} userdbkeys_t;
#endif /* !WITHOUT_USERAUTH */
void NORET oom_die(const char *) NONNULL(1);
cert_t *opts_load_cert_chain_key(const char *) NONNULL(1);

@ -66,7 +66,9 @@
#define PRIVSEP_REQ_OPENFILE_P 2 /* open content log file w/mkpath */
#define PRIVSEP_REQ_OPENSOCK 3 /* open socket and pass fd */
#define PRIVSEP_REQ_CERTFILE 4 /* open cert file in certgendir */
#ifndef WITHOUT_USERAUTH
#define PRIVSEP_REQ_UPDATE_ATIME 5 /* update ip,user atime */
#endif /* !WITHOUT_USERAUTH */
/* response byte */
#define PRIVSEP_ANS_SUCCESS 0 /* success */
#define PRIVSEP_ANS_UNK_CMD 1 /* unknown command */
@ -327,6 +329,7 @@ privsep_server_certfile(const char *fn)
return fd;
}
#ifndef WITHOUT_USERAUTH
static int WUNRES
privsep_server_update_atime(global_t *global, const userdbkeys_t *keys)
{
@ -350,6 +353,7 @@ privsep_server_update_atime(global_t *global, const userdbkeys_t *keys)
sqlite3_reset(global->update_user_atime);
return 0;
}
#endif /* !WITHOUT_USERAUTH */
/*
* Handle a single request on a readable server socket.
@ -495,6 +499,7 @@ privsep_server_handle_req(global_t *global, int srvsock)
/* not reached */
break;
}
#ifndef WITHOUT_USERAUTH
case PRIVSEP_REQ_UPDATE_ATIME: {
userdbkeys_t arg;
@ -531,6 +536,7 @@ privsep_server_handle_req(global_t *global, int srvsock)
/* not reached */
break;
}
#endif /* !WITHOUT_USERAUTH */
case PRIVSEP_REQ_CERTFILE: {
char *fn;
int fd;
@ -926,6 +932,7 @@ privsep_client_close(int clisock)
return 0;
}
#ifndef WITHOUT_USERAUTH
int
privsep_client_update_atime(int clisock, const userdbkeys_t *keys)
{
@ -974,6 +981,7 @@ privsep_client_update_atime(int clisock, const userdbkeys_t *keys)
// Does not return an fd
return 0;
}
#endif /* !WITHOUT_USERAUTH */
/*
* Fork and set up privilege separated monitor process.

@ -38,7 +38,9 @@ int privsep_client_openfile(int, const char *, int);
int privsep_client_opensock(int, const proxyspec_t *spec);
int privsep_client_certfile(int, const char *);
int privsep_client_close(int);
#ifndef WITHOUT_USERAUTH
int privsep_client_update_atime(int, const userdbkeys_t *);
#endif /* !WITHOUT_USERAUTH */
#endif /* !PRIVSEP_H */
/* vim: set noet ft=c: */

@ -135,9 +135,11 @@ protoautossl_bev_readcb_src(struct bufferevent *bev, pxy_conn_ctx_t *ctx)
protoautossl_ctx_t *autossl_ctx = ctx->protoctx->arg;
#ifndef WITHOUT_USERAUTH
if (prototcp_try_send_userauth_msg(bev, ctx)) {
return;
}
#endif /* !WITHOUT_USERAUTH */
if (autossl_ctx->clienthello_search) {
if (protoautossl_peek_and_upgrade(ctx) != 0) {
@ -185,9 +187,11 @@ protoautossl_bev_readcb_srvdst(struct bufferevent *bev, pxy_conn_ctx_t *ctx)
{
log_finest_va("ENTER, size=%zu", evbuffer_get_length(bufferevent_get_input(bev)));
#ifndef WITHOUT_USERAUTH
if (prototcp_try_send_userauth_msg(ctx->src.bev, ctx)) {
return;
}
#endif /* !WITHOUT_USERAUTH */
// @todo We should validate the response from the server to protect the client,
// as we do with the smtp protocol, @see protosmtp_bev_readcb_srvdst()
@ -292,9 +296,11 @@ protoautossl_bev_eventcb_connected_srvdst(UNUSED struct bufferevent *bev, pxy_co
return;
}
#ifndef WITHOUT_USERAUTH
if (!ctx->term && !ctx->enomem) {
pxy_userauth(ctx);
}
#endif /* !WITHOUT_USERAUTH */
}
static void NONNULL(1,2)

@ -74,7 +74,11 @@ protohttp_log_connect(pxy_conn_ctx_t *ctx)
#ifdef HAVE_LOCAL_PROCINFO
" %s"
#endif /* HAVE_LOCAL_PROCINFO */
"%s user:%s\n",
"%s"
#ifndef WITHOUT_USERAUTH
" user:%s"
#endif /* !WITHOUT_USERAUTH */
"\n",
STRORDASH(ctx->srchost_str),
STRORDASH(ctx->srcport_str),
STRORDASH(ctx->dsthost_str),
@ -87,8 +91,11 @@ protohttp_log_connect(pxy_conn_ctx_t *ctx)
#ifdef HAVE_LOCAL_PROCINFO
lpi,
#endif /* HAVE_LOCAL_PROCINFO */
http_ctx->ocsp_denied ? " ocsp:denied" : "",
STRORDASH(ctx->user));
http_ctx->ocsp_denied ? " ocsp:denied" : ""
#ifndef WITHOUT_USERAUTH
, STRORDASH(ctx->user)
#endif /* !WITHOUT_USERAUTH */
);
} else {
rv = asprintf(&msg, "CONN: https %s %s %s %s %s %s %s %s %s "
"sni:%s names:%s "
@ -97,7 +104,11 @@ protohttp_log_connect(pxy_conn_ctx_t *ctx)
#ifdef HAVE_LOCAL_PROCINFO
" %s"
#endif /* HAVE_LOCAL_PROCINFO */
"%s user:%s\n",
"%s"
#ifndef WITHOUT_USERAUTH
" user:%s"
#endif /* !WITHOUT_USERAUTH */
"\n",
STRORDASH(ctx->srchost_str),
STRORDASH(ctx->srcport_str),
STRORDASH(ctx->dsthost_str),
@ -118,8 +129,11 @@ protohttp_log_connect(pxy_conn_ctx_t *ctx)
#ifdef HAVE_LOCAL_PROCINFO
lpi,
#endif /* HAVE_LOCAL_PROCINFO */
http_ctx->ocsp_denied ? " ocsp:denied" : "",
STRORDASH(ctx->user));
http_ctx->ocsp_denied ? " ocsp:denied" : ""
#ifndef WITHOUT_USERAUTH
, STRORDASH(ctx->user)
#endif /* !WITHOUT_USERAUTH */
);
}
if ((rv < 0 ) || !msg) {
ctx->enomem = 1;
@ -416,6 +430,7 @@ protohttp_filter_request_header(struct evbuffer *inbuf, struct evbuffer *outbuf,
}
}
#ifndef WITHOUT_USERAUTH
static char * NONNULL(1,2)
protohttp_get_url(struct evbuffer *inbuf, pxy_conn_ctx_t *ctx)
{
@ -477,6 +492,7 @@ memout:
free(path);
return url;
}
#endif /* !WITHOUT_USERAUTH */
// Size = 39
static char *http_methods[] = { "GET", "PUT", "ICY", "COPY", "HEAD", "LOCK", "MOVE", "POLL", "POST", "BCOPY", "BMOVE", "MKCOL", "TRACE", "LABEL", "MERGE", "DELETE",
@ -542,6 +558,7 @@ protohttp_validate(pxy_conn_ctx_t *ctx)
static void NONNULL(1,2)
protohttp_bev_readcb_src(struct bufferevent *bev, pxy_conn_ctx_t *ctx)
{
#ifndef WITHOUT_USERAUTH
static const char redirect[] =
"HTTP/1.1 302 Found\r\n"
"Location: %s\r\n"
@ -550,6 +567,7 @@ protohttp_bev_readcb_src(struct bufferevent *bev, pxy_conn_ctx_t *ctx)
"HTTP/1.1 302 Found\r\n"
"Location: %s?SSLproxy=%s\r\n"
"\r\n";
#endif /* !WITHOUT_USERAUTH */
static const char proto_error[] =
"HTTP/1.1 400 Bad request\r\n"
"Cache-Control: no-cache\r\n"
@ -568,6 +586,7 @@ protohttp_bev_readcb_src(struct bufferevent *bev, pxy_conn_ctx_t *ctx)
struct evbuffer *inbuf = bufferevent_get_input(bev);
struct evbuffer *outbuf = bufferevent_get_output(ctx->dst.bev);
#ifndef WITHOUT_USERAUTH
if (ctx->spec->opts->user_auth && !ctx->user) {
log_finest("Redirecting conn");
char *url = protohttp_get_url(inbuf, ctx);
@ -581,6 +600,7 @@ protohttp_bev_readcb_src(struct bufferevent *bev, pxy_conn_ctx_t *ctx)
ctx->sent_userauth_msg = 1;
return;
}
#endif /* !WITHOUT_USERAUTH */
if (ctx->spec->opts->validate_proto && !ctx->protoctx->is_valid) {
http_ctx->seen_bytes += evbuffer_get_length(inbuf);
@ -874,9 +894,11 @@ protohttp_bev_writecb_src(struct bufferevent *bev, pxy_conn_ctx_t *ctx)
{
log_finest("ENTER");
#ifndef WITHOUT_USERAUTH
if (prototcp_try_close_unauth_conn(bev, ctx)) {
return;
}
#endif /* !WITHOUT_USERAUTH */
if (prototcp_try_close_protoerror_conn(bev, ctx)) {
return;

@ -129,9 +129,11 @@ protopassthrough_bev_readcb_src(struct bufferevent *bev, pxy_conn_ctx_t *ctx)
return;
}
#ifndef WITHOUT_USERAUTH
if (prototcp_try_send_userauth_msg(bev, ctx)) {
return;
}
#endif /* !WITHOUT_USERAUTH */
evbuffer_add_buffer(bufferevent_get_output(ctx->srvdst.bev), bufferevent_get_input(bev));
pxy_try_set_watermark(bev, ctx, ctx->srvdst.bev);
@ -157,9 +159,11 @@ protopassthrough_bev_writecb_src(struct bufferevent *bev, pxy_conn_ctx_t *ctx)
{
log_finest("ENTER");
#ifndef WITHOUT_USERAUTH
if (prototcp_try_close_unauth_conn(bev, ctx)) {
return;
}
#endif /* !WITHOUT_USERAUTH */
// @attention srvdst.bev may be NULL
if (ctx->srvdst.closed) {
@ -222,9 +226,11 @@ protopassthrough_bev_eventcb_connected_srvdst(struct bufferevent *bev, pxy_conn_
return;
}
#ifndef WITHOUT_USERAUTH
if (!ctx->term && !ctx->enomem) {
pxy_userauth(ctx);
}
#endif /* !WITHOUT_USERAUTH */
}
static void NONNULL(1,2)

@ -185,9 +185,11 @@ protosmtp_bev_readcb_srvdst(struct bufferevent *bev, pxy_conn_ctx_t *ctx)
return;
}
#ifndef WITHOUT_USERAUTH
if (prototcp_try_send_userauth_msg(ctx->src.bev, ctx)) {
return;
}
#endif /* !WITHOUT_USERAUTH */
struct evbuffer *inbuf = bufferevent_get_input(bev);
struct evbuffer *outbuf = bufferevent_get_output(ctx->src.bev);

@ -581,10 +581,18 @@ protossl_srccert_create(pxy_conn_ctx_t *ctx)
static int NONNULL(1,2)
protossl_pass_user(pxy_conn_ctx_t *ctx, passsite_t *passsite)
{
#ifndef WITHOUT_USERAUTH
log_finest_va("ENTER, %s, %s, %s, %s", passsite->site, STRORDASH(passsite->ip), passsite->all ? "*" : STRORDASH(passsite->user), STRORDASH(passsite->keyword));
#else /* WITHOUT_USERAUTH */
log_finest_va("ENTER, %s, %s", passsite->site, STRORDASH(passsite->ip));
#endif /* WITHOUT_USERAUTH */
// No filter or * (all) without desc keyword defined
if (!passsite->ip && !passsite->user && !passsite->keyword) {
if (!passsite->ip
#ifndef WITHOUT_USERAUTH
&& !passsite->user && !passsite->keyword
#endif /* !WITHOUT_USERAUTH */
) {
return 1;
}
@ -595,14 +603,16 @@ protossl_pass_user(pxy_conn_ctx_t *ctx, passsite_t *passsite)
return 1;
}
#ifndef WITHOUT_USERAUTH
log_finest_va("Filter user: %s, %s", STRORDASH(ctx->user), STRORDASH(ctx->desc));
// Make sure ctx->user and ctx->desc are set, otherwise if the user did not log in yet, they may be NULL
// Make sure ctx->user and ctx->desc are set, otherwise if the user has not logged in yet, they may be NULL
// User and/or description keyword filters defined
if (ctx->spec->opts->user_auth && (passsite->all || (passsite->user && ctx->user && !strcmp(ctx->user, passsite->user))) &&
(!passsite->keyword || (ctx->desc && strcasestr(ctx->desc, passsite->keyword)))) {
return 1;
}
#endif /* !WITHOUT_USERAUTH */
return 0;
}
@ -720,8 +730,12 @@ protossl_srcssl_create(pxy_conn_ctx_t *ctx, SSL *origssl)
while (passsite) {
if (protossl_pass_user(ctx, passsite) && protossl_pass_site(ctx, passsite->site)) {
// Do not print the surrounding slashes
#ifndef WITHOUT_USERAUTH
log_err_level_printf(LOG_WARNING, "Found pass site: %.*s for user %s and keyword %s\n", (int)strlen(passsite->site) - 2, passsite->site + 1,
passsite->ip ? passsite->ip : (passsite->all ? "*" : STRORDASH(passsite->user)), STRORDASH(passsite->keyword));
#else /* WITHOUT_USERAUTH */
log_err_level_printf(LOG_WARNING, "Found pass site: %.*s for ip %s\n", (int)strlen(passsite->site) - 2, passsite->site + 1, STRORDASH(passsite->ip));
#endif /* WITHOUT_USERAUTH */
cert_free(cert);
// Differentiate passsite from passthrough option by raising the passsite flag
ctx->sslctx->passsite = 1;
@ -1521,9 +1535,11 @@ protossl_bev_eventcb_connected_srvdst(UNUSED struct bufferevent *bev, pxy_conn_c
return;
}
#ifndef WITHOUT_USERAUTH
if (!ctx->term && !ctx->enomem) {
pxy_userauth(ctx);
}
#endif /* !WITHOUT_USERAUTH */
}
static void NONNULL(1,2)

@ -214,6 +214,7 @@ prototcp_init_conn(UNUSED evutil_socket_t fd, UNUSED short what, void *arg)
pxy_conn_connect(ctx);
}
#ifndef WITHOUT_USERAUTH
int
prototcp_try_send_userauth_msg(struct bufferevent *bev, pxy_conn_ctx_t *ctx)
{
@ -226,6 +227,7 @@ prototcp_try_send_userauth_msg(struct bufferevent *bev, pxy_conn_ctx_t *ctx)
}
return 0;
}
#endif /* !WITHOUT_USERAUTH */
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)
@ -266,9 +268,11 @@ prototcp_bev_readcb_src(struct bufferevent *bev, pxy_conn_ctx_t *ctx)
return;
}
#ifndef WITHOUT_USERAUTH
if (prototcp_try_send_userauth_msg(bev, ctx)) {
return;
}
#endif /* !WITHOUT_USERAUTH */
struct evbuffer *inbuf = bufferevent_get_input(bev);
struct evbuffer *outbuf = bufferevent_get_output(ctx->dst.bev);
@ -369,6 +373,7 @@ prototcp_bev_readcb_dst_child(struct bufferevent *bev, pxy_conn_child_ctx_t *ctx
pxy_try_set_watermark(bev, ctx->conn, ctx->src.bev);
}
#ifndef WITHOUT_USERAUTH
int
prototcp_try_close_unauth_conn(struct bufferevent *bev, pxy_conn_ctx_t *ctx)
{
@ -386,6 +391,7 @@ prototcp_try_close_unauth_conn(struct bufferevent *bev, pxy_conn_ctx_t *ctx)
}
return 0;
}
#endif /* !WITHOUT_USERAUTH */
int
prototcp_try_close_protoerror_conn(struct bufferevent *bev, pxy_conn_ctx_t *ctx)
@ -408,9 +414,11 @@ prototcp_bev_writecb_src(struct bufferevent *bev, pxy_conn_ctx_t *ctx)
{
log_finest("ENTER");
#ifndef WITHOUT_USERAUTH
if (prototcp_try_close_unauth_conn(bev, ctx)) {
return;
}
#endif /* !WITHOUT_USERAUTH */
if (prototcp_try_close_protoerror_conn(bev, ctx)) {
return;
@ -522,9 +530,11 @@ prototcp_bev_eventcb_connected_srvdst(UNUSED struct bufferevent *bev, pxy_conn_c
return;
}
#ifndef WITHOUT_USERAUTH
if (!ctx->term && !ctx->enomem) {
pxy_userauth(ctx);
}
#endif /* !WITHOUT_USERAUTH */
}
void

@ -34,8 +34,10 @@
void prototcp_init_conn(evutil_socket_t, short, void *);
#ifndef WITHOUT_USERAUTH
int prototcp_try_send_userauth_msg(struct bufferevent *, pxy_conn_ctx_t *) NONNULL(1,2);
int prototcp_try_close_unauth_conn(struct bufferevent *, pxy_conn_ctx_t *) NONNULL(1,2);
#endif /* !WITHOUT_USERAUTH */
int prototcp_try_close_protoerror_conn(struct bufferevent *, pxy_conn_ctx_t *) NONNULL(1,2);
void prototcp_bev_readcb_src(struct bufferevent *, pxy_conn_ctx_t *) NONNULL(1,2);

@ -148,8 +148,11 @@ proxy_setup_proto(pxy_conn_ctx_t *ctx)
pxy_conn_ctx_t *
proxy_conn_ctx_new(evutil_socket_t fd,
pxy_thrmgr_ctx_t *thrmgr,
proxyspec_t *spec, global_t *global,
evutil_socket_t clisock)
proxyspec_t *spec, global_t *global
#ifndef WITHOUT_USERAUTH
, evutil_socket_t clisock
#endif /* !WITHOUT_USERAUTH */
)
{
log_finest_main_va("ENTER, fd=%d", fd);
@ -175,7 +178,9 @@ proxy_conn_ctx_new(evutil_socket_t fd,
}
ctx->global = global;
#ifndef WITHOUT_USERAUTH
ctx->clisock = clisock;
#endif /* !WITHOUT_USERAUTH */
#ifdef HAVE_LOCAL_PROCINFO
ctx->lproc.pid = -1;
@ -229,7 +234,11 @@ proxy_listener_acceptcb(UNUSED struct evconnlistener *listener,
log_finest_main_va("ENTER, fd=%d", fd);
/* create per connection state */
pxy_conn_ctx_t *ctx = proxy_conn_ctx_new(fd, lctx->thrmgr, lctx->spec, lctx->global, lctx->clisock);
pxy_conn_ctx_t *ctx = proxy_conn_ctx_new(fd, lctx->thrmgr, lctx->spec, lctx->global
#ifndef WITHOUT_USERAUTH
, lctx->clisock
#endif /* !WITHOUT_USERAUTH */
);
if (!ctx) {
log_err_level_printf(LOG_CRIT, "Error allocating ctx memory\n");
evutil_closesocket(fd);
@ -319,7 +328,9 @@ proxy_listener_setup(struct event_base *evbase, pxy_thrmgr_ctx_t *thrmgr,
return NULL;
}
#ifndef WITHOUT_USERAUTH
lctx->clisock = clisock;
#endif /* !WITHOUT_USERAUTH */
// @attention Do not pass NULL as user-supplied pointer
lctx->evcl = evconnlistener_new(evbase, proxy_listener_acceptcb,
@ -490,8 +501,10 @@ proxy_new(global_t *global, int clisock)
goto leave4;
evtimer_add(ctx->gcev, &gc_delay);
// @attention Do not close privsep sock, we use it to update user atime
//privsep_client_close(clisock);
// @attention Do not close privsep sock if the USERAUTH feature is compiled in, we use it to update user atime
#ifdef WITHOUT_USERAUTH
privsep_client_close(clisock);
#endif /* !WITHOUT_USERAUTH */
return ctx;
leave4:

@ -44,7 +44,9 @@ typedef struct proxy_listener_ctx {
pxy_thrmgr_ctx_t *thrmgr;
proxyspec_t *spec;
global_t *global;
#ifndef WITHOUT_USERAUTH
evutil_socket_t clisock;
#endif /* !WITHOUT_USERAUTH */
struct evconnlistener *evcl;
struct proxy_listener_ctx *next;
} proxy_listener_ctx_t;
@ -55,7 +57,11 @@ void proxy_loopbreak(proxy_ctx_t *, int) NONNULL(1);
void proxy_free(proxy_ctx_t *) NONNULL(1);
void proxy_listener_errorcb(struct evconnlistener *, UNUSED void *);
pxy_conn_ctx_t *proxy_conn_ctx_new(evutil_socket_t, pxy_thrmgr_ctx_t *, proxyspec_t *, global_t *, evutil_socket_t) MALLOC NONNULL(2,3,4);
pxy_conn_ctx_t *proxy_conn_ctx_new(evutil_socket_t, pxy_thrmgr_ctx_t *, proxyspec_t *, global_t *
#ifndef WITHOUT_USERAUTH
, evutil_socket_t
#endif /* !WITHOUT_USERAUTH */
) MALLOC NONNULL(2,3,4);
#endif /* !PROXY_H */
/* vim: set noet ft=c: */

@ -309,6 +309,7 @@ pxy_conn_ctx_free(pxy_conn_ctx_t *ctx, int by_requestor)
}
}
#ifndef WITHOUT_USERAUTH
if (ctx->spec->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
unsigned int idletime = ctx->idletime + (time(NULL) - ctx->ctime);
@ -330,6 +331,7 @@ pxy_conn_ctx_free(pxy_conn_ctx_t *ctx, int by_requestor)
log_finest_va("Will not update user atime, idletime=%u", idletime);
}
}
#endif /* !WITHOUT_USERAUTH */
pxy_thr_detach(ctx);
@ -368,6 +370,7 @@ pxy_conn_ctx_free(pxy_conn_ctx_t *ctx, int by_requestor)
}
free(ctx->protoctx);
#ifndef WITHOUT_USERAUTH
if (ctx->user) {
free(ctx->user);
}
@ -377,6 +380,7 @@ pxy_conn_ctx_free(pxy_conn_ctx_t *ctx, int by_requestor)
if (ctx->desc) {
free(ctx->desc);
}
#endif /* !WITHOUT_USERAUTH */
free(ctx);
}
@ -454,16 +458,22 @@ pxy_log_connect_nonhttp(pxy_conn_ctx_t *ctx)
#ifdef HAVE_LOCAL_PROCINFO
" %s"
#endif /* HAVE_LOCAL_PROCINFO */
" user:%s\n",
#ifndef WITHOUT_USERAUTH
" user:%s"
#endif /* !WITHOUT_USERAUTH */
"\n",
ctx->proto == PROTO_PASSTHROUGH ? "passthrough" : (ctx->proto == PROTO_POP3 ? "pop3" : (ctx->proto == PROTO_SMTP ? "smtp" : "tcp")),
STRORDASH(ctx->srchost_str),
STRORDASH(ctx->srcport_str),
STRORDASH(ctx->dsthost_str),
STRORDASH(ctx->dstport_str),
STRORDASH(ctx->dstport_str)
#ifdef HAVE_LOCAL_PROCINFO
lpi,
, lpi
#endif /* HAVE_LOCAL_PROCINFO */
STRORDASH(ctx->user));
#ifndef WITHOUT_USERAUTH
, STRORDASH(ctx->user)
#endif /* !WITHOUT_USERAUTH */
);
} else {
rv = asprintf(&msg, "CONN: %s %s %s %s %s "
"sni:%s names:%s "
@ -472,7 +482,10 @@ pxy_log_connect_nonhttp(pxy_conn_ctx_t *ctx)
#ifdef HAVE_LOCAL_PROCINFO
" %s"
#endif /* HAVE_LOCAL_PROCINFO */
" user:%s\n",
#ifndef WITHOUT_USERAUTH
" user:%s"
#endif /* !WITHOUT_USERAUTH */
"\n",
ctx->proto == PROTO_AUTOSSL ? "autossl" : (ctx->proto == PROTO_POP3S ? "pop3s" : (ctx->proto == PROTO_SMTPS ? "smtps" : "ssl")),
STRORDASH(ctx->srchost_str),
STRORDASH(ctx->srcport_str),
@ -485,11 +498,14 @@ pxy_log_connect_nonhttp(pxy_conn_ctx_t *ctx)
STRORDASH(ctx->sslctx->srvdst_ssl_version),
STRORDASH(ctx->sslctx->srvdst_ssl_cipher),
STRORDASH(ctx->sslctx->origcrtfpr),
STRORDASH(ctx->sslctx->usedcrtfpr),
STRORDASH(ctx->sslctx->usedcrtfpr)
#ifdef HAVE_LOCAL_PROCINFO
lpi,
, lpi
#endif /* HAVE_LOCAL_PROCINFO */
STRORDASH(ctx->user));
#ifndef WITHOUT_USERAUTH
, STRORDASH(ctx->user)
#endif /* !WITHOUT_USERAUTH */
);
}
if ((rv < 0) || !msg) {
ctx->enomem = 1;
@ -1152,16 +1168,22 @@ pxy_setup_child_listener(pxy_conn_ctx_t *ctx)
return -1;
}
#ifndef WITHOUT_USERAUTH
int user_len = 0;
if (ctx->spec->opts->user_auth && ctx->user) {
// +1 for comma
user_len = strlen(ctx->user) + 1;
}
#endif /* !WITHOUT_USERAUTH */
// SSLproxy: [127.0.0.1]:34649,[192.168.3.24]:47286,[74.125.206.108]:465,s,soner
// SSLproxy: + + [ + addr + ] + : + p + , + [ + srchost_str + ] + : + srcport_str + , + [ + dsthost_str + ] + : + dstport_str + , + s + , + user
// SSLPROXY_KEY_LEN + 1 + 1 + strlen(addr) + 1 + 1 + port_len + 1 + 1 + strlen(ctx->srchost_str) + 1 + 1 + strlen(ctx->srcport_str) + 1 + 1 + strlen(ctx->dsthost_str) + 1 + 1 + strlen(ctx->dstport_str) + 1 + 1 + user_len
ctx->sslproxy_header_len = SSLPROXY_KEY_LEN + strlen(addr) + port_len + strlen(ctx->srchost_str) + strlen(ctx->srcport_str) + strlen(ctx->dsthost_str) + strlen(ctx->dstport_str) + 14 + user_len;
ctx->sslproxy_header_len = SSLPROXY_KEY_LEN + strlen(addr) + port_len + strlen(ctx->srchost_str) + strlen(ctx->srcport_str) + strlen(ctx->dsthost_str) + strlen(ctx->dstport_str) + 14
#ifndef WITHOUT_USERAUTH
+ user_len
#endif /* !WITHOUT_USERAUTH */
;
// +1 for NULL
ctx->sslproxy_header = malloc(ctx->sslproxy_header_len + 1);
@ -1172,9 +1194,17 @@ pxy_setup_child_listener(pxy_conn_ctx_t *ctx)
// printf(3): "snprintf() will write at most size-1 of the characters (the size'th character then gets the terminating NULL)"
// So, +1 for NULL
if (snprintf(ctx->sslproxy_header, ctx->sslproxy_header_len + 1, "%s [%s]:%u,[%s]:%s,[%s]:%s,%s%s%s",
if (snprintf(ctx->sslproxy_header, ctx->sslproxy_header_len + 1, "%s [%s]:%u,[%s]:%s,[%s]:%s,%s"
#ifndef WITHOUT_USERAUTH
"%s%s"
#endif /* !WITHOUT_USERAUTH */
,
SSLPROXY_KEY, addr, port, STRORNONE(ctx->srchost_str), STRORNONE(ctx->srcport_str),
STRORNONE(ctx->dsthost_str), STRORNONE(ctx->dstport_str), ctx->spec->ssl ? "s":"p", user_len ? "," : "", user_len ? ctx->user : "") < 0) {
STRORNONE(ctx->dsthost_str), STRORNONE(ctx->dstport_str), ctx->spec->ssl ? "s":"p"
#ifndef WITHOUT_USERAUTH
, user_len ? "," : "", user_len ? ctx->user : ""
#endif /* !WITHOUT_USERAUTH */
) < 0) {
// ctx->sslproxy_header is freed by pxy_conn_ctx_free()
pxy_conn_term(ctx, 1);
return -1;
@ -1547,6 +1577,7 @@ pxy_conn_connect(pxy_conn_ctx_t *ctx)
}
}
#ifndef WITHOUT_USERAUTH
#if defined(__OpenBSD__) || defined(__linux__)
static void
identify_user(UNUSED evutil_socket_t fd, UNUSED short what, void *arg)
@ -1816,6 +1847,7 @@ pxy_userauth(pxy_conn_ctx_t *ctx)
}
return 0;
}
#endif /* !WITHOUT_USERAUTH */
int
pxy_conn_init(pxy_conn_ctx_t *ctx)

@ -52,7 +52,9 @@
#define SSLPROXY_KEY "SSLproxy:"
#define SSLPROXY_KEY_LEN strlen(SSLPROXY_KEY)
#ifndef WITHOUT_USERAUTH
#define USERAUTH_MSG "You must authenticate to access the Internet at %s\r\n"
#endif /* !WITHOUT_USERAUTH */
#define PROTOERROR_MSG "Connection is terminated due to protocol error\r\n"
#define PROTOERROR_MSG_LEN strlen(PROTOERROR_MSG)
@ -250,8 +252,10 @@ struct pxy_conn_ctx {
evutil_socket_t dst_fd;
evutil_socket_t srvdst_fd;
#ifndef WITHOUT_USERAUTH
// Privsep socket to update user atime
evutil_socket_t clisock;
#endif /* !WITHOUT_USERAUTH */
// fd of event listener for children, explicitly closed on error (not for stats only)
evutil_socket_t child_fd;
@ -289,6 +293,7 @@ struct pxy_conn_ctx {
// Expired conns are link-listed using this pointer, a temporary list used in conn thr timercb only
pxy_conn_ctx_t *next_expired;
#ifndef WITHOUT_USERAUTH
// Number of times we try to acquire user db before giving up
unsigned int identify_user_count;
// User owner of conn
@ -301,6 +306,7 @@ struct pxy_conn_ctx {
char *desc;
// We send redirect/error msg to client if user auth or proto validation fails
unsigned int sent_userauth_msg : 1; /* 1 until error msg is sent */
#endif /* !WITHOUT_USERAUTH */
unsigned int sent_protoerror_msg : 1; /* 1 until error msg is sent */
#ifdef HAVE_LOCAL_PROCINFO
@ -400,7 +406,9 @@ void pxy_bev_writecb_child(struct bufferevent *, void *);
void pxy_bev_eventcb_child(struct bufferevent *, short, void *);
void pxy_conn_connect(pxy_conn_ctx_t *) NONNULL(1);
#ifndef WITHOUT_USERAUTH
int pxy_userauth(pxy_conn_ctx_t *) NONNULL(1);
#endif /* !WITHOUT_USERAUTH */
void pxy_conn_setup(evutil_socket_t, struct sockaddr *, int,
pxy_thrmgr_ctx_t *, proxyspec_t *, global_t *,
evutil_socket_t)

@ -132,18 +132,33 @@ pxy_thr_get_expired_conns(pxy_thr_ctx_t *tctx, pxy_conn_ctx_t **expired_conns)
time_t atime = now - ctx->atime;
time_t ctime = now - ctx->ctime;
#ifndef WITHOUT_USERAUTH
log_finest_main_va("thr=%d, id=%llu, fd=%d, child_fd=%d, dst=%d, srvdst=%d, child_src=%d, child_dst=%d, p=%d-%d-%d c=%d-%d, ce=%d cc=%d, at=%lld ct=%lld, src_addr=%s:%s, dst_addr=%s:%s, user=%s, valid=%d",
tctx->id, ctx->id, ctx->fd, ctx->child_fd, ctx->dst_fd, ctx->srvdst_fd, ctx->child_src_fd, ctx->child_dst_fd,
ctx->src.closed, ctx->dst.closed, ctx->srvdst.closed, ctx->children ? ctx->children->src.closed : 0, ctx->children ? ctx->children->dst.closed : 0,
ctx->children ? 1:0, ctx->child_count, (long long)atime, (long long)ctime,
STRORDASH(ctx->srchost_str), STRORDASH(ctx->srcport_str), STRORDASH(ctx->dsthost_str), STRORDASH(ctx->dstport_str),
STRORDASH(ctx->user), ctx->protoctx->is_valid);
#else /* WITHOUT_USERAUTH */
log_finest_main_va("thr=%d, id=%llu, fd=%d, child_fd=%d, dst=%d, srvdst=%d, child_src=%d, child_dst=%d, p=%d-%d-%d c=%d-%d, ce=%d cc=%d, at=%lld ct=%lld, src_addr=%s:%s, dst_addr=%s:%s, valid=%d",
tctx->id, ctx->id, ctx->fd, ctx->child_fd, ctx->dst_fd, ctx->srvdst_fd, ctx->child_src_fd, ctx->child_dst_fd,
ctx->src.closed, ctx->dst.closed, ctx->srvdst.closed, ctx->children ? ctx->children->src.closed : 0, ctx->children ? ctx->children->dst.closed : 0,
ctx->children ? 1:0, ctx->child_count, (long long)atime, (long long)ctime,
STRORDASH(ctx->srchost_str), STRORDASH(ctx->srcport_str), STRORDASH(ctx->dsthost_str), STRORDASH(ctx->dstport_str), ctx->protoctx->is_valid);
#endif /* WITHOUT_USERAUTH */
char *msg;
if (asprintf(&msg, "EXPIRED: atime=%lld, ctime=%lld, src_addr=%s:%s, dst_addr=%s:%s, user=%s, valid=%d\n",
if (asprintf(&msg, "EXPIRED: atime=%lld, ctime=%lld, src_addr=%s:%s, dst_addr=%s:%s, "
#ifndef WITHOUT_USERAUTH
"user=%s, "
#endif /* !WITHOUT_USERAUTH */
"valid=%d\n",
(long long)atime, (long long)ctime,
STRORDASH(ctx->srchost_str), STRORDASH(ctx->srcport_str), STRORDASH(ctx->dsthost_str), STRORDASH(ctx->dstport_str),
STRORDASH(ctx->user), ctx->protoctx->is_valid) < 0) {
#ifndef WITHOUT_USERAUTH
STRORDASH(ctx->user),
#endif /* !WITHOUT_USERAUTH */
ctx->protoctx->is_valid) < 0) {
break;
}
@ -191,19 +206,35 @@ pxy_thr_print_info(pxy_thr_ctx_t *tctx)
time_t atime = now - ctx->atime;
time_t ctime = now - ctx->ctime;
#ifndef WITHOUT_USERAUTH
log_finest_main_va("PARENT CONN: thr=%d, id=%llu, fd=%d, child_fd=%d, dst=%d, srvdst=%d, child_src=%d, child_dst=%d, p=%d-%d-%d c=%d-%d, ce=%d cc=%d, at=%lld ct=%lld, src_addr=%s:%s, dst_addr=%s:%s, user=%s, valid=%d",
tctx->id, ctx->id, ctx->fd, ctx->child_fd, ctx->dst_fd, ctx->srvdst_fd, ctx->child_src_fd, ctx->child_dst_fd,
ctx->src.closed, ctx->dst.closed, ctx->srvdst.closed, ctx->children ? ctx->children->src.closed : 0, ctx->children ? ctx->children->dst.closed : 0,
ctx->children ? 1:0, ctx->child_count, (long long)atime, (long long)ctime,
STRORDASH(ctx->srchost_str), STRORDASH(ctx->srcport_str), STRORDASH(ctx->dsthost_str), STRORDASH(ctx->dstport_str),
STRORDASH(ctx->user), ctx->protoctx->is_valid);
#else /* WITHOUT_USERAUTH */
log_finest_main_va("PARENT CONN: thr=%d, id=%llu, fd=%d, child_fd=%d, dst=%d, srvdst=%d, child_src=%d, child_dst=%d, p=%d-%d-%d c=%d-%d, ce=%d cc=%d, at=%lld ct=%lld, src_addr=%s:%s, dst_addr=%s:%s, valid=%d",
tctx->id, ctx->id, ctx->fd, ctx->child_fd, ctx->dst_fd, ctx->srvdst_fd, ctx->child_src_fd, ctx->child_dst_fd,
ctx->src.closed, ctx->dst.closed, ctx->srvdst.closed, ctx->children ? ctx->children->src.closed : 0, ctx->children ? ctx->children->dst.closed : 0,
ctx->children ? 1:0, ctx->child_count, (long long)atime, (long long)ctime,
STRORDASH(ctx->srchost_str), STRORDASH(ctx->srcport_str), STRORDASH(ctx->dsthost_str), STRORDASH(ctx->dstport_str),
ctx->protoctx->is_valid);
#endif /* WITHOUT_USERAUTH */
// @attention Report idle connections only, i.e. the conns which have been idle since the last time we checked for expired conns
if (atime >= (time_t)tctx->thrmgr->global->expired_conn_check_period) {
if (asprintf(&smsg, "IDLE: atime=%lld, ctime=%lld, src_addr=%s:%s, dst_addr=%s:%s, user=%s, valid=%d\n",
if (asprintf(&smsg, "IDLE: atime=%lld, ctime=%lld, src_addr=%s:%s, dst_addr=%s:%s, "
#ifndef WITHOUT_USERAUTH
"user=%s, "
#endif /* !WITHOUT_USERAUTH */
"valid=%d\n",
(long long)atime, (long long)ctime,
STRORDASH(ctx->srchost_str), STRORDASH(ctx->srcport_str), STRORDASH(ctx->dsthost_str), STRORDASH(ctx->dstport_str),
STRORDASH(ctx->user), ctx->protoctx->is_valid) < 0) {
#ifndef WITHOUT_USERAUTH
STRORDASH(ctx->user),
#endif /* !WITHOUT_USERAUTH */
ctx->protoctx->is_valid) < 0) {
return;
}
if (log_conn(smsg) == -1) {

@ -69,8 +69,10 @@ typedef struct pxy_thr_ctx {
// List of active connections on the thread
pxy_conn_ctx_t *conns;
#ifndef WITHOUT_USERAUTH
// Per-thread sqlite stmt is necessary to prevent multithreading issues between threads
struct sqlite3_stmt *get_user;
#endif /* !WITHOUT_USERAUTH */
} pxy_thr_ctx_t;
void pxy_thr_attach(pxy_conn_ctx_t *) NONNULL(1);

@ -106,11 +106,13 @@ pxy_thrmgr_run(pxy_thrmgr_ctx_t *ctx)
ctx->thr[i]->timeout_count = 0;
ctx->thr[i]->thrmgr = ctx;
#ifndef WITHOUT_USERAUTH
if ((ctx->global->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)) {
log_err_level_printf(LOG_CRIT, "Error preparing get_user sql stmt: %s\n", sqlite3_errmsg(ctx->global->userdb));
goto leave;
}
#endif /* !WITHOUT_USERAUTH */
}
log_dbg_printf("Initialized %d connection handling threads\n", ctx->num_thr);
@ -144,10 +146,12 @@ leave:
if (ctx->thr[i]->evbase) {
event_base_free(ctx->thr[i]->evbase);
}
#ifndef WITHOUT_USERAUTH
if (ctx->global->userdb) {
// sqlite3.h: "Invoking sqlite3_finalize() on a NULL pointer is a harmless no-op."
sqlite3_finalize(ctx->thr[i]->get_user);
}
#endif /* !WITHOUT_USERAUTH */
free(ctx->thr[i]);
}
i--;
@ -180,10 +184,12 @@ pxy_thrmgr_free(pxy_thrmgr_ctx_t *ctx)
if (ctx->thr[i]->evbase) {
event_base_free(ctx->thr[i]->evbase);
}
#ifndef WITHOUT_USERAUTH
if (ctx->global->userdb) {
// sqlite3.h: "Invoking sqlite3_finalize() on a NULL pointer is a harmless no-op."
sqlite3_finalize(ctx->thr[i]->get_user);
}
#endif /* !WITHOUT_USERAUTH */
free(ctx->thr[i]);
}
free(ctx->thr);

@ -619,13 +619,19 @@ START_TEST(opts_set_pass_site_01)
fail_unless(!strcmp(opts->passsites->site, "/example.com/"), "site not /example.com/");
fail_unless(!opts->passsites->ip, "ip set");
#ifndef WITHOUT_USERAUTH
fail_unless(!opts->passsites->user, "user set");
fail_unless(!opts->passsites->all, "all not 0");
fail_unless(!opts->passsites->keyword, "keyword set");
#endif /* !WITHOUT_USERAUTH */
fail_unless(!opts->passsites->next, "next set");
ps = passsite_str(opts->passsites);
#ifndef WITHOUT_USERAUTH
fail_unless(!strcmp(ps, "passsite 0: site=/example.com/,ip=,user=,keyword=,all=0"), "failed parsing passite example.com");
#else /* WITHOUT_USERAUTH */
fail_unless(!strcmp(ps, "passsite 0: site=/example.com/,ip="), "failed parsing passite example.com");
#endif /* WITHOUT_USERAUTH */
free(ps);
opts_free(opts);
@ -643,19 +649,26 @@ START_TEST(opts_set_pass_site_02)
fail_unless(!strcmp(opts->passsites->site, "/example.com/"), "site not /example.com/");
fail_unless(!strcmp(opts->passsites->ip, "192.168.0.1"), "ip not 192.168.0.1");
#ifndef WITHOUT_USERAUTH
fail_unless(!opts->passsites->user, "user set");
fail_unless(!opts->passsites->all, "all not 0");
fail_unless(!opts->passsites->keyword, "keyword set");
#endif /* !WITHOUT_USERAUTH */
fail_unless(!opts->passsites->next, "next set");
ps = passsite_str(opts->passsites);
#ifndef WITHOUT_USERAUTH
fail_unless(!strcmp(ps, "passsite 0: site=/example.com/,ip=192.168.0.1,user=,keyword=,all=0"), "failed parsing passite example.com 192.168.0.1");
#else /* WITHOUT_USERAUTH */
fail_unless(!strcmp(ps, "passsite 0: site=/example.com/,ip=192.168.0.1"), "failed parsing passite example.com 192.168.0.1");
#endif /* !WITHOUT_USERAUTH */
free(ps);
opts_free(opts);
}
END_TEST
#ifndef WITHOUT_USERAUTH
START_TEST(opts_set_pass_site_03)
{
char *ps;
@ -705,6 +718,7 @@ START_TEST(opts_set_pass_site_04)
opts_free(opts);
}
END_TEST
#endif /* !WITHOUT_USERAUTH */
START_TEST(opts_set_pass_site_05)
{
@ -724,6 +738,7 @@ START_TEST(opts_set_pass_site_05)
fail_unless(opts->passsites->next, "next not set");
fail_unless(!opts->passsites->next->next, "next->next set");
#ifndef WITHOUT_USERAUTH
opts->user_auth = 1;
// Use root user, opts_set_pass_site() calls sys_isuser() to validate the user
s = strdup("example.com root");
@ -737,8 +752,10 @@ START_TEST(opts_set_pass_site_05)
s = strdup("*.google.com * android");
opts_set_pass_site(opts, s, 3);
free(s);
#endif /* !WITHOUT_USERAUTH */
ps = passsite_str(opts->passsites);
fail_unless(opts->passsites->next, "next not set");
#ifndef WITHOUT_USERAUTH
fail_unless(opts->passsites->next->next, "next->next not set");
fail_unless(opts->passsites->next->next->next, "next->next->next not set");
fail_unless(!opts->passsites->next->next->next->next, "next->next->next->next set");
@ -747,6 +764,11 @@ START_TEST(opts_set_pass_site_05)
"passsite 2: site=/example.com/,ip=192.168.0.1,user=,keyword=,all=0\n"
"passsite 3: site=/example.com/,ip=,user=,keyword=,all=0"),
"failed parsing multiple passites");
#else /* WITHOUT_USERAUTH */
fail_unless(!strcmp(ps, "passsite 0: site=/example.com/,ip=192.168.0.1\n"
"passsite 1: site=/example.com/,ip="),
"failed parsing multiple passites");
#endif /* WITHOUT_USERAUTH */
free(ps);
opts_free(opts);
@ -930,8 +952,10 @@ opts_suite(void)
tcase_add_test(tc, opts_debug_01);
tcase_add_test(tc, opts_set_pass_site_01);
tcase_add_test(tc, opts_set_pass_site_02);
#ifndef WITHOUT_USERAUTH
tcase_add_test(tc, opts_set_pass_site_03);
tcase_add_test(tc, opts_set_pass_site_04);
#endif /* !WITHOUT_USERAUTH */
tcase_add_test(tc, opts_set_pass_site_05);
tcase_add_test(tc, opts_check_value_yes_01);
tcase_add_test(tc, opts_check_value_yes_02);

@ -71,7 +71,11 @@ proto_init(protocol_t proto)
spec->smtp = 1;
}
pxy_conn_ctx_t *ctx = proxy_conn_ctx_new(0, thrmgr, spec, global, 0);
pxy_conn_ctx_t *ctx = proxy_conn_ctx_new(0, thrmgr, spec, global
#ifndef WITHOUT_USERAUTH
, 0
#endif /* !WITHOUT_USERAUTH */
);
pxy_thrmgr_assign_thr(ctx);
pxy_thr_attach(ctx);

@ -33,7 +33,6 @@
#include <sys/types.h>
#include <sys/socket.h>
#include <sqlite3.h>
/*
* Print helper for logging code.

Loading…
Cancel
Save