DWORD AddNodeManagerAndUserACEsToObject()

in hadoop-common-project/hadoop-common/src/main/winutils/task.c [302:528]


DWORD AddNodeManagerAndUserACEsToObject(
  __in HANDLE hObject,
  __in LPCWSTR user,
  __in ACCESS_MASK accessMask) {

  DWORD dwError = ERROR_SUCCESS;
  size_t      countTokens = 0;
  size_t      len = 0;
  LPCWSTR     value = NULL;
  WCHAR**     tokens = NULL;
  DWORD       crt = 0;
  PACL        pDacl = NULL;
  PSECURITY_DESCRIPTOR  psdProcess = NULL;
  LPWSTR      lpszOldDacl = NULL, lpszNewDacl = NULL;
  ULONG       daclLen = 0;
  PACL        pNewDacl = NULL;
  ACL_SIZE_INFORMATION si;
  DWORD       dwNewAclSize = 0;
  PACE_HEADER pTempAce = NULL;
  BYTE        sidTemp[SECURITY_MAX_SID_SIZE];
  DWORD       cbSid = SECURITY_MAX_SID_SIZE;
  PSID        tokenSid = NULL;
  // These hard-coded SIDs are allways added
  WELL_KNOWN_SID_TYPE forcesSidTypes[] = {
    WinLocalSystemSid,
    WinBuiltinAdministratorsSid};
  BOOL        logSDs = IsDebuggerPresent(); // Check only once to avoid attach-while-running
 
  
  dwError = GetSecurityInfo(hObject,
      SE_KERNEL_OBJECT,
      DACL_SECURITY_INFORMATION,
      NULL,
      NULL,
      &pDacl,
      NULL,
      &psdProcess);
  if (dwError) {
    ReportErrorCode(L"GetSecurityInfo", dwError);
    goto done;
  }

  // This is debug only output for troubleshooting
  if (logSDs) {
    if (!ConvertSecurityDescriptorToStringSecurityDescriptor(
        psdProcess,
        SDDL_REVISION_1,
        DACL_SECURITY_INFORMATION,
        &lpszOldDacl,
        &daclLen)) {
      dwError = GetLastError();
      ReportErrorCode(L"ConvertSecurityDescriptorToStringSecurityDescriptor", dwError);
      goto done;
    }
  }

  ZeroMemory(&si, sizeof(si));
  if (!GetAclInformation(pDacl, &si, sizeof(si), AclSizeInformation)) {
    dwError = GetLastError();
    ReportErrorCode(L"GetAclInformation", dwError);
    goto done;  
  }

  dwError = GetConfigValue(wsceConfigRelativePath, NM_WSCE_ALLOWED, &len, &value);
  if (ERROR_SUCCESS != dwError) {
    ReportErrorCode(L"GetConfigValue", dwError);
    goto done;
  }

  if (0 == len) {
    dwError = ERROR_BAD_CONFIGURATION;
    ReportErrorCode(L"GetConfigValue", dwError);
    goto done;
  }

  dwError = SplitStringIgnoreSpaceW(len, value, L',', &countTokens, &tokens);
  if (ERROR_SUCCESS != dwError) {
    ReportErrorCode(L"SplitStringIgnoreSpaceW", dwError);
    goto done;
  }

  // We're gonna add 1 ACE for each token found, +1 for user and +1 for each forcesSidTypes[]
  // ACCESS_ALLOWED_ACE struct contains the first DWORD of the SID 
  //
  dwNewAclSize = si.AclBytesInUse + 
      (DWORD)(countTokens + 1 + sizeof(forcesSidTypes)/sizeof(forcesSidTypes[0])) * 
              (sizeof(ACCESS_ALLOWED_ACE) + SECURITY_MAX_SID_SIZE - sizeof(DWORD));

  pNewDacl = (PSID) LocalAlloc(LPTR, dwNewAclSize);
  if (!pNewDacl) {
    dwError = ERROR_OUTOFMEMORY;
    ReportErrorCode(L"LocalAlloc", dwError);
    goto done;
  }

  if (!InitializeAcl(pNewDacl, dwNewAclSize, ACL_REVISION)) {
    dwError = ERROR_OUTOFMEMORY;
    ReportErrorCode(L"InitializeAcl", dwError);
    goto done;
  }

  // Copy over old ACEs
  for (crt = 0; crt < si.AceCount; ++crt) {
    if (!GetAce(pDacl, crt, &pTempAce)) {
      dwError = ERROR_OUTOFMEMORY;
      ReportErrorCode(L"InitializeAcl", dwError);
      goto done;
    }
    if (!AddAce(pNewDacl, ACL_REVISION, MAXDWORD, pTempAce, pTempAce->AceSize)) {
      dwError = ERROR_OUTOFMEMORY;
      ReportErrorCode(L"InitializeAcl", dwError);
      goto done;
    }
  }

  // Add the configured allowed SIDs
  for (crt = 0; crt < countTokens; ++crt) {
    dwError = GetSidFromAcctNameW(tokens[crt], &tokenSid);
    if (ERROR_SUCCESS != dwError) {
      ReportErrorCode(L"GetSidFromAcctNameW", dwError);
      goto done;
    }
    if (!AddAccessAllowedAceEx(
                pNewDacl,
                ACL_REVISION_DS,
                CONTAINER_INHERIT_ACE | OBJECT_INHERIT_ACE,
                PROCESS_ALL_ACCESS,
                tokenSid)) {
      dwError = GetLastError();
      ReportErrorCode(L"AddAccessAllowedAceEx:1", dwError);
      goto done;
    }
    LocalFree(tokenSid);
    tokenSid = NULL;
  }

  // add the forced SIDs ACE 
  for (crt = 0; crt < sizeof(forcesSidTypes)/sizeof(forcesSidTypes[0]); ++crt) {
    cbSid = SECURITY_MAX_SID_SIZE;
    if (!CreateWellKnownSid(forcesSidTypes[crt], NULL, &sidTemp, &cbSid)) {
      dwError = GetLastError();
      ReportErrorCode(L"CreateWellKnownSid", dwError);
      goto done;
    }
    if (!AddAccessAllowedAceEx(
              pNewDacl,
              ACL_REVISION_DS,
              CONTAINER_INHERIT_ACE | OBJECT_INHERIT_ACE,
              accessMask,
              (PSID) sidTemp)) {
      dwError = GetLastError();
      ReportErrorCode(L"AddAccessAllowedAceEx:2", dwError);
      goto done;
    }
  }
  
  // add the user ACE
  dwError = GetSidFromAcctNameW(user, &tokenSid);
  if (ERROR_SUCCESS != dwError) {
    ReportErrorCode(L"GetSidFromAcctNameW:user", dwError);
    goto done;
  }    

  if (!AddAccessAllowedAceEx(
              pNewDacl,
              ACL_REVISION_DS,
              CONTAINER_INHERIT_ACE | OBJECT_INHERIT_ACE,
              PROCESS_ALL_ACCESS,
              tokenSid)) {
    dwError = GetLastError();
    ReportErrorCode(L"AddAccessAllowedAceEx:3", dwError);
    goto done;
  }

  LocalFree(tokenSid);
  tokenSid = NULL;

  dwError = SetSecurityInfo(hObject,
    SE_KERNEL_OBJECT,
    DACL_SECURITY_INFORMATION,
    NULL,
    NULL,
    pNewDacl,
    NULL);
  if (dwError) {
    ReportErrorCode(L"SetSecurityInfo", dwError);
    goto done;
  }

  // This is debug only output for troubleshooting
  if (logSDs) {
    dwError = GetSecurityInfo(hObject,
        SE_KERNEL_OBJECT,
        DACL_SECURITY_INFORMATION,
        NULL,
        NULL,
        &pDacl,
        NULL,
        &psdProcess);
    if (dwError) {
      ReportErrorCode(L"GetSecurityInfo:2", dwError);
      goto done;
    }

    if (!ConvertSecurityDescriptorToStringSecurityDescriptor(
        psdProcess,
        SDDL_REVISION_1,
        DACL_SECURITY_INFORMATION,
        &lpszNewDacl,
        &daclLen)) {
      dwError = GetLastError();
      ReportErrorCode(L"ConvertSecurityDescriptorToStringSecurityDescriptor:2", dwError);
      goto done;
    }

    LogDebugMessage(L"Old DACL: %ls\nNew DACL: %ls\n", lpszOldDacl, lpszNewDacl);
  }
  
done:
  if (tokenSid) LocalFree(tokenSid);
  if (pNewDacl) LocalFree(pNewDacl);
  if (lpszOldDacl) LocalFree(lpszOldDacl);
  if (lpszNewDacl) LocalFree(lpszNewDacl);
  if (psdProcess) LocalFree(psdProcess);

  return dwError;
}