summaryrefslogtreecommitdiffstats
path: root/src/responder
diff options
context:
space:
mode:
authorSimo Sorce <simo@redhat.com>2016-03-17 15:48:01 -0400
committerJakub Hrozek <jhrozek@redhat.com>2016-06-29 21:46:57 +0200
commite625eb47a3091d92eda2271b123f8aab06227b63 (patch)
treeb87f78d1e97f14ed3845d75f107c2e1381698f42 /src/responder
parent8f2a34cc6964a1f80a1434e05315a7ae0bb5774e (diff)
downloadsssd-e625eb47a3091d92eda2271b123f8aab06227b63.tar.gz
sssd-e625eb47a3091d92eda2271b123f8aab06227b63.tar.xz
sssd-e625eb47a3091d92eda2271b123f8aab06227b63.zip
Local secrets provider Content-Type handling
Properly handle and enforce ithe presence of the content-type header in the local and proxy providers to conform to the Custoida protocol. Avoids different behavior between the local provider and a remote server that may cause developers to have an application working against the local storage and then fail when the administrator configures a remote storage. Signed-off-by: Simo Sorce <simo@redhat.com> Reviewed-by: Jakub Hrozek <jhrozek@redhat.com>
Diffstat (limited to 'src/responder')
-rw-r--r--src/responder/secrets/local.c46
-rw-r--r--src/responder/secrets/providers.c27
-rw-r--r--src/responder/secrets/secsrv_private.h3
3 files changed, 68 insertions, 8 deletions
diff --git a/src/responder/secrets/local.c b/src/responder/secrets/local.c
index 6451ef95b..6fb46c3ce 100644
--- a/src/responder/secrets/local.c
+++ b/src/responder/secrets/local.c
@@ -405,6 +405,8 @@ struct tevent_req *local_secret_req(TALLOC_CTX *mem_ctx,
struct local_secret_state *state;
struct local_context *lctx;
struct sec_data body = { 0 };
+ const char *content_type;
+ bool body_is_json;
char *req_path;
char *secret;
char **keys;
@@ -423,6 +425,19 @@ struct tevent_req *local_secret_req(TALLOC_CTX *mem_ctx,
goto done;
}
+ if (sec_req_has_header(secreq, "Content-Type",
+ "application/json")) {
+ body_is_json = true;
+ content_type = "application/json";
+ } else if (sec_req_has_header(secreq, "Content-Type",
+ "application/octet-stream")) {
+ body_is_json = false;
+ content_type = "application/octet-stream";
+ } else {
+ ret = EINVAL;
+ goto done;
+ }
+
ret = local_secrets_map_path(state, secreq, &req_path);
if (ret) goto done;
@@ -434,21 +449,36 @@ struct tevent_req *local_secret_req(TALLOC_CTX *mem_ctx,
ret = sec_array_to_json(state, keys, nkeys, &body.data);
if (ret) goto done;
- } else {
- ret = local_db_get_simple(state, lctx, req_path, &secret);
- if (ret) goto done;
+ body.length = strlen(body.data);
+ break;
+ }
+
+ ret = local_db_get_simple(state, lctx, req_path, &secret);
+ if (ret) goto done;
+
+ if (body_is_json) {
ret = sec_simple_secret_to_json(state, secret, &body.data);
if (ret) goto done;
+
+ body.length = strlen(body.data);
+ } else {
+ body.data = (void *)sss_base64_decode(state, secret, &body.length);
+ ret = body.data ? EOK : ENOMEM;
}
+ if (ret) goto done;
- body.length = strlen(body.data);
break;
case HTTP_PUT:
- /*FIXME: check fot content-type */
-
- ret = sec_json_to_simple_secret(state, secreq->body.data, &secret);
+ if (body_is_json) {
+ ret = sec_json_to_simple_secret(state, secreq->body.data,
+ &secret);
+ } else {
+ secret = sss_base64_encode(state, (uint8_t *)secreq->body.data,
+ secreq->body.length);
+ ret = secret ? EOK : ENOMEM;
+ }
if (ret) goto done;
ret = local_db_put_simple(state, lctx, req_path, secret);
@@ -467,7 +497,7 @@ struct tevent_req *local_secret_req(TALLOC_CTX *mem_ctx,
if (body.data) {
ret = sec_http_reply_with_body(secreq, &secreq->reply, STATUS_200,
- "application/json", &body);
+ content_type, &body);
} else {
ret = sec_http_status_reply(secreq, &secreq->reply, STATUS_200);
}
diff --git a/src/responder/secrets/providers.c b/src/responder/secrets/providers.c
index 5dff01a7f..2826a7040 100644
--- a/src/responder/secrets/providers.c
+++ b/src/responder/secrets/providers.c
@@ -242,6 +242,8 @@ int sec_http_reply_with_headers(TALLOC_CTX *mem_ctx, struct sec_data *reply,
struct sec_data *body)
{
const char *reason_phrase = reason ? reason : "";
+ bool add_content_length = true;
+ bool has_content_type = false;
int ret;
/* Status-Line */
@@ -251,11 +253,24 @@ int sec_http_reply_with_headers(TALLOC_CTX *mem_ctx, struct sec_data *reply,
/* Headers */
for (int i = 0; i < num_headers; i++) {
+ if (strcasecmp(headers[i].name, "Content-Length") == 0) {
+ add_content_length = false;
+ } else if (strcasecmp(headers[i].name, "Content-Type") == 0) {
+ has_content_type = true;
+ }
ret = sec_http_append_header(mem_ctx, &reply->data,
headers[i].name, headers[i].value);
if (ret) return ret;
}
+ if (!has_content_type) return EINVAL;
+
+ if (add_content_length) {
+ reply->data = talloc_asprintf_append_buffer(reply->data,
+ "Content-Length: %u\r\n", (unsigned)body->length);
+ if (!reply->data) return ENOMEM;
+ }
+
/* CRLF separator before body */
reply->data = talloc_strdup_append_buffer(reply->data, "\r\n");
@@ -461,3 +476,15 @@ int sec_add_provider(struct sec_ctx *sctx, struct provider_handle *handle)
return EOK;
}
+
+bool sec_req_has_header(struct sec_req_ctx *req,
+ const char *name, const char *value)
+{
+ for (int i = 0; i < req->num_headers; i++) {
+ if (strcasecmp(name, req->headers[i].name) == 0) {
+ if (value == NULL) return true;
+ return (strcasecmp(value, req->headers[i].value) == 0);
+ }
+ }
+ return false;
+}
diff --git a/src/responder/secrets/secsrv_private.h b/src/responder/secrets/secsrv_private.h
index ce8cf8216..c3b663996 100644
--- a/src/responder/secrets/secsrv_private.h
+++ b/src/responder/secrets/secsrv_private.h
@@ -131,6 +131,9 @@ int sec_array_to_json(TALLOC_CTX *mem_ctx,
char **array, int count,
char **output);
+bool sec_req_has_header(struct sec_req_ctx *req,
+ const char *name, const char *value);
+
/* secsrv_cmd.c */
#define SEC_REQUEST_MAX_SIZE 65536
#define SEC_PACKET_MAX_RECV_SIZE 8192