# HG changeset patch # User Andre Heinecke # Date 1410889519 -7200 # Node ID fd85a02d771d9a5f278160ad97b35793cebad867 # Parent 5b6203f78b4e2a9f2077e765d7ffd500c739c47c# Parent 1c1964c27b39659d3581e693fb784dc205ca44d1 (issue54) Implement a privilege drop to execute the program after installation. This commit is extremly ugly as I accidentally worked in a working tree that was partially merged with default. To review the real change please check the commit that will merge this branch into default. diff -r 5b6203f78b4e -r fd85a02d771d CMakeLists.txt --- a/CMakeLists.txt Tue Sep 16 11:45:32 2014 +0200 +++ b/CMakeLists.txt Tue Sep 16 19:45:19 2014 +0200 @@ -153,12 +153,7 @@ add_subdirectory(manuals) endif() -# Configure packaging script for testing -configure_file (packaging/win-createpackage.sh.in packaging/win-createpackage.sh @ONLY) -configure_file (packaging/create-dist-package.sh.in packaging/create-dist-package.sh @ONLY) -configure_file (packaging/linux-createpackage.sh.in packaging/linux-createpackage.sh @ONLY) -configure_file (packaging/linux-installer.inc.in packaging/linux-installer.inc @ONLY) -configure_file (packaging/linux-installer.l10n-de packaging/linux-installer.l10n-de COPYONLY) +add_subdirectory(packaging) if (ENABLE_PROFILING) configure_file (make-coverage.sh.in make-coverage.sh) diff -r 5b6203f78b4e -r fd85a02d771d cinst/nssstore_win.c --- a/cinst/nssstore_win.c Tue Sep 16 11:45:32 2014 +0200 +++ b/cinst/nssstore_win.c Tue Sep 16 19:45:19 2014 +0200 @@ -39,7 +39,6 @@ */ #include -#include #include #include #include @@ -99,73 +98,6 @@ xfree (item); } -/** @brief get a restricted access token to execute nss process - * - * This function uses the Software Restriction API to obtain the - * access token for a process run als normal user. - * - * @returns A restricted handle or NULL on error. - */ -static HANDLE -get_restricted_token() -{ - SAFER_LEVEL_HANDLE user_level = NULL; - HANDLE retval = NULL; - SID_IDENTIFIER_AUTHORITY medium_identifier = {SECURITY_MANDATORY_LABEL_AUTHORITY}; - PSID medium_sid = NULL; - TOKEN_MANDATORY_LABEL integrity_label; - - memset (&integrity_label, 0, sizeof (integrity_label)); - - if (!SaferCreateLevel(SAFER_SCOPEID_USER, - SAFER_LEVELID_NORMALUSER, - SAFER_LEVEL_OPEN, &user_level, NULL)) - { - PRINTLASTERROR ("Failed to create user level.\n"); - return NULL; - } - - if (!SaferComputeTokenFromLevel(user_level, NULL, &retval, 0, NULL)) - { - SaferCloseLevel(user_level); - return NULL; - } - - SaferCloseLevel(user_level); - - /* Set the SID to medium it will still be high otherwise. Even if - there is no high access allowed. */ - if (!AllocateAndInitializeSid(&medium_identifier, - 1, - SECURITY_MANDATORY_MEDIUM_RID, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - &medium_sid)) - { - PRINTLASTERROR ("Failed to initialize sid.\n"); - return NULL; - } - - integrity_label.Label.Attributes = SE_GROUP_INTEGRITY; - integrity_label.Label.Sid = medium_sid; - - if (!SetTokenInformation(retval, - TokenIntegrityLevel, - &integrity_label, - sizeof(TOKEN_MANDATORY_LABEL))) - { - PRINTLASTERROR ("Failed to set token integrity.\n"); - return NULL; - } - - return retval; -} - /**@brief Write strv of instructions to a handle * * Writes the null terminated list of instructions to diff -r 5b6203f78b4e -r fd85a02d771d common/util.c --- a/common/util.c Tue Sep 16 11:45:32 2014 +0200 +++ b/common/util.c Tue Sep 16 19:45:19 2014 +0200 @@ -16,6 +16,7 @@ #include #include #else +#include #include #include #include @@ -782,3 +783,72 @@ return retval; } #endif + +#ifdef WIN32 +/** @brief get a restricted access token + * + * This function uses the Software Restriction API to obtain the + * access token for a process run als normal user. + * + * @returns A restricted handle or NULL on error. + */ +HANDLE +get_restricted_token() +{ + SAFER_LEVEL_HANDLE user_level = NULL; + HANDLE retval = NULL; + SID_IDENTIFIER_AUTHORITY medium_identifier = {SECURITY_MANDATORY_LABEL_AUTHORITY}; + PSID medium_sid = NULL; + TOKEN_MANDATORY_LABEL integrity_label; + + memset (&integrity_label, 0, sizeof (integrity_label)); + + if (!SaferCreateLevel(SAFER_SCOPEID_USER, + SAFER_LEVELID_NORMALUSER, + SAFER_LEVEL_OPEN, &user_level, NULL)) + { + PRINTLASTERROR ("Failed to create user level.\n"); + return NULL; + } + + if (!SaferComputeTokenFromLevel(user_level, NULL, &retval, 0, NULL)) + { + SaferCloseLevel(user_level); + return NULL; + } + + SaferCloseLevel(user_level); + + /* Set the SID to medium it will still be high otherwise. Even if + there is no high access allowed. */ + if (!AllocateAndInitializeSid(&medium_identifier, + 1, + SECURITY_MANDATORY_MEDIUM_RID, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + &medium_sid)) + { + PRINTLASTERROR ("Failed to initialize sid.\n"); + return NULL; + } + + integrity_label.Label.Attributes = SE_GROUP_INTEGRITY; + integrity_label.Label.Sid = medium_sid; + + if (!SetTokenInformation(retval, + TokenIntegrityLevel, + &integrity_label, + sizeof(TOKEN_MANDATORY_LABEL))) + { + PRINTLASTERROR ("Failed to set token integrity.\n"); + return NULL; + } + + return retval; +} +#endif diff -r 5b6203f78b4e -r fd85a02d771d common/util.h --- a/common/util.h Tue Sep 16 11:45:32 2014 +0200 +++ b/common/util.h Tue Sep 16 19:45:19 2014 +0200 @@ -150,6 +150,23 @@ */ bool has_high_integrity(HANDLE hToken); +/** @brief get a restricted access token to execute nss process + * + * This function uses the Software Restriction API to obtain the + * access token for a process run als normal user. + * + * @returns A restricted handle or NULL on error. + */ +HANDLE get_restricted_token(); + +/** @brief get a normal user access token + * + * The trusted acces token is not elevated but has the normal user rights. + * + * @returns A normal user handle or NULL on error. + */ +HANDLE get_normal_token(); + #endif #ifdef __cplusplus diff -r 5b6203f78b4e -r fd85a02d771d packaging/CMakeLists.txt --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/packaging/CMakeLists.txt Tue Sep 16 19:45:19 2014 +0200 @@ -0,0 +1,23 @@ +# Configure packaging script for testing +configure_file (win-createpackage.sh.in win-createpackage.sh @ONLY) +configure_file (create-dist-package.sh.in create-dist-package.sh @ONLY) +configure_file (linux-createpackage.sh.in linux-createpackage.sh @ONLY) +configure_file (linux-installer.inc.in linux-installer.inc @ONLY) +configure_file (linux-installer.l10n-de linux-installer.l10n-de COPYONLY) + +if (WIN32) + # Build the nss safer plugin. + include_directories(${CMAKE_SOURCE_DIR}/common) + + add_library(desktopshellrun SHARED desktopshellrun.cpp) + target_link_libraries(desktopshellrun + trustbridge_common + -luserenv + -lshell32 + -lcrypt32 + -lssp + -lshlwapi + ${POLARSSL_LIBRARIES}) # trustbridge_common pulls it in. + set_target_properties(desktopshellrun PROPERTIES PREFIX "") + set_target_properties(desktopshellrun PROPERTIES OUTPUT_NAME "DesktopShellRun") +endif() diff -r 5b6203f78b4e -r fd85a02d771d packaging/create-dist-package.sh.in --- a/packaging/create-dist-package.sh.in Tue Sep 16 11:45:32 2014 +0200 +++ b/packaging/create-dist-package.sh.in Tue Sep 16 19:45:19 2014 +0200 @@ -58,6 +58,7 @@ # Create a temporary NSIS file for the uninstaller cration LC_ALL="de_DE.latin-1" makensis -Dfiles_dir=$TMPDIR/windows \ -Dcompany="Bundesamt für Sicherheit in der Informationstechnik" \ + -Dplugin_dir="@CMAKE_CURRENT_BINARY_DIR@" \ -Dversion_number=@PROJECT_VERSION@ \ -Dsetupname="$TMPDIR/TrustBridge-@PROJECT_VERSION@-uni.exe" \ -Dproductname="TrustBridge" \ diff -r 5b6203f78b4e -r fd85a02d771d packaging/desktopshellrun.cpp --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/packaging/desktopshellrun.cpp Tue Sep 16 19:45:19 2014 +0200 @@ -0,0 +1,326 @@ +/* Copyright (C) 2014 by Bundesamt für Sicherheit in der Informationstechnik + * Software engineering by Intevation GmbH + * + * This file is Free Software under the GNU GPL (v>=2) + * and comes with ABSOLUTELY NO WARRANTY! + * See LICENSE.txt for details. + */ + +/** + * @file tasksched_run_as.cpp + * @brief Run a command with the Task Scheduler API + * + * This effectively starts a program as the user regardles of the current + * process token. + */ +#include +#include "logging.h" +#include "strhelp.h" + +#ifndef INITGUID +#define INITGUID +#endif + +#include +#include +#include +#include +#include +#include +#include +#include + +/* Some declarations missing in mingw-w64 3.1.0 taken from msdn */ + +__CRT_UUID_DECL(IShellWindows, 0x85CB6900, 0x4D95, 0x11CF, + 0x96, 0x0C, 0x00, 0x80, 0xC7, 0xF4, 0xEE, 0x85); + +DEFINE_GUID(IID_IShellWindows, + 0x85CB6900, 0x4D95, 0x11CF, + 0x96, 0x0C, 0x00, 0x80, 0xC7, 0xF4, 0xEE, 0x85); +DEFINE_GUID(CLSID_ShellWindows, + 0x9BA05972, 0xF6A8, 0x11CF, + 0xA4, 0x42, 0x00, 0xA0, 0xC9, 0x0A, 0x8F, 0x39); + + +__CRT_UUID_DECL(IShellDispatch2, 0xA4C6892C, 0x3BA9, 0x11d2, + 0x9D, 0xEA, 0x00, 0xC0, 0x4F, 0xB1, 0x61, 0x62); +__CRT_UUID_DECL(IShellFolderViewDual, 0xe7a1af80, 0x4d96, + 0x11cf, 0x96, 0x0c, 0x00, 0x80, 0xc7, 0xf4, 0xee, 0x85); + +#ifndef SWC_DESKTOP /* Will probably be addedd in future mingw */ +#define SWC_DESKTOP 0x00000008 +/* from http://msdn.microsoft.com/en-us/library/windows/desktop/cc836581%28v=vs.85%29.aspx */ +#endif + +#undef INITGUID + +#ifdef DO_RELEASE_BUILD +bool g_debug = false; +#else +bool g_debug = true; +#endif + +typedef struct _stack_t +{ + struct _stack_t *next; + char text[1]; /* This should be the length of string_size. */ +} stack_t; + +static HINSTANCE g_hInstance; /* Our Instance. */ + +#define UNUSED(x) (void)(x) + +/** @brief the actual execuation call on the shell dispatcher + * + * @param[in] disp The shell dispatcher to use for shell execute. + * @param[in] fName The file that should be exectued. + * + * @returns true on success. + */ +static bool +shellexecute(IShellDispatch2 *disp, wchar_t *fName) +{ + BSTR bName = NULL, + bParam = NULL, + bDir = NULL, + bOp = NULL; + VARIANT vParams[4]; + HRESULT hr; + + if (!fName || !disp) + { + ERRORPRINTF ("Invalid call to shellexecute."); + return false; + } + + bName = SysAllocString(fName); + bParam = SysAllocString(L""); + bDir = SysAllocString(L""); + bOp = SysAllocString(L""); + + if (!bName || !bParam || !bDir || !bOp) + { + /* Out of memory */ + ERRORPRINTF ("Failed to allocate bstr values "); + return false; + } + + vParams[0].vt = VT_BSTR; + vParams[0].bstrVal = bParam; + vParams[1].vt = VT_BSTR; + vParams[1].bstrVal = bDir; + vParams[2].vt = VT_BSTR; + vParams[2].bstrVal = bOp; + vParams[3].vt = VT_INT; + vParams[3].intVal = SW_SHOWNORMAL; + + hr = disp->ShellExecute(bName, vParams[0], vParams[1], vParams[2], vParams[3]); + + SysFreeString(bName); + SysFreeString(bParam); + SysFreeString(bOp); + SysFreeString(bDir); + + if (FAILED(hr)) + { + ERRORPRINTF ("Failed to execute."); + return false; + } + return true; +} + +#ifdef __cplusplus +extern "C" { +#endif + +/* Standard entry point for DLLs. */ +int WINAPI +DllMain (HANDLE hinst, DWORD reason, LPVOID reserved) +{ + UNUSED(reserved); + if (reason == DLL_PROCESS_ATTACH) + g_hInstance = (HINSTANCE)hinst; + return TRUE; +} + +/** @brief Execute a command with the current running shell. + * + * This function is intended to be called when you want to + * make sure that your application is not executed with higher + * privileges then the normal desktop session. + * + * The code is based on the idea: + * http://blogs.msdn.com/b/oldnewthing/archive/2013/11/18/10468726.aspx + * + * The function signature is explained by NSIS. + */ +void __declspec(dllexport) __cdecl Exec(HWND hwndParent, + int string_size, + char *variables, + stack_t **stacktop) +{ + UNUSED(hwndParent); + UNUSED(string_size); + HRESULT hr; + wchar_t *wbuf = NULL; + IShellWindows *shellWindows = NULL; + IShellBrowser *shellBrowser = NULL; + IShellView *shellView = NULL; + IShellFolderViewDual *folderView = NULL; + IShellDispatch2 *shellDispatch = NULL; + IServiceProvider *serviceProv = NULL; + HWND hwnd; + IDispatch *disp = NULL, + *bgDisp = NULL, + *sDisp = NULL; + VARIANT vEmpty = {}; + + + if (!stacktop || !*stacktop || !(*stacktop)->text) + { + ERRORPRINTF ("Invalid call to exec :"); + return; + } + + /* Initialize com ctx */ + hr = CoInitialize(NULL); + if(FAILED(hr)) + { + ERRORPRINTF ("CoInitializeEx failed. error = 0x%lx.", hr); + return; + } + + /* Get the shell interface */ + hr = CoCreateInstance(CLSID_ShellWindows, + NULL, CLSCTX_LOCAL_SERVER, + IID_PPV_ARGS(&shellWindows)); + if (FAILED(hr)) + { + ERRORPRINTF ("Failed to get shell interface."); + goto done; + } + + /* Get the desktop shell window */ + hr = shellWindows->FindWindowSW(&vEmpty, + &vEmpty, + SWC_DESKTOP, + (long*)&hwnd, + SWFO_NEEDDISPATCH, + &disp); + if (FAILED(hr)) + { + ERRORPRINTF ("Failed to find the desktop dispatcher."); + goto done; + } + + hr = disp->QueryInterface(IID_PPV_ARGS(&serviceProv)); + + if (FAILED(hr)) + { + ERRORPRINTF ("Failed to get the service provider."); + goto done; + } + + /* Get the shell browser */ + hr = serviceProv->QueryService(SID_STopLevelBrowser, IID_PPV_ARGS(&shellBrowser)); + if (FAILED(hr)) + { + ERRORPRINTF ("Failed to find the top level browser."); + goto done; + } + + hr = shellBrowser->QueryActiveShellView(&shellView); + + if (FAILED(hr)) + { + ERRORPRINTF ("Failed to find the active view."); + goto done; + } + + hr = shellView->GetItemObject(SVGIO_BACKGROUND, IID_PPV_ARGS(&bgDisp)); + + if (FAILED(hr)) + { + ERRORPRINTF ("Failed to get the views background."); + goto done; + } + + hr = bgDisp->QueryInterface(IID_PPV_ARGS(&folderView)); + + if (FAILED(hr)) + { + ERRORPRINTF ("Failed to get the folder view."); + goto done; + } + + + hr = folderView->get_Application(&sDisp); + + if (FAILED(hr)) + { + ERRORPRINTF ("Failed to get the shell dispatch."); + goto done; + } + + hr = sDisp->QueryInterface(IID_PPV_ARGS(&shellDispatch)); + + if (FAILED(hr)) + { + ERRORPRINTF ("Failed to get the shell dispatch interface."); + goto done; + } + + wbuf = utf8_to_wchar((*stacktop)->text, strlen((*stacktop)->text)); + if (!wbuf) + { + ERRORPRINTF ("Failed to convert argument to wchar. error = 0x%lx.", hr); + goto done; + } + + if (!shellexecute(shellDispatch, wbuf)) + { + ERRORPRINTF ("Failed to execute."); + } + xfree (wbuf); +done: + if (folderView) + { + folderView->Release(); + } + if (disp) + { + disp->Release(); + } + if (shellBrowser) + { + shellBrowser->Release(); + } + if (shellWindows) + { + shellWindows->Release(); + } + if (shellView) + { + shellView->Release(); + } + if (sDisp) + { + sDisp->Release(); + } + if (shellDispatch) + { + shellDispatch->Release(); + } + if (serviceProv) + { + serviceProv->Release(); + } + CoUninitialize(); + return; +} +#ifdef __cplusplus +} +#endif + + diff -r 5b6203f78b4e -r fd85a02d771d packaging/exdll.h --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/packaging/exdll.h Tue Sep 16 19:45:19 2014 +0200 @@ -0,0 +1,39 @@ +/* exdll.h for use with TrustBrdige + * Copyright (C) 1999-2005 Nullsoft, Inc. + * + * This license applies to everything in the NSIS package, except + * where otherwise noted. + * + * This software is provided 'as-is', without any express or implied + * warranty. In no event will the authors be held liable for any + * damages arising from the use of this software. + * + * Permission is granted to anyone to use this software for any + * purpose, including commercial applications, and to alter it and + * redistribute it freely, subject to the following restrictions: + * + * 1. The origin of this software must not be misrepresented; you must + * not claim that you wrote the original software. If you use this + * software in a product, an acknowledgment in the product + * documentation would be appreciated but is not required. + * + * 2. Altered source versions must be plainly marked as such, and must + * not be misrepresented as being the original software. + * + * 3. This notice may not be removed or altered from any source + * distribution. + ************************************************************ + * 2005-11-14 wk Applied license text to orginal exdll.h file from + * NSIS 2.0.4 and did some formatting changes. + * 2014-09-16 ah Stripped out uneccesary stuff for TrustBridge plugin + */ + +#ifndef _EXDLL_H_ +#define _EXDLL_H_ + +/* only include this file from one place in your DLL. (it is all + static, if you use it in two places it will fail) */ + +/* For page showing plug-ins */ + +#endif//_EXDLL_H_ diff -r 5b6203f78b4e -r fd85a02d771d packaging/trustbridge.nsi --- a/packaging/trustbridge.nsi Tue Sep 16 11:45:32 2014 +0200 +++ b/packaging/trustbridge.nsi Tue Sep 16 19:45:19 2014 +0200 @@ -27,6 +27,8 @@ !define MULTIUSER_INSTALLMODE_INSTDIR_REGISTRY_VALUENAME "" !define MULTIUSER_INSTALLMODE_INSTDIR "${productname_short}" +!addplugindir "${plugin_dir}" + !include "MultiUser.nsh" !include "MUI2.nsh" !include "FileFunc.nsh" @@ -93,9 +95,9 @@ Computer installliert. $\r$\n$\r$\n\ Klicken Sie auf 'Fertig stellen', um den Installations-Assistenten\ zu schließen." -;!define MUI_FINISHPAGE_RUN $INSTDIR\trustbridge.exe -;!define MUI_FINISHPAGE_RUN_TEXT "Anwendung starten" -;!define MUI_FINISHPAGE_RUN_FUNCTION RunAsUser +!define MUI_FINISHPAGE_RUN $INSTDIR\trustbridge.exe +!define MUI_FINISHPAGE_RUN_TEXT "Anwendung starten" +!define MUI_FINISHPAGE_RUN_FUNCTION RunAsUser !define MUI_FINISHPAGE_LINK "Mehr unter ${info_url}" !define MUI_FINISHPAGE_LINK_LOCATION "${info_url}" @@ -186,7 +188,7 @@ ; the UI elevated as this could be a security ; problem. Function RunAsUser - ExecShell "" "$INSTDIR\trustbridge.exe" + DesktopShellRun::Exec "$INSTDIR\trustbridge.exe" FunctionEnd ;-------------------------------- @@ -258,6 +260,9 @@ !insertmacro MUI_STARTMENU_WRITE_END done: + StrCmp $is_update '1' run_silent dont_run +run_silent: +dont_run: SectionEnd diff -r 5b6203f78b4e -r fd85a02d771d packaging/win-createpackage.sh.in --- a/packaging/win-createpackage.sh.in Tue Sep 16 11:45:32 2014 +0200 +++ b/packaging/win-createpackage.sh.in Tue Sep 16 19:45:19 2014 +0200 @@ -26,6 +26,7 @@ makensis -Dfiles_dir=$TMPDIR \ -Dcompany="Bundesamt für Sicherheit in der Informationstechnik" \ + -Dplugin_dir="@CMAKE_CURRENT_BINARY_DIR@" \ -Dversion_number=@PROJECT_VERSION@ \ -Dsetupname="$TMPINST" \ -Dproductname="TrustBridge" \ @@ -42,6 +43,7 @@ makensis -Dfiles_dir=$TMPDIR \ -Dcompany="Bundesamt für Sicherheit in der Informationstechnik" \ + -Dplugin_dir="@CMAKE_CURRENT_BINARY_DIR@" \ -Dversion_number=@PROJECT_VERSION@ \ -Dsetupname="@CMAKE_BINARY_DIR@/TrustBridge-@PROJECT_VERSION@.exe" \ -Dproductname="TrustBridge" \