Add client validation to server credentials (#363)

* Add ability to validate clients to server credentials.
This commit is contained in:
Nic Hite 2020-09-29 11:55:28 -07:00 committed by GitHub
parent a774583de0
commit a657916168
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
5 changed files with 52 additions and 15 deletions

View File

@ -1,3 +1,8 @@
## 2.5.0
* Expose a `validateClient` method for server credentials so gRPC server
users may know when clients are loopback addresses.
## 2.4.1 ## 2.4.1
* Plumb stacktraces through request / response stream error handlers. * Plumb stacktraces through request / response stream error handlers.

View File

@ -43,7 +43,12 @@ export 'src/client/transport/http2_credentials.dart'
export 'src/server/call.dart' show ServiceCall; export 'src/server/call.dart' show ServiceCall;
export 'src/server/interceptor.dart' show Interceptor; export 'src/server/interceptor.dart' show Interceptor;
export 'src/server/server.dart' show ServerTlsCredentials, Server; export 'src/server/server.dart'
show
ServerCredentials,
ServerLocalCredentials,
ServerTlsCredentials,
Server;
export 'src/server/service.dart' show ServiceMethod, Service; export 'src/server/service.dart' show ServiceMethod, Service;
export 'src/shared/message.dart' export 'src/shared/message.dart'

View File

@ -18,7 +18,7 @@
/// Mainly intended to be imported by generated code. /// Mainly intended to be imported by generated code.
library service_api; library service_api;
export 'src/client/call.dart' show CallOptions; export 'src/client/call.dart' show CallOptions, MetadataProvider;
export 'src/client/channel.dart' show ClientChannel; export 'src/client/channel.dart' show ClientChannel;
export 'src/client/client.dart' show Client; export 'src/client/client.dart' show Client;
export 'src/client/common.dart' show ResponseFuture, ResponseStream; export 'src/client/common.dart' show ResponseFuture, ResponseStream;

View File

@ -25,7 +25,27 @@ import 'handler.dart';
import 'interceptor.dart'; import 'interceptor.dart';
import 'service.dart'; import 'service.dart';
class ServerTlsCredentials { /// Wrapper around grpc_server_credentials, a way to authenticate a server.
abstract class ServerCredentials {
/// Validates incoming connection. Returns [true] if connection is
/// allowed to proceed.
bool validateClient(Socket socket) => true;
/// Creates [SecurityContext] from these credentials if possible.
/// Otherwise returns [null].
SecurityContext get securityContext;
}
/// Set of credentials that only allows local TCP connections.
class ServerLocalCredentials extends ServerCredentials {
@override
bool validateClient(Socket socket) => socket.remoteAddress.isLoopback;
@override
SecurityContext get securityContext => null;
}
class ServerTlsCredentials extends ServerCredentials {
final List<int> certificate; final List<int> certificate;
final String certificatePassword; final String certificatePassword;
final List<int> privateKey; final List<int> privateKey;
@ -52,6 +72,9 @@ class ServerTlsCredentials {
} }
return context; return context;
} }
@override
bool validateClient(Socket socket) => true;
} }
/// A gRPC server. /// A gRPC server.
@ -87,21 +110,18 @@ class Server {
Future<void> serve( Future<void> serve(
{dynamic address, {dynamic address,
int port, int port,
ServerTlsCredentials security, ServerCredentials security,
ServerSettings http2ServerSettings, ServerSettings http2ServerSettings,
int backlog: 0, int backlog: 0,
bool v6Only: false, bool v6Only: false,
bool shared: false}) async { bool shared: false}) async {
// TODO(dart-lang/grpc-dart#9): Handle HTTP/1.1 upgrade to h2c, if allowed. // TODO(dart-lang/grpc-dart#9): Handle HTTP/1.1 upgrade to h2c, if allowed.
Stream<Socket> server; Stream<Socket> server;
if (security != null) { final securityContext = security?.securityContext;
if (securityContext != null) {
_secureServer = await SecureServerSocket.bind( _secureServer = await SecureServerSocket.bind(
address ?? InternetAddress.anyIPv4, address ?? InternetAddress.anyIPv4, port ?? 443, securityContext,
port ?? 443, backlog: backlog, shared: shared, v6Only: v6Only);
security.securityContext,
backlog: backlog,
shared: shared,
v6Only: v6Only);
server = _secureServer; server = _secureServer;
} else { } else {
_insecureServer = await ServerSocket.bind( _insecureServer = await ServerSocket.bind(
@ -119,6 +139,11 @@ class Server {
final connection = ServerTransportConnection.viaSocket(socket, final connection = ServerTransportConnection.viaSocket(socket,
settings: http2ServerSettings); settings: http2ServerSettings);
_connections.add(connection); _connections.add(connection);
if (security != null && !security.validateClient(socket)) {
_printSocketError(
'cannot serve $address:$port - unable to validate client socket');
return socket.close();
}
ServerHandler_ handler; ServerHandler_ handler;
// TODO(jakobr): Set active state handlers, close connection after idle // TODO(jakobr): Set active state handlers, close connection after idle
// timeout. // timeout.
@ -134,9 +159,11 @@ class Server {
handler?.cancel(); handler?.cancel();
_connections.remove(connection); _connections.remove(connection);
}); });
}, onError: (error) { }, onError: _printSocketError);
print('Socket error: $error'); }
});
void _printSocketError(Object error) {
print('Socket error: $error');
} }
@visibleForTesting @visibleForTesting

View File

@ -1,7 +1,7 @@
name: grpc name: grpc
description: Dart implementation of gRPC, a high performance, open-source universal RPC framework. description: Dart implementation of gRPC, a high performance, open-source universal RPC framework.
version: 2.4.1 version: 2.5.0
author: Dart Team <misc@dartlang.org> author: Dart Team <misc@dartlang.org>
homepage: https://github.com/dart-lang/grpc-dart homepage: https://github.com/dart-lang/grpc-dart