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