/* Do some black magic with the NT security API. * We prepare a DACL (Discretionary Access Control List) so that * we, the creator, are allowed all access, while "Everyone Else" * is only allowed to read and write to the pipe. * This avoids security issues on shared hosts where a luser messes * with the lower-level pipe settings and screws up the FastCGI service. */ static PACL prepare_named_pipe_acl(PSECURITY_DESCRIPTOR sd, LPSECURITY_ATTRIBUTES sa) { DWORD req_acl_size; char everyone_buf[32], owner_buf[32]; PSID sid_everyone, sid_owner; SID_IDENTIFIER_AUTHORITY siaWorld = SECURITY_WORLD_SID_AUTHORITY, siaCreator = SECURITY_CREATOR_SID_AUTHORITY; PACL acl; sid_everyone = (PSID)&everyone_buf; sid_owner = (PSID)&owner_buf; req_acl_size = sizeof(ACL) + (2 * ((sizeof(ACCESS_ALLOWED_ACE) - sizeof(DWORD)) + GetSidLengthRequired(1))); acl = malloc(req_acl_size); if (acl == NULL) { return NULL; } if (!InitializeSid(sid_everyone, &siaWorld, 1)) { goto out_fail; } *GetSidSubAuthority(sid_everyone, 0) = SECURITY_WORLD_RID; if (!InitializeSid(sid_owner, &siaCreator, 1)) { goto out_fail; } *GetSidSubAuthority(sid_owner, 0) = SECURITY_CREATOR_OWNER_RID; if (!InitializeAcl(acl, req_acl_size, ACL_REVISION)) { goto out_fail; } if (!AddAccessAllowedAce(acl, ACL_REVISION, FILE_GENERIC_READ | FILE_GENERIC_WRITE, sid_everyone)) { goto out_fail; } if (!AddAccessAllowedAce(acl, ACL_REVISION, FILE_ALL_ACCESS, sid_owner)) { goto out_fail; } if (!InitializeSecurityDescriptor(sd, SECURITY_DESCRIPTOR_REVISION)) { goto out_fail; } if (!SetSecurityDescriptorDacl(sd, TRUE, acl, FALSE)) { goto out_fail; } sa->lpSecurityDescriptor = sd; return acl; out_fail: free(acl); return NULL; }
wchar_t *get_app_sid(HANDLE process) { wchar_t *ret = NULL; DWORD size_ret; BOOL success; HANDLE token; if (OpenProcessToken(process, TOKEN_QUERY, &token)) { DWORD info_len = GetSidLengthRequired(12) + sizeof(TOKEN_APPCONTAINER_INFORMATION); PTOKEN_APPCONTAINER_INFORMATION info = malloc(info_len); success = GetTokenInformation(token, TokenAppContainerSid, info, info_len, &size_ret); if (success) ConvertSidToStringSidW(info->TokenAppContainer, &ret); free(info); CloseHandle(token); } return ret; }
BOOL LookupUserGroupFromRid( LPWSTR TargetComputer, DWORD Rid, LPWSTR Name, PDWORD cchName ) { PUSER_MODALS_INFO_2 umi2; NET_API_STATUS nas; UCHAR SubAuthorityCount; PSID pSid; SID_NAME_USE snu; WCHAR DomainName[DNLEN+1]; DWORD cchDomainName = DNLEN; BOOL bSuccess = FALSE; // assume failure // // get the account domain Sid on the target machine // note: if you were looking up multiple sids based on the same // account domain, only need to call this once. // nas = NetUserModalsGet(TargetComputer, 2, (LPBYTE *)&umi2); if(nas != NERR_Success) { SetLastError(nas); return FALSE; } SubAuthorityCount = *GetSidSubAuthorityCount (umi2->usrmod2_domain_id); // // allocate storage for new Sid. account domain Sid + account Rid // pSid = (PSID)HeapAlloc(GetProcessHeap(), 0, GetSidLengthRequired((UCHAR)(SubAuthorityCount + 1))); if(pSid != NULL) { if(InitializeSid( pSid, GetSidIdentifierAuthority(umi2->usrmod2_domain_id), (BYTE)(SubAuthorityCount+1) )) { DWORD SubAuthIndex = 0; // // copy existing subauthorities from account domain Sid into // new Sid // for( ; SubAuthIndex < SubAuthorityCount ; SubAuthIndex++) { *GetSidSubAuthority(pSid, SubAuthIndex) = *GetSidSubAuthority(umi2->usrmod2_domain_id, SubAuthIndex); } // // append Rid to new Sid // *GetSidSubAuthority(pSid, SubAuthorityCount) = Rid; bSuccess = LookupAccountSidW( TargetComputer, pSid, Name, cchName, DomainName, &cchDomainName, &snu ); } HeapFree(GetProcessHeap(), 0, pSid); } NetApiBufferFree(umi2); return bSuccess; }
void initialize (void) { ULONG SidWithZeroSubAuthorities; ULONG SidWithOneSubAuthority; ULONG SidWithThreeSubAuthorities; ULONG SidWithFourSubAuthorities; SID_IDENTIFIER_AUTHORITY NullSidAuthority = SECURITY_NULL_SID_AUTHORITY; SID_IDENTIFIER_AUTHORITY WorldSidAuthority = SECURITY_WORLD_SID_AUTHORITY; SID_IDENTIFIER_AUTHORITY LocalSidAuthority = SECURITY_LOCAL_SID_AUTHORITY; SID_IDENTIFIER_AUTHORITY CreatorSidAuthority = SECURITY_CREATOR_SID_AUTHORITY; SID_IDENTIFIER_AUTHORITY NtAuthority = SECURITY_NT_AUTHORITY; // // The following SID sizes need to be allocated // SidWithZeroSubAuthorities = GetSidLengthRequired( 0 ); SidWithOneSubAuthority = GetSidLengthRequired( 1 ); SidWithThreeSubAuthorities = GetSidLengthRequired( 3 ); SidWithFourSubAuthorities = GetSidLengthRequired( 4 ); // // Allocate and initialize the universal SIDs // NullSid = (PSID)RtlAllocateHeap( RtlProcessHeap(), 0,SidWithOneSubAuthority); WorldSid = (PSID)RtlAllocateHeap( RtlProcessHeap(), 0,SidWithOneSubAuthority); LocalSid = (PSID)RtlAllocateHeap( RtlProcessHeap(), 0,SidWithOneSubAuthority); CreatorOwnerSid = (PSID)RtlAllocateHeap( RtlProcessHeap(), 0,SidWithOneSubAuthority); InitializeSid( NullSid, &NullSidAuthority, 1 ); InitializeSid( WorldSid, &WorldSidAuthority, 1 ); InitializeSid( LocalSid, &LocalSidAuthority, 1 ); InitializeSid( CreatorOwnerSid, &CreatorSidAuthority, 1 ); *(GetSidSubAuthority( NullSid, 0 )) = SECURITY_NULL_RID; *(GetSidSubAuthority( WorldSid, 0 )) = SECURITY_WORLD_RID; *(GetSidSubAuthority( LocalSid, 0 )) = SECURITY_LOCAL_RID; *(GetSidSubAuthority( CreatorOwnerSid, 0 )) = SECURITY_CREATOR_OWNER_RID; // // Allocate and initialize the NT defined SIDs // NtAuthoritySid = (PSID)RtlAllocateHeap( RtlProcessHeap(), 0,SidWithZeroSubAuthorities); DialupSid = (PSID)RtlAllocateHeap( RtlProcessHeap(), 0,SidWithOneSubAuthority); NetworkSid = (PSID)RtlAllocateHeap( RtlProcessHeap(), 0,SidWithOneSubAuthority); BatchSid = (PSID)RtlAllocateHeap( RtlProcessHeap(), 0,SidWithOneSubAuthority); InteractiveSid = (PSID)RtlAllocateHeap( RtlProcessHeap(), 0,SidWithOneSubAuthority); LocalSystemSid = (PSID)RtlAllocateHeap( RtlProcessHeap(), 0,SidWithOneSubAuthority); InitializeSid( NtAuthoritySid, &NtAuthority, 0 ); InitializeSid( DialupSid, &NtAuthority, 1 ); InitializeSid( NetworkSid, &NtAuthority, 1 ); InitializeSid( BatchSid, &NtAuthority, 1 ); InitializeSid( InteractiveSid, &NtAuthority, 1 ); InitializeSid( LocalSystemSid, &NtAuthority, 1 ); *(GetSidSubAuthority( DialupSid, 0 )) = SECURITY_DIALUP_RID; *(GetSidSubAuthority( NetworkSid, 0 )) = SECURITY_NETWORK_RID; *(GetSidSubAuthority( BatchSid, 0 )) = SECURITY_BATCH_RID; *(GetSidSubAuthority( InteractiveSid, 0 )) = SECURITY_INTERACTIVE_RID; *(GetSidSubAuthority( LocalSystemSid, 0 )) = SECURITY_LOCAL_SYSTEM_RID; // // Initialize the well known privilege values // SeCreateTokenPrivilege = RtlConvertLongToLargeInteger(SE_CREATE_TOKEN_PRIVILEGE); SeAssignPrimaryTokenPrivilege = RtlConvertLongToLargeInteger(SE_ASSIGNPRIMARYTOKEN_PRIVILEGE); SeLockMemoryPrivilege = RtlConvertLongToLargeInteger(SE_LOCK_MEMORY_PRIVILEGE); SeIncreaseQuotaPrivilege = RtlConvertLongToLargeInteger(SE_INCREASE_QUOTA_PRIVILEGE); SeUnsolicitedInputPrivilege = RtlConvertLongToLargeInteger(SE_UNSOLICITED_INPUT_PRIVILEGE); SeTcbPrivilege = RtlConvertLongToLargeInteger(SE_TCB_PRIVILEGE); SeSecurityPrivilege = RtlConvertLongToLargeInteger(SE_SECURITY_PRIVILEGE); SeTakeOwnershipPrivilege = RtlConvertLongToLargeInteger(SE_TAKE_OWNERSHIP_PRIVILEGE); SeLoadDriverPrivilege = RtlConvertLongToLargeInteger(SE_LOAD_DRIVER_PRIVILEGE); SeCreatePagefilePrivilege = RtlConvertLongToLargeInteger(SE_CREATE_PAGEFILE_PRIVILEGE); SeIncreaseBasePriorityPrivilege = RtlConvertLongToLargeInteger(SE_INC_BASE_PRIORITY_PRIVILEGE); SeSystemProfilePrivilege = RtlConvertLongToLargeInteger(SE_SYSTEM_PROFILE_PRIVILEGE); SeSystemtimePrivilege = RtlConvertLongToLargeInteger(SE_SYSTEMTIME_PRIVILEGE); SeProfileSingleProcessPrivilege = RtlConvertLongToLargeInteger(SE_PROF_SINGLE_PROCESS_PRIVILEGE); SeCreatePermanentPrivilege = RtlConvertLongToLargeInteger(SE_CREATE_PERMANENT_PRIVILEGE); SeBackupPrivilege = RtlConvertLongToLargeInteger(SE_BACKUP_PRIVILEGE); SeRestorePrivilege = RtlConvertLongToLargeInteger(SE_RESTORE_PRIVILEGE); SeShutdownPrivilege = RtlConvertLongToLargeInteger(SE_SHUTDOWN_PRIVILEGE); SeDebugPrivilege = RtlConvertLongToLargeInteger(SE_DEBUG_PRIVILEGE); SeAuditPrivilege = RtlConvertLongToLargeInteger(SE_AUDIT_PRIVILEGE); SeSystemEnvironmentPrivilege = RtlConvertLongToLargeInteger(SE_SYSTEM_ENVIRONMENT_PRIVILEGE); SeChangeNotifyPrivilege = RtlConvertLongToLargeInteger(SE_CHANGE_NOTIFY_PRIVILEGE); SeRemoteShutdownPrivilege = RtlConvertLongToLargeInteger(SE_REMOTE_SHUTDOWN_PRIVILEGE); }
BOOL BuildGenericAccessAcl( PACL* ppAcl, PDWORD cbAclSize ) /*++ Routine Description This function builds a Dacl which grants the creator of the objects GENERIC_ALL (Full Control) and Everyone GENERIC_READ, GENERIC_WRITE and GENERIC_EXECUTE access to the object. This Dacl allows for higher security than a NULL Dacl, as this only grants the creator/owner write access to the security descriptor, and grants Everyone the ability to "use" the object. This scenario prevents a malevolent user from disrupting service by preventing arbitrary access manipulation. Arguments PACL* pAcl - Pointer to buffer for pointer to allocated PACL. Must be freed with LocalFree PDWORD cbAclSize - Pointer to dword receiving size of acl. Return value Bool, true on success, false on error --*/ { DWORD dwAclSize; SID_IDENTIFIER_AUTHORITY siaWorld = SECURITY_WORLD_SID_AUTHORITY; SID_IDENTIFIER_AUTHORITY siaCreator = SECURITY_CREATOR_SID_AUTHORITY; PSID pEveryoneSid = NULL; PSID pOwnerSid = NULL; BOOL bSuccess = FALSE; __try { // // compute size of acl // dwAclSize = sizeof(ACL) + 2 * ( sizeof(ACCESS_ALLOWED_ACE) - sizeof(DWORD) ) + GetSidLengthRequired( 1 ) + // well-known Everyone Sid GetSidLengthRequired( 1 ) ; // well-known Creator Owner Sid (*ppAcl) = LocalAlloc(0,dwAclSize); if(*ppAcl == NULL) { HandleError(GetLastError(), TEXT("LocalAlloc"), TRUE, TRUE); __leave; } *cbAclSize = dwAclSize; InitializeAcl(*ppAcl,dwAclSize,ACL_REVISION); // // build well known sids // // build EVERYONE SID AllocateAndInitializeSid( &siaWorld, 1, SECURITY_WORLD_RID, 0,0,0,0,0,0,0, &pEveryoneSid ); // build Creator/Owner SID AllocateAndInitializeSid( &siaCreator, 1, SECURITY_CREATOR_OWNER_RID, 0,0,0,0,0,0,0, &pOwnerSid ); if (!AddAccessAllowedAce( *ppAcl, ACL_REVISION, GENERIC_READ | GENERIC_WRITE | GENERIC_EXECUTE, pEveryoneSid )) { HandleError(GetLastError(),TEXT("AddAccessAllowedAce"),TRUE,TRUE); __leave; } if (!AddAccessAllowedAce( *ppAcl, ACL_REVISION, GENERIC_ALL, pOwnerSid )) { HandleError(GetLastError(),TEXT("AddAccessAllowedAce (2)"),TRUE,TRUE); __leave; } bSuccess = TRUE; } __finally { if (pEveryoneSid) FreeSid(pEveryoneSid); if (pOwnerSid) FreeSid(pOwnerSid); } return bSuccess; }
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); }