/* * Copyright (c) 2001 Lucas Fisher * Copyright (c) 2009 Andreas Schneider * Copyright (c) 2020 Martin Sandsmark * KDE2 port * Copyright (c) 2022 Mavridis Philippe * Trinity port * * This library is free software; you can redistribute it and/or * modify it under the terms of the GNU Library General Public * License (LGPL) as published by the Free Software Foundation; * either version 2 of the License, or (at your option) any later * version. * * This library is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU * Library General Public License for more details. * * You should have received a copy of the GNU Library General Public License * along with this library; see the file COPYING.LIB. If not, write to * the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, * Boston, MA 02110-1301, USA. */ #ifndef __tdeio_sftp_h__ #define __tdeio_sftp_h__ #include #include #include #include #include #include #include #include #include // How big should each data packet be? Definitely not bigger than 64kb or // you will overflow the 2 byte size variable in a sftp packet. #define MAX_XFER_BUF_SIZE 60 * 1024 #define TDEIO_SFTP_DB 7120 #if LIBSSH_VERSION_INT < SSH_VERSION_INT(0, 7, 90) #define TDEIO_SSH_KNOWN_HOSTS_OK SSH_SERVER_KNOWN_OK #define TDEIO_SSH_KNOWN_HOSTS_OTHER SSH_SERVER_FOUND_OTHER #define TDEIO_SSH_KNOWN_HOSTS_CHANGED SSH_SERVER_KNOWN_CHANGED #define TDEIO_SSH_KNOWN_HOSTS_NOT_FOUND SSH_SERVER_FILE_NOT_FOUND #define TDEIO_SSH_KNOWN_HOSTS_UNKNOWN SSH_SERVER_NOT_KNOWN #define TDEIO_SSH_KNOWN_HOSTS_ERROR SSH_SERVER_ERROR #else #define TDEIO_SSH_KNOWN_HOSTS_OK SSH_KNOWN_HOSTS_OK #define TDEIO_SSH_KNOWN_HOSTS_OTHER SSH_KNOWN_HOSTS_OTHER #define TDEIO_SSH_KNOWN_HOSTS_CHANGED SSH_KNOWN_HOSTS_CHANGED #define TDEIO_SSH_KNOWN_HOSTS_NOT_FOUND SSH_KNOWN_HOSTS_NOT_FOUND #define TDEIO_SSH_KNOWN_HOSTS_UNKNOWN SSH_KNOWN_HOSTS_UNKNOWN #define TDEIO_SSH_KNOWN_HOSTS_ERROR SSH_KNOWN_HOSTS_ERROR #endif namespace TDEIO { class AuthInfo; } class sftpProtocol : public TDEIO::SlaveBase { public: sftpProtocol(const TQCString &pool_socket, const TQCString &app_socket); virtual ~sftpProtocol(); virtual void setHost(const TQString& h, int port, const TQString& user, const TQString& pass) override; virtual void get(const KURL& url) override; virtual void listDir(const KURL& url) override; virtual void mimetype(const KURL& url) override; virtual void stat(const KURL& url) override; virtual void put(const KURL& url, int permissions, bool overwrite, bool resume) override; virtual void copy(const KURL &src, const KURL &dest, int permissions, bool overwrite) override; virtual void closeConnection() override; virtual void slave_status() override; virtual void del(const KURL &url, bool isfile) override; virtual void chmod(const KURL& url, int permissions) override; virtual void symlink(const TQString& target, const KURL& dest, bool overwrite) override; virtual void rename(const KURL& src, const KURL& dest, bool overwrite) override; virtual void mkdir(const KURL& url, int permissions) override; virtual void openConnection() override; // libssh authentication callback (note that this is called by the // global ::auth_callback() call. int auth_callback(const char *prompt, char *buf, size_t len, int echo, int verify, void *userdata); // libssh logging callback (note that this is called by the // global ::log_callback() call. void log_callback(ssh_session session, int priority, const char *message, void *userdata); // Callbacks for SSHAuthMethod-derived strategies int authenticatePublicKey(); int authenticateKeyboardInteractive(bool noPaswordQuery = false); int authenticatePassword(bool noPaswordQuery = false); /** Some extra authentication failure reasons intended to use alongside was declared in libssh */ enum extra_ssh_auth_e { SSH_AUTH_CANCELED=128, //< user canceled password entry dialog SSH_AUTH_NEED_RECONNECT //< it is required to reinitialize connection from scratch }; private: // Private variables /** True if ioslave is connected to sftp server. */ bool mConnected; /** Host we are connected to. */ TQString mHost; /** Port we are connected to. */ int mPort; /** The ssh session for the connection */ ssh_session mSession; /** The sftp session for the connection */ sftp_session mSftp; /** Username to use when connecting, Note: it's the one passed in the URL */ TQString mUsername; /** Username to use with the next connection attempt: it's either from the cached data or from * the password dialog that was prompted to the user. */ TQString mCachedUsername; /** User's password. Note: the password would be set only if it was somehow cached: passed to * setHost(), received from passwdserver's cache or was entered by user before reconnection */ TQString mPassword; /** The open file */ sftp_file mOpenFile; /** The open URL */ KURL mOpenUrl; ssh_callbacks mCallbacks; /** Version of the sftp protocol we are using. */ int sftpVersion; //struct Status //{ // int code; // TDEIO::filesize_t size; // TQString text; //}; /** Some data needed to interact with auth_callback() */ struct { /** List of keys user was already prompted to enter the passphrase for. * Note: Under most sane circumstances the list shouldn't go beyond size=2, * so no fancy containers here */ TQStringList attemptedKeys; /** A backup for SlaveBase::s_seqNr to pass the same value to prompts for different keys */ long current_seqNr; /** true if callback was called */ bool wasCalled; /** true if user canceled all passphrase entry dialogues */ bool wasCanceled; } mPubKeyAuthData; /** true if the password dialog was prompted to the user at leas once */ bool mPasswordWasPrompted = false; private: // private methods void statMime(const KURL &url); void closeFile(); /** @returns username used by libssh during the connection */ TQString sshUsername(); /** Adds ssh error (if any) to the given message string */ TQString sshError(TQString errMsg=TQString()); /** A small helper function to construct auth info skeleton for the protocol */ TDEIO::AuthInfo authInfo(); /** A helper function encapsulating creation of an ssh connection before authentication */ int initializeConnection(); void reportError(const KURL &url, const int err); bool createUDSEntry(const TQString &filename, const TQByteArray &path, TDEIO::UDSEntry &entry, short int details); TQString canonicalizePath(const TQString &path); }; /** A base class for ssh authentication methods. */ class SSHAuthMethod { public: /** libssh's flag for he method */ virtual unsigned flag() = 0; /** The user-friendly (probably translated) name of the method */ virtual TQString name() {return flagToStr(flag());} /** Actually do perform the auth process */ virtual int authenticate(sftpProtocol *ioslave) const = 0; /** Creates a copy of derived class */ virtual SSHAuthMethod* clone() = 0; virtual ~SSHAuthMethod() {}; /** Returns a name for the given libssh auth method flag */ static TQString flagToStr(unsigned method); /** Returns a list of names for all the methods set in the given libssh auth method bitset */ static TQStringList bitsetToStr(unsigned method); }; #endif