static dpl_status_t add_data_to_json_body(dpl_chunk_t *chunk, json_object *body_obj) { int ret; json_object *data_obj = NULL; char *base64_str; int base64_len; //encode body to base64 base64_str = alloca(DPL_BASE64_LENGTH(chunk->len) + 1); base64_len = dpl_base64_encode((const u_char *) chunk->buf, chunk->len, (u_char *) base64_str); base64_str[base64_len] = 0; data_obj = json_object_new_string(base64_str); if (NULL == data_obj) { ret = DPL_ENOMEM; goto end; } json_object_object_add(body_obj, "value", data_obj); //XXX check return value data_obj = NULL; ret = DPL_SUCCESS; end: if (NULL != data_obj) json_object_put(data_obj); return ret; }
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; }
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; }
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); }
/* 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; }
/** * 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; }