blob: 8416bfa5a86b267cd71371b29f6a34d452682bdb [file] [log] [blame]
Julien Boeuf8ca294e2016-05-02 14:56:30 -07001/*
2 *
3 * Copyright 2016, Google Inc.
4 * All rights reserved.
5 *
6 * Redistribution and use in source and binary forms, with or without
7 * modification, are permitted provided that the following conditions are
8 * met:
9 *
10 * * Redistributions of source code must retain the above copyright
11 * notice, this list of conditions and the following disclaimer.
12 * * Redistributions in binary form must reproduce the above
13 * copyright notice, this list of conditions and the following disclaimer
14 * in the documentation and/or other materials provided with the
15 * distribution.
16 * * Neither the name of Google Inc. nor the names of its
17 * contributors may be used to endorse or promote products derived from
18 * this software without specific prior written permission.
19 *
20 * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
21 * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
22 * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
23 * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
24 * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
25 * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
26 * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
27 * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
28 * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
29 * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
30 * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
31 *
32 */
33
34#include "src/core/lib/security/credentials/plugin/plugin_credentials.h"
35
36#include <string.h>
37
yang-gc580af32016-09-15 15:28:38 -070038#include <grpc/grpc.h>
Julien Boeuf8ca294e2016-05-02 14:56:30 -070039#include <grpc/support/alloc.h>
40#include <grpc/support/log.h>
41#include <grpc/support/string_util.h>
42#include <grpc/support/sync.h>
43
Craig Tillerbd1795c2016-10-31 15:30:00 -070044#include "src/core/lib/slice/slice_internal.h"
Craig Tiller7c70b6c2017-01-23 07:48:42 -080045#include "src/core/lib/slice/slice_string_helpers.h"
Craig Tillerbd1795c2016-10-31 15:30:00 -070046#include "src/core/lib/surface/api_trace.h"
Craig Tiller7c70b6c2017-01-23 07:48:42 -080047#include "src/core/lib/surface/validate_metadata.h"
Craig Tillerbd1795c2016-10-31 15:30:00 -070048
Julien Boeuf8ca294e2016-05-02 14:56:30 -070049typedef struct {
50 void *user_data;
51 grpc_credentials_metadata_cb cb;
52} grpc_metadata_plugin_request;
53
Craig Tillerbd1795c2016-10-31 15:30:00 -070054static void plugin_destruct(grpc_exec_ctx *exec_ctx,
55 grpc_call_credentials *creds) {
Julien Boeuf8ca294e2016-05-02 14:56:30 -070056 grpc_plugin_credentials *c = (grpc_plugin_credentials *)creds;
57 if (c->plugin.state != NULL && c->plugin.destroy != NULL) {
58 c->plugin.destroy(c->plugin.state);
59 }
60}
61
62static void plugin_md_request_metadata_ready(void *request,
63 const grpc_metadata *md,
64 size_t num_md,
65 grpc_status_code status,
66 const char *error_details) {
67 /* called from application code */
Craig Tiller7c70b6c2017-01-23 07:48:42 -080068 grpc_exec_ctx exec_ctx = GRPC_EXEC_CTX_INITIALIZER(
69 GRPC_EXEC_CTX_FLAG_IS_FINISHED | GRPC_EXEC_CTX_FLAG_THREAD_RESOURCE_LOOP,
70 NULL, NULL);
Julien Boeuf8ca294e2016-05-02 14:56:30 -070071 grpc_metadata_plugin_request *r = (grpc_metadata_plugin_request *)request;
72 if (status != GRPC_STATUS_OK) {
73 if (error_details != NULL) {
74 gpr_log(GPR_ERROR, "Getting metadata from plugin failed with error: %s",
75 error_details);
76 }
Julien Boeufbfc7ed62016-06-04 18:03:42 -070077 r->cb(&exec_ctx, r->user_data, NULL, 0, GRPC_CREDENTIALS_ERROR,
78 error_details);
Julien Boeuf8ca294e2016-05-02 14:56:30 -070079 } else {
80 size_t i;
yang-gc580af32016-09-15 15:28:38 -070081 bool seen_illegal_header = false;
Julien Boeuf8ca294e2016-05-02 14:56:30 -070082 grpc_credentials_md *md_array = NULL;
yang-gc580af32016-09-15 15:28:38 -070083 for (i = 0; i < num_md; i++) {
Craig Tiller7c70b6c2017-01-23 07:48:42 -080084 if (!GRPC_LOG_IF_ERROR("validate_metadata_from_plugin",
85 grpc_validate_header_key_is_legal(md[i].key))) {
yang-gc580af32016-09-15 15:28:38 -070086 seen_illegal_header = true;
87 break;
Craig Tiller7c70b6c2017-01-23 07:48:42 -080088 } else if (!grpc_is_binary_header(md[i].key) &&
89 !GRPC_LOG_IF_ERROR(
90 "validate_metadata_from_plugin",
91 grpc_validate_header_nonbin_value_is_legal(md[i].value))) {
yang-gc580af32016-09-15 15:28:38 -070092 gpr_log(GPR_ERROR, "Plugin added invalid metadata value.");
93 seen_illegal_header = true;
94 break;
95 }
96 }
97 if (seen_illegal_header) {
98 r->cb(&exec_ctx, r->user_data, NULL, 0, GRPC_CREDENTIALS_ERROR,
99 "Illegal metadata");
100 } else if (num_md > 0) {
Julien Boeuf8ca294e2016-05-02 14:56:30 -0700101 md_array = gpr_malloc(num_md * sizeof(grpc_credentials_md));
102 for (i = 0; i < num_md; i++) {
Craig Tiller7c70b6c2017-01-23 07:48:42 -0800103 md_array[i].key = grpc_slice_ref_internal(md[i].key);
104 md_array[i].value = grpc_slice_ref_internal(md[i].value);
Julien Boeuf8ca294e2016-05-02 14:56:30 -0700105 }
yang-gc580af32016-09-15 15:28:38 -0700106 r->cb(&exec_ctx, r->user_data, md_array, num_md, GRPC_CREDENTIALS_OK,
107 NULL);
Julien Boeuf8ca294e2016-05-02 14:56:30 -0700108 for (i = 0; i < num_md; i++) {
Craig Tillerbd1795c2016-10-31 15:30:00 -0700109 grpc_slice_unref_internal(&exec_ctx, md_array[i].key);
110 grpc_slice_unref_internal(&exec_ctx, md_array[i].value);
Julien Boeuf8ca294e2016-05-02 14:56:30 -0700111 }
112 gpr_free(md_array);
Jan Tattermusch998fdd02016-11-09 22:54:05 +0100113 } else if (num_md == 0) {
114 r->cb(&exec_ctx, r->user_data, NULL, 0, GRPC_CREDENTIALS_OK, NULL);
Julien Boeuf8ca294e2016-05-02 14:56:30 -0700115 }
116 }
117 gpr_free(r);
118 grpc_exec_ctx_finish(&exec_ctx);
119}
120
121static void plugin_get_request_metadata(grpc_exec_ctx *exec_ctx,
122 grpc_call_credentials *creds,
David Garcia Quintas2a50dfe2016-05-31 15:09:12 -0700123 grpc_polling_entity *pollent,
Julien Boeuf8ca294e2016-05-02 14:56:30 -0700124 grpc_auth_metadata_context context,
125 grpc_credentials_metadata_cb cb,
126 void *user_data) {
127 grpc_plugin_credentials *c = (grpc_plugin_credentials *)creds;
128 if (c->plugin.get_metadata != NULL) {
Craig Tiller6f417882017-02-16 14:09:39 -0800129 grpc_metadata_plugin_request *request = gpr_zalloc(sizeof(*request));
Julien Boeuf8ca294e2016-05-02 14:56:30 -0700130 request->user_data = user_data;
131 request->cb = cb;
132 c->plugin.get_metadata(c->plugin.state, context,
133 plugin_md_request_metadata_ready, request);
134 } else {
Julien Boeufbfc7ed62016-06-04 18:03:42 -0700135 cb(exec_ctx, user_data, NULL, 0, GRPC_CREDENTIALS_OK, NULL);
Julien Boeuf8ca294e2016-05-02 14:56:30 -0700136 }
137}
138
139static grpc_call_credentials_vtable plugin_vtable = {
140 plugin_destruct, plugin_get_request_metadata};
141
142grpc_call_credentials *grpc_metadata_credentials_create_from_plugin(
143 grpc_metadata_credentials_plugin plugin, void *reserved) {
Craig Tiller6f417882017-02-16 14:09:39 -0800144 grpc_plugin_credentials *c = gpr_zalloc(sizeof(*c));
Julien Boeuf8ca294e2016-05-02 14:56:30 -0700145 GRPC_API_TRACE("grpc_metadata_credentials_create_from_plugin(reserved=%p)", 1,
146 (reserved));
147 GPR_ASSERT(reserved == NULL);
Julien Boeuf8ca294e2016-05-02 14:56:30 -0700148 c->base.type = plugin.type;
149 c->base.vtable = &plugin_vtable;
150 gpr_ref_init(&c->base.refcount, 1);
151 c->plugin = plugin;
152 return &c->base;
153}