NTSTATUS LsaAllocateSecurityDescriptor( OUT PSECURITY_DESCRIPTOR_RELATIVE *ppOut, IN PLSA_SECURITY_DESCRIPTOR_BUFFER pIn ) { NTSTATUS ntStatus = STATUS_SUCCESS; PSECURITY_DESCRIPTOR_RELATIVE pSecDesc = NULL; BAIL_ON_INVALID_PTR(ppOut, ntStatus); BAIL_ON_INVALID_PTR(pIn, ntStatus); ntStatus = LsaRpcAllocateMemory(OUT_PPVOID(&pSecDesc), pIn->BufferLen); BAIL_ON_NT_STATUS(ntStatus); memcpy(pSecDesc, pIn->pBuffer, pIn->BufferLen); *ppOut = pSecDesc; cleanup: return ntStatus; error: if (pSecDesc) { LsaRpcFreeMemory(pSecDesc); } *ppOut = NULL; goto cleanup; }
NTSTATUS LsaQuerySecurity( IN LSA_BINDING hBinding, IN void *hObject, IN DWORD SecurityInfo, OUT PSECURITY_DESCRIPTOR_RELATIVE *ppSecDesc, OUT PDWORD pSecDescLen ) { NTSTATUS ntStatus = STATUS_SUCCESS; PLSA_SECURITY_DESCRIPTOR_BUFFER pSecurityDescBuffer = NULL; PSECURITY_DESCRIPTOR_RELATIVE pSecurityDesc = NULL; BAIL_ON_INVALID_PTR(hBinding, ntStatus); BAIL_ON_INVALID_PTR(hObject, ntStatus); BAIL_ON_INVALID_PTR(ppSecDesc, ntStatus); BAIL_ON_INVALID_PTR(pSecDescLen, ntStatus); DCERPC_CALL(ntStatus, cli_LsaQuerySecurity( (handle_t)hBinding, hObject, SecurityInfo, &pSecurityDescBuffer)); BAIL_ON_NT_STATUS(ntStatus); ntStatus = LsaAllocateSecurityDescriptor( &pSecurityDesc, pSecurityDescBuffer); BAIL_ON_NT_STATUS(ntStatus); *ppSecDesc = pSecurityDesc; *pSecDescLen = pSecurityDescBuffer->BufferLen; cleanup: if (pSecurityDescBuffer) { LsaFreeStubSecurityDescriptorBuffer(pSecurityDescBuffer); } return ntStatus; error: if (pSecurityDesc) { LsaRpcFreeMemory(pSecurityDesc); } if (ppSecDesc) { *ppSecDesc = NULL; } if (pSecDescLen) { *pSecDescLen = 0; } goto cleanup; }
NTSTATUS LsaLookupNames3( IN LSA_BINDING hBinding, IN POLICY_HANDLE hPolicy, IN UINT32 dwNumNames, IN PWSTR *ppwszNames, OUT RefDomainList **ppDomList, OUT TranslatedSid3 **ppSids, IN WORD swLevel, IN OUT PDWORD pdwCount ) { NTSTATUS ntStatus = STATUS_SUCCESS; NTSTATUS ntRetStatus = STATUS_SUCCESS; DWORD dwError = ERROR_SUCCESS; UINT32 unknown1 = 0; UINT32 unknown2 = 0; PUNICODE_STRING pLsaNames = NULL; DWORD iName = 0; RefDomainList *pRefDomains = NULL; RefDomainList *pOutDomains = NULL; TranslatedSidArray3 SidArray = {0}; TranslatedSid3* pTransSids = NULL; DWORD dwOffset = 0; DWORD dwSpaceLeft = 0; DWORD dwSize = 0; BAIL_ON_INVALID_PTR(hBinding, ntStatus); BAIL_ON_INVALID_PTR(hPolicy, ntStatus); BAIL_ON_INVALID_PTR(ppwszNames, ntStatus); BAIL_ON_INVALID_PTR(ppDomList, ntStatus); BAIL_ON_INVALID_PTR(ppSids, ntStatus); BAIL_ON_INVALID_PTR(pdwCount, ntStatus); dwError = LwAllocateMemory(sizeof(pLsaNames[0]) * dwNumNames, OUT_PPVOID(&pLsaNames)); BAIL_ON_WIN_ERROR(dwError); for (iName = 0; iName < dwNumNames; iName++) { dwError = LwAllocateUnicodeStringFromWc16String( &pLsaNames[iName], ppwszNames[iName]); BAIL_ON_WIN_ERROR(dwError); } *pdwCount = 0; DCERPC_CALL(ntStatus, cli_LsaLookupNames3( (handle_t)hBinding, hPolicy, dwNumNames, pLsaNames, &pRefDomains, &SidArray, swLevel, pdwCount, unknown1, unknown2)); ntRetStatus = ntStatus; /* Status other than success doesn't have to mean failure here */ if (ntRetStatus != STATUS_SUCCESS && ntRetStatus != LW_STATUS_SOME_NOT_MAPPED) { BAIL_ON_NT_STATUS(ntRetStatus); } if (SidArray.count > 0) { ntStatus = LsaAllocateTranslatedSids3(NULL, &dwOffset, NULL, &SidArray, &dwSize); BAIL_ON_NT_STATUS(ntStatus); dwSpaceLeft = dwSize; dwSize = 0; dwOffset = 0; ntStatus = LsaRpcAllocateMemory(OUT_PPVOID(&pTransSids), dwSpaceLeft); BAIL_ON_NT_STATUS(ntStatus); ntStatus = LsaAllocateTranslatedSids3(pTransSids, &dwOffset, &dwSpaceLeft, &SidArray, &dwSize); BAIL_ON_NT_STATUS(ntStatus); } if (pRefDomains) { dwSize = 0; dwOffset = 0; ntStatus = LsaAllocateRefDomainList(NULL, &dwOffset, NULL, pRefDomains, &dwSize); BAIL_ON_NT_STATUS(ntStatus); dwSpaceLeft = dwSize; dwSize = 0; dwOffset = 0; ntStatus = LsaRpcAllocateMemory(OUT_PPVOID(&pOutDomains), dwSpaceLeft); BAIL_ON_NT_STATUS(ntStatus); ntStatus = LsaAllocateRefDomainList(pOutDomains, &dwOffset, &dwSpaceLeft, pRefDomains, &dwSize); BAIL_ON_NT_STATUS(ntStatus); } *ppSids = pTransSids; *ppDomList = pOutDomains; *pdwCount = SidArray.count; cleanup: if (pLsaNames) { for (iName = 0; iName < dwNumNames; iName++) { LwFreeUnicodeString(&(pLsaNames[iName])); } LW_SAFE_FREE_MEMORY(pLsaNames); } /* Free pointers returned from stub */ LsaCleanStubTranslatedSidArray3(&SidArray); if (pRefDomains) { LsaFreeStubRefDomainList(pRefDomains); } if (ntStatus == STATUS_SUCCESS && dwError != ERROR_SUCCESS) { ntStatus = LwWin32ErrorToNtStatus(dwError); } if (ntStatus == STATUS_SUCCESS && (ntRetStatus == STATUS_SUCCESS || ntRetStatus == LW_STATUS_SOME_NOT_MAPPED)) { ntStatus = ntRetStatus; } return ntStatus; error: if (pTransSids) { LsaRpcFreeMemory(pTransSids); } if (pOutDomains) { LsaRpcFreeMemory(pOutDomains); } if (ppSids) { *ppSids = NULL; } if (ppDomList) { *ppDomList = NULL; } if (pdwCount) { *pdwCount = 0; } goto cleanup; }
NTSTATUS LsaEnumPrivileges( IN LSA_BINDING hBinding, IN POLICY_HANDLE hPolicy, IN OUT PDWORD pResume, IN DWORD PreferredMaxSize, OUT PWSTR **ppNames, OUT PLUID *ppValues, OUT PDWORD pNumPrivileges ) { NTSTATUS ntStatus = STATUS_SUCCESS; NTSTATUS ntEnumStatus = STATUS_SUCCESS; LSA_PRIVILEGE_ENUM_BUFFER privileges = {0}; DWORD offset = 0; DWORD spaceLeft = 0; DWORD size = 0; PWSTR *pNames = NULL; PLUID pValues = NULL; DWORD i = 0; BAIL_ON_INVALID_PTR(hBinding, ntStatus); BAIL_ON_INVALID_PTR(hPolicy, ntStatus); BAIL_ON_INVALID_PTR(pResume, ntStatus); BAIL_ON_INVALID_PTR(ppNames, ntStatus); BAIL_ON_INVALID_PTR(ppValues, ntStatus); BAIL_ON_INVALID_PTR(pNumPrivileges, ntStatus); DCERPC_CALL(ntStatus, cli_LsaEnumPrivileges( (handle_t)hBinding, hPolicy, pResume, PreferredMaxSize, &privileges)); if (ntStatus == STATUS_MORE_ENTRIES || ntStatus == STATUS_NO_MORE_ENTRIES) { ntEnumStatus = ntStatus; ntStatus = STATUS_SUCCESS; } else if (ntStatus != STATUS_SUCCESS) { BAIL_ON_NT_STATUS(ntStatus); } offset = 0; spaceLeft = 0; size = 0; ntStatus = LsaAllocatePrivilegeNames( pNames, &offset, &spaceLeft, &privileges, &size); BAIL_ON_NT_STATUS(ntStatus); offset = 0; spaceLeft = size; size = 0; ntStatus = LsaRpcAllocateMemory( OUT_PPVOID(&pNames), spaceLeft); BAIL_ON_NT_STATUS(ntStatus); ntStatus = LsaAllocatePrivilegeNames( pNames, &offset, &spaceLeft, &privileges, &size); BAIL_ON_NT_STATUS(ntStatus); ntStatus = LsaRpcAllocateMemory( OUT_PPVOID(&pValues), sizeof(pValues[0]) * privileges.NumPrivileges); BAIL_ON_NT_STATUS(ntStatus); for (i = 0; i < privileges.NumPrivileges; i++) { pValues[i] = privileges.pPrivilege[i].Value; } *ppNames = pNames; *ppValues = pValues; *pNumPrivileges = privileges.NumPrivileges; error: if (ntStatus) { if (pNames) { LsaRpcFreeMemory(pNames); } if (ppNames) { *ppNames = NULL; } if (ppValues) { *ppValues = NULL; } if (pNumPrivileges) { *pNumPrivileges = 0; } } LsaCleanStubPrivilegeBuffer(&privileges); if (ntStatus == STATUS_SUCCESS) { ntStatus = ntEnumStatus; } return ntStatus; }
static NTSTATUS LsaSrvLookupForeignDomainSids( PPOLICY_CONTEXT pPolCtx, PACCOUNT_SIDS pAccountSids, DWORD dwLevel, RefDomainList *pDomains, TranslatedNameArray2 *pNamesArray ) { NTSTATUS ntStatus = STATUS_SUCCESS; DWORD dwError = ERROR_SUCCESS; PDOMAIN_ENTRY pDomEntry = NULL; handle_t hLsaBinding = NULL; POLICY_HANDLE hDcPolicy = NULL; PSID pDomSid = NULL; DWORD iDomSid = 0; DWORD iResolvSid = 0; DWORD iSid = 0; DWORD dwDomIndex = 0; ACCOUNT_SIDS ForeignSids = {0}; SID_ARRAY Sids = {0}; RefDomainList *pForeignDomains = NULL; TranslatedName *pForeignNames = NULL; DWORD dwForeignNamesCount = 0; DWORD iDomain = 0; DWORD i = 0; PSID pSid = NULL; DWORD dwSidIndex = 0; /* * Allocate enough space for potential sequence of sid lookups */ dwError = LwAllocateMemory( sizeof(ForeignSids.ppSids[0]) * pAccountSids->dwCount, OUT_PPVOID(&ForeignSids.ppSids)); BAIL_ON_LSA_ERROR(dwError); dwError = LwAllocateMemory( sizeof(ForeignSids.pdwIndices[0]) * pAccountSids->dwCount, OUT_PPVOID(&ForeignSids.pdwIndices)); BAIL_ON_LSA_ERROR(dwError); dwError = LwAllocateMemory( sizeof(Sids.pSids[0]) * pAccountSids->dwCount, OUT_PPVOID(&Sids.pSids)); BAIL_ON_LSA_ERROR(dwError); while (iDomSid < pAccountSids->dwCount) { ntStatus = RtlDuplicateSid(&pDomSid, pAccountSids->ppSids[iDomSid]); BAIL_ON_NTSTATUS_ERROR(ntStatus); pDomSid->SubAuthorityCount--; pDomSid->SubAuthority[pDomSid->SubAuthorityCount] = 0; iResolvSid = 0; for (iSid = iDomSid; iSid < pAccountSids->dwCount; iSid++) { pSid = pAccountSids->ppSids[iSid]; dwSidIndex = pAccountSids->pdwIndices[iSid]; if (RtlIsPrefixSid(pDomSid, pSid)) { ntStatus = RtlDuplicateSid( &(ForeignSids.ppSids[iResolvSid]), pSid); BAIL_ON_NTSTATUS_ERROR(ntStatus); ForeignSids.pdwIndices[iResolvSid] = dwSidIndex; ForeignSids.dwCount = ++iResolvSid; /* * Free the sid so it's not looked up again */ RTL_FREE(&pAccountSids->ppSids[iSid]); pAccountSids->ppSids[iSid] = NULL; pSid = NULL; } } for (i = 0; i < ForeignSids.dwCount; i++) { Sids.pSids[i].pSid = ForeignSids.ppSids[i]; } Sids.dwNumSids = ForeignSids.dwCount; ntStatus = LsaSrvConnectDomainBySid(pPolCtx, pDomSid, &pDomEntry); BAIL_ON_NTSTATUS_ERROR(ntStatus); hLsaBinding = pDomEntry->hLsaBinding; hDcPolicy = pDomEntry->hPolicy; ntStatus = LsaLookupSids(hLsaBinding, hDcPolicy, &Sids, &pForeignDomains, &pForeignNames, dwLevel, &dwForeignNamesCount); if (ntStatus == STATUS_SUCCESS || ntStatus == STATUS_SOME_NOT_MAPPED) { for (iDomain = 0; iDomain < pForeignDomains->count; iDomain++) { LsaDomainInfo *pSrcDomInfo = NULL; LsaDomainInfo *pDstDomInfo = NULL; dwDomIndex = pDomains->count; pSrcDomInfo = &(pForeignDomains->domains[iDomain]); pDstDomInfo = &(pDomains->domains[dwDomIndex]); ntStatus = LsaSrvDuplicateUnicodeStringEx(&pDstDomInfo->name, &pSrcDomInfo->name); BAIL_ON_NTSTATUS_ERROR(ntStatus); ntStatus = LsaSrvDuplicateSid(&pDstDomInfo->sid, pSrcDomInfo->sid); BAIL_ON_NTSTATUS_ERROR(ntStatus); for (iSid = 0; iSid < dwForeignNamesCount; iSid++) { DWORD iTransName = ForeignSids.pdwIndices[iSid]; TranslatedName *pSrcName = &(pForeignNames[iSid]); TranslatedName2 *pDstName = &(pNamesArray->names[iTransName]); if (iDomain != pSrcName->sid_index) { continue; } ntStatus = LsaSrvDuplicateUnicodeString(&pDstName->name, &pSrcName->name); BAIL_ON_NTSTATUS_ERROR(ntStatus); pDstName->type = pSrcName->type; pDstName->sid_index = dwDomIndex; pDstName->unknown1 = 0; } pDomains->count = (++dwDomIndex); } pNamesArray->count += dwForeignNamesCount; } else if (ntStatus == STATUS_NONE_MAPPED) { for (i = 0; i < ForeignSids.dwCount; i++) { DWORD iTransName = ForeignSids.pdwIndices[i]; TranslatedName2 *pDstName = &(pNamesArray->names[iTransName]); pDstName->type = SID_TYPE_UNKNOWN; pDstName->sid_index = 0; pDstName->unknown1 = 0; } pNamesArray->count += ForeignSids.dwCount; } else { BAIL_ON_NTSTATUS_ERROR(ntStatus); } /* * Free the sids array before the next round of lookup. * The entire allocated space (i.e. as big as pAccountSids) * is cleaned up. */ for (i = 0; i < pAccountSids->dwCount; i++) { RTL_FREE(&(ForeignSids.ppSids[i])); ForeignSids.ppSids[i] = NULL; Sids.pSids[i].pSid = NULL; ForeignSids.pdwIndices[i] = -1; } Sids.dwNumSids = 0; if (pDomEntry) { LsaSrvDomainEntryFree(&pDomEntry); } if (pForeignDomains) { LsaRpcFreeMemory(pForeignDomains); pForeignDomains = NULL; } if (pForeignNames) { LsaRpcFreeMemory(pForeignNames); pForeignNames = NULL; } RTL_FREE(&pDomSid); /* * Find another domain name (first name that hasn't * been nulled out) */ iDomSid = 0; while (iDomSid < pAccountSids->dwCount && pAccountSids->ppSids[iDomSid] == NULL) { iDomSid++; } } /* * Lookup status is checked later by the caller * so avoid bailing accidentally because other lookups * may be successful */ if (ntStatus == STATUS_SOME_NOT_MAPPED || ntStatus == STATUS_NONE_MAPPED) { ntStatus = STATUS_SUCCESS; } cleanup: for (i = 0; i < pAccountSids->dwCount; i++) { RTL_FREE(&(ForeignSids.ppSids[i])); } LW_SAFE_FREE_MEMORY(ForeignSids.ppSids); LW_SAFE_FREE_MEMORY(ForeignSids.pdwIndices); LW_SAFE_FREE_MEMORY(Sids.pSids); if (pDomEntry) { LsaSrvDomainEntryFree(&pDomEntry); } if (pForeignDomains) { LsaRpcFreeMemory(pForeignDomains); } if (pForeignNames) { LsaRpcFreeMemory(pForeignNames); } RTL_FREE(&pDomSid); if (ntStatus == STATUS_SUCCESS && dwError != ERROR_SUCCESS) { ntStatus = LwWin32ErrorToNtStatus(dwError); } return ntStatus; error: goto cleanup; }
static NTSTATUS LsaSrvLookupDomainSids( PPOLICY_CONTEXT pPolCtx, PACCOUNT_SIDS pAccountSids, DWORD dwLevel, RefDomainList *pDomains, TranslatedNameArray2 *pNamesArray ) { NTSTATUS ntStatus = STATUS_SUCCESS; DWORD dwError = ERROR_SUCCESS; PDOMAIN_ENTRY pDomEntry = NULL; handle_t hLsaBinding = NULL; POLICY_HANDLE hDcPolicy = NULL; DWORD dwDomIndex = 0; SID_ARRAY Sids = {0}; RefDomainList *pDomain = NULL; TranslatedName *pDomainNames = NULL; DWORD dwDomainNamesCount = 0; DWORD iDomain = 0; DWORD iSid = 0; DWORD i = 0; ntStatus = LsaSrvGetDomainBySid(pPolCtx, pPolCtx->pDomainSid, &pDomEntry); if (ntStatus == STATUS_NO_SUCH_DOMAIN) { ntStatus = LsaSrvConnectDomainBySid(pPolCtx, pPolCtx->pDomainSid, &pDomEntry); BAIL_ON_NTSTATUS_ERROR(ntStatus); hLsaBinding = pDomEntry->hLsaBinding; hDcPolicy = pDomEntry->hPolicy; } else if (ntStatus == STATUS_SUCCESS) { hLsaBinding = pDomEntry->hLsaBinding; hDcPolicy = pDomEntry->hPolicy; } else { BAIL_ON_NTSTATUS_ERROR(ntStatus); } Sids.dwNumSids = pAccountSids->dwCount; dwError = LwAllocateMemory(sizeof(Sids.pSids[0]) * Sids.dwNumSids, OUT_PPVOID(&Sids.pSids)); BAIL_ON_LSA_ERROR(dwError); for (i = 0; i < Sids.dwNumSids; i++) { Sids.pSids[i].pSid = pAccountSids->ppSids[i]; } ntStatus = LsaLookupSids(hLsaBinding, hDcPolicy, &Sids, &pDomain, &pDomainNames, dwLevel, &dwDomainNamesCount); if (ntStatus == STATUS_SUCCESS || ntStatus == STATUS_SOME_NOT_MAPPED) { for (iDomain = 0; iDomain < pDomain->count; iDomain++) { LsaDomainInfo *pSrcDomInfo = NULL; LsaDomainInfo *pDstDomInfo = NULL; dwDomIndex = pDomains->count; pSrcDomInfo = &(pDomain->domains[iDomain]); pDstDomInfo = &(pDomains->domains[dwDomIndex]); ntStatus = LsaSrvDuplicateUnicodeStringEx(&pDstDomInfo->name, &pSrcDomInfo->name); BAIL_ON_NTSTATUS_ERROR(ntStatus); ntStatus = LsaSrvDuplicateSid(&pDstDomInfo->sid, pSrcDomInfo->sid); BAIL_ON_NTSTATUS_ERROR(ntStatus); for (iSid = 0; iSid < dwDomainNamesCount; iSid++) { DWORD iTransName = pAccountSids->pdwIndices[iSid]; TranslatedName *pSrcName = &(pDomainNames[iSid]); TranslatedName2 *pDstName = &(pNamesArray->names[iTransName]); if (iDomain != pSrcName->sid_index) { continue; } ntStatus = LsaSrvDuplicateUnicodeString(&pDstName->name, &pSrcName->name); BAIL_ON_NTSTATUS_ERROR(ntStatus); pDstName->type = pSrcName->type; pDstName->sid_index = dwDomIndex; pDstName->unknown1 = 0; } pDomains->count = (++dwDomIndex); } pNamesArray->count += dwDomainNamesCount; } else if (ntStatus == STATUS_NONE_MAPPED) { for (i = 0; i < pAccountSids->dwCount; i++) { DWORD iTransName = pAccountSids->pdwIndices[i]; TranslatedName2 *pDstName = &(pNamesArray->names[iTransName]); pDstName->type = SID_TYPE_UNKNOWN; pDstName->sid_index = 0; pDstName->unknown1 = 0; } pNamesArray->count += pAccountSids->dwCount; } else { BAIL_ON_NTSTATUS_ERROR(ntStatus); } /* * Lookup status is checked later by the caller * so avoid bailing accidentally because other lookups * may be successful */ if (ntStatus == STATUS_SOME_NOT_MAPPED || ntStatus == STATUS_NONE_MAPPED) { ntStatus = STATUS_SUCCESS; } cleanup: LW_SAFE_FREE_MEMORY(Sids.pSids); if (pDomEntry) { LsaSrvDomainEntryFree(&pDomEntry); } if (pDomain) { LsaRpcFreeMemory(pDomain); } if (pDomainNames) { LsaRpcFreeMemory(pDomainNames); } if (ntStatus == STATUS_SUCCESS && dwError != ERROR_SUCCESS) { ntStatus = LwWin32ErrorToNtStatus(dwError); } return ntStatus; error: goto cleanup; }
static DWORD ProcessEnumerateAccountUserRights( IN PRPC_PARAMETERS pRpcParams, IN PSTR AccountName ) { DWORD err = ERROR_SUCCESS; NTSTATUS ntStatus = STATUS_SUCCESS; LSA_BINDING hLsa = NULL; LW_PIO_CREDS pCreds = NULL; WCHAR wszSysName[] = {'\\', '\\', '\0'}; DWORD policyAccessMask = LSA_ACCESS_LOOKUP_NAMES_SIDS | LSA_ACCESS_VIEW_POLICY_INFO; POLICY_HANDLE hPolicy = NULL; PSID pAccountSid = NULL; PSTR pszSid = NULL; PWSTR *pAccountRights = NULL; DWORD numAccountRights = 0; DWORD i = 0; PSTR pszAccountRight = NULL; err = CreateRpcCredentials(pRpcParams, &pCreds); BAIL_ON_LSA_ERROR(err); err = CreateLsaRpcBinding(pRpcParams, pCreds, &hLsa); BAIL_ON_LSA_ERROR(err); ntStatus = LsaOpenPolicy2(hLsa, wszSysName, NULL, policyAccessMask, &hPolicy); BAIL_ON_NT_STATUS(ntStatus); err = ResolveAccountNameToSid( hLsa, AccountName, &pAccountSid); BAIL_ON_LSA_ERROR(err); ntStatus = RtlAllocateCStringFromSid( &pszSid, pAccountSid); BAIL_ON_NT_STATUS(ntStatus); fprintf(stdout, "%s Account Rights\n:" "==================================================" "==============================\n", AccountName); ntStatus = LsaEnumAccountRights( hLsa, hPolicy, pAccountSid, &pAccountRights, &numAccountRights); BAIL_ON_NT_STATUS(ntStatus); for (i = 0; i < numAccountRights; i++) { err = LwWc16sToMbs(pAccountRights[i], &pszAccountRight); BAIL_ON_LSA_ERROR(err); fprintf(stdout, "%s\n", pszAccountRight); LW_SAFE_FREE_MEMORY(pszAccountRight); } error: if (ntStatus || err) { PCSTR errName = LwNtStatusToName(ntStatus); PCSTR errDescription = LwNtStatusToDescription(ntStatus); if (ntStatus) { errName = LwNtStatusToName(ntStatus); errDescription = LwNtStatusToDescription(ntStatus); } else { errName = LwWin32ErrorToName(err); errDescription = LwWin32ErrorToDescription(err); } fprintf(stderr, "Error: %s (%s)\n", LSA_SAFE_LOG_STRING(errName), LSA_SAFE_LOG_STRING(errDescription)); } if (hPolicy) { LsaClose(hLsa, hPolicy); } if (hLsa) { LsaFreeBinding(&hLsa); } if (pCreds) { LwIoDeleteCreds(pCreds); } if (pAccountRights) { LsaRpcFreeMemory(pAccountRights); } LW_SAFE_FREE_MEMORY(pszAccountRight); if (err == ERROR_SUCCESS && ntStatus != STATUS_SUCCESS) { err = LwNtStatusToWin32Error(ntStatus); } return err; }
static DWORD ProcessEnumerateAccounts( IN PRPC_PARAMETERS pRpcParams, IN PSTR UserRightName ) { DWORD err = ERROR_SUCCESS; NTSTATUS ntStatus = STATUS_SUCCESS; LSA_BINDING hLsa = NULL; LW_PIO_CREDS pCreds = NULL; WCHAR wszSysName[] = {'\\', '\\', '\0'}; DWORD policyAccessMask = LSA_ACCESS_LOOKUP_NAMES_SIDS | LSA_ACCESS_VIEW_POLICY_INFO; POLICY_HANDLE hPolicy = NULL; PWSTR pwszUserRightName = NULL; DWORD resume = 0; PSID *ppSids = NULL; DWORD numSids = 0; DWORD prefMaxSize = 64; DWORD i = 0; SID_ARRAY sids = {0}; RefDomainList *pDomList = NULL; TranslatedName *pTransNames = NULL; DWORD count = 0; PSTR pszAccountSid = NULL; PSTR pszAccountDomain = NULL; PSTR pszAccountName = NULL; BOOLEAN moreEntries = FALSE; err = CreateRpcCredentials(pRpcParams, &pCreds); BAIL_ON_LSA_ERROR(err); err = CreateLsaRpcBinding(pRpcParams, pCreds, &hLsa); BAIL_ON_LSA_ERROR(err); ntStatus = LsaOpenPolicy2(hLsa, wszSysName, NULL, policyAccessMask, &hPolicy); BAIL_ON_NT_STATUS(ntStatus); fprintf(stdout, "LSA Accounts"); do { moreEntries = FALSE; if (UserRightName) { fprintf(stdout, " with AccountRight = %s:\n", UserRightName); fprintf(stdout, "==================================================" "==============================\n"); err = LwMbsToWc16s(UserRightName, &pwszUserRightName); BAIL_ON_LSA_ERROR(err); ntStatus = LsaEnumAccountsWithUserRight( hLsa, hPolicy, pwszUserRightName, &ppSids, &numSids); BAIL_ON_NT_STATUS(ntStatus); } else { fprintf(stdout, ":\n"); fprintf(stdout, "==================================================" "==============================\n"); ntStatus = LsaEnumAccounts(hLsa, hPolicy, &resume, &ppSids, &numSids, prefMaxSize); if (ntStatus == STATUS_MORE_ENTRIES) { ntStatus = STATUS_SUCCESS; moreEntries = TRUE; } else if (ntStatus != STATUS_SUCCESS) { BAIL_ON_NT_STATUS(ntStatus); } } err = LwAllocateMemory( sizeof(sids.pSids[0]) * numSids, OUT_PPVOID(&sids.pSids)); BAIL_ON_LSA_ERROR(err); sids.dwNumSids = numSids; for (i = 0; i < sids.dwNumSids; i++) { sids.pSids[i].pSid = ppSids[i]; } ntStatus = LsaLookupSids(hLsa, hPolicy, &sids, &pDomList, &pTransNames, LSA_LOOKUP_NAMES_ALL, &count); if (ntStatus == STATUS_SOME_NOT_MAPPED || ntStatus == STATUS_NONE_MAPPED) { ntStatus = STATUS_SUCCESS; } else if (ntStatus != STATUS_SUCCESS) { BAIL_ON_NT_STATUS(ntStatus); } for (i = 0; i < sids.dwNumSids; i++) { DWORD domainIndex = 0; ntStatus = RtlAllocateCStringFromSid( &pszAccountSid, sids.pSids[i].pSid); BAIL_ON_NT_STATUS(ntStatus); if (pTransNames[i].type == SID_TYPE_USER || pTransNames[i].type == SID_TYPE_DOM_GRP || pTransNames[i].type == SID_TYPE_DOMAIN || pTransNames[i].type == SID_TYPE_ALIAS || pTransNames[i].type == SID_TYPE_WKN_GRP) { ntStatus = RtlCStringAllocateFromUnicodeString( &pszAccountName, &pTransNames[i].name); BAIL_ON_NT_STATUS(ntStatus); domainIndex = pTransNames[i].sid_index; ntStatus = RtlCStringAllocateFromUnicodeString( &pszAccountDomain, &pDomList->domains[domainIndex].name); BAIL_ON_NT_STATUS(ntStatus); } if (pszAccountSid) { fprintf(stdout, "%s ", pszAccountSid); } if (pszAccountDomain && pszAccountName) { fprintf(stdout, "(%s\\%s)", pszAccountDomain, pszAccountName); } else if (pszAccountDomain && !pszAccountName) { fprintf(stdout, "(%s\\)", pszAccountDomain); } else if (!pszAccountDomain && pszAccountName) { fprintf(stdout, "(%s)", pszAccountName); } else { fprintf(stdout, "(unknown)"); } fprintf(stdout, "\n"); RTL_FREE(&pszAccountSid); RTL_FREE(&pszAccountDomain); RTL_FREE(&pszAccountName); } if (pTransNames) { LsaRpcFreeMemory(pTransNames); pTransNames = NULL; } if (pDomList) { LsaRpcFreeMemory(pDomList); pDomList = NULL; } if (ppSids) { LsaRpcFreeMemory(ppSids); ppSids = NULL; } LW_SAFE_FREE_MEMORY(sids.pSids); } while (moreEntries && ntStatus == STATUS_SUCCESS); error: if (ntStatus || err) { PCSTR errName = LwNtStatusToName(ntStatus); PCSTR errDescription = LwNtStatusToDescription(ntStatus); if (ntStatus) { errName = LwNtStatusToName(ntStatus); errDescription = LwNtStatusToDescription(ntStatus); } else { errName = LwWin32ErrorToName(err); errDescription = LwWin32ErrorToDescription(err); } fprintf(stderr, "Error: %s (%s)\n", LSA_SAFE_LOG_STRING(errName), LSA_SAFE_LOG_STRING(errDescription)); } if (hPolicy) { LsaClose(hLsa, hPolicy); } if (hLsa) { LsaFreeBinding(&hLsa); } if (pCreds) { LwIoDeleteCreds(pCreds); } LW_SAFE_FREE_MEMORY(pwszUserRightName); RTL_FREE(&pszAccountSid); RTL_FREE(&pszAccountDomain); RTL_FREE(&pszAccountName); if (pTransNames) { LsaRpcFreeMemory(pTransNames); } if (pDomList) { LsaRpcFreeMemory(pDomList); } if (ppSids) { LsaRpcFreeMemory(ppSids); } LW_SAFE_FREE_MEMORY(sids.pSids); if (err == ERROR_SUCCESS && ntStatus != STATUS_SUCCESS) { err = LwNtStatusToWin32Error(ntStatus); } return err; }