aboutsummaryrefslogtreecommitdiffhomepage
path: root/src/core/security/auth.c
diff options
context:
space:
mode:
Diffstat (limited to 'src/core/security/auth.c')
-rw-r--r--src/core/security/auth.c61
1 files changed, 24 insertions, 37 deletions
diff --git a/src/core/security/auth.c b/src/core/security/auth.c
index 130698c11b..4af2c67d83 100644
--- a/src/core/security/auth.c
+++ b/src/core/security/auth.c
@@ -44,12 +44,15 @@
#include "src/core/security/credentials.h"
#include "src/core/surface/call.h"
+#define MAX_CREDENTIALS_METADATA_COUNT 4
+
/* We can have a per-call credentials. */
typedef struct {
grpc_credentials *creds;
grpc_mdstr *host;
grpc_mdstr *method;
grpc_call_op op;
+ grpc_linked_mdelem md_links[MAX_CREDENTIALS_METADATA_COUNT];
} call_data;
/* We can have a per-channel credentials. */
@@ -62,30 +65,8 @@ typedef struct {
grpc_mdstr *status_key;
} channel_data;
-static void do_nothing(void *ignored, grpc_op_error error) {}
-
static void bubbleup_error(grpc_call_element *elem, const char *error_msg) {
- grpc_call_op finish_op;
- channel_data *channeld = elem->channel_data;
- char status[GPR_LTOA_MIN_BUFSIZE];
-
- gpr_log(GPR_ERROR, "%s", error_msg);
- finish_op.type = GRPC_RECV_METADATA;
- finish_op.dir = GRPC_CALL_UP;
- finish_op.flags = 0;
- finish_op.data.metadata = grpc_mdelem_from_metadata_strings(
- channeld->md_ctx, grpc_mdstr_ref(channeld->error_msg_key),
- grpc_mdstr_from_string(channeld->md_ctx, error_msg));
- finish_op.done_cb = do_nothing;
- finish_op.user_data = NULL;
- grpc_call_next_op(elem, &finish_op);
-
- gpr_ltoa(GRPC_STATUS_UNAUTHENTICATED, status);
- finish_op.data.metadata = grpc_mdelem_from_metadata_strings(
- channeld->md_ctx, grpc_mdstr_ref(channeld->status_key),
- grpc_mdstr_from_string(channeld->md_ctx, status));
- grpc_call_next_op(elem, &finish_op);
-
+ grpc_call_element_recv_status(elem, GRPC_STATUS_UNAUTHENTICATED, error_msg);
grpc_call_element_send_cancel(elem);
}
@@ -93,11 +74,15 @@ static void on_credentials_metadata(void *user_data, grpc_mdelem **md_elems,
size_t num_md,
grpc_credentials_status status) {
grpc_call_element *elem = (grpc_call_element *)user_data;
+ call_data *calld = elem->call_data;
+ grpc_call_op op = calld->op;
size_t i;
+ GPR_ASSERT(num_md <= MAX_CREDENTIALS_METADATA_COUNT);
for (i = 0; i < num_md; i++) {
- grpc_call_element_send_metadata(elem, grpc_mdelem_ref(md_elems[i]));
+ grpc_metadata_batch_add_tail(&op.data.metadata, &calld->md_links[i],
+ grpc_mdelem_ref(md_elems[i]));
}
- grpc_call_next_op(elem, &((call_data *)elem->call_data)->op);
+ grpc_call_next_op(elem, &op);
}
static char *build_service_url(const char *url_scheme, call_data *calld) {
@@ -159,6 +144,7 @@ static void on_host_checked(void *user_data, grpc_security_status status) {
gpr_asprintf(&error_msg, "Invalid host %s set in :authority metadata.",
grpc_mdstr_as_c_string(calld->host));
bubbleup_error(elem, error_msg);
+ grpc_metadata_batch_destroy(&calld->op.data.metadata);
gpr_free(error_msg);
calld->op.done_cb(calld->op.user_data, GRPC_OP_ERROR);
}
@@ -174,21 +160,22 @@ static void call_op(grpc_call_element *elem, grpc_call_element *from_elem,
/* grab pointers to our data from the call element */
call_data *calld = elem->call_data;
channel_data *channeld = elem->channel_data;
+ grpc_linked_mdelem *l;
switch (op->type) {
case GRPC_SEND_METADATA:
- /* Pointer comparison is OK for md_elems created from the same context. */
- if (op->data.metadata->key == channeld->authority_string) {
- if (calld->host != NULL) grpc_mdstr_unref(calld->host);
- calld->host = grpc_mdstr_ref(op->data.metadata->value);
- } else if (op->data.metadata->key == channeld->path_string) {
- if (calld->method != NULL) grpc_mdstr_unref(calld->method);
- calld->method = grpc_mdstr_ref(op->data.metadata->value);
+ for (l = op->data.metadata.list.head; l != NULL; l = l->next) {
+ grpc_mdelem *md = l->md;
+ /* Pointer comparison is OK for md_elems created from the same context.
+ */
+ if (md->key == channeld->authority_string) {
+ if (calld->host != NULL) grpc_mdstr_unref(calld->host);
+ calld->host = grpc_mdstr_ref(md->value);
+ } else if (md->key == channeld->path_string) {
+ if (calld->method != NULL) grpc_mdstr_unref(calld->method);
+ calld->method = grpc_mdstr_ref(md->value);
+ }
}
- grpc_call_next_op(elem, op);
- break;
-
- case GRPC_SEND_START:
if (calld->host != NULL) {
grpc_security_status status;
const char *call_host = grpc_mdstr_as_c_string(calld->host);
@@ -202,6 +189,7 @@ static void call_op(grpc_call_element *elem, grpc_call_element *from_elem,
"Invalid host %s set in :authority metadata.",
call_host);
bubbleup_error(elem, error_msg);
+ grpc_metadata_batch_destroy(&calld->op.data.metadata);
gpr_free(error_msg);
op->done_cb(op->user_data, GRPC_OP_ERROR);
}
@@ -210,7 +198,6 @@ static void call_op(grpc_call_element *elem, grpc_call_element *from_elem,
}
send_security_metadata(elem, op);
break;
-
default:
/* pass control up or down the stack depending on op->dir */
grpc_call_next_op(elem, op);