]> git.ipfire.org Git - thirdparty/haproxy.git/commitdiff
BUG/MINOR: only mark connections private if NTLM is detected
authorLukas Tribus <lukas@ltri.eu>
Sat, 27 Oct 2018 18:06:59 +0000 (20:06 +0200)
committerWilly Tarreau <w@1wt.eu>
Sat, 27 Oct 2018 20:10:29 +0000 (22:10 +0200)
Instead of marking all connections that see a 401/407 response private
(for connection reuse), this patch detects a RFC4559/NTLM authentication
scheme and restricts the private setting to those connections.

This is so we can reuse connections with 401/407 responses with
deterministic load balancing algorithms later (which requires another fix).

This fixes the problem reported here by Elliot Barlas :

  https://discourse.haproxy.org/t/unable-to-configure-load-balancing-per-request-over-persistent-connection/3144

Should be backported to 1.8.

doc/configuration.txt
src/proto_http.c

index 95b0b977cb284dbd30af63346dee474adee73e98..b140b60abc9efa2dcb597eef0fae7eff370f599d 100644 (file)
@@ -4848,10 +4848,8 @@ http-reuse { never | safe | aggressive | always }
     - connections sent to a server with a TLS SNI extension are marked private
       and are never shared;
 
-    - connections receiving a status code 401 or 407 expect some authentication
-      to be sent in return. Due to certain bogus authentication schemes (such
-      as NTLM) relying on the connection, these connections are marked private
-      and are never shared;
+    - connections with certain bogus authentication schemes (relying on the
+      connection) like NTLM are detected, marked private and are never shared;
 
   No connection pool is involved, once a session dies, the last idle connection
   it was attached to is deleted at the same time. This ensures that connections
index 8ac4c018ba24520dfd0269d4fc9a34a9a2d6018c..980525decc70820726411bc66453b7f8265d1118 100644 (file)
@@ -3715,8 +3715,6 @@ void http_end_txn_clean_session(struct stream *s)
                 * it's better to do it (at least it helps with debugging).
                 */
                s->txn->flags |= TX_PREFER_LAST;
-               if (srv_conn)
-                       srv_conn->flags |= CO_FL_PRIVATE;
        }
 
        /* Never ever allow to reuse a connection from a non-reuse backend */
@@ -4380,10 +4378,13 @@ int http_wait_for_response(struct stream *s, struct channel *rep, int an_bit)
        struct http_txn *txn = s->txn;
        struct http_msg *msg = &txn->rsp;
        struct hdr_ctx ctx;
+       struct connection *srv_conn;
        int use_close_only;
        int cur_idx;
        int n;
 
+       srv_conn = cs_conn(objt_cs(s->si[1].end));
+
        DPRINTF(stderr,"[%u] %s: stream=%p b=%p, exp(r,w)=%u,%u bf=%08x bh=%lu analysers=%02x\n",
                now_ms, __FUNCTION__,
                s,
@@ -4915,6 +4916,27 @@ int http_wait_for_response(struct stream *s, struct channel *rep, int an_bit)
                msg->body_len = msg->chunk_len = cl;
        }
 
+       /* check for NTML authentication headers in 401 (WWW-Authenticate) and
+        * 407 (Proxy-Authenticate) responses and set the connection to private
+        */
+       if (srv_conn && txn->status == 401) {
+           /* check for Negotiate/NTLM WWW-Authenticate headers */
+           ctx.idx = 0;
+           while (http_find_header2("WWW-Authenticate", 16, ci_head(rep), &txn->hdr_idx, &ctx)) {
+                   if ((ctx.vlen >= 9 && word_match(ctx.line + ctx.val, ctx.vlen, "Negotiate", 9)) ||
+                         (ctx.vlen >= 4 && word_match(ctx.line + ctx.val, ctx.vlen, "NTLM", 4)))
+                               srv_conn->flags |= CO_FL_PRIVATE;
+           }
+       } else if (srv_conn && txn->status == 407) {
+           /* check for Negotiate/NTLM Proxy-Authenticate headers */
+           ctx.idx = 0;
+           while (http_find_header2("Proxy-Authenticate", 18, ci_head(rep), &txn->hdr_idx, &ctx)) {
+                   if ((ctx.vlen >= 9 && word_match(ctx.line + ctx.val, ctx.vlen, "Negotiate", 9)) ||
+                         (ctx.vlen >= 4 && word_match(ctx.line + ctx.val, ctx.vlen, "NTLM", 4)))
+                               srv_conn->flags |= CO_FL_PRIVATE;
+           }
+       }
+
  skip_content_length:
        /* Now we have to check if we need to modify the Connection header.
         * This is more difficult on the response than it is on the request,