From 1597d5f3848cdb39b7d458f0c6c33ecdfc3125d5 Mon Sep 17 00:00:00 2001 From: Alexander Golubev Date: Tue, 30 Jan 2024 00:44:29 +0300 Subject: [PATCH] tdeioslave/sftp: better erros for unsupported auth methods Also: - do not translate auth methods names as the names appear in config files verbatim - libssh actually doesn't supports hostbased auth, so exclude it from bitset of supported Signed-off-by: Alexander Golubev --- tdeioslave/sftp/tdeio_sftp.cpp | 57 ++++++++++++++++++++++------------ tdeioslave/sftp/tdeio_sftp.h | 8 ++++- 2 files changed, 44 insertions(+), 21 deletions(-) diff --git a/tdeioslave/sftp/tdeio_sftp.cpp b/tdeioslave/sftp/tdeio_sftp.cpp index b71e9c1b5..971cdb30d 100644 --- a/tdeioslave/sftp/tdeio_sftp.cpp +++ b/tdeioslave/sftp/tdeio_sftp.cpp @@ -174,7 +174,6 @@ void log_callback(ssh_session session, int priority, const char *message, class PublicKeyAuth: public SSHAuthMethod { public: int flag() override {return SSH_AUTH_METHOD_PUBLICKEY;}; - TQString name() override { return i18n("public key"); }; int authenticate(sftpProtocol *ioslave) const override { return ioslave->authenticatePublicKey(); } @@ -186,7 +185,6 @@ public: KeyboardInteractiveAuth(bool noPaswordQuery = false): mNoPaswordQuery(noPaswordQuery) {} int flag() override {return SSH_AUTH_METHOD_INTERACTIVE;}; - TQString name() override { return i18n("keyboard interactive"); }; int authenticate(sftpProtocol *ioslave) const override { return ioslave->authenticateKeyboardInteractive(mNoPaswordQuery); } @@ -201,7 +199,6 @@ public: PasswordAuth(bool noPaswordQuery = false): mNoPaswordQuery(noPaswordQuery) {} int flag() override {return SSH_AUTH_METHOD_PASSWORD;}; - TQString name() override { return i18n("password"); }; int authenticate(sftpProtocol *ioslave) const override { return ioslave->authenticatePassword(mNoPaswordQuery); } @@ -211,6 +208,31 @@ private: const bool mNoPaswordQuery; }; +TQString SSHAuthMethod::flagToStr (int m) { + switch (m) { + case SSH_AUTH_METHOD_NONE : return TQString::fromLatin1 ( "none" ); + case SSH_AUTH_METHOD_PASSWORD : return TQString::fromLatin1 ( "password" ); + case SSH_AUTH_METHOD_PUBLICKEY : return TQString::fromLatin1 ( "publickey" ); + case SSH_AUTH_METHOD_HOSTBASED : return TQString::fromLatin1 ( "hostbased" ); + case SSH_AUTH_METHOD_INTERACTIVE : return TQString::fromLatin1 ( "keyboard-interactive" ); + case SSH_AUTH_METHOD_GSSAPI_MIC : return TQString::fromLatin1 ( "gssapi-with-mic" ); + default : return TQString::fromLatin1 ( "unknown" ); + } +} + +TQStringList SSHAuthMethod::bitsetToStr (int m) { + TQStringList rv; + + for (int i=0; m>>i; i++) { + int flag = m & (1 << i); + if (flag) { + rv.append(flagToStr(flag)); + } + } + return rv; +} + + // Public key authentication int sftpProtocol::auth_callback(const char *prompt, char *buf, size_t len, int echo, int verify, void *userdata) @@ -1116,7 +1138,7 @@ connection_restart: } // Preinit the list of supported auth methods - static const auto authMethodsNormal= [](){ + static const auto authMethodsNormal = [](){ std::vector> rv; rv.emplace_back(std::make_unique()); rv.emplace_back(std::make_unique()); @@ -1126,7 +1148,7 @@ connection_restart: const static int supportedMethods = std::accumulate( authMethodsNormal.begin(), authMethodsNormal.end(), - SSH_AUTH_METHOD_NONE | SSH_AUTH_METHOD_HOSTBASED, //< methods supported automagically + SSH_AUTH_METHOD_NONE, //< none is supported by default [](int acc, const auto &m){ return acc |= m->flag(); }); int attemptedMethods = 0; @@ -1150,12 +1172,13 @@ connection_restart: // Technically libssh docs suggest that the server merely MAY send auth methods, but it's // highly unclear what we should do in such case and it looks like openssh doesn't have an // option for that, so let's just consider this server a jerk and don't talk to him anymore. - error(TDEIO::ERR_COULD_NOT_LOGIN, i18n("Authentication failed." - " The server did not send any authentication methods!")); + error(TDEIO::ERR_COULD_NOT_LOGIN, i18n("Authentication failed.\n" + "The server did not send any authentication methods!")); return; } else if (!(availableMethodes & supportedMethods)) { - error(TDEIO::ERR_COULD_NOT_LOGIN, i18n("Authentication failed." - " The server sent only unsupported authentication methods!")); + error(TDEIO::ERR_COULD_NOT_LOGIN, i18n("Authentication failed.\n" + "The server sent only unsupported authentication methods (%1)!") + .arg(SSHAuthMethod::bitsetToStr(availableMethodes).join(", "))); return; } @@ -1216,23 +1239,17 @@ connection_restart: error(TDEIO::ERR_USER_CANCELED, TQString::null); return; } else if (rc != SSH_AUTH_SUCCESS && rc != SSH_AUTH_PARTIAL) { - TQStringList attemptedMethodsLst; - for (auto &method: authMethodsNormal) { - if (attemptedMethods & method->flag()) { attemptedMethodsLst << method->name(); } - } - - TQString errMsg = i18n("Authentication denied (attempted method was: %1).", - "Authentication denied (attempted methods were: %1).", - attemptedMethodsLst.size()) - .arg(attemptedMethodsLst.join(", ")); + TQString errMsg = i18n("Authentication denied (attempted methods: %1).") + .arg(SSHAuthMethod::bitsetToStr(attemptedMethods).join(", ")); if (availableMethodes & ~supportedMethods) { errMsg.append("\n") - .append(i18n("Note: server also declares some other unsupported authentication methods")); + .append(i18n("Note: server also declares some unsupported authentication methods (%1)") + .arg(SSHAuthMethod::bitsetToStr(availableMethodes & ~supportedMethods).join(", "))); } error(TDEIO::ERR_COULD_NOT_LOGIN, errMsg); return; } - } + } // while (rc != SSH_AUTH_SUCCESS) // start sftp session kdDebug(TDEIO_SFTP_DB) << "Trying to request the sftp session" << endl; diff --git a/tdeioslave/sftp/tdeio_sftp.h b/tdeioslave/sftp/tdeio_sftp.h index 54d4e8242..303014ead 100644 --- a/tdeioslave/sftp/tdeio_sftp.h +++ b/tdeioslave/sftp/tdeio_sftp.h @@ -201,13 +201,19 @@ public: /** libssh's flag for he method */ virtual int flag() = 0; /** The user-friendly (probably translated) name of the method */ - virtual TQString name() = 0; + 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(int method); + + /** Returns a list of names for all the methods set in the given libssh auth method bitset */ + static TQStringList bitsetToStr(int method); }; #endif