Skip to content

Commit

Permalink
extend local credentials to support tcp loopback.
Browse files Browse the repository at this point in the history
  • Loading branch information
yihuazhang committed Dec 12, 2018
1 parent a310778 commit 42861db
Show file tree
Hide file tree
Showing 10 changed files with 183 additions and 56 deletions.
6 changes: 3 additions & 3 deletions include/grpc/grpc_security_constants.h
Original file line number Diff line number Diff line change
Expand Up @@ -106,10 +106,10 @@ typedef enum {
} grpc_ssl_client_certificate_request_type;

/**
* Type of local connection for which local channel/server credentials will be
* applied. It only supports UDS for now.
* Type of local connections for which local channel/server credentials will be
* applied. It supports UDS and local TCP connections.
*/
typedef enum { UDS = 0 } grpc_local_connect_type;
typedef enum { UDS = 0, LOCAL_TCP } grpc_local_connect_type;

#ifdef __cplusplus
}
Expand Down
1 change: 1 addition & 0 deletions src/core/lib/http/httpcli_security_connector.cc
Original file line number Diff line number Diff line change
Expand Up @@ -71,6 +71,7 @@ static void httpcli_ssl_add_handshakers(grpc_channel_security_connector* sc,
}

static void httpcli_ssl_check_peer(grpc_security_connector* sc, tsi_peer peer,
grpc_endpoint* ep,
grpc_auth_context** auth_context,
grpc_closure* on_peer_checked) {
grpc_httpcli_ssl_channel_security_connector* c =
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -177,7 +177,7 @@ grpc_security_status grpc_alts_auth_context_from_tsi_peer(
} // namespace grpc_core

static void alts_check_peer(grpc_security_connector* sc, tsi_peer peer,
grpc_auth_context** auth_context,
grpc_endpoint* ep, grpc_auth_context** auth_context,
grpc_closure* on_peer_checked) {
grpc_security_status status;
status = grpc_core::internal::grpc_alts_auth_context_from_tsi_peer(
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -157,6 +157,7 @@ static void fake_check_peer(grpc_security_connector* sc, tsi_peer peer,
}

static void fake_channel_check_peer(grpc_security_connector* sc, tsi_peer peer,
grpc_endpoint* ep,
grpc_auth_context** auth_context,
grpc_closure* on_peer_checked) {
fake_check_peer(sc, peer, auth_context, on_peer_checked);
Expand All @@ -166,6 +167,7 @@ static void fake_channel_check_peer(grpc_security_connector* sc, tsi_peer peer,
}

static void fake_server_check_peer(grpc_security_connector* sc, tsi_peer peer,
grpc_endpoint* ep,
grpc_auth_context** auth_context,
grpc_closure* on_peer_checked) {
fake_check_peer(sc, peer, auth_context, on_peer_checked);
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -31,6 +31,11 @@
#include "src/core/ext/filters/client_channel/client_channel.h"
#include "src/core/lib/channel/channel_args.h"
#include "src/core/lib/iomgr/pollset.h"
#include "src/core/lib/iomgr/resolve_address.h"
#include "src/core/lib/iomgr/sockaddr.h"
#include "src/core/lib/iomgr/sockaddr_utils.h"
#include "src/core/lib/iomgr/socket_utils.h"
#include "src/core/lib/iomgr/unix_sockets_posix.h"
#include "src/core/lib/security/credentials/local/local_credentials.h"
#include "src/core/lib/security/transport/security_handshaker.h"
#include "src/core/tsi/local_transport_security.h"
Expand Down Expand Up @@ -124,27 +129,97 @@ static grpc_security_status local_auth_context_create(grpc_auth_context** ctx) {
}

static void local_check_peer(grpc_security_connector* sc, tsi_peer peer,
grpc_endpoint* ep,
grpc_auth_context** auth_context,
grpc_closure* on_peer_checked) {
grpc_closure* on_peer_checked,
grpc_local_connect_type type) {
int fd = grpc_endpoint_get_fd(ep);
grpc_resolved_address resolved_addr;
memset(&resolved_addr, 0, sizeof(resolved_addr));
resolved_addr.len = GRPC_MAX_SOCKADDR_SIZE;
bool is_endpoint_local = false;
if (getsockname(fd, reinterpret_cast<grpc_sockaddr*>(resolved_addr.addr),
&resolved_addr.len) == 0) {
grpc_resolved_address addr_normalized;
grpc_resolved_address* addr =
grpc_sockaddr_is_v4mapped(&resolved_addr, &addr_normalized)
? &addr_normalized
: &resolved_addr;
grpc_sockaddr* sock_addr = reinterpret_cast<grpc_sockaddr*>(&addr->addr);
// UDS
if (type == UDS && grpc_is_unix_socket(addr)) {
is_endpoint_local = true;
// IPV4
} else if (type == LOCAL_TCP && sock_addr->sa_family == GRPC_AF_INET) {
const grpc_sockaddr_in* addr4 =
reinterpret_cast<const grpc_sockaddr_in*>(sock_addr);
if (grpc_htonl(addr4->sin_addr.s_addr) == INADDR_LOOPBACK) {
is_endpoint_local = true;
}
// IPv6
} else if (type == LOCAL_TCP && sock_addr->sa_family == GRPC_AF_INET6) {
const grpc_sockaddr_in6* addr6 =
reinterpret_cast<const grpc_sockaddr_in6*>(addr);
if (memcmp(&addr6->sin6_addr, &in6addr_loopback,
sizeof(in6addr_loopback)) == 0) {
is_endpoint_local = true;
}
}
}
grpc_error* error = GRPC_ERROR_NONE;
if (!is_endpoint_local) {
error = GRPC_ERROR_CREATE_FROM_STATIC_STRING(
"Endpoint is neither UDS or TCP loopback address.");
GRPC_CLOSURE_SCHED(on_peer_checked, error);
return;
}
grpc_security_status status;
/* Create an auth context which is necessary to pass the santiy check in
* {client, server}_auth_filter that verifies if the peer's auth context is
* obtained during handshakes. The auth context is only checked for its
* existence and not actually used.
*/
status = local_auth_context_create(auth_context);
grpc_error* error = status == GRPC_SECURITY_OK
? GRPC_ERROR_NONE
: GRPC_ERROR_CREATE_FROM_STATIC_STRING(
"Could not create local auth context");
error = status == GRPC_SECURITY_OK
? GRPC_ERROR_NONE
: GRPC_ERROR_CREATE_FROM_STATIC_STRING(
"Could not create local auth context");
GRPC_CLOSURE_SCHED(on_peer_checked, error);
}

static void local_channel_check_peer(grpc_security_connector* sc, tsi_peer peer,
grpc_endpoint* ep,
grpc_auth_context** auth_context,
grpc_closure* on_peer_checked) {
grpc_channel_security_connector* c =
reinterpret_cast<grpc_channel_security_connector*>(sc);
GPR_ASSERT(c != nullptr);
GPR_ASSERT(c->channel_creds != nullptr);
grpc_local_credentials* creds =
reinterpret_cast<grpc_local_credentials*>(c->channel_creds);
local_check_peer(sc, peer, ep, auth_context, on_peer_checked,
creds->connect_type);
}

static void local_server_check_peer(grpc_security_connector* sc, tsi_peer peer,
grpc_endpoint* ep,
grpc_auth_context** auth_context,
grpc_closure* on_peer_checked) {
grpc_server_security_connector* c =
reinterpret_cast<grpc_server_security_connector*>(sc);
GPR_ASSERT(c != nullptr);
GPR_ASSERT(c->server_creds != nullptr);
grpc_local_server_credentials* creds =
reinterpret_cast<grpc_local_server_credentials*>(c->server_creds);
local_check_peer(sc, peer, ep, auth_context, on_peer_checked,
creds->connect_type);
}

static grpc_security_connector_vtable local_channel_vtable = {
local_channel_destroy, local_check_peer, local_channel_cmp};
local_channel_destroy, local_channel_check_peer, local_channel_cmp};

static grpc_security_connector_vtable local_server_vtable = {
local_server_destroy, local_check_peer, local_server_cmp};
local_server_destroy, local_server_check_peer, local_server_cmp};

static bool local_check_call_host(grpc_channel_security_connector* sc,
const char* host,
Expand Down Expand Up @@ -173,28 +248,22 @@ grpc_security_status grpc_local_channel_security_connector_create(
const grpc_channel_args* args, const char* target_name,
grpc_channel_security_connector** sc) {
if (channel_creds == nullptr || sc == nullptr || target_name == nullptr) {
gpr_log(
GPR_ERROR,
"Invalid arguments to grpc_local_channel_security_connector_create()");
gpr_log(GPR_ERROR,
"Invalid arguments to grpc_local_channel_security_connector_create()");
return GRPC_SECURITY_ERROR;
}
// Check if local_connect_type is UDS. Only UDS is supported for now.
// Perform sanity check on UDS address. For TCP local connection, the check
// will be done during check_peer procedure.
grpc_local_credentials* creds =
reinterpret_cast<grpc_local_credentials*>(channel_creds);
if (creds->connect_type != UDS) {
gpr_log(GPR_ERROR,
"Invalid local channel type to "
"grpc_local_channel_security_connector_create()");
return GRPC_SECURITY_ERROR;
}
// Check if target_name is a valid UDS address.
const grpc_arg* server_uri_arg =
grpc_channel_args_find(args, GRPC_ARG_SERVER_URI);
const char* server_uri_str = grpc_channel_arg_get_string(server_uri_arg);
if (strncmp(GRPC_UDS_URI_PATTERN, server_uri_str,
if (creds->connect_type == UDS &&
strncmp(GRPC_UDS_URI_PATTERN, server_uri_str,
strlen(GRPC_UDS_URI_PATTERN)) != 0) {
gpr_log(GPR_ERROR,
"Invalid target_name to "
"Invalid UDS target_name to "
"grpc_local_channel_security_connector_create()");
return GRPC_SECURITY_ERROR;
}
Expand Down Expand Up @@ -224,20 +293,13 @@ grpc_security_status grpc_local_server_security_connector_create(
"Invalid arguments to grpc_local_server_security_connector_create()");
return GRPC_SECURITY_ERROR;
}
// Check if local_connect_type is UDS. Only UDS is supported for now.
grpc_local_server_credentials* creds =
reinterpret_cast<grpc_local_server_credentials*>(server_creds);
if (creds->connect_type != UDS) {
gpr_log(GPR_ERROR,
"Invalid local server type to "
"grpc_local_server_security_connector_create()");
return GRPC_SECURITY_ERROR;
}
auto c = static_cast<grpc_local_server_security_connector*>(
gpr_zalloc(sizeof(grpc_local_server_security_connector)));
gpr_ref_init(&c->base.base.refcount, 1);
c->base.base.vtable = &local_server_vtable;
c->base.server_creds = grpc_server_credentials_ref(server_creds);
grpc_local_server_credentials* creds =
reinterpret_cast<grpc_local_server_credentials*>(server_creds);
c->base.base.url_scheme =
creds->connect_type == UDS ? GRPC_UDS_URL_SCHEME : nullptr;
c->base.add_handshakers = local_server_add_handshakers;
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -59,7 +59,7 @@ void grpc_server_security_connector_add_handshakers(
}

void grpc_security_connector_check_peer(grpc_security_connector* sc,
tsi_peer peer,
tsi_peer peer, grpc_endpoint* ep,
grpc_auth_context** auth_context,
grpc_closure* on_peer_checked) {
if (sc == nullptr) {
Expand All @@ -68,7 +68,7 @@ void grpc_security_connector_check_peer(grpc_security_connector* sc,
"cannot check peer -- no security connector"));
tsi_peer_destruct(&peer);
} else {
sc->vtable->check_peer(sc, peer, auth_context, on_peer_checked);
sc->vtable->check_peer(sc, peer, ep, auth_context, on_peer_checked);
}
}

Expand Down
4 changes: 2 additions & 2 deletions src/core/lib/security/security_connector/security_connector.h
Original file line number Diff line number Diff line change
Expand Up @@ -50,7 +50,7 @@ typedef struct grpc_security_connector grpc_security_connector;
typedef struct {
void (*destroy)(grpc_security_connector* sc);
void (*check_peer)(grpc_security_connector* sc, tsi_peer peer,
grpc_auth_context** auth_context,
grpc_endpoint* ep, grpc_auth_context** auth_context,
grpc_closure* on_peer_checked);
int (*cmp)(grpc_security_connector* sc, grpc_security_connector* other);
} grpc_security_connector_vtable;
Expand Down Expand Up @@ -84,7 +84,7 @@ void grpc_security_connector_unref(grpc_security_connector* policy);
/* Check the peer. Callee takes ownership of the peer object.
When done, sets *auth_context and invokes on_peer_checked. */
void grpc_security_connector_check_peer(grpc_security_connector* sc,
tsi_peer peer,
tsi_peer peer, grpc_endpoint* ep,
grpc_auth_context** auth_context,
grpc_closure* on_peer_checked);

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -231,6 +231,7 @@ static grpc_error* ssl_check_peer(grpc_security_connector* sc,
}

static void ssl_channel_check_peer(grpc_security_connector* sc, tsi_peer peer,
grpc_endpoint* ep,
grpc_auth_context** auth_context,
grpc_closure* on_peer_checked) {
grpc_ssl_channel_security_connector* c =
Expand Down Expand Up @@ -268,6 +269,7 @@ static void ssl_channel_check_peer(grpc_security_connector* sc, tsi_peer peer,
}

static void ssl_server_check_peer(grpc_security_connector* sc, tsi_peer peer,
grpc_endpoint* ep,
grpc_auth_context** auth_context,
grpc_closure* on_peer_checked) {
grpc_error* error = ssl_check_peer(sc, nullptr, &peer, auth_context);
Expand Down
4 changes: 2 additions & 2 deletions src/core/lib/security/transport/security_handshaker.cc
Original file line number Diff line number Diff line change
Expand Up @@ -222,8 +222,8 @@ static grpc_error* check_peer_locked(security_handshaker* h) {
return grpc_set_tsi_error_result(
GRPC_ERROR_CREATE_FROM_STATIC_STRING("Peer extraction failed"), result);
}
grpc_security_connector_check_peer(h->connector, peer, &h->auth_context,
&h->on_peer_checked);
grpc_security_connector_check_peer(h->connector, peer, h->args->endpoint,
&h->auth_context, &h->on_peer_checked);
return GRPC_ERROR_NONE;
}

Expand Down

0 comments on commit 42861db

Please sign in to comment.