diff options
author | 2017-07-21 15:55:38 -0700 | |
---|---|---|
committer | 2017-07-21 15:55:38 -0700 | |
commit | 781fd6f6ea03645a520cd5c675da67ab61f87e4b (patch) | |
tree | 448ddfe243ec91548dc0a5b3c0d1b6ceecd7833c /src/core/ext | |
parent | e8e05f90a40c59a7ee6b1fe43fb097bb3badbeea (diff) | |
parent | d0c1e50ea91b9c4aefc7357a21daeae689d7bb48 (diff) |
Merge pull request #11884 from yashykt/connect-auth
HTTP CONNECT Auth support
Diffstat (limited to 'src/core/ext')
-rw-r--r-- | src/core/ext/filters/client_channel/http_proxy.c | 64 |
1 files changed, 54 insertions, 10 deletions
diff --git a/src/core/ext/filters/client_channel/http_proxy.c b/src/core/ext/filters/client_channel/http_proxy.c index aa3f61c991..ef3512ed83 100644 --- a/src/core/ext/filters/client_channel/http_proxy.c +++ b/src/core/ext/filters/client_channel/http_proxy.c @@ -30,15 +30,23 @@ #include "src/core/ext/filters/client_channel/proxy_mapper_registry.h" #include "src/core/ext/filters/client_channel/uri_parser.h" #include "src/core/lib/channel/channel_args.h" +#include "src/core/lib/slice/b64.h" #include "src/core/lib/support/env.h" #include "src/core/lib/support/string.h" -static char* grpc_get_http_proxy_server(grpc_exec_ctx* exec_ctx) { +/** + * Parses the 'http_proxy' env var and returns the proxy hostname to resolve or + * NULL on error. Also sets 'user_cred' to user credentials if present in the + * 'http_proxy' env var, otherwise leaves it unchanged. It is caller's + * responsibility to gpr_free user_cred. + */ +static char* get_http_proxy_server(grpc_exec_ctx* exec_ctx, char** user_cred) { + GPR_ASSERT(user_cred != NULL); + char* proxy_name = NULL; char* uri_str = gpr_getenv("http_proxy"); if (uri_str == NULL) return NULL; grpc_uri* uri = grpc_uri_parse(exec_ctx, uri_str, false /* suppress_errors */); - char* proxy_name = NULL; if (uri == NULL || uri->authority == NULL) { gpr_log(GPR_ERROR, "cannot parse value of 'http_proxy' env var"); goto done; @@ -47,11 +55,27 @@ static char* grpc_get_http_proxy_server(grpc_exec_ctx* exec_ctx) { gpr_log(GPR_ERROR, "'%s' scheme not supported in proxy URI", uri->scheme); goto done; } - if (strchr(uri->authority, '@') != NULL) { - gpr_log(GPR_ERROR, "userinfo not supported in proxy URI"); - goto done; + /* Split on '@' to separate user credentials from host */ + char** authority_strs = NULL; + size_t authority_nstrs; + gpr_string_split(uri->authority, "@", &authority_strs, &authority_nstrs); + GPR_ASSERT(authority_nstrs != 0); /* should have at least 1 string */ + if (authority_nstrs == 1) { + /* User cred not present in authority */ + proxy_name = authority_strs[0]; + } else if (authority_nstrs == 2) { + /* User cred found */ + *user_cred = authority_strs[0]; + proxy_name = authority_strs[1]; + gpr_log(GPR_DEBUG, "userinfo found in proxy URI"); + } else { + /* Bad authority */ + for (size_t i = 0; i < authority_nstrs; i++) { + gpr_free(authority_strs[i]); + } + proxy_name = NULL; } - proxy_name = gpr_strdup(uri->authority); + gpr_free(authority_strs); done: gpr_free(uri_str); grpc_uri_destroy(uri); @@ -64,7 +88,8 @@ static bool proxy_mapper_map_name(grpc_exec_ctx* exec_ctx, const grpc_channel_args* args, char** name_to_resolve, grpc_channel_args** new_args) { - *name_to_resolve = grpc_get_http_proxy_server(exec_ctx); + char* user_cred = NULL; + *name_to_resolve = get_http_proxy_server(exec_ctx, &user_cred); if (*name_to_resolve == NULL) return false; grpc_uri* uri = grpc_uri_parse(exec_ctx, server_uri, false /* suppress_errors */); @@ -73,12 +98,16 @@ static bool proxy_mapper_map_name(grpc_exec_ctx* exec_ctx, "'http_proxy' environment variable set, but cannot " "parse server URI '%s' -- not using proxy", server_uri); - if (uri != NULL) grpc_uri_destroy(uri); + if (uri != NULL) { + gpr_free(user_cred); + grpc_uri_destroy(uri); + } return false; } if (strcmp(uri->scheme, "unix") == 0) { gpr_log(GPR_INFO, "not using proxy for Unix domain socket '%s'", server_uri); + gpr_free(user_cred); grpc_uri_destroy(uri); return false; } @@ -126,10 +155,25 @@ static bool proxy_mapper_map_name(grpc_exec_ctx* exec_ctx, } } } - grpc_arg new_arg = grpc_channel_arg_string_create( + grpc_arg args_to_add[2]; + args_to_add[0] = grpc_channel_arg_string_create( GRPC_ARG_HTTP_CONNECT_SERVER, uri->path[0] == '/' ? uri->path + 1 : uri->path); - *new_args = grpc_channel_args_copy_and_add(args, &new_arg, 1); + if (user_cred != NULL) { + /* Use base64 encoding for user credentials as stated in RFC 7617 */ + char* encoded_user_cred = + grpc_base64_encode(user_cred, strlen(user_cred), 0, 0); + char* header; + gpr_asprintf(&header, "Proxy-Authorization:Basic %s", encoded_user_cred); + gpr_free(encoded_user_cred); + args_to_add[1] = + grpc_channel_arg_string_create(GRPC_ARG_HTTP_CONNECT_HEADERS, header); + *new_args = grpc_channel_args_copy_and_add(args, args_to_add, 2); + gpr_free(header); + } else { + *new_args = grpc_channel_args_copy_and_add(args, args_to_add, 1); + } + gpr_free(user_cred); grpc_uri_destroy(uri); return true; } |