END_TEST START_TEST(remove_test) { dpl_dict_t *dict; int i; dpl_status_t r; char valbuf[128]; /* create with a small table to ensure we have some chains */ dict = dpl_dict_new(5); dpl_assert_ptr_not_null(dict); /* add all the keys */ for (i = 0 ; i < nkeys ; i++) { dpl_dict_add(dict, keys[i], make_value(i, valbuf, sizeof(valbuf)), /* lowered */0); } dpl_assert_int_eq(nkeys, dpl_dict_count(dict)); /* remove the keys again */ for (i = 0 ; i < nkeys ; i++) { dpl_dict_var_t *var = dpl_dict_get(dict, keys[i]); dpl_assert_ptr_not_null(var); dpl_assert_str_eq(var->key, keys[i]); dpl_dict_remove(dict, var); dpl_assert_int_eq(nkeys-1-i, dpl_dict_count(dict)); } /* add all the keys back again */ for (i = 0 ; i < nkeys ; i++) { dpl_dict_add(dict, keys[i], make_value(i, valbuf, sizeof(valbuf)), /* lowered */0); } dpl_assert_int_eq(nkeys, dpl_dict_count(dict)); /* remove the keys again in reverse order; we do * this to exercise some hash chain manipulation * corner cases */ for (i = nkeys-1 ; i >= 0 ; i--) { dpl_dict_var_t *var = dpl_dict_get(dict, keys[i]); dpl_assert_ptr_not_null(var); dpl_assert_str_eq(var->key, keys[i]); dpl_dict_remove(dict, var); dpl_assert_int_eq(i, dpl_dict_count(dict)); } dpl_dict_free(dict); }
dpl_status_t dpl_s3_get_authorization_v2_params(const dpl_req_t *req, dpl_dict_t *query_params, struct tm UNUSED *tm) { dpl_status_t ret; char expires_str[128], resource_ue[DPL_URL_LENGTH(strlen(req->resource)) + 1]; snprintf(expires_str, sizeof(expires_str), "%ld", req->expires); if ('/' != req->resource[0]) { resource_ue[0] = '/'; dpl_url_encode_no_slashes(req->resource, resource_ue + 1); } else dpl_url_encode_no_slashes(req->resource, resource_ue); ret = dpl_dict_add(query_params, "AWSAccessKeyId", req->ctx->access_key, 0); if (ret != DPL_SUCCESS) return DPL_FAILURE; { char sign_str[1024]; u_int sign_len; char hmac_str[1024]; u_int hmac_len; char base64_str[1024]; u_int base64_len; char base64_ue_str[1024]; const char *method = dpl_method_str(req->method); ret = dpl_s3_make_signature_v2(req->ctx, method, req->bucket, resource_ue, NULL, expires_str, NULL, sign_str, sizeof (sign_str), &sign_len); if (ret != DPL_SUCCESS) return DPL_FAILURE; DPRINTF("%s\n", sign_str); hmac_len = dpl_hmac_sha1(req->ctx->secret_key, strlen(req->ctx->secret_key), sign_str, sign_len, hmac_str); base64_len = dpl_base64_encode((const u_char *) hmac_str, hmac_len, (u_char *) base64_str); base64_str[base64_len] = 0; dpl_url_encode(base64_str, base64_ue_str); ret = dpl_dict_add(query_params, "Signature", base64_ue_str, 0); if (ret != DPL_SUCCESS) return DPL_FAILURE; } ret = dpl_dict_add(query_params, "Expires", expires_str, 0); if (ret != DPL_SUCCESS) return DPL_FAILURE; return DPL_SUCCESS; }
static dpl_status_t add_authorization_to_headers(const dpl_req_t *req, dpl_dict_t *headers) { int ret, ret2; char basic_str[1024]; int basic_len; char base64_str[1024]; int base64_len; char auth_str[1024]; snprintf(basic_str, sizeof (basic_str), "%s:%s", req->ctx->access_key, req->ctx->secret_key); basic_len = strlen(basic_str); base64_len = dpl_base64_encode((const u_char *) basic_str, basic_len, (u_char *) base64_str); snprintf(auth_str, sizeof (auth_str), "Basic %.*s", base64_len, base64_str); ret2 = dpl_dict_add(headers, "Authorization", auth_str, 0); if (DPL_SUCCESS != ret2) { ret = ret2; goto end; } ret = DPL_SUCCESS; end: return ret; }
static dpl_status_t add_metadata_to_headers(dpl_dict_t *metadata, dpl_dict_t *headers) { int bucket; dpl_dict_var_t *var; char header[dpl_header_size]; int ret; for (bucket = 0;bucket < metadata->n_buckets;bucket++) { for (var = metadata->buckets[bucket];var;var = var->prev) { snprintf(header, sizeof (header), "%s%s", DPL_X_AMZ_META_PREFIX, var->key); assert(DPL_VALUE_STRING == var->val->type); ret = dpl_dict_add(headers, header, dpl_sbuf_get_str(var->val->string), 0); if (DPL_SUCCESS != ret) { return DPL_FAILURE; } } } return DPL_SUCCESS; }
dpl_status_t dpl_req_add_metadatum(dpl_req_t *req, const char *key, const char *value) { return dpl_dict_add(req->metadata, key, value, 0); }
END_TEST static dpl_status_t send_authenticated_request(const char *username, const char *password, struct request *reqp) { dpl_status_t s; dpl_dict_t *prof2; char id[41]; static const char data[] = "Carles wolf yr Austin, chambray twee lo-fi iPhone brunch Neutra" "slow-carb. Viral"; prof2 = dpl_dict_dup(profile); if (username) dpl_assert_int_eq(DPL_SUCCESS, dpl_dict_add(prof2, "access_key", username, 0)); if (password) dpl_assert_int_eq(DPL_SUCCESS, dpl_dict_add(prof2, "secret_key", password, 0)); /* create an unauthenticated context */ ctx = dpl_ctx_new_from_dict(prof2); dpl_assert_ptr_not_null(ctx); dpl_dict_free(prof2); s = dpl_gen_random_key(ctx, DPL_STORAGE_CLASS_STANDARD, /*custom*/NULL, id, sizeof(id)); dpl_assert_int_eq(DPL_SUCCESS, s); s = dpl_put_id(ctx, "foobucket", id, /*options*/NULL, DPL_FTYPE_REG, /*condition*/NULL, /*range*/NULL, /*metadata*/NULL, /*sysmd*/NULL, data, sizeof(data)-1); if (reqp) *reqp = state->request; /* sample before disconnection */ dpl_ctx_free(ctx); ctx = NULL; return s; }
END_TEST /* * Test replacing an existing value with dpl_dict_add( */ START_TEST(replace_test) { dpl_dict_t *dict; int i; dpl_status_t r; char valbuf[128]; /* strings courtesy http://hipsteripsum.me/ */ static const char key0[] = "Sriracha"; static const char val0[] = "Banksy"; static const char val0_new[] = "polaroid"; static const char key1[] = "trust"; static const char val1[] = "fund"; dict = dpl_dict_new(13); dpl_assert_ptr_not_null(dict); /* add the values */ dpl_dict_add(dict, key0, val0, /* lowered */0); dpl_dict_add(dict, key1, val1, /* lowered */0); dpl_assert_int_eq(2, dpl_dict_count(dict)); /* check the values are there */ dpl_assert_str_eq(dpl_dict_get_value(dict, key0), val0); dpl_assert_str_eq(dpl_dict_get_value(dict, key1), val1); /* replace one of the values */ dpl_dict_add(dict, key0, val0_new, /* lowered */0); /* check the element count is correct */ dpl_assert_int_eq(2, dpl_dict_count(dict)); /* check the new value is there */ dpl_assert_str_eq(dpl_dict_get_value(dict, key0), val0_new); /* check the other key is unaffected */ dpl_assert_str_eq(dpl_dict_get_value(dict, key1), val1); dpl_dict_free(dict); }
void assign_meta_to_dict(dpl_dict_t *dict, char *meta, unsigned long val) { char *buf = NULL; buf = tmpstr_printf("%lu", val); LOG(LOG_DEBUG, "meta='%s', value='%s'", meta, buf); if (DPL_SUCCESS != dpl_dict_add(dict, meta, buf, 1)) LOG(LOG_ERR, "can't update value '%s' for '%s'", buf, meta); }
void copy_nameless_object_with_new_md() { dpl_async_task_t *atask = NULL; dpl_buf_t *buf = NULL; dpl_status_t ret; dpl_dict_t *metadata = NULL; banner("11 - copy nameless object with new metadata"); metadata = dpl_dict_new(13); if (NULL == metadata) { ret = DPL_ENOMEM; exit(1); } ret = dpl_dict_add(metadata, "bar", "qux", 0); if (DPL_SUCCESS != ret) { fprintf(stderr, "error updating metadatum: %s (%d)\n", dpl_status_str(ret), ret); exit(1); } /* * note: With Dewpoint, it would be possible to copy nameless object into another nameless object. * Does it make sense ? for now we copy it into a named object */ atask = (dpl_async_task_t *) dpl_copy_id_async_prepare(ctx, NULL, //no src bucket id1, //the src resource NULL, //no dst bucket file1_path, //dst resource NULL, //no option DPL_FTYPE_REG, //regular file DPL_COPY_DIRECTIVE_COPY, //rename metadata, //metadata NULL, //no sysmd NULL); //no server side condition if (NULL == atask) { fprintf(stderr, "error preparing task\n"); exit(1); } atask->cb_func = cb_copy_nameless_object_with_new_md; atask->cb_arg = atask; dpl_task_pool_put(pool, (dpl_task_t *) atask); }
void update_metadata_named_object() { dpl_async_task_t *atask = NULL; dpl_status_t ret; dpl_option_t option; dpl_dict_t *metadata = NULL; banner("6 - append metadata to existing named object"); metadata = dpl_dict_new(13); if (NULL == metadata) { ret = DPL_ENOMEM; exit(1); } ret = dpl_dict_add(metadata, "foo", "bar", 0); if (DPL_SUCCESS != ret) { fprintf(stderr, "error updating metadatum: %s (%d)\n", dpl_status_str(ret), ret); exit(1); } option.mask = DPL_OPTION_APPEND_METADATA; atask = (dpl_async_task_t *) dpl_put_async_prepare(ctx, NULL, //no bucket file3_path, //the id &option, //option DPL_FTYPE_REG, //regular object NULL, //condition NULL, //range metadata, //the metadata NULL, //no sysmd NULL); //object body dpl_dict_free(metadata); if (NULL == atask) { fprintf(stderr, "error preparing task\n"); exit(1); } atask->cb_func = cb_update_metadata_named_object; atask->cb_arg = atask; dpl_task_pool_put(pool, (dpl_task_t *) atask); }
static dpl_status_t add_source_to_headers(const dpl_req_t *req, dpl_dict_t *headers) { int ret, ret2; char buf[1024]; u_int len = sizeof (buf); char *p; char src_resource_ue[DPL_URL_LENGTH(strlen(req->src_resource)) + 1]; //resource if ('/' != req->src_resource[0]) { src_resource_ue[0] = '/'; dpl_url_encode(req->src_resource, src_resource_ue + 1); } else { src_resource_ue[0] = '/'; //some servers do not like encoded slash dpl_url_encode(req->src_resource + 1, src_resource_ue + 1); } p = buf; DPL_APPEND_STR("/"); DPL_APPEND_STR(req->src_bucket); DPL_APPEND_STR(src_resource_ue); //subresource and query params if (NULL != req->src_subresource) { DPL_APPEND_STR("?"); DPL_APPEND_STR(req->src_subresource); } DPL_APPEND_CHAR(0); ret2 = dpl_dict_add(headers, "x-amz-copy-source", buf, 0); if (DPL_SUCCESS != ret2) { ret = ret2; goto end; } ret = DPL_SUCCESS; end: return ret; }
dpl_status_t dpl_add_range_to_headers_internal(const dpl_range_t *range, const char *field, dpl_dict_t *headers) { int ret; char buf[1024]; int len = sizeof (buf); char *p; int first = 1; char str[128]; p = buf; DPL_APPEND_STR("bytes="); if (1 == first) first = 0; else DPL_APPEND_STR(","); if (DPL_UNDEF == range->start && DPL_UNDEF == range->end) return DPL_EINVAL; else if (DPL_UNDEF == range->start) { snprintf(str, sizeof (str), "-%lu", range->end); DPL_APPEND_STR(str); } else if (DPL_UNDEF == range->end) { snprintf(str, sizeof (str), "%lu-", range->start); DPL_APPEND_STR(str); } else { snprintf(str, sizeof (str), "%lu-%lu", range->start, range->end); DPL_APPEND_STR(str); } DPL_APPEND_CHAR(0); ret = dpl_dict_add(headers, field, buf, 0); if (DPL_SUCCESS != ret) { return DPL_FAILURE; } return DPL_SUCCESS; }
static dpl_status_t add_date_to_headers(dpl_dict_t *headers) { int ret; time_t t; struct tm tm_buf; char date_str[128]; (void) time(&t); ret = strftime(date_str, sizeof (date_str), "%a, %d %b %Y %H:%M:%S GMT", gmtime_r(&t, &tm_buf)); if (ret == 0) return DPL_FAILURE; else return dpl_dict_add(headers, "Date", date_str, 0); }
void copy_named_object_with_new_md() { dpl_async_task_t *atask = NULL; dpl_buf_t *buf = NULL; dpl_status_t ret; dpl_dict_t *metadata = NULL; banner("12 - copy named object with new metadata"); metadata = dpl_dict_new(13); if (NULL == metadata) { ret = DPL_ENOMEM; exit(1); } ret = dpl_dict_add(metadata, "qux", "baz", 0); if (DPL_SUCCESS != ret) { fprintf(stderr, "error updating metadatum: %s (%d)\n", dpl_status_str(ret), ret); exit(1); } atask = (dpl_async_task_t *) dpl_copy_async_prepare(ctx, NULL, //no src bucket file1_path, //the src resource NULL, //no dst bucket file4_path, //dst resource NULL, //no option DPL_FTYPE_REG, //regular file DPL_COPY_DIRECTIVE_COPY, //rename metadata, //metadata NULL, //no sysmd NULL); //no server side condition if (NULL == atask) { fprintf(stderr, "error preparing task\n"); exit(1); } atask->cb_func = cb_copy_named_object_with_new_md; atask->cb_arg = atask; dpl_task_pool_put(pool, (dpl_task_t *) atask); }
/** * parse a string of the form query_params1=value1;query_params2=value2... * * @param query_params * * @return */ dpl_dict_t * dpl_parse_query_params(char *query_params) { char *saveptr = NULL; char *str, *tok, *p; int ret; dpl_dict_t *dict; char *nquery_params; nquery_params = strdup(query_params); if (NULL == nquery_params) return NULL; dict = dpl_dict_new(13); if (NULL == dict) { free(nquery_params); return NULL; } for (str = query_params;;str = NULL) { tok = strtok_r(str, ";", &saveptr); if (NULL == tok) break ; DPRINTF("tok=%s\n", tok); p = index(tok, '='); if (NULL == p) p = ""; else *p++ = 0; ret = dpl_dict_add(dict, tok, p, 0); if (DPL_SUCCESS != ret) { dpl_dict_free(dict); free(nquery_params); return NULL; } } free(nquery_params); return dict; }
/** * parse a string of the form metadata1=value1;metadata2=value2... * * @param metadata * * @return */ dpl_dict_t * dpl_parse_metadata(char *metadata) { char *saveptr = NULL; char *str, *tok, *p; int ret; dpl_dict_t *dict; char *nmetadata; nmetadata = strdup(metadata); if (NULL == nmetadata) return NULL; dict = dpl_dict_new(13); if (NULL == dict) { free(nmetadata); return NULL; } for (str = metadata;;str = NULL) { tok = strtok_r(str, ";", &saveptr); if (NULL == tok) break ; DPRINTF("tok=%s\n", tok); p = index(tok, '='); if (NULL == p) p = ""; else *p++ = 0; ret = dpl_dict_add(dict, tok, p, 0); if (DPL_SUCCESS != ret) { dpl_dict_free(dict); free(nmetadata); return NULL; } } free(nmetadata); return dict; }
dpl_status_t dpl_s3_add_authorization_v2_to_headers(const dpl_req_t *req, dpl_dict_t *headers, const dpl_dict_t UNUSED *query_params, struct tm UNUSED *tm) { int ret; const char *method = dpl_method_str(req->method); char resource_ue[DPL_URL_LENGTH(strlen(req->resource)) + 1]; char sign_str[1024]; u_int sign_len; char hmac_str[1024]; u_int hmac_len; char base64_str[1024]; u_int base64_len; char auth_str[1024]; char *date_str = NULL; //resource if ('/' != req->resource[0]) { resource_ue[0] = '/'; dpl_url_encode_no_slashes(req->resource, resource_ue + 1); } else dpl_url_encode_no_slashes(req->resource, resource_ue); date_str = dpl_dict_get_value(headers, "x-amz-date"); if (date_str == NULL) date_str = dpl_dict_get_value(headers, "Date"); ret = dpl_s3_make_signature_v2(req->ctx, method, req->bucket, resource_ue, req->subresource, date_str, headers, sign_str, sizeof (sign_str), &sign_len); if (DPL_SUCCESS != ret) return DPL_FAILURE; /* DPL_TRACE(req->ctx, DPL_TRACE_REQ, "stringtosign=%.*s", sign_len, sign_str); */ hmac_len = dpl_hmac_sha1(req->ctx->secret_key, strlen(req->ctx->secret_key), sign_str, sign_len, hmac_str); base64_len = dpl_base64_encode((const u_char *) hmac_str, hmac_len, (u_char *) base64_str); snprintf(auth_str, sizeof (auth_str), "AWS %s:%.*s", req->ctx->access_key, base64_len, base64_str); return dpl_dict_add(headers, "Authorization", auth_str, 0); }
static int cb_ntinydb(const char *key_ptr, int key_len, void *cb_arg) { struct mdparse_data *arg = (struct mdparse_data *) cb_arg; int ret, ret2; const char *value_returned = NULL; int value_len_returned; char *key_str; char *value_str; DPRINTF("%.*s\n", key_len, key_ptr); key_str = alloca(key_len + 1); memcpy(key_str, key_ptr, key_len); key_str[key_len] = 0; ret2 = dpl_ntinydb_get(arg->orig, arg->orig_len, key_str, &value_returned, &value_len_returned); if (DPL_SUCCESS != ret2) { ret = -1; goto end; } DPRINTF("%.*s\n", value_len_returned, value_returned); value_str = alloca(value_len_returned + 1); memcpy(value_str, value_returned, value_len_returned); value_str[value_len_returned] = 0; ret2 = dpl_dict_add(arg->metadata, key_str, value_str, 0); if (DPL_SUCCESS != ret2) { ret = -1; goto end; } ret = 0; end: return ret; }
static dpl_status_t cb_httpreply_header(void *cb_arg, const char *header, const char *value) { struct httreply_conven *hc = (struct httreply_conven *) cb_arg; int ret; if (NULL == hc->headers) { hc->headers = dpl_dict_new(13); if (NULL == hc->headers) return DPL_ENOMEM; } ret = dpl_dict_add(hc->headers, header, value, 1); if (DPL_SUCCESS != ret) return DPL_ENOMEM; return DPL_SUCCESS; }
void update_metadata() { dpl_async_task_t *atask = NULL; dpl_buf_t *buf = NULL; dpl_status_t ret; fprintf(stderr, "setting MD only\n"); ret = dpl_dict_add(metadata, "foo", "bar2", 0); if (DPL_SUCCESS != ret) { fprintf(stderr, "error updating metadatum: %s (%d)\n", dpl_status_str(ret), ret); exit(1); } atask = (dpl_async_task_t *) dpl_copy_async_prepare(ctx, //the context NULL, //no src bucket new_path, //the key NULL, //no dst bucket new_path, //the same key NULL, //no option DPL_FTYPE_REG, //object type DPL_COPY_DIRECTIVE_METADATA_REPLACE, //tell server to replace metadata metadata, //the updated metadata NULL, //no sysmd NULL); //no condition if (NULL == atask) { fprintf(stderr, "error preparing task\n"); exit(1); } atask->cb_func = cb_update_metadata; atask->cb_arg = atask; dpl_task_pool_put(pool, (dpl_task_t *) atask); }
static dpl_status_t add_payload_signature_to_headers(const dpl_req_t *req, dpl_dict_t *headers) { uint8_t digest[SHA256_DIGEST_LENGTH]; char digest_hex[DPL_HEX_LENGTH(sizeof digest) + 1]; int i; dpl_dict_var_t *var; var = dpl_dict_get(headers, "x-amz-content-sha256"); if (var != NULL) return DPL_SUCCESS; if (req->data_enabled) dpl_sha256((uint8_t *) req->data_buf, req->data_len, digest); else dpl_sha256((uint8_t *) "", 0, digest); for (i = 0; i < sizeof digest; i++) sprintf(digest_hex + 2 * i, "%02x", (u_char) digest[i]); return dpl_dict_add(headers, "x-amz-content-sha256", digest_hex, 0); }
END_TEST /* * Use the dict with long key strings; tests * some corner cases e.g. in the hash function. */ START_TEST(long_key_test) { #define N 512 dpl_dict_t *dict; int i; int j; const char *act; const char *exp; char keybuf[1024]; char valbuf[1024]; dict = dpl_dict_new(13); dpl_assert_ptr_not_null(dict); for (i = 0 ; i < N ; i++) { dpl_dict_add(dict, make_key(i, keybuf, sizeof(keybuf)), make_value(i, valbuf, sizeof(valbuf)), /* lowered */0); } dpl_assert_int_eq(N, dpl_dict_count(dict)); for (i = 0 ; i < N ; i++) { act = dpl_dict_get_value(dict, make_key(i, keybuf, sizeof(keybuf))); exp = make_value(i, valbuf, sizeof(valbuf)); dpl_assert_str_eq(act, exp); } dpl_dict_free(dict); #undef N }
/* Add RFC2617 Basic authorization to a request's headers */ dpl_status_t dpl_add_basic_authorization_to_headers(const dpl_req_t *req, dpl_dict_t *headers) { int ret, ret2; char basic_str[1024]; int basic_len; char base64_str[1024]; int base64_len; char auth_str[1024]; /* No username or no password in the profile means * we silently don't send the header */ if (NULL == req->ctx->access_key || NULL == req->ctx->secret_key) return DPL_SUCCESS; snprintf(basic_str, sizeof (basic_str), "%s:%s", req->ctx->access_key, req->ctx->secret_key); basic_len = strlen(basic_str); base64_len = dpl_base64_encode((const u_char *) basic_str, basic_len, (u_char *) base64_str); snprintf(auth_str, sizeof (auth_str), "Basic %.*s", base64_len, base64_str); ret2 = dpl_dict_add(headers, "Authorization", auth_str, 0); if (DPL_SUCCESS != ret2) { ret = ret2; goto end; } ret = DPL_SUCCESS; end: return ret; }
dpl_status_t dpl_add_host_to_headers(dpl_req_t *req, dpl_dict_t *headers) { dpl_status_t ret; if (NULL != req->host) { char buf[256]; if (strcmp("80", req->port)) snprintf(buf, sizeof (buf), "%s:%s", req->host, req->port); else snprintf(buf, sizeof (buf), "%s", req->host); ret = dpl_dict_add(headers, "Host", buf, 0); if (DPL_SUCCESS != ret) { return ret; } } return DPL_SUCCESS; }
static void setup(void) { int r; unsetenv("DPLDIR"); unsetenv("DPLPROFILE"); dpl_init(); r = toyserver_start(NULL, &state); dpl_assert_int_eq(r, 0); profile = dpl_dict_new(13); dpl_assert_ptr_not_null(profile); dpl_assert_int_eq(DPL_SUCCESS, dpl_dict_add(profile, "host", toyserver_addrlist(state), 0)); dpl_assert_int_eq(DPL_SUCCESS, dpl_dict_add(profile, "backend", "sproxyd", 0)); dpl_assert_int_eq(DPL_SUCCESS, dpl_dict_add(profile, "base_path", "/proxy/chord", 0)); dpl_assert_int_eq(DPL_SUCCESS, dpl_dict_add(profile, "droplet_dir", "/never/seen", 0)); dpl_assert_int_eq(DPL_SUCCESS, dpl_dict_add(profile, "profile_name", "viral", 0)); /* need this to disable the event log, otherwise the droplet_dir needs to exist */ dpl_assert_int_eq(DPL_SUCCESS, dpl_dict_add(profile, "pricing_dir", "", 0)); }
dpl_status_t dpl_s3_get_authorization_v4_params(const dpl_req_t *req, dpl_dict_t *query_params, struct tm *i_tm) { dpl_status_t ret; char date_str[32] = ""; char signature[DPL_HEX_LENGTH(SHA256_DIGEST_LENGTH) + 1]; struct tm tm; ret = get_current_utc_date(&tm, i_tm, date_str, sizeof(date_str)); if (ret != DPL_SUCCESS) return ret; ret = dpl_dict_add(query_params, "X-Amz-Algorithm", "AWS4-HMAC-SHA256", 0); if (ret != DPL_SUCCESS) return DPL_FAILURE; { int ret2; char credentials[128], date_buf[9]; char credentials_ue[DPL_URL_LENGTH(sizeof(credentials)) + 1]; ret2 = strftime(date_buf, sizeof(date_buf), "%Y%m%d", &tm); if (ret2 == 0) return DPL_FAILURE; snprintf(credentials, sizeof(credentials), "%s/%s/%s/s3/aws4_request", req->ctx->access_key, date_buf, req->ctx->aws_region); dpl_url_encode(credentials, credentials_ue); ret = dpl_dict_add(query_params, "X-Amz-Credential", credentials_ue, 0); if (ret != DPL_SUCCESS) return DPL_FAILURE; } ret = dpl_dict_add(query_params, "X-Amz-Date", date_str, 0); if (ret != DPL_SUCCESS) return DPL_FAILURE; { char expires_str[128]; snprintf(expires_str, sizeof(expires_str), "%ld", req->expires - time(0)); ret = dpl_dict_add(query_params, "X-Amz-Expires", expires_str, 0); if (ret != DPL_SUCCESS) return DPL_FAILURE; } ret = dpl_dict_add(query_params, "X-Amz-SignedHeaders", "host", 0); if (ret != DPL_SUCCESS) return DPL_FAILURE; ret = dpl_s3_insert_signature_v4_params(req, query_params, &tm, date_str, signature); if (ret != DPL_SUCCESS) return DPL_FAILURE; return dpl_dict_add(query_params, "X-Amz-Signature", signature, 0); }
dpl_status_t dpl_s3_add_authorization_v4_to_headers(const dpl_req_t *req, dpl_dict_t *headers, const dpl_dict_t *query_params, struct tm *i_tm) { int item; dpl_status_t ret; char canonical_request[4096] = ""; char sign_request[1024] = ""; char signature[DPL_HEX_LENGTH(SHA256_DIGEST_LENGTH) + 1]; char authorization[1024] = ""; char date_str[32] = ""; dpl_vec_t *canonical_headers; dpl_vec_t *canonical_params; struct tm tm; ret = add_payload_signature_to_headers(req, headers); if (ret != DPL_SUCCESS) return ret; ret = get_current_utc_date(&tm, i_tm, date_str, sizeof(date_str)); if (ret != DPL_SUCCESS) return ret; ret = dpl_dict_add(headers, "x-amz-date", date_str, 0); if (ret != DPL_SUCCESS) return ret; canonical_headers = get_canonical_headers(headers); if (canonical_headers == NULL) return DPL_FAILURE; canonical_params = get_canonical_params(req->subresource, query_params, 1); if (canonical_params == NULL) { dpl_vec_free(canonical_headers); return DPL_FAILURE; } ret = create_canonical_request(req, headers, canonical_headers, canonical_params, canonical_request, sizeof(canonical_request)); if (ret == DPL_SUCCESS) { DPRINTF("Canonical request:\n%s\n", canonical_request); ret = create_sign_request(req, canonical_request, &tm, date_str, sign_request, sizeof(sign_request)); } if (ret == DPL_SUCCESS) { DPRINTF("Signing request:\n%s\n", sign_request); ret = create_signature(req, &tm, sign_request, signature); } if (ret == DPL_SUCCESS) { DPRINTF("Signature: %s\n", signature); ret = create_authorization(req, &tm, canonical_headers, signature, authorization, sizeof(authorization)); } if (ret == DPL_SUCCESS) ret = dpl_dict_add(headers, "Authorization", authorization, 0); for (item = 0; item < canonical_params->n_items; item++) { dpl_dict_var_t *param = (dpl_dict_var_t *) dpl_vec_get(canonical_params, item); free(param->key); dpl_dict_var_free(param); } dpl_vec_free(canonical_params); dpl_vec_free(canonical_headers); return ret; }
dpl_status_t dpl_add_condition_to_headers(const dpl_condition_t *cond, dpl_dict_t *headers) { int ret; char *header; int i; for (i = 0;i < cond->n_conds;i++) { const dpl_condition_one_t *condition = &cond->conds[i]; if (condition->type == DPL_CONDITION_IF_MODIFIED_SINCE || condition->type == DPL_CONDITION_IF_UNMODIFIED_SINCE) { char date_str[128]; struct tm tm_buf; ret = strftime(date_str, sizeof (date_str), "%a, %d %b %Y %H:%M:%S GMT", gmtime_r(&condition->time, &tm_buf)); if (0 == ret) return DPL_FAILURE; if (condition->type == DPL_CONDITION_IF_MODIFIED_SINCE) { header = "If-Modified-Since"; ret = dpl_dict_add(headers, header, date_str, 0); if (DPL_SUCCESS != ret) { return DPL_FAILURE; } } if (condition->type == DPL_CONDITION_IF_UNMODIFIED_SINCE) { header = "If-Unmodified-Since"; ret = dpl_dict_add(headers, header, date_str, 0); if (DPL_SUCCESS != ret) { return DPL_FAILURE; } } } if (condition->type == DPL_CONDITION_IF_MATCH) { header = "If-Match"; ret = dpl_dict_add(headers, header, condition->etag, 0); if (DPL_SUCCESS != ret) { return DPL_FAILURE; } } if (condition->type == DPL_CONDITION_IF_NONE_MATCH) { header = "If-None-Match"; ret = dpl_dict_add(headers, header, condition->etag, 0); if (DPL_SUCCESS != ret) { return DPL_FAILURE; } } } return DPL_SUCCESS; }
static dpl_status_t add_condition_to_headers(const dpl_condition_one_t *condition, dpl_dict_t *headers, int copy_source) { int ret; char *header; if (condition->type == DPL_CONDITION_IF_MODIFIED_SINCE || condition->type == DPL_CONDITION_IF_UNMODIFIED_SINCE) { char date_str[128]; struct tm tm_buf; ret = strftime(date_str, sizeof (date_str), "%a, %d %b %Y %H:%M:%S GMT", gmtime_r(&condition->time, &tm_buf)); if (0 == ret) return DPL_FAILURE; if (condition->type == DPL_CONDITION_IF_MODIFIED_SINCE) { if (1 == copy_source) header = "x-amz-copy-source-if-modified-since"; else header = "If-Modified-Since"; ret = dpl_dict_add(headers, header, date_str, 0); if (DPL_SUCCESS != ret) { return DPL_FAILURE; } } if (condition->type == DPL_CONDITION_IF_UNMODIFIED_SINCE) { if (1 == copy_source) header = "x-amz-copy-source-if-unmodified-since"; else header = "If-Unmodified-Since"; ret = dpl_dict_add(headers, header, date_str, 0); if (DPL_SUCCESS != ret) { return DPL_FAILURE; } } } if (condition->type == DPL_CONDITION_IF_MATCH) { if (1 == copy_source) header = "x-amz-copy-source-if-match"; else header = "If-Match"; ret = dpl_dict_add(headers, header, condition->etag, 0); if (DPL_SUCCESS != ret) { return DPL_FAILURE; } } if (condition->type == DPL_CONDITION_IF_NONE_MATCH) { if (1 == copy_source) header = "x-amz-copy-source-if-none-match"; else header = "If-None-Match"; ret = dpl_dict_add(headers, header, condition->etag, 0); if (DPL_SUCCESS != ret) { return DPL_FAILURE; } } return DPL_SUCCESS; }
/** * build headers from request * * @param req * @param headersp * * @return */ dpl_status_t dpl_s3_req_build(const dpl_req_t *req, dpl_s3_req_mask_t req_mask, dpl_dict_t **headersp) { dpl_dict_t *headers = NULL; int ret, ret2; const char *method = dpl_method_str(req->method); char resource_ue[DPL_URL_LENGTH(strlen(req->resource) + (req->subresource ? strlen(req->subresource) : 0)) + 1]; DPL_TRACE(req->ctx, DPL_TRACE_REQ, "req_build method=%s bucket=%s resource=%s subresource=%s", method, req->bucket, req->resource, req->subresource); //resource if ('/' != req->resource[0]) { resource_ue[0] = '/'; dpl_url_encode(req->resource, resource_ue + 1); } else { resource_ue[0] = '/'; //some servers do not like encoded slash dpl_url_encode(req->resource + 1, resource_ue + 1); } // Append subresource if (req->subresource) { dpl_url_encode("?", resource_ue + strlen(resource_ue)); dpl_url_encode(req->subresource, resource_ue + strlen(resource_ue)); } headers = dpl_dict_new(13); if (NULL == headers) { ret = DPL_ENOMEM; goto end; } /* * per method headers */ if (DPL_METHOD_GET == req->method || DPL_METHOD_HEAD == req->method) { if (req->range_enabled) { ret2 = dpl_add_range_to_headers(&req->range, headers); if (DPL_SUCCESS != ret2) { ret = ret2; goto end; } } ret2 = add_conditions_to_headers(&req->condition, headers, 0); if (DPL_SUCCESS != ret2) { ret = ret2; goto end; } } else if (DPL_METHOD_PUT == req->method || DPL_METHOD_POST == req->method) { char buf[64]; if (NULL != req->cache_control) { ret2 = dpl_dict_add(headers, "Cache-Control", req->cache_control, 0); if (DPL_SUCCESS != ret2) { ret = ret2; goto end; } } if (NULL != req->content_disposition) { ret2 = dpl_dict_add(headers, "Content-Disposition", req->content_disposition, 0); if (DPL_SUCCESS != ret2) { ret = ret2; goto end; } } if (NULL != req->content_encoding) { ret2 = dpl_dict_add(headers, "Content-Encoding", req->content_encoding, 0); if (DPL_SUCCESS != ret2) { ret = ret2; goto end; } } if (req->behavior_flags & DPL_BEHAVIOR_MD5) { MD5_CTX ctx; u_char digest[MD5_DIGEST_LENGTH]; char b64_digest[DPL_BASE64_LENGTH(MD5_DIGEST_LENGTH) + 1]; u_int b64_digest_len; if (!req->data_enabled) { ret = DPL_EINVAL; goto end; } MD5_Init(&ctx); MD5_Update(&ctx, req->data_buf, req->data_len); MD5_Final(digest, &ctx); b64_digest_len = dpl_base64_encode(digest, MD5_DIGEST_LENGTH, (u_char *) b64_digest); b64_digest[b64_digest_len] = 0; ret2 = dpl_dict_add(headers, "Content-MD5", b64_digest, 0); if (DPL_SUCCESS != ret2) { ret = ret2; goto end; } } if (req->data_enabled) { snprintf(buf, sizeof (buf), "%u", req->data_len); ret2 = dpl_dict_add(headers, "Content-Length", buf, 0); if (DPL_SUCCESS != ret2) { ret = DPL_ENOMEM; goto end; } } if (NULL != req->content_type) { ret2 = dpl_dict_add(headers, "Content-Type", req->content_type, 0); if (DPL_SUCCESS != ret2) { ret = ret2; goto end; } } if (req->behavior_flags & DPL_BEHAVIOR_EXPECT) { ret2 = dpl_dict_add(headers, "Expect", "100-continue", 0); if (DPL_SUCCESS != ret2) { ret = DPL_ENOMEM; goto end; } } if (DPL_CANNED_ACL_UNDEF != req->canned_acl) { char *str; str = dpl_canned_acl_str(req->canned_acl); if (NULL == str) { ret = DPL_FAILURE; goto end; } ret2 = dpl_dict_add(headers, "x-amz-acl", str, 0); if (DPL_SUCCESS != ret2) { ret = DPL_ENOMEM; goto end; } } ret2 = add_metadata_to_headers(req->metadata, headers); if (DPL_SUCCESS != ret2) { ret = ret2; goto end; } if (DPL_STORAGE_CLASS_UNDEF != req->storage_class) { char *str; str = dpl_storage_class_str(req->storage_class); if (NULL == str) { ret = DPL_FAILURE; goto end; } ret2 = dpl_dict_add(headers, "x-amz-storage-class", str, 0); if (DPL_SUCCESS != ret2) { ret = DPL_ENOMEM; goto end; } } /* * copy */ if (req_mask & DPL_S3_REQ_COPY) { ret2 = add_source_to_headers(req, headers); if (DPL_SUCCESS != ret2) { ret = ret2; goto end; } if (DPL_COPY_DIRECTIVE_UNDEF != req->copy_directive) { char *str; switch (req->copy_directive) { case DPL_COPY_DIRECTIVE_UNDEF: case DPL_COPY_DIRECTIVE_COPY: case DPL_COPY_DIRECTIVE_LINK: case DPL_COPY_DIRECTIVE_SYMLINK: case DPL_COPY_DIRECTIVE_MOVE: case DPL_COPY_DIRECTIVE_MKDENT: case DPL_COPY_DIRECTIVE_RMDENT: case DPL_COPY_DIRECTIVE_MVDENT: ret = DPL_ENOTSUPP; goto end; case DPL_COPY_DIRECTIVE_METADATA_REPLACE: str = "REPLACE"; break ; } ret2 = dpl_dict_add(headers, "x-amz-metadata-directive", str, 0); if (DPL_SUCCESS != ret2) { ret = DPL_ENOMEM; goto end; } } ret2 = add_conditions_to_headers(&req->copy_source_condition, headers, 1); if (DPL_SUCCESS != ret2) { ret = ret2; goto end; } } } else if (DPL_METHOD_DELETE == req->method) { //XXX todo x-amz-mfa } else { ret = DPL_EINVAL; goto end; } /* * common headers */ if (req->behavior_flags & DPL_BEHAVIOR_KEEP_ALIVE) { ret2 = dpl_dict_add(headers, "Connection", "Keep-Alive", 0); if (DPL_SUCCESS != ret2) { ret = DPL_ENOMEM; goto end; } } ret2 = add_date_to_headers(headers); if (DPL_SUCCESS != ret2) { ret = ret2; goto end; } if (NULL != headersp) { *headersp = headers; headers = NULL; //consume it } ret = DPL_SUCCESS; end: if (NULL != headers) dpl_dict_free(headers); return ret; }