[PATCH] tabled/libhttpstor: fix HTTP header signing bug

Jeff Garzik <[email protected]>
Newsgroups org.kernel.vger.hail-devel
Message-ID <[email protected]>
commit 223c5f7ceab19bd0630943e77de15372a865a7ea
Author: Jeff Garzik <[email protected]>
Date:   Sun Mar 7 07:57:24 2010 -0500

    libhttpstor: sign user-provided headers
    
    We forgot to sign user-provided headers for AWS authentication.
    
    Signed-off-by: Jeff Garzik <[email protected]>

diff --git a/lib/httpstor.c b/lib/httpstor.c
index 189aab5..b024cad 100644
--- a/lib/httpstor.c
+++ b/lib/httpstor.c
@@ -22,6 +22,7 @@
 
 #include <stdlib.h>
 #include <string.h>
+#include <ctype.h>
 #include <curl/curl.h>
 #include <openssl/hmac.h>
 #include <libxml/tree.h>
@@ -443,9 +444,9 @@ bool httpstor_put(struct httpstor_client *httpstor, const char *bucket, const ch
 {
 	struct http_req req;
 	char datestr[80], timestr[64], hmac[64], auth[128], host[80],
-		url[80], *orig_path, *stmp;
+		url[80], *orig_path, *stmp, *uhdr_buf = NULL;
 	struct curl_slist *headers = NULL;
-	int rc;
+	int rc = -1;
 
 	if (asprintf(&stmp, "/%s/%s", bucket, key) < 0)
 		return false;
@@ -461,6 +462,51 @@ bool httpstor_put(struct httpstor_client *httpstor, const char *bucket, const ch
 
 	req_hdr_push(&req, "Date", timestr);
 
+	if (user_hdrs) {
+		int idx = 0;
+		size_t uhdr_len = 0, ukey_len;
+		void *p;
+		char *colon, *ukey, *uval;
+
+		/* 1. add to curl hdr list.  2. count hdr byte size */
+		while (user_hdrs[idx]) {
+			headers = curl_slist_append(headers, user_hdrs[idx]);
+			uhdr_len += strlen(user_hdrs[idx]) + 2;
+			idx++;
+		}
+
+		/* alloc buf to hold all hdr strings */
+		uhdr_buf = calloc(1, uhdr_len);
+		if (!uhdr_buf)
+			goto out;
+
+		/* copy and nul-terminate hdr keys and values for signing */
+		idx = 0;
+		p = uhdr_buf;
+		while (user_hdrs[idx]) {
+			ukey = p;
+			colon = strchr(user_hdrs[idx], ':');
+			if (colon) {
+				ukey_len = colon - user_hdrs[idx];
+				memcpy(ukey, user_hdrs[idx], ukey_len);
+				ukey[ukey_len] = 0;
+
+				p += ukey_len + 1;
+
+				colon++;
+				while (*colon && isspace(*colon))
+					colon++;
+
+				uval = p;
+				strcpy(uval, colon);
+				p += strlen(uval) + 1;
+
+				req_hdr_push(&req, ukey, uval);
+			}
+			idx++;
+		}
+	}
+
 	req_sign(&req, NULL, httpstor->key, hmac);
 
 	sprintf(auth, "Authorization: AWS %s:%s", httpstor->user, hmac);
@@ -471,15 +517,6 @@ bool httpstor_put(struct httpstor_client *httpstor, const char *bucket, const ch
 	headers = curl_slist_append(headers, datestr);
 	headers = curl_slist_append(headers, auth);
 
-	if (user_hdrs) {
-		int idx = 0;
-
-		while (user_hdrs[idx]) {
-			headers = curl_slist_append(headers, user_hdrs[idx]);
-			idx++;
-		}
-	}
-
 	curl_easy_reset(httpstor->curl);
 	if (httpstor->verbose)
 		curl_easy_setopt(httpstor->curl, CURLOPT_VERBOSE, 1);
@@ -499,6 +536,8 @@ bool httpstor_put(struct httpstor_client *httpstor, const char *bucket, const ch
 	curl_slist_free_all(headers);
 	free(orig_path);
 
+out:
+	free(uhdr_buf);
 	return (rc == 0);
 }
lmpx.com only provides a reader for public news (NNTP) servers. It is not affiliated with the servers or forums shown here and is not responsible for the content of articles, which is written by their respective authors.