Skip to content

Commit 5d50c02

Browse files
PettitWesleyedsiper
authored andcommitted
signv4: fix sigv4 algorithm
The previous implementation had 2 problems: - the logic for sorting uri params was incorrect - the uri encoding for param keys and values needed to encode "/" In addition, the tests had to be modified to remove the host and content-length headers that are auto added when creating an flb_http_client. In the tests, all headers come from the test files. Signed-off-by: Wesley Pettit <[email protected]>
1 parent fcf15a9 commit 5d50c02

File tree

2 files changed

+71
-13
lines changed

2 files changed

+71
-13
lines changed

src/flb_signv4.c

Lines changed: 51 additions & 13 deletions
Original file line numberDiff line numberDiff line change
@@ -85,18 +85,16 @@ static int hmac_sha256_sign(unsigned char out[32],
8585

8686
static int kv_key_cmp(const void *a_arg, const void *b_arg)
8787
{
88+
int ret;
8889
struct flb_kv *kv_a = *(struct flb_kv **) a_arg;
8990
struct flb_kv *kv_b = *(struct flb_kv **) b_arg;
9091

91-
return strcmp(kv_a->key, kv_b->key);
92-
}
93-
94-
static int kv_val_cmp(const void *a_arg, const void *b_arg)
95-
{
96-
struct flb_kv *kv_a = *(struct flb_kv **) a_arg;
97-
struct flb_kv *kv_b = *(struct flb_kv **) b_arg;
92+
ret = strcmp(kv_a->key, kv_b->key);
93+
if (ret == 0) {
94+
ret = strcmp(kv_a->val, kv_b->val);
95+
}
9896

99-
return strcmp(kv_a->val, kv_b->val);
97+
return ret;
10098
}
10199

102100
static inline int to_encode(char c)
@@ -218,6 +216,49 @@ static flb_sds_t uri_encode(const char *uri, size_t len)
218216
return buf;
219217
}
220218

219+
/*
220+
* Encodes URI parameters, which can not have "/" characters in them
221+
* (This happens in an STS request, the role ARN has a slash and is
222+
* given as a query parameter).
223+
*/
224+
static flb_sds_t uri_encode_params(const char *uri, size_t len)
225+
{
226+
int i;
227+
flb_sds_t buf = NULL;
228+
flb_sds_t tmp = NULL;
229+
230+
buf = flb_sds_create_size(len * 2);
231+
if (!buf) {
232+
flb_error("[signv4] cannot allocate buffer for URI encoding");
233+
return NULL;
234+
}
235+
236+
for (i = 0; i < len; i++) {
237+
if (to_encode(uri[i]) == FLB_TRUE || uri[i] == '/') {
238+
tmp = flb_sds_printf(&buf, "%%%02X", (unsigned char) *(uri + i));
239+
if (!tmp) {
240+
flb_error("[signv4] error formatting special character");
241+
flb_sds_destroy(buf);
242+
return NULL;
243+
}
244+
buf = tmp;
245+
continue;
246+
}
247+
248+
/* Direct assignment, just copy the character */
249+
if (buf) {
250+
tmp = flb_sds_cat(buf, uri + i, 1);
251+
if (!tmp) {
252+
flb_error("[signv4] error composing outgoing buffer");
253+
flb_sds_destroy(buf);
254+
return NULL;
255+
}
256+
}
257+
}
258+
259+
return buf;
260+
}
261+
221262
/*
222263
* Convert URL encoded params (query string or POST payload) to a sorted
223264
* key/value linked list
@@ -261,9 +302,9 @@ static flb_sds_t url_params_format(char *params)
261302
p++;
262303

263304
/* URI encode every key and value */
264-
key = uri_encode(e->str, len);
305+
key = uri_encode_params(e->str, len);
265306
len++;
266-
val = uri_encode(p, flb_sds_len(e->str) - len);
307+
val = uri_encode_params(p, flb_sds_len(e->str) - len);
267308
if (!key || !val) {
268309
flb_error("[signv4] error encoding uri for query string");
269310
if (key) {
@@ -315,9 +356,6 @@ static flb_sds_t url_params_format(char *params)
315356
/* sort headers by key */
316357
qsort(arr, items, sizeof(struct flb_kv *), kv_key_cmp);
317358

318-
/* re-sort by values (duplicated keys) */
319-
qsort(arr, items, sizeof(struct flb_kv *), kv_val_cmp);
320-
321359
/* Format query string parameters */
322360
buf = flb_sds_create_size(items * 64);
323361
if (!buf) {

tests/internal/signv4.c

Lines changed: 20 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -292,6 +292,26 @@ static struct flb_http_client *convert_request_file(char *request,
292292
req->payload, req->payload ? flb_sds_len(req->payload): -1,
293293
NULL, -1, NULL, 0);
294294

295+
/*
296+
* flb_http_client automatically adds host and content-length
297+
* for the tests we remove these since all headers come from
298+
* the the test file
299+
*/
300+
mk_list_foreach(head, &c->headers) {
301+
kv = mk_list_entry(head, struct flb_kv, _head);
302+
if (strncasecmp(kv->key, "Host", 4) == 0) {
303+
flb_kv_item_destroy(kv);
304+
break;
305+
}
306+
}
307+
mk_list_foreach(head, &c->headers) {
308+
kv = mk_list_entry(head, struct flb_kv, _head);
309+
if (strncasecmp(kv->key, "Content-Length", 14) == 0) {
310+
flb_kv_item_destroy(kv);
311+
break;
312+
}
313+
}
314+
295315
/* Append registered headers */
296316
mk_list_foreach(head, &req->headers) {
297317
kv = mk_list_entry(head, struct flb_kv, _head);

0 commit comments

Comments
 (0)