private bool ValidateClientRequest(TTFSHTTPRequestParser request) { // Parser checked a lot of stuff already, but we need to make sure it is fully parsed if (!request.ReceivedFullRequest) { return(false); } // Client should not be allowed to specify a path outside the ttfspath string fullPath = Path.GetFullPath(Path.Combine(ttfsPath, request.RequestTargetPath)); if (!fullPath.StartsWith(ttfsPath, StringComparison.Ordinal)) { return(false); } // Hosts should match if (!hostAddress.Equals(request.HostEndPoint.Address) || !localPort.Equals(request.HostEndPoint.Port)) { return(false); } // Seems to be an ok request return(true); }
private async Task HandleClientAsync(TcpClient client, EndPoint remoteEndPoint, RenegadeDispatcher dispatcher, CancellationToken cancellationToken) { try { TTFSHTTPRequestParser requestParser = new TTFSHTTPRequestParser(ClientGetRequestBufferSize); NetworkStream clientStream = client.GetStream(); while (!requestParser.IsBufferFull && !cancellationToken.IsCancellationRequested) { TTFSHTTPReadResult readResult = await requestParser.ReadAsync(clientStream, cancellationToken); if (readResult == TTFSHTTPReadResult.PeerSocketClosed) { // We're done here, client closed connection return; } // We've succesfully parsed the entire request, or it was invalid if (readResult == TTFSHTTPReadResult.Done || readResult == TTFSHTTPReadResult.InvalidData) { break; } } if (cancellationToken.IsCancellationRequested) { // We're done here return; } if (ValidateClientRequest(requestParser)) { await SendFileToClient(client, remoteEndPoint, requestParser.RequestTargetPath, dispatcher, cancellationToken); } else { // Client did something wrong await SendBadRequestResponse(client, remoteEndPoint, dispatcher, cancellationToken); } } catch (SocketException ex) { if ( ex.SocketErrorCode == SocketError.Interrupted || ex.SocketErrorCode == SocketError.ConnectionAborted || ex.SocketErrorCode == SocketError.ConnectionRefused || ex.SocketErrorCode == SocketError.ConnectionReset) { throw new OperationCanceledException(); } else { dispatcher.InvokeAsync(() => { Engine.ConsoleOutput($"[{nameof(PackageServer)}]: Client {remoteEndPoint} triggered internal server error '{ex.Message}'\n"); }); } } catch (ObjectDisposedException) when(cancellationToken.IsCancellationRequested) { throw new OperationCanceledException(); } }