// ---------------------------------------------------------------------------- // // SecDescr.c // // // Author: Jost Eckhardt // // This code was written for ECO Kommunikation Insight // Copyright (c) 1997-1999 Microsoft Corporation // ---------------------------------------------------------------------------- #include #include #include #include #include #include "_UMTool.h" static PSECURITY_DESCRIPTOR GetObjectSecurityDescr( obj_sec_descr_tsp obj, DWORD dwAccessMaskOwner, DWORD dwAccessMaskLoggedOnUser); static BOOL GetUserSidFromToken(HANDLE hToken, PSID *ppSid); static BOOL GetGroupSidFromToken(HANDLE hToken, PSID *ppSid); // --------------------------- // InitSecurityAttributes - initialize the security descriptor in the // obj_sec_attr_tsp struct using a null DACL. // // Caller must call ClearSecurityAttributes when done with the struct. // void InitSecurityAttributes(obj_sec_attr_tsp psa) { memset(psa,0,sizeof(obj_sec_attr_ts)); psa->sa.nLength = sizeof(SECURITY_ATTRIBUTES); psa->sa.bInheritHandle = TRUE; psa->sa.lpSecurityDescriptor = GetObjectSecurityDescr(&psa->objsd, 0, 0); } // --------------------------- // InitSecurityAttributesEx - initialize the security descriptor in the // obj_sec_attr_tsp struct using a non-null DACL // // dwAccessMaskOwner - If non-zero specifies the access allowed to the creator // dwAccessMaskLoggedOnUser - If non-zero specifies the access allowed to the current user // // If dwAccessMaskOwner and dwAccessMaskLoggedOnUser are zero the security descriptor // will have a NULL DACL. Caller must call ClearSecurityAttributes when done // with the struct. // void InitSecurityAttributesEx(obj_sec_attr_tsp psa, DWORD dwAccessMaskOwner, DWORD dwAccessMaskLoggedOnUser) { memset(psa,0,sizeof(obj_sec_attr_ts)); psa->sa.nLength = sizeof(SECURITY_ATTRIBUTES); psa->sa.bInheritHandle = TRUE; psa->sa.lpSecurityDescriptor = GetObjectSecurityDescr(&psa->objsd, dwAccessMaskOwner, dwAccessMaskLoggedOnUser); } // --------------------------- // ClearSecurityAttributes - free memory from the security descriptor // void ClearSecurityAttributes(obj_sec_attr_tsp psa) { if (psa->sa.lpSecurityDescriptor) free(psa->sa.lpSecurityDescriptor); if (psa->objsd.psidUser) free(psa->objsd.psidUser); if (psa->objsd.psidGroup) free(psa->objsd.psidGroup); memset(psa,0,sizeof(obj_sec_attr_ts)); } // --------------------------- static PSECURITY_DESCRIPTOR GetObjectSecurityDescr( obj_sec_descr_tsp obj, DWORD dwAccessMaskOwner, DWORD dwAccessMaskLoggedOnUser) { PSECURITY_DESCRIPTOR psd = NULL; HANDLE hToken; GENERIC_MAPPING gm = {1, 2, 4, 8}; DWORD dwDesired = 1; BOOL fAccess = FALSE; DWORD dwGranted; PRIVILEGE_SET ps; DWORD cbPriv = sizeof (ps); PACL pAcl; ULONG cbAcl; PSID psidCurUser; obj->psidUser = obj->psidGroup = NULL; // Get the user's SID if (!ImpersonateSelf(SecurityImpersonation)) return NULL; if (!OpenThreadToken(GetCurrentThread(), TOKEN_QUERY, TRUE, &hToken)) goto GSSD_ERROR; if (!GetUserSidFromToken(hToken, &obj->psidUser)) goto GSSD_ERROR; // assumption: if either access masks are given // then the owner access mask must be given if (dwAccessMaskLoggedOnUser && !dwAccessMaskOwner) goto GSSD_ERROR; // Figure the size of an access-allowed ACL (if an // access mask is supplied there will be one ACE) cbAcl = 0; if (dwAccessMaskOwner) { cbAcl = sizeof(ACL) + sizeof(ACCESS_ALLOWED_ACE) - sizeof(DWORD) + GetLengthSid(obj->psidUser); } psidCurUser = 0; if (dwAccessMaskLoggedOnUser) { psidCurUser = InteractiveUserSid(TRUE); if (psidCurUser) { cbAcl += sizeof(ACCESS_ALLOWED_ACE) - sizeof(DWORD) + GetLengthSid(psidCurUser); } } // Allocate space for the SD and the ACL psd = malloc(SECURITY_DESCRIPTOR_MIN_LENGTH + cbAcl); if (!psd) goto GSSD_ERROR; // Add ACEs to the ACL if specified pAcl = NULL; if (dwAccessMaskOwner) { // Point to the ACL in the security descriptor pAcl = (ACL *)((BYTE *)psd + SECURITY_DESCRIPTOR_MIN_LENGTH); if (!InitializeAcl(pAcl, cbAcl, ACL_REVISION)) goto GSSD_ERROR; // Set access allowed for creator if (!AddAccessAllowedAce(pAcl, ACL_REVISION, dwAccessMaskOwner, obj->psidUser)) goto GSSD_ERROR; // Set access allowed for everyone else if (psidCurUser) { if (!AddAccessAllowedAce(pAcl, ACL_REVISION, dwAccessMaskLoggedOnUser, psidCurUser)) goto GSSD_ERROR; } } // Initialize the security descriptor etc... if (!InitializeSecurityDescriptor(psd, SECURITY_DESCRIPTOR_REVISION)) goto GSSD_ERROR; if (!SetSecurityDescriptorDacl(psd, TRUE, (dwAccessMaskOwner)?pAcl:NULL, FALSE)) goto GSSD_ERROR; if (!SetSecurityDescriptorOwner(psd, obj->psidUser, FALSE)) goto GSSD_ERROR; if (!GetGroupSidFromToken(hToken, &obj->psidGroup)) goto GSSD_ERROR; if (!SetSecurityDescriptorGroup(psd, obj->psidGroup, FALSE)) goto GSSD_ERROR; if (!AccessCheck(psd, hToken, dwDesired, &gm, &ps, &cbPriv,&dwGranted, &fAccess)) goto GSSD_ERROR; RevertToSelf(); return psd; GSSD_ERROR: if (psd) free(psd); if (obj->psidUser) free(obj->psidUser); if (obj->psidGroup) free(obj->psidGroup); RevertToSelf(); return NULL; } // ---------------------------------------- static BOOL GetGroupSidFromToken(HANDLE hToken, PSID *ppSid) { TOKEN_PRIMARY_GROUP *pGroup = NULL; PSID psidGroup = NULL; DWORD cbSid; DWORD cbRequired; if (GetTokenInformation(hToken, TokenPrimaryGroup, NULL, 0, &cbRequired)) return FALSE; if (GetLastError() != ERROR_INSUFFICIENT_BUFFER) return FALSE; pGroup = malloc(cbRequired); if (!pGroup) return FALSE; if (!GetTokenInformation(hToken, TokenPrimaryGroup, pGroup,cbRequired, &cbRequired)) goto GGSFT_ERROR; cbSid = GetLengthSid(pGroup->PrimaryGroup); psidGroup = malloc(cbSid); if (!psidGroup) goto GGSFT_ERROR; if (!CopySid(cbSid, psidGroup, pGroup->PrimaryGroup)) goto GGSFT_ERROR; *ppSid = psidGroup; psidGroup = NULL; return TRUE; GGSFT_ERROR: if (psidGroup) free(psidGroup); free(pGroup); return FALSE; } // ---------------------------------------- static BOOL GetUserSidFromToken(HANDLE hToken, PSID *ppSid) { TOKEN_USER *pUser = NULL; PSID psidUser = NULL; DWORD cbSid; DWORD cbRequired; if (GetTokenInformation(hToken, TokenUser, NULL, 0, &cbRequired)) return FALSE; if (GetLastError() != ERROR_INSUFFICIENT_BUFFER ) return FALSE; pUser = malloc(cbRequired); if (!pUser) return FALSE; if (!GetTokenInformation(hToken, TokenUser, pUser, cbRequired,&cbRequired)) goto GUSFT_ERROR; cbSid = GetLengthSid(pUser->User.Sid); psidUser = malloc(cbSid); if (!psidUser) goto GUSFT_ERROR; if (!CopySid(cbSid, psidUser, pUser->User.Sid)) goto GUSFT_ERROR; *ppSid = psidUser; psidUser = NULL; return TRUE; GUSFT_ERROR: if (psidUser) free(psidUser); free(pUser); return FALSE; } PSID EveryoneSid(BOOL fFetch) { static PSID psidEverybody = 0; SID_IDENTIFIER_AUTHORITY siaEverybody = SECURITY_WORLD_SID_AUTHORITY; BOOL fRv = FALSE; if (!fFetch) { if (psidEverybody) { FreeSid(psidEverybody); psidEverybody = 0; } return 0; } if (!psidEverybody) { if (!AllocateAndInitializeSid( &siaEverybody, 1, SECURITY_WORLD_RID, 0, 0, 0, 0, 0, 0, 0, &psidEverybody )) { psidEverybody = 0; } } return psidEverybody; } PSID AdminSid(BOOL fFetch) { static PSID psidAdmin = 0; SID_IDENTIFIER_AUTHORITY siaNtAuthority = SECURITY_NT_AUTHORITY; BOOL fRv = FALSE; if (!fFetch) { if (psidAdmin) { FreeSid(psidAdmin); psidAdmin = 0; } return 0; } if (!psidAdmin) { if (!AllocateAndInitializeSid(&siaNtAuthority, 2, SECURITY_BUILTIN_DOMAIN_RID, DOMAIN_ALIAS_RID_ADMINS, 0, 0, 0, 0, 0, 0, &psidAdmin)) { psidAdmin = 0; } } return psidAdmin; } PSID InteractiveUserSid(BOOL fFetch) { static PSID psidInteractiveUser = 0; SID_IDENTIFIER_AUTHORITY siaLocalSystem = SECURITY_NT_AUTHORITY; BOOL fRv = FALSE; if (!fFetch) { if (psidInteractiveUser) { FreeSid(psidInteractiveUser); psidInteractiveUser = 0; } return 0; } if (!psidInteractiveUser) { if (!AllocateAndInitializeSid(&siaLocalSystem, 1, SECURITY_INTERACTIVE_RID, 0, 0, 0, 0, 0, 0, 0, &psidInteractiveUser)) { psidInteractiveUser = 0; } } return psidInteractiveUser; } PSID SystemSid(BOOL fFetch) { static PSID psidSystem = 0; SID_IDENTIFIER_AUTHORITY siaLocalSystem = SECURITY_NT_AUTHORITY; BOOL fRv = FALSE; if (!fFetch) { if (psidSystem) { FreeSid(psidSystem); psidSystem = 0; } return 0; } if (!psidSystem) { if (!AllocateAndInitializeSid(&siaLocalSystem, 1, SECURITY_LOCAL_SYSTEM_RID, 0, 0, 0, 0, 0, 0, 0, &psidSystem)) { psidSystem = 0; } } return psidSystem; } void InitWellknownSids() { EveryoneSid(TRUE); AdminSid(TRUE); InteractiveUserSid(TRUE); SystemSid(TRUE); } void UninitWellknownSids() { EveryoneSid(FALSE); AdminSid(FALSE); InteractiveUserSid(FALSE); SystemSid(FALSE); }