Example #1
0
        public async Task <string> Receive(byte[] rawRequest, Transport transport)
        {
            Debug.Assert(transport == Transport.UDP);

            try
            {
                if (rawRequest == null || rawRequest.Length == 0)
                {
                    throw new Exception("TLSClient received null or empty packet");
                }

                var tlsEnvelope = new TLSEnvelope(rawRequest);

                if (!TLSEnvelopeExtensions.ValidateCrc32(rawRequest, out var actualCrc32))
                {
                    throw new Exception($"TLSEnvelope CRC32 Error: Expected: {tlsEnvelope.Crc32}, actual: {actualCrc32}");
                }

                var request = await this.Ratchet.DecryptRequest(tlsEnvelope);


                var command = request.ParseCommand();
                if (!command.CommandId.IsCommandDefined())
                {
                    throw new Exception($"TLSClient: The command {command.CommandId} is not defined.");
                }

                await ProcessCommand(command);
            }
            catch (Exception e)
            {
                var error = $"{nameof(TLSClient)} received bad request via {transport}: {e.Message}";
                this._log.LogError(error);
            }
            return(null); // this goes back to the IUdpConnection and is not used there.
        }
Example #2
0
        public async Task <byte[]> ProcessRequestAsync(byte[] rawRequest, string clientInformation)
        {
            if (rawRequest == null || rawRequest.Length == 0)
            {
                return(null);
            }

            var tlsEnvelope = new TLSEnvelope(rawRequest);
            var request     = this.tlsServerRatchet.TLSServerDecryptRequest(tlsEnvelope);

            if (request == null)
            {
                this.logger.LogWarning($"TLSServerRequestHandler: Unknown DynamicPublicKey {tlsEnvelope.DynamicPublicKeyId}, sending {CommandId.LostDynamicKey_Response}.");
                // request == null means we lost the dynamic private key to to the public key the client used.
                // We don't know who the client is, because TLS could not decrypt the message at all.
                // We now need to tell the client it needs to reset its key schedule, i.e. start over
                // using my static public key.
                // We must use our static private key to encrypt this message, so that the client knows the server is talking.
                // We then use the dynamic public key we just received, to calculate a new shared secret that only the unknown
                // client can reproduce for decryption of this message.
                byte[] lostDynamicKeyResponseCommand = this.commandProcessor.ExecuteLostDynamicKey();
                byte[] lostDynamicKeyResponse        = this.tlsServerRatchet.TLSServerEncryptRequestAnonymous(lostDynamicKeyResponseCommand, tlsEnvelope.DynamicPublicKey, tlsEnvelope.DynamicPublicKeyId).Serialize();
                return(lostDynamicKeyResponse);
            }

            Command command = request.ParseCommand();

            if (!command.CommandId.IsCommandDefined())
            {
                return(null);
            }

            byte[] response;
            if (CommandProtocol.IsAuthenticationRequired(command.CommandId))
            {
                if (!request.IsAuthenticated)
                {
                    this.logger.LogWarning($"ServerRequestHandler: Command {command.CommandId} from {request.UserId} requires Auth, which failed. Sending {CommandId.NoSuchUser_Response}");
                    // We may be here, when the server has lost the identity (and client public key for the calling user id), or if the
                    // user id is locked, revoked etc.
                    byte[] noSuchUserResponseCommand = this.commandProcessor.ExecuteNoSuchUser();
                    byte[] noSuchUserResponse        = this.tlsServerRatchet.TLSServerEncryptRequestAnonymous(noSuchUserResponseCommand, tlsEnvelope.DynamicPublicKey, tlsEnvelope.DynamicPublicKeyId).Serialize();
                    return(noSuchUserResponse);
                }

                response = await this.commandProcessor.ExecuteAuthenticatedRequestAsync(command);
            }
            else
            {
                response = await this.commandProcessor.ExecutePublishIdentityAsync(command, this.tlsServerRatchet.RefreshTLSUser);

                // when PublishIdentity has returned successfully, we can save the DynamicPublicKey we did not save in TLSDecrpt, because we wanted more logic to run before this
                // Specifically, the IdentityController has called RefreshTLSUser by now, creating the place where this key can be stored.
                if (response != null)
                {
                    this.tlsServerRatchet.SaveIncomingDynamicPublicKey(request.UserId, tlsEnvelope.DynamicPublicKey, tlsEnvelope.DynamicPublicKeyId);
                }
            }
            return(response == null ?
                   null :
                   this.tlsServerRatchet.TLSServerEncryptRequest(response, request.UserId).Serialize());
        }