Esempio n. 1
0
        internal static TlsClientProtocol OpenTlsConnection(string hostname, int port, TlsClient client)
        {
            TcpClient tcp = new TcpClient(hostname, port);

            TlsClientProtocol protocol = new TlsClientProtocol(tcp.GetStream(), secureRandom);
            protocol.Connect(client);
            return protocol;
        }
Esempio n. 2
0
        public SecureTcpClient(string host, int port, TlsClient tlsClient)
            : base(AddressFamily.InterNetwork)
        {
            this.tlsClient = tlsClient;

            var myEndpoint = new DnsEndPoint(host, port);
            InnerConnect(myEndpoint);
        }
Esempio n. 3
0
        public virtual DtlsTransport Connect(TlsClient client, DatagramTransport transport)
        {
            if (client == null)
                throw new ArgumentNullException("client");
            if (transport == null)
                throw new ArgumentNullException("transport");

            SecurityParameters securityParameters = new SecurityParameters();
            securityParameters.entity = ConnectionEnd.client;

            ClientHandshakeState state = new ClientHandshakeState();
            state.client = client;
            state.clientContext = new TlsClientContextImpl(mSecureRandom, securityParameters);

            securityParameters.clientRandom = TlsProtocol.CreateRandomBlock(client.ShouldUseGmtUnixTime(),
                state.clientContext.NonceRandomGenerator);

            client.Init(state.clientContext);

            DtlsRecordLayer recordLayer = new DtlsRecordLayer(transport, state.clientContext, client, ContentType.handshake);

            TlsSession sessionToResume = state.client.GetSessionToResume();
            if (sessionToResume != null && sessionToResume.IsResumable)
            {
                SessionParameters sessionParameters = sessionToResume.ExportSessionParameters();
                if (sessionParameters != null)
                {
                    state.tlsSession = sessionToResume;
                    state.sessionParameters = sessionParameters;
                }
            }

            try
            {
                return ClientHandshake(state, recordLayer);
            }
            catch (TlsFatalAlert fatalAlert)
            {
                AbortClientHandshake(state, recordLayer, fatalAlert.AlertDescription);
                throw fatalAlert;
            }
            catch (IOException e)
            {
                AbortClientHandshake(state, recordLayer, AlertDescription.internal_error);
                throw e;
            }
            catch (Exception e)
            {
                AbortClientHandshake(state, recordLayer, AlertDescription.internal_error);
                throw new TlsFatalAlert(AlertDescription.internal_error, e);
            }
            finally
            {
                securityParameters.Clear();
            }
        }
        /**
         * Initiates a TLS handshake in the role of client
         *
         * @param tlsClient The {@link TlsClient} to use for the handshake.
         * @throws IOException If handshake was not successful.
         */
        public virtual void Connect(TlsClient tlsClient)
        {
            if (tlsClient == null)
                throw new ArgumentNullException("tlsClient");
            if (this.mTlsClient != null)
                throw new InvalidOperationException("'Connect' can only be called once");

            this.mTlsClient = tlsClient;

            this.mSecurityParameters = new SecurityParameters();
            this.mSecurityParameters.entity = ConnectionEnd.client;

            this.mTlsClientContext = new TlsClientContextImpl(mSecureRandom, mSecurityParameters);

            this.mSecurityParameters.clientRandom = CreateRandomBlock(tlsClient.ShouldUseGmtUnixTime(),
                mTlsClientContext.NonceRandomGenerator);

            this.mTlsClient.Init(mTlsClientContext);
            this.mRecordStream.Init(mTlsClientContext);

            TlsSession sessionToResume = tlsClient.GetSessionToResume();
            if (sessionToResume != null && sessionToResume.IsResumable)
            {
                SessionParameters sessionParameters = sessionToResume.ExportSessionParameters();
                if (sessionParameters != null)
                {
                    this.mTlsSession = sessionToResume;
                    this.mSessionParameters = sessionParameters;
                }
            }

            SendClientHelloMessage();
            this.mConnectionState = CS_CLIENT_HELLO;

            CompleteHandshake();
        }
