static rc_t CC _SD_Dacl_Ace_Creator_Set ( XFSNType NodeType, ACL * Dacl ) { SID * Sid = NULL; if ( Dacl == NULL ) { return XFS_RC ( rcNull ); } if ( NodeType != kxfsDir ) { return 0; } Sid = _SidStorageGet ( _sCreatorName ); if ( Sid == NULL ) { return XFS_RC ( rcInvalid ); } if ( AddAccessAllowedAceEx ( Dacl, ACL_REVISION, _sCreatorAceGrantFlagsDir, GENERIC_ALL, Sid ) == 0 ) { return XFS_RC ( rcInvalid ); } return 0; } /* _SD_Dacl_Ace_Creator_Set () */
static rc_t CC _SD_Dacl_Ace_Power_Set ( const char * AccName, XFSNType NodeType, ACL * Dacl ) { SID * Sid; DWORD Flags; Sid = NULL; Flags = 0; if ( AccName == NULL || Dacl == NULL ) { return XFS_RC ( rcNull ); } Sid = _SidStorageGet ( AccName ); if ( Sid == NULL ) { return XFS_RC ( rcInvalid ); } Flags = NodeType == kxfsDir ? _sAceFlagsDir : _sAceGrantFlags_File; if ( AddAccessAllowedAceEx ( Dacl, ACL_REVISION, Flags, SYNCHRONIZE | STANDARD_RIGHTS_REQUIRED | 0x1FF, Sid ) == 0 ) { return XFS_RC ( rcInvalid ); } return 0; } /* _SD_Dacl_Ace_Power_Set () */
bool CSecRunAsUser::SetObjectPermission(CString strDirFile, DWORD lGrantedAccess){ if (!m_hADVAPI32_DLL){ ASSERT ( false ); return false; } if ( strDirFile.IsEmpty() ) return true; SID_NAME_USE snuType; TCHAR* szDomain = NULL; LPVOID pUserSID = NULL; PACL pNewACL = NULL; PSECURITY_DESCRIPTOR pSD = NULL; BOOL fAPISuccess; try { // get user sid DWORD cbDomain = 0; DWORD cbUserSID = 0; fAPISuccess = LookupAccountName(NULL, EMULEACCOUNTW, pUserSID, &cbUserSID, szDomain, &cbDomain, &snuType); if ( (!fAPISuccess) && GetLastError() != ERROR_INSUFFICIENT_BUFFER) throw CString(_T("Run as unpriveleged user: Error: LookupAccountName() failed,")); pUserSID = MHeapAlloc(cbUserSID); if (!pUserSID) throw CString(_T("Run as unpriveleged user: Error: Allocating memory failed,")); szDomain = (TCHAR*)MHeapAlloc(cbDomain * sizeof(TCHAR)); if (!szDomain) throw CString(_T("Run as unpriveleged user: Error: Allocating memory failed,")); fAPISuccess = LookupAccountName(NULL, EMULEACCOUNTW, pUserSID, &cbUserSID, szDomain, &cbDomain, &snuType); if (!fAPISuccess) throw CString(_T("Run as unpriveleged user: Error: LookupAccountName()2 failed")); if (CStringW(szDomain) != m_strDomain) throw CString(_T("Run as unpriveleged user: Logical Error: Domainname mismatch")); // get old ACL PACL pOldACL = NULL; fAPISuccess = GetNamedSecurityInfo(strDirFile.GetBuffer(), SE_FILE_OBJECT, DACL_SECURITY_INFORMATION, NULL, NULL, &pOldACL, NULL, &pSD); strDirFile.ReleaseBuffer(); if (fAPISuccess != ERROR_SUCCESS){ throw CString(_T("Run as unpriveleged user: Error: GetNamedSecurityInfo() failed")); } // calculate size for new ACL ACL_SIZE_INFORMATION AclInfo; AclInfo.AceCount = 0; // Assume NULL DACL. AclInfo.AclBytesFree = 0; AclInfo.AclBytesInUse = sizeof(ACL); if (pOldACL != NULL && !GetAclInformation(pOldACL, &AclInfo, sizeof(ACL_SIZE_INFORMATION), AclSizeInformation)) throw CString(_T("Run as unpriveleged user: Error: GetAclInformation() failed")); // Create new ACL DWORD cbNewACL = AclInfo.AclBytesInUse + sizeof(ACCESS_ALLOWED_ACE) + GetLengthSid(pUserSID) - sizeof(DWORD); pNewACL = (PACL)MHeapAlloc(cbNewACL); if (!pNewACL) throw CString(_T("Run as unpriveleged user: Error: Allocating memory failed,")); if (!InitializeAcl(pNewACL, cbNewACL, ACL_REVISION2)) throw CString(_T("Run as unpriveleged user: Error: Allocating memory failed,")); // copy the entries form the old acl into the new one and enter a new ace in the right order uint32 newAceIndex = 0; uint32 CurrentAceIndex = 0; if (AclInfo.AceCount) { for (CurrentAceIndex = 0; CurrentAceIndex < AclInfo.AceCount; CurrentAceIndex++) { LPVOID pTempAce = NULL; if (!GetAce(pOldACL, CurrentAceIndex, &pTempAce)) throw CString(_T("Run as unpriveleged user: Error: GetAce() failed,")); if (((ACCESS_ALLOWED_ACE *)pTempAce)->Header.AceFlags & INHERITED_ACE) break; // no multiple entries if (EqualSid(pUserSID, &(((ACCESS_ALLOWED_ACE *)pTempAce)->SidStart))) continue; if (!AddAce(pNewACL, ACL_REVISION, MAXDWORD, pTempAce, ((PACE_HEADER) pTempAce)->AceSize)) throw CString(_T("Run as unpriveleged user: Error: AddAce()1 failed,")); newAceIndex++; } } // here we add the actually entry if (!AddAccessAllowedAceEx(pNewACL, ACL_REVISION2, CONTAINER_INHERIT_ACE | OBJECT_INHERIT_ACE, lGrantedAccess, pUserSID)) throw CString(_T("Run as unpriveleged user: Error: AddAccessAllowedAceEx() failed,")); // copy the rest if (AclInfo.AceCount) { for (; CurrentAceIndex < AclInfo.AceCount; CurrentAceIndex++) { LPVOID pTempAce = NULL; if (!GetAce(pOldACL, CurrentAceIndex, &pTempAce)) throw CString(_T("Run as unpriveleged user: Error: GetAce()2 failed,")); if (!AddAce(pNewACL, ACL_REVISION, MAXDWORD, pTempAce, ((PACE_HEADER) pTempAce)->AceSize)) throw CString(_T("Run as unpriveleged user: Error: AddAce()2 failed,")); } } fAPISuccess = SetNamedSecurityInfo(strDirFile.GetBuffer(), SE_FILE_OBJECT, DACL_SECURITY_INFORMATION, NULL, NULL, pNewACL, NULL); strDirFile.ReleaseBuffer(); if (fAPISuccess != ERROR_SUCCESS) throw CString(_T("Run as unpriveleged user: Error: SetNamedSecurityInfo() failed,")); fAPISuccess = TRUE; } catch(CString error){ fAPISuccess = FALSE; theApp.QueueDebugLogLine(false, error); } // clean up if (pUserSID != NULL) MHeapFree(pUserSID); if (szDomain != NULL) MHeapFree(szDomain); if (pNewACL != NULL) MHeapFree(pNewACL); if (pSD != NULL) LocalFree(pSD); // finished return fAPISuccess!=FALSE; }
/* * AddUserToTokenDacl(HANDLE hToken) * * This function adds the current user account to the restricted * token used when we create a restricted process. * * This is required because of some security changes in Windows * that appeared in patches to XP/2K3 and in Vista/2008. * * On these machines, the Administrator account is not included in * the default DACL - you just get Administrators + System. For * regular users you get User + System. Because we strip Administrators * when we create the restricted token, we are left with only System * in the DACL which leads to access denied errors for later CreatePipe() * and CreateProcess() calls when running as Administrator. * * This function fixes this problem by modifying the DACL of the * token the process will use, and explicitly re-adding the current * user account. This is still secure because the Administrator account * inherits its privileges from the Administrators group - it doesn't * have any of its own. */ BOOL AddUserToTokenDacl(HANDLE hToken) { int i; ACL_SIZE_INFORMATION asi; ACCESS_ALLOWED_ACE *pace; DWORD dwNewAclSize; DWORD dwSize = 0; DWORD dwTokenInfoLength = 0; PACL pacl = NULL; PTOKEN_USER pTokenUser = NULL; TOKEN_DEFAULT_DACL tddNew; TOKEN_DEFAULT_DACL *ptdd = NULL; TOKEN_INFORMATION_CLASS tic = TokenDefaultDacl; BOOL ret = FALSE; /* Figure out the buffer size for the DACL info */ if (!GetTokenInformation(hToken, tic, (LPVOID) NULL, dwTokenInfoLength, &dwSize)) { if (GetLastError() == ERROR_INSUFFICIENT_BUFFER) { ptdd = (TOKEN_DEFAULT_DACL *) LocalAlloc(LPTR, dwSize); if (ptdd == NULL) { log_error("could not allocate %lu bytes of memory", dwSize); goto cleanup; } if (!GetTokenInformation(hToken, tic, (LPVOID) ptdd, dwSize, &dwSize)) { log_error("could not get token information: error code %lu", GetLastError()); goto cleanup; } } else { log_error("could not get token information buffer size: error code %lu", GetLastError()); goto cleanup; } } /* Get the ACL info */ if (!GetAclInformation(ptdd->DefaultDacl, (LPVOID) &asi, (DWORD) sizeof(ACL_SIZE_INFORMATION), AclSizeInformation)) { log_error("could not get ACL information: error code %lu", GetLastError()); goto cleanup; } /* Get the current user SID */ if (!GetTokenUser(hToken, &pTokenUser)) goto cleanup; /* callee printed a message */ /* Figure out the size of the new ACL */ dwNewAclSize = asi.AclBytesInUse + sizeof(ACCESS_ALLOWED_ACE) + GetLengthSid(pTokenUser->User.Sid) -sizeof(DWORD); /* Allocate the ACL buffer & initialize it */ pacl = (PACL) LocalAlloc(LPTR, dwNewAclSize); if (pacl == NULL) { log_error("could not allocate %lu bytes of memory", dwNewAclSize); goto cleanup; } if (!InitializeAcl(pacl, dwNewAclSize, ACL_REVISION)) { log_error("could not initialize ACL: error code %lu", GetLastError()); goto cleanup; } /* Loop through the existing ACEs, and build the new ACL */ for (i = 0; i < (int) asi.AceCount; i++) { if (!GetAce(ptdd->DefaultDacl, i, (LPVOID *) &pace)) { log_error("could not get ACE: error code %lu", GetLastError()); goto cleanup; } if (!AddAce(pacl, ACL_REVISION, MAXDWORD, pace, ((PACE_HEADER) pace)->AceSize)) { log_error("could not add ACE: error code %lu", GetLastError()); goto cleanup; } } /* Add the new ACE for the current user */ if (!AddAccessAllowedAceEx(pacl, ACL_REVISION, OBJECT_INHERIT_ACE, GENERIC_ALL, pTokenUser->User.Sid)) { log_error("could not add access allowed ACE: error code %lu", GetLastError()); goto cleanup; } /* Set the new DACL in the token */ tddNew.DefaultDacl = pacl; if (!SetTokenInformation(hToken, tic, (LPVOID) &tddNew, dwNewAclSize)) { log_error("could not set token information: error code %lu", GetLastError()); goto cleanup; } ret = TRUE; cleanup: if (pTokenUser) LocalFree((HLOCAL) pTokenUser); if (pacl) LocalFree((HLOCAL) pacl); if (ptdd) LocalFree((HLOCAL) ptdd); return ret; }