diff --git a/0001-BUG-MEDIUM-http-fetch-base-is-not-compatible-with-se.patch b/0001-BUG-MEDIUM-http-fetch-base-is-not-compatible-with-se.patch new file mode 100644 index 0000000..1828405 --- /dev/null +++ b/0001-BUG-MEDIUM-http-fetch-base-is-not-compatible-with-se.patch @@ -0,0 +1,44 @@ +From f86d9bb6dd56d56e7425246f91a6c105a5f38659 Mon Sep 17 00:00:00 2001 +From: Willy Tarreau +Date: Tue, 24 Jun 2014 17:27:02 +0200 +Subject: [PATCH 1/6] BUG/MEDIUM: http: fetch "base" is not compatible with + set-header + +The sample fetch function "base" makes use of the trash which is also +used by set-header/add-header etc... everything which builds a formated +line. So we end up with some junk in the header if base is in use. Let's +fix this as all other fetches by using a trash chunk instead. + +This bug was reported by Baptiste Assmann, and also affects 1.5. +--- + src/proto_http.c | 6 ++++-- + 1 file changed, 4 insertions(+), 2 deletions(-) + +diff --git a/src/proto_http.c b/src/proto_http.c +index 231d49a12875..5321f7d53e6a 100644 +--- a/src/proto_http.c ++++ b/src/proto_http.c +@@ -10247,6 +10247,7 @@ smp_fetch_base(struct proxy *px, struct session *l4, void *l7, unsigned int opt, + struct http_txn *txn = l7; + char *ptr, *end, *beg; + struct hdr_ctx ctx; ++ struct chunk *temp; + + CHECK_HTTP_MESSAGE_FIRST(); + +@@ -10255,9 +10256,10 @@ smp_fetch_base(struct proxy *px, struct session *l4, void *l7, unsigned int opt, + return smp_fetch_path(px, l4, l7, opt, args, smp, kw); + + /* OK we have the header value in ctx.line+ctx.val for ctx.vlen bytes */ +- memcpy(trash.str, ctx.line + ctx.val, ctx.vlen); ++ temp = get_trash_chunk(); ++ memcpy(temp->str, ctx.line + ctx.val, ctx.vlen); + smp->type = SMP_T_STR; +- smp->data.str.str = trash.str; ++ smp->data.str.str = temp->str; + smp->data.str.len = ctx.vlen; + + /* now retrieve the path */ +-- +1.8.4.5 + diff --git a/0002-BUG-MINOR-ssl-Fix-external-function-in-order-not-to-.patch b/0002-BUG-MINOR-ssl-Fix-external-function-in-order-not-to-.patch new file mode 100644 index 0000000..fd32686 --- /dev/null +++ b/0002-BUG-MINOR-ssl-Fix-external-function-in-order-not-to-.patch @@ -0,0 +1,100 @@ +From 87e56ce15591dbb98046fe9fb923f28769eb6056 Mon Sep 17 00:00:00 2001 +From: Emeric Brun +Date: Tue, 24 Jun 2014 18:26:41 +0200 +Subject: [PATCH 2/6] BUG/MINOR: ssl: Fix external function in order not to + return a pointer on an internal trash buffer. + +'ssl_sock_get_common_name' applied to a connection was also renamed +'ssl_sock_get_remote_common_name'. Currently, this function is only used +with protocol PROXYv2 to retrieve the client certificate's common name. +A further usage could be to retrieve the server certificate's common name +on an outgoing connection. +--- + include/proto/ssl_sock.h | 2 +- + src/connection.c | 5 ++--- + src/ssl_sock.c | 23 +++++++++++------------ + 3 files changed, 14 insertions(+), 16 deletions(-) + +diff --git a/include/proto/ssl_sock.h b/include/proto/ssl_sock.h +index 0902fde989bb..3e111cd68490 100644 +--- a/include/proto/ssl_sock.h ++++ b/include/proto/ssl_sock.h +@@ -52,7 +52,7 @@ const char *ssl_sock_get_cipher_name(struct connection *conn); + const char *ssl_sock_get_proto_version(struct connection *conn); + char *ssl_sock_get_version(struct connection *conn); + int ssl_sock_get_cert_used(struct connection *conn); +-char *ssl_sock_get_common_name(struct connection *conn); ++int ssl_sock_get_remote_common_name(struct connection *conn, struct chunk *out); + unsigned int ssl_sock_get_verify_result(struct connection *conn); + #ifdef SSL_CTRL_SET_TLSEXT_STATUS_REQ_CB + int ssl_sock_update_ocsp_response(struct chunk *ocsp_response, char **err); +diff --git a/src/connection.c b/src/connection.c +index 0b154d802a80..20a911bcd41f 100644 +--- a/src/connection.c ++++ b/src/connection.c +@@ -682,9 +682,8 @@ int make_proxy_line_v2(char *buf, int buf_len, struct server *srv, struct connec + tlv->verify = htonl(ssl_sock_get_verify_result(remote)); + } + if (srv->pp_opts & SRV_PP_V2_SSL_CN) { +- value = ssl_sock_get_common_name(remote); +- if (value) { +- tlv_len = make_tlv(&buf[ret+ssl_tlv_len], (buf_len - ret - ssl_tlv_len), PP2_TYPE_SSL_CN, strlen(value), value); ++ if (ssl_sock_get_remote_common_name(remote, &trash) > 0) { ++ tlv_len = make_tlv(&buf[ret+ssl_tlv_len], (buf_len - ret - ssl_tlv_len), PP2_TYPE_SSL_CN, trash.len, trash.str); + ssl_tlv_len += tlv_len; + } + } +diff --git a/src/ssl_sock.c b/src/ssl_sock.c +index 328b97880b8d..375225d19f72 100644 +--- a/src/ssl_sock.c ++++ b/src/ssl_sock.c +@@ -2654,21 +2654,25 @@ char *ssl_sock_get_version(struct connection *conn) + return (char *)SSL_get_version(conn->xprt_ctx); + } + +-/* returns common name, NULL terminated, from client certificate, or NULL if none */ +-char *ssl_sock_get_common_name(struct connection *conn) ++/* Extract peer certificate's common name into the chunk dest ++ * Returns ++ * the len of the extracted common name ++ * or 0 if no CN found in DN ++ * or -1 on error case (i.e. no peer certificate) ++ */ ++int ssl_sock_get_remote_common_name(struct connection *conn, struct chunk *dest) + { + X509 *crt = NULL; + X509_NAME *name; +- struct chunk *cn_trash; + const char find_cn[] = "CN"; + const struct chunk find_cn_chunk = { + .str = (char *)&find_cn, + .len = sizeof(find_cn)-1 + }; +- char *result = NULL; ++ int result = -1; + + if (!ssl_sock_is_ssl(conn)) +- return NULL; ++ goto out; + + /* SSL_get_peer_certificate, it increase X509 * ref count */ + crt = SSL_get_peer_certificate(conn->xprt_ctx); +@@ -2679,13 +2683,8 @@ char *ssl_sock_get_common_name(struct connection *conn) + if (!name) + goto out; + +- cn_trash = get_trash_chunk(); +- if (ssl_sock_get_dn_entry(name, &find_cn_chunk, 1, cn_trash) <= 0) +- goto out; +- cn_trash->str[cn_trash->len] = '\0'; +- result = cn_trash->str; +- +- out: ++ result = ssl_sock_get_dn_entry(name, &find_cn_chunk, 1, dest); ++out: + if (crt) + X509_free(crt); + +-- +1.8.4.5 + diff --git a/0003-BUG-MINOR-counters-do-not-untrack-counters-before-lo.patch b/0003-BUG-MINOR-counters-do-not-untrack-counters-before-lo.patch new file mode 100644 index 0000000..818363c --- /dev/null +++ b/0003-BUG-MINOR-counters-do-not-untrack-counters-before-lo.patch @@ -0,0 +1,41 @@ +From ecde57996941ab79f8e3ee5d6114ede49adaaf17 Mon Sep 17 00:00:00 2001 +From: Willy Tarreau +Date: Wed, 25 Jun 2014 15:36:04 +0200 +Subject: [PATCH 3/6] BUG/MINOR: counters: do not untrack counters before + logging + +Baptiste Assmann reported a corner case in the releasing of stick-counters: +we release content-aware counters before logging. In the past it was not a +problem, but since now we can log them it, it prevents one from logging +their value. Simply switching the log production and the release of the +counter fixes the issue. + +This should be backported into 1.5. +--- + src/proto_http.c | 3 ++- + 1 file changed, 2 insertions(+), 1 deletion(-) + +diff --git a/src/proto_http.c b/src/proto_http.c +index 5321f7d53e6a..d566bcc819ec 100644 +--- a/src/proto_http.c ++++ b/src/proto_http.c +@@ -4808,7 +4808,6 @@ void http_end_txn_clean_session(struct session *s) + + s->logs.t_close = tv_ms_elapsed(&s->logs.tv_accept, &now); + session_process_counters(s); +- session_stop_content_counters(s); + + if (s->txn.status) { + int n; +@@ -4842,6 +4841,8 @@ void http_end_txn_clean_session(struct session *s) + s->do_log(s); + } + ++ /* stop tracking content-based counters */ ++ session_stop_content_counters(s); + session_update_time_stats(s); + + s->logs.accept_date = date; /* user-visible date for logging */ +-- +1.8.4.5 + diff --git a/0004-BUG-MAJOR-sample-correctly-reinitialize-sample-fetch.patch b/0004-BUG-MAJOR-sample-correctly-reinitialize-sample-fetch.patch new file mode 100644 index 0000000..d08b65c --- /dev/null +++ b/0004-BUG-MAJOR-sample-correctly-reinitialize-sample-fetch.patch @@ -0,0 +1,64 @@ +From 6747e44f116b7f20c96514454174cf0c0a2e1a4b Mon Sep 17 00:00:00 2001 +From: Willy Tarreau +Date: Wed, 25 Jun 2014 16:56:41 +0200 +Subject: [PATCH 4/6] BUG/MAJOR: sample: correctly reinitialize sample fetch + context before calling sample_process() + +We used to only clear flags when reusing the static sample before calling +sample_process(), but that's not enough because there's a context in samples +that can be used by some fetch functions such as auth, headers and cookies, +and not reinitializing it risks that a pointer of a different type is used +in the wrong context. + +An example configuration which triggers the case consists in mixing hdr() +and http_auth_group() which both make use of contexts : + + http-request add-header foo2 %[hdr(host)],%[http_auth_group(foo)] + +The solution is simple, initialize all the sample and not just the flags. +This fix must be backported into 1.5 since it was introduced in 1.5-dev19. +--- + src/proto_http.c | 3 +++ + src/sample.c | 5 +++-- + 2 files changed, 6 insertions(+), 2 deletions(-) + +diff --git a/src/proto_http.c b/src/proto_http.c +index d566bcc819ec..01fe62d09246 100644 +--- a/src/proto_http.c ++++ b/src/proto_http.c +@@ -9748,6 +9748,9 @@ smp_prefetch_http(struct proxy *px, struct session *s, void *l7, unsigned int op + return 1; + } + ++/* Note: these functinos *do* modify the sample. Even in case of success, at ++ * least the type and uint value are modified. ++ */ + #define CHECK_HTTP_MESSAGE_FIRST() \ + do { int r = smp_prefetch_http(px, l4, l7, opt, args, smp, 1); if (r <= 0) return r; } while (0) + +diff --git a/src/sample.c b/src/sample.c +index 9f22ef97156f..3a0f3fbbcff2 100644 +--- a/src/sample.c ++++ b/src/sample.c +@@ -905,7 +905,7 @@ struct sample *sample_process(struct proxy *px, struct session *l4, void *l7, + + if (p == NULL) { + p = &temp_smp; +- p->flags = 0; ++ memset(p, 0, sizeof(*p)); + } + + if (!expr->fetch->process(px, l4, l7, opt, expr->arg_p, p, expr->fetch->kw)) +@@ -1160,7 +1160,8 @@ struct sample *sample_fetch_string(struct proxy *px, struct session *l4, void *l + { + struct sample *smp = &temp_smp; + +- smp->flags = 0; ++ memset(smp, 0, sizeof(*smp)); ++ + if (!sample_process(px, l4, l7, opt, expr, smp)) { + if ((smp->flags & SMP_F_MAY_CHANGE) && !(opt & SMP_OPT_FINAL)) + return smp; +-- +1.8.4.5 + diff --git a/0005-MINOR-stick-table-make-stktable_fetch_key-indicate-w.patch b/0005-MINOR-stick-table-make-stktable_fetch_key-indicate-w.patch new file mode 100644 index 0000000..fc2db6d --- /dev/null +++ b/0005-MINOR-stick-table-make-stktable_fetch_key-indicate-w.patch @@ -0,0 +1,108 @@ +From f0b3bcc98e0d3fc372f0ec658e6c402af8b98412 Mon Sep 17 00:00:00 2001 +From: Willy Tarreau +Date: Wed, 25 Jun 2014 16:20:53 +0200 +Subject: [PATCH 5/6] MINOR: stick-table: make stktable_fetch_key() indicate + why it failed + +stktable_fetch_key() does not indicate whether it returns NULL because +the input sample was not found or because it's unstable. It causes trouble +with track-sc* rules. Just like with sample_fetch_string(), we want it to +be able to give more information to the caller about what it found. Thus, +now we use the pointer to a sample passed by the caller, and fill it with +the information we have about the sample. That way, even if we return NULL, +the caller has the ability to check whether a sample was found and if it is +still changing or not. +--- + include/proto/stick_table.h | 2 +- + src/proto_tcp.c | 4 ++-- + src/session.c | 4 ++-- + src/stick_table.c | 12 +++++++----- + 4 files changed, 12 insertions(+), 10 deletions(-) + +diff --git a/include/proto/stick_table.h b/include/proto/stick_table.h +index 0c26fbea3052..57ca2234317c 100644 +--- a/include/proto/stick_table.h ++++ b/include/proto/stick_table.h +@@ -48,7 +48,7 @@ struct stksess *stktable_lookup_key(struct stktable *t, struct stktable_key *key + struct stksess *stktable_update_key(struct stktable *table, struct stktable_key *key); + struct stktable_key *stktable_fetch_key(struct stktable *t, struct proxy *px, + struct session *l4, void *l7, unsigned int opt, +- struct sample_expr *expr); ++ struct sample_expr *expr, struct sample *smp); + int stktable_compatible_sample(struct sample_expr *expr, unsigned long table_type); + int stktable_get_data_type(char *name); + struct proxy *find_stktable(const char *name); +diff --git a/src/proto_tcp.c b/src/proto_tcp.c +index 65c4fdad379e..1aac0d9225d9 100644 +--- a/src/proto_tcp.c ++++ b/src/proto_tcp.c +@@ -1027,7 +1027,7 @@ int tcp_inspect_request(struct session *s, struct channel *req, int an_bit) + continue; + + t = rule->act_prm.trk_ctr.table.t; +- key = stktable_fetch_key(t, s->be, s, &s->txn, SMP_OPT_DIR_REQ|SMP_OPT_FINAL, rule->act_prm.trk_ctr.expr); ++ key = stktable_fetch_key(t, s->be, s, &s->txn, SMP_OPT_DIR_REQ|SMP_OPT_FINAL, rule->act_prm.trk_ctr.expr, NULL); + + if (key && (ts = stktable_get_entry(t, key))) { + session_track_stkctr(&s->stkctr[tcp_trk_idx(rule->action)], t, ts); +@@ -1228,7 +1228,7 @@ int tcp_exec_req_rules(struct session *s) + continue; + + t = rule->act_prm.trk_ctr.table.t; +- key = stktable_fetch_key(t, s->be, s, &s->txn, SMP_OPT_DIR_REQ|SMP_OPT_FINAL, rule->act_prm.trk_ctr.expr); ++ key = stktable_fetch_key(t, s->be, s, &s->txn, SMP_OPT_DIR_REQ|SMP_OPT_FINAL, rule->act_prm.trk_ctr.expr, NULL); + + if (key && (ts = stktable_get_entry(t, key))) + session_track_stkctr(&s->stkctr[tcp_trk_idx(rule->action)], t, ts); +diff --git a/src/session.c b/src/session.c +index e26f5ad17a6b..df85170cd13a 100644 +--- a/src/session.c ++++ b/src/session.c +@@ -1458,7 +1458,7 @@ static int process_sticking_rules(struct session *s, struct channel *req, int an + if (ret) { + struct stktable_key *key; + +- key = stktable_fetch_key(rule->table.t, px, s, &s->txn, SMP_OPT_DIR_REQ|SMP_OPT_FINAL, rule->expr); ++ key = stktable_fetch_key(rule->table.t, px, s, &s->txn, SMP_OPT_DIR_REQ|SMP_OPT_FINAL, rule->expr, NULL); + if (!key) + continue; + +@@ -1561,7 +1561,7 @@ static int process_store_rules(struct session *s, struct channel *rep, int an_bi + if (ret) { + struct stktable_key *key; + +- key = stktable_fetch_key(rule->table.t, px, s, &s->txn, SMP_OPT_DIR_RES|SMP_OPT_FINAL, rule->expr); ++ key = stktable_fetch_key(rule->table.t, px, s, &s->txn, SMP_OPT_DIR_RES|SMP_OPT_FINAL, rule->expr, NULL); + if (!key) + continue; + +diff --git a/src/stick_table.c b/src/stick_table.c +index c6463ec7b95a..a708d3c53386 100644 +--- a/src/stick_table.c ++++ b/src/stick_table.c +@@ -601,15 +601,17 @@ static sample_to_key_fct sample_to_key[SMP_TYPES][STKTABLE_TYPES] = { + * Process a fetch + format conversion as defined by the sample expression + * on request or response considering the parameter. Returns either NULL if + * no key could be extracted, or a pointer to the converted result stored in +- * static_table_key in format . ++ * static_table_key in format . If is not NULL, it will be reset ++ * and its flags will be initialized so that the caller gets a copy of the input ++ * sample, and knows why it was not accepted (eg: SMP_F_MAY_CHANGE is present). + */ + struct stktable_key *stktable_fetch_key(struct stktable *t, struct proxy *px, struct session *l4, void *l7, +- unsigned int opt, +- struct sample_expr *expr) ++ unsigned int opt, struct sample_expr *expr, struct sample *smp) + { +- struct sample *smp; ++ if (smp) ++ memset(smp, 0, sizeof(*smp)); + +- smp = sample_process(px, l4, l7, opt, expr, NULL); ++ smp = sample_process(px, l4, l7, opt, expr, smp); + if (!smp) + return NULL; + +-- +1.8.4.5 + diff --git a/0006-BUG-MEDIUM-counters-fix-track-sc-to-wait-on-unstable.patch b/0006-BUG-MEDIUM-counters-fix-track-sc-to-wait-on-unstable.patch new file mode 100644 index 0000000..2c51a23 --- /dev/null +++ b/0006-BUG-MEDIUM-counters-fix-track-sc-to-wait-on-unstable.patch @@ -0,0 +1,56 @@ +From 08901b038aa0837786fbb1049508fb28c92a15d7 Mon Sep 17 00:00:00 2001 +From: Willy Tarreau +Date: Wed, 25 Jun 2014 17:01:56 +0200 +Subject: [PATCH 6/6] BUG/MEDIUM: counters: fix track-sc* to wait on unstable + contents + +I've been facing multiple configurations which involved track-sc* rules +in tcp-request content without the "if ..." to force it to wait for the +contents, resulting in random behaviour with contents sometimes retrieved +and sometimes not. + +Reading the doc doesn't make it clear either that the tracking will be +performed only if data are already there and that waiting on an ACL is +the only way to avoid this. + +Since this behaviour is not natural and we now have the ability to fix +it, this patch ensures that if input data are still moving, instead of +silently dropping them, we naturally wait for them to stabilize up to +the inspect-delay. This way it's not needed anymore to implement an +ACL-based condition to force to wait for data, eventhough the behaviour +is not changed for when an ACL is present. + +The most obvious usage will be when track-sc is followed by any HTTP +sample expression, there's no need anymore for adding "if HTTP". + +It's probably worth backporting this to 1.5 to avoid further configuration +issues. Note that it requires previous patch. +--- + src/proto_tcp.c | 6 +++++- + 1 file changed, 5 insertions(+), 1 deletion(-) + +diff --git a/src/proto_tcp.c b/src/proto_tcp.c +index 1aac0d9225d9..e9dbc9c0b6de 100644 +--- a/src/proto_tcp.c ++++ b/src/proto_tcp.c +@@ -1022,12 +1022,16 @@ int tcp_inspect_request(struct session *s, struct channel *req, int an_bit) + * applies. + */ + struct stktable_key *key; ++ struct sample smp; + + if (stkctr_entry(&s->stkctr[tcp_trk_idx(rule->action)])) + continue; + + t = rule->act_prm.trk_ctr.table.t; +- key = stktable_fetch_key(t, s->be, s, &s->txn, SMP_OPT_DIR_REQ|SMP_OPT_FINAL, rule->act_prm.trk_ctr.expr, NULL); ++ key = stktable_fetch_key(t, s->be, s, &s->txn, SMP_OPT_DIR_REQ | partial, rule->act_prm.trk_ctr.expr, &smp); ++ ++ if (smp.flags & SMP_F_MAY_CHANGE) ++ goto missing_data; + + if (key && (ts = stktable_get_entry(t, key))) { + session_track_stkctr(&s->stkctr[tcp_trk_idx(rule->action)], t, ts); +-- +1.8.4.5 + diff --git a/haproxy.changes b/haproxy.changes index 1fbc49c..bd8acd1 100644 --- a/haproxy.changes +++ b/haproxy.changes @@ -1,3 +1,21 @@ +------------------------------------------------------------------- +Tue Jul 1 12:13:33 UTC 2014 - kgronlund@suse.com + +- BUG/MEDIUM: counters: fix track-sc* to wait on unstable contents +- MINOR: stick-table: make stktable_fetch_key() indicate why it failed +- BUG/MAJOR: sample: correctly reinitialize sample fetch context before calling sample_process() +- BUG/MINOR: counters: do not untrack counters before logging +- BUG/MINOR: ssl: Fix external function in order not to return a pointer on an internal trash buffer. +- BUG/MEDIUM: http: fetch "base" is not compatible with set-header + +- Add patches: + - 0001-BUG-MEDIUM-http-fetch-base-is-not-compatible-with-se.patch + - 0002-BUG-MINOR-ssl-Fix-external-function-in-order-not-to-.patch + - 0003-BUG-MINOR-counters-do-not-untrack-counters-before-lo.patch + - 0004-BUG-MAJOR-sample-correctly-reinitialize-sample-fetch.patch + - 0005-MINOR-stick-table-make-stktable_fetch_key-indicate-w.patch + - 0006-BUG-MEDIUM-counters-fix-track-sc-to-wait-on-unstable.patch + ------------------------------------------------------------------- Tue Jun 24 15:55:48 UTC 2014 - mrueckert@suse.de diff --git a/haproxy.spec b/haproxy.spec index 5688373..76f111e 100644 --- a/haproxy.spec +++ b/haproxy.spec @@ -61,6 +61,18 @@ Patch1: haproxy-1.2.16_config_haproxy_user.patch Patch2: haproxy-makefile_lib.patch Patch3: sec-options.patch Patch4: haproxy-1.5_check_config_before_start.patch +# PATCH-FIX-UPSTREAM: http: fetch "base" is not compatible with set-header +Patch5: 0001-BUG-MEDIUM-http-fetch-base-is-not-compatible-with-se.patch +# PATCH-FIX-UPSTREAM: ssl: Fix external function in order not to return a pointer on an internal trash buffer. +Patch6: 0002-BUG-MINOR-ssl-Fix-external-function-in-order-not-to-.patch +# PATCH-FIX-UPSTREAM: counters: do not untrack counters before logging +Patch7: 0003-BUG-MINOR-counters-do-not-untrack-counters-before-lo.patch +# PATCH-FIX-UPSTREAM: sample: correctly reinitialize sample fetch context before calling sample_process() +Patch8: 0004-BUG-MAJOR-sample-correctly-reinitialize-sample-fetch.patch +# PATCH-FIX-UPSTREAM: stick-table: make stktable_fetch_key() indicate why it failed +Patch9: 0005-MINOR-stick-table-make-stktable_fetch_key-indicate-w.patch +# PATCH-FIX-UPSTREAM: counters: fix track-sc* to wait on unstable contents +Patch10: 0006-BUG-MEDIUM-counters-fix-track-sc-to-wait-on-unstable.patch Source99: haproxy-rpmlintrc # Summary: The Reliable, High Performance TCP/HTTP Load Balancer @@ -94,6 +106,12 @@ the most work done from every CPU cycle. %patch2 %patch3 %patch4 -p1 +%patch5 -p1 +%patch6 -p1 +%patch7 -p1 +%patch8 -p1 +%patch9 -p1 +%patch10 -p1 %build %{__make} \