Esempio n. 5
0
        private TlsClient InitializeTlsClient(string connectionString)
        {
            Dictionary <string, string> settings;
            string setting;

            SimplePolicyChecker certificateChecker;
            TlsClient           remotingClient;

            SslProtocols         enabledSslProtocols;
            SslPolicyErrors      validPolicyErrors;
            X509ChainStatusFlags validChainFlags;

            // Initialize remoting client socket.
            certificateChecker = new SimplePolicyChecker();
            remotingClient     = new TlsClient();
            remotingClient.ConnectionString                    = connectionString;
            remotingClient.PayloadAware                        = true;
            remotingClient.IgnoreInvalidCredentials            = true;
            remotingClient.MaxConnectionAttempts               = -1;
            remotingClient.RemoteCertificateValidationCallback = RemoteCertificateValidationCallback;
            remotingClient.CertificateChecker                  = certificateChecker;

            // Parse connection string into key-value pairs
            settings = connectionString.ParseKeyValuePairs();

            // See if user wants to connect to remote service using integrated security
            if (settings.TryGetValue("integratedSecurity", out setting) && !string.IsNullOrWhiteSpace(setting))
            {
                remotingClient.IntegratedSecurity = setting.ParseBoolean();
            }

            // See if the user has explicitly defined the set of enabled SslProtocols
            try
            {
                if (settings.TryGetValue("enabledSslProtocols", out setting) && Enum.TryParse(setting, true, out enabledSslProtocols))
                {
                    remotingClient.EnabledSslProtocols = enabledSslProtocols;
                }
                else
                {
                    remotingClient.EnabledSslProtocols = SslProtocols.Tls12;
                }
            }
            catch (SecurityException)
            {
                // Security exception can occur when user forces use of older TLS protocol through configuration but event log warning entry cannot be written
            }

            // See if the user has explicitly defined valid policy errors or valid chain flags
            if (settings.TryGetValue("validPolicyErrors", out setting) && Enum.TryParse(setting, true, out validPolicyErrors))
            {
                certificateChecker.ValidPolicyErrors = validPolicyErrors;
            }
            else
            {
                certificateChecker.ValidPolicyErrors = SslPolicyErrors.RemoteCertificateChainErrors;
            }

            if (settings.TryGetValue("validChainFlags", out setting) && Enum.TryParse(setting, true, out validChainFlags))
            {
                certificateChecker.ValidChainFlags = validChainFlags;
            }
            else
            {
                certificateChecker.ValidChainFlags = X509ChainStatusFlags.UntrustedRoot;
            }

            // See if the user has explicitly defined whether to execute revocation checks on server certificates
            if (settings.TryGetValue("checkCertificateRevocation", out setting) && !string.IsNullOrWhiteSpace(setting))
            {
                remotingClient.CheckCertificateRevocation = setting.ParseBoolean();
            }

            return(remotingClient);
        }
        private void CleanupClients(object state)
        {
            List <string> toRemove = new List <string>();

            /* Scan for dead clients
             * According to MSDN, a client will be detected to be dead
             * only after a failed I/O.
             * If no messages run on channel, lots of dead clients won't be
             * discovered. This is why we force flushing the stream: if client
             * is dead, IOException is triggered and Connected is set to false
             */
            _listLock.AcquireReaderLock(DEFAULT_JOIN_TIMEOUT);
            try
            {
                foreach (KeyValuePair <string, TlsClient> kvp in _clients)
                {
                    try
                    {
                        kvp.Value.Stream.Flush();
                    }
                    catch (IOException)
                    {
                    } //Flush did its real job

                    if (!kvp.Value.Client.Connected)
                    {
                        toRemove.Add(kvp.Key);
                    }
                }

                if (toRemove.Count > 0)
                {
                    LockCookie ck = _listLock.UpgradeToWriterLock(DEFAULT_JOIN_TIMEOUT);
                    try
                    {
                        foreach (string id in toRemove)
                        {
                            try
                            {
                                TlsClient client = _clients[id];
                                _clients.Remove(id);
                                client.Dispose();
                            }
                            catch (KeyNotFoundException ex)
                            {
                                //Strange
                                Log.Debug("Error occurred when purging dead TLS client: {0}", ex.Message);
                            }
                        }
                    }
                    finally
                    {
                        _listLock.DowngradeFromWriterLock(ref ck);
                    }
                }
            }
            finally
            {
                _listLock.ReleaseReaderLock();
            }
            if (toRemove.Count > 0)
            {
                Log.Notice("TLS transport {0} cleaned up {1} dead clients", GetHashCode(), toRemove.Count);
            }
        }
        private void DispatchLoop()
        {
            try
            {
                while (true)
                {
                    SyslogMessage[] msgs = _queue.Flush();
                    if (msgs == null || msgs.Length == 0)
                    {
                        msgs = new[] { _queue.Dequeue() }
                    }
                    ;

                    byte[] data;

                    using (MemoryStream ms = new MemoryStream(8192))
                    {
                        foreach (SyslogMessage msg in msgs)
                        {
                            byte[] payload = Encoding.UTF8.GetBytes(msg.ToRfc5424String());
                            foreach (char c in payload.Length.ToString(CultureInfo.InvariantCulture))
                            {
                                ms.WriteByte((byte)c);
                            }

                            ms.WriteByte((byte)' ');

                            ms.Write(payload, 0, payload.Length);
                            _messagesSent++;
                        }
                        data = ms.ToArray();
                    }

                    //Waiting for pending writes

                    //Critical section. Obtain a snapshot of list and release lock ASAP
                    TlsClient[] clients;
                    _listLock.AcquireReaderLock(DEFAULT_JOIN_TIMEOUT);
                    try
                    {
                        clients = new TlsClient[_clients.Count];
                        _clients.Values.CopyTo(clients, 0);
                    }
                    finally
                    {
                        _listLock.ReleaseReaderLock();
                    }

                    foreach (TlsClient client in clients)
                    {
                        if (client.AsyncResult != null)
                        {
                            try
                            {
                                client.Stream.EndWrite(client.AsyncResult);
                                client.AsyncResult = null;
                            }
                            catch (ObjectDisposedException) { }
                            catch (IOException ex)
                            {
                                Log.Warning("Unable to send paylod to TLS client {0}", client.Client.Client.RemoteEndPoint.ToString());
                                Log.Debug("Error details: {0}", ex.Message);
                            }
                        }
                    }

                    foreach (TlsClient client in clients)
                    {
                        try
                        {
                            /* Asynchronously writing data to buffer.
                             * Once writing is completed, the callback signals the AutoResetEvent
                             * and once all clients signal the AutoResetEvent, new data will be written.
                             * Meanwhile, TlsClient encodes new data to send
                             */
                            client.AsyncResult = client.Stream.BeginWrite(data, 0, data.Length, null, null);
                        }
                        catch (IOException ex)
                        {
                            Log.Warning("Unable to send paylod to TLS client {0}", client.Client.Client.RemoteEndPoint.ToString());
                            Log.Debug("Error details: {0}", ex.Message);
                        }
                        catch (ObjectDisposedException) { }
                    }
                }
            }
            catch (ThreadInterruptedException) { }
            catch (Exception ex)
            {
                Log.Error("Failed TLS cycle in SyslogTlsTransport");
                Log.Debug("Error details: {0}", ex.Message);
                Dispose();
            }
        }
        /// <summary>
        /// Implements IOutboundTransport.SubscribeClient
        /// </summary>
        /// <remarks>
        /// Input instructions: (both required)
        /// <list>
        /// <item><c>host</c>: host name to connect to and validate certificate for</item>
        /// <item><c>port</c>: port number to use</item>
        /// <item><c>ip</c> (optional): overrides host, which is still required for certificate validation</item>
        /// </list>
        ///
        /// Output instructions: none
        /// </remarks>
        public string SubscribeClient(IEnumerable <KeyValuePair <string, string> > inputInstructions,
                                      out IEnumerable <KeyValuePair <string, string> > outputInstructions)
        {
            if (_disposed)
            {
                throw new ObjectDisposedException(GetType().FullName);
            }

            if (inputInstructions == null)
            {
                throw new ArgumentNullException("inputInstructions");
            }

            string    host = null, portno = null;
            int       port;
            IPAddress ipOverride = null;

            foreach (KeyValuePair <string, string> kvp in inputInstructions)
            {
                switch (kvp.Key)
                {
                case "host":
                {
                    host = kvp.Value;
                    break;
                }

                case "port":
                {
                    portno = kvp.Value;
                    break;
                }

                case "ip":
                {
                    if (!IPAddress.TryParse(kvp.Value, out ipOverride))
                    {
                        throw new TransportException("Invalid IP address specified");
                    }
                    break;
                }
                }
            }

            //Parameter error detection
            if (host == null)
            {
                throw new TransportException("Host name not specified");
            }
            if (portno == null)
            {
                throw new TransportException("Port number not specified");
            }
            if (!int.TryParse(portno, out port))
            {
                throw new TransportException("Invalid TCP port number");
            }
            if (port < 1 || port > 65534)
            {
                throw new TransportException("Invalid TCP port number");
            }

            outputInstructions = new Dictionary <string, string>();

            try
            {
                TcpClient newTcpClient;

                if (ipOverride == null)
                {
                    newTcpClient = new TcpClient(host, port);
                }
                else
                {
                    newTcpClient = new TcpClient(ipOverride.AddressFamily)
                    {
                        NoDelay = true, SendBufferSize = 65536
                    };
                    newTcpClient.Connect(ipOverride, port);
                }

                SslStream sslStream = new SslStream(newTcpClient.GetStream(), false, RemoteCertificateValidation,
                                                    LocalCertificateSelection);

                sslStream.AuthenticateAsClient(host);

                TlsClient newClient = new TlsClient(newTcpClient, sslStream);
                string    id        = newClient.GetHashCode().ToString();

                _listLock.AcquireWriterLock(DEFAULT_JOIN_TIMEOUT);
                try
                {
                    _clients.Add(id, newClient);
                    return(id);
                }
                finally
                {
                    _listLock.ReleaseWriterLock();
                }
            }
            catch (Exception ex)
            {
                Log.Error("Unable to subscribe new TLS client");
                Log.Debug("Error details: {0}", ex);
                throw new TransportException("Unable to subscribe client", ex);
            }
        }
        public virtual DtlsTransport Connect(TlsClient client, DatagramTransport transport)
        {
            if (client == null)
            {
                throw new ArgumentNullException("client");
            }
            if (transport == null)
            {
                throw new ArgumentNullException("transport");
            }

            SecurityParameters securityParameters = new SecurityParameters();

            securityParameters.entity = ConnectionEnd.client;

            ClientHandshakeState state = new ClientHandshakeState();

            state.client        = client;
            state.clientContext = new TlsClientContextImpl(mSecureRandom, securityParameters);

            securityParameters.clientRandom = TlsProtocol.CreateRandomBlock(client.ShouldUseGmtUnixTime(),
                                                                            state.clientContext.NonceRandomGenerator);

            client.Init(state.clientContext);

            DtlsRecordLayer recordLayer = new DtlsRecordLayer(transport, state.clientContext, client, ContentType.handshake);

            TlsSession sessionToResume = state.client.GetSessionToResume();

            if (sessionToResume != null && sessionToResume.IsResumable)
            {
                SessionParameters sessionParameters = sessionToResume.ExportSessionParameters();
                if (sessionParameters != null && sessionParameters.IsExtendedMasterSecret)
                {
                    state.tlsSession        = sessionToResume;
                    state.sessionParameters = sessionParameters;
                }
            }

            try
            {
                return(ClientHandshake(state, recordLayer));
            }
            catch (TlsFatalAlert fatalAlert)
            {
                AbortClientHandshake(state, recordLayer, fatalAlert.AlertDescription);
                throw fatalAlert;
            }
            catch (IOException e)
            {
                AbortClientHandshake(state, recordLayer, AlertDescription.internal_error);
                throw e;
            }
            catch (Exception e)
            {
                AbortClientHandshake(state, recordLayer, AlertDescription.internal_error);
                throw new TlsFatalAlert(AlertDescription.internal_error, e);
            }
            finally
            {
                securityParameters.Clear();
            }
        }
