Only init DNS when DNS is required by proxy specs

Only initialize evdns if DNS lookups are actually required by the loaded
proxy specifications.  This allows sslsplit to work in non-DNS modes in
situations where the local DNS resolver does not work, such as for local
use on a system without network connectivity.  Currently, only SNI based
proxy specs require DNS.  On systems without network connectivity, DNS
subsystem init may fail due to /etc/resolv.conf being (temporarily)
unavailable.

Issue:		#104
pull/13/head
Daniel Roethlisberger 9 years ago
parent 0d38bca4e0
commit 0e2b748bba

@ -1,6 +1,8 @@
### SSLsplit develop
- Only initialize DNS subsystems when DNS lookups are actually needed by the
loaded proxy specifications (related to issue #104).
- Fix build with LibreSSL that lacks recent OpenSSL API additions.
- Fix build with OpenSSL versions that had SSLv3 support removed.
- Warn when an OpenSSL version mismatch is detected (issue #88).

@ -131,6 +131,23 @@ opts_has_ssl_spec(opts_t *opts)
return 0;
}
/*
* Return 1 if opts_t contains a proxyspec with dns, 0 otherwise.
*/
int
opts_has_dns_spec(opts_t *opts)
{
proxyspec_t *p = opts->spec;
while (p) {
if (p->dns)
return 1;
p = p->next;
}
return 0;
}
/*
* Parse SSL proto string in optarg and look up the corresponding SSL method.
* Calls exit() on failure.
@ -398,6 +415,7 @@ proxyspec_parse(int *argc, char **argv[], const char *natengine)
**argv);
exit(EXIT_FAILURE);
}
spec->dns = 1;
state = 0;
break;
}

@ -39,6 +39,7 @@
typedef struct proxyspec {
unsigned int ssl : 1;
unsigned int http : 1;
unsigned int dns : 1; /* set if spec needs DNS lookups */
struct sockaddr_storage listen_addr;
socklen_t listen_addrlen;
/* connect_addr and connect_addrlen are set: static mode;
@ -107,6 +108,7 @@ typedef struct opts {
opts_t *opts_new(void) MALLOC;
void opts_free(opts_t *) NONNULL(1);
int opts_has_ssl_spec(opts_t *) NONNULL(1) WUNRES;
int opts_has_dns_spec(opts_t *) NONNULL(1) WUNRES;
void opts_proto_force(opts_t *, const char *, const char *) NONNULL(1,2,3);
void opts_proto_disable(opts_t *, const char *, const char *) NONNULL(1,2,3);
void opts_proto_dbg_dump(opts_t *) NONNULL(1);

@ -279,26 +279,29 @@ proxy_new(opts_t *opts, int clisock)
goto leave1;
}
/* create a dnsbase here purely for being able to test parsing
* resolv.conf while we can still alert the user about it. */
dnsbase = evdns_base_new(ctx->evbase, 0);
if (!dnsbase) {
log_err_printf("Error creating dns event base\n");
goto leave1b;
}
rc = evdns_base_resolv_conf_parse(dnsbase, DNS_OPTIONS_ALL,
"/etc/resolv.conf");
evdns_base_free(dnsbase, 0);
if (rc != 0) {
log_err_printf("evdns cannot parse resolv.conf: %s (%d)\n",
rc == 1 ? "failed to open file" :
rc == 2 ? "failed to stat file" :
rc == 3 ? "file too large" :
rc == 4 ? "out of memory" :
rc == 5 ? "short read from file" :
rc == 6 ? "no nameservers listed in file" :
"unknown error", rc);
goto leave1b;
if (opts_has_dns_spec(opts)) {
/* create a dnsbase here purely for being able to test parsing
* resolv.conf while we can still alert the user about it. */
dnsbase = evdns_base_new(ctx->evbase, 0);
if (!dnsbase) {
log_err_printf("Error creating dns event base\n");
goto leave1b;
}
rc = evdns_base_resolv_conf_parse(dnsbase, DNS_OPTIONS_ALL,
"/etc/resolv.conf");
evdns_base_free(dnsbase, 0);
if (rc != 0) {
log_err_printf("evdns cannot parse resolv.conf: "
"%s (%d)\n",
rc == 1 ? "failed to open file" :
rc == 2 ? "failed to stat file" :
rc == 3 ? "file too large" :
rc == 4 ? "out of memory" :
rc == 5 ? "short read from file" :
rc == 6 ? "no nameservers in file" :
"unknown error", rc);
goto leave1b;
}
}
if (OPTS_DEBUG(opts)) {

@ -52,6 +52,7 @@ typedef struct pxy_thr_ctx {
struct pxy_thrmgr_ctx {
int num_thr;
opts_t *opts;
pxy_thr_ctx_t **thr;
pthread_mutex_t mutex;
};
@ -94,7 +95,7 @@ pxy_thrmgr_thr(void *arg)
* This gets called before forking to background.
*/
pxy_thrmgr_ctx_t *
pxy_thrmgr_new(UNUSED opts_t *opts)
pxy_thrmgr_new(opts_t *opts)
{
pxy_thrmgr_ctx_t *ctx;
@ -102,6 +103,7 @@ pxy_thrmgr_new(UNUSED opts_t *opts)
return NULL;
memset(ctx, 0, sizeof(pxy_thrmgr_ctx_t));
ctx->opts = opts;
ctx->num_thr = 2 * sys_get_cpu_cores();
return ctx;
}
@ -115,11 +117,13 @@ pxy_thrmgr_new(UNUSED opts_t *opts)
int
pxy_thrmgr_run(pxy_thrmgr_ctx_t *ctx)
{
int idx = -1;
int idx = -1, dns = 0;
if (!ctx)
return -1;
dns = opts_has_dns_spec(ctx->opts);
pthread_mutex_init(&ctx->mutex, NULL);
if (!(ctx->thr = malloc(ctx->num_thr * sizeof(pxy_thr_ctx_t*)))) {
@ -139,11 +143,15 @@ pxy_thrmgr_run(pxy_thrmgr_ctx_t *ctx)
log_dbg_printf("Failed to create evbase %d\n", idx);
goto leave;
}
ctx->thr[idx]->dnsbase = evdns_base_new(
ctx->thr[idx]->evbase, 1);
if (!ctx->thr[idx]->dnsbase) {
log_dbg_printf("Failed to create dnsbase %d\n", idx);
goto leave;
if (dns) {
/* only create dns base if we actually need it later */
ctx->thr[idx]->dnsbase = evdns_base_new(
ctx->thr[idx]->evbase, 1);
if (!ctx->thr[idx]->dnsbase) {
log_dbg_printf("Failed to create dnsbase %d\n",
idx);
goto leave;
}
}
ctx->thr[idx]->load = 0;
ctx->thr[idx]->running = 0;

Loading…
Cancel
Save