public async Task Connect_Invalid() { //invalid handshake { var handshake = new Handshake(); var metadata = new Metadata { { GrpcConsts.PubkeyMetadataKey, "0454dcd0afc20d015e328666d8d25f3f28b13ccd9744eb6b153e4a69709aab399" } }; var context = BuildServerCallContext(metadata); var connectReply = await _service.Connect(handshake, context); connectReply.Err.ShouldBe(AuthError.InvalidHandshake); } //wrong sig { var handshake = await _peerPool.GetHandshakeAsync(); handshake.HskData.PublicKey = ByteString.CopyFrom(CryptoHelpers.GenerateKeyPair().PublicKey); var metadata = new Metadata { { GrpcConsts.PubkeyMetadataKey, "0454dcd0afc20d015e328666d8d25f3f28b13ccd9744eb6b153e4a69709aab399" } }; var context = TestServerCallContext.Create("mock", "127.0.0.1", DateTime.UtcNow.AddHours(1), metadata, CancellationToken.None, "ipv4:127.0.0.1:2000", null, null, m => TaskUtils.CompletedTask, () => new WriteOptions(), writeOptions => { }); var connectReply = await _service.Connect(handshake, context); connectReply.Err.ShouldBe(AuthError.WrongSig); } //invalid peer { var handshake = await _peerPool.GetHandshakeAsync(); var metadata = new Metadata { { GrpcConsts.PubkeyMetadataKey, "0454dcd0afc20d015e328666d8d25f3f28b13ccd9744eb6b153e4a69709aab399" } }; var context = BuildServerCallContext(metadata); var connectReply = await _service.Connect(handshake, context); connectReply.Err.ShouldBe(AuthError.InvalidPeer); } //wrong auth { var handshake = await _peerPool.GetHandshakeAsync(); var metadata = new Metadata { { GrpcConsts.PubkeyMetadataKey, "0454dcd0afc20d015e328666d8d25f3f28b13ccd9744eb6b153e4a69709aab399" } }; var context = TestServerCallContext.Create("mock", "127.0.0.1", DateTime.UtcNow.AddHours(1), metadata, CancellationToken.None, "ipv4:127.0.0.1:2000", null, null, m => TaskUtils.CompletedTask, () => new WriteOptions(), writeOptions => { }); var connectReply = await _service.Connect(handshake, context); connectReply.Err.ShouldBe(AuthError.WrongAuth); } }
/// <summary> /// First step of the connect/auth process. Used to initiate a connection. The provided payload should be the /// clients authentication information. When receiving this call, protocol dictates you send the client your auth /// information. The response says whether or not you can connect. /// </summary> public override async Task <ConnectReply> Connect(Handshake handshake, ServerCallContext context) { Logger.LogTrace($"{context.Peer} has initiated a connection request."); if (handshake?.HskData == null) { return new ConnectReply { Err = AuthError.InvalidHandshake } } ; // verify chain id if (handshake.HskData.ChainId != _blockChainService.GetChainId()) { return new ConnectReply { Err = AuthError.ChainMismatch } } ; // verify protocol if (handshake.HskData.Version != KernelConstants.ProtocolVersion) { return new ConnectReply { Err = AuthError.ProtocolMismatch } } ; // verify signature var validData = await _accountService.VerifySignatureAsync(handshake.Sig.ToByteArray(), Hash.FromMessage(handshake.HskData).ToByteArray(), handshake.HskData.PublicKey.ToByteArray()); if (!validData) { return new ConnectReply { Err = AuthError.WrongSig } } ; var peer = GrpcUrl.Parse(context.Peer); if (peer == null) { return new ConnectReply { Err = AuthError.InvalidPeer } } ; var peerAddress = peer.IpAddress + ":" + handshake.HskData.ListeningPort; Logger.LogDebug($"Attempting to create channel to {peerAddress}"); Channel channel = new Channel(peerAddress, ChannelCredentials.Insecure); var client = new PeerService.PeerServiceClient(channel.Intercept(metadata => { metadata.Add(GrpcConsts.PubkeyMetadataKey, AsyncHelper.RunSync(() => _accountService.GetPublicKeyAsync()).ToHex()); return(metadata); })); if (channel.State != ChannelState.Ready) { var c = channel.WaitForStateChangedAsync(channel.State); } var pubKey = handshake.HskData.PublicKey.ToHex(); var grpcPeer = new GrpcPeer(channel, client, pubKey, peerAddress); // Verify auth bool valid = _peerPool.IsAuthenticatePeer(pubKey); if (!valid) { await channel.ShutdownAsync(); Logger.LogDebug($"Failed to reach {grpcPeer}"); return(new ConnectReply { Err = AuthError.WrongAuth }); } // send our credentials var hsk = await _peerPool.GetHandshakeAsync(); // If auth ok -> add it to our peers _peerPool.AddPeer(grpcPeer); return(new ConnectReply { Handshake = hsk }); }