From 76d2cef0c2f11e54c4eb2b4fbf3c219649e69c6d Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Fr=C3=A9d=C3=A9ric=20L=C3=A9caille?= Date: Tue, 12 Feb 2019 19:12:32 +0100 Subject: [PATCH] BUG/MEDIUM: peers: Missing peer initializations. Initialize ->srv peer field for all the peers, the local peer included. Indeed, a haproxy process needs to connect to the local peer of a remote process. Furthermore, when a "peer" or "server" line is parsed by parse_server() the address must be copied to ->addr field of the peer object only if this address has been also parsed by parse_server(). This is not the case if this address belongs to the local peer and is provided on a "server" line. After having parsed the "peer" or "server" lines of a peer sections, the ->srv part of all the peer must be initialized for SSL, if enabled. Same thing for the binding part. Revert 1417f0b commit which is no more required. No backport is needed, this is purely 2.0. --- include/proto/peers.h | 4 ++-- src/cfgparse.c | 46 ++++++++++++++++++++++++++++--------------- 2 files changed, 32 insertions(+), 18 deletions(-) diff --git a/include/proto/peers.h b/include/proto/peers.h index 8b04cc864..ce4feaa4c 100644 --- a/include/proto/peers.h +++ b/include/proto/peers.h @@ -32,7 +32,7 @@ #if defined(USE_OPENSSL) static inline enum obj_type *peer_session_target(struct peer *p, struct stream *s) { - if (p->srv && p->srv->use_ssl) + if (p->srv->use_ssl) return &p->srv->obj_type; else return &s->be->obj_type; @@ -40,7 +40,7 @@ static inline enum obj_type *peer_session_target(struct peer *p, struct stream * static inline struct xprt_ops *peer_xprt(struct peer *p) { - return (p->srv && p->srv->use_ssl) ? xprt_get(XPRT_SSL) : xprt_get(XPRT_RAW); + return p->srv->use_ssl ? xprt_get(XPRT_SSL) : xprt_get(XPRT_RAW); } #else static inline enum obj_type *peer_session_target(struct peer *p, struct stream *s) diff --git a/src/cfgparse.c b/src/cfgparse.c index e178db069..59ba77376 100644 --- a/src/cfgparse.c +++ b/src/cfgparse.c @@ -809,21 +809,29 @@ int cfg_parse_peers(const char *file, int linenum, char **args, int kwm) goto out; } - /* This initializes curpeer->peers->peers_fe->srv. */ + /* This initializes curpeer->peers->peers_fe->srv. + * The server address is parsed only if we are parsing a "peer" line, + * or if we are parsing a "server" line and the current peer is not the local one. + */ err_code |= parse_server(file, linenum, args, curpeers->peers_fe, NULL, peer || !local_peer); if (!curpeers->peers_fe->srv) goto out; - newpeer->addr = curpeers->peers_fe->srv->addr; - newpeer->proto = protocol_by_family(newpeer->addr.ss_family); + /* If the peer address has just been parsed, let's copy it to + * and initializes ->proto. + */ + if (peer || !local_peer) { + newpeer->addr = curpeers->peers_fe->srv->addr; + newpeer->proto = protocol_by_family(newpeer->addr.ss_family); + } + newpeer->xprt = xprt_get(XPRT_RAW); newpeer->sock_init_arg = NULL; HA_SPIN_INIT(&newpeer->lock); - if (!newpeer->local) { - newpeer->srv = curpeers->peers_fe->srv; + newpeer->srv = curpeers->peers_fe->srv; + if (!newpeer->local) goto out; - } /* The lines above are reserved to "peer" lines. */ if (*args[0] == 's') @@ -3864,24 +3872,30 @@ out_uri_auth_compat: curpeers->peers_fe = NULL; } else { + /* Initializes the transport layer of the server part of all the peers belonging to + * section if required. + * Note that ->srv is used by the local peer of a new process to connect to the local peer + * of an old process. + */ p = curpeers->remote; while (p) { if (p->srv) { if (p->srv->use_ssl && xprt_get(XPRT_SSL) && xprt_get(XPRT_SSL)->prepare_srv) cfgerr += xprt_get(XPRT_SSL)->prepare_srv(p->srv); } - else if (!LIST_ISEMPTY(&curpeers->peers_fe->conf.bind)) { - struct list *l; - struct bind_conf *bind_conf; - - l = &curpeers->peers_fe->conf.bind; - bind_conf = LIST_ELEM(l->n, typeof(bind_conf), by_fe); - if (bind_conf->xprt->prepare_bind_conf && - bind_conf->xprt->prepare_bind_conf(bind_conf) < 0) - cfgerr++; - } p = p->next; } + /* Configure the SSL bindings of the local peer if required. */ + if (!LIST_ISEMPTY(&curpeers->peers_fe->conf.bind)) { + struct list *l; + struct bind_conf *bind_conf; + + l = &curpeers->peers_fe->conf.bind; + bind_conf = LIST_ELEM(l->n, typeof(bind_conf), by_fe); + if (bind_conf->xprt->prepare_bind_conf && + bind_conf->xprt->prepare_bind_conf(bind_conf) < 0) + cfgerr++; + } if (!peers_init_sync(curpeers)) { ha_alert("Peers section '%s': out of memory, giving up on peers.\n", curpeers->id);