Ejemplo n.º 1
0
static
DWORD
LocalCfgSetHomedirPrefix(
    PLOCAL_CONFIG   pConfig,
    PCSTR           pszName,
    PCSTR           pszValue
    )
{
    DWORD dwError = 0;
    PSTR pszHomedirPrefix = NULL;

    if (LW_IS_NULL_OR_EMPTY_STR(pszValue))
    {
        goto error;
    }

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

    LwStripWhitespace(pszHomedirPrefix, TRUE, TRUE);

    if (LW_IS_NULL_OR_EMPTY_STR(pszHomedirPrefix))
    {
        goto error;
    }

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

    LW_SAFE_FREE_STRING(pConfig->pszHomedirPrefix);

    pConfig->pszHomedirPrefix = pszHomedirPrefix;
    pszHomedirPrefix = NULL;

cleanup:

    return dwError;

error:
    LW_SAFE_FREE_STRING(pszHomedirPrefix);

    goto cleanup;
}
Ejemplo n.º 2
0
DWORD
LWSetConfigValueBySection(
    PCFGSECTION pSection,
    PCSTR pszName,
    PCSTR pszValue
    )
{
    DWORD dwError = 0;
    PNVPAIR pNVPair = NULL;
    PNVPAIR pTmpNVPair = NULL;

    pTmpNVPair = pSection->pNVPairList;
    while (pTmpNVPair) {
        if (!strcmp(pTmpNVPair->pszName, pszName)) {
            pNVPair = pTmpNVPair;
            break;
        }
        pTmpNVPair = pTmpNVPair->pNext;
    }

    if (pNVPair == NULL) {

        dwError = LwAllocateMemory(sizeof(NVPAIR), (PVOID*)&pNVPair);
        BAIL_ON_MAC_ERROR(dwError);

        dwError = LwAllocateString(pszName, &pNVPair->pszName);
        BAIL_ON_MAC_ERROR(dwError);

        LwStripWhitespace(pNVPair->pszName, TRUE, TRUE);

        if (!IsNullOrEmptyString(pszValue)) {
            dwError = LwAllocateString(pszValue, &pNVPair->pszValue);
            BAIL_ON_MAC_ERROR(dwError);
        }

        if (!pSection->pNVPairList) {
            pSection->pNVPairList = pNVPair;
            pNVPair = NULL;

        } else {

            pTmpNVPair = pSection->pNVPairList;
            while (pTmpNVPair->pNext != NULL)
                pTmpNVPair = pTmpNVPair->pNext;

            pTmpNVPair->pNext = pNVPair;
            pNVPair = NULL;

        }

    } else {

        if (pNVPair->pszValue) {

            LW_SAFE_FREE_STRING(pNVPair->pszValue);
            pNVPair->pszValue = NULL;

            if (!IsNullOrEmptyString(pszValue)) {
                dwError = LwAllocateString(pszValue, &pNVPair->pszValue);
                BAIL_ON_MAC_ERROR(dwError);
            }

        }

    }

cleanup:

    return dwError;

error:

    if (pNVPair) {
        LWFreeNVPair(pNVPair);
    }

    goto cleanup;
}
Ejemplo n.º 3
0
DWORD
LWParseConfigFile(
    PCSTR pszFilePath,
    PCFGSECTION* ppCfgSectionList,
    BOOLEAN bWindowsDoubleByteFormat
    )
{
    DWORD dwError = 0;
    PCFGSECTION pSectionList = NULL;
    PCFGSECTION pSection = NULL;
    PNVPAIR pNVPair = NULL;
    FILE* fp = NULL;
    CHAR staticBuffer[1024+1];
    PSTR szBuf = NULL;
    DWORD dwLen = 0;
    PSTR pszTmp = NULL;
    PSTR pszName = NULL;
    PSTR pszValue = NULL;
    DWORD dwSignature = 0;
    /*DWORD nRead = 0;*/
    BOOLEAN bEOF = FALSE;

    if ((fp = fopen(pszFilePath, "r")) == NULL) {
        dwError = errno;
        goto error;
    }

    if (fcntl(fileno(fp), F_SETFD, FD_CLOEXEC) < 0) {
        dwError = errno;
        BAIL_ON_MAC_ERROR(dwError);
    }

    if (bWindowsDoubleByteFormat) {
        dwError = ParseHeader(fp, &dwSignature);
        BAIL_ON_MAC_ERROR(dwError);

        if (dwSignature != 0xFEFF) {
            dwError = MAC_AD_ERROR_INVALID_TAG;
            BAIL_ON_MAC_ERROR(dwError);
        }
    }

    while (!bEOF) {
        LW_SAFE_FREE_STRING(szBuf);

        if (bWindowsDoubleByteFormat) {

            staticBuffer[0] = '\0';
            dwError = ReadNextDoubleByteLine(fp, staticBuffer, 1024, &bEOF);
            BAIL_ON_MAC_ERROR(dwError);
            dwError = LwAllocateString(staticBuffer, &szBuf);
            BAIL_ON_MAC_ERROR(dwError);

        } else {

            dwError = ReadNextLine(fp, &szBuf, &bEOF);
            BAIL_ON_MAC_ERROR(dwError);

        }

        LwStripWhitespace(szBuf, TRUE, TRUE);

        if (!(dwLen=strlen(szBuf)))
            continue;

        /* Skip comments for now */
        if (szBuf[0] == '#' ||
            szBuf[0] == ';')
            continue;

        if (szBuf[0]       == '[' &&
            szBuf[dwLen-1] == ']') {

            if (pSection) {
                pSection->pNext = pSectionList;
                pSectionList = pSection;
                pSection = NULL;
            }

            dwError = LwAllocateMemory(sizeof(CFGSECTION), (PVOID*)&pSection);
            BAIL_ON_MAC_ERROR(dwError);

            szBuf[dwLen-1] = '\0';

            dwError = LwAllocateString(szBuf+1, &pSection->pszName);
            BAIL_ON_MAC_ERROR(dwError);

            LwStripWhitespace(pSection->pszName, TRUE, TRUE);

        } else {

            if (!pSection) {
                dwError = MAC_AD_ERROR_NO_SUCH_ATTRIBUTE;
                BAIL_ON_MAC_ERROR(dwError);
            }

            if ((pszTmp = strchr(szBuf, '=')) == NULL) {
                continue;
            }

            if (pszTmp == szBuf) {
                dwError = MAC_AD_ERROR_INVALID_TAG;
                BAIL_ON_MAC_ERROR(dwError);
            }

            dwError = LwAllocateMemory(pszTmp-szBuf+1, (PVOID*)&pszName);
            BAIL_ON_MAC_ERROR(dwError);

            strncpy(pszName, szBuf, pszTmp-szBuf);

            pszTmp++;
            while (*pszTmp != '\0' && isspace((int)*pszTmp))
                pszTmp++;

            if (*pszTmp != '\0') {
                dwError = LwAllocateString(pszTmp, &pszValue);
                BAIL_ON_MAC_ERROR(dwError);
            }

            dwError = LwAllocateMemory(sizeof(NVPAIR), (PVOID*)&pNVPair);
            BAIL_ON_MAC_ERROR(dwError);

            LwStripWhitespace(pszName, TRUE, TRUE);
            LwStripWhitespace(pszValue, TRUE, TRUE);

            pNVPair->pszName = pszName; pszName = NULL;
            pNVPair->pszValue = pszValue; pszValue = NULL;

            pNVPair->pNext = pSection->pNVPairList;
            pSection->pNVPairList = pNVPair;
            pNVPair = NULL;

        }
    }

    if (pSection) {
        pSection->pNext = pSectionList;
        pSectionList = pSection;
        pSection = NULL;
    }

    pSectionList = ReverseSectionsAndNVPairs(pSectionList);

    *ppCfgSectionList = pSectionList;

    fclose(fp); fp = NULL;

cleanup:

    LW_SAFE_FREE_STRING(szBuf);

    if (fp) {
        fclose(fp);
    }

    LW_SAFE_FREE_STRING(pszName);
    LW_SAFE_FREE_STRING(pszValue);

    return dwError;

error:

    *ppCfgSectionList = NULL;

    if (pSectionList)
    {
       LWFreeConfigSectionList(pSectionList);
    }

    if (pSection)
    {
        LWFreeSection(pSection);
    }

    if (pNVPair)
    {
        LWFreeNVPair(pNVPair);
    }

    goto cleanup;
}
Ejemplo n.º 4
0
static
DWORD
EVTStringSplit(
    PCSTR   pszInput,
    PDWORD  pdwCount,
    PSTR**  pppszArray
    )
{
    DWORD  dwError = 0;
    DWORD  dwCount = 0;
    PCSTR  pszStart = NULL;
    PCSTR  pszEnd = NULL;
    PSTR* ppszArray = NULL;
    PSTR pszAdd = NULL;

    for (pszStart = pszInput; *pszStart !=  0; pszStart++)
    {
        if (*pszStart == ',') dwCount++;
    }
    dwCount++;

    dwError = LwAllocateMemory(
                  (dwCount+1)*sizeof(PCSTR),
                  (PVOID *)&ppszArray);

    dwCount = 0;
    pszStart = pszInput;
    while (TRUE)
    {
        pszEnd = strchr(pszStart, ',');
        if ( pszEnd )
        {
            dwError = LwStrndup(
                         pszStart,
                         pszEnd - pszStart,
                         &pszAdd);
            BAIL_ON_EVT_ERROR(dwError);
        }
        else
        {
            dwError = LwAllocateString(
                        pszStart,
                        &pszAdd);
            BAIL_ON_EVT_ERROR(dwError);
        }
        LwStripWhitespace(pszAdd, TRUE, TRUE);
        if (pszAdd[0])
        {
            ppszArray[dwCount++] = pszAdd;
            pszAdd = NULL;
        }
        else
        {
            LW_SAFE_FREE_STRING(pszAdd);
        }

        if (pszEnd)
        {
            pszStart = pszEnd + 1;
        }
        else
        {
            break;
        }
    }

    *pppszArray = ppszArray;
    *pdwCount = dwCount;

cleanup:
    LW_SAFE_FREE_STRING(pszAdd);
    return dwError;

error:
    LwFreeStringArray(
        ppszArray,
        dwCount);
    goto cleanup;
}
Ejemplo n.º 5
0
DWORD
UmnSrvUpdateADAccounts(
    HANDLE hLsass,
    PLW_EVENTLOG_CONNECTION pEventlog,
    HANDLE hReg,
    HKEY hParameters,
    long long PreviousRun,
    long long Now
    )
{
    DWORD dwError = 0;
    PSTR pMemberList = NULL;
    PCSTR pIter = NULL;
    PSTR  pMember = NULL;
    PLW_HASH_TABLE pUsers = NULL;
    LWREG_CONFIG_ITEM ADConfigDescription[] =
    {
        {
            "RequireMembershipOf",
            TRUE,
            LwRegTypeMultiString,
            0,
            MAXDWORD,
            NULL,
            &pMemberList,
            NULL
        },
    };
    PLSASTATUS pLsaStatus = NULL;
    // Do not free
    PSTR pDomain = NULL;
    // Do not free
    PSTR pCell = NULL;
    PLSA_SECURITY_OBJECT pAllUsers = NULL;
    DWORD i = 0;

    dwError = LwHashCreate(
                    100,
                    LwHashStringCompare,
                    LwHashStringHash,
                    UmnSrvHashFreeObjectValue,
                    NULL,
                    &pUsers);
    BAIL_ON_UMN_ERROR(dwError);

    dwError = RegProcessConfig(
                AD_PROVIDER_REGKEY,
                AD_PROVIDER_POLICY_REGKEY,
                ADConfigDescription,
                sizeof(ADConfigDescription)/sizeof(ADConfigDescription[0]));
    BAIL_ON_UMN_ERROR(dwError);

    if (pMemberList && pMemberList[0])
    {
        pIter = pMemberList;
        while (*pIter != 0)
        {
            dwError = LwStrDupOrNull(
                            pIter,
                            &pMember);
            BAIL_ON_UMN_ERROR(dwError);

            LwStripWhitespace(
                    pMember,
                    TRUE,
                    TRUE);

            dwError = UmnSrvAddUsersFromMembership(
                            hLsass,
                            pUsers,
                            pMember);
            BAIL_ON_UMN_ERROR(dwError);

            pIter += strlen(pIter) + 1;
        }
    }
    else
    {
        dwError = LsaGetStatus2(
                        hLsass,
                        NULL,
                        &pLsaStatus);
        BAIL_ON_UMN_ERROR(dwError);

        for (i = 0; i < pLsaStatus->dwCount; i++)
        {
            if (pLsaStatus->pAuthProviderStatusList[i].pszDomain)
            {
                pDomain = pLsaStatus->pAuthProviderStatusList[i].pszDomain;
            }
            if (pLsaStatus->pAuthProviderStatusList[i].pszCell)
            {
                pCell = pLsaStatus->pAuthProviderStatusList[i].pszCell;
            }
        }

        if (pDomain || pCell)
        {
            dwError = LwAllocateMemory(
                            sizeof(*pAllUsers),
                            (PVOID*)&pAllUsers);
            BAIL_ON_UMN_ERROR(dwError);

            dwError = LwAllocateString(
                            "S-INVALID",
                            &pAllUsers->pszObjectSid);
            BAIL_ON_UMN_ERROR(dwError);

            pAllUsers->enabled = TRUE;
            pAllUsers->bIsLocal = FALSE;

            dwError = LwAllocateString(
                            "AllDomains",
                            &pAllUsers->pszNetbiosDomainName);
            BAIL_ON_UMN_ERROR(dwError);

            dwError = LwAllocateString(
                            "AllUsers",
                            &pAllUsers->pszSamAccountName);
            BAIL_ON_UMN_ERROR(dwError);

            pAllUsers->type = LSA_OBJECT_TYPE_USER;

            dwError = LwAllocateString(
                            "S-INVALID",
                            &pAllUsers->userInfo.pszPrimaryGroupSid);
            BAIL_ON_UMN_ERROR(dwError);

            dwError = LwAllocateString(
                            "All Users",
                            &pAllUsers->userInfo.pszUnixName);
            BAIL_ON_UMN_ERROR(dwError);

            dwError = LwAllocateString(
                            "All Users",
                            &pAllUsers->userInfo.pszGecos);
            BAIL_ON_UMN_ERROR(dwError);

            dwError = LwAllocateString(
                            "",
                            &pAllUsers->userInfo.pszShell);
            BAIL_ON_UMN_ERROR(dwError);

            dwError = LwAllocateString(
                            "",
                            &pAllUsers->userInfo.pszHomedir);
            BAIL_ON_UMN_ERROR(dwError);

            if (pCell)
            {
                dwError = LwAllocateStringPrintf(
                                &pAllUsers->userInfo.pszDisplayName,
                                "All Users in cell %s",
                                pCell);
                BAIL_ON_UMN_ERROR(dwError);
            }
            else
            {
                dwError = LwAllocateStringPrintf(
                                &pAllUsers->userInfo.pszDisplayName,
                                "All Users accessible from domain %s",
                                pDomain);
                BAIL_ON_UMN_ERROR(dwError);
            }

            dwError = LwHashSetValue(
                            pUsers,
                            pAllUsers->pszObjectSid,
                            pAllUsers);
            BAIL_ON_UMN_ERROR(dwError);

            pAllUsers = NULL;
        }
    }

    dwError = UmnSrvUpdateADAccountsByHash(
                    hLsass,
                    pEventlog,
                    hReg,
                    hParameters,
                    pUsers,
                    PreviousRun,
                    Now);
    BAIL_ON_UMN_ERROR(dwError);

cleanup:
    if (pLsaStatus)
    {
        LsaFreeStatus(pLsaStatus);
    }
    LW_SAFE_FREE_STRING(pMemberList);
    LW_SAFE_FREE_STRING(pMember);
    LwHashSafeFree(&pUsers);
    if (pAllUsers)
    {
        LsaFreeSecurityObject(pAllUsers);
    }
    return dwError;

error:
    goto cleanup;
}
Ejemplo n.º 6
0
static
DWORD
SamDbBuildSqlQuery(
    PSAM_DIRECTORY_CONTEXT pDirectoryContext,
    PWSTR                  pwszFilter,
    PWSTR                  wszAttributes[],
    ULONG                  ulAttributesOnly,
    PSTR*                  ppszQuery,
    PBOOLEAN               pbMembersAttrExists,
    PSAM_DB_COLUMN_VALUE*  ppColumnValueList
    )
{
    DWORD dwError = 0;
    BOOLEAN bMembersAttrExists = FALSE;
    DWORD dwQueryLen = 0;
    DWORD dwColNamesLen = 0;
    DWORD dwNumAttrs = 0;
    PSTR  pszQuery = NULL;
    PSTR  pszQueryCursor = NULL;
    PSTR  pszCursor = NULL;
    PSTR  pszFilter = NULL;
    PSAM_DB_COLUMN_VALUE pColumnValueList = NULL;
    PSAM_DB_COLUMN_VALUE pIter = NULL;

    if (pwszFilter)
    {
        dwError = LwWc16sToMbs(
                        pwszFilter,
                        &pszFilter);
        BAIL_ON_SAMDB_ERROR(dwError);

        LwStripWhitespace(pszFilter, TRUE, TRUE);
    }

    while (wszAttributes[dwNumAttrs])
    {
        PWSTR pwszAttrName = wszAttributes[dwNumAttrs];
        wchar16_t wszMembersAttrName[] = SAM_DB_DIR_ATTR_MEMBERS;

        if (!wc16scasecmp(pwszAttrName, &wszMembersAttrName[0]))
        {
            bMembersAttrExists = TRUE;
        }
        else
        {
            PSAM_DB_COLUMN_VALUE  pColumnValue = NULL;
            PSAM_DB_ATTRIBUTE_MAP pAttrMap = NULL;

            dwError = SamDbAttributeLookupByName(
                            pDirectoryContext->pAttrLookup,
                            pwszAttrName,
                            &pAttrMap);
            BAIL_ON_SAMDB_ERROR(dwError);

            if (!pAttrMap->bIsQueryable)
            {
                dwError = LW_ERROR_INVALID_PARAMETER;
                BAIL_ON_SAMDB_ERROR(dwError);
            }

            dwError = DirectoryAllocateMemory(
                            sizeof(SAM_DB_COLUMN_VALUE),
                            (PVOID*)&pColumnValue);
            BAIL_ON_SAMDB_ERROR(dwError);

            pColumnValue->pAttrMap = pAttrMap;
            pColumnValue->pNext = pColumnValueList;
            pColumnValueList = pColumnValue;
            pColumnValue = NULL;

            if (dwColNamesLen)
            {
                dwColNamesLen += sizeof(SAM_DB_SEARCH_QUERY_FIELD_SEPARATOR)-1;
            }

            dwColNamesLen += strlen(&pAttrMap->szDbColumnName[0]);
        }

        dwNumAttrs++;
    }

    dwQueryLen = sizeof(SAM_DB_SEARCH_QUERY_PREFIX) - 1;
    dwQueryLen += dwColNamesLen;
    dwQueryLen += sizeof(SAM_DB_SEARCH_QUERY_FROM) - 1;

    if (pszFilter && *pszFilter)
    {
        dwQueryLen += sizeof(SAM_DB_SEARCH_QUERY_WHERE) - 1;
        dwQueryLen += strlen(pszFilter);
    }
    dwQueryLen += sizeof(SAM_DB_SEARCH_QUERY_SUFFIX) - 1;
    dwQueryLen++;

    dwError = DirectoryAllocateMemory(
                    dwQueryLen,
                    (PVOID*)&pszQuery);
    BAIL_ON_SAMDB_ERROR(dwError);

    pColumnValueList = SamDbReverseColumnValueList(pColumnValueList);

    pszQueryCursor = pszQuery;
    dwColNamesLen = 0;

    pszCursor = SAM_DB_SEARCH_QUERY_PREFIX;
    while (pszCursor && *pszCursor)
    {
        *pszQueryCursor++ = *pszCursor++;
    }

    for (pIter = pColumnValueList; pIter; pIter = pIter->pNext)
    {
        if (dwColNamesLen)
        {
            pszCursor = SAM_DB_SEARCH_QUERY_FIELD_SEPARATOR;
            while (pszCursor && *pszCursor)
            {
                *pszQueryCursor++ = *pszCursor++;
                dwColNamesLen++;
            }
        }

        pszCursor = &pIter->pAttrMap->szDbColumnName[0];
        while (pszCursor && *pszCursor)
        {
            *pszQueryCursor++ = *pszCursor++;
            dwColNamesLen++;
        }
    }

    pszCursor = SAM_DB_SEARCH_QUERY_FROM;
    while (pszCursor && *pszCursor)
    {
        *pszQueryCursor++ = *pszCursor++;
    }

    if (pszFilter && *pszFilter)
    {
        pszCursor = SAM_DB_SEARCH_QUERY_WHERE;
        while (pszCursor && *pszCursor)
        {
            *pszQueryCursor++ = *pszCursor++;
        }

        pszCursor = pszFilter;
        while (pszCursor && *pszCursor)
        {
            *pszQueryCursor++ = *pszCursor++;
        }
    }

    pszCursor = SAM_DB_SEARCH_QUERY_SUFFIX;
    while (pszCursor && *pszCursor)
    {
        *pszQueryCursor++ = *pszCursor++;
    }

    *ppszQuery = pszQuery;
    *pbMembersAttrExists = bMembersAttrExists;
    *ppColumnValueList = pColumnValueList;

cleanup:

    DIRECTORY_FREE_STRING(pszFilter);

    return dwError;

error:

    *ppszQuery = NULL;
    *pbMembersAttrExists = FALSE;
    *ppColumnValueList = NULL;

    DIRECTORY_FREE_STRING(pszQuery);

    if (pColumnValueList)
    {
        SamDbFreeColumnValueList(pColumnValueList);
    }

    goto cleanup;
}
Ejemplo n.º 7
0
DWORD
GetSecretsPath(
    PCSTR pSmbdPath,
    PSTR* ppPath
    )
{
    DWORD error = 0;
    PSTR pCommandLine = NULL;
    PCSTR ppArgs[] = {
        "/bin/sh",
        "-c",
        NULL,
        NULL
    };
    PSTR pSambaPrivateDir = NULL;
    PSTR pPath = NULL;
    struct stat statBuf = { 0 };

    // Look for secrets.tdb in the statedir (Ubuntu 10.10 is like this)
    error = LwAllocateStringPrintf(
            &pCommandLine,
            "%s -b | grep STATEDIR:",
            pSmbdPath
            );
    BAIL_ON_LSA_ERROR(error);

    ppArgs[2] = pCommandLine;

    error = CaptureOutputWithStderr(
                "/bin/sh",
                ppArgs,
                &pSambaPrivateDir,
                NULL);
    if (error == ERROR_BAD_COMMAND)
    {
        pSambaPrivateDir = NULL;
        error = ERROR_BAD_COMMAND;
    }
    else
    {
        if (strstr(pSambaPrivateDir, ": "))
        {
            char *pValueStart = strstr(pSambaPrivateDir, ": ") + 2;
            memmove(
                    pSambaPrivateDir,
                    pValueStart,
                    strlen(pSambaPrivateDir) -
                        (pValueStart - pSambaPrivateDir) + 1);
        }

        LwStripWhitespace(
                pSambaPrivateDir,
                TRUE,
                TRUE);

        error = LwAllocateStringPrintf(
                &pPath,
                "%s/secrets.tdb",
                pSambaPrivateDir
                );
        BAIL_ON_LSA_ERROR(error);
        
        // Verify the path exists
        if (stat(pPath, &statBuf) < 0)
        {
            if (errno == ENOENT)
            {
                // Try the private dir instead
                LW_SAFE_FREE_STRING(pSambaPrivateDir);
                LW_SAFE_FREE_STRING(pPath);
            }
            else
            {
                LW_RTL_LOG_ERROR("Cannot find secrets.tdb at %s",
                        pPath);
                error = LwMapErrnoToLwError(errno);
                BAIL_ON_LSA_ERROR(error);   
            }
        }
    }

    if (pPath == NULL)
    {
        // This version of smbd is older than 3.5, or the distro vendor decided
        // to put the file in the private dir (Fedora 14 is like that).
        LW_SAFE_FREE_STRING(pCommandLine);

        error = LwAllocateStringPrintf(
                &pCommandLine,
                "%s -b | grep PRIVATE_DIR:",
                pSmbdPath
                );
        BAIL_ON_LSA_ERROR(error);

        ppArgs[2] = pCommandLine;

        error = CaptureOutputWithStderr(
                    "/bin/sh",
                    ppArgs,
                    &pSambaPrivateDir,
                    NULL);
        BAIL_ON_LSA_ERROR(error);

        LwStripWhitespace(
                pSambaPrivateDir,
                TRUE,
                TRUE);

        if (strstr(pSambaPrivateDir, ": "))
        {
            char *pValueStart = strstr(pSambaPrivateDir, ": ") + 2;
            memmove(
                    pSambaPrivateDir,
                    pValueStart,
                    strlen(pSambaPrivateDir) -
                        (pValueStart - pSambaPrivateDir) + 1);
        }

        error = LwAllocateStringPrintf(
                &pPath,
                "%s/secrets.tdb",
                pSambaPrivateDir
                );
        BAIL_ON_LSA_ERROR(error);
    }

cleanup:
    *ppPath = pPath;
    LW_SAFE_FREE_STRING(pCommandLine);
    LW_SAFE_FREE_STRING(pSambaPrivateDir);
    return error;
}
Ejemplo n.º 8
0
DWORD
LsaReadVersionFile(
    PLSA_VERSION pVersion
    )
{  
    DWORD dwError = 0;
    DWORD dwMajor = 0;
    DWORD dwMinor = 0;
    DWORD dwBuild = 0;
    DWORD dwRevision = 0;
    int versionFile = -1;
    // A typical version file is 40 bytes long. The whole file can be read into
    // a static buffer, because if the file is too long, then it is invalid.
    char szFileBuffer[200];
    ssize_t dwCount = 0;
    // Do not free
    PSTR pszPos = szFileBuffer;

#ifdef MINIMAL_LSASS
    versionFile = open(LOCALSTATEDIR "/VERSION", O_RDONLY, 0);
#else
    versionFile = open(PREFIXDIR "/data/ENTERPRISE_VERSION", O_RDONLY, 0);
    if (versionFile < 0 && errno == ENOENT)
    {
        versionFile = open(PREFIXDIR "/data/VERSION", O_RDONLY, 0);
    }
#endif
    if (versionFile < 0)
    {
        dwError = LwMapErrnoToLwError(errno);
        BAIL_ON_LSA_ERROR(dwError);
    }

    dwCount = read(versionFile, szFileBuffer, sizeof(szFileBuffer));
    if (dwCount < 0)
    {
        dwError = LwMapErrnoToLwError(errno);
        BAIL_ON_LSA_ERROR(dwError);
    }

    if (dwCount == sizeof(szFileBuffer))
    {
        dwError = LW_ERROR_INVALID_AGENT_VERSION;
        BAIL_ON_LSA_ERROR(dwError);
    }
    szFileBuffer[dwCount] = 0;

    while (*pszPos)
    {
        LwStripWhitespace(pszPos, TRUE, TRUE);
        if (!strncmp(pszPos, "VERSION=", sizeof("VERSION=") - 1))
        {
            pszPos += sizeof("VERSION=") - 1;

            errno = 0;
            dwMajor = strtoul(pszPos, &pszPos, 10);

            dwError = LwMapErrnoToLwError(errno);
            BAIL_ON_LSA_ERROR(dwError);

            if (pszPos[0] != '.')
            {
                dwError = LW_ERROR_INVALID_AGENT_VERSION;
                BAIL_ON_LSA_ERROR(dwError);
            }
            pszPos++;
            dwMinor = strtoul(pszPos, &pszPos, 10);

            dwError = LwMapErrnoToLwError(errno);
            BAIL_ON_LSA_ERROR(dwError);
        }
        else if (!strncmp(pszPos, "BUILD=", sizeof("BUILD=") - 1))
        {
            pszPos += sizeof("BUILD=") - 1;

            errno = 0;
            dwBuild = strtoul(pszPos, &pszPos, 10);
            dwError = LwMapErrnoToLwError(errno);
            BAIL_ON_LSA_ERROR(dwError);
        }
        else if (!strncmp(pszPos, "REVISION=", sizeof("REVISION=") - 1))
        {
            pszPos += sizeof("REVISION=") - 1;

            errno = 0;
            dwRevision = strtoul(pszPos, &pszPos, 10);
            dwError = LwMapErrnoToLwError(errno);
            if (dwError != 0)
            {
                LSA_LOG_DEBUG("Unable to parse revision due to error %u", dwError);
                dwRevision = 0;
                dwError = 0;
            }
        }
        pszPos = strchr(pszPos, '\n');
        if (!pszPos)
        {
            break;
        }
        // Skip the \n
        pszPos++;
        if (*pszPos == '\r')
        {
            pszPos++;
        }
    }
    
    pVersion->dwMajor = dwMajor;
    pVersion->dwMinor = dwMinor;
    pVersion->dwBuild = dwBuild;
    pVersion->dwRevision = dwRevision;
    
cleanup:
    if (versionFile != -1)
    {
        close(versionFile);
    }
    return dwError;
    
error:
    memset(pVersion, 0, sizeof(*pVersion));
    goto cleanup;
}
Ejemplo n.º 9
0
DWORD
CheckSambaVersion(
    PCSTR pSmbdPath,
    PSTR *ppVersion
    )
{
    DWORD error = 0;
    PCSTR ppArgs[] = {
        pSmbdPath,
        "-V",
        0
    };
    PSTR pVersionString = NULL;

    error = CaptureOutputWithStderr(
                pSmbdPath,
                ppArgs,
                &pVersionString,
                NULL);
    BAIL_ON_LSA_ERROR(error);

    if (!strncmp(pVersionString, "Version ", sizeof("Version ") -1))
    {
        memmove(
                pVersionString,
                pVersionString + (sizeof("Version ") - 1),
                strlen(pVersionString) - (sizeof("Version ") - 1) + 1);
    }
    LwStripWhitespace(
            pVersionString,
            TRUE,
            TRUE);

    LW_RTL_LOG_ERROR("Found smbd version %s", pVersionString);

    if (!strncmp(pVersionString, "3.2.", sizeof("3.2.") - 1))
    {
    }
    else if (!strncmp(pVersionString, "3.4.", sizeof("3.4.") - 1))
    {
    }
    else if (!strncmp(pVersionString, "3.5.", sizeof("3.5.") - 1))
    {
    }
    else if (!strncmp(pVersionString, "3.6.", sizeof("3.6.") - 1))
    {
    }
    else if (!strncmp(pVersionString, "3.0.", sizeof("3.0.") - 1))
    {
        int build = 0;
        sscanf(pVersionString, "3.0.%d.", &build);

        if (build < 25)
        {
            LW_RTL_LOG_ERROR("Unsupported smbd version %s", pVersionString);
            error = ERROR_PRODUCT_VERSION;
            BAIL_ON_LSA_ERROR(error);
        }
    }
    else if (!strncmp(pVersionString, "4.", sizeof("4.") - 1))
    {
    }
    else
    {
        LW_RTL_LOG_ERROR("Unsupported smbd version %s", pVersionString);
        error = ERROR_PRODUCT_VERSION;
        BAIL_ON_LSA_ERROR(error);
    }


cleanup:
    if (error)
    {
        LW_SAFE_FREE_STRING(pVersionString);
    }
    *ppVersion = pVersionString;
    return error;
}
Ejemplo n.º 10
0
DWORD
GetIdmapDir(
    PCSTR pSmbdPath,
    PSTR* ppDir
    )
{
    DWORD error = 0;
    PSTR pCommandLine = NULL;
    PCSTR ppArgs[] = {
        "/bin/sh",
        "-c",
        NULL,
        NULL
    };
    PSTR pSambaLibdir = NULL;
    PSTR pDir = NULL;

    error = LwAllocateStringPrintf(
            &pCommandLine,
            "%s -b | grep MODULESDIR:",
            pSmbdPath
            );
    BAIL_ON_LSA_ERROR(error);

    ppArgs[2] = pCommandLine;

    error = CaptureOutputWithStderr(
                "/bin/sh",
                ppArgs,
                &pSambaLibdir,
                NULL);
    if (error == ERROR_BAD_COMMAND)
    {
        // This version of smbd is older than 3.4. Try looking for the LIBDIR
        // instead.
        LW_SAFE_FREE_STRING(pCommandLine);

        error = LwAllocateStringPrintf(
                &pCommandLine,
                "%s -b | grep LIBDIR:",
                pSmbdPath
                );
        BAIL_ON_LSA_ERROR(error);

        ppArgs[2] = pCommandLine;

        error = CaptureOutputWithStderr(
                    "/bin/sh",
                    ppArgs,
                    &pSambaLibdir,
                    NULL);
    }
    BAIL_ON_LSA_ERROR(error);

    LwStripWhitespace(
            pSambaLibdir,
            TRUE,
            TRUE);

    if (strstr(pSambaLibdir, ": "))
    {
        char *pValueStart = strstr(pSambaLibdir, ": ") + 2;
        memmove(
                pSambaLibdir,
                pValueStart,
                strlen(pSambaLibdir) - (pValueStart - pSambaLibdir) + 1);
    }

    error = LwAllocateStringPrintf(
            &pDir,
            "%s/idmap",
            pSambaLibdir
            );
    BAIL_ON_LSA_ERROR(error);

cleanup:
    *ppDir = pDir;
    LW_SAFE_FREE_STRING(pCommandLine);
    LW_SAFE_FREE_STRING(pSambaLibdir);
    return error;
}
Ejemplo n.º 11
0
DWORD
GetWbclientDir(
    PCSTR pSmbdPath,
    PSTR* ppDir
    )
{
    PCSTR ppBackupPaths[] = {
        "/usr/lib",
        "/usr/lib64",
        NULL,
    };
    DWORD index = 0;
    DWORD error = 0;
    BOOLEAN exists = 0;
    PSTR pFoundPath = NULL;
    PSTR pCommandLine = NULL;
    PCSTR ppArgs[] = {
        "/bin/sh",
        "-c",
        NULL,
        NULL
    };
    PSTR pSambaLibdir = NULL;

    *ppDir = NULL;

    // First see if libwbclient.so.0 is in Samba's libdir. There may be two
    // copies of libwbclient.so.0 because of different architectures. This will
    // identify which one is the primary one.
    error = LwAllocateStringPrintf(
            &pCommandLine,
            "%s -b | grep LIBDIR:",
            pSmbdPath
            );
    BAIL_ON_LSA_ERROR(error);

    ppArgs[2] = pCommandLine;

    error = CaptureOutputWithStderr(
                "/bin/sh",
                ppArgs,
                &pSambaLibdir,
                NULL);
    BAIL_ON_LSA_ERROR(error);

    LwStripWhitespace(
            pSambaLibdir,
            TRUE,
            TRUE);

    if (strstr(pSambaLibdir, ": "))
    {
        char *pValueStart = strstr(pSambaLibdir, ": ") + 2;
        memmove(
                pSambaLibdir,
                pValueStart,
                strlen(pSambaLibdir) - (pValueStart - pSambaLibdir) + 1);
    }

    error = FindFileInPath(
                    WBCLIENT_FILENAME,
                    pSambaLibdir,
                    &pFoundPath);
    if (error == ERROR_FILE_NOT_FOUND)
    {
        // Fall back to trying the two standard system paths
        error = FindFileInPath(
                        WBCLIENT_FILENAME,
                        "/usr/lib:/usr/lib64",
                        &pFoundPath);
        if (error == ERROR_FILE_NOT_FOUND)
        {
            error = 0;
        }
    }
    BAIL_ON_LSA_ERROR(error);

    if (pFoundPath)
    {
        pFoundPath[strlen(pFoundPath) - (sizeof(WBCLIENT_FILENAME) -1) - 1] = 0;
        *ppDir = pFoundPath;
        pFoundPath = NULL;
        goto cleanup;
    }

    // Could not find an existing libwbclient.so.0. This could be a Samba 3.0.x
    // build. Just stick the file in a system path.
    for (index = 0; ppBackupPaths[index]; index++)
    {
        error = LwCheckFileTypeExists(
                    ppBackupPaths[index],
                    LWFILE_DIRECTORY,
                    &exists);
        BAIL_ON_LSA_ERROR(error);

        if (exists)
        {
            error = LwAllocateString(ppBackupPaths[index], ppDir);
            BAIL_ON_LSA_ERROR(error);
            goto cleanup;
        }
    }

    // Could not find the system library paths.
    error = ERROR_FILE_NOT_FOUND;
    BAIL_ON_LSA_ERROR(error);

cleanup:
    LW_SAFE_FREE_STRING(pFoundPath);
    LW_SAFE_FREE_STRING(pCommandLine);
    LW_SAFE_FREE_STRING(pSambaLibdir);
    return error;
}
Ejemplo n.º 12
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;
}
Ejemplo n.º 13
0
DWORD
LsaNISGetNicknames(
    PCSTR         pszNicknameFilePath,
    PDLINKEDLIST* ppNicknameList
    )
{
    typedef enum
    {
        NIS_NICKNAME_ALIAS = 0,
        NIS_NICKNAME_NAME
    } NISNicknameTokenType;
    DWORD dwError = 0;
    PDLINKEDLIST pNicknameList = NULL;
    BOOLEAN bFileExists = FALSE;
    PLSA_NIS_NICKNAME pNickname = NULL;
    FILE* fp = NULL;
    NISNicknameTokenType nextTokenType = NIS_NICKNAME_ALIAS;

    dwError = LsaCheckFileExists(
                    pszNicknameFilePath,
                    &bFileExists);
    BAIL_ON_LSA_ERROR(dwError);

    if (!bFileExists)
    {
        dwError = ERROR_FILE_NOT_FOUND;
        BAIL_ON_LSA_ERROR(dwError);
    }

    fp = fopen(pszNicknameFilePath, "r");
    if (!fp)
    {
        dwError = LwMapErrnoToLwError(errno);
        BAIL_ON_LSA_ERROR(dwError);
    }

    while (1)
    {
        CHAR  szBuf[1024+1];
        PSTR  pszToken = NULL;
        PCSTR pszDelim = " \t\r\n";

        szBuf[0] = '\0';

        if (fgets(szBuf, 1024, fp) == NULL)
        {
            if (feof(fp))
            {
                break;
            }
            else
            {
                dwError = LwMapErrnoToLwError(errno);
                BAIL_ON_LSA_ERROR(dwError);
            }
        }

        LwStripWhitespace(szBuf, TRUE, TRUE);

        if (!szBuf[0] || (szBuf[0] == '#'))
        {
            // skip comments
            continue;
        }

        if ((pszToken = strchr(szBuf, '#')))
        {
            // Skip trailing comments
            *pszToken = '\0';
        }

        pszToken = szBuf;

        if (nextTokenType == NIS_NICKNAME_ALIAS)
        {
            size_t stLen = 0;

            stLen = strcspn(pszToken, pszDelim);
            if (!stLen)
            {
                dwError = LW_ERROR_INTERNAL;
                BAIL_ON_LSA_ERROR(dwError);
            }

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

            dwError = LwStrndup(
                            pszToken,
                            stLen,
                            &pNickname->pszMapAlias);
            BAIL_ON_LSA_ERROR(dwError);

            // Skip token
            pszToken += stLen;

            stLen = strspn(pszToken, pszDelim);
            if (stLen)
            {
                // Skip delimiter
                pszToken += stLen;
            }

            nextTokenType = NIS_NICKNAME_NAME;
        }

        // The name might appear on the same line
        // Or it might appear on the next line
        if (nextTokenType == NIS_NICKNAME_NAME)
        {
            if (LW_IS_NULL_OR_EMPTY_STR(pszToken))
            {
                continue;
            }

            // The rest of the line is the name
            // we already removed trailing comments
            dwError = LwAllocateString(
                            pszToken,
                            &pNickname->pszMapName);
            BAIL_ON_LSA_ERROR(dwError);

            dwError = LsaDLinkedListAppend(
                            &pNicknameList,
                            pNickname);
            BAIL_ON_LSA_ERROR(dwError);

            pNickname = NULL;

            nextTokenType = NIS_NICKNAME_ALIAS;
        }
    }

    *ppNicknameList = pNicknameList;

cleanup:

    if (fp)
    {
        fclose(fp);
    }

    if (pNickname)
    {
        LsaNISFreeNickname(pNickname);
    }

    return dwError;

error:

    *ppNicknameList = NULL;

    if (pNicknameList)
    {
        LsaNISFreeNicknameList(pNicknameList);
    }

    goto cleanup;
}
Ejemplo n.º 14
0
static
DWORD
LsaAdBatchMarshalUserInfo(
    IN PLSA_AD_PROVIDER_STATE pState,
    IN OUT PLSA_AD_BATCH_ITEM_USER_INFO pUserInfo,
    OUT PLSA_SECURITY_OBJECT_USER_INFO pObjectUserInfo,
    IN PCSTR pszDnsDomainName,
    IN PCSTR pszNetbiosDomainName,
    IN PCSTR pszSamAccountName,
    IN PCSTR pszSid
    )
{
    DWORD dwError = 0;
    PAD_PROVIDER_DATA pProviderData = pState->pProviderData;

    pObjectUserInfo->bIsGeneratedUPN = FALSE;

    if (LsaAdBatchIsUnprovisionedMode(pProviderData))
    {
        dwError = LsaAdBatchMarshalUnprovisionedUser(
                        pProviderData,
                        pUserInfo,
                        pszDnsDomainName,
                        pszNetbiosDomainName,
                        pszSamAccountName,
                        pszSid);
        BAIL_ON_LSA_ERROR(dwError);
    }

    pObjectUserInfo->uid = pUserInfo->uid;
    pObjectUserInfo->gid = pUserInfo->gid;

    if (pUserInfo->dwPrimaryGroupRid)
    {
        dwError = LsaReplaceSidRid(
            pszSid,
            pUserInfo->dwPrimaryGroupRid,
            &pObjectUserInfo->pszPrimaryGroupSid);
        BAIL_ON_LSA_ERROR(dwError);
    }

    LSA_XFER_STRING(pUserInfo->pszAlias, pObjectUserInfo->pszAliasName);
    LSA_XFER_STRING(pUserInfo->pszPasswd, pObjectUserInfo->pszPasswd);
    LSA_XFER_STRING(pUserInfo->pszGecos, pObjectUserInfo->pszGecos);
    LSA_XFER_STRING(pUserInfo->pszShell, pObjectUserInfo->pszShell);
    LSA_XFER_STRING(pUserInfo->pszHomeDirectory, pObjectUserInfo->pszHomedir);
    LSA_XFER_STRING(pUserInfo->pszUserPrincipalName, pObjectUserInfo->pszUPN);
    LSA_XFER_STRING(pUserInfo->pszDisplayName, pObjectUserInfo->pszDisplayName);
    LSA_XFER_STRING(pUserInfo->pszWindowsHomeFolder, pObjectUserInfo->pszWindowsHomeFolder);
    LSA_XFER_STRING(pUserInfo->pszLocalWindowsHomeFolder, pObjectUserInfo->pszLocalWindowsHomeFolder);

    pObjectUserInfo->qwPwdLastSet = pUserInfo->PasswordLastSet;
    pObjectUserInfo->qwPwdExpires = pUserInfo->PasswordExpires;
    pObjectUserInfo->qwAccountExpires = pUserInfo->AccountExpires;

    // Handle shell.
    LwStripWhitespace(pObjectUserInfo->pszShell, TRUE, TRUE);
    dwError = LsaAdBatchMarshalUserInfoFixShell(
                  pState,
                  &pObjectUserInfo->pszShell);
    BAIL_ON_LSA_ERROR(dwError);

    // Handle home directory.
    LwStripWhitespace(pObjectUserInfo->pszHomedir, TRUE, TRUE);
    dwError = LsaAdBatchMarshalUserInfoFixHomeDirectory(
                    pState,
                    &pObjectUserInfo->pszHomedir,
                    pszNetbiosDomainName,
                    pszSamAccountName);
    BAIL_ON_LSA_ERROR(dwError);

    // Handle local windows home folder
    LwStripWhitespace(pObjectUserInfo->pszLocalWindowsHomeFolder, TRUE, TRUE);
    dwError = LsaAdBatchMarshalUserInfoFixLocalWindowsHomeFolder(
                    pState,
                    &pObjectUserInfo->pszLocalWindowsHomeFolder,
                    pszNetbiosDomainName,
                    pszSamAccountName);
    BAIL_ON_LSA_ERROR(dwError);

    // Handle UPN.
    if (!pObjectUserInfo->pszUPN)
    {
        dwError = ADGetLDAPUPNString(
                        0,
                        NULL,
                        pszDnsDomainName,
                        pszSamAccountName,
                        &pObjectUserInfo->pszUPN,
                        &pObjectUserInfo->bIsGeneratedUPN);
        BAIL_ON_LSA_ERROR(dwError);
    }

    // Decode account control flags.
    LsaAdBatchMarshalUserInfoAccountControl(
            pUserInfo->UserAccountControl,
            pObjectUserInfo);

    // Figure out account expiration.
    dwError = LsaAdBatchMarshalUserInfoAccountExpires(
                    pUserInfo->AccountExpires,
                    pObjectUserInfo,
                    pszSamAccountName);
    BAIL_ON_LSA_ERROR(dwError);

    // Figure out password prompting.
    dwError = LsaAdBatchMarshalUserInfoPasswordExpires(
                    pUserInfo->PasswordExpires,
                    pObjectUserInfo,
                    pszSamAccountName);
    BAIL_ON_LSA_ERROR(dwError);

cleanup:
    return dwError;

error:
    goto cleanup;
}
Ejemplo n.º 15
0
DWORD
LWNetDnsGetNameServerList(
    OUT PSTR** pppszNameServerList,
    OUT PDWORD pdwNumServers
    )
// Call LWNET_SAFE_FREE_STRING_ARRAY on returned server list
{
    DWORD   dwError = 0;
    PSTR*   ppszNameServerList = NULL;
    DWORD   dwNumServers = 0;
    FILE*   fp = NULL;
    BOOLEAN bFileExists = FALSE;
    PCSTR   pszConfigFilePath = "/etc/resolv.conf";
    const   DWORD dwMaxLineLen = 1024;
    CHAR    szBuf[dwMaxLineLen + 1];
    regex_t rx;
    PDLINKEDLIST pNameServerList = NULL;
    PSTR    pszNameServer = NULL;
    
    memset(&rx, 0, sizeof(rx));
    
    if (regcomp(&rx, "^nameserver[[:space:]].*$", REG_EXTENDED) < 0) {
        dwError = ERROR_BAD_FORMAT;
        BAIL_ON_LWNET_ERROR(dwError);
    }
    
    dwError = LwCheckFileTypeExists(
                    pszConfigFilePath,
                    LWFILE_REGULAR,
                    &bFileExists);
    BAIL_ON_LWNET_ERROR(dwError);
    
    if (!bFileExists) {
        *pppszNameServerList = NULL;
        *pdwNumServers = 0;
        goto cleanup;
    }
    
    if ((fp = fopen(pszConfigFilePath, "r")) == NULL) {
        dwError = LwMapErrnoToLwError(errno);
        BAIL_ON_LWNET_ERROR(dwError);
    } 
    
    while (1)
    {
          if (fgets(szBuf, dwMaxLineLen, fp) == NULL) {
             if (!feof(fp)) {
                dwError = LwMapErrnoToLwError(errno);
                BAIL_ON_LWNET_ERROR(dwError);
             } else {
                break;
             }
          }
          
          LwStripWhitespace(szBuf, TRUE, TRUE);
          
          if (!LWNetDnsConfigLineIsComment(szBuf) &&
              !regexec(&rx, szBuf, (size_t)0, NULL, 0))
          {
             PSTR pszLocation = NULL;
             PCSTR pszSearchString = "nameserver";
             
             if ((pszLocation = strstr(szBuf, pszSearchString))) {
                pszLocation += strlen(pszSearchString);
                
                if (!IsNullOrEmptyString(pszLocation)) {
                   dwError = LWNetAllocateString(pszLocation, &pszNameServer);
                   BAIL_ON_LWNET_ERROR(dwError);
                }
                
                dwError = LWNetDLinkedListAppend(
                                    &pNameServerList,
                                    pszNameServer);
                BAIL_ON_LWNET_ERROR(dwError);
                
                pszNameServer = NULL;
                
                dwNumServers++;
             }
          }
    }
    
    if (dwNumServers)
    {
        PDLINKEDLIST pListMember = NULL;
        DWORD iMember = 0;

        dwError = LWNetAllocateMemory(dwNumServers * sizeof(PSTR), (PVOID*)&ppszNameServerList);
        BAIL_ON_LWNET_ERROR(dwError);

        pListMember = pNameServerList;
        while (pListMember)
        {
            ppszNameServerList[iMember++] = (PSTR)pListMember->pItem;
            pListMember->pItem = NULL;
            pListMember = pListMember->pNext;
        }
    }

    *pppszNameServerList = ppszNameServerList;
    *pdwNumServers = dwNumServers;

cleanup:

    regfree(&rx);
    
    LWNetDLinkedListFree(pNameServerList);
    
    LWNET_SAFE_FREE_STRING(pszNameServer);
    
    if (fp) {
        fclose(fp);
    }

    return dwError;
    
error:

    *pppszNameServerList = NULL;
    *pdwNumServers = 0;
    
    if (ppszNameServerList) {
       LWNetFreeStringArray(ppszNameServerList, dwNumServers);
    }

    goto cleanup;
}