AuthenticateAsClientAsync() 공개 메소드

public AuthenticateAsClientAsync ( string targetHost ) : System.Threading.Tasks.Task
targetHost string
리턴 System.Threading.Tasks.Task
예제 #1
0
        /// <summary>
        /// Initializes a client instance of <see cref="DesktopNetworkStream"/>.
        /// </summary>
        /// <param name="host">Network host.</param>
        /// <param name="port">Network port.</param>
        /// <param name="useTls">Use TLS layer?</param>
        /// <param name="noDelay">No delay?</param>
        /// <param name="ignoreSslPolicyErrors">Ignore SSL policy errors?</param>
        internal DesktopNetworkStream(string host, int port, bool useTls, bool noDelay, bool ignoreSslPolicyErrors)
        {
            this.Host = host;
            this.Port = port;
#if NETSTANDARD
            this.tcpClient = new TcpClient { NoDelay = noDelay };
            this.tcpClient.ConnectAsync(host, port).Wait();
#else
            this.tcpClient = new TcpClient(host, port) { NoDelay = noDelay };
#endif

            Stream stream = this.tcpClient.GetStream();
            if (useTls)
            {
                var ssl = new SslStream(
                    stream,
                    false,
                    (sender, certificate, chain, errors) => errors == SslPolicyErrors.None || ignoreSslPolicyErrors);
#if NETSTANDARD
                ssl.AuthenticateAsClientAsync(host).Wait();
#else
                ssl.AuthenticateAsClient(host);
#endif
                stream = ssl;
            }

            this.networkStream = stream;
        }
예제 #2
0
        public ServiceEndPoint Discover(ServiceEndPoint serviceEndpoint)
        {
            try
            {
                using (var client = CreateConnectedTcpClient(serviceEndpoint))
                {
                    using (var stream = client.GetStream())
                    {
                        using (var ssl = new SslStream(stream, false, ValidateCertificate))
                        {
                            ssl.AuthenticateAsClientAsync(serviceEndpoint.BaseUri.Host, new X509Certificate2Collection(), SslProtocols.Tls | SslProtocols.Tls11 | SslProtocols.Tls12, false)
                                .GetAwaiter()
                                .GetResult();
                            ssl.Write(HelloLine, 0, HelloLine.Length);
                            ssl.Flush();

                            if (ssl.RemoteCertificate == null)
                                throw new Exception("The server did not provide an SSL certificate");

                            return new ServiceEndPoint(serviceEndpoint.BaseUri, new X509Certificate2(ssl.RemoteCertificate.Export(X509ContentType.Cert)).Thumbprint);
                        }
                    }
                }
            }
            catch (Exception ex)
            {
                throw new HalibutClientException(ex.Message, ex);
            }
        }
 public override Task PostEmailAsync(string name, string[] to, string[] cc, string[] bcc, string subject, string message, params Attachment[] Attachments)
 {
     if (!ssl)
         return Task.Factory.StartNew(async () =>
         {
             using (var client = new TcpClient())
             {
                 await client.ConnectAsync(server, port);
                 using (var stream = client.GetStream())
                 using (var reader = new StreamReader(stream))
                 using (var writer = new StreamWriter(stream) { AutoFlush = true, NewLine = "\r\n" })
                 {
                     TcpWrite(writer, reader, name, to, cc, bcc, subject, message, Attachments);
                 }
             }
         });
     else
         return Task.Factory.StartNew(async () =>
         {
             using (var client = new TcpClient())
             {
                 await client.ConnectAsync(server, port);
                 using (var stream = new SslStream(client.GetStream(), false))
                 {
                     await stream.AuthenticateAsClientAsync(server);
                     using (var reader = new StreamReader(stream))
                     using (var writer = new StreamWriter(stream) { AutoFlush = true, NewLine = "\r\n" })
                     {
                         TcpWrite(writer, reader, name, to, cc, bcc, subject, message, Attachments);
                     }
                 }
             }
         });
 }
 public async Task<Stream> ConnectAsync(string host, int port, X509Certificate clientCert, CancellationToken cancel)
 {
     Stream lowerStream = null;
     SslStream sslStream = null;
     X509CertificateCollection certCollection = null;;
     if (clientCert != null)
     {
         certCollection = new X509CertificateCollection(new[] { clientCert });
     }
     try
     {
         lowerStream = await _connectionResolver.ConnectAsync(host, port, cancel);
         sslStream = new SslStream(lowerStream);
         await sslStream.AuthenticateAsClientAsync(host, certCollection, _protocols, checkCertificateRevocation: true);
         return sslStream;
     }
     catch (Exception)
     {
         if (sslStream != null)
         {
             sslStream.Dispose();
         }
         if (lowerStream != null)
         {
             lowerStream.Dispose();
         }
         throw;
     }
 }
예제 #5
0
        public static void Main(string[] args)
        {
            Console.WriteLine("Starting...");
            X509Certificate2 serverCertificate = new X509Certificate2("certificate.pfx"); // Any valid certificate with private key will work fine.
            TcpListener listener = new TcpListener(IPAddress.Any, 4567);
            TcpClient client = new TcpClient();
            listener.Start();

            Task clientConnectTask = client.ConnectAsync(IPAddress.Loopback, 4567);
            Task<TcpClient> listenerAcceptTask = listener.AcceptTcpClientAsync();
            Task.WaitAll(clientConnectTask, listenerAcceptTask);

            TcpClient server = listenerAcceptTask.Result;
            SslStream clientStream = new SslStream(client.GetStream(), false, new RemoteCertificateValidationCallback(ValidateServerCertificate), null, EncryptionPolicy.RequireEncryption);
            SslStream serverStream = new SslStream(server.GetStream(), false, null, null, EncryptionPolicy.RequireEncryption);

            Task clientAuthenticationTask = clientStream.AuthenticateAsClientAsync(serverCertificate.GetNameInfo(X509NameType.SimpleName, false), null, SslProtocols.Tls12, false);
            Task serverAuthenticationTask = serverStream.AuthenticateAsServerAsync(serverCertificate, false, SslProtocols.Tls12, false);
            Task.WaitAll(clientAuthenticationTask, serverAuthenticationTask);
            
            byte[] readBuffer = new byte[256];
            Task<int> readTask = clientStream.ReadAsync(readBuffer, 0, readBuffer.Length); // Create a pending ReadAsync, which will wait for data that will never come (for testing purposes).
            byte[] writeBuffer = new byte[256];
            Task writeTask = clientStream.WriteAsync(writeBuffer, 0, writeBuffer.Length); // The main thread actually blocks here (not asychronously waits) on .NET Core making this call.
            bool result = Task.WaitAll(new Task[1] { writeTask }, 5000); // This code won't even be reached on .NET Core. Works fine on .NET Framework.

            if (result)
            {
                Console.WriteLine("WriteAsync completed successfully while ReadAsync was pending... nothing locked up.");
            }
            else
            {
                Console.WriteLine("WriteAsync failed to complete after 5 seconds.");
            }
        }
