Blame SOURCES/0088-secrets-always-add-Content-Length-header.patch

bb7cd1
From 07271dbd7c8f28a6aace48787040580973eb5a4e Mon Sep 17 00:00:00 2001
bb7cd1
From: =?UTF-8?q?Pavel=20B=C5=99ezina?= <pbrezina@redhat.com>
bb7cd1
Date: Wed, 15 Mar 2017 15:15:08 +0100
bb7cd1
Subject: [PATCH 88/90] secrets: always add Content-Length header
bb7cd1
bb7cd1
If custodia server does not reply with Content-Length header, curl may
bb7cd1
wait for non-existing body of http reply if such body does not exist
bb7cd1
(for example during POST operation when creating a container).
bb7cd1
bb7cd1
Reviewed-by: Simo Sorce <simo@redhat.com>
bb7cd1
Reviewed-by: Jakub Hrozek <jhrozek@redhat.com>
bb7cd1
(cherry picked from commit 13d720de13e490850c1139eea865bcd5195a2630)
bb7cd1
---
bb7cd1
 src/responder/secrets/providers.c | 72 ++++++++++++++++++++++++++++++++++++---
bb7cd1
 1 file changed, 68 insertions(+), 4 deletions(-)
bb7cd1
bb7cd1
diff --git a/src/responder/secrets/providers.c b/src/responder/secrets/providers.c
bb7cd1
index 80a443d91135447ec8ce8d424b692a6d7e26a907..a27fb720b394e7c76d1b65f656146bcd00755449 100644
bb7cd1
--- a/src/responder/secrets/providers.c
bb7cd1
+++ b/src/responder/secrets/providers.c
bb7cd1
@@ -388,20 +388,84 @@ int sec_http_reply_with_headers(TALLOC_CTX *mem_ctx, struct sec_data *reply,
bb7cd1
     return EOK;
bb7cd1
 }
bb7cd1
 
bb7cd1
+static errno_t
bb7cd1
+sec_http_iobuf_split(struct sss_iobuf *response,
bb7cd1
+                     const char **headers,
bb7cd1
+                     const char **body)
bb7cd1
+{
bb7cd1
+    const char *data = (const char *)sss_iobuf_get_data(response);
bb7cd1
+    char *delim;
bb7cd1
+
bb7cd1
+    /* The last header ends with \r\n and then comes \r\n again as a separator
bb7cd1
+     * of body from headers. We can use this to find this point. */
bb7cd1
+    delim = strstr(data, "\r\n\r\n");
bb7cd1
+    if (delim == NULL) {
bb7cd1
+        return EINVAL;
bb7cd1
+    }
bb7cd1
+
bb7cd1
+    /* Skip to the body delimiter. */
bb7cd1
+    delim = delim + sizeof("\r\n") - 1;
bb7cd1
+
bb7cd1
+    /* Replace \r\n with zeros turning data into:
bb7cd1
+     * from HEADER\r\nBODY into HEADER\0\0BODY format. */
bb7cd1
+    delim[0] = '\0';
bb7cd1
+    delim[1] = '\0';
bb7cd1
+
bb7cd1
+    /* Split the buffer. */
bb7cd1
+    *headers = data;
bb7cd1
+    *body = delim + 2;
bb7cd1
+
bb7cd1
+    return 0;
bb7cd1
+}
bb7cd1
+
bb7cd1
+static const char *
bb7cd1
+sec_http_iobuf_add_content_length(TALLOC_CTX *mem_ctx,
bb7cd1
+                                  const char *headers,
bb7cd1
+                                  size_t body_len)
bb7cd1
+{
bb7cd1
+    /* If Content-Length is already present we do nothing. */
bb7cd1
+    if (strstr(headers, "Content-Length:") != NULL) {
bb7cd1
+        return headers;
bb7cd1
+    }
bb7cd1
+
bb7cd1
+    return talloc_asprintf(mem_ctx, "%sContent-Length: %zu\r\n",
bb7cd1
+                           headers, body_len);
bb7cd1
+}
bb7cd1
+
bb7cd1
 errno_t sec_http_reply_iobuf(TALLOC_CTX *mem_ctx,
bb7cd1
                              struct sec_data *reply,
bb7cd1
                              int response_code,
bb7cd1
                              struct sss_iobuf *response)
bb7cd1
 {
bb7cd1
+    const char *headers;
bb7cd1
+    const char *body;
bb7cd1
+    size_t body_len;
bb7cd1
+    errno_t ret;
bb7cd1
+
bb7cd1
     DEBUG(SSSDBG_TRACE_LIBS, "HTTP reply %d\n", response_code);
bb7cd1
 
bb7cd1
-    reply->data = (char *)sss_iobuf_get_data(response);
bb7cd1
-    reply->length = sss_iobuf_get_len(response);
bb7cd1
+    ret = sec_http_iobuf_split(response, &headers, &body);
bb7cd1
+    if (ret != EOK) {
bb7cd1
+        DEBUG(SSSDBG_OP_FAILURE,
bb7cd1
+              "Unexpected HTTP reply, returning what we got from server\n");
bb7cd1
+        reply->data = (char *)sss_iobuf_get_data(response);
bb7cd1
+        reply->length = sss_iobuf_get_len(response);
bb7cd1
 
bb7cd1
-    talloc_steal(mem_ctx, reply->data);
bb7cd1
+        return EOK;
bb7cd1
+    }
bb7cd1
 
bb7cd1
+    /* Add Content-Length header if not present so client does not await
bb7cd1
+     * not-existing incoming data. */
bb7cd1
+    body_len = strlen(body);
bb7cd1
+    headers = sec_http_iobuf_add_content_length(mem_ctx, headers, body_len);
bb7cd1
+    if (headers == NULL) {
bb7cd1
+        return ENOMEM;
bb7cd1
+    }
bb7cd1
+
bb7cd1
+    reply->length = strlen(headers) + sizeof("\r\n") - 1 + body_len;
bb7cd1
+    reply->data = talloc_asprintf(mem_ctx, "%s\r\n%s", headers, body);
bb7cd1
     if (reply->data == NULL) {
bb7cd1
-        return EINVAL;
bb7cd1
+        return ENOMEM;
bb7cd1
     }
bb7cd1
 
bb7cd1
     return EOK;
bb7cd1
-- 
bb7cd1
2.9.3
bb7cd1