aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorBrian P. Hinz <bphinz@users.sf.net>2017-08-21 18:10:32 -0400
committerBrian P. Hinz <bphinz@users.sf.net>2017-08-21 18:10:32 -0400
commit6a7f9082fd783a1b24387cef0755426e90a0402d (patch)
tree2828f74f4bcb0af4471450722cb9efcb45566ca2
parent324043eba6decc6d1b73c453299f5dab27f41621 (diff)
downloadtigervnc-6a7f9082fd783a1b24387cef0755426e90a0402d.tar.gz
tigervnc-6a7f9082fd783a1b24387cef0755426e90a0402d.zip
Hook up the "Load X.509 Cert/Key" dialogs in winvnc
-rw-r--r--release/tigervnc.iss.in5
-rw-r--r--win/vncconfig/Authentication.h86
2 files changed, 88 insertions, 3 deletions
diff --git a/release/tigervnc.iss.in b/release/tigervnc.iss.in
index a27b971f..b78b4e57 100644
--- a/release/tigervnc.iss.in
+++ b/release/tigervnc.iss.in
@@ -18,6 +18,11 @@ DefaultGroupName=TigerVNC
#endif
LicenseFile=@CMAKE_SOURCE_DIR@\LICENCE.txt
+[Dirs]
+; This directory is necessary to prevent the X509 file chooser from causing
+; an error dialog to appear when GetOpenFileName is called by SYSTEM account.
+Name: "{sys}\config\systemprofile\Desktop"
+
[Files]
#ifdef BUILD_WINVNC
Source: "@CMAKE_CURRENT_BINARY_DIR@\win\winvnc\winvnc4.exe"; DestDir: "{app}"; Flags: ignoreversion restartreplace;
diff --git a/win/vncconfig/Authentication.h b/win/vncconfig/Authentication.h
index 7fa85a2f..2967444a 100644
--- a/win/vncconfig/Authentication.h
+++ b/win/vncconfig/Authentication.h
@@ -18,6 +18,16 @@
#ifndef WINVNCCONF_AUTHENTICATION
#define WINVNCCONF_AUTHENTICATION
+#include <windows.h>
+#include <commctrl.h>
+
+#ifdef HAVE_GNUTLS
+#include <assert.h>
+#include <gnutls/gnutls.h>
+#include <gnutls/x509.h>
+#define CHECK(x) assert((x)>=0)
+#endif
+
#include <vncconfig/PasswordDialog.h>
#include <rfb_win32/Registry.h>
#include <rfb_win32/SecurityPage.h>
@@ -26,6 +36,7 @@
#include <rfb/Security.h>
#include <rfb/SecurityServer.h>
#include <rfb/SSecurityVncAuth.h>
+#include <rfb/SSecurityTLS.h>
#include <rfb/Password.h>
static rfb::BoolParameter queryOnlyIfLoggedOn("QueryOnlyIfLoggedOn",
@@ -53,11 +64,20 @@ namespace rfb {
bool onCommand(int id, int cmd) {
SecurityPage::onCommand(id, cmd);
- setChanged(true);
+ setChanged(true);
if (id == IDC_AUTH_VNC_PASSWD) {
PasswordDialog passwdDlg(regKey, registryInsecure);
passwdDlg.showDialog(handle);
+ } else if (id == IDC_LOAD_CERT) {
+ const TCHAR* title = _T("X509Cert");
+ const TCHAR* filter =
+ _T("X.509 Certificates (*.crt;*.cer;*.pem)\0*.crt;*.cer;*.pem\0All\0*.*\0");
+ showFileChooser(regKey, title, filter, handle);
+ } else if (id == IDC_LOAD_CERTKEY) {
+ const TCHAR* title = _T("X509Key");
+ const TCHAR* filter = _T("X.509 Keys (*.key;*.pem)\0*.key;*.pem\0All\0*.*\0");
+ showFileChooser(regKey, title, filter, handle);
} else if (id == IDC_QUERY_LOGGED_ON) {
enableItem(IDC_QUERY_LOGGED_ON, enableQueryOnlyIfLoggedOn());
}
@@ -76,6 +96,37 @@ namespace rfb {
regKey.setBinary(_T("Password"), 0, 0);
}
+#ifdef HAVE_GNUTLS
+ if (isItemChecked(IDC_ENC_X509)) {
+ gnutls_certificate_credentials_t xcred;
+ CHECK(gnutls_global_init());
+ CHECK(gnutls_certificate_allocate_credentials(&xcred));
+ int ret = gnutls_certificate_set_x509_key_file (xcred,
+ regKey.getString("X509Cert"),
+ regKey.getString("X509Key"),
+ GNUTLS_X509_FMT_PEM);
+ if (ret >= 0) {
+ SSecurityTLS::X509_CertFile.setParam(regKey.getString("X509Cert"));
+ SSecurityTLS::X509_CertFile.setParam(regKey.getString("X509Key"));
+ } else {
+ if (ret == GNUTLS_E_CERTIFICATE_KEY_MISMATCH) {
+ MsgBox(0, _T("Private key does not match certificate.\n")
+ _T("X.509 security types will not be enabled!"),
+ MB_ICONWARNING | MB_OK);
+ } else if (ret == GNUTLS_E_UNSUPPORTED_CERTIFICATE_TYPE) {
+ MsgBox(0, _T("Unsupported certificate type.\n")
+ _T("X.509 security types will not be enabled!"),
+ MB_ICONWARNING | MB_OK);
+ } else {
+ MsgBox(0, _T("Unknown error while importing X.509 certificate or private key.\n")
+ _T("X.509 security types will not be enabled!"),
+ MB_ICONWARNING | MB_OK);
+ }
+ }
+ gnutls_global_deinit();
+ }
+#endif
+
regKey.setString(_T("SecurityTypes"), security->ToString());
regKey.setBool(_T("QueryConnect"), isItemChecked(IDC_QUERY_CONNECT));
regKey.setBool(_T("QueryOnlyIfLoggedOn"), isItemChecked(IDC_QUERY_LOGGED_ON));
@@ -124,8 +175,37 @@ namespace rfb {
private:
inline void modifyAuthMethod(int enc_idc, int auth_idc, bool enable)
{
- setItemChecked(enc_idc, enable);
- setItemChecked(auth_idc, enable);
+ setItemChecked(enc_idc, enable);
+ setItemChecked(auth_idc, enable);
+ }
+ inline bool showFileChooser(const RegKey& rk,
+ const char* title,
+ const char* filter,
+ HWND hwnd)
+ {
+ OPENFILENAME ofn;
+ char filename[MAX_PATH];
+
+ ZeroMemory(&ofn, sizeof(ofn));
+ ZeroMemory(&filename, sizeof(filename));
+ filename[0] = '\0';
+ ofn.lStructSize = sizeof(ofn);
+ ofn.hwndOwner = hwnd;
+ ofn.lpstrFile = filename;
+ ofn.nMaxFile = sizeof(filename);
+ ofn.lpstrFilter = (char*)filter;
+ ofn.nFilterIndex = 1;
+ ofn.lpstrFileTitle = NULL;
+ ofn.nMaxFileTitle = 0;
+ ofn.lpstrTitle = (char*)title;
+ ofn.lpstrInitialDir = NULL;
+ ofn.Flags = OFN_PATHMUSTEXIST | OFN_FILEMUSTEXIST;
+
+ if (GetOpenFileName(&ofn)==TRUE) {
+ regKey.setString(title, filename);
+ return true;
+ }
+ return false;
}
};