public static void SetDh(HandshakeState state, byte[] ephemeral) { var flags = BindingFlags.Instance | BindingFlags.NonPublic; var setDh = state.GetType().GetMethod("SetDh", flags); setDh.Invoke(state, new object[] { new FixedKeyDh(ephemeral) }); }
protected HandshakeSession(SecurityParameters securityParameters, ILogger logger) { this.logger = logger; _pluginManager = new CipherSuitePluginManager(this.logger); _state = HandshakeState.Initial; _minVersion = securityParameters.MinimumVersion; _maxVersion = securityParameters.MaximumVersion; _supportedCipherSuites = securityParameters.CipherSuiteIDs.ToArray(); _supportedCompressions = securityParameters.CompressionIDs.ToArray(); _availableCertificates = new List<X509CertificateCollection>(securityParameters.AvailableCertificates); _availablePrivateKeys = new List<CertificatePrivateKey>(securityParameters.AvailablePrivateKeys); _clientCertificates = new X509CertificateCollection(); _serverCertificates = new X509CertificateCollection(); // Initialize the default ClientHello version, to // be as compatible as possible based on maxVersion _version = _minVersion; _cipherSuite = new CipherSuite(_version); }
protected HandshakeSession(SecurityParameters securityParameters) { string path = System.Reflection.Assembly.GetAssembly(typeof(HandshakeSession)).Location; string directory = Path.GetDirectoryName(path); _pluginManager = new CipherSuitePluginManager(directory); _state = HandshakeState.Initial; _minVersion = securityParameters.MinimumVersion; _maxVersion = securityParameters.MaximumVersion; _supportedCipherSuites = securityParameters.CipherSuiteIDs.ToArray(); _supportedCompressions = securityParameters.CompressionIDs.ToArray(); _availableCertificates = new List <X509CertificateCollection>(securityParameters.AvailableCertificates); _availablePrivateKeys = new List <CertificatePrivateKey>(securityParameters.AvailablePrivateKeys); _clientCertificates = new X509CertificateCollection(); _serverCertificates = new X509CertificateCollection(); // Initialize the default ClientHello version, to // be as compatible as possible based on maxVersion if (_maxVersion == ProtocolVersion.SSL3_0) { _version = ProtocolVersion.SSL3_0; } else if (_maxVersion.IsUsingDatagrams) { _version = ProtocolVersion.DTLS1_0; } else { _version = ProtocolVersion.TLS1_0; } _cipherSuite = new CipherSuite(_version); }
private static async Task Server(HandshakeState handshakeState) { var buffer = new byte[Protocol.MaxMessageLength]; // Receive the first handshake message from the client. var received = await clientToServer.Receive(); handshakeState.ReadMessage(received, buffer); // Send the second handshake message to the client. var(bytesWritten, _, transport) = handshakeState.WriteMessage(null, buffer); await serverToClient.Send(Slice(buffer, bytesWritten)); // Handshake complete, switch to transport mode. using (transport) { for (;;) { // Receive the message from the client. var request = await clientToServer.Receive(); var bytesRead = transport.ReadMessage(request, buffer); // Echo the message back to the client. bytesWritten = transport.WriteMessage(Slice(buffer, bytesRead), buffer); await serverToClient.Send(Slice(buffer, bytesWritten)); } } }
private static async Task Client(HandshakeState state) { var buffer = new byte[Protocol.MaxMessageLength]; // Send the first handshake message to the server. var(bytesWritten, _, _) = state.WriteMessage(null, buffer); await clientToServer.Send(Slice(buffer, bytesWritten)); // Receive the second handshake message from the server. var received = await serverToClient.Receive(); var(_, _, transport) = state.ReadMessage(received, buffer); // Handshake complete, switch to transport mode. using (transport) { foreach (var message in messages) { Memory <byte> request = Encoding.UTF8.GetBytes(message); // Send the message to the server. bytesWritten = transport.WriteMessage(request.Span, buffer); await clientToServer.Send(Slice(buffer, bytesWritten)); // Receive the response and print it to the standard output. var response = await serverToClient.Receive(); var bytesRead = transport.ReadMessage(response, buffer); Console.WriteLine(Encoding.UTF8.GetString(Slice(buffer, bytesRead))); } } }
/// <summary> /// Sent to backend /// </summary> public Handshake(string host, int port, HandshakeState state) { Version = MinecraftServer.BackendVersion; Host = host; Port = port; State = state; Prepare(); }
protected override void Parse(EndianBinaryReader r) { Version = (ProtocolVersion)ReadVarInt(r); Host = ReadString8(r); Port = r.ReadUInt16(); State = (HandshakeState)ReadVarInt(r); DebugGotAll(r); }
/// <summary> /// Renegotiate session keys - calls SSL_renegotiate /// </summary> public void Renegotiate() { if (ssl != null) { // Call the SSL_renegotiate to reset the SSL object state // to start handshake Native.ExpectSuccess(Native.SSL_renegotiate(ssl.Handle)); handShakeState = HandshakeState.Renegotiate; } }
public virtual void Clear() { compressionMethod = SecurityCompressionType.None; serverSettings = new TlsServerSettings(); clientSettings = new TlsClientSettings(); handshakeMessages = new TlsStream(); sessionId = null; handshakeState = HandshakeState.None; ClearKeyInfo(); }
public virtual void Clear() { this.compressionMethod = SecurityCompressionType.None; this.serverSettings = new TlsServerSettings(); this.clientSettings = new TlsClientSettings(); this.handshakeMessages = new TlsStream(); this.sessionId = (byte[])null; this.handshakeState = HandshakeState.None; this.ClearKeyInfo(); }
public Context(SecurityProtocolType securityProtocolType) { this.SecurityProtocol = securityProtocolType; this.compressionMethod = SecurityCompressionType.None; this.serverSettings = new TlsServerSettings(); this.clientSettings = new TlsClientSettings(); this.handshakeMessages = new TlsStream(); this.sessionId = null; this.handshakeState = HandshakeState.None; this.random = RandomNumberGenerator.Create(); }
public unsafe NoiseProtocol(bool initiator, byte *sk, PskRef psk, byte[] publicKey = default, string id = default, TextWriter @out = default) { _initiator = initiator; _id = id ?? "[NOISE]"; _out = @out; var psks = new List <PskRef> { psk }; _state = Protocol.Create(initiator, default, sk, (int)Crypto.EncryptionKeyBytes, publicKey, psks);
public void Connect(VpnChannel channel) { string serverPort = "8000"; string secret = "test"; string parameters = null; _datagramSocket = new DatagramSocket(); channel.AssociateTransport(_datagramSocket, null); _datagramSocket.MessageReceived += (s, e) => { DataReader dataReader = e.GetDataReader(); if (dataReader.UnconsumedBufferLength > 0 && dataReader.ReadByte() == 0) { parameters = dataReader.ReadString(dataReader.UnconsumedBufferLength); _handshakeState = HandshakeState.Received; } }; var serverHostName = channel.Configuration.ServerHostNameList[0]; XmlDocument xmlDocument = new XmlDocument(); xmlDocument.LoadXml(channel.Configuration.CustomField); var firstChild = xmlDocument.FirstChild; if (firstChild.Name.Equals("ToyVpnConfig")) { foreach (XmlNode childNode in firstChild.ChildNodes) { if (childNode.Name.Equals("ServerPort")) { serverPort = childNode.InnerText; } else if (childNode.Name.Equals("Secret")) { secret = childNode.InnerText; } } } _datagramSocket.ConnectAsync(serverHostName, serverPort).AsTask().GetAwaiter().GetResult(); _handshakeState = HandshakeState.Waiting; HandShake(_datagramSocket, secret).AsTask().GetAwaiter().GetResult(); if (_handshakeState == HandshakeState.Received) { ConfigureAndConnect(channel, parameters); } else { channel.Stop(); } }
private IAsyncResult BeginHandshake(InternalAsyncResult readwriteAsyncResult) { if (disposed) { return(null); } //!! // Move the handshake state to the next state //if (handShakeState == HandshakeState.Renegotiate) //{ // handShakeState = HandshakeState.RenegotiateInProcess; //} //else if (handShakeState != HandshakeState.Renegotiate) { handShakeState = HandshakeState.InProcess; } // Wrap the read/write InternalAsyncResult in the Handshake InternalAsyncResult instance var handshakeAsyncResult = new InternalAsyncResult( AsyncHandshakeComplete, readwriteAsyncResult, null, 0, 0, readwriteAsyncResult.IsWriteOperation, readwriteAsyncResult.ContinueAfterHandshake); if (ProcessHandshake()) { handShakeState = HandshakeState.Complete; handshakeAsyncResult.SetComplete(); } else { //!! if (readwriteAsyncResult.IsWriteOperation) if (write_bio.BytesPending > 0) { handshakeAsyncResult.IsWriteOperation = true; BeginWrite(new byte[0], 0, 0, AsyncHandshakeCallback, handshakeAsyncResult); } else { handshakeAsyncResult.IsWriteOperation = false; BeginRead(new byte[0], 0, 0, AsyncHandshakeCallback, handshakeAsyncResult); } } return(handshakeAsyncResult); }
protected HandshakeSession(SecurityParameters securityParameters) { _pluginManager = new CipherSuitePluginManager(); _state = HandshakeState.Initial; _minVersion = securityParameters.MinimumVersion; _maxVersion = securityParameters.MaximumVersion; _supportedCipherSuites = securityParameters.CipherSuiteIDs.ToArray(); _supportedCompressions = securityParameters.CompressionIDs.ToArray(); _availableCertificates = new List <X509CertificateCollection>(securityParameters.AvailableCertificates); _availablePrivateKeys = new List <CertificatePrivateKey>(securityParameters.AvailablePrivateKeys); _clientCertificates = new X509CertificateCollection(); _serverCertificates = new X509CertificateCollection(); // Initialize the default ClientHello version, to // be as compatible as possible based on maxVersion _version = _minVersion; _cipherSuite = new CipherSuite(_version); }
private void Reinitialize(Protocol protocol, ProtocolConfig config, State state) { bool fallback = state == State.Switch && (protocol.Modifiers & PatternModifiers.Fallback) != 0; if (fallback && handshakeState == null) { throw new InvalidOperationException("Cannot perform the fallback handshake on an uninitialized server."); } if (protocol.HandshakePattern.Patterns.Count() == 1) { throw new NotSupportedException("One-way patterns are not yet supported."); } if (transport != null) { throw new InvalidOperationException($"Cannot change protocol after the handshake has been completed."); } if (this.state != State.Initial) { throw new InvalidOperationException($"Cannot change protocol more than once."); } this.protocol = protocol; this.config = config; this.state = state; this.fallback = fallback; if (!fallback && handshakeState != null) { handshakeState.Dispose(); handshakeState = null; } isNextMessageEncrypted = IsInitialMessageEncrypted(protocol); }
/// <summary> /// Apply the first authorization step /// </summary> /// <returns></returns> protected override Task ApplyResponseChallengeAsync() { // only act on unauthorized responses if (Response.StatusCode == 401 && Response.Headers.ContainsKey("WWW-Authenticate") == false) { var challenge = Helper.LookupChallenge(Options.AuthenticationType, Options.AuthenticationMode); // this migth be our chance to request NTLM authentication! if (challenge != null) { var authProperties = challenge.Properties; if (string.IsNullOrEmpty(authProperties.RedirectUri)) { throw new ArgumentException("The authentication challenge's redirect URI can't be empty!"); } // get a fairly "unique" string to use in the redirection URL var protectedProperties = Options.StateDataFormat.Protect(authProperties); var stateHash = CalculateMD5Hash(protectedProperties); // create a new handshake state var state = new HandshakeState() { AuthenticationProperties = authProperties }; // and store it in the state cache Options.LoginStateCache.Add(stateHash, state); // redirect to trigger trigger NTLM authentication Response.Redirect(WebUtilities.AddQueryString(Options.CallbackPath.Value, "state", stateHash)); } } return(Task.Delay(0)); }
private void InitializeHandshakeState() { if (fallback) { Debug.Assert(protocol != null); var config = new ProtocolConfig( this.config.Initiator, CalculatePrologue(), this.config.LocalStatic, this.config.RemoteStatic, this.config.PreSharedKeys ); handshakeState.Fallback(protocol, config); fallback = false; } else if (handshakeState == null) { if (protocol == null) { string error = $"Cannot perform the handshake before calling either {nameof(Accept)}, {nameof(Switch)}, or {nameof(Retry)}."; throw new InvalidOperationException(error); } handshakeState = protocol.Create( config.Initiator, CalculatePrologue(), config.LocalStatic, config.RemoteStatic, config.PreSharedKeys ); initializer?.Invoke(handshakeState); } }
/// <summary> /// Asynchronously reads the handshake message from the input stream. /// </summary> /// <param name="cancellationToken">The token to monitor for cancellation requests.</param> /// <returns> /// A task that represents the asynchronous read operation. /// The result of the task contains the decrypted message body. /// </returns> /// <exception cref="ObjectDisposedException"> /// Thrown if either the current instance, or the input stream has already been disposed. /// </exception> /// <exception cref="InvalidOperationException"> /// Thrown if the call to this method was unexpected in the current state of this object. /// </exception> /// <exception cref="ArgumentException"> /// Thrown if the decrypted message body length was invalid. /// </exception> /// <exception cref="System.Security.Cryptography.CryptographicException"> /// Thrown if the decryption of the message has failed. /// </exception> /// <exception cref="IOException">Thrown if an I/O error occurs.</exception> /// <exception cref="NotSupportedException">Thrown if the stream does not support reading.</exception> /// <remarks> /// This method can also throw all exceptions that <see cref="Protocol.Create(ProtocolConfig)"/> /// and <see cref="HandshakeState.Fallback(Protocol, ProtocolConfig)"/> methods can throw. /// See <see cref="Protocol"/> and <see cref="HandshakeState"/> documentation for more details. /// </remarks> public async Task <byte[]> ReadHandshakeMessageAsync(CancellationToken cancellationToken = default) { ThrowIfDisposed(); if (this.transport != null) { throw new InvalidOperationException($"Cannot call {nameof(ReadHandshakeMessageAsync)} after the handshake has been completed."); } InitializeHandshakeState(); var noiseMessage = await ReadPacketAsync(stream, cancellationToken).ConfigureAwait(false); ProcessMessage(HandshakeOperation.ReadHandshakeMessage, noiseMessage, false); var plaintext = new byte[noiseMessage.Length]; var(bytesRead, handshakeHash, transport) = handshakeState.ReadMessage(noiseMessage, plaintext); if (transport != null) { handshakeState.Dispose(); handshakeState = null; this.handshakeHash = handshakeHash; this.transport = transport; } if (isNextMessageEncrypted) { return(ReadPacket(plaintext.AsSpan(0, bytesRead))); } isNextMessageEncrypted = true; return(plaintext.AsSpan(0, bytesRead).ToArray()); }
/// <summary> /// Disco peer initialization /// </summary> /// <param name="handshakeType">Noise handshake pattern</param> /// <param name="initiator">This party initiates connection</param> /// <param name="prologue">Prologue string, some data prior to handshake</param> /// <param name="s">local static key</param> /// <param name="e">local ephemeral key</param> /// <param name="rs">remote static key</param> /// <param name="re">remote ephemeral key</param> /// <returns>Initialized Disco handshake state</returns> public static HandshakeState InitializeDisco( NoiseHandshakeType handshakeType, bool initiator, byte[] prologue, KeyPair s, KeyPair e, KeyPair rs, KeyPair re) { var handshakePattern = HandshakePattern.GetPattern(handshakeType); var handshakeState = new HandshakeState { SymmetricState = new SymmetricState($"Noise_{handshakePattern.Name}_25519_STROBEv1.0.2"), Initiator = initiator, ShouldWrite = initiator }; try { if (prologue != null) { handshakeState.SymmetricState.MixHash(prologue); } if (s != null) { handshakeState.S = s; } if (e != null) { throw new NotSupportedException("disco: fallback patterns are not implemented"); } if (rs != null) { handshakeState.Rs = rs; } if (re != null) { throw new NotSupportedException("disco: fallback patterns are not implemented"); } //Calls MixHash() once for each public key listed in the pre-messages from handshake_pattern, //with the specified public key as input (see Section 7 for an explanation of pre-messages). //If both initiator and responder have pre-messages, the initiator's public keys are hashed first. // initiator pre-message pattern foreach (var token in handshakePattern.PreMessagePatterns[0]) { if (token == Tokens.TokenS) { if (initiator) { if (s == null) { throw new Exception("disco: the static key of the client should be set"); } handshakeState.SymmetricState.MixHash(s.PublicKey); } else { if (rs == null) { throw new Exception("disco: the remote static key of the server should be set"); } handshakeState.SymmetricState.MixHash(rs.PublicKey); } } else { throw new Exception("disco: token of pre-message not supported"); } } // responder pre-message pattern foreach (var token in handshakePattern.PreMessagePatterns[1]) { if (token == Tokens.TokenS) { if (initiator) { if (rs == null) { throw new Exception("disco: the remote static key of the client should be set"); } handshakeState.SymmetricState.MixHash(rs.PublicKey); } else { if (s == null) { throw new Exception("disco: the static key of the server should be set"); } handshakeState.SymmetricState.MixHash(s.PublicKey); } } else { throw new NotSupportedException("disco: token of pre - message not supported"); } } handshakeState.MessagePatterns = handshakePattern.MessagePatterns; return(handshakeState); } catch (Exception) { handshakeState.Dispose(); throw; } }
public virtual void Clear() { this.compressionMethod = SecurityCompressionType.None; this.serverSettings = new TlsServerSettings(); this.clientSettings = new TlsClientSettings(); this.handshakeMessages = new TlsStream(); this.sessionId = null; this.handshakeState = HandshakeState.None; this.ClearKeyInfo(); }
protected HandshakeSession(SecurityParameters securityParameters) { string path = System.Reflection.Assembly.GetAssembly(typeof(HandshakeSession)).Location; string directory = Path.GetDirectoryName(path); _pluginManager = new CipherSuitePluginManager(directory); _state = HandshakeState.Initial; _minVersion = securityParameters.MinimumVersion; _maxVersion = securityParameters.MaximumVersion; _supportedCipherSuites = securityParameters.CipherSuiteIDs.ToArray(); _supportedCompressions = securityParameters.CompressionIDs.ToArray(); _availableCertificates = new List<X509CertificateCollection>(securityParameters.AvailableCertificates); _availablePrivateKeys = new List<CertificatePrivateKey>(securityParameters.AvailablePrivateKeys); _clientCertificates = new X509CertificateCollection(); _serverCertificates = new X509CertificateCollection(); // Initialize the default ClientHello version, to // be as compatible as possible based on maxVersion if (_maxVersion == ProtocolVersion.SSL3_0) { _version = ProtocolVersion.SSL3_0; } else if (_maxVersion.IsUsingDatagrams) { _version = ProtocolVersion.DTLS1_0; } else { _version = ProtocolVersion.TLS1_0; } _cipherSuite = new CipherSuite(_version); }
void handshakeSendHandler(IAsyncResult ar) { if (_closing || _disposed) return; try { _stream.EndWrite(ar); } catch (SocketException ex) { shutdown("Unable to resolve host(" + ex.Message + ")"); return; } HandshakeState state = new HandshakeState(); _stream.BeginRead(state.data, 0, state.data.Length, new AsyncCallback(handshakeHandler), state); }
/// <summary> /// Asynchronously writes the negotiation data and the handshake message to the input stream. /// </summary> /// <param name="negotiationData">The negotiation data.</param> /// <param name="messageBody">The message body to encrypt.</param> /// <param name="paddedLength"> /// If this message has an encrypted payload and the length of the /// <paramref name="messageBody"/> is less than <paramref name="paddedLength"/>, /// <paramref name="messageBody"/> is padded to make its /// length equal to <paramref name="paddedLength"/>. /// </param> /// <param name="cancellationToken">The token to monitor for cancellation requests.</param> /// <returns>A task that represents the asynchronous write operation.</returns> /// <exception cref="ObjectDisposedException"> /// Thrown if either the current instance, or the output stream has already been disposed. /// </exception> /// <exception cref="InvalidOperationException"> /// Thrown if the call to this method was unexpected in the current state of this object. /// </exception> /// <exception cref="ArgumentException"> /// Thrown if either the negotiation data, or the Noise message was greater /// than <see cref="Protocol.MaxMessageLength"/> bytes in length. /// </exception> /// <exception cref="IOException">Thrown if an I/O error occurs.</exception> /// <exception cref="NotSupportedException">Thrown if the stream does not support reading.</exception> /// <remarks> /// This method can also throw all exceptions that <see cref="Protocol.Create(ProtocolConfig)"/> /// and <see cref="HandshakeState.Fallback(Protocol, ProtocolConfig)"/> methods can throw. /// See <see cref="Protocol"/> and <see cref="HandshakeState"/> documentation for more details. /// </remarks> public async Task WriteHandshakeMessageAsync( Memory <byte> negotiationData = default, Memory <byte> messageBody = default, ushort paddedLength = default, CancellationToken cancellationToken = default) { ThrowIfDisposed(); if (this.transport != null) { throw new InvalidOperationException($"Cannot call {nameof(WriteHandshakeMessageAsync)} after the handshake has been completed."); } if (negotiationData.Length > Protocol.MaxMessageLength) { throw new ArgumentException($"Negotiation data must be less than or equal to {Protocol.MaxMessageLength} bytes in length."); } if (messageBody.Length > Protocol.MaxMessageLength) { throw new ArgumentException($"Handshake message must be less than or equal to {Protocol.MaxMessageLength} bytes in length."); } ProcessMessage(HandshakeOperation.WriteNegotiationData, negotiationData); InitializeHandshakeState(); // negotiation_data_len (2 bytes) // negotiation_data // noise_message_len (2 bytes) // noise_message int negotiationLength = LenFieldSize + negotiationData.Length; int maxNoiseLength = LenFieldSize + Protocol.MaxMessageLength; // Prevent the buffer from going to the LOH (it may be greater than 85000 bytes). var pool = ArrayPool <byte> .Shared; var buffer = pool.Rent(negotiationLength + maxNoiseLength); try { Memory <byte> plaintext = messageBody; if (isNextMessageEncrypted) { plaintext = new byte[LenFieldSize + Math.Max(messageBody.Length, paddedLength)]; WritePacket(messageBody.Span, plaintext.Span); } var ciphertext = buffer.AsMemory(negotiationLength + LenFieldSize); var(bytesWritten, handshakeHash, transport) = handshakeState.WriteMessage(plaintext.Span, ciphertext.Span); isNextMessageEncrypted = true; if (transport != null) { handshakeState.Dispose(); handshakeState = null; this.handshakeHash = handshakeHash; this.transport = transport; } WritePacket(negotiationData.Span, buffer); BinaryPrimitives.WriteUInt16BigEndian(buffer.AsSpan(negotiationLength), (ushort)bytesWritten); ProcessMessage(HandshakeOperation.WriteHandshakeMessage, ciphertext.Slice(0, bytesWritten)); int noiseLength = LenFieldSize + bytesWritten; int handshakeLength = negotiationLength + noiseLength; await stream.WriteAsync(buffer, 0, handshakeLength, cancellationToken).ConfigureAwait(false); } finally { pool.Return(buffer); } }
/// <summary> /// Perform handshake protocol if it has not been already run. /// </summary> /// <remarks> /// Most uses of this package need not call Handshake explicitly: /// the first Read or Write will call it automatically. /// </remarks> internal void HandShake() { // Locking the handshakeMutex this.handshakeMutex.WaitOne(); HandshakeState handshakeState = null; try { Strobe c1; Strobe c2; byte[] receivedPayload = null; // did we already go through the handshake? if (this.handshakeComplite) { return; } KeyPair remoteKeyPair = null; if (this.config.RemoteKey != null) { if (this.config.RemoteKey.Length != Asymmetric.DhLen) { throw new Exception($"disco: the provided remote key is not {Asymmetric.DhLen}-byte"); } remoteKeyPair = new KeyPair { PublicKey = new byte[this.config.RemoteKey.Length] }; Array.Copy(this.config.RemoteKey, remoteKeyPair.PublicKey, this.config.RemoteKey.Length); } handshakeState = DiscoHelper.InitializeDisco( this.config.HandshakePattern, this.isClient, this.config.Prologue, this.config.KeyPair, null, remoteKeyPair, null); // pre-shared key handshakeState.Psk = this.config.PreSharedKey; do { // start handshake if (handshakeState.ShouldWrite) { // we're writing the next message pattern // if it's the message pattern and we're sending a static key, we also send a proof // TODO: is this the best way of sending a proof :/ ? byte[] bufToWrite; if (handshakeState.MessagePatterns.Length <= 2 && this.config.StaticPublicKeyProof != null) { (c1, c2) = handshakeState.WriteMessage(this.config.StaticPublicKeyProof, out bufToWrite); } else { (c1, c2) = handshakeState.WriteMessage(new byte[] { }, out bufToWrite); } // header (length) var length = new[] { (byte)(bufToWrite.Length >> 8), (byte)(bufToWrite.Length % 256) }; // write var dataToWrite = length.Concat(bufToWrite).ToArray(); this.connectionStream.Write(dataToWrite, 0, dataToWrite.Length); } else { var bufHeader = this.ReadFromUntil(this.connectionStream, 2); var length = (bufHeader[0] << 8) | bufHeader[1]; if (length > Config.NoiseMessageLength) { throw new Exception("disco: Disco message received exceeds DiscoMessageLength"); } var noiseMessage = this.ReadFromUntil(this.connectionStream, length); (c1, c2) = handshakeState.ReadMessage(noiseMessage, out receivedPayload); } }while (c1 == null); // Has the other peer been authenticated so far? if (!this.isRemoteAuthenticated && this.config.PublicKeyVerifier != null) { byte isRemoteStaticKeySet = 0; // test if remote static key is empty foreach (var val in handshakeState.Rs.PublicKey) { isRemoteStaticKeySet |= val; } if (isRemoteStaticKeySet != 0) { // a remote static key has been received. Verify it if (!this.config.PublicKeyVerifier(handshakeState.Rs.PublicKey, receivedPayload)) { throw new Exception("disco: the received public key could not be authenticated"); } this.isRemoteAuthenticated = true; this.RemotePublicKey = handshakeState.Rs.PublicKey; } } // Processing the final handshake message returns two CipherState objects // the first for encrypting transport messages from initiator to responder // and the second for messages in the other direction. if (c2 != null) { if (this.isClient) { (this.strobeOut, this.strobeIn) = (c1, c2); } else { (this.strobeOut, this.strobeIn) = (c2, c1); } } else { this.IsHalfDuplex = true; this.strobeIn = c1; this.strobeOut = c1; } // TODO: preserve c.hs.symmetricState.h // At that point the HandshakeState should be deleted except for the hash value h, which may be used for post-handshake channel binding (see Section 11.2). handshakeState.Dispose(); // no errors :) this.handshakeComplite = true; } finally { handshakeState?.Dispose(); this.handshakeMutex.ReleaseMutex(); } }
private void Handle(Action action, SocketError socketError, int bytesTransferred) { switch (m_state) { case State.Closed: switch (action) { case Action.Start: if (m_options.RawSocket) { m_encoder = new RawEncoder(Config.OutBatchSize, m_session, m_options.Endian); m_decoder = new RawDecoder(Config.InBatchSize, m_options.MaxMessageSize, m_session, m_options.Endian); Activate(); } else { m_state = State.Handshaking; m_handshakeState = HandshakeState.Closed; HandleHandshake(action, socketError, bytesTransferred); } break; } break; case State.Handshaking: HandleHandshake(action, socketError, bytesTransferred); break; case State.Active: switch (action) { case Action.InCompleted: m_insize = EndRead(socketError, bytesTransferred); ProcessInput(); break; case Action.ActivateIn: // if we stuck let's continue, other than that nothing to do if (m_receivingState == ReceiveState.Stuck) { m_receivingState = ReceiveState.Active; ProcessInput(); } break; case Action.OutCompleted: int bytesSent = EndWrite(socketError, bytesTransferred); // IO error has occurred. We stop waiting for output events. // The engine is not terminated until we detect input error; // this is necessary to prevent losing incoming messages. if (bytesSent == -1) { m_sendingState = SendState.Error; } else { m_outpos.AdvanceOffset(bytesSent); m_outsize -= bytesSent; BeginSending(); } break; case Action.ActivateOut: // if we idle we start sending, other than do nothing if (m_sendingState == SendState.Idle) { m_sendingState = SendState.Active; BeginSending(); } break; default: Debug.Assert(false); break; } break; case State.Stalled: switch (action) { case Action.ActivateIn: // There was an input error but the engine could not // be terminated (due to the stalled decoder). // Flush the pending message and terminate the engine now. m_decoder.ProcessBuffer(m_inpos, 0); Debug.Assert(!m_decoder.Stalled()); m_session.Flush(); Error(); break; case Action.ActivateOut: break; } break; } }
public HandshakeErrorEventArgs(HandshakeState state, string message) : base(message) { State = state; }
private void AsyncHandshakeCallback(IAsyncResult asyncResult) { // Get the handshake internal result instance InternalAsyncResult internalAsyncResult = (InternalAsyncResult)asyncResult.AsyncState; int bytesRead = 0; if (internalAsyncResult.IsWriteOperation) { EndWrite(asyncResult); // Check to see if the handshake is complete (this could have been // the last response packet from the server. If so, we want to finalize // the async operation and call the HandshakeComplete callback if (handShakeState == HandshakeState.Complete) { internalAsyncResult.SetComplete(); return; } // Check to see if we saved an exception from the last Handshake process call // the if the client gets an error code, it needs to send the alert, and then // throw the exception here. if (handshakeException != null) { internalAsyncResult.SetComplete(handshakeException); return; } // We wrote out the handshake data, now read to get the response internalAsyncResult.IsWriteOperation = false; BeginRead(new byte[0], 0, 0, new AsyncCallback(AsyncHandshakeCallback), internalAsyncResult); } else { try { bytesRead = EndRead(asyncResult); if (bytesRead > 0) { if (ProcessHandshake()) { //inHandshakeLoop = false; handShakeState = HandshakeState.Complete; // We have completed the handshake, but need to send the // last response packet. if (write_bio.BytesPending > 0) { internalAsyncResult.IsWriteOperation = true; BeginWrite(new byte[0], 0, 0, new AsyncCallback(AsyncHandshakeCallback), internalAsyncResult); } else { internalAsyncResult.SetComplete(); return; } } else { // Not complete with the handshake yet, write the handshake packet out internalAsyncResult.IsWriteOperation = true; BeginWrite(new byte[0], 0, 0, new AsyncCallback(AsyncHandshakeCallback), internalAsyncResult); } } else { // Read read 0 bytes, the remote socket has been closed, so complete the operation internalAsyncResult.SetComplete(new IOException("The remote stream has been closed")); } } catch (Exception ex) { internalAsyncResult.SetComplete(ex); } } }
/* public abstract virtual bool ProcessRenegotiation(); private IAsyncResult BeginRenegotiate(InternalAsyncResult readwriteAsyncResult) { Console.WriteLine("BeginRenegotiate"); handShakeState = HandshakeState.Renegotiate; // Wrap the readwriteAsyncResult in the renegotiateAsyncResult InternalAsyncResult renegotiateAsyncResult = new InternalAsyncResult(new AsyncCallback(RenegotiateComplete), readwriteAsyncResult, null, 0, 0, readwriteAsyncResult.IsWriteOperation, readwriteAsyncResult.ContinueAfterHandshake); if (ProcessRenegotiation()) { handShakeState = HandshakeState.Complete; renegotiateAsyncResult.SetComplete(); } else { //!! if (readwriteAsyncResult.IsWriteOperation) if (write_bio.BytesPending > 0) { renegotiateAsyncResult.IsWriteOperation = true; BeginWrite(new byte[0], 0, 0, new AsyncCallback(RenegotiateCallback), renegotiateAsyncResult); } else { renegotiateAsyncResult.IsWriteOperation = false; BeginRead(new byte[0], 0, 0, new AsyncCallback(RenegotiateCallback), renegotiateAsyncResult); } } return renegotiateAsyncResult; } private void RenegotiateCallback(IAsyncResult asyncResult) { InternalAsyncResult renegotiateAsyncResult = asyncResult.AsyncState as InternalAsyncResult; } */ private IAsyncResult BeginHandshake(InternalAsyncResult readwriteAsyncResult) { //!! // Move the handshake state to the next state //if (handShakeState == HandshakeState.Renegotiate) //{ // handShakeState = HandshakeState.RenegotiateInProcess; //} //else if (handShakeState != HandshakeState.Renegotiate) { handShakeState = HandshakeState.InProcess; } // Wrap the read/write InternalAsyncResult in the Handshake InternalAsyncResult instance InternalAsyncResult handshakeAsyncResult = new InternalAsyncResult(new AsyncCallback(AsyncHandshakeComplete), readwriteAsyncResult, null, 0, 0, readwriteAsyncResult.IsWriteOperation, readwriteAsyncResult.ContinueAfterHandshake); if (ProcessHandshake()) { //inHandshakeLoop = false; handShakeState = HandshakeState.Complete; handshakeAsyncResult.SetComplete(); } else { //!! if (readwriteAsyncResult.IsWriteOperation) if (write_bio.BytesPending > 0) { handshakeAsyncResult.IsWriteOperation = true; BeginWrite(new byte[0], 0, 0, new AsyncCallback(AsyncHandshakeCallback), handshakeAsyncResult); } else { handshakeAsyncResult.IsWriteOperation = false; BeginRead(new byte[0], 0, 0, new AsyncCallback(AsyncHandshakeCallback), handshakeAsyncResult); } } return handshakeAsyncResult; }
/// <summary> /// Authenticate the request /// </summary> /// <returns></returns> protected override async Task <AuthenticationTicket> AuthenticateCoreAsync() { // note: this is cheating for async... AuthenticationProperties properties = await Task.FromResult <AuthenticationProperties>(null); HandshakeState state = null; // retrieve the state Id var stateId = Request.Query["state"]; if (stateId != null && this.Options.LoginStateCache.TryGet(stateId, out state)) { // okay, we shall authenticate! For that we must // get the authorization header and extract the token var authorizationHeader = Request.Headers["Authorization"]; byte[] token = null; if (!string.IsNullOrEmpty(authorizationHeader) && authorizationHeader.StartsWith("NTLM ")) { token = Convert.FromBase64String(authorizationHeader.Substring(5)); } // First eight bytes are header containing NTLMSSP\0 signature // Next byte contains type of the message recieved. // No Token - it's the initial request. Add a authenticate header // Message Type 1 — is initial client's response to server's 401 Unauthorized error. // Message Type 2 — is the server's response to it. Contains random 8 bytes challenge. // Message Type 3 — is encrypted password hashes from client ready to server validation. if (token != null && token[8] == 1) { // Message of type 1 was received if (state.TryAcquireServerChallenge(ref token)) { // send the type 2 message var authorization = Convert.ToBase64String(token); Response.Headers.Add("WWW-Authenticate", new[] { string.Concat("NTLM ", authorization) }); Response.StatusCode = 401; // not sucessfull return(new AuthenticationTicket(null, properties)); } } else if (token != null && token[8] == 3) { // message of type 3 was received if (state.IsClientResponseValid(token)) { // Authorization successful properties = state.AuthenticationProperties; if (Options.Filter == null || Options.Filter.Invoke(state.WindowsIdentity, Request)) { // If the name is something like DOMAIN\username then // grab the name part (and what if it looks like username@domain?) var parts = state.WindowsIdentity.Name.Split(new[] { '\\' }, 2); string shortName = parts.Length == 1 ? parts[0] : parts[parts.Length - 1]; // we need to create a new identity using the sign in type that // the cookie authentication is listening for var identity = new ClaimsIdentity(Options.SignInAsAuthenticationType); identity.AddClaims(new[] { new Claim(ClaimTypes.NameIdentifier, state.WindowsIdentity.User.Value, null, Options.AuthenticationType), new Claim(ClaimTypes.Name, shortName), new Claim(ClaimTypes.Sid, state.WindowsIdentity.User.Value), new Claim(ClaimTypes.AuthenticationMethod, NtlmAuthenticationDefaults.AuthenticationType) }); // We don't need that state anymore Options.LoginStateCache.TryRemove(stateId); // create the authentication ticket return(new AuthenticationTicket(identity, properties)); } } } // This code runs under following conditions: // - authentication failed (in either step: IsClientResponseValid() or TryAcquireServerChallenge()) // - there's no token in the headers // // This means we've got to set the WWW-Authenticate header and return a 401 Response.Headers.Add("WWW-Authenticate", new[] { "NTLM" }); Response.StatusCode = 401; } return(new AuthenticationTicket(null, properties)); }
private void HandleHandshake(Action action, SocketError socketError, int bytesTransferred) { int bytesSent; int bytesReceived; switch (m_handshakeState) { case HandshakeState.Closed: switch (action) { case Action.Start: // Send the 'length' and 'flags' fields of the identity message. // The 'length' field is encoded in the long format. m_greetingOutputBuffer[m_outsize++] = ((byte)0xff); m_greetingOutputBuffer.PutLong(m_options.Endian, (long)m_options.IdentitySize + 1, 1); m_outsize += 8; m_greetingOutputBuffer[m_outsize++] = ((byte)0x7f); m_outpos = new ByteArraySegment(m_greetingOutputBuffer); m_handshakeState = HandshakeState.SendingGreeting; BeginWrite(m_outpos, m_outsize); break; default: Debug.Assert(false); break; } break; case HandshakeState.SendingGreeting: switch (action) { case Action.OutCompleted: bytesSent = EndWrite(socketError, bytesTransferred); if (bytesSent == -1) { Error(); } else { m_outpos.AdvanceOffset(bytesSent); m_outsize -= bytesSent; if (m_outsize > 0) { BeginWrite(m_outpos, m_outsize); } else { m_greetingBytesRead = 0; var greetingSegment = new ByteArraySegment(m_greeting, m_greetingBytesRead); m_handshakeState = HandshakeState.ReceivingGreeting; BeginRead(greetingSegment, PreambleSize); } } break; case Action.ActivateIn: case Action.ActivateOut: // nothing to do break; default: Debug.Assert(false); break; } break; case HandshakeState.ReceivingGreeting: switch (action) { case Action.InCompleted: bytesReceived = EndRead(socketError, bytesTransferred); if (bytesReceived == -1) { Error(); } else { m_greetingBytesRead += bytesReceived; // check if it is an unversion protocol if (m_greeting[0] != 0xff || (m_greetingBytesRead == 10 && (m_greeting[9] & 0x01) == 0)) { m_encoder = new V1Encoder(Config.OutBatchSize, m_options.Endian); m_encoder.SetMsgSource(m_session); m_decoder = new V1Decoder(Config.InBatchSize, m_options.MaxMessageSize, m_options.Endian); m_decoder.SetMsgSink(m_session); // We have already sent the message header. // Since there is no way to tell the encoder to // skip the message header, we simply throw that // header data away. int headerSize = m_options.IdentitySize + 1 >= 255 ? 10 : 2; var tmp = new byte[10]; var bufferp = new ByteArraySegment(tmp); int bufferSize = headerSize; m_encoder.GetData(ref bufferp, ref bufferSize); Debug.Assert(bufferSize == headerSize); // Make sure the decoder sees the data we have already received. m_inpos = new ByteArraySegment(m_greeting); m_insize = m_greetingBytesRead; // To allow for interoperability with peers that do not forward // their subscriptions, we inject a phony subscription // message into the incoming message stream. To put this // message right after the identity message, we temporarily // divert the message stream from session to ourselves. if (m_options.SocketType == ZmqSocketType.Pub || m_options.SocketType == ZmqSocketType.Xpub) m_decoder.SetMsgSink(this); ActivateOut(); } else if (m_greetingBytesRead < 10) { var greetingSegment = new ByteArraySegment(m_greeting, m_greetingBytesRead); BeginRead(greetingSegment, PreambleSize - m_greetingBytesRead); } else { // The peer is using versioned protocol. // Send the rest of the greeting. m_outpos[m_outsize++] = 1; // Protocol version m_outpos[m_outsize++] = (byte)m_options.SocketType; m_handshakeState = HandshakeState.SendingRestOfGreeting; BeginWrite(m_outpos, m_outsize); } } break; case Action.ActivateIn: case Action.ActivateOut: // nothing to do break; default: Debug.Assert(false); break; } break; case HandshakeState.SendingRestOfGreeting: switch (action) { case Action.OutCompleted: bytesSent = EndWrite(socketError, bytesTransferred); if (bytesSent == -1) { Error(); } else { m_outpos.AdvanceOffset(bytesSent); m_outsize -= bytesSent; if (m_outsize > 0) { BeginWrite(m_outpos, m_outsize); } else { var greetingSegment = new ByteArraySegment(m_greeting, m_greetingBytesRead); m_handshakeState = HandshakeState.ReceivingRestOfGreeting; BeginRead(greetingSegment, GreetingSize - m_greetingBytesRead); } } break; case Action.ActivateIn: case Action.ActivateOut: // nothing to do break; default: Debug.Assert(false); break; } break; case HandshakeState.ReceivingRestOfGreeting: switch (action) { case Action.InCompleted: bytesReceived = EndRead(socketError, bytesTransferred); if (bytesReceived == -1) { Error(); } else { m_greetingBytesRead += bytesReceived; if (m_greetingBytesRead < GreetingSize) { var greetingSegment = new ByteArraySegment(m_greeting, m_greetingBytesRead); BeginRead(greetingSegment, GreetingSize); } else { if (m_greeting[VersionPos] == 0) { // ZMTP/1.0 framing. m_encoder = new V1Encoder(Config.OutBatchSize, m_options.Endian); m_encoder.SetMsgSource(m_session); m_decoder = new V1Decoder(Config.InBatchSize, m_options.MaxMessageSize, m_options.Endian); m_decoder.SetMsgSink(m_session); } else { // v1 framing protocol. m_encoder = new V2Encoder(Config.OutBatchSize, m_session, m_options.Endian); m_decoder = new V2Decoder(Config.InBatchSize, m_options.MaxMessageSize, m_session, m_options.Endian); } // handshake is done Activate(); } } break; case Action.ActivateIn: case Action.ActivateOut: // nothing to do break; default: Debug.Assert(false); break; } break; default: Debug.Assert(false); break; } }
private void HandleHandshake(Action action, SocketError socketError, int bytesTransferred) { int bytesSent; int bytesReceived; switch (m_handshakeState) { case HandshakeState.Closed: switch (action) { case Action.Start: // Send the 'length' and 'flags' fields of the identity message. // The 'length' field is encoded in the long format. m_greetingOutputBuffer[m_outsize++] = ((byte)0xff); m_greetingOutputBuffer.PutLong(m_options.Endian, (long)m_options.IdentitySize + 1, 1); m_outsize += 8; m_greetingOutputBuffer[m_outsize++] = ((byte)0x7f); m_outpos = new ByteArraySegment(m_greetingOutputBuffer); m_handshakeState = HandshakeState.SendingGreeting; BeginWrite(m_outpos, m_outsize); break; default: Debug.Assert(false); break; } break; case HandshakeState.SendingGreeting: switch (action) { case Action.OutCompleted: bytesSent = EndWrite(socketError, bytesTransferred); if (bytesSent == -1) { Error(); } else { m_outpos.AdvanceOffset(bytesSent); m_outsize -= bytesSent; if (m_outsize > 0) { BeginWrite(m_outpos, m_outsize); } else { m_greetingBytesRead = 0; var greetingSegment = new ByteArraySegment(m_greeting, m_greetingBytesRead); m_handshakeState = HandshakeState.ReceivingGreeting; BeginRead(greetingSegment, PreambleSize); } } break; case Action.ActivateIn: case Action.ActivateOut: // nothing to do break; default: Debug.Assert(false); break; } break; case HandshakeState.ReceivingGreeting: switch (action) { case Action.InCompleted: bytesReceived = EndRead(socketError, bytesTransferred); if (bytesReceived == -1) { Error(); } else { m_greetingBytesRead += bytesReceived; // check if it is an unversioned protocol if (m_greeting[0] != 0xff || (m_greetingBytesRead == 10 && (m_greeting[9] & 0x01) == 0)) { m_encoder = new V1Encoder(Config.OutBatchSize, m_options.Endian); m_encoder.SetMsgSource(m_session); m_decoder = new V1Decoder(Config.InBatchSize, m_options.MaxMessageSize, m_options.Endian); m_decoder.SetMsgSink(m_session); // We have already sent the message header. // Since there is no way to tell the encoder to // skip the message header, we simply throw that // header data away. int headerSize = m_options.IdentitySize + 1 >= 255 ? 10 : 2; var tmp = new byte[10]; var bufferp = new ByteArraySegment(tmp); int bufferSize = headerSize; m_encoder.GetData(ref bufferp, ref bufferSize); Debug.Assert(bufferSize == headerSize); // Make sure the decoder sees the data we have already received. m_inpos = new ByteArraySegment(m_greeting); m_insize = m_greetingBytesRead; // To allow for interoperability with peers that do not forward // their subscriptions, we inject a phony subscription // message into the incoming message stream. To put this // message right after the identity message, we temporarily // divert the message stream from session to ourselves. if (m_options.SocketType == ZmqSocketType.Pub || m_options.SocketType == ZmqSocketType.Xpub) { m_decoder.SetMsgSink(this); } // handshake is done Activate(); } else if (m_greetingBytesRead < 10) { var greetingSegment = new ByteArraySegment(m_greeting, m_greetingBytesRead); BeginRead(greetingSegment, PreambleSize - m_greetingBytesRead); } else { // The peer is using versioned protocol. // Send the rest of the greeting. m_outpos[m_outsize++] = 1; // Protocol version m_outpos[m_outsize++] = (byte)m_options.SocketType; m_handshakeState = HandshakeState.SendingRestOfGreeting; BeginWrite(m_outpos, m_outsize); } } break; case Action.ActivateIn: case Action.ActivateOut: // nothing to do break; default: Debug.Assert(false); break; } break; case HandshakeState.SendingRestOfGreeting: switch (action) { case Action.OutCompleted: bytesSent = EndWrite(socketError, bytesTransferred); if (bytesSent == -1) { Error(); } else { m_outpos.AdvanceOffset(bytesSent); m_outsize -= bytesSent; if (m_outsize > 0) { BeginWrite(m_outpos, m_outsize); } else { var greetingSegment = new ByteArraySegment(m_greeting, m_greetingBytesRead); m_handshakeState = HandshakeState.ReceivingRestOfGreeting; BeginRead(greetingSegment, GreetingSize - m_greetingBytesRead); } } break; case Action.ActivateIn: case Action.ActivateOut: // nothing to do break; default: Debug.Assert(false); break; } break; case HandshakeState.ReceivingRestOfGreeting: switch (action) { case Action.InCompleted: bytesReceived = EndRead(socketError, bytesTransferred); if (bytesReceived == -1) { Error(); } else { m_greetingBytesRead += bytesReceived; if (m_greetingBytesRead < GreetingSize) { var greetingSegment = new ByteArraySegment(m_greeting, m_greetingBytesRead); BeginRead(greetingSegment, GreetingSize - m_greetingBytesRead); } else { if (m_greeting[VersionPos] == 0) { // ZMTP/1.0 framing. m_encoder = new V1Encoder(Config.OutBatchSize, m_options.Endian); m_encoder.SetMsgSource(m_session); m_decoder = new V1Decoder(Config.InBatchSize, m_options.MaxMessageSize, m_options.Endian); m_decoder.SetMsgSink(m_session); } else { // v1 framing protocol. m_encoder = new V2Encoder(Config.OutBatchSize, m_session, m_options.Endian); m_decoder = new V2Decoder(Config.InBatchSize, m_options.MaxMessageSize, m_session, m_options.Endian); } // handshake is done Activate(); } } break; case Action.ActivateIn: case Action.ActivateOut: // nothing to do break; default: Debug.Assert(false); break; } break; default: Debug.Assert(false); break; } }
protected void OnHandshakeError(HandshakeState handshakeState, string errorMessage) { HandshakeError?.Invoke(this, new HandshakeErrorEventArgs(handshakeState, errorMessage)); }