예제 #6
0
 async protected override Task InitRemoteStream()
 {
     await base.InitRemoteStream();
     var secureRemoteStream = new SslStream(RemoteStream, true, RemoteCertificateValidator);
     var targetHost = WrapperRequest.Prologue.Headers.First(x => x.Key == "Host").Value;
     await secureRemoteStream.AuthenticateAsClientAsync(targetHost);
     SecureRemoteStream = secureRemoteStream;
 }
예제 #7
0
        public async Task Connect ()
        {
            if (IsConnected ())
                return;

            tcp = new TcpClient ();

            // Disable Nagle for HTTP/2
            tcp.NoDelay = true;

            await tcp.ConnectAsync (Host, (int)Port);

            if (UseTls) {
                sslStream = new SslStream (tcp.GetStream (), false, 
                    (sender, certificate, chain, sslPolicyErrors) => true);
                
                await sslStream.AuthenticateAsClientAsync (
                    Host, 
                    Certificates ?? new X509CertificateCollection (), 
                    System.Security.Authentication.SslProtocols.Tls12, 
                    false);

                clientStream = sslStream;
            } else {
                clientStream = tcp.GetStream ();
            }

            // Send out preface data
            var prefaceData = System.Text.Encoding.ASCII.GetBytes (ConnectionPreface);
            await clientStream.WriteAsync (prefaceData, 0, prefaceData.Length);
            await clientStream.FlushAsync ();
            
            // Start reading the stream on another thread
            var readTask = Task.Factory.StartNew (() => {
                try { read (); }
                catch (Exception ex) {
                    Console.WriteLine ("Read error: " + ex);
                    Disconnect ();
                }
            }, TaskCreationOptions.LongRunning);

            readTask.ContinueWith (t => {
                // TODO: Handle the error
                Console.WriteLine ("Error: " + t.Exception);
                Disconnect ();
            }, TaskContinuationOptions.OnlyOnFaulted);

            // Send an un-ACK'd settings frame
            await SendFrame(new SettingsFrame ());

            // We need to wait for settings server preface to come back now
            resetEventConnectionSettingsFrame = new ManualResetEventSlim ();
            resetEventConnectionSettingsFrame.Reset ();
            if (!resetEventConnectionSettingsFrame.Wait (ConnectionTimeout)) {
                Disconnect ();
                throw new Exception ("Connection timed out");
            }
        }
예제 #8
0
        protected override Stream createClientStream(string host, int port)
        {
            var rval = new SslStream(base.createClientStream(host, port), false, (o, cert, chain, errors) => true);

            //rval.AuthenticateAsClient(host);
            Task task = rval.AuthenticateAsClientAsync(host);
            task.Wait();

            return rval;
        }
예제 #9
0
 /// <summary>
 ///     Establishes a TCP connection with the endpoint at the specified address/port pair.
 /// </summary>
 /// <param name="address">The address of the endpoint to connect to.</param>
 /// <param name="port">The port of the endpoint to connect to.</param>
 /// <param name="secure">True to enable TLS on the socket.</param>
 public async Task ConnectAsync(string address, int port, bool secure = false)
 {
     await _backingTcpClient.ConnectAsync(address, port);
     InitializeWriteStream();
     if (secure)
     {
         var secureStream = new SslStream(_writeStream, true, (sender, cert, chain, sslPolicy) => ServerValidationCallback(sender, cert, chain, sslPolicy));
         await secureStream.AuthenticateAsClientAsync(address, null, System.Security.Authentication.SslProtocols.Tls, false);
         _secureStream = secureStream;
     }            
 }
예제 #10
0
		} // proc OnRunJob

		private async Task OnRunJobAsync()
		{
			inConnectionPhase = true;
			try
			{
				var timeoutSource = new CancellationTokenSource(30000);

				// resolve end point
				var serverTcp = this.GetService<IServerTcp>(true);
				if (endPoint == null)
					endPoint = await serverTcp.ResolveEndpointAsync(targetHost, targetPort, timeoutSource.Token);

				// register the connection
				if (endPoint != null)
				{
					var protocol = this.GetService<OdetteFileTransferProtocolItem>(true);

					// check if the protocol is running
					if (protocol.IsActiveProtocol(ChannelName))
						Log.Info("Protocol is already active.");
					else // create the connection
						try
						{
							var stream = await serverTcp.CreateConnectionAsync(endPoint, timeoutSource.Token);

							if (useSsl)
							{
								var ssl = new SslStream(stream, false, SslRemoteCertificateValidateCallback); // , SslLocalCertificateSelector
								await ssl.AuthenticateAsClientAsync(targetHost);

								var cert = ssl.RemoteCertificate;
								Log.Info($"Ssl active: auth={ssl.IsAuthenticated}, encrypt={ssl.IsEncrypted}, signed={ssl.IsSigned}\nissuer={cert.Issuer}\nsubject={cert.Subject}");
								stream = ssl;
							}

							await protocol.StartProtocolAsync(new OdetteNetworkStream(stream, channelName, Config), true);
						}
						catch (Exception e)
						{
							Log.Except("Connection failed.", e);
						}
				}
			}
			catch (Exception e)
			{
				Log.Except(e);
			}
			finally
			{
				inConnectionPhase = false;
			}
		} // proc OnRunJobAsync
        private async Task<Stream> CreateStream(Uri uri, Socket socket)
        {
            Stream stream = new NetworkStream(socket);

            if (uri.Scheme.Equals("https", StringComparison.OrdinalIgnoreCase))
            {
                var sslStream = new SslStream(stream);
                await sslStream.AuthenticateAsClientAsync(uri.Host, new X509CertificateCollection(), _sslProtocols, checkCertificateRevocation: false);
                stream = sslStream;
            }

            return stream;
        }
