STDMETHOD(GetSecurity) (THIS_ SECURITY_INFORMATION RequestedInformation, PSECURITY_DESCRIPTOR *ppSecurityDescriptor, BOOL fDefault ) { try { _variant_t vsd = m_filesystem->GetPathSecurityDescriptor(m_pathName); SECURITY_DESCRIPTOR* self; SafeArrayAccessData(vsd.parray, (void**)&self); DWORD absSize = 0; DWORD daclSize = 0; DWORD saclSize = 0; DWORD ownerSize = 0; DWORD primGroupSize = 0; MakeAbsoluteSD(self, NULL, &absSize, NULL, &daclSize, NULL, &saclSize, NULL, &ownerSize, NULL, &primGroupSize); pSD = LocalAlloc(0, absSize); MakeAbsoluteSD(self, pSD, &absSize, /*pSD->Dacl =*/ (PACL)LocalAlloc(0, daclSize), &daclSize, /*pSD->Sacl =*/ (PACL)LocalAlloc(0, saclSize), &saclSize, /*pSD->Owner =*/ (PSID)LocalAlloc(0, ownerSize), &ownerSize, /*pSD->Group =*/ (PSID)LocalAlloc(0, primGroupSize), &primGroupSize); SafeArrayUnaccessData(vsd.parray); } catch (_com_error &e) { com_error_Message(e); } *ppSecurityDescriptor = pSD; return S_OK; }
/// Prelude actions to start up the service, e.g. to set any global variables from the settings or perform /// any system specific actions. E.g. the Windows implementation registers with the service control manager /// and can optionally set the security descriptor on the process to allow clients to kill/restart it. /// /// @param[in] nReason how the startup is occuring (e.g. SERVICE_RUN_INLINE) - different actions may be /// required depending on whether the code is running direct from main() or through another mechansim static void _ServiceStartup (int nReason) { CSettings oSettings; #ifdef _WIN32 if (nReason == SERVICE_RUN_SCM) { g_hServiceStatus = RegisterServiceCtrlHandler (oSettings.GetServiceName (), ServiceHandler); } PCTSTR pszSDDL = oSettings.GetServiceSDDL (); if (pszSDDL) { LOGDEBUG (TEXT ("Setting security descriptor ") << pszSDDL); PSECURITY_DESCRIPTOR psdRelative; if (ConvertStringSecurityDescriptorToSecurityDescriptor (pszSDDL, SDDL_REVISION_1, &psdRelative, NULL)) { DWORD cbAbsolute = 1024; PSECURITY_DESCRIPTOR psdAbsolute = (PSECURITY_DESCRIPTOR)malloc (cbAbsolute); DWORD cbD = 1024; PACL paclD = (PACL)malloc (cbD); DWORD cbS = 1024; PACL paclS = (PACL)malloc (cbS); DWORD cbOwner = 1024; PSID psidOwner = (PSID)malloc (cbOwner); DWORD cbPGroup = 1024; PSID psidPGroup = (PSID)malloc (cbPGroup); if (MakeAbsoluteSD (psdRelative, psdAbsolute, &cbAbsolute, paclD, &cbD, paclS, &cbS, psidOwner, &cbOwner, psidPGroup, &cbPGroup)) { DWORD dwError = SetSecurityInfo (GetCurrentProcess (), SE_KERNEL_OBJECT, DACL_SECURITY_INFORMATION, NULL, NULL, paclD, NULL); if (dwError == ERROR_SUCCESS) { LOGINFO (TEXT ("Security descriptor set on process handle")); } else { LOGWARN (TEXT ("Couldn't set security descriptor on process handle, error ") << GetLastError ()); } } else { LOGWARN (TEXT ("Couldn't create absolute security description, error ") << GetLastError ()); } free (psdAbsolute); free (paclD); free (paclS); free (psidOwner); free (psidPGroup); LocalFree (psdRelative); } else { LOGWARN (TEXT ("Couldn't parse SDDL ") << pszSDDL << TEXT (", error ") << GetLastError ()); } } else { LOGDEBUG (TEXT ("No security descriptor specified")); } #endif /* ifdef _WIN32 */ g_lBusyTimeout = oSettings.GetBusyTimeout (); _ReportStateStarting (); }
/*---------------------------------------------------------------------------*\ * NAME: MakeSDAbsolute * --------------------------------------------------------------------------* * DESCRIPTION: Takes a self-relative security descriptor and returns a * newly created absolute security descriptor. \*---------------------------------------------------------------------------*/ DWORD MakeSDAbsolute ( 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 fPresent = FALSE; BOOL fSystemDefault = FALSE; DWORD dwReturnValue = ERROR_SUCCESS; // Get SACL if (!GetSecurityDescriptorSacl (psidOld, &fPresent, &pSacl, &fSystemDefault)) { dwReturnValue = GetLastError(); goto CLEANUP; } if (pSacl && fPresent) { cbSacl = pSacl->AclSize; } // Get DACL if (!GetSecurityDescriptorDacl (psidOld, &fPresent, &pDacl, &fSystemDefault)) { dwReturnValue = GetLastError(); goto CLEANUP; } if (pDacl && fPresent) { cbDacl = pDacl->AclSize; } // Get Owner if (!GetSecurityDescriptorOwner (psidOld, &psidOwner, &fSystemDefault)) { dwReturnValue = GetLastError(); goto CLEANUP; } cbOwnerSID = GetLengthSid (psidOwner); // Get Group if (!GetSecurityDescriptorGroup (psidOld, &psidGroup, &fSystemDefault)) { dwReturnValue = GetLastError(); goto CLEANUP; } 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) { dwReturnValue = ERROR_OUTOFMEMORY; goto CLEANUP; } ZeroMemory(pSid, cbDescriptor); if (!InitializeSecurityDescriptor (pSid, SECURITY_DESCRIPTOR_REVISION)) { dwReturnValue = GetLastError(); goto CLEANUP; } if (!MakeAbsoluteSD (psidOld, pSid, &cbDescriptor, pDacl, &cbDacl, pSacl, &cbSacl, psidOwner, &cbOwnerSID, psidGroup, &cbGroupSID)) { dwReturnValue = GetLastError(); goto CLEANUP; } CLEANUP: if(dwReturnValue != ERROR_SUCCESS && pSid) { free(pSid); pSid = NULL; } *psidNew = pSid; return dwReturnValue; }
/// Prelude actions to start up the service, e.g. to set any global variables from the settings or perform /// any system specific actions. E.g. the Windows implementation registers with the service control manager /// and can optionally set the security descriptor on the process to allow clients to kill/restart it. /// /// @param[in] nReason how the startup is occuring (e.g. SERVICE_RUN_INLINE) - different actions may be /// required depending on whether the code is running direct from main() or through another mechansim static void _ServiceStartup (int nReason) { CSettings oSettings; #ifdef _WIN32 if (nReason == SERVICE_RUN_SCM) { g_hServiceStatus = RegisterServiceCtrlHandler (oSettings.GetServiceName (), ServiceHandler); } PCTSTR pszSDDL = oSettings.GetServiceSDDL (); if (pszSDDL) { LOGDEBUG (TEXT ("Setting security descriptor ") << pszSDDL); PSECURITY_DESCRIPTOR psdRelative; if (ConvertStringSecurityDescriptorToSecurityDescriptor (pszSDDL, SDDL_REVISION_1, &psdRelative, NULL)) { DWORD cbAbsolute = 1024; PSECURITY_DESCRIPTOR psdAbsolute = (PSECURITY_DESCRIPTOR)malloc (cbAbsolute); DWORD cbD = 1024; PACL paclD = (PACL)malloc (cbD); DWORD cbS = 1024; PACL paclS = (PACL)malloc (cbS); DWORD cbOwner = 1024; PSID psidOwner = (PSID)malloc (cbOwner); DWORD cbPGroup = 1024; PSID psidPGroup = (PSID)malloc (cbPGroup); if (MakeAbsoluteSD (psdRelative, psdAbsolute, &cbAbsolute, paclD, &cbD, paclS, &cbS, psidOwner, &cbOwner, psidPGroup, &cbPGroup)) { DWORD dwError = SetSecurityInfo (GetCurrentProcess (), SE_KERNEL_OBJECT, DACL_SECURITY_INFORMATION, NULL, NULL, paclD, NULL); if (dwError == ERROR_SUCCESS) { LOGINFO (TEXT ("Security descriptor set on process handle")); } else { LOGWARN (TEXT ("Couldn't set security descriptor on process handle, error ") << GetLastError ()); } if (nReason == SERVICE_RUN_SCM) { SC_HANDLE hSCM = OpenSCManager (NULL, NULL, GENERIC_READ); if (hSCM) { SC_HANDLE hService = OpenService (hSCM, oSettings.GetServiceName (), GENERIC_WRITE | WRITE_DAC); if (hService) { dwError = SetSecurityInfo (hService, SE_SERVICE, DACL_SECURITY_INFORMATION, NULL, NULL, paclD, NULL); if (dwError == ERROR_SUCCESS) { LOGINFO (TEXT ("Security descriptor set on service")); } else { LOGWARN (TEXT ("Couldn't set security descriptor on service, error ") << GetLastError ()); } CloseServiceHandle (hService); } else { LOGWARN (TEXT ("Couldn't open service, error ") << GetLastError ()); } CloseServiceHandle (hSCM); } else { LOGWARN (TEXT ("Couldn't open SCM, error ") << GetLastError ()); } } } else { LOGWARN (TEXT ("Couldn't create absolute security description, error ") << GetLastError ()); } free (psdAbsolute); free (paclD); free (paclS); free (psidOwner); free (psidPGroup); LocalFree (psdRelative); } else { LOGWARN (TEXT ("Couldn't parse SDDL ") << pszSDDL << TEXT (", error ") << GetLastError ()); } } else { LOGDEBUG (TEXT ("No security descriptor specified")); } #else /* ifdef _WIN32 */ if (nReason == SERVICE_RUN_DAEMON) { const TCHAR *pszPID = oSettings.GetPidFile (); if (pszPID) { LOGINFO (TEXT ("Creating PID file ") << pszPID); FILE *f = fopen (pszPID, "wt"); if (f) { fprintf (f, "%d", getpid ()); fclose (f); } else { LOGWARN (TEXT ("Couldn't write to PID file ") << pszPID << TEXT (", error ") << GetLastError ()); } } else { LOGWARN (TEXT ("No PID file")); } } #endif /* ifdef _WIN32 */ g_lBusyTimeout = oSettings.GetBusyTimeout (); _ReportStateStarting (); }
DWORD MakeSDAbsolute ( PSECURITY_DESCRIPTOR OldSD, PSECURITY_DESCRIPTOR *NewSD ) { PSECURITY_DESCRIPTOR sd = NULL; DWORD descriptorSize; DWORD daclSize; DWORD saclSize; DWORD ownerSIDSize; DWORD groupSIDSize; PACL dacl; PACL sacl; PSID ownerSID; PSID groupSID; BOOL present; BOOL systemDefault; // // Get SACL // if (!GetSecurityDescriptorSacl (OldSD, &present, &sacl, &systemDefault)) return GetLastError(); if (sacl && present) { saclSize = sacl->AclSize; } else saclSize = 0; // // Get DACL // if (!GetSecurityDescriptorDacl (OldSD, &present, &dacl, &systemDefault)) return GetLastError(); if (dacl && present) { daclSize = dacl->AclSize; } else daclSize = 0; // // Get Owner // if (!GetSecurityDescriptorOwner (OldSD, &ownerSID, &systemDefault)) return GetLastError(); ownerSIDSize = GetLengthSid (ownerSID); // // Get Group // if (!GetSecurityDescriptorGroup (OldSD, &groupSID, &systemDefault)) return GetLastError(); groupSIDSize = GetLengthSid (groupSID); // // Do the conversion // descriptorSize = 0; MakeAbsoluteSD (OldSD, sd, &descriptorSize, dacl, &daclSize, sacl, &saclSize, ownerSID, &ownerSIDSize, groupSID, &groupSIDSize); sd = (PSECURITY_DESCRIPTOR) new BYTE [SECURITY_DESCRIPTOR_MIN_LENGTH]; if (!InitializeSecurityDescriptor (sd, SECURITY_DESCRIPTOR_REVISION)) return GetLastError(); if (!MakeAbsoluteSD (OldSD, sd, &descriptorSize, dacl, &daclSize, sacl, &saclSize, ownerSID, &ownerSIDSize, groupSID, &groupSIDSize)) return GetLastError(); *NewSD = sd; return ERROR_SUCCESS; }
HRESULT ConvertSecurityDescriptor( PSECURITY_DESCRIPTOR pSelfRelSD, PSECURITY_DESCRIPTOR *ppAbsoluteSD) { BOOL bResult; PACL pDacl = nullptr; PACL pSacl = nullptr; PSID pOwner = nullptr; PSID pPrimaryGroup = nullptr; DWORD dwAbsoluteSDSize = 0; DWORD dwDaclSize = 0; DWORD dwSaclSize = 0; DWORD dwOwnerSize = 0; DWORD dwPrimaryGroupSize = 0; size_t sizeNeeded = 0; *ppAbsoluteSD = nullptr; // Confirm that pSelfRelSD is actually self relative if( !ARGUMENT_PRESENT(pSelfRelSD) || !IS_FLAG_SET(((SECURITY_DESCRIPTOR*)(pSelfRelSD))->Control, SE_SELF_RELATIVE) ) { return E_INVALIDARG; } // Call it once so that the sizes will be set to the correct values. This // will return a buffer-too-small error, so we don't check the return value MakeAbsoluteSD( pSelfRelSD, nullptr, &dwAbsoluteSDSize, nullptr, &dwDaclSize, nullptr, &dwSaclSize, nullptr, &dwOwnerSize, nullptr, &dwPrimaryGroupSize ); sizeNeeded = dwAbsoluteSDSize + dwDaclSize + dwSaclSize + dwOwnerSize + dwPrimaryGroupSize; *ppAbsoluteSD = (PSECURITY_DESCRIPTOR)LocalAlloc(LMEM_FIXED, sizeNeeded); if ( !*ppAbsoluteSD ) { return E_OUTOFMEMORY; } BYTE* position = (BYTE *)(*ppAbsoluteSD); pDacl = reinterpret_cast<PACL>(position += dwAbsoluteSDSize); pSacl = reinterpret_cast<PACL>(position += dwDaclSize); pOwner = reinterpret_cast<PSID>(position += dwSaclSize); pPrimaryGroup = reinterpret_cast<PSID>(position += dwOwnerSize); bResult = MakeAbsoluteSD( pSelfRelSD, *ppAbsoluteSD, &dwAbsoluteSDSize, pDacl, &dwDaclSize, pSacl, &dwSaclSize, pOwner, &dwOwnerSize, pPrimaryGroup, &dwPrimaryGroupSize ); if ( !bResult ) { LocalFree(*ppAbsoluteSD); return HRESULT_FROM_WIN32(GetLastError()); } return S_OK; }