Пример #1
0
 /// <summary>
 /// Connect to the FTP server. Overridden in proxy classes.
 /// </summary>
 protected virtual Task ConnectAsync(FtpSocketStream stream, string host, int port, FtpIpVersion ipVersions, CancellationToken token)
 {
     return(stream.ConnectAsync(host, port, ipVersions, token));
 }
Пример #2
0
 /// <summary>
 /// Connect to the FTP server. Overridden in proxy classes.
 /// </summary>
 /// <param name="stream"></param>
 /// <param name="token"></param>
 protected virtual async Task ConnectAsync(FtpSocketStream stream, CancellationToken token)
 {
     await stream.ConnectAsync(Host, Port, InternetProtocolVersions, token);
 }
Пример #3
0
 /// <summary>
 /// Connect to the FTP server. Overridden in proxy classes.
 /// </summary>
 protected virtual void Connect(FtpSocketStream stream, string host, int port, FtpIpVersion ipVersions)
 {
     stream.Connect(host, port, ipVersions);
 }
Пример #4
0
 /// <summary>
 /// Connect to the FTP server. Overridden in proxy classes.
 /// </summary>
 /// <param name="stream"></param>
 protected virtual void Connect(FtpSocketStream stream)
 {
     stream.Connect(Host, Port, InternetProtocolVersions);
 }
