#include #include #include "common.h" #include "security.h" #include "debugout.h" /* * GetTokenHandle */ BOOL GetTokenHandle( PHANDLE pTokenHandle ) { if (OpenThreadToken( GetCurrentThread(), TOKEN_READ, FALSE, pTokenHandle)) return TRUE; if (GetLastError() != ERROR_NO_TOKEN) return FALSE; if (OpenProcessToken( GetCurrentProcess(), TOKEN_READ, pTokenHandle)) return TRUE; return FALSE; } /* * MakeLocalOnlySD * * Purpose: Generate a self-relative SD whose ACL contains only an * entry for LocalSystem/GENERIC_ALL access. This SD will be used * in calls to CreateFile() for clipbook page files. * * Parameters: None * * Returns: Pointer to the security descriptor. This pointer may be freed. * Returns NULL on failure. */ PSECURITY_DESCRIPTOR MakeLocalOnlySD (void) { PSECURITY_DESCRIPTOR pSD; PSECURITY_DESCRIPTOR pSDSelfRel = NULL; SID_IDENTIFIER_AUTHORITY authNT = SECURITY_NT_AUTHORITY; PSID sidLocal; PACL Acl; DWORD dwAclSize; if (AllocateAndInitializeSid(&authNT, 1, SECURITY_LOCAL_SYSTEM_RID, 0, 0, 0, 0, 0, 0, 0, &sidLocal)) { if (InitializeSecurityDescriptor(&pSD, SECURITY_DESCRIPTOR_REVISION)) { // Allocate space for DACL with "System Full Control" access dwAclSize = sizeof(ACL)+ GetLengthSid(sidLocal) + sizeof(ACCESS_ALLOWED_ACE) + 42; // 42==fudge factor if (Acl = (PACL)GlobalAlloc(GPTR, dwAclSize)) { if (InitializeAcl(Acl, dwAclSize, ACL_REVISION)) { // LocalSystem gets all access, nobody else gets any. if (AddAccessAllowedAce(Acl, ACL_REVISION, GENERIC_ALL, sidLocal)) { if (SetSecurityDescriptorDacl(pSD, TRUE, Acl, TRUE)) { DWORD dwSelfRelLen; dwSelfRelLen = GetSecurityDescriptorLength(pSD); pSDSelfRel = GlobalAlloc(GPTR, dwSelfRelLen); if (pSDSelfRel) { if (!MakeSelfRelativeSD(pSD, pSDSelfRel, &dwSelfRelLen)) { GlobalFree((HANDLE)pSDSelfRel); pSDSelfRel = NULL; } } } } } GlobalFree((HANDLE)Acl); } } FreeSid(sidLocal); } return(pSDSelfRel); } /* * CurrentUserOnlySD * * Purpose: Create a security descriptor containing only a single * DACL entry-- one to allow the user whose context we are running * in GENERIC_ALL access. * * Parameters: None. * * Returns: A pointer to the security descriptor described above, * or NULL on failure. */ PSECURITY_DESCRIPTOR CurrentUserOnlySD (void) { SID_IDENTIFIER_AUTHORITY NtAuthority = SECURITY_NT_AUTHORITY; SECURITY_DESCRIPTOR aSD; PSECURITY_DESCRIPTOR pSD = NULL; BOOL OK; PACL TmpAcl; PACCESS_ALLOWED_ACE TmpAce; DWORD lSD; LONG DaclLength; DWORD lTokenInfo; HANDLE hClientToken; TOKEN_USER *pUserTokenInfo; if (!InitializeSecurityDescriptor(&aSD, SECURITY_DESCRIPTOR_REVISION) || GetTokenHandle(&hClientToken)) { PERROR(TEXT("Couldn't get token handle or InitSD bad \r\n")); return NULL; } // See if the token info fits in 50 bytes. If it does, fine. // If not, realloc to proper size and get the token info. pUserTokenInfo = (TOKEN_USER *)LocalAlloc( LMEM_FIXED, 50 ); if (pUserTokenInfo && !GetTokenInformation( hClientToken, TokenUser, (LPVOID) pUserTokenInfo, 50, &lTokenInfo ) ) { LocalFree( pUserTokenInfo ); pUserTokenInfo = (TOKEN_USER *)LocalAlloc( LMEM_FIXED, lTokenInfo ); if (!GetTokenInformation( hClientToken, TokenUser, (LPVOID) pUserTokenInfo, lTokenInfo, &lTokenInfo ) ) { LocalFree( pUserTokenInfo ); pUserTokenInfo = NULL; } } if (!pUserTokenInfo) { PERROR(TEXT("Couldn't get usertokeninfo\r\n")); } else { // Figure out how big a Dacl we'll need for just me to be on it. DaclLength = (DWORD)sizeof(ACL) + GetLengthSid( pUserTokenInfo->User.Sid ) + (DWORD)sizeof( ACCESS_ALLOWED_ACE ); if (!(TmpAcl = (PACL)LocalAlloc(LMEM_FIXED, DaclLength ))) { PERROR(TEXT("LocalAllof for Acl fail\r\n")); } else { if (!InitializeAcl( TmpAcl, DaclLength, ACL_REVISION )) { PERROR(TEXT("InitializeAcl fail\r\n")); } else if (!AddAccessAllowedAce( TmpAcl, ACL_REVISION, GENERIC_ALL, pUserTokenInfo->User.Sid )) { PERROR(TEXT("AddAccessAllowedAce fail\r\n")); } else if (!GetAce( TmpAcl, 0, (LPVOID *)&TmpAce)) { PERROR("GetAce error %d", GetLastError()); } else { TmpAce->Header.AceFlags = 0; OK = SetSecurityDescriptorDacl(&aSD, TRUE, TmpAcl, FALSE); lSD = GetSecurityDescriptorLength( &aSD); if (pSD = (PSECURITY_DESCRIPTOR)LocalAlloc(LMEM_FIXED, lSD)) { MakeSelfRelativeSD( &aSD, pSD, &lSD); if( IsValidSecurityDescriptor( pSD ) ) { LocalFree(pSD); pSD = NULL; } else { PERROR(TEXT("Failed creating self-relative SD (%d)."), GetLastError()); } } else { PERROR(TEXT("LocalAlloc for pSD fail\r\n")); } } LocalFree((HANDLE)TmpAcl); } LocalFree((HANDLE)pUserTokenInfo); } CloseHandle(hClientToken); return pSD; } #ifdef DEBUG /* * HexDumpBytes */ void HexDumpBytes( char *pv, unsigned cb) { char achHex[]="0123456789ABCDEF"; char achOut[80]; unsigned iOut; iOut = 0; while (cb) { if (iOut >= 78) { PINFO(achOut); iOut = 0; } achOut[iOut++] = achHex[(*pv >> 4) & 0x0f]; achOut[iOut++] = achHex[*pv++ & 0x0f]; achOut[iOut] = '\0'; cb--; } if (iOut) { PINFO(achOut); } } /* * PrintSid */ void PrintSid( PSID sid) { DWORD cSubAuth; DWORD i; PINFO(TEXT("\r\nSID: ")); if (sid) { HexDumpBytes((char *)GetSidIdentifierAuthority(sid), sizeof(SID_IDENTIFIER_AUTHORITY)); SetLastError(0); cSubAuth = *GetSidSubAuthorityCount(sid); if (GetLastError()) { PINFO(TEXT("Invalid SID\r\n")); } else { for (i = 0;i < cSubAuth; i++) { PINFO(TEXT("-")); HexDumpBytes((char *)GetSidSubAuthority(sid, i), sizeof(DWORD)); } PINFO(TEXT("\r\n")); } } else { PINFO(TEXT("NULL SID\r\n")); } } /* * PrintAcl * * Purpose: Print out the entries in an access-control list. */ void PrintAcl( PACL pacl) { ACL_SIZE_INFORMATION aclsi; ACCESS_ALLOWED_ACE *pace; unsigned i; if (pacl) { if (GetAclInformation (pacl, &aclsi, sizeof(aclsi), AclSizeInformation)) { for (i = 0;i < aclsi.AceCount;i++) { GetAce(pacl, i, &pace); PINFO(TEXT("Type(%x) Flags(%x) Access(%lx)\r\nSID:"), (int)pace->Header.AceType, (int)pace->Header.AceFlags, pace->Mask); PrintSid((PSID)&(pace->SidStart)); } } } else { PINFO(TEXT("NULL PACL\r\n")); } } /* * PrintSD */ void PrintSD( PSECURITY_DESCRIPTOR pSD) { DWORD dwRev; WORD wSDC; BOOL fDefault, fAcl; PACL pacl; PSID sid; if (NULL == pSD) { PINFO(TEXT("NULL sd\r\n")); return; } if (!IsValidSecurityDescriptor(pSD)) { PINFO(TEXT("Bad SD %p"), pSD); return; } // Drop control info and revision if (GetSecurityDescriptorControl(pSD, &wSDC, &dwRev)) { PINFO(TEXT("SD - Length: [%ld] Control: [%x] [%lx]\r\nGroup:"), GetSecurityDescriptorLength(pSD), wSDC, dwRev); } else { PINFO(TEXT("Couldn't get control\r\nGroup")); } // Show group and owner if (GetSecurityDescriptorGroup(pSD, &sid, &fDefault) && sid && IsValidSid(sid)) { PrintSid(sid); PINFO(TEXT(" %s default.\r\nOwner:"), fDefault ? TEXT(" ") : TEXT("Not")); } else { PINFO(TEXT("Couldn't get group\r\n")); } if (GetSecurityDescriptorOwner(pSD, &sid, &fDefault) && sid && IsValidSid(sid)) { PrintSid(sid); PINFO(TEXT(" %s default.\r\n"), fDefault ? TEXT(" ") : TEXT("Not")); } else { PINFO(TEXT("Couldn't get owner\r\n")); } // Print DACL and SACL if (GetSecurityDescriptorDacl(pSD, &fAcl, &pacl, &fDefault)) { PINFO(TEXT("DACL: %s %s\r\n"), fAcl ? "Yes" : "No", fDefault ? "Default" : " "); if (fAcl) { if (pacl && IsValidAcl(pacl)) { PrintAcl(pacl); } else { PINFO(TEXT("Invalid Acl %p\r\n"), pacl); } } } else { PINFO(TEXT("Couldn't get DACL\r\n")); } if (GetSecurityDescriptorSacl(pSD, &fAcl, &pacl, &fDefault)) { PINFO(TEXT("SACL: %s %s\r\n"), fAcl ? "Yes" : "No", fDefault ? "Default" : " "); if (fAcl) { if (pacl && IsValidAcl(pacl)) { PrintAcl(pacl); } else { PINFO(TEXT("Invalid ACL %p\r\n"), pacl); } } } else { PINFO(TEXT("Couldn't get SACL\r\n")); } } #else #define PrintSid(x) #define PrintSD(x) #endif