Beispiel #1
0
static
DWORD
LsaAdBatchMarshalUserInfoFixShell(
    IN PLSA_AD_PROVIDER_STATE pState,
    IN OUT PSTR* ppszShell
    )
{
    DWORD dwError = 0;
    PSTR pszShell = *ppszShell;

    if (LW_IS_NULL_OR_EMPTY_STR(pszShell))
    {
        dwError = AD_GetUnprovisionedModeShell(
                      pState,
                      &pszShell);
        BAIL_ON_LSA_ERROR(dwError);
        BAIL_ON_INVALID_STRING(pszShell);
    }

cleanup:
    *ppszShell = pszShell;
    return dwError;

error:
    goto cleanup;
}
Beispiel #2
0
static
DWORD
AD_CheckList(
    PCSTR pszNeedle,
    PCSTR pszaHaystack,
    PBOOLEAN pbFoundIt
)
{
    DWORD dwError = 0;
    BOOLEAN bFoundIt = FALSE;
    PCSTR pszCurrent = NULL;

    BAIL_ON_INVALID_STRING(pszNeedle);

    pszCurrent = pszaHaystack;
    if (pszCurrent)
    {
        while (*pszCurrent)
        {
            if (!strcasecmp(pszCurrent, pszNeedle))
            {
                bFoundIt = TRUE;
                goto cleanup;
            }
            pszCurrent = pszCurrent + strlen(pszCurrent) + 1;
        }
    }

cleanup:
    *pbFoundIt = bFoundIt;
    return dwError;

error:
    goto cleanup;
}
Beispiel #3
0
static
DWORD
SetMachineSid(
    PSTR pszSid
    )
{
    DWORD dwError = 0;
    HANDLE hLsaConnection = NULL;

    BAIL_ON_INVALID_STRING(pszSid);

    dwError = LsaOpenServer(&hLsaConnection);
    BAIL_ON_LSA_ERROR(dwError);

    dwError = LsaSetMachineSid(hLsaConnection,
                               pszSid);
    BAIL_ON_LSA_ERROR(dwError);

    fprintf(stdout, "Successfully set machine SID to %s\n", pszSid);

cleanup:
    if (hLsaConnection != (HANDLE)NULL) {
        LsaCloseServer(hLsaConnection);
    }

    return dwError;

error:
    goto cleanup;
}
Beispiel #4
0
static
DWORD
LsaAdBatchMarshalUserInfoFixHomeDirectory(
    IN PLSA_AD_PROVIDER_STATE pState,
    IN OUT PSTR* ppszHomeDirectory,
    IN PCSTR pszNetbiosDomainName,
    IN PCSTR pszSamAccountName
    )
{
    DWORD dwError = 0;
    PSTR pszHomeDirectory = *ppszHomeDirectory;
    PSTR pszNewHomeDirectory = NULL;

    if (LW_IS_NULL_OR_EMPTY_STR(pszHomeDirectory))
    {
        dwError = AD_GetUnprovisionedModeHomedirTemplate(
                      pState,
                      &pszHomeDirectory);
        BAIL_ON_LSA_ERROR(dwError);
        BAIL_ON_INVALID_STRING(pszHomeDirectory);
    }

    if (strstr(pszHomeDirectory, "%"))
    {
        dwError = AD_BuildHomeDirFromTemplate(
                      pState,
                      pszHomeDirectory,
                      pszNetbiosDomainName,
                      pszSamAccountName,
                      &pszNewHomeDirectory);
        if (dwError)
        {
            // If we encounter a problem with fixing up the shell, leave the user object with the actual
            // value stored in AD and log the problem.
            LSA_LOG_INFO("While processing information for user (%s), an invalid homedir value was detected (homedir: '%s')",
                         LSA_SAFE_LOG_STRING(pszSamAccountName),
                         LSA_SAFE_LOG_STRING(pszHomeDirectory));
            dwError = 0;
            goto cleanup;
        }

        LW_SAFE_FREE_STRING(pszHomeDirectory);
        LSA_XFER_STRING(pszNewHomeDirectory, pszHomeDirectory);
    }

    LwStrCharReplace(pszHomeDirectory, ' ', '_');

cleanup:
    *ppszHomeDirectory = pszHomeDirectory;
    return dwError;

error:
    goto cleanup;
}
Beispiel #5
0
static
DWORD
LocalCfgSetHomedirPrefix(
    PLOCAL_CONFIG pConfig,
    PCSTR          pszName,
    PCSTR          pszValue
    )
{
    DWORD dwError = 0;
    PSTR pszHomedirPrefix = NULL;

    BAIL_ON_INVALID_STRING(pszValue);

    dwError = LwAllocateString(
                pszValue,
                &pszHomedirPrefix);
    BAIL_ON_UP_ERROR(dwError);

    LwStripWhitespace(pszHomedirPrefix, TRUE, TRUE);

    BAIL_ON_INVALID_STRING(pszHomedirPrefix);

    if (*pszHomedirPrefix != '/')
    {
        LOG_ERROR("Invalid home directory prefix [%s]", pszHomedirPrefix);
        goto error;
    }

    LW_SAFE_FREE_STRING(pConfig->pszHomedirPrefix);
    pConfig->pszHomedirPrefix = pszHomedirPrefix;

cleanup:

    return 0;

error:

    LW_SAFE_FREE_STRING(pszHomedirPrefix);

    goto cleanup;
}
Beispiel #6
0
LSASS_API
DWORD
LsaDeleteGroupByName(
    HANDLE hLsaConnection,
    PCSTR  pszName
    )
{
    DWORD dwError = 0;
    PVOID pGroupInfo = NULL;
    DWORD dwGroupInfoLevel = 0;

    if (geteuid() != 0)
    {
        dwError = LW_ERROR_ACCESS_DENIED;
        BAIL_ON_LSA_ERROR(dwError);
    }

    BAIL_ON_INVALID_HANDLE(hLsaConnection);
    BAIL_ON_INVALID_STRING(pszName);

    dwError = LsaValidateGroupName(pszName);
    BAIL_ON_LSA_ERROR(dwError);

    dwError = LsaFindGroupByName(
                    hLsaConnection,
                    pszName,
                    0,
                    dwGroupInfoLevel,
                    &pGroupInfo);
    BAIL_ON_LSA_ERROR(dwError);

    dwError = LsaDeleteGroupById(
                    hLsaConnection,
                    ((PLSA_GROUP_INFO_0)pGroupInfo)->gid);
    BAIL_ON_LSA_ERROR(dwError);

cleanup:

    if (pGroupInfo) {
        LsaFreeGroupInfo(dwGroupInfoLevel, pGroupInfo);
    }

    return dwError;

error:

    goto cleanup;
}
Beispiel #7
0
static
DWORD
ValidateParameters(
    PCSTR pszSid
    )
{
    DWORD dwError = 0;
    NTSTATUS ntStatus = STATUS_SUCCESS;
    PSID pSid = NULL;

    BAIL_ON_INVALID_STRING(pszSid);

    ntStatus = RtlAllocateSidFromCString(&pSid,
                                         pszSid);
    if (ntStatus != STATUS_SUCCESS)
    {
        dwError = LW_ERROR_INVALID_PARAMETER;
        BAIL_ON_LSA_ERROR(dwError);
    }

    if (RtlValidSid(pSid) &&
        pSid->SubAuthorityCount != 4)
    {
        dwError = LW_ERROR_INVALID_PARAMETER;
        BAIL_ON_LSA_ERROR(dwError);
    }

cleanup:
    if (pSid)
    {
        RTL_FREE(&pSid);
    }

    return dwError;

error:
    goto cleanup;
}
Beispiel #8
0
static
DWORD
LocalCfgSetDefaultLoginShell(
    PLOCAL_CONFIG pConfig,
    PCSTR          pszName,
    PCSTR          pszValue
    )
{
    DWORD dwError = 0;
    PSTR  pszLoginShell = NULL;

    BAIL_ON_INVALID_STRING(pszValue);

    if (access(pszValue, X_OK) != 0)
    {
        dwError = LW_ERROR_INVALID_PARAMETER;
        BAIL_ON_UP_ERROR(dwError);
    }

    dwError = LwAllocateString(
                    pszValue,
                    &pszLoginShell);
    BAIL_ON_UP_ERROR(dwError);

    LW_SAFE_FREE_STRING(pConfig->pszLoginShell);

    pConfig->pszLoginShell = pszLoginShell;

cleanup:

    return dwError;

error:

    LW_SAFE_FREE_STRING(pszLoginShell);

    goto cleanup;
}
static
DWORD
ValidateParameters(
    PCSTR pszName
    )
{
    DWORD dwError = 0;

    BAIL_ON_INVALID_STRING(pszName);

    if (strlen(pszName) > 15)
    {
        fprintf(stdout, "Machine name can have up to 15 characters\n");

        dwError = LW_ERROR_INVALID_PARAMETER;
        BAIL_ON_LSA_ERROR(dwError);
    }

cleanup:
    return dwError;

error:
    goto cleanup;
}
Beispiel #10
0
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;
}
Beispiel #11
0
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;
}
Beispiel #12
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;
}
Beispiel #13
0
DWORD
LsaSetSMBCreds(
    IN PCSTR pszUserPrincipalName,
    IN PCSTR pszPassword,
    IN BOOLEAN bSetDefaultCachePath,
    OUT PLSA_CREDS_FREE_INFO* ppFreeInfo
    )
{
    DWORD dwError = 0;
    krb5_error_code ret = 0;
    PSTR pszNewCachePath = NULL;
    PCSTR  pszCacheName = NULL;
    PCSTR  pszCacheType = NULL;
    krb5_context ctx = 0;
    krb5_ccache cc = 0;
    LW_PIO_CREDS pNewCreds = NULL;
    LW_PIO_CREDS pOldCreds = NULL;
    PLSA_CREDS_FREE_INFO pFreeInfo = NULL;
    PSTR pszOldCachePath = NULL;
    BOOLEAN bSwitchedPath = FALSE;

    BAIL_ON_INVALID_POINTER(ppFreeInfo);
    BAIL_ON_INVALID_STRING(pszUserPrincipalName);

    ret = krb5_init_context(&ctx);
    BAIL_ON_KRB_ERROR(ctx, ret);

    /* Generates a new filed based credentials cache in /tmp. The file will
     * be owned by root and only accessible by root.
     */
    ret = krb5_cc_new_unique(
            ctx,
            "FILE",
            "hint",
            &cc);
    BAIL_ON_KRB_ERROR(ctx, ret);

    pszCacheType = krb5_cc_get_type(ctx, cc);
    pszCacheName = krb5_cc_get_name(ctx, cc);
    dwError = LwAllocateStringPrintf(&pszNewCachePath, "%s:%s", pszCacheType, pszCacheName);
    BAIL_ON_LSA_ERROR(dwError);

    dwError = LwKrb5GetTgt(
                pszUserPrincipalName,
                pszPassword,
                pszNewCachePath,
                NULL);
    BAIL_ON_LSA_ERROR(dwError);

    if (bSetDefaultCachePath)
    {
        LSA_LOG_DEBUG("Switching default credentials path for new access token"); 
        dwError = LwKrb5SetThreadDefaultCachePath(
                  pszNewCachePath,
                  &pszOldCachePath);
        BAIL_ON_LSA_ERROR(dwError);
        bSwitchedPath = TRUE;
    }

    dwError = LwIoCreateKrb5CredsA(
        pszUserPrincipalName,
        pszNewCachePath,
        &pNewCreds);
    BAIL_ON_LSA_ERROR(dwError);

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

    dwError = LwIoGetThreadCreds(&pOldCreds);
    BAIL_ON_LSA_ERROR(dwError);

    dwError = LwIoSetThreadCreds(pNewCreds);
    BAIL_ON_LSA_ERROR(dwError);

    pFreeInfo->ctx = ctx;
    pFreeInfo->cc = cc;
    pFreeInfo->pRestoreCreds = pOldCreds;
    pFreeInfo->pszRestoreCache = pszOldCachePath;
    pFreeInfo->bKrbCreds = TRUE;
    pOldCreds = NULL;

cleanup:
    *ppFreeInfo = pFreeInfo;
    if (pOldCreds != NULL)
    {
        LwIoDeleteCreds(pOldCreds);
    }

    if (pNewCreds != NULL)
    {
        LwIoDeleteCreds(pNewCreds);
    }
    LW_SAFE_FREE_STRING(pszNewCachePath);

    return dwError;

error:
    if (ctx != NULL)
    {
        if (cc != NULL)
        {
            krb5_cc_destroy(ctx, cc);
        }
        krb5_free_context(ctx);
    }

    if (pFreeInfo)
    {
        LwFreeMemory(pFreeInfo);
        pFreeInfo = NULL;
    }
    if (bSwitchedPath)
    {
        LwKrb5SetThreadDefaultCachePath(
                  pszOldCachePath,
                  NULL);
        LW_SAFE_FREE_STRING(pszOldCachePath);
    }

    goto cleanup;
}
Beispiel #14
0
//Convert to seconds string of form ##s, ##m, ##h, or ##d
//where s,m,h,d = seconds, minutes, hours, days.
DWORD
LsaParseDateString(
    PCSTR  pszTimeInterval,
    PDWORD pdwTimeInterval
    )
{
    DWORD  dwError = 0;
    DWORD  dwTimeInterval = 0;
    PSTR   pszTimeIntervalLocal = 0;
    DWORD  dwTimeIntervalLocalLen = 0;
    DWORD  dwUnitMultiplier = 0;
    PSTR   pszUnitCode = NULL;
    
    LwStripWhitespace(pszTimeIntervalLocal, TRUE, TRUE);

    BAIL_ON_INVALID_STRING(pszTimeInterval);
        
    dwError = LwAllocateString(
                    pszTimeInterval, 
                    &pszTimeIntervalLocal
                    );
    BAIL_ON_LSA_ERROR(dwError);

    dwTimeIntervalLocalLen = strlen(pszTimeIntervalLocal);
    
    pszUnitCode = pszTimeIntervalLocal + dwTimeIntervalLocalLen - 1;

    if (isdigit((int)(*pszUnitCode))) 
    {
        dwUnitMultiplier = 1;
    }

    else 
    {

        switch(*pszUnitCode) 
        {
            case 's':
            case 'S':
    	        dwUnitMultiplier = 1;
    	        break;
	        
            case 'm':
            case 'M':
    	        dwUnitMultiplier = LSA_SECONDS_IN_MINUTE;
    	        break;

            case 'h':
            case 'H':
                dwUnitMultiplier = LSA_SECONDS_IN_HOUR;
                break;

            case 'd':
            case 'D':
                dwUnitMultiplier = LSA_SECONDS_IN_DAY;
                break;

            default:
                dwError = LW_ERROR_INVALID_PARAMETER;
                BAIL_ON_LSA_ERROR(dwError);
                break;
        }

        *pszUnitCode = ' ';
    }
    
    LwStripWhitespace(pszTimeIntervalLocal, TRUE, TRUE);
    
    dwTimeInterval = (DWORD) atoi(pszTimeIntervalLocal) * dwUnitMultiplier;
    
    *pdwTimeInterval = dwTimeInterval;
    
cleanup:
    
    LW_SAFE_FREE_STRING(pszTimeIntervalLocal);
    
    return dwError;

error:
    
    goto cleanup;
}
Beispiel #15
0
DWORD
LwTaskAcquireCredsA(
    PCSTR           pszUsername,  /* IN     */
    PCSTR           pszPassword,  /* IN     */
    PLW_TASK_CREDS* ppCreds       /* IN OUT */
    )
{
    DWORD dwError = 0;
    krb5_error_code ret = 0;
    PSTR   pszNewCachePath = NULL;
    PLW_TASK_CREDS pCreds = NULL;

    BAIL_ON_INVALID_POINTER(ppCreds);
    BAIL_ON_INVALID_STRING(pszUsername);

    dwError = LwAllocateMemory(sizeof(*pCreds), (PVOID*)&pCreds);
    BAIL_ON_LW_TASK_ERROR(dwError);

    ret = krb5_init_context(&pCreds->ctx);
    BAIL_ON_KRB_ERROR(pCreds->ctx, ret);

    /* Generates a new filed based credentials cache in /tmp.
     * The file will be owned by root and only accessible by root.
     */
    ret = krb5_cc_new_unique(pCreds->ctx, "FILE", "hint", &pCreds->cc);
    BAIL_ON_KRB_ERROR(pCreds->ctx, ret);

    dwError = LwAllocateStringPrintf(
                    &pszNewCachePath,
                    "%s:%s",
                    krb5_cc_get_type(pCreds->ctx, pCreds->cc),
                    krb5_cc_get_name(pCreds->ctx, pCreds->cc));
    BAIL_ON_LW_TASK_ERROR(dwError);

    dwError = LwKrb5GetTgt(pszUsername, pszPassword, pszNewCachePath, NULL);
    BAIL_ON_LW_TASK_ERROR(dwError);

    dwError = LwKrb5SetDefaultCachePath(
                    pszNewCachePath,
                    &pCreds->pszRestoreCache);
    BAIL_ON_LW_TASK_ERROR(dwError);

    dwError = LwIoCreateKrb5CredsA(
                    pszUsername,
                    pszNewCachePath,
                    &pCreds->pKrb5Creds);
    BAIL_ON_LW_TASK_ERROR(dwError);

    *ppCreds = pCreds;

cleanup:

    LW_SAFE_FREE_STRING(pszNewCachePath);

    return dwError;

error:

    *ppCreds = NULL;

    if (pCreds)
    {
        LwTaskFreeCreds(pCreds);
    }

    goto cleanup;
}
Beispiel #16
0
LSASS_API
DWORD
LsaFindGroupByName(
    HANDLE hLsaConnection,
    PCSTR  pszGroupName,
    LSA_FIND_FLAGS FindFlags,
    DWORD  dwGroupInfoLevel,
    PVOID* ppGroupInfo
    )
{
    DWORD dwError = 0;
    PVOID pGroupInfo = NULL;
    LSA_QUERY_LIST QueryList;
    LSA_QUERY_ITEM QueryItem;
    DWORD dwObjectCount = 1;
    PLSA_SECURITY_OBJECT* ppObjects = NULL;
    PLSA_SECURITY_OBJECT pGroup = NULL;

    BAIL_ON_INVALID_HANDLE(hLsaConnection);
    BAIL_ON_INVALID_STRING(pszGroupName);

    dwError = LsaValidateGroupInfoLevel(dwGroupInfoLevel);
    BAIL_ON_LSA_ERROR(dwError);

    BAIL_ON_INVALID_POINTER(ppGroupInfo);

    switch (dwGroupInfoLevel)
    {
    case 1:
        /* Fast path */
        QueryItem.pszString = pszGroupName;
        
        dwError = LsaFindGroupAndExpandedMembers(
            hLsaConnection,
            NULL,
            FindFlags,
            LSA_QUERY_TYPE_BY_NAME,
            QueryItem,
            &pGroup,
            &dwObjectCount,
            &ppObjects);
        BAIL_ON_LSA_ERROR(dwError);
        
        dwError = LsaMarshalGroupInfo1(
            hLsaConnection,
            FindFlags,
            pGroup,
            dwObjectCount,
            ppObjects,
            dwGroupInfoLevel,
            &pGroupInfo);
        BAIL_ON_LSA_ERROR(dwError);
        break;
    default:
        QueryList.ppszStrings = &pszGroupName;
        
        dwError = LsaFindObjects(
            hLsaConnection,
            NULL,
            0,
            LSA_OBJECT_TYPE_GROUP,
            LSA_QUERY_TYPE_BY_NAME,
            1,
            QueryList,
        &ppObjects);
        BAIL_ON_LSA_ERROR(dwError);
        
        if (ppObjects[0] == NULL)
        {
            dwError = LW_ERROR_NO_SUCH_GROUP;
            BAIL_ON_LSA_ERROR(dwError);
        }
        
        dwError = LsaMarshalGroupInfo(
            hLsaConnection,
            FindFlags,
            ppObjects[0],
            dwGroupInfoLevel,
            &pGroupInfo);
        BAIL_ON_LSA_ERROR(dwError);
    }

error:

    if (ppGroupInfo)
    {
        *ppGroupInfo = pGroupInfo;
    }

    if (pGroup)
    {
        LsaFreeSecurityObject(pGroup);
    }

    if (ppObjects)
    {
        LsaFreeSecurityObjectList(dwObjectCount, ppObjects);
    }

    return dwError;
}
Beispiel #17
0
// Give an attribute name "pszAttributeName"
// Return all the values of the attribute for a given DN "pszDN"
// The number of values can be more than 1500 since "ranging" is handled correctly in the routine
// Now accept whether to do an extended DN search and whether to parse result to get Sids
DWORD
ADLdap_GetAttributeValuesList(
    IN PLSA_DM_LDAP_CONNECTION pConn,
    IN PCSTR pszDN,
    IN PCSTR pszAttributeName,
    IN BOOLEAN bDoExtDnSearch,
    IN BOOLEAN bDoSidParsing,
    OUT PDWORD pdwTotalCount,
    OUT PSTR** pppszValues
    )
{
    DWORD dwError = 0;
    // Do not free "szAttributeList"
    PSTR szAttributeList[2] = {NULL,NULL};
    PSTR* ppszValuesTotal = NULL;
    PSTR* ppszValues = NULL;
    LDAPMessage* pMessage = NULL;
    DWORD dwCount = 0;
    DWORD dwTotalCount = 0;
    PLW_DLINKED_LIST pList = NULL;
    PLW_DLINKED_LIST pNode = NULL;
    PLSA_AD_QUERY_LISTS_ENTRY pEntry = NULL;
    PSTR pszRangeAttr = NULL;
    LDAP* pLd = NULL;
    BerElement* pBer = NULL;
    PSTR pszRetrievedAttr = NULL;
    //Do Not free "pszRetrievedRangeAttr"
    PSTR pszRetrievedRangeAttr = NULL;
    BOOLEAN bIsEnd = FALSE;
    DWORD iValues = 0;
    DWORD iValuesTotal = 0;
    PSTR pszAttributeRangedName = NULL;
    HANDLE hDirectory = NULL;

    BAIL_ON_INVALID_STRING(pszAttributeName);
    szAttributeList[0] = (PSTR)pszAttributeName;

    for (;;)
    {
        if (pMessage)
        {
            ldap_msgfree(pMessage);
            pMessage = NULL;
        }

        if (!bDoExtDnSearch && bDoSidParsing)
        {
            dwError = LW_ERROR_INVALID_PARAMETER;
            BAIL_ON_LSA_ERROR(dwError);
        }

        if (bDoExtDnSearch)
        {
            dwError = LsaDmLdapDirectoryExtendedDNSearch(
                            pConn,
                            pszDN,
                            "(objectClass=*)",
                            szAttributeList,
                            LDAP_SCOPE_BASE,
                            &hDirectory,
                            &pMessage);
            BAIL_ON_LSA_ERROR(dwError);
        }
        else
        {
            dwError = LsaDmLdapDirectorySearch(
                            pConn,
                            pszDN,
                            LDAP_SCOPE_BASE,
                            "(objectClass=*)",
                            szAttributeList,
                            &hDirectory,
                            &pMessage);
            BAIL_ON_LSA_ERROR(dwError);
        }
        pLd = LwLdapGetSession(hDirectory);

        dwError = LwLdapGetStringsWithExtDnResult(
                        hDirectory,
                        pMessage,
                        pszAttributeName,
                        bDoSidParsing,
                        &ppszValues,
                        &dwCount);
        BAIL_ON_LSA_ERROR(dwError);

        if (ppszValues && dwCount)
        {
            if (pList)
            {
                // This is the case where we started out getting
                // ranged info but the info became non-ranged.
                // We might actually want to allow this to handle
                // a case where the membership list is trimmed
                // while we are enumerating.
                dwError = LW_ERROR_LDAP_ERROR;
                BAIL_ON_LSA_ERROR(dwError);
            }

            dwTotalCount = dwCount;
            ppszValuesTotal = ppszValues;

            dwCount = 0;
            ppszValues = NULL;

            break;
        }

        if (pszRetrievedAttr)
        {
            ldap_memfree(pszRetrievedAttr);
            pszRetrievedAttr = NULL;
        }

        if (pBer)
        {
             ber_free(pBer, 0);
        }

        LW_SAFE_FREE_STRING(pszAttributeRangedName);

        dwError = LwAllocateStringPrintf(
                      &pszAttributeRangedName,
                      "%s;Range=",
                      pszAttributeName);
        BAIL_ON_LSA_ERROR(dwError);

        pszRetrievedAttr = ldap_first_attribute(pLd, pMessage, &pBer);
        while (pszRetrievedAttr)
        {
            if (!strncasecmp(pszRetrievedAttr, pszAttributeRangedName, strlen(pszAttributeRangedName)))
            {
                pszRetrievedRangeAttr = pszRetrievedAttr;
                break;
            }
            ldap_memfree(pszRetrievedAttr);
            pszRetrievedAttr = NULL;

            pszRetrievedAttr = ldap_next_attribute(pLd, pMessage, pBer);
        }

        if (!pszRetrievedRangeAttr)
        {
            // This happens when we have an group with no members,
            break;
        }

        if ('*' == pszRetrievedRangeAttr[strlen(pszRetrievedRangeAttr)-1])
        {
            bIsEnd = TRUE;
        }

        dwError = LwLdapGetStringsWithExtDnResult(
                        hDirectory,
                        pMessage,
                        pszRetrievedRangeAttr,
                        bDoSidParsing,
                        &ppszValues,
                        &dwCount);
        BAIL_ON_LSA_ERROR(dwError);

        dwTotalCount += dwCount;

        dwError = CreateQueryListEntry(
                        &pEntry,
                        dwCount,
                        ppszValues);
        BAIL_ON_LSA_ERROR(dwError);
        ppszValues = NULL;
        dwCount = 0;

        dwError = LwDLinkedListPrepend(&pList, pEntry);
        BAIL_ON_LSA_ERROR(dwError);
        pEntry = NULL;

        if (bIsEnd)
        {
            break;
        }

        LW_SAFE_FREE_STRING(pszRangeAttr);

        dwError = LwAllocateStringPrintf(
                        &pszRangeAttr,
                        "%s%u-*",
                        pszAttributeRangedName,
                        dwTotalCount);
        BAIL_ON_LSA_ERROR(dwError);

        szAttributeList[0] = pszRangeAttr;
    }

    if (pList && !ppszValuesTotal)
    {
        dwError = LwAllocateMemory(
                        sizeof(*ppszValuesTotal) * dwTotalCount,
                        (PVOID*)&ppszValuesTotal);
        BAIL_ON_LSA_ERROR(dwError);

        for (pNode = pList; pNode; pNode = pNode->pNext)
        {
            PLSA_AD_QUERY_LISTS_ENTRY pEntry = (PLSA_AD_QUERY_LISTS_ENTRY)pNode->pItem;

            for (iValues = 0; iValues < pEntry->dwQueryCount; iValues++)
            {
                ppszValuesTotal[iValuesTotal] = pEntry->ppszQueryValues[iValues];
                pEntry->ppszQueryValues[iValues] = NULL;
                iValuesTotal++;
            }
        }
    }

    *pdwTotalCount = dwTotalCount;
    *pppszValues = ppszValuesTotal;

cleanup:
    if (pMessage)
    {
        ldap_msgfree(pMessage);
    }

    if (pszRetrievedAttr)
    {
        ldap_memfree(pszRetrievedAttr);
    }

    if (pBer)
    {
        ber_free(pBer, 0);
    }

    LwFreeStringArray(ppszValues, dwCount);
    DestroyQueryListEntry(&pEntry);
    LW_SAFE_FREE_STRING(pszAttributeRangedName);
    LW_SAFE_FREE_STRING(pszRangeAttr);

    for (pNode = pList; pNode; pNode = pNode->pNext)
    {
        PLSA_AD_QUERY_LISTS_ENTRY pEntry = (PLSA_AD_QUERY_LISTS_ENTRY)pNode->pItem;
        DestroyQueryListEntry(&pEntry);
    }
    LwDLinkedListFree(pList);

    return dwError;

error:
    LwFreeStringArray(ppszValuesTotal, iValuesTotal);

    *pdwTotalCount = 0;
    *pppszValues = NULL;

    goto cleanup;
}
Beispiel #18
0
DWORD
ADGuidStrToHex(
        PCSTR pszStr,
        PSTR* ppszHexStr)
{
   DWORD dwError = 0;
   PSTR pszHexStr = NULL;
   PSTR pszUUIDStr = NULL;
   int iValue = 0, jValue = 0;
   uuid_t uuid= {0};
   unsigned char temp;

   BAIL_ON_INVALID_STRING(pszStr);

   dwError = LwAllocateString(
                 pszStr,
                 &pszUUIDStr);
   BAIL_ON_LSA_ERROR(dwError);

   if (uuid_parse(pszUUIDStr, uuid) < 0) {
       dwError = LW_ERROR_INVALID_OBJECTGUID;
       BAIL_ON_LSA_ERROR(dwError);
   }

   for(iValue = 0; iValue < 2; iValue++){
       temp = uuid[iValue];
       uuid[iValue] = uuid[3-iValue];
       uuid[3-iValue] = temp;
   }
   temp = uuid[4];
   uuid[4] = uuid[5];
   uuid[5] = temp;

   temp = uuid[6];
   uuid[6] = uuid[7];
   uuid[7] = temp;

   dwError = LwAllocateMemory(
                sizeof(CHAR)*(AD_GUID_SIZE*3+1),
               (PVOID*)&pszHexStr);
   BAIL_ON_LSA_ERROR(dwError);

   for (iValue = 0, jValue = 0; jValue < AD_GUID_SIZE; ){
       if (iValue % 3 == 0){
           *((char*)(pszHexStr+iValue++)) = '\\';
       }
       else{
           sprintf((char*)pszHexStr+iValue, "%.2X", uuid[jValue]);
           iValue += 2;
           jValue++;
       }
   }

   *ppszHexStr = pszHexStr;

cleanup:

    LW_SAFE_FREE_STRING(pszUUIDStr);

    return dwError;

error:

    *ppszHexStr = NULL;

    LW_SAFE_FREE_STRING(pszHexStr);

    goto cleanup;
}
Beispiel #19
0
static
DWORD
ADUnprovPlugin_QueryByIdWithDomainName(
    IN PLSA_AD_PROVIDER_STATE pState,
    IN BOOLEAN bIsUser,
    IN DWORD dwId,
    IN PCSTR pszDnsDomainName,
    OUT PSTR* ppszSid,
    OUT PSTR* ppszAlias
    )
{
    DWORD dwError = 0;
    PSID pDomainSid = NULL;
    PSTR pszDomainSid = NULL;
    PSTR pszSid = NULL;
    PSTR pszAlias = NULL;

    // lsass unprovisioned mode converts a group/user uid/gid to objectSid/name with the same algorithm

    dwError = LsaDmQueryDomainInfo(pState->hDmState,
                                   pszDnsDomainName,
                                   NULL,
                                   NULL,
                                   &pDomainSid,
                                   NULL,
                                   NULL,
                                   NULL,
                                   NULL,
                                   NULL,
                                   NULL,
                                   NULL,
                                   NULL,
                                   NULL,
                                   NULL,
                                   NULL,
                                   NULL);
    if (LW_ERROR_NO_SUCH_DOMAIN == dwError)
    {
        LSA_LOG_WARNING("Domain '%s' is unknown.", pszDnsDomainName);
    }
    BAIL_ON_LSA_ERROR(dwError);

    dwError = LsaAllocateCStringFromSid(
                 &pszDomainSid,
                 pDomainSid);
    BAIL_ON_LSA_ERROR(dwError);

    BAIL_ON_INVALID_STRING(pszDomainSid);

    dwError = UnprovisionedModeMakeLocalSID(
                     pszDomainSid,
                     dwId,
                     &pszSid);
    BAIL_ON_LSA_ERROR(dwError);

    *ppszSid = pszSid;
    *ppszAlias = pszAlias;

cleanup:
    LW_SAFE_FREE_MEMORY(pDomainSid);
    LW_SAFE_FREE_STRING(pszDomainSid);

    return dwError;

error:
    LW_SAFE_FREE_STRING(pszSid);
    LW_SAFE_FREE_STRING(pszAlias);
    *ppszSid = NULL;
    *ppszAlias = NULL;

    goto cleanup;
}
Beispiel #20
0
LSASS_API
DWORD
LsaGetGidsForUserByName(
    HANDLE  hLsaConnection,
    PCSTR   pszUserName,
    PDWORD  pdwGroupFound,
    gid_t** ppGidResults
    )
{
    DWORD dwError = 0;
    PVOID pUserInfo = NULL;
    DWORD dwUserInfoLevel = 0;
    static const DWORD dwGroupInfoLevel = 0;
    DWORD dwGroupFound = 0;
    gid_t* pGidResult = NULL;
    PVOID*  ppGroupInfoList = NULL;
    DWORD iGroup = 0;

    BAIL_ON_INVALID_HANDLE(hLsaConnection);
    BAIL_ON_INVALID_STRING(pszUserName);
    BAIL_ON_INVALID_POINTER(ppGidResults);

    dwError = LsaValidateUserName(pszUserName);
    BAIL_ON_LSA_ERROR(dwError);

    dwError = LsaFindUserByName(
                  hLsaConnection,
                  pszUserName,
                  dwUserInfoLevel,
                  &pUserInfo);
    BAIL_ON_LSA_ERROR(dwError);

    dwError = LsaGetGroupsForUserById(
                hLsaConnection,
                ((PLSA_USER_INFO_0)pUserInfo)->uid,
                LSA_FIND_FLAGS_NSS,
                dwGroupInfoLevel,
                &dwGroupFound,
                &ppGroupInfoList);
    BAIL_ON_LSA_ERROR(dwError);

    dwError = LwAllocateMemory(
                    sizeof(gid_t) * dwGroupFound,
                    (PVOID*)&pGidResult);
    BAIL_ON_LSA_ERROR(dwError);

    for (iGroup = 0; iGroup < dwGroupFound; iGroup++)
    {
        *(pGidResult+iGroup) = ((PLSA_GROUP_INFO_0)(*(ppGroupInfoList+iGroup)))->gid;
    }

    *ppGidResults = pGidResult;
    *pdwGroupFound = dwGroupFound;

cleanup:

    if (pUserInfo) {
        LsaFreeUserInfo(dwUserInfoLevel, pUserInfo);
    }

    if (ppGroupInfoList) {
        LsaFreeGroupInfoList(dwGroupInfoLevel, (PVOID*)ppGroupInfoList, dwGroupFound);
    }

    return dwError;

error:

    *ppGidResults = NULL;
    *pdwGroupFound = 0;

    goto cleanup;
}