Exemplo n.º 1
0
static
DWORD
LsaAdBatchGatherUnprovisionedMode(
    IN OUT PLSA_AD_BATCH_ITEM pItem,
    IN HANDLE hDirectory,
    IN LDAPMessage* pMessage
    )
{
    DWORD dwError = 0;

    switch (pItem->ObjectType)
    {
        case LSA_AD_BATCH_OBJECT_TYPE_USER:
            dwError = LsaAdBatchGatherUnprovisionedModeUser(
                            pItem,
                            hDirectory,
                            pMessage);
            BAIL_ON_LSA_ERROR(dwError);
            break;
        case LSA_AD_BATCH_OBJECT_TYPE_GROUP:
            // Nothing special for groups.
            break;
        default:
            LSA_ASSERT(FALSE);
            dwError = LW_ERROR_INTERNAL;
            BAIL_ON_LSA_ERROR(dwError);
    }

cleanup:
    return dwError;

error:
    goto cleanup;
}
Exemplo n.º 2
0
static
DWORD
LsaUnjoinDomain(
    IN PCWSTR pwszDnsDomainName,
    IN PCWSTR pwszMachineSamAccountName,
    IN OPTIONAL PCWSTR pwszUserName,
    IN OPTIONAL PCWSTR pwszUserDomain,
    IN OPTIONAL PCWSTR pwszUserPassword,
    IN DWORD dwUnjoinFlags
    )
{
    DWORD dwError = ERROR_SUCCESS;
    NTSTATUS ntStatus = STATUS_SUCCESS;
    PWSTR pwszDCName = NULL;
    PIO_CREDS pCreds = NULL;

    dwError = LsaGetRwDcName(pwszDnsDomainName,
                             FALSE,
                             &pwszDCName);
    BAIL_ON_LSA_ERROR(dwError);

    /* disable the account only if requested */
    if (dwUnjoinFlags & LSAJOIN_ACCT_DELETE)
    {
        if (pwszUserName && pwszUserPassword)
        {
            ntStatus = LwIoCreatePlainCredsW(pwszUserName,
                                             pwszUserDomain,
                                             pwszUserPassword,
                                             &pCreds);
            dwError = LwNtStatusToWin32Error(ntStatus);
            BAIL_ON_LSA_ERROR(dwError);
        }
        else
        {
            ntStatus = LwIoGetActiveCreds(NULL,
                                          &pCreds);
            dwError = LwNtStatusToWin32Error(ntStatus);
            BAIL_ON_LSA_ERROR(dwError);
        }

        ntStatus = LsaDisableMachineAccount(pwszDCName,
                                            pCreds,
                                            pwszMachineSamAccountName);
        dwError = LwNtStatusToWin32Error(ntStatus);
        BAIL_ON_LSA_ERROR(dwError);
    }

error:
    LSA_ASSERT(!ntStatus || dwError);

    LW_SAFE_FREE_MEMORY(pwszDCName);

    if (pCreds)
    {
        LwIoDeleteCreds(pCreds);
    }

    return dwError;
}
Exemplo n.º 3
0
static
DWORD
AD_ConvertMultiStringToStringArray(
    IN PCSTR pszMultiString,
    OUT PSTR** pppszStringArray,
    OUT PDWORD pdwCount
)
{
    DWORD dwError = 0;
    PSTR* ppszStringArray = NULL;
    DWORD dwCount = 0;
    PCSTR pszIter = NULL;
    DWORD dwIndex = 0;

    dwCount = 0;
    for (pszIter = pszMultiString;
            pszIter && *pszIter;
            pszIter += strlen(pszIter) + 1)
    {
        dwCount++;
    }

    if (dwCount)
    {
        dwError = LwAllocateMemory(
                      dwCount * sizeof(*ppszStringArray),
                      OUT_PPVOID(&ppszStringArray));
        BAIL_ON_LSA_ERROR(dwError);
    }

    dwIndex = 0;
    for (pszIter = pszMultiString;
            pszIter && *pszIter;
            pszIter += strlen(pszIter) + 1)
    {
        dwError = LwAllocateString(pszIter, &ppszStringArray[dwIndex]);
        BAIL_ON_LSA_ERROR(dwError);

        dwIndex++;
    }

    LSA_ASSERT(dwIndex == dwCount);

cleanup:

    *pppszStringArray = ppszStringArray;
    *pdwCount = dwCount;

    return dwError;

error:

    LwFreeStringArray(ppszStringArray, dwCount);
    ppszStringArray = NULL;
    dwCount = 0;

    goto cleanup;
}
Exemplo n.º 4
0
DWORD
LsaAdBatchGatherPseudoObjectSidFromGc(
    IN PAD_PROVIDER_DATA pProviderData,
    IN OUT PLSA_AD_BATCH_ITEM pItem,
    IN LSA_AD_BATCH_OBJECT_TYPE ObjectType,
    IN OPTIONAL DWORD dwKeywordValuesCount,
    IN OPTIONAL PSTR* ppszKeywordValues,
    IN HANDLE hDirectory,
    IN LDAPMessage* pMessage
    )
{
    DWORD dwError = 0;

    LSA_ASSERT(LSA_IS_XOR(LsaAdBatchIsDefaultSchemaMode(pProviderData), ppszKeywordValues));

    LSA_ASSERT(!IsSetFlag(pItem->Flags, LSA_AD_BATCH_ITEM_FLAG_HAVE_PSEUDO));

    dwError = LsaAdBatchGatherObjectType(pItem, ObjectType);
    BAIL_ON_LSA_ERROR(dwError);

    if (!pItem->pszSid)
    {
        dwError = LsaAdBatchGatherPseudoSid(
                        &pItem->pszSid,
                        pProviderData,
                        dwKeywordValuesCount,
                        ppszKeywordValues,
                        hDirectory,
                        pMessage);
        BAIL_ON_LSA_ERROR(dwError);
    }

cleanup:
    return dwError;

error:
    SetFlag(pItem->Flags, LSA_AD_BATCH_ITEM_FLAG_ERROR);
    goto cleanup;
}
Exemplo n.º 5
0
DWORD
LsaAdBatchMarshalList(
    IN PLSA_AD_PROVIDER_STATE pState,
    IN PCSTR pszDnsDomainName,
    IN PCSTR pszNetbiosDomainName,
    IN OUT PLSA_LIST_LINKS pBatchItemList,
    IN DWORD dwAvailableCount,
    OUT PLSA_SECURITY_OBJECT* ppObjects,
    OUT PDWORD pdwUsedCount
    )
{
    DWORD dwError = 0;
    PLSA_LIST_LINKS pLinks = NULL;
    DWORD dwIndex = 0;

    for (pLinks = pBatchItemList->Next;
         pLinks != pBatchItemList;
         pLinks = pLinks->Next)
    {
        PLSA_AD_BATCH_ITEM pItem = LW_STRUCT_FROM_FIELD(pLinks, LSA_AD_BATCH_ITEM, BatchItemListLinks);

        if (dwIndex >= dwAvailableCount)
        {
            LSA_ASSERT(FALSE);
            dwError = LW_ERROR_INTERNAL;
            BAIL_ON_LSA_ERROR(dwError);
        }

        dwError = LsaAdBatchMarshal(
                        pState,
                        pszDnsDomainName,
                        pszNetbiosDomainName,
                        pItem,
                        &ppObjects[dwIndex]);
        BAIL_ON_LSA_ERROR(dwError);
        if (ppObjects[dwIndex])
        {
            dwIndex++;
        }
    }

cleanup:
    *pdwUsedCount = dwIndex;
    return dwError;

error:
    goto cleanup;
}
Exemplo n.º 6
0
static
DWORD
LsaAdBatchGatherPseudoSid(
    OUT PSTR* ppszSid,
    IN PAD_PROVIDER_DATA pProviderData,
    IN OPTIONAL DWORD dwKeywordValuesCount,
    IN OPTIONAL PSTR* ppszKeywordValues,
    IN HANDLE hDirectory,
    IN LDAPMessage* pMessage
    )
{
    DWORD dwError = 0;
    PSTR pszSid = NULL;

    if (LsaAdBatchIsDefaultSchemaMode(pProviderData))
    {
        dwError = ADLdap_GetObjectSid(hDirectory, pMessage, &pszSid);
        BAIL_ON_LSA_ERROR(dwError);
    }
    else
    {
        PCSTR pszSidFromKeywords = NULL;

        LSA_ASSERT(ppszKeywordValues);

        pszSidFromKeywords = LsaAdBatchFindKeywordAttributeStatic(
                                    dwKeywordValuesCount,
                                    ppszKeywordValues,
                                    AD_LDAP_BACKLINK_PSEUDO_TAG);
        if (LW_IS_NULL_OR_EMPTY_STR(pszSidFromKeywords))
        {
            dwError = LW_ERROR_INVALID_SID;
            BAIL_ON_LSA_ERROR(dwError);
        }

        dwError = LwAllocateString(pszSidFromKeywords, &pszSid);
        BAIL_ON_LSA_ERROR(dwError);
    }

cleanup:
    *ppszSid = pszSid;
    return dwError;

error:
    LW_SAFE_FREE_STRING(pszSid);
    goto cleanup;
}
Exemplo n.º 7
0
static
DWORD
LsaAdBatchGatherNonSchemaMode(
    IN OUT PLSA_AD_BATCH_ITEM pItem,
    IN DWORD dwKeywordValuesCount,
    IN PSTR* ppszKeywordValues
    )
{
    DWORD dwError = 0;

    switch (pItem->ObjectType)
    {
        case LSA_AD_BATCH_OBJECT_TYPE_USER:
            dwError = LsaAdBatchGatherNonSchemaModeUser(
                            pItem,
                            dwKeywordValuesCount,
                            ppszKeywordValues);
            BAIL_ON_LSA_ERROR(dwError);
            break;
        case LSA_AD_BATCH_OBJECT_TYPE_GROUP:
            dwError = LsaAdBatchGatherNonSchemaModeGroup(
                            pItem,
                            dwKeywordValuesCount,
                            ppszKeywordValues);
            BAIL_ON_LSA_ERROR(dwError);
            break;
        default:
            LSA_ASSERT(FALSE);
            dwError = LW_ERROR_INTERNAL;
            BAIL_ON_LSA_ERROR(dwError);
    }

cleanup:
    return dwError;

error:
    goto cleanup;
}
Exemplo n.º 8
0
DWORD
ADLdap_GetObjectGroupMembership(
    IN PAD_PROVIDER_CONTEXT pContext,
    IN PLSA_SECURITY_OBJECT pObject,
    OUT int* piPrimaryGroupIndex,
    OUT size_t* psNumGroupsFound,
    OUT PLSA_SECURITY_OBJECT** pppGroupInfoList
    )
{
    DWORD dwError =  0;
    PLSA_DM_LDAP_CONNECTION pConn = NULL;
    PSTR pszFullDomainName = NULL;
    INT i = 0;
    PLSA_SECURITY_OBJECT* ppGroupInfoList = NULL;
    size_t sNumGroupsFound = 0;
    int    iPrimaryGroupIndex = -1;
    DWORD gcMembershipCount = 0;
    PSTR* ppGcMembershipList = NULL;
    DWORD dcMembershipCount = 0;
    PSTR* ppDcMembershipList = NULL;
    PLW_HASH_TABLE pGroupHash = NULL;
    LSA_TRUST_DIRECTION trustDirection = LSA_TRUST_DIRECTION_UNKNOWN;
    LSA_TRUST_MODE trustMode = LSA_TRUST_MODE_UNKNOWN;
    DWORD index = 0;
    DWORD totalSidCount = 0;
    PSTR* ppTotalSidList = NULL;

    // If we cannot get dn, then we cannot get DN information for this objects, hence BAIL
    if (LW_IS_NULL_OR_EMPTY_STR(pObject->pszDN))
    {
        dwError = LW_ERROR_NO_SUCH_USER;
        BAIL_ON_LSA_ERROR(dwError);
    }

    dwError = LwLdapConvertDNToDomain(
                 pObject->pszDN,
                 &pszFullDomainName);
    BAIL_ON_LSA_ERROR(dwError);

    // Note that this function is called only for 2-way trusts.  However,
    // the trust could be an external trust or a forest trust.  We can only
    // query the GC if there is a forest trust.

    dwError = AD_DetermineTrustModeandDomainName(
                    pContext->pState,
                    pszFullDomainName,
                    &trustDirection,
                    &trustMode,
                    NULL,
                    NULL);
    BAIL_ON_LSA_ERROR(dwError);

    // We could only have the DN path for the user if (s)he came from a two way
    // trusted domain or the joined domain.
    LSA_ASSERT(LSA_TRUST_DIRECTION_TWO_WAY == trustDirection ||
            LSA_TRUST_DIRECTION_SELF == trustDirection);

    if (trustMode != LSA_TRUST_MODE_EXTERNAL)
    {
        // Get forest info from domain's GC since there is a forest trust.
        // This will only include universal group information.  (The domain
        // global groups will not include membership info in the GC.)
        dwError = LsaDmLdapOpenGc(
                      pContext,
                      pszFullDomainName,
                      &pConn);
        BAIL_ON_LSA_ERROR(dwError);

        dwError = ADLdap_GetAttributeValuesList(
                        pConn,
                        pObject->pszDN,
                        AD_LDAP_MEMBEROF_TAG,
                        TRUE,
                        TRUE,
                        &gcMembershipCount,
                        &ppGcMembershipList);
        BAIL_ON_LSA_ERROR(dwError);

        LsaDmLdapClose(pConn);
        pConn = NULL;
    }

    dwError = LsaDmLdapOpenDc(
                  pContext,
                  pszFullDomainName,
                  &pConn);
    BAIL_ON_LSA_ERROR(dwError);

    dwError = ADLdap_GetAttributeValuesList(
                    pConn,
                    pObject->pszDN,
                    AD_LDAP_MEMBEROF_TAG,
                    TRUE,
                    TRUE,
                    &dcMembershipCount,
                    &ppDcMembershipList);
    BAIL_ON_LSA_ERROR(dwError);

    dwError = LwHashCreate(
                    (dcMembershipCount + gcMembershipCount + 1) * 2,
                    LwHashCaselessStringCompare,
                    LwHashCaselessStringHash,
                    ADLdap_FreeHashStringValue,
                    NULL,
                    &pGroupHash);
    BAIL_ON_LSA_ERROR(dwError);

    for (index = 0; index < gcMembershipCount; index++)
    {
        PSTR pSid = ppGcMembershipList[index];
        if (!LwHashExists(pGroupHash, pSid))
        {
            // Set the value of the hash entry as NULL so this string is not
            // freed with the hash.
            dwError = LwHashSetValue(pGroupHash, pSid, NULL);
            BAIL_ON_LSA_ERROR(dwError);
        }
    }

    for (index = 0; index < dcMembershipCount; index++)
    {
        PSTR pSid = ppDcMembershipList[index];
        if (!LwHashExists(pGroupHash, pSid))
        {
            // Set the value of the hash entry as NULL so this string is not
            // freed with the hash.
            dwError = LwHashSetValue(pGroupHash, pSid, NULL);
            BAIL_ON_LSA_ERROR(dwError);
        }
    }

    if (pObject->type == LSA_OBJECT_TYPE_USER && pObject->userInfo.pszPrimaryGroupSid)
    {
        // Add the pszPrimaryGroupSID entry to the hash
        PSTR pSid = pObject->userInfo.pszPrimaryGroupSid;
        if (!LwHashExists(pGroupHash, pSid))
        {
            // Set the value of the hash entry as NULL so this string is not
            // freed with the hash.
            dwError = LwHashSetValue(pGroupHash, pSid, NULL);
            BAIL_ON_LSA_ERROR(dwError);
        }
    }

    // Check if the user came from a domain other than the computer's domain
    if (LSA_TRUST_DIRECTION_TWO_WAY == trustDirection)
    {
        dwError = ADLdap_AddDomainLocalGroups(
                        pContext,
                        pObject,
                        pGroupHash);
        BAIL_ON_LSA_ERROR(dwError);
    }

    dwError = ADLdap_MoveHashKeysToArray(
                    pGroupHash,
                    &totalSidCount,
                    (PVOID**)(PVOID)&ppTotalSidList);
    BAIL_ON_LSA_ERROR(dwError);
    
    dwError = AD_FindObjectsBySidList(
                    pContext,
                    totalSidCount,
                    ppTotalSidList,
                    &sNumGroupsFound,
                    &ppGroupInfoList);
    BAIL_ON_LSA_ERROR(dwError);

    AD_FilterNullEntries(
            ppGroupInfoList,
            &sNumGroupsFound);

    // Determine primary group index
    if (pObject->type == LSA_OBJECT_TYPE_USER &&
        pObject->userInfo.pszPrimaryGroupSid &&
        ppGroupInfoList &&
        sNumGroupsFound)
    {
        for (i = (INT)sNumGroupsFound - 1; i >= 0; i--)
        {
            if (!strcmp(ppGroupInfoList[i]->pszObjectSid, pObject->userInfo.pszPrimaryGroupSid))
            {
                iPrimaryGroupIndex = i;
                break;
            }
        }
    }

    *psNumGroupsFound = sNumGroupsFound;
    *pppGroupInfoList = ppGroupInfoList;
    *piPrimaryGroupIndex = iPrimaryGroupIndex;

cleanup:
    LwHashSafeFree(&pGroupHash);
    LW_SAFE_FREE_STRING(pszFullDomainName);
    LwFreeStringArray(ppGcMembershipList, gcMembershipCount);
    LwFreeStringArray(ppDcMembershipList, dcMembershipCount);
    // Do not free the string pointers inside. They are borrowed from the
    // hash.
    LW_SAFE_FREE_MEMORY(ppTotalSidList);

    LsaDmLdapClose(pConn);

    return dwError;

error:

    *pppGroupInfoList = NULL;
    *psNumGroupsFound = 0;
    *piPrimaryGroupIndex = -1;

    if ( dwError != LW_ERROR_DOMAIN_IS_OFFLINE )
    {
        LSA_LOG_ERROR("Failed to group memberships of SID=%s. [error code:%u]",
                      pObject->pszObjectSid, dwError);
    }

    ADCacheSafeFreeObjectList((DWORD)sNumGroupsFound, &ppGroupInfoList);

    goto cleanup;
}
Exemplo n.º 9
0
static
DWORD
LsaPcachepLoadPasswordInfoInLock(
    IN LSA_MACHINEPWD_CACHE_HANDLE pPcache
    )
{
    DWORD dwError = 0;
    PLSA_MACHINE_PASSWORD_INFO_A pPasswordInfoA = NULL;
    PLSA_MACHINE_PASSWORD_INFO_W pPasswordInfoW = NULL;

    LSA_ASSERT(!pPcache->bIsLoaded);
    LSA_ASSERT(!pPcache->pEntry);

    //
    // Read information from LSA Pstore
    //

    dwError = LsaPstoreGetPasswordInfoA(
                    pPcache->pszDomainName,
                    &pPasswordInfoA);
    BAIL_ON_LSA_ERROR(dwError);

    dwError = LsaPstoreGetPasswordInfoW(
                    pPcache->pwszDomainName,
                    &pPasswordInfoW);
    BAIL_ON_LSA_ERROR(dwError);

    LSA_ASSERT(pPasswordInfoA->Account.KeyVersionNumber == pPasswordInfoW->Account.KeyVersionNumber);
    LSA_ASSERT(pPasswordInfoA->Account.LastChangeTime == pPasswordInfoW->Account.LastChangeTime);

    //
    // Stash information from LSA Pstore
    //

    dwError = LwAllocateMemory(
                    sizeof(*pPcache->pEntry),
                    OUT_PPVOID(&pPcache->pEntry));
    BAIL_ON_LSA_ERROR(dwError);
    pPcache->pEntry->RefCount = 1;

    dwError = LsaImplFillMachinePasswordInfoA(
                    pPasswordInfoA,
                    &pPcache->pEntry->PasswordInfoA);
    BAIL_ON_LSA_ERROR(dwError);

    dwError = LsaImplFillMachinePasswordInfoW(
                    pPasswordInfoW,
                    &pPcache->pEntry->PasswordInfoW);
    BAIL_ON_LSA_ERROR(dwError);

    pPcache->bIsLoaded = TRUE;

error:
    if (dwError)
    {
        LsaPcachepClearPasswordInfoInLock(pPcache);
    }

    if (pPasswordInfoW)
    {
        LsaPstoreFreePasswordInfoW(pPasswordInfoW);
    }
    if (pPasswordInfoA)
    {
        LsaPstoreFreePasswordInfoA(pPasswordInfoA);
    }

    return dwError;
}
Exemplo n.º 10
0
DWORD
LsaAdBatchBuildQueryForRpc(
    IN PCSTR pszNetbiosDomainName,
    IN LSA_AD_BATCH_QUERY_TYPE QueryType,
    // List of PLSA_AD_BATCH_ITEM
    IN PLSA_LIST_LINKS pFirstLinks,
    IN PLSA_LIST_LINKS pEndLinks,
    OUT PLSA_LIST_LINKS* ppNextLinks,
    IN DWORD dwMaxQueryCount,
    OUT PDWORD pdwQueryCount,
    OUT PSTR** pppszQueryList
    )
{
    DWORD dwError = 0;
    PLSA_LIST_LINKS pLinks = NULL;
    PSTR* ppszQueryList = NULL;
    PLSA_LIST_LINKS pLastLinks = pFirstLinks;
    DWORD dwQueryCount = 0;
    DWORD dwSavedQueryCount = 0;

    pLinks = pFirstLinks;
    for (pLinks = pFirstLinks; pLinks != pEndLinks; pLinks = pLinks->Next)
    {
        PLSA_AD_BATCH_ITEM pBatchItem = LW_STRUCT_FROM_FIELD(pLinks, LSA_AD_BATCH_ITEM, BatchItemListLinks);
        PCSTR pszQueryTerm = NULL;

        switch (QueryType)
        {
            case LSA_AD_BATCH_QUERY_TYPE_BY_SID:
            {
                if (pBatchItem->pszSid)
                {
                    pszQueryTerm = pBatchItem->pszSid;
                }
                else if (QueryType == pBatchItem->QueryTerm.Type)
                {
                    pszQueryTerm = pBatchItem->QueryTerm.pszString;
                }
                break;
            }
            case LSA_AD_BATCH_QUERY_TYPE_BY_NT4:
            {
                if (pBatchItem->pszSamAccountName)
                {
                    pszQueryTerm = pBatchItem->pszSamAccountName;
                }
                else if (QueryType == pBatchItem->QueryTerm.Type)
                {
                    pszQueryTerm = pBatchItem->QueryTerm.pszString;
                }
                break;
            }
            default:
                LSA_ASSERT(FALSE);
                dwError = LW_ERROR_INTERNAL;
                BAIL_ON_LSA_ERROR(dwError);
        }

        if (!LW_IS_NULL_OR_EMPTY_STR(pszQueryTerm))
        {
            DWORD dwNewQueryCount = dwQueryCount + 1;

            if (dwMaxQueryCount && (dwNewQueryCount > dwMaxQueryCount))
            {
                break;
            }
            dwQueryCount = dwNewQueryCount;
        }
    }
    pLastLinks = pLinks;
    dwSavedQueryCount = dwQueryCount;

    if (dwQueryCount < 1)
    {
        goto cleanup;
    }

    dwError = LwAllocateMemory(dwQueryCount*sizeof(*ppszQueryList), (PVOID*)&ppszQueryList);
    BAIL_ON_LSA_ERROR(dwError);

    dwQueryCount = 0;
    // Loop until we reach last links.
    for (pLinks = pFirstLinks; pLinks != pLastLinks; pLinks = pLinks->Next)
    {
        PLSA_AD_BATCH_ITEM pBatchItem = LW_STRUCT_FROM_FIELD(pLinks, LSA_AD_BATCH_ITEM, BatchItemListLinks);

        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);
        }

        switch (QueryType)
        {
            case LSA_AD_BATCH_QUERY_TYPE_BY_SID:
            {
                PCSTR pszUseSid = NULL;
                if (pBatchItem->pszSid)
                {
                    pszUseSid = pBatchItem->pszSid;
                }
                else if (QueryType == pBatchItem->QueryTerm.Type)
                {
                    pszUseSid = pBatchItem->QueryTerm.pszString;
                }
                // We might not have a SID if we failed to find a pseudo.
                if (pszUseSid)
                {
                    dwError = LwAllocateString(pszUseSid,
                                                &ppszQueryList[dwQueryCount++]);
                    BAIL_ON_LSA_ERROR(dwError);
                    pBatchItem->pszQueryMatchTerm = (PSTR)pszUseSid;
                }
                break;
            }

            case LSA_AD_BATCH_QUERY_TYPE_BY_NT4:
            {
                PCSTR pszUseSamAccountName = NULL;
                if (pBatchItem->pszSamAccountName)
                {
                    pszUseSamAccountName = pBatchItem->pszSamAccountName;
                }
                else if (QueryType == pBatchItem->QueryTerm.Type)
                {
                    pszUseSamAccountName = pBatchItem->QueryTerm.pszString;
                }
                if (pszUseSamAccountName)
                {
                    dwError = LwAllocateStringPrintf(
                                    &ppszQueryList[dwQueryCount++],
                                    "%s\\%s",
                                    pszNetbiosDomainName,
                                    pszUseSamAccountName);
                    BAIL_ON_LSA_ERROR(dwError);
                    pBatchItem->pszQueryMatchTerm = (PSTR)pszUseSamAccountName;
                }
                break;
            }
            default:
                LSA_ASSERT(FALSE);
                dwError = LW_ERROR_INTERNAL;
                BAIL_ON_LSA_ERROR(dwError);
        }
    }

    assert(dwSavedQueryCount == dwQueryCount);

cleanup:
    // We handle error here instead of error label
    // because there is a goto cleanup above.
    if (dwError)
    {
        LwFreeStringArray(ppszQueryList, dwSavedQueryCount);
        ppszQueryList = NULL;
        dwQueryCount = 0;
        dwSavedQueryCount = 0;
        pLastLinks = pFirstLinks;
    }

    *pppszQueryList = ppszQueryList;
    *pdwQueryCount = dwQueryCount;
    *ppNextLinks = pLastLinks;

    return dwError;

error:
    // Do not actually handle any errors here.
    goto cleanup;
}
Exemplo n.º 11
0
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;
}
Exemplo n.º 12
0
static
DWORD
LsaAdBatchBuildQueryForPseudoInternal(
    IN PAD_PROVIDER_DATA pProviderData,
    IN BOOLEAN bIsSchemaMode,
    IN OPTIONAL PDWORD pdwDirectoryMode,
    IN LSA_AD_BATCH_QUERY_TYPE QueryType,
    // List of PLSA_AD_BATCH_ITEM
    IN PLSA_LIST_LINKS pFirstLinks,
    IN PLSA_LIST_LINKS pEndLinks,
    OUT PLSA_LIST_LINKS* ppNextLinks,
    IN DWORD dwMaxQuerySize,
    IN DWORD dwMaxQueryCount,
    OUT PDWORD pdwQueryCount,
    OUT PSTR* ppszQuery
    )
{
    DWORD dwError = 0;
    PLSA_LIST_LINKS pNextLinks = NULL;
    DWORD dwQueryCount = 0;
    PSTR pszQuery = NULL;
    PCSTR pszAttributeName = NULL;
    PCSTR pszPrefix = NULL;
    PCSTR pszSuffix = NULL;
    LSA_AD_BATCH_BUILDER_BATCH_ITEM_CONTEXT context = { 0 };

    pszAttributeName = LsaAdBatchBuilderGetPseudoQueryAttributeInternal(
                            pdwDirectoryMode,
                            bIsSchemaMode,
                            QueryType);
    if (!pszAttributeName)
    {
        LSA_ASSERT(FALSE);
        dwError = LW_ERROR_INVALID_PARAMETER;
        BAIL_ON_LSA_ERROR(dwError);
    }

    pszPrefix = LsaAdBatchBuilderGetPseudoQueryPrefixInternal(
                        pProviderData,
                        pdwDirectoryMode,
                        bIsSchemaMode,
                        QueryType,
                        LsaAdBatchGetObjectTypeFromQueryType(QueryType),
                        &pszSuffix);

    if (!pszPrefix || !pszSuffix)
    {
        LSA_ASSERT(FALSE);
        dwError = LW_ERROR_INVALID_PARAMETER;
        BAIL_ON_LSA_ERROR(dwError);
    }

    context.QueryType = QueryType;
    context.bIsForRealObject = FALSE;

    dwError = LsaAdBatchBuilderCreateQuery(
                    pProviderData,
                    pszPrefix,
                    pszSuffix,
                    pszAttributeName,
                    pFirstLinks,
                    pEndLinks,
                    (PVOID*)&pNextLinks,
                    &context,
                    LsaAdBatchBuilderBatchItemGetAttributeValue,
                    LsaAdBatchBuilderGenericFreeValueContext,
                    LsaAdBatchBuilderBatchItemNextItem,
                    dwMaxQuerySize,
                    dwMaxQueryCount,
                    &dwQueryCount,
                    &pszQuery);
    BAIL_ON_LSA_ERROR(dwError);

cleanup:
    *ppNextLinks = pNextLinks;
    *pdwQueryCount = dwQueryCount;
    *ppszQuery = pszQuery;
    return dwError;

error:
    // set output on cleanup
    pNextLinks = pFirstLinks;
    dwQueryCount = 0;
    LW_SAFE_FREE_STRING(pszQuery);
    goto cleanup;
}
Exemplo n.º 13
0
DWORD
AD_BuildHomeDirFromTemplate(
    PLSA_AD_PROVIDER_STATE pState,
    PCSTR pszHomedirTemplate,
    PCSTR pszNetBIOSDomainName,
    PCSTR pszSamAccountName,
    PSTR* ppszHomedir
    )
{
    DWORD dwError = 0;
    PSTR pszHomedirPrefix = NULL;
    PSTR pszHomedir = NULL;
    DWORD dwOffset = 0;
    PCSTR pszIterTemplate = pszHomedirTemplate;
    DWORD dwBytesAllocated = 0;
    DWORD dwNetBIOSDomainNameLength = 0;
    DWORD dwSamAccountNameLength = 0;
    DWORD dwHomedirPrefixLength = 0;
    PSTR pszHostName = NULL;
    DWORD dwHostNameLength = 0;
    CHAR szEscapedPercent[2] = "%";
    DWORD dwEscapedPercentLength = 0;

    BAIL_ON_INVALID_STRING(pszHomedirTemplate);
    BAIL_ON_INVALID_STRING(pszNetBIOSDomainName);
    BAIL_ON_INVALID_STRING(pszSamAccountName);

    if (strstr(pszHomedirTemplate, "%H"))
    {
        dwError = AD_GetHomedirPrefixPath(pState, &pszHomedirPrefix);
        BAIL_ON_LSA_ERROR(dwError);

        BAIL_ON_INVALID_STRING(pszHomedirPrefix);

        dwHomedirPrefixLength = strlen(pszHomedirPrefix);
    }

    if (strstr(pszHomedirTemplate, "%L"))
    {
        dwError = LsaDnsGetHostInfo(&pszHostName);
        BAIL_ON_LSA_ERROR(dwError);

        BAIL_ON_INVALID_STRING(pszHostName);

        dwHostNameLength = strlen(pszHostName);
    }

    if (strstr(pszHomedirTemplate, "%%"))
    {
        dwEscapedPercentLength = strlen(szEscapedPercent);
    }

    dwNetBIOSDomainNameLength = strlen(pszNetBIOSDomainName);
    dwSamAccountNameLength = strlen(pszSamAccountName);

    // Handle common case where we might use all replacements.
    dwBytesAllocated = (strlen(pszHomedirTemplate) +
                        dwNetBIOSDomainNameLength +
                        dwSamAccountNameLength +
                        dwHomedirPrefixLength +
                        dwHostNameLength +
                        dwEscapedPercentLength +
                        1);

    dwError = LwAllocateMemory(
                    sizeof(CHAR) * dwBytesAllocated,
                    (PVOID*)&pszHomedir);
    BAIL_ON_LSA_ERROR(dwError);

    while (pszIterTemplate[0])
    {
        // Do not count the terminating NULL as "available".
        DWORD dwBytesRemaining = dwBytesAllocated - dwOffset - 1;
        PCSTR pszInsert = NULL;
        DWORD dwInsertLength = 0;
        BOOLEAN bNeedUpper = FALSE;
        BOOLEAN bNeedLower = FALSE;

        LSA_ASSERT(dwOffset < dwBytesAllocated);

        if (pszIterTemplate[0] == '%')
        {
            switch (pszIterTemplate[1])
            {
                case 'D':
                    pszInsert = pszNetBIOSDomainName;
                    dwInsertLength = dwNetBIOSDomainNameLength;
                    bNeedUpper = TRUE;
                    break;
                case 'U':
                    pszInsert = pszSamAccountName;
                    dwInsertLength = dwSamAccountNameLength;
                    bNeedLower = TRUE;
                    break;
                case 'H':
                    pszInsert = pszHomedirPrefix;
                    dwInsertLength = dwHomedirPrefixLength;
                    break;
                case 'L':
                    pszInsert = pszHostName;
                    dwInsertLength = dwHostNameLength;
                    break;
                case '%':
                    pszInsert = szEscapedPercent;
                    dwInsertLength = dwEscapedPercentLength;
                    break;
                default:
                    dwError = LW_ERROR_INVALID_HOMEDIR_TEMPLATE;
                    BAIL_ON_LSA_ERROR(dwError);
            }
            LSA_ASSERT(!(bNeedUpper && bNeedLower));
            pszIterTemplate += 2;
        }
        else
        {
            PCSTR pszEnd = strchr(pszIterTemplate, '%');
            if (!pszEnd)
            {
                dwInsertLength = strlen(pszIterTemplate);
            }
            else
            {
                dwInsertLength = pszEnd - pszIterTemplate;
            }
            pszInsert = pszIterTemplate;
            pszIterTemplate += dwInsertLength;
        }

        if (dwBytesRemaining < dwInsertLength)
        {
            // We will increment by at least a minimum amount.
            DWORD dwAllocate = LSA_MAX(dwInsertLength - dwBytesRemaining, 64);
            PSTR pszNewHomedir = NULL;
            dwError = LwReallocMemory(
                            pszHomedir,
                            (PVOID*)&pszNewHomedir,
                            dwBytesAllocated + dwAllocate);
            BAIL_ON_LSA_ERROR(dwError);
            pszHomedir = pszNewHomedir;
            dwBytesAllocated += dwAllocate;
        }
        memcpy(pszHomedir + dwOffset,
               pszInsert,
               dwInsertLength);
        if (bNeedUpper)
        {
            LwStrnToUpper(pszHomedir + dwOffset, dwInsertLength);
        }
        else if (bNeedLower)
        {
            LwStrnToLower(pszHomedir + dwOffset, dwInsertLength);
        }
        dwOffset += dwInsertLength;
    }

    // We should still have enough room for NULL.
    LSA_ASSERT(dwOffset < dwBytesAllocated);

    pszHomedir[dwOffset] = 0;
    dwOffset++;

    *ppszHomedir = pszHomedir;

cleanup:
    LW_SAFE_FREE_STRING(pszHomedirPrefix);
    LW_SAFE_FREE_STRING(pszHostName);

    return dwError;

error:
    *ppszHomedir = NULL;
    LW_SAFE_FREE_MEMORY(pszHomedir);

    goto cleanup;
}
Exemplo n.º 14
0
static
DWORD
AD_GetComputerDn(
    IN OPTIONAL PCSTR pszDnsDomainName,
    OUT PSTR* ppszComputerDn
    )
{
    DWORD dwError = 0;
    PSTR pszComputerDn = NULL;
    PLSA_MACHINE_PASSWORD_INFO_A pPasswordInfo = NULL;
    PSTR pszUserPrincipalName = NULL;
    PCSTR pszKrb5CachePath = "MEMORY:lsass_get_computer_dn";
    PSTR pszPreviousKrb5CachePath = NULL;
    HANDLE hDirectory = NULL;
    // Lock to protect the cache:
    static pthread_mutex_t mutex = PTHREAD_MUTEX_INITIALIZER;
    BOOLEAN isLocked = FALSE;
    BOOLEAN needDestroyCache = FALSE;

    //
    // In the future, if we have cached DN information in the domain state,
    // we will use that.  However, since that does not currently exist,
    // we will fetch it directly.
    //
    // Since this code should work regardless of the internal state,
    // we will need to use a private memory cache to establish credentials.
    //

    dwError = AD_GetMachinePasswordInfoA(pszDnsDomainName, &pPasswordInfo);
    BAIL_ON_LSA_ERROR(dwError);

    dwError = LwAllocateStringPrintf(
                    &pszUserPrincipalName,
                    "%s@%s",
                    pPasswordInfo->Account.SamAccountName,
                    pPasswordInfo->Account.DnsDomainName);
    BAIL_ON_LSA_ERROR(dwError);

    dwError = LwMapErrnoToLwError(pthread_mutex_lock(&mutex));
    BAIL_ON_LSA_ERROR(dwError);
    isLocked = TRUE;

    dwError = LwKrb5InitializeCredentials(
                    pszUserPrincipalName,
                    pPasswordInfo->Password,
                    pszKrb5CachePath,
                    NULL);
    BAIL_ON_LSA_ERROR(dwError);
    needDestroyCache = TRUE;

    dwError = LwKrb5SetThreadDefaultCachePath(pszKrb5CachePath, &pszPreviousKrb5CachePath);
    BAIL_ON_LSA_ERROR(dwError);

    dwError = LsaLdapOpenDirectoryDomain(
                    pPasswordInfo->Account.DnsDomainName,
                    NULL,
                    0,
                    &hDirectory);
    BAIL_ON_LSA_ERROR(dwError);

    dwError = AD_RawFindComputerDn(
                    hDirectory,
                    pPasswordInfo->Account.DnsDomainName,
                    pPasswordInfo->Account.SamAccountName,
                    &pszComputerDn);
    BAIL_ON_LSA_ERROR(dwError);

error:
    if (dwError)
    {
        LW_SAFE_FREE_STRING(pszComputerDn);
    }

    if (needDestroyCache)
    {
        LwKrb5DestroyCache(pszKrb5CachePath);
    }

    if (pszPreviousKrb5CachePath)
    {
        LwKrb5SetThreadDefaultCachePath(pszPreviousKrb5CachePath, NULL);
    }

    if (isLocked)
    {
        int localError = pthread_mutex_unlock(&mutex);
        LSA_ASSERT(!localError);
    }

    LsaSrvFreeMachinePasswordInfoA(pPasswordInfo);
    LW_SAFE_FREE_STRING(pszUserPrincipalName);
    LW_SAFE_FREE_STRING(pszPreviousKrb5CachePath);

    if (hDirectory)
    {
        LwLdapCloseDirectory(hDirectory);
    }

    *ppszComputerDn = pszComputerDn;

    return dwError;
}
Exemplo n.º 15
0
static
DWORD
LsaAdBatchGatherRealUser(
    IN OUT PLSA_AD_BATCH_ITEM pItem,
    IN HANDLE hDirectory,
    IN LDAPMessage* pMessage
    )
{
    DWORD dwError = 0;

    dwError = LwLdapGetUInt32(
                hDirectory,
                pMessage,
                AD_LDAP_PRIMEGID_TAG,
                &pItem->UserInfo.dwPrimaryGroupRid);
    BAIL_ON_LSA_ERROR(dwError);


    LSA_ASSERT(!pItem->UserInfo.pszUserPrincipalName);

    dwError = LwLdapGetString(
                    hDirectory,
                    pMessage,
                    AD_LDAP_UPN_TAG,
                    &pItem->UserInfo.pszUserPrincipalName);
    BAIL_ON_LSA_ERROR(dwError);

    if (pItem->UserInfo.pszUserPrincipalName)
    {
        // Do not touch the non-realm part, just the realm part
        // to make sure the realm conforms to spec.
        LsaPrincipalRealmToUpper(pItem->UserInfo.pszUserPrincipalName);
    }

    dwError = LwLdapGetUInt32(
                    hDirectory,
                    pMessage,
                    AD_LDAP_USER_CTRL_TAG,
                    &pItem->UserInfo.UserAccountControl);
    if (dwError == LW_ERROR_INVALID_LDAP_ATTR_VALUE)
    {
        LSA_LOG_VERBOSE(
                "User %s has an invalid value for the userAccountControl"
                " attribute. Please check that it is set and that the "
                "machine account has permission to read it. Assuming 0x%x",
                pItem->pszSid, LSA_AD_UF_DEFAULT);
        pItem->UserInfo.UserAccountControl = LSA_AD_UF_DEFAULT;
        dwError = 0;
    }
    BAIL_ON_LSA_ERROR(dwError);

    dwError = LwLdapGetUInt64(
                    hDirectory,
                    pMessage,
                    AD_LDAP_ACCOUT_EXP_TAG,
                    &pItem->UserInfo.AccountExpires);
    if (dwError == LW_ERROR_INVALID_LDAP_ATTR_VALUE)
    {
        LSA_LOG_VERBOSE(
                "User %s has an invalid value for the accountExpires"
                " attribute. Please check that it is set and that the "
                "machine account has permission to read it.",
                pItem->pszSid);
        pItem->UserInfo.AccountExpires = 0;
        dwError = 0;
    }
    BAIL_ON_LSA_ERROR(dwError);

    dwError = LwLdapGetUInt64(
                    hDirectory,
                    pMessage,
                    AD_LDAP_PWD_LASTSET_TAG,
                    &pItem->UserInfo.PasswordLastSet);
    if (dwError == LW_ERROR_INVALID_LDAP_ATTR_VALUE)
    {
        LSA_LOG_VERBOSE(
                "User %s has an invalid value for the passwordLastSet"
                " attribute. Please check that it is set and that the "
                "machine account has permission to read it.",
                pItem->pszSid);
        dwError = ADGetCurrentNtTime(&pItem->UserInfo.PasswordLastSet);
    }
    BAIL_ON_LSA_ERROR(dwError);

    LSA_ASSERT(!pItem->UserInfo.pszDisplayName);

    dwError = LwLdapGetString(
                    hDirectory,
                    pMessage,
                    AD_LDAP_DISPLAY_NAME_TAG,
                    &pItem->UserInfo.pszDisplayName);
    BAIL_ON_LSA_ERROR(dwError);

    dwError = LwLdapGetString(
                    hDirectory,
                    pMessage,
                    AD_LDAP_WINDOWSHOMEFOLDER_TAG,
                    &pItem->UserInfo.pszWindowsHomeFolder);
    BAIL_ON_LSA_ERROR(dwError);

    SetFlag(pItem->Flags, LSA_AD_BATCH_ITEM_FLAG_ACCOUNT_INFO_KNOWN);

cleanup:
    return dwError;

error:
    goto cleanup;
}
Exemplo n.º 16
0
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;
}
Exemplo n.º 17
0
DWORD
LsaAdBatchGatherPseudoObject(
    IN PAD_PROVIDER_DATA pProviderData,
    IN OUT PLSA_AD_BATCH_ITEM pItem,
    IN LSA_AD_BATCH_OBJECT_TYPE ObjectType,
    IN BOOLEAN bIsSchemaMode,
    IN OPTIONAL DWORD dwKeywordValuesCount,
    IN OPTIONAL PSTR* ppszKeywordValues,
    IN HANDLE hDirectory,
    IN LDAPMessage* pMessage
    )
{
    DWORD dwError = 0;
    PSTR pszComparePseudoDn = NULL;

    LSA_ASSERT(LSA_IS_XOR(LsaAdBatchIsDefaultSchemaMode(pProviderData), ppszKeywordValues));

    SetFlag(pItem->Flags, LSA_AD_BATCH_ITEM_FLAG_HAVE_PSEUDO);

    dwError = LsaAdBatchGatherObjectType(pItem, ObjectType);
    BAIL_ON_LSA_ERROR(dwError);

    if (!pItem->pszSid)
    {
        dwError = LsaAdBatchGatherPseudoSid(
                        &pItem->pszSid,
                        pProviderData,
                        dwKeywordValuesCount,
                        ppszKeywordValues,
                        hDirectory,
                        pMessage);
        BAIL_ON_LSA_ERROR(dwError);
    }
    if (!pItem->pszPseudoDn)
    {
        dwError = LwLdapGetString(
                        hDirectory,
                        pMessage,
                        AD_LDAP_DN_TAG,
                        &pItem->pszPseudoDn);
        BAIL_ON_LSA_ERROR(dwError);
        if (LW_IS_NULL_OR_EMPTY_STR(pItem->pszPseudoDn))
        {
            dwError = LW_ERROR_DATA_ERROR;
            BAIL_ON_LSA_ERROR(dwError);
        }
    }
    pItem->FoundPseudoCount++;
    if (pItem->FoundPseudoCount > 1)
    {
        dwError = LwLdapGetString(
                        hDirectory,
                        pMessage,
                        AD_LDAP_DN_TAG,
                        &pszComparePseudoDn);
        BAIL_ON_LSA_ERROR(dwError);

        LSA_LOG_WARNING("Found pseudo object %s that conflicts with pseudo object %s for SID %s",
            LSA_SAFE_LOG_STRING(pItem->pszPseudoDn),
            LSA_SAFE_LOG_STRING(pszComparePseudoDn),
            LSA_SAFE_LOG_STRING(pItem->pszSid));
        dwError = LW_ERROR_DUPLICATE_USER_OR_GROUP;
        BAIL_ON_LSA_ERROR(dwError);
    }

    if (bIsSchemaMode)
    {
        dwError = LsaAdBatchGatherSchemaMode(
                        pItem,
                        hDirectory,
                        pMessage);
        BAIL_ON_LSA_ERROR(dwError);

        // In default Schema mode, originally the following portion of code tries to gather real use information
        // using 'pMessage' obtained during pseudo objects lookup
        // However, a GC search is used on pseudo objects lookup,
        // Some of the attributes, such as user-specific attributes, i.e. 'accountExpires' etc.
        // are not available in GC. We still need to look up real objects in that particular domain for those missing attributes
        // Hence, we do not gather real object information until we actually do a real object lookup later on.
#if 0
        if (LsaAdBatchIsDefaultSchemaMode() &&
            !IsSetFlag(pItem->Flags, LSA_AD_BATCH_ITEM_FLAG_HAVE_REAL))
        {
            dwError = LsaAdBatchGatherRealObject(
                            pItem,
                            ObjectType,
                            NULL,
                            hDirectory,
                            pMessage);
            BAIL_ON_LSA_ERROR(dwError);
        }
#endif
    }
    else
    {
        dwError = LsaAdBatchGatherNonSchemaMode(
                        pItem,
                        dwKeywordValuesCount,
                        ppszKeywordValues);
        BAIL_ON_LSA_ERROR(dwError);
    }

cleanup:
    LW_SAFE_FREE_STRING(pszComparePseudoDn);
    return dwError;

error:
    SetFlag(pItem->Flags, LSA_AD_BATCH_ITEM_FLAG_ERROR);
    goto cleanup;
}
Exemplo n.º 18
0
DWORD
LsaAdBatchGatherRealObjectInternal(
    IN PAD_PROVIDER_DATA pProviderData,
    IN OUT PLSA_AD_BATCH_ITEM pItem,
    IN OPTIONAL PDWORD pdwDirectoryMode,
    IN OPTIONAL ADConfigurationMode* pAdMode,
    IN LSA_AD_BATCH_OBJECT_TYPE ObjectType,
    IN OUT OPTIONAL PSTR* ppszSid,
    IN HANDLE hDirectory,
    IN LDAPMessage* pMessage
    )
{
    DWORD dwError = 0;
    DWORD dwDirectoryMode = pdwDirectoryMode == NULL ? pProviderData->dwDirectoryMode : *pdwDirectoryMode;
    ADConfigurationMode adMode = pAdMode == NULL ? pProviderData->adConfigurationMode : *pAdMode;

    SetFlag(pItem->Flags, LSA_AD_BATCH_ITEM_FLAG_HAVE_REAL);

    dwError = LsaAdBatchGatherObjectType(pItem, ObjectType);
    BAIL_ON_LSA_ERROR(dwError);

    if (!pItem->pszSid)
    {
        if (ppszSid)
        {
            LSA_XFER_STRING(*ppszSid, pItem->pszSid);
        }
        else
        {
            dwError = ADLdap_GetObjectSid(hDirectory, pMessage, &pItem->pszSid);
            BAIL_ON_LSA_ERROR(dwError);
        }
    }

    if (LW_IS_NULL_OR_EMPTY_STR(pItem->pszSid))
    {
        dwError = LW_ERROR_DATA_ERROR;
        BAIL_ON_LSA_ERROR(dwError);
    }

    LSA_ASSERT(!pItem->pszSamAccountName);

    dwError = LwLdapGetString(
                    hDirectory,
                    pMessage,
                    AD_LDAP_SAM_NAME_TAG,
                    &pItem->pszSamAccountName);
    BAIL_ON_LSA_ERROR(dwError);
    if (LW_IS_NULL_OR_EMPTY_STR(pItem->pszSamAccountName))
    {
        dwError = LW_ERROR_DATA_ERROR;
        BAIL_ON_LSA_ERROR(dwError);
    }

    LSA_ASSERT(!pItem->pszDn);

    dwError = LwLdapGetString(
                    hDirectory,
                    pMessage,
                    AD_LDAP_DN_TAG,
                    &pItem->pszDn);
    BAIL_ON_LSA_ERROR(dwError);
    if (LW_IS_NULL_OR_EMPTY_STR(pItem->pszDn))
    {
        dwError = LW_ERROR_DATA_ERROR;
        BAIL_ON_LSA_ERROR(dwError);
    }

    // Handle cases where real contains pseudo.
    if (DEFAULT_MODE == dwDirectoryMode && SchemaMode == adMode)
    {
        // But only if we are not being called by a pseudo
        // lookup for default schema mode.
        if (!IsSetFlag(pItem->Flags, LSA_AD_BATCH_ITEM_FLAG_HAVE_PSEUDO))
        {
            SetFlag(pItem->Flags, LSA_AD_BATCH_ITEM_FLAG_HAVE_PSEUDO);
            dwError = LsaAdBatchGatherSchemaMode(
                            pItem,
                            hDirectory,
                            pMessage);
            BAIL_ON_LSA_ERROR(dwError);
        }
    }
    else if (UNPROVISIONED_MODE == dwDirectoryMode)
    {
        dwError = LsaAdBatchGatherUnprovisionedMode(
                        pItem,
                        hDirectory,
                        pMessage);
        BAIL_ON_LSA_ERROR(dwError);
    }

    // User object has some AD-specific fields.
    if (LSA_AD_BATCH_OBJECT_TYPE_USER == pItem->ObjectType)
    {
        dwError = LsaAdBatchGatherRealUser(
                        pItem,
                        hDirectory,
                        pMessage);
        BAIL_ON_LSA_ERROR(dwError);
    }

cleanup:
    return dwError;

error:
    SetFlag(pItem->Flags, LSA_AD_BATCH_ITEM_FLAG_ERROR);
    goto cleanup;
}