예제 #12
0
 public async Task<ConnectStatus> ConnectTls ()
 {
     try {
         SslStream ssl = new SslStream(tcpc.GetStream(), false, CertificateValidationCallBack);
         await ssl.AuthenticateAsClientAsync(host);
         stream = ssl;
         return ConnectStatus.Ok;
     }
     catch
     {
         return ConnectStatus.Failed;
     }
 }
예제 #13
0
 async Task<Stream> IConnectionFactory.Connect(string hostname, int port, bool useSsl)
 {
     TcpClient client = new TcpClient();
     client.NoDelay = true;
     await client.ConnectAsync(hostname, port);
     if (useSsl)
     {
         SslStream sslStream = new SslStream(client.GetStream());
         await sslStream.AuthenticateAsClientAsync(hostname);
         return sslStream;
     }
     return client.GetStream();
 }
        protected override async Task<Stream> GetNetworkStream(TcpClient client)
        {
            var sslStream = new SslStream(
                client.GetStream(),
                false,
                ValidateServerCertificate,
                null
                );

            await sslStream.AuthenticateAsClientAsync(Hostname).ConfigureAwait(false);

            return sslStream;
        }
예제 #15
0
        private async Task Connect()
        {
            try
            {
                // Could be a reconnect - get rid of the old stream if so
                if (_stream != null)
                {
                    _stream.Dispose();
                    _stream = null;
                }

                await _tcpClient.ConnectAsync(_host, _port);

                _stream = _tcpClient.GetStream();
                _stream.ReadTimeout = _configuration.WaitForDataTimeoutInMilliseconds;

                if (_configuration.Ssl)
                {
                    var sslStream = new SslStream(_stream, false, _configuration.CertificateValidationCallback);
                    await sslStream.AuthenticateAsClientAsync(_host);
                    _stream = sslStream;
                }

                if (_configuration.Password != null)
                {
                    var response = await Command.From("AUTH", _configuration.Password).SendAsync(this);

                    if (response.Value.IsError || response.Value.ToString() != "OK")
                        throw ExceptionBecause.Connection.FailedToAuthenticate(response);
                }

                _configuration.Events.OnConnectionOpened(new ConnectionEventArgs
                {
                    Host = _host,
                    Port = _port
                });
            }
            catch (Exception e)
            {
                _configuration.Events.OnConnectionError(new ConnectionEventArgs
                {
                    Host = _host,
                    Port = _port,
                    Exception = e
                });

                throw;
            }
        }
예제 #16
0
        public async Task<Stream> GetStreamAsync(Socket socket, HttpRequestMessage request)
        {
            Stream networkStream = new NetworkStream(socket);

            if (request.RequestUri.Scheme.Equals("https", StringComparison.OrdinalIgnoreCase))
            {
                var httpsStream = new SslStream(networkStream);

                await httpsStream.AuthenticateAsClientAsync(request.RequestUri.DnsSafeHost);

                networkStream = httpsStream;
            }

            return networkStream;
        }
예제 #17
0
 public async Task Connect(string Server, int Port)
 {
     try
     {
         TCPClient.Connect(Server, Port);
         SSLStream = new SslStream(TCPClient.GetStream(), false,
             (object sender, X509Certificate certificate, X509Chain chain, SslPolicyErrors sslPolicyErrors) =>
             {
                 return true;
             }) { ReadTimeout = 50000, WriteTimeout = 50000 };
         await SSLStream.AuthenticateAsClientAsync(Server);
     }
     catch
     {
     }
 }
		private async Task<SslStream> GetStream() {
			await streamSemaphore.WaitAsync();
			try {
				if(stream!=null) return stream;
				var tcpClient = new TcpClient();
				await tcpClient.ConnectAsync(Host, Port);
				stream = new SslStream(tcpClient.GetStream(), false, (source, cert, chain, policy) => {
					return Fingerprint==null || Fingerprint.Equals(cert.GetCertHashString(), StringComparison.OrdinalIgnoreCase);
				});
				await stream.AuthenticateAsClientAsync("", new X509CertificateCollection(), SslProtocols.Tls, true);
				DrainStream(stream);
				return stream;
			} finally {
				streamSemaphore.Release();
			}
		}
예제 #19
0
        public async Task ConnectAsync(Address address, ConnectionFactory factory)
        {
            Socket socket = new Socket(SocketType.Stream, ProtocolType.Tcp);

            if (factory.tcpSettings != null)
            {
                factory.tcpSettings.Configure(socket);
            }

            await Task.Factory.FromAsync(
                (c, s) => ((Socket)s).BeginConnect(address.Host, address.Port, c, s),
                (r) => ((Socket)r.AsyncState).EndConnect(r),
                socket);

            IAsyncTransport transport;
            if (address.UseSsl)
            {
                SslStream sslStream;
                var ssl = factory.SslInternal;
                if (ssl == null)
                {
                    sslStream = new SslStream(new NetworkStream(socket));
                    await sslStream.AuthenticateAsClientAsync(address.Host);
                }
                else
                {
                    sslStream = new SslStream(new NetworkStream(socket), false, ssl.RemoteCertificateValidationCallback, ssl.LocalCertificateSelectionCallback);
                    await sslStream.AuthenticateAsClientAsync(address.Host, ssl.ClientCertificates,
                        ssl.Protocols, ssl.CheckCertificateRevocation);
                }

                transport = new SslSocket(this, sslStream);
            }
            else
            {
                transport = new TcpSocket(this, socket);
            }

            this.socketTransport = transport;
            this.writer = new Writer(this, this.socketTransport);
        }
        public async Task<Stream> CreateStreamAsync(EndPoint endPoint, CancellationToken cancellationToken)
        {
            var stream = await _wrapped.CreateStreamAsync(endPoint, cancellationToken).ConfigureAwait(false);

            var sslStream = new SslStream(
                stream,
                leaveInnerStreamOpen: false,
                userCertificateValidationCallback: _settings.ServerCertificateValidationCallback,
                userCertificateSelectionCallback: _settings.ClientCertificateSelectionCallback);

            string targetHost;
            DnsEndPoint dnsEndPoint;
            IPEndPoint ipEndPoint;
            if ((dnsEndPoint = endPoint as DnsEndPoint) != null)
            {
                targetHost = dnsEndPoint.Host;
            }
            else if ((ipEndPoint = endPoint as IPEndPoint) != null)
            {
                targetHost = ipEndPoint.Address.ToString();
            }
            else
            {
                targetHost = endPoint.ToString();
            }

            var clientCertificates = new X509CertificateCollection(_settings.ClientCertificates.ToArray());

            try
            {
                await sslStream.AuthenticateAsClientAsync(targetHost, clientCertificates, _settings.EnabledSslProtocols, _settings.CheckCertificateRevocation).ConfigureAwait(false);
            }
            catch
            {
                stream.Close();
                stream.Dispose();
                throw;
            }
            return sslStream;
        }
