From 1b0387a36cf5f22a34b955d9c3f7ff0860e7467c Mon Sep 17 00:00:00 2001 From: Kang Lin Date: Tue, 30 Jul 2024 12:53:52 +0800 Subject: [PATCH] Move getUserPasswd()/showMsgBox() to CConnection Problems with the original code: A process can only establish one connection. After modification, multiple connections can be supported. --- common/rfb/CConnection.h | 25 ++++++++++++++++++- common/rfb/CSecurity.h | 10 -------- common/rfb/CSecurityDH.cxx | 2 +- common/rfb/CSecurityMSLogonII.cxx | 2 +- common/rfb/CSecurityPlain.cxx | 3 +-- common/rfb/CSecurityRSAAES.cxx | 7 +++--- common/rfb/CSecurityRSAAES.h | 2 -- common/rfb/CSecurityTLS.cxx | 22 ++++++++--------- common/rfb/CSecurityTLS.h | 1 - common/rfb/CSecurityVncAuth.cxx | 2 +- common/rfb/SecurityClient.cxx | 10 -------- common/rfb/UserMsgBox.h | 41 ------------------------------- common/rfb/UserPasswdGetter.h | 36 --------------------------- tests/perf/decperf.cxx | 12 +++++++++ tests/perf/encperf.cxx | 11 +++++++++ vncviewer/CConn.cxx | 19 +++++++++++++- vncviewer/CConn.h | 12 +++++++++ vncviewer/UserDialog.cxx | 2 +- vncviewer/UserDialog.h | 13 ++++------ vncviewer/vncviewer.cxx | 12 --------- vncviewer/vncviewer.h | 1 - 21 files changed, 100 insertions(+), 145 deletions(-) delete mode 100644 common/rfb/UserMsgBox.h delete mode 100644 common/rfb/UserPasswdGetter.h diff --git a/common/rfb/CConnection.h b/common/rfb/CConnection.h index b30a997b..3f277d71 100644 --- a/common/rfb/CConnection.h +++ b/common/rfb/CConnection.h @@ -36,6 +36,18 @@ namespace rfb { class CMsgWriter; class CSecurity; + enum MsgBoxFlags{ + M_OK = 0, + M_OKCANCEL = 1, + M_YESNO = 4, + M_ICONERROR = 0x10, + M_ICONQUESTION = 0x20, + M_ICONWARNING = 0x30, + M_ICONINFORMATION = 0x40, + M_DEFBUTTON1 = 0, + M_DEFBUTTON2 = 0x100 + }; + class CConnection : public CMsgHandler { public: @@ -111,7 +123,7 @@ namespace rfb { void serverCutText(const char* str) override; void handleClipboardCaps(uint32_t flags, - const uint32_t* lengths) override; + const uint32_t* lengths) override; void handleClipboardRequest(uint32_t flags) override; void handleClipboardPeek() override; void handleClipboardNotify(uint32_t flags) override; @@ -121,6 +133,17 @@ namespace rfb { // Methods to be overridden in a derived class + // getUserPasswd() gets the username and password. This might + // involve a dialog, getpass(), etc. The user buffer pointer can be + // null, in which case no user name will be retrieved. + virtual void getUserPasswd(bool secure, std::string* user, + std::string* password) = 0; + + // showMsgBox() displays a message box with the specified style and + // contents. The return value is true if the user clicked OK/Yes. + virtual bool showMsgBox(MsgBoxFlags flags, const char *title, + const char *text) = 0; + // authSuccess() is called when authentication has succeeded. virtual void authSuccess(); diff --git a/common/rfb/CSecurity.h b/common/rfb/CSecurity.h index 549db794..be74a1fd 100644 --- a/common/rfb/CSecurity.h +++ b/common/rfb/CSecurity.h @@ -38,9 +38,6 @@ #ifndef __RFB_CSECURITY_H__ #define __RFB_CSECURITY_H__ -#include -#include - namespace rfb { class CConnection; class CSecurity { @@ -51,13 +48,6 @@ namespace rfb { virtual int getType() const = 0; virtual bool isSecure() const { return false; } - /* - * Use variable directly instead of dumb get/set methods. - * It MUST be set by viewer. - */ - static UserPasswdGetter *upg; - static UserMsgBox *msg; - protected: CConnection* cc; }; diff --git a/common/rfb/CSecurityDH.cxx b/common/rfb/CSecurityDH.cxx index f3b085c7..6eafbd9c 100644 --- a/common/rfb/CSecurityDH.cxx +++ b/common/rfb/CSecurityDH.cxx @@ -108,7 +108,7 @@ void CSecurityDH::writeCredentials() std::string password; rdr::RandomStream rs; - (CSecurity::upg)->getUserPasswd(isSecure(), &username, &password); + cc->getUserPasswd(isSecure(), &username, &password); std::vector bBytes(keyLength); if (!rs.hasData(keyLength)) diff --git a/common/rfb/CSecurityMSLogonII.cxx b/common/rfb/CSecurityMSLogonII.cxx index dc817518..f8ff36c1 100644 --- a/common/rfb/CSecurityMSLogonII.cxx +++ b/common/rfb/CSecurityMSLogonII.cxx @@ -97,7 +97,7 @@ void CSecurityMSLogonII::writeCredentials() std::string password; rdr::RandomStream rs; - (CSecurity::upg)->getUserPasswd(isSecure(), &username, &password); + cc->getUserPasswd(isSecure(), &username, &password); std::vector bBytes(8); if (!rs.hasData(8)) diff --git a/common/rfb/CSecurityPlain.cxx b/common/rfb/CSecurityPlain.cxx index d9599f9c..1cbf62e1 100644 --- a/common/rfb/CSecurityPlain.cxx +++ b/common/rfb/CSecurityPlain.cxx @@ -23,7 +23,6 @@ #include #include -#include #include @@ -36,7 +35,7 @@ bool CSecurityPlain::processMsg() std::string username; std::string password; - (CSecurity::upg)->getUserPasswd(cc->isSecure(), &username, &password); + cc->getUserPasswd(cc->isSecure(), &username, &password); // Return the response to the server os->writeU32(username.size()); diff --git a/common/rfb/CSecurityRSAAES.cxx b/common/rfb/CSecurityRSAAES.cxx index a78739ac..cc031fe3 100644 --- a/common/rfb/CSecurityRSAAES.cxx +++ b/common/rfb/CSecurityRSAAES.cxx @@ -38,7 +38,6 @@ #include #include #include -#include #include #include #include @@ -215,7 +214,7 @@ void CSecurityRSAAES::verifyServer() "Fingerprint: %02x-%02x-%02x-%02x-%02x-%02x-%02x-%02x\n" "Please verify that the information is correct and press \"Yes\". " "Otherwise press \"No\"", f[0], f[1], f[2], f[3], f[4], f[5], f[6], f[7]); - if (!msg->showMsgBox(UserMsgBox::M_YESNO, title, text.c_str())) + if (!cc->showMsgBox(MsgBoxFlags::M_YESNO, title, text.c_str())) throw Exception("server key mismatch"); } @@ -438,9 +437,9 @@ void CSecurityRSAAES::writeCredentials() std::string password; if (subtype == secTypeRA2UserPass) - (CSecurity::upg)->getUserPasswd(isSecure(), &username, &password); + cc->getUserPasswd(isSecure(), &username, &password); else - (CSecurity::upg)->getUserPasswd(isSecure(), nullptr, &password); + cc->getUserPasswd(isSecure(), nullptr, &password); if (subtype == secTypeRA2UserPass) { if (username.size() > 255) diff --git a/common/rfb/CSecurityRSAAES.h b/common/rfb/CSecurityRSAAES.h index 29bfd575..35b0513b 100644 --- a/common/rfb/CSecurityRSAAES.h +++ b/common/rfb/CSecurityRSAAES.h @@ -27,13 +27,11 @@ #include #include #include -#include #include #include #include namespace rfb { - class UserMsgBox; class CSecurityRSAAES : public CSecurity { public: CSecurityRSAAES(CConnection* cc, uint32_t secType, diff --git a/common/rfb/CSecurityTLS.cxx b/common/rfb/CSecurityTLS.cxx index 2a7a1179..eff215ab 100644 --- a/common/rfb/CSecurityTLS.cxx +++ b/common/rfb/CSecurityTLS.cxx @@ -38,7 +38,6 @@ #include #include #include -#include #include #include #include @@ -442,7 +441,7 @@ void CSecurityTLS::checkSession() "Do you want to make an exception for this " "server?", info.data); - if (!msg->showMsgBox(UserMsgBox::M_YESNO, + if (!cc->showMsgBox(MsgBoxFlags::M_YESNO, "Unknown certificate issuer", text.c_str())) throw AuthCancelledException(); @@ -462,8 +461,7 @@ void CSecurityTLS::checkSession() "\n" "Do you want to make an exception for this " "server?", info.data); - - if (!msg->showMsgBox(UserMsgBox::M_YESNO, + if (!cc->showMsgBox(MsgBoxFlags::M_YESNO, "Certificate is not yet valid", text.c_str())) throw AuthCancelledException(); @@ -482,7 +480,7 @@ void CSecurityTLS::checkSession() "Do you want to make an exception for this " "server?", info.data); - if (!msg->showMsgBox(UserMsgBox::M_YESNO, + if (!cc->showMsgBox(MsgBoxFlags::M_YESNO, "Expired certificate", text.c_str())) throw AuthCancelledException(); @@ -501,7 +499,7 @@ void CSecurityTLS::checkSession() "Do you want to make an exception for this " "server?", info.data); - if (!msg->showMsgBox(UserMsgBox::M_YESNO, + if (!cc->showMsgBox(MsgBoxFlags::M_YESNO, "Insecure certificate algorithm", text.c_str())) throw AuthCancelledException(); @@ -526,7 +524,7 @@ void CSecurityTLS::checkSession() "Do you want to make an exception for this " "server?", client->getServerName(), info.data); - if (!msg->showMsgBox(UserMsgBox::M_YESNO, + if (!cc->showMsgBox(MsgBoxFlags::M_YESNO, "Certificate hostname mismatch", text.c_str())) throw AuthCancelledException(); @@ -552,7 +550,7 @@ void CSecurityTLS::checkSession() "Do you want to make an exception for this " "server?", info.data); - if (!msg->showMsgBox(UserMsgBox::M_YESNO, + if (!cc->showMsgBox(MsgBoxFlags::M_YESNO, "Unexpected server certificate", text.c_str())) throw AuthCancelledException(); @@ -575,7 +573,7 @@ void CSecurityTLS::checkSession() "Do you want to make an exception for this " "server?", info.data); - if (!msg->showMsgBox(UserMsgBox::M_YESNO, + if (!cc->showMsgBox(MsgBoxFlags::M_YESNO, "Unexpected server certificate", text.c_str())) throw AuthCancelledException(); @@ -596,7 +594,7 @@ void CSecurityTLS::checkSession() "Do you want to make an exception for this " "server?", info.data); - if (!msg->showMsgBox(UserMsgBox::M_YESNO, + if (!cc->showMsgBox(MsgBoxFlags::M_YESNO, "Unexpected server certificate", text.c_str())) throw AuthCancelledException(); @@ -617,7 +615,7 @@ void CSecurityTLS::checkSession() "Do you want to make an exception for this " "server?", info.data); - if (!msg->showMsgBox(UserMsgBox::M_YESNO, + if (!cc->showMsgBox(MsgBoxFlags::M_YESNO, "Unexpected server certificate", text.c_str())) throw AuthCancelledException(); @@ -644,7 +642,7 @@ void CSecurityTLS::checkSession() "Do you want to make an exception for this " "server?", client->getServerName(), info.data); - if (!msg->showMsgBox(UserMsgBox::M_YESNO, + if (!cc->showMsgBox(MsgBoxFlags::M_YESNO, "Unexpected server certificate", text.c_str())) throw AuthCancelledException(); diff --git a/common/rfb/CSecurityTLS.h b/common/rfb/CSecurityTLS.h index 8688b742..848ef9bb 100644 --- a/common/rfb/CSecurityTLS.h +++ b/common/rfb/CSecurityTLS.h @@ -28,7 +28,6 @@ #include #include -#include #include #include #include diff --git a/common/rfb/CSecurityVncAuth.cxx b/common/rfb/CSecurityVncAuth.cxx index e5f842ba..2fd83fe9 100644 --- a/common/rfb/CSecurityVncAuth.cxx +++ b/common/rfb/CSecurityVncAuth.cxx @@ -54,7 +54,7 @@ bool CSecurityVncAuth::processMsg() uint8_t challenge[vncAuthChallengeSize]; is->readBytes(challenge, vncAuthChallengeSize); std::string passwd; - (CSecurity::upg)->getUserPasswd(cc->isSecure(), nullptr, &passwd); + cc->getUserPasswd(cc->isSecure(), nullptr, &passwd); // Calculate the correct response uint8_t key[8]; diff --git a/common/rfb/SecurityClient.cxx b/common/rfb/SecurityClient.cxx index d1507eb5..9cd3b904 100644 --- a/common/rfb/SecurityClient.cxx +++ b/common/rfb/SecurityClient.cxx @@ -40,11 +40,6 @@ using namespace rfb; -UserPasswdGetter *CSecurity::upg = nullptr; -#if defined(HAVE_GNUTLS) || defined(HAVE_NETTLE) -UserMsgBox *CSecurity::msg = nullptr; -#endif - StringParameter SecurityClient::secTypes ("SecurityTypes", "Specify which security scheme to use (None, VncAuth, Plain" @@ -66,11 +61,6 @@ ConfViewer); CSecurity* SecurityClient::GetCSecurity(CConnection* cc, uint32_t secType) { - assert (CSecurity::upg != nullptr); /* (upg == nullptr) means bug in the viewer */ -#if defined(HAVE_GNUTLS) || defined(HAVE_NETTLE) - assert (CSecurity::msg != nullptr); -#endif - if (!IsSupported(secType)) goto bail; diff --git a/common/rfb/UserMsgBox.h b/common/rfb/UserMsgBox.h deleted file mode 100644 index 392950d1..00000000 --- a/common/rfb/UserMsgBox.h +++ /dev/null @@ -1,41 +0,0 @@ -/* Copyright (C) 2002-2005 RealVNC Ltd. All Rights Reserved. - * Copyright (C) 2010 TigerVNC Team - * - * This is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation; either version 2 of the License, or - * (at your option) any later version. - * - * This software 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 General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this software; if not, write to the Free Software - * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, - * USA. - */ -#ifndef __RFB_USERMSGBOX_H__ -#define __RFB_USERMSGBOX_H__ - -namespace rfb { - class UserMsgBox { - public: - enum MsgBoxFlags{ - M_OK = 0, - M_OKCANCEL = 1, - M_YESNO = 4, - M_ICONERROR = 0x10, - M_ICONQUESTION = 0x20, - M_ICONWARNING = 0x30, - M_ICONINFORMATION = 0x40, - M_DEFBUTTON1 = 0, - M_DEFBUTTON2 = 0x100 - }; - /* TODO Implement as function with variable arguments */ - virtual bool showMsgBox(int flags,const char* title, const char* text)=0; - }; -} - -#endif diff --git a/common/rfb/UserPasswdGetter.h b/common/rfb/UserPasswdGetter.h deleted file mode 100644 index db7df396..00000000 --- a/common/rfb/UserPasswdGetter.h +++ /dev/null @@ -1,36 +0,0 @@ -/* Copyright (C) 2002-2005 RealVNC Ltd. All Rights Reserved. - * - * This is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation; either version 2 of the License, or - * (at your option) any later version. - * - * This software 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 General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this software; if not, write to the Free Software - * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, - * USA. - */ -#ifndef __RFB_USERPASSWDGETTER_H__ -#define __RFB_USERPASSWDGETTER_H__ - -#include - -namespace rfb { - class UserPasswdGetter { - public: - // getUserPasswd gets the username and password. This might involve a - // dialog, getpass(), etc. The user buffer pointer can be null, in which - // case no user name will be retrieved. - virtual void getUserPasswd(bool secure, std::string* user, - std::string* password)=0; - - virtual ~UserPasswdGetter() {} - }; -} - -#endif diff --git a/tests/perf/decperf.cxx b/tests/perf/decperf.cxx index ef53a686..fb2390be 100644 --- a/tests/perf/decperf.cxx +++ b/tests/perf/decperf.cxx @@ -75,6 +75,8 @@ public: void setColourMapEntries(int, int, uint16_t*) override; void bell() override; void serverCutText(const char*) override; + virtual void getUserPasswd(bool secure, std::string *user, std::string *password) override; + virtual bool showMsgBox(rfb::MsgBoxFlags flags, const char *title, const char *text) override; public: double cpuTime; @@ -82,6 +84,7 @@ public: protected: rdr::FileInStream *in; DummyOutStream *out; + }; DummyOutStream::DummyOutStream() @@ -174,6 +177,15 @@ void CConn::serverCutText(const char*) { } +void CConn::getUserPasswd(bool, std::string *, std::string *) +{ +} + +bool CConn::showMsgBox(rfb::MsgBoxFlags, const char *, const char *) +{ + return true; +} + struct stats { double decodeTime; diff --git a/tests/perf/encperf.cxx b/tests/perf/encperf.cxx index ac8e9d47..c6e2d3b7 100644 --- a/tests/perf/encperf.cxx +++ b/tests/perf/encperf.cxx @@ -108,6 +108,8 @@ public: void setColourMapEntries(int, int, uint16_t*) override; void bell() override; void serverCutText(const char*) override; + virtual void getUserPasswd(bool secure, std::string *user, std::string *password) override; + virtual bool showMsgBox(rfb::MsgBoxFlags flags, const char *title, const char *text) override; public: double decodeTime; @@ -279,6 +281,15 @@ void CConn::serverCutText(const char*) { } +void CConn::getUserPasswd(bool, std::string *, std::string *) +{ +} + +bool CConn::showMsgBox(rfb::MsgBoxFlags, const char *, const char *) +{ + return true; +} + Manager::Manager(class rfb::SConnection *conn_) : EncodeManager(conn_) { diff --git a/vncviewer/CConn.cxx b/vncviewer/CConn.cxx index e1c75962..81bea534 100644 --- a/vncviewer/CConn.cxx +++ b/vncviewer/CConn.cxx @@ -275,7 +275,7 @@ void CConn::socketEvent(FL_SOCKET fd, void *data) vlog.info("%s", e.str()); disconnect(); } catch (rfb::AuthFailureException& e) { - reset_password_data(); + cc->resetPassword(); vlog.error(_("Authentication failed: %s"), e.str()); abort_connection(_("Failed to authenticate with the server. Reason " "given by the server:\n\n%s"), e.str()); @@ -292,8 +292,25 @@ void CConn::socketEvent(FL_SOCKET fd, void *data) recursing = false; } +void CConn::resetPassword() +{ + dlg.resetPassword(); +} + ////////////////////// CConnection callback methods ////////////////////// +bool CConn::showMsgBox(MsgBoxFlags flags, const char *title, + const char *text) +{ + return dlg.showMsgBox(flags, title, text); +} + +void CConn::getUserPasswd(bool secure, std::string *user, + std::string *password) +{ + dlg.getUserPasswd(secure, user, password); +} + // initDone() is called when the serverInit message has been received. At // this point we create the desktop window and display it. We also tell the // server the pixel format and encodings to use and request the first update. diff --git a/vncviewer/CConn.h b/vncviewer/CConn.h index fcaf49f6..1e71be94 100644 --- a/vncviewer/CConn.h +++ b/vncviewer/CConn.h @@ -24,6 +24,7 @@ #include #include +#include "UserDialog.h" namespace network { class Socket; } @@ -44,7 +45,16 @@ public: // Callback when socket is ready (or broken) static void socketEvent(FL_SOCKET fd, void *data); + // Forget any saved password + void resetPassword(); + // CConnection callback methods + + bool showMsgBox(rfb::MsgBoxFlags flags, const char *title, + const char *text) override; + void getUserPasswd(bool secure, std::string *user, + std::string *password) override; + void initDone() override; void setDesktopSize(int w, int h) override; @@ -105,6 +115,8 @@ private: struct timeval updateStartTime; size_t updateStartPos; unsigned long long bpsEstimate; + + UserDialog dlg; }; #endif diff --git a/vncviewer/UserDialog.cxx b/vncviewer/UserDialog.cxx index a3767857..901503c6 100644 --- a/vncviewer/UserDialog.cxx +++ b/vncviewer/UserDialog.cxx @@ -248,7 +248,7 @@ void UserDialog::getUserPasswd(bool secure_, std::string* user, throw rfb::AuthCancelledException(); } -bool UserDialog::showMsgBox(int flags, const char* title, const char* text) +bool UserDialog::showMsgBox(MsgBoxFlags flags, const char* title, const char* text) { char buffer[1024]; diff --git a/vncviewer/UserDialog.h b/vncviewer/UserDialog.h index aa50127e..c16923c1 100644 --- a/vncviewer/UserDialog.h +++ b/vncviewer/UserDialog.h @@ -19,11 +19,9 @@ #ifndef __USERDIALOG_H__ #define __USERDIALOG_H__ -#include -#include +#include -class UserDialog : public rfb::UserPasswdGetter, - public rfb::UserMsgBox +class UserDialog { public: UserDialog(); @@ -32,15 +30,14 @@ public: // UserPasswdGetter callbacks void getUserPasswd(bool secure, std::string* user, - std::string* password) override; + std::string* password); // UserMsgBox callbacks - - bool showMsgBox(int flags, const char* title, const char* text) override; + bool showMsgBox(rfb::MsgBoxFlags flags, const char* title, const char* text); void resetPassword(); - private: +private: std::string savedUsername; std::string savedPassword; }; diff --git a/vncviewer/vncviewer.cxx b/vncviewer/vncviewer.cxx index 24099e12..ab95c0c6 100644 --- a/vncviewer/vncviewer.cxx +++ b/vncviewer/vncviewer.cxx @@ -93,8 +93,6 @@ static bool exitMainloop = false; static char *exitError = nullptr; static bool fatalError = false; -static UserDialog dlg; - static const char *about_text() { static char buffer[1024]; @@ -171,11 +169,6 @@ bool should_disconnect() return exitMainloop; } -void reset_password_data() -{ - dlg.resetPassword(); -} - void about_vncviewer() { fl_message_title(_("About TigerVNC Viewer")); @@ -776,11 +769,6 @@ int main(int argc, char** argv) create_base_dirs(); - CSecurity::upg = &dlg; -#if defined(HAVE_GNUTLS) || defined(HAVE_NETTLE) - CSecurity::msg = &dlg; -#endif - Socket *sock = nullptr; #ifndef WIN32 diff --git a/vncviewer/vncviewer.h b/vncviewer/vncviewer.h index c864805c..f39a5776 100644 --- a/vncviewer/vncviewer.h +++ b/vncviewer/vncviewer.h @@ -33,7 +33,6 @@ void abort_connection_with_unexpected_error(const rdr::Exception &); void disconnect(); bool should_disconnect(); -void reset_password_data(); void about_vncviewer(); -- 2.39.5