The branch, build-baikal has been updated via ac14ad24e7a2d3d3fd08e61098769b5391f4ea8b (commit) from a77d761dbb16d28206e7c2446654539935746e4e (commit) Those revisions listed above that are new to this repository have not appeared on any other notification email; so we list those revisions in full, below. - Log ----------------------------------------------------------------- ----------------------------------------------------------------------- Summary of changes: debian/changelog | 1 + onmainwindow.cpp | 17 ++++-- onmainwindow.h | 2 +- sshmasterconnection.cpp | 148 +++++++++++++++++++++++++++++++++++++++++++---- sshmasterconnection.h | 7 ++- sshprocess.cpp | 2 +- 6 files changed, 159 insertions(+), 18 deletions(-) The diff of changes is: diff --git a/debian/changelog b/debian/changelog index f8d5a5b..582891f 100644 --- a/debian/changelog +++ b/debian/changelog @@ -60,6 +60,7 @@ x2goclient (4.0.1.2-0x2go2) UNRELEASED; urgency=low sessions. - Support for GSSApi(Kerberos 5) authentication. Using ssh/scp commands on Linux and Mac and plink/pscp on Windows. + - Support for ChallengeResponseAuthentication (Google Authenticator) [ Heinrich Schuchardt ] * New upstream version (4.0.1.2): diff --git a/onmainwindow.cpp b/onmainwindow.cpp index 7a0a2a8..946e6ae 100644 --- a/onmainwindow.cpp +++ b/onmainwindow.cpp @@ -2853,8 +2853,8 @@ SshMasterConnection* ONMainWindow::startSshConnection ( QString host, QString po connect ( con, SIGNAL ( serverAuthError ( int,QString, SshMasterConnection* ) ),this, SLOT ( slotSshServerAuthError ( int,QString, SshMasterConnection* ) ) ); - connect ( con, SIGNAL ( needPassPhrase(SshMasterConnection*)),this, - SLOT ( slotSshServerAuthPassphrase(SshMasterConnection*)) ); + connect ( con, SIGNAL ( needPassPhrase(SshMasterConnection*, bool)),this, + SLOT ( slotSshServerAuthPassphrase(SshMasterConnection*, bool)) ); connect ( con, SIGNAL ( userAuthError ( QString ) ),this,SLOT ( slotSshUserAuthError ( QString ) ) ); connect ( con, SIGNAL ( connectionError ( QString,QString ) ), this, SLOT ( slotSshConnectionError ( QString,QString ) ) ); @@ -2946,11 +2946,20 @@ void ONMainWindow::slotServSshConnectionOk(QString server) con->executeCommand( "export HOSTNAME && x2golistsessions", this, SLOT (slotListAllSessions ( bool,QString,int ) )); } -void ONMainWindow::slotSshServerAuthPassphrase(SshMasterConnection* connection) +void ONMainWindow::slotSshServerAuthPassphrase(SshMasterConnection* connection, bool verificationCode) { bool ok; + QString message; + if(verificationCode) + { + message=tr("Verification code:"); + } + else + { + message=tr("Enter passphrase to decrypt a key"); + } QString phrase=QInputDialog::getText(0,connection->getUser()+"@"+connection->getHost()+":"+QString::number(connection->getPort()), - tr("Enter passphrase to decrypt a key"),QLineEdit::Password,QString::null, &ok); + message,QLineEdit::Password,QString::null, &ok); if(!ok) { phrase=QString::null; diff --git a/onmainwindow.h b/onmainwindow.h index 7e51291..6f26417 100644 --- a/onmainwindow.h +++ b/onmainwindow.h @@ -941,7 +941,7 @@ private slots: void showSessionStatus(); void slotSshConnectionError ( QString message, QString lastSessionError ); void slotSshServerAuthError ( int error, QString sshMessage, SshMasterConnection* connection ); - void slotSshServerAuthPassphrase ( SshMasterConnection* connection ); + void slotSshServerAuthPassphrase ( SshMasterConnection* connection, bool verificationCode ); void slotSshUserAuthError ( QString error ); void slotSshConnectionOk(); void slotServSshConnectionOk(QString server); diff --git a/sshmasterconnection.cpp b/sshmasterconnection.cpp index 9a81853..d705f7c 100644 --- a/sshmasterconnection.cpp +++ b/sshmasterconnection.cpp @@ -47,7 +47,7 @@ #define PROXYTUNNELPORT 44444 #undef DEBUG -#define DEBUG +// #define DEBUG #undef SSH_DEBUG // #define SSH_DEBUG @@ -181,6 +181,7 @@ SshMasterConnection::SshMasterConnection (QObject* parent, QString host, int por reverseTunnel=false; mainWnd=(ONMainWindow*) parent; kerberos=krblogin; + challengeAuthVerificationCode=QString::null; #ifdef DEBUG if (kerberos) { @@ -352,9 +353,13 @@ SshMasterConnection* SshMasterConnection::reverseTunnelConnection ( SshProcess* proxypassword, proxykey, proxyautologin, localProxyPort ); con->kerberos=kerberos; + con->setVerficationCode(challengeAuthVerificationCode); + connect ( con,SIGNAL ( ioErr ( SshProcess*,QString,QString ) ),this,SIGNAL ( ioErr ( SshProcess*,QString,QString ) ) ); connect ( con,SIGNAL ( stdErr ( SshProcess*,QByteArray ) ),this,SIGNAL ( stdErr ( SshProcess*,QByteArray ) ) ); connect ( con,SIGNAL ( reverseListenOk ( SshProcess* ) ), this, SIGNAL ( reverseListenOk ( SshProcess* ) ) ); + connect ( con,SIGNAL ( needPassPhrase(SshMasterConnection*, bool)), this, SIGNAL (needPassPhrase(SshMasterConnection*, bool))); + con->keyPhrase=keyPhrase; con->keyPhraseReady=true; con->start(); @@ -383,8 +388,8 @@ void SshMasterConnection::run() connect ( sshProxy, SIGNAL ( serverAuthError ( int,QString,SshMasterConnection* ) ),this, SLOT ( slotSshProxyServerAuthError ( int,QString, SshMasterConnection* ) ) ); - connect ( sshProxy, SIGNAL ( needPassPhrase(SshMasterConnection*)),this, - SIGNAL ( needPassPhrase(SshMasterConnection*)) ); + connect ( sshProxy, SIGNAL ( needPassPhrase(SshMasterConnection*, bool)),this, + SIGNAL ( needPassPhrase(SshMasterConnection*, bool)) ); connect ( sshProxy, SIGNAL ( serverAuthAborted()),this, SLOT ( slotSshProxyServerAuthAborted()) ); connect ( sshProxy, SIGNAL ( userAuthError ( QString ) ),this,SLOT ( slotSshProxyUserAuthError ( QString ) ) ); @@ -800,20 +805,141 @@ int SshMasterConnection::serverAuth ( QString& errorMsg ) return state; } +void SshMasterConnection::setVerficationCode(QString code) +{ + challengeAuthVerificationCode=code; +} -bool SshMasterConnection::userAuthWithPass() + +bool SshMasterConnection::userChallengeAuth() { - int rc = ssh_userauth_password ( my_ssh_session, NULL, pass.toAscii() ); - if ( rc != SSH_AUTH_SUCCESS ) + int rez=ssh_userauth_kbdint(my_ssh_session, NULL, NULL); + int prompts; + + switch( rez) { + case SSH_AUTH_INFO: + prompts=ssh_userauth_kbdint_getnprompts(my_ssh_session); +#ifdef DEBUG + x2goDebug<<"Have prompts: "<<prompts<<endl; +#endif + if(prompts) + { + const char *prompt= ssh_userauth_kbdint_getprompt(my_ssh_session,0,NULL); +#ifdef DEBUG + x2goDebug<<"Prompt[0]: |"<<prompt<<"|"<<endl; +#endif + QString pr=prompt; + if(pr=="Password: ") + { +#ifdef DEBUG + x2goDebug<<"Password request"<<endl; +#endif + ssh_userauth_kbdint_setanswer(my_ssh_session,0,pass.toAscii()); + return userChallengeAuth(); + } + if(pr=="Verification code: ") + { +#ifdef DEBUG + x2goDebug<<"Verification code request"<<endl; +#endif + + challengeAuthPasswordAccepted=true; + if(challengeAuthVerificationCode == QString::null) + { + keyPhraseReady=false; + emit needPassPhrase(this, true); + for(;;) + { + bool ready=false; + this->usleep(200); + keyPhraseMutex.lock(); + if(keyPhraseReady) + ready=true; + keyPhraseMutex.unlock(); + if(ready) + break; + } + challengeAuthVerificationCode=keyPhrase; + if(challengeAuthVerificationCode==QString::null) + { + authErrors<<tr("Authentication failed"); + return false; + } + } + ssh_userauth_kbdint_setanswer(my_ssh_session,0,challengeAuthVerificationCode.toAscii()); + return userChallengeAuth(); + } + QString err=ssh_get_error ( my_ssh_session ); + authErrors<<err; + + return false; + } + else + { + return userChallengeAuth(); + } + case SSH_AUTH_SUCCESS: +#ifdef DEBUG + x2goDebug<<"Challenge auth ok"<<endl; +#endif + return true; + case SSH_AUTH_DENIED: + if(!challengeAuthPasswordAccepted ) + { + QString err=ssh_get_error ( my_ssh_session ); + authErrors<<err; + return false; + } + else + { + challengeAuthVerificationCode=QString::null; + //try with another verification code + return userChallengeAuth(); + } + default: QString err=ssh_get_error ( my_ssh_session ); authErrors<<err; + + return false; + } + return false; + +} + + +bool SshMasterConnection::userAuthWithPass() +{ + int method = ssh_userauth_list(my_ssh_session, NULL); + + if (method& SSH_AUTH_METHOD_INTERACTIVE) + { #ifdef DEBUG - x2goDebug<<"userAuthWithPass failed:" <<err<<endl; + x2goDebug<<"Challenge authentication"<<endl; #endif - return false; + challengeAuthPasswordAccepted=false; + return userChallengeAuth(); } - return true; + + if (method & SSH_AUTH_METHOD_PASSWORD) + { +#ifdef DEBUG + x2goDebug<<"Password authentication"<<endl; +#endif + int rc = ssh_userauth_password ( my_ssh_session, NULL, pass.toAscii() ); + if ( rc != SSH_AUTH_SUCCESS ) + { + QString err=ssh_get_error ( my_ssh_session ); + authErrors<<err; +#ifdef DEBUG + x2goDebug<<"userAuthWithPass failed:" <<err<<endl; +#endif + return false; + } + return true; + } + + return false; } @@ -826,7 +952,7 @@ bool SshMasterConnection::userAuthAuto() if(!reverseTunnel) { keyPhraseReady=false; - emit needPassPhrase(this); + emit needPassPhrase(this, false); for(;;) { bool ready=false; @@ -901,7 +1027,7 @@ bool SshMasterConnection::userAuthWithKey() if(!reverseTunnel) { keyPhraseReady=false; - emit needPassPhrase(this); + emit needPassPhrase(this, false); for(;;) { bool ready=false; diff --git a/sshmasterconnection.h b/sshmasterconnection.h index dda9772..8a8c6a2 100644 --- a/sshmasterconnection.h +++ b/sshmasterconnection.h @@ -113,12 +113,14 @@ private: bool userAuthWithPass(); bool userAuthAuto(); bool userAuthWithKey(); + bool userChallengeAuth(); bool userAuth(); bool userAuthKrb(); void channelLoop(); void finalize(int arg1); void copy(); int serverAuth(QString& errorMsg); + void setVerficationCode(QString code); #ifdef Q_OS_WIN void parseKnownHosts(); #endif @@ -187,6 +189,9 @@ private: bool sshProxyReady; bool breakLoop; + bool challengeAuthPasswordAccepted; + QString challengeAuthVerificationCode; + signals: void stdErr(SshProcess* caller, QByteArray data); void stdOut(SshProcess* caller, QByteArray data); @@ -204,7 +209,7 @@ signals: void reverseListenOk(SshProcess* creator); void connectionOk( QString host); - void needPassPhrase(SshMasterConnection*); + void needPassPhrase(SshMasterConnection*, bool verificationCode); }; diff --git a/sshprocess.cpp b/sshprocess.cpp index 69a057e..96d73e7 100644 --- a/sshprocess.cpp +++ b/sshprocess.cpp @@ -29,7 +29,7 @@ #endif #undef DEBUG -#define DEBUG +// #define DEBUG #ifdef Q_OS_DARWIN #define KEEPALIVE_OPTION " -o ServerAliveInterval=60 " hooks/post-receive -- x2goclient.git (X2Go Client) This is an automated email from the git hooks/post-receive script. It was generated because a ref change was pushed to the repository containing the project "x2goclient.git" (X2Go Client).