예제 #21
0
            public async Task<EndpointStatus> GetStatus()
            {
                try
                {
                    var socket = await ConnectSocket().ConfigureAwait(false);

                    if (socket == null)
                    {
                        return new EndpointStatus(false, _endpoint);
                    }

                    socket.SendTimeout = _timeoutMilliseconds;
                    socket.ReceiveTimeout = _timeoutMilliseconds;

                    EndpointStatus endpointStatus;

                    using (var networkStream = new NetworkStream(socket, true))
                    {
                        Stream stream = networkStream;

                        if (_isHttps)
                        {
                            var sslStream = new SslStream(networkStream);
                            await sslStream.AuthenticateAsClientAsync(_server).ConfigureAwait(false);
                            stream = sslStream;
                        }

                        endpointStatus = await GetStatus(stream).ConfigureAwait(false);
                    }

                    return endpointStatus;
                }
                catch
                {
                    return new EndpointStatus(false, _endpoint);
                }
            }
예제 #22
0
        public async Task ConnectAsyncCore(Uri uri, CancellationToken cancellationToken, ClientWebSocketOptions options)
        {
            // TODO: Not currently implemented:
            // - ClientWebSocketOptions.Credentials
            // - ClientWebSocketOptions.Proxy

            // Establish connection to the server
            CancellationTokenRegistration registration = cancellationToken.Register(s => ((WebSocketHandle)s).Abort(), this);
            try
            {
                // Connect to the remote server
                Socket connectedSocket = await ConnectSocketAsync(uri.Host, uri.Port, cancellationToken).ConfigureAwait(false);
                Stream stream = new AsyncEventArgsNetworkStream(connectedSocket);

                // Upgrade to SSL if needed
                if (uri.Scheme == UriScheme.Wss)
                {
                    var sslStream = new SslStream(stream);
                    await sslStream.AuthenticateAsClientAsync(
                        uri.Host,
                        options.ClientCertificates,
                        SecurityProtocol.AllowedSecurityProtocols,
                        checkCertificateRevocation: false).ConfigureAwait(false);
                    stream = sslStream;
                }

                // Create the security key and expected response, then build all of the request headers
                KeyValuePair<string, string> secKeyAndSecWebSocketAccept = CreateSecKeyAndSecWebSocketAccept();
                byte[] requestHeader = BuildRequestHeader(uri, options, secKeyAndSecWebSocketAccept.Key);

                // Write out the header to the connection
                await stream.WriteAsync(requestHeader, 0, requestHeader.Length, cancellationToken).ConfigureAwait(false);

                // Parse the response and store our state for the remainder of the connection
                string subprotocol = await ParseAndValidateConnectResponseAsync(stream, options, secKeyAndSecWebSocketAccept.Value, cancellationToken).ConfigureAwait(false);

                _webSocket = ManagedWebSocket.CreateFromConnectedStream(stream, false, subprotocol);

                // If a concurrent Abort or Dispose came in before we set _webSocket, make sure to update it appropriately
                if (_state == WebSocketState.Aborted)
                {
                    _webSocket.Abort();
                }
                else if (_state == WebSocketState.Closed)
                {
                    _webSocket.Dispose();
                }
            }
            catch (Exception exc)
            {
                if (_state < WebSocketState.Closed)
                {
                    _state = WebSocketState.Closed;
                }

                Abort();

                if (exc is WebSocketException)
                {
                    throw;
                }
                throw new WebSocketException(SR.net_webstatus_ConnectFailure, exc);
            }
            finally
            {
                registration.Dispose();
            }
        }
        public async Task CertificatePassedToHttpContext()
        {
            RemoteCertificateValidationCallback validationCallback =
                    (sender, cert, chain, sslPolicyErrors) => true;

            try
            {
#if DNX451
                ServicePointManager.ServerCertificateValidationCallback += validationCallback;
#endif

                var serverAddress = "https://*****:*****@"TestResources/testCert.pfx", "testPassword"),
                            ClientCertificateMode = ClientCertificateMode.RequireCertificate,
                            ClientCertificateValidation = (certificate, chain, sslPolicyErrors) => true
                        },
                        new NoOpConnectionFilter())
                };

                RequestDelegate app = context =>
                {
                    var tlsFeature = context.Features.Get<ITlsConnectionFeature>();
                    Assert.NotNull(tlsFeature);
                    Assert.NotNull(tlsFeature.ClientCertificate);
                    Assert.NotNull(context.Connection.ClientCertificate);
                    return context.Response.WriteAsync("hello world");
                };

                using (var server = new TestServer(app, serviceContext, serverAddress))
                {
                    // SslStream is used to ensure the certificate is actually passed to the server
                    // HttpClient might not send the certificate because it is invalid or it doesn't match any
                    // of the certificate authorities sent by the server in the SSL handshake.
                    using (var client = new TcpClient())
                    {
                        await client.ConnectAsync("127.0.0.1", 54321);

                        SslStream stream = new SslStream(client.GetStream(), false, (sender, certificate, chain, errors) => true,
                            (sender, host, certificates, certificate, issuers) => new X509Certificate2(@"TestResources/testCert.pfx", "testPassword"));
                        await stream.AuthenticateAsClientAsync("localhost");

                        var request = Encoding.UTF8.GetBytes("GET / HTTP/1.0\r\n\r\n");
                        await stream.WriteAsync(request, 0, request.Length);

                        var reader = new StreamReader(stream);
                        var line = await reader.ReadLineAsync();
                        Assert.Equal("HTTP/1.0 200 OK", line);
                    }
                }
            }
            finally
            {
#if DNX451
                ServicePointManager.ServerCertificateValidationCallback -= validationCallback;
#endif
            }
        }
