//+------------------------------------------------------------------- // // Microsoft Windows // Copyright (C) Microsoft Corporation, 1996 - 1996. // // File: alsup.cxx // // Contents: CAccessList support functions // // Classes: // // History: 06-Nov-96 MacM Created // //-------------------------------------------------------------------- #include #pragma hdrstop #include #include #include #include #include #include #include DWORD InitializeEvents(void); //+--------------------------------------------------------------------------- // // Function: GetOrderTypeForAccessEntry // // Synopsis: Determines the "order" type of entry given the node // information // // Arguments: [pwszProperty] -- The property this entry is // associated with // [pAE] -- The entry to check // [SeInfo] -- Type of node this is supposed to // be // // Returns: The type of the node. This is a bitmask flag of the types // ACCLIST_DENIED through ACCLIST_PROP_ALLOWED // // Notes: // //---------------------------------------------------------------------------- ULONG GetOrderTypeForAccessEntry(IN PWSTR pwszProperty, IN PACTRL_ACCESS_ENTRY pAE, IN SECURITY_INFORMATION SeInfo) { ULONG Type = 0; // // First, check the simple cases (like audit or invalid) // if(FLAG_ON(SeInfo, DACL_SECURITY_INFORMATION)) { if(FLAG_ON(pAE->fAccessFlags, ACTRL_AUDIT_SUCCESS | ACTRL_AUDIT_FAILURE)) { Type = ACCLIST_AUDIT; } } else { if(!FLAG_ON(pAE->fAccessFlags, ACTRL_AUDIT_SUCCESS | ACTRL_AUDIT_FAILURE) && FLAG_ON(pAE->fAccessFlags, ACTRL_ACCESS_ALLOWED | ACTRL_ACCESS_DENIED)) { Type = ACCLIST_UNKOWN_ENTRY; } else { Type = ACCLIST_AUDIT; } } if(Type == 0) { if(pwszProperty == NULL && pAE->lpInheritProperty == NULL) { Type = pAE->fAccessFlags == ACTRL_ACCESS_DENIED ? ACCLIST_DENIED : ACCLIST_ALLOWED; } else if(pwszProperty == NULL) { Type = pAE->fAccessFlags == ACTRL_ACCESS_DENIED ? ACCLIST_OBJ_DENIED : ACCLIST_PROP_ALLOWED; } else { Type = pAE->fAccessFlags == ACTRL_ACCESS_DENIED ? ACCLIST_OBJ_DENIED : ACCLIST_OBJ_ALLOWED; } // // See if it's inherited. If it is, and we don't have a level // flag, assume it's level 1 and mark it as such // if(FLAG_ON(pAE->Inheritance, INHERITED_ACCESS_ENTRY) && !FLAG_ON(pAE->Inheritance, INHERITED_PARENT | INHERITED_GRANDPARENT)) { pAE->Inheritance |= INHERITED_PARENT; } } return(Type); } //+--------------------------------------------------------------------------- // // Function: OrderListBySid // // Synopsis: Orders an acclist_cnode list by sid. The order would be: // Everyone // Well known groups // Groups // Users // Anyone else // // Arguments: [pList] -- List of the nodes to sort // [iStart] -- Where to start in the list // [iLen] -- Number of nodes in the list // // Returns: ERROR_SUCCESS -- Success // // Notes: // //---------------------------------------------------------------------------- ULONG OrderListBySid(IN PACCLIST_CNODE pList, IN ULONG iStart, IN ULONG iLen) { DWORD dwErr = ERROR_SUCCESS; return(dwErr); } // // Local functions // //+--------------------------------------------------------------------------- // // Function: DelAcclistNode // // Synopsis: Deletes an ACCLIST_NODE that's kept in the _AccList. This is // used by the CSList // // Arguments: [IN pvNode] -- Node to delete // // Returns: VOID // //---------------------------------------------------------------------------- void DelAcclistNode(PVOID pvNode) { PACCLIST_NODE pNode = (PACCLIST_NODE)pvNode; AccFree(pNode->pAccessList); AccFree(pNode->pAuditList); AccFree(pNode->pwszProperty); AccFree(pNode); } //+--------------------------------------------------------------------------- // // Function: DelTrusteeNode // // Synopsis: Deletes an TRUSTEE_NODE that's kept in the _TrusteeList. // This is used by the CSList // // Arguments: [IN pvNode] -- Node to delete // // Returns: VOID // //---------------------------------------------------------------------------- void DelTrusteeNode(PVOID pvNode) { acDebugOut((DEB_TRACE_ACC, "IN DelTrusteeNode\n")); PTRUSTEE_NODE pNode = (PTRUSTEE_NODE)pvNode; if(FLAG_ON(pNode->fFlags,TRUSTEE_DELETE_SID)) { AccFree(pNode->pSid); } if(FLAG_ON(pNode->fFlags,TRUSTEE_DELETE_NAME)) { AccFree(pNode->pwszTrusteeName); AccFree(pNode->pwszDomainName); } else if(FLAG_ON(pNode->fFlags, TRUSTEE_DELETE_DOMAIN)) { AccFree(pNode->pwszDomainName); } AccFree(pNode); acDebugOut((DEB_TRACE_ACC, "Out DelTrusteeNode\n")); } //+--------------------------------------------------------------------------- // // Function: CompInheritProps // // Synopsis: Compare the given property name to the PIPROP_IN_BUFF stuct // // Arguments: [IN pvTrustee] -- Trustee to look for // [IN pvNode2] -- 2nd node to compare // // Returns: TRUE -- Nodes equal // FALSE -- Nodes not equal // //---------------------------------------------------------------------------- BOOL CompInheritProps(IN PVOID pvInheritProp, IN PVOID pvNode2) { BOOL fRet = FALSE; PIPROP_IN_BUFF pPIB = (PIPROP_IN_BUFF)pvNode2; if(pvInheritProp != NULL) { if(_wcsicmp((PWSTR)pvInheritProp, (PWSTR)(pPIB->pwszIProp)) == 0) { fRet = TRUE; } } return(fRet); } //+--------------------------------------------------------------------------- // // Function: CompTrustees // // Synopsis: Compare two TRUSTEE_NODES. Used by _TrusteeList. // // Arguments: [IN pvTrustee] -- Trustee to look for // [IN pvNode2] -- 2nd node to compare // // Returns: TRUE -- Nodes equal // FALSE -- Nodes not equal // //---------------------------------------------------------------------------- BOOL CompTrustees(IN PVOID pvTrustee, IN PVOID pvTrustee2) { PTRUSTEE pTrustee = (PTRUSTEE)pvTrustee; TRUSTEE_NODE TrusteeNode; BOOL Result = FALSE; memset( &TrusteeNode, 0, sizeof( TrusteeNode ) ); memcpy( &TrusteeNode.Trustee, pvTrustee2, sizeof( TRUSTEE ) ); Result = CompTrusteeToTrusteeNode(pvTrustee, &TrusteeNode); if(FLAG_ON(TrusteeNode.fFlags,TRUSTEE_DELETE_SID)) { AccFree(TrusteeNode.pSid); } if(FLAG_ON(TrusteeNode.fFlags,TRUSTEE_DELETE_NAME)) { AccFree(TrusteeNode.pwszTrusteeName); AccFree(TrusteeNode.pwszDomainName); TrusteeNode.pwszDomainName = NULL; } if(FLAG_ON(TrusteeNode.fFlags, TRUSTEE_DELETE_DOMAIN)) { AccFree(TrusteeNode.pwszDomainName); } return(Result); } //+--------------------------------------------------------------------------- // // Function: CompTrusteeToTrusteeNode // // Synopsis: Compare two trustees for equality // // Arguments: [IN pvTrustee] -- Trustee to look for // [IN pvNode2] -- 2nd node to compare // // Returns: TRUE -- Nodes equal // FALSE -- Nodes not equal // //---------------------------------------------------------------------------- BOOL CompTrusteeToTrusteeNode(IN PVOID pvTrustee, IN PVOID pvNode2) { PTRUSTEE pTrustee = (PTRUSTEE)pvTrustee; PTRUSTEE_NODE pNode2 = (PTRUSTEE_NODE)pvNode2; DWORD dwErr = ERROR_SUCCESS; BOOL fMatch = FALSE; if(pTrustee->MultipleTrusteeOperation == pNode2->Trustee.MultipleTrusteeOperation) { // // Ok, first compare the base trustee information... // if(pTrustee->TrusteeForm != pNode2->Trustee.TrusteeForm) { // // We don't have matching information, so we'll have to look // it up. // ULONG fOptions = 0; if(pTrustee->TrusteeForm == TRUSTEE_IS_NAME) { fOptions = TRUSTEE_OPT_NAME; } else { fOptions = TRUSTEE_OPT_SID; } dwErr = LookupTrusteeNodeInformation(NULL, pNode2, fOptions); } // // Now, do the comparrisons // if(dwErr == ERROR_SUCCESS) { // // Now, compare the trustees // if(pTrustee->TrusteeForm == TRUSTEE_IS_NAME) { if(_wcsicmp(pTrustee->ptstrName, pNode2->pwszTrusteeName ? pNode2->pwszTrusteeName : pNode2->Trustee.ptstrName) == 0) { fMatch = TRUE; } } else { if(pTrustee->ptstrName == NULL || (pNode2->Trustee.ptstrName == NULL && pNode2->pSid == NULL)) { fMatch = FALSE; } else { fMatch = RtlEqualSid((PSID)(pTrustee->ptstrName), (PSID)(pNode2->pSid ? pNode2->pSid : pNode2->Trustee.ptstrName)); } } } // // Now, if that worked, look for the multiple trustee case // if(fMatch == TRUE && pTrustee->MultipleTrusteeOperation == TRUSTEE_IS_IMPERSONATE) { fMatch = CompTrusteeToTrusteeNode(pTrustee->pMultipleTrustee, pNode2->pImpersonate); } } return(fMatch); } //+--------------------------------------------------------------------------- // // Function: DoPropertiesMatch // // Synopsis: Determines if 2 properties are equal. It takes into account // the possibility of a NULL property. // // Arguments: [IN pwszProp1] -- 1st property to compare // [IN pwszProp2] -- 2nd property to compare // // Returns: TRUE -- Properties are equal // FALSE -- Properties are not equal // //---------------------------------------------------------------------------- BOOL DoPropertiesMatch(IN PWSTR pwszProp1, IN PWSTR pwszProp2) { BOOL fReturn = FALSE; if(pwszProp1 == NULL || pwszProp2 == NULL) { if(pwszProp1 == pwszProp2) { fReturn = TRUE; } } else { if(_wcsicmp(pwszProp1, pwszProp2) == 0) { fReturn = TRUE; } } return(fReturn); } //+--------------------------------------------------------------------------- // // Function: CompProps // // Synopsis: Compare an ACCLIST_NODE to a property // // Arguments: [IN pvProp] -- Property string // [IN pvNode] -- Node to compare // // Returns: TRUE -- Nodes equal // FALSE -- Nodes not equal // //---------------------------------------------------------------------------- BOOL CompProps(IN PVOID pvProp, IN PVOID pvNode) { PACCLIST_NODE pAN = (PACCLIST_NODE)pvNode; return(DoPropertiesMatch((PWSTR)pvProp, pAN->pwszProperty)); } //+--------------------------------------------------------------------------- // // Function: CompGuids // // Synopsis: Compare an ACCLIST_ATOACCESS structure to a guid // // Arguments: [IN pvGuid] -- Guid // [IN pvNode] -- Node to compare // // Returns: TRUE -- Nodes equal // FALSE -- Nodes not equal // //---------------------------------------------------------------------------- BOOL CompGuids(IN PVOID pvGuid, IN PVOID pvNode) { PACCLIST_ATOACCESS pAA = (PACCLIST_ATOACCESS)pvNode; GUID *pGuid = (GUID *)pvGuid; if(pGuid == NULL && pAA->pGuid == NULL) { return(TRUE); } else if(pGuid == NULL || pAA->pGuid == NULL) { return(FALSE); } return((BOOL)!memcmp(pGuid, pAA->pGuid, sizeof(GUID))); } //+--------------------------------------------------------------------------- // // Function: LookupTrusteeNodeInformation // // Synopsis: Looks up the appropriate trustee information. This involves // either looking up the trustees sid or name, depending on // the options // // Arguments: [pwszServer] -- Name of server to lookup information on // [pTrusteeNode] -- Trustee to lookup the information // for // [fOptions] -- What information to lookup // // Returns: ERROR_SUCCESS -- Success // // Notes: // //---------------------------------------------------------------------------- DWORD LookupTrusteeNodeInformation(IN PWSTR pwszServer, IN PTRUSTEE_NODE pTrusteeNode, IN ULONG fOptions) { DWORD dwErr = ERROR_SUCCESS; SID_NAME_USE SidType = SidTypeUnknown; // // Need to make sure we have the SID // if(FLAG_ON(fOptions, TRUSTEE_OPT_SID)) { // // Make sure we have the sids // if(pTrusteeNode->pSid == NULL) { dwErr = AccctrlLookupSid(pwszServer, pTrusteeNode->Trustee.ptstrName, TRUE, &(pTrusteeNode->pSid), &SidType); if(dwErr == ERROR_SUCCESS) { pTrusteeNode->fFlags |= TRUSTEE_DELETE_SID; } } } // // Ok, we need to have the name // if(dwErr == ERROR_SUCCESS && FLAG_ON(fOptions, TRUSTEE_OPT_NAME)) { // // Make sure we have the name // if(pTrusteeNode->pwszTrusteeName == NULL) { dwErr = AccctrlLookupName(pwszServer, pTrusteeNode->pSid, TRUE, &(pTrusteeNode->pwszTrusteeName), &SidType); if(dwErr == ERROR_SUCCESS) { pTrusteeNode->fFlags |= TRUSTEE_DELETE_NAME; } } } // // Then, take care of our sid type // if(dwErr == ERROR_SUCCESS && pTrusteeNode->SidType == SidTypeUnknown) { pTrusteeNode->SidType = SidType; if(SidType == SidTypeUnknown) { pTrusteeNode->Trustee.TrusteeType = TRUSTEE_IS_UNKNOWN; } else { pTrusteeNode->Trustee.TrusteeType = (TRUSTEE_TYPE)(SidType); } } return(dwErr); } //+--------------------------------------------------------------------------- // // Function: GetATypeForEntry // // Synopsis: Determines the type of entry given the node information // // Arguments: [pwszProperty] -- The property this entry is // associated with // [pAE] -- The entry to check // [SeInfo] -- Type of node this is supposed to // be // // Returns: The type of the node // // Notes: // //---------------------------------------------------------------------------- ACC_ACLBLD_TYPE GetATypeForEntry(IN PWSTR pwszProperty, IN PACTRL_ACCESS_ENTRY pAE, IN SECURITY_INFORMATION SeInfo) { ACC_ACLBLD_TYPE AType = AAT_DENIED; // // First, check the simple cases (like audit or invalid) // if(FLAG_ON(SeInfo, DACL_SECURITY_INFORMATION)) { if(FLAG_ON(pAE->fAccessFlags, ACTRL_AUDIT_SUCCESS | ACTRL_AUDIT_FAILURE)) { AType = AAT_INVALID; } } else { if(!FLAG_ON(pAE->fAccessFlags, ACTRL_AUDIT_SUCCESS | ACTRL_AUDIT_FAILURE) && FLAG_ON(pAE->fAccessFlags, ACTRL_ACCESS_ALLOWED | ACTRL_ACCESS_DENIED)) { AType = AAT_INVALID; } else { AType = AAT_AUDIT; } } if(AType == 0) { if(pwszProperty == NULL && pAE->lpInheritProperty == NULL) { AType = pAE->fAccessFlags == ACTRL_ACCESS_DENIED ? AAT_DENIED : AAT_ALLOWED; } else if(pwszProperty == NULL) { AType = pAE->fAccessFlags == ACTRL_ACCESS_DENIED ? AAT_OBJ_DENIED : AAT_PROP_ALLOWED; } else { AType = pAE->fAccessFlags == ACTRL_ACCESS_DENIED ? AAT_OBJ_DENIED : AAT_OBJ_ALLOWED; } // // See if it's inherited // if(FLAG_ON(pAE->Inheritance, INHERITED_ACCESS_ENTRY)) { AType =(ACC_ACLBLD_TYPE) ((ULONG)AType + ((ULONG)AAT_IDENIED - (ULONG)AAT_DENIED)); } } return(AType); } //+--------------------------------------------------------------------------- // // Function: CNodeCompare // // Synopsis: Used by CSList class. Used to determine if 2 acclist_cnodes are // identical, based upon the property // // Arguments: [pv1] -- 1st node // [pv2] -- 2nd node // // Returns: 0 on equality // non-0 otherwise // // Notes: // //---------------------------------------------------------------------------- int __cdecl CNodeCompare(const void *pv1, const void *pv2) { PACCLIST_CNODE pCN1 = (PACCLIST_CNODE)pv1; PACCLIST_CNODE pCN2 = (PACCLIST_CNODE)pv2; if(pCN1->pONode->pwszProperty == NULL) { return(-1); } if(pCN2->pONode->pwszProperty == NULL) { return(1); } return(_wcsicmp(pCN1->pONode->pwszProperty, pCN2->pONode->pwszProperty)); } //+--------------------------------------------------------------------------- // // Function: CompAndMarkCompressNode // // Synopsis: Used by CSList class. Used to determine if 2 nodes can be // compressed into one. If so, the first node has its access // flag marked with a bit signifying it can be compressed. See // below for the definition of what it means to be compressible // // Arguments: [pvAE] -- New node // [pvNode] -- Node already existing in list // // Returns: 0 on equality // non-0 otherwise // // Notes: // //---------------------------------------------------------------------------- BOOL CompAndMarkCompressNode(IN PVOID pvAE, IN PVOID pvNode) { PACTRL_ACCESS_ENTRY pAE1 = (PACTRL_ACCESS_ENTRY)pvAE; PACTRL_ACCESS_ENTRY pAE2 = (PACTRL_ACCESS_ENTRY)pvNode; // // We will consider nodes identical iff: // They match trustee, inheritance, and access flags exactly and the // inherit property or (along with the rest of the above): // - Both nodes are inherited and one is marked l1 inherited and the // other is not marked at all, or neither node is inherited // and the inheritance is identical or the inheritance is different // but the access masks are the same // - fAccessFlags indicates that combining this 2 nodes will still // yield an audit node. // if(CompTrustees(&pAE1->Trustee,&pAE2->Trustee) == TRUE && // // Check the inheritance // (pAE1->Inheritance == pAE2->Inheritance || (pAE1->Inheritance & ~INHERITED_PARENT) == (pAE2->Inheritance & ~INHERITED_PARENT) || (!FLAG_ON(pAE1->Inheritance, INHERITED_ACCESS_ENTRY) && !FLAG_ON(pAE2->Inheritance, INHERITED_ACCESS_ENTRY)&& (pAE1->Inheritance != 0 && pAE2->Inheritance != 0) && (pAE1->Access) == pAE2->Access)) && // // Check the access // (((pAE1->fAccessFlags & ~(ACCLIST_COMPRESS | ~ACCLIST_VALID_TYPE_FLAGS)) == ( pAE2->fAccessFlags & ~~ACCLIST_VALID_TYPE_FLAGS ) || (((((pAE1->fAccessFlags & ~(ACCLIST_COMPRESS | ~ACCLIST_VALID_TYPE_FLAGS)) | (pAE2->fAccessFlags & ~~ACCLIST_VALID_TYPE_FLAGS)) & ~(ACTRL_AUDIT_SUCCESS | ACTRL_AUDIT_FAILURE)) == 0))) && pAE1->Access == pAE2->Access) && // // Check the properties // DoPropertiesMatch(pAE1->lpInheritProperty, pAE2->lpInheritProperty) == TRUE) { pAE1->fAccessFlags |= ACCLIST_COMPRESS; return(TRUE); } return(FALSE); } //+--------------------------------------------------------------------------- // // Function: GetNodeForProperty // // Synopsis: This function will lookup the existing list node for the given // property. If the node doesn't exist, it will be created and // inserted into the list // // Arguments: [List] -- List to examine // [pwszProperty] -- The property to look for // [ppNode] -- Where the found or inserted node is // returned // // Returns: ERROR_SUCCESS -- Success // ERROR_NOT_ENOUGH_MEMORY A memory allocation failed // // Notes: // //---------------------------------------------------------------------------- DWORD GetNodeForProperty(CSList& List, PWSTR pwszProperty, PACCLIST_NODE *ppNode) { DWORD dwErr = ERROR_SUCCESS; PACCLIST_NODE pAccNode = (PACCLIST_NODE)List.Find(pwszProperty, CompProps); if(pAccNode == NULL) { // // Doesn't exist. We'll have to add it... // pAccNode = (PACCLIST_NODE)AccAlloc(sizeof(ACCLIST_NODE)); if(pAccNode == NULL) { dwErr = ERROR_NOT_ENOUGH_MEMORY; } else { if(pwszProperty != NULL) { ACC_ALLOC_AND_COPY_STRINGW(pwszProperty, pAccNode->pwszProperty, dwErr); } if(dwErr == ERROR_SUCCESS) { dwErr = List.Insert((PVOID)pAccNode); if(dwErr != ERROR_SUCCESS) { AccFree(pAccNode->pwszProperty); AccFree(pAccNode); } } else { AccFree(pAccNode); pAccNode = 0; } } } *ppNode = pAccNode; return(dwErr); } VOID FreeAToAccessStruct(PVOID pv) { ((PACCLIST_ATOACCESS)pv)->AceList.FreeList((FreeFunc)AccFree); AccFree(pv); } //+--------------------------------------------------------------------------- // // Function: GetNodeForGuid // // Synopsis: Finds the node in the given list based upon the guid. If the // node doesn't exist, it is inserted // // Arguments: [List] -- List to examine // [pGuid] -- The guid to look for // [ppNode] -- Where the found or inserted node is // returned // // Returns: ERROR_SUCCESS -- Success // ERROR_NOT_ENOUGH_MEMORY A memory allocation failed // // Notes: // //---------------------------------------------------------------------------- DWORD GetNodeForGuid(CSList& List, GUID *pGuid, PACCLIST_ATOACCESS *ppNode) { DWORD dwErr = ERROR_SUCCESS; List.Init((FreeFunc)FreeAToAccessStruct); PACCLIST_ATOACCESS pNode = (PACCLIST_ATOACCESS)List.Find(pGuid, CompGuids); if(pNode == NULL) { // // Doesn't exist. We'll have to add it... // pNode = (PACCLIST_ATOACCESS)AccAlloc(sizeof(ACCLIST_ATOACCESS)); if(pNode == NULL) { dwErr = ERROR_NOT_ENOUGH_MEMORY; } else { pNode->AceList.Init((FreeFunc)AccFree); if(pGuid != NULL) { pNode->pGuid = (GUID *)AccAlloc(sizeof(GUID)); if(pNode->pGuid == NULL) { dwErr = ERROR_NOT_ENOUGH_MEMORY; AccFree(pNode); pNode = 0; } else { memcpy(pNode->pGuid, pGuid, sizeof(GUID)); } } if(dwErr == ERROR_SUCCESS) { dwErr = List.Insert((PVOID)pNode); if(dwErr != ERROR_SUCCESS) { AccFree(pNode->pGuid); AccFree(pNode); } } } } *ppNode = pNode; return(dwErr); } //+--------------------------------------------------------------------------- // // Function: InsertAtoANode // // Synopsis: Inserts an access to ace node into the list. // // Arguments: [List] -- List to insert in // [pProperty] -- Property to match // [pAce] -- Ace to be inserted // [fInherit] -- Inheritance flags // // Returns: ERROR_SUCCESS -- Success // ERROR_NOT_ENOUGH_MEMORY A memory allocation failed // // Notes: // //---------------------------------------------------------------------------- DWORD InsertAtoANode(CSList& List, GUID *pProperty, PACE_HEADER pAce, ULONG fInherit) { DWORD dwErr = ERROR_SUCCESS; PACCLIST_ATOANODE pAANode = (PACCLIST_ATOANODE)AccAlloc(sizeof(ACCLIST_ATOANODE)); if(pAANode == NULL) { dwErr = ERROR_NOT_ENOUGH_MEMORY; } else { pAANode->pAce = pAce; pAANode->fInherit = fInherit; PACCLIST_ATOACCESS pParent; dwErr = GetNodeForGuid(List, pProperty, &pParent); if(dwErr == ERROR_SUCCESS) { dwErr = pParent->AceList.Insert((PVOID)pAANode); } if(dwErr != ERROR_SUCCESS) { AccFree(pAANode); } } return(dwErr); } //+--------------------------------------------------------------------------- // // Function: AceToAccessEntry // // Synopsis: Converts an ACE into an access entry // // Arguments: [pAce] -- Ace to convert // [fInheritLevel] -- What inheritance level (effective, // parent inherit, etc) are we at // [ObjType] -- Type of object we're dealing with // [pAE] -- Already existing access entry to // initialize // // Returns: ERROR_SUCCESS -- Success // ERROR_INVALID_ACL -- A bad ace type was encountered // // Notes: // //---------------------------------------------------------------------------- DWORD AceToAccessEntry(PACE_HEADER pAce, ULONG fInheritLevel, SE_OBJECT_TYPE ObjType, IN MARTA_KERNEL_TYPE KernelObjectType, PACTRL_ACCESS_ENTRY pAE) { DWORD dwErr = ERROR_SUCCESS; // // Go ahead and initialize the node // BOOL fIsImpersonate = FALSE; BOOL fIsExtendedAce = FALSE; // // Ok, now lets try to figure out what type of ACE this is, so we can // do the neccessary mapping into the provider rights // switch(pAce->AceType) { case ACCESS_ALLOWED_ACE_TYPE: pAE->fAccessFlags = ACTRL_ACCESS_ALLOWED; break; case ACCESS_ALLOWED_OBJECT_ACE_TYPE: pAE->fAccessFlags = ACTRL_ACCESS_ALLOWED; fIsExtendedAce = TRUE; break; // // Currently unsupported // case ACCESS_ALLOWED_COMPOUND_ACE_TYPE: pAE->fAccessFlags = ACTRL_ACCESS_ALLOWED; fIsImpersonate = TRUE; dwErr = ERROR_INVALID_ACL; break; case ACCESS_DENIED_ACE_TYPE: pAE->fAccessFlags = ACTRL_ACCESS_DENIED; break; case ACCESS_DENIED_OBJECT_ACE_TYPE: pAE->fAccessFlags = ACTRL_ACCESS_DENIED; fIsExtendedAce = TRUE; break; case SYSTEM_AUDIT_OBJECT_ACE_TYPE: pAE->fAccessFlags = 0; if(FLAG_ON(pAce->AceFlags,SUCCESSFUL_ACCESS_ACE_FLAG)) { pAE->fAccessFlags |= ACTRL_AUDIT_SUCCESS; } if(FLAG_ON(pAce->AceFlags,FAILED_ACCESS_ACE_FLAG)) { pAE->fAccessFlags |= ACTRL_AUDIT_FAILURE; } fIsExtendedAce = TRUE; break; case SYSTEM_AUDIT_ACE_TYPE: pAE->fAccessFlags = 0; if(FLAG_ON(pAce->AceFlags,SUCCESSFUL_ACCESS_ACE_FLAG)) { pAE->fAccessFlags |= ACTRL_AUDIT_SUCCESS; } if(FLAG_ON(pAce->AceFlags,FAILED_ACCESS_ACE_FLAG)) { pAE->fAccessFlags |= ACTRL_AUDIT_FAILURE; } break; default: dwErr = ERROR_INVALID_ACL; break; } if(dwErr == ERROR_SUCCESS) { // // Pull what we can from the ace header // pAE->Inheritance = (INHERIT_FLAGS)( pAce->AceFlags & VALID_INHERIT_FLAGS ); pAE->Inheritance |= fInheritLevel; PSID pSid = NULL; ACCESS_MASK AccessMask = 0; if(fIsImpersonate == FALSE) { if(fIsExtendedAce == TRUE) { pSid = RtlObjectAceSid(pAce); AccessMask = ((PKNOWN_OBJECT_ACE)pAce)->Mask; } else { pSid = &((PKNOWN_ACE)pAce)->SidStart; AccessMask = ((PKNOWN_ACE)pAce)->Mask; } } else { if(fIsExtendedAce == TRUE) { dwErr = ERROR_INVALID_ACL; } else { pSid = (PSID)Add2Ptr(&((PCOMPOUND_ACCESS_ALLOWED_ACE)pAce)->SidStart, RtlLengthSid(&((PCOMPOUND_ACCESS_ALLOWED_ACE)pAce)->SidStart)); AccessMask = ((PCOMPOUND_ACCESS_ALLOWED_ACE)pAce)->Mask; } } // // Build the trustee // pAE->Trustee.pMultipleTrustee = NULL; pAE->Trustee.MultipleTrusteeOperation = NO_MULTIPLE_TRUSTEE; pAE->Trustee.TrusteeForm = TRUSTEE_IS_SID; pAE->Trustee.TrusteeType = TRUSTEE_IS_UNKNOWN; pAE->Trustee.ptstrName = (LPWSTR)pSid; // // Convert our access // AccConvertAccessMaskToActrlAccess(AccessMask, ObjType, KernelObjectType, pAE); // // Deal with the inheritance property... // if(fIsExtendedAce == TRUE) { PACCESS_ALLOWED_OBJECT_ACE pExAce = (PACCESS_ALLOWED_OBJECT_ACE)pAce; if(FLAG_ON(pExAce->Flags, ACE_INHERITED_OBJECT_TYPE_PRESENT)) { PWSTR StrUuid; dwErr = UuidToString(RtlObjectAceInheritedObjectType(pAce), &StrUuid ); // // The calling functions expect a buffer allocated with AccAlloc // if(dwErr == ERROR_SUCCESS) { ACC_ALLOC_AND_COPY_STRINGW(StrUuid, (PWSTR)pAE->lpInheritProperty, dwErr); RpcStringFree(&StrUuid); } } } else { pAE->lpInheritProperty = NULL; } } if(dwErr != ERROR_SUCCESS) { if(pAE->lpInheritProperty != NULL) { AccFree((PWSTR)pAE->lpInheritProperty); } } return(dwErr); } //+--------------------------------------------------------------------------- // // Function: ConvertToAutoInheritSD // // Synopsis: Determines the inheritance necessary for the current security // descriptor given the parent security descriptor // // Arguments: [IN pCurrentSD] -- The security descriptor to // update // [IN pParentSD] -- The parent security descriptor // [IN fIsContainer] -- Does the Sec. Desc. refer to // a container? // [IN pGenericMapping] -- Generic mapping to apply // [OUT ppNewSD] -- Where the new SD is returned // // Returns: ERROR_SUCCESS -- Success // // Notes: The returned security descriptor must be freed via a call to // DestroyPrivateObjectSecurity // //---------------------------------------------------------------------------- DWORD ConvertToAutoInheritSD(IN PSECURITY_DESCRIPTOR pParentSD, IN PSECURITY_DESCRIPTOR pCurrentSD, IN BOOL fIsContainer, IN PGENERIC_MAPPING pGenericMapping, OUT PSECURITY_DESCRIPTOR *ppNewSD) { DWORD dwErr = ERROR_SUCCESS; SECURITY_DESCRIPTOR_CONTROL OldControl; // // Turn off the inherited bits, so we can always do the // necessary inheritance checks. This is because we don't know if some // downlevel process came in and messed with one of our security // descriptors, and left is in a hosed state // OldControl = ((SECURITY_DESCRIPTOR *)pCurrentSD)->Control; ((SECURITY_DESCRIPTOR *)pCurrentSD)->Control &= ~(SE_DACL_AUTO_INHERITED | SE_SACL_AUTO_INHERITED); #ifdef DBG if(pParentSD != NULL) { ASSERT(IsValidSecurityDescriptor(pParentSD)); DebugDumpSD("CTAIPOS ParentSD", pParentSD); } ASSERT(IsValidSecurityDescriptor(pCurrentSD)); DebugDumpSD("CTAIPOS CurrentSD", pCurrentSD); #endif if(ConvertToAutoInheritPrivateObjectSecurity(pParentSD, pCurrentSD, ppNewSD, NULL, fIsContainer != 0, pGenericMapping) == FALSE) { dwErr = GetLastError(); } #ifdef DBG else { ASSERT(IsValidSecurityDescriptor(*ppNewSD)); DebugDumpSD("CTAIPOS NewSD", *ppNewSD); } #endif ((SECURITY_DESCRIPTOR *)pCurrentSD)->Control = OldControl; return(dwErr); } //+--------------------------------------------------------------------------- // // Function: MakeSDAbsolute // // Synopsis: Allocates a new security descriptor and makes an absolute copy // of the supplied SD // // Arguments: [IN pOriginalSD] -- The security descriptor to // convert // [IN SeInfo] -- SD components to care about // [IN *ppNewSD] -- Where the new SD is returned // [IN pOwnerToAdd] -- OPTIONAL. Owner SID to add to // absolute SD. // [IN pGroupToAdd] -- OPTIONAL. Group SID to add to // absolute SD. // // Returns: ERROR_SUCCESS -- Success // ERROR_NOT_ENOUGH_MEMORY -- A memory allocation falied // // Notes: The returned security descriptor must be freed via a call to // AccFree // //---------------------------------------------------------------------------- DWORD MakeSDAbsolute(IN PSECURITY_DESCRIPTOR pOriginalSD, IN SECURITY_INFORMATION SeInfo, OUT PSECURITY_DESCRIPTOR *ppNewSD, IN PSID pOwnerToAdd, IN PSID pGroupToAdd) { DWORD dwErr = ERROR_SUCCESS; BOOL fDAclPresent = FALSE; BOOL fSAclPresent = FALSE; BOOL fDAclDef = FALSE, fSAclDef = FALSE; BOOL fOwnerDef = FALSE, fGroupDef = FALSE; PACL pDAcl = NULL, pSAcl = NULL; PSID pOwner = NULL, pGroup = NULL; ULONG cSize = 0; // // First, get the info out of the current SD // if(FLAG_ON(SeInfo, DACL_SECURITY_INFORMATION)) { if(GetSecurityDescriptorDacl(pOriginalSD, &fDAclPresent, &pDAcl, &fDAclDef) == FALSE) { dwErr = GetLastError(); } else { if(pDAcl != NULL) { cSize += pDAcl->AclSize; } } } if(dwErr == ERROR_SUCCESS && FLAG_ON(SeInfo, SACL_SECURITY_INFORMATION)) { if(GetSecurityDescriptorSacl(pOriginalSD, &fSAclPresent, &pSAcl, &fSAclDef) == FALSE) { dwErr = GetLastError(); } else { if(pSAcl != NULL) { cSize += pSAcl->AclSize; } } } if(pOwnerToAdd != NULL) { pOwner = pOwnerToAdd; } else { if(dwErr == ERROR_SUCCESS && FLAG_ON(SeInfo, OWNER_SECURITY_INFORMATION)) { if(GetSecurityDescriptorOwner(pOriginalSD, &pOwner, &fOwnerDef) == FALSE) { dwErr = GetLastError(); } } } if(pGroupToAdd != NULL) { pGroup = pGroupToAdd; } else { if(dwErr == ERROR_SUCCESS && FLAG_ON(SeInfo, GROUP_SECURITY_INFORMATION)) { if(GetSecurityDescriptorGroup(pOriginalSD, &pGroup, &fGroupDef) == FALSE) { dwErr = GetLastError(); } } } if(pOwner != NULL) { cSize += RtlLengthSid(pOwner); } if(pGroup != NULL) { cSize += RtlLengthSid(pGroup); } if(dwErr == ERROR_SUCCESS) { // // Allocate the buffer... // PBYTE pBuff = (PBYTE)AccAlloc(cSize + sizeof(SECURITY_DESCRIPTOR)); if(pBuff == NULL) { dwErr = ERROR_NOT_ENOUGH_MEMORY; } else { // // Start copying in the existing items... // DWORD cLen; PBYTE pbEndOBuf = pBuff + cSize + sizeof(SECURITY_DESCRIPTOR); if(pOwner != NULL) { cLen = RtlLengthSid(pOwner); pbEndOBuf -= cLen; RtlCopyMemory(pbEndOBuf, pOwner, cLen); pOwner = (PSID)pbEndOBuf; } if(pGroup != NULL) { cLen = RtlLengthSid(pGroup); pbEndOBuf -= cLen; RtlCopyMemory(pbEndOBuf, pGroup, cLen); pGroup = (PSID)pbEndOBuf; } if(pDAcl != NULL) { pbEndOBuf -= pDAcl->AclSize; RtlCopyMemory(pbEndOBuf, pDAcl, pDAcl->AclSize); pDAcl = (PACL)pbEndOBuf; } if(pSAcl != NULL) { pbEndOBuf -= pSAcl->AclSize; RtlCopyMemory(pbEndOBuf, pSAcl, pSAcl->AclSize); pSAcl = (PACL)pbEndOBuf; } // // Ok, now build it... // *ppNewSD = (PSECURITY_DESCRIPTOR)pBuff; if(InitializeSecurityDescriptor(*ppNewSD, SECURITY_DESCRIPTOR_REVISION) == FALSE) { dwErr = GetLastError(); } if(dwErr == ERROR_SUCCESS && fDAclPresent == TRUE) { if(SetSecurityDescriptorDacl(*ppNewSD, TRUE, pDAcl, fDAclDef) == FALSE) { dwErr = GetLastError(); } } if(dwErr == ERROR_SUCCESS && fSAclPresent == TRUE) { if(SetSecurityDescriptorSacl(*ppNewSD, TRUE, pSAcl, fSAclDef) == FALSE) { dwErr = GetLastError(); } } if(dwErr == ERROR_SUCCESS && pOwner != NULL) { if(SetSecurityDescriptorOwner(*ppNewSD, pOwner, fOwnerDef) == FALSE) { dwErr = GetLastError(); } } if(dwErr == ERROR_SUCCESS && pGroup != NULL) { if(SetSecurityDescriptorGroup(*ppNewSD, pGroup, fGroupDef) == FALSE) { dwErr = GetLastError(); } } // // Set the new control bits to look like the old ones (minus the selfrel flag, of // course... // if(dwErr == ERROR_SUCCESS) { RtlpPropagateControlBits((PISECURITY_DESCRIPTOR)*ppNewSD, (PISECURITY_DESCRIPTOR)pOriginalSD, ~SE_SELF_RELATIVE ); } if(dwErr != ERROR_SUCCESS) { AccFree(*ppNewSD); *ppNewSD = NULL; } } } return(dwErr); } //+--------------------------------------------------------------------------- // // Function: EqualSecurityDescriptors // // Synopsis: Determines if 2 security descriptors are identical. It does // this by comparing control fields, owner/group, and sids. // // Arguments: [IN pSD1] -- 1st SD to compare // [IN pSD2] -- 2nd SD to compare // // Returns: TRUE -- They are identical // FALSE -- They are not identical // // //---------------------------------------------------------------------------- BOOL EqualSecurityDescriptors(IN PSECURITY_DESCRIPTOR pSD1, IN PSECURITY_DESCRIPTOR pSD2) { BOOL fRet = TRUE; SECURITY_DESCRIPTOR *pS1 = (SECURITY_DESCRIPTOR *)pSD1; SECURITY_DESCRIPTOR *pS2 = (SECURITY_DESCRIPTOR *)pSD2; if(pS1->Control != pS2->Control) { return(FALSE); } PACL pA1, pA2; // // Dacl // pA1 = RtlpDaclAddrSecurityDescriptor(pS1); pA2 = RtlpDaclAddrSecurityDescriptor(pS2); if((pA1 == NULL && pA2 != NULL) || (pA2 == NULL && pA1 != NULL)) { return(FALSE); } if(pA1 != NULL) { if(!(pA1->AclSize == pA2->AclSize && memcmp(pA1, pA2, pA1->AclSize))) { return(FALSE); } } // // Sacl // pA1 = RtlpSaclAddrSecurityDescriptor(pS1); pA2 = RtlpSaclAddrSecurityDescriptor(pS2); if((pA1 == NULL && pA2 != NULL) || (pA2 == NULL && pA1 != NULL)) { return(FALSE); } if(pA1 != NULL) { if(!(pA1->AclSize == pA2->AclSize && memcmp(pA1, pA2, pA1->AclSize))) { return(FALSE); } } // // Group // PSID pSid1, pSid2; pSid1 = RtlpGroupAddrSecurityDescriptor(pS1); pSid2 = RtlpGroupAddrSecurityDescriptor(pS2); if((pSid1 == NULL && pSid2 != NULL) || (pSid2 == NULL && pSid1 != NULL)) { return(FALSE); } if(pSid1 != NULL) { if(!RtlEqualSid(pSid1, pSid2)) { return(FALSE); } } // // Owner // pSid1 = RtlpOwnerAddrSecurityDescriptor(pS1); pSid2 = RtlpOwnerAddrSecurityDescriptor(pS2); if((pSid1 == NULL && pSid2 != NULL) || (pSid2 == NULL && pSid1 != NULL)) { return(FALSE); } if(pSid1 != NULL) { if(!RtlEqualSid(pSid1, pSid2)) { return(FALSE); } } acDebugOut((DEB_TRACE, "Nodes 0x%lx and 0x%lx are equal!\n", pSD1, pSD2)); #ifdef DBG DebugDumpSD("SD1", pSD1); DebugDumpSD("SD2", pSD2); #endif return(TRUE); } //+--------------------------------------------------------------------------- // // Function: InsertPropagationFailureEntry // // Synopsis: Adds a propagation failure entry to the list of items // to be written to the event log // // Arguments: [IN LogList] -- Reference to the log list // [IN ErrorCode] -- Error of propagation // [IN Protected] -- Flags determining whether the dacl // or sacl was protected // [IN pwszPath] -- Path that expierneced the error // // Returns: ERROR_SUCCESS -- Success // ERROR_NOT_ENOUGH_MEMORY -- A memory allocation failed // // //---------------------------------------------------------------------------- DWORD InsertPropagationFailureEntry( IN CSList& LogList, IN ULONG ErrorCode, IN ULONG Protected, IN PWSTR pwszPath) { DWORD dwErr = ERROR_SUCCESS; PACCESS_PROP_LOG_ENTRY pEntry = NULL; pEntry = (PACCESS_PROP_LOG_ENTRY)AccAlloc(sizeof(ACCESS_PROP_LOG_ENTRY)); if(pEntry == NULL) { dwErr = ERROR_NOT_ENOUGH_MEMORY; } else { ACC_ALLOC_AND_COPY_STRINGW(pwszPath, pEntry->pwszPath, dwErr ); if(pwszPath == NULL) { AccFree(pEntry); dwErr = ERROR_NOT_ENOUGH_MEMORY; } else { pEntry->Protected = Protected; pEntry->Error = ErrorCode; dwErr = LogList.Insert(pEntry); if(dwErr != ERROR_SUCCESS) { FreePropagationFailureListEntry(pEntry); } } } return(dwErr); } //+--------------------------------------------------------------------------- // // Function: FreePropagationFailureListEntry // // Synopsis: Frees the propagation failure list // // Arguments: [IN LogList] -- Reference to the log list // // Returns: VOID // // //---------------------------------------------------------------------------- VOID FreePropagationFailureListEntry(IN PVOID Entry) { PACCESS_PROP_LOG_ENTRY pLogEntry = (PACCESS_PROP_LOG_ENTRY)Entry; AccFree(pLogEntry->pwszPath); AccFree(pLogEntry); } //+--------------------------------------------------------------------------- // // Function: WritePropagationFailureList // // Synopsis: Logs the propagation failures to the event log // // Arguments: [IN EventType] -- Type of event to log: // registry or filesystem // [IN LogList] -- Reference to the log list // [IN hToken] -- Current process/thread token // // Returns: ERROR_SUCCESS -- Success // ERROR_NOT_ENOUGH_MEMORY -- A memory allocation failed // //---------------------------------------------------------------------------- DWORD WritePropagationFailureList(IN ULONG EventType, IN CSList& LogList, IN HANDLE hToken) { DWORD dwErr = ERROR_SUCCESS; HANDLE hEventlog = NULL; TOKEN_USER *UserInfo; ULONG InfoSize, StrCount, i; PSID pSid = NULL; BYTE Buffer[ 7 * sizeof( ULONG ) + sizeof( TOKEN_USER ) ], *pBuff = NULL; WCHAR ErrorNumberBuffer[25]; WCHAR wszErrorBuffer[ 256]; PWSTR pwszStringBuffer = NULL, pwszCurrent; PACCESS_PROP_LOG_ENTRY pLogEntry; ULONG ProtectedValue; if(LogList.QueryCount() == 0) { return(dwErr); } // // Get the user sid // if(GetTokenInformation(hToken, TokenUser, (PVOID)&Buffer, sizeof(Buffer), &InfoSize ) == FALSE ) { dwErr = GetLastError(); if(dwErr == ERROR_INSUFFICIENT_BUFFER) { pBuff = (PBYTE)AccAlloc( InfoSize ); if(pBuff == NULL) { dwErr = ERROR_NOT_ENOUGH_MEMORY; } else { if(GetTokenInformation(hToken, TokenUser, (PVOID)pBuff, InfoSize, &InfoSize ) == FALSE ) { dwErr = GetLastError(); } else { dwErr = ERROR_SUCCESS; } } } } else { pBuff = Buffer; } if(dwErr == ERROR_SUCCESS) { UserInfo = ( PTOKEN_USER )pBuff; pSid = UserInfo->User.Sid; } // // Build the list of paths and associated error codes // The format of the buffer is [tab][path] [error][cr/lf] // if(dwErr == ERROR_SUCCESS) { InfoSize = 1; LogList.Reset(); pLogEntry = (PACCESS_PROP_LOG_ENTRY)LogList.NextData(); for(; pLogEntry;) { InfoSize += 1 + wcslen( pLogEntry->pwszPath ) + 5; // // Determine the size of the buffer for the error message // if(pLogEntry->Protected) { switch(pLogEntry->Protected & (SE_DACL_PROTECTED | SE_SACL_PROTECTED)) { case SE_DACL_PROTECTED | SE_SACL_PROTECTED: ProtectedValue = ACCPROV_MARTA_BOTH_PROTECTED; break; case SE_DACL_PROTECTED: ProtectedValue = ACCPROV_MARTA_DACL_PROTECTED; break; case SE_SACL_PROTECTED: ProtectedValue = ACCPROV_MARTA_SACL_PROTECTED; break; default: ProtectedValue = 0; break; } if (LoadString(ghDll, ProtectedValue, wszErrorBuffer, sizeof( wszErrorBuffer ) / sizeof( WCHAR )) == 0) { dwErr = GetLastError(); break; } } else { if( FormatMessage( FORMAT_MESSAGE_FROM_SYSTEM, NULL, pLogEntry->Error, MAKELANGID(LANG_ENGLISH, SUBLANG_ENGLISH_US), wszErrorBuffer, 256, NULL ) == 0 ) { dwErr = GetLastError(); break; } } InfoSize += wcslen( wszErrorBuffer ); pLogEntry = (PACCESS_PROP_LOG_ENTRY)LogList.NextData(); } // // Now, allocate the buffer // if(dwErr == ERROR_SUCCESS) { pwszStringBuffer = (PWSTR)AccAlloc(( InfoSize + 1 ) * sizeof( WCHAR )); if(pwszStringBuffer == NULL) { dwErr = ERROR_NOT_ENOUGH_MEMORY; } else { LogList.Reset(); pwszCurrent = pwszStringBuffer; pLogEntry = (PACCESS_PROP_LOG_ENTRY)LogList.NextData(); for(; pLogEntry;) { if(pLogEntry->Protected == 0 ) { FormatMessage( FORMAT_MESSAGE_FROM_SYSTEM, NULL, pLogEntry->Error, MAKELANGID(LANG_ENGLISH, SUBLANG_ENGLISH_US), wszErrorBuffer, 256, NULL ); } else { switch( pLogEntry->Protected & (SE_DACL_PROTECTED | SE_SACL_PROTECTED)) { case SE_DACL_PROTECTED | SE_SACL_PROTECTED: ProtectedValue = ACCPROV_MARTA_BOTH_PROTECTED; break; case SE_DACL_PROTECTED: ProtectedValue = ACCPROV_MARTA_DACL_PROTECTED; break; case SE_SACL_PROTECTED: ProtectedValue = ACCPROV_MARTA_SACL_PROTECTED; break; default: ProtectedValue = 0; break; } LoadString(ghDll, ProtectedValue, wszErrorBuffer, sizeof( wszErrorBuffer ) / sizeof( WCHAR )); } InfoSize = swprintf( pwszCurrent, L"\r\n\t%ws\t\t%ws", pLogEntry->pwszPath, wszErrorBuffer ); pwszCurrent += InfoSize; pLogEntry = (PACCESS_PROP_LOG_ENTRY)LogList.NextData(); } } } } // // Write to the event log // if(dwErr == ERROR_SUCCESS) { dwErr = InitializeEvents(); if(dwErr == ERROR_SUCCESS) { hEventlog = RegisterEventSource( NULL, L"AclPropagation" ); if(hEventlog == NULL) { dwErr = GetLastError(); if(dwErr == RPC_S_UNKNOWN_IF) { acDebugOut(( DEB_ERROR, "Eventlog service not started!\n" )); dwErr = ERROR_SUCCESS; } } else { if( ReportEvent(hEventlog, EVENTLOG_INFORMATION_TYPE, CATEGORY_NTMARTA, EventType, pSid, 1, 0, (LPCTSTR *)&pwszStringBuffer, NULL ) == FALSE ) { dwErr = GetLastError(); } DeregisterEventSource(hEventlog); } } } if(pBuff != Buffer) { AccFree(pBuff); } if ((dwErr != ERROR_SUCCESS) && (pwszStringBuffer != NULL)) { AccFree(pwszStringBuffer); } return(dwErr); } //+--------------------------------------------------------------------------- // // Function: InitializeEvents // // Synopsis: Sets the registry values to enable NTMARTA to act as an event source // // Arguments: void // // Returns: ERROR_SUCCESS -- Success // //---------------------------------------------------------------------------- DWORD InitializeEvents(void) { HKEY hKey; DWORD dwErr, disp; dwErr = RegCreateKeyEx( HKEY_LOCAL_MACHINE, TEXT("System\\CurrentControlSet\\Services\\EventLog\\Application\\AclPropagation"), 0, TEXT(""), REG_OPTION_NON_VOLATILE, KEY_WRITE, NULL, &hKey, &disp); if(dwErr != ERROR_SUCCESS) { return(dwErr); } if (disp == REG_CREATED_NEW_KEY) { RegSetValueEx( hKey, TEXT("EventMessageFile"), 0, REG_EXPAND_SZ, (PBYTE) TEXT("%SystemRoot%\\system32\\ntmarta.dll"), sizeof(TEXT("%SystemRoot%\\system32\\ntmarta.dll")) ); RegSetValueEx( hKey, TEXT("CategoryMessageFile"), 0, REG_EXPAND_SZ, (PBYTE) TEXT("%SystemRoot%\\system32\\ntmarta.dll"), sizeof(TEXT("%SystemRoot%\\system32\\ntmarta.dll")) ); disp = EVENTLOG_ERROR_TYPE | EVENTLOG_WARNING_TYPE | EVENTLOG_INFORMATION_TYPE ; RegSetValueEx( hKey, TEXT("TypesSupported"), 0, REG_DWORD, (PBYTE) &disp, sizeof(DWORD) ); disp = CATEGORY_MAX_CATEGORY - 1; RegSetValueEx( hKey, TEXT("CategoryCount"), 0, REG_DWORD, (PBYTE) &disp, sizeof(DWORD) ); } RegCloseKey(hKey); return(dwErr); } //+--------------------------------------------------------------------------- // // Function: SetAccessListLookupServer // // Synopsis: Sets the name of the server to lookup the names/sids on for // the given path // // Arguments: [IN pwszPath] -- Path to get the server name for // [IN AccessList] -- Reference to CAccessList class that // needs the server name // // Returns: ERROR_SUCCESS -- Success // //---------------------------------------------------------------------------- DWORD SetAccessListLookupServer(IN PWSTR pwszPath, IN CAccessList &AccessList ) { DWORD dwErr = ERROR_SUCCESS; PWSTR pwszServer, pwszSep; if( pwszPath && IS_UNC_PATH( pwszPath, wcslen( pwszPath ) ) ) { pwszServer = pwszPath + 2; pwszSep = wcschr(pwszServer, L'\\'); if(pwszSep) { *pwszSep = UNICODE_NULL; } dwErr = AccessList.SetLookupServer(pwszServer); if(pwszSep) { *pwszSep = L'\\'; } } return(dwErr); }