You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

94 lines
4.0 KiB

  1. commit 7b728d616e417f0a8cd25375f70b8a332ad23a71
  2. Author: Lukas Tribus <lukas@ltri.eu>
  3. Date: Sat Oct 27 20:06:59 2018 +0200
  4. BUG/MINOR: only mark connections private if NTLM is detected
  5. Instead of marking all connections that see a 401/407 response private
  6. (for connection reuse), this patch detects a RFC4559/NTLM authentication
  7. scheme and restricts the private setting to those connections.
  8. This is so we can reuse connections with 401/407 responses with
  9. deterministic load balancing algorithms later (which requires another fix).
  10. This fixes the problem reported here by Elliot Barlas :
  11. https://discourse.haproxy.org/t/unable-to-configure-load-balancing-per-request-over-persistent-connection/3144
  12. Should be backported to 1.8.
  13. (cherry picked from commit fd9b68c48ecdba5e7971899f4eec315c8e3a3cfe)
  14. Signed-off-by: Willy Tarreau <w@1wt.eu>
  15. diff --git a/doc/configuration.txt b/doc/configuration.txt
  16. index 09980248..43b1b822 100644
  17. --- a/doc/configuration.txt
  18. +++ b/doc/configuration.txt
  19. @@ -4798,10 +4798,8 @@ http-reuse { never | safe | aggressive | always }
  20. - connections sent to a server with a TLS SNI extension are marked private
  21. and are never shared;
  22. - - connections receiving a status code 401 or 407 expect some authentication
  23. - to be sent in return. Due to certain bogus authentication schemes (such
  24. - as NTLM) relying on the connection, these connections are marked private
  25. - and are never shared;
  26. + - connections with certain bogus authentication schemes (relying on the
  27. + connection) like NTLM are detected, marked private and are never shared;
  28. No connection pool is involved, once a session dies, the last idle connection
  29. it was attached to is deleted at the same time. This ensures that connections
  30. diff --git a/src/proto_http.c b/src/proto_http.c
  31. index 8f86422d..cde2dbf7 100644
  32. --- a/src/proto_http.c
  33. +++ b/src/proto_http.c
  34. @@ -4388,8 +4388,6 @@ void http_end_txn_clean_session(struct stream *s)
  35. * it's better to do it (at least it helps with debugging).
  36. */
  37. s->txn->flags |= TX_PREFER_LAST;
  38. - if (srv_conn)
  39. - srv_conn->flags |= CO_FL_PRIVATE;
  40. }
  41. /* Never ever allow to reuse a connection from a non-reuse backend */
  42. @@ -5053,10 +5051,13 @@ int http_wait_for_response(struct stream *s, struct channel *rep, int an_bit)
  43. struct http_txn *txn = s->txn;
  44. struct http_msg *msg = &txn->rsp;
  45. struct hdr_ctx ctx;
  46. + struct connection *srv_conn;
  47. int use_close_only;
  48. int cur_idx;
  49. int n;
  50. + srv_conn = cs_conn(objt_cs(s->si[1].end));
  51. +
  52. DPRINTF(stderr,"[%u] %s: stream=%p b=%p, exp(r,w)=%u,%u bf=%08x bh=%d analysers=%02x\n",
  53. now_ms, __FUNCTION__,
  54. s,
  55. @@ -5588,6 +5589,27 @@ int http_wait_for_response(struct stream *s, struct channel *rep, int an_bit)
  56. msg->body_len = msg->chunk_len = cl;
  57. }
  58. + /* check for NTML authentication headers in 401 (WWW-Authenticate) and
  59. + * 407 (Proxy-Authenticate) responses and set the connection to private
  60. + */
  61. + if (srv_conn && txn->status == 401) {
  62. + /* check for Negotiate/NTLM WWW-Authenticate headers */
  63. + ctx.idx = 0;
  64. + while (http_find_header2("WWW-Authenticate", 16, rep->buf->p, &txn->hdr_idx, &ctx)) {
  65. + if ((ctx.vlen >= 9 && word_match(ctx.line + ctx.val, ctx.vlen, "Negotiate", 9)) ||
  66. + (ctx.vlen >= 4 && word_match(ctx.line + ctx.val, ctx.vlen, "NTLM", 4)))
  67. + srv_conn->flags |= CO_FL_PRIVATE;
  68. + }
  69. + } else if (srv_conn && txn->status == 407) {
  70. + /* check for Negotiate/NTLM Proxy-Authenticate headers */
  71. + ctx.idx = 0;
  72. + while (http_find_header2("Proxy-Authenticate", 18, rep->buf->p, &txn->hdr_idx, &ctx)) {
  73. + if ((ctx.vlen >= 9 && word_match(ctx.line + ctx.val, ctx.vlen, "Negotiate", 9)) ||
  74. + (ctx.vlen >= 4 && word_match(ctx.line + ctx.val, ctx.vlen, "NTLM", 4)))
  75. + srv_conn->flags |= CO_FL_PRIVATE;
  76. + }
  77. + }
  78. +
  79. skip_content_length:
  80. /* Now we have to check if we need to modify the Connection header.
  81. * This is more difficult on the response than it is on the request,