From patchwork Tue Oct 16 10:26:23 2018 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 8bit Subject: [Openvpn-devel,1/5] Set output name to libopenvpnmsica.dll in MSVC builds too X-Patchwork-Submitter: Simon Rozman X-Patchwork-Id: 554 Message-Id: <20181016102627.18676-1-simon@rozman.si> To: openvpn-devel@lists.sourceforge.net Date: Tue, 16 Oct 2018 12:26:23 +0200 From: Simon Rozman List-Id: On MinGW builds, the Libtool produces libopenvpnmsica.dll. The MSVC properties were updated to match this. Acked-by: Jon Kunkee --- src/openvpnmsica/openvpnmsica.props | 4 +++- src/openvpnmsica/openvpnmsica_resources.rc | 2 +- 2 files changed, 4 insertions(+), 2 deletions(-) diff --git a/src/openvpnmsica/openvpnmsica.props b/src/openvpnmsica/openvpnmsica.props index 0e31bc4f..fa408296 100644 --- a/src/openvpnmsica/openvpnmsica.props +++ b/src/openvpnmsica/openvpnmsica.props @@ -2,7 +2,9 @@ - + + lib$(ProjectName) + ..\compat;$(TAP_WINDOWS_HOME)/include;%(AdditionalIncludeDirectories) diff --git a/src/openvpnmsica/openvpnmsica_resources.rc b/src/openvpnmsica/openvpnmsica_resources.rc index ce60b4a1..9e8069f4 100644 --- a/src/openvpnmsica/openvpnmsica_resources.rc +++ b/src/openvpnmsica/openvpnmsica_resources.rc @@ -50,7 +50,7 @@ BEGIN VALUE "FileVersion", PACKAGE_VERSION ".0" VALUE "InternalName", "OpenVPN" VALUE "LegalCopyright", "Copyright © The OpenVPN Project" - VALUE "OriginalFilename", "openvpnmsica.dll" + VALUE "OriginalFilename", "libopenvpnmsica.dll" VALUE "ProductName", "OpenVPN" VALUE "ProductVersion", PACKAGE_VERSION ".0" END From patchwork Tue Oct 16 10:26:24 2018 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit Subject: [Openvpn-devel,2/5] Prevent __stdcall name mangling of MSVC X-Patchwork-Submitter: Simon Rozman X-Patchwork-Id: 557 Message-Id: <20181016102627.18676-2-simon@rozman.si> To: openvpn-devel@lists.sourceforge.net Date: Tue, 16 Oct 2018 12:26:24 +0200 From: Simon Rozman List-Id: Using `extern "C" __declspec(dllexport) __stdcall`, Win32 MSVC compiler exports the functions are as `_name@N`. Exporting functions using `/EXPORT` linker flag allows us to specify exact function name. Note: The 64-bit MSVC compiler does not exhibit `__stdcall` name- mangling. Acked-by: Jon Kunkee --- src/openvpnmsica/openvpnmsica.c | 12 ++++++++++++ src/openvpnmsica/openvpnmsica.h | 14 +++++++++++--- 2 files changed, 23 insertions(+), 3 deletions(-) diff --git a/src/openvpnmsica/openvpnmsica.c b/src/openvpnmsica/openvpnmsica.c index 82333991..3b90ce05 100644 --- a/src/openvpnmsica/openvpnmsica.c +++ b/src/openvpnmsica/openvpnmsica.c @@ -145,6 +145,10 @@ openvpnmsica_setup_sequence_filename( UINT __stdcall FindTAPInterfaces(_In_ MSIHANDLE hInstall) { +#ifdef _MSC_VER +#pragma comment(linker, DLLEXP_EXPORT) +#endif + #ifdef _DEBUG MessageBox(NULL, TEXT("Attach debugger!"), TEXT(__FUNCTION__) TEXT(" v") TEXT(PACKAGE_VERSION), MB_OK); #endif @@ -247,6 +251,10 @@ cleanup_CoInitialize: UINT __stdcall EvaluateTAPInterfaces(_In_ MSIHANDLE hInstall) { +#ifdef _MSC_VER +#pragma comment(linker, DLLEXP_EXPORT) +#endif + #ifdef _DEBUG MessageBox(NULL, TEXT("Attach debugger!"), TEXT(__FUNCTION__) TEXT(" v") TEXT(PACKAGE_VERSION), MB_OK); #endif @@ -505,6 +513,10 @@ cleanup_exec_seq: UINT __stdcall ProcessDeferredAction(_In_ MSIHANDLE hInstall) { +#ifdef _MSC_VER +#pragma comment(linker, DLLEXP_EXPORT) +#endif + #ifdef _DEBUG MessageBox(NULL, TEXT("Attach debugger!"), TEXT(__FUNCTION__) TEXT(" v") TEXT(PACKAGE_VERSION), MB_OK); #endif diff --git a/src/openvpnmsica/openvpnmsica.h b/src/openvpnmsica/openvpnmsica.h index 3a64fbaa..bb8e28ec 100644 --- a/src/openvpnmsica/openvpnmsica.h +++ b/src/openvpnmsica/openvpnmsica.h @@ -55,6 +55,14 @@ extern DWORD openvpnmsica_tlsidx_session; extern "C" { #endif +#ifdef __GNUC__ +#define DLLEXP_DECL __declspec(dllexport) +#else +#define DLLEXP_DECL +#define DLLEXP_EXPORT "/EXPORT:"__FUNCTION__"="__FUNCDNAME__ +#endif + + /** * Find existing TAP interfaces and set TAPINTERFACES property with semicolon delimited list * of installed TAP interface GUIDs. @@ -64,7 +72,7 @@ extern "C" { * @return ERROR_SUCCESS on success; An error code otherwise * See: https://msdn.microsoft.com/en-us/library/windows/desktop/aa368072.aspx */ -__declspec(dllexport) UINT __stdcall +DLLEXP_DECL UINT __stdcall FindTAPInterfaces(_In_ MSIHANDLE hInstall); @@ -77,7 +85,7 @@ FindTAPInterfaces(_In_ MSIHANDLE hInstall); * @return ERROR_SUCCESS on success; An error code otherwise * See: https://msdn.microsoft.com/en-us/library/windows/desktop/aa368072.aspx */ -__declspec(dllexport) UINT __stdcall +DLLEXP_DECL UINT __stdcall EvaluateTAPInterfaces(_In_ MSIHANDLE hInstall); @@ -89,7 +97,7 @@ EvaluateTAPInterfaces(_In_ MSIHANDLE hInstall); * @return ERROR_SUCCESS on success; An error code otherwise * See: https://msdn.microsoft.com/en-us/library/windows/desktop/aa368072.aspx */ -__declspec(dllexport) UINT __stdcall +DLLEXP_DECL UINT __stdcall ProcessDeferredAction(_In_ MSIHANDLE hInstall); #ifdef __cplusplus From patchwork Tue Oct 16 10:26:25 2018 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit Subject: [Openvpn-devel,3/5] Define _WIN32_WINNT=_WIN32_WINNT_VISTA in MSVC X-Patchwork-Submitter: Simon Rozman X-Patchwork-Id: 558 Message-Id: <20181016102627.18676-3-simon@rozman.si> To: openvpn-devel@lists.sourceforge.net Date: Tue, 16 Oct 2018 12:26:25 +0200 From: Simon Rozman List-Id: This makes MSVC and MinGW build environments more alike. Acked-by: Jon Kunkee --- src/openvpnmsica/openvpnmsica.props | 1 + src/tapctl/tapctl.props | 2 +- 2 files changed, 2 insertions(+), 1 deletion(-) diff --git a/src/openvpnmsica/openvpnmsica.props b/src/openvpnmsica/openvpnmsica.props index fa408296..074635d0 100644 --- a/src/openvpnmsica/openvpnmsica.props +++ b/src/openvpnmsica/openvpnmsica.props @@ -8,6 +8,7 @@ ..\compat;$(TAP_WINDOWS_HOME)/include;%(AdditionalIncludeDirectories) + _WIN32_WINNT=_WIN32_WINNT_VISTA;%(PreprocessorDefinitions) Windows diff --git a/src/tapctl/tapctl.props b/src/tapctl/tapctl.props index 152954ed..0257b9ff 100644 --- a/src/tapctl/tapctl.props +++ b/src/tapctl/tapctl.props @@ -7,7 +7,7 @@ - _CONSOLE;%(PreprocessorDefinitions) + _CONSOLE;_WIN32_WINNT=_WIN32_WINNT_VISTA;%(PreprocessorDefinitions) ..\compat;$(TAP_WINDOWS_HOME)/include;%(AdditionalIncludeDirectories) From patchwork Tue Oct 16 10:26:26 2018 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit Subject: [Openvpn-devel,4/5] Add MSI custom action for reliable Windows 10 detection X-Patchwork-Submitter: Simon Rozman X-Patchwork-Id: 556 Message-Id: <20181016102627.18676-4-simon@rozman.si> To: openvpn-devel@lists.sourceforge.net Date: Tue, 16 Oct 2018 12:26:26 +0200 From: Simon Rozman List-Id: This patch introduces a `FindSystemInfo()` MSI custom action to reliably detect Windows 10. The MSI built-in properties for Windows version detection depend on bootstrapper's manifest. We could provide our own Windows 10 compatible EXE bootstrapper, but that would cover the Windows 10 detection in the `InstallUISequence` only. The `InstallExecuteSequence` is launched by msiexec.exe which we cannot tamper with would still report `VersionNT` as Windows 8 (603). Acked-by: Jon Kunkee --- src/openvpnmsica/Makefile.am | 2 +- src/openvpnmsica/openvpnmsica.c | 124 ++++++++++++++++++++++++++++++-- src/openvpnmsica/openvpnmsica.h | 15 ++++ 3 files changed, 136 insertions(+), 5 deletions(-) diff --git a/src/openvpnmsica/Makefile.am b/src/openvpnmsica/Makefile.am index d46170b4..ecca74bc 100644 --- a/src/openvpnmsica/Makefile.am +++ b/src/openvpnmsica/Makefile.am @@ -41,7 +41,7 @@ libopenvpnmsica_la_CFLAGS = \ -municode -D_UNICODE \ -UNTDDI_VERSION -U_WIN32_WINNT \ -D_WIN32_WINNT=_WIN32_WINNT_VISTA -libopenvpnmsica_la_LDFLAGS = -ladvapi32 -lole32 -lmsi -lsetupapi -lshlwapi -no-undefined -avoid-version +libopenvpnmsica_la_LDFLAGS = -ladvapi32 -lole32 -lmsi -lsetupapi -lshlwapi -lversion -no-undefined -avoid-version endif libopenvpnmsica_la_SOURCES = \ diff --git a/src/openvpnmsica/openvpnmsica.c b/src/openvpnmsica/openvpnmsica.c index 3b90ce05..d1642d6a 100644 --- a/src/openvpnmsica/openvpnmsica.c +++ b/src/openvpnmsica/openvpnmsica.c @@ -36,13 +36,15 @@ #include #include #include -#ifdef _MSC_VER -#pragma comment(lib, "shlwapi.lib") -#endif #include #include #include +#ifdef _MSC_VER +#pragma comment(lib, "shlwapi.lib") +#pragma comment(lib, "version.lib") +#endif + /** * Local constants @@ -119,7 +121,7 @@ openvpnmsica_setup_sequence_filename( { size_t len_action_name_z = _tcslen(openvpnmsica_cleanup_action_seqs[i].szName) + 1; TCHAR *szPropertyEx = (TCHAR*)malloc((len_property_name + len_action_name_z) * sizeof(TCHAR)); - memcpy(szPropertyEx , szProperty , len_property_name * sizeof(TCHAR)); + memcpy(szPropertyEx , szProperty , len_property_name * sizeof(TCHAR)); memcpy(szPropertyEx + len_property_name, openvpnmsica_cleanup_action_seqs[i].szName, len_action_name_z * sizeof(TCHAR)); _stprintf_s( szFilenameEx, _countof(szFilenameEx), @@ -142,6 +144,120 @@ openvpnmsica_setup_sequence_filename( } +UINT __stdcall +FindSystemInfo(_In_ MSIHANDLE hInstall) +{ +#ifdef _MSC_VER +#pragma comment(linker, DLLEXP_EXPORT) +#endif + +#ifdef _DEBUG + MessageBox(NULL, TEXT("Attach debugger!"), TEXT(__FUNCTION__) TEXT(" v") TEXT(PACKAGE_VERSION), MB_OK); +#endif + + UINT uiResult; + BOOL bIsCoInitialized = SUCCEEDED(CoInitialize(NULL)); + + /* Set MSI session handle in TLS. */ + struct openvpnmsica_tls_data *s = (struct openvpnmsica_tls_data *)TlsGetValue(openvpnmsica_tlsidx_session); + s->hInstall = hInstall; + + // Get Windows version. + OSVERSIONINFOEX ver_info = { .dwOSVersionInfoSize = sizeof(OSVERSIONINFOEX) }; + if (!GetVersionEx((LPOSVERSIONINFO)&ver_info)) { + uiResult = GetLastError(); + msg(M_NONFATAL | M_ERRNO, "%s: GetVersionEx() failed", __FUNCTION__); + goto cleanup_CoInitialize; + } + + // The Windows version is usually spoofed, check using RtlGetVersion(). + TCHAR szDllPath[0x1000]; + ExpandEnvironmentStrings(TEXT("%SystemRoot%\\System32\\ntdll.dll"), szDllPath, +#ifdef UNICODE + _countof(szDllPath) +#else + _countof(szDllPath) - 1 +#endif + ); + HMODULE hNtDllModule = LoadLibrary(szDllPath); + if (hNtDllModule) + { + typedef NTSTATUS (WINAPI* fnRtlGetVersion)(PRTL_OSVERSIONINFOW); + fnRtlGetVersion RtlGetVersion = (fnRtlGetVersion)GetProcAddress(hNtDllModule, "RtlGetVersion"); + if (RtlGetVersion) + { + RTL_OSVERSIONINFOW rtl_ver_info = { .dwOSVersionInfoSize = sizeof(RTL_OSVERSIONINFOW) }; + if (RtlGetVersion(&rtl_ver_info) == 0) + if ( + rtl_ver_info.dwMajorVersion > ver_info.dwMajorVersion || + rtl_ver_info.dwMajorVersion == ver_info.dwMajorVersion && rtl_ver_info.dwMinorVersion > ver_info.dwMinorVersion || + rtl_ver_info.dwMajorVersion == ver_info.dwMajorVersion && rtl_ver_info.dwMinorVersion == ver_info.dwMinorVersion && rtl_ver_info.dwBuildNumber > ver_info.dwBuildNumber) + { + // We got RtlGetVersion() and it reported newer version than GetVersionEx(). + ver_info.dwMajorVersion = rtl_ver_info.dwMajorVersion; + ver_info.dwMinorVersion = rtl_ver_info.dwMinorVersion; + ver_info.dwBuildNumber = rtl_ver_info.dwBuildNumber; + ver_info.dwPlatformId = rtl_ver_info.dwPlatformId; + } + } + + FreeLibrary(hNtDllModule); + } + + // We don't trust RtlGetVersion() either. Check the version resource of kernel32.dll. + ExpandEnvironmentStrings(TEXT("%SystemRoot%\\System32\\kernel32.dll"), szDllPath, +#ifdef UNICODE + _countof(szDllPath) +#else + _countof(szDllPath)-1 +#endif + ); + + DWORD dwHandle; + DWORD dwVerInfoSize = GetFileVersionInfoSize(szDllPath, &dwHandle); + if (dwVerInfoSize) + { + LPVOID pVersionInfo = malloc(dwVerInfoSize); + if (pVersionInfo) + { + // Read version info. + if (GetFileVersionInfo(szDllPath, dwHandle, dwVerInfoSize, pVersionInfo)) + { + // Get the value for the root block. + UINT uiSize = 0; + VS_FIXEDFILEINFO *pVSFixedFileInfo = NULL; + if (VerQueryValue(pVersionInfo, TEXT("\\"), &pVSFixedFileInfo, &uiSize) && uiSize && pVSFixedFileInfo) + if (HIWORD(pVSFixedFileInfo->dwProductVersionMS) > ver_info.dwMajorVersion || + HIWORD(pVSFixedFileInfo->dwProductVersionMS) == ver_info.dwMajorVersion && LOWORD(pVSFixedFileInfo->dwProductVersionMS) > ver_info.dwMinorVersion || + HIWORD(pVSFixedFileInfo->dwProductVersionMS) == ver_info.dwMajorVersion && LOWORD(pVSFixedFileInfo->dwProductVersionMS) == ver_info.dwMinorVersion && HIWORD(pVSFixedFileInfo->dwProductVersionLS) > ver_info.dwBuildNumber) + { + // We got kernel32.dll version and it is newer. + ver_info.dwMajorVersion = HIWORD(pVSFixedFileInfo->dwProductVersionMS); + ver_info.dwMinorVersion = LOWORD(pVSFixedFileInfo->dwProductVersionMS); + ver_info.dwBuildNumber = HIWORD(pVSFixedFileInfo->dwProductVersionLS); + } + } + + free(pVersionInfo); + } + } + + uiResult = MsiSetProperty(hInstall, TEXT("DriverCertification"), ver_info.dwMajorVersion >= 10 ? ver_info.wProductType > VER_NT_WORKSTATION ? TEXT("whql") : TEXT("attsgn") : TEXT("")); + if (uiResult != ERROR_SUCCESS) + { + SetLastError(uiResult); /* MSDN does not mention MsiSetProperty() to set GetLastError(). But we do have an error code. Set last error manually. */ + msg(M_NONFATAL | M_ERRNO, "%s: MsiSetProperty(\"TAPINTERFACES\") failed", __FUNCTION__); + goto cleanup_CoInitialize; + } + + uiResult = ERROR_SUCCESS; + +cleanup_CoInitialize: + if (bIsCoInitialized) CoUninitialize(); + return uiResult; +} + + UINT __stdcall FindTAPInterfaces(_In_ MSIHANDLE hInstall) { diff --git a/src/openvpnmsica/openvpnmsica.h b/src/openvpnmsica/openvpnmsica.h index bb8e28ec..da145062 100644 --- a/src/openvpnmsica/openvpnmsica.h +++ b/src/openvpnmsica/openvpnmsica.h @@ -63,6 +63,21 @@ extern "C" { #endif +/** + * Determines Windows information: + * - Sets `DriverCertification` MSI property to "", "attsgn" or "whql" + * according to the driver certification required by the running version of + * Windows. + * + * @param hInstall Handle to the installation provided to the DLL custom action + * + * @return ERROR_SUCCESS on success; An error code otherwise + * See: https://msdn.microsoft.com/en-us/library/windows/desktop/aa368072.aspx + */ +DLLEXP_DECL UINT __stdcall +FindSystemInfo(_In_ MSIHANDLE hInstall); + + /** * Find existing TAP interfaces and set TAPINTERFACES property with semicolon delimited list * of installed TAP interface GUIDs. From patchwork Tue Oct 16 10:26:27 2018 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit Subject: [Openvpn-devel,5/5] Detect TAP interfaces with root-enumerated hardware ID X-Patchwork-Submitter: Simon Rozman X-Patchwork-Id: 555 Message-Id: <20181016102627.18676-5-simon@rozman.si> To: openvpn-devel@lists.sourceforge.net Date: Tue, 16 Oct 2018 12:26:27 +0200 From: Simon Rozman List-Id: This patch extends the TAP interface enumerating to detect the TAP interfaces registered using "root\tap0901" hardware ID. Before, only TAP interfaces with legacy "tap0901" HWID were detected by openvpn.exe. The openvpnmsica.dll and tapctl.exe install TAP interfaces using root- enumerated HWIDs, and were not detected by openvpn.exe. Acked-by: Gert Doering --- src/openvpn/tun.c | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/src/openvpn/tun.c b/src/openvpn/tun.c index 948fd17d..5fde2ab8 100644 --- a/src/openvpn/tun.c +++ b/src/openvpn/tun.c @@ -3524,7 +3524,8 @@ get_tap_reg(struct gc_arena *gc) if (status == ERROR_SUCCESS && data_type == REG_SZ) { - if (!strcmp(component_id, TAP_WIN_COMPONENT_ID)) + if (!strcmp(component_id, TAP_WIN_COMPONENT_ID) || + !strcmp(component_id, "root\\" TAP_WIN_COMPONENT_ID)) { struct tap_reg *reg; ALLOC_OBJ_CLEAR_GC(reg, struct tap_reg, gc);