protected static SecureSocket GetHandshakedSocket(Uri uri) { string selectedProtocol = null; var extensions = new[] { ExtensionType.Renegotiation, ExtensionType.ALPN }; var options = _useSecurePort ? new SecurityOptions(SecureProtocol.Tls1, extensions, new[] { Protocols.Http2, Protocols.Http1 }, ConnectionEnd.Client) : new SecurityOptions(SecureProtocol.None, extensions, new[] { Protocols.Http2, Protocols.Http1 }, ConnectionEnd.Client); options.VerificationType = CredentialVerification.None; options.Certificate = Org.Mentalis.Security.Certificates.Certificate.CreateFromCerFile(@"certificate.pfx"); options.Flags = SecurityFlags.Default; options.AllowedAlgorithms = SslAlgorithms.RSA_AES_256_SHA | SslAlgorithms.NULL_COMPRESSION; var sessionSocket = new SecureSocket(AddressFamily.InterNetwork, SocketType.Stream, ProtocolType.Tcp, options); using (var monitor = new ALPNExtensionMonitor()) { monitor.OnProtocolSelected += (sender, args) => { selectedProtocol = args.SelectedProtocol; }; sessionSocket.Connect(new DnsEndPoint(uri.Host, uri.Port), monitor); if (_useHandshake) { var handshakeEnv = new Dictionary <string, object> { { ":method", "get" }, { ":version", Protocols.Http1 }, { ":path", uri.PathAndQuery }, { ":scheme", uri.Scheme }, { ":host", uri.Host }, { "securityOptions", options }, { "secureSocket", sessionSocket }, { "end", ConnectionEnd.Client } }; _handshakeResult = HandshakeManager.GetHandshakeAction(handshakeEnv).Invoke(); } } SendSessionHeader(sessionSocket); return(sessionSocket); }
public void UpgradeHandshakeSuccessful() { const string requestStr = @"http://*****:*****@"certificate.pfx"), Flags = SecurityFlags.Default, AllowedAlgorithms = SslAlgorithms.RSA_AES_256_SHA | SslAlgorithms.NULL_COMPRESSION }; var sessionSocket = new SecureSocket(AddressFamily.InterNetwork, SocketType.Stream, ProtocolType.Tcp, options); sessionSocket.Connect(new DnsEndPoint(uri.Host, uri.Port)); var handshakeEnv = new Dictionary <string, object> { { ":method", "get" }, { ":version", Protocols.Http1 }, { ":path", uri.PathAndQuery }, { ":scheme", uri.Scheme }, { ":host", uri.Host }, { "securityOptions", options }, { "secureSocket", sessionSocket }, { "end", ConnectionEnd.Client } }; bool gotFailedException = false; try { HandshakeManager.GetHandshakeAction(handshakeEnv).Invoke(); } catch (Http2HandshakeFailed) { gotFailedException = true; } sessionSocket.Close(); Assert.Equal(gotFailedException, false); }
public void AlpnSelectionHttp2Successful() { const string requestStr = @"https://*****:*****@"certificate.pfx"), Flags = SecurityFlags.Default, AllowedAlgorithms = SslAlgorithms.RSA_AES_256_SHA | SslAlgorithms.NULL_COMPRESSION }; var sessionSocket = new SecureSocket(AddressFamily.InterNetwork, SocketType.Stream, ProtocolType.Tcp, options); using (var monitor = new ALPNExtensionMonitor()) { monitor.OnProtocolSelected += (sender, args) => { selectedProtocol = args.SelectedProtocol; }; sessionSocket.Connect(new DnsEndPoint(uri.Host, uri.Port), monitor); var handshakeEnv = new Dictionary <string, object> { { ":method", "get" }, { ":version", Protocols.Http1 }, { ":path", uri.PathAndQuery }, { ":scheme", uri.Scheme }, { ":host", uri.Host }, { "securityOptions", options }, { "secureSocket", sessionSocket }, { "end", ConnectionEnd.Client } }; HandshakeManager.GetHandshakeAction(handshakeEnv).Invoke(); } sessionSocket.Close(); Assert.Equal(Protocols.Http2, selectedProtocol); }
public bool Connect(Uri connectUri) { _path = connectUri.PathAndQuery; _version = Protocols.Http2; _scheme = connectUri.Scheme; _host = connectUri.Host; _port = connectUri.Port; ServerUri = connectUri.Authority; if (_clientSession != null) { return(false); } try { int port = connectUri.Port; int securePort; if (!int.TryParse(ConfigurationManager.AppSettings["securePort"], out securePort)) { Http2Logger.LogError("Incorrect port in the config file!"); return(false); } //Connect alpn extension, set known protocols var extensions = new[] { ExtensionType.Renegotiation, ExtensionType.ALPN }; _options = port == securePort ? new SecurityOptions(SecureProtocol.Tls1, extensions, new[] { Protocols.Http1, Protocols.Http2 }, ConnectionEnd.Client) : new SecurityOptions(SecureProtocol.None, extensions, new[] { Protocols.Http1, Protocols.Http2 }, ConnectionEnd.Client); _options.VerificationType = CredentialVerification.None; _options.Certificate = Org.Mentalis.Security.Certificates.Certificate.CreateFromCerFile(CertificatePath); _options.Flags = SecurityFlags.Default; _options.AllowedAlgorithms = SslAlgorithms.RSA_AES_256_SHA | SslAlgorithms.NULL_COMPRESSION; _socket = new SecureSocket(AddressFamily.InterNetwork, SocketType.Stream, ProtocolType.Tcp, _options); IDictionary <string, object> handshakeResult = null; using (var monitor = new ALPNExtensionMonitor()) { monitor.OnProtocolSelected += (o, args) => { _selectedProtocol = args.SelectedProtocol; }; _socket.Connect(new DnsEndPoint(connectUri.Host, connectUri.Port), monitor); if (_useHandshake) { var handshakeEnvironment = MakeHandshakeEnvironment(_socket); //Handshake manager determines what handshake must be used: upgrade or secure handshakeResult = HandshakeManager.GetHandshakeAction(handshakeEnvironment).Invoke(); Http2Logger.LogDebug("Handshake finished"); if (_selectedProtocol == Protocols.Http1) { _useHttp20 = false; return(true); } } } SendSessionHeader(); _useHttp20 = true; _clientSession = new Http2Session(_socket, ConnectionEnd.Client, _usePriorities, _useFlowControl, handshakeResult); //For saving incoming data _clientSession.OnFrameReceived += FrameReceivedHandler; _clientSession.OnRequestSent += RequestSentHandler; _clientSession.OnSessionDisposed += (sender, args) => Dispose(false); } catch (Http2HandshakeFailed ex) { if (ex.Reason == HandshakeFailureReason.InternalError) { _useHttp20 = false; } else { Http2Logger.LogError("Specified server did not respond"); Dispose(true); return(false); } } catch (SocketException) { Http2Logger.LogError("Check if any server listens port " + connectUri.Port); Dispose(true); return(false); } catch (Exception ex) { Http2Logger.LogError("Unknown connection exception was caught: " + ex.Message); Dispose(true); return(false); } return(true); }
private void HandleAcceptedClient(SecureSocket incomingClient) { bool backToHttp11 = false; string alpnSelectedProtocol = Protocols.Http2; var handshakeEnvironment = MakeHandshakeEnvironment(incomingClient); IDictionary <string, object> handshakeResult = null; //Think out smarter way to get handshake result. //DO NOT change Middleware function. If you will do so, server will not even launch. (It's owin's problem) Func <Task> handshakeAction = () => { var handshakeTask = new Task(() => { handshakeResult = HandshakeManager.GetHandshakeAction(handshakeEnvironment).Invoke(); }); return(handshakeTask); }; if (_useHandshake) { var environment = new Dictionary <string, object> { //Sets the handshake action depends on port. { "HandshakeAction", handshakeAction }, }; try { var handshakeTask = _next(environment); handshakeTask.Start(); if (!handshakeTask.Wait(6000)) { incomingClient.Close(); Http2Logger.LogError("Handshake timeout. Connection dropped."); return; } alpnSelectedProtocol = incomingClient.SelectedProtocol; } catch (Http2HandshakeFailed ex) { if (ex.Reason == HandshakeFailureReason.InternalError) { backToHttp11 = true; } else { incomingClient.Close(); Http2Logger.LogError("Handshake timeout. Client was disconnected."); return; } } catch (Exception e) { Http2Logger.LogError("Exception occured. Closing client's socket. " + e.Message); incomingClient.Close(); return; } } try { HandleRequest(incomingClient, alpnSelectedProtocol, backToHttp11, handshakeResult); } catch (Exception e) { Http2Logger.LogError("Exception occured. Closing client's socket. " + e.Message); incomingClient.Close(); } }