diff --git a/Makefile b/Makefile index 2123b5dca1c..35c2d848003 100644 --- a/Makefile +++ b/Makefile @@ -1224,6 +1224,7 @@ LIBGRPC_SRC = \ src/core/security/auth.c \ src/core/security/base64.c \ src/core/security/credentials.c \ + src/core/security/factories.c \ src/core/security/google_root_certs.c \ src/core/security/json_token.c \ src/core/security/secure_endpoint.c \ diff --git a/build.json b/build.json index ee92033e886..659b24d0768 100644 --- a/build.json +++ b/build.json @@ -257,6 +257,7 @@ "src/core/security/auth.c", "src/core/security/base64.c", "src/core/security/credentials.c", + "src/core/security/factories.c", "src/core/security/google_root_certs.c", "src/core/security/json_token.c", "src/core/security/secure_endpoint.c", diff --git a/include/grpc/grpc_security.h b/include/grpc/grpc_security.h index 26f373d5caa..644b31f763b 100644 --- a/include/grpc/grpc_security.h +++ b/include/grpc/grpc_security.h @@ -97,7 +97,6 @@ grpc_credentials *grpc_fake_transport_security_credentials_create(void); grpc_credentials *grpc_iam_credentials_create(const char *authorization_token, const char *authority_selector); - /* --- Secure channel creation. --- */ /* The caller of the secure_channel_create functions may override the target @@ -152,7 +151,6 @@ grpc_server_credentials *grpc_ssl_server_credentials_create( grpc_server_credentials *grpc_fake_transport_security_server_credentials_create( void); - /* --- Secure server creation. --- */ /* Creates a secure server using the passed-in server credentials. */ diff --git a/src/core/security/credentials.c b/src/core/security/credentials.c index c99ac8021d9..d3bba0fb1f6 100644 --- a/src/core/security/credentials.c +++ b/src/core/security/credentials.c @@ -819,6 +819,26 @@ const grpc_credentials_array *grpc_composite_credentials_get_credentials( return &c->inner; } +grpc_credentials *grpc_credentials_contains_type( + grpc_credentials *creds, const char *type, + grpc_credentials **composite_creds) { + size_t i; + if (!strcmp(creds->type, type)) { + if (composite_creds != NULL) *composite_creds = NULL; + return creds; + } else if (!strcmp(creds->type, GRPC_CREDENTIALS_TYPE_COMPOSITE)) { + const grpc_credentials_array *inner_creds_array = + grpc_composite_credentials_get_credentials(creds); + for (i = 0; i < inner_creds_array->num_creds; i++) { + if (!strcmp(type, inner_creds_array->creds_array[i]->type)) { + if (composite_creds != NULL) *composite_creds = creds; + return inner_creds_array->creds_array[i]; + } + } + } + return NULL; +} + /* -- IAM credentials. -- */ typedef struct { @@ -877,4 +897,3 @@ grpc_credentials *grpc_iam_credentials_create(const char *token, /* -- Default credentials TODO(jboeuf). -- */ grpc_credentials *grpc_default_credentials_create(void) { return NULL; } - diff --git a/src/core/security/credentials.h b/src/core/security/credentials.h index 036a44493e2..8559f239d51 100644 --- a/src/core/security/credentials.h +++ b/src/core/security/credentials.h @@ -108,6 +108,14 @@ typedef struct { const grpc_credentials_array *grpc_composite_credentials_get_credentials( grpc_credentials *composite_creds); +/* Returns creds if creds is of the specified type or the inner creds of the + specified type (if found), if the creds is of type COMPOSITE. + If composite_creds is not NULL, *composite_creds will point to creds if of + type COMPOSITE in case of success. */ +grpc_credentials *grpc_credentials_contains_type( + grpc_credentials *creds, const char *type, + grpc_credentials **composite_creds); + /* Exposed for testing only. */ grpc_credentials_status grpc_oauth2_token_fetcher_credentials_parse_server_response( @@ -118,7 +126,6 @@ grpc_oauth2_token_fetcher_credentials_parse_server_response( grpc_credentials *grpc_fake_oauth2_credentials_create( const char *token_md_value, int is_async); - /* --- grpc_server_credentials. --- */ typedef struct { @@ -136,5 +143,4 @@ struct grpc_server_credentials { const grpc_ssl_config *grpc_ssl_server_credentials_get_config( const grpc_server_credentials *ssl_creds); - #endif /* __GRPC_INTERNAL_SECURITY_CREDENTIALS_H__ */ diff --git a/src/core/security/factories.c b/src/core/security/factories.c new file mode 100644 index 00000000000..d89c692989c --- /dev/null +++ b/src/core/security/factories.c @@ -0,0 +1,80 @@ +/* + * + * Copyright 2014, Google Inc. + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions are + * met: + * + * * Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * * Redistributions in binary form must reproduce the above + * copyright notice, this list of conditions and the following disclaimer + * in the documentation and/or other materials provided with the + * distribution. + * * Neither the name of Google Inc. nor the names of its + * contributors may be used to endorse or promote products derived from + * this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS + * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT + * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR + * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT + * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, + * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT + * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, + * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY + * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE + * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + * + */ + +#include + +#include "src/core/security/credentials.h" +#include "src/core/security/security_context.h" +#include "src/core/surface/lame_client.h" +#include +#include +#include + +grpc_channel *grpc_secure_channel_create(grpc_credentials *creds, + const char *target, + const grpc_channel_args *args) { + grpc_secure_channel_factory factories[] = { + {GRPC_CREDENTIALS_TYPE_SSL, grpc_ssl_channel_create}, + {GRPC_CREDENTIALS_TYPE_FAKE_TRANSPORT_SECURITY, + grpc_fake_transport_security_channel_create}}; + return grpc_secure_channel_create_with_factories( + factories, GPR_ARRAY_SIZE(factories), creds, target, args); +} + +grpc_server *grpc_secure_server_create(grpc_server_credentials *creds, + grpc_completion_queue *cq, + const grpc_channel_args *args) { + grpc_security_status status = GRPC_SECURITY_ERROR; + grpc_security_context *ctx = NULL; + grpc_server *server = NULL; + if (creds == NULL) return NULL; /* TODO(ctiller): Return lame server. */ + + if (!strcmp(creds->type, GRPC_CREDENTIALS_TYPE_SSL)) { + status = grpc_ssl_server_security_context_create( + grpc_ssl_server_credentials_get_config(creds), &ctx); + } else if (!strcmp(creds->type, + GRPC_CREDENTIALS_TYPE_FAKE_TRANSPORT_SECURITY)) { + ctx = grpc_fake_server_security_context_create(); + status = GRPC_SECURITY_OK; + } + + if (status != GRPC_SECURITY_OK) { + gpr_log(GPR_ERROR, + "Unable to create secure server with credentials of type %s.", + creds->type); + return NULL; /* TODO(ctiller): Return lame server. */ + } + server = grpc_secure_server_create_internal(cq, args, ctx); + grpc_security_context_unref(ctx); + return server; +} diff --git a/src/core/security/security_context.c b/src/core/security/security_context.c index 917a22f4538..a0c72e2d699 100644 --- a/src/core/security/security_context.c +++ b/src/core/security/security_context.c @@ -438,19 +438,18 @@ error: return GRPC_SECURITY_ERROR; } - - /* -- High level objects. -- */ -static grpc_channel *grpc_ssl_channel_create(grpc_credentials *creds, - const grpc_ssl_config *config, - const char *target, - const grpc_channel_args *args) { +grpc_channel *grpc_ssl_channel_create(grpc_credentials *ssl_creds, + grpc_credentials *request_metadata_creds, + const char *target, + const grpc_channel_args *args) { grpc_channel_security_context *ctx = NULL; grpc_channel *channel = NULL; grpc_security_status status = GRPC_SECURITY_OK; size_t i = 0; const char *secure_peer_name = target; + for (i = 0; args && i < args->num_args; i++) { grpc_arg *arg = &args->args[i]; if (!strcmp(arg->key, GRPC_SSL_TARGET_NAME_OVERRIDE_ARG) && @@ -459,8 +458,9 @@ static grpc_channel *grpc_ssl_channel_create(grpc_credentials *creds, break; } } - status = grpc_ssl_channel_security_context_create(creds, config, - secure_peer_name, &ctx); + status = grpc_ssl_channel_security_context_create( + request_metadata_creds, grpc_ssl_credentials_get_config(ssl_creds), + secure_peer_name, &ctx); if (status != GRPC_SECURITY_OK) { return grpc_lame_client_channel_create(); } @@ -469,36 +469,22 @@ static grpc_channel *grpc_ssl_channel_create(grpc_credentials *creds, return channel; } - -static grpc_credentials *get_creds_from_composite( - grpc_credentials *composite_creds, const char *type) { - size_t i; - const grpc_credentials_array *inner_creds_array = - grpc_composite_credentials_get_credentials(composite_creds); - for (i = 0; i < inner_creds_array->num_creds; i++) { - if (!strcmp(type, inner_creds_array->creds_array[i]->type)) { - return inner_creds_array->creds_array[i]; - } - } - return NULL; +grpc_channel *grpc_fake_transport_security_channel_create( + grpc_credentials *fake_creds, grpc_credentials *request_metadata_creds, + const char *target, const grpc_channel_args *args) { + grpc_channel_security_context *ctx = + grpc_fake_channel_security_context_create(request_metadata_creds); + grpc_channel *channel = + grpc_secure_channel_create_internal(target, args, ctx); + grpc_security_context_unref(&ctx->base); + return channel; } -static grpc_channel *grpc_channel_create_from_composite_creds( - grpc_credentials *composite_creds, const char *target, +grpc_channel *grpc_secure_channel_create_with_factories( + const grpc_secure_channel_factory *factories, size_t num_factories, + grpc_credentials *creds, const char *target, const grpc_channel_args *args) { - grpc_credentials *creds = - get_creds_from_composite(composite_creds, GRPC_CREDENTIALS_TYPE_SSL); - if (creds != NULL) { - return grpc_ssl_channel_create( - composite_creds, grpc_ssl_credentials_get_config(creds), target, args); - } - gpr_log(GPR_ERROR, "Credentials is insufficient to create a secure channel."); - return grpc_lame_client_channel_create(); -} - -grpc_channel *grpc_secure_channel_create(grpc_credentials *creds, - const char *target, - const grpc_channel_args *args) { + size_t i; if (creds == NULL) { gpr_log(GPR_ERROR, "No credentials to create a secure channel."); return grpc_lame_client_channel_create(); @@ -508,25 +494,22 @@ grpc_channel *grpc_secure_channel_create(grpc_credentials *creds, "Credentials is insufficient to create a secure channel."); return grpc_lame_client_channel_create(); } - if (!strcmp(creds->type, GRPC_CREDENTIALS_TYPE_SSL)) { - return grpc_ssl_channel_create(NULL, grpc_ssl_credentials_get_config(creds), - target, args); - } else if (!strcmp(creds->type, - GRPC_CREDENTIALS_TYPE_FAKE_TRANSPORT_SECURITY)) { - grpc_channel_security_context *ctx = - grpc_fake_channel_security_context_create(NULL); - grpc_channel *channel = - grpc_secure_channel_create_internal(target, args, ctx); - grpc_security_context_unref(&ctx->base); - return channel; - } else if (!strcmp(creds->type, GRPC_CREDENTIALS_TYPE_COMPOSITE)) { - return grpc_channel_create_from_composite_creds(creds, target, args); - } else { - gpr_log(GPR_ERROR, - "Unknown credentials type %s for creating a secure channel.", - creds->type); - return grpc_lame_client_channel_create(); + + for (i = 0; i < num_factories; i++) { + grpc_credentials *composite_creds = NULL; + grpc_credentials *transport_security_creds = NULL; + transport_security_creds = grpc_credentials_contains_type( + creds, factories[i].creds_type, &composite_creds); + if (transport_security_creds != NULL) { + return factories[i].factory(transport_security_creds, composite_creds, + target, args); + } } + + gpr_log(GPR_ERROR, + "Unknown credentials type %s for creating a secure channel.", + creds->type); + return grpc_lame_client_channel_create(); } grpc_channel *grpc_default_secure_channel_create( @@ -534,30 +517,3 @@ grpc_channel *grpc_default_secure_channel_create( return grpc_secure_channel_create(grpc_default_credentials_create(), target, args); } - -grpc_server *grpc_secure_server_create(grpc_server_credentials *creds, - grpc_completion_queue *cq, - const grpc_channel_args *args) { - grpc_security_status status = GRPC_SECURITY_ERROR; - grpc_security_context *ctx = NULL; - grpc_server *server = NULL; - if (creds == NULL) return NULL; /* TODO(ctiller): Return lame server. */ - if (!strcmp(creds->type, GRPC_CREDENTIALS_TYPE_SSL)) { - status = grpc_ssl_server_security_context_create( - grpc_ssl_server_credentials_get_config(creds), &ctx); - } else if (!strcmp(creds->type, - GRPC_CREDENTIALS_TYPE_FAKE_TRANSPORT_SECURITY)) { - ctx = grpc_fake_server_security_context_create(); - status = GRPC_SECURITY_OK; - } else { - gpr_log(GPR_ERROR, - "Unable to create secure server with credentials of type %s.", - creds->type); - } - if (status != GRPC_SECURITY_OK) { - return NULL; /* TODO(ctiller): Return lame server. */ - } - server = grpc_secure_server_create_internal(cq, args, ctx); - grpc_security_context_unref(ctx); - return server; -} diff --git a/src/core/security/security_context.h b/src/core/security/security_context.h index bbd7ff3b1a5..65073abf0cb 100644 --- a/src/core/security/security_context.h +++ b/src/core/security/security_context.h @@ -159,17 +159,41 @@ grpc_security_status grpc_ssl_channel_security_context_create( grpc_security_status grpc_ssl_server_security_context_create( const grpc_ssl_config *config, grpc_security_context **ctx); - /* --- Creation of high level objects. --- */ /* Secure client channel creation. */ + +grpc_channel *grpc_ssl_channel_create(grpc_credentials *ssl_creds, + grpc_credentials *request_metadata_creds, + const char *target, + const grpc_channel_args *args); + +grpc_channel *grpc_fake_transport_security_channel_create( + grpc_credentials *fake_creds, grpc_credentials *request_metadata_creds, + const char *target, const grpc_channel_args *args); + grpc_channel *grpc_secure_channel_create_internal( const char *target, const grpc_channel_args *args, grpc_channel_security_context *ctx); +typedef grpc_channel *(*grpc_secure_channel_factory_func)( + grpc_credentials *transport_security_creds, + grpc_credentials *request_metadata_creds, const char *target, + const grpc_channel_args *args); + +typedef struct { + const char *creds_type; + grpc_secure_channel_factory_func factory; +} grpc_secure_channel_factory; + +grpc_channel *grpc_secure_channel_create_with_factories( + const grpc_secure_channel_factory *factories, size_t num_factories, + grpc_credentials *creds, const char *target, const grpc_channel_args *args); + /* Secure server creation. */ -grpc_server *grpc_secure_server_create_internal( - grpc_completion_queue *cq, const grpc_channel_args *args, - grpc_security_context *ctx); -#endif /* __GRPC_INTERNAL_SECURITY_SECURITY_CONTEXT_H__ */ +grpc_server *grpc_secure_server_create_internal(grpc_completion_queue *cq, + const grpc_channel_args *args, + grpc_security_context *ctx); + +#endif /* __GRPC_INTERNAL_SECURITY_SECURITY_CONTEXT_H__ */ diff --git a/src/cpp/client/credentials.cc b/src/cpp/client/credentials.cc index cac1d3d106c..430582b263b 100644 --- a/src/cpp/client/credentials.cc +++ b/src/cpp/client/credentials.cc @@ -34,7 +34,7 @@ #include -#include +#include #include #include diff --git a/src/cpp/server/server_credentials.cc b/src/cpp/server/server_credentials.cc index f9ca1622bac..fe6c8f9a986 100644 --- a/src/cpp/server/server_credentials.cc +++ b/src/cpp/server/server_credentials.cc @@ -32,7 +32,7 @@ */ -#include +#include #include diff --git a/vsprojects/vs2013/grpc.vcxproj b/vsprojects/vs2013/grpc.vcxproj index 294b73f155e..9a8c0e2edda 100644 --- a/vsprojects/vs2013/grpc.vcxproj +++ b/vsprojects/vs2013/grpc.vcxproj @@ -175,6 +175,8 @@ + + diff --git a/vsprojects/vs2013/grpc_unsecure.vcxproj b/vsprojects/vs2013/grpc_unsecure.vcxproj index 294b73f155e..9a8c0e2edda 100644 --- a/vsprojects/vs2013/grpc_unsecure.vcxproj +++ b/vsprojects/vs2013/grpc_unsecure.vcxproj @@ -175,6 +175,8 @@ + +