Пример #5
0
        // TODO: add example
        /// <summary>
        /// Connect to the server
        /// </summary>
        /// <exception cref="ObjectDisposedException">Thrown if this object has been disposed.</exception>
        public virtual async Task ConnectAsync(CancellationToken token = default(CancellationToken))
        {
            FtpReply reply;

            LogFunc(nameof(ConnectAsync));

            if (IsDisposed)
            {
                throw new ObjectDisposedException("This FtpClient object has been disposed. It is no longer accessible.");
            }

            if (m_stream == null)
            {
                m_stream = new FtpSocketStream(this);
                m_stream.ValidateCertificate += new FtpSocketStreamSslValidation(FireValidateCertficate);
            }
            else
            {
                if (IsConnected)
                {
                    Disconnect();
                }
            }

            if (Host == null)
            {
                throw new FtpException("No host has been specified");
            }

            if (m_capabilities == null)
            {
                m_capabilities = new List <FtpCapability>();
            }

            ResetStateFlags();

            m_hashAlgorithms            = FtpHashAlgorithm.NONE;
            m_stream.ConnectTimeout     = m_connectTimeout;
            m_stream.SocketPollInterval = m_socketPollInterval;
            await ConnectAsync(m_stream, token);

            m_stream.SetSocketOption(SocketOptionLevel.Socket, SocketOptionName.KeepAlive, m_keepAlive);

#if !NO_SSL
            if (EncryptionMode == FtpEncryptionMode.Implicit)
            {
                await m_stream.ActivateEncryptionAsync(Host, m_clientCerts.Count > 0?m_clientCerts : null, m_SslProtocols);
            }
#endif

            await HandshakeAsync(token);

            m_serverType = FtpServerSpecificHandler.DetectFtpServer(this, HandshakeReply);

            if (SendHost)
            {
                if (!(reply = await ExecuteAsync("HOST " + (SendHostDomain != null ? SendHostDomain : Host), token)).Success)
                {
                    throw new FtpException("HOST command failed.");
                }
            }

#if !NO_SSL
            // try to upgrade this connection to SSL if supported by the server
            if (EncryptionMode == FtpEncryptionMode.Explicit || EncryptionMode == FtpEncryptionMode.Auto)
            {
                reply = await ExecuteAsync("AUTH TLS", token);

                if (!reply.Success)
                {
                    _ConnectionFTPSFailure = true;
                    if (EncryptionMode == FtpEncryptionMode.Explicit)
                    {
                        throw new FtpSecurityNotAvailableException("AUTH TLS command failed.");
                    }
                }
                else if (reply.Success)
                {
                    await m_stream.ActivateEncryptionAsync(Host, m_clientCerts.Count > 0?m_clientCerts : null, m_SslProtocols);
                }
            }
#endif


            if (m_credentials != null)
            {
                await AuthenticateAsync(token);
            }

            // configure the default FTPS settings
            if (IsEncrypted && DataConnectionEncryption)
            {
                if (!(reply = await ExecuteAsync("PBSZ 0", token)).Success)
                {
                    throw new FtpCommandException(reply);
                }

                if (!(reply = await ExecuteAsync("PROT P", token)).Success)
                {
                    throw new FtpCommandException(reply);
                }
            }

            // if this is a clone these values should have already been loaded
            // so save some bandwidth and CPU time and skip executing this again.
            // otherwise clear the capabilities in case connection is reused to
            // a different server
            if (!m_isClone && m_checkCapabilities)
            {
                m_capabilities.Clear();
            }
            bool assumeCaps = false;
            if (m_capabilities.IsBlank() && m_checkCapabilities)
            {
                if ((reply = await ExecuteAsync("FEAT", token)).Success && reply.InfoMessages != null)
                {
                    GetFeatures(reply);
                }
                else
                {
                    assumeCaps = true;
                }
            }

            // Enable UTF8 if the encoding is ASCII and UTF8 is supported
            if (m_textEncodingAutoUTF && m_textEncoding == Encoding.ASCII && HasFeature(FtpCapability.UTF8))
            {
                m_textEncoding = Encoding.UTF8;
            }

            LogStatus(FtpTraceLevel.Info, "Text encoding: " + m_textEncoding.ToString());

            if (m_textEncoding == Encoding.UTF8)
            {
                // If the server supports UTF8 it should already be enabled and this
                // command should not matter however there are conflicting drafts
                // about this so we'll just execute it to be safe.
                if ((reply = await ExecuteAsync("OPTS UTF8 ON", token)).Success)
                {
                    _ConnectionUTF8Success = true;
                }
            }

            // Get the system type - Needed to auto-detect file listing parser
            if ((reply = await ExecuteAsync("SYST", token)).Success)
            {
                m_systemType = reply.Message;
                m_serverType = FtpServerSpecificHandler.DetectFtpServerBySyst(this);
                m_serverOS   = FtpServerSpecificHandler.DetectFtpOSBySyst(this);
            }

            // Set a FTP server handler if a custom handler has not already been set
            if (ServerHandler == null)
            {
                ServerHandler = FtpServerSpecificHandler.GetServerHandler(m_serverType);
            }
            // Assume the system's capabilities if FEAT command not supported by the server
            if (assumeCaps)
            {
                FtpServerSpecificHandler.AssumeCapabilities(this, ServerHandler, m_capabilities, ref m_hashAlgorithms);
            }

#if !NO_SSL && !CORE
            if (IsEncrypted && PlainTextEncryption)
            {
                if (!(reply = await ExecuteAsync("CCC", token)).Success)
                {
                    throw new FtpSecurityNotAvailableException("Failed to disable encryption with CCC command. Perhaps your server does not support it or is not configured to allow it.");
                }
                else
                {
                    // close the SslStream and send close_notify command to server
                    m_stream.DeactivateEncryption();

                    // read stale data (server's reply?)
                    await ReadStaleDataAsync(false, true, false, token);
                }
            }
#endif

            // Unless a custom list parser has been set,
            // Detect the listing parser and prefer machine listings over any other type
            // FIX : #739 prefer using machine listings to fix issues with GetListing and DeleteDirectory
            if (ListingParser != FtpParser.Custom)
            {
                ListingParser = ServerHandler != null?ServerHandler.GetParser() : FtpParser.Auto;

                if (HasFeature(FtpCapability.MLSD))
                {
                    ListingParser = FtpParser.Machine;
                }
            }

            // Create the parser even if the auto-OS detection failed
            m_listParser.Init(m_serverOS, ListingParser);

            // FIX : #318 always set the type when we create a new connection
            ForceSetDataType = true;

            // Execute server-specific post-connection event
            if (ServerHandler != null)
            {
                await ServerHandler.AfterConnectedAsync(this, token);
            }
        }
