diff --git a/OxtService/OxtGuestServices.cpp b/OxtService/OxtGuestServices.cpp new file mode 100644 index 0000000..99121b3 --- /dev/null +++ b/OxtService/OxtGuestServices.cpp @@ -0,0 +1,119 @@ +/* + * Copyright (c) 2012 Citrix Systems, Inc. + * Copyright (c) 2016 Assured Information Security, Inc + * + * Permission is hereby granted, free of charge, to any person obtaining a copy + * of this software and associated documentation files (the "Software"), to deal + * in the Software without restriction, including without limitation the rights + * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell + * copies of the Software, and to permit persons to whom the Software is + * furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included in + * all copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE + * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER + * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, + * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN + * THE SOFTWARE. + */ + +// OxtGuestServices.cpp : Implementation of COxtGuestServices + +#include "stdafx.h" +#include +#include "oxtmsg.h" +#include "OxtGuestServices.h" +#include "OxtSecurityHelper.h" + +HRESULT COxtGuestServices::FinalConstruct() +{ + HRESULT hr = S_OK; + + do { + // Open an XS instance for use by this object + if (!m_clXs.XS2Open()) + { + hr = LogCreateFailure((IDS_FAILED_TO_OPEN_XENSTORE___HRESUL_OXTGUESTSERVICES_32), + E_FAIL); + break; + } + + // Register this object - if it fails the global count is exceeded + if (!m_pclOxtSvc->RegisterXgs()) + { + m_clXs.XS2Close(); + hr = E_ACCESSDENIED; + LogCreateFailure((IDS_MAXIMUM_INSTANCE_COUNT_REACHED___OXTGUESTSERVICES_61), hr); + } + } while (false); + + return hr; +} + +void COxtGuestServices::FinalRelease() +{ + // Drop out of the main list + m_pclOxtSvc->UnregisterXgs(); + + m_clXs.XS2Close(); +} + +HRESULT COxtGuestServices::LogCreateFailure(ULONG ulMsg, HRESULT hr) +{ + m_pclOxtSvc->LogEventTypeId(ulMsg, EVENTLOG_ERROR_TYPE, EVMSG_CREATION_FAILURE, hr); + return hr; +} + +STDMETHODIMP COxtGuestServices::InterfaceSupportsErrorInfo(REFIID riid) +{ + static const IID* arr[] = + { + &IID_IOxtGuestServices + }; + + for (int i=0; i < sizeof(arr) / sizeof(arr[0]); i++) + { + if (InlineIsEqualGUID(*arr[i],riid)) + return S_OK; + } + return S_FALSE; +} + +STDMETHODIMP COxtGuestServices::XenStoreRead(BSTR bstrPath, BSTR *pbstrValue) +{ + LPCSTR szValue; + CComBSTR bstrValue; + HRESULT hr; + + szValue = (LPCSTR)m_clXs.XS2Read(CW2A(bstrPath), NULL); + if (szValue == NULL) + { + hr = LogCreateFailure((IDS_FAILED_TO_OPEN_XENSTORE___HRESUL_OXTGUESTSERVICES_32), + E_UNEXPECTED); + return hr; + } + + bstrValue = szValue; + + m_clXs.XS2Free((LPVOID)szValue); + *pbstrValue = bstrValue.Copy(); + return S_OK; +} + +STDMETHODIMP COxtGuestServices::XenStoreWrite(BSTR bstrPath, BSTR bstrValue) +{ + HRESULT hr; + + if (!m_clXs.XS2Write(CW2A(bstrPath), CW2A(bstrValue))) + { + hr = LogCreateFailure((IDS_FAILED_TO_OPEN_XENSTORE___HRESUL_OXTGUESTSERVICES_32), + E_UNEXPECTED); + return hr; + } + + return S_OK; +} \ No newline at end of file diff --git a/OxtService/OxtGuestServices.h b/OxtService/OxtGuestServices.h new file mode 100644 index 0000000..6a72fad --- /dev/null +++ b/OxtService/OxtGuestServices.h @@ -0,0 +1,74 @@ +/* + * Copyright (c) 2012 Citrix Systems, Inc. + * Copyright (c) 2016 Assured Information Security, Inc + * + * Permission is hereby granted, free of charge, to any person obtaining a copy + * of this software and associated documentation files (the "Software"), to deal + * in the Software without restriction, including without limitation the rights + * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell + * copies of the Software, and to permit persons to whom the Software is + * furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included in + * all copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE + * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER + * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, + * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN + * THE SOFTWARE. + */ + +// OxtGuestServices.h : Declaration of the COxtGuestServices + +#pragma once +#include "resource.h" // main symbols + +#include "OxtService_i.h" +#include "OxtService.h" +#include "XenStoreWrapper.h" + +// COxtGuestServices + +class ATL_NO_VTABLE COxtGuestServices : + public CComObjectRootEx, + public CComCoClass, + public ISupportErrorInfo, + public IDispatchImpl +{ +private: + COxtService *m_pclOxtSvc; + CXenStoreWrapper m_clXs; + +public: + COxtGuestServices() : m_pclOxtSvc(&_OxtService) + { + } + +DECLARE_REGISTRY_RESOURCEID(IDR_OXTGUESTSERVICES) + +BEGIN_COM_MAP(COxtGuestServices) + COM_INTERFACE_ENTRY(IOxtGuestServices) + COM_INTERFACE_ENTRY(IDispatch) + COM_INTERFACE_ENTRY(ISupportErrorInfo) +END_COM_MAP() + +// ISupportsErrorInfo + STDMETHOD(InterfaceSupportsErrorInfo)(REFIID riid); + + DECLARE_PROTECT_FINAL_CONSTRUCT() + + HRESULT FinalConstruct(); + void FinalRelease(); + + HRESULT LogCreateFailure(ULONG ulMsg, HRESULT hr); + +public: + + STDMETHOD(XenStoreRead)(BSTR bstrPath, BSTR *pbstrValue); + STDMETHOD(XenStoreWrite)(BSTR bstrPath, BSTR bstrValue); +}; + +OBJECT_ENTRY_AUTO(__uuidof(OxtGuestServices), COxtGuestServices) diff --git a/OxtService/OxtGuestServices.rgs b/OxtService/OxtGuestServices.rgs new file mode 100644 index 0000000..8ef36d8 --- /dev/null +++ b/OxtService/OxtGuestServices.rgs @@ -0,0 +1,24 @@ +HKCR +{ + OxtService.OxtGuestServices.1 = s 'OxtGuestServices Class' + { + CLSID = s '{79E8108A-57E6-4E3D-B98F-DB90572B7F5A}' + } + OxtService.OxtGuestServices = s 'OxtGuestServices Class' + { + CLSID = s '{79E8108A-57E6-4E3D-B98F-DB90572B7F5A}' + CurVer = s 'OxtService.OxtGuestServices.1' + } + NoRemove CLSID + { + ForceRemove {79E8108A-57E6-4E3D-B98F-DB90572B7F5A} = s 'OxtGuestServices Class' + { + ProgID = s 'OxtService.OxtGuestServices.1' + VersionIndependentProgID = s 'OxtService.OxtGuestServices' + ForceRemove 'Programmable' + LocalServer32 = s '%MODULE%' + val AppID = s '%APPID%' + 'TypeLib' = s '{CB46685A-BBB0-406B-BB1D-CF1641FFF17D}' + } + } +} diff --git a/OxtService/OxtSecurityHelper.cpp b/OxtService/OxtSecurityHelper.cpp new file mode 100644 index 0000000..7277f54 --- /dev/null +++ b/OxtService/OxtSecurityHelper.cpp @@ -0,0 +1,1834 @@ +/* + * Copyright (c) 2012 Citrix Systems, Inc. + * Copyright (c) 2016 Assured Information Security, Inc + * + * Permission is hereby granted, free of charge, to any person obtaining a copy + * of this software and associated documentation files (the "Software"), to deal + * in the Software without restriction, including without limitation the rights + * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell + * copies of the Software, and to permit persons to whom the Software is + * furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included in + * all copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE + * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER + * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, + * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN + * THE SOFTWARE. + */ + +#include "stdafx.h" +#include "resource.h" +#include "oxtmsg.h" +#include +#include +#include +#include "OxtSecurityHelper.h" + +#define XSH_PRINCIPAL_COUNT 3 +#define XSH_NAME_LEN 255 + +#define SDTYPE_APPLICATION_LAUNCH 0x10L +#define SDTYPE_APPLICATION_ACCESS 0x20L + +static const TCHAR *g_ptszPrincipals[XSH_PRINCIPAL_COUNT] = { + _T("NT AUTHORITY\\INTERACTIVE"), + _T("NT AUTHORITY\\SYSTEM"), + _T("BUILTIN\\Administrators") +}; + +static const TCHAR *g_ptszSidStrings[XSH_PRINCIPAL_COUNT] = { + _T("S-1-5-4"), + _T("S-1-5-18"), + _T("S-1-5-32-544") +}; + +const DWORD g_dwAccessAccessMask = COM_RIGHTS_EXECUTE_REMOTE|COM_RIGHTS_EXECUTE; +const DWORD g_dwLaunchActivateMask = COM_RIGHTS_ACTIVATE_REMOTE|COM_RIGHTS_EXECUTE_REMOTE|COM_RIGHTS_EXECUTE; + +void COxtSecurityHelper::LogSecuritySetupFailure(LPCTSTR tszPrincipal, + LPCTSTR tszPermissionName, + LPCTSTR tszOp, + DWORD dwError) +{ + m_pclOxtSvc->LogEventTypeId(ctxLS(IDS_PRINCIPAL__zS_PERMISSION__zS_OPE_OXTSECURITYHELPER_35), + EVENTLOG_ERROR_TYPE, + EVMSG_SECURITY_SETUP_FAILURE, + tszPrincipal, + tszPermissionName, + tszOp, + dwError); +} + +bool COxtSecurityHelper::IsLegacySecurityModel() +{ + bool br = false; + const OSVERSIONINFOEX *posvi = m_pclOxtSvc->GetOsInfo(); + + if (posvi->dwMajorVersion == 5) // = 2k, xp, 2k3 + { + if (posvi->dwMinorVersion < 1) // < xp + { + br = true; + } + else if (posvi->dwMinorVersion == 1) // = xp + { + if (posvi->wServicePackMajor < 2) // < xpsp2 + br = true; + } + else if (posvi->dwMinorVersion == 2) // = 2k3 + { + if (posvi->wServicePackMajor < 1) // < 2k3sp1 + br = true; + } + + } + else if (posvi->dwMajorVersion < 5) // nt? + br = true; + + return br; +} + +DWORD COxtSecurityHelper::CopyACL(PACL paclOld, PACL paclNew) +{ + ACL_SIZE_INFORMATION aclSizeInfo = {0}; + LPVOID pvAce = NULL; + ACE_HEADER *pAceHeader = NULL; + ULONG i; + + if(!::GetAclInformation(paclOld, (LPVOID)&aclSizeInfo, + sizeof(aclSizeInfo), AclSizeInformation)) + { + return ::GetLastError(); + } + + // Copy all of the ACEs to the new ACL + for (i = 0; i < aclSizeInfo.AceCount; i++) + { + // Get the ACE and header info + if (!::GetAce(paclOld, i, &pvAce)) + return ::GetLastError(); + + pAceHeader = (ACE_HEADER *)pvAce; + + // Add the ACE to the new list + if (!::AddAce(paclNew, ACL_REVISION, 0xffffffff, pvAce, pAceHeader->AceSize)) + return ::GetLastError(); + } + + return ERROR_SUCCESS; +} + +DWORD COxtSecurityHelper::AddAccessAllowedACEToACL(PACL *paclOrig, + DWORD dwAccessMask, + LPCTSTR tszPrincipal) +{ + ACL_SIZE_INFORMATION aclSizeInfo = {0}; + int cbAclSize = 0; + DWORD dwReturnValue = ERROR_SUCCESS; + PSID psidPrincipal = NULL; + PACL paclOld = NULL; + PACL paclNew = NULL; + + if (paclOrig == NULL) + return ERROR_BAD_ARGUMENTS; + + paclOld = *paclOrig; + + do { + dwReturnValue = GetPrincipalSID(tszPrincipal, &psidPrincipal); + if (dwReturnValue != ERROR_SUCCESS) + break; + + if (!::GetAclInformation(paclOld, (LPVOID)&aclSizeInfo, + sizeof (ACL_SIZE_INFORMATION), AclSizeInformation)) + { + dwReturnValue = ::GetLastError(); + break; + } + + cbAclSize = aclSizeInfo.AclBytesInUse + sizeof (ACL) + sizeof (ACCESS_ALLOWED_ACE) + + ::GetLengthSid(psidPrincipal) - sizeof (DWORD); + + paclNew = (PACL)malloc(cbAclSize); + if (paclNew == NULL) + { + dwReturnValue = ERROR_OUTOFMEMORY; + break; + } + + if (!::InitializeAcl(paclNew, cbAclSize, ACL_REVISION)) + { + dwReturnValue = ::GetLastError(); + break; + } + + dwReturnValue = CopyACL(paclOld, paclNew); + if (dwReturnValue != ERROR_SUCCESS) + break; + + if (!::AddAccessAllowedAce(paclNew, ACL_REVISION2, dwAccessMask, psidPrincipal)) + { + dwReturnValue = ::GetLastError(); + break; + } + + *paclOrig = paclNew; + + } while (false); + + if((dwReturnValue != ERROR_SUCCESS)&&(paclNew != NULL)) + free(paclNew); + + if (psidPrincipal != NULL) + ::LocalFree(psidPrincipal); + + return dwReturnValue; +} + +DWORD COxtSecurityHelper::AddAccessDeniedACEToACL(PACL *paclOrig, + DWORD dwAccessMask, + LPCTSTR tszPrincipal) +{ + ACL_SIZE_INFORMATION aclSizeInfo = {0}; + int cbAclSize = 0; + DWORD dwReturnValue = ERROR_SUCCESS; + PSID psidPrincipal = NULL; + PACL paclOld = NULL; + PACL paclNew = NULL; + + if (paclOrig == NULL) + return ERROR_BAD_ARGUMENTS; + + paclOld = *paclOrig; + + do { + dwReturnValue = GetPrincipalSID(tszPrincipal, &psidPrincipal); + if (dwReturnValue != ERROR_SUCCESS) + break; + + if (!::GetAclInformation(paclOld, (LPVOID)&aclSizeInfo, + sizeof (ACL_SIZE_INFORMATION), AclSizeInformation)) + { + dwReturnValue = ::GetLastError(); + break; + } + + cbAclSize = aclSizeInfo.AclBytesInUse + sizeof (ACL) + sizeof (ACCESS_DENIED_ACE) + + ::GetLengthSid (psidPrincipal) - sizeof (DWORD); + + paclNew = (PACL)malloc(cbAclSize); + if (paclNew == NULL) + { + dwReturnValue = ERROR_OUTOFMEMORY; + break; + } + + if (!::InitializeAcl(paclNew, cbAclSize, ACL_REVISION)) + { + dwReturnValue = ::GetLastError(); + break; + } + + if (!::AddAccessDeniedAce(paclNew, ACL_REVISION2, dwAccessMask, psidPrincipal)) + { + dwReturnValue = ::GetLastError(); + break; + } + + dwReturnValue = CopyACL(paclOld, paclNew); + if (dwReturnValue != ERROR_SUCCESS) + break; + + *paclOrig = paclNew; + } while (false); + + if (psidPrincipal != NULL) + ::LocalFree(psidPrincipal); + + return dwReturnValue; +} + +DWORD COxtSecurityHelper::SetLegacyACLDefaults(PACL *ppDacl, DWORD dwSDType) +{ + DWORD dwReturnValue = ERROR_BAD_ARGUMENTS; + + switch (dwSDType) + { + case SDTYPE_APPLICATION_LAUNCH: + { + dwReturnValue = AddAccessAllowedACEToACL(ppDacl, + COM_RIGHTS_EXECUTE, + g_ptszPrincipals[1]); // SYSTEM + + if (dwReturnValue != ERROR_SUCCESS) + break; + + dwReturnValue = AddAccessAllowedACEToACL(ppDacl, + COM_RIGHTS_EXECUTE, + g_ptszPrincipals[2]); // Administrators + + if (dwReturnValue != ERROR_SUCCESS) + break; + + dwReturnValue = AddAccessAllowedACEToACL(ppDacl, + COM_RIGHTS_EXECUTE, + g_ptszPrincipals[0]); // INTERACTIVE + break; + } + case SDTYPE_APPLICATION_ACCESS: + { + dwReturnValue = AddAccessAllowedACEToACL(ppDacl, + COM_RIGHTS_EXECUTE, + g_ptszPrincipals[1]); // SYSTEM + + if (dwReturnValue != ERROR_SUCCESS) + break; + + dwReturnValue = AddAccessAllowedACEToACL(ppDacl, + COM_RIGHTS_EXECUTE, + g_ptszPrincipals[0]); // INTERACTIVE + break; + } + default: + break; + } + + return dwReturnValue; +} + +DWORD COxtSecurityHelper::SetACLDefaults(PACL *ppDacl, DWORD dwSDType) +{ + DWORD dwReturnValue = ERROR_BAD_ARGUMENTS; + + if (IsLegacySecurityModel()) + return SetLegacyACLDefaults(ppDacl, dwSDType); + + switch (dwSDType) + { + case SDTYPE_APPLICATION_LAUNCH: + { + dwReturnValue = AddAccessAllowedACEToACL(ppDacl, + COM_RIGHTS_ACTIVATE_LOCAL | + COM_RIGHTS_EXECUTE_LOCAL | + COM_RIGHTS_EXECUTE, + g_ptszPrincipals[1]); // SYSTEM + + if (dwReturnValue != ERROR_SUCCESS) + break; + + dwReturnValue = AddAccessAllowedACEToACL(ppDacl, + COM_RIGHTS_ACTIVATE_LOCAL | + COM_RIGHTS_EXECUTE_LOCAL | + COM_RIGHTS_EXECUTE, + g_ptszPrincipals[2]); // Administrators + + if (dwReturnValue != ERROR_SUCCESS) + break; + + dwReturnValue = AddAccessAllowedACEToACL(ppDacl, + COM_RIGHTS_ACTIVATE_LOCAL | + COM_RIGHTS_EXECUTE_LOCAL | + COM_RIGHTS_EXECUTE, + g_ptszPrincipals[0]); // INTERACTIVE + break; + } + case SDTYPE_APPLICATION_ACCESS: + { + dwReturnValue = AddAccessAllowedACEToACL(ppDacl, + COM_RIGHTS_EXECUTE_LOCAL | + COM_RIGHTS_EXECUTE, + g_ptszPrincipals[1]); // SYSTEM + + if (dwReturnValue != ERROR_SUCCESS) + break; + + dwReturnValue = AddAccessAllowedACEToACL(ppDacl, + COM_RIGHTS_EXECUTE_LOCAL | + COM_RIGHTS_EXECUTE, + g_ptszPrincipals[2]); // Administrators + + if (dwReturnValue != ERROR_SUCCESS) + break; + + dwReturnValue = AddAccessAllowedACEToACL(ppDacl, + COM_RIGHTS_EXECUTE_LOCAL | + COM_RIGHTS_EXECUTE, + g_ptszPrincipals[0]); // INTERACTIVE + + break; + } + default: + break; + } + + return dwReturnValue; +} + +DWORD COxtSecurityHelper::CreateNewSecurityDescriptor(SECURITY_DESCRIPTOR **ppSecurityDesc) +{ + PACL pAcl = NULL; + DWORD cbSid = 0; + PSID pSid = NULL; + PSID psidGroup = NULL; + PSID psidOwner = NULL; + DWORD dwReturnValue = ERROR_SUCCESS; + SID_IDENTIFIER_AUTHORITY SystemSidAuthority = SECURITY_NT_AUTHORITY; + + if (!ppSecurityDesc) + return ERROR_BAD_ARGUMENTS; + + *ppSecurityDesc = NULL; + + do { + if (!::AllocateAndInitializeSid(&SystemSidAuthority, 2, SECURITY_BUILTIN_DOMAIN_RID, + DOMAIN_ALIAS_RID_ADMINS, 0, 0, 0, 0, 0, 0, &pSid)) + { + dwReturnValue = GetLastError(); + break; + } + + cbSid = ::GetLengthSid(pSid); + + *ppSecurityDesc = (SECURITY_DESCRIPTOR*)malloc(sizeof(ACL) + (2*cbSid) + sizeof(SECURITY_DESCRIPTOR)); + if (*ppSecurityDesc == NULL) + { + dwReturnValue = ERROR_OUTOFMEMORY; + break; + } + + psidGroup = (SID *)(*ppSecurityDesc + 1); + psidOwner = (SID *)(((BYTE *) psidGroup) + cbSid); + pAcl = (ACL *)(((BYTE *) psidOwner) + cbSid); + + if (!::InitializeSecurityDescriptor(*ppSecurityDesc, SECURITY_DESCRIPTOR_REVISION)) + { + dwReturnValue = ::GetLastError(); + break; + } + + if (!::InitializeAcl(pAcl, (sizeof(ACL) + sizeof (ACCESS_ALLOWED_ACE) + cbSid), ACL_REVISION2)) + { + dwReturnValue = ::GetLastError(); + break; + } + + if (!::SetSecurityDescriptorDacl(*ppSecurityDesc, TRUE, pAcl, FALSE)) + { + dwReturnValue = ::GetLastError(); + break; + } + + memcpy(psidGroup, pSid, cbSid); + if (!::SetSecurityDescriptorGroup(*ppSecurityDesc, psidGroup, FALSE)) + { + dwReturnValue = ::GetLastError(); + break; + } + + memcpy(psidOwner, pSid, cbSid); + if (!::SetSecurityDescriptorOwner(*ppSecurityDesc, psidOwner, FALSE)) + { + dwReturnValue = ::GetLastError(); + break; + } + } while (false); + + if (dwReturnValue != ERROR_SUCCESS) + { + if (*ppSecurityDesc) + free(*ppSecurityDesc); + } + + if (pSid) + ::FreeSid(pSid); + + return dwReturnValue; +} + +DWORD COxtSecurityHelper::GetPrincipalSIDByName(LPCTSTR tszPrincipal, PSID *ppSid) +{ + SID_NAME_USE snu; + DWORD cbSid = 0; + DWORD cbRefDomain = 0; + DWORD dwReturnValue = ERROR_SUCCESS; + TCHAR tszRefDomain[XSH_NAME_LEN + 1] = {0}; + + cbSid = 0; + cbRefDomain = XSH_NAME_LEN; + + ::LookupAccountName(NULL, tszPrincipal, *ppSid, &cbSid, + tszRefDomain, &cbRefDomain, &snu); + + dwReturnValue = ::GetLastError(); + if (dwReturnValue != ERROR_INSUFFICIENT_BUFFER) + return dwReturnValue; + + dwReturnValue = ERROR_SUCCESS; + + *ppSid = (PSID)::LocalAlloc(LMEM_FIXED, cbSid); + if (*ppSid == NULL) + return ERROR_OUTOFMEMORY; + + cbRefDomain = XSH_NAME_LEN; + + if (!::LookupAccountName(NULL, tszPrincipal, *ppSid, &cbSid, + tszRefDomain, &cbRefDomain, &snu)) + { + dwReturnValue = ::GetLastError(); + ::LocalFree(*ppSid); + *ppSid = NULL; + } + + return dwReturnValue; +} + +DWORD COxtSecurityHelper::GetPrincipalSID(LPCTSTR tszPrincipal, PSID *ppSid) +{ + const TCHAR *tszStringSid = NULL; + DWORD i; + + *ppSid = NULL; + + for (i = 0; i < XSH_PRINCIPAL_COUNT; i++) + { + if (_tcsicmp(g_ptszPrincipals[i], tszPrincipal) == 0) + { + tszStringSid = g_ptszSidStrings[i]; + break; + } + } + + if (tszStringSid == NULL) + return ERROR_BAD_ARGUMENTS; + + if (!::ConvertStringSidToSid(tszStringSid, ppSid)) + { + *ppSid = NULL; + return ::GetLastError(); + } + + return ERROR_SUCCESS; +} + +DWORD COxtSecurityHelper::GetSecurityDescripterByName(LPCTSTR tszPermissionName, + SECURITY_DESCRIPTOR **ppSecurityDesc, + BOOL *pbNew) +{ + DWORD dwReturnValue = ERROR_SUCCESS; + HKEY hkeyReg = NULL; + DWORD dwType = 0; + DWORD cbSize = 0; + + if (pbNew) + *pbNew = FALSE; + + if (!ppSecurityDesc) + return ERROR_BAD_ARGUMENTS; + + *ppSecurityDesc = NULL; + + do { + // Get the security descriptor from the named value. If it doesn't + // exist, create a fresh one. + dwReturnValue = ::RegOpenKeyEx(HKEY_CLASSES_ROOT, m_tszAppIdKey, 0, KEY_ALL_ACCESS, &hkeyReg); + + if (dwReturnValue != ERROR_SUCCESS) + break; + + dwReturnValue = ::RegQueryValueEx(hkeyReg, tszPermissionName, NULL, &dwType, NULL, &cbSize); + + if ((dwReturnValue != ERROR_SUCCESS)&&(dwReturnValue != ERROR_INSUFFICIENT_BUFFER)) + break; + + *ppSecurityDesc = (SECURITY_DESCRIPTOR *)malloc(cbSize); + if (*ppSecurityDesc == NULL) + { + dwReturnValue = ERROR_OUTOFMEMORY; + break; + } + + dwReturnValue = ::RegQueryValueEx(hkeyReg, tszPermissionName, NULL, + &dwType, (LPBYTE)*ppSecurityDesc, &cbSize); + } while (false); + + + if (dwReturnValue != ERROR_SUCCESS) + { + if (*ppSecurityDesc) + free(*ppSecurityDesc); + *ppSecurityDesc = NULL; + + if (pbNew) + { + dwReturnValue = CreateNewSecurityDescriptor(ppSecurityDesc); + if (dwReturnValue == ERROR_SUCCESS) + *pbNew = TRUE; + } + } + + if (hkeyReg != NULL) + ::RegCloseKey(hkeyReg); + + return dwReturnValue; +} + +DWORD COxtSecurityHelper::SetSecurityDescriptorByName(LPCTSTR tszPermissionName, + SECURITY_DESCRIPTOR *pSecurityDesc) +{ + DWORD dwReturnValue = ERROR_SUCCESS; + DWORD dwDisposition = 0; + DWORD dwLength; + HKEY hkeyReg = NULL; + + // Create new key or open existing key + dwReturnValue = ::RegCreateKeyEx(HKEY_CLASSES_ROOT, m_tszAppIdKey, 0, _T(""), 0, + KEY_ALL_ACCESS, NULL, &hkeyReg, &dwDisposition); + if (dwReturnValue != ERROR_SUCCESS) + return dwReturnValue; + + // Write the security descriptor + dwLength = ::GetSecurityDescriptorLength(pSecurityDesc); + dwReturnValue = ::RegSetValueEx(hkeyReg, tszPermissionName, 0, REG_BINARY, + (LPBYTE)pSecurityDesc, dwLength); + ::RegCloseKey(hkeyReg); + + return dwReturnValue; +} + +DWORD COxtSecurityHelper::CanonicalizeSecurityDescriptor(PSECURITY_DESCRIPTOR pSD) +{ + BOOL bACLPresent = FALSE; + BOOL bDefaulted = FALSE; + ACL* pACL = NULL; + + if (!::GetSecurityDescriptorDacl(pSD, &bACLPresent, &pACL, &bDefaulted)) + return ::GetLastError(); + + ACCESS_MASK dwOtherRights = COM_RIGHTS_EXECUTE_LOCAL | + COM_RIGHTS_EXECUTE_REMOTE | + COM_RIGHTS_ACTIVATE_LOCAL | + COM_RIGHTS_ACTIVATE_REMOTE; + + DWORD dwSizeOfACL = sizeof(ACL); + ULONG_PTR ulptrACL = (ULONG_PTR)pACL; + PACE_HEADER pAceHeader = (PACE_HEADER)(ulptrACL + dwSizeOfACL); + PACCESS_MASK pAccessMask = (PACCESS_MASK)((ULONG_PTR)pAceHeader+sizeof(ACE_HEADER)); + + // Iterate through the ACE's in the ACL and canonicalize the representation + // Each ACE has a header and Mask Field as a minimum. + if (pACL != NULL) + { + for (int i = 0; i < pACL->AceCount; i++) + { + DWORD dwError = NULL; + void* pNewAcl = NULL; + + // Protect against bad ACL structure + if (((ULONG_PTR)pAceHeader-(ULONG_PTR)pACL) >= (pACL->AclSize - sizeof(ACCESS_MASK))) + return ERROR_INVALID_PARAMETER; + + DWORD dwAceSize = pAceHeader->AceSize; + + // Ensure minimum size ACE + if (dwAceSize < (sizeof(ACE_HEADER)+sizeof(ACCESS_MASK))) + return ERROR_INVALID_PARAMETER; + + // Canonicalize AccessMask + if (*pAccessMask & COM_RIGHTS_EXECUTE) + { + // When COM_RIGHTS_EXECUTE is set but no other RIGHTS + // This means grant all other RIGHTS + if ((*pAccessMask & dwOtherRights) == 0) + *pAccessMask |= dwOtherRights; + } + else + { + // COM_RIGHTS_EXECUTE Not Set so clear all other RIGHTS bits + *pAccessMask &= ~dwOtherRights; + } + + ulptrACL = (ULONG_PTR)pAceHeader; + pAceHeader = (PACE_HEADER)(ulptrACL + dwAceSize); + pAccessMask = (PACCESS_MASK)((ULONG_PTR)pAceHeader + sizeof(ACE_HEADER)); + } + } + + return ERROR_SUCCESS; +} + +DWORD COxtSecurityHelper::RemovePrincipalFromACL(PACL paclOrig, LPCTSTR tszPrincipal) +{ + ACL_SIZE_INFORMATION aclSizeInfo = {0}; + LONG i; + LPVOID pvAce = NULL; + ACCESS_DENIED_ACE *pAccessDeniedAce = NULL; + PSID psidPrincipal = NULL; + DWORD dwReturnValue = ERROR_SUCCESS; + ACE_HEADER *pAceHeader = NULL; + DWORD dwFoundValue = ERROR_FILE_NOT_FOUND; + + do { + dwReturnValue = GetPrincipalSID(tszPrincipal, &psidPrincipal); + if (dwReturnValue != ERROR_SUCCESS) + break; + + if (!::GetAclInformation(paclOrig, (LPVOID)&aclSizeInfo, + sizeof(ACL_SIZE_INFORMATION), AclSizeInformation)) + { + dwReturnValue = ::GetLastError(); + break; + } + + for (i = aclSizeInfo.AceCount - 1; i >= 0; i--) + { + if (!::GetAce(paclOrig, i, &pvAce)) + { + dwReturnValue = ::GetLastError(); + break; // inner loop + } + + pAceHeader = (ACE_HEADER*)pvAce; + + // Searching for ACCESS_DENIED_ACE_TYPE types only + if (pAceHeader->AceType == ACCESS_DENIED_ACE_TYPE) + { + pAccessDeniedAce = (ACCESS_DENIED_ACE*)pvAce; + + if (::EqualSid(psidPrincipal, (PSID)&pAccessDeniedAce->SidStart)) + { + if (pAccessDeniedAce->Mask & SPECIFIC_RIGHTS_ALL) + ::DeleteAce(paclOrig, i); + + dwFoundValue = ERROR_SUCCESS; + } + } + } + } while (false); + + if (psidPrincipal != NULL) + ::LocalFree(psidPrincipal); + + if (dwReturnValue == ERROR_SUCCESS) + dwReturnValue = dwFoundValue; + + return dwReturnValue; +} + +DWORD COxtSecurityHelper::UpdatePrincipalInACL(PACL paclOrig, LPCTSTR tszPrincipal, DWORD dwAccessMask) +{ + ACL_SIZE_INFORMATION aclSizeInfo = {0}; + LONG i; + LPVOID pvAce = NULL; + ACCESS_ALLOWED_ACE *pAccessAllowedAce = NULL; + ACCESS_DENIED_ACE *pAccessDeniedAce = NULL; + SYSTEM_AUDIT_ACE *pSystemAuditAce = NULL; + PSID psidPrincipal = NULL; + DWORD dwReturnValue = ERROR_SUCCESS; + ACE_HEADER *pAceHeader = NULL; + DWORD dwFoundValue = ERROR_FILE_NOT_FOUND; + + do { + // Construct a SID for this principal + dwReturnValue = GetPrincipalSID(tszPrincipal, &psidPrincipal); + if (dwReturnValue != ERROR_SUCCESS) + break; + + if (!::GetAclInformation(paclOrig, (LPVOID)&aclSizeInfo, + sizeof(ACL_SIZE_INFORMATION), AclSizeInformation)) + { + dwReturnValue = ::GetLastError(); + break; + } + + // Iterate through all of the ACEs in this ACL looking for a SID that corresponds + // to the principal. + for (i = aclSizeInfo.AceCount - 1; i >= 0; i--) + { + if (!::GetAce(paclOrig, i, &pvAce)) + { + dwReturnValue = ::GetLastError(); + break; // inner loop + } + + pAceHeader = (ACE_HEADER*)pvAce; + + // Searching for ACCESS_DENIED_ACE_TYPE types only + if (pAceHeader->AceType == ACCESS_ALLOWED_ACE_TYPE) + { + pAccessAllowedAce = (ACCESS_ALLOWED_ACE*)pvAce; + + if (::EqualSid(psidPrincipal, (PSID)&pAccessAllowedAce->SidStart)) + { + // Found an ACE, modify the mask bits + if (pAccessAllowedAce->Mask & SPECIFIC_RIGHTS_ALL) + { + pAccessAllowedAce->Mask &= ~dwAccessMask; + // If there are any COM rights reamining we must ensure + // COM_RIGHTS_EXECUTE is set before leaving. + if (pAccessAllowedAce->Mask & (COM_RIGHTS_ACTIVATE_LOCAL | + COM_RIGHTS_ACTIVATE_REMOTE | + COM_RIGHTS_EXECUTE_LOCAL | + COM_RIGHTS_EXECUTE_REMOTE)) + { + pAccessAllowedAce->Mask |= COM_RIGHTS_EXECUTE; + } + else if((pAccessAllowedAce->Mask & SPECIFIC_RIGHTS_ALL) == 0) + { + // If there are no more specific rights on this ACE, delete it. + ::DeleteAce(paclOrig, i); + } + } + else + { + pAccessAllowedAce->Mask |= dwAccessMask; + } + dwFoundValue = ERROR_SUCCESS; + } + } + } + } while (false); + + if (psidPrincipal != NULL) + ::LocalFree(psidPrincipal); + + if (dwReturnValue == ERROR_SUCCESS) + dwReturnValue = dwFoundValue; + + return dwReturnValue; +} + +DWORD COxtSecurityHelper::MakeAbsoluteSecurityDescriptor(PSECURITY_DESCRIPTOR psidOld, + PSECURITY_DESCRIPTOR *psidNew) +{ + PSECURITY_DESCRIPTOR pSid = NULL; + DWORD cbDescriptor = 0; + DWORD cbDacl = 0; + DWORD cbSacl = 0; + DWORD cbOwnerSID = 0; + DWORD cbGroupSID = 0; + PACL pDacl = NULL; + PACL pSacl = NULL; + PSID psidOwner = NULL; + PSID psidGroup = NULL; + BOOL bPresent = FALSE; + BOOL bSystemDefault = FALSE; + DWORD dwReturnValue = ERROR_SUCCESS; + + do { + if (!::GetSecurityDescriptorSacl(psidOld, &bPresent, &pSacl, &bSystemDefault)) + { + dwReturnValue = GetLastError(); + break; + } + + if ((pSacl != NULL)&&(bPresent)) + cbSacl = pSacl->AclSize; + + if (!::GetSecurityDescriptorDacl(psidOld, &bPresent, &pDacl, &bSystemDefault)) + { + dwReturnValue = GetLastError(); + break; + } + + if ((pDacl != NULL)&&(bPresent)) + cbDacl = pDacl->AclSize; + + if (!::GetSecurityDescriptorOwner(psidOld, &psidOwner, &bSystemDefault)) + { + dwReturnValue = GetLastError(); + break; + } + + cbOwnerSID = GetLengthSid(psidOwner); + + if (!::GetSecurityDescriptorGroup(psidOld, &psidGroup, &bSystemDefault)) + { + dwReturnValue = GetLastError(); + break; + } + + cbGroupSID = GetLengthSid(psidGroup); + + // Do the conversion + cbDescriptor = 0; + + ::MakeAbsoluteSD(psidOld, pSid, &cbDescriptor, pDacl, &cbDacl, pSacl, + &cbSacl, psidOwner, &cbOwnerSID, psidGroup, &cbGroupSID); + + pSid = (PSECURITY_DESCRIPTOR)malloc(cbDescriptor); + if (pSid == NULL) + { + dwReturnValue = ERROR_OUTOFMEMORY; + break; + } + + ::ZeroMemory(pSid, cbDescriptor); + + if (!::InitializeSecurityDescriptor(pSid, SECURITY_DESCRIPTOR_REVISION)) + { + dwReturnValue = GetLastError(); + break; + } + + if (!::MakeAbsoluteSD(psidOld, pSid, &cbDescriptor, pDacl, &cbDacl, pSacl, + &cbSacl, psidOwner, &cbOwnerSID, psidGroup, &cbGroupSID)) + { + dwReturnValue = GetLastError(); + break; + } + + } while (false); + + if ((dwReturnValue != ERROR_SUCCESS)&&(pSid != NULL)) + { + free(pSid); + pSid = NULL; + } + + *psidNew = pSid; + + return dwReturnValue; +} + +DWORD COxtSecurityHelper::RemovePrincipalFromSecurityDescriptor(LPCTSTR tszPermissionName, + LPCTSTR tszPrincipal) +{ + DWORD dwReturnValue = ERROR_SUCCESS; + SECURITY_DESCRIPTOR *pSD = NULL; + SECURITY_DESCRIPTOR *psdSelfRelative = NULL; + SECURITY_DESCRIPTOR *psdAbsolute = NULL; + DWORD cbSecurityDesc = 0; + BOOL bPresent = FALSE; + BOOL bDefaultDACL = FALSE; + PACL pDacl = NULL; + + do { + // Get security descriptor from registry, if it is not there then + // just return - nothing to do. + dwReturnValue = GetSecurityDescripterByName(tszPermissionName, &pSD, NULL); + if (dwReturnValue != ERROR_SUCCESS) + { + if (dwReturnValue == ERROR_FILE_NOT_FOUND) + dwReturnValue = ERROR_SUCCESS; + break; + } + + if (!::GetSecurityDescriptorDacl(pSD, &bPresent, &pDacl, &bDefaultDACL)) + { + dwReturnValue = ::GetLastError(); + break; + } + + // Remove the Principal that the caller wants removed + dwReturnValue = RemovePrincipalFromACL(pDacl, tszPrincipal); + if (dwReturnValue == ERROR_FILE_NOT_FOUND) + { + dwReturnValue = ERROR_SUCCESS; + break; + } + else if (dwReturnValue != ERROR_SUCCESS) + break; + + // Make the security descriptor absolute if it isn't new + dwReturnValue = MakeAbsoluteSecurityDescriptor((PSECURITY_DESCRIPTOR)pSD, (PSECURITY_DESCRIPTOR *)&psdAbsolute); + if (dwReturnValue != ERROR_SUCCESS) + break; + + // Set the discretionary ACL on the security descriptor + if (!::SetSecurityDescriptorDacl(psdAbsolute, TRUE, pDacl, FALSE)) + { + dwReturnValue = ::GetLastError(); + break; + } + + // Make the security descriptor self-relative so that we can + // store it in the registry + cbSecurityDesc = 0; + ::MakeSelfRelativeSD(psdAbsolute, psdSelfRelative, &cbSecurityDesc); + + psdSelfRelative = (SECURITY_DESCRIPTOR *)malloc(cbSecurityDesc); + if (psdSelfRelative == NULL) + { + dwReturnValue = ERROR_OUTOFMEMORY; + break; + } + + if (!::MakeSelfRelativeSD(psdAbsolute, psdSelfRelative, &cbSecurityDesc)) + { + dwReturnValue = ::GetLastError(); + break; + } + + // Store the security descriptor in the registry + dwReturnValue = SetSecurityDescriptorByName(tszPermissionName, psdSelfRelative); + } while (false); + + if (pSD != NULL) + free(pSD); + if (psdSelfRelative != NULL) + free(psdSelfRelative); + if (psdAbsolute != NULL) + free(psdAbsolute); + + return dwReturnValue; +} + +DWORD COxtSecurityHelper::UpdatePrincipalInNamedSecurityDescriptor(LPCTSTR tszPermissionName, + LPCTSTR tszPrincipal, + DWORD dwAccessMask) +{ + DWORD dwReturnValue = ERROR_SUCCESS; + SECURITY_DESCRIPTOR *pSD = NULL; + SECURITY_DESCRIPTOR *psdSelfRelative = NULL; + SECURITY_DESCRIPTOR *psdAbsolute = NULL; + DWORD cbSecurityDesc = 0; + BOOL bPresent = FALSE; + BOOL bDefaultDACL = FALSE; + PACL pDacl = NULL; + + do { + // Get security descriptor from registry + dwReturnValue = GetSecurityDescripterByName(tszPermissionName, &pSD, NULL); + if (dwReturnValue != ERROR_SUCCESS) + { + if (dwReturnValue == ERROR_FILE_NOT_FOUND) + dwReturnValue = ERROR_SUCCESS; + break; + } + + if (!::GetSecurityDescriptorDacl(pSD, &bPresent, &pDacl, &bDefaultDACL)) + { + dwReturnValue = ::GetLastError(); + break; + } + + // Update the tszPrincipal that the caller wants to change + dwReturnValue = UpdatePrincipalInACL(pDacl, tszPrincipal, dwAccessMask); + if(dwReturnValue == ERROR_FILE_NOT_FOUND) + { + dwReturnValue = ERROR_SUCCESS; + break; + } + else if (dwReturnValue != ERROR_SUCCESS) + { + dwReturnValue = ::GetLastError(); + break; + } + + // Make the security descriptor absolute + dwReturnValue = MakeAbsoluteSecurityDescriptor((PSECURITY_DESCRIPTOR)pSD, + (PSECURITY_DESCRIPTOR *)&psdAbsolute); + if (dwReturnValue != ERROR_SUCCESS) + break; + + // Set the discretionary ACL on the security descriptor + if (!::SetSecurityDescriptorDacl(psdAbsolute, TRUE, pDacl, FALSE)) + { + dwReturnValue = ::GetLastError(); + break; + } + + // Now ensure consistency of the SD + dwReturnValue = CanonicalizeSecurityDescriptor(psdAbsolute); + if (dwReturnValue != ERROR_SUCCESS) + break; + + // Make the security descriptor self-relative so that we can + // store it in the registry + cbSecurityDesc = 0; + ::MakeSelfRelativeSD(psdAbsolute, psdSelfRelative, &cbSecurityDesc); + + psdSelfRelative = (SECURITY_DESCRIPTOR *)malloc(cbSecurityDesc); + if (psdSelfRelative == NULL) + { + dwReturnValue = ERROR_OUTOFMEMORY; + break; + } + + if (!::MakeSelfRelativeSD(psdAbsolute, psdSelfRelative, &cbSecurityDesc)) + { + dwReturnValue = ::GetLastError(); + break; + } + + // Store the security descriptor in the registry + dwReturnValue = SetSecurityDescriptorByName(tszPermissionName, psdSelfRelative); + } while (false); + + if (pSD != NULL) + free(pSD); + if (psdSelfRelative != NULL) + free(psdSelfRelative); + if (psdAbsolute != NULL) + free(psdAbsolute); + + return dwReturnValue; +} + +DWORD COxtSecurityHelper::AddPrincipalToNamedSecurityDescriptor(LPCTSTR tszPermissionName, + LPCTSTR tszPrincipal, + DWORD dwAccessMask, + DWORD dwSDType) +{ + DWORD dwReturnValue = ERROR_SUCCESS; + SECURITY_DESCRIPTOR *pSD = NULL; + SECURITY_DESCRIPTOR *psdSelfRelative = NULL; + SECURITY_DESCRIPTOR *psdAbsolute = NULL; + DWORD cbSecurityDesc = 0; + BOOL bPresent = FALSE; + BOOL bDefaultDACL = FALSE; + PACL pDacl = NULL; + BOOL bNewSD = FALSE; + + do { + // Get security descriptor from registry or create a new one + dwReturnValue = GetSecurityDescripterByName(tszPermissionName, &pSD, &bNewSD); + if (dwReturnValue != ERROR_SUCCESS) + break; + + if (!::GetSecurityDescriptorDacl(pSD, &bPresent, &pDacl, &bDefaultDACL)) + { + dwReturnValue = ::GetLastError(); + break; + } + + if (bNewSD) + { + dwReturnValue = SetACLDefaults(&pDacl, dwSDType); + if (dwReturnValue != ERROR_SUCCESS) + break; + } + + // Add the Principal that the caller wants added + dwReturnValue = AddAccessDeniedACEToACL(&pDacl, dwAccessMask, tszPrincipal); + if (dwReturnValue != ERROR_SUCCESS) + break; + + // Make the security descriptor absolute if it isn't new + if (!bNewSD) + { + dwReturnValue = MakeAbsoluteSecurityDescriptor((PSECURITY_DESCRIPTOR)pSD, + (PSECURITY_DESCRIPTOR *)&psdAbsolute); + if (dwReturnValue != ERROR_SUCCESS) + break; + } + else + psdAbsolute = pSD; + + // Set the discretionary ACL on the security descriptor + if (!::SetSecurityDescriptorDacl(psdAbsolute, TRUE, pDacl, FALSE)) + { + dwReturnValue = ::GetLastError(); + break; + } + + // Now ensure consistency of the SD + dwReturnValue = CanonicalizeSecurityDescriptor(psdAbsolute); + if (dwReturnValue != ERROR_SUCCESS) + break; + + // Make the security descriptor self-relative so that we can + // store it in the registry + cbSecurityDesc = 0; + + ::MakeSelfRelativeSD(psdAbsolute, psdSelfRelative, &cbSecurityDesc); + + psdSelfRelative = (SECURITY_DESCRIPTOR *)malloc(cbSecurityDesc); + + if (psdSelfRelative == NULL) + { + dwReturnValue = ERROR_OUTOFMEMORY; + break; + } + + if (!::MakeSelfRelativeSD(psdAbsolute, psdSelfRelative, &cbSecurityDesc)) + { + dwReturnValue = GetLastError(); + break; + } + + // Store the security descriptor in the registry + dwReturnValue = SetSecurityDescriptorByName(tszPermissionName, psdSelfRelative); + } while (false); + + + if (pSD != NULL) + free(pSD); + if (psdSelfRelative != NULL) + free(psdSelfRelative); + if ((psdAbsolute != NULL)&&(pSD != psdAbsolute)) + free(psdAbsolute); + + return dwReturnValue; +} + +void COxtSecurityHelper::DenyRemoteAccess() +{ + DWORD dwRet = ERROR_SUCCESS; + int i; + + for (i = 0; i < XSH_PRINCIPAL_COUNT; i++) + { + // Loop and update each of the 3 Principals with deny remote + // access SDs. + dwRet = RemovePrincipalFromSecurityDescriptor(_T("AccessPermission"), + g_ptszPrincipals[i]); + if (dwRet != ERROR_SUCCESS) + { + LogSecuritySetupFailure(g_ptszPrincipals[i], + _T("AccessPermission"), + _T("RemovePrincipalFromSecurityDescriptor"), + dwRet); + break; + } + + dwRet = UpdatePrincipalInNamedSecurityDescriptor(_T("AccessPermission"), + g_ptszPrincipals[i], + g_dwAccessAccessMask); + if (dwRet != ERROR_SUCCESS) + { + LogSecuritySetupFailure(g_ptszPrincipals[i], + _T("AccessPermission"), + _T("UpdatePrincipalInNamedSecurityDescriptor"), + dwRet); + break; + } + + dwRet = AddPrincipalToNamedSecurityDescriptor(_T("AccessPermission"), + g_ptszPrincipals[i], + g_dwAccessAccessMask, + SDTYPE_APPLICATION_ACCESS); + if (dwRet != ERROR_SUCCESS) + { + LogSecuritySetupFailure(g_ptszPrincipals[i], + _T("AccessPermission"), + _T("AddPrincipalToNamedSecurityDescriptor"), + dwRet); + break; + } + } +} + +void COxtSecurityHelper::DenyRemoteLaunchAndActivate() +{ + DWORD dwRet = ERROR_SUCCESS; + int i; + + for (i = 0; i < XSH_PRINCIPAL_COUNT; i++) + { + // Loop and update each of the 3 Principals with deny remote + // access SDs. + dwRet = RemovePrincipalFromSecurityDescriptor(_T("LaunchPermission"), + g_ptszPrincipals[i]); + if (dwRet != ERROR_SUCCESS) + { + LogSecuritySetupFailure(g_ptszPrincipals[i], + _T("LaunchPermission"), + _T("RemovePrincipalFromSecurityDescriptor"), + dwRet); + break; + } + + dwRet = UpdatePrincipalInNamedSecurityDescriptor(_T("LaunchPermission"), + g_ptszPrincipals[i], + g_dwLaunchActivateMask); + if (dwRet != ERROR_SUCCESS) + { + LogSecuritySetupFailure(g_ptszPrincipals[i], + _T("LaunchPermission"), + _T("UpdatePrincipalInNamedSecurityDescriptor"), + dwRet); + break; + } + + dwRet = AddPrincipalToNamedSecurityDescriptor(_T("LaunchPermission"), + g_ptszPrincipals[i], + g_dwLaunchActivateMask, + SDTYPE_APPLICATION_LAUNCH); + if (dwRet != ERROR_SUCCESS) + { + LogSecuritySetupFailure(g_ptszPrincipals[i], + _T("LaunchPermission"), + _T("AddPrincipalToNamedSecurityDescriptor"), + dwRet); + break; + } + } +} + +void COxtSecurityHelper::LogDenyCheckFailure(LPCTSTR tszPermissionName, + LPCTSTR tszOp) +{ + m_pclOxtSvc->LogEventTypeId(ctxLS(IDS_DENY_CHECK_FAILURE___PERMISSION__OXTSECURITYHELPER_1244), + EVENTLOG_ERROR_TYPE, + EVMSG_SECURITY_FAILURE, + tszPermissionName, + tszOp, + ::GetLastError()); +} + +bool COxtSecurityHelper::DenyCheckUser(DWORD dwAccessMask, + DWORD dwSDType, + LPCTSTR tszUser, + LPCTSTR tszDomain, + BOOL bPermit) +{ + + if (IsLegacySecurityModel()) + { + // We don't really support anything lower than XPSP3 so we will just + // drop out on the legacy check. + // NOTE: removed check for WarnIfGlobalPolicySet() + return true; + } + + // All local access is fine and this check is not concerned with whether + // everything has been denied. So the only case that is bad is permitting + // remote access. + + if (dwSDType & SDTYPE_APPLICATION_ACCESS) + { + BOOL bRemoteAccess = (dwAccessMask & COM_RIGHTS_EXECUTE_REMOTE ) || + ((dwAccessMask & COM_RIGHTS_EXECUTE) && + !(dwAccessMask & COM_RIGHTS_EXECUTE_LOCAL)); + + if ((bPermit)&&(bRemoteAccess)) + { + m_pclOxtSvc->LogEventTypeId(ctxLS(IDS_DENY_REMOTE_CHECK_FOR_zS_DETECTE_OXTSECURITYHELPER_1279), + EVENTLOG_ERROR_TYPE, EVMSG_SECURITY_FAILURE, + _T("AccessPermission")); + return false; + } + } + + if (dwSDType & SDTYPE_APPLICATION_LAUNCH) + { + BOOL bRemoteLaunchAccess = (dwAccessMask & COM_RIGHTS_EXECUTE_REMOTE ) || + ((dwAccessMask & COM_RIGHTS_EXECUTE) && + !(dwAccessMask & (COM_RIGHTS_EXECUTE_LOCAL | + COM_RIGHTS_ACTIVATE_REMOTE | + COM_RIGHTS_ACTIVATE_LOCAL))); + + BOOL bRemoteActivateAccess = (dwAccessMask & COM_RIGHTS_ACTIVATE_REMOTE) || + ((dwAccessMask & COM_RIGHTS_EXECUTE) && + !(dwAccessMask & (COM_RIGHTS_EXECUTE_LOCAL | + COM_RIGHTS_EXECUTE_REMOTE | + COM_RIGHTS_ACTIVATE_LOCAL))); + if ((bPermit)&&(bRemoteLaunchAccess)) + { + m_pclOxtSvc->LogEventTypeId(ctxLS(IDS_DENY_REMOTE_CHECK_FOR_zS_DETECTE_OXTSECURITYHELPER_1301), + EVENTLOG_ERROR_TYPE, EVMSG_SECURITY_FAILURE, + _T("LaunchPermission-Launch")); + return false; + } + + if ((bPermit)&&(bRemoteActivateAccess)) + { + m_pclOxtSvc->LogEventTypeId(ctxLS(IDS_DENY_REMOTE_CHECK_FOR_zS_DETECTE_OXTSECURITYHELPER_1309), + EVENTLOG_ERROR_TYPE, EVMSG_SECURITY_FAILURE, + _T("LaunchPermission-Activate")); + return false; + } + } + + return true; +} + +bool COxtSecurityHelper::DenyCheckACL(PACL pACL, LPCTSTR tszPermissionName, DWORD dwSDType) +{ + ACL_SIZE_INFORMATION aclSizeInfo = {0}; + ACL_REVISION_INFORMATION aclRevInfo = {0}; + ULONG i; + LPVOID pvAce = NULL; + ACE_HEADER *pAceHeader = NULL; + ACCESS_ALLOWED_ACE *pAccessAllowedAce = NULL; + ACCESS_DENIED_ACE *pAccessDeniedAce = NULL; + TCHAR tszDomainName[XSH_NAME_LEN + 1] = {0}; + TCHAR tszUserName[XSH_NAME_LEN + 1] = {0}; + DWORD cchName = 0; + SID_NAME_USE snu; + BOOL rc; + BOOL bPermit; + PSID pSID; + ACCESS_MASK dwMask; + + if (!::GetAclInformation(pACL, &aclSizeInfo, sizeof(ACL_SIZE_INFORMATION), AclSizeInformation)) + { + LogDenyCheckFailure(tszPermissionName, _T("GET AclSizeInformation")); + return false; + } + + if (!::GetAclInformation(pACL, &aclRevInfo, sizeof(ACL_REVISION_INFORMATION), AclRevisionInformation)) + { + LogDenyCheckFailure(tszPermissionName, _T("GET AclRevisionInformation")); + return false; + } + + for (i = 0; i < aclSizeInfo.AceCount; i++) + { + rc = ::GetAce(pACL, i, &pvAce); + if (!rc) + { + LogDenyCheckFailure(tszPermissionName, _T("GetAce")); + return false; + } + + pAceHeader = (ACE_HEADER*)pvAce; + + if (pAceHeader->AceType == ACCESS_ALLOWED_ACE_TYPE) + { + pAccessAllowedAce = (ACCESS_ALLOWED_ACE*)pvAce; + pSID = (PSID)&pAccessAllowedAce->SidStart; + dwMask = pAccessAllowedAce->Mask; + bPermit = TRUE; + } + else if (pAceHeader->AceType == ACCESS_DENIED_ACE_TYPE) + { + pAccessDeniedAce = (ACCESS_DENIED_ACE*)pvAce; + pSID = (PSID)&pAccessDeniedAce->SidStart; + dwMask = pAccessDeniedAce->Mask; + bPermit = FALSE; + } + + cchName = XSH_NAME_LEN; + rc = ::LookupAccountSid(NULL, + pSID, + tszUserName, + &cchName, + tszDomainName, + &cchName, + &snu); + + if (!rc) + { + LogDenyCheckFailure(tszPermissionName, _T("LookupAccountSid")); + return false; + } + + rc = DenyCheckUser(dwMask, + dwSDType, + tszUserName, + tszDomainName, + bPermit); + if (!rc) + return false; + } + + return true; +} + +bool COxtSecurityHelper::CheckDenyRemoteAccess() +{ + DWORD dwReturnValue = ERROR_SUCCESS; + SECURITY_DESCRIPTOR *pSD = NULL; + BOOL bPresent = FALSE; + BOOL bDefaultDACL = FALSE; + PACL pDACL = NULL; + bool rc = true; + + // First test AccessPermission for denied remote access + do { + dwReturnValue = GetSecurityDescripterByName(_T("AccessPermission"), &pSD, NULL); + if (dwReturnValue != ERROR_SUCCESS) + { + // using default, no SD for this permission + LogDenyCheckFailure(_T("AccessPermission"), _T("NO SD (using defaults)")); + rc = false; + break; + } + + if (!::GetSecurityDescriptorDacl(pSD, &bPresent, &pDACL, &bDefaultDACL)) + { + LogDenyCheckFailure(_T("AccessPermission"), _T("GET SD DACL")); + rc = false; + break; + } + + if (!bPresent) + { + m_pclOxtSvc->LogEventTypeId(ctxLS(IDS_DENY_CHECK_FOUND_NO_SD_DACL_FOR__OXTSECURITYHELPER_1431), + EVENTLOG_WARNING_TYPE, EVMSG_SECURITY_WARNING, + _T("AccessPermission")); + // go on with other checks for launch access below + break; + } + + rc = DenyCheckACL(pDACL, _T("AccessPermission"), SDTYPE_APPLICATION_ACCESS); + // Specific issues logged in call + } while (false); + + if (pSD != NULL) + { + free(pSD); + pSD = NULL; + } + + if (!rc) + return false; // first check failed + + dwReturnValue = ERROR_SUCCESS; + bPresent = FALSE; + bDefaultDACL = FALSE; + pDACL = NULL; + + // Now test LaunchPermission for denied remote access + do { + dwReturnValue = GetSecurityDescripterByName(_T("LaunchPermission"), &pSD, NULL); + if (dwReturnValue != ERROR_SUCCESS) + { + // using default, no SD for this permission + LogDenyCheckFailure(_T("AccessPermission"), _T("NO SD (using defaults)")); + rc = false; + break; + } + + if (!::GetSecurityDescriptorDacl(pSD, &bPresent, &pDACL, &bDefaultDACL)) + { + LogDenyCheckFailure(_T("LaunchPermission"), _T("GET SD DACL")); + rc = false; + break; + } + + if (!bPresent) + { + m_pclOxtSvc->LogEventTypeId(ctxLS(IDS_DENY_CHECK_FOUND_NO_SD_DACL_FOR__OXTSECURITYHELPER_1476), + EVENTLOG_WARNING_TYPE, EVMSG_SECURITY_WARNING, + _T("LaunchPermission")); + // go on with other checks for launch access below + break; + } + + rc = DenyCheckACL(pDACL, _T("LaunchPermission"), SDTYPE_APPLICATION_LAUNCH); + // Specific issues logged in call + } while (false); + + if (pSD != NULL) + { + free(pSD); + pSD = NULL; + } + + return rc; +} + +// DACL to allow interactive users access to named events and objects +static const WCHAR g_XgsEventDACL[] = +{ + SDDL_DACL SDDL_DELIMINATOR SDDL_PROTECTED + + // Local system - full access + SDDL_ACE_BEGIN + SDDL_ACCESS_ALLOWED + SDDL_SEPERATOR + SDDL_SEPERATOR + SDDL_GENERIC_ALL + SDDL_SEPERATOR + SDDL_SEPERATOR + SDDL_SEPERATOR + SDDL_LOCAL_SYSTEM + SDDL_ACE_END + + // Creator/Owner - full access + SDDL_ACE_BEGIN + SDDL_ACCESS_ALLOWED + SDDL_SEPERATOR + SDDL_SEPERATOR + SDDL_GENERIC_ALL + SDDL_SEPERATOR + SDDL_SEPERATOR + SDDL_SEPERATOR + SDDL_CREATOR_OWNER + SDDL_ACE_END + + // LocalService - All access. + SDDL_ACE_BEGIN + SDDL_ACCESS_ALLOWED + SDDL_SEPERATOR + SDDL_SEPERATOR + SDDL_GENERIC_ALL + SDDL_SEPERATOR + SDDL_SEPERATOR + SDDL_SEPERATOR + SDDL_LOCAL_SERVICE + SDDL_ACE_END + + // Interactive - All access. + SDDL_ACE_BEGIN + SDDL_ACCESS_ALLOWED + SDDL_SEPERATOR + SDDL_SEPERATOR + SDDL_GENERIC_ALL + SDDL_SEPERATOR + SDDL_SEPERATOR + SDDL_SEPERATOR + SDDL_INTERACTIVE + SDDL_ACE_END +}; + +SECURITY_ATTRIBUTES* COxtSecurityHelper::CreateXgaSecurityAttributes() +{ + SECURITY_ATTRIBUTES *pSA = NULL; + PSECURITY_DESCRIPTOR pSD = NULL; + BOOL rc; + + pSA = (SECURITY_ATTRIBUTES*)::LocalAlloc(LMEM_FIXED, sizeof(SECURITY_ATTRIBUTES)); + if (pSA == NULL) + { + m_pclOxtSvc->LogEventTypeId(ctxLS(IDS_FAILED_TO_ALLOCATE_SECURITY_ATTR_OXTSECURITYHELPER_1559), + EVENTLOG_ERROR_TYPE, EVMSG_SECURITY_FAILURE); + return NULL; + } + pSA->nLength = sizeof(SECURITY_ATTRIBUTES); + pSA->bInheritHandle = FALSE; + + rc = ::ConvertStringSecurityDescriptorToSecurityDescriptor(g_XgsEventDACL, SDDL_REVISION_1, &pSD, NULL); + if ((!rc)||(pSD == NULL)) + { + m_pclOxtSvc->LogEventTypeId(ctxLS(IDS_FAILED_TO_CREATE_SECURITY_DESCRI_OXTSECURITYHELPER_1569), + EVENTLOG_ERROR_TYPE, EVMSG_SECURITY_FAILURE, + (pSD == NULL) ? ERROR_OUTOFMEMORY : ::GetLastError()); + ::LocalFree(pSA); + return NULL; + } + pSA->lpSecurityDescriptor = pSD; + + return pSA; +} + +SECURITY_ATTRIBUTES* COxtSecurityHelper::CreateXgaSecurityAttributesAbsolute() +{ + DWORD dwRet = ERROR_SUCCESS; + PSECURITY_DESCRIPTOR pSD = NULL; + PSECURITY_ATTRIBUTES pSA; + ULONG ulSdSize = 0; + ULONG ulDaclSize = 0; + ULONG ulSaclSize = 0; + ULONG ulOwnerSize = 0; + ULONG ulGroupSize = 0; + ULONG ulNewSdSize = 0; + PACL pDACL; + PACL pSACL; + PSID pOwner; + PSID pGroup; + + // First create our relate descriptor + pSA = CreateXgaSecurityAttributes(); + if (pSA == NULL) + return NULL; + + // Determine buffer size needed to convert self-relative SD to absolute. + if (!::MakeAbsoluteSD(pSA->lpSecurityDescriptor, + NULL, &ulSdSize, + NULL, &ulDaclSize, + NULL, &ulSaclSize, + NULL, &ulOwnerSize, + NULL, &ulGroupSize)) + { + dwRet = GetLastError(); + } + + if (dwRet != ERROR_INSUFFICIENT_BUFFER) + { + m_pclOxtSvc->LogEventTypeId(ctxLS(IDS_FAILED_TO_GET_SIZES_FROM_MAKEABS_OXTSECURITYHELPER_1614), + EVENTLOG_ERROR_TYPE, EVMSG_SECURITY_FAILURE, dwRet); + FreeXgaSecurityAttributes(pSA); + return NULL; + } + + // Allocate memory for the absolute SD and setup various pointers + ulNewSdSize = ulSdSize + ulDaclSize + ulSaclSize + ulOwnerSize + ulGroupSize; + pSD = (SECURITY_DESCRIPTOR*)::LocalAlloc(LMEM_FIXED, ulNewSdSize); + if (pSD == NULL) + { + m_pclOxtSvc->LogEventTypeId(ctxLS(IDS_FAILED_TO_ALLOCATE_SECURITY_DESC_OXTSECURITYHELPER_1625), + EVENTLOG_ERROR_TYPE, EVMSG_SECURITY_FAILURE); + FreeXgaSecurityAttributes(pSA); + return NULL; + } + + pDACL = (PACL)((PCHAR)pSD + ulSdSize); + pSACL = (PACL)((PCHAR)pDACL + ulDaclSize); + pOwner = (PSID)((PCHAR)pSACL + ulSaclSize); + pGroup = (PSID)((PCHAR)pOwner + ulOwnerSize); + + // Now convert self-relative SD to absolute format. + if (!::MakeAbsoluteSD(pSA->lpSecurityDescriptor, + pSD, &ulSdSize, + pDACL, &ulDaclSize, + pSACL, &ulSaclSize, + pOwner, &ulOwnerSize, + pGroup, &ulGroupSize)) + { + m_pclOxtSvc->LogEventTypeId(ctxLS(IDS_FAILED_CREATE_SD_IN_MAKEABSOLUTE_OXTSECURITYHELPER_1644), + EVENTLOG_ERROR_TYPE, EVMSG_SECURITY_FAILURE, ::GetLastError()); + ::LocalFree(pSD); + FreeXgaSecurityAttributes(pSA); + return NULL; + } + + // Free the original SD and set the new one. + ::LocalFree(pSA->lpSecurityDescriptor); + pSA->lpSecurityDescriptor = pSD; + + return pSA; +} + +void COxtSecurityHelper::FreeXgaSecurityAttributes(SECURITY_ATTRIBUTES *pSA) +{ + if (pSA != NULL) + { + if (pSA->lpSecurityDescriptor != NULL) + ::LocalFree(pSA->lpSecurityDescriptor); + ::LocalFree(pSA); + } +} + +WINADVAPI +BOOL +WINAPI +CreateWellKnownSid( + __in WELL_KNOWN_SID_TYPE WellKnownSidType, + __in_opt PSID DomainSid, + __out_bcount_part_opt(*cbSid, *cbSid) PSID pSid, + __inout DWORD *cbSid + ); + +XSH_DESCRIPTOR* COxtSecurityHelper::CreateXgaComSecurityDescriptor() +{ + DWORD dwRet; + DWORD dwSidSize; + BOOL bRet; + XSH_DESCRIPTOR *pXD = NULL; + EXPLICIT_ACCESS ea = {0}; + + pXD = (XSH_DESCRIPTOR*)::LocalAlloc(LMEM_FIXED, sizeof(XSH_DESCRIPTOR)); + if (pXD == NULL) + { + m_pclOxtSvc->LogEventTypeId(ctxLS(IDS_FAILED_TO_ALLOCATE_XSH_DESCRIPTO_OXTSECURITYHELPER_1689), + EVENTLOG_ERROR_TYPE, EVMSG_SECURITY_FAILURE); + return NULL; + } + ::ZeroMemory(pXD, sizeof(XSH_DESCRIPTOR)); + + do { + bRet = ::InitializeSecurityDescriptor(&pXD->stSD, SECURITY_DESCRIPTOR_REVISION); + if (!bRet) + { + m_pclOxtSvc->LogEventTypeId(ctxLS(IDS_FAILED_TO_INITIALIZE_COM_SID___E_OXTSECURITYHELPER_1699), + EVENTLOG_ERROR_TYPE, EVMSG_SECURITY_FAILURE, ::GetLastError()); + break; + } + + // Create some SIDs + dwSidSize = SECURITY_MAX_SID_SIZE; + pXD->pInteractivSID = (PSID*)::LocalAlloc(LMEM_FIXED, dwSidSize); + if (pXD->pInteractivSID == NULL) + { + m_pclOxtSvc->LogEventTypeId(ctxLS(IDS_FAILED_TO_ALLOCATE_PINTERACTIVSI_OXTSECURITYHELPER_1709), + EVENTLOG_ERROR_TYPE, EVMSG_SECURITY_FAILURE); + bRet = FALSE; + break; + } + + pXD->pAdminsSID = (PSID*)::LocalAlloc(LMEM_FIXED, dwSidSize); + if (pXD->pAdminsSID == NULL) + { + m_pclOxtSvc->LogEventTypeId(ctxLS(IDS_FAILED_TO_ALLOCATE_ADMINS_SID_OXTSECURITYHELPER_1718), + EVENTLOG_ERROR_TYPE, EVMSG_SECURITY_FAILURE); + bRet = FALSE; + break; + } + + bRet = ::CreateWellKnownSid(WinInteractiveSid, NULL, pXD->pInteractivSID, &dwSidSize); + if (!bRet) + { + m_pclOxtSvc->LogEventTypeId(ctxLS(IDS_FAILED_CREATEWELLKNOWNSID_PINTER_OXTSECURITYHELPER_1727), + EVENTLOG_ERROR_TYPE, EVMSG_SECURITY_FAILURE, ::GetLastError()); + break; + } + + dwSidSize = SECURITY_MAX_SID_SIZE; + bRet = ::CreateWellKnownSid(WinBuiltinAdministratorsSid, NULL, pXD->pAdminsSID, &dwSidSize); + if (!bRet) + { + m_pclOxtSvc->LogEventTypeId(ctxLS(IDS_FAILED_CREATEWELLKNOWNSID_PADMIN_OXTSECURITYHELPER_1736), + EVENTLOG_ERROR_TYPE, EVMSG_SECURITY_FAILURE, ::GetLastError()); + break; + } + + // Setup AuthenticatedUsers for COM access. + ea.grfAccessPermissions = COM_RIGHTS_EXECUTE; + ea.grfAccessMode = SET_ACCESS; + ea.grfInheritance = NO_INHERITANCE; + ea.Trustee.pMultipleTrustee = NULL; + ea.Trustee.MultipleTrusteeOperation = NO_MULTIPLE_TRUSTEE; + ea.Trustee.TrusteeForm = TRUSTEE_IS_SID; + ea.Trustee.TrusteeType = TRUSTEE_IS_GROUP; + ea.Trustee.ptstrName = (LPTSTR)pXD->pInteractivSID; + + // Create the Interactive user ACL with this new ACE + dwRet = ::SetEntriesInAcl(1, &ea, NULL, &pXD->pACL); + if (dwRet != ERROR_SUCCESS) + { + m_pclOxtSvc->LogEventTypeId(ctxLS(IDS_FAILED_SETENTRIESINACL_PINTERACT_OXTSECURITYHELPER_1755), + EVENTLOG_ERROR_TYPE, EVMSG_SECURITY_FAILURE, dwRet); + bRet = FALSE; + break; + } + + // Setup Administrator as owner and group for SD + bRet = ::SetSecurityDescriptorOwner(&pXD->stSD, pXD->pAdminsSID, FALSE); + if (!bRet) + { + m_pclOxtSvc->LogEventTypeId(ctxLS(IDS_FAILED_TO_SET_ADMINS_SID_AS_OWNE_OXTSECURITYHELPER_1765), + EVENTLOG_ERROR_TYPE, EVMSG_SECURITY_FAILURE, ::GetLastError()); + break; + } + + bRet = ::SetSecurityDescriptorGroup(&pXD->stSD, pXD->pAdminsSID, FALSE); + if (!bRet) + { + m_pclOxtSvc->LogEventTypeId(ctxLS(IDS_FAILED_TO_SET_ADMINS_SID_AS_GROU_OXTSECURITYHELPER_1773), + EVENTLOG_ERROR_TYPE, EVMSG_SECURITY_FAILURE, ::GetLastError()); + break; + } + + // Set ACL on descriptor + bRet = ::SetSecurityDescriptorDacl(&pXD->stSD, TRUE, pXD->pACL, FALSE); + if (!bRet) + { + m_pclOxtSvc->LogEventTypeId(ctxLS(IDS_FAILED_TO_SET_DACL_FOR_SD___ERRO_OXTSECURITYHELPER_1782), + EVENTLOG_ERROR_TYPE, EVMSG_SECURITY_FAILURE, ::GetLastError()); + break; + } + + } while (false); + + if (!bRet) + { + FreeXgaComSecurityDescriptor(pXD); + pXD = NULL; + } + + return pXD; +} + +void COxtSecurityHelper::FreeXgaComSecurityDescriptor(XSH_DESCRIPTOR* pXD) +{ + if (pXD != NULL) + { + if (pXD->pACL != NULL) + ::LocalFree(pXD->pACL); + if (pXD->pAdminsSID != NULL) + ::LocalFree(pXD->pAdminsSID); + if (pXD->pInteractivSID != NULL) + ::LocalFree(pXD->pInteractivSID); + ::LocalFree(pXD); + } +} + diff --git a/OxtService/OxtSecurityHelper.h b/OxtService/OxtSecurityHelper.h new file mode 100644 index 0000000..4583601 --- /dev/null +++ b/OxtService/OxtSecurityHelper.h @@ -0,0 +1,115 @@ +/* + * Copyright (c) 2012 Citrix Systems, Inc. + * Copyright (c) 2016 Assured Information Security, Inc + * + * Permission is hereby granted, free of charge, to any person obtaining a copy + * of this software and associated documentation files (the "Software"), to deal + * in the Software without restriction, including without limitation the rights + * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell + * copies of the Software, and to permit persons to whom the Software is + * furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included in + * all copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE + * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER + * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, + * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN + * THE SOFTWARE. + */ + + +#pragma once +#include "resource.h" // main symbols +#include "OxtService.h" + +#define XSH_APPID_LEN 45 + +typedef struct _XSH_DESCRIPTOR +{ + SECURITY_DESCRIPTOR stSD; + PACL pACL; + PSID pAdminsSID; + PSID pInteractivSID; +} XSH_DESCRIPTOR, *PXSH_DESCRIPTOR; + +class COxtSecurityHelper +{ +private: + COxtService *m_pclOxtSvc; + TCHAR m_tszAppIdKey[XSH_APPID_LEN + 1]; + +public: + COxtSecurityHelper(COxtService *pclOxtSvc) + { + m_pclOxtSvc = pclOxtSvc; + _sntprintf_s(m_tszAppIdKey, XSH_APPID_LEN, _TRUNCATE, _T("APPID\\%s"), CA2T(APPID_OxtService)); + m_tszAppIdKey[XSH_APPID_LEN] = _T('\0'); + } + + ~COxtSecurityHelper() + { + } + + void DenyRemoteAccess(); + void DenyRemoteLaunchAndActivate(); + bool CheckDenyRemoteAccess(); + + SECURITY_ATTRIBUTES* CreateXgaSecurityAttributes(); + SECURITY_ATTRIBUTES* CreateXgaSecurityAttributesAbsolute(); + void FreeXgaSecurityAttributes(SECURITY_ATTRIBUTES *pSA); + + XSH_DESCRIPTOR* CreateXgaComSecurityDescriptor(); + void FreeXgaComSecurityDescriptor(XSH_DESCRIPTOR* pXD); + +private: + void LogSecuritySetupFailure(LPCTSTR tszPrincipal, + LPCTSTR tszPermissionName, + LPCTSTR tszOp, + DWORD dwError); + bool IsLegacySecurityModel(); + DWORD CopyACL(PACL paclOld, PACL paclNew); + DWORD AddAccessAllowedACEToACL(PACL *paclOrig, + DWORD dwAccessMask, + LPCTSTR tszPrincipal); + DWORD AddAccessDeniedACEToACL(PACL *paclOrig, + DWORD dwAccessMask, + LPCTSTR tszPrincipal); + DWORD SetLegacyACLDefaults(PACL *ppDacl, DWORD dwSDType); + DWORD SetACLDefaults(PACL *ppDacl, DWORD dwSDType); + DWORD CreateNewSecurityDescriptor(SECURITY_DESCRIPTOR **ppSecurityDesc); + DWORD GetPrincipalSIDByName(LPCTSTR tszPrincipal, PSID *ppSid); + DWORD GetPrincipalSID(LPCTSTR tszPrincipal, PSID *ppSid); + DWORD GetSecurityDescripterByName(LPCTSTR tszPermissionName, + SECURITY_DESCRIPTOR **ppSecurityDesc, + BOOL *pbNew); + DWORD SetSecurityDescriptorByName(LPCTSTR tszPermissionName, + SECURITY_DESCRIPTOR *pSecurityDesc); + DWORD CanonicalizeSecurityDescriptor(PSECURITY_DESCRIPTOR pSD); + DWORD RemovePrincipalFromACL(PACL paclOrig, LPCTSTR tszPrincipal); + DWORD UpdatePrincipalInACL(PACL paclOrig, + LPCTSTR tszPrincipal, + DWORD dwAccessMask); + DWORD MakeAbsoluteSecurityDescriptor(PSECURITY_DESCRIPTOR psidOld, + PSECURITY_DESCRIPTOR *psidNew); + DWORD RemovePrincipalFromSecurityDescriptor(LPCTSTR tszPermissionName, + LPCTSTR tszPrincipal); + DWORD UpdatePrincipalInNamedSecurityDescriptor(LPCTSTR tszPermissionName, + LPCTSTR tszPrincipal, + DWORD dwAccessMask); + DWORD AddPrincipalToNamedSecurityDescriptor(LPCTSTR tszPermissionName, + LPCTSTR tszPrincipal, + DWORD dwAccessMask, + DWORD dwSDType); + void LogDenyCheckFailure(LPCTSTR tszPermissionName, + LPCTSTR tszOp); + bool DenyCheckUser(DWORD dwAccessMask, + DWORD dwSDType, + LPCTSTR tszUser, + LPCTSTR tszDomain, + BOOL bPermit); + bool DenyCheckACL(PACL pACL, LPCTSTR tszPermissionName, DWORD dwSDType); +}; diff --git a/OxtService/OxtService.cpp b/OxtService/OxtService.cpp new file mode 100644 index 0000000..f0144e5 --- /dev/null +++ b/OxtService/OxtService.cpp @@ -0,0 +1,888 @@ +/* + * Copyright (c) 2014 Citrix Systems, Inc. + * Copyright (c) 2016 Assured Information Security, Inc. + * + * Permission is hereby granted, free of charge, to any person obtaining a copy + * of this software and associated documentation files (the "Software"), to deal + * in the Software without restriction, including without limitation the rights + * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell + * copies of the Software, and to permit persons to whom the Software is + * furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included in + * all copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE + * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER + * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, + * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN + * THE SOFTWARE. + */ + +// OxtService.cpp : Implementation of WinMain + +#include "stdafx.h" +#include "resource.h" +#include "oxtmsg.h" +#include "OxtService.h" +#include "OxtService_i.h" +#include "XenStoreWrapper.h" +#include "OxtSecurityHelper.h" + +#include +#include +#include +#include +#include + +#define XGA_INSTALL_REGKEY _T("Software\\Citrix\\XenGuestPlugin") +#define XC_INSTALL_REGKEY _T("Software\\Citrix\\XenTools") +#define XGA_INSTALL_INSTVAL _T("Install_Dir") +#define XGA_SERVICE_INFO_SIZE 256 +#define XGA_RUN_REGKEY _T("Software\\Microsoft\\Windows\\CurrentVersion\\Run") +#define XGA_RUN_INSTVAL _T("XciPlugin") +#define XGA_RUN_BLANK _T("") + +extern "C" { + int poweropts(); +} + +#ifdef _DEBUG +//#define _CAN_CONSOLE +#endif // _DEBUG + +class COxtServiceModule : public CAtlServiceModuleT< COxtServiceModule, IDS_SERVICENAME > +{ +public : + HINSTANCE m_hInstance; + TCHAR m_tszDisplayName[XGA_SERVICE_INFO_SIZE]; + TCHAR m_tszServiceDesc[XGA_SERVICE_INFO_SIZE]; + TCHAR m_tszParamsKey[XGA_SERVICE_INFO_SIZE]; + + DECLARE_LIBID(LIBID_OxtServiceLib) + DECLARE_REGISTRY_APPID_RESOURCEID(IDR_OXTSERVICE, APPID_OxtService) + + HRESULT InitializeSecurity() throw() + { + COxtSecurityHelper clXsh(&_OxtService); + + // If not a consolable build, check not running remotely +# ifndef _CAN_CONSOLE + // If the remote access check fails, fail to start the service. + if (!clXsh.CheckDenyRemoteAccess()) + return E_ACCESSDENIED; +# else //!_CAN_CONSOLE + //CoInitializeSecurity(NULL // pSecDesc + // ,0 // cAuthSvc + // ,NULL // asAuthSvc + // ,NULL // pReserved1 + // ,0 // dwAuthnLevel + // ,0 // dwImplLevel + // ,NULL // pAuthList + // ,0 // dwCapabilities + // ,NULL // pReserved3 + // ); +# endif //_CAN_CONSOLE + + // Calling CoInitializeSecurity at this point will override the values + // setup for the AppID in the registry. These values explicitly set the + // security access control to deny all remote access and to allow only + // the interactive user access and launch permissions (aside from the + // administrator). The default authentication values are fine for this. + + // NOTE: One oddity was that a NULL DACL was being passed to CoInitializeSecurity + // earlier but the values in the AppID were still being used. Perhaps + // there is more to the overriding of AppID registry values than simply + // ignoring them in some cases. + + return S_OK; + } + + void LoadStrings(HINSTANCE hInstance) + { + m_hInstance = hInstance; + + ::LoadString(m_hInstance, IDS_DISPLAYNAME, m_tszDisplayName, sizeof(m_tszDisplayName)/sizeof(TCHAR)); + ::LoadString(m_hInstance, IDS_SERVICEDESC, m_tszServiceDesc, sizeof(m_tszServiceDesc)/sizeof(TCHAR)); + + _sntprintf_s(m_tszParamsKey, + XGA_SERVICE_INFO_SIZE, + _TRUNCATE, + _T("SYSTEM\\CurrentControlSet\\Services\\%s\\Parameters"), + m_szServiceName); + } + + void SetupParameterKey() + { + LONG lRet; + CRegKey keyParams; + + lRet = keyParams.Open(HKEY_LOCAL_MACHINE, m_tszParamsKey); + if (lRet != ERROR_SUCCESS) + { + // Attempt to create the key + lRet = keyParams.Create(HKEY_LOCAL_MACHINE, m_tszParamsKey); + if (_OxtService.LogEventTypeIdLastRegistryError(ctxLS(IDS_SETUPPARAMETERKEY_COULD_NOT_CREA_OXTSERVICE_106) + ,EVENTLOG_ERROR_TYPE + ,EVMSG_START_FAILURE + ,lRet)) + { + return; + } + } + lRet = keyParams.SetDWORDValue(_T("LogCommunicationErrors"), 0); + if (_OxtService.LogEventTypeIdLastRegistryError(ctxLS(IDS_SETUPPARAMETERKEY_COULD_NOT_SET__OXTSERVICE_115) + ,EVENTLOG_ERROR_TYPE + ,EVMSG_START_FAILURE + ,lRet)) + { + return; + } + lRet = keyParams.SetDWORDValue(_T("LogOperationErrors"), 0); + if (_OxtService.LogEventTypeIdLastRegistryError(ctxLS(IDS_SETUPPARAMETERKEY_COULD_NOT_SET__OXTSERVICE_123) + ,EVENTLOG_ERROR_TYPE + ,EVMSG_START_FAILURE + ,lRet)) + { + return; + } + } + + void RegisterEventSource() + { + LONG lRet; + CRegKey keyAppLog; + CRegKey keyNewApp; + TCHAR tszImageName[_MAX_PATH + 1]; + + ::ZeroMemory(tszImageName, sizeof(TCHAR)*(_MAX_PATH + 1)); + ::GetModuleFileName(NULL, tszImageName, _MAX_PATH); + + // Open the app log key + lRet = keyAppLog.Open(HKEY_LOCAL_MACHINE, + _T("SYSTEM\\CurrentControlSet\\Services\\EventLog\\Application")); + if (_OxtService.LogEventTypeIdLastRegistryError(ctxLS(IDS_REGISTEREVENTSOURCE_COULD_NOT_OP_OXTSERVICE_145) + ,EVENTLOG_ERROR_TYPE + ,EVMSG_START_FAILURE + ,lRet)) + { + return; + } + + // Create a new key for event logging for this service + lRet = keyNewApp.Create(keyAppLog, m_szServiceName); + if (_OxtService.LogEventTypeIdLastRegistryError(ctxLS(IDS_REGISTEREVENTSOURCE_COULD_NOT_CR_OXTSERVICE_155) + ,EVENTLOG_ERROR_TYPE + ,EVMSG_START_FAILURE + ,lRet)) + { + return; + } + + // Set the value of the message code base + lRet = keyNewApp.SetStringValue(_T("EventMessageFile"), tszImageName); + if (_OxtService.LogEventTypeIdLastRegistryError(ctxLS(IDS_REGISTEREVENTSOURCE_COULD_NOT_SE_OXTSERVICE_165) + ,EVENTLOG_ERROR_TYPE + ,EVMSG_START_FAILURE + ,lRet)) + { + return; + } + + // Set the event types allowed + DWORD dwData = EVENTLOG_ERROR_TYPE | EVENTLOG_WARNING_TYPE | EVENTLOG_INFORMATION_TYPE; + lRet = keyNewApp.SetDWORDValue(_T("TypesSupported"), dwData); + if (_OxtService.LogEventTypeIdLastRegistryError(ctxLS(IDS_REGISTEREVENTSOURCE_COULD_NOT_SE_OXTSERVICE_176) + ,EVENTLOG_ERROR_TYPE + ,EVMSG_START_FAILURE + ,lRet)) + { + return; + } + } + + void UnregisterEventSource() + { + LONG lRet; + CRegKey keyAppLog; + + // Open the app log key + lRet = keyAppLog.Open(HKEY_LOCAL_MACHINE, + _T("SYSTEM\\CurrentControlSet\\Services\\EventLog\\Application")); + if (_OxtService.LogEventTypeIdLastRegistryError(ctxLS(IDS_UNREGISTEREVENTSOURCE_COULD_NOT__OXTSERVICE_193) + ,EVENTLOG_ERROR_TYPE + ,EVMSG_START_FAILURE + ,lRet)) + { + return; + } + + // Delete this service's logging key + keyAppLog.DeleteSubKey(m_szServiceName); + } + + void DenyRemoteAccess() + { + COxtSecurityHelper clXsh(&_OxtService); + clXsh.DenyRemoteAccess(); + clXsh.DenyRemoteLaunchAndActivate(); + } + + void CheckRemoteAccess() + { + COxtSecurityHelper clXsh(&_OxtService); + + if (clXsh.CheckDenyRemoteAccess()) + ::MessageBox(NULL, _T("CheckRemoteAccess: Remote access is denied."), m_szServiceName, MB_OK|MB_ICONINFORMATION); + else + ::MessageBox(NULL, _T("CheckRemoteAccess: WARNING remote access is not denied!"), m_szServiceName, MB_OK|MB_ICONEXCLAMATION); + } + + void UpdateServiceRegistry() + { + SC_HANDLE hSCM = NULL; + SC_HANDLE hService = NULL; + BOOL rc; + SERVICE_DESCRIPTION stDesc; + + do { + hSCM = ::OpenSCManager(NULL, NULL, SC_MANAGER_ALL_ACCESS); + if (hSCM == NULL) + { + _OxtService.LogEventTypeId(ctxLS(IDS_UPDATESERVICEREGISTRY_COULD_NOT__OXTSERVICE_233), + EVENTLOG_ERROR_TYPE, + EVMSG_START_FAILURE, + ::GetLastError()); + break; + } + + hService = ::OpenService(hSCM, m_szServiceName, SERVICE_CHANGE_CONFIG); + if (hSCM == NULL) + { + ::CloseServiceHandle(hSCM); + _OxtService.LogEventTypeId(ctxLS(IDS_UPDATESERVICEREGISTRY_COULD_NOT__OXTSERVICE_244), + EVENTLOG_ERROR_TYPE, + EVMSG_START_FAILURE, + ::GetLastError()); + break; + } + + rc = ::ChangeServiceConfig(hService, + SERVICE_NO_CHANGE, + SERVICE_AUTO_START, + SERVICE_NO_CHANGE, + NULL, + NULL, + NULL, + NULL, + NULL, + NULL, + m_tszDisplayName); + if (!rc) + { + _OxtService.LogEventTypeId(ctxLS(IDS_UPDATESERVICEREGISTRY_CHANGE_SER_OXTSERVICE_264), + EVENTLOG_ERROR_TYPE, + EVMSG_START_FAILURE, + ::GetLastError()); + break; + } + + stDesc.lpDescription = m_tszServiceDesc; + rc = ::ChangeServiceConfig2(hService, SERVICE_CONFIG_DESCRIPTION, (LPVOID)&stDesc); + if (!rc) + { + _OxtService.LogEventTypeId(ctxLS(IDS_UPDATESERVICEREGISTRY_CHANGE_SER_OXTSERVICE_275), + EVENTLOG_ERROR_TYPE, + EVMSG_START_FAILURE, + ::GetLastError()); + } + } while (false); + + if (hService != NULL) + ::CloseServiceHandle(hService); + + if (hSCM != NULL) + ::CloseServiceHandle(hSCM); + } + + bool PreStartTasks() + { + LPTSTR lpCmdLine = GetCommandLine(); + TCHAR tszTokens[] = _T("-/"); + bool rc = false; + + LPCTSTR lpszToken = FindOneOf(lpCmdLine, tszTokens); + while (lpszToken != NULL) + { + if (WordCmpI(lpszToken, _T("RegServer")) == 0) + { + RegisterEventSource(); + break; + } + + if (WordCmpI(lpszToken, _T("Service")) == 0) + { + RegisterEventSource(); + SetupParameterKey(); + break; + } + + if (WordCmpI(lpszToken, _T("UnregServer")) == 0) + { + UnregisterEventSource(); + break; + } + + if (WordCmpI(lpszToken, _T("DenyRemoteAccess")) == 0) + { + DenyRemoteAccess(); + rc = true; + break; + } + + if (WordCmpI(lpszToken, _T("CheckRemoteAccess")) == 0) + { + CheckRemoteAccess(); + rc = true; + break; + } + + lpszToken = FindOneOf(lpszToken, tszTokens); + } + + return rc; + } + + void PostStartTasks() + { + LPTSTR lpCmdLine = GetCommandLine(); + TCHAR tszTokens[] = _T("-/"); + + LPCTSTR lpszToken = FindOneOf(lpCmdLine, tszTokens); + while (lpszToken != NULL) + { + if (WordCmpI(lpszToken, _T("Service"))==0) + { + UpdateServiceRegistry(); + break; + } + + lpszToken = FindOneOf(lpszToken, tszTokens); + } + } + + //! @brief Try to run the program as a console executable. + //! Useful for debugging. + //! @param dwArgc Number of command line params. + //! @param lpszArgv Command line params. + void ConsoleMain(DWORD dwArgc, LPTSTR* lpszArgv) throw() + { + lpszArgv; + dwArgc; + m_status.dwWin32ExitCode = S_OK; + m_status.dwCheckPoint = 0; + m_status.dwWaitHint = 0; + +#ifndef _ATL_NO_COM_SUPPORT + + HRESULT hr = E_FAIL; + hr = COxtServiceModule::InitializeCom(); + if (FAILED(hr)) + { + // Ignore RPC_E_CHANGED_MODE if CLR is loaded. Error is due to CLR initializing + // COM and InitializeCOM trying to initialize COM with different flags. + if (hr != RPC_E_CHANGED_MODE || GetModuleHandle(_T("Mscoree.dll")) == NULL) + { + return; + } + } + else + { + m_bComInitialized = true; + } + + m_bDelayShutdown = false; +#endif //_ATL_NO_COM_SUPPORT + // When the Run function returns, the service has stopped. + m_status.dwWin32ExitCode = this->Run(SW_HIDE); + + // Ok, I give up. How do we remote debug with the correct credentials ? +# ifdef _CAN_CONSOLE + if (m_status.dwWin32ExitCode == CO_E_WRONG_SERVER_IDENTITY) + { + this->RunMessageLoop(); + this->PostMessageLoop(); + } +# endif // _CAN_CONSOLE + +#ifndef _ATL_NO_COM_SUPPORT + if (m_bService && m_bComInitialized) + COxtServiceModule::UninitializeCom(); +#endif + + SetServiceStatus(SERVICE_STOPPED); + LogEvent(_T("Service running as Console stopped")); + } + + HRESULT Start(int nShowCmd) throw() + { + // Explicitly load the xs2.dll here for use in the service. + if (!CXenStoreWrapper::XS2Initialize()) + { + _OxtService.LogEventTypeId(ctxLS(IDS_FAILED_TO_LOAD_XS2_LIBRARY___ERR_OXTSERVICE_413), + EVENTLOG_ERROR_TYPE, EVMSG_START_FAILURE, ::GetLastError()); + return E_FAIL; + } + + // We are overriding start with our own. Since we are always a service then + // can ditch the registry checks. First, start the non-COM related tasks. + if (!_OxtService.Start()) + return E_UNEXPECTED; + + // Now start the COM service + m_bService = TRUE; + + SERVICE_TABLE_ENTRY st[] = + { + { m_szServiceName, _ServiceMain }, + { NULL, NULL } + }; + if (::StartServiceCtrlDispatcher(st) == 0) + { + DWORD const dwLastError = GetLastError(); + if (dwLastError == ERROR_FAILED_SERVICE_CONTROLLER_CONNECT) // If failed to connect + { +# ifndef _CAN_CONSOLE + m_status.dwWin32ExitCode = dwLastError; +# endif // _CAN_CONSOLE + _OxtService.LogEventTypeIdLastError(ctxLS(IDS_FAILED_TO_START__SERVICE_SHOULD__OXTSERVICE_439) + ,EVENTLOG_ERROR_TYPE + ,EVMSG_START_FAILURE + ); + // Allow debug build to attempt to run as console program. + // Currently doesn't always work that well since there's a problem with + // "CoRegisterClassObject()" failing with CO_E_WRONG_SERVER_IDENTITY causing an assert. +# ifdef _CAN_CONSOLE +# ifdef UNICODE + LPTSTR *lpCmdLine = __wargv; +# else //!UNICODE + LPTSTR *lpCmdLine = __argv; +# endif //!UNICODE + ConsoleMain(__argc, lpCmdLine); +# endif _CAN_CONSOLE + + } // Ends if failed to connect + else // Else unknown error + { + m_status.dwWin32ExitCode = dwLastError; + _OxtService.LogEventTypeIdLastError(ctxLS(IDS_FAILED_TO_START_SERVICE_OXTSERVICE_459) + ,EVENTLOG_ERROR_TYPE + ,EVMSG_START_FAILURE + ); + } // Ends else unknown error + } + + return m_status.dwWin32ExitCode; + } + + void OnStop() throw() + { + // Override the OnStop to get control of our shutdown event first + _OxtService.SetShutdownEvent(); + // Call up to parent class to shut the service down + CAtlServiceModuleT::OnStop(); + } +}; + +COxtServiceModule _AtlModule; + +bool COxtService::Initialize() +{ +#define XGA_MAX_MESSAGE 512 + LONG lRet; + DWORD dwVal; + CRegKey clInstKey; + CRegKey keyParams; + + m_osvi.dwOSVersionInfoSize = sizeof(OSVERSIONINFOEX); + if (!::GetVersionEx((OSVERSIONINFO*)&m_osvi)) + { + LogEventTypeId(ctxLS(IDS_GETVERSIONEX_FAILED_____ERROR__z_OXTSERVICE_537), // SNO! + EVENTLOG_ERROR_TYPE, EVMSG_START_FAILURE, ::GetLastError()); + return false; + } + + m_hShutdownEvent = ::CreateEvent(NULL, TRUE, FALSE, NULL); + if (m_hShutdownEvent == NULL) + { + LogEventTypeId(ctxLS(IDS_FAILED_TO_CREATE_SHUTDOWN_EVENT__OXTSERVICE_545), + EVENTLOG_ERROR_TYPE, EVMSG_START_FAILURE, ::GetLastError()); + return false; + } + + // Try reading the logging flags if they are there. + lRet = keyParams.Open(HKEY_LOCAL_MACHINE, _AtlModule.m_tszParamsKey); + if (lRet == ERROR_SUCCESS) + { + lRet = keyParams.QueryDWORDValue(_T("LogCommunicationErrors"), dwVal); + if (lRet == ERROR_SUCCESS) + m_bLogCommunicationErrors = (dwVal == 0) ? false : true; + + lRet = keyParams.QueryDWORDValue(_T("LogOperationErrors"), dwVal); + if (lRet == ERROR_SUCCESS) + m_bLogOperationErrors = (dwVal == 0) ? false : true; + } + + return true; +} + +void COxtService::Uninitialize() +{ + if (m_hShutdownEvent != NULL) + { + ::CloseHandle(m_hShutdownEvent); + m_hShutdownEvent = NULL; + } +} + +bool COxtService::Start() +{ + // Configure power options + poweropts(); + return true; +} + +void COxtService::LogEventTypeId(LPCTSTR tszFormat, WORD wType, DWORD dwEventId, va_list args) +{ + TCHAR tszMsg[XGA_MAX_MESSAGE + 1]; + + // Check log flags + if ((dwEventId == EVMSG_COMMUNICATION_FAILURE)&&(!m_bLogCommunicationErrors)) + return; + if ((dwEventId == EVMSG_OPERATION_FAILURE)&&(!m_bLogOperationErrors)) + return; + + if (tszFormat != NULL) + { + _vsntprintf_s(tszMsg, XGA_MAX_MESSAGE, _TRUNCATE, tszFormat, args); + + _AtlModule.LogEventEx(dwEventId, tszMsg, wType); + } + else + _AtlModule.LogEventEx(dwEventId, NULL, wType); +} + +void COxtService::LogEventTypeId(ULONG ulFormat, WORD wType, DWORD dwEventId, va_list args) +{ + if (ulFormat != 0) + { + TCHAR tszFormat[_MAX_PATH]; + + _stprintf_s(tszFormat, _MAX_PATH, _T("%d"), ulFormat); + LoadString(NULL, ulFormat, tszFormat, _MAX_PATH); + LogEventTypeId(tszFormat, wType, dwEventId, args); + } + else + LogEventTypeId((LPCTSTR)NULL, wType, dwEventId, args); +} + +void COxtService::LogEventTypeId(ULONG ulFormat, WORD wType, DWORD dwEventId, ...) +{ + va_list pArg; + va_start(pArg, dwEventId); + LogEventTypeId(ulFormat, wType, dwEventId, pArg); + va_end(pArg); +} + +//! @brief Log event on error, using "GetLastError()". +//! If there is a text description of the error available from Windows, include it in the event log output. +//! @param tszFormat Format string. +//! @param wType Event type. +//! @param dwEventId Event Id. +//! @param lRet Return value from registry call. +//! @param args ellipsis arguments. +//! @return true if error occurred, otherwise false. +bool COxtService::LogEventTypeIdLastError(ULONG ulFormat, WORD wType, DWORD dwEventId, va_list args) +{ +# ifdef UNICODE + typedef std::wstring tstring; + typedef std::wostringstream tostringstream; +# else // !UNICODE + typedef std::string tstring; + typedef std::ostringstream tostringstream; +# endif // !UNICODE + static size_t const HexWidth = 2; + DWORD const dwLastError = ::GetLastError(); + bool const bError = dwLastError != 0; + TCHAR tszFormat[_MAX_PATH]; + + _stprintf_s(tszFormat, _MAX_PATH, _T("%d"), ulFormat); + LoadString(NULL, ulFormat, tszFormat, _MAX_PATH); + + if (bError) // If error occurred + { + LPVOID lpMsgBuf = NULL; + tostringstream strstrFormat; + DWORD dwFormatMessageResult; + + strstrFormat << tszFormat << _T(" - ERROR"); + + dwFormatMessageResult = FormatMessage( + FORMAT_MESSAGE_ALLOCATE_BUFFER | + FORMAT_MESSAGE_FROM_SYSTEM | + FORMAT_MESSAGE_IGNORE_INSERTS + ,NULL // source + ,dwLastError // Message ID + ,MAKELANGID(LANG_NEUTRAL, SUBLANG_DEFAULT) // Language ID + ,(LPTSTR) &lpMsgBuf // Buffer + ,0 // Size + ,NULL // Arguments + ); + + bool const bGotDescription = dwFormatMessageResult != 0 && lpMsgBuf != NULL; + if (bGotDescription) // If got error description + { + strstrFormat << _T("("); + + } // Ends if got error description + else // Else no error description + { + strstrFormat << _T(": "); + + } // Ends else no error description + + // Output the error code. + strstrFormat << dwLastError; + + if (bGotDescription) // If got error description + { + strstrFormat << _T("): ") << reinterpret_cast(lpMsgBuf); + + } // Ends else got error description + + if (lpMsgBuf != NULL) // If got message + { + LocalFree(lpMsgBuf); + + } // Ends if got message + + LogEventTypeId(strstrFormat.str().c_str() + ,EVENTLOG_ERROR_TYPE + ,EVMSG_START_FAILURE + ,args + ); + } // Ends if error occurred + + return bError; +} + +bool COxtService::LogEventTypeIdLastError(ULONG ulFormat, WORD wType, DWORD dwEventId, ...) +{ + va_list pArg; + va_start(pArg, dwEventId); + bool const bResult = LogEventTypeIdLastError(ulFormat, wType, dwEventId, pArg); + va_end(pArg); + return bResult; +} + +//! @brief Log event on registry error, using "GetLastError()" if possible, otherwise last registry error argument. +//! If there is a text description of the error available from Windows, include it in the event log output. +//! @param tszFormat Format string. +//! @param wType Event type. +//! @param dwEventId Event Id. +//! @param lRet Return value from registry call. +//! @param args ellipsis arguments. +//! @return true if registry error occurred, otherwise false. +bool COxtService::LogEventTypeIdLastRegistryError(ULONG ulFormat, WORD wType, DWORD dwEventId, LONG lRet, va_list args) +{ +# ifdef UNICODE + typedef std::wstring tstring; + typedef std::wostringstream tostringstream; +# else // !UNICODE + typedef std::string tstring; + typedef std::ostringstream tostringstream; +# endif // !UNICODE + static size_t const HexWidth = 2; + bool const bError = lRet != ERROR_SUCCESS; + TCHAR tszFormat[_MAX_PATH]; + + _stprintf_s(tszFormat, _MAX_PATH, _T("%d"), ulFormat); + LoadString(NULL, ulFormat, tszFormat, _MAX_PATH); + if (bError) // If error occurred + { + LPVOID lpMsgBuf = NULL; + DWORD const dwLastError = ::GetLastError(); + tostringstream strstrFormat; + DWORD dwFormatMessageResult; + + strstrFormat << tszFormat << _T(" - error "); + + if (dwLastError != 0) // If there is a last error + { + dwFormatMessageResult = FormatMessage( + FORMAT_MESSAGE_ALLOCATE_BUFFER | + FORMAT_MESSAGE_FROM_SYSTEM | + FORMAT_MESSAGE_IGNORE_INSERTS + ,NULL // source + ,dwLastError // Message ID + ,MAKELANGID(LANG_NEUTRAL, SUBLANG_NEUTRAL) // Language ID + ,(LPTSTR) &lpMsgBuf // Buffer + ,0 // Size + ,NULL // Arguments + ); + } // Ends if there is a last error + else // Else no last error + { + // Work out what went wrong with the registry key. + // Retrieve the system error message for the last-error code. + dwFormatMessageResult = FormatMessage( + FORMAT_MESSAGE_ALLOCATE_BUFFER | + FORMAT_MESSAGE_FROM_SYSTEM | + FORMAT_MESSAGE_IGNORE_INSERTS + ,NULL // source + ,lRet // Message ID + ,MAKELANGID(LANG_NEUTRAL, SUBLANG_NEUTRAL) // Language ID + ,(LPTSTR) &lpMsgBuf // Buffer + ,0 // Size + ,NULL // Arguments + ); + } // Ends else no last error + + bool const bGotDescription = dwFormatMessageResult != 0 && lpMsgBuf != NULL; + if (bGotDescription) // If got error description + { + strstrFormat << _T("("); + } + + // Output the error code in hex. + strstrFormat << _T("0x") << std::hex << std::setfill(_T('0')) << std::setw(HexWidth); + + if (dwLastError != 0) // If last error + { + strstrFormat << dwLastError; + + } // Ends if last error + else // Else no last error + { + strstrFormat << lRet; + + } // Ends else no last error + + strstrFormat << std::resetiosflags(strstrFormat.flags()); + + if (bGotDescription) // If got error description + { + strstrFormat << _T("): ") << reinterpret_cast(lpMsgBuf); + + } // Ends else got error description + + if (lpMsgBuf != NULL) // If got message + { + LocalFree(lpMsgBuf); + + } // Ends if got message + + LogEventTypeId(strstrFormat.str().c_str() + ,EVENTLOG_ERROR_TYPE + ,EVMSG_START_FAILURE + ,args + ); + } // Ends if error occurred + + return bError; +} + +bool COxtService::LogEventTypeIdLastRegistryError(ULONG ulFormat, WORD wType, DWORD dwEventId, LONG lRet, ...) +{ + va_list args; + va_start(args, lRet); + bool const bResult = LogEventTypeIdLastRegistryError(ulFormat, wType, dwEventId, lRet, args); + va_end(args); + return bResult; +} + +//! @brief Log event on error, using "GetLastError()". If no error, log output anyway. +//! If there is a text description of the error available from Windows, include it in the event log output. +//! @param tszFormat Format string. +//! @param wType Event type. +//! @param dwEventId Event Id. +//! @param lRet Return value from registry call. +//! @param args ellipsis arguments. +//! @return true if error occurred, otherwise false. +bool COxtService::LogEventTypeIdLastErrorAlways(ULONG ulFormat, WORD wType, DWORD dwEventId, va_list args) +{ + bool const bError = LogEventTypeIdLastError(ulFormat, wType, dwEventId, args); + if (!bError) + { + LogEventTypeId(ulFormat, wType, dwEventId); + } + return bError; +} + +bool COxtService::LogEventTypeIdLastErrorAlways(ULONG ulFormat, WORD wType, DWORD dwEventId, ...) +{ + va_list args; + va_start(args, dwEventId); + bool const bResult = LogEventTypeIdLastErrorAlways(ulFormat, wType, dwEventId, args); + va_end(args); + return bResult; +} + +bool COxtService::RegisterXgs() +{ + LONG lRet; + + lRet = ::InterlockedIncrement(&m_ulXgsCount); + + if (lRet > XGS_MAX_INSTANCES) + { + ::InterlockedDecrement(&m_ulXgsCount); + return false; + } + return true; +} + +void COxtService::UnregisterXgs() +{ + ::InterlockedDecrement(&m_ulXgsCount); + assert(m_ulXgsCount >= 0); +} + +COxtService _OxtService; + +extern "C" int WINAPI _tWinMain(HINSTANCE hInstance, HINSTANCE /*hPrevInstance*/, + LPTSTR /*lpCmdLine*/, int nShowCmd) +{ + int iRet; + + _AtlModule.LoadStrings(hInstance); + + if (!_OxtService.Initialize()) + { + _OxtService.SetShutdownEvent(); + _OxtService.Uninitialize(); + return -2; + } + + // Up front tasks like registering the event log message binary. For + // tasks like updating local only access, the app will quite following these. + if (_AtlModule.PreStartTasks()) + return 0; + + iRet = _AtlModule.WinMain(nShowCmd); + + // Tasks after server/service registration + _AtlModule.PostStartTasks(); + + _OxtService.SetShutdownEvent(); + _OxtService.Uninitialize(); + + // Free the xs2.dll library as late as possible after all threads are done. If + // it was not loaded, the routine will handle that. + CXenStoreWrapper::XS2Uninitialize(); + + return iRet; +} + diff --git a/OxtService/OxtService.en.rc b/OxtService/OxtService.en.rc new file mode 100644 index 0000000..e2237b4 --- /dev/null +++ b/OxtService/OxtService.en.rc @@ -0,0 +1,134 @@ +STRINGTABLE +BEGIN + IDS_SERVICENAME "OxtService" + IDS_DISPLAYNAME "OpenXT Xen Guest Services" + IDS_SERVICEDESC "Provides in-guest services for Xen user domains." + IDS_ATLBASE_NO_HANDLER "Handler not installed" + IDS_ATLBASE_SERVICE_STOPPED "Service stopped" + IDS_ATLBASE_SERVICE_STARTED "Service started" + IDS_ATLBASE_BAD_SERVICE "Bad service request" +END +STRINGTABLE DISCARDABLE +BEGIN + IDS_FAILED_TO_CREATE_OBJECT_LOCK___H_OXTGUESTSERVICES_24 "Failed to create object lock - HRESULT: 0x%x" + IDS_FAILED_TO_OPEN_XENSTORE___HRESUL_OXTGUESTSERVICES_32 "Failed to open XenStore - HRESULT: 0x%x" + IDS_FAILED_TO_INITIALIZE_VM_VALUES___OXTGUESTSERVICES_53 "Failed to initialize VM values - HRESULT: 0x%x" + IDS_MAXIMUM_INSTANCE_COUNT_REACHED___OXTGUESTSERVICES_61 "Maximum instance count reached - HRESULT: 0x%x" + IDS_FAILED_TO_CREATE_VMS_EVENT_GUID__OXTGUESTSERVICES_474 "Failed to create VMS Event GUID - HRESULT: 0x%x" + IDS_FAILED_TO_CREATE_VMS_EVENT___HRE_OXTGUESTSERVICES_492 "Failed to create VMS Event - HRESULT: 0x%x" + IDS_FAILED_TO_CREATE_ALERTS_EVENT_GU_OXTGUESTSERVICES_532 "Failed to create Alerts Event GUID - HRESULT: 0x%x" + IDS_FAILED_TO_CREATE_ALERTS_EVENT____OXTGUESTSERVICES_550 "Failed to create Alerts Event - HRESULT: 0x%x" +END +STRINGTABLE DISCARDABLE +BEGIN + IDS_PRINCIPAL__zS_PERMISSION__zS_OPE_OXTSECURITYHELPER_35 "PRINCIPAL: %s PERMISSION: %s OPERATION: %s ERROR: %d" + IDS_DENY_CHECK_FAILURE___PERMISSION__OXTSECURITYHELPER_1244 "DENY CHECK FAILURE - PERMISSION: %s OPERATION: %s ERROR: %d" + IDS_DENY_REMOTE_CHECK_FOR_zS_DETECTE_OXTSECURITYHELPER_1279 "Deny remote check for %s detected remote access is allowed!" + IDS_ACCESSPERMISSION_OXTSECURITYHELPER_1281 "AccessPermission" + IDS_LAUNCHPERMISSION_LAUNCH_OXTSECURITYHELPER_1303 "LaunchPermission-Launch" + IDS_LAUNCHPERMISSION_ACTIVATE_OXTSECURITYHELPER_1311 "LaunchPermission-Activate" + IDS_DENY_CHECK_FOUND_NO_SD_DACL_FOR__OXTSECURITYHELPER_1431 "Deny check found no SD DACL for %s - access may be denied to everyone" + IDS_LAUNCHPERMISSION_OXTSECURITYHELPER_1478 "LaunchPermission" + IDS_FAILED_TO_ALLOCATE_SECURITY_ATTR_OXTSECURITYHELPER_1559 "Failed to allocate SECURITY_ATTRIBUTES" + IDS_FAILED_TO_CREATE_SECURITY_DESCRI_OXTSECURITYHELPER_1569 "Failed to create security descriptor - error: %d" + IDS_FAILED_TO_GET_SIZES_FROM_MAKEABS_OXTSECURITYHELPER_1614 "Failed to get sizes from MakeAbsoluteSD - error: %d" + IDS_FAILED_TO_ALLOCATE_SECURITY_DESC_OXTSECURITYHELPER_1625 "Failed to allocate SECURITY_DESCRIPTOR" + IDS_FAILED_CREATE_SD_IN_MAKEABSOLUTE_OXTSECURITYHELPER_1644 "Failed create SD in MakeAbsoluteSD - error: %d" + IDS_FAILED_TO_ALLOCATE_XSH_DESCRIPTO_OXTSECURITYHELPER_1689 "Failed to allocate XSH_DESCRIPTOR" + IDS_FAILED_TO_INITIALIZE_COM_SID___E_OXTSECURITYHELPER_1699 "Failed to initialize COM SID - error: %d" + IDS_FAILED_TO_ALLOCATE_PINTERACTIVSI_OXTSECURITYHELPER_1709 "failed to allocate pInteractivSID SID" +END +STRINGTABLE DISCARDABLE +BEGIN + IDS_FAILED_TO_ALLOCATE_ADMINS_SID_OXTSECURITYHELPER_1718 "Failed to allocate Admins SID" + IDS_FAILED_CREATEWELLKNOWNSID_PINTER_OXTSECURITYHELPER_1727 "Failed CreateWellKnownSid(pInteractivSID) - error: %d" + IDS_FAILED_CREATEWELLKNOWNSID_PADMIN_OXTSECURITYHELPER_1736 "Failed CreateWellKnownSid(pAdminsSID) - error: %d" + IDS_FAILED_SETENTRIESINACL_PINTERACT_OXTSECURITYHELPER_1755 "Failed SetEntriesInAcl(pInteractivSID) - error: %d" + IDS_FAILED_TO_SET_ADMINS_SID_AS_OWNE_OXTSECURITYHELPER_1765 "Failed to set Admins SID as owner - error: %d" + IDS_FAILED_TO_SET_ADMINS_SID_AS_GROU_OXTSECURITYHELPER_1773 "Failed to set Admins SID as group - error: %d" + IDS_FAILED_TO_SET_DACL_FOR_SD___ERRO_OXTSECURITYHELPER_1782 "Failed to set DACL for SD - error: %d" +END +STRINGTABLE DISCARDABLE +BEGIN + IDS_SETUPPARAMETERKEY_COULD_NOT_CREA_OXTSERVICE_106 "SetupParameterKey could not create parameters key" + IDS_SETUPPARAMETERKEY_COULD_NOT_SET__OXTSERVICE_115 "SetupParameterKey could not set LogCommunicationErrors" + IDS_SETUPPARAMETERKEY_COULD_NOT_SET__OXTSERVICE_123 "SetupParameterKey could not set LogOperationErrors" + IDS_REGISTEREVENTSOURCE_COULD_NOT_OP_OXTSERVICE_145 "RegisterEventSource could not open event logging key" + IDS_REGISTEREVENTSOURCE_COULD_NOT_CR_OXTSERVICE_155 "RegisterEventSource could not create new event logging key" + IDS_REGISTEREVENTSOURCE_COULD_NOT_SE_OXTSERVICE_165 "RegisterEventSource could not set logging messsage source" + IDS_REGISTEREVENTSOURCE_COULD_NOT_SE_OXTSERVICE_176 "RegisterEventSource could not set allowed event types" + IDS_UNREGISTEREVENTSOURCE_COULD_NOT__OXTSERVICE_193 "UnregisterEventSource could not remove logging event key" + IDS_UPDATESERVICEREGISTRY_COULD_NOT__OXTSERVICE_233 "UpdateServiceRegistry could not open SCM - error: 0x%x" + IDS_UPDATESERVICEREGISTRY_COULD_NOT__OXTSERVICE_244 "UpdateServiceRegistry could not open Service - error: 0x%x" + IDS_UPDATESERVICEREGISTRY_CHANGE_SER_OXTSERVICE_264 "UpdateServiceRegistry change service config - error: 0x%x" + IDS_UPDATESERVICEREGISTRY_CHANGE_SER_OXTSERVICE_275 "UpdateServiceRegistry change service config 2 - error: 0x%x" + IDS_FAILED_TO_LOAD_XS2_LIBRARY___ERR_OXTSERVICE_413 "failed to load xs2 library - ERROR: %d" + IDS_FAILED_TO_START__SERVICE_SHOULD__OXTSERVICE_439 "Failed to start. Service should be started from the Service Control Manager, and not run directly as an executable" + IDS_FAILED_TO_START_SERVICE_OXTSERVICE_459 "Failed to start service" + IDS_GETVERSIONEX_FAILED_____ERROR__z_OXTSERVICE_537 "GetVersionEx failed!! - ERROR: %d" +END +STRINGTABLE DISCARDABLE +BEGIN + IDS_FAILED_TO_CREATE_SHUTDOWN_EVENT__OXTSERVICE_545 "failed to create shutdown event - ERROR: %d" + IDS_FAILED_TO_CREATE_VMS_EVENT___ERR_OXTSERVICE_553 "failed to create VMS event - ERROR: %d" + IDS_FAILED_TO_CREATE_VMS_VECTOR_LOCK_OXTSERVICE_561 "failed to create VMS vector lock - ERROR: %d" + IDS_FAILED_TO_CREATE_ALERTS_VECTOR_L_OXTSERVICE_569 "failed to create Alerts vector lock - ERROR: %d" + IDS_XS2OPEN_FAILED_FOR_START__NOT_RU_OXTSERVICE_689 "XS2Open failed for Start (Not running on Xen?) - ERROR: %d" + IDS_XS2READ_FAILED_FOR_VM___ERROR__z_OXTSERVICE_697 "XS2Read failed for vm - ERROR: %d" + IDS_FAILED_TO_START_TASK_THREAD___ER_OXTSERVICE_730 "failed to start Task thread - ERRORNO: %d" + IDS_FAILED_TO_START_VMS_WATCH_THREAD_OXTSERVICE_739 "failed to start VMS watch thread - ERRORNO: %d" + IDS_FAILED_TO_START_ALERTS_WATCH_THR_OXTSERVICE_748 "failed to start Alerts watch thread - ERRORNO: %d" + IDS_XS2OPEN_FAILED_FOR_LOADVMS___ERR_OXTSERVICE_1090 "XS2Open failed for LoadVms - ERROR: %d" + IDS_XS2DIRECTORY_NO_VMS_RETURNED____OXTSERVICE_1101 "XS2Directory no VMs returned???" + IDS_FAILED_TO_RETURN_SYSTEM_DIRECTOR_OXTSERVICE_1248 "Failed to return system directory" + IDS_FAILED_TO_LAUNCH_POWERCFG_TOOL___OXTSERVICE_1261 "Failed to launch powercfg tool : Error: %d" + IDS_FAILURE_RETURNED_FROM_POWEROPTS__OXTSERVICE_1282 "Failure returned from poweropts - ERROR: %d" + IDS_WLANPROF__WLANAPI_DLL_NOT_FOUND_OXTSERVICE_1302 "WLANPROF: WLANAPI.DLL not found" + IDS_WLANPROF__ERROR_LOADING_WIFI_API_OXTSERVICE_1306 "WLANPROF: Error loading Wifi API procedure(s)" +END +STRINGTABLE DISCARDABLE +BEGIN + IDS_WLANPROF__ERROR_GETTING_LIST_OF__OXTSERVICE_1310 "WLANPROF: Error getting list of device interfaces: WLAN Status = %d" + IDS_WLANPROF__ERROR_ADDING_AP__WLAN__OXTSERVICE_1314 "WLANPROF: Error adding AP: WLAN Status = %d" + IDS_WLANPROF__UNKNOWN_FAILURE_ENCOUN_OXTSERVICE_1318 "WLANPROF: Unknown failure encountered: %d" + IDS_XS2OPEN_FAILED_FOR_WATCHES___ERR_OXTSERVICE_1339 "XS2Open failed for watches - ERROR: %d" + IDS_FAILED_TO_OPEN_XENSTORE_VMS_WATC_OXTSERVICE_1349 "Failed to open XenStore VMS watch - ERROR: %d" + IDS_XS_WATCH_THREAD_SHUTTING_DOWN__OXTSERVICE_1359 "XS Watch thread shutting down." + IDS_WAIT_FAILED_DURING_XS_WATCH_WAIT_OXTSERVICE_1370 "WAIT_FAILED during XS watch WaitForMultipleObjects?? - ERROR: %d" + IDS_UNKNOWN_FAILURE_DURING_XS_WATCH__OXTSERVICE_1378 "Unknown failure during XS watch WaitForMultipleObjects?? - ERROR: %d" + IDS_RECEIVED_XCDIAG_REQUEST_OXTSERVICE_1414 "Received xcdiag request" + IDS_FAILED_TO_LAUNCH_XCDIAG_TOOL___E_OXTSERVICE_1430 "Failed to launch xcdiag tool : Error: %d" + IDS_FAILED_TO_OPEN_XCDIAG_OUTPUT_FIL_OXTSERVICE_1465 "Failed to open xcdiag output file" + IDS_XCDIAG_OUTPUT_FILE_APPEARS_EMPTY_OXTSERVICE_1476 "xcdiag output file appears empty" + IDS_FAILED_TO_ALLOCATE_MEMORY_FOR_XC_OXTSERVICE_1486 "Failed to allocate memory for xcdiag output" + IDS_FAILED_TO_ACCESS_XCDIAG_FILE_OXTSERVICE_1502 "Failed to access xcdiag file" + IDS_FAILED_TO_VIEW_XCDIAG_OUTPUT_OXTSERVICE_1520 "Failed to view xcdiag output" + IDS_XCDIAG_ZIP_FILE_SENT__OXTSERVICE_1591 "xcdiag zip file sent." +END +STRINGTABLE DISCARDABLE +BEGIN + IDS_DOPOST___OPERATION_FAILED___ERRO_OXTSERVICE_1596 "DoPOST() operation failed - error: %d HTTP code: %d" + IDS_DOGET___FAILED_TO_REGISTER_FOR_A_OXTSERVICE_1652 "DoGET() failed to register for alert signals - error: %d HTTP code: %d. Interface: %s" + IDS_FAILED_TO_OPEN_V4V_CHANNEL_ON_FI_OXTSERVICE_1721 "Failed to open V4V channel on first attempt, will retry - HRESULT: 0x%x" + IDS_SAFEARRAYACCESSDATA___FAILED___H_OXTSERVICE_1800 "SafeArrayAccessData() failed - HRESULT: 0x%x" + IDS_ALERTS_THREAD_SHUTTING_DOWN__OXTSERVICE_1825 "Alerts thread shutting down." + IDS_DOGET___FAILED_TO_RECEIVE_SIGNAL_OXTSERVICE_1831 "DoGET() failed to receive signal - error: %d HTTP code: %d" + IDS_FAILED_TO_RESET_SIGNAL_REGISTRAT_OXTSERVICE_1838 "Failed to reset signal registration" + IDS_SAFEARRAYCOPY___FAILED___HRESULT_OXTSERVICE_1875 "SafeArrayCopy() failed - HRESULT: 0x%x" + IDS_E_OUTOFMEMORY___HRESULT__0XzX_OXTSERVICE_1881 "E_OUTOFMEMORY - HRESULT: 0x%x" +END +STRINGTABLE DISCARDABLE +BEGIN + IDS_SAFEARRAYACCESSDATA___FAILED___H_OXTGUESTSERVICES_230 "SafeArrayAccessData() failed - HRESULT: 0x%x" + IDS_SAFEARRAYACCESSDATA___RETRIEVED__OXTGUESTSERVICES_237 "SafeArrayAccessData() retrieved NULL data" + IDS_XS_WATCH_THREAD_SHUTTING_DOWN__OXTGUESTSERVICES_301 "XS Watch thread shutting down." + IDS_DOGET___FAILED___ERROR__zD_HTTP__OXTGUESTSERVICES_308 "DoGET() failed - error: %d HTTP code: %d" + IDS_COCREATEINSTANCE_CLSID_XENVMINFO_OXTGUESTSERVICES_378 "CoCreateInstance(CLSID_XenVmInfo) failed - HRESULT: 0x%x" + IDS_QUERYINTERFACE_IXENVMINITIALIZE__OXTGUESTSERVICES_385 "QueryInterface(IXenVmInitialize) failed - HRESULT: 0x%x" + IDS_QUERYINTERFACE_IXENVMINITIALIZE__OXTGUESTSERVICES_391 "QueryInterface(IXenVmInitialize) did not return interface pointer - HRESULT: 0x%x" + IDS_LOADIMAGEUID_FAILED__IMAGE__zS___OXTGUESTSERVICES_406 "LoadImageUid failed, image: %s - HRESULT: 0x%x" + IDS_FAILED_TO_OPEN_XENINP_FILE_HANDL_OXTGUESTSERVICES_674 "Failed to open XenInp file handle - ERROR: %d" + IDS_FAILED_TO_SEND_XENINP_IOCTL_ACCE_OXTGUESTSERVICES_683 "Failed to send XENINP_IOCTL_ACCELERATION - ERROR: %d" + IDS_ARRAY "Array" + IDS_BOOL "Bool" +END diff --git a/OxtService/OxtService.h b/OxtService/OxtService.h new file mode 100644 index 0000000..ab7292d --- /dev/null +++ b/OxtService/OxtService.h @@ -0,0 +1,97 @@ +/* + * Copyright (c) 2012 Citrix Systems, Inc. + * Copyright (c) 2016 Assured Information Security, Inc + * + * Permission is hereby granted, free of charge, to any person obtaining a copy + * of this software and associated documentation files (the "Software"), to deal + * in the Software without restriction, including without limitation the rights + * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell + * copies of the Software, and to permit persons to whom the Software is + * furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included in + * all copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE + * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER + * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, + * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN + * THE SOFTWARE. + */ + +// XenGuestServices.h : Declaration of the CXenGuestServices + +#pragma once +#include "resource.h" // main symbols +#include "input.h" +#include "OxtService_i.h" + +#define APPID_OxtService "{50DCAB6F-A549-4E77-BF95-A3B688BDF625}" + +#define XGS_MAX_INSTANCES 64 + +// A single instance of this class connects the various bits and pieces of the +// OxtService service together. + +class COxtService +{ +private: + OSVERSIONINFOEX m_osvi; + volatile LONG m_ulXgsCount; + HANDLE m_hShutdownEvent; + bool m_bLogCommunicationErrors; + bool m_bLogOperationErrors;; + +public: + COxtService() : m_ulXgsCount(0), + m_hShutdownEvent(NULL), + m_bLogCommunicationErrors(false), + m_bLogOperationErrors(false) + { + ::ZeroMemory(&m_osvi, sizeof(OSVERSIONINFO)); + } + + ~COxtService() + { + } + + HANDLE GetShutdownEvent() + { + return m_hShutdownEvent; + } + + VOID SetShutdownEvent() + { + if (m_hShutdownEvent != NULL) + ::SetEvent(m_hShutdownEvent); + } + + const OSVERSIONINFOEX* GetOsInfo() + { + return &m_osvi; + } + + bool Initialize(); + VOID Uninitialize(); + bool Start(); + + VOID LogEventTypeId(LPCTSTR tszFormat, WORD wType, DWORD dwEventId, va_list args); + VOID LogEventTypeId(ULONG ulFormat, WORD wType, DWORD dwEventId, va_list args); + VOID LogEventTypeId(ULONG ulFormat, WORD wType, DWORD dwEventId, ...); + bool LogEventTypeIdLastError(ULONG ulFormat, WORD wType, DWORD dwEventId, va_list args); + bool LogEventTypeIdLastError(ULONG ulFormat, WORD wType, DWORD dwEventId, ...); + bool LogEventTypeIdLastRegistryError(ULONG ulFormat, WORD wType, DWORD dwEventId, LONG lRet, va_list args); + bool LogEventTypeIdLastRegistryError(ULONG ulFormat, WORD wType, DWORD dwEventId, LONG lRet, ...); + bool LogEventTypeIdLastErrorAlways(ULONG ulFormat, WORD wType, DWORD dwEventId, va_list args); + bool LogEventTypeIdLastErrorAlways(ULONG ulFormat, WORD wType, DWORD dwEventId, ...); + + bool RegisterXgs(); + void UnregisterXgs(); + +private: + +}; + +extern COxtService _OxtService; diff --git a/OxtService/OxtService.idl b/OxtService/OxtService.idl new file mode 100644 index 0000000..70d256c --- /dev/null +++ b/OxtService/OxtService.idl @@ -0,0 +1,62 @@ +/* + * Copyright (c) 2012 Citrix Systems, Inc. + * Copyright (c) 2016 Assured Information Security, Inc + * + * Permission is hereby granted, free of charge, to any person obtaining a copy + * of this software and associated documentation files (the "Software"), to deal + * in the Software without restriction, including without limitation the rights + * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell + * copies of the Software, and to permit persons to whom the Software is + * furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included in + * all copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE + * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER + * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, + * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN + * THE SOFTWARE. + */ + +// OxtGuestAgent.idl : IDL source for XenGuestAgent +// + +// This file will be processed by the MIDL tool to +// produce the type library (XenGuestAgent.tlb) and marshalling code. + +import "oaidl.idl"; +import "ocidl.idl"; + +[ + object, + uuid(3F2A5FA9-D569-4670-BCBB-2C7243C7DC0B), + dual, + nonextensible, + helpstring("IOxtGuestServices Interface"), + pointer_default(unique) +] +interface IOxtGuestServices : IDispatch{ + [id(1), helpstring("method XenStoreRead")] HRESULT XenStoreRead([in] BSTR bstrPath, [out,retval] BSTR* pbstrValue); + [id(2), helpstring("method XenStoreRead")] HRESULT XenStoreWrite([in] BSTR bstrPath, [in] BSTR bstrValue); +}; + +[ + uuid(CB46685A-BBB0-406B-BB1D-CF1641FFF17D), + version(1.0), + helpstring("OxtService 1.0 Type Library") +] +library OxtServiceLib +{ + importlib("stdole2.tlb"); + [ + uuid(79E8108A-57E6-4E3D-B98F-DB90572B7F5A), + helpstring("OxtGuestServices Class") + ] + coclass OxtGuestServices + { + [default] interface IOxtGuestServices; + }; +}; diff --git a/OxtService/OxtService.rc b/OxtService/OxtService.rc new file mode 100644 index 0000000..6ae5745 --- /dev/null +++ b/OxtService/OxtService.rc @@ -0,0 +1,152 @@ +// Microsoft Visual C++ generated resource script. +// +#include "resource.h" + +#define APSTUDIO_READONLY_SYMBOLS +///////////////////////////////////////////////////////////////////////////// +// +// Generated from the TEXTINCLUDE 2 resource. +// +#ifndef APSTUDIO_INVOKED +#include "targetver.h" +#endif +#include "winres.h" + +///////////////////////////////////////////////////////////////////////////// +#undef APSTUDIO_READONLY_SYMBOLS + +///////////////////////////////////////////////////////////////////////////// +// English (United States) resources + +#if !defined(AFX_RESOURCE_DLL) || defined(AFX_TARG_ENU) +LANGUAGE LANG_ENGLISH, SUBLANG_ENGLISH_US +#pragma code_page(1252) + +#ifdef APSTUDIO_INVOKED +///////////////////////////////////////////////////////////////////////////// +// +// TEXTINCLUDE +// + +1 TEXTINCLUDE +BEGIN + "resource.h\0" +END + +2 TEXTINCLUDE +BEGIN + "#ifndef APSTUDIO_INVOKED\r\n" + "#include ""targetver.h""\r\n" + "#endif\r\n" + "#include ""winres.h""\r\n" + "\0" +END + +3 TEXTINCLUDE +BEGIN + "1 TYPELIB ""OxtService.tlb""\r\n" + "#include ""oxtmsg.rc""\r\n" + "#include ""OxtService.en.rc""\r\n" + "\0" +END + +#endif // APSTUDIO_INVOKED + + +///////////////////////////////////////////////////////////////////////////// +// +// Version +// + +VS_VERSION_INFO VERSIONINFO + FILEVERSION 16,0,0,0 + PRODUCTVERSION 16,0,0,0 + FILEFLAGSMASK 0x3fL +#ifdef _DEBUG + FILEFLAGS 0x1L +#else + FILEFLAGS 0x0L +#endif + FILEOS 0x4L + FILETYPE 0x1L + FILESUBTYPE 0x0L +BEGIN + BLOCK "StringFileInfo" + BEGIN + BLOCK "040904e4" + BEGIN + VALUE "CompanyName", "OpenXT Project" + VALUE "FileDescription", "OpenXT Xen guest services provider" + VALUE "FileVersion", "16.0.0.0" + VALUE "InternalName", "OxtService.exe" + VALUE "LegalCopyright", "Copyright © 2016 Put Your Company Name Here" + VALUE "OriginalFilename", "OxtService.exe" + VALUE "ProductName", "OpenXT Tools for Virtual Machines" + VALUE "ProductVersion", "16.0.0.0" + END + END + BLOCK "VarFileInfo" + BEGIN + VALUE "Translation", 0x409, 1252 + END +END + + +///////////////////////////////////////////////////////////////////////////// +// +// REGISTRY +// + +IDR_OXTSERVICE REGISTRY "OxtService.rgs" +IDR_OXTGUESTSERVICES REGISTRY "OxtGuestServices.rgs" + +///////////////////////////////////////////////////////////////////////////// +// +// Icon +// + +// Icon with lowest ID value placed first to ensure application icon +// remains consistent on all systems. +IDI_ICON1 ICON "xen.ico" + +///////////////////////////////////////////////////////////////////////////// +// +// String Table +// + +STRINGTABLE +BEGIN + IDS_SERVICENAME "OxtService" +END + +STRINGTABLE +BEGIN + IDS_DISPLAYNAME "OpenXT Xen Guest Services" + IDS_SERVICEDESC "Provides in-guest services for Xen user domains." +END + +STRINGTABLE +BEGIN + IDS_ATLBASE_NO_HANDLER "Handler not installed" + IDS_ATLBASE_SERVICE_STOPPED "Service stopped" + IDS_ATLBASE_SERVICE_STARTED "Service started" + IDS_ATLBASE_BAD_SERVICE "Bad service request" +END + +#endif // English (United States) resources +///////////////////////////////////////////////////////////////////////////// + + + +#ifndef APSTUDIO_INVOKED +///////////////////////////////////////////////////////////////////////////// +// +// Generated from the TEXTINCLUDE 3 resource. +// +1 TYPELIB "OxtService.tlb" +#include "oxtmsg.rc" +#include "OxtService.en.rc" + +///////////////////////////////////////////////////////////////////////////// +#endif // not APSTUDIO_INVOKED + diff --git a/OxtService/OxtService.rgs b/OxtService/OxtService.rgs new file mode 100644 index 0000000..e5d0b41 --- /dev/null +++ b/OxtService/OxtService.rgs @@ -0,0 +1,11 @@ +HKCR +{ + NoRemove AppID + { + '%APPID%' = s 'OxtService' + 'OxtService.EXE' + { + val AppID = s '%APPID%' + } + } +} diff --git a/OxtService/OxtService.sln b/OxtService/OxtService.sln new file mode 100644 index 0000000..c1c90d6 --- /dev/null +++ b/OxtService/OxtService.sln @@ -0,0 +1,44 @@ + +Microsoft Visual Studio Solution File, Format Version 12.00 +# Visual Studio 2012 +Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "OxtService", "OxtService.vcxproj", "{68BD6C4D-B34B-450C-ABD1-EF4D4BAB123A}" +EndProject +Global + GlobalSection(SolutionConfigurationPlatforms) = preSolution + Debug|Mixed Platforms = Debug|Mixed Platforms + Debug|Win32 = Debug|Win32 + Debug|x64 = Debug|x64 + Debug|x86 = Debug|x86 + dummy|Mixed Platforms = dummy|Mixed Platforms + dummy|Win32 = dummy|Win32 + dummy|x64 = dummy|x64 + dummy|x86 = dummy|x86 + Release|Mixed Platforms = Release|Mixed Platforms + Release|Win32 = Release|Win32 + Release|x64 = Release|x64 + Release|x86 = Release|x86 + EndGlobalSection + GlobalSection(ProjectConfigurationPlatforms) = postSolution + {68BD6C4D-B34B-450C-ABD1-EF4D4BAB123A}.Debug|Mixed Platforms.ActiveCfg = Debug|Win32 + {68BD6C4D-B34B-450C-ABD1-EF4D4BAB123A}.Debug|Mixed Platforms.Build.0 = Debug|Win32 + {68BD6C4D-B34B-450C-ABD1-EF4D4BAB123A}.Debug|Win32.ActiveCfg = Debug|Win32 + {68BD6C4D-B34B-450C-ABD1-EF4D4BAB123A}.Debug|Win32.Build.0 = Debug|Win32 + {68BD6C4D-B34B-450C-ABD1-EF4D4BAB123A}.Debug|x64.ActiveCfg = Debug|Win32 + {68BD6C4D-B34B-450C-ABD1-EF4D4BAB123A}.Debug|x86.ActiveCfg = Debug|Win32 + {68BD6C4D-B34B-450C-ABD1-EF4D4BAB123A}.dummy|Mixed Platforms.ActiveCfg = Debug|Win32 + {68BD6C4D-B34B-450C-ABD1-EF4D4BAB123A}.dummy|Mixed Platforms.Build.0 = Debug|Win32 + {68BD6C4D-B34B-450C-ABD1-EF4D4BAB123A}.dummy|Win32.ActiveCfg = Debug|Win32 + {68BD6C4D-B34B-450C-ABD1-EF4D4BAB123A}.dummy|Win32.Build.0 = Debug|Win32 + {68BD6C4D-B34B-450C-ABD1-EF4D4BAB123A}.dummy|x64.ActiveCfg = Debug|Win32 + {68BD6C4D-B34B-450C-ABD1-EF4D4BAB123A}.dummy|x86.ActiveCfg = Debug|Win32 + {68BD6C4D-B34B-450C-ABD1-EF4D4BAB123A}.Release|Mixed Platforms.ActiveCfg = Release|Win32 + {68BD6C4D-B34B-450C-ABD1-EF4D4BAB123A}.Release|Mixed Platforms.Build.0 = Release|Win32 + {68BD6C4D-B34B-450C-ABD1-EF4D4BAB123A}.Release|Win32.ActiveCfg = Release|Win32 + {68BD6C4D-B34B-450C-ABD1-EF4D4BAB123A}.Release|Win32.Build.0 = Release|Win32 + {68BD6C4D-B34B-450C-ABD1-EF4D4BAB123A}.Release|x64.ActiveCfg = Release|Win32 + {68BD6C4D-B34B-450C-ABD1-EF4D4BAB123A}.Release|x86.ActiveCfg = Release|Win32 + EndGlobalSection + GlobalSection(SolutionProperties) = preSolution + HideSolutionNode = FALSE + EndGlobalSection +EndGlobal diff --git a/OxtService/OxtService.vcxproj b/OxtService/OxtService.vcxproj new file mode 100644 index 0000000..bd6d982 --- /dev/null +++ b/OxtService/OxtService.vcxproj @@ -0,0 +1,195 @@ + + + + + Debug + Win32 + + + Release + Win32 + + + + {68BD6C4D-B34B-450C-ABD1-EF4D4BAB123A} + OxtService + AtlProj + + + + Application + v110_xp + Static + Unicode + + + Application + v110_xp + Static + Unicode + + + + + + + + + + + + + <_ProjectFileVersion>11.0.50727.1 + + + $(OutDir) + $(OutDir) + true + true + + + $(OutDir) + $(OutDir) + true + false + + + + _DEBUG;%(PreprocessorDefinitions) + false + Win32 + true + $(IntDir)OxtService.tlb + OxtService_i.h + + OxtService_i.c + OxtService_p.c + true + + + Disabled + .;..\inc;.\xenhdrs;..\xenuser\xs2;%(AdditionalIncludeDirectories) + WIN32;_WINDOWS;_DEBUG;%(PreprocessorDefinitions) + true + EnableFastChecks + MultiThreadedDebug + + Level3 + EditAndContinue + + + _DEBUG;%(PreprocessorDefinitions) + 0x0409 + $(IntDir);%(AdditionalIncludeDirectories) + + + user32.lib;uuid.lib;kernel32.lib;powrprof.lib;%(AdditionalDependencies) + %(AdditionalLibraryDirectories) + true + Windows + MachineX86 + + + Performing registration + "$(TargetPath)" /RegServer + + + + + NDEBUG;%(PreprocessorDefinitions) + false + Win32 + true + $(IntDir)OxtService.tlb + OxtService_i.h + + OxtService_i.c + OxtService_p.c + true + + + MaxSpeed + .;..\inc;..\xenhdrs;..\xenuser\xs2;%(AdditionalIncludeDirectories) + WIN32;_WINDOWS;NDEBUG;%(PreprocessorDefinitions) + MultiThreaded + + Level3 + ProgramDatabase + + + NDEBUG;%(PreprocessorDefinitions) + 0x0409 + $(IntDir);%(AdditionalIncludeDirectories) + + + user32.lib;uuid.lib;kernel32.lib;powrprof.lib;%(AdditionalDependencies) + %(AdditionalLibraryDirectories) + true + Windows + true + true + MachineX86 + + + Performing registration + "$(TargetPath)" /RegServer + + + + + + Create + Create + + + + + + + + + false + + + false + + + + + + + + + + + + + + + + + + + + + + + + + + + mc .\oxtmsg.mc + + oxtmsg.rc;oxtmsg.h;%(Outputs) + mc .\oxtmsg.mc + + oxtmsg.rc;oxtmsg.h;%(Outputs) + + + + + + + + + \ No newline at end of file diff --git a/OxtService/OxtServiceTest/OxtServiceTest.cpp b/OxtService/OxtServiceTest/OxtServiceTest.cpp new file mode 100644 index 0000000..cd3b58a --- /dev/null +++ b/OxtService/OxtServiceTest/OxtServiceTest.cpp @@ -0,0 +1,177 @@ +/* + * Copyright (c) 2012 Citrix Systems, Inc. + * + * Permission is hereby granted, free of charge, to any person obtaining a copy + * of this software and associated documentation files (the "Software"), to deal + * in the Software without restriction, including without limitation the rights + * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell + * copies of the Software, and to permit persons to whom the Software is + * furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included in + * all copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE + * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER + * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, + * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN + * THE SOFTWARE. + */ + +// XenGuestTest.cpp : Defines the entry point for the console application. +// + +#include "stdafx.h" +#include "XenGuestAgent_i.h" +#include + +static const WCHAR g_XgsEventDACL[] = +{ + SDDL_DACL SDDL_DELIMINATOR SDDL_PROTECTED + + // Local system - full access + SDDL_ACE_BEGIN + SDDL_ACCESS_ALLOWED + SDDL_SEPERATOR + SDDL_SEPERATOR + SDDL_GENERIC_ALL + SDDL_SEPERATOR + SDDL_SEPERATOR + SDDL_SEPERATOR + SDDL_LOCAL_SYSTEM + SDDL_ACE_END + + // Creator/Owner - full access + SDDL_ACE_BEGIN + SDDL_ACCESS_ALLOWED + SDDL_SEPERATOR + SDDL_SEPERATOR + SDDL_GENERIC_ALL + SDDL_SEPERATOR + SDDL_SEPERATOR + SDDL_SEPERATOR + SDDL_CREATOR_OWNER + SDDL_ACE_END + + // LocalService - Read access. + SDDL_ACE_BEGIN + SDDL_ACCESS_ALLOWED + SDDL_SEPERATOR + SDDL_SEPERATOR + SDDL_GENERIC_ALL + SDDL_SEPERATOR + SDDL_SEPERATOR + SDDL_SEPERATOR + SDDL_LOCAL_SERVICE + SDDL_ACE_END + + // Interactive - Read access. + SDDL_ACE_BEGIN + SDDL_ACCESS_ALLOWED + SDDL_SEPERATOR + SDDL_SEPERATOR + SDDL_GENERIC_READ + SDDL_SEPERATOR + SDDL_SEPERATOR + SDDL_SEPERATOR + SDDL_INTERACTIVE + SDDL_ACE_END +}; + +void make_event() +{ + BOOL b; + PSECURITY_DESCRIPTOR pdesc = NULL; + SECURITY_ATTRIBUTES sa; + HANDLE h; + + b = ::ConvertStringSecurityDescriptorToSecurityDescriptor(g_XgsEventDACL, SDDL_REVISION_1, &pdesc, NULL); + if (!b) + return; + sa.nLength = sizeof(SECURITY_ATTRIBUTES); + sa.lpSecurityDescriptor = pdesc; + sa.bInheritHandle = FALSE; + + h = ::CreateEvent(&sa, FALSE, FALSE, L"testevent"); + + ::CloseHandle(h); + ::LocalFree(pdesc); +} + +void test_remote() +{ + HRESULT hr; + COSERVERINFO csi = {0, L"10.204.2.52", 0, 0}; + MULTI_QI mqi[] = {&IID_IXenGuestServices, NULL, S_OK}; + + ::CoInitializeEx(NULL, COINIT_MULTITHREADED); + + hr = CoCreateInstanceEx(CLSID_XenGuestServices, NULL, CLSCTX_SERVER, &csi, 1, mqi); +} + +int _tmain(int argc, _TCHAR* argv[]) +{ + HRESULT hr; + IXenGuestServices *piXgs = NULL; + IXenVmInfo *piXvi = NULL; + USHORT usd; + BSTR uuid; + ULONG c; + SAFEARRAY *psa; + + ::CoInitializeEx(NULL, COINIT_MULTITHREADED); + hr = ::CoCreateInstance(CLSID_XenGuestServices, + NULL, + CLSCTX_LOCAL_SERVER, + IID_IXenGuestServices, + (LPVOID*)&piXgs); + + + if (FAILED(hr)) + { + _tprintf(_T("Borked...\n")); + return -1; + } + + piXgs->GetDomId(&usd); + _tprintf(_T("My DOMID: %d\n"), usd); + + piXgs->GetUuid(&uuid); + wprintf(L"My UUID: %s\n", uuid); + ::SysFreeString(uuid); + + piXgs->QueryVms(&c); + wprintf(L"Domains: %d\n", c); + + if (c == 0) + goto done; + + piXgs->GetVmObject(0, &piXvi); + + if (piXvi == NULL) + { + wprintf(L"Hosed...\n"); + goto done; + } + + piXvi->GetUuid(&uuid); + wprintf(L"VM UUID: %s\n", uuid); + ::SysFreeString(uuid); + + piXvi->GetImage(&psa); + if (psa != NULL) + { + wprintf(L"Elements: %d\n", psa->cbElements); + ::SafeArrayDestroy(psa); + } + + piXvi->Release(); + +done: + piXgs->Release(); + ::CoUninitialize(); + return 0; +} + diff --git a/OxtService/OxtServiceTest/OxtServiceTest.sln b/OxtService/OxtServiceTest/OxtServiceTest.sln new file mode 100644 index 0000000..762797d --- /dev/null +++ b/OxtService/OxtServiceTest/OxtServiceTest.sln @@ -0,0 +1,20 @@ + +Microsoft Visual Studio Solution File, Format Version 10.00 +# Visual Studio 2008 +Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "XenGuestTest", "XenGuestTest.vcproj", "{EEC805B2-AF3B-44BF-9A7A-AB4BFE3A924F}" +EndProject +Global + GlobalSection(SolutionConfigurationPlatforms) = preSolution + Debug|Win32 = Debug|Win32 + Release|Win32 = Release|Win32 + EndGlobalSection + GlobalSection(ProjectConfigurationPlatforms) = postSolution + {EEC805B2-AF3B-44BF-9A7A-AB4BFE3A924F}.Debug|Win32.ActiveCfg = Debug|Win32 + {EEC805B2-AF3B-44BF-9A7A-AB4BFE3A924F}.Debug|Win32.Build.0 = Debug|Win32 + {EEC805B2-AF3B-44BF-9A7A-AB4BFE3A924F}.Release|Win32.ActiveCfg = Release|Win32 + {EEC805B2-AF3B-44BF-9A7A-AB4BFE3A924F}.Release|Win32.Build.0 = Release|Win32 + EndGlobalSection + GlobalSection(SolutionProperties) = preSolution + HideSolutionNode = FALSE + EndGlobalSection +EndGlobal diff --git a/OxtService/OxtServiceTest/OxtServiceTest.vcxproj b/OxtService/OxtServiceTest/OxtServiceTest.vcxproj new file mode 100644 index 0000000..211ed90 --- /dev/null +++ b/OxtService/OxtServiceTest/OxtServiceTest.vcxproj @@ -0,0 +1,122 @@ + + + + + Debug + Win32 + + + Release + Win32 + + + + {EEC805B2-AF3B-44BF-9A7A-AB4BFE3A924F} + XenGuestTest + Win32Proj + + + + Application + v110_xp + Static + Unicode + true + + + Application + v110_xp + Static + Unicode + + + + + + + + + + + + + + + <_ProjectFileVersion>10.0.40219.1 + $(SolutionDir)$(Configuration)\ + $(Configuration)\ + true + false + AllRules.ruleset + + + AllRules.ruleset + + + + + + Disabled + ..\;%(AdditionalIncludeDirectories) + WIN32;_DEBUG;_CONSOLE;%(PreprocessorDefinitions) + true + EnableFastChecks + MultiThreadedDebug + + + Level3 + EditAndContinue + + + true + Console + MachineX86 + + + + + MaxSpeed + true + ..\;%(AdditionalIncludeDirectories) + WIN32;NDEBUG;_CONSOLE;%(PreprocessorDefinitions) + MultiThreaded + true + + + Level3 + ProgramDatabase + + + true + Console + true + true + MachineX86 + + + + + Create + Create + + + + + + + + + + + + + + + {68bd6c4d-b34b-450c-abd1-ef4d4bab123a} + false + + + + + + \ No newline at end of file diff --git a/OxtService/OxtServiceTest/oxtsec_test.cpp b/OxtService/OxtServiceTest/oxtsec_test.cpp new file mode 100644 index 0000000..35fe71d --- /dev/null +++ b/OxtService/OxtServiceTest/oxtsec_test.cpp @@ -0,0 +1,71 @@ +/* + * Copyright (c) 2012 Citrix Systems, Inc. + * + * Permission is hereby granted, free of charge, to any person obtaining a copy + * of this software and associated documentation files (the "Software"), to deal + * in the Software without restriction, including without limitation the rights + * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell + * copies of the Software, and to permit persons to whom the Software is + * furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included in + * all copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE + * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER + * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, + * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN + * THE SOFTWARE. + */ + +// xgasec_test.cpp : Defines the entry point for the console application. +// + +#include "stdafx.h" +#include "XenGuestAgent_i.h" + +int wmain(int argc, WCHAR* argv[]) +{ + HRESULT hr; + COSERVERINFO csi = {0, L"", 0, 0}; + MULTI_QI mqi[1] = {&IID_IXenGuestServices, NULL, S_OK}; + + if (argc < 2) + { + wprintf(L"USAGE: xgasec_test \n"); + return 0; + } + + ::CoInitializeEx(NULL, COINIT_MULTITHREADED); + + // Try to create the remote object + csi.pwszName = argv[1]; + hr = ::CoCreateInstanceEx(CLSID_XenGuestServices, NULL, CLSCTX_SERVER, &csi, 1, mqi); + if (hr == S_OK) + { + wprintf(L"XGA security check FAILED! Remote object was able to be created!\n"); + wprintf(L" -- Remote object was able to be created!\n"); + mqi[0].pItf->Release(); + } + else + { + wprintf(L"XGA security check PASSED. Could not create object.\n"); + wprintf(L" -- Failure code returned: 0x%x\n", hr); + if (hr != E_ACCESSDENIED) + { + wprintf(L" -- Access was blocked by a firewall or some other means\n"); + wprintf(L" -- including the service not running.\n"); + } + else + { + wprintf(L" -- E_ACCESSDENIED indicates the tool contacted the DCOM server\n"); + wprintf(L" -- but the security settings prevent object creation.\n"); + } + } + + ::CoUninitialize(); + return 0; +} + diff --git a/OxtService/OxtServiceTest/stdafx.cpp b/OxtService/OxtServiceTest/stdafx.cpp new file mode 100644 index 0000000..78d8a8a --- /dev/null +++ b/OxtService/OxtServiceTest/stdafx.cpp @@ -0,0 +1,30 @@ +/* + * Copyright (c) 2012 Citrix Systems, Inc. + * + * Permission is hereby granted, free of charge, to any person obtaining a copy + * of this software and associated documentation files (the "Software"), to deal + * in the Software without restriction, including without limitation the rights + * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell + * copies of the Software, and to permit persons to whom the Software is + * furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included in + * all copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE + * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER + * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, + * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN + * THE SOFTWARE. + */ + +// stdafx.cpp : source file that includes just the standard includes +// XenGuestTest.pch will be the pre-compiled header +// stdafx.obj will contain the pre-compiled type information + +#include "stdafx.h" + +// TODO: reference any additional headers you need in STDAFX.H +// and not in this file diff --git a/OxtService/OxtServiceTest/stdafx.h b/OxtService/OxtServiceTest/stdafx.h new file mode 100644 index 0000000..59ecb53 --- /dev/null +++ b/OxtService/OxtServiceTest/stdafx.h @@ -0,0 +1,41 @@ +/* + * Copyright (c) 2012 Citrix Systems, Inc. + * + * Permission is hereby granted, free of charge, to any person obtaining a copy + * of this software and associated documentation files (the "Software"), to deal + * in the Software without restriction, including without limitation the rights + * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell + * copies of the Software, and to permit persons to whom the Software is + * furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included in + * all copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE + * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER + * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, + * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN + * THE SOFTWARE. + */ + +// stdafx.h : include file for standard system include files, +// or project specific include files that are used frequently, but +// are changed infrequently +// + +#pragma once + +#include "targetver.h" + +#include +#include + + +#define _ATL_CSTRING_EXPLICIT_CONSTRUCTORS // some CString constructors will be explicit + +#include +#include + +// TODO: reference additional headers your program requires here diff --git a/OxtService/OxtServiceTest/targetver.h b/OxtService/OxtServiceTest/targetver.h new file mode 100644 index 0000000..f28d969 --- /dev/null +++ b/OxtService/OxtServiceTest/targetver.h @@ -0,0 +1,46 @@ +/* + * Copyright (c) 2012 Citrix Systems, Inc. + * + * Permission is hereby granted, free of charge, to any person obtaining a copy + * of this software and associated documentation files (the "Software"), to deal + * in the Software without restriction, including without limitation the rights + * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell + * copies of the Software, and to permit persons to whom the Software is + * furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included in + * all copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE + * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER + * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, + * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN + * THE SOFTWARE. + */ + +#pragma once + +// The following macros define the minimum required platform. The minimum required platform +// is the earliest version of Windows, Internet Explorer etc. that has the necessary features to run +// your application. The macros work by enabling all features available on platform versions up to and +// including the version specified. + +// Modify the following defines if you have to target a platform prior to the ones specified below. +// Refer to MSDN for the latest info on corresponding values for different platforms. +#ifndef WINVER // Specifies that the minimum required platform is Windows Vista. +#define WINVER 0x0500 // Change this to the appropriate value to target other versions of Windows. +#endif + +#ifndef _WIN32_WINNT // Specifies that the minimum required platform is Windows Vista. +#define _WIN32_WINNT 0x0500 // Change this to the appropriate value to target other versions of Windows. +#endif + +#ifndef _WIN32_WINDOWS // Specifies that the minimum required platform is Windows 98. +#define _WIN32_WINDOWS 0x0410 // Change this to the appropriate value to target Windows Me or later. +#endif + +#ifndef _WIN32_IE // Specifies that the minimum required platform is Internet Explorer 7.0. +#define _WIN32_IE 0x0700 // Change this to the appropriate value to target other versions of IE. +#endif diff --git a/OxtService/ReadMe.txt b/OxtService/ReadMe.txt new file mode 100644 index 0000000..25fa887 --- /dev/null +++ b/OxtService/ReadMe.txt @@ -0,0 +1,78 @@ +======================================================================== + OxtService +======================================================================== + +Building: + +The OxtService project was based off the original XenGuestAgent and was +created using Developer Studio 2008. It now is built with VS 2012. + +======================================================================== + ACTIVE TEMPLATE LIBRARY : OxtService Project Overview +======================================================================== + +AppWizard has created this XenGuestAgent project for you to use as the starting point for +writing your Service (EXE). + +This file contains a summary of what you will find in each of the files that +make up your project. + +OxtService.vcproj + This is the main project file for VC++ projects generated using an Application Wizard. + It contains information about the version of Visual C++ that generated the file, and + information about the platforms, configurations, and project features selected with the + Application Wizard. + +OxtService.idl + This file contains the IDL definitions of the type library, the interfaces + and co-classes defined in your project. + This file will be processed by the MIDL compiler to generate: + C++ interface definitions and GUID declarations (OxtService.h) + GUID definitions (OxtService_i.c) + A type library (OxtService.tlb) + Marshaling code (OxtService_p.c and dlldata.c) + +OxtService.h + This file contains the C++ interface definitions and GUID declarations of the + items defined in OxtService.idl. It will be regenerated by MIDL during compilation. + +OxtService.cpp + This file contains the object map and the implementation of WinMain, ServiceMain, and + the service management functions. + +OxtService.rc + This is a listing of all of the Microsoft Windows resources that the + program uses. + + +///////////////////////////////////////////////////////////////////////////// +Other standard files: + +StdAfx.h, StdAfx.cpp + These files are used to build a precompiled header (PCH) file + named XenGuestAgent.pch and a precompiled types file named StdAfx.obj. + +Resource.h + This is the standard header file that defines resource IDs. + +///////////////////////////////////////////////////////////////////////////// +Proxy/stub DLL project and module definition file: + +We are using all automation types so we don't need a custom proxy/stub. We will +use the generic oleaut32 marshaller. + +///////////////////////////////////////////////////////////////////////////// + + +///////////////////////////////////////////////////////////////////////////// +NOTE: We had to switch to using SP1 for Studio 2008. There is a bug in the ATL +wizard that generates incorrect COM registry files so the class factory +registration fails. Clients all receive 0x80080005 trying to create objects. + +NOTE: SP1 does not fix teh problem. To work around it, you have to add this to +each of the RGS files for the coclasses created: +val AppID = s '%APPID%' + +NOTE: UseOfATL="1" to statically link the ATL library to reduce dependencies. + +///////////////////////////////////////////////////////////////////////////// \ No newline at end of file diff --git a/OxtService/XenStoreWrapper.cpp b/OxtService/XenStoreWrapper.cpp new file mode 100644 index 0000000..95a95fb --- /dev/null +++ b/OxtService/XenStoreWrapper.cpp @@ -0,0 +1,436 @@ +/* + * Copyright (c) 2012 Citrix Systems, Inc. + * Copyright (c) 2016 Assured Information Security, Inc + * + * Permission is hereby granted, free of charge, to any person obtaining a copy + * of this software and associated documentation files (the "Software"), to deal + * in the Software without restriction, including without limitation the rights + * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell + * copies of the Software, and to permit persons to whom the Software is + * furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included in + * all copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE + * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER + * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, + * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN + * THE SOFTWARE. + */ + +#include "stdafx.h" +#include "resource.h" +#include "XenStoreWrapper.h" + +#define XSW_XENTOOLS_REGKEY _T("Software\\Citrix\\XenTools") +#define XSW_DEFAULT_XS2PATH _T("C:\\Program Files\\Citrix\\XenTools\\xs2.dll") +#define XSW_XENTOOLS_XS2DLL _T("xs2.dll") + +#if !defined(_WIN64) +#define XS2_OPEN "_xs2_open@0" +#else +#define XS2_OPEN "xs2_open" +#endif + +#if !defined(_WIN64) +#define XS2_CLOSE "_xs2_close@4" +#else +#define XS2_CLOSE "xs2_close" +#endif + +#if !defined(_WIN64) +#define XS2_FREE "_xs2_free@4" +#else +#define XS2_FREE "xs2_free" +#endif + +#if !defined(_WIN64) +#define XS2_WRITE "_xs2_write@12" +#else +#define XS2_WRITE "xs2_write" +#endif + +#if !defined(_WIN64) +#define XS2_WRITE_BIN "_xs2_write_bin@16" +#else +#define XS2_WRITE_BIN "xs2_write_bin" +#endif + +#if !defined(_WIN64) +#define XS2_READ "_xs2_read@12" +#else +#define XS2_READ "xs2_read" +#endif + +#if !defined(_WIN64) +#define XS2_DIRECTORY "_xs2_directory@12" +#else +#define XS2_DIRECTORY "xs2_directory" +#endif + +#if !defined(_WIN64) +#define XS2_REMOVE "_xs2_remove@8" +#else +#define XS2_REMOVE "xs2_remove" +#endif + +#if !defined(_WIN64) +#define XS2_WATCH "_xs2_watch@12" +#else +#define XS2_WATCH "xs2_watch" +#endif + +#if !defined(_WIN64) +#define XS2_UNWATCH "_xs2_unwatch@4" +#else +#define XS2_UNWATCH "xs2_unwatch" +#endif + +typedef struct xs2_handle *(WINAPI *xs2_open_t)(void); +typedef void (WINAPI *xs2_close_t)(struct xs2_handle *handle); +typedef void (WINAPI *xs2_free_t)(const void *mem); +typedef BOOL (WINAPI *xs2_write_t)(struct xs2_handle *handle, + const char *path, + const char *data); +typedef BOOL (WINAPI *xs2_write_bin_t)(struct xs2_handle *handle, + const char *path, + const void *data, + size_t size); +typedef char** (WINAPI *xs2_directory_t)(struct xs2_handle *handle, + const char *path, + unsigned int *num); +typedef void* (WINAPI *xs2_read_t)(struct xs2_handle *handle, + const char *path, + size_t *len); +typedef BOOL (WINAPI *xs2_remove_t)(struct xs2_handle *handle, + const char *path); +typedef struct xs2_watch* (WINAPI *xs2_watch_t)(struct xs2_handle *handle, + const char *path, + HANDLE event); +typedef void (WINAPI *xs2_unwatch_t)(struct xs2_watch *watch); + +typedef struct _XSW_FUNCTIONS { + xs2_open_t fp_xs2_open; + xs2_close_t fp_xs2_close; + xs2_free_t fp_xs2_free; + xs2_write_t fp_xs2_write; + xs2_write_bin_t fp_xs2_write_bin; + xs2_read_t fp_xs2_read; + xs2_directory_t fp_xs2_directory; + xs2_remove_t fp_xs2_remove; + xs2_watch_t fp_xs2_watch; + xs2_unwatch_t fp_xs2_unwatch; +} XSW_FUNCTIONS; + +void *CXenStoreWrapper::m_fps = NULL; +HMODULE CXenStoreWrapper::m_hxs2 = NULL; + +bool CXenStoreWrapper::XS2Initialize() +{ + bool rc = false; + LONG lRes; + DWORD dwLen; + CRegKey clXenTools; + TCHAR tszXs2Path[_MAX_PATH + 1]; + XSW_FUNCTIONS *fps; + + do { + if (m_hxs2 != NULL) + { + ::SetLastError(ERROR_GEN_FAILURE); + break; + } + + m_fps = malloc(sizeof(XSW_FUNCTIONS)); + if (m_fps == NULL) + { + ::SetLastError(ERROR_OUTOFMEMORY); + break; + } + ::ZeroMemory(m_fps, sizeof(XSW_FUNCTIONS)); + fps = (XSW_FUNCTIONS*)m_fps; + + // Load a default location + _tcsncpy_s(tszXs2Path, _MAX_PATH, XSW_DEFAULT_XS2PATH, _TRUNCATE); + + // Find library in registry, load and get proc addresses. + lRes = clXenTools.Open(HKEY_LOCAL_MACHINE, XSW_XENTOOLS_REGKEY, KEY_READ); + if (lRes == ERROR_SUCCESS) + { + dwLen = _MAX_PATH; + lRes = clXenTools.QueryStringValue(XSW_XENTOOLS_XS2DLL, tszXs2Path, &dwLen); + if ((lRes != ERROR_SUCCESS)||(dwLen == 0)) + { + _tcsncpy_s(tszXs2Path, _MAX_PATH, XSW_DEFAULT_XS2PATH, _TRUNCATE); + } + } + + m_hxs2 = ::LoadLibrary(tszXs2Path); + if (m_hxs2 == NULL) + break; + +#define XSW_CHECK_FP(f) \ + if (f == NULL) {::SetLastError(ERROR_INVALID_FUNCTION); break;} + + fps->fp_xs2_open = (xs2_open_t)::GetProcAddress(m_hxs2, XS2_OPEN); + XSW_CHECK_FP(fps->fp_xs2_open); + + fps->fp_xs2_close = (xs2_close_t)::GetProcAddress(m_hxs2, XS2_CLOSE); + XSW_CHECK_FP(fps->fp_xs2_close); + + fps->fp_xs2_free = (xs2_free_t)::GetProcAddress(m_hxs2, XS2_FREE); + XSW_CHECK_FP(fps->fp_xs2_free); + + fps->fp_xs2_write = (xs2_write_t)::GetProcAddress(m_hxs2, XS2_WRITE); + XSW_CHECK_FP(fps->fp_xs2_write); + + fps->fp_xs2_write_bin = (xs2_write_bin_t)::GetProcAddress(m_hxs2, XS2_WRITE_BIN); + XSW_CHECK_FP(fps->fp_xs2_write_bin); + + fps->fp_xs2_read = (xs2_read_t)::GetProcAddress(m_hxs2, XS2_READ); + XSW_CHECK_FP(fps->fp_xs2_read); + + fps->fp_xs2_directory = (xs2_directory_t)::GetProcAddress(m_hxs2, XS2_DIRECTORY); + XSW_CHECK_FP(fps->fp_xs2_directory); + + fps->fp_xs2_remove = (xs2_remove_t)::GetProcAddress(m_hxs2, XS2_REMOVE); + XSW_CHECK_FP(fps->fp_xs2_remove); + + fps->fp_xs2_watch = (xs2_watch_t)::GetProcAddress(m_hxs2, XS2_WATCH); + XSW_CHECK_FP(fps->fp_xs2_watch); + + fps->fp_xs2_unwatch = (xs2_unwatch_t)::GetProcAddress(m_hxs2, XS2_UNWATCH); + XSW_CHECK_FP(fps->fp_xs2_unwatch); + + rc = true; + } while (false); + + if (!rc) + CXenStoreWrapper::XS2Uninitialize(); + + return rc; +} + +void CXenStoreWrapper::XS2Uninitialize() +{ + if (m_hxs2 != NULL) + { + ::FreeLibrary(m_hxs2); + m_hxs2 = NULL; + } + + if (m_fps != NULL) + { + free(m_fps); + m_fps = NULL; + } +} + +bool CXenStoreWrapper::XS2Open() +{ + XSW_FUNCTIONS *fps = (XSW_FUNCTIONS*)m_fps; + + if (m_hxs2 == NULL) + { + ::SetLastError(ERROR_INVALID_FUNCTION); + return false; + } + + // Note if the xs2 call fails it will set the last error + m_xsh = fps->fp_xs2_open(); + + return (m_xsh != NULL) ? true : false; +} + +bool CXenStoreWrapper::XS2Close() +{ + XSW_FUNCTIONS *fps = (XSW_FUNCTIONS*)m_fps; + ULONG i; + + if ((m_hxs2 == NULL)||(m_xsh == NULL)) + { + ::SetLastError(ERROR_INVALID_PARAMETER); + return false; + } + + // Clean up any watches that were opened + for (i = 0; i < XSW_MAX_WATCHES; i++) + { + if (m_watches[i] != NULL) + { + XS2Unwatch(m_watches[i]); + m_watches[i] = NULL; + } + } + + fps->fp_xs2_close(m_xsh); + m_xsh = NULL; + + return true; +} + +void CXenStoreWrapper::XS2Free(LPVOID pvMem) +{ + XSW_FUNCTIONS *fps = (XSW_FUNCTIONS*)m_fps; + + if (fps == NULL) + return; + + fps->fp_xs2_free(pvMem); +} + +bool CXenStoreWrapper::XS2Write(LPCSTR szPath, LPCSTR szData) +{ + XSW_FUNCTIONS *fps = (XSW_FUNCTIONS*)m_fps; + + if ((m_hxs2 == NULL)||(m_xsh == NULL)||(szPath == NULL)||(szData == NULL)) + { + ::SetLastError(ERROR_INVALID_PARAMETER); + return false; + } + + if (!fps->fp_xs2_write(m_xsh, szPath, szData)) + return false; + + return true; +} + +bool CXenStoreWrapper::XS2WriteBin(LPCSTR szPath, LPVOID pvData, DWORD dwLen) +{ + XSW_FUNCTIONS *fps = (XSW_FUNCTIONS*)m_fps; + + if ((m_hxs2 == NULL)||(m_xsh == NULL)||(szPath == NULL)||(pvData == NULL)) + { + ::SetLastError(ERROR_INVALID_PARAMETER); + return false; + } + + if (!fps->fp_xs2_write_bin(m_xsh, szPath, pvData, dwLen)) + return false; + + return true; +} + +LPVOID CXenStoreWrapper::XS2Read(LPCSTR szPath, LPDWORD pdwCount) +{ + XSW_FUNCTIONS *fps = (XSW_FUNCTIONS*)m_fps; + void *pv; + UINT ui; + + + if ((m_hxs2 == NULL)||(m_xsh == NULL)||(szPath == NULL)) + { + ::SetLastError(ERROR_INVALID_PARAMETER); + return NULL; + } + + pv = fps->fp_xs2_read(m_xsh, szPath, &ui); + + if (pdwCount != NULL) + *pdwCount = ui; + + return pv; +} + +LPSTR* CXenStoreWrapper::XS2Directory(LPCSTR szPath, LPDWORD pdwCount) +{ + XSW_FUNCTIONS *fps = (XSW_FUNCTIONS*)m_fps; + char **ppc; + UINT ui; + + + if ((m_hxs2 == NULL)||(m_xsh == NULL)||(szPath == NULL)||(pdwCount == NULL)) + { + ::SetLastError(ERROR_INVALID_PARAMETER); + return NULL; + } + + ppc = fps->fp_xs2_directory(m_xsh, szPath, &ui); + + *pdwCount = ui; + + return ppc; +} + +void CXenStoreWrapper::XS2FreeDirectory(LPSTR* pszDir, DWORD dwCount) +{ + XSW_FUNCTIONS *fps = (XSW_FUNCTIONS*)m_fps; + DWORD i; + + if ((m_hxs2 == NULL)||(m_xsh == NULL)||(pszDir == NULL)||(dwCount == 0)) + return; + + for (i = 0; i < dwCount; i++) + fps->fp_xs2_free(pszDir[i]); + + fps->fp_xs2_free(pszDir); +} + +bool CXenStoreWrapper::XS2Remove(LPCSTR szPath) +{ + XSW_FUNCTIONS *fps = (XSW_FUNCTIONS*)m_fps; + + if ((m_hxs2 == NULL)||(m_xsh == NULL)||(szPath == NULL)) + { + ::SetLastError(ERROR_INVALID_PARAMETER); + return false; + } + + if (!fps->fp_xs2_remove(m_xsh, szPath)) + return false; + + return true; +} + +LPVOID CXenStoreWrapper::XS2Watch(LPCSTR szPath, HANDLE hEvent) +{ + XSW_FUNCTIONS *fps = (XSW_FUNCTIONS*)m_fps; + void *pv; + ULONG i; + + if ((m_hxs2 == NULL)||(m_xsh == NULL)||(szPath == NULL)||(hEvent == NULL)) + { + ::SetLastError(ERROR_INVALID_PARAMETER); + return NULL; + } + + for (i = 0; i < XSW_MAX_WATCHES; i++) + { + if (m_watches[i] == NULL) + break; + } + + if (i >= XSW_MAX_WATCHES) + { + ::SetLastError(ERROR_NOT_ENOUGH_MEMORY); + return NULL; + } + + pv = (LPVOID)fps->fp_xs2_watch(m_xsh, szPath, hEvent); + m_watches[i] = pv; + + return pv; +} + +void CXenStoreWrapper::XS2Unwatch(LPVOID pvWatch) +{ + XSW_FUNCTIONS *fps = (XSW_FUNCTIONS*)m_fps; + ULONG i; + + if ((m_hxs2 == NULL)||(m_xsh == NULL)||(pvWatch == NULL)) + return; + + for (i = 0; i < XSW_MAX_WATCHES; i++) + { + if (m_watches[i] == pvWatch) + { + m_watches[i] = NULL; + break; + } + } + + fps->fp_xs2_unwatch((struct xs2_watch*)pvWatch); +} diff --git a/OxtService/XenStoreWrapper.h b/OxtService/XenStoreWrapper.h new file mode 100644 index 0000000..cf0302a --- /dev/null +++ b/OxtService/XenStoreWrapper.h @@ -0,0 +1,65 @@ +/* + * Copyright (c) 2012 Citrix Systems, Inc. + * Copyright (c) 2016 Assured Information Security, Inc + * + * Permission is hereby granted, free of charge, to any person obtaining a copy + * of this software and associated documentation files (the "Software"), to deal + * in the Software without restriction, including without limitation the rights + * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell + * copies of the Software, and to permit persons to whom the Software is + * furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included in + * all copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE + * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER + * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, + * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN + * THE SOFTWARE. + */ + +#pragma once +#include "resource.h" // main symbols +#include "xs2.h" + +#define XSW_MAX_WATCHES 16 + +class CXenStoreWrapper +{ +private: + static void *m_fps; + static HMODULE m_hxs2; + + struct xs2_handle *m_xsh; + LPVOID m_watches[16]; + + +public: + CXenStoreWrapper() : m_xsh(NULL) + { + ::ZeroMemory(m_watches, 16*sizeof(LPVOID)); + } + + ~CXenStoreWrapper() + { + XS2Close(); + } + + static bool XS2Initialize(); + static void XS2Uninitialize(); + + bool XS2Open(); + bool XS2Close(); + void XS2Free(LPVOID pvMem); + bool XS2Write(LPCSTR szPath, LPCSTR szData); + bool XS2WriteBin(LPCSTR szPath, LPVOID pvData, DWORD dwLen); + LPVOID XS2Read(LPCSTR szPath, LPDWORD pdwCount); + LPSTR* XS2Directory(LPCSTR szPath, LPDWORD pdwCount); + void XS2FreeDirectory(LPSTR* pszDir, DWORD dwCount); + bool XS2Remove(LPCSTR szPath); + LPVOID XS2Watch(LPCSTR szPath, HANDLE hEvent); + void XS2Unwatch(LPVOID pvWatch); +}; diff --git a/OxtService/common.h b/OxtService/common.h new file mode 100644 index 0000000..8ac27dc --- /dev/null +++ b/OxtService/common.h @@ -0,0 +1,27 @@ +/* + * Copyright (c) 2014 Citrix Systems, Inc. + * Copyright (c) 2016 Assured Information Security, Inc + * + * Permission is hereby granted, free of charge, to any person obtaining a copy + * of this software and associated documentation files (the "Software"), to deal + * in the Software without restriction, including without limitation the rights + * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell + * copies of the Software, and to permit persons to whom the Software is + * furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included in + * all copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE + * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER + * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, + * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN + * THE SOFTWARE. + */ + +#define COMMON_VERSION_STR "16.0.0.0" +#define COMMON_VERSION 16,0,0,0 +#define COMMON_COMPANY "Put Your Company Name Here" +#define COMMON_COPYRIGHT "Copyright © 2016 Put Your Company Name Here" diff --git a/OxtService/oxtmsg.mc b/OxtService/oxtmsg.mc new file mode 100644 index 0000000..82c0e63 --- /dev/null +++ b/OxtService/oxtmsg.mc @@ -0,0 +1,64 @@ +LanguageNames = ( + NeutralEnglish = 0x0009:Messages_en +) + +MessageId=0x00000000 +SymbolicName=EVMSG_GENERAL +Language=NeutralEnglish +General message: %1 +. + +MessageId=0x00000099 +SymbolicName=EVMSG_CRITICAL_FAILURE +Language=NeutralEnglish +Critical failure or bug detected: %1 +. + +MessageId=0x00000100 +SymbolicName=EVMSG_WARNING +Language=NeutralEnglish +Warning message: %1 +. + +MessageId=0x00000101 +SymbolicName=EVMSG_START_FAILURE +Language=NeutralEnglish +Startup failure: %1 +. + +MessageId=0x00000102 +SymbolicName=EVMSG_CREATION_FAILURE +Language=NeutralEnglish +Object creation failure: %1 +. + +MessageId=0x00000103 +SymbolicName=EVMSG_SECURITY_SETUP_FAILURE +Language=NeutralEnglish +Error during security setup. %1 +. + +MessageId=0x00000104 +SymbolicName=EVMSG_SECURITY_FAILURE +Language=NeutralEnglish +Security related failure occured. %1 +. + +MessageId=0x00000105 +SymbolicName=EVMSG_SECURITY_WARNING +Language=NeutralEnglish +Security warning. %1 +. + +MessageId=0x00000106 +SymbolicName=EVMSG_OPERATION_FAILURE +Language=NeutralEnglish +Error during service operation. %1 +. + +MessageId=0x00000107 +SymbolicName=EVMSG_COMMUNICATION_FAILURE +Language=NeutralEnglish +Communication error during service operation. %1 +. + diff --git a/OxtService/poweropts.c b/OxtService/poweropts.c new file mode 100644 index 0000000..d83c57f --- /dev/null +++ b/OxtService/poweropts.c @@ -0,0 +1,224 @@ +/* + * Copyright (c) 2010 Citrix Systems, Inc. + * Copyright (c) 2016 Assured Information Security, Inc + * + * Permission is hereby granted, free of charge, to any person obtaining a copy + * of this software and associated documentation files (the "Software"), to deal + * in the Software without restriction, including without limitation the rights + * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell + * copies of the Software, and to permit persons to whom the Software is + * furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included in + * all copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE + * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER + * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, + * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN + * THE SOFTWARE. + */ + +#include +#include +#include +#include +#include + +#define SIZECHARS(x) (sizeof(x)/sizeof(TCHAR)) + +// +// Enumerate Functions. +// +typedef +DWORD +(WINAPI *POWER_ENUMERATE) ( + __in_opt HKEY RootPowerKey, + __in_opt CONST GUID *SchemeGuid, + __in_opt CONST GUID *SubGroupOfPowerSettingsGuid, + __in POWER_DATA_ACCESSOR AccessFlags, + __in ULONG Index, + __out_bcount_opt(*BufferSize) UCHAR *Buffer, + __inout DWORD *BufferSize + ); + +typedef +DWORD +(WINAPI *POWER_READ_FRIENDLY_NAME) ( + __in_opt HKEY RootPowerKey, + __in_opt CONST GUID *SchemeGuid, + __in_opt CONST GUID *SubGroupOfPowerSettingsGuid, + __in_opt CONST GUID *PowerSettingGuid, + __out_bcount_opt(*BufferSize) PUCHAR Buffer, + __inout LPDWORD BufferSize + ); + +// +// Write functions. +// +typedef +DWORD +(WINAPI *POWER_WRITE_AC_VALUE_INDEX) ( + __in_opt HKEY RootPowerKey, + __in CONST GUID *SchemeGuid, + __in_opt CONST GUID *SubGroupOfPowerSettingsGuid, + __in_opt CONST GUID *PowerSettingGuid, + __in DWORD AcValueIndex + ); + +typedef +DWORD +(WINAPI *POWER_WRITE_DC_VALUE_INDEX) ( + __in_opt HKEY RootPowerKey, + __in CONST GUID *SchemeGuid, + __in_opt CONST GUID *SubGroupOfPowerSettingsGuid, + __in_opt CONST GUID *PowerSettingGuid, + __in DWORD DcValueIndex + ); + +POWER_ENUMERATE pPowerEnumerate = NULL; +POWER_READ_FRIENDLY_NAME pPowerReadFriendlyName = NULL; +POWER_WRITE_AC_VALUE_INDEX pPowerWriteACValueIndex = NULL; +POWER_WRITE_DC_VALUE_INDEX pPowerWriteDCValueIndex = NULL; + + +void PowerDisplayError(DWORD error) +{ + wchar_t *messageBuffer = NULL; + DWORD ret; + + ret = FormatMessageW(FORMAT_MESSAGE_ALLOCATE_BUFFER | FORMAT_MESSAGE_FROM_SYSTEM, + NULL, + error, + MAKELANGID(LANG_NEUTRAL, SUBLANG_DEFAULT), + (wchar_t*)&messageBuffer, + 0, + NULL); + if (ret == 0) { + return; + } + + // [XC-4655] This should never be used in a Windows service + // since it's not allowed to interact with the desktop +// MessageBoxW(NULL, messageBuffer, L"PowerOpts Error", MB_OK); + + if (messageBuffer != NULL) { + LocalFree(messageBuffer); + } +} + +#define POWER_BUFFER_SIZE 2048 + +static int PowerDisableHybridSleep(void) +{ + DWORD i1 = 0, i2; + DWORD ret, gsize = sizeof(GUID), bsize; + GUID scheme, setting; + wchar_t buf[(POWER_BUFFER_SIZE - 1)/sizeof(wchar_t)]; + int stat = 0; + + // Level one, enum the power schemes present + do { + // Each scheme is a GUID + ret = pPowerEnumerate(NULL, NULL, NULL, ACCESS_SCHEME, i1, (UCHAR*)&scheme, &gsize); + if (ret != ERROR_SUCCESS) { + break; + } + + // Level two, enum the individual settings for the sleep subgroup for this scheme + i2 = 0; + do { + // Each individual setting w/in a scheme and subgroup is also a GUID + ret = pPowerEnumerate(NULL, &scheme, &GUID_SLEEP_SUBGROUP, ACCESS_INDIVIDUAL_SETTING, i2, (UCHAR*)&setting, &gsize); + if (ret != ERROR_SUCCESS) { + // This is expected when there are no more power schemes + break; + } + + // Read each friendly name and find "Allow hybrid sleep" + bsize = POWER_BUFFER_SIZE; + ret = pPowerReadFriendlyName(NULL, &scheme, &GUID_SLEEP_SUBGROUP, &setting, (UCHAR*)buf, &bsize); + if (ret != ERROR_SUCCESS) { + // [XC-4655] Special case the return code of ERROR_FILE_NOT_FOUND + // This is returned when there are no more power schemes to enumerate + if (ret != ERROR_FILE_NOT_FOUND) { + PowerDisplayError(ret); + stat = -6; + } + break; + } + + if (_wcsnicmp(buf, L"allow hybrid sleep", bsize/sizeof(wchar_t)) == 0) { + + // Set the AC and DC value indices for this setting to 0 which sets a value of OFF + (void)pPowerWriteACValueIndex(NULL, &scheme, &GUID_SLEEP_SUBGROUP, &setting, 0); + + (void)pPowerWriteDCValueIndex(NULL, &scheme, &GUID_SLEEP_SUBGROUP, &setting, 0); + } + + i2++; + } while (TRUE); + + i1++; + } while (TRUE); + + return stat; +} + +int LoadPowerProfDll() +{ + HMODULE hModule = NULL; + TCHAR NewDevPath[MAX_PATH]; + // + // Load the entry points into the POWRPROF DLL... + // + GetSystemDirectory(NewDevPath, SIZECHARS(NewDevPath)); + StringCchCat (NewDevPath, SIZECHARS(NewDevPath), TEXT("\\POWRPROF.DLL")); + hModule = LoadLibrary(NewDevPath); + if (!hModule) + { + return -1; + } + + pPowerEnumerate = (POWER_ENUMERATE)GetProcAddress(hModule, "PowerEnumerate"); + pPowerReadFriendlyName = (POWER_READ_FRIENDLY_NAME)GetProcAddress(hModule, "PowerReadFriendlyName"); + pPowerWriteACValueIndex = (POWER_WRITE_AC_VALUE_INDEX)GetProcAddress(hModule, "PowerWriteACValueIndex"); + pPowerWriteDCValueIndex = (POWER_WRITE_DC_VALUE_INDEX)GetProcAddress(hModule, "PowerWriteDCValueIndex"); + + if (!pPowerEnumerate || !pPowerReadFriendlyName || !pPowerWriteACValueIndex || !pPowerWriteDCValueIndex) + { +//@@@ MessageBox(hWnd, "Error loading Wifi API procedure(s)", "Error", MB_OK); + return -2; + } + + return 0; +} + +int poweropts() +{ + OSVERSIONINFO osvi = {0}; + + osvi.dwOSVersionInfoSize = sizeof(OSVERSIONINFO); + if (!GetVersionEx((OSVERSIONINFO*)&osvi)) { + PowerDisplayError(GetLastError()); + return -1; + } + + if (osvi.dwMajorVersion < 6) { +// MessageBoxW(NULL, L"This utility only runs on Windows Vista and later operating systems", L"PowerOpts Error", MB_OK); + return -2; + } + + if (LoadPowerProfDll() != 0) { + return -3; + } + + // + // May use this for other power settings later. For now, use it to turn off + // hybrid-sleep settings + // + // [XC-4655] Propagate the final status back to the caller + return PowerDisableHybridSleep(); +} diff --git a/OxtService/resource.h b/OxtService/resource.h new file mode 100644 index 0000000..6428f36 --- /dev/null +++ b/OxtService/resource.h @@ -0,0 +1,159 @@ +/* + * Copyright (c) 2012 Citrix Systems, Inc. + * + * Permission is hereby granted, free of charge, to any person obtaining a copy + * of this software and associated documentation files (the "Software"), to deal + * in the Software without restriction, including without limitation the rights + * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell + * copies of the Software, and to permit persons to whom the Software is + * furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included in + * all copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE + * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER + * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, + * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN + * THE SOFTWARE. + */ + +//{{NO_DEPENDENCIES}} +// Microsoft Visual C++ generated include file. +// Used by OxtService.rc +// +#define IDS_SERVICENAME 100 +#define IDR_OXTSERVICE 101 +#define IDR_OXTGUESTSERVICES 102 +#define IDS_DISPLAYNAME 200 +#define IDS_SERVICEDESC 201 +#define IDI_ICON1 201 +#define IDS_ATLBASE_NO_HANDLER 401 +#define IDS_ATLBASE_SERVICE_STOPPED 402 +#define IDS_ATLBASE_SERVICE_STARTED 403 +#define IDS_ATLBASE_BAD_SERVICE 404 + +#define IDS_FAILED_TO_CREATE_OBJECT_LOCK___H_OXTGUESTSERVICES_24 4000 +#define IDS_FAILED_TO_OPEN_XENSTORE___HRESUL_OXTGUESTSERVICES_32 4001 +#define IDS_FAILED_TO_INITIALIZE_VM_VALUES___OXTGUESTSERVICES_53 4002 +#define IDS_MAXIMUM_INSTANCE_COUNT_REACHED___OXTGUESTSERVICES_61 4003 +#define IDS_FAILED_TO_CREATE_VMS_EVENT_GUID__OXTGUESTSERVICES_474 4004 +#define IDS_FAILED_TO_CREATE_VMS_EVENT___HRE_OXTGUESTSERVICES_492 4005 +#define IDS_FAILED_TO_CREATE_ALERTS_EVENT_GU_OXTGUESTSERVICES_532 4006 +#define IDS_FAILED_TO_CREATE_ALERTS_EVENT____OXTGUESTSERVICES_550 4007 +#define IDS_PRINCIPAL__zS_PERMISSION__zS_OPE_OXTSECURITYHELPER_35 4008 +#define IDS_DENY_CHECK_FAILURE___PERMISSION__OXTSECURITYHELPER_1244 4009 +#define IDS_DENY_REMOTE_CHECK_FOR_zS_DETECTE_OXTSECURITYHELPER_1279 4010 +#define IDS_ACCESSPERMISSION_OXTSECURITYHELPER_1281 4011 +#define IDS_DENY_REMOTE_CHECK_FOR_zS_DETECTE_OXTSECURITYHELPER_1301 4012 +#define IDS_LAUNCHPERMISSION_LAUNCH_OXTSECURITYHELPER_1303 4013 +#define IDS_DENY_REMOTE_CHECK_FOR_zS_DETECTE_OXTSECURITYHELPER_1309 4014 +#define IDS_LAUNCHPERMISSION_ACTIVATE_OXTSECURITYHELPER_1311 4015 +#define IDS_DENY_CHECK_FOUND_NO_SD_DACL_FOR__OXTSECURITYHELPER_1431 4016 +#define IDS_ACCESSPERMISSION_OXTSECURITYHELPER_1433 4017 +#define IDS_DENY_CHECK_FOUND_NO_SD_DACL_FOR__OXTSECURITYHELPER_1476 4018 +#define IDS_LAUNCHPERMISSION_OXTSECURITYHELPER_1478 4019 +#define IDS_FAILED_TO_ALLOCATE_SECURITY_ATTR_OXTSECURITYHELPER_1559 4020 +#define IDS_FAILED_TO_CREATE_SECURITY_DESCRI_OXTSECURITYHELPER_1569 4021 +#define IDS_FAILED_TO_GET_SIZES_FROM_MAKEABS_OXTSECURITYHELPER_1614 4022 +#define IDS_FAILED_TO_ALLOCATE_SECURITY_DESC_OXTSECURITYHELPER_1625 4023 +#define IDS_FAILED_CREATE_SD_IN_MAKEABSOLUTE_OXTSECURITYHELPER_1644 4024 +#define IDS_FAILED_TO_ALLOCATE_XSH_DESCRIPTO_OXTSECURITYHELPER_1689 4025 +#define IDS_FAILED_TO_INITIALIZE_COM_SID___E_OXTSECURITYHELPER_1699 4026 +#define IDS_FAILED_TO_ALLOCATE_PINTERACTIVSI_OXTSECURITYHELPER_1709 4027 +#define IDS_FAILED_TO_ALLOCATE_ADMINS_SID_OXTSECURITYHELPER_1718 4028 +#define IDS_FAILED_CREATEWELLKNOWNSID_PINTER_OXTSECURITYHELPER_1727 4029 +#define IDS_FAILED_CREATEWELLKNOWNSID_PADMIN_OXTSECURITYHELPER_1736 4030 +#define IDS_FAILED_SETENTRIESINACL_PINTERACT_OXTSECURITYHELPER_1755 4031 +#define IDS_FAILED_TO_SET_ADMINS_SID_AS_OWNE_OXTSECURITYHELPER_1765 4032 +#define IDS_FAILED_TO_SET_ADMINS_SID_AS_GROU_OXTSECURITYHELPER_1773 4033 +#define IDS_FAILED_TO_SET_DACL_FOR_SD___ERRO_OXTSECURITYHELPER_1782 4034 +#define IDS_SETUPPARAMETERKEY_COULD_NOT_CREA_OXTSERVICE_106 4053 +#define IDS_SETUPPARAMETERKEY_COULD_NOT_SET__OXTSERVICE_115 4054 +#define IDS_SETUPPARAMETERKEY_COULD_NOT_SET__OXTSERVICE_123 4055 +#define IDS_REGISTEREVENTSOURCE_COULD_NOT_OP_OXTSERVICE_145 4056 +#define IDS_REGISTEREVENTSOURCE_COULD_NOT_CR_OXTSERVICE_155 4057 +#define IDS_REGISTEREVENTSOURCE_COULD_NOT_SE_OXTSERVICE_165 4058 +#define IDS_REGISTEREVENTSOURCE_COULD_NOT_SE_OXTSERVICE_176 4059 +#define IDS_UNREGISTEREVENTSOURCE_COULD_NOT__OXTSERVICE_193 4060 +#define IDS_UPDATESERVICEREGISTRY_COULD_NOT__OXTSERVICE_233 4061 +#define IDS_UPDATESERVICEREGISTRY_COULD_NOT__OXTSERVICE_244 4062 +#define IDS_UPDATESERVICEREGISTRY_CHANGE_SER_OXTSERVICE_264 4063 +#define IDS_UPDATESERVICEREGISTRY_CHANGE_SER_OXTSERVICE_275 4064 +#define IDS_FAILED_TO_LOAD_XS2_LIBRARY___ERR_OXTSERVICE_413 4065 +#define IDS_FAILED_TO_START__SERVICE_SHOULD__OXTSERVICE_439 4066 +#define IDS_FAILED_TO_START_SERVICE_OXTSERVICE_459 4067 +#define IDS_GETVERSIONEX_FAILED_____ERROR__z_OXTSERVICE_537 4068 +#define IDS_FAILED_TO_CREATE_SHUTDOWN_EVENT__OXTSERVICE_545 4069 +#define IDS_FAILED_TO_CREATE_VMS_EVENT___ERR_OXTSERVICE_553 4070 +#define IDS_FAILED_TO_CREATE_VMS_VECTOR_LOCK_OXTSERVICE_561 4071 +#define IDS_FAILED_TO_CREATE_ALERTS_VECTOR_L_OXTSERVICE_569 4072 +#define IDS_XS2OPEN_FAILED_FOR_START__NOT_RU_OXTSERVICE_689 4073 +#define IDS_XS2READ_FAILED_FOR_VM___ERROR__z_OXTSERVICE_697 4074 +#define IDS_XS2READ_FAILED_FOR_VM___ERROR__z_OXTSERVICE_720 4075 +#define IDS_FAILED_TO_START_TASK_THREAD___ER_OXTSERVICE_730 4076 +#define IDS_FAILED_TO_START_VMS_WATCH_THREAD_OXTSERVICE_739 4077 +#define IDS_FAILED_TO_START_ALERTS_WATCH_THR_OXTSERVICE_748 4078 +#define IDS_XS2OPEN_FAILED_FOR_LOADVMS___ERR_OXTSERVICE_1090 4079 +#define IDS_XS2DIRECTORY_NO_VMS_RETURNED____OXTSERVICE_1101 4080 +#define IDS_FAILED_TO_RETURN_SYSTEM_DIRECTOR_OXTSERVICE_1248 4081 +#define IDS_FAILED_TO_LAUNCH_POWERCFG_TOOL___OXTSERVICE_1261 4082 +#define IDS_FAILURE_RETURNED_FROM_POWEROPTS__OXTSERVICE_1282 4083 +#define IDS_WLANPROF__WLANAPI_DLL_NOT_FOUND_OXTSERVICE_1302 4084 +#define IDS_WLANPROF__ERROR_LOADING_WIFI_API_OXTSERVICE_1306 4085 +#define IDS_WLANPROF__ERROR_GETTING_LIST_OF__OXTSERVICE_1310 4086 +#define IDS_WLANPROF__ERROR_ADDING_AP__WLAN__OXTSERVICE_1314 4087 +#define IDS_WLANPROF__UNKNOWN_FAILURE_ENCOUN_OXTSERVICE_1318 4088 +#define IDS_XS2OPEN_FAILED_FOR_WATCHES___ERR_OXTSERVICE_1339 4089 +#define IDS_FAILED_TO_OPEN_XENSTORE_VMS_WATC_OXTSERVICE_1349 4090 +#define IDS_XS_WATCH_THREAD_SHUTTING_DOWN__OXTSERVICE_1359 4091 +#define IDS_WAIT_FAILED_DURING_XS_WATCH_WAIT_OXTSERVICE_1370 4092 +#define IDS_UNKNOWN_FAILURE_DURING_XS_WATCH__OXTSERVICE_1378 4093 +#define IDS_RECEIVED_XCDIAG_REQUEST_OXTSERVICE_1414 4094 +#define IDS_FAILED_TO_LAUNCH_XCDIAG_TOOL___E_OXTSERVICE_1430 4095 +#define IDS_FAILED_TO_OPEN_XCDIAG_OUTPUT_FIL_OXTSERVICE_1465 4096 +#define IDS_XCDIAG_OUTPUT_FILE_APPEARS_EMPTY_OXTSERVICE_1476 4097 +#define IDS_FAILED_TO_ALLOCATE_MEMORY_FOR_XC_OXTSERVICE_1486 4098 +#define IDS_FAILED_TO_ACCESS_XCDIAG_FILE_OXTSERVICE_1502 4099 +#define IDS_FAILED_TO_VIEW_XCDIAG_OUTPUT_OXTSERVICE_1520 4100 +#define IDS_XCDIAG_ZIP_FILE_SENT__OXTSERVICE_1591 4101 +#define IDS_DOPOST___OPERATION_FAILED___ERRO_OXTSERVICE_1596 4102 +#define IDS_DOGET___FAILED_TO_REGISTER_FOR_A_OXTSERVICE_1652 4103 +#define IDS_FAILED_TO_OPEN_V4V_CHANNEL_ON_FI_OXTSERVICE_1721 4104 +#define IDS_FAILED_TO_PARSE_JSON_SIGNAL___ER_OXTSERVICE_1759 4105 +#define IDS_SAFEARRAYACCESSDATA___FAILED___H_OXTSERVICE_1800 4106 +#define IDS_ALERTS_THREAD_SHUTTING_DOWN__OXTSERVICE_1825 4107 +#define IDS_DOGET___FAILED_TO_RECEIVE_SIGNAL_OXTSERVICE_1831 4108 +#define IDS_FAILED_TO_RESET_SIGNAL_REGISTRAT_OXTSERVICE_1838 4109 +#define IDS_SAFEARRAYCOPY___FAILED___HRESULT_OXTSERVICE_1875 4110 +#define IDS_E_OUTOFMEMORY___HRESULT__0XzX_OXTSERVICE_1881 4111 +#define IDS_SAFEARRAYACCESSDATA___FAILED___H_OXTGUESTSERVICES_230 4112 +#define IDS_SAFEARRAYACCESSDATA___RETRIEVED__OXTGUESTSERVICES_237 4113 +#define IDS_XS_WATCH_THREAD_SHUTTING_DOWN__OXTGUESTSERVICES_301 4114 +#define IDS_DOGET___FAILED___ERROR__zD_HTTP__OXTGUESTSERVICES_308 4115 +#define IDS_COCREATEINSTANCE_CLSID_XENVMINFO_OXTGUESTSERVICES_378 4116 +#define IDS_QUERYINTERFACE_IXENVMINITIALIZE__OXTGUESTSERVICES_385 4117 +#define IDS_QUERYINTERFACE_IXENVMINITIALIZE__OXTGUESTSERVICES_391 4118 +#define IDS_LOADIMAGEUID_FAILED__IMAGE__zS___OXTGUESTSERVICES_406 4119 +#define IDS_DELETING_XCIPLUGIN_RUN_VALUE_FAI_OXTGUESTSERVICES_640 4120 +#define IDS_CREATING_XCIPLUGIN_RUN_VALUE_FAI_OXTGUESTSERVICES_652 4121 +#define IDS_FAILED_TO_OPEN_XENINP_FILE_HANDL_OXTGUESTSERVICES_674 4122 +#define IDS_FAILED_TO_SEND_XENINP_IOCTL_ACCE_OXTGUESTSERVICES_683 4123 +#define IDS_FAILED_TO_PARSE_JSON_PROPERTY__ER_OXTSERVICE 4124 +#define IDS_UNEXPECTED_JSON_VALUE__ER_OXTSERVICE 4125 +#define IDS_ARRAY 4126 +#define IDS_BOOL 4127 +// Next default values for new objects +// +#ifdef APSTUDIO_INVOKED +#ifndef APSTUDIO_READONLY_SYMBOLS +#define _APS_NEXT_RESOURCE_VALUE 202 +#define _APS_NEXT_COMMAND_VALUE 32768 +#define _APS_NEXT_CONTROL_VALUE 201 +#define _APS_NEXT_SYMED_VALUE 105 +#endif +#endif + +#define ctxLS diff --git a/OxtService/stdafx.cpp b/OxtService/stdafx.cpp new file mode 100644 index 0000000..2d1a582 --- /dev/null +++ b/OxtService/stdafx.cpp @@ -0,0 +1,28 @@ +/* + * Copyright (c) 2012 Citrix Systems, Inc. + * Copyright (c) 2016 Assured Information Security, Inc + * + * Permission is hereby granted, free of charge, to any person obtaining a copy + * of this software and associated documentation files (the "Software"), to deal + * in the Software without restriction, including without limitation the rights + * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell + * copies of the Software, and to permit persons to whom the Software is + * furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included in + * all copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE + * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER + * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, + * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN + * THE SOFTWARE. + */ + +// stdafx.cpp : source file that includes just the standard includes +// XenGuestAgent.pch will be the pre-compiled header +// stdafx.obj will contain the pre-compiled type information + +#include "stdafx.h" diff --git a/OxtService/stdafx.h b/OxtService/stdafx.h new file mode 100644 index 0000000..377e3b4 --- /dev/null +++ b/OxtService/stdafx.h @@ -0,0 +1,51 @@ +/* + * Copyright (c) 2012 Citrix Systems, Inc. + * Copyright (c) 2016 Assured Information Security, Inc + * + * Permission is hereby granted, free of charge, to any person obtaining a copy + * of this software and associated documentation files (the "Software"), to deal + * in the Software without restriction, including without limitation the rights + * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell + * copies of the Software, and to permit persons to whom the Software is + * furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included in + * all copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE + * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER + * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, + * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN + * THE SOFTWARE. + */ + +// stdafx.h : include file for standard system include files, +// or project specific include files that are used frequently, +// but are changed infrequently + +#pragma once + +#ifndef STRICT +#define STRICT +#endif + +#include "targetver.h" + +#define _ATL_APARTMENT_THREADED +#define _ATL_NO_AUTOMATIC_NAMESPACE + +#define _ATL_CSTRING_EXPLICIT_CONSTRUCTORS // some CString constructors will be explicit + +#include "resource.h" +#include +#include +#include +#include +#include +#include +#include +#include + +using namespace ATL; diff --git a/OxtService/targetver.h b/OxtService/targetver.h new file mode 100644 index 0000000..7ff5412 --- /dev/null +++ b/OxtService/targetver.h @@ -0,0 +1,49 @@ +/* + * Copyright (c) 2012 Citrix Systems, Inc. + * Copyright (c) 2016 Assured Information Security, Inc + * + * Permission is hereby granted, free of charge, to any person obtaining a copy + * of this software and associated documentation files (the "Software"), to deal + * in the Software without restriction, including without limitation the rights + * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell + * copies of the Software, and to permit persons to whom the Software is + * furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included in + * all copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE + * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER + * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, + * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN + * THE SOFTWARE. + */ + + +#pragma once + +// The following macros define the minimum required platform. The minimum required platform +// is the earliest version of Windows, Internet Explorer etc. that has the necessary features to run +// your application. The macros work by enabling all features available on platform versions up to and +// including the version specified. + +// Modify the following defines if you have to target a platform prior to the ones specified below. +// Refer to MSDN for the latest info on corresponding values for different platforms. +#ifndef WINVER // Specifies that the minimum required platform is Windows Vista. +#define WINVER 0x0500 // Change this to the appropriate value to target other versions of Windows. +#endif + +#ifndef _WIN32_WINNT // Specifies that the minimum required platform is Windows XP. +#define _WIN32_WINNT 0x0501 // Change this to the appropriate value to target other versions of Windows. +#endif + +#ifndef _WIN32_WINDOWS // Specifies that the minimum required platform is Windows 98. +#define _WIN32_WINDOWS 0x0410 // Change this to the appropriate value to target Windows Me or later. +#endif + +#ifndef _WIN32_IE // Specifies that the minimum required platform is Internet Explorer 7.0. +#define _WIN32_IE 0x0700 // Change this to the appropriate value to target other versions of IE. +#endif + diff --git a/OxtService/xen.ico b/OxtService/xen.ico new file mode 100644 index 0000000..1af209e Binary files /dev/null and b/OxtService/xen.ico differ diff --git a/OxtUserAgent/OxtUserAgent.sln b/OxtUserAgent/OxtUserAgent.sln new file mode 100644 index 0000000..ea38904 --- /dev/null +++ b/OxtUserAgent/OxtUserAgent.sln @@ -0,0 +1,28 @@ + +Microsoft Visual Studio Solution File, Format Version 12.00 +# Visual Studio 2012 +Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "OxtUserAgent", "OxtUserAgent\OxtUserAgent.vcxproj", "{B99F006E-D0DF-4B3D-9CD2-F44EEB998A35}" +EndProject +Global + GlobalSection(SolutionConfigurationPlatforms) = preSolution + Debug|Win32 = Debug|Win32 + Debug|x64 = Debug|x64 + Release|Win32 = Release|Win32 + Release|x64 = Release|x64 + EndGlobalSection + GlobalSection(ProjectConfigurationPlatforms) = postSolution + {B99F006E-D0DF-4B3D-9CD2-F44EEB998A35}.Debug|Win32.ActiveCfg = Debug|Win32 + {B99F006E-D0DF-4B3D-9CD2-F44EEB998A35}.Debug|Win32.Build.0 = Debug|Win32 + {B99F006E-D0DF-4B3D-9CD2-F44EEB998A35}.Debug|Win32.Deploy.0 = Debug|Win32 + {B99F006E-D0DF-4B3D-9CD2-F44EEB998A35}.Debug|x64.ActiveCfg = Debug|x64 + {B99F006E-D0DF-4B3D-9CD2-F44EEB998A35}.Debug|x64.Build.0 = Debug|x64 + {B99F006E-D0DF-4B3D-9CD2-F44EEB998A35}.Release|Win32.ActiveCfg = Release|Win32 + {B99F006E-D0DF-4B3D-9CD2-F44EEB998A35}.Release|Win32.Build.0 = Release|Win32 + {B99F006E-D0DF-4B3D-9CD2-F44EEB998A35}.Release|Win32.Deploy.0 = Release|Win32 + {B99F006E-D0DF-4B3D-9CD2-F44EEB998A35}.Release|x64.ActiveCfg = Release|x64 + {B99F006E-D0DF-4B3D-9CD2-F44EEB998A35}.Release|x64.Build.0 = Release|x64 + EndGlobalSection + GlobalSection(SolutionProperties) = preSolution + HideSolutionNode = FALSE + EndGlobalSection +EndGlobal diff --git a/OxtUserAgent/OxtUserAgent/OxtUserAgent.cpp b/OxtUserAgent/OxtUserAgent/OxtUserAgent.cpp new file mode 100644 index 0000000..f75567d --- /dev/null +++ b/OxtUserAgent/OxtUserAgent/OxtUserAgent.cpp @@ -0,0 +1,215 @@ +/* + * Copyright (c) 2016 Assured Information Security, Inc. + * + * Permission is hereby granted, free of charge, to any person obtaining a copy + * of this software and associated documentation files (the "Software"), to deal + * in the Software without restriction, including without limitation the rights + * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell + * copies of the Software, and to permit persons to whom the Software is + * furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included in + * all copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE + * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER + * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, + * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN + * THE SOFTWARE. + */ + +#include "stdafx.h" +#include +#include +#include "OxtUserAgent.h" +#include "OxtService_i.h" + +#pragma warning(disable:4996) + +#define MAX_LOADSTRING 100 + +// Global Variables: +HINSTANCE hInst; // current instance +TCHAR szTitle[MAX_LOADSTRING]; // The title bar text +TCHAR szWindowClass[MAX_LOADSTRING]; // the main window class name + +static void OxtUpdateScreens(BOOL bClearScreens) +{ + DWORD dwDevNum; + int iCount = 0; + DISPLAY_DEVICE DisplayDevice; + BOOL bRet; + IOxtGuestServices *piOxtSvcs = NULL; + HRESULT hr; + int iWidth, iHeight; + WCHAR wszData[MAX_LOADSTRING]; + CComBSTR bstrPath, bstrValue; + + hr = ::CoCreateInstance(CLSID_OxtGuestServices, + NULL, + CLSCTX_LOCAL_SERVER, + IID_IOxtGuestServices, + (LPVOID*)&piOxtSvcs); + if (FAILED(hr)) + { + // Not much we can do... + return; + } + + if (bClearScreens) + { + bstrPath = L"display/activeAdapter"; + bstrValue = L"0"; + piOxtSvcs->XenStoreWrite(bstrPath, bstrValue); + return; + } + + ::memset(&DisplayDevice, 0, sizeof(DISPLAY_DEVICE)); + DisplayDevice.cb = sizeof(DISPLAY_DEVICE); + + for (dwDevNum = 0; ; dwDevNum++) + { + bRet = ::EnumDisplayDevices(NULL, dwDevNum, &DisplayDevice, 0); + if (!bRet) + { + // We are done, error returned when there are no more + break; + } + + if (((DisplayDevice.StateFlags & DISPLAY_DEVICE_ACTIVE) == 0) || + (DisplayDevice.StateFlags & DISPLAY_DEVICE_REMOTE)) + { + continue; + } + + _snwprintf(wszData, MAX_LOADSTRING, L"display/activeAdapter/%d", iCount); + bstrPath = wszData; + bstrValue = DisplayDevice.DeviceString; + piOxtSvcs->XenStoreWrite(bstrPath, bstrValue); + + iCount++; + } + + // First the active adapter count (not sure if it is used though). + bstrPath = L"display/activeAdapter"; + _snwprintf(wszData, MAX_LOADSTRING, L"%d", iCount); + bstrValue = wszData; + piOxtSvcs->XenStoreWrite(bstrPath, bstrValue); + + iWidth = ::GetSystemMetrics(SM_CXVIRTUALSCREEN); + iHeight = ::GetSystemMetrics(SM_CYVIRTUALSCREEN); + + bstrPath = L"attr/desktopDimensions"; + _snwprintf(wszData, MAX_LOADSTRING, L"%d %d", iWidth, iHeight); + bstrValue = wszData; + piOxtSvcs->XenStoreWrite(bstrPath, bstrValue); + + piOxtSvcs->Release(); +} + +LRESULT CALLBACK OxtWndProc(HWND hWnd, UINT message, WPARAM wParam, LPARAM lParam) +{ + switch (message) + { + case WM_POWERBROADCAST: + if (wParam == PBT_APMRESUMEAUTOMATIC) + { + OxtUpdateScreens(FALSE); + } + if (wParam == PBT_APMSUSPEND) + { + OxtUpdateScreens(TRUE); + } + break; + case WM_DISPLAYCHANGE: + OxtUpdateScreens(FALSE); + break; + case WM_DESTROY: + PostQuitMessage(0); + break; + default: + return ::DefWindowProc(hWnd, message, wParam, lParam); + } + return 0; +} + +static BOOL OxtInitInstance(HINSTANCE hInstance, int nCmdShow) +{ + HWND hWnd; + + hInst = hInstance; // Store instance handle in our global variable + + hWnd = ::CreateWindow(szWindowClass, szTitle, WS_OVERLAPPEDWINDOW, + CW_USEDEFAULT, 0, CW_USEDEFAULT, 0, NULL, NULL, hInstance, NULL); + if (!hWnd) + { + return FALSE; + } + + // We do not want to see the winder + //ShowWindow(hWnd, nCmdShow); + //UpdateWindow(hWnd); + + return TRUE; +} + +static void OxtRegisterClass(HINSTANCE hInstance) +{ + WNDCLASSEX wcex; + + wcex.cbSize = sizeof(WNDCLASSEX); + wcex.style = CS_HREDRAW | CS_VREDRAW; + wcex.lpfnWndProc = OxtWndProc; + wcex.cbClsExtra = 0; + wcex.cbWndExtra = 0; + wcex.hInstance = hInstance; + wcex.hIcon = LoadIcon(hInstance, MAKEINTRESOURCE(IDI_OXTUSERAGENT)); + wcex.hCursor = LoadCursor(NULL, IDC_ARROW); + wcex.hbrBackground = (HBRUSH)(COLOR_WINDOW+1); + wcex.lpszMenuName = MAKEINTRESOURCE(IDC_OXTUSERAGENT); + wcex.lpszClassName = szWindowClass; + wcex.hIconSm = LoadIcon(wcex.hInstance, MAKEINTRESOURCE(IDI_OXTUSERAGENT)); + + (void)::RegisterClassEx(&wcex); +} + +int APIENTRY _tWinMain(_In_ HINSTANCE hInstance, + _In_opt_ HINSTANCE hPrevInstance, + _In_ LPTSTR lpCmdLine, + _In_ int nCmdShow) +{ + MSG msg; + + UNREFERENCED_PARAMETER(hPrevInstance); + UNREFERENCED_PARAMETER(lpCmdLine); + UNREFERENCED_PARAMETER(nCmdShow); + + ::CoInitializeEx(NULL, COINIT_MULTITHREADED); + + LoadString(hInstance, IDS_APP_TITLE, szTitle, MAX_LOADSTRING); + LoadString(hInstance, IDC_OXTUSERAGENT, szWindowClass, MAX_LOADSTRING); + + OxtRegisterClass(hInstance); + + // Perform application initialization: + if (!OxtInitInstance(hInstance, nCmdShow)) + { + return FALSE; + } + + // Call once to initialize things a bit + OxtUpdateScreens(FALSE); + + // Main message loop: + while (GetMessage(&msg, NULL, 0, 0)) + { + TranslateMessage(&msg); + DispatchMessage(&msg); + } + + ::CoUninitialize(); + + return (int) msg.wParam; +} \ No newline at end of file diff --git a/OxtUserAgent/OxtUserAgent/OxtUserAgent.h b/OxtUserAgent/OxtUserAgent/OxtUserAgent.h new file mode 100644 index 0000000..e60f2eb --- /dev/null +++ b/OxtUserAgent/OxtUserAgent/OxtUserAgent.h @@ -0,0 +1,3 @@ +#pragma once + +#include "resource.h" diff --git a/OxtUserAgent/OxtUserAgent/OxtUserAgent.ico b/OxtUserAgent/OxtUserAgent/OxtUserAgent.ico new file mode 100644 index 0000000..7291ff2 Binary files /dev/null and b/OxtUserAgent/OxtUserAgent/OxtUserAgent.ico differ diff --git a/OxtUserAgent/OxtUserAgent/OxtUserAgent.rc b/OxtUserAgent/OxtUserAgent/OxtUserAgent.rc new file mode 100644 index 0000000..3b0c6ac Binary files /dev/null and b/OxtUserAgent/OxtUserAgent/OxtUserAgent.rc differ diff --git a/OxtUserAgent/OxtUserAgent/OxtUserAgent.vcxproj b/OxtUserAgent/OxtUserAgent/OxtUserAgent.vcxproj new file mode 100644 index 0000000..5e63f37 --- /dev/null +++ b/OxtUserAgent/OxtUserAgent/OxtUserAgent.vcxproj @@ -0,0 +1,176 @@ + + + + + Debug + Win32 + + + Debug + x64 + + + Release + Win32 + + + Release + x64 + + + + {B99F006E-D0DF-4B3D-9CD2-F44EEB998A35} + Win32Proj + OxtUserAgent + + + + Application + true + v110 + Unicode + + + Application + true + v110 + Unicode + + + Application + false + v110 + true + Unicode + + + Application + false + v110 + true + Unicode + + + + + + + + + + + + + + + + + + + true + + + true + + + false + + + false + + + + NotUsing + Level3 + Disabled + WIN32;_DEBUG;_WINDOWS;%(PreprocessorDefinitions) + ..\..\OxtService;%(AdditionalIncludeDirectories) + MultiThreadedDebug + + + Windows + true + %(AdditionalDependencies) + + + + + NotUsing + Level3 + Disabled + WIN32;_DEBUG;_WINDOWS;%(PreprocessorDefinitions) + ..\..\OxtService;%(AdditionalIncludeDirectories) + MultiThreadedDebug + + + Windows + true + %(AdditionalDependencies) + + + + + Level3 + NotUsing + MaxSpeed + true + true + WIN32;NDEBUG;_WINDOWS;%(PreprocessorDefinitions) + ..\..\OxtService;%(AdditionalIncludeDirectories) + MultiThreaded + + + Windows + true + true + true + %(AdditionalDependencies) + + + + + Level3 + NotUsing + MaxSpeed + true + true + WIN32;NDEBUG;_WINDOWS;%(PreprocessorDefinitions) + ..\..\OxtService;%(AdditionalIncludeDirectories) + MultiThreaded + + + Windows + true + true + true + %(AdditionalDependencies) + + + + + + + + + + + + + + Create + Create + Create + Create + + + + + + + + + + + + + \ No newline at end of file diff --git a/OxtUserAgent/OxtUserAgent/resource.h b/OxtUserAgent/OxtUserAgent/resource.h new file mode 100644 index 0000000..9980094 Binary files /dev/null and b/OxtUserAgent/OxtUserAgent/resource.h differ diff --git a/OxtUserAgent/OxtUserAgent/stdafx.cpp b/OxtUserAgent/OxtUserAgent/stdafx.cpp new file mode 100644 index 0000000..83547a9 --- /dev/null +++ b/OxtUserAgent/OxtUserAgent/stdafx.cpp @@ -0,0 +1,8 @@ +// stdafx.cpp : source file that includes just the standard includes +// OxtUserAgent.pch will be the pre-compiled header +// stdafx.obj will contain the pre-compiled type information + +#include "stdafx.h" + +// TODO: reference any additional headers you need in STDAFX.H +// and not in this file diff --git a/OxtUserAgent/OxtUserAgent/stdafx.h b/OxtUserAgent/OxtUserAgent/stdafx.h new file mode 100644 index 0000000..b6fe754 --- /dev/null +++ b/OxtUserAgent/OxtUserAgent/stdafx.h @@ -0,0 +1,22 @@ +// stdafx.h : include file for standard system include files, +// or project specific include files that are used frequently, but +// are changed infrequently +// + +#pragma once + +#include "targetver.h" + +#define WIN32_LEAN_AND_MEAN // Exclude rarely-used stuff from Windows headers +// Windows Header Files: +#include + +// C RunTime Header Files +#include +#include +#include +#include +#include + + +// TODO: reference additional headers your program requires here diff --git a/OxtUserAgent/OxtUserAgent/targetver.h b/OxtUserAgent/OxtUserAgent/targetver.h new file mode 100644 index 0000000..90e767b --- /dev/null +++ b/OxtUserAgent/OxtUserAgent/targetver.h @@ -0,0 +1,8 @@ +#pragma once + +// Including SDKDDKVer.h defines the highest available Windows platform. + +// If you wish to build your application for a previous Windows platform, include WinSDKVer.h and +// set the _WIN32_WINNT macro to the platform you wish to support before including SDKDDKVer.h. + +#include diff --git a/dirs b/dirs index 141de31..25bcd4c 100644 --- a/dirs +++ b/dirs @@ -20,5 +20,4 @@ DIRS=removedev \ copyvif \ fixdiskfilters \ input \ - xengfx \ xenaud diff --git a/do_build.ps1 b/do_build.ps1 index 44c4d3a..63469a1 100644 --- a/do_build.ps1 +++ b/do_build.ps1 @@ -32,16 +32,16 @@ $branch = $argtable["BuildBranch"] $MSBuild = $argtable["MSBuild"] $giturl = $argtable["GitUrl"] $gitbin = $argtable["GitBin"] -$crosssign = $argtable["CrossSign"] +$crosssign = $argtable["CrossSign"] $compile = $true # can be set to false if you just want to get to signing quickly #Set some important variables $mywd = Split-Path -Parent $MyInvocation.MyCommand.Path -if ($signtool.Length -lt 1) { - throw "Please specify the location of a directory containing signtool using the /signtool argument" -} - +if ($signtool.Length -lt 1) { + throw "Please specify the location of a directory containing signtool using the /signtool argument" +} + Push-Location -Path $mywd #Set build type @@ -50,8 +50,8 @@ if ($type.ToLower().CompareTo("debug") -eq 0) { $cfg = "chk" } - - + + Write-Host ("Building Xen Tools version: " + $verstr + " in: " + $mywd) @@ -145,16 +145,36 @@ if ($type.ToLower().CompareTo("debug") -eq 0) { Checked-Copy ".\xc-vusb\Drivers\xenvusb\x64\Win7Release\xenvusb.sys" ".\xc-vusb\build\x64\" } -if ($crosssign) { - Invoke-CommandChecked "do_sign" powershell ./do_sign.ps1 -certname ("'"+$certname+"'") -signtool ("'"+$signtool+"'") -crosssign ("'"+$crosssign+"'") -} else { - Invoke-CommandChecked "do_sign" powershell ./do_sign.ps1 -certname ("'"+$certname+"'") -signtool ("'"+$signtool+"'") -} +# Build the Oxt service and user agent +if ($compile) { + Invoke-CommandChecked "OxtService build" $MSBuild .\OxtService\OxtService.sln /p:Configuration=$type /t:Rebuild /m + Invoke-CommandChecked "OxtUserAgent build" $MSBuild .\OxtUserAgent\OxtUserAgent.sln /p:Configuration=$type /t:Rebuild /m +} + +if ($type -eq "Release") { + Invoke-CommandChecked "sign OxtService EXE" ($signtool+"\signtool.exe") sign /a /s my /n ('"'+$certname+'"') /t http://timestamp.verisign.com/scripts/timestamp.dll OxtService\$type\OxtService.exe + Invoke-CommandChecked "sign OxtUserAgent EXE" ($signtool+"\signtool.exe") sign /a /s my /n ('"'+$certname+'"') /t http://timestamp.verisign.com/scripts/timestamp.dll OxtUserAgent\$type\OxtUserAgent.exe +} + +if ($type.ToLower().CompareTo("debug") -eq 0) { + Checked-Copy ".\OxtService\Debug\OxtService.exe" ".\build\i386\" + Checked-Copy ".\OxtUserAgent\Debug\OxtUserAgent.exe" ".\build\i386\" +} else { + Checked-Copy ".\OxtService\Release\OxtService.exe" ".\build\i386\" + Checked-Copy ".\OxtUserAgent\Release\OxtUserAgent.exe" ".\build\i386\" +} + +# Main signing +if ($crosssign) { + Invoke-CommandChecked "do_sign" powershell ./do_sign.ps1 -certname ("'"+$certname+"'") -signtool ("'"+$signtool+"'") -crosssign ("'"+$crosssign+"'") +} else { + Invoke-CommandChecked "do_sign" powershell ./do_sign.ps1 -certname ("'"+$certname+"'") -signtool ("'"+$signtool+"'") +} #Only do verification if not doing a developer build if($developer -ne $true){ #Verify the drivers are signed using default signtool through %PATH% or use a specific one - Invoke-CommandChecked "doverifysign" .\doverifysign.ps1 $signtool\signtool.exe + Invoke-CommandChecked "doverifysign" .\doverifysign.ps1 $signtool\signtool.exe } Pop-Location @@ -166,7 +186,7 @@ Checked-Copy $licfile ".\license.txt" # Package the NSIS installer - need the individual version numbers here Write-Host "Building driver installer" -Invoke-CommandChecked "makensis" makensis "/DINSTALL_XENVESA" "/DINSTALL_XENVESA8" ("/DVERMAJOR=" + $ver0) ("/DVERMINOR=" + $ver1) ("/DVERMICRO=" + $ver2) ("/DVERBUILD=" + $ver3) "xensetup.nsi" +Invoke-CommandChecked "makensis" makensis "/DINSTALL_XENVESA" "/DINSTALL_XENVESA8" ("/DVERMAJOR=" + $ver0) ("/DVERMINOR=" + $ver1) ("/DVERMICRO=" + $ver2) ("/DVERBUILD=" + $ver3) "xensetup.nsi" if (!(Test-Path -Path ".\xensetup.exe" -PathType Leaf)) { diff --git a/install/xensetup.nsi b/install/xensetup.nsi index d5b11fd..b792ce7 100644 --- a/install/xensetup.nsi +++ b/install/xensetup.nsi @@ -708,6 +708,9 @@ ${EndIf} File ${BUILD_PREFIX}\copyvif.exe File ${BUILD_PREFIX}\fixdiskfilters.exe + File ${BUILD_PREFIX}\OxtService.exe + File ${BUILD_PREFIX}\OxtUserAgent.exe + ; this is the 64bit definition DO NOT RENAME THE FILES ${Else} File ${SIGN_PREFIX_64}\xenvusb.sys @@ -797,6 +800,9 @@ ${EndIf} File ${BUILD_PREFIX64}\copyvif.exe File ${BUILD_PREFIX64}\fixdiskfilters.exe + File ${BUILD_PREFIX}\OxtService.exe + File ${BUILD_PREFIX}\OxtUserAgent.exe + ${EndIf} ${LogText} "File copy done." @@ -1064,6 +1070,11 @@ DoneCheckingServicesTimeout: IntCmp "$0" 0 0 error !endif + ${LogText} "Installing OxtService service and OxtUserAgent..." + ExecWait '"$INSTDIR\OxtService.exe" /Service' $0 + ExecWait '"$INSTDIR\OxtService.exe" /DenyRemoteAccess' $0 + WriteRegStr HKLM "SOFTWARE\Microsoft\Windows\CurrentVersion\Run" "OxtUserAgent" "$INSTDIR\OxtUserAgent.exe" + ${LogText} "Drivers/service installation done." DetailPrint "Drivers/service installation done." @@ -1123,6 +1134,8 @@ DoneCheckingServicesTimeout: !ifndef NO_INSTALL_XENSERVICE Delete /REBOOTOK $UpgradingFromPath\xenservice.exe !endif + Delete /REBOOTOK $UpgradingFromPath\OxtService.exe + Delete /REBOOTOK $UpgradingFromPath\OxtUserAgent.exe Delete /REBOOTOK $UpgradingFromPath\xenvbd.inf Delete /REBOOTOK $UpgradingFromPath\xenvbd.sys Delete /REBOOTOK $UpgradingFromPath\xenvbd.cat @@ -1242,6 +1255,9 @@ SkipResettingServicesTimeout: DeleteRegKey HKLM SYSTEM\CurrentControlSet\Services\EventLog\Application\xensvc !endif + ExecWait '"$INSTDIR\OxtService.exe" /UnregServer' $0 + DeleteRegKey HKLM "SOFTWARE\Microsoft\Windows\CurrentVersion\Run\OxtUserAgent" + # Make sure that the devices can be disabled. ExecWait '"$INSTDIR\enableuninst.exe"' @@ -1415,6 +1431,8 @@ ${EndIf} !ifndef NO_INSTALL_XENSERVICE Delete /REBOOTOK $INSTDIR\xenservice.exe !endif + Delete /REBOOTOK $INSTDIR\OxtService.exe + Delete /REBOOTOK $INSTDIR\OxtUserAgent.exe Delete /REBOOTOK $INSTDIR\xenvbd.inf Delete /REBOOTOK $INSTDIR\xenvbd.sys Delete /REBOOTOK $INSTDIR\xenvbd.cat