"Fossies" - the Fresh Open Source Software Archive  

Source code changes of the file "src/hitch.c" between
hitch-1.6.1.tar.gz and hitch-1.7.0.tar.gz

About: Hitch is a libev-based high performance SSL/TLS proxy that terminates TLS/SSL connections and forwards the unencrypted traffic to some backend.

hitch.c  (hitch-1.6.1):hitch.c  (hitch-1.7.0)
skipping to change at line 205 skipping to change at line 205
VTAILQ_HEAD(listen_sock_head, listen_sock); VTAILQ_HEAD(listen_sock_head, listen_sock);
struct frontend { struct frontend {
unsigned magic; unsigned magic;
#define FRONTEND_MAGIC 0x5b04e577 #define FRONTEND_MAGIC 0x5b04e577
int match_global_certs; int match_global_certs;
int sni_nomatch_abort; int sni_nomatch_abort;
struct sni_name_s *sni_names; struct sni_name_s *sni_names;
struct sslctx_s *ssl_ctxs; struct sslctx_s *ssl_ctxs;
struct sslctx_s *default_ctx; struct sslctx_s *default_ctx;
char *pspec; const struct front_arg *arg;
struct addrinfo *addrs;
struct listen_sock_head socks; struct listen_sock_head socks;
VTAILQ_ENTRY(frontend) list; VTAILQ_ENTRY(frontend) list;
}; };
VTAILQ_HEAD(frontend_head, frontend); VTAILQ_HEAD(frontend_head, frontend);
static struct frontend_head frontends; static struct frontend_head frontends;
#ifdef USE_SHARED_CACHE #ifdef USE_SHARED_CACHE
static ev_io shcupd_listener; static ev_io shcupd_listener;
static int shcupd_socket; static int shcupd_socket;
struct addrinfo *shcupd_peers[MAX_SHCUPD_PEERS+1]; struct addrinfo *shcupd_peers[MAX_SHCUPD_PEERS+1];
static unsigned char shared_secret[SHA_DIGEST_LENGTH]; static unsigned char shared_secret[SHA_DIGEST_LENGTH];
#endif /*USE_SHARED_CACHE*/ #endif /*USE_SHARED_CACHE*/
int create_workers; int create_workers;
static struct vpf_fh *pfh = NULL; static struct vpf_fh *pfh = NULL;
static char tcp_proxy_line[128] = "";
/* What agent/state requests the shutdown--for proper half-closed /* What agent/state requests the shutdown--for proper half-closed
* handling */ * handling */
typedef enum _SHUTDOWN_REQUESTOR { typedef enum _SHUTDOWN_REQUESTOR {
SHUTDOWN_HARD, SHUTDOWN_HARD,
SHUTDOWN_CLEAR, SHUTDOWN_CLEAR,
SHUTDOWN_SSL SHUTDOWN_SSL
} SHUTDOWN_REQUESTOR; } SHUTDOWN_REQUESTOR;
static const char *SHUTDOWN_STR[] = { static const char *SHUTDOWN_STR[] = {
[SHUTDOWN_HARD] = "SHUTDOWN_HARD", [SHUTDOWN_HARD] = "SHUTDOWN_HARD",
skipping to change at line 323 skipping to change at line 322
dh = PEM_read_bio_DHparams(bio, NULL, NULL, NULL); dh = PEM_read_bio_DHparams(bio, NULL, NULL, NULL);
BIO_free(bio); BIO_free(bio);
if (!dh) { if (!dh) {
LOG("{core} Note: no DH parameters found in %s\n", cert); LOG("{core} Note: no DH parameters found in %s\n", cert);
return (-1); return (-1);
} }
LOG("{core} Using DH parameters from %s\n", cert); LOG("{core} Using DH parameters from %s\n", cert);
if (!SSL_CTX_set_tmp_dh(ctx, dh)) { if (!SSL_CTX_set_tmp_dh(ctx, dh)) {
DH_free(dh);
log_ssl_error(NULL, "{core} Error setting temp DH params"); log_ssl_error(NULL, "{core} Error setting temp DH params");
return (-1); return (-1);
} }
LOG("{core} DH initialized with %d bit key\n", 8*DH_size(dh)); LOG("{core} DH initialized with %d bit key\n", 8*DH_size(dh));
DH_free(dh); DH_free(dh);
return (0); return (0);
} }
static int init_ecdh(SSL_CTX *ctx, const char *ecdh_curve) { static int init_ecdh(SSL_CTX *ctx, const char *ecdh_curve) {
#ifndef OPENSSL_NO_EC #ifndef OPENSSL_NO_EC
skipping to change at line 1406 skipping to change at line 1406
VTAILQ_REMOVE(&fr->socks, ls, list); VTAILQ_REMOVE(&fr->socks, ls, list);
destroy_lsock(ls); destroy_lsock(ls);
} }
HASH_ITER(hh, fr->ssl_ctxs, sc, sctmp) { HASH_ITER(hh, fr->ssl_ctxs, sc, sctmp) {
HASH_DEL(fr->ssl_ctxs, sc); HASH_DEL(fr->ssl_ctxs, sc);
sctx_free(sc, &fr->sni_names); sctx_free(sc, &fr->sni_names);
} }
AZ(HASH_COUNT(fr->sni_names)); AZ(HASH_COUNT(fr->sni_names));
free(fr->pspec);
FREE_OBJ(fr); FREE_OBJ(fr);
} }
/* Create the bound socket in the parent process */ /* Create the bound socket in the parent process */
static int static int
frontend_listen(const struct front_arg *fa, struct listen_sock_head *slist) frontend_listen(const struct front_arg *fa, struct frontend *fr)
{ {
struct addrinfo *ai, hints, *it; struct addrinfo *ai, hints, *it;
struct listen_sock *ls, *lstmp; struct listen_sock *ls, *lstmp;
struct listen_sock_head *slist;
char buf[INET6_ADDRSTRLEN+20]; char buf[INET6_ADDRSTRLEN+20];
char abuf[INET6_ADDRSTRLEN]; char abuf[INET6_ADDRSTRLEN];
char pbuf[8]; char pbuf[8];
int r, count = 0; int r, count = 0;
CHECK_OBJ_NOTNULL(fa, FRONT_ARG_MAGIC); CHECK_OBJ_NOTNULL(fa, FRONT_ARG_MAGIC);
memset(&hints, 0, sizeof hints); CHECK_OBJ_NOTNULL(fr, FRONTEND_MAGIC);
hints.ai_family = AF_UNSPEC; slist = &fr->socks;
hints.ai_socktype = SOCK_STREAM;
hints.ai_flags = AI_PASSIVE | AI_ADDRCONFIG; ai = fr->addrs;
r = getaddrinfo(fa->ip, fa->port, if (ai == NULL) {
&hints, &ai); memset(&hints, 0, sizeof hints);
if (r != 0) { hints.ai_family = AF_UNSPEC;
ERR("{getaddrinfo-listen}: %s: %s\n", fa->pspec, hints.ai_socktype = SOCK_STREAM;
gai_strerror(r)); hints.ai_flags = AI_PASSIVE | AI_ADDRCONFIG;
return (-1); r = getaddrinfo(fa->ip, fa->port,
&hints, &ai);
if (r != 0) {
ERR("{getaddrinfo-listen}: %s: %s\n", fa->pspec,
gai_strerror(r));
return (-1);
}
} }
for (it = ai; it != NULL; it = it->ai_next) { for (it = ai; it != NULL; it = it->ai_next) {
ALLOC_OBJ(ls, LISTEN_SOCK_MAGIC); ALLOC_OBJ(ls, LISTEN_SOCK_MAGIC);
VTAILQ_INSERT_TAIL(slist, ls, list); VTAILQ_INSERT_TAIL(slist, ls, list);
count++; count++;
ls->sock = socket(it->ai_family, SOCK_STREAM, IPPROTO_TCP); ls->sock = socket(it->ai_family, SOCK_STREAM, IPPROTO_TCP);
if (ls->sock == -1) { if (ls->sock == -1) {
ERR("{socket: main}: %s: %s\n", strerror(errno), ERR("{socket: main}: %s: %s\n", strerror(errno),
skipping to change at line 1552 skipping to change at line 1558
goto creat_frontend_err; goto creat_frontend_err;
} }
if (it->ai_addr->sa_family == AF_INET6) { if (it->ai_addr->sa_family == AF_INET6) {
sprintf(buf, "[%s]:%s", abuf, pbuf); sprintf(buf, "[%s]:%s", abuf, pbuf);
} else { } else {
sprintf(buf, "%s:%s", abuf, pbuf); sprintf(buf, "%s:%s", abuf, pbuf);
} }
ls->name = strdup(buf); ls->name = strdup(buf);
AN(ls->name); AN(ls->name);
LOG("{core} Listening on %s\n", ls->name); if (getpid() != master_pid)
LOG("{core} Listening on %s\n", ls->name);
} }
freeaddrinfo(ai); if (fr->addrs == NULL) {
assert(getpid() == master_pid);
VTAILQ_FOREACH_SAFE(ls, slist, list, lstmp) {
VTAILQ_REMOVE(slist, ls, list);
destroy_lsock(ls);
}
fr->addrs = ai;
} else {
fr->addrs = NULL;
freeaddrinfo(ai);
}
return (count); return (count);
creat_frontend_err: creat_frontend_err:
freeaddrinfo(ai); freeaddrinfo(ai);
VTAILQ_FOREACH_SAFE(ls, slist, list, lstmp) { VTAILQ_FOREACH_SAFE(ls, slist, list, lstmp) {
VTAILQ_REMOVE(slist, ls, list); VTAILQ_REMOVE(slist, ls, list);
free(ls->name); destroy_lsock(ls);
if (ls->sock > 0)
(void) close(ls->sock);
FREE_OBJ(ls);
} }
return (-1); return (-1);
} }
static struct frontend * static struct frontend *
create_frontend(const struct front_arg *fa) create_frontend(const struct front_arg *fa)
{ {
struct frontend *fr; struct frontend *fr;
sslctx *so; sslctx *so;
int count = 0; int count = 0;
struct frontend_head tmp_list; struct frontend_head tmp_list;
struct cfg_cert_file *cf; struct cfg_cert_file *cf;
CHECK_OBJ_NOTNULL(fa, FRONT_ARG_MAGIC); CHECK_OBJ_NOTNULL(fa, FRONT_ARG_MAGIC);
ALLOC_OBJ(fr, FRONTEND_MAGIC); ALLOC_OBJ(fr, FRONTEND_MAGIC);
VTAILQ_INIT(&fr->socks); VTAILQ_INIT(&fr->socks);
AN(fr); AN(fr);
fr->pspec = strdup(fa->pspec); fr->arg = fa;
fr->match_global_certs = fa->match_global_certs; fr->match_global_certs = fa->match_global_certs;
fr->sni_nomatch_abort = fa->sni_nomatch_abort; fr->sni_nomatch_abort = fa->sni_nomatch_abort;
VTAILQ_INIT(&tmp_list); VTAILQ_INIT(&tmp_list);
count = frontend_listen(fa, &fr->socks); count = frontend_listen(fa, fr);
if (count < 0) { if (count < 0) {
destroy_frontend(fr); destroy_frontend(fr);
return (NULL); return (NULL);
} }
for (cf = fa->certs; cf != NULL; cf = cf->hh.next) { for (cf = fa->certs; cf != NULL; cf = cf->hh.next) {
so = make_ctx_fr(cf, fr, fa); so = make_ctx_fr(cf, fr, fa);
if (so == NULL) { if (so == NULL) {
destroy_frontend(fr); destroy_frontend(fr);
return (NULL); return (NULL);
skipping to change at line 2011 skipping to change at line 2025
len = strlen(val); len = strlen(val);
if (dstlen < len + 3) if (dstlen < len + 3)
return (0); return (0);
dst[0] = type; dst[0] = type;
dst[1] = (len >> 8) & 0xff; dst[1] = (len >> 8) & 0xff;
dst[2] = len & 0xff; dst[2] = len & 0xff;
memcpy(dst + 3, val, len); memcpy(dst + 3, val, len);
return (len + 3); return (len + 3);
} }
static int
proxy_tlv_cert(struct proxystate *ps, char *dst, ssize_t dstlen)
{
X509 *crt;
BIO *bio;
struct buf_mem_st bm[1];
crt = SSL_get_peer_certificate(ps->ssl);
if (crt == NULL)
return (0);
memset(bm, 0, sizeof(*bm));
/* set aside the first three bytes for PROXY tlv type and size */
bm->data = dst + 3;
bm->max = dstlen - 3;
bio = BIO_new(BIO_s_mem());
AN(bio); /* this should only fail if OOM */
BIO_set_mem_buf(bio, bm, BIO_NOCLOSE);
if (PEM_write_bio_X509_AUX(bio, crt) == 0) {
BIO_free(bio);
X509_free(crt);
log_ssl_error(ps,
"proxy-client-cert (PEM_write_bio_X509_AUX) failed");
return (0);
}
X509_free(crt);
AN(BIO_free(bio));
/* Type flag. Types 0xe0-0xef are available for custom
* application-specific use. */
dst[0] = 0xe0;
dst[1] = (bm->length >> 8) & 0xff;
dst[2] = bm->length & 0xff;
return (bm->length + 3);
}
static void static void
write_proxy_v2(proxystate *ps, const struct sockaddr *local) write_proxy_v2(proxystate *ps, const struct sockaddr *local)
{ {
struct pp2_hdr *p; struct pp2_hdr *p;
size_t len = 16, maxlen; size_t len = 16, maxlen;
char *base; char *base;
const char *tlv_tok; const char *tlv_tok;
unsigned tlv_len; unsigned tlv_len;
int i; int i;
skipping to change at line 2095 skipping to change at line 2148
if (CONFIG->PROXY_AUTHORITY) { if (CONFIG->PROXY_AUTHORITY) {
tlv_tok = SSL_get_servername(ps->ssl, tlv_tok = SSL_get_servername(ps->ssl,
TLSEXT_NAMETYPE_host_name); TLSEXT_NAMETYPE_host_name);
if (tlv_tok != NULL) { if (tlv_tok != NULL) {
tlv_len = strlen(tlv_tok); tlv_len = strlen(tlv_tok);
i = proxy_tlv_append(base + len, maxlen - len, i = proxy_tlv_append(base + len, maxlen - len,
PP2_TYPE_AUTHORITY, tlv_tok, tlv_len); PP2_TYPE_AUTHORITY, tlv_tok, tlv_len);
len += i; len += i;
} }
} }
if (CONFIG->PROXY_CLIENT_CERT)
len += proxy_tlv_cert(ps, base + len, maxlen - len);
if (CONFIG->PROXY_TLV) { if (CONFIG->PROXY_TLV) {
X509 *crt; X509 *crt;
ssize_t sz = 0; ssize_t sz = 0;
struct pp2_tlv_ssl *tlv; struct pp2_tlv_ssl *tlv;
char *tlvp = base + len; char *tlvp = base + len;
const char *tmp; const char *tmp;
tlvp[0] = PP2_TYPE_SSL; tlvp[0] = PP2_TYPE_SSL;
/* tlvp[1..2] to be updated with payload length later */ /* tlvp[1..2] to be updated with payload length later */
len += 3; len += 3;
skipping to change at line 2308 skipping to change at line 2364
/* if incoming buffer is not full */ /* if incoming buffer is not full */
if (!ringbuffer_is_full(&ps->ring_ssl2clear)) if (!ringbuffer_is_full(&ps->ring_ssl2clear))
safe_enable_io(ps, &ps->ev_r_ssl); safe_enable_io(ps, &ps->ev_r_ssl);
/* if outgoing buffer is not empty */ /* if outgoing buffer is not empty */
if (!ringbuffer_is_empty(&ps->ring_clear2ssl)) if (!ringbuffer_is_empty(&ps->ring_clear2ssl))
// not safe.. we want to resume stream even during half-closed // not safe.. we want to resume stream even during half-closed
ev_io_start(loop, &ps->ev_w_ssl); ev_io_start(loop, &ps->ev_w_ssl);
} }
static int
client_proxy_proxy2(struct proxystate *ps, BIO *b, char *buf, int c)
{
struct pp2_hdr hdr;
char *ring, *p;
int n, sz, rlen;
memcpy(&hdr, buf, c);
p = (char *) &hdr;
p += c;
n = BIO_read(b, p, PP2_HDR_LEN - c);
if (n <= 0 || n != PP2_HDR_LEN - c) {
LOG("{client} Unexpected read error in proxy-proxyv2: "
"BIO_read: %d\n", n);
shutdown_proxy(ps, SHUTDOWN_SSL);
return (1);
}
sz = ntohs(hdr.len);
AN(ringbuffer_is_empty(&ps->ring_ssl2clear));
rlen = ps->ring_ssl2clear.data_len;
if (sz + PP2_HDR_LEN > rlen) {
/* we have 32k of space, so this should relly never occur. */
LOG("{client} PROXYv2 overflow: header too long\n");
shutdown_proxy(ps, SHUTDOWN_SSL);
return (1);
}
ring = ringbuffer_write_ptr(&ps->ring_ssl2clear);
memcpy(ring, &hdr, PP2_HDR_LEN);
n = BIO_read(b, ring + PP2_HDR_LEN, sz);
if (n != sz) {
LOG("{client} proxy-proxyv2: Short read: %d\n", n);
shutdown_proxy(ps, SHUTDOWN_SSL);
return (1);
}
ringbuffer_write_append(&ps->ring_ssl2clear, n + PP2_HDR_LEN);
return (0);
}
static int
client_proxy_proxy1(struct proxystate *ps, BIO *b, char *buf, int n)
{
char *begin, *end, *p;
int t;
assert(ringbuffer_is_empty(&ps->ring_ssl2clear));
begin = ringbuffer_write_ptr(&ps->ring_ssl2clear);
/* PROXY spec says 107 bytes is the maximum size */
end = begin + 108;
memcpy(begin, buf, n);
p = begin + n;
// Copy characters one-by-one until we hit a \n or an error
while (p != end && (t = BIO_read(b, p, 1)) == 1) {
if (*p++ == '\n')
break;
}
if (p == end) {
LOG("{client} Unexpectedly long PROXY line. Malformed req?\n");
shutdown_proxy(ps, SHUTDOWN_SSL);
return (1);
} else if (t != 1) {
LOG("{client} Unexpected error reading PROXY line\n");
shutdown_proxy(ps, SHUTDOWN_SSL);
return (1);
}
ringbuffer_write_append(&ps->ring_ssl2clear,
p - begin);
return (0);
}
static void static void
client_proxy_proxy(struct ev_loop *loop, ev_io *w, int revents) client_proxy_proxy(struct ev_loop *loop, ev_io *w, int revents)
{ {
(void)revents;
int t;
char *proxy = tcp_proxy_line;
char *end = tcp_proxy_line + sizeof(tcp_proxy_line);
proxystate *ps; proxystate *ps;
BIO *b; BIO *b;
char buf[32];
int n;
(void) revents;
CAST_OBJ_NOTNULL(ps, w->data, PROXYSTATE_MAGIC); CAST_OBJ_NOTNULL(ps, w->data, PROXYSTATE_MAGIC);
b = SSL_get_rbio(ps->ssl); b = SSL_get_rbio(ps->ssl);
// Copy characters one-by-one until we hit a \n or an error /* PROXYv1: 'PROXY ' */
while (proxy != end && (t = BIO_read(b, proxy, 1)) == 1) { /* PROXYv2: PP2_SIG, (12 octets) */
if (*proxy++ == '\n')
break;
}
if (proxy == end) { n = BIO_read(b, buf, 12);
LOG("{client} Unexpectedly long PROXY line. Malformed req?"); if (n != 12) {
LOG("{client} Unexpected read error in proxy-proxyv2: "
"BIO_read: %d\n", n);
shutdown_proxy(ps, SHUTDOWN_SSL); shutdown_proxy(ps, SHUTDOWN_SSL);
} else if (t == 1) { return;
if (ringbuffer_is_full(&ps->ring_ssl2clear)) { }
LOG("{client} Error writing PROXY line");
shutdown_proxy(ps, SHUTDOWN_SSL);
return;
}
char *ring = ringbuffer_write_ptr(&ps->ring_ssl2clear);
memcpy(ring, tcp_proxy_line, proxy - tcp_proxy_line);
ringbuffer_write_append(&ps->ring_ssl2clear,
proxy - tcp_proxy_line);
// Finished reading the PROXY header
if (*(proxy - 1) == '\n') {
ev_io_stop(loop, &ps->ev_proxy);
// Start the real handshake if (memcmp(buf, "PROXY ", 6) == 0) {
start_handshake(ps, SSL_ERROR_WANT_READ); if (client_proxy_proxy1(ps, b, buf, n))
} return;
} else if (!BIO_should_retry(b)) { } else if (memcmp(buf, PP2_SIG, 12) == 0) {
LOG("{client} Unexpected error reading PROXY line"); if (client_proxy_proxy2(ps, b, buf, n))
return;
} else {
LOG("{client} Received invalid PROXY/PROXYv2 header\n");
shutdown_proxy(ps, SHUTDOWN_SSL); shutdown_proxy(ps, SHUTDOWN_SSL);
} }
ev_io_stop(loop, &ps->ev_proxy);
start_handshake(ps, SSL_ERROR_WANT_READ);
} }
/* The libev I/O handler during the OpenSSL handshake phase. Basically, just /* The libev I/O handler during the OpenSSL handshake phase. Basically, just
* let OpenSSL do what it likes with the socket and obey its requests for reads * let OpenSSL do what it likes with the socket and obey its requests for reads
* or writes */ * or writes */
static void static void
client_handshake(struct ev_loop *loop, ev_io *w, int revents) client_handshake(struct ev_loop *loop, ev_io *w, int revents)
{ {
(void)revents; (void)revents;
int t; int t;
skipping to change at line 3242 skipping to change at line 3367
openlog("hitch", LOG_CONS | LOG_PID | LOG_NDELAY, openlog("hitch", LOG_CONS | LOG_PID | LOG_NDELAY,
CONFIG->SYSLOG_FACILITY); CONFIG->SYSLOG_FACILITY);
} }
/* Forks COUNT children starting with START_INDEX. We keep a struct /* Forks COUNT children starting with START_INDEX. We keep a struct
* child_proc per child so the parent can manage it later. */ * child_proc per child so the parent can manage it later. */
void void
start_workers(int start_index, int count) start_workers(int start_index, int count)
{ {
struct worker_proc *c; struct worker_proc *c;
struct frontend *fr;
int pfd[2]; int pfd[2];
/* don't do anything if we're not allowed to create new workers */ /* don't do anything if we're not allowed to create new workers */
if (!create_workers) if (!create_workers)
return; return;
for (core_id = start_index; for (core_id = start_index;
core_id < start_index + count; core_id++) { core_id < start_index + count; core_id++) {
ALLOC_OBJ(c, WORKER_PROC_MAGIC); ALLOC_OBJ(c, WORKER_PROC_MAGIC);
AZ(pipe(pfd)); AZ(pipe(pfd));
skipping to change at line 3263 skipping to change at line 3389
c->gen = worker_gen; c->gen = worker_gen;
c->pid = fork(); c->pid = fork();
c->core_id = core_id; c->core_id = core_id;
if (c->pid == -1) { if (c->pid == -1) {
ERR("{core} fork() failed: %s; Goodbye cruel world!\n", ERR("{core} fork() failed: %s; Goodbye cruel world!\n",
strerror(errno)); strerror(errno));
exit(1); exit(1);
} else if (c->pid == 0) { /* child */ } else if (c->pid == 0) { /* child */
close(pfd[1]); close(pfd[1]);
FREE_OBJ(c); FREE_OBJ(c);
VTAILQ_FOREACH(fr, &frontends, list) {
CHECK_OBJ_NOTNULL(fr->arg, FRONT_ARG_MAGIC);
assert(frontend_listen(fr->arg, fr) > 0);
}
if (CONFIG->CHROOT && CONFIG->CHROOT[0]) if (CONFIG->CHROOT && CONFIG->CHROOT[0])
change_root(); change_root();
if (CONFIG->UID >= 0 || CONFIG->GID >= 0) if (CONFIG->UID >= 0 || CONFIG->GID >= 0)
drop_privileges(); drop_privileges();
if (!verify_privileges()) if (!verify_privileges())
_exit(1); _exit(1);
handle_connections(pfd[0]); handle_connections(pfd[0]);
exit(0); exit(0);
} else { /* parent. Track new child. */ } else { /* parent. Track new child. */
close(pfd[0]); close(pfd[0]);
skipping to change at line 3654 skipping to change at line 3784
Success: Caller calls .commit() Success: Caller calls .commit()
*/ */
static int static int
frontend_query(struct front_arg *new_set, struct cfg_tpc_obj_head *cfg_objs) frontend_query(struct front_arg *new_set, struct cfg_tpc_obj_head *cfg_objs)
{ {
struct frontend *fr; struct frontend *fr;
struct front_arg *fa, *ftmp; struct front_arg *fa, *ftmp;
struct cfg_tpc_obj *o; struct cfg_tpc_obj *o;
VTAILQ_FOREACH(fr, &frontends, list) { VTAILQ_FOREACH(fr, &frontends, list) {
HASH_FIND_STR(new_set, fr->pspec, fa); HASH_FIND_STR(new_set, fr->arg->pspec, fa);
if (fa != NULL) { if (fa != NULL) {
fa->mark = 1; fa->mark = 1;
o = make_cfg_obj(CFG_FRONTEND, CFG_TPC_KEEP, fr, NULL, o = make_cfg_obj(CFG_FRONTEND, CFG_TPC_KEEP, fr, NULL,
frontend_rollback, frontend_commit); frontend_rollback, frontend_commit);
if(cert_fr_query(fr, fa, cfg_objs) < 0) { if(cert_fr_query(fr, fa, cfg_objs) < 0) {
FREE_OBJ(o); FREE_OBJ(o);
return (-1); return (-1);
} }
} else } else
skipping to change at line 3849 skipping to change at line 3979
} }
} while (i == -1 && errno == EINTR); } while (i == -1 && errno == EINTR);
if (wu->type == WORKER_GEN) if (wu->type == WORKER_GEN)
(void)close(c->pfd); (void)close(c->pfd);
} }
} }
} }
/*
* Print Hitch's listen enpoints to a file.
* Used for testing purposes.
*/
int
listen_endpoint_print(const char *fn)
{
FILE *fp;
int n;
struct frontend *fr;
struct addrinfo *it;
char hostbuf[NI_MAXHOST];
char servbuf[NI_MAXSERV];
fp = fopen(fn, "w");
if (fp == NULL) {
perror("fopen");
return (1);
}
VTAILQ_FOREACH(fr, &frontends, list) {
for (it = fr->addrs; it != NULL; it = it->ai_next) {
if (it->ai_addr->sa_family != AF_INET)
continue;
n = getnameinfo(it->ai_addr, it->ai_addrlen,
hostbuf, sizeof(hostbuf), servbuf, sizeof(servbuf),
NI_NUMERICHOST|NI_NUMERICSERV);
AZ(n);
fprintf(fp, "%s:%s\n", hostbuf, servbuf);
}
}
fclose(fp);
return (0);
}
static void static void
reconfigure(int argc, char **argv) reconfigure(int argc, char **argv)
{ {
hitch_config *cfg_new; hitch_config *cfg_new;
struct cfg_tpc_obj_head cfg_objs; struct cfg_tpc_obj_head cfg_objs;
struct cfg_tpc_obj *cto, *cto_tmp; struct cfg_tpc_obj *cto, *cto_tmp;
struct timeval tv; struct timeval tv;
double t0, t1; double t0, t1;
struct worker_update wu; struct worker_update wu;
struct frontend *fr; struct frontend *fr;
skipping to change at line 3894 skipping to change at line 4060
return; return;
} else { } else {
VTAILQ_FOREACH_SAFE(cto, &cfg_objs, list, cto_tmp) { VTAILQ_FOREACH_SAFE(cto, &cfg_objs, list, cto_tmp) {
VTAILQ_REMOVE(&cfg_objs, cto, list); VTAILQ_REMOVE(&cfg_objs, cto, list);
AN(cto->commit); AN(cto->commit);
cto->commit(cto); cto->commit(cto);
FREE_OBJ(cto); FREE_OBJ(cto);
} }
} }
/* Rewire default sslctx for each frontend after a reload */ /* Rewire default sslctx and front_arg for each frontend after
* a reload */
VTAILQ_FOREACH(fr, &frontends, list) { VTAILQ_FOREACH(fr, &frontends, list) {
struct front_arg *fa; struct front_arg *fa;
struct cfg_cert_file *cf; struct cfg_cert_file *cf;
sslctx *sc; sslctx *sc;
HASH_FIND_STR(cfg_new->LISTEN_ARGS, fr->arg->pspec, fa);
CHECK_OBJ_NOTNULL(fa, FRONT_ARG_MAGIC);
/* rewire fr->arg: the previous value will be freed
* below when we config_destroy() the old
* configuration set. */
fr->arg = fa;
if (HASH_COUNT(fr->ssl_ctxs) == 0) { if (HASH_COUNT(fr->ssl_ctxs) == 0) {
fr->default_ctx = NULL; fr->default_ctx = NULL;
continue; continue;
} }
HASH_FIND_STR(cfg_new->LISTEN_ARGS, fr->pspec, fa);
AN(fa);
cf = fa->certs; cf = fa->certs;
CHECK_OBJ_NOTNULL(cf, CFG_CERT_FILE_MAGIC); CHECK_OBJ_NOTNULL(cf, CFG_CERT_FILE_MAGIC);
while (cf->hh.next != NULL) while (cf->hh.next != NULL)
cf = cf->hh.next; cf = cf->hh.next;
HASH_FIND_STR(fr->ssl_ctxs, cf->filename, sc); HASH_FIND_STR(fr->ssl_ctxs, cf->filename, sc);
CHECK_OBJ_NOTNULL(sc, SSLCTX_MAGIC); CHECK_OBJ_NOTNULL(sc, SSLCTX_MAGIC);
fr->default_ctx = sc; fr->default_ctx = sc;
} }
AZ(gettimeofday(&tv, NULL)); AZ(gettimeofday(&tv, NULL));
skipping to change at line 3928 skipping to change at line 4101
LOGL("{core} Config reloaded in %.2lf seconds. " LOGL("{core} Config reloaded in %.2lf seconds. "
"Starting new child processes.\n", t1 - t0); "Starting new child processes.\n", t1 - t0);
config_destroy(CONFIG); config_destroy(CONFIG);
CONFIG = cfg_new; CONFIG = cfg_new;
worker_gen++; worker_gen++;
start_workers(0, CONFIG->NCORES); start_workers(0, CONFIG->NCORES);
if (CONFIG->DEBUG_LISTEN_ADDR)
listen_endpoint_print(CONFIG->DEBUG_LISTEN_ADDR);
wu.type = WORKER_GEN; wu.type = WORKER_GEN;
wu.payload.gen = worker_gen; wu.payload.gen = worker_gen;
notify_workers(&wu); notify_workers(&wu);
if (ocsp_proc_pid > 0) { if (ocsp_proc_pid > 0) {
(void) kill(ocsp_proc_pid, SIGTERM); (void) kill(ocsp_proc_pid, SIGTERM);
/* /*
* Restarting the OCSP process is taken * Restarting the OCSP process is taken
* care of in do_wait * care of in do_wait
*/ */
skipping to change at line 3978 skipping to change at line 4154
} }
/* Process command line args, create the bound socket, /* Process command line args, create the bound socket,
* spawn child (worker) processes, and respawn if any die */ * spawn child (worker) processes, and respawn if any die */
int int
main(int argc, char **argv) main(int argc, char **argv)
{ {
// initialize configuration // initialize configuration
struct front_arg *fa, *ftmp; struct front_arg *fa, *ftmp;
master_pid = getpid();
CONFIG = config_new(); CONFIG = config_new();
// parse command line // parse command line
if (config_parse_cli(argc, argv, CONFIG) != 0) { if (config_parse_cli(argc, argv, CONFIG) != 0) {
fprintf(stderr, "%s\n", config_error_get()); fprintf(stderr, "%s\n", config_error_get());
return (1); return (1);
} }
if (CONFIG->LOG_FILENAME) { if (CONFIG->LOG_FILENAME) {
FILE* f; FILE* f;
skipping to change at line 4073 skipping to change at line 4250
"Hitch will not produce log messages.\n"); "Hitch will not produce log messages.\n");
} }
if (logfile == stdout || logfile == stderr) if (logfile == stdout || logfile == stderr)
logfile = NULL; logfile = NULL;
if (daemon(0, 0) == -1) { if (daemon(0, 0) == -1) {
ERR("Unable to daemonize: %s\n", strerror(errno)); ERR("Unable to daemonize: %s\n", strerror(errno));
exit(1); exit(1);
} }
} }
/* Reset master_pid in case we daemonized */
master_pid = getpid(); master_pid = getpid();
if (CONFIG->PIDFILE) { if (CONFIG->PIDFILE) {
pfh = VPF_Open(CONFIG->PIDFILE, 0644, NULL); pfh = VPF_Open(CONFIG->PIDFILE, 0644, NULL);
if (pfh == NULL) { if (pfh == NULL) {
ERR("FATAL: Could not open pid (-p) file (%s): %s\n", ERR("FATAL: Could not open pid (-p) file (%s): %s\n",
CONFIG->PIDFILE, strerror(errno)); CONFIG->PIDFILE, strerror(errno));
exit(1); exit(1);
} }
AZ(VPF_Write(pfh)); AZ(VPF_Write(pfh));
atexit(remove_pfh); atexit(remove_pfh);
} }
start_workers(0, CONFIG->NCORES); start_workers(0, CONFIG->NCORES);
if (CONFIG->DEBUG_LISTEN_ADDR) {
listen_endpoint_print(CONFIG->DEBUG_LISTEN_ADDR);
}
if (CONFIG->OCSP_DIR != NULL) if (CONFIG->OCSP_DIR != NULL)
start_ocsp_proc(); start_ocsp_proc();
#ifdef USE_SHARED_CACHE #ifdef USE_SHARED_CACHE
if (CONFIG->SHCUPD_PORT) { if (CONFIG->SHCUPD_PORT) {
/* start event loop to receive cache updates */ /* start event loop to receive cache updates */
loop = ev_default_loop(EVFLAG_AUTO); loop = ev_default_loop(EVFLAG_AUTO);
ev_io_init(&shcupd_listener, handle_shcupd, shcupd_socket, ev_io_init(&shcupd_listener, handle_shcupd, shcupd_socket,
EV_READ); EV_READ);
ev_io_start(loop, &shcupd_listener); ev_io_start(loop, &shcupd_listener);
 End of changes. 33 change blocks. 
58 lines changed or deleted 240 lines changed or added

Home  |  About  |  Features  |  All  |  Newest  |  Dox  |  Diffs  |  RSS Feeds  |  Screenshots  |  Comments  |  Imprint  |  Privacy  |  HTTP(S)