예제 #24
0
		/// <summary>
		/// Establishes a connection to the specified SMTP or SMTP/S server.
		/// </summary>
		/// <remarks>
		/// <para>Establishes a connection to the specified SMTP or SMTP/S server.</para>
		/// <para>If the <paramref name="port"/> has a value of <c>0</c>, then the
		/// <paramref name="options"/> parameter is used to determine the default port to
		/// connect to. The default port used with <see cref="SecureSocketOptions.SslOnConnect"/>
		/// is <c>465</c>. All other values will use a default port of <c>25</c>.</para>
		/// <para>If the <paramref name="options"/> has a value of
		/// <see cref="SecureSocketOptions.Auto"/>, then the <paramref name="port"/> is used
		/// to determine the default security options. If the <paramref name="port"/> has a value
		/// of <c>465</c>, then the default options used will be
		/// <see cref="SecureSocketOptions.SslOnConnect"/>. All other values will use
		/// <see cref="SecureSocketOptions.StartTlsWhenAvailable"/>.</para>
		/// <para>Once a connection is established, properties such as
		/// <see cref="AuthenticationMechanisms"/> and <see cref="Capabilities"/> will be
		/// populated.</para>
		/// <note type="note">The connection established by any of the
		/// <a href="Overload_MailKit_Net_Smtp_SmtpClient_Connect.htm">Connect</a>
		/// methods may be re-used if an application wishes to send multiple messages
		/// to the same SMTP server. Since connecting and authenticating can be expensive
		/// operations, re-using a connection can significantly improve performance when
		/// sending a large number of messages to the same SMTP server over a short
		/// period of time.</note>
		/// </remarks>
		/// <example>
		/// <code language="c#" source="Examples\SmtpExamples.cs" region="SendMessage"/>
		/// </example>
		/// <param name="host">The host name to connect to.</param>
		/// <param name="port">The port to connect to. If the specified port is <c>0</c>, then the default port will be used.</param>
		/// <param name="options">The secure socket options to when connecting.</param>
		/// <param name="cancellationToken">The cancellation token.</param>
		/// <exception cref="System.ArgumentNullException">
		/// <paramref name="host"/> is <c>null</c>.
		/// </exception>
		/// <exception cref="System.ArgumentOutOfRangeException">
		/// <paramref name="port"/> is not between <c>0</c> and <c>65535</c>.
		/// </exception>
		/// <exception cref="System.ArgumentException">
		/// The <paramref name="host"/> is a zero-length string.
		/// </exception>
		/// <exception cref="System.ObjectDisposedException">
		/// The <see cref="SmtpClient"/> has been disposed.
		/// </exception>
		/// <exception cref="System.InvalidOperationException">
		/// The <see cref="SmtpClient"/> is already connected.
		/// </exception>
		/// <exception cref="System.NotSupportedException">
		/// <paramref name="options"/> was set to
		/// <see cref="MailKit.Security.SecureSocketOptions.StartTls"/>
		/// and the SMTP server does not support the STARTTLS extension.
		/// </exception>
		/// <exception cref="System.OperationCanceledException">
		/// The operation was canceled.
		/// </exception>
		/// <exception cref="System.Net.Sockets.SocketException">
		/// A socket error occurred trying to connect to the remote host.
		/// </exception>
		/// <exception cref="System.IO.IOException">
		/// An I/O error occurred.
		/// </exception>
		/// <exception cref="SmtpCommandException">
		/// An SMTP command failed.
		/// </exception>
		/// <exception cref="SmtpProtocolException">
		/// An SMTP protocol error occurred.
		/// </exception>
		public override void Connect (string host, int port = 0, SecureSocketOptions options = SecureSocketOptions.Auto, CancellationToken cancellationToken = default (CancellationToken))
		{
			if (host == null)
				throw new ArgumentNullException (nameof (host));

			if (host.Length == 0)
				throw new ArgumentException ("The host name cannot be empty.", nameof (host));

			if (port < 0 || port > 65535)
				throw new ArgumentOutOfRangeException (nameof (port));
			
			CheckDisposed ();

			if (IsConnected)
				throw new InvalidOperationException ("The SmtpClient is already connected.");

			capabilities = SmtpCapabilities.None;
			AuthenticationMechanisms.Clear ();
			MaxSize = 0;

			SmtpResponse response;
			Stream stream;
			bool starttls;
			Uri uri;

			ComputeDefaultValues (host, ref port, ref options, out uri, out starttls);

#if !NETFX_CORE
#if COREFX
			var ipAddresses = Dns.GetHostAddressesAsync (uri.DnsSafeHost).GetAwaiter ().GetResult ();
#else
			var ipAddresses = Dns.GetHostAddresses (uri.DnsSafeHost);
#endif
			Socket socket = null;

			for (int i = 0; i < ipAddresses.Length; i++) {
				socket = new Socket (ipAddresses[i].AddressFamily, SocketType.Stream, ProtocolType.Tcp) {
					ReceiveTimeout = timeout,
					SendTimeout = timeout
				};

				try {
					cancellationToken.ThrowIfCancellationRequested ();

					if (LocalEndPoint != null)
						socket.Bind (LocalEndPoint);

					socket.Connect (ipAddresses[i], port);
					break;
				} catch (OperationCanceledException) {
					socket.Dispose ();
					socket = null;
					throw;
				} catch {
					socket.Dispose ();
					socket = null;

					if (i + 1 == ipAddresses.Length)
						throw;
				}
			}

			if (socket == null)
				throw new IOException (string.Format ("Failed to resolve host: {0}", host));

			this.host = host;

			if (options == SecureSocketOptions.SslOnConnect) {
				var ssl = new SslStream (new NetworkStream (socket, true), false, ValidateRemoteCertificate);

				try {
#if COREFX
					ssl.AuthenticateAsClientAsync (host, ClientCertificates, SslProtocols, true).GetAwaiter ().GetResult ();
#else
					ssl.AuthenticateAsClient (host, ClientCertificates, SslProtocols, true);
#endif
				} catch {
					ssl.Dispose ();
					throw;
				}

				secure = true;
				stream = ssl;
			} else {
				stream = new NetworkStream (socket, true);
				secure = false;
			}
#else
			var protection = options == SecureSocketOptions.SslOnConnect ? SocketProtectionLevel.Tls12 : SocketProtectionLevel.PlainSocket;
			var socket = new StreamSocket ();

			try {
				cancellationToken.ThrowIfCancellationRequested ();
				socket.ConnectAsync (new HostName (host), port.ToString (), protection)
					.AsTask (cancellationToken)
					.GetAwaiter ()
					.GetResult ();
			} catch {
				socket.Dispose ();
				throw;
			}

			stream = new DuplexStream (socket.InputStream.AsStreamForRead (0), socket.OutputStream.AsStreamForWrite (0));
			secure = options == SecureSocketOptions.SslOnConnect;
			this.host = host;
#endif

			if (stream.CanTimeout) {
				stream.WriteTimeout = timeout;
				stream.ReadTimeout = timeout;
			}

			ProtocolLogger.LogConnect (uri);

			Stream = new SmtpStream (stream, socket, ProtocolLogger);

			try {
				// read the greeting
				response = Stream.ReadResponse (cancellationToken);

				if (response.StatusCode != SmtpStatusCode.ServiceReady)
					throw new SmtpCommandException (SmtpErrorCode.UnexpectedStatusCode, response.StatusCode, response.Response);

				// Send EHLO and get a list of supported extensions
				Ehlo (cancellationToken);

				if (options == SecureSocketOptions.StartTls && (capabilities & SmtpCapabilities.StartTLS) == 0)
					throw new NotSupportedException ("The SMTP server does not support the STARTTLS extension.");

				if (starttls && (capabilities & SmtpCapabilities.StartTLS) != 0) {
					response = SendCommand ("STARTTLS", cancellationToken);
					if (response.StatusCode != SmtpStatusCode.ServiceReady)
						throw new SmtpCommandException (SmtpErrorCode.UnexpectedStatusCode, response.StatusCode, response.Response);

#if !NETFX_CORE
					var tls = new SslStream (stream, false, ValidateRemoteCertificate);
#if COREFX
					tls.AuthenticateAsClientAsync (host, ClientCertificates, SslProtocols, true).GetAwaiter ().GetResult ();
#else
					tls.AuthenticateAsClient (host, ClientCertificates, SslProtocols, true);
#endif
					Stream.Stream = tls;
#else
					socket.UpgradeToSslAsync (SocketProtectionLevel.Tls12, new HostName (host))
						.AsTask (cancellationToken)
						.GetAwaiter ()
						.GetResult ();
#endif

					secure = true;

					// Send EHLO again and get the new list of supported extensions
					Ehlo (cancellationToken);
				}

				connected = true;
			} catch {
				Stream.Dispose ();
				secure = false;
				Stream = null;
				throw;
			}

			OnConnected ();
		}
예제 #25
0
		/// <summary>
		/// Establish a connection to the specified SMTP or SMTP/S server using the provided socket.
		/// </summary>
		/// <remarks>
		/// <para>Establishes a connection to the specified SMTP or SMTP/S server.</para>
		/// <para>If the <paramref name="port"/> has a value of <c>0</c>, then the
		/// <paramref name="options"/> parameter is used to determine the default port to
		/// connect to. The default port used with <see cref="SecureSocketOptions.SslOnConnect"/>
		/// is <c>465</c>. All other values will use a default port of <c>25</c>.</para>
		/// <para>If the <paramref name="options"/> has a value of
		/// <see cref="SecureSocketOptions.Auto"/>, then the <paramref name="port"/> is used
		/// to determine the default security options. If the <paramref name="port"/> has a value
		/// of <c>465</c>, then the default options used will be
		/// <see cref="SecureSocketOptions.SslOnConnect"/>. All other values will use
		/// <see cref="SecureSocketOptions.StartTlsWhenAvailable"/>.</para>
		/// <para>Once a connection is established, properties such as
		/// <see cref="AuthenticationMechanisms"/> and <see cref="Capabilities"/> will be
		/// populated.</para>
		/// <note type="note">The connection established by any of the
		/// <a href="Overload_MailKit_Net_Smtp_SmtpClient_Connect.htm">Connect</a>
		/// methods may be re-used if an application wishes to send multiple messages
		/// to the same SMTP server. Since connecting and authenticating can be expensive
		/// operations, re-using a connection can significantly improve performance when
		/// sending a large number of messages to the same SMTP server over a short
		/// period of time./</note>
		/// </remarks>
		/// <param name="socket">The socket to use for the connection.</param>
		/// <param name="host">The host name to connect to.</param>
		/// <param name="port">The port to connect to. If the specified port is <c>0</c>, then the default port will be used.</param>
		/// <param name="options">The secure socket options to when connecting.</param>
		/// <param name="cancellationToken">The cancellation token.</param>
		/// <exception cref="System.ArgumentNullException">
		/// <para><paramref name="socket"/> is <c>null</c>.</para>
		/// <para>-or-</para>
		/// <para><paramref name="host"/> is <c>null</c>.</para>
		/// </exception>
		/// <exception cref="System.ArgumentOutOfRangeException">
		/// <paramref name="port"/> is not between <c>0</c> and <c>65535</c>.
		/// </exception>
		/// <exception cref="System.ArgumentException">
		/// <para><paramref name="socket"/> is not connected.</para>
		/// <para>-or-</para>
		/// The <paramref name="host"/> is a zero-length string.
		/// </exception>
		/// <exception cref="System.ObjectDisposedException">
		/// The <see cref="SmtpClient"/> has been disposed.
		/// </exception>
		/// <exception cref="System.InvalidOperationException">
		/// The <see cref="SmtpClient"/> is already connected.
		/// </exception>
		/// <exception cref="System.NotSupportedException">
		/// <paramref name="options"/> was set to
		/// <see cref="MailKit.Security.SecureSocketOptions.StartTls"/>
		/// and the SMTP server does not support the STARTTLS extension.
		/// </exception>
		/// <exception cref="System.OperationCanceledException">
		/// The operation was canceled.
		/// </exception>
		/// <exception cref="System.IO.IOException">
		/// An I/O error occurred.
		/// </exception>
		/// <exception cref="SmtpCommandException">
		/// An SMTP command failed.
		/// </exception>
		/// <exception cref="SmtpProtocolException">
		/// An SMTP protocol error occurred.
		/// </exception>
		public void Connect (Socket socket, string host, int port = 0, SecureSocketOptions options = SecureSocketOptions.Auto, CancellationToken cancellationToken = default (CancellationToken))
		{
			if (socket == null)
				throw new ArgumentNullException (nameof (socket));

			if (!socket.Connected)
				throw new ArgumentException ("The socket is not connected.", nameof (socket));

			if (host == null)
				throw new ArgumentNullException (nameof (host));

			if (host.Length == 0)
				throw new ArgumentException ("The host name cannot be empty.", nameof (host));

			if (port < 0 || port > 65535)
				throw new ArgumentOutOfRangeException (nameof (port));

			CheckDisposed ();

			if (IsConnected)
				throw new InvalidOperationException ("The SmtpClient is already connected.");

			capabilities = SmtpCapabilities.None;
			AuthenticationMechanisms.Clear ();
			MaxSize = 0;

			SmtpResponse response;
			Stream stream;
			bool starttls;
			Uri uri;

			ComputeDefaultValues (host, ref port, ref options, out uri, out starttls);

			this.host = host;

			if (options == SecureSocketOptions.SslOnConnect) {
				var ssl = new SslStream (new NetworkStream (socket, true), false, ValidateRemoteCertificate);

				try {
#if COREFX
					ssl.AuthenticateAsClientAsync (host, ClientCertificates, SslProtocols, true).GetAwaiter ().GetResult ();
#else
					ssl.AuthenticateAsClient (host, ClientCertificates, SslProtocols, true);
#endif
				} catch {
					ssl.Dispose ();
					throw;
				}

				secure = true;
				stream = ssl;
			} else {
				stream = new NetworkStream (socket, true);
				secure = false;
			}

			if (stream.CanTimeout) {
				stream.WriteTimeout = timeout;
				stream.ReadTimeout = timeout;
			}

			ProtocolLogger.LogConnect (uri);

			Stream = new SmtpStream (stream, socket, ProtocolLogger);

			try {
				// read the greeting
				response = Stream.ReadResponse (cancellationToken);

				if (response.StatusCode != SmtpStatusCode.ServiceReady)
					throw new SmtpCommandException (SmtpErrorCode.UnexpectedStatusCode, response.StatusCode, response.Response);

				// Send EHLO and get a list of supported extensions
				Ehlo (cancellationToken);

				if (options == SecureSocketOptions.StartTls && (capabilities & SmtpCapabilities.StartTLS) == 0)
					throw new NotSupportedException ("The SMTP server does not support the STARTTLS extension.");

				if (starttls && (capabilities & SmtpCapabilities.StartTLS) != 0) {
					response = SendCommand ("STARTTLS", cancellationToken);
					if (response.StatusCode != SmtpStatusCode.ServiceReady)
						throw new SmtpCommandException (SmtpErrorCode.UnexpectedStatusCode, response.StatusCode, response.Response);

					var tls = new SslStream (stream, false, ValidateRemoteCertificate);
#if COREFX
					tls.AuthenticateAsClientAsync (host, ClientCertificates, SslProtocols, true).GetAwaiter ().GetResult ();
#else
					tls.AuthenticateAsClient (host, ClientCertificates, SslProtocols, true);
#endif
					Stream.Stream = tls;

					secure = true;

					// Send EHLO again and get the new list of supported extensions
					Ehlo (cancellationToken);
				}

				connected = true;
			} catch {
				Stream.Dispose ();
				secure = false;
				Stream = null;
				throw;
			}

			OnConnected ();
		}
        public async Task ConnectAsync(string host, int port, string scheme, TimeSpan timeout)
        {
            this.host = host;
            bool succeeded = false;
            try
            {
                // Connect without proxy
                this.TcpClient = new TcpClient();
                await this.TcpClient.ConnectAsync(host, port);

                if (string.Equals(WebSocketConstants.Scheme, scheme, StringComparison.OrdinalIgnoreCase))
                {
                    // In the real world, web-socket will happen over HTTPS
                    var sslStream = new SslStream(this.TcpClient.GetStream(), false, IotHubConnection.OnRemoteCertificateValidation);
                    await sslStream.AuthenticateAsClientAsync(host);
                    this.WebSocketStream = sslStream;
                }
                else
                {
                    this.WebSocketStream = this.TcpClient.GetStream();
                }

                var upgradeRequest = this.BuildUpgradeRequest();
                byte[] upgradeRequestBytes = Encoding.ASCII.GetBytes(upgradeRequest);

                this.TcpClient.Client.SendTimeout = GetSocketTimeoutInMilliSeconds(timeout);

                // Send WebSocket Upgrade request
                await this.WebSocketStream.WriteAsync(upgradeRequestBytes, 0, upgradeRequestBytes.Length);

                // receive WebSocket Upgrade response
                var responseBuffer = new byte[8 * 1024];

                var upgradeResponse = new HttpResponse(this.TcpClient, this.WebSocketStream, responseBuffer);

                await upgradeResponse.ReadAsync(timeout);

                if (upgradeResponse.StatusCode != HttpStatusCode.SwitchingProtocols)
                {
                    // the HTTP response code was not 101
                    if (this.TcpClient.Connected)
                    {
                        this.WebSocketStream.Close();
                        this.TcpClient.Close();
                    }

                    throw new IOException(ServerRejectedUpgradeRequest + " " + upgradeResponse);
                }

                if (!this.VerifyWebSocketUpgradeResponse(upgradeResponse.Headers))
                {
                    if (this.TcpClient.Connected)
                    {
                        this.WebSocketStream.Close();
                        this.TcpClient.Close();
                    }

                    throw new IOException(UpgradeProtocolNotSupported.FormatInvariant(WebSocketConstants.SubProtocols.Amqpwsb10));
                }

                this.State = WebSocketState.Open;
                succeeded = true;
            }
            finally
            {
                if (!succeeded)
                {
                    this.Abort();
                }
            }
        }
        /// <summary>
        /// Initializes the stream asynchronous.
        /// </summary>
        /// <returns></returns>
        private Task InitializeStreamAsync()
        {

            var stream = _client.GetStream();
            if (!_isSecure)
            {
                _stream = stream;
                return TaskAsyncHelper.Empty;
            }
            
            var sslStream = new SslStream(stream);
            _stream = sslStream;
            return sslStream.AuthenticateAsClientAsync(_host);
        }
예제 #28
0
        private async Task SocketEntryAsync(CancellationToken ct)
        {
            _stream = _tcpClient.GetStream();
            if (IsSecure)
            {
                var sslStream = new SslStream(_stream, true, (sender, cert, chain, sslPolicyErrors) =>                
                {
                    if (!AcceptInsecureCertificate)
                    {
                        if (sslPolicyErrors == SslPolicyErrors.None)
                        {
                            return true;
                        }
                        else
                        {
                            OnConnectionError(new ErrorEventArgs("Server has an invalid Ssl Certificate"));
                        }
                    }
                    return true; // accept all insecure certificates
                });
                await sslStream.AuthenticateAsClientAsync(Hostname).ConfigureAwait(false);
                _stream = sslStream;
            }


            TaskFactory f = new TaskFactory();
            await f.StartNew(async () =>
            {
                await Task.Yield(); // yield to fire and forget
                try
                {
                    await SocketLoopAsync(ct).ConfigureAwait(false);
                }
                catch (IOException ex)
                {
                    OnConnectionError(new ErrorEventArgs(ex));
                }
                catch (SocketException ex)
                {
                    OnConnectionError(new ErrorEventArgs(ex));
                }                
                finally
                {
                    Close();
                }
            }, _wtoken.Token, TaskCreationOptions.LongRunning, TaskScheduler.Default).ConfigureAwait(false);            
        }
예제 #29
0
        public async Task ConnectAsync(Address address, ConnectionFactory factory)
        {
            IPAddress[] ipAddresses;
            IPAddress ip;
            if (IPAddress.TryParse(address.Host, out ip))
            {
                ipAddresses = new IPAddress[] { ip };
            }
            else
            {
                ipAddresses = await TaskExtensions.GetHostAddressesAsync(address.Host);
            }

            // need to handle both IPv4 and IPv6
            Socket socket = null;
            Exception exception = null;
            for (int i = 0; i < ipAddresses.Length; i++)
            {
                if (ipAddresses[i] == null ||
                    (ipAddresses[i].AddressFamily == AddressFamily.InterNetwork && !Socket.OSSupportsIPv4) ||
                    (ipAddresses[i].AddressFamily == AddressFamily.InterNetworkV6 && !Socket.OSSupportsIPv6))
                {
                    continue;
                }

                socket = new Socket(ipAddresses[i].AddressFamily, SocketType.Stream, ProtocolType.Tcp);
                try
                {
                    await socket.ConnectAsync(ipAddresses[i], address.Port);
                    exception = null;
                    break;
                }
                catch (Exception e)
                {
                    exception = e;
                    socket.Dispose();
                    socket = null;
                }
            }

            if (socket == null)
            {
                throw exception ?? new SocketException((int)SocketError.AddressNotAvailable);
            }

            if (factory.tcpSettings != null)
            {
                factory.tcpSettings.Configure(socket);
            }

            IAsyncTransport transport;
            if (address.UseSsl)
            {
                SslStream sslStream;
                var ssl = factory.SslInternal;
                if (ssl == null)
                {
                    sslStream = new SslStream(new NetworkStream(socket));
                    await sslStream.AuthenticateAsClientAsync(address.Host);
                }
                else
                {
                    sslStream = new SslStream(new NetworkStream(socket), false, ssl.RemoteCertificateValidationCallback, ssl.LocalCertificateSelectionCallback);
                    await sslStream.AuthenticateAsClientAsync(address.Host, ssl.ClientCertificates,
                        ssl.Protocols, ssl.CheckCertificateRevocation);
                }

                transport = new SslSocket(this, sslStream);
            }
            else
            {
                transport = new TcpSocket(this, socket);
            }

            this.socketTransport = transport;
            this.writer = new Writer(this, this.socketTransport);
        }
예제 #30
0
        private async Task<Stream> NegotiateStream(Stream stream)
        {
            if (!_sslEnabled)
                return stream;

            var validateRemoteCertificate = new RemoteCertificateValidationCallback(
                (object sender,
                X509Certificate certificate,
                X509Chain chain,
                SslPolicyErrors sslPolicyErrors)
                =>
                {
                    if (sslPolicyErrors == SslPolicyErrors.None)
                        return true;

                    if (_configuration.SslPolicyErrorsBypassed)
                        return true;
                    else
                        _log.ErrorFormat("Error occurred when validating remote certificate: [{0}], [{1}].",
                            this.RemoteEndPoint, sslPolicyErrors);

                    return false;
                });

            var sslStream = new SslStream(
                stream,
                false,
                validateRemoteCertificate,
                null,
                _configuration.SslEncryptionPolicy);

            if (_configuration.SslClientCertificates == null || _configuration.SslClientCertificates.Count == 0)
            {
                await sslStream.AuthenticateAsClientAsync( // No client certificates are used in the authentication. The certificate revocation list is not checked during authentication.
                    _configuration.SslTargetHost); // The name of the server that will share this SslStream. The value specified for targetHost must match the name on the server's certificate.
            }
            else
            {
                await sslStream.AuthenticateAsClientAsync(
                    _configuration.SslTargetHost, // The name of the server that will share this SslStream. The value specified for targetHost must match the name on the server's certificate.
                    _configuration.SslClientCertificates, // The X509CertificateCollection that contains client certificates.
                    _configuration.SslEnabledProtocols, // The SslProtocols value that represents the protocol used for authentication.
                    _configuration.SslCheckCertificateRevocation); // A Boolean value that specifies whether the certificate revocation list is checked during authentication.
            }

            // When authentication succeeds, you must check the IsEncrypted and IsSigned properties 
            // to determine what security services are used by the SslStream. 
            // Check the IsMutuallyAuthenticated property to determine whether mutual authentication occurred.
            _log.DebugFormat(
                "Ssl Stream: SslProtocol[{0}], IsServer[{1}], IsAuthenticated[{2}], IsEncrypted[{3}], IsSigned[{4}], IsMutuallyAuthenticated[{5}], "
                + "HashAlgorithm[{6}], HashStrength[{7}], KeyExchangeAlgorithm[{8}], KeyExchangeStrength[{9}], CipherAlgorithm[{10}], CipherStrength[{11}].",
                sslStream.SslProtocol,
                sslStream.IsServer,
                sslStream.IsAuthenticated,
                sslStream.IsEncrypted,
                sslStream.IsSigned,
                sslStream.IsMutuallyAuthenticated,
                sslStream.HashAlgorithm,
                sslStream.HashStrength,
                sslStream.KeyExchangeAlgorithm,
                sslStream.KeyExchangeStrength,
                sslStream.CipherAlgorithm,
                sslStream.CipherStrength);

            return sslStream;
        }