/* * FreeSD: Frees the memory of an absolute SD. */ void vncAccessControl::FreeSD(PSECURITY_DESCRIPTOR pSD){ PSID pOwnerSID = NULL; PSID pGroupSID = NULL; PACL pDACL = NULL; PACL pSACL = NULL; BOOL bOwnerDefaulted = FALSE; BOOL bGroupDefaulted = FALSE; BOOL bDaclPresent = FALSE; BOOL bDaclDefaulted = FALSE; BOOL bSaclPresent = FALSE; BOOL bSaclDefaulted = FALSE; if (pSD) { GetSecurityDescriptorOwner(pSD, &pOwnerSID, &bOwnerDefaulted); GetSecurityDescriptorGroup(pSD, &pGroupSID, &bGroupDefaulted); GetSecurityDescriptorDacl(pSD, &bDaclPresent, &pDACL, &bDaclDefaulted); GetSecurityDescriptorSacl(pSD, &bSaclPresent, &pSACL, &bSaclDefaulted); } // Clean up if (pSD) HeapFree(GetProcessHeap(), 0, pSD); if (bDaclPresent && pDACL) HeapFree(GetProcessHeap(), 0, pDACL); if (bSaclPresent && pSACL) HeapFree(GetProcessHeap(), 0, pSACL); if (pOwnerSID) HeapFree(GetProcessHeap(), 0, pOwnerSID); if (pGroupSID) HeapFree(GetProcessHeap(), 0, pGroupSID); }
/* --- PRIVATE FUNCTIONS ---------------------------------------------------- */ static void CallbackSdOwner( _In_ HANDLE hOutfile, _Inout_ PLDAP_RETRIEVED_DATA pLdapRetreivedData ) { BOOL bResult = FALSE; BOOL bDaclPresent = FALSE; BOOL bDaclDefaulted = FALSE; PACL pDacl = { 0 }; PSECURITY_DESCRIPTOR pSd = (PSECURITY_DESCRIPTOR)pLdapRetreivedData->ppbData[0]; if (!IsValidSecurityDescriptor(pSd)) { LOG(Err, _T("Invalid security descriptor")); return; } bResult = ControlWriteOwnerOutline(hOutfile, pSd, pLdapRetreivedData->tDN, CONTROL_AD_OWNER_KEYWORD); if (!bResult) { LOG(Err, _T("Cannot write owner control relation for <%s>"), pLdapRetreivedData->tDN); } bResult = GetSecurityDescriptorDacl(pSd, &bDaclPresent, &pDacl, &bDaclDefaulted); if (bResult == FALSE) { LOG(Err, _T("Failed to get DACL <%u>"), GetLastError()); return; } if (bDaclPresent == FALSE || pDacl == NULL) { LOG(Info, "Null or no DACL for element <%s>", pLdapRetreivedData->tDN); bResult = ControlWriteOutline(hOutfile, gs_ptSidEveryone, pLdapRetreivedData->tDN, CONTROL_AD_NULL_DACL_KEYWORD); if (bResult == FALSE) { LOG(Err, _T("Cannot write null-dacl control relation for <%s>"), pLdapRetreivedData->tDN); return; } } }
void DumpSD(PSECURITY_DESCRIPTOR pSD) { DWORD dwSize = GetSecurityDescriptorLength(pSD); printf("\nSecurity Descriptor is of size %d", dwSize); BOOL DaclPresent, DaclDefaulted; PACL pDacl; if(GetSecurityDescriptorDacl(pSD, &DaclPresent, &pDacl, &DaclDefaulted) && DaclPresent) { // Dump the aces ACL_SIZE_INFORMATION inf; DWORD dwNumAces; if(GetAclInformation( pDacl, &inf, sizeof(ACL_SIZE_INFORMATION), AclSizeInformation )) { dwNumAces = inf.AceCount; printf("\nThe DACL has %d ACEs", dwNumAces); for(DWORD dwCnt = 0; dwCnt < dwNumAces; dwCnt++) { ACCESS_ALLOWED_ACE * pAce; if(GetAce(pDacl, dwCnt, (LPVOID *)&pAce)) DumpAce(pAce); } } } }
HANDLE GetAnonymousToken() { ImpersonateAnonymousToken(GetCurrentThread()); HANDLE hToken; OpenThreadToken(GetCurrentThread(), TOKEN_ALL_ACCESS, TRUE, &hToken); RevertToSelf(); PSECURITY_DESCRIPTOR pSD; ULONG sd_length; if (!ConvertStringSecurityDescriptorToSecurityDescriptor(L"D:(A;;GA;;;WD)(A;;GA;;;AN)", SDDL_REVISION_1, &pSD, &sd_length)) { printf("Error converting SDDL: %d\n", GetLastError()); exit(1); } TOKEN_DEFAULT_DACL dacl; BOOL bPresent; BOOL bDefaulted; PACL pDACL; GetSecurityDescriptorDacl(pSD, &bPresent, &pDACL, &bDefaulted); dacl.DefaultDacl = pDACL; if (!SetTokenInformation(hToken, TokenDefaultDacl, &dacl, sizeof(dacl))) { printf("Error setting default DACL: %d\n", GetLastError()); exit(1); } return hToken; }
DWORD GetObjectSecurityDescriptorDacl( IN HANDLE object, OUT SECURITY_DESCRIPTOR **sd, OUT BOOL *daclPresent, OUT ACL **dacl ) { DWORD status; SECURITY_INFORMATION si; DWORD sizeNeeded; BOOL daclDefaulted; if (!sd || !daclPresent || !dacl) return ERROR_INVALID_PARAMETER; si = DACL_SECURITY_INFORMATION; if (!GetUserObjectSecurity( object, &si, NULL, 0, &sizeNeeded)) { status = GetLastError(); if (ERROR_INSUFFICIENT_BUFFER != status) { return perror("GetUserObjectSecurity"); } } *sd = LocalAlloc(LPTR, sizeNeeded); if (*sd == NULL) { return perror("LocalAlloc"); } if (!GetUserObjectSecurity( object, &si, *sd, sizeNeeded, &sizeNeeded)) { return perror("GetUserObjectSecurity"); } if (!GetSecurityDescriptorDacl(*sd, daclPresent, dacl, &daclDefaulted)) { status = GetLastError(); LocalFree(*sd); return perror2(status, "GetSecurityDescriptorDacl"); } return ERROR_SUCCESS; }
/* * SetSD: Changes the class variable pACL and the reg key. * The ACL is the DACL of the provided SD. */ BOOL vncAccessControl::SetSD(PSECURITY_DESCRIPTOR pSD){ BOOL isOK = FALSE; BOOL bDaclPresent = FALSE; BOOL bDaclDefaulted = FALSE; PACL pDACL = NULL; GetSecurityDescriptorDacl(pSD, &bDaclPresent, &pDACL, &bDaclDefaulted); if (bDaclPresent && pDACL && IsValidAcl(pDACL) && StoreACL(pDACL)) isOK = TRUE; return isOK; }
/* * Returns pointer discretionary access-control list (ACL) from the security * descriptor of the specified file. */ static ACL* getFileDACL(JNIEnv* env, SECURITY_DESCRIPTOR* sd) { ACL *acl; int defaulted, present; if (!GetSecurityDescriptorDacl(sd, &present, &acl, &defaulted)) { JNU_ThrowIOExceptionWithLastError(env, "GetSecurityDescriptorDacl failed"); return NULL; } if (!present) { JNU_ThrowInternalError(env, "Security descriptor does not contain a DACL"); return NULL; } return acl; }
BOOL ValidateSecurity(uch *securitydata) { PSECURITY_DESCRIPTOR sd = (PSECURITY_DESCRIPTOR)securitydata; PACL pAcl; PSID pSid; BOOL bAclPresent; BOOL bDefaulted; if(!IsWinNT()) return TRUE; /* don't do anything if not on WinNT */ if(!IsValidSecurityDescriptor(sd)) return FALSE; /* verify Dacl integrity */ if(!GetSecurityDescriptorDacl(sd, &bAclPresent, &pAcl, &bDefaulted)) return FALSE; if(bAclPresent && pAcl!=NULL) { if(!IsValidAcl(pAcl)) return FALSE; } /* verify Sacl integrity */ if(!GetSecurityDescriptorSacl(sd, &bAclPresent, &pAcl, &bDefaulted)) return FALSE; if(bAclPresent && pAcl!=NULL) { if(!IsValidAcl(pAcl)) return FALSE; } /* verify owner integrity */ if(!GetSecurityDescriptorOwner(sd, &pSid, &bDefaulted)) return FALSE; if(pSid != NULL) { if(!IsValidSid(pSid)) return FALSE; } /* verify group integrity */ if(!GetSecurityDescriptorGroup(sd, &pSid, &bDefaulted)) return FALSE; if(pSid != NULL) { if(!IsValidSid(pSid)) return FALSE; } return TRUE; }
DWORD ListNamedValueSD ( HKEY RootKey, LPTSTR KeyName, LPTSTR ValueName ) { DWORD returnValue; SECURITY_DESCRIPTOR *sd; BOOL present; BOOL defaultDACL; PACL dacl; BOOL newSD = FALSE; returnValue = GetNamedValueSD (RootKey, KeyName, ValueName, &sd, &newSD); if ((returnValue != ERROR_SUCCESS) || (newSD == TRUE)) { _tprintf (TEXT("<Using Default Permissions>\n")); free (sd); return returnValue; } if (!GetSecurityDescriptorDacl (sd, &present, &dacl, &defaultDACL)) { free (sd); return GetLastError(); } if (!present) { _tprintf (TEXT("<Access is denied to everyone>\n")); free (sd); return ERROR_SUCCESS; } ListACL (dacl); free (sd); return ERROR_SUCCESS; }
/*---------------------------------------------------------------------------*\ * NAME: ListNamedValueSD * --------------------------------------------------------------------------* * DESCRIPTION: Displays the designated security descriptor. \*---------------------------------------------------------------------------*/ DWORD ListNamedValueSD ( HKEY hkeyRoot, LPTSTR tszKeyName, LPTSTR tszValueName, DWORD dwSDType ) { DWORD dwReturnValue = ERROR_SUCCESS; SECURITY_DESCRIPTOR *pSD = NULL; BOOL fPresent = FALSE; BOOL fDefaultDACL = FALSE; PACL dacl = NULL; dwReturnValue = GetNamedValueSD (hkeyRoot, tszKeyName, tszValueName, &pSD, NULL); if (dwReturnValue != ERROR_SUCCESS) { _tprintf (_T("<Using Default Permissions>\n")); goto CLEANUP; } if (!GetSecurityDescriptorDacl (pSD, &fPresent, &dacl, &fDefaultDACL)) { dwReturnValue = GetLastError(); goto CLEANUP; } if (!fPresent) { _tprintf (_T("<Access is denied to everyone>\n")); goto CLEANUP; } ListACL (dacl, dwSDType); CLEANUP: if(pSD) free (pSD); return dwReturnValue; }
/* (in) PSECURITY_DESCRIPTOR file or directory handle (in/out) struct acl * acl */ int get_file_acl(PSECURITY_DESCRIPTOR pSD,struct acl * acl) { DWORD dwLastError; PACL pDacl; PSID pOwnerSid,pGroupSid; SID_NAME_USE eUse; BOOL bPresent; BOOL bDef; int i; if (0 == GetSecurityDescriptorOwner(pSD, &pOwnerSid, &bDef)){ return (-1); } if (0 == GetSecurityDescriptorGroup(pSD, &pGroupSid, &bDef)){ return(-1); } if (0 == GetSecurityDescriptorDacl(pSD,&bPresent,&pDacl,&bDef)){ return(-1); } if (get_account_sid(pOwnerSid,acl->owner,MAX_LEN,&eUse) == -1){ return (-1); } if (get_account_sid(pGroupSid,acl->group,MAX_LEN,&eUse) == -1){ return (-1); } if (pDacl != NULL) get_ace(pDacl,acl,&eUse); return (0); }
/** * This function adjusts the specified WindowStation to include the specfied * user. * * See: http://msdn2.microsoft.com/en-us/library/aa379608(VS.85).aspx **/ BOOL AddAceToWindowStation(HWINSTA hwinsta, PSID psid) { ACCESS_ALLOWED_ACE *pace = NULL; ACL_SIZE_INFORMATION aclSizeInfo; BOOL bDaclExist; BOOL bDaclPresent; BOOL bSuccess = FALSE; DWORD dwNewAclSize; DWORD dwSidSize = 0; DWORD dwSdSizeNeeded; PACL pacl = NULL; PACL pNewAcl = NULL; PSECURITY_DESCRIPTOR psd = NULL; PSECURITY_DESCRIPTOR psdNew = NULL; PVOID pTempAce; SECURITY_INFORMATION si = DACL_SECURITY_INFORMATION; unsigned int i; try { // Obtain the DACL for the window station. if (!GetUserObjectSecurity( hwinsta, &si, psd, dwSidSize, &dwSdSizeNeeded) ) if (GetLastError() == ERROR_INSUFFICIENT_BUFFER) { psd = (PSECURITY_DESCRIPTOR)HeapAlloc( GetProcessHeap(), HEAP_ZERO_MEMORY, dwSdSizeNeeded); if (psd == NULL) throw; psdNew = (PSECURITY_DESCRIPTOR)HeapAlloc( GetProcessHeap(), HEAP_ZERO_MEMORY, dwSdSizeNeeded); if (psdNew == NULL) throw; dwSidSize = dwSdSizeNeeded; if (!GetUserObjectSecurity( hwinsta, &si, psd, dwSidSize, &dwSdSizeNeeded) ) throw; } else throw; // Create a new DACL. if (!InitializeSecurityDescriptor( psdNew, SECURITY_DESCRIPTOR_REVISION) ) throw; // Get the DACL from the security descriptor. if (!GetSecurityDescriptorDacl( psd, &bDaclPresent, &pacl, &bDaclExist) ) throw; // Initialize the ACL. ZeroMemory(&aclSizeInfo, sizeof(ACL_SIZE_INFORMATION)); aclSizeInfo.AclBytesInUse = sizeof(ACL); // Call only if the DACL is not NULL. if (pacl != NULL) { // get the file ACL size info if (!GetAclInformation( pacl, (LPVOID)&aclSizeInfo, sizeof(ACL_SIZE_INFORMATION), AclSizeInformation) ) throw; } // Compute the size of the new ACL. dwNewAclSize = aclSizeInfo.AclBytesInUse + (2*sizeof(ACCESS_ALLOWED_ACE)) + (2*GetLengthSid(psid)) - (2*sizeof(DWORD)); // Allocate memory for the new ACL. pNewAcl = (PACL)HeapAlloc( GetProcessHeap(), HEAP_ZERO_MEMORY, dwNewAclSize); if (pNewAcl == NULL) throw; // Initialize the new DACL. if (!InitializeAcl(pNewAcl, dwNewAclSize, ACL_REVISION)) throw; // If DACL is present, copy it to a new DACL. if (bDaclPresent) { // Copy the ACEs to the new ACL. if (aclSizeInfo.AceCount) { for (i=0; i < aclSizeInfo.AceCount; i++) { // Get an ACE. if (!GetAce(pacl, i, &pTempAce)) throw; // Add the ACE to the new ACL. if (!AddAce( pNewAcl, ACL_REVISION, MAXDWORD, pTempAce, ((PACE_HEADER)pTempAce)->AceSize) ) throw; } } } // Add the first ACE to the window station. pace = (ACCESS_ALLOWED_ACE *)HeapAlloc( GetProcessHeap(), HEAP_ZERO_MEMORY, sizeof(ACCESS_ALLOWED_ACE) + GetLengthSid(psid) - sizeof(DWORD) ); if (pace == NULL) throw; pace->Header.AceType = ACCESS_ALLOWED_ACE_TYPE; pace->Header.AceFlags = CONTAINER_INHERIT_ACE | INHERIT_ONLY_ACE | OBJECT_INHERIT_ACE; pace->Header.AceSize = (WORD)sizeof(ACCESS_ALLOWED_ACE) + (WORD)GetLengthSid(psid) - (WORD)sizeof(DWORD); pace->Mask = GENERIC_ALL; if (!CopySid(GetLengthSid(psid), &pace->SidStart, psid)) throw; if (!AddAce( pNewAcl, ACL_REVISION, MAXDWORD, (LPVOID)pace, pace->Header.AceSize) ) throw; // Add an ACE to the window station. pace->Header.AceFlags = NO_PROPAGATE_INHERIT_ACE; pace->Mask = GENERIC_ALL; if (!AddAce( pNewAcl, ACL_REVISION, MAXDWORD, (LPVOID)pace, pace->Header.AceSize) ) throw; // Set a new DACL for the security descriptor. if (!SetSecurityDescriptorDacl( psdNew, TRUE, pNewAcl, FALSE) ) throw; // Set the new security descriptor for the window station. if (!SetUserObjectSecurity(hwinsta, &si, psdNew)) throw; // Indicate success. bSuccess = TRUE; } catch(...) { // Free the allocated buffers. if (pace != NULL) HeapFree(GetProcessHeap(), 0, (LPVOID)pace); if (pNewAcl != NULL) HeapFree(GetProcessHeap(), 0, (LPVOID)pNewAcl); if (psd != NULL) HeapFree(GetProcessHeap(), 0, (LPVOID)psd); if (psdNew != NULL) HeapFree(GetProcessHeap(), 0, (LPVOID)psdNew); } return bSuccess; }
BOOL Process::AddAceToProc(DWORD mask,PSID psid){//Здесь происходит очень сильная магия. И я не разобрался до конца почему тут косяки //Смысл в том, что нельзя просто так добавить ACE в DACL. //Придется создать DACL бОльшего размера чем предыдущий, и скопировать все в новый из старого. //Потом вручную насоздавть структур и сохранить их. //Проблема в том, что почему-то не сохраняется нужный RID. ВЫдается ошибка, что сессия уже используется. printf("Adding ace\n"); BOOL bSuccess = FALSE; ACCESS_ALLOWED_ACE *pAce = NULL; ACL_SIZE_INFORMATION aclSizeInfo; PACL pacl; PACL pNewAcl = NULL; PSECURITY_DESCRIPTOR psd = NULL; PSECURITY_DESCRIPTOR psdNew = NULL; PVOID pTemAce; SECURITY_INFORMATION si = DACL_SECURITY_INFORMATION; DWORD dwSidSize = 0; DWORD dwSidSizeNeeded; DWORD dwNewAclSize; BOOL bDaclPresent; BOOL bDaclExist; __try{ if (!GetUserObjectSecurity( _handle, &si, psd, dwSidSize, &dwSidSizeNeeded) ) if (GetLastError() == ERROR_INSUFFICIENT_BUFFER){ psd = (PSECURITY_DESCRIPTOR)HeapAlloc( GetProcessHeap(), HEAP_ZERO_MEMORY, dwSidSizeNeeded); if (psd == NULL){ printf("psd: %d\n",GetLastError()); __leave; } psdNew = (PSECURITY_DESCRIPTOR)HeapAlloc( GetProcessHeap(), HEAP_ZERO_MEMORY, dwSidSizeNeeded); if (psdNew == NULL){ printf("psdNew : %d\n",GetLastError()); __leave; } dwSidSize = dwSidSizeNeeded; if (!GetUserObjectSecurity( _handle, &si, psd, dwSidSize, &dwSidSizeNeeded) ){ printf("GetUserObjectSEcurity: %d\n",GetLastError()); __leave; } }else{ printf("Some thing else: %d\n",GetLastError()); __leave; } if (!InitializeSecurityDescriptor( psdNew, SECURITY_DESCRIPTOR_REVISION) ){ printf("init secur descr: %d\n",GetLastError()); __leave; } if (!GetSecurityDescriptorDacl( psd, &bDaclPresent, &pacl, &bDaclExist) ){ printf("get dacl: %d\n",GetLastError()); __leave; } ZeroMemory(&aclSizeInfo, sizeof(ACL_SIZE_INFORMATION)); aclSizeInfo.AclBytesInUse = sizeof(ACL); if (pacl != NULL){ if (!GetAclInformation( pacl, (LPVOID)&aclSizeInfo, sizeof(ACL_SIZE_INFORMATION), AclSizeInformation) ){ printf("get acl info -size : %d\n",GetLastError()); __leave; } } dwNewAclSize = aclSizeInfo.AclBytesInUse + (2*sizeof(ACCESS_ALLOWED_ACE)) + (2*GetLengthSid(psid)) - (2*sizeof(DWORD)); pNewAcl = (PACL)HeapAlloc( GetProcessHeap(), HEAP_ZERO_MEMORY, dwNewAclSize); if (pNewAcl == NULL) __leave; if (!InitializeAcl(pNewAcl,dwNewAclSize,ACL_REVISION)){ printf("init new acl : %d \n",GetLastError()); __leave; } if (bDaclPresent){ // Copy the ACEs to the new ACL. if (aclSizeInfo.AceCount){ for (DWORD i=0; i < aclSizeInfo.AceCount; i++){ // Get an ACE. if (!GetAce(pacl, i, &pTemAce)) __leave; // Add the ACE to the new ACL. if (!AddAce( pNewAcl, ACL_REVISION, MAXDWORD, pTemAce, ((PACE_HEADER)pTemAce)->AceSize) ){ printf("add ace in filling: %d",GetLastError()); __leave; } } } } pAce = (ACCESS_ALLOWED_ACE *)HeapAlloc( GetProcessHeap(), HEAP_ZERO_MEMORY, sizeof(ACCESS_ALLOWED_ACE) + GetLengthSid(psid) - sizeof(DWORD)); if (pAce==NULL) __leave; pAce->Header.AceType = ACCESS_ALLOWED_ACE_TYPE; pAce->Header.AceFlags = CONTAINER_INHERIT_ACE | INHERIT_ONLY_ACE | OBJECT_INHERIT_ACE; pAce->Header.AceSize = LOWORD(sizeof(ACCESS_ALLOWED_ACE)+GetLengthSid(psid)-sizeof(DWORD)); pAce->Mask = mask; // if(!CopySid(GetLengthSid(psid), &pAce->SidStart, psid)){ //official way to save sid in ace, but strange // printf("copy sid : %d\n",GetLastError()); // __leave; // } pAce->SidStart = parseRID(psid); if(!AddAce( pNewAcl, ACL_REVISION, MAXDWORD, (LPVOID)pAce, pAce->Header.AceSize) ) { printf("add new ace %d\n",GetLastError()); __leave; } printf("WAIT!!! %d %u %d\n",pAce->SidStart,pAce->Mask,parseRID(psid)); if(!SetSecurityDescriptorDacl( psdNew, TRUE, pNewAcl, FALSE) ) { printf("set dacl %d\n",GetLastError()); __leave; } if(!SetKernelObjectSecurity(_handle,si,psdNew)){ printf("set obj secur %d\n",GetLastError()); __leave; } bSuccess = TRUE; printf("Success. added %u for %d\n",pAce->Mask,pAce->SidStart); } __finally{ if (pAce != NULL) HeapFree(GetProcessHeap(), 0, (LPVOID)pAce); if (pNewAcl != NULL) HeapFree(GetProcessHeap(), 0, (LPVOID)pNewAcl); if (psd != NULL) HeapFree(GetProcessHeap(), 0, (LPVOID)psd); if (psdNew != NULL) HeapFree(GetProcessHeap(), 0, (LPVOID)psdNew); } return bSuccess; }
int _changeAccess(LPCTSTR lpServiceName){ int returnValue = 0; SC_HANDLE schSCManager; SC_HANDLE schService; schSCManager = OpenSCManager(NULL, SERVICES_ACTIVE_DATABASE, SC_MANAGER_ALL_ACCESS); if(!schSCManager){ returnValue = GetLastError(); }else{ schService = OpenService(schSCManager, lpServiceName, READ_CONTROL|WRITE_DAC); if(!schService){ returnValue = GetLastError(); }else{ PSECURITY_DESCRIPTOR psd = NULL; DWORD dwSize, dwBytesNeeded = 0; if(!QueryServiceObjectSecurity(schService, DACL_SECURITY_INFORMATION, &psd, // using NULL does not work on all versions 0, &dwBytesNeeded)){ dwSize = dwBytesNeeded; std::vector<unsigned int> buf(dwSize); psd = (PSECURITY_DESCRIPTOR)&buf[0]; if(!QueryServiceObjectSecurity(schService, DACL_SECURITY_INFORMATION, psd, dwSize, &dwBytesNeeded)){ returnValue = GetLastError(); }else{ BOOL bDaclPresent = FALSE; PACL pacl = NULL; PACL pNewAcl = NULL; BOOL bDaclDefaulted = FALSE; if(!GetSecurityDescriptorDacl(psd, &bDaclPresent, &pacl, &bDaclDefaulted)){ returnValue = GetLastError(); }else{ EXPLICIT_ACCESS ea; BuildExplicitAccessWithName(&ea, L"GUEST", SERVICE_START|SERVICE_STOP| SERVICE_CHANGE_CONFIG|SERVICE_QUERY_CONFIG|DELETE, SET_ACCESS, NO_INHERITANCE); if(SetEntriesInAcl(1, &ea, pacl, &pNewAcl)!=ERROR_SUCCESS){ returnValue = GetLastError(); }else{ SECURITY_DESCRIPTOR sd; if(!InitializeSecurityDescriptor(&sd, SECURITY_DESCRIPTOR_REVISION)){ returnValue = GetLastError(); }else{ if(SetSecurityDescriptorDacl(&sd, TRUE, pNewAcl, FALSE)){ if(!SetServiceObjectSecurity(schService, DACL_SECURITY_INFORMATION, &sd)){ returnValue = GetLastError(); } } } LocalFree((HLOCAL)pNewAcl); } } } } CloseServiceHandle(schService); } CloseServiceHandle(schSCManager); } return returnValue; }
// // get_permissions: 1 = yes, 0 = no, -1 = unknown/error // int perm::get_permissions( const char *file_name, ACCESS_MASK &AccessRights ) { DWORD retVal; PACL pacl; PSECURITY_DESCRIPTOR pSD; DWORD pSD_length = 0; DWORD pSD_length_needed = 0; BOOL acl_present = FALSE; BOOL acl_defaulted = FALSE; // Do the call first to find out how much space is needed. pSD = NULL; GetFileSecurity( file_name, // address of string for file name DACL_SECURITY_INFORMATION, // requested information pSD, // address of security descriptor pSD_length, // size of security descriptor buffer &pSD_length_needed // address of required size of buffer ); if( pSD_length_needed <= 0 ) { // Find out how much space is needed, if <=0 then error if ( (GetLastError() == ERROR_FILE_NOT_FOUND) || (GetLastError() == ERROR_PATH_NOT_FOUND) ) { // Here we have the tricky part of walking up the directory path // Typically it works like this: If the filename exists, great, we'll // get the permissions on that. If the filename does not exist, then // we pop the filename part off the file_name and look at the // directory. If that directory should be (for some odd reason) non- // existant, then we just pop that off, until either we find something // thats will give us a permissions bitmask, or we run out of places // to look (which shouldn't happen since c:\ should always give us // SOMETHING... int i = strlen( file_name ) - 1; while ( i >= 0 && ( file_name[i] != '\\' && file_name[i] != '/' ) ) { i--; } if ( i < 0 ) { // We've nowhere else to look, and this is bad. return -1; // Its not a no, its an unknown } char *new_file_name = new char[i+1]; strncpy(new_file_name, file_name, i); new_file_name[i]= '\0'; // Now that we've chopped off more of the filename, call get_permissions // again... retVal = get_permissions( new_file_name, AccessRights ); delete[] new_file_name; // ... and return what it returns. (after deleting the string that was // allocated. return retVal; } dprintf(D_ALWAYS, "perm::GetFileSecurity failed (err=%d)\n", GetLastError()); return -1; } pSD_length = pSD_length_needed + 2; // Add 2 for safety. pSD_length_needed = 0; pSD = new BYTE[pSD_length]; // Okay, now that we've found something, and know how large of an SD we need, // call the thing for real and lets get ON WITH IT ALREADY... if( !GetFileSecurity( file_name, // address of string for file name DACL_SECURITY_INFORMATION, // requested information pSD, // address of security descriptor pSD_length, // size of security descriptor buffer &pSD_length_needed // address of required size of buffer ) ) { dprintf(D_ALWAYS, "perm::GetFileSecurity(%s) failed (err=%d)\n", file_name, GetLastError()); delete[] pSD; return -1; } // Now, get the ACL from the security descriptor if( !GetSecurityDescriptorDacl( pSD, // address of security descriptor &acl_present, // address of flag for presence of disc. ACL &pacl, // address of pointer to ACL &acl_defaulted // address of flag for default disc. ACL ) ) { dprintf(D_ALWAYS, "perm::GetSecurityDescriptorDacl failed (file=%s err=%d)\n", file_name, GetLastError()); delete[] pSD; return -1; } // This is the workaround for the broken API GetEffectiveRightsFromAcl(). // It should be guaranteed to work on all versions of NT and 2000 but be aware // that nested global group permissions are not supported. // C. Stolley - June 2001 ACL_SIZE_INFORMATION acl_info; // Structure contains the following members: // DWORD AceCount; // DWORD AclBytesInUse; // DWORD AclBytesFree; // first get the number of ACEs in the ACL if (! GetAclInformation( pacl, // acl to get info from &acl_info, // buffer to receive info sizeof(acl_info), // size in bytes of buffer AclSizeInformation // class of info to retrieve ) ) { dprintf(D_ALWAYS, "Perm::GetAclInformation failed with error %d\n", GetLastError() ); return -1; } ACCESS_MASK allow = 0x0; ACCESS_MASK deny = 0x0; unsigned int aceCount = acl_info.AceCount; int result; // now look at each ACE in the ACL and see if it contains the user we're looking for for (unsigned int i=0; i < aceCount; i++) { LPVOID current_ace; if (! GetAce( pacl, // pointer to ACL i, // index of ACE we want ¤t_ace // pointer to ACE ) ) { dprintf(D_ALWAYS, "Perm::GetAce() failed! Error code %d\n", GetLastError() ); return -1; } dprintf(D_FULLDEBUG, "Calling Perm::userInAce() for %s\\%s\n", (Domain_name) ? Domain_name : "NULL", (Account_name) ? Account_name : "NULL" ); result = userInAce ( current_ace, Account_name, Domain_name ); if (result == 1) { switch ( ( (PACE_HEADER) current_ace)->AceType ) { case ACCESS_ALLOWED_ACE_TYPE: case ACCESS_ALLOWED_OBJECT_ACE_TYPE: allow |= ( (ACCESS_ALLOWED_ACE*) current_ace)->Mask; break; case ACCESS_DENIED_ACE_TYPE: case ACCESS_DENIED_OBJECT_ACE_TYPE: deny |= ( (ACCESS_DENIED_ACE*) current_ace)->Mask; break; } } } AccessRights = allow; AccessRights &= ~deny; // and now if we've made this far everything's happy so return true return 1; }
/** * Sets the access control list for user access for the specified service. * * @param hService The service to set the access control list on * @param pNewAcl The out param ACL which should be freed by caller * @param psd out param security descriptor, should be freed by caller * @return ERROR_SUCCESS if successful */ DWORD SetUserAccessServiceDACL(SC_HANDLE hService, PACL &pNewAcl, PSECURITY_DESCRIPTOR psd) { // Get the current security descriptor needed size DWORD needed = 0; if (!QueryServiceObjectSecurity(hService, DACL_SECURITY_INFORMATION, &psd, 0, &needed)) { if (GetLastError() != ERROR_INSUFFICIENT_BUFFER) { LOG(("Warning: Could not query service object security size. (%d)\n", GetLastError())); return GetLastError(); } DWORD size = needed; psd = (PSECURITY_DESCRIPTOR)LocalAlloc(LPTR, size); if (!psd) { LOG(("Warning: Could not allocate security descriptor. (%d)\n", GetLastError())); return ERROR_INSUFFICIENT_BUFFER; } // Get the actual security descriptor now if (!QueryServiceObjectSecurity(hService, DACL_SECURITY_INFORMATION, psd, size, &needed)) { LOG(("Warning: Could not allocate security descriptor. (%d)\n", GetLastError())); return GetLastError(); } } // Get the current DACL from the security descriptor. PACL pacl = NULL; BOOL bDaclPresent = FALSE; BOOL bDaclDefaulted = FALSE; if ( !GetSecurityDescriptorDacl(psd, &bDaclPresent, &pacl, &bDaclDefaulted)) { LOG(("Warning: Could not obtain DACL. (%d)\n", GetLastError())); return GetLastError(); } PSID sid; DWORD SIDSize = SECURITY_MAX_SID_SIZE; sid = LocalAlloc(LMEM_FIXED, SIDSize); if (!sid) { LOG(("Could not allocate SID memory. (%d)\n", GetLastError())); return GetLastError(); } if (!CreateWellKnownSid(WinBuiltinUsersSid, NULL, sid, &SIDSize)) { DWORD lastError = GetLastError(); LOG(("Could not create well known SID. (%d)\n", lastError)); LocalFree(sid); return lastError; } // Lookup the account name, the function fails if you don't pass in // a buffer for the domain name but it's not used since we're using // the built in account Sid. SID_NAME_USE accountType; WCHAR accountName[UNLEN + 1] = { L'\0' }; WCHAR domainName[DNLEN + 1] = { L'\0' }; DWORD accountNameSize = UNLEN + 1; DWORD domainNameSize = DNLEN + 1; if (!LookupAccountSidW(NULL, sid, accountName, &accountNameSize, domainName, &domainNameSize, &accountType)) { LOG(("Warning: Could not lookup account Sid, will try Users. (%d)\n", GetLastError())); wcsncpy(accountName, L"Users", UNLEN); } // We already have the group name so we can get rid of the SID FreeSid(sid); sid = NULL; // Build the ACE, BuildExplicitAccessWithName cannot fail so it is not logged. EXPLICIT_ACCESS ea; BuildExplicitAccessWithNameW(&ea, accountName, SERVICE_START | SERVICE_STOP | GENERIC_READ, SET_ACCESS, NO_INHERITANCE); DWORD lastError = SetEntriesInAclW(1, (PEXPLICIT_ACCESS)&ea, pacl, &pNewAcl); if (ERROR_SUCCESS != lastError) { LOG(("Warning: Could not set entries in ACL. (%d)\n", lastError)); return lastError; } // Initialize a new security descriptor. SECURITY_DESCRIPTOR sd; if (!InitializeSecurityDescriptor(&sd, SECURITY_DESCRIPTOR_REVISION)) { LOG(("Warning: Could not initialize security descriptor. (%d)\n", GetLastError())); return GetLastError(); } // Set the new DACL in the security descriptor. if (!SetSecurityDescriptorDacl(&sd, TRUE, pNewAcl, FALSE)) { LOG(("Warning: Could not set security descriptor DACL. (%d)\n", GetLastError())); return GetLastError(); } // Set the new security descriptor for the service object. if (!SetServiceObjectSecurity(hService, DACL_SECURITY_INFORMATION, &sd)) { LOG(("Warning: Could not set object security. (%d)\n", GetLastError())); return GetLastError(); } // Woohoo, raise the roof LOG(("User access was set successfully on the service.\n")); return ERROR_SUCCESS; }
/** * This function adjusts the specified Desktop to include the specfied * user. * * See: http://msdn2.microsoft.com/en-us/library/aa379608(VS.85).aspx **/ BOOL AddAceToDesktop(HDESK hdesk, PSID psid) { ACL_SIZE_INFORMATION aclSizeInfo; BOOL bDaclExist; BOOL bDaclPresent; BOOL bSuccess = FALSE; DWORD dwNewAclSize; DWORD dwSidSize = 0; DWORD dwSdSizeNeeded; PACL pacl = NULL; PACL pNewAcl = NULL; PSECURITY_DESCRIPTOR psd = NULL; PSECURITY_DESCRIPTOR psdNew = NULL; PVOID pTempAce; SECURITY_INFORMATION si = DACL_SECURITY_INFORMATION; unsigned int i; try { // Obtain the security descriptor for the desktop object. if (!GetUserObjectSecurity( hdesk, &si, psd, dwSidSize, &dwSdSizeNeeded)) { if (GetLastError() == ERROR_INSUFFICIENT_BUFFER) { psd = (PSECURITY_DESCRIPTOR)HeapAlloc( GetProcessHeap(), HEAP_ZERO_MEMORY, dwSdSizeNeeded ); if (psd == NULL) throw; psdNew = (PSECURITY_DESCRIPTOR)HeapAlloc( GetProcessHeap(), HEAP_ZERO_MEMORY, dwSdSizeNeeded); if (psdNew == NULL) throw; dwSidSize = dwSdSizeNeeded; if (!GetUserObjectSecurity( hdesk, &si, psd, dwSidSize, &dwSdSizeNeeded) ) throw; } else throw; } // Create a new security descriptor. if (!InitializeSecurityDescriptor( psdNew, SECURITY_DESCRIPTOR_REVISION) ) throw; // Obtain the DACL from the security descriptor. if (!GetSecurityDescriptorDacl( psd, &bDaclPresent, &pacl, &bDaclExist) ) throw; // Initialize. ZeroMemory(&aclSizeInfo, sizeof(ACL_SIZE_INFORMATION)); aclSizeInfo.AclBytesInUse = sizeof(ACL); // Call only if NULL DACL. if (pacl != NULL) { // Determine the size of the ACL information. if (!GetAclInformation( pacl, (LPVOID)&aclSizeInfo, sizeof(ACL_SIZE_INFORMATION), AclSizeInformation) ) throw; } // Compute the size of the new ACL. dwNewAclSize = aclSizeInfo.AclBytesInUse + sizeof(ACCESS_ALLOWED_ACE) + GetLengthSid(psid) - sizeof(DWORD); // Allocate buffer for the new ACL. pNewAcl = (PACL)HeapAlloc( GetProcessHeap(), HEAP_ZERO_MEMORY, dwNewAclSize); if (pNewAcl == NULL) throw; // Initialize the new ACL. if (!InitializeAcl(pNewAcl, dwNewAclSize, ACL_REVISION)) throw; // If DACL is present, copy it to a new DACL. if (bDaclPresent) { // Copy the ACEs to the new ACL. if (aclSizeInfo.AceCount) { for (i=0; i < aclSizeInfo.AceCount; i++) { // Get an ACE. if (!GetAce(pacl, i, &pTempAce)) throw; // Add the ACE to the new ACL. if (!AddAce( pNewAcl, ACL_REVISION, MAXDWORD, pTempAce, ((PACE_HEADER)pTempAce)->AceSize) ) throw; } } } // Add ACE to the DACL. if (!AddAccessAllowedAce( pNewAcl, ACL_REVISION, GENERIC_ALL, psid) ) throw; // Set new DACL to the new security descriptor. if (!SetSecurityDescriptorDacl( psdNew, TRUE, pNewAcl, FALSE) ) throw; // Set the new security descriptor for the desktop object. if (!SetUserObjectSecurity(hdesk, &si, psdNew)) throw; // Indicate success. bSuccess = TRUE; } catch(...) { // Free buffers. if (pNewAcl != NULL) HeapFree(GetProcessHeap(), 0, (LPVOID)pNewAcl); if (psd != NULL) HeapFree(GetProcessHeap(), 0, (LPVOID)psd); if (psdNew != NULL) HeapFree(GetProcessHeap(), 0, (LPVOID)psdNew); } return bSuccess; }
void changeServiceAccess(const char* szName) { gcAssert(szName); SC_HANDLE scm = nullptr; SC_HANDLE Service = nullptr; BOOL bDaclPresent = FALSE; BOOL bDaclDefaulted = FALSE; DWORD dwSize = 0; EXPLICIT_ACCESS ea; PACL pacl = nullptr; PACL pNewAcl = nullptr; PSECURITY_DESCRIPTOR psd = nullptr; SECURITY_DESCRIPTOR sd; //open connection to SCM scm = OpenSCManager(nullptr, nullptr, SC_MANAGER_CONNECT); if (!scm) throw gcException(ERR_NULLSCMANAGER, GetLastError(), "Failed to open the Service Control Manager"); gcWString wName(szName); try { //open service Service = OpenService(scm, wName.c_str(), READ_CONTROL|WRITE_DAC); if (!Service) throw gcException(ERR_NULLSERVICE, GetLastError(), gcString("Failed to open service: {0}", szName)); // Get the current security descriptor. if (!QueryServiceObjectSecurity(Service, DACL_SECURITY_INFORMATION, psd, 0, &dwSize)) { if (GetLastError() == ERROR_INSUFFICIENT_BUFFER) { psd = (PSECURITY_DESCRIPTOR)HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY, dwSize); if (!psd) throw gcException(ERR_SERVICE, gcString("Failed heap allocation for service service: {0}", szName)); //get securtty info if (!QueryServiceObjectSecurity(Service, DACL_SECURITY_INFORMATION, psd, dwSize, &dwSize)) throw gcException(ERR_SERVICE, GetLastError(), gcString("QueryServiceObjectSecurity failed for service: {0}", szName)); } } if (!psd) throw gcException(ERR_SERVICE, gcString("Failed heap allocation for service service: {0}", szName)); // Get the DACL. if (!GetSecurityDescriptorDacl(psd, &bDaclPresent, &pacl, &bDaclDefaulted)) throw gcException(ERR_SERVICE, GetLastError(), gcString("GetSecurityDescriptorDacl failed for service: {0}", szName)); DWORD SidSize; PSID TheSID; SidSize = SECURITY_MAX_SID_SIZE; // Allocate enough memory for the largest possible SID. if(!(TheSID = LocalAlloc(LMEM_FIXED, SidSize))) { LocalFree(TheSID); throw gcException(ERR_SERVICE, GetLastError(), gcString("LocalAlloc failed for service: {0}", szName)); } if(!CreateWellKnownSid(WinWorldSid, nullptr, TheSID, &SidSize)) { LocalFree(TheSID); throw gcException(ERR_SERVICE, GetLastError(), gcString("CreateWellKnownSid failed for service: {0}", szName)); } wchar_t everyone[255]; wchar_t domain[255]; DWORD eSize = 255; DWORD dSize = 255; SID_NAME_USE rSidNameUse; if (!LookupAccountSid(nullptr, TheSID, everyone, &eSize, domain, &dSize, &rSidNameUse)) { LocalFree(TheSID); throw gcException(ERR_SERVICE, GetLastError(), gcString("LookupAccountSid failed for service: {0}", szName)); } LocalFree(TheSID); // Build the ACE. BuildExplicitAccessWithName(&ea, everyone, SERVICE_START|SERVICE_STOP|READ_CONTROL|SERVICE_QUERY_STATUS|PROCESS_QUERY_INFORMATION, SET_ACCESS, NO_INHERITANCE); if (SetEntriesInAcl(1, &ea, pacl, &pNewAcl) != ERROR_SUCCESS) { throw gcException(ERR_SERVICE, GetLastError(), gcString("SetEntriesInAcl failed for service: {0}", szName)); } // Initialize a NEW Security Descriptor. if (!InitializeSecurityDescriptor(&sd, SECURITY_DESCRIPTOR_REVISION)) throw gcException(ERR_SERVICE, GetLastError(), gcString("InitializeSecurityDescriptor failed for service: {0}", szName)); // Set the new DACL in the Security Descriptor. if (!SetSecurityDescriptorDacl(&sd, TRUE, pNewAcl, FALSE)) throw gcException(ERR_SERVICE, GetLastError(), gcString("SetSecurityDescriptorDacl failed for service: {0}", szName)); // Set the new DACL for the service object. if (!SetServiceObjectSecurity(Service, DACL_SECURITY_INFORMATION, &sd)) throw gcException(ERR_SERVICE, GetLastError(), gcString("SetServiceObjectSecurity failed for service: {0}", szName)); } catch (gcException &e) { if (Service) CloseServiceHandle(Service); if (scm) CloseServiceHandle(scm); // Free buffers. LocalFree((HLOCAL)pNewAcl); HeapFree(GetProcessHeap(), 0, (LPVOID)psd); throw e; } CloseServiceHandle(scm); CloseServiceHandle(Service); // Free buffers. LocalFree((HLOCAL)pNewAcl); HeapFree(GetProcessHeap(), 0, (LPVOID)psd); }
/*---------------------------------------------------------------------------*\ * NAME: CanonicalizeSD * --------------------------------------------------------------------------* * DESCRIPTION: Ensures the entire security descriptor is consistent with the new permission * format. \*---------------------------------------------------------------------------*/ DWORD CanonicalizeSD(PSECURITY_DESCRIPTOR pSD) { BOOL fSuccess = FALSE, fACLPresent = FALSE, fDefaulted = FALSE; ACL* pACL = NULL; if(IsLegacySecurityModel()) return ERROR_SUCCESS; fSuccess = GetSecurityDescriptorDacl(pSD, &fACLPresent, &pACL, &fDefaulted); if (fSuccess == FALSE) { 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 ) { 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; }
BOOL RemoveAceFromDesktop(HDESK hdesk, PSID psid) { // Obtain the security descriptor for the desktop object. SECURITY_INFORMATION si = DACL_SECURITY_INFORMATION; DWORD sd_size = 0; if (!GetUserObjectSecurity(hdesk, &si, NULL, 0, &sd_size)) { if (GetLastError() != ERROR_INSUFFICIENT_BUFFER) { printf("GetUserObjectSecurity() failed: %d\n", GetLastError()); return FALSE; } } auto_buffer<PSECURITY_DESCRIPTOR> psd(sd_size); if (!GetUserObjectSecurity(hdesk, &si, psd.get(), sd_size, &sd_size)) { printf("GetUserObjectSecurity() failed: %d\n", GetLastError()); return FALSE; } // Create a new security descriptor. auto_buffer<PSECURITY_DESCRIPTOR> psd_new(sd_size); if (!InitializeSecurityDescriptor(psd_new.get(), SECURITY_DESCRIPTOR_REVISION)) { printf("InitializeSecurityDescriptor() failed: %d\n", GetLastError()); return FALSE; } // Obtain the DACL from the security descriptor. BOOL bDaclPresent; PACL pacl; BOOL bDaclExist; if (!GetSecurityDescriptorDacl(psd.get(), &bDaclPresent, &pacl, &bDaclExist)) { printf("GetSecurityDescriptorDacl() failed: %d\n", GetLastError()); return FALSE; } // Initialize. ACL_SIZE_INFORMATION aclSizeInfo = {}; aclSizeInfo.AclBytesInUse = sizeof(ACL); if (pacl != NULL) { // Determine the size of the ACL information. if (!GetAclInformation(pacl, (LPVOID)&aclSizeInfo, sizeof aclSizeInfo, AclSizeInformation)) { printf("GetAclInformation() failed: %d\n", GetLastError()); return FALSE; } } // Allocate buffer for the new ACL. DWORD dwNewAclSize = aclSizeInfo.AclBytesInUse - (sizeof(ACCESS_ALLOWED_ACE) + GetLengthSid(psid) - sizeof(DWORD)); auto_buffer<PACL> new_acl(dwNewAclSize); // Initialize the new ACL. if (!InitializeAcl(new_acl.get(), dwNewAclSize, ACL_REVISION)) { printf("InitializeAcl() failed: %d\n", GetLastError()); return FALSE; } // If DACL is present, copy it to a new DACL. if (bDaclPresent) { // Copy the ACEs to the new ACL. for (DWORD i = 0; i != aclSizeInfo.AceCount; ++i) { // Get an ACE. ACCESS_ALLOWED_ACE* pace; if (!GetAce(pacl, i, (void**)&pace)) { printf("GetAce() failed: %d\n", GetLastError()); return FALSE; } if (!EqualSid(psid, &pace->SidStart)) { // Add the ACE to the new ACL. if (!AddAce(new_acl.get(), ACL_REVISION,MAXDWORD, pace, pace->Header.AceSize)) { printf("AddAce() failed: %d\n", GetLastError()); return FALSE; } } } } // Set new DACL to the new security descriptor. if (!SetSecurityDescriptorDacl(psd_new.get(), TRUE, new_acl.get(), FALSE)) { printf("SetSecurityDescriptorDacl() failed: %d\n", GetLastError()); return FALSE; } // Set the new security descriptor for the desktop object. if (!SetUserObjectSecurity(hdesk, &si, psd_new.get())) { printf("SetUserObjectSecurity() failed: %d\n", GetLastError()); return FALSE; } return TRUE; }
BOOL AddAceToWindowStation(HWINSTA hwinsta, PSID psid) { // Obtain the DACL for the window station. SECURITY_INFORMATION si = DACL_SECURITY_INFORMATION; DWORD sd_length = 0; if (!GetUserObjectSecurity(hwinsta, &si, NULL, 0, &sd_length)) { if (GetLastError() != ERROR_INSUFFICIENT_BUFFER) { printf("GetUserObjectSecurity() failed: %d\n", GetLastError()); return FALSE; } } auto_buffer<PSECURITY_DESCRIPTOR> psd(sd_length); if (!GetUserObjectSecurity(hwinsta, &si, psd.get(), sd_length, &sd_length)) { printf("GetUserObjectSecurity() failed: %d\n", GetLastError()); return FALSE; } // Create a new DACL. auto_buffer<PSECURITY_DESCRIPTOR> psd_new(sd_length); if (!InitializeSecurityDescriptor(psd_new.get(), SECURITY_DESCRIPTOR_REVISION)) { printf("InitializeSecurityDescriptor() failed: %d\n", GetLastError()); return FALSE; } // Get the DACL from the security descriptor. BOOL bDaclPresent; PACL pacl; BOOL bDaclExist; if (!GetSecurityDescriptorDacl(psd.get(), &bDaclPresent, &pacl, &bDaclExist)) { printf("GetSecurityDescriptorDacl() failed: %d\n", GetLastError()); return FALSE; } // Initialize the ACL. ACL_SIZE_INFORMATION aclSizeInfo = {}; aclSizeInfo.AclBytesInUse = sizeof(ACL); if (NULL != pacl) { // get the file ACL size info if (!GetAclInformation(pacl, &aclSizeInfo, sizeof aclSizeInfo, AclSizeInformation)) { printf("GetAclInformation() failed: %d\n", GetLastError()); return FALSE; } } // Compute the size of the new ACL. DWORD new_acl_size = aclSizeInfo.AclBytesInUse + (2 * sizeof(ACCESS_ALLOWED_ACE)) + (2 * GetLengthSid(psid)) - (2 * sizeof(DWORD)); auto_buffer<PACL> new_acl(new_acl_size); // Initialize the new DACL. if (!InitializeAcl(new_acl.get(), new_acl_size, ACL_REVISION)) { printf("InitializeAcl() failed: %d\n", GetLastError()); return FALSE; } // If DACL is present, copy it to a new DACL. if (bDaclPresent) { // Copy the ACEs to the new ACL. if (aclSizeInfo.AceCount) { for (DWORD i = 0; i != aclSizeInfo.AceCount; ++i) { LPVOID pTempAce; if (!GetAce(pacl, i, &pTempAce)) { printf("GetAce() failed: %d\n", GetLastError()); return FALSE; } if (!AddAce(new_acl.get(), ACL_REVISION, MAXDWORD, pTempAce, ((PACE_HEADER)pTempAce)->AceSize)) { printf("AddAce() failed: %d\n", GetLastError()); return FALSE; } } } } // Add the first ACE to the window station. auto_buffer<ACCESS_ALLOWED_ACE*> ace(sizeof(ACCESS_ALLOWED_ACE) + GetLengthSid(psid) - sizeof(DWORD)); ace->Header.AceType = ACCESS_ALLOWED_ACE_TYPE; ace->Header.AceFlags = CONTAINER_INHERIT_ACE | INHERIT_ONLY_ACE | OBJECT_INHERIT_ACE; ace->Header.AceSize = (WORD) (sizeof(ACCESS_ALLOWED_ACE) + GetLengthSid(psid) - sizeof(DWORD)); ace->Mask = GENERIC_ACCESS; if (!CopySid(GetLengthSid(psid), &ace->SidStart, psid)) { printf("CopySid() failed: %d\n", GetLastError()); return FALSE; } if (!AddAce(new_acl.get(), ACL_REVISION, MAXDWORD, ace.get(), ace->Header.AceSize)) { printf("AddAce() failed: %d\n", GetLastError()); return FALSE; } // Add the second ACE to the window station. ace->Header.AceFlags = NO_PROPAGATE_INHERIT_ACE; ace->Mask = WINSTA_ALL; if (!AddAce(new_acl.get(), ACL_REVISION,MAXDWORD, ace.get(), ace->Header.AceSize)) { printf("AddAce() failed: %d\n", GetLastError()); return FALSE; } // Set a new DACL for the security descriptor. if (!SetSecurityDescriptorDacl(psd_new.get(), TRUE, new_acl.get(), FALSE)) { printf("SetSecurityDescriptorDacl() failed: %d\n", GetLastError()); return FALSE; } // Set the new security descriptor for the window station. if (!SetUserObjectSecurity(hwinsta, &si, psd_new.get())) { printf("SetUserObjectSecurity() failed: %d\n", GetLastError()); return FALSE; } return TRUE; }
HRESULT COpcSecurity::Attach(PSECURITY_DESCRIPTOR pSelfRelativeSD) { PACL pDACL = NULL; PACL pSACL = NULL; BOOL bDACLPresent, bSACLPresent; BOOL bDefaulted; PACL m_pDACL = NULL; ACCESS_ALLOWED_ACE* pACE; HRESULT hr; PSID pUserSid; PSID pGroupSid; hr = Initialize(); if(FAILED(hr)) return hr; // get the existing DACL. if (!GetSecurityDescriptorDacl(pSelfRelativeSD, &bDACLPresent, &pDACL, &bDefaulted)) goto failed; if (bDACLPresent) { if (pDACL) { // allocate new DACL. m_pDACL = (PACL) malloc(pDACL->AclSize); if (m_pDACL == NULL) { hr = E_OUTOFMEMORY; goto failedMemory; } // initialize the DACL if (!InitializeAcl(m_pDACL, pDACL->AclSize, ACL_REVISION)) goto failed; // copy the ACES for (int i = 0; i < pDACL->AceCount; i++) { if (!GetAce(pDACL, i, (void **)&pACE)) goto failed; if (!AddAccessAllowedAce(m_pDACL, ACL_REVISION, pACE->Mask, (PSID)&(pACE->SidStart))) goto failed; } if (!IsValidAcl(m_pDACL)) goto failed; } // set the DACL if (!SetSecurityDescriptorDacl(m_pSD, m_pDACL ? TRUE : FALSE, m_pDACL, bDefaulted)) goto failed; } // get the existing SACL. if (!GetSecurityDescriptorSacl(pSelfRelativeSD, &bSACLPresent, &pSACL, &bDefaulted)) goto failed; if (bSACLPresent) { if (pSACL) { // allocate new SACL. m_pSACL = (PACL) malloc(pSACL->AclSize); if (m_pSACL == NULL) { hr = E_OUTOFMEMORY; goto failedMemory; } // initialize the SACL if (!InitializeAcl(m_pSACL, pSACL->AclSize, ACL_REVISION)) goto failed; // copy the ACES for (int i = 0; i < pSACL->AceCount; i++) { if (!GetAce(pSACL, i, (void **)&pACE)) goto failed; if (!AddAccessAllowedAce(m_pSACL, ACL_REVISION, pACE->Mask, (PSID)&(pACE->SidStart))) goto failed; } if (!IsValidAcl(m_pSACL)) goto failed; } // set the SACL if (!SetSecurityDescriptorSacl(m_pSD, m_pSACL ? TRUE : FALSE, m_pSACL, bDefaulted)) goto failed; } if (!GetSecurityDescriptorOwner(m_pSD, &pUserSid, &bDefaulted)) goto failed; if (FAILED(SetOwner(pUserSid, bDefaulted))) goto failed; if (!GetSecurityDescriptorGroup(m_pSD, &pGroupSid, &bDefaulted)) goto failed; if (FAILED(SetGroup(pGroupSid, bDefaulted))) goto failed; if (!IsValidSecurityDescriptor(m_pSD)) goto failed; return hr; failed: hr = HRESULT_FROM_WIN32(hr); failedMemory: if (m_pDACL) { free(m_pDACL); m_pDACL = NULL; } if (m_pSD) { free(m_pSD); m_pSD = NULL; } return hr; }
BOOL RemoveAceFromWindowStation(HWINSTA hwinsta, PSID psid) { // Obtain the DACL for the window station. SECURITY_INFORMATION si = DACL_SECURITY_INFORMATION; DWORD sd_length = 0; if (!GetUserObjectSecurity(hwinsta, &si, NULL, 0, &sd_length)) { if (GetLastError() != ERROR_INSUFFICIENT_BUFFER) { printf("GetUserObjectSecurity() failed: %d\n", GetLastError()); return FALSE; } } auto_buffer<PSECURITY_DESCRIPTOR> psd(sd_length); if (!GetUserObjectSecurity(hwinsta, &si, psd.get(), sd_length, &sd_length)) { printf("GetUserObjectSecurity() failed: %d\n", GetLastError()); return FALSE; } // Create a new DACL. auto_buffer<PSECURITY_DESCRIPTOR> psd_new(sd_length); if (!InitializeSecurityDescriptor(psd_new.get(), SECURITY_DESCRIPTOR_REVISION)) { printf("InitializeSecurityDescriptor() failed: %d\n", GetLastError()); return FALSE; } // Get the DACL from the security descriptor. BOOL bDaclPresent; PACL pacl; BOOL bDaclExist; if (!GetSecurityDescriptorDacl(psd.get(), &bDaclPresent, &pacl, &bDaclExist)) { printf("GetSecurityDescriptorDacl() failed: %d\n", GetLastError()); return FALSE; } // Initialize the ACL. ACL_SIZE_INFORMATION aclSizeInfo = {}; aclSizeInfo.AclBytesInUse = sizeof(ACL); if (NULL != pacl) { // get the file ACL size info if (!GetAclInformation(pacl, &aclSizeInfo, sizeof aclSizeInfo, AclSizeInformation)) { printf("GetAclInformation() failed: %d\n", GetLastError()); return FALSE; } } // Compute the size of the new ACL. DWORD new_acl_size = aclSizeInfo.AclBytesInUse - ((2 * sizeof(ACCESS_ALLOWED_ACE)) + (2 * GetLengthSid(psid)) - (2 * sizeof(DWORD))); auto_buffer<PACL> new_acl(new_acl_size); // Initialize the new DACL. if (!InitializeAcl(new_acl.get(), new_acl_size, ACL_REVISION)) { printf("InitializeAcl() failed: %d\n", GetLastError()); return FALSE; } // If DACL is present, copy it to a new DACL. if (bDaclPresent) { // Copy the ACEs to the new ACL. for (DWORD i = 0; i != aclSizeInfo.AceCount; ++i) { ACCESS_ALLOWED_ACE* pace; if (!GetAce(pacl, i, (void**)&pace)) { printf("GetAce() failed: %d\n", GetLastError()); return FALSE; } if (!EqualSid(psid, &pace->SidStart)) { if (!AddAce(new_acl.get(), ACL_REVISION, MAXDWORD, pace, pace->Header.AceSize)) { printf("AddAce() failed: %d\n", GetLastError()); return FALSE; } } } } // Set a new DACL for the security descriptor. if (!SetSecurityDescriptorDacl(psd_new.get(), TRUE, new_acl.get(), FALSE)) { printf("SetSecurityDescriptorDacl() failed: %d\n", GetLastError()); return FALSE; } // Set the new security descriptor for the window station. if (!SetUserObjectSecurity(hwinsta, &si, psd_new.get())) { printf("SetUserObjectSecurity() failed: %d\n", GetLastError()); return FALSE; } return TRUE; }
/*---------------------------------------------------------------------------*\ * NAME: UpdatePrincipalInNamedValueSD * --------------------------------------------------------------------------* * DESCRIPTION: Retrieves the designated security descriptor from the * registry and updates all ACLs that belong to the named principal. \*---------------------------------------------------------------------------*/ DWORD UpdatePrincipalInNamedValueSD ( HKEY hkeyRoot, LPTSTR tszKeyName, LPTSTR tszValueName, LPTSTR tszPrincipal, DWORD dwAccessMask, BOOL fRemove, DWORD fAceType ) { DWORD dwReturnValue = ERROR_SUCCESS; SECURITY_DESCRIPTOR *pSD = NULL; SECURITY_DESCRIPTOR *psdSelfRelative = NULL; SECURITY_DESCRIPTOR *psdAbsolute = NULL; DWORD cbSecurityDesc = 0; BOOL fPresent = FALSE; BOOL fDefaultDACL = FALSE; PACL pDacl = NULL; // Get security descriptor from registry dwReturnValue = GetNamedValueSD (hkeyRoot, tszKeyName, tszValueName, &pSD, NULL); if (dwReturnValue != ERROR_SUCCESS) { if(dwReturnValue == ERROR_FILE_NOT_FOUND && fRemove) { dwReturnValue = ERROR_SUCCESS; } goto CLEANUP; } if (!GetSecurityDescriptorDacl (pSD, &fPresent, &pDacl, &fDefaultDACL)) { dwReturnValue = GetLastError(); goto CLEANUP; } // Update the tszPrincipal that the caller wants to change dwReturnValue = UpdatePrincipalInACL (pDacl, tszPrincipal, dwAccessMask, fRemove, fAceType); if(dwReturnValue == ERROR_FILE_NOT_FOUND) { dwReturnValue = ERROR_SUCCESS; goto CLEANUP; } else if (dwReturnValue != ERROR_SUCCESS) { dwReturnValue = GetLastError(); goto CLEANUP; } // Make the security descriptor absolute dwReturnValue = MakeSDAbsolute ((PSECURITY_DESCRIPTOR) pSD, (PSECURITY_DESCRIPTOR *) &psdAbsolute); if (dwReturnValue != ERROR_SUCCESS) goto CLEANUP; // Set the discretionary ACL on the security descriptor if (!SetSecurityDescriptorDacl (psdAbsolute, TRUE, pDacl, FALSE)) { dwReturnValue = GetLastError(); goto CLEANUP; } //Now ensure consistency of the SD dwReturnValue = CanonicalizeSD(psdAbsolute); if (dwReturnValue != ERROR_SUCCESS) goto CLEANUP; // 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 (!MakeSelfRelativeSD (psdAbsolute, psdSelfRelative, &cbSecurityDesc)) { dwReturnValue = GetLastError(); goto CLEANUP; } // Store the security descriptor in the registry dwReturnValue = SetNamedValueSD (hkeyRoot, tszKeyName, tszValueName, psdSelfRelative); CLEANUP: if(pSD) free (pSD); if(psdSelfRelative) free (psdSelfRelative); if(psdAbsolute) free (psdAbsolute); return dwReturnValue; }
/*---------------------------------------------------------------------------*\ * NAME: RemovePrincipalFromNamedValueSD * --------------------------------------------------------------------------* * DESCRIPTION: Retrieves the designated security descriptor from the * registry and removes all ACLs that belong to the named principal. \*---------------------------------------------------------------------------*/ DWORD RemovePrincipalFromNamedValueSD ( HKEY hkeyRoot, LPTSTR tszKeyName, LPTSTR tszValueName, LPTSTR tszPrincipal, DWORD fAceType ) { DWORD dwReturnValue = ERROR_SUCCESS; SECURITY_DESCRIPTOR *pSD = NULL; SECURITY_DESCRIPTOR *psdSelfRelative = NULL; SECURITY_DESCRIPTOR *psdAbsolute = NULL; DWORD cbSecurityDesc = 0; BOOL fPresent = FALSE; BOOL fDefaultDACL = FALSE; PACL pDacl = NULL; dwReturnValue = GetNamedValueSD (hkeyRoot, tszKeyName, tszValueName, &pSD, NULL); // Get security descriptor from registry or create a new one if (dwReturnValue != ERROR_SUCCESS) { if(dwReturnValue == ERROR_FILE_NOT_FOUND) { dwReturnValue = ERROR_SUCCESS; } goto CLEANUP; } if (!GetSecurityDescriptorDacl (pSD, &fPresent, &pDacl, &fDefaultDACL)) { dwReturnValue = GetLastError(); goto CLEANUP; } // Remove the tszPrincipal that the caller wants removed dwReturnValue = RemovePrincipalFromACL (pDacl, tszPrincipal, fAceType); if(dwReturnValue == ERROR_FILE_NOT_FOUND) { dwReturnValue = ERROR_SUCCESS; goto CLEANUP; } else if (dwReturnValue != ERROR_SUCCESS) { dwReturnValue = GetLastError(); goto CLEANUP; } // Make the security descriptor absolute if it isn't new dwReturnValue = MakeSDAbsolute ((PSECURITY_DESCRIPTOR) pSD, (PSECURITY_DESCRIPTOR *) &psdAbsolute); if (dwReturnValue != ERROR_SUCCESS) goto CLEANUP; // Set the discretionary ACL on the security descriptor if (!SetSecurityDescriptorDacl (psdAbsolute, TRUE, pDacl, FALSE)) { dwReturnValue = GetLastError(); goto CLEANUP; } // 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 (!MakeSelfRelativeSD (psdAbsolute, psdSelfRelative, &cbSecurityDesc)) { dwReturnValue = GetLastError(); goto CLEANUP; } // Store the security descriptor in the registry dwReturnValue = SetNamedValueSD (hkeyRoot, tszKeyName, tszValueName, psdSelfRelative); CLEANUP: if(pSD) free (pSD); if(psdSelfRelative) free (psdSelfRelative); if(psdAbsolute) free (psdAbsolute); return dwReturnValue; }
/*---------------------------------------------------------------------------*\ * NAME: AddPrincipalToNamedValueSD * --------------------------------------------------------------------------* * DESCRIPTION: Retrieves the designated security descriptor from the * registry and adds an ACE for the designated principal. \*---------------------------------------------------------------------------*/ DWORD AddPrincipalToNamedValueSD ( HKEY hkeyRoot, LPTSTR tszKeyName, LPTSTR tszValueName, LPTSTR tszPrincipal, BOOL fPermit, DWORD dwAccessMask, DWORD dwSDType ) { DWORD dwReturnValue = ERROR_SUCCESS; SECURITY_DESCRIPTOR *pSD = NULL; SECURITY_DESCRIPTOR *psdSelfRelative = NULL; SECURITY_DESCRIPTOR *psdAbsolute = NULL; DWORD cbSecurityDesc = 0; BOOL fPresent = FALSE; BOOL fDefaultDACL = FALSE; PACL pDacl = NULL; BOOL fNewSD = FALSE; dwReturnValue = GetNamedValueSD (hkeyRoot, tszKeyName, tszValueName, &pSD, &fNewSD); // Get security descriptor from registry or create a new one if (dwReturnValue != ERROR_SUCCESS) goto CLEANUP; if (!GetSecurityDescriptorDacl (pSD, &fPresent, &pDacl, &fDefaultDACL)) { dwReturnValue = GetLastError(); goto CLEANUP; } if (fNewSD) { dwReturnValue = SetAclDefaults(&pDacl, dwSDType); if (dwReturnValue != ERROR_SUCCESS) goto CLEANUP; } // Add the tszPrincipal that the caller wants added if (fPermit) { dwReturnValue = AddAccessAllowedACEToACL (&pDacl, dwAccessMask, tszPrincipal); } else { dwReturnValue = AddAccessDeniedACEToACL (&pDacl, dwAccessMask, tszPrincipal); } if (dwReturnValue != ERROR_SUCCESS) goto CLEANUP; // Make the security descriptor absolute if it isn't new if (!fNewSD) { dwReturnValue = MakeSDAbsolute ((PSECURITY_DESCRIPTOR) pSD, (PSECURITY_DESCRIPTOR *) &psdAbsolute); if (dwReturnValue != ERROR_SUCCESS) goto CLEANUP; } else { psdAbsolute = pSD; } // Set the discretionary ACL on the security descriptor if (!SetSecurityDescriptorDacl (psdAbsolute, TRUE, pDacl, FALSE)) { dwReturnValue = GetLastError(); goto CLEANUP; } //Now ensure consistency of the SD dwReturnValue = CanonicalizeSD(psdAbsolute); if (dwReturnValue != ERROR_SUCCESS) goto CLEANUP; // 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) { dwReturnValue = ERROR_OUTOFMEMORY; goto CLEANUP; } if (!MakeSelfRelativeSD (psdAbsolute, psdSelfRelative, &cbSecurityDesc)) { dwReturnValue = GetLastError(); goto CLEANUP; } // Store the security descriptor in the registry SetNamedValueSD (hkeyRoot, tszKeyName, tszValueName, psdSelfRelative); CLEANUP: if(pSD) free (pSD); if(psdSelfRelative) free (psdSelfRelative); if(psdAbsolute && pSD != psdAbsolute) free (psdAbsolute); return dwReturnValue; }
/*---------------------------------------------------------------------------*\ * 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; }
// https://ru.wikipedia.org/wiki/DACL + https://github.com/hfiref0x/WinObjEx64/tree/master/Source BOOL AddAllowSidForDevice(PWCHAR wchPath, PSID lpSid, DWORD dwSidLength) { OBJECT_ATTRIBUTES ObjAtt; RtlZeroMemory(&ObjAtt, sizeof(ObjAtt)); UNICODE_STRING UserModeDeviceName; WCHAR PathBuffer[MAX_PATH] = { 0 }; wcscpy_s(PathBuffer, L"\\??\\"); wcscat_s(PathBuffer, wchPath); UserModeDeviceName.Buffer = PathBuffer; UserModeDeviceName.Length = (USHORT)(wcslen(PathBuffer) * sizeof(WCHAR)); UserModeDeviceName.MaximumLength = (USHORT)(UserModeDeviceName.Length + sizeof(WCHAR)); InitializeObjectAttributes(&ObjAtt, &UserModeDeviceName, 0, 0, 0); HANDLE hFile; IO_STATUS_BLOCK IoStatusBlock; NTSTATUS status = ntdll_ZwOpenFile(&hFile, WRITE_DAC | READ_CONTROL, &ObjAtt, &IoStatusBlock, 0, 0); if (status != STATUS_SUCCESS) { DebugOut("ZwOpenFile(..., %S,...) failed! (status=%x)\n", wchPath, status); return FALSE; } DWORD LastError; SECURITY_DESCRIPTOR *lpSd = NULL; // адрес дескриптора безопасности DWORD dwSdLength = 0; // длина SD if (!GetKernelObjectSecurity(hFile, DACL_SECURITY_INFORMATION, NULL, dwSdLength, &dwSdLength)) { LastError = GetLastError(); if (LastError == ERROR_INSUFFICIENT_BUFFER) { dwSdLength += 1000; // !! FIX_ME lpSd = (SECURITY_DESCRIPTOR*)malloc(dwSdLength); if (!GetKernelObjectSecurity(hFile, DACL_SECURITY_INFORMATION, lpSd, dwSdLength, &dwSdLength)) { DebugOut("GetKernelObjectSecurity[2](...) failed! (LastError=0x%x)\n", GetLastError()); CloseHandle(hFile); return FALSE; } } else { DebugOut("GetKernelObjectSecurity[1](...) failed! (LastError=0x%x)\n", LastError); CloseHandle(hFile); return FALSE; } } ACL* lpOldDacl; // указатель на старый DACL BOOL bDaclPresent; // признак присутствия списка DACL BOOL bDaclDefaulted; // признак списка DACL по умолчанию if (!GetSecurityDescriptorDacl(lpSd, &bDaclPresent, &lpOldDacl, &bDaclDefaulted)) { // получаем список DACL из дескриптора безопасности DebugOut("GetSecurityDescriptorDacl(...) failed! (LastError=0x%x)\n", GetLastError()); CloseHandle(hFile); return FALSE; } DWORD dwDaclLength = lpOldDacl->AclSize + sizeof(ACCESS_ALLOWED_ACE) - sizeof(DWORD) + dwSidLength; // определяем длину нового DACL ACL* lpNewDacl = (ACL*)malloc(dwDaclLength); if (!InitializeAcl(lpNewDacl, dwDaclLength, ACL_REVISION)) { // инициализируем новый DACL DebugOut("InitializeAcl(...) failed! (LastError=0x%x)\n", GetLastError()); free(lpNewDacl); CloseHandle(hFile); return FALSE; } if (!AddAccessAllowedAce(lpNewDacl, ACL_REVISION,ACCOUNT_ALLOW_RIGHTS, lpSid)) { // добавляем новый элемент в новый DACL DebugOut("AddAccessAllowedAce(...) failed! (LastError=0x%x)\n", GetLastError()); free(lpNewDacl); CloseHandle(hFile); return FALSE; } LPVOID lpAce; // указатель на элемент ACE if (!GetAce(lpOldDacl, 0, &lpAce)) { // получаем адрес первого ACE в старом списке DACL DebugOut("GetAce(...) failed! (LastError=0x%x)\n", GetLastError()); free(lpNewDacl); CloseHandle(hFile); return FALSE; } // переписываем элементы из старого DACL в новый DACL if (bDaclPresent) { if (!AddAce(lpNewDacl, ACL_REVISION, MAXDWORD, lpAce, lpOldDacl->AclSize - sizeof(ACL))) { DebugOut("AddAce(...) failed! (LastError=0x%x)\n", GetLastError()); free(lpNewDacl); CloseHandle(hFile); return FALSE; } } if (!IsValidAcl(lpNewDacl)) { // проверяем достоверность DACL DebugOut("IsValidAcl(...) == FALSE! (LastError=0x%x)\n", GetLastError()); free(lpNewDacl); CloseHandle(hFile); return FALSE; } SECURITY_DESCRIPTOR sdAbsoluteSd; // абсолютный формат SD if (!InitializeSecurityDescriptor(&sdAbsoluteSd, SECURITY_DESCRIPTOR_REVISION)) { // создаем новый дескриптор безопасности в абсолютной форме DebugOut("InitializeSecurityDescriptor(...) failed! (LastError=0x%x)\n", GetLastError()); free(lpNewDacl); CloseHandle(hFile); return FALSE; } if (!SetSecurityDescriptorDacl(&sdAbsoluteSd, TRUE, lpNewDacl, FALSE)) { // устанавливаем DACL в новый дескриптор безопасности DebugOut("SetSecurityDescriptorDacl(...) failed! (LastError=0x%x)\n", GetLastError()); free(lpNewDacl); CloseHandle(hFile); return FALSE; } // проверяем структуру дескриптора безопасности if (!IsValidSecurityDescriptor(&sdAbsoluteSd)) { DebugOut("IsValidSecurityDescriptor(...) == FALSE! (LastError=0x%x)\n", GetLastError()); free(lpNewDacl); CloseHandle(hFile); return FALSE; } if (!SetKernelObjectSecurity(hFile, DACL_SECURITY_INFORMATION, &sdAbsoluteSd)) { // устанавливаем новый дескриптор безопасности DebugOut("IsValidSecurityDescriptor(...) == FALSE! (LastError=0x%x)\n", GetLastError()); free(lpNewDacl); CloseHandle(hFile); return FALSE; } free(lpNewDacl); CloseHandle(hFile); DebugOut("ACL Rules applyed to \"%S\"\n", PathBuffer); return TRUE; }
static int TestplatformChmod( const char *nativePath, int pmode) { static const SECURITY_INFORMATION infoBits = OWNER_SECURITY_INFORMATION | GROUP_SECURITY_INFORMATION | DACL_SECURITY_INFORMATION; static const DWORD readOnlyMask = FILE_DELETE_CHILD | FILE_ADD_FILE | FILE_ADD_SUBDIRECTORY | FILE_WRITE_EA | FILE_APPEND_DATA | FILE_WRITE_DATA | DELETE; /* * References to security functions (only available on NT and later). */ const BOOL set_readOnly = !(pmode & 0222); BOOL acl_readOnly_found = FALSE, curAclPresent, curAclDefaulted; SID_IDENTIFIER_AUTHORITY userSidAuthority = { SECURITY_WORLD_SID_AUTHORITY }; BYTE *secDesc = 0; DWORD secDescLen, attr, newAclSize; ACL_SIZE_INFORMATION ACLSize; PACL curAcl, newAcl = 0; WORD j; SID *userSid = 0; char *userDomain = 0; int res = 0; /* * Process the chmod request. */ attr = GetFileAttributesA(nativePath); /* * nativePath not found */ if (attr == 0xffffffff) { res = -1; goto done; } /* * If nativePath is not a directory, there is no special handling. */ if (!(attr & FILE_ATTRIBUTE_DIRECTORY)) { goto done; } /* * Set the result to error, if the ACL change is successful it will be * reset to 0. */ res = -1; /* * Read the security descriptor for the directory. Note the first call * obtains the size of the security descriptor. */ if (!GetFileSecurityA(nativePath, infoBits, NULL, 0, &secDescLen)) { DWORD secDescLen2 = 0; if (GetLastError() != ERROR_INSUFFICIENT_BUFFER) { goto done; } secDesc = (BYTE *) ckalloc(secDescLen); if (!GetFileSecurityA(nativePath, infoBits, (PSECURITY_DESCRIPTOR) secDesc, secDescLen, &secDescLen2) || (secDescLen < secDescLen2)) { goto done; } } /* * Get the World SID. */ userSid = (SID *) ckalloc(GetSidLengthRequired((UCHAR) 1)); InitializeSid(userSid, &userSidAuthority, (BYTE) 1); *(GetSidSubAuthority(userSid, 0)) = SECURITY_WORLD_RID; /* * If curAclPresent == false then curAcl and curAclDefaulted not valid. */ if (!GetSecurityDescriptorDacl((PSECURITY_DESCRIPTOR) secDesc, &curAclPresent, &curAcl, &curAclDefaulted)) { goto done; } if (!curAclPresent || !curAcl) { ACLSize.AclBytesInUse = 0; ACLSize.AceCount = 0; } else if (!GetAclInformation(curAcl, &ACLSize, sizeof(ACLSize), AclSizeInformation)) { goto done; } /* * Allocate memory for the new ACL. */ newAclSize = ACLSize.AclBytesInUse + sizeof(ACCESS_DENIED_ACE) + GetLengthSid(userSid) - sizeof(DWORD); newAcl = (ACL *) ckalloc(newAclSize); /* * Initialize the new ACL. */ if (!InitializeAcl(newAcl, newAclSize, ACL_REVISION)) { goto done; } /* * Add denied to make readonly, this will be known as a "read-only tag". */ if (set_readOnly && !AddAccessDeniedAce(newAcl, ACL_REVISION, readOnlyMask, userSid)) { goto done; } acl_readOnly_found = FALSE; for (j = 0; j < ACLSize.AceCount; j++) { LPVOID pACE2; ACE_HEADER *phACE2; if (!GetAce(curAcl, j, &pACE2)) { goto done; } phACE2 = (ACE_HEADER *) pACE2; /* * Do NOT propagate inherited ACEs. */ if (phACE2->AceFlags & INHERITED_ACE) { continue; } /* * Skip the "read-only tag" restriction (either added above, or it is * being removed). */ if (phACE2->AceType == ACCESS_DENIED_ACE_TYPE) { ACCESS_DENIED_ACE *pACEd = (ACCESS_DENIED_ACE *) phACE2; if (pACEd->Mask == readOnlyMask && EqualSid(userSid, (PSID) &pACEd->SidStart)) { acl_readOnly_found = TRUE; continue; } } /* * Copy the current ACE from the old to the new ACL. */ if (!AddAce(newAcl, ACL_REVISION, MAXDWORD, (PACL *) pACE2, ((PACE_HEADER) pACE2)->AceSize)) { goto done; } } /* * Apply the new ACL. */ if (set_readOnly == acl_readOnly_found || SetNamedSecurityInfoA( (LPSTR) nativePath, SE_FILE_OBJECT, DACL_SECURITY_INFORMATION, NULL, NULL, newAcl, NULL) == ERROR_SUCCESS) { res = 0; } done: if (secDesc) { ckfree((char *) secDesc); } if (newAcl) { ckfree((char *) newAcl); } if (userSid) { ckfree((char *) userSid); } if (userDomain) { ckfree((char *) userDomain); } if (res != 0) { return res; } /* * Run normal chmod command. */ return chmod(nativePath, pmode); }
HRESULT CSecurityInformation::SetSecurity( SECURITY_INFORMATION SecurityInformation, PSECURITY_DESCRIPTOR pSecurityDescriptor) { HRESULT hr = 1; // Get the Dacl PACL pDACL = NULL; BOOL fPresent, fDefaulted; GetSecurityDescriptorDacl(pSecurityDescriptor, &fPresent, &pDACL, &fDefaulted); // Get the SACL PACL pSACL = NULL; GetSecurityDescriptorSacl(pSecurityDescriptor, &fPresent, &pSACL, &fDefaulted); // Get the owner PSID psidOwner = NULL; GetSecurityDescriptorOwner(pSecurityDescriptor, &psidOwner, &fDefaulted); // Get the group PSID psidGroup = NULL; GetSecurityDescriptorOwner(pSecurityDescriptor, &psidGroup, &fDefaulted); // Find out if DACL and SACL inherit from parent objects SECURITY_DESCRIPTOR_CONTROL sdCtrl = NULL; ULONG ulRevision; GetSecurityDescriptorControl(pSecurityDescriptor, &sdCtrl, &ulRevision); if ((sdCtrl & SE_DACL_PROTECTED) != SE_DACL_PROTECTED) SecurityInformation |= UNPROTECTED_DACL_SECURITY_INFORMATION; else SecurityInformation |= PROTECTED_DACL_SECURITY_INFORMATION; if ((sdCtrl & SE_SACL_PROTECTED) != SE_SACL_PROTECTED) SecurityInformation |= UNPROTECTED_SACL_SECURITY_INFORMATION; else SecurityInformation |= PROTECTED_SACL_SECURITY_INFORMATION; // Set the security ULONG lErr; if (m_Info.m_szName[0] != 0) // Is it named { lErr = SetNamedSecurityInfo(m_Info.m_szName, m_Type.m_objSecurType, SecurityInformation, psidOwner, psidGroup, pDACL, pSACL); } else { // Is it a handle case lErr = SetSecurityInfo(m_Info.m_hHandle, m_Type.m_objSecurType, SecurityInformation, psidOwner, psidGroup, pDACL, pSACL); } // Report error if (lErr != ERROR_SUCCESS) { MessageBox(NULL, TEXT("An error occurred saving security information for this object,\n") TEXT("possibly due to insufficient access rights.\n"), TEXT("Security Notice"), MB_OK); } else { hr = S_OK; } return(hr); }