private void SafeReadData() { try { rs.ReadData(); } catch (TlsFatalAlert e) { if (!this.closed) { this.FailWithError(AlertLevel.fatal, e.AlertDescription); } throw e; } catch (IOException e) { if (!this.closed) { this.FailWithError(AlertLevel.fatal, AlertDescription.internal_error); } throw e; } catch (Exception e) { if (!this.closed) { this.FailWithError(AlertLevel.fatal, AlertDescription.internal_error); } throw e; } }
private void SafeReadData() { try { rs.ReadData(); } catch (EndOfStreamException) { if (this.connection_state == CS_DONE) { this.Close(); } else { throw; } } catch (TlsFatalAlert e) { if (!this.closed) { this.FailWithError(AlertLevel.fatal, e.AlertDescription); } throw e; } catch (IOException e) { if (!this.closed) { this.FailWithError(AlertLevel.fatal, AlertDescription.internal_error); } throw e; } catch (Exception e) { if (!this.closed) { this.FailWithError(AlertLevel.fatal, AlertDescription.internal_error); } throw e; } }
/// <summary>Connects to the remote system.</summary> /// <param name="verifyer">Will be used when a certificate is received to verify /// that this certificate is accepted by the client.</param> /// <exception cref="IOException">If handshake was not successful</exception> public virtual void Connect( ICertificateVerifyer verifyer) { this.verifyer = verifyer; /* * Send Client hello * * First, generate some random data. */ this.clientRandom = new byte[32]; /* * TLS 1.0 requires a unix-timestamp in the first 4 bytes */ int t = (int)(DateTimeUtilities.CurrentUnixMs() / 1000L); this.clientRandom[0] = (byte)(t >> 24); this.clientRandom[1] = (byte)(t >> 16); this.clientRandom[2] = (byte)(t >> 8); this.clientRandom[3] = (byte)t; random.NextBytes(this.clientRandom, 4, 28); MemoryStream outStr = new MemoryStream(); TlsUtilities.WriteVersion(outStr); outStr.Write(this.clientRandom, 0, this.clientRandom.Length); /* * Length of Session id */ TlsUtilities.WriteUint8((short)0, outStr); /* * Cipher suites */ TlsCipherSuiteManager.WriteCipherSuites(outStr); /* * Compression methods, just the null method. */ byte[] compressionMethods = new byte[] { 0x00 }; TlsUtilities.WriteUint8((short)compressionMethods.Length, outStr); outStr.Write(compressionMethods, 0, compressionMethods.Length); MemoryStream bos = new MemoryStream(); TlsUtilities.WriteUint8(HP_CLIENT_HELLO, bos); TlsUtilities.WriteUint24((int)outStr.Length, bos); byte[] outBytes = outStr.ToArray(); bos.Write(outBytes, 0, outBytes.Length); byte[] message = bos.ToArray(); rs.WriteMessage(RL_HANDSHAKE, message, 0, message.Length); connection_state = CS_CLIENT_HELLO_SEND; /* * We will now read data, until we have completed the handshake. */ while (connection_state != CS_DONE) { rs.ReadData(); } this.tlsInputStream = new TlsInputStream(this); this.tlsOutputStream = new TlsOuputStream(this); }
// public void Connect(ICertificateVerifyer verifyer, Certificate clientCertificate, // AsymmetricKeyParameter clientPrivateKey) // { // DefaultTlsClient client = new DefaultTlsClient(verifyer); // client.EnableClientAuthentication(clientCertificate, clientPrivateKey); // // this.Connect(client); // } // TODO Make public internal virtual void Connect(TlsClient tlsClient) { if (tlsClient == null) { throw new ArgumentNullException("tlsClient"); } if (this.tlsClient != null) { throw new InvalidOperationException("Connect can only be called once"); } this.tlsClient = tlsClient; this.tlsClient.Init(this); /* * Send Client hello * * First, generate some random data. */ securityParameters = new SecurityParameters(); securityParameters.clientRandom = new byte[32]; random.NextBytes(securityParameters.clientRandom, 4, 28); TlsUtilities.WriteGmtUnixTime(securityParameters.clientRandom, 0); MemoryStream outStr = new MemoryStream(); TlsUtilities.WriteVersion(outStr); outStr.Write(securityParameters.clientRandom, 0, 32); /* * Length of Session id */ TlsUtilities.WriteUint8((short)0, outStr); /* * Cipher suites */ this.offeredCipherSuites = this.tlsClient.GetCipherSuites(); // Note: 1 extra slot for TLS_EMPTY_RENEGOTIATION_INFO_SCSV TlsUtilities.WriteUint16(2 * (offeredCipherSuites.Length + 1), outStr); for (int i = 0; i < offeredCipherSuites.Length; ++i) { TlsUtilities.WriteUint16(offeredCipherSuites[i], outStr); } // RFC 5746 3.3 // Note: If renegotiation added, remove this (and extra slot above) TlsUtilities.WriteUint16(TLS_EMPTY_RENEGOTIATION_INFO_SCSV, outStr); /* * Compression methods, just the null method. */ byte[] compressionMethods = new byte[] { 0x00 }; TlsUtilities.WriteOpaque8(compressionMethods, outStr); /* * Extensions */ // Int32 -> byte[] Hashtable clientExtensions = this.tlsClient.GenerateClientExtensions(); // RFC 5746 3.4 // Note: If renegotiation is implemented, need to use this instead of TLS_EMPTY_RENEGOTIATION_INFO_SCSV // { // if (clientExtensions == null) // clientExtensions = new Hashtable(); // // clientExtensions[EXT_RenegotiationInfo] = CreateRenegotiationInfo(emptybuf); // } this.extendedClientHello = clientExtensions != null && clientExtensions.Count > 0; if (extendedClientHello) { MemoryStream ext = new MemoryStream(); foreach (int extType in clientExtensions.Keys) { byte[] extValue = (byte[])clientExtensions[extType]; TlsUtilities.WriteUint16(extType, ext); TlsUtilities.WriteOpaque16(extValue, ext); } TlsUtilities.WriteOpaque16(ext.ToArray(), outStr); } MemoryStream bos = new MemoryStream(); TlsUtilities.WriteUint8(HP_CLIENT_HELLO, bos); TlsUtilities.WriteUint24((int)outStr.Length, bos); byte[] outBytes = outStr.ToArray(); bos.Write(outBytes, 0, outBytes.Length); byte[] message = bos.ToArray(); rs.WriteMessage(RL_HANDSHAKE, message, 0, message.Length); connection_state = CS_CLIENT_HELLO_SEND; /* * We will now read data, until we have completed the handshake. */ while (connection_state != CS_DONE) { // TODO Should we send fatal alerts in the event of an exception // (see readApplicationData) rs.ReadData(); } this.tlsStream = new TlsStream(this); }