From ff659159e041bf6c083e6b7fcb9b726065a9dd73 Mon Sep 17 00:00:00 2001 From: Rob Mensching Date: Mon, 3 May 2021 09:55:22 -0700 Subject: Move Util.wixext into ext --- src/ext/Util/ca/scasmbexec.cpp | 316 +++++++++++++++++++++++++++++++++++++++++ 1 file changed, 316 insertions(+) create mode 100644 src/ext/Util/ca/scasmbexec.cpp (limited to 'src/ext/Util/ca/scasmbexec.cpp') diff --git a/src/ext/Util/ca/scasmbexec.cpp b/src/ext/Util/ca/scasmbexec.cpp new file mode 100644 index 00000000..ced3aa78 --- /dev/null +++ b/src/ext/Util/ca/scasmbexec.cpp @@ -0,0 +1,316 @@ +// Copyright (c) .NET Foundation and contributors. All rights reserved. Licensed under the Microsoft Reciprocal License. See LICENSE.TXT file in the project root for full license information. + +#include "precomp.h" + + +/******************************************************************** + AllocateAcl - allocate an acl and populate it with this user and + permission information user could be user or domain\user + +********************************************************************/ +HRESULT AllocateAcl(SCA_SMBP* pssp, PACL* ppACL) +{ + HRESULT hr = S_OK; + EXPLICIT_ACCESSW* pEA = NULL; + DWORD cEA = 0; + DWORD dwCounter = 0; + + PSID psid = NULL; + LPCWSTR wzUser = NULL; + DWORD nPermissions = 0; + DWORD nErrorReturn = 0; + ACCESS_MODE accessMode = NOT_USED_ACCESS; + + cEA = pssp->dwUserPermissionCount + 1; + if (cEA >= MAXSIZE_T / sizeof(EXPLICIT_ACCESSW)) + { + ExitOnFailure(hr = E_OUTOFMEMORY, "Too many user permissions to allocate: %u", cEA); + } + + pEA = static_cast(MemAlloc(cEA * sizeof(EXPLICIT_ACCESSW), TRUE)); + ExitOnNull(pEA, hr, E_OUTOFMEMORY, "failed to allocate memory for explicit access structure"); + + // figure out how big the psid is + for (dwCounter = 0; dwCounter < pssp->dwUserPermissionCount; ++dwCounter) + { + wzUser = pssp->pUserPerms[dwCounter].wzUser; + nPermissions = pssp->pUserPerms[dwCounter].nPermissions; + accessMode = pssp->pUserPerms[dwCounter].accessMode; + // + // create the appropriate SID + // + + // figure out the right user to put into the access block + if (0 == lstrcmpW(wzUser, L"Everyone")) + { + hr = AclGetWellKnownSid(WinWorldSid, &psid); + } + else if (0 == lstrcmpW(wzUser, L"Administrators")) + { + hr = AclGetWellKnownSid(WinBuiltinAdministratorsSid, &psid); + } + else if (0 == lstrcmpW(wzUser, L"LocalSystem")) + { + hr = AclGetWellKnownSid(WinLocalSystemSid, &psid); + } + else if (0 == lstrcmpW(wzUser, L"LocalService")) + { + hr = AclGetWellKnownSid(WinLocalServiceSid, &psid); + } + else if (0 == lstrcmpW(wzUser, L"NetworkService")) + { + hr = AclGetWellKnownSid(WinNetworkServiceSid, &psid); + } + else if (0 == lstrcmpW(wzUser, L"AuthenticatedUser")) + { + hr = AclGetWellKnownSid(WinAuthenticatedUserSid, &psid); + } + else if (0 == lstrcmpW(wzUser, L"Guests")) + { + hr = AclGetWellKnownSid(WinBuiltinGuestsSid, &psid); + } + else if(0 == lstrcmpW(wzUser, L"CREATOR OWNER")) + { + hr = AclGetWellKnownSid(WinCreatorOwnerSid, &psid); + } + else + { + hr = AclGetAccountSid(NULL, wzUser, &psid); + } + ExitOnFailure(hr, "failed to get sid for account: %ls", wzUser); + + // we now have a valid pSid, fill in the EXPLICIT_ACCESS + + /* Permissions options: (see sca.sdh for defined sdl options) + #define GENERIC_READ (0x80000000L) 2147483648 + #define GENERIC_WRITE (0x40000000L) 1073741824 + #define GENERIC_EXECUTE (0x20000000L) 536870912 + #define GENERIC_ALL (0x10000000L) 268435456 + */ + pEA[dwCounter].grfAccessPermissions = nPermissions; + pEA[dwCounter].grfAccessMode = accessMode; + pEA[dwCounter].grfInheritance = SUB_CONTAINERS_AND_OBJECTS_INHERIT; +#pragma prefast(push) +#pragma prefast(disable:25029) + ::BuildTrusteeWithSidW(&(pEA[dwCounter].Trustee), psid); +#pragma prefast(pop) + } + + // create a new ACL that contains the ACE + *ppACL = NULL; +#pragma prefast(push) +#pragma prefast(disable:25029) + nErrorReturn = ::SetEntriesInAclW(dwCounter, pEA, NULL, ppACL); +#pragma prefast(pop) + ExitOnFailure(hr = HRESULT_FROM_WIN32(nErrorReturn), "failed to allocate ACL"); + +LExit: + if (psid) + { + AclFreeSid(psid); + } + + ReleaseMem(pEA); + + return hr; +} + + + +/******************************************************************** + FillShareInfo - fill the NetShareAdd data structure + +********************************************************************/ +void FillShareInfo(SHARE_INFO_502* psi, SCA_SMBP* pssp, PSECURITY_DESCRIPTOR pSD) +{ + psi->shi502_netname = pssp->wzKey; + psi->shi502_type = STYPE_DISKTREE; + psi->shi502_remark = pssp->wzDescription; + psi->shi502_permissions = 0; // not used + psi->shi502_max_uses = 0xFFFFFFFF; + psi->shi502_current_uses = 0; + psi->shi502_path = pssp->wzDirectory; + psi->shi502_passwd = NULL; // not file share perms + psi->shi502_reserved = 0; + psi->shi502_security_descriptor = pSD; +} + + + +/* NET_API_STATUS return codes +NERR_Success = 0 +NERR_DuplicateShare = 2118 +NERR_BufTooSmall = 2123 +NERR_NetNameNotFound = 2310 +NERR_RedirectedPath = 2117 +NERR_UnknownDevDir = 2116 +*/ + +/******************************************************************** + DoesShareExists - Does a share of this name exist on this computer? + +********************************************************************/ +HRESULT DoesShareExist(__in LPWSTR wzShareName) +{ + HRESULT hr = S_OK; + NET_API_STATUS s; + SHARE_INFO_502* psi = NULL; + s = ::NetShareGetInfo(NULL, wzShareName, 502, (BYTE**) &psi); + + switch (s) + { + case NERR_Success: + hr = S_OK; + break; + case NERR_NetNameNotFound: + hr = E_FILENOTFOUND; + break; + default: + WcaLogError(s, "NetShareGetInfo returned an unexpected value.", NULL); + hr = HRESULT_FROM_WIN32(s); + break; + } + + ::NetApiBufferFree(psi); + + return hr; +} + + + +/******************************************************************** + CreateShare - create the file share on this computer + +********************************************************************/ +HRESULT CreateShare(SCA_SMBP* pssp) +{ + if (!pssp || !(pssp->wzKey)) + return E_INVALIDARG; + + HRESULT hr = S_OK; + PACL pACL = NULL; + SHARE_INFO_502 si; + NET_API_STATUS s; + DWORD dwParamErr = 0; + + BOOL fShareExists = SUCCEEDED(DoesShareExist(pssp->wzKey)); + + PSECURITY_DESCRIPTOR pSD = static_cast(MemAlloc(SECURITY_DESCRIPTOR_MIN_LENGTH, TRUE)); + ExitOnNull(pSD, hr, E_OUTOFMEMORY, "Failed to allocate memory for security descriptor"); + +#pragma prefast(push) +#pragma prefast(disable:25029) + if (!::InitializeSecurityDescriptor(pSD, SECURITY_DESCRIPTOR_REVISION)) +#pragma prefast(pop) + { + ExitOnLastError(hr, "failed to initialize security descriptor"); + } + + hr = AllocateAcl(pssp, &pACL); + ExitOnFailure(hr, "Failed to allocate ACL for fileshare"); + + if (NULL == pACL) + { + WcaLog(LOGMSG_VERBOSE, "Ignoring NULL DACL."); + } +#pragma prefast(push) +#pragma prefast(disable:25028) // We only call this when pACL isn't NULL, so this call is safe according to the docs + // add the ACL to the security descriptor. + else if (!::SetSecurityDescriptorDacl(pSD, TRUE, pACL, FALSE)) + { + ExitOnLastError(hr, "Failed to set security descriptor"); + } +#pragma prefast(pop) + + // all that is left is to create the share + FillShareInfo(&si, pssp, pSD); + + // Fail if the directory doesn't exist + if (!DirExists(pssp->wzDirectory, NULL)) + ExitOnFailure(hr = HRESULT_FROM_WIN32(ERROR_OBJECT_NOT_FOUND), "Can't create a file share on directory that doesn't exist: %ls.", pssp->wzDirectory); + + WcaLog(LOGMSG_VERBOSE, "Creating file share on directory \'%ls\' named \'%ls\'.", pssp->wzDirectory, pssp->wzKey); + + if (!fShareExists) + { + s = ::NetShareAdd(NULL, 502, (BYTE*) &si, &dwParamErr); + WcaLog(LOGMSG_VERBOSE, "Adding a new file share."); + } + else + { + // The share exists. Write our new permissions over the top. + s = ::NetShareSetInfo(NULL, pssp->wzKey, 502, (BYTE*) &si, &dwParamErr); + WcaLog(LOGMSG_VERBOSE, "Setting permissions on existing share."); + } + + if (NERR_Success != s) + { + hr = E_FAIL; + if (!fShareExists && NERR_DuplicateShare == s) + WcaLog(LOGMSG_VERBOSE, "Duplicate error when existence check failed."); + + // error codes listed above. + ExitOnFailure(hr, "Failed to create/modify file share: Err: %d", s); + } + +LExit: + if (pACL) + { + ::LocalFree(pACL); + } + + ReleaseMem(pSD); + + return hr; +} + + +/******************************************************************** + ScaEnsureSmbExists + +********************************************************************/ +HRESULT ScaEnsureSmbExists(SCA_SMBP* pssp) +{ + HRESULT hr = S_OK; + + // create the share + hr = CreateShare(pssp); + + return hr; +} + + +// +// Delete File Shares - real work +// + +/******************************************************************** + ScaDropSmb - delete this file share from this computer + +********************************************************************/ +HRESULT ScaDropSmb(SCA_SMBP* pssp) +{ + HRESULT hr = S_OK; + NET_API_STATUS s; + + hr = DoesShareExist(pssp->wzKey); + + if (E_FILENOTFOUND == hr) + { + WcaLog(LOGMSG_VERBOSE, "Share doesn't exist, share removal skipped. (%ls)", pssp->wzKey); + ExitFunction1(hr = S_OK); + + } + + ExitOnFailure(hr, "Unable to detect share. (%ls)", pssp->wzKey); + + s = ::NetShareDel(NULL, pssp->wzKey, 0); + if (NERR_Success != s) + { + hr = E_FAIL; + ExitOnFailure(hr, "Failed to remove file share: Err: %d", s); + } + +LExit: + return hr; +} -- cgit v1.2.3-55-g6feb