Esempio n. 10
0
        public 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");
            }

            /*
             * Send Client hello
             *
             * First, generate some random data.
             */
            this.securityParameters = new SecurityParameters();
            this.securityParameters.clientRandom = new byte[32];
            random.NextBytes(securityParameters.clientRandom, 4, 28);
            TlsUtilities.WriteGmtUnixTime(securityParameters.clientRandom, 0);

            this.tlsClientContext = new TlsClientContextImpl(random, securityParameters);
            this.tlsClient        = tlsClient;
            this.tlsClient.Init(tlsClientContext);

            MemoryStream outStr = new MemoryStream();

            TlsUtilities.WriteVersion(outStr);
            outStr.Write(securityParameters.clientRandom, 0, 32);

            /*
             * Length of Session id
             */
            TlsUtilities.WriteUint8(0, outStr);

            this.offeredCipherSuites = this.tlsClient.GetCipherSuites();

            // ExtensionType -> byte[]
            this.clientExtensions = this.tlsClient.GetClientExtensions();

            // Cipher Suites (and SCSV)
            {
                /*
                 * RFC 5746 3.4.
                 * The client MUST include either an empty "renegotiation_info"
                 * extension, or the TLS_EMPTY_RENEGOTIATION_INFO_SCSV signaling
                 * cipher suite value in the ClientHello.  Including both is NOT
                 * RECOMMENDED.
                 */
                bool noRenegExt = clientExtensions == null ||
                                  !clientExtensions.Contains(ExtensionType.renegotiation_info);

                int count = offeredCipherSuites.Length;
                if (noRenegExt)
                {
                    // Note: 1 extra slot for TLS_EMPTY_RENEGOTIATION_INFO_SCSV
                    ++count;
                }

                TlsUtilities.WriteUint16(2 * count, outStr);

                for (int i = 0; i < offeredCipherSuites.Length; ++i)
                {
                    TlsUtilities.WriteUint16((int)offeredCipherSuites[i], outStr);
                }

                if (noRenegExt)
                {
                    TlsUtilities.WriteUint16((int)CipherSuite.TLS_EMPTY_RENEGOTIATION_INFO_SCSV, outStr);
                }
            }

            /*
             * Compression methods, just the null method.
             */
            this.offeredCompressionMethods = tlsClient.GetCompressionMethods();

            {
                TlsUtilities.WriteUint8((byte)offeredCompressionMethods.Length, outStr);
                for (int i = 0; i < offeredCompressionMethods.Length; ++i)
                {
                    TlsUtilities.WriteUint8((byte)offeredCompressionMethods[i], outStr);
                }
            }

            // Extensions
            if (clientExtensions != null)
            {
                MemoryStream ext = new MemoryStream();

                foreach (ExtensionType extType in clientExtensions.Keys)
                {
                    WriteExtension(ext, extType, (byte[])clientExtensions[extType]);
                }

                TlsUtilities.WriteOpaque16(ext.ToArray(), outStr);
            }

            MemoryStream bos = new MemoryStream();

            TlsUtilities.WriteUint8((byte)HandshakeType.client_hello, bos);
            TlsUtilities.WriteUint24((int)outStr.Length, bos);
            byte[] outBytes = outStr.ToArray();
            bos.Write(outBytes, 0, outBytes.Length);
            byte[] message = bos.ToArray();
            SafeWriteMessage(ContentType.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)
            {
                SafeReadData();
            }

            this.tlsStream = new TlsStream(this);
        }
Esempio n. 11
0
        /// <summary>
        /// Create a communications client
        /// </summary>
        /// <remarks>
        /// Note that typical connection string should be prefixed with a "protocol=tcp", "protocol=udp", "protocol=serial" or "protocol=file"
        /// </remarks>
        /// <returns>A communications client.</returns>
        /// <param name="connectionString">Connection string for the client.</param>
        public static IClient Create(string connectionString)
        {
            Dictionary <string, string> connectionSettings = connectionString.ParseKeyValuePairs();
            IClient client;
            string  protocol;

            if (connectionSettings.TryGetValue("protocol", out protocol))
            {
                connectionSettings.Remove("protocol");
                StringBuilder settings = new StringBuilder();

                foreach (string key in connectionSettings.Keys)
                {
                    settings.Append(key);
                    settings.Append("=");
                    settings.Append(connectionSettings[key]);
                    settings.Append(";");
                }

                // Create a client instance for the specified protocol.
                switch (protocol.Trim().ToLower())
                {
                case "tls":
                    client = new TlsClient(settings.ToString());
                    break;

                case "tcp":
                    client = new TcpClient(settings.ToString());
                    break;

                case "udp":
                    client = new UdpClient(settings.ToString());
                    break;

                case "file":
                    client = new FileClient(settings.ToString());
                    break;

                case "serial":
                    client = new SerialClient(settings.ToString());
                    break;

                default:
                    throw new ArgumentException(protocol + " is not a valid transport protocol");
                }

                // Apply client settings from the connection string to the client.
                foreach (KeyValuePair <string, string> setting in connectionSettings)
                {
                    PropertyInfo property = client.GetType().GetProperty(setting.Key);
                    if (property != null)
                    {
                        property.SetValue(client, Convert.ChangeType(setting.Value, property.PropertyType), null);
                    }
                }
            }
            else
            {
                throw new ArgumentException("Transport protocol must be specified");
            }

            return(client);
        }
Esempio n. 12
0
        internal static TlsClientProtocol OpenTlsConnection(string hostname, int port, TlsClient client)
        {
            TcpClient tcp = new TcpClient(hostname, port);

            TlsClientProtocol protocol = new TlsClientProtocol(tcp.GetStream(), secureRandom);

            protocol.Connect(client);
            return(protocol);
        }
Esempio n. 13
0
        protected virtual byte[] GenerateClientHello(DtlsClientProtocol.ClientHandshakeState state, TlsClient client)
        {
            MemoryStream    memoryStream  = new MemoryStream();
            ProtocolVersion clientVersion = client.ClientVersion;

            if (!clientVersion.IsDtls)
            {
                throw new TlsFatalAlert(80);
            }
            TlsClientContextImpl clientContext = state.clientContext;

            clientContext.SetClientVersion(clientVersion);
            TlsUtilities.WriteVersion(clientVersion, memoryStream);
            SecurityParameters securityParameters = clientContext.SecurityParameters;

            memoryStream.Write(securityParameters.ClientRandom, 0, securityParameters.ClientRandom.Length);
            byte[] array = TlsUtilities.EmptyBytes;
            if (state.tlsSession != null)
            {
                array = state.tlsSession.SessionID;
                if (array == null || array.Length > 32)
                {
                    array = TlsUtilities.EmptyBytes;
                }
            }
            TlsUtilities.WriteOpaque8(array, memoryStream);
            TlsUtilities.WriteOpaque8(TlsUtilities.EmptyBytes, memoryStream);
            bool isFallback = client.IsFallback;

            state.offeredCipherSuites = client.GetCipherSuites();
            state.clientExtensions    = client.GetClientExtensions();
            byte[] extensionData = TlsUtilities.GetExtensionData(state.clientExtensions, 65281);
            bool   flag          = null == extensionData;
            bool   flag2         = !Arrays.Contains(state.offeredCipherSuites, 255);

            if (flag && flag2)
            {
                state.offeredCipherSuites = Arrays.Append(state.offeredCipherSuites, 255);
            }
            if (isFallback && !Arrays.Contains(state.offeredCipherSuites, 22016))
            {
                state.offeredCipherSuites = Arrays.Append(state.offeredCipherSuites, 22016);
            }
            TlsUtilities.WriteUint16ArrayWithUint16Length(state.offeredCipherSuites, memoryStream);
            byte[] offeredCompressionMethods = new byte[1];
            state.offeredCompressionMethods = offeredCompressionMethods;
            TlsUtilities.WriteUint8ArrayWithUint8Length(state.offeredCompressionMethods, memoryStream);
            if (state.clientExtensions != null)
            {
                TlsProtocol.WriteExtensions(memoryStream, state.clientExtensions);
            }
            return(memoryStream.ToArray());
        }
        protected virtual byte[] GenerateClientHello(ClientHandshakeState state, TlsClient client)
        {
            MemoryStream buf = new MemoryStream();

            ProtocolVersion client_version = client.ClientVersion;
            if (!client_version.IsDtls)
                throw new TlsFatalAlert(AlertDescription.internal_error);

            TlsClientContextImpl context = state.clientContext;

            context.SetClientVersion(client_version);
            TlsUtilities.WriteVersion(client_version, buf);

            SecurityParameters securityParameters = context.SecurityParameters;
            buf.Write(securityParameters.ClientRandom, 0, securityParameters.ClientRandom.Length);

            // Session ID
            byte[] session_id = TlsUtilities.EmptyBytes;
            if (state.tlsSession != null)
            {
                session_id = state.tlsSession.SessionID;
                if (session_id == null || session_id.Length > 32)
                {
                    session_id = TlsUtilities.EmptyBytes;
                }
            }
            TlsUtilities.WriteOpaque8(session_id, buf);

            // Cookie
            TlsUtilities.WriteOpaque8(TlsUtilities.EmptyBytes, buf);

            bool fallback = client.IsFallback;

            /*
             * Cipher suites
             */
            state.offeredCipherSuites = client.GetCipherSuites();

            // Integer -> byte[]
            state.clientExtensions = client.GetClientExtensions();

            // Cipher Suites (and SCSV)
            {
                /*
                 * RFC 5746 3.4. The client MUST include either an empty "renegotiation_info" extension,
                 * or the TLS_EMPTY_RENEGOTIATION_INFO_SCSV signaling cipher suite value in the
                 * ClientHello. Including both is NOT RECOMMENDED.
                 */
                byte[] renegExtData = TlsUtilities.GetExtensionData(state.clientExtensions, ExtensionType.renegotiation_info);
                bool noRenegExt = (null == renegExtData);

                bool noRenegSCSV = !Arrays.Contains(state.offeredCipherSuites, CipherSuite.TLS_EMPTY_RENEGOTIATION_INFO_SCSV);

                if (noRenegExt && noRenegSCSV)
                {
                    // TODO Consider whether to default to a client extension instead
                    state.offeredCipherSuites = Arrays.Append(state.offeredCipherSuites, CipherSuite.TLS_EMPTY_RENEGOTIATION_INFO_SCSV);
                }

                /*
                 * draft-ietf-tls-downgrade-scsv-00 4. If a client sends a ClientHello.client_version
                 * containing a lower value than the latest (highest-valued) version supported by the
                 * client, it SHOULD include the TLS_FALLBACK_SCSV cipher suite value in
                 * ClientHello.cipher_suites.
                 */
                if (fallback && !Arrays.Contains(state.offeredCipherSuites, CipherSuite.TLS_FALLBACK_SCSV))
                {
                    state.offeredCipherSuites = Arrays.Append(state.offeredCipherSuites, CipherSuite.TLS_FALLBACK_SCSV);
                }

                TlsUtilities.WriteUint16ArrayWithUint16Length(state.offeredCipherSuites, buf);
            }

            // TODO Add support for compression
            // Compression methods
            // state.offeredCompressionMethods = client.getCompressionMethods();
            state.offeredCompressionMethods = new byte[]{ CompressionMethod.cls_null };

            TlsUtilities.WriteUint8ArrayWithUint8Length(state.offeredCompressionMethods, buf);

            // Extensions
            if (state.clientExtensions != null)
            {
                TlsProtocol.WriteExtensions(buf, state.clientExtensions);
            }

            return buf.ToArray();
        }
Esempio n. 15
0
        /// <summary>
        /// Send a HTTP request to the remote socket
        /// </summary>
        /// <param name="method"></param>
        /// <param name="resource"></param>
        /// <param name="httpVersion"></param>
        /// <param name="client"></param>
        /// <param name="headers"></param>
        /// <returns>Response Stream</returns>
        public Stream SendHttp(string method, string resource, string data, string httpVersion, TlsClient client, HttpHeaders headers)
        {
            TlsClientProtocol protocol = new TlsClientProtocol(_tcpClient.GetStream(), new SecureRandom());

            try
            {
                protocol.Connect(client);
            }
            catch (TlsException)
            {
                throw new ProtocolVersionNotSupported();
            }

            // build protocol info, headers & body
            StringBuilder sb = new StringBuilder();

            sb.AppendLine($"{method.ToUpper()} {resource} HTTP/{httpVersion}");
            if (!headers.Contains("host"))
            {
                headers.Add("Host", _host);
            }
            sb.AppendLine(headers.ToString());

            // append data in case of POST or similar
            if (data != null)
            {
                sb.Append(data);
            }
            // Console.WriteLine(sb.ToString());

            var requestBytes = Encoding.ASCII.GetBytes(sb.ToString());

            Stream stream = protocol.Stream;

            stream.Write(requestBytes, 0, requestBytes.Length);
            stream.Flush();

            return(stream);
        }
Esempio n. 16
0
//    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);
		}
Esempio n. 17
0
        protected virtual byte[] GenerateClientHello(ClientHandshakeState state, TlsClient client)
        {
            MemoryStream buf = new MemoryStream();

            ProtocolVersion client_version = client.ClientVersion;

            if (!client_version.IsDtls)
            {
                throw new TlsFatalAlert(AlertDescription.internal_error);
            }

            TlsClientContextImpl context = state.clientContext;

            context.SetClientVersion(client_version);
            TlsUtilities.WriteVersion(client_version, buf);

            SecurityParameters securityParameters = context.SecurityParameters;

            buf.Write(securityParameters.ClientRandom, 0, securityParameters.ClientRandom.Length);

            // Session ID
            byte[] session_id = TlsUtilities.EmptyBytes;
            if (state.tlsSession != null)
            {
                session_id = state.tlsSession.SessionID;
                if (session_id == null || session_id.Length > 32)
                {
                    session_id = TlsUtilities.EmptyBytes;
                }
            }
            TlsUtilities.WriteOpaque8(session_id, buf);

            // Cookie
            TlsUtilities.WriteOpaque8(TlsUtilities.EmptyBytes, buf);

            bool fallback = client.IsFallback;

            /*
             * Cipher suites
             */
            state.offeredCipherSuites = client.GetCipherSuites();

            // Integer -> byte[]
            state.clientExtensions = client.GetClientExtensions();

            // Cipher Suites (and SCSV)
            {
                /*
                 * RFC 5746 3.4. The client MUST include either an empty "renegotiation_info" extension,
                 * or the TLS_EMPTY_RENEGOTIATION_INFO_SCSV signaling cipher suite value in the
                 * ClientHello. Including both is NOT RECOMMENDED.
                 */
                byte[] renegExtData = TlsUtilities.GetExtensionData(state.clientExtensions, ExtensionType.renegotiation_info);
                bool   noRenegExt   = (null == renegExtData);

                bool noRenegSCSV = !Arrays.Contains(state.offeredCipherSuites, CipherSuite.TLS_EMPTY_RENEGOTIATION_INFO_SCSV);

                if (noRenegExt && noRenegSCSV)
                {
                    // TODO Consider whether to default to a client extension instead
                    state.offeredCipherSuites = Arrays.Append(state.offeredCipherSuites, CipherSuite.TLS_EMPTY_RENEGOTIATION_INFO_SCSV);
                }

                /*
                 * draft-ietf-tls-downgrade-scsv-00 4. If a client sends a ClientHello.client_version
                 * containing a lower value than the latest (highest-valued) version supported by the
                 * client, it SHOULD include the TLS_FALLBACK_SCSV cipher suite value in
                 * ClientHello.cipher_suites.
                 */
                if (fallback && !Arrays.Contains(state.offeredCipherSuites, CipherSuite.TLS_FALLBACK_SCSV))
                {
                    state.offeredCipherSuites = Arrays.Append(state.offeredCipherSuites, CipherSuite.TLS_FALLBACK_SCSV);
                }

                TlsUtilities.WriteUint16ArrayWithUint16Length(state.offeredCipherSuites, buf);
            }

            // TODO Add support for compression
            // Compression methods
            // state.offeredCompressionMethods = client.getCompressionMethods();
            state.offeredCompressionMethods = new byte[] { CompressionMethod.cls_null };

            TlsUtilities.WriteUint8ArrayWithUint8Length(state.offeredCompressionMethods, buf);

            // Extensions
            if (state.clientExtensions != null)
            {
                TlsProtocol.WriteExtensions(buf, state.clientExtensions);
            }

            return(buf.ToArray());
        }
Esempio n. 18
0
//    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);
        }
		public 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");

			/*
             * Send Client hello
             *
             * First, generate some random data.
             */
            this.securityParameters = new SecurityParameters();
            this.securityParameters.clientRandom = new byte[32];
            random.NextBytes(securityParameters.clientRandom, 4, 28);
            TlsUtilities.WriteGmtUnixTime(securityParameters.clientRandom, 0);

			this.tlsClientContext = new TlsClientContextImpl(random, securityParameters);
			this.tlsClient = tlsClient;
			this.tlsClient.Init(tlsClientContext);

            MemoryStream outStr = new MemoryStream();
            TlsUtilities.WriteVersion(outStr);
            outStr.Write(securityParameters.clientRandom, 0, 32);

            /*
            * Length of Session id
            */
            TlsUtilities.WriteUint8(0, outStr);

            this.offeredCipherSuites = this.tlsClient.GetCipherSuites();

            // ExtensionType -> byte[]
            this.clientExtensions = this.tlsClient.GetClientExtensions();

            // Cipher Suites (and SCSV)
            {
                /*
                 * RFC 5746 3.4.
                 * The client MUST include either an empty "renegotiation_info"
                 * extension, or the TLS_EMPTY_RENEGOTIATION_INFO_SCSV signaling
                 * cipher suite value in the ClientHello.  Including both is NOT
                 * RECOMMENDED.
                 */
                bool noRenegExt = clientExtensions == null
                    || !clientExtensions.Contains(ExtensionType.renegotiation_info);

                int count = offeredCipherSuites.Length;
                if (noRenegExt)
                {
                    // Note: 1 extra slot for TLS_EMPTY_RENEGOTIATION_INFO_SCSV
                    ++count;
                }

                TlsUtilities.WriteUint16(2 * count, outStr);

                for (int i = 0; i < offeredCipherSuites.Length; ++i)
                {
                    TlsUtilities.WriteUint16((int)offeredCipherSuites[i], outStr);
                }

                if (noRenegExt)
                {
                    TlsUtilities.WriteUint16((int)CipherSuite.TLS_EMPTY_RENEGOTIATION_INFO_SCSV, outStr);
                }
            }

            /*
             * Compression methods, just the null method.
             */
            this.offeredCompressionMethods = tlsClient.GetCompressionMethods();

            {
                TlsUtilities.WriteUint8((byte)offeredCompressionMethods.Length, outStr);
                for (int i = 0; i < offeredCompressionMethods.Length; ++i)
                {
                    TlsUtilities.WriteUint8((byte)offeredCompressionMethods[i], outStr);
                }
            }

            // Extensions
            if (clientExtensions != null)
            {
                MemoryStream ext = new MemoryStream();

                foreach (ExtensionType extType in clientExtensions.Keys)
                {
                    WriteExtension(ext, extType, (byte[])clientExtensions[extType]);
                }

                TlsUtilities.WriteOpaque16(ext.ToArray(), outStr);
            }

            MemoryStream bos = new MemoryStream();
            TlsUtilities.WriteUint8((byte)HandshakeType.client_hello, bos);
            TlsUtilities.WriteUint24((int)outStr.Length, bos);
            byte[] outBytes = outStr.ToArray();
            bos.Write(outBytes, 0, outBytes.Length);
            byte[] message = bos.ToArray();
            SafeWriteMessage(ContentType.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)
            {
				SafeReadData();
            }

            this.tlsStream = new TlsStream(this);
        }
Esempio n. 20
0
        protected virtual byte[] GenerateClientHello(ClientHandshakeState state, TlsClient client)
        {
            ProtocolVersion client_version = client.ClientVersion;

            if (!client_version.IsDtls)
            {
                throw new TlsFatalAlert(AlertDescription.internal_error);
            }

            TlsClientContextImpl context = state.clientContext;

            context.SetClientVersion(client_version);

            SecurityParameters securityParameters = context.SecurityParameters;

            // Session ID
            byte[] session_id = TlsUtilities.EmptyBytes;
            if (state.tlsSession != null)
            {
                session_id = state.tlsSession.SessionID;
                if (session_id == null || session_id.Length > 32)
                {
                    session_id = TlsUtilities.EmptyBytes;
                }
            }

            bool fallback = client.IsFallback;

            state.offeredCipherSuites = client.GetCipherSuites();

            if (session_id.Length > 0 && state.sessionParameters != null)
            {
                if (!state.sessionParameters.IsExtendedMasterSecret ||
                    !Arrays.Contains(state.offeredCipherSuites, state.sessionParameters.CipherSuite) ||
                    CompressionMethod.cls_null != state.sessionParameters.CompressionAlgorithm)
                {
                    session_id = TlsUtilities.EmptyBytes;
                }
            }

            state.clientExtensions = TlsExtensionsUtilities.EnsureExtensionsInitialised(client.GetClientExtensions());

            TlsExtensionsUtilities.AddExtendedMasterSecretExtension(state.clientExtensions);

            MemoryStream buf = new MemoryStream();

            TlsUtilities.WriteVersion(client_version, buf);

            buf.Write(securityParameters.ClientRandom, 0, securityParameters.ClientRandom.Length);

            TlsUtilities.WriteOpaque8(session_id, buf);

            // Cookie
            TlsUtilities.WriteOpaque8(TlsUtilities.EmptyBytes, buf);

            // Cipher Suites (and SCSV)
            {
                /*
                 * RFC 5746 3.4. The client MUST include either an empty "renegotiation_info" extension,
                 * or the TLS_EMPTY_RENEGOTIATION_INFO_SCSV signaling cipher suite value in the
                 * ClientHello. Including both is NOT RECOMMENDED.
                 */
                byte[] renegExtData = TlsUtilities.GetExtensionData(state.clientExtensions, ExtensionType.renegotiation_info);
                bool   noRenegExt   = (null == renegExtData);

                bool noRenegSCSV = !Arrays.Contains(state.offeredCipherSuites, CipherSuite.TLS_EMPTY_RENEGOTIATION_INFO_SCSV);

                if (noRenegExt && noRenegSCSV)
                {
                    // TODO Consider whether to default to a client extension instead
                    state.offeredCipherSuites = Arrays.Append(state.offeredCipherSuites, CipherSuite.TLS_EMPTY_RENEGOTIATION_INFO_SCSV);
                }

                /*
                 * RFC 7507 4. If a client sends a ClientHello.client_version containing a lower value
                 * than the latest (highest-valued) version supported by the client, it SHOULD include
                 * the TLS_FALLBACK_SCSV cipher suite value in ClientHello.cipher_suites [..]. (The
                 * client SHOULD put TLS_FALLBACK_SCSV after all cipher suites that it actually intends
                 * to negotiate.)
                 */
                if (fallback && !Arrays.Contains(state.offeredCipherSuites, CipherSuite.TLS_FALLBACK_SCSV))
                {
                    state.offeredCipherSuites = Arrays.Append(state.offeredCipherSuites, CipherSuite.TLS_FALLBACK_SCSV);
                }

                TlsUtilities.WriteUint16ArrayWithUint16Length(state.offeredCipherSuites, buf);
            }

            TlsUtilities.WriteUint8ArrayWithUint8Length(new byte[] { CompressionMethod.cls_null }, buf);

            TlsProtocol.WriteExtensions(buf, state.clientExtensions);

            return(buf.ToArray());
        }