VOID LsaNssClearEnumUsersState( HANDLE hLsaConnection, PLSA_ENUMUSERS_STATE pState ) { if (pState->ppUserInfoList) { LsaFreeUserInfoList( pState->dwUserInfoLevel, pState->ppUserInfoList, pState->dwNumUsers ); pState->ppUserInfoList = (HANDLE)NULL; } if (hLsaConnection && pState->hResume != (HANDLE)NULL) { LsaEndEnumUsers(hLsaConnection, pState->hResume); pState->hResume = (HANDLE)NULL; } memset(pState, 0, sizeof(LSA_ENUMUSERS_STATE)); }
/* * CheckLsaEnumUsers * * Check LSA_USER_INFO_* list from LsaEnumUsers has expected user. * */ DWORD CheckLsaEnumUsers( HANDLE hLsaConnection, PCSTR pszUser, DWORD dwUserInfoLevel, DWORD dwMaxNumUsers ) { DWORD dwError = LW_ERROR_SUCCESS; DWORD dwLocalError = LW_ERROR_SUCCESS; DWORD dwNumUsers = 0; HANDLE hResume = NULL; PVOID *ppUserInfoList = NULL; /* Set to true if we ever return more users than we should. * Used to avoid repeating messages uselessly. */ BOOL bViolated_dwMaxNumUsers = 0; char szTestMsg[128] = { 0 }; PCSTR pszTestDescription = "LsaEnumUsers retrieved LSA_USER_INFO_* list containing expected user."; PCSTR pszTestAPIs = "LsaBeginEnumUsers," "LsaEnumUsers," "LsaFreeUserInfoList," "LsaEndEnumUsers"; snprintf( szTestMsg, sizeof(szTestMsg), "Looking for %s, lists of max length %lu, dwUserInfoLevel = %lu.", pszUser, (unsigned long)dwMaxNumUsers, (unsigned long)dwUserInfoLevel); /* Only one flag right now: LSA_FIND_FLAGS_NSS */ dwLocalError = LsaBeginEnumUsers( hLsaConnection, dwUserInfoLevel, dwMaxNumUsers, 0, /* Flags */ &hResume); BAIL_ON_TEST_BROKE(dwLocalError); do { dwNumUsers = 0; dwLocalError = LsaEnumUsers( hLsaConnection, hResume, &dwNumUsers, (PVOID**) &ppUserInfoList); BAIL_ON_TEST_BROKE(dwLocalError); /* Avoid testing/reporting problem more than once. */ if ( ! bViolated_dwMaxNumUsers ) { if ( dwNumUsers > dwMaxNumUsers ) { char buf[64]; bViolated_dwMaxNumUsers = 1; snprintf( buf, sizeof(buf), "Violation: returned %lu users.", (unsigned long)dwNumUsers); Lwt_strcat( szTestMsg, sizeof(szTestMsg), buf); dwError = LW_ERROR_TEST_FAILED; } } if ( CheckForUserInUserInfoList( dwUserInfoLevel, ppUserInfoList, dwNumUsers, pszUser) == LW_ERROR_SUCCESS ) { /* Found user, good, time to leave. */ goto cleanup; } LsaFreeUserInfoList(dwUserInfoLevel, ppUserInfoList, dwNumUsers); ppUserInfoList = NULL; } while ( dwNumUsers > 0 ); /* If we are here, a user was missing. */ dwError = LW_ERROR_TEST_FAILED; cleanup: if ( ppUserInfoList ) { LsaFreeUserInfoList(dwUserInfoLevel, ppUserInfoList, dwNumUsers); ppUserInfoList = NULL; dwNumUsers = 0; } if ( hResume != (HANDLE)NULL) { LsaEndEnumUsers(hLsaConnection, hResume); hResume = NULL; } LWT_LOG_TEST(szTestMsg); return dwError; error: goto cleanup; }
PVOID LADSEnumGroups( PVOID pData ) { DWORD dwError = 0; PVOID pResult = NULL; DWORD dwInfoLevel = gLADSStressData[LADS_ENUM_GROUPS].dwInfoLevel; DWORD dwMaxNumGroups = 500; DWORD dwNumGroupsFound = 0; PVOID* ppGroupInfos = NULL; HANDLE hProvider = (HANDLE)NULL; HANDLE hResume = (HANDLE)NULL; while (!LADSProcessShouldStop()) { dwError = gpAuthProvider->pFnTable->pfnOpenHandle( geteuid(), getegid(), getpid(), &hProvider); BAIL_ON_LSA_ERROR(dwError); dwError = gpAuthProvider->pFnTable->pfnBeginEnumGroups( hProvider, dwInfoLevel, FALSE, 0, &hResume); BAIL_ON_LSA_ERROR(dwError); do { if (dwNumGroupsFound) { LsaFreeUserInfoList( dwInfoLevel, ppGroupInfos, dwNumGroupsFound); ppGroupInfos = NULL; dwNumGroupsFound = 0; } dwError = gpAuthProvider->pFnTable->pfnEnumGroups( hProvider, hResume, dwMaxNumGroups, &dwNumGroupsFound, &ppGroupInfos); BAIL_ON_LSA_ERROR(dwError); } while (dwNumGroupsFound && !LADSProcessShouldStop()); gpAuthProvider->pFnTable->pfnEndEnumGroups( hProvider, hResume); hResume = (HANDLE)NULL; gpAuthProvider->pFnTable->pfnCloseHandle(hProvider); hProvider = (HANDLE)NULL; if (gLADSStressData[LADS_ENUM_GROUPS].dwSleepMSecs) { sleep(gLADSStressData[LADS_ENUM_GROUPS].dwSleepMSecs); } } cleanup: if (dwNumGroupsFound) { LsaFreeUserInfoList( dwInfoLevel, ppGroupInfos, dwNumGroupsFound); } if (hProvider != (HANDLE)NULL) { if (hResume != (HANDLE)NULL) { gpAuthProvider->pFnTable->pfnEndEnumGroups( hProvider, hResume); } gpAuthProvider->pFnTable->pfnCloseHandle(hProvider); } return pResult; error: LSA_LOG_ERROR("Failed to enumerate groups [error code: %u]", dwError); LADSStopProcess(); goto cleanup; }
int enum_users_main( int argc, char* argv[] ) { DWORD dwError = 0; DWORD dwUserInfoLevel = 0; DWORD dwBatchSize = 10; HANDLE hLsaConnection = (HANDLE)NULL; HANDLE hResume = (HANDLE)NULL; PVOID* ppUserInfoList = NULL; DWORD dwNumUsersFound = 0; DWORD dwTotalUsersFound = 0; size_t dwErrorBufferSize = 0; BOOLEAN bPrintOrigError = TRUE; BOOLEAN bCheckUserInList = FALSE; dwError = ParseArgs(argc, argv, &dwUserInfoLevel, &dwBatchSize, &bCheckUserInList); BAIL_ON_LSA_ERROR(dwError); dwError = LsaOpenServer(&hLsaConnection); BAIL_ON_LSA_ERROR(dwError); dwError = LsaBeginEnumUsers( hLsaConnection, dwUserInfoLevel, dwBatchSize, 0, &hResume); BAIL_ON_LSA_ERROR(dwError); do { DWORD iUser = 0; if (ppUserInfoList) { LsaFreeUserInfoList(dwUserInfoLevel, ppUserInfoList, dwNumUsersFound); ppUserInfoList = NULL; } dwError = LsaEnumUsers( hLsaConnection, hResume, &dwNumUsersFound, &ppUserInfoList); BAIL_ON_LSA_ERROR(dwError); if (!dwNumUsersFound) { break; } dwTotalUsersFound+=dwNumUsersFound; for (iUser = 0; iUser < dwNumUsersFound; iUser++) { BOOLEAN bAllowedLogon = TRUE; PVOID pUserInfo = *(ppUserInfoList + iUser); if (bCheckUserInList) { dwError = LsaCheckUserInList( hLsaConnection, ((PLSA_USER_INFO_0)pUserInfo)->pszName, NULL); if (dwError) { bAllowedLogon = FALSE; } } switch(dwUserInfoLevel) { case 0: PrintUserInfo_0((PLSA_USER_INFO_0)pUserInfo, bCheckUserInList, bAllowedLogon); break; case 1: PrintUserInfo_1((PLSA_USER_INFO_1)pUserInfo, bCheckUserInList, bAllowedLogon); break; case 2: PrintUserInfo_2((PLSA_USER_INFO_2)pUserInfo, bCheckUserInList, bAllowedLogon); break; default: fprintf(stderr, "Error: Invalid user info level %u\n", dwUserInfoLevel); break; } } } while (dwNumUsersFound); fprintf(stdout, "TotalNumUsersFound: %u\n", dwTotalUsersFound); cleanup: if (ppUserInfoList) { LsaFreeUserInfoList(dwUserInfoLevel, ppUserInfoList, dwNumUsersFound); } if ((hResume != (HANDLE)NULL) && (hLsaConnection != (HANDLE)NULL)) { LsaEndEnumUsers(hLsaConnection, hResume); } if (hLsaConnection != (HANDLE)NULL) { LsaCloseServer(hLsaConnection); } return (dwError); error: dwError = MapErrorCode(dwError); dwErrorBufferSize = LwGetErrorString(dwError, NULL, 0); if (dwErrorBufferSize > 0) { DWORD dwError2 = 0; PSTR pszErrorBuffer = NULL; dwError2 = LwAllocateMemory( dwErrorBufferSize, (PVOID*)&pszErrorBuffer); if (!dwError2) { DWORD dwLen = LwGetErrorString(dwError, pszErrorBuffer, dwErrorBufferSize); if ((dwLen == dwErrorBufferSize) && !LW_IS_NULL_OR_EMPTY_STR(pszErrorBuffer)) { fprintf(stderr, "Failed to enumerate users. Error code %u (%s).\n" "%s\n", dwError, LW_PRINTF_STRING(LwWin32ExtErrorToName(dwError)), pszErrorBuffer); bPrintOrigError = FALSE; } if (dwError == ERROR_INVALID_DATA) { fprintf(stderr, "The users list has changed while enumerating. " "Try again.\n"); } } LW_SAFE_FREE_STRING(pszErrorBuffer); } if (bPrintOrigError) { fprintf(stderr, "Failed to enumerate users. Error code %u (%s).\n", dwError, LW_PRINTF_STRING(LwWin32ExtErrorToName(dwError))); } goto cleanup; }
static DWORD EnumerateUsers( HANDLE hLsaConnection, BOOLEAN bPrintKeys, BOOLEAN bIndexById ) { DWORD dwError = 0; DWORD dwUserInfoLevel = 2; DWORD dwBatchSize = 100; DWORD dwNumUsersFound = 0; PVOID* ppUserInfoList = NULL; HANDLE hResume = (HANDLE)NULL; dwError = LsaBeginEnumUsers( hLsaConnection, dwUserInfoLevel, dwBatchSize, 0, &hResume); BAIL_ON_LSA_ERROR(dwError); do { DWORD iUser = 0; if (ppUserInfoList) { LsaFreeUserInfoList(dwUserInfoLevel, ppUserInfoList, dwNumUsersFound); ppUserInfoList = NULL; } dwError = LsaEnumUsers( hLsaConnection, hResume, &dwNumUsersFound, &ppUserInfoList); BAIL_ON_LSA_ERROR(dwError); if (!dwNumUsersFound) { break; } for (iUser = 0; iUser < dwNumUsersFound; iUser++) { PLSA_USER_INFO_2 pUserInfo = (PLSA_USER_INFO_2)*(ppUserInfoList + iUser); PrintUserInfo_2(pUserInfo, bPrintKeys, bIndexById); } } while (dwNumUsersFound); cleanup: if (ppUserInfoList) { LsaFreeUserInfoList(dwUserInfoLevel, ppUserInfoList, dwNumUsersFound); } if ((hResume != (HANDLE)NULL) && (hLsaConnection != (HANDLE)NULL)) { LsaEndEnumUsers(hLsaConnection, hResume); } return dwError; error: goto cleanup; }
NSS_STATUS LsaNssCommonPasswdGetpwent( PLSA_NSS_CACHED_HANDLE pConnection, PLSA_ENUMUSERS_STATE pEnumUsersState, struct passwd * pResultUser, char* pszBuf, size_t bufLen, int* pErrorNumber ) { int ret = NSS_STATUS_NOTFOUND; HANDLE hLsaConnection = pConnection->hLsaConnection; if (hLsaConnection == (HANDLE)NULL) { ret = MAP_LSA_ERROR(pErrorNumber, LW_ERROR_INVALID_LSA_CONNECTION); BAIL_ON_NSS_ERROR(ret); } if (!pEnumUsersState->bTryAgain) { if (!pEnumUsersState->idxUser || (pEnumUsersState->idxUser >= pEnumUsersState->dwNumUsers)) { if (pEnumUsersState->ppUserInfoList) { LsaFreeUserInfoList( pEnumUsersState->dwUserInfoLevel, pEnumUsersState->ppUserInfoList, pEnumUsersState->dwNumUsers); pEnumUsersState->ppUserInfoList = NULL; pEnumUsersState->dwNumUsers = 0; pEnumUsersState->idxUser = 0; } ret = MAP_LSA_ERROR(pErrorNumber, LsaEnumUsers( hLsaConnection, pEnumUsersState->hResume, &pEnumUsersState->dwNumUsers, &pEnumUsersState->ppUserInfoList)); BAIL_ON_NSS_ERROR(ret); } } if (pEnumUsersState->dwNumUsers) { PLSA_USER_INFO_0 pUserInfo = (PLSA_USER_INFO_0)*(pEnumUsersState->ppUserInfoList+pEnumUsersState->idxUser); ret = MAP_LSA_ERROR(pErrorNumber, LsaNssWriteUserInfo( pEnumUsersState->dwUserInfoLevel, pUserInfo, pResultUser, &pszBuf, bufLen)); BAIL_ON_NSS_ERROR(ret); pEnumUsersState->idxUser++; ret = NSS_STATUS_SUCCESS; } else { ret = NSS_STATUS_UNAVAIL; if (pErrorNumber) { *pErrorNumber = ENOENT; } } pEnumUsersState->bTryAgain = FALSE; cleanup: return ret; error: if ((ret == NSS_STATUS_TRYAGAIN) && pErrorNumber && (*pErrorNumber == ERANGE)) { pEnumUsersState->bTryAgain = TRUE; } else { LsaNssClearEnumUsersState(hLsaConnection, pEnumUsersState); if ( hLsaConnection != (HANDLE)NULL) { if (ret != NSS_STATUS_TRYAGAIN && ret != NSS_STATUS_NOTFOUND) { LsaNssCommonCloseConnection(pConnection); } } } if (bufLen && pszBuf) { memset(pszBuf, 0, bufLen); } goto cleanup; }