Пример #6
0
 /// <summary>
 /// Catches the socket stream ssl validation event and fires the event handlers
 /// attached to this object for validating SSL certificates
 /// </summary>
 /// <param name="stream">The stream that fired the event</param>
 /// <param name="e">The event args used to validate the certificate</param>
 private void FireValidateCertficate(FtpSocketStream stream, FtpSslValidationEventArgs e)
 {
     OnValidateCertficate(e);
 }
Пример #7
0
        // TODO: add example
        /// <summary>
        /// Connect to the server
        /// </summary>
        /// <exception cref="ObjectDisposedException">Thrown if this object has been disposed.</exception>
        /// <example><code source="..\Examples\Connect.cs" lang="cs" /></example>
        public virtual async Task ConnectAsync(CancellationToken token = default(CancellationToken))
        {
            FtpReply reply;

            LogFunc(nameof(ConnectAsync));

            if (IsDisposed)
            {
                throw new ObjectDisposedException("This FtpClient object has been disposed. It is no longer accessible.");
            }

            if (m_stream == null)
            {
                m_stream        = new FtpSocketStream(m_SslProtocols);
                m_stream.Client = this;
                m_stream.ValidateCertificate += new FtpSocketStreamSslValidation(FireValidateCertficate);
            }
            else
            {
                if (IsConnected)
                {
                    Disconnect();
                }
            }

            if (Host == null)
            {
                throw new FtpException("No host has been specified");
            }

            if (!IsClone)
            {
                m_capabilities = new List <FtpCapability>();
            }

            m_hashAlgorithms            = FtpHashAlgorithm.NONE;
            m_stream.ConnectTimeout     = m_connectTimeout;
            m_stream.SocketPollInterval = m_socketPollInterval;
            await ConnectAsync(m_stream, token);

            m_stream.SetSocketOption(SocketOptionLevel.Socket, SocketOptionName.KeepAlive, m_keepAlive);

#if !NO_SSL
            if (EncryptionMode == FtpEncryptionMode.Implicit)
            {
                await m_stream.ActivateEncryptionAsync(Host, m_clientCerts.Count > 0?m_clientCerts : null, m_SslProtocols);
            }
#endif

            await HandshakeAsync(token);

            m_serverType = FtpServerSpecificHandler.DetectFtpServer(this, HandshakeReply);

            if (SendHost)
            {
                if (!(reply = await ExecuteAsync("HOST " + (SendHostDomain != null ? SendHostDomain : Host), token)).Success)
                {
                    throw new FtpException("HOST command failed.");
                }
            }

#if !NO_SSL
            if (EncryptionMode == FtpEncryptionMode.Explicit)
            {
                if (!(reply = await ExecuteAsync("AUTH TLS", token)).Success)
                {
                    throw new FtpSecurityNotAvailableException("AUTH TLS command failed.");
                }

                await m_stream.ActivateEncryptionAsync(Host, m_clientCerts.Count > 0?m_clientCerts : null, m_SslProtocols);
            }
#endif

            if (m_credentials != null)
            {
                await AuthenticateAsync(token);
            }

            if (m_stream.IsEncrypted && DataConnectionEncryption)
            {
                if (!(reply = await ExecuteAsync("PBSZ 0", token)).Success)
                {
                    throw new FtpCommandException(reply);
                }

                if (!(reply = await ExecuteAsync("PROT P", token)).Success)
                {
                    throw new FtpCommandException(reply);
                }
            }

            // if this is a clone these values should have already been loaded
            // so save some bandwidth and CPU time and skip executing this again.
            bool assumeCaps = false;
            if (!IsClone && m_checkCapabilities)
            {
                if ((reply = await ExecuteAsync("FEAT", token)).Success && reply.InfoMessages != null)
                {
                    GetFeatures(reply);
                }
                else
                {
                    assumeCaps = true;
                }
            }

            // Enable UTF8 if the encoding is ASCII and UTF8 is supported
            if (m_textEncodingAutoUTF && m_textEncoding == Encoding.ASCII && HasFeature(FtpCapability.UTF8))
            {
                m_textEncoding = Encoding.UTF8;
            }

            LogStatus(FtpTraceLevel.Info, "Text encoding: " + m_textEncoding.ToString());

            if (m_textEncoding == Encoding.UTF8)
            {
                // If the server supports UTF8 it should already be enabled and this
                // command should not matter however there are conflicting drafts
                // about this so we'll just execute it to be safe.
                await ExecuteAsync("OPTS UTF8 ON", token);
            }

            // Get the system type - Needed to auto-detect file listing parser
            if ((reply = await ExecuteAsync("SYST", token)).Success)
            {
                m_systemType = reply.Message;
                m_serverType = FtpServerSpecificHandler.DetectFtpServerBySyst(this);
                m_serverOS   = FtpServerSpecificHandler.DetectFtpOSBySyst(this);
            }

            // Assume the system's capabilities if FEAT command not supported by the server
            if (assumeCaps)
            {
                FtpServerSpecificHandler.AssumeCapabilities(this, m_capabilities, ref m_hashAlgorithms);
            }

#if !NO_SSL && !CORE
            if (m_stream.IsEncrypted && PlainTextEncryption)
            {
                if (!(reply = await ExecuteAsync("CCC", token)).Success)
                {
                    throw new FtpSecurityNotAvailableException("Failed to disable encryption with CCC command. Perhaps your server does not support it or is not configured to allow it.");
                }
                else
                {
                    // close the SslStream and send close_notify command to server
                    m_stream.DeactivateEncryption();

                    // read stale data (server's reply?)
                    await ReadStaleDataAsync(false, true, false, token);
                }
            }
#endif

            // Create the parser after OS auto-detection
            m_listParser.Init(m_serverOS, FtpServerSpecificHandler.GetParserByServerType(this));
        }
Пример #8
0
        /// <summary>
        /// Connect to the server
        /// </summary>
        /// <exception cref="ObjectDisposedException">Thrown if this object has been disposed.</exception>
        /// <example><code source="..\Examples\Connect.cs" lang="cs" /></example>
        public virtual void Connect()
        {
            FtpReply reply;

#if !CORE14
            lock (m_lock) {
#endif

            LogFunc(nameof(Connect));

            if (IsDisposed)
            {
                throw new ObjectDisposedException("This FtpClient object has been disposed. It is no longer accessible.");
            }

            if (m_stream == null)
            {
                m_stream        = new FtpSocketStream(m_SslProtocols);
                m_stream.Client = this;
                m_stream.ValidateCertificate += new FtpSocketStreamSslValidation(FireValidateCertficate);
            }
            else
            {
                if (IsConnected)
                {
                    Disconnect();
                }
            }

            if (Host == null)
            {
                throw new FtpException("No host has been specified");
            }

            if (!IsClone)
            {
                m_capabilities = new List <FtpCapability>();
            }

            ResetStateFlags();

            m_hashAlgorithms            = FtpHashAlgorithm.NONE;
            m_stream.ConnectTimeout     = m_connectTimeout;
            m_stream.SocketPollInterval = m_socketPollInterval;
            Connect(m_stream);

            m_stream.SetSocketOption(SocketOptionLevel.Socket, SocketOptionName.KeepAlive, m_keepAlive);

#if !NO_SSL
            if (EncryptionMode == FtpEncryptionMode.Implicit)
            {
                m_stream.ActivateEncryption(Host, m_clientCerts.Count > 0 ? m_clientCerts : null, m_SslProtocols);
            }
#endif

            Handshake();
            m_serverType = FtpServerSpecificHandler.DetectFtpServer(this, HandshakeReply);

            if (SendHost)
            {
                if (!(reply = Execute("HOST " + (SendHostDomain != null ? SendHostDomain : Host))).Success)
                {
                    throw new FtpException("HOST command failed.");
                }
            }

#if !NO_SSL
            // try to upgrade this connection to SSL if supported by the server
            if (EncryptionMode == FtpEncryptionMode.Explicit || EncryptionMode == FtpEncryptionMode.Auto)
            {
                reply = Execute("AUTH TLS");
                if (!reply.Success && EncryptionMode == FtpEncryptionMode.Explicit)
                {
                    throw new FtpSecurityNotAvailableException("AUTH TLS command failed.");
                }
                else if (reply.Success)
                {
                    m_stream.ActivateEncryption(Host, m_clientCerts.Count > 0 ? m_clientCerts : null, m_SslProtocols);
                }
            }
#endif

            if (m_credentials != null)
            {
                Authenticate();
            }

            // configure the default FTPS settings
            if (IsEncrypted && DataConnectionEncryption)
            {
                if (!(reply = Execute("PBSZ 0")).Success)
                {
                    throw new FtpCommandException(reply);
                }

                if (!(reply = Execute("PROT P")).Success)
                {
                    throw new FtpCommandException(reply);
                }
            }

            // if this is a clone these values should have already been loaded
            // so save some bandwidth and CPU time and skip executing this again.
            bool assumeCaps = false;
            if (!IsClone && m_checkCapabilities)
            {
                if ((reply = Execute("FEAT")).Success && reply.InfoMessages != null)
                {
                    GetFeatures(reply);
                }
                else
                {
                    assumeCaps = true;
                }
            }

            // Enable UTF8 if the encoding is ASCII and UTF8 is supported
            if (m_textEncodingAutoUTF && m_textEncoding == Encoding.ASCII && HasFeature(FtpCapability.UTF8))
            {
                m_textEncoding = Encoding.UTF8;
            }

            LogStatus(FtpTraceLevel.Info, "Text encoding: " + m_textEncoding.ToString());

            if (m_textEncoding == Encoding.UTF8)
            {
                // If the server supports UTF8 it should already be enabled and this
                // command should not matter however there are conflicting drafts
                // about this so we'll just execute it to be safe.
                Execute("OPTS UTF8 ON");
            }

            // Get the system type - Needed to auto-detect file listing parser
            if ((reply = Execute("SYST")).Success)
            {
                m_systemType = reply.Message;
                m_serverType = FtpServerSpecificHandler.DetectFtpServerBySyst(this);
                m_serverOS   = FtpServerSpecificHandler.DetectFtpOSBySyst(this);
            }

            // Set a FTP server handler if a custom handler has not already been set
            if (ServerHandler == null)
            {
                ServerHandler = FtpServerSpecificHandler.GetServerHandler(m_serverType);
            }

            // Assume the system's capabilities if FEAT command not supported by the server
            if (assumeCaps)
            {
                FtpServerSpecificHandler.AssumeCapabilities(this, ServerHandler, m_capabilities, ref m_hashAlgorithms);
            }

#if !NO_SSL && !CORE
            if (IsEncrypted && PlainTextEncryption)
            {
                if (!(reply = Execute("CCC")).Success)
                {
                    throw new FtpSecurityNotAvailableException("Failed to disable encryption with CCC command. Perhaps your server does not support it or is not configured to allow it.");
                }
                else
                {
                    // close the SslStream and send close_notify command to server
                    m_stream.DeactivateEncryption();

                    // read stale data (server's reply?)
                    ReadStaleData(false, true, false);
                }
            }
#endif

            // Create the parser even if the auto-OS detection failed
            var forcedParser = ServerHandler != null?ServerHandler.GetParser() : FtpParser.Auto;

            m_listParser.Init(m_serverOS, forcedParser);

            // FIX : #318 always set the type when we create a new connection
            ForceSetDataType = true;

#if !CORE14
        }
#endif
        }