DWORD DefaultModeNonSchemaEnumNSSArtefacts( PLSA_DM_LDAP_CONNECTION pConn, PCSTR pszCellDN, PCSTR pszNetBIOSDomainName, PAD_ENUM_STATE pEnumState, DWORD dwMaxNumNSSArtefacts, PDWORD pdwNumNSSArtefactsFound, PVOID** pppNSSArtefactInfoList ) { DWORD dwError = 0; DWORD dwCount = 0; PCSTR pszQuery = "(&(objectClass=serviceConnectionPoint)(keywords=objectClass=centerisLikewiseMapEntry))"; PSTR pszDN = NULL; PSTR pszEscapedDN = NULL; PVOID* ppNSSArtefactInfoList = NULL; PVOID* ppNSSArtefactInfoList_accumulate = NULL; DWORD dwTotalNumNSSArtefactsFound = 0; DWORD dwNumNSSArtefactsFound = 0; DWORD dwNSSArtefactInfoLevel = 0; PSTR szAttributeList[] = { AD_LDAP_NAME_TAG, AD_LDAP_KEYWORDS_TAG, NULL }; LDAPMessage *pMessagePseudo = NULL; LDAP *pLd = NULL; HANDLE hDirectory = NULL; DWORD dwNumNSSArtefactsWanted = dwMaxNumNSSArtefacts; dwNSSArtefactInfoLevel = pEnumState->dwInfoLevel; BAIL_ON_INVALID_STRING(pEnumState->pszMapName); dwError = LwAllocateStringPrintf( &pszDN, "CN=%s,CN=Maps,%s", pEnumState->pszMapName, pszCellDN); BAIL_ON_LSA_ERROR(dwError); dwError = LwLdapEscapeString( &pszEscapedDN, pszDN); BAIL_ON_LSA_ERROR(dwError); if (pEnumState->Cookie.bSearchFinished){ dwError = LW_ERROR_NO_MORE_NSS_ARTEFACTS; BAIL_ON_LSA_ERROR(dwError); } do { dwError = LsaDmLdapDirectoryOnePagedSearch( pConn, pszEscapedDN, pszQuery, szAttributeList, dwNumNSSArtefactsWanted, &pEnumState->Cookie, LDAP_SCOPE_ONELEVEL, &hDirectory, &pMessagePseudo); BAIL_ON_LSA_ERROR(dwError); pLd = LwLdapGetSession(hDirectory); dwCount = ldap_count_entries( pLd, pMessagePseudo); if (dwCount < 0) { dwError = LW_ERROR_LDAP_ERROR; } else if (dwCount == 0) { dwError = LW_ERROR_NO_MORE_NSS_ARTEFACTS; } BAIL_ON_LSA_ERROR(dwError); dwError = ADNonSchemaMarshalNSSArtefactInfoList( hDirectory, pszNetBIOSDomainName, pMessagePseudo, pEnumState->dwMapFlags, dwNSSArtefactInfoLevel, &ppNSSArtefactInfoList, &dwNumNSSArtefactsFound ); BAIL_ON_LSA_ERROR(dwError); dwNumNSSArtefactsWanted -= dwNumNSSArtefactsFound; dwError = LsaAppendAndFreePtrs( &dwTotalNumNSSArtefactsFound, &ppNSSArtefactInfoList_accumulate, &dwNumNSSArtefactsFound, &ppNSSArtefactInfoList); BAIL_ON_LSA_ERROR(dwError); if (pMessagePseudo) { ldap_msgfree(pMessagePseudo); pMessagePseudo = NULL; } } while (!pEnumState->Cookie.bSearchFinished && dwNumNSSArtefactsWanted); *pppNSSArtefactInfoList = ppNSSArtefactInfoList_accumulate; *pdwNumNSSArtefactsFound = dwTotalNumNSSArtefactsFound; cleanup: LW_SAFE_FREE_STRING(pszDN); LW_SAFE_FREE_STRING(pszEscapedDN); return dwError; error: *pppNSSArtefactInfoList = NULL; *pdwNumNSSArtefactsFound = 0; if (ppNSSArtefactInfoList) { LsaFreeNSSArtefactInfoList(dwNSSArtefactInfoLevel, ppNSSArtefactInfoList, dwNumNSSArtefactsFound); } if (ppNSSArtefactInfoList_accumulate) { LsaFreeNSSArtefactInfoList(dwNSSArtefactInfoLevel, ppNSSArtefactInfoList_accumulate, dwTotalNumNSSArtefactsFound); } if (dwError == LW_ERROR_LDAP_NO_SUCH_OBJECT) { dwError = LW_ERROR_NO_MORE_NSS_ARTEFACTS; } goto cleanup; }
DWORD DefaultModeNonSchemaFindNSSArtefactByKey( IN PLSA_DM_LDAP_CONNECTION pConn, PCSTR pszCellDN, PCSTR pszNetBIOSDomainName, PCSTR pszKeyName, PCSTR pszMapName, DWORD dwInfoLevel, LSA_NIS_MAP_QUERY_FLAGS dwFlags, PVOID* ppNSSArtefactInfo ) { DWORD dwError = 0; DWORD dwCount = 0; PSTR pszQuery = NULL; PSTR pszDN = NULL; PSTR pszEscapedDN = NULL; PSTR szAttributeList[] = { AD_LDAP_NAME_TAG, AD_LDAP_KEYWORDS_TAG, NULL }; LDAPMessage *pMessagePseudo = NULL; PVOID* ppArtefactInfos = NULL; DWORD dwNumInfos = 0; BOOLEAN bMapExists = FALSE; LDAP *pLd = NULL; HANDLE hDirectory = NULL; BAIL_ON_INVALID_STRING(pszMapName); BAIL_ON_INVALID_STRING(pszKeyName); dwError = LwAllocateStringPrintf( &pszDN, "CN=%s,CN=Maps,%s", pszMapName, pszCellDN); BAIL_ON_LSA_ERROR(dwError); dwError = LwLdapEscapeString( &pszEscapedDN, pszDN); BAIL_ON_LSA_ERROR(dwError); dwError = ADLdap_IsValidDN( pConn, pszEscapedDN, &bMapExists); BAIL_ON_LSA_ERROR(dwError); if (!bMapExists) { dwError = LW_ERROR_NO_SUCH_NSS_MAP; BAIL_ON_LSA_ERROR(dwError); } dwError = LwAllocateStringPrintf( &pszQuery, "(&(objectClass=serviceConnectionPoint)(keywords=objectClass=centerisLikewiseMapEntry)(name=%s))", pszKeyName); BAIL_ON_LSA_ERROR(dwError); dwError = LsaDmLdapDirectorySearch( pConn, pszEscapedDN, LDAP_SCOPE_ONELEVEL, pszQuery, szAttributeList, &hDirectory, &pMessagePseudo); BAIL_ON_LSA_ERROR(dwError); pLd = LwLdapGetSession(hDirectory); dwCount = ldap_count_entries( pLd, pMessagePseudo); if (dwCount < 0) { dwError = LW_ERROR_LDAP_ERROR; } else if (dwCount == 0) { dwError = LW_ERROR_NO_SUCH_NSS_KEY; } BAIL_ON_LSA_ERROR(dwError); dwError = ADNonSchemaMarshalNSSArtefactInfoList( hDirectory, pszNetBIOSDomainName, pMessagePseudo, dwFlags, dwInfoLevel, &ppArtefactInfos, &dwNumInfos); BAIL_ON_LSA_ERROR(dwError); *ppNSSArtefactInfo = *ppArtefactInfos; *ppArtefactInfos = NULL; cleanup: if (pMessagePseudo) { ldap_msgfree(pMessagePseudo); } if (ppArtefactInfos) { LsaFreeNSSArtefactInfoList(dwInfoLevel, ppArtefactInfos, dwNumInfos); } LW_SAFE_FREE_STRING(pszDN); LW_SAFE_FREE_STRING(pszEscapedDN); LW_SAFE_FREE_STRING(pszQuery); return dwError; error: *ppNSSArtefactInfo = NULL; if (dwError == LW_ERROR_LDAP_NO_SUCH_OBJECT) { dwError = LW_ERROR_NO_SUCH_NSS_KEY; } goto cleanup; }
static DWORD LsaAdBatchBuilderBatchItemGetAttributeValue( IN PAD_PROVIDER_DATA pProviderData, IN PVOID pCallbackContext, IN PVOID pItem, OUT PCSTR* ppszValue, OUT PVOID* ppFreeValueContext ) { DWORD dwError = 0; PLSA_AD_BATCH_BUILDER_BATCH_ITEM_CONTEXT pContext = (PLSA_AD_BATCH_BUILDER_BATCH_ITEM_CONTEXT)pCallbackContext; LSA_AD_BATCH_QUERY_TYPE QueryType = pContext->QueryType; BOOLEAN bIsForRealObject = pContext->bIsForRealObject; PLSA_LIST_LINKS pLinks = (PLSA_LIST_LINKS)pItem; PLSA_AD_BATCH_ITEM pBatchItem = LW_STRUCT_FROM_FIELD(pLinks, LSA_AD_BATCH_ITEM, BatchItemListLinks); PSTR pszValueToEscape = NULL; PSTR pszValueToHex = NULL; PSTR pszValue = NULL; PVOID pFreeValueContext = NULL; // Free this on error only. PSTR pszMatchTerm = NULL; PSTR pszAllocatedMatchTermValue = NULL; BOOLEAN bHaveReal = IsSetFlag(pBatchItem->Flags, LSA_AD_BATCH_ITEM_FLAG_HAVE_REAL); BOOLEAN bHavePseudo = IsSetFlag(pBatchItem->Flags, LSA_AD_BATCH_ITEM_FLAG_HAVE_PSEUDO); if (IsSetFlag(pBatchItem->Flags, LSA_AD_BATCH_ITEM_FLAG_ALLOCATED_MATCH_TERM)) { LW_SAFE_FREE_STRING(pBatchItem->pszQueryMatchTerm); ClearFlag(pBatchItem->Flags, LSA_AD_BATCH_ITEM_FLAG_ALLOCATED_MATCH_TERM); } if ((bIsForRealObject && bHaveReal) || (!bIsForRealObject && bHavePseudo)) { // This can only happen in the linked cells case, but even // that should go away in the future as we just keep an // unresolved batch items list. LSA_ASSERT(!bIsForRealObject && (pProviderData->dwDirectoryMode == CELL_MODE)); goto cleanup; } switch (QueryType) { case LSA_AD_BATCH_QUERY_TYPE_BY_DN: // Must be looking for real object LSA_ASSERT(bIsForRealObject); LSA_ASSERT(QueryType == pBatchItem->QueryTerm.Type); pszValueToEscape = (PSTR)pBatchItem->QueryTerm.pszString; LSA_ASSERT(pszValueToEscape); break; case LSA_AD_BATCH_QUERY_TYPE_BY_SID: if (pBatchItem->pszSid) { // This is case where we already got the SID by resolving // the pseudo object by id/alias. pszValue = pBatchItem->pszSid; } else if (QueryType == pBatchItem->QueryTerm.Type) { // This is the case where the original query was // a query by SID. pszValue = (PSTR)pBatchItem->QueryTerm.pszString; LSA_ASSERT(pszValue); } // Will be NULL if we cannot find a SID for which to query. // This can happen if this batch item is for an object // that we did not find real but are trying to look up pseudo. // In that case, we have NULL and will just skip it. // If we have a SID string, make sure it looks like a SID. // Note that we must do some sanity checking to make sure // that the string does not need escaping since we are // not setting pszValueToEscape. (The SID check takes // care of that.) if (pszValue && !LsaAdBatchHasValidCharsForSid(pszValue)) { LSA_ASSERT(FALSE); dwError = LW_ERROR_INTERNAL; BAIL_ON_LSA_ERROR(dwError); } if (bIsForRealObject) { // "S-"-style SID string are only handled starting with // Windows 2003. So an LDAP hex-formatted SID string // is needed to handle Windows 2000. pszValueToHex = pszValue; pszValue = NULL; } break; case LSA_AD_BATCH_QUERY_TYPE_BY_NT4: LSA_ASSERT(bIsForRealObject); if (pBatchItem->pszSamAccountName) { // Unprovisioned id/alias case where id mapper returned // a SAM account name (and domain name) but no SID. pszValueToEscape = pBatchItem->pszSamAccountName; // However, we currently do not have this sort of id mapper // support, so we LSA_ASSERT(FALSE) for now. LSA_ASSERT(FALSE); } else if (QueryType == pBatchItem->QueryTerm.Type) { pszValueToEscape = (PSTR)pBatchItem->QueryTerm.pszString; LSA_ASSERT(pszValueToEscape); } break; case LSA_AD_BATCH_QUERY_TYPE_BY_UID: case LSA_AD_BATCH_QUERY_TYPE_BY_GID: LSA_ASSERT(!bIsForRealObject); LSA_ASSERT(QueryType == pBatchItem->QueryTerm.Type); dwError = LwAllocateStringPrintf( &pszAllocatedMatchTermValue, "%u", (unsigned int)pBatchItem->QueryTerm.dwId); BAIL_ON_LSA_ERROR(dwError); pszValue = pszAllocatedMatchTermValue; // Note: It is ok to set this here because it is ok for // this flag to be set if the match term field in the // batch item is still NULL (i.e., if we fail later in // this function). SetFlag(pBatchItem->Flags, LSA_AD_BATCH_ITEM_FLAG_ALLOCATED_MATCH_TERM); break; case LSA_AD_BATCH_QUERY_TYPE_BY_USER_ALIAS: case LSA_AD_BATCH_QUERY_TYPE_BY_GROUP_ALIAS: LSA_ASSERT(!bIsForRealObject); LSA_ASSERT(QueryType == pBatchItem->QueryTerm.Type); pszValueToEscape = (PSTR)pBatchItem->QueryTerm.pszString; LSA_ASSERT(pszValueToEscape); break; default: dwError = LW_ERROR_INVALID_PARAMETER; BAIL_ON_LSA_ERROR(dwError); } LSA_ASSERT(!pszMatchTerm); LSA_ASSERT(!(pszValueToEscape && pszValueToHex)); if (pszValueToEscape) { LSA_ASSERT(!pszValue); dwError = LwLdapEscapeString(&pszValue, pszValueToEscape); BAIL_ON_LSA_ERROR(dwError); pszMatchTerm = pszValueToEscape; pFreeValueContext = pszValue; } else if (pszValueToHex) { LSA_ASSERT(!pszValue); dwError = LsaSidStrToLdapFormatHexStr(pszValueToHex, &pszValue); BAIL_ON_LSA_ERROR(dwError); pszMatchTerm = pszValueToHex; pFreeValueContext = pszValue; } else { pszMatchTerm = pszValue; } cleanup: // Note that the match value can be different from the value, // which we may need to escape or hex. pBatchItem->pszQueryMatchTerm = pszMatchTerm; *ppszValue = pszValue; *ppFreeValueContext = pFreeValueContext; return dwError; error: // assing output in cleanup in case of goto cleanup in function. pszValueToEscape = NULL; pszValue = NULL; LW_SAFE_FREE_STRING(pFreeValueContext); LW_SAFE_FREE_STRING(pszAllocatedMatchTermValue); goto cleanup; }
static DWORD AD_RawFindComputerDn( IN HANDLE hDirectory, IN PCSTR pszDnsDomainName, IN PCSTR pszSamAccountName, OUT PSTR* ppszComputerDn ) { DWORD dwError = 0; LDAP* pLd = NULL; PSTR pszDirectoryRoot = NULL; PSTR pszEscapedSamAccountName = NULL; PSTR szAttributeList[] = {"*", NULL}; PSTR pszQuery = NULL; LDAPMessage *pMessage = NULL; int count = 0; PSTR pszComputerDn = NULL; pLd = LwLdapGetSession(hDirectory); dwError = LwLdapConvertDomainToDN( pszDnsDomainName, &pszDirectoryRoot); BAIL_ON_LSA_ERROR(dwError); dwError = LwLdapEscapeString( &pszEscapedSamAccountName, pszSamAccountName); BAIL_ON_LSA_ERROR(dwError); LwStrToUpper(pszEscapedSamAccountName); dwError = LwAllocateStringPrintf( &pszQuery, "(sAMAccountName=%s)", pszEscapedSamAccountName); BAIL_ON_LSA_ERROR(dwError); dwError = LwLdapDirectorySearch( hDirectory, pszDirectoryRoot, LDAP_SCOPE_SUBTREE, pszQuery, szAttributeList, &pMessage); BAIL_ON_LSA_ERROR(dwError); count = ldap_count_entries(pLd, pMessage); if (count < 0) { dwError = LW_ERROR_LDAP_ERROR; } else if (count == 0) { dwError = LW_ERROR_NO_SUCH_DOMAIN; } else if (count > 1) { dwError = LW_ERROR_DUPLICATE_DOMAINNAME; } BAIL_ON_LSA_ERROR(dwError); dwError = LwLdapGetDN(hDirectory, pMessage, &pszComputerDn); BAIL_ON_LSA_ERROR(dwError); if (LW_IS_NULL_OR_EMPTY_STR(pszComputerDn)) { dwError = LW_ERROR_LDAP_FAILED_GETDN; BAIL_ON_LSA_ERROR(dwError); } error: if (dwError) { LW_SAFE_FREE_STRING(pszComputerDn); } LW_SAFE_FREE_STRING(pszDirectoryRoot); LW_SAFE_FREE_STRING(pszEscapedSamAccountName); LW_SAFE_FREE_STRING(pszQuery); if (pMessage) { ldap_msgfree(pMessage); } *ppszComputerDn = pszComputerDn; return dwError; }
DWORD ADFindComputerDN( IN PLSA_DM_LDAP_CONNECTION pConn, PCSTR pszSamAccountName, PCSTR pszDomainName, PSTR* ppszComputerDN ) { DWORD dwError = 0; LDAP *pLd = NULL; PSTR pszDirectoryRoot = NULL; PSTR szAttributeList[] = {"*", NULL}; PSTR pszQuery = NULL; LDAPMessage *pMessage = NULL; DWORD dwCount = 0; PSTR pszComputerDN = NULL; PSTR pszEscapedUpperSamAccountName = NULL; HANDLE hDirectory = NULL; dwError = LwLdapConvertDomainToDN(pszDomainName, &pszDirectoryRoot); BAIL_ON_LSA_ERROR(dwError); dwError = LwLdapEscapeString( &pszEscapedUpperSamAccountName, pszSamAccountName); BAIL_ON_LSA_ERROR(dwError); LwStrToUpper(pszEscapedUpperSamAccountName); dwError = LwAllocateStringPrintf(&pszQuery, "(sAMAccountName=%s)", pszEscapedUpperSamAccountName); BAIL_ON_LSA_ERROR(dwError); dwError = LsaDmLdapDirectorySearch( pConn, pszDirectoryRoot, LDAP_SCOPE_SUBTREE, pszQuery, szAttributeList, &hDirectory, &pMessage); BAIL_ON_LSA_ERROR(dwError); pLd = LwLdapGetSession(hDirectory); dwCount = ldap_count_entries( pLd, pMessage ); if (dwCount < 0) { dwError = LW_ERROR_LDAP_ERROR; } else if (dwCount == 0) { dwError = LW_ERROR_NO_SUCH_DOMAIN; } else if (dwCount > 1) { dwError = LW_ERROR_DUPLICATE_DOMAINNAME; } BAIL_ON_LSA_ERROR(dwError); dwError = LwLdapGetDN( hDirectory, pMessage, &pszComputerDN); BAIL_ON_LSA_ERROR(dwError); if (LW_IS_NULL_OR_EMPTY_STR(pszComputerDN)) { dwError = LW_ERROR_LDAP_FAILED_GETDN; BAIL_ON_LSA_ERROR(dwError); } *ppszComputerDN = pszComputerDN; cleanup: LW_SAFE_FREE_STRING(pszEscapedUpperSamAccountName); LW_SAFE_FREE_STRING(pszDirectoryRoot); LW_SAFE_FREE_STRING(pszQuery); if (pMessage) { ldap_msgfree(pMessage); } return dwError; error: *ppszComputerDN = NULL; LW_SAFE_FREE_STRING(pszComputerDN); goto cleanup; }
DWORD ADLdap_AddDomainLocalGroups( IN PAD_PROVIDER_CONTEXT pContext, IN PLSA_SECURITY_OBJECT pObject, IN OUT PLW_HASH_TABLE pGroupHash ) { DWORD dwError = 0; PLSA_DM_LDAP_CONNECTION pConn = NULL; PSTR szAttributeList[] = { AD_LDAP_OBJECTSID_TAG, NULL }; PSTR pDomainDN = NULL; PSTR pszEscapedDN = NULL; // Do not free. This is owned by pConn HANDLE hDirectory = NULL; LDAPMessage* pMessage = NULL; // Do not free. This is owned by pConn LDAP* pLd = NULL; PSTR pGroupSid = NULL; PSTR pFilter = NULL; // Do not free LDAPMessage* pCurrentMessage = NULL; dwError = LsaDmLdapOpenDc( pContext, pContext->pState->pszDomainName, &pConn); BAIL_ON_LSA_ERROR(dwError); dwError = LwLdapConvertDomainToDN( pContext->pState->pszDomainName, &pDomainDN); BAIL_ON_LSA_ERROR(dwError); dwError = LwLdapEscapeString(&pszEscapedDN, pObject->pszDN); BAIL_ON_LSA_ERROR(dwError); // groupType: 2147483652 = 0x80000004 = ( GROUP_TYPE_RESOURCE_GROUP | // GROUP_TYPE_SECURITY_ENABLED ) = domain local security group dwError = LwAllocateStringPrintf( &pFilter, "(&(|(member=%s)(member=CN=%s,CN=ForeignSecurityPrincipals,%s))(groupType=2147483652))", pszEscapedDN, pObject->pszObjectSid, pDomainDN); BAIL_ON_LSA_ERROR(dwError); dwError = LsaDmLdapDirectorySearch( pConn, pDomainDN, LDAP_SCOPE_SUBTREE, pFilter, szAttributeList, &hDirectory, &pMessage); BAIL_ON_LSA_ERROR(dwError); pLd = LwLdapGetSession(hDirectory); pCurrentMessage = ldap_first_entry(pLd, pMessage); while (pCurrentMessage) { LW_SAFE_FREE_STRING(pGroupSid); dwError = ADLdap_GetObjectSid( hDirectory, pCurrentMessage, &pGroupSid); BAIL_ON_LSA_ERROR(dwError); if (!LwHashExists(pGroupHash, pGroupSid)) { // Set the value of the hash entry so this string gets freed with // the hash. dwError = LwHashSetValue(pGroupHash, pGroupSid, pGroupSid); BAIL_ON_LSA_ERROR(dwError); pGroupSid = NULL; } pCurrentMessage = ldap_next_entry(pLd, pCurrentMessage); } cleanup: LsaDmLdapClose(pConn); LW_SAFE_FREE_STRING(pszEscapedDN); LW_SAFE_FREE_STRING(pDomainDN); LW_SAFE_FREE_STRING(pFilter); LW_SAFE_FREE_STRING(pGroupSid); if (pMessage) { ldap_msgfree(pMessage); } return dwError; error: goto cleanup; }