summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--src/net/tcp/httpconn.c9
-rw-r--r--src/net/tcp/httpcore.c12
2 files changed, 19 insertions, 2 deletions
diff --git a/src/net/tcp/httpconn.c b/src/net/tcp/httpconn.c
index 2cfca9c9..5121ff6c 100644
--- a/src/net/tcp/httpconn.c
+++ b/src/net/tcp/httpconn.c
@@ -252,8 +252,13 @@ int http_connect ( struct interface *xfer, struct uri *uri ) {
/* Identify port */
port = uri_port ( uri, scheme->port );
- /* Look for a reusable connection in the pool */
- list_for_each_entry ( conn, &http_connection_pool, pool.list ) {
+ /* Look for a reusable connection in the pool. Reuse the most
+ * recent connection in order to accommodate authentication
+ * schemes that break the stateless nature of HTTP and rely on
+ * the same connection being reused for authentication
+ * responses.
+ */
+ list_for_each_entry_reverse ( conn, &http_connection_pool, pool.list ) {
/* Sanity checks */
assert ( conn->uri != NULL );
diff --git a/src/net/tcp/httpcore.c b/src/net/tcp/httpcore.c
index b3c9a00e..f755fb72 100644
--- a/src/net/tcp/httpcore.c
+++ b/src/net/tcp/httpcore.c
@@ -778,6 +778,18 @@ static int http_transfer_complete ( struct http_transaction *http ) {
http->len = 0;
assert ( http->remaining == 0 );
+ /* Retry immediately if applicable. We cannot rely on an
+ * immediate timer expiry, since certain Microsoft-designed
+ * HTTP extensions such as NTLM break the fundamentally
+ * stateless nature of HTTP and rely on the same connection
+ * being reused for authentication. See RFC7230 section 2.3
+ * for further details.
+ */
+ if ( ! http->response.retry_after ) {
+ http_reopen ( http );
+ return 0;
+ }
+
/* Start timer to initiate retry */
DBGC2 ( http, "HTTP %p retrying after %d seconds\n",
http, http->response.retry_after );