summaryrefslogtreecommitdiffstats
path: root/tdeioslave
diff options
context:
space:
mode:
authorAlexander Golubev <[email protected]>2024-01-19 09:29:00 +0300
committerTDE Gitea <[email protected]>2024-03-04 11:04:10 +0000
commita1fa8a79bbd7f6385d312cce709768944506d960 (patch)
tree6c80a5969fb27160723472a4dbefc1a63c537a5c /tdeioslave
parenta646f58853c9bc888488ed5508012e468148e983 (diff)
downloadtdebase-a1fa8a79bbd7f6385d312cce709768944506d960.tar.gz
tdebase-a1fa8a79bbd7f6385d312cce709768944506d960.zip
tdeioslave/sftp: fix keyboard-interactive authentication
This is a partial fix to the sftp ioslave. Subsequent commits will fix other issues. Closes: https://mirror.git.trinitydesktop.org/gitea/TDE/tdebase/issues/443 Signed-off-by: Alexander Golubev <[email protected]>
Diffstat (limited to 'tdeioslave')
-rw-r--r--tdeioslave/sftp/tdeio_sftp.cpp128
1 files changed, 85 insertions, 43 deletions
diff --git a/tdeioslave/sftp/tdeio_sftp.cpp b/tdeioslave/sftp/tdeio_sftp.cpp
index 8b74023c0..cc086d5aa 100644
--- a/tdeioslave/sftp/tdeio_sftp.cpp
+++ b/tdeioslave/sftp/tdeio_sftp.cpp
@@ -180,11 +180,20 @@ int sftpProtocol::authenticateKeyboardInteractive(AuthInfo &info) {
kdDebug(TDEIO_SFTP_DB) << "Entering keyboard interactive function" << endl;
- err = ssh_userauth_kbdint(mSession, mUsername.utf8().data(), NULL);
- while (err == SSH_AUTH_INFO) {
+ while (1) {
int n = 0;
int i = 0;
+ err = ssh_userauth_kbdint(mSession, NULL, NULL);
+
+ if (err != SSH_AUTH_INFO) {
+ kdDebug(TDEIO_SFTP_DB) << "Finishing kbdint auth err=" << err
+ << " ssh_err=" << ssh_get_error_code(mSession)
+ << " (" << ssh_get_error(mSession) << ")" << endl;
+
+ break;
+ }
+
name = TQString::fromUtf8(ssh_userauth_kbdint_getname(mSession));
instruction = TQString::fromUtf8(ssh_userauth_kbdint_getinstruction(mSession));
n = ssh_userauth_kbdint_getnprompts(mSession);
@@ -193,22 +202,58 @@ int sftpProtocol::authenticateKeyboardInteractive(AuthInfo &info) {
<< " prompts" << n << endl;
for (i = 0; i < n; ++i) {
+ // See RFC4256 Section 3.3 User Interface
char echo;
- const char *answer = "";
+ TQString answer;
prompt = TQString::fromUtf8(ssh_userauth_kbdint_getprompt(mSession, i, &echo));
kdDebug(TDEIO_SFTP_DB) << "prompt=" << prompt << " echo=" << TQString::number(echo) << endl;
- if (echo) {
- // See RFC4256 Section 3.3 User Interface
- TQString newPrompt;
- TDEIO::AuthInfo infoKbdInt;
- infoKbdInt.url.setProtocol("sftp");
- infoKbdInt.url.setHost(mHost);
- infoKbdInt.url.setPort(mPort);
+ TDEIO::AuthInfo infoKbdInt(info);
- infoKbdInt.caption = i18n("SFTP Login");
- infoKbdInt.comment = "sftp://" + mUsername + "@" + mHost;
+ if (!echo) {
+ // ssh server requests us to ask user a question without displaying an answer. In normal
+ // circumstances this is probably a password, but it might be something else depending
+ // on the server configuration.
+ bool isPassword = false;
+ if (prompt.lower().startsWith("password")) {
+ // We can assume that the ssh server asks for a password and we want a more
+ // user-friendly prompt in that case
+ infoKbdInt.prompt = i18n("Please enter your password.");
+ isPassword = true;
+ infoKbdInt.keepPassword = true;
+ if (!mPassword.isNull()) { // if we have a cached password we might use it
+ kdDebug(TDEIO_SFTP_DB) << "Using cached password" << endl;
+ answer = mPassword;
+ }
+ } else {
+ // If the server's request doesn't look like a password, keep the servers prompt and
+ // don't bother saving it
+ infoKbdInt.prompt = prompt;
+ infoKbdInt.keepPassword = false;
+ }
+
+ infoKbdInt.readOnly = true; // set username readonly
+ /* FIXME: We can query a new user name but we will have to reinitialize the connection if
+ * it changes <2024-01-10 Fat-Zer> */
+ if (answer.isNull()) {
+ if (openPassDlg(infoKbdInt)) {
+ kdDebug(TDEIO_SFTP_DB) << "Got the answer from the password dialog" << endl;
+ answer = infoKbdInt.password;
+ if(isPassword) {
+ info.password = infoKbdInt.password; // return the answer to the caller
+ }
+ } else {
+ /* FIXME: Some reasonable action upon cancellation? <2024-01-10 Fat-Zer> */
+ }
+ }
+ } else {
+ // ssh server asks for some clear-text information from a user (e.g. a one-time
+ // identification code) which should be echoed while user enters it. As for now tdeio has
+ // no means of handle that correctly, so we will have to be creative with the password
+ // dialog.
+ TQString newPrompt;
+ infoKbdInt.comment = "sftp://" + infoKbdInt.username + "@" + mHost;
if (!name.isEmpty()) {
infoKbdInt.caption = TQString(i18n("SFTP Login") + " - " + name);
@@ -221,42 +266,25 @@ int sftpProtocol::authenticateKeyboardInteractive(AuthInfo &info) {
newPrompt.append(prompt + "\n\n");
infoKbdInt.readOnly = false;
infoKbdInt.keepPassword = false;
- infoKbdInt.prompt = i18n("Use the username input field to answer this question.");
-
+ newPrompt.append(i18n("Use the username input field to answer this question."));
+ infoKbdInt.prompt = newPrompt;
if (openPassDlg(infoKbdInt)) {
- kdDebug(TDEIO_SFTP_DB) << "Got the answer from the password dialog" << endl;
- answer = info.username.utf8().data();
- }
-
- if (ssh_userauth_kbdint_setanswer(mSession, i, answer) < 0) {
- kdDebug(TDEIO_SFTP_DB) << "An error occurred setting the answer: "
- << ssh_get_error(mSession) << endl;
- return SSH_AUTH_ERROR;
- }
- break;
- } else {
- if (prompt.lower().startsWith("password")) {
- answer = mPassword.utf8().data();
+ answer = infoKbdInt.username;
+ kdDebug(TDEIO_SFTP_DB) << "Got the answer from the password dialog: " << answer << endl;
} else {
- info.readOnly = true; // set username readonly
- info.prompt = prompt;
-
- if (openPassDlg(info)) {
- kdDebug(TDEIO_SFTP_DB) << "Got the answer from the password dialog" << endl;
- answer = info.password.utf8().data();
- }
+ /* FIXME: Some reasonable action upon cancellation? <2024-01-10 Fat-Zer> */
}
+ }
- if (ssh_userauth_kbdint_setanswer(mSession, i, answer) < 0) {
- kdDebug(TDEIO_SFTP_DB) << "An error occurred setting the answer: "
- << ssh_get_error(mSession) << endl;
- return SSH_AUTH_ERROR;
- }
+ if (ssh_userauth_kbdint_setanswer(mSession, i, answer.utf8().data()) < 0) {
+ kdDebug(TDEIO_SFTP_DB) << "An error occurred setting the answer: "
+ << ssh_get_error(mSession) << endl;
+ /* FIXME: display the error to the user <2024-01-10 Fat-Zer> */
+ return SSH_AUTH_ERROR;
}
- }
- err = ssh_userauth_kbdint(mSession, mUsername.utf8().data(), NULL);
- }
+ } // for each ssh_userauth_kbdint_getprompt()
+ } // while (1)
return err;
}
@@ -733,6 +761,18 @@ void sftpProtocol::openConnection() {
kdDebug(TDEIO_SFTP_DB) << "Trying to authenticate with the server" << endl;
+ // If no username was set upon connection, get the name from connection
+ // (probably it'd be the current user's name)
+ if (mUsername.isEmpty()) {
+ char *ssh_username = NULL;
+ rc = ssh_options_get(mSession, SSH_OPTIONS_USER, &ssh_username);
+ if (rc == 0 && ssh_username && ssh_username[0]) {
+ mUsername = ssh_username;
+ info.username = mUsername;
+ }
+ ssh_string_free_char(ssh_username);
+ }
+
// Try to authenticate
rc = ssh_userauth_none(mSession, NULL);
if (rc == SSH_AUTH_ERROR) {
@@ -786,6 +826,8 @@ void sftpProtocol::openConnection() {
if (rc == SSH_AUTH_SUCCESS)
{
info = tmpInfo;
+ mUsername = info.username;
+ mPassword = info.password;
}
else if (rc == SSH_AUTH_ERROR)
{
@@ -794,7 +836,7 @@ void sftpProtocol::openConnection() {
.arg(i18n("keyboard interactive")));
return;
}
- }
+ }
// Try to authenticate with password
if (rc != SSH_AUTH_SUCCESS && (method & SSH_AUTH_METHOD_PASSWORD))