Esempio n. 1
0
        /// <summary>
        /// Connect to the remote servers, with the details from Profile
        /// </summary>
        /// <param name="reconnecting">True if this is an attempt to re-establish a closed connection</param>
        public void Connect(bool reconnecting = false)
        {
            Notifications.ChangeTrayText(reconnecting ? MessageType.Reconnecting : MessageType.Connecting);
            Log.Write(l.Debug, "{0} client...", reconnecting ? "Reconnecting" : "Connecting");

            if (FTP)
            {
                _ftpc = new FtpClient {
                    Host = controller.Account.Host, Port = controller.Account.Port
                };

                // Add accepted certificates
                _ftpc.ClientCertificates.AddRange(Certificates);

                if (controller.Account.Protocol == FtpProtocol.FTPS)
                {
                    _ftpc.ValidateCertificate += (sender, x) =>
                    {
                        var fingerPrint = new X509Certificate2(x.Certificate).Thumbprint;

                        if (_ftpc.ClientCertificates.Count <= 0 && x.PolicyErrors != SslPolicyErrors.None)
                        {
                            Certificates.Add(x.Certificate);
                            x.Accept = false;
                            return;
                        }

                        // if ValidateCertificate handler isn't set, accept the certificate and move on
                        if (ValidateCertificate == null || Settings.TrustedCertificates.Contains(fingerPrint))
                        {
                            Log.Write(l.Client, "Trusted: {0}", fingerPrint);
                            x.Accept = true;
                            return;
                        }

                        var e = new ValidateCertificateEventArgs
                        {
                            Fingerprint  = fingerPrint,
                            SerialNumber = x.Certificate.GetSerialNumberString(),
                            Algorithm    = x.Certificate.GetKeyAlgorithmParametersString(),
                            ValidFrom    = x.Certificate.GetEffectiveDateString(),
                            ValidTo      = x.Certificate.GetExpirationDateString(),
                            Issuer       = x.Certificate.Issuer
                        };
                        // Prompt user to validate
                        ValidateCertificate(null, e);
                        x.Accept = e.IsTrusted;
                    };

                    // Change Security Protocol
                    if (controller.Account.FtpsMethod == FtpsMethod.Explicit)
                    {
                        _ftpc.EncryptionMode = FtpEncryptionMode.Explicit;
                    }
                    else if (controller.Account.FtpsMethod == FtpsMethod.Implicit)
                    {
                        _ftpc.EncryptionMode = FtpEncryptionMode.Implicit;
                    }
                }

                _ftpc.Credentials = new NetworkCredential(controller.Account.Username, controller.Account.Password);

                try
                {
                    _ftpc.Connect();
                }
                catch (Exception exc)
                {
                    // Since the ClientCertificates are added when accepted in ValidateCertificate, the first
                    // attempt to connect will fail with an AuthenticationException. If this is the case, a
                    // re-connect is attempted, this time with the certificates properly set.
                    // This is a workaround to avoid storing Certificate files locally...
                    if (exc is System.Security.Authentication.AuthenticationException &&
                        _ftpc.ClientCertificates.Count <= 0)
                    {
                        Connect();
                    }
                    else
                    {
                        throw;
                    }
                }
            }
            else             // SFTP
            {
                ConnectionInfo connectionInfo;
                if (controller.isPrivateKeyValid)
                {
                    connectionInfo = new PrivateKeyConnectionInfo(controller.Account.Host, controller.Account.Port, controller.Account.Username, new PrivateKeyFile(controller.Account.PrivateKeyFile, controller.Account.Password));
                }
                else
                {
                    connectionInfo = new PasswordConnectionInfo(controller.Account.Host, controller.Account.Port, controller.Account.Username, controller.Account.Password);
                }

                _sftpc = new SftpClient(connectionInfo);
                _sftpc.ConnectionInfo.AuthenticationBanner += (o, x) => Log.Write(l.Warning, x.BannerMessage);

                _sftpc.HostKeyReceived += (o, x) =>
                {
                    var fingerPrint = x.FingerPrint.GetCertificateData();

                    // if ValidateCertificate handler isn't set, accept the certificate and move on
                    if (ValidateCertificate == null || Settings.TrustedCertificates.Contains(fingerPrint))
                    {
                        Log.Write(l.Client, "Trusted: {0}", fingerPrint);
                        x.CanTrust = true;
                        return;
                    }

                    var e = new ValidateCertificateEventArgs
                    {
                        Fingerprint = fingerPrint,
                        Key         = x.HostKeyName,
                        KeySize     = x.KeyLength.ToString()
                    };
                    // Prompt user to validate
                    ValidateCertificate(null, e);
                    x.CanTrust = e.IsTrusted;
                };

                _sftpc.Connect();

                _sftpc.ErrorOccurred += (o, e) =>
                {
                    if (!isConnected)
                    {
                        Notifications.ChangeTrayText(MessageType.Nothing);
                    }
                    if (ConnectionClosed != null)
                    {
                        ConnectionClosed(null, new ConnectionClosedEventArgs {
                            Text = e.Exception.Message
                        });
                    }

                    if (e.Exception is Renci.SshNet.Common.SftpPermissionDeniedException)
                    {
                        Log.Write(l.Warning, "Permission denied error occured");
                    }
                    if (e.Exception is Renci.SshNet.Common.SshConnectionException)
                    {
                        Reconnect();
                    }
                };
            }

            controller.HomePath = WorkingDirectory;

            if (isConnected)
            {
                if (!string.IsNullOrWhiteSpace(controller.Paths.Remote) && !controller.Paths.Remote.Equals("/"))
                {
                    WorkingDirectory = controller.Paths.Remote;
                }
            }

            Log.Write(l.Debug, "Client connected sucessfully");
            Notifications.ChangeTrayText(MessageType.Ready);

            if (Settings.IsDebugMode)
            {
                LogServerInfo();
            }

            // Periodically send NOOP (KeepAlive) to server if a non-zero interval is set
            SetKeepAlive();
        }