static NET_API_STATUS EnumerateUsers(VOID) { PUSER_INFO_0 pBuffer = NULL; PSERVER_INFO_100 pServer = NULL; DWORD dwRead = 0, dwTotal = 0; DWORD i; DWORD_PTR ResumeHandle = 0; NET_API_STATUS Status; Status = NetServerGetInfo(NULL, 100, (LPBYTE*)&pServer); if (Status != NERR_Success) return Status; ConPuts(StdOut, L"\n"); ConResPrintf(StdOut, IDS_USER_ACCOUNTS, pServer->sv100_name); ConPuts(StdOut, L"\n\n"); PrintPadding(L'-', 79); ConPuts(StdOut, L"\n"); NetApiBufferFree(pServer); do { Status = NetUserEnum(NULL, 0, 0, (LPBYTE*)&pBuffer, MAX_PREFERRED_LENGTH, &dwRead, &dwTotal, &ResumeHandle); if ((Status != NERR_Success) && (Status != ERROR_MORE_DATA)) return Status; qsort(pBuffer, dwRead, sizeof(PUSER_INFO_0), CompareInfo); for (i = 0; i < dwRead; i++) { if (pBuffer[i].usri0_name) ConPrintf(StdOut, L"%s\n", pBuffer[i].usri0_name); } NetApiBufferFree(pBuffer); pBuffer = NULL; } while (Status == ERROR_MORE_DATA); return NERR_Success; }
// @pymethod ([dict, ...], total, resumeHandle)|win32net|NetUserEnum|Enumerates all users. // @rdesc The result is a list of items read (with each item being a dictionary of format // <o PyUSER_INFO_*>, depending on the level parameter), // the total available, and a new "resume handle". The first time you call // this function, you should pass zero for the resume handle. If more data // is available than what was returned, a new non-zero resume handle will be // returned, which can be used to call the function again to fetch more data. // This process may repeat, each time with a new resume handle, until zero is // returned for the new handle, indicating all the data has been read. PyObject *PyNetUserEnum(PyObject *self, PyObject *args) { WCHAR *szServer = NULL; PyObject *obServer; PyObject *ret = NULL; PyNET_STRUCT *pInfo; DWORD err; DWORD dwPrefLen = MAX_PREFERRED_LENGTH; DWORD level; DWORD filter = FILTER_NORMAL_ACCOUNT; BOOL ok = FALSE; DWORD resumeHandle = 0; DWORD numRead, i; PyObject *list; BYTE *buf = NULL; DWORD totalEntries = 0; // @pyparm string/<o PyUnicode>|server||The name of the server, or None. // @pyparm int|level||The level of data required. // @pyparm int|filter|win32netcon.FILTER_NORMAL_ACCOUNT|The types of accounts to enumerate. // @pyparm int|resumeHandle|0|A resume handle. See the return description for more information. // @pyparm int|prefLen|MAX_PREFERRED_LENGTH|The preferred length of the data buffer. if (!PyArg_ParseTuple(args, "Oi|iii", &obServer, &level, &filter, &resumeHandle, &dwPrefLen)) return NULL; if (!PyWinObject_AsWCHAR(obServer, &szServer, TRUE)) goto done; if (!FindNET_STRUCT(level, user_infos, &pInfo)) goto done; err = NetUserEnum(szServer, level, filter, &buf, dwPrefLen, &numRead, &totalEntries, &resumeHandle); if (err!=0 && err != ERROR_MORE_DATA) { ReturnNetError("NetUserEnum",err); // @pyseeapi NetUserEnum goto done; } list = PyList_New(numRead); if (list==NULL) goto done; for (i=0;i<numRead;i++) { PyObject *sub = PyObject_FromNET_STRUCT(pInfo, buf+(i*pInfo->structsize)); if (sub==NULL) goto done; PyList_SET_ITEM(list, i, sub); } resumeHandle = err==0 ? 0 : resumeHandle; ret = Py_BuildValue("Oll", list, totalEntries, resumeHandle); Py_DECREF(list); ok = TRUE; done: if (buf) NetApiBufferFree(buf); if (!ok) { Py_XDECREF(ret); ret = NULL; } PyWinObject_FreeWCHAR(szServer); return ret; }
bool CScannerNetBios::GetUsers(list<userinfo*> *lpUsers) { DWORD dwEntriesRead=0, dwRemaining=0, dwResume=0, dwRC; do { dwRC=NetUserEnum(m_wszServer, 1, 0, (LPBYTE*)&m_UserInfo, MAX_PREFERRED_LENGTH, &dwEntriesRead, &dwRemaining, &dwResume); if(dwRC!=ERROR_MORE_DATA && dwRC!=ERROR_SUCCESS) break; USER_INFO_1 *l_UserInfo=m_UserInfo; for(int x=0; x<(int)dwEntriesRead; x++) { userinfo *pUser=new userinfo; WideCharToMultiByte(CP_ACP, 0, l_UserInfo->usri1_name, -1, pUser->sName.GetBuffer(256), 256, NULL, NULL); WideCharToMultiByte(CP_ACP, 0, m_wszHost, -1, pUser->sServer.GetBuffer(256), 256, NULL, NULL); lpUsers->push_back(pUser); l_UserInfo++; } if(m_UserInfo!=0) NetApiBufferFree(m_UserInfo); } while(dwRC==ERROR_MORE_DATA); if(dwRC!=ERROR_SUCCESS) return false; return true; }
static VOID UpdateUsersList(HWND hwndListView) { NET_API_STATUS netStatus; PUSER_INFO_20 pBuffer; DWORD entriesread; DWORD totalentries; DWORD resume_handle = 0; DWORD i; LV_ITEM lvi; INT iItem; for (;;) { netStatus = NetUserEnum(NULL, 20, FILTER_NORMAL_ACCOUNT, (LPBYTE*)&pBuffer, 1024, &entriesread, &totalentries, &resume_handle); if (netStatus != NERR_Success && netStatus != ERROR_MORE_DATA) break; for (i = 0; i < entriesread; i++) { memset(&lvi, 0x00, sizeof(lvi)); lvi.mask = LVIF_TEXT | LVIF_STATE | LVIF_IMAGE; lvi.pszText = pBuffer[i].usri20_name; lvi.state = 0; lvi.iImage = (pBuffer[i].usri20_flags & UF_ACCOUNTDISABLE) ? 1 : 0; iItem = ListView_InsertItem(hwndListView, &lvi); if (pBuffer[i].usri20_full_name != NULL) ListView_SetItemText(hwndListView, iItem, 1, pBuffer[i].usri20_full_name); if (pBuffer[i].usri20_comment != NULL) ListView_SetItemText(hwndListView, iItem, 2, pBuffer[i].usri20_comment); } NetApiBufferFree(pBuffer); /* No more data left */ if (netStatus != ERROR_MORE_DATA) break; } }
static int get_all_local_users(struct oscap_list *list) { NET_API_STATUS status; USER_INFO_0 *buffer = NULL; DWORD preffered_max_len = MAX_PREFERRED_LENGTH; DWORD entries_read = 0; DWORD total_entries = 0; DWORD resume_handle = 0; status = NetUserEnum(NULL, 0, 0, (LPBYTE *)&buffer, preffered_max_len, &entries_read, &total_entries, &resume_handle); if (status != NERR_Success) { dD("NetUserEnum failed: %d", status); return 1; } for (DWORD i = 0; i < entries_read; i++) { WCHAR *user_name = buffer[i].usri0_name; oscap_list_add(list, wcsdup(user_name)); } NetApiBufferFree(buffer); return 0; }
APIERR MNetUserEnum( const TCHAR FAR * pszServer, UINT Level, UINT Filter, BYTE FAR ** ppbBuffer, ULONG ulMaxPreferred, UINT FAR * pcEntriesRead, UINT FAR * pcTotalEntries, VOID FAR * pResumeKey ) { return (APIERR)NetUserEnum( (TCHAR *)pszServer, Level, Filter, ppbBuffer, ulMaxPreferred, pcEntriesRead, pcTotalEntries, pResumeKey ); } // MNetUserEnum
std::vector<Account*> UserUtilities::GetAccountList() { std::vector<Account*> lstAccount; USER_INFO_2* user = NULL; USER_INFO_2* tempuser; DWORD level = 2; DWORD filter = 2; BYTE* iAccountNum; DWORD iEntriesRead = 0; DWORD iTotalEntries = 0; DWORD iResume = 0; int iRes = NetUserEnum(NULL, level, filter, (LPBYTE*)&user, -1, &iEntriesRead, &iTotalEntries, &iResume); tempuser = user; for(int i = 0;i < iEntriesRead;i++) { Account* acc = new Account(); acc->m_StrUserName = tempuser->usri2_name; acc->m_StrFullName = tempuser->usri2_full_name; acc->m_StrDescription = tempuser->usri2_comment; acc->iType = tempuser->usri2_priv; lstAccount.push_back(acc); tempuser++; } if (user != NULL) { NetApiBufferFree(user); user = NULL; } return lstAccount; }
QueryData genUsers(QueryContext& context) { QueryData results; // USER_INFO_3 conains generic user information LPUSER_INFO_3 pUserBuffer = nullptr; DWORD dwGenericUserLevel = 3; DWORD dwPreferredMaxLength = MAX_PREFERRED_LENGTH; DWORD dwEntriesRead = 0; DWORD dwTotalEntries = 0; DWORD dwResumeHandle = 0; NET_API_STATUS nEnumStatus; nEnumStatus = NetUserEnum(nullptr, dwGenericUserLevel, FILTER_NORMAL_ACCOUNT, (LPBYTE*)&pUserBuffer, dwPreferredMaxLength, &dwEntriesRead, &dwTotalEntries, &dwResumeHandle); // We save the original pointer to the USER_INFO_3 buff for mem management LPUSER_INFO_3 pUserIterationBuffer = pUserBuffer; if (pUserIterationBuffer == nullptr || nEnumStatus != NERR_Success) { if (pUserBuffer != nullptr) { NetApiBufferFree(pUserBuffer); } return results; } for (DWORD i = 0; i < dwEntriesRead; i++) { Row r; r["username"] = wstringToString(pUserIterationBuffer->usri3_name); r["description"] = wstringToString(pUserIterationBuffer->usri3_comment); r["uid"] = BIGINT(pUserIterationBuffer->usri3_user_id); r["gid"] = BIGINT(pUserIterationBuffer->usri3_primary_group_id); r["uid_signed"] = r["uid"]; r["gid_signed"] = r["gid"]; r["shell"] = "C:\\Windows\\system32\\cmd.exe"; // USER_INFO_23 contains detailed info, like the user Sid DWORD dwDetailedUserLevel = 23; LPUSER_INFO_23 pSidUserBuffer = nullptr; NET_API_STATUS nStatus; nStatus = NetUserGetInfo(nullptr, pUserIterationBuffer->usri3_name, dwDetailedUserLevel, (LPBYTE*)&pSidUserBuffer); if (nStatus != NERR_Success) { if (pSidUserBuffer != nullptr) { NetApiBufferFree(pSidUserBuffer); pSidUserBuffer = nullptr; } continue; } LPTSTR sStringSid = nullptr; auto ret = ConvertSidToStringSid(pSidUserBuffer->usri23_user_sid, &sStringSid); if (ret == 0) { if (pSidUserBuffer != nullptr) { NetApiBufferFree(pSidUserBuffer); } continue; } r["uuid"] = sStringSid; std::string query = "SELECT LocalPath FROM Win32_UserProfile where SID=\"" + std::string(sStringSid) + "\""; WmiRequest wmiRequest(query); std::vector<WmiResultItem>& wmiResults = wmiRequest.results(); if (wmiResults.size() != 0) { wmiResults[0].GetString("LocalPath", r["directory"]); } LocalFree(sStringSid); NetApiBufferFree(pSidUserBuffer); results.push_back(r); pUserIterationBuffer++; } NetApiBufferFree(pUserBuffer); if (nEnumStatus == ERROR_MORE_DATA) { LOG(WARNING) << "NetUserEnum contains more data: users table may be incomplete"; } return results; }
/** * Searches the account name based on a display (real) name (e.g. "John Doe" -> "jdoe"). * Result "ppwszAccoutName" needs to be freed with CoTaskMemFree! */ BOOL VBoxCredProvCredential::TranslateAccountName(PWSTR pwszDisplayName, PWSTR *ppwszAccoutName) { AssertPtrReturn(pwszDisplayName, FALSE); VBoxCredProvVerbose(0, "VBoxCredProvCredential::TranslateAccountName: Getting account name for \"%ls\" ...\n", pwszDisplayName); /** @todo Do we need ADS support (e.g. TranslateNameW) here? */ BOOL fFound = FALSE; /* Did we find the desired user? */ NET_API_STATUS rcStatus; DWORD dwLevel = 2; /* Detailed information about user accounts. */ DWORD dwPrefMaxLen = MAX_PREFERRED_LENGTH; DWORD dwEntriesRead = 0; DWORD dwTotalEntries = 0; DWORD dwResumeHandle = 0; LPUSER_INFO_2 pBuf = NULL; LPUSER_INFO_2 pCurBuf = NULL; do { rcStatus = NetUserEnum(NULL, /* Server name, NULL for localhost. */ dwLevel, FILTER_NORMAL_ACCOUNT, (LPBYTE*)&pBuf, dwPrefMaxLen, &dwEntriesRead, &dwTotalEntries, &dwResumeHandle); if ( rcStatus == NERR_Success || rcStatus == ERROR_MORE_DATA) { if ((pCurBuf = pBuf) != NULL) { for (DWORD i = 0; i < dwEntriesRead; i++) { /* * Search for the "display name" - that might be * "John Doe" or something similar the user recognizes easier * and may not the same as the "account" name (e.g. "jdoe"). */ if ( pCurBuf && pCurBuf->usri2_full_name && StrCmpI(pwszDisplayName, pCurBuf->usri2_full_name) == 0) { /* * Copy the real user name (e.g. "jdoe") to our * output buffer. */ LPWSTR pwszTemp; HRESULT hr = SHStrDupW(pCurBuf->usri2_name, &pwszTemp); if (hr == S_OK) { *ppwszAccoutName = pwszTemp; fFound = TRUE; } else VBoxCredProvVerbose(0, "VBoxCredProvCredential::TranslateAccountName: Error copying data, hr=%08x\n", hr); break; } pCurBuf++; } } if (pBuf != NULL) { NetApiBufferFree(pBuf); pBuf = NULL; } } } while (rcStatus == ERROR_MORE_DATA && !fFound); if (pBuf != NULL) { NetApiBufferFree(pBuf); pBuf = NULL; } VBoxCredProvVerbose(0, "VBoxCredProvCredential::TranslateAccountName returned rcStatus=%ld, fFound=%RTbool\n", rcStatus, fFound); return fFound; #if 0 DWORD dwErr = NO_ERROR; ULONG cbLen = 0; if ( TranslateNameW(pwszName, NameUnknown, NameUserPrincipal, NULL, &cbLen) && cbLen > 0) { VBoxCredProvVerbose(0, "VBoxCredProvCredential::GetAccountName: Translated ADS name has %u characters\n", cbLen)); ppwszAccoutName = (PWSTR)RTMemAlloc(cbLen * sizeof(WCHAR)); AssertPtrReturn(pwszName, FALSE); if (TranslateNameW(pwszName, NameUnknown, NameUserPrincipal, ppwszAccoutName, &cbLen)) { VBoxCredProvVerbose(0, "VBoxCredProvCredential::GetAccountName: Real ADS account name of '%ls' is '%ls'\n", pwszName, ppwszAccoutName)); }
static NET_API_STATUS test_netuserenum(struct torture_context *tctx, const char *hostname, uint32_t level, const char *username) { NET_API_STATUS status; uint32_t entries_read = 0; uint32_t total_entries = 0; uint32_t resume_handle = 0; const char *current_name = NULL; int found_user = 0; uint8_t *buffer = NULL; int i; struct USER_INFO_0 *info0 = NULL; struct USER_INFO_1 *info1 = NULL; struct USER_INFO_2 *info2 = NULL; struct USER_INFO_3 *info3 = NULL; struct USER_INFO_4 *info4 = NULL; struct USER_INFO_10 *info10 = NULL; struct USER_INFO_11 *info11 = NULL; struct USER_INFO_20 *info20 = NULL; struct USER_INFO_23 *info23 = NULL; torture_comment(tctx, "Testing NetUserEnum level %d\n", level); do { status = NetUserEnum(hostname, level, FILTER_NORMAL_ACCOUNT, &buffer, (uint32_t)-1, &entries_read, &total_entries, &resume_handle); if (status == 0 || status == ERROR_MORE_DATA) { switch (level) { case 0: info0 = (struct USER_INFO_0 *)buffer; break; case 1: info1 = (struct USER_INFO_1 *)buffer; break; case 2: info2 = (struct USER_INFO_2 *)buffer; break; case 3: info3 = (struct USER_INFO_3 *)buffer; break; case 4: info4 = (struct USER_INFO_4 *)buffer; break; case 10: info10 = (struct USER_INFO_10 *)buffer; break; case 11: info11 = (struct USER_INFO_11 *)buffer; break; case 20: info20 = (struct USER_INFO_20 *)buffer; break; case 23: info23 = (struct USER_INFO_23 *)buffer; break; default: return -1; } for (i=0; i<entries_read; i++) { switch (level) { case 0: current_name = info0->usri0_name; break; case 1: current_name = info1->usri1_name; break; case 2: current_name = info2->usri2_name; break; case 3: current_name = info3->usri3_name; break; case 4: current_name = info4->usri4_name; break; case 10: current_name = info10->usri10_name; break; case 11: current_name = info11->usri11_name; break; case 20: current_name = info20->usri20_name; break; case 23: current_name = info23->usri23_name; break; default: return -1; } if (strcasecmp(current_name, username) == 0) { found_user = 1; } switch (level) { case 0: info0++; break; case 1: info1++; break; case 2: info2++; break; case 3: info3++; break; case 4: info4++; break; case 10: info10++; break; case 11: info11++; break; case 20: info20++; break; case 23: info23++; break; default: break; } } NetApiBufferFree(buffer); } } while (status == ERROR_MORE_DATA); if (status) { return status; } if (!found_user) { torture_comment(tctx, "failed to get user\n"); return -1; } return 0; }
// // MIB_user_lmget // Retrieve print queue table information from Lan Manager. // If not cached, sort it and then // cache it. // // Notes: // // Return Codes: // SNMPAPI_NOERROR // SNMPAPI_ERROR // // Error Codes: // None. // SNMPAPI MIB_users_lmget( ) { DWORD entriesread; DWORD totalentries; LPBYTE bufptr; unsigned lmCode; unsigned i; USER_INFO_0 *DataTable; USER_ENTRY *MIB_UserTableElement ; int First_of_this_block; LPSTR ansi_string; time_t curr_time ; SNMPAPI nResult = SNMPAPI_NOERROR; DWORD resumehandle=0; time(&curr_time); // get the time // // // If cached, return piece of info. // // if((NULL != cache_table[C_USER_TABLE].bufptr) && (curr_time < (cache_table[C_USER_TABLE].acquisition_time + cache_expire[C_USER_TABLE] ) ) ) { // it has NOT expired! goto Exit ; // the global table is valid } // // // Do network call to gather information and put it in a nice array // // // // remember to free the existing data // MIB_UserTableElement = MIB_UserTable.Table ; // iterate over the whole table for(i=0; i<MIB_UserTable.Len ;i++) { // free any alloc'ed elements of the structure SnmpUtilOidFree(&(MIB_UserTableElement->Oid)); SafeFree(MIB_UserTableElement->svUserName.stream); MIB_UserTableElement ++ ; // increment table entry } SafeFree(MIB_UserTable.Table) ; // free the base Table MIB_UserTable.Table = NULL ; // just for safety MIB_UserTable.Len = 0 ; // just for safety #if 0 // done above // init the length MIB_UserTable.Len = 0; #endif First_of_this_block = 0; do { // as long as there is more data to process lmCode = NetUserEnum( NULL, // local server 0, // level 0, no admin priv. FILTER_NORMAL_ACCOUNT, &bufptr, // data structure to return MAX_PREFERRED_LENGTH, &entriesread, &totalentries, &resumehandle // resume handle ); DataTable = (USER_INFO_0 *) bufptr ; if((NERR_Success == lmCode) || (ERROR_MORE_DATA == lmCode)) { // valid so process it, otherwise error if(0 == MIB_UserTable.Len) { // 1st time, alloc the whole table // alloc the table space MIB_UserTable.Table = SnmpUtilMemAlloc(totalentries * sizeof(USER_ENTRY) ); } MIB_UserTableElement = MIB_UserTable.Table + First_of_this_block ; for(i=0; i<entriesread; i++) { // once for each entry in the buffer // increment the entry number MIB_UserTable.Len ++; // Stuff the data into each item in the table // convert the undocumented unicode to something readable SnmpUtilUnicodeToAnsi( &ansi_string, DataTable->usri0_name, TRUE ); // auto alloc the space for ansi // client name MIB_UserTableElement->svUserName.stream = ansi_string; MIB_UserTableElement->svUserName.length = strlen( ansi_string ) ; MIB_UserTableElement->svUserName.dynamic = TRUE; ansi_string = NULL; MIB_UserTableElement ++ ; // and table entry DataTable ++ ; // advance pointer to next sess entry in buffer } // for each entry in the data table // free all of the lan man data SafeBufferFree( bufptr ) ; // indicate where to start adding on next pass, if any First_of_this_block = i ; } // if data is valid to process else { // Signal error nResult = SNMPAPI_ERROR; goto Exit; } } while (ERROR_MORE_DATA == lmCode) ; // iterate over the table populating the Oid field build_user_entry_oids(); // Sort the table information using MSC QuickSort routine qsort( &MIB_UserTable.Table[0], MIB_UserTable.Len, sizeof(USER_ENTRY), user_entry_cmp ); // // // Cache table // // if(0 != MIB_UserTable.Len) { cache_table[C_USER_TABLE].acquisition_time = curr_time ; cache_table[C_USER_TABLE].bufptr = bufptr ; } // // // Return piece of information requested // // Exit: return nResult; } // MIB_user_get
int main(int argc, const char **argv) { NET_API_STATUS status; struct libnetapi_ctx *ctx = NULL; const char *hostname = NULL; uint8_t *buffer = NULL; uint32_t entries_read = 0; uint32_t total_entries = 0; uint32_t resume_handle = 0; int i; struct USER_INFO_0 *info0; poptContext pc; int opt; struct poptOption long_options[] = { POPT_AUTOHELP POPT_COMMON_LIBNETAPI_EXAMPLES POPT_TABLEEND }; status = libnetapi_init(&ctx); if (status != 0) { return status; } pc = poptGetContext("user_enum", argc, argv, long_options, 0); poptSetOtherOptionHelp(pc, "hostname"); while((opt = poptGetNextOpt(pc)) != -1) { } if (!poptPeekArg(pc)) { poptPrintHelp(pc, stderr, 0); goto out; } hostname = poptGetArg(pc); /* NetUserEnum */ do { status = NetUserEnum(hostname, 0, 0, &buffer, (uint32_t)-1, &entries_read, &total_entries, &resume_handle); if (status == 0 || status == ERROR_MORE_DATA) { info0 = (struct USER_INFO_0 *)buffer; for (i=0; i<entries_read; i++) { printf("user %d: %s\n", i, info0->usri0_name); info0++; } NetApiBufferFree(buffer); } } while (status == ERROR_MORE_DATA); if (status != 0) { printf("NetUserEnum failed with: %s\n", libnetapi_get_error_string(ctx, status)); } out: libnetapi_free(ctx); poptFreeContext(pc); return status; }