void ADCacheSafeFreeObjectList( size_t sCount, PLSA_SECURITY_OBJECT** pppObjectList) { if (*pppObjectList != NULL) { size_t sIndex; for (sIndex = 0; sIndex < sCount; sIndex++) { ADCacheSafeFreeObject(&(*pppObjectList)[sIndex]); } LW_SAFE_FREE_MEMORY(*pppObjectList); } }
DWORD AD_GroupExpansionDataGetNextGroupToExpand( IN PLSA_AD_GROUP_EXPANSION_DATA pExpansionData, OUT PLSA_SECURITY_OBJECT* ppGroupToExpand, OUT PDWORD pdwGroupToExpandDepth ) { DWORD dwError = 0; PLSA_SECURITY_OBJECT pGroupToExpand = NULL; DWORD dwGroupToExpandDepth = 0; const LW_HASH_ENTRY* pHashEntry = NULL; dwError = pExpansionData->dwLastError; BAIL_ON_LSA_ERROR(dwError); if (pExpansionData->pGroupsToExpand->sCount < 1) { // Nothing to return goto cleanup; } if (pExpansionData->bIsIteratorInitialized) { pHashEntry = LwHashNext(&pExpansionData->GroupsToExpandIterator); } if (!pHashEntry) { // Either the iterator is not initialized or we // reached the end of the hash table and need to start over. dwError = LwHashGetIterator( pExpansionData->pGroupsToExpand, &pExpansionData->GroupsToExpandIterator); BAIL_ON_LSA_ERROR(dwError); pExpansionData->bIsIteratorInitialized = TRUE; pHashEntry = LwHashNext(&pExpansionData->GroupsToExpandIterator); if (!pHashEntry) { dwError = LW_ERROR_INTERNAL; BAIL_ON_LSA_ERROR(dwError); } } pGroupToExpand = (PLSA_SECURITY_OBJECT) pHashEntry->pKey; dwGroupToExpandDepth = (size_t) pHashEntry->pValue; dwGroupToExpandDepth++; // Move the object to the expanded list. Note that the object is // not necessarily expanded yet, but we must remove it from // the "to expand" list. It does not hurt to track it in the // "expanded" list. dwError = LwHashSetValue(pExpansionData->pExpandedGroups, pGroupToExpand, (PVOID)(size_t)dwGroupToExpandDepth); BAIL_ON_LSA_ERROR(dwError); dwError = LwHashRemoveKey(pExpansionData->pGroupsToExpand, pGroupToExpand); if (dwError) { LSA_LOG_DEBUG("ASSERT: cannot fail"); } BAIL_ON_LSA_ERROR(dwError); cleanup: *ppGroupToExpand = pGroupToExpand; *pdwGroupToExpandDepth = dwGroupToExpandDepth; return dwError; error: ADCacheSafeFreeObject(&pGroupToExpand); dwGroupToExpandDepth = 0; if (dwError && !pExpansionData->dwLastError) { pExpansionData->dwLastError = dwError; } goto cleanup; }
DWORD AD_GroupExpansionDataAddExpansionResults( IN PLSA_AD_GROUP_EXPANSION_DATA pExpansionData, IN DWORD dwExpandedGroupDepth, IN OUT size_t* psMembersCount, IN OUT PLSA_SECURITY_OBJECT** pppMembers ) { DWORD dwError = 0; size_t sMembersCount = *psMembersCount; PLSA_SECURITY_OBJECT* ppMembers = *pppMembers; dwError = pExpansionData->dwLastError; BAIL_ON_LSA_ERROR(dwError); if (dwExpandedGroupDepth > pExpansionData->dwMaxDepth) { // This should never happen dwError = LW_ERROR_INTERNAL; BAIL_ON_LSA_ERROR(dwError); } if ((sMembersCount + pExpansionData->pUsers->sCount) * 2 > pExpansionData->pUsers->sTableSize) { dwError = LwHashResize( pExpansionData->pUsers, (sMembersCount + pExpansionData->pUsers->sCount + 10) * 3); BAIL_ON_LSA_ERROR(dwError); } if ((sMembersCount + pExpansionData->pGroupsToExpand->sCount) * 2 > pExpansionData->pGroupsToExpand->sTableSize) { dwError = LwHashResize( pExpansionData->pGroupsToExpand, (sMembersCount + pExpansionData->pGroupsToExpand->sCount + 10) * 3); BAIL_ON_LSA_ERROR(dwError); } for (; sMembersCount > 0; sMembersCount--) { PLSA_SECURITY_OBJECT pCurrentMember = ppMembers[sMembersCount-1]; if (!pCurrentMember) { continue; } if (pCurrentMember->type == LSA_OBJECT_TYPE_USER) { if (!LwHashExists(pExpansionData->pUsers, ppMembers[sMembersCount-1])) { dwError = LwHashSetValue( pExpansionData->pUsers, ppMembers[sMembersCount-1], (PVOID)(size_t)dwExpandedGroupDepth); BAIL_ON_LSA_ERROR(dwError); ppMembers[sMembersCount-1] = NULL; } else { ADCacheSafeFreeObject(&ppMembers[sMembersCount-1]); } } else if (pCurrentMember->type == LSA_OBJECT_TYPE_GROUP) { if (dwExpandedGroupDepth >= pExpansionData->dwMaxDepth) { pExpansionData->bDiscardedDueToDepth = TRUE; ADCacheSafeFreeObject(&ppMembers[sMembersCount-1]); } else if (LwHashExists(pExpansionData->pExpandedGroups, pCurrentMember) || LwHashExists(pExpansionData->pGroupsToExpand, pCurrentMember)) { ADCacheSafeFreeObject(&ppMembers[sMembersCount-1]); } else { dwError = LwHashSetValue( pExpansionData->pGroupsToExpand, ppMembers[sMembersCount-1], (PVOID)(size_t)dwExpandedGroupDepth); BAIL_ON_LSA_ERROR(dwError); ppMembers[sMembersCount-1] = NULL; } } else { // some other kind of object -- should not happen ADCacheSafeFreeObject(&ppMembers[sMembersCount-1]); } } cleanup: if (ppMembers && (sMembersCount == 0)) { ADCacheSafeFreeObjectList(sMembersCount, &ppMembers); } *psMembersCount = sMembersCount; *pppMembers = ppMembers; return dwError; error: ADCacheSafeFreeObjectList(sMembersCount, &ppMembers); if (dwError && !pExpansionData->dwLastError) { pExpansionData->dwLastError = dwError; } goto cleanup; }
DWORD LsaAdBatchMarshal( IN PLSA_AD_PROVIDER_STATE pState, IN PCSTR pszDnsDomainName, IN PCSTR pszNetbiosDomainName, IN OUT PLSA_AD_BATCH_ITEM pItem, OUT PLSA_SECURITY_OBJECT* ppObject ) { DWORD dwError = 0; PAD_PROVIDER_DATA pProviderData = pState->pProviderData; PLSA_SECURITY_OBJECT pObject = NULL; // To marshal, the following conditions to be satisfied: // // 1) Object must have user or group type. // 2) Object must have real information. if ((LSA_AD_BATCH_OBJECT_TYPE_UNDEFINED == pItem->ObjectType) || !IsSetFlag(pItem->Flags, LSA_AD_BATCH_ITEM_FLAG_HAVE_REAL)) { PCSTR pszType = NULL; BOOLEAN bIsString = FALSE; PCSTR pszString = NULL; DWORD dwId = 0; LsaAdBatchQueryTermDebugInfo( &pItem->QueryTerm, &pszType, &bIsString, &pszString, &dwId); if (bIsString) { LSA_LOG_VERBOSE("Did not find object by %s '%s'", pszType, pszString); } else { LSA_LOG_VERBOSE("Did not find object by %s %u", pszType, dwId); } dwError = 0; goto cleanup; } if (!IsSetFlag(pItem->Flags, LSA_AD_BATCH_ITEM_FLAG_HAVE_PSEUDO) && !LsaAdBatchIsUnprovisionedMode(pProviderData)) { SetFlag(pItem->Flags, LSA_AD_BATCH_ITEM_FLAG_DISABLED); } #if 0 // Disable in svn commit r45217 // Fix regression that could cause NULL objects to be returned by LsaEnumObjects(): // Don't filter out disabled objects when enumerating in the AD provider - If we // ever do filter out objects, don't leave NULLs in the array // // This code also has to be disabled for to support returning non-provisioned objects // (computers, users, ...) that need an access token for use in Likewise-CIFS if (IsSetFlag(pItem->Flags, LSA_AD_BATCH_ITEM_FLAG_DISABLED) && (pItem->ObjectType != LSA_AD_BATCH_OBJECT_TYPE_GROUP)) { // Skip any disabled non-groups. LSA_LOG_VERBOSE("Skipping disabled object (sid = %s, name = %s\\%s)", LSA_SAFE_LOG_STRING(pItem->pszSid), LSA_SAFE_LOG_STRING(pszNetbiosDomainName), LSA_SAFE_LOG_STRING(pItem->pszSamAccountName)); dwError = 0; goto cleanup; } #endif dwError = LwAllocateMemory(sizeof(*pObject), (PVOID*)&pObject); BAIL_ON_LSA_ERROR(dwError); pObject->version.qwDbId = -1; pObject->enabled = !IsSetFlag(pItem->Flags, LSA_AD_BATCH_ITEM_FLAG_DISABLED); // Transfer the data LSA_XFER_STRING(pItem->pszSid, pObject->pszObjectSid); LSA_XFER_STRING(pItem->pszSamAccountName, pObject->pszSamAccountName); LSA_XFER_STRING(pItem->pszDn, pObject->pszDN); dwError = LwAllocateString( pszNetbiosDomainName, &pObject->pszNetbiosDomainName); BAIL_ON_LSA_ERROR(dwError); switch (pItem->ObjectType) { case LSA_AD_BATCH_OBJECT_TYPE_USER: pObject->type = LSA_OBJECT_TYPE_USER; dwError = LsaAdBatchMarshalUserInfo( pState, &pItem->UserInfo, &pObject->userInfo, pszDnsDomainName, pObject->pszNetbiosDomainName, pObject->pszSamAccountName, pObject->pszObjectSid); BAIL_ON_LSA_ERROR(dwError); pObject->userInfo.bIsAccountInfoKnown = IsSetFlag(pItem->Flags, LSA_AD_BATCH_ITEM_FLAG_ACCOUNT_INFO_KNOWN); break; case LSA_AD_BATCH_OBJECT_TYPE_GROUP: pObject->type = LSA_OBJECT_TYPE_GROUP; dwError = LsaAdBatchMarshalGroupInfo( pProviderData, &pItem->GroupInfo, &pObject->groupInfo, pszDnsDomainName, pObject->pszNetbiosDomainName, pObject->pszSamAccountName, pObject->pszObjectSid); BAIL_ON_LSA_ERROR(dwError); break; default: LSA_ASSERT(FALSE); dwError = LW_ERROR_INTERNAL; BAIL_ON_LSA_ERROR(dwError); } cleanup: *ppObject = pObject; return dwError; error: if (pObject) { ADCacheSafeFreeObject(&pObject); } goto cleanup; }
DWORD ADCacheDuplicateObject( OUT PLSA_SECURITY_OBJECT* ppDest, IN PLSA_SECURITY_OBJECT pSrc ) { DWORD dwError = 0; PLSA_SECURITY_OBJECT pDest = NULL; dwError = LwAllocateMemory( sizeof(*pDest), (PVOID*)&pDest); BAIL_ON_LSA_ERROR(dwError); pDest->version = pSrc->version; dwError = LwAllocateString( pSrc->pszObjectSid, &pDest->pszObjectSid); BAIL_ON_LSA_ERROR(dwError); pDest->enabled = pSrc->enabled; dwError = LwAllocateString( pSrc->pszNetbiosDomainName, &pDest->pszNetbiosDomainName); BAIL_ON_LSA_ERROR(dwError); dwError = LwAllocateString( pSrc->pszSamAccountName, &pDest->pszSamAccountName); BAIL_ON_LSA_ERROR(dwError); dwError = LwStrDupOrNull( pSrc->pszDN, &pDest->pszDN); BAIL_ON_LSA_ERROR(dwError); pDest->type = pSrc->type; if (pDest->type == LSA_OBJECT_TYPE_USER) { pDest->userInfo.uid = pSrc->userInfo.uid; pDest->userInfo.gid = pSrc->userInfo.gid; dwError = LwStrDupOrNull( pSrc->userInfo.pszPrimaryGroupSid, &pDest->userInfo.pszPrimaryGroupSid); BAIL_ON_LSA_ERROR(dwError); dwError = LwStrDupOrNull( pSrc->userInfo.pszUPN, &pDest->userInfo.pszUPN); BAIL_ON_LSA_ERROR(dwError); dwError = LwStrDupOrNull( pSrc->userInfo.pszAliasName, &pDest->userInfo.pszAliasName); BAIL_ON_LSA_ERROR(dwError); dwError = LwStrDupOrNull( pSrc->userInfo.pszUnixName, &pDest->userInfo.pszUnixName); BAIL_ON_LSA_ERROR(dwError); dwError = LwStrDupOrNull( pSrc->userInfo.pszPasswd, &pDest->userInfo.pszPasswd); BAIL_ON_LSA_ERROR(dwError); dwError = LwStrDupOrNull( pSrc->userInfo.pszGecos, &pDest->userInfo.pszGecos); BAIL_ON_LSA_ERROR(dwError); dwError = LwStrDupOrNull( pSrc->userInfo.pszShell, &pDest->userInfo.pszShell); BAIL_ON_LSA_ERROR(dwError); dwError = LwStrDupOrNull( pSrc->userInfo.pszHomedir, &pDest->userInfo.pszHomedir); BAIL_ON_LSA_ERROR(dwError); dwError = LwStrDupOrNull( pSrc->userInfo.pszWindowsHomeFolder, &pDest->userInfo.pszWindowsHomeFolder); BAIL_ON_LSA_ERROR(dwError); dwError = LwStrDupOrNull( pSrc->userInfo.pszLocalWindowsHomeFolder, &pDest->userInfo.pszLocalWindowsHomeFolder); BAIL_ON_LSA_ERROR(dwError); dwError = LwStrDupOrNull( pSrc->userInfo.pszDisplayName, &pDest->userInfo.pszDisplayName); BAIL_ON_LSA_ERROR(dwError); pDest->userInfo.qwPwdLastSet = pSrc->userInfo.qwPwdLastSet; pDest->userInfo.qwPwdExpires = pSrc->userInfo.qwPwdExpires; pDest->userInfo.qwAccountExpires = pSrc->userInfo.qwAccountExpires; pDest->userInfo.bIsGeneratedUPN = pSrc->userInfo.bIsGeneratedUPN; pDest->userInfo.bIsAccountInfoKnown = pSrc->userInfo.bIsAccountInfoKnown; pDest->userInfo.bPasswordExpired = pSrc->userInfo.bPasswordExpired; pDest->userInfo.bPasswordNeverExpires = pSrc->userInfo.bPasswordNeverExpires; pDest->userInfo.bPromptPasswordChange = pSrc->userInfo.bPromptPasswordChange; pDest->userInfo.bUserCanChangePassword = pSrc->userInfo.bUserCanChangePassword; pDest->userInfo.bAccountDisabled = pSrc->userInfo.bAccountDisabled; pDest->userInfo.bAccountExpired = pSrc->userInfo.bAccountExpired; pDest->userInfo.bAccountLocked = pSrc->userInfo.bAccountLocked; } else if (pDest->type == LSA_OBJECT_TYPE_GROUP) { pDest->groupInfo.gid = pSrc->groupInfo.gid; dwError = LwStrDupOrNull( pSrc->groupInfo.pszAliasName, &pDest->groupInfo.pszAliasName); BAIL_ON_LSA_ERROR(dwError); dwError = LwStrDupOrNull( pSrc->groupInfo.pszUnixName, &pDest->groupInfo.pszUnixName); BAIL_ON_LSA_ERROR(dwError); dwError = LwStrDupOrNull( pSrc->groupInfo.pszPasswd, &pDest->groupInfo.pszPasswd); BAIL_ON_LSA_ERROR(dwError); } *ppDest = pDest; cleanup: return dwError; error: ADCacheSafeFreeObject(&pDest); *ppDest = NULL; goto cleanup; }
DWORD ADLdap_GetGroupMembers( IN PAD_PROVIDER_CONTEXT pContext, IN PCSTR pszDomainName, IN PCSTR pszSid, OUT size_t* psCount, OUT PLSA_SECURITY_OBJECT** pppResults ) { DWORD dwError = LW_ERROR_SUCCESS; DWORD dwSidCount = 0; PSTR pszDnsDomainName = NULL; PLSA_SECURITY_OBJECT pGroupObj = NULL; PLSA_SECURITY_OBJECT* ppResults = NULL; PSTR *ppszLDAPValues = NULL; size_t sFoundCount = 0; PLSA_DM_LDAP_CONNECTION pConn = NULL; dwError = AD_FindObjectBySid( pContext, pszSid, &pGroupObj); BAIL_ON_LSA_ERROR(dwError); if (pGroupObj->type != LSA_OBJECT_TYPE_GROUP) { dwError = LW_ERROR_DATA_ERROR; BAIL_ON_LSA_ERROR(dwError); } dwError = LsaDmWrapGetDomainName( pContext->pState->hDmState, pszDomainName, &pszDnsDomainName, NULL); BAIL_ON_LSA_ERROR(dwError); dwError = LsaDmLdapOpenDc( pContext, pszDnsDomainName, &pConn); BAIL_ON_LSA_ERROR(dwError); dwError = ADLdap_GetAttributeValuesList( pConn, pGroupObj->pszDN, AD_LDAP_MEMBER_TAG, TRUE, TRUE, &dwSidCount, &ppszLDAPValues); BAIL_ON_LSA_ERROR(dwError); dwError = AD_FindObjectsBySidList( pContext, dwSidCount, ppszLDAPValues, &sFoundCount, &ppResults); BAIL_ON_LSA_ERROR(dwError); *psCount = sFoundCount; *pppResults = ppResults; cleanup: LW_SAFE_FREE_STRING(pszDnsDomainName); ADCacheSafeFreeObject(&pGroupObj); LwFreeStringArray(ppszLDAPValues, dwSidCount); LsaDmLdapClose(pConn); return dwError; error: *psCount = 0; *pppResults = NULL; LSA_LOG_ERROR("Failed to find group's members of objectSid=%s. [error code:%u]", LSA_SAFE_LOG_STRING(pszSid), dwError); ADCacheSafeFreeObjectList((DWORD)sFoundCount, &ppResults); goto cleanup; }