DWORD LsaSetSMBAnonymousCreds( OUT PLSA_CREDS_FREE_INFO* ppFreeInfo ) { DWORD dwError = 0; LW_PIO_CREDS pNewCreds = NULL; LW_PIO_CREDS pOldCreds = NULL; PLSA_CREDS_FREE_INFO pFreeInfo = NULL; BAIL_ON_INVALID_POINTER(ppFreeInfo); dwError = LwIoCreatePlainCredsA( "", "", "", &pNewCreds); BAIL_ON_LSA_ERROR(dwError); dwError = LwAllocateMemory(sizeof(*pFreeInfo), (PVOID*)&pFreeInfo); BAIL_ON_LSA_ERROR(dwError); dwError = LwIoGetThreadCreds(&pOldCreds); BAIL_ON_LSA_ERROR(dwError); dwError = LwIoSetThreadCreds(pNewCreds); BAIL_ON_LSA_ERROR(dwError); pFreeInfo->pRestoreCreds = pOldCreds; pFreeInfo->bKrbCreds = FALSE; pOldCreds = NULL; cleanup: *ppFreeInfo = pFreeInfo; if (pOldCreds != NULL) { LwIoDeleteCreds(pOldCreds); } if (pNewCreds != NULL) { LwIoDeleteCreds(pNewCreds); } return dwError; error: if (pFreeInfo) { LwFreeMemory(pFreeInfo); pFreeInfo = NULL; } goto cleanup; }
static VOID LwNtCreateFileComplete( PIO_CLIENT_ASYNC_CONTEXT pBase, NTSTATUS status ) { PCREATEFILE_CONTEXT pContext = (PCREATEFILE_CONTEXT) pBase; PNT_IPC_MESSAGE_CREATE_FILE_RESULT pResponse = pBase->out.data; if (status == STATUS_SUCCESS) { *pContext->FileHandle = pResponse->FileHandle; pResponse->FileHandle = NULL; pContext->IoStatusBlock->Status = pResponse->Status; pContext->IoStatusBlock->CreateResult = pResponse->CreateResult; status = pContext->IoStatusBlock->Status; } else { pContext->IoStatusBlock->Status = status; } if (pContext->Request.pSecurityToken) { LwIoDeleteCreds(pContext->Request.pSecurityToken); } if (pContext->Request.EcpList) { RTL_FREE(&pContext->Request.EcpList); } }
static DWORD LsaUnjoinDomain( IN PCWSTR pwszDnsDomainName, IN PCWSTR pwszMachineSamAccountName, IN OPTIONAL PCWSTR pwszUserName, IN OPTIONAL PCWSTR pwszUserDomain, IN OPTIONAL PCWSTR pwszUserPassword, IN DWORD dwUnjoinFlags ) { DWORD dwError = ERROR_SUCCESS; NTSTATUS ntStatus = STATUS_SUCCESS; PWSTR pwszDCName = NULL; PIO_CREDS pCreds = NULL; dwError = LsaGetRwDcName(pwszDnsDomainName, FALSE, &pwszDCName); BAIL_ON_LSA_ERROR(dwError); /* disable the account only if requested */ if (dwUnjoinFlags & LSAJOIN_ACCT_DELETE) { if (pwszUserName && pwszUserPassword) { ntStatus = LwIoCreatePlainCredsW(pwszUserName, pwszUserDomain, pwszUserPassword, &pCreds); dwError = LwNtStatusToWin32Error(ntStatus); BAIL_ON_LSA_ERROR(dwError); } else { ntStatus = LwIoGetActiveCreds(NULL, &pCreds); dwError = LwNtStatusToWin32Error(ntStatus); BAIL_ON_LSA_ERROR(dwError); } ntStatus = LsaDisableMachineAccount(pwszDCName, pCreds, pwszMachineSamAccountName); dwError = LwNtStatusToWin32Error(ntStatus); BAIL_ON_LSA_ERROR(dwError); } error: LSA_ASSERT(!ntStatus || dwError); LW_SAFE_FREE_MEMORY(pwszDCName); if (pCreds) { LwIoDeleteCreds(pCreds); } return dwError; }
NTSTATUS LwIoSetThreadCreds( PIO_CREDS pCreds ) { NTSTATUS Status = STATUS_SUCCESS; PIO_THREAD_STATE pState = NULL; Status = LwIoGetThreadState(&pState); BAIL_ON_NT_STATUS(Status); if (pState->pCreds) { LwIoDeleteCreds(pState->pCreds); } Status = LwIoCopyCreds( pCreds ? pCreds : gpProcessCreds, &pState->pCreds); BAIL_ON_NT_STATUS(Status); error: return Status; }
VOID __LwIoDestruct() { BOOLEAN bInLock = FALSE; LWIO_LOCK_MUTEX(bInLock, &gLock); if (gpClient) { lwmsg_peer_delete(gpClient); gpClient = NULL; gpSession = NULL; } if (!gpProcessCreds) { LwIoDeleteCreds(gpProcessCreds); gpProcessCreds = NULL; } if (gbStateKeyInit) { pthread_key_delete(gStateKey); gbStateKeyInit = FALSE; } LWIO_UNLOCK_MUTEX(bInLock, &gLock); LwIoShutdown(); }
VOID LwTaskFreeCreds( PLW_TASK_CREDS pCreds /* IN OUT */ ) { if (pCreds->pKrb5Creds != NULL) { LwIoDeleteCreds(pCreds->pKrb5Creds); } if (pCreds->pszRestoreCache) { LwKrb5SetDefaultCachePath(pCreds->pszRestoreCache, NULL); LwFreeString(pCreds->pszRestoreCache); } if (pCreds->ctx != NULL) { if (pCreds->cc != NULL) { krb5_cc_destroy(pCreds->ctx, pCreds->cc); } krb5_free_context(pCreds->ctx); } LwFreeMemory(pCreds); }
static void LwIoThreadStateDestruct( void* pData ) { PIO_THREAD_STATE pState = (PIO_THREAD_STATE) pData; if (pState) { if (pState->pCreds) { LwIoDeleteCreds(pState->pCreds); } LwIoFreeMemory(pState); } }
NTSTATUS LwIoCreatePlainCredsW( PCWSTR pwszUsername, PCWSTR pwszDomain, PCWSTR pwszPassword, PIO_CREDS* ppCreds ) { NTSTATUS Status = STATUS_SUCCESS; PIO_CREDS pCreds = NULL; Status = LwIoAllocateMemory(sizeof(*pCreds), OUT_PPVOID(&pCreds)); BAIL_ON_NT_STATUS(Status); pCreds->type = IO_CREDS_TYPE_PLAIN; Status = RtlWC16StringDuplicate( &pCreds->payload.plain.pwszUsername, pwszUsername); BAIL_ON_NT_STATUS(Status); Status = RtlWC16StringDuplicate( &pCreds->payload.plain.pwszDomain, pwszDomain); Status = RtlWC16StringDuplicate( &pCreds->payload.plain.pwszPassword, pwszPassword); BAIL_ON_NT_STATUS(Status); *ppCreds = pCreds; cleanup: return Status; error: if (pCreds) { LwIoDeleteCreds(pCreds); } goto cleanup; }
static VOID LwIoDeletePathCreds( PIO_PATH_CREDS pPathCreds ) { if (pPathCreds) { LwRtlUnicodeStringFree(&pPathCreds->PathPrefix); if (pPathCreds->pCreds) { LwIoDeleteCreds(pPathCreds->pCreds); } RTL_FREE(&pPathCreds); } }
void LsaFreeSMBCreds( IN OUT PLSA_CREDS_FREE_INFO* ppFreeInfo ) { PLSA_CREDS_FREE_INFO pFreeInfo = *ppFreeInfo; if (!pFreeInfo) { goto cleanup; } LwIoSetThreadCreds(pFreeInfo->pRestoreCreds); if (pFreeInfo->pRestoreCreds != NULL) { LwIoDeleteCreds(pFreeInfo->pRestoreCreds); } if (pFreeInfo->bKrbCreds) { LwKrb5SetThreadDefaultCachePath( pFreeInfo->pszRestoreCache, NULL); LW_SAFE_FREE_STRING(pFreeInfo->pszRestoreCache); if (pFreeInfo->ctx != NULL) { if (pFreeInfo->cc != NULL) { krb5_cc_destroy(pFreeInfo->ctx, pFreeInfo->cc); } krb5_free_context(pFreeInfo->ctx); } } LwFreeMemory(pFreeInfo); *ppFreeInfo = NULL; cleanup: return; }
NTSTATUS LwIoCreateKrb5CredsW( PCWSTR pwszPrincipal, PCWSTR pwszCachePath, PIO_CREDS* ppCreds ) { NTSTATUS Status = STATUS_SUCCESS; PIO_CREDS pCreds = NULL; Status = LwIoAllocateMemory(sizeof(*pCreds), OUT_PPVOID(&pCreds)); BAIL_ON_NT_STATUS(Status); pCreds->type = IO_CREDS_TYPE_KRB5_CCACHE; Status = RtlWC16StringDuplicate( &pCreds->payload.krb5Ccache.pwszPrincipal, pwszPrincipal); BAIL_ON_NT_STATUS(Status); Status = RtlWC16StringDuplicate( &pCreds->payload.krb5Ccache.pwszCachePath, pwszCachePath); BAIL_ON_NT_STATUS(Status); *ppCreds = pCreds; cleanup: return Status; error: if (pCreds) { LwIoDeleteCreds(pCreds); } goto cleanup; }
NTSTATUS LwIoCopyCreds( PIO_CREDS pCreds, PIO_CREDS* ppCredsCopy ) { NTSTATUS Status = STATUS_SUCCESS; PIO_CREDS pCredsCopy = NULL; if (pCreds) { Status = LwIoAllocateMemory(sizeof(*pCredsCopy), OUT_PPVOID(&pCredsCopy)); BAIL_ON_NT_STATUS(Status); pCredsCopy->type = pCreds->type; switch (pCreds->type) { case IO_CREDS_TYPE_PLAIN: Status = RtlWC16StringDuplicate( &pCredsCopy->payload.plain.pwszUsername, pCreds->payload.plain.pwszUsername); BAIL_ON_NT_STATUS(Status); Status = RtlWC16StringDuplicate( &pCredsCopy->payload.plain.pwszDomain, pCreds->payload.plain.pwszDomain); BAIL_ON_NT_STATUS(Status); Status = RtlWC16StringDuplicate( &pCredsCopy->payload.plain.pwszPassword, pCreds->payload.plain.pwszPassword); BAIL_ON_NT_STATUS(Status); break; case IO_CREDS_TYPE_KRB5_CCACHE: Status = RtlWC16StringDuplicate( &pCredsCopy->payload.krb5Ccache.pwszPrincipal, pCreds->payload.krb5Ccache.pwszPrincipal); BAIL_ON_NT_STATUS(Status); Status = RtlWC16StringDuplicate( &pCredsCopy->payload.krb5Ccache.pwszCachePath, pCreds->payload.krb5Ccache.pwszCachePath); BAIL_ON_NT_STATUS(Status); break; case IO_CREDS_TYPE_KRB5_TGT: Status = RtlWC16StringDuplicate( &pCredsCopy->payload.krb5Tgt.pwszClientPrincipal, pCreds->payload.krb5Tgt.pwszClientPrincipal); BAIL_ON_NT_STATUS(Status); Status = RtlWC16StringDuplicate( &pCredsCopy->payload.krb5Tgt.pwszServerPrincipal, pCreds->payload.krb5Tgt.pwszServerPrincipal); BAIL_ON_NT_STATUS(Status); pCredsCopy->payload.krb5Tgt.authTime = pCreds->payload.krb5Tgt.authTime; pCredsCopy->payload.krb5Tgt.startTime = pCreds->payload.krb5Tgt.startTime; pCredsCopy->payload.krb5Tgt.endTime = pCreds->payload.krb5Tgt.endTime; pCredsCopy->payload.krb5Tgt.renewTillTime = pCreds->payload.krb5Tgt.renewTillTime; pCredsCopy->payload.krb5Tgt.keyType = pCreds->payload.krb5Tgt.keyType; pCredsCopy->payload.krb5Tgt.ulKeySize = pCreds->payload.krb5Tgt.ulKeySize; Status = LwIoAllocateMemory( pCreds->payload.krb5Tgt.ulKeySize, OUT_PPVOID(&pCredsCopy->payload.krb5Tgt.pKeyData)); BAIL_ON_NT_STATUS(Status); memcpy( pCredsCopy->payload.krb5Tgt.pKeyData, pCreds->payload.krb5Tgt.pKeyData, pCreds->payload.krb5Tgt.ulKeySize); pCredsCopy->payload.krb5Tgt.tgtFlags = pCreds->payload.krb5Tgt.tgtFlags; pCredsCopy->payload.krb5Tgt.ulTgtSize = pCreds->payload.krb5Tgt.ulTgtSize; Status = LwIoAllocateMemory( pCreds->payload.krb5Tgt.ulTgtSize, OUT_PPVOID(&pCredsCopy->payload.krb5Tgt.pTgtData)); BAIL_ON_NT_STATUS(Status); memcpy( pCredsCopy->payload.krb5Tgt.pTgtData, pCreds->payload.krb5Tgt.pTgtData, pCreds->payload.krb5Tgt.ulTgtSize); break; } *ppCredsCopy = pCredsCopy; } else { *ppCredsCopy = NULL; } cleanup: return Status; error: if (pCredsCopy) { LwIoDeleteCreds(pCredsCopy); } goto cleanup; }
NET_API_STATUS NetUserGetLocalGroups( PCWSTR pwszHostname, PCWSTR pwszUsername, DWORD dwLevel, DWORD dwFlags, PVOID *ppBuffer, DWORD dwMaxBufferSize, PDWORD pdwNumEntries, PDWORD pdwTotalEntries ) { const DWORD dwBuiltinDomainAccess = DOMAIN_ACCESS_OPEN_ACCOUNT | DOMAIN_ACCESS_ENUM_ACCOUNTS; const DWORD dwUserAccess = USER_ACCESS_GET_GROUP_MEMBERSHIP; NTSTATUS status = STATUS_SUCCESS; WINERROR err = ERROR_SUCCESS; PNET_CONN pConn = NULL; SAMR_BINDING hSamrBinding = NULL; DOMAIN_HANDLE hDomain = NULL; DOMAIN_HANDLE hBtinDomain = NULL; ACCOUNT_HANDLE hUser = NULL; PSID pDomainSid = NULL; PSID pUserSid = NULL; DWORD dwUserRid = 0; DWORD dwSidLen = 0; DWORD i = 0; PDWORD pdwUserRids = NULL; PDWORD pdwBuiltinUserRids = NULL; DWORD dwRidsCount = 0; DWORD dwBuiltinRidsCount = 0; DWORD dwInfoLevelSize = 0; DWORD dwTotalNumEntries = 0; PWSTR *ppwszAliasNames = NULL; PWSTR *ppwszBuiltinAliasNames = NULL; PDWORD pdwAliasTypes = NULL; PDWORD pdwBuiltinAliasTypes = NULL; PWSTR *ppwszLocalGroupNames = NULL; PVOID pSourceBuffer = NULL; PVOID pBuffer = NULL; PVOID pBufferCursor = NULL; DWORD dwSize = 0; DWORD dwTotalSize = 0; DWORD dwNumEntries = 0; DWORD dwSpaceAvailable = 0; PIO_CREDS pCreds = NULL; NET_VALIDATION_LEVEL eValidation = NET_VALIDATION_NONE; BAIL_ON_INVALID_PTR(pwszUsername, err); BAIL_ON_INVALID_PTR(ppBuffer, err); BAIL_ON_INVALID_PTR(pdwNumEntries, err); BAIL_ON_INVALID_PTR(pdwTotalEntries, err); switch (dwLevel) { case 0: dwInfoLevelSize = sizeof(LOCALGROUP_USERS_INFO_0); break; default: err = ERROR_INVALID_LEVEL; BAIL_ON_WIN_ERROR(err); } status = LwIoGetActiveCreds(NULL, &pCreds); BAIL_ON_NT_STATUS(status); status = NetConnectSamr(&pConn, pwszHostname, 0, dwBuiltinDomainAccess, pCreds); BAIL_ON_NT_STATUS(status); hSamrBinding = pConn->Rpc.Samr.hBinding; hDomain = pConn->Rpc.Samr.hDomain; hBtinDomain = pConn->Rpc.Samr.hBuiltin; pDomainSid = pConn->Rpc.Samr.pDomainSid; status = NetOpenUser(pConn, pwszUsername, dwUserAccess, &hUser, &dwUserRid); BAIL_ON_NT_STATUS(status); dwSidLen = RtlLengthRequiredSid(pDomainSid->SubAuthorityCount + 1); err = LwAllocateMemory(dwSidLen, OUT_PPVOID(&pUserSid)); BAIL_ON_WIN_ERROR(err); status = RtlCopySid(dwSidLen, pUserSid, pDomainSid); BAIL_ON_NT_STATUS(status); status = RtlAppendRidSid(dwSidLen, pUserSid, dwUserRid); BAIL_ON_NT_STATUS(status); status = SamrGetAliasMembership(hSamrBinding, hDomain, &pUserSid, 1, &pdwUserRids, &dwRidsCount); BAIL_ON_NT_STATUS(status); status = SamrGetAliasMembership(hSamrBinding, hBtinDomain, &pUserSid, 1, &pdwBuiltinUserRids, &dwBuiltinRidsCount); BAIL_ON_NT_STATUS(status); dwTotalNumEntries = dwRidsCount + dwBuiltinRidsCount; err = LwAllocateMemory( sizeof(ppwszLocalGroupNames[0]) * dwTotalNumEntries, OUT_PPVOID(&ppwszLocalGroupNames)); BAIL_ON_WIN_ERROR(err); if (dwRidsCount > 0) { status = SamrLookupRids(hSamrBinding, hDomain, dwRidsCount, pdwUserRids, &ppwszAliasNames, &pdwAliasTypes); BAIL_ON_NT_STATUS(status); for (i = 0; i < dwRidsCount; i++) { ppwszLocalGroupNames[i] = ppwszAliasNames[i]; } } if (dwBuiltinRidsCount > 0) { status = SamrLookupRids(hSamrBinding, hBtinDomain, dwBuiltinRidsCount, pdwBuiltinUserRids, &ppwszBuiltinAliasNames, &pdwBuiltinAliasTypes); BAIL_ON_NT_STATUS(status); for (i = 0; i < dwBuiltinRidsCount; i++) { ppwszLocalGroupNames[i + dwRidsCount] = ppwszBuiltinAliasNames[i]; } } for (i = 0; i < dwTotalNumEntries; i++) { pSourceBuffer = ppwszLocalGroupNames[i]; dwSize = 0; err = NetAllocateLocalGroupUsersInfo(NULL, NULL, dwLevel, pSourceBuffer, &dwSize, eValidation); BAIL_ON_WIN_ERROR(err); dwTotalSize += dwSize; dwNumEntries++; if (dwTotalSize > dwMaxBufferSize) { dwTotalSize -= dwSize; dwNumEntries--; break; } } if (dwTotalNumEntries > 0 && dwNumEntries == 0) { err = ERROR_INSUFFICIENT_BUFFER; BAIL_ON_WIN_ERROR(err); } if (dwTotalSize) { status = NetAllocateMemory(OUT_PPVOID(&pBuffer), dwTotalSize); BAIL_ON_NT_STATUS(status); } dwSize = 0; pBufferCursor = pBuffer; dwSpaceAvailable = dwTotalSize; for (i = 0; i < dwNumEntries; i++) { pSourceBuffer = ppwszLocalGroupNames[i]; pBufferCursor = pBuffer + (i * dwInfoLevelSize); err = NetAllocateLocalGroupUsersInfo(pBufferCursor, &dwSpaceAvailable, dwLevel, pSourceBuffer, &dwSize, eValidation); BAIL_ON_WIN_ERROR(err); } if (dwNumEntries < dwTotalNumEntries) { err = ERROR_MORE_DATA; } status = SamrClose(hSamrBinding, hUser); BAIL_ON_NT_STATUS(status); *ppBuffer = pBuffer; *pdwNumEntries = dwNumEntries; *pdwTotalEntries = dwTotalNumEntries; cleanup: LW_SAFE_FREE_MEMORY(pUserSid); LW_SAFE_FREE_MEMORY(ppwszLocalGroupNames); if (pdwUserRids) { SamrFreeMemory(pdwUserRids); } if (pdwBuiltinUserRids) { SamrFreeMemory(pdwBuiltinUserRids); } if (ppwszAliasNames) { SamrFreeMemory(ppwszAliasNames); } if (pdwAliasTypes) { SamrFreeMemory(pdwAliasTypes); } if (ppwszBuiltinAliasNames) { SamrFreeMemory(ppwszBuiltinAliasNames); } if (pdwBuiltinAliasTypes) { SamrFreeMemory(pdwBuiltinAliasTypes); } if (pCreds) { LwIoDeleteCreds(pCreds); } return err; error: if (pBuffer) { NetFreeMemory(pBuffer); } *ppBuffer = NULL; *pdwNumEntries = 0; *pdwTotalEntries = 0; goto cleanup; }
NET_API_STATUS NetUserAdd( PCWSTR pwszHostname, DWORD dwLevel, PVOID pBuffer, PDWORD pdwParmErr ) { const DWORD dwUserAccess = USER_ACCESS_GET_NAME_ETC | USER_ACCESS_SET_LOC_COM | USER_ACCESS_GET_LOCALE | USER_ACCESS_GET_LOGONINFO | USER_ACCESS_GET_ATTRIBUTES | USER_ACCESS_GET_GROUPS | USER_ACCESS_GET_GROUP_MEMBERSHIP | USER_ACCESS_CHANGE_GROUP_MEMBERSHIP | USER_ACCESS_SET_ATTRIBUTES | USER_ACCESS_SET_PASSWORD; const DWORD dwDomainAccess = DOMAIN_ACCESS_CREATE_USER | DOMAIN_ACCESS_LOOKUP_INFO_1; NTSTATUS status = STATUS_SUCCESS; WINERROR err = ERROR_SUCCESS; PNET_CONN pConn = NULL; SAMR_BINDING hSamrBinding = NULL; DOMAIN_HANDLE hDomain = NULL; ACCOUNT_HANDLE hUser = NULL; DWORD dwSamrInfoLevel = 0; DWORD dwSamrPasswordInfoLevel = 0; DWORD dwParmErr = 0; UserInfo *pSamrUserInfo = NULL; UserInfo *pSamrPasswordUserInfo = NULL; DWORD dwSize = 0; DWORD dwSpaceLeft = 0; PIO_CREDS pCreds = NULL; PWSTR pwszUsername = NULL; DWORD dwRid = 0; BOOL bPasswordSet = FALSE; NET_VALIDATION_LEVEL eValidation = NET_VALIDATION_USER_ADD; BAIL_ON_INVALID_PTR(pBuffer, err); if (!(dwLevel == 1 || dwLevel == 2 || dwLevel == 3 || dwLevel == 4)) { err = ERROR_INVALID_LEVEL; BAIL_ON_WIN_ERROR(err); } status = LwIoGetActiveCreds(NULL, &pCreds); BAIL_ON_NT_STATUS(status); err = NetAllocateSamrUserInfo(NULL, &dwSamrInfoLevel, NULL, dwLevel, pBuffer, pConn, &dwSize, eValidation, &dwParmErr); BAIL_ON_WIN_ERROR(err); dwSpaceLeft = dwSize; dwSize = 0; if (dwSpaceLeft) { status = NetAllocateMemory((void**)&pSamrUserInfo, dwSpaceLeft); BAIL_ON_NT_STATUS(status); } err = NetAllocateSamrUserInfo(&pSamrUserInfo->info21, &dwSamrInfoLevel, &dwSpaceLeft, dwLevel, pBuffer, pConn, &dwSize, eValidation, &dwParmErr); BAIL_ON_WIN_ERROR(err); status = NetConnectSamr(&pConn, pwszHostname, dwDomainAccess, 0, pCreds); BAIL_ON_NT_STATUS(status); hSamrBinding = pConn->Rpc.Samr.hBinding; hDomain = pConn->Rpc.Samr.hDomain; err = LwAllocateWc16StringFromUnicodeString( &pwszUsername, (PUNICODE_STRING)&pSamrUserInfo->info21.account_name); BAIL_ON_WIN_ERROR(err); status = SamrCreateUser(hSamrBinding, hDomain, pwszUsername, dwUserAccess, &hUser, &dwRid); if (status == STATUS_USER_EXISTS) { err = NERR_UserExists; } else if (status == STATUS_ALIAS_EXISTS) { err = NERR_GroupExists; } BAIL_ON_NT_STATUS(status); /* * Check if there's password to be set (if it's NULL * the function returns ERROR_INVALID_PASSWORD) */ dwSamrPasswordInfoLevel = 26; dwSize = 0; err = NetAllocateSamrUserInfo(NULL, &dwSamrPasswordInfoLevel, NULL, dwLevel, pBuffer, pConn, &dwSize, eValidation, &dwParmErr); if (err == ERROR_SUCCESS) { dwSpaceLeft = dwSize; dwSize = 0; if (dwSpaceLeft) { status = NetAllocateMemory((void**)&pSamrPasswordUserInfo, dwSpaceLeft); BAIL_ON_NT_STATUS(status); } err = NetAllocateSamrUserInfo(&pSamrPasswordUserInfo->info26, &dwSamrPasswordInfoLevel, &dwSpaceLeft, dwLevel, pBuffer, pConn, &dwSize, eValidation, &dwParmErr); BAIL_ON_WIN_ERROR(err); status = SamrSetUserInfo(hSamrBinding, hUser, dwSamrPasswordInfoLevel, pSamrPasswordUserInfo); BAIL_ON_NT_STATUS(status); bPasswordSet = TRUE; } else if (err == ERROR_INVALID_PASSWORD) { /* This error only means we're not going to try set the password */ err = ERROR_SUCCESS; } else { BAIL_ON_WIN_ERROR(err); } /* * Prevent from trying to rename (to the same name) the account * that has just been created. Created samr user info buffer * contains whatever is passed from net user info buffer. */ if (dwSamrInfoLevel == 21 && (pSamrUserInfo->info21.fields_present & SAMR_FIELD_ACCOUNT_NAME)) { pSamrUserInfo->info21.fields_present ^= SAMR_FIELD_ACCOUNT_NAME; } /* * Disable the account only if there was no password */ if (!bPasswordSet && dwSamrInfoLevel == 21) { pSamrUserInfo->info21.account_flags |= ACB_DISABLED; } status = SamrSetUserInfo(hSamrBinding, hUser, dwSamrInfoLevel, pSamrUserInfo); BAIL_ON_NT_STATUS(status); status = SamrClose(hSamrBinding, hUser); BAIL_ON_NT_STATUS(status); cleanup: NetDisconnectSamr(&pConn); if (pdwParmErr) { *pdwParmErr = dwParmErr; } if (pSamrUserInfo) { NetFreeMemory(pSamrUserInfo); } if (pSamrPasswordUserInfo) { NetFreeMemory(pSamrPasswordUserInfo); } LW_SAFE_FREE_MEMORY(pwszUsername); if (pCreds) { LwIoDeleteCreds(pCreds); } if (err == ERROR_SUCCESS && status != STATUS_SUCCESS) { err = NtStatusToWin32Error(status); } return err; error: goto cleanup; }
NET_API_STATUS NetLocalGroupEnum( PCWSTR pwszHostname, DWORD dwLevel, PVOID *ppBuffer, DWORD dwMaxBufferSize, PDWORD pdwNumEntries, PDWORD pdwTotalNumEntries, PDWORD pdwResume ) { const DWORD dwAccountFlags = 0; const DWORD dwAliasAccessFlags = ALIAS_ACCESS_LOOKUP_INFO; const WORD wInfoLevel = ALIAS_INFO_ALL; NTSTATUS status = STATUS_SUCCESS; WINERROR err = ERROR_SUCCESS; DWORD dwResume = 0; PNET_CONN pConn = NULL; SAMR_BINDING hSamrBinding = NULL; DOMAIN_HANDLE hDomain = NULL; DOMAIN_HANDLE hBtinDomain = NULL; DWORD dwSamrResume = 0; PWSTR *ppwszDomainAliases = NULL; PDWORD pdwDomainRids = NULL; DWORD dwNumDomainEntries = 0; DWORD dwTotalNumDomainEntries = 0; PWSTR *ppwszBtinDomainAliases = NULL; PDWORD pdwBtinDomainRids = NULL; DWORD dwNumBtinDomainEntries = 0; DWORD dwTotalNumBtinDomainEntries = 0; DWORD dwTotalNumEntries = 0; DWORD dwNumEntries = 0; DWORD i = 0; PDWORD pdwRids = NULL; PWSTR *ppwszAliases = NULL; ACCOUNT_HANDLE hAlias = NULL; AliasInfo *pSamrAliasInfo = NULL; AliasInfoAll **ppAliasInfo = NULL; DWORD dwInfoLevelSize = 0; PVOID pSourceBuffer = NULL; DWORD dwSize = 0; DWORD dwTotalSize = 0; DWORD dwSpaceAvailable = 0; PVOID pBuffer = NULL; PVOID pBufferCursor = NULL; PIO_CREDS pCreds = NULL; NET_VALIDATION_LEVEL eValidation = NET_VALIDATION_NONE; BAIL_ON_INVALID_PTR(ppBuffer, err); BAIL_ON_INVALID_PTR(pdwNumEntries, err); BAIL_ON_INVALID_PTR(pdwTotalNumEntries, err); BAIL_ON_INVALID_PTR(pdwResume, err); switch (dwLevel) { case 0: dwInfoLevelSize = sizeof(LOCALGROUP_INFO_0); break; case 1: dwInfoLevelSize = sizeof(LOCALGROUP_INFO_1); break; default: err = ERROR_INVALID_LEVEL; BAIL_ON_WIN_ERROR(err); } dwResume = *pdwResume; status = LwIoGetActiveCreds(NULL, &pCreds); BAIL_ON_NT_STATUS(status); status = NetConnectSamr(&pConn, pwszHostname, 0, 0, pCreds); BAIL_ON_NT_STATUS(status); hSamrBinding = pConn->Rpc.Samr.hBinding; hDomain = pConn->Rpc.Samr.hDomain; hBtinDomain = pConn->Rpc.Samr.hBuiltin; do { status = SamrEnumDomainAliases(hSamrBinding, hDomain, &dwSamrResume, dwAccountFlags, &ppwszDomainAliases, &pdwDomainRids, &dwNumDomainEntries); if (status != STATUS_SUCCESS && status != STATUS_MORE_ENTRIES) { BAIL_ON_NT_STATUS(status); } if (ppwszDomainAliases) { SamrFreeMemory(ppwszDomainAliases); ppwszDomainAliases = NULL; } if (pdwDomainRids) { SamrFreeMemory(pdwDomainRids); pdwDomainRids = NULL; } dwTotalNumDomainEntries += dwNumDomainEntries; dwNumDomainEntries = 0; } while (status == STATUS_MORE_ENTRIES); dwSamrResume = 0; do { status = SamrEnumDomainAliases(hSamrBinding, hBtinDomain, &dwSamrResume, dwAccountFlags, &ppwszBtinDomainAliases, &pdwBtinDomainRids, &dwNumBtinDomainEntries); if (status != STATUS_SUCCESS && status != STATUS_MORE_ENTRIES) { BAIL_ON_NT_STATUS(status); } if (ppwszBtinDomainAliases) { SamrFreeMemory(ppwszBtinDomainAliases); ppwszBtinDomainAliases = NULL; } if (pdwBtinDomainRids) { SamrFreeMemory(pdwBtinDomainRids); pdwBtinDomainRids = NULL; } dwTotalNumBtinDomainEntries += dwNumBtinDomainEntries; dwNumBtinDomainEntries = 0; } while (status == STATUS_MORE_ENTRIES); dwTotalNumEntries = dwTotalNumDomainEntries + dwTotalNumBtinDomainEntries; status = NetAllocateMemory(OUT_PPVOID(&pdwRids), sizeof(pdwRids[0]) * dwTotalNumEntries); BAIL_ON_NT_STATUS(status); status = NetAllocateMemory(OUT_PPVOID(&ppwszAliases), sizeof(ppwszAliases[0]) * dwTotalNumEntries); BAIL_ON_NT_STATUS(status); status = NetAllocateMemory(OUT_PPVOID(&ppAliasInfo), sizeof(ppAliasInfo[0]) * dwTotalNumEntries); BAIL_ON_NT_STATUS(status); dwTotalNumDomainEntries = 0; dwTotalNumBtinDomainEntries = 0; dwSamrResume = 0; do { status = SamrEnumDomainAliases(hSamrBinding, hDomain, &dwSamrResume, dwAccountFlags, &ppwszDomainAliases, &pdwDomainRids, &dwNumDomainEntries); if (status != STATUS_SUCCESS && status != STATUS_MORE_ENTRIES) { BAIL_ON_NT_STATUS(status); } for (i = 0; i < dwNumDomainEntries; i++) { err = LwAllocateWc16String(&ppwszAliases[dwTotalNumDomainEntries + i], ppwszDomainAliases[i]); BAIL_ON_WIN_ERROR(err); pdwRids[dwTotalNumDomainEntries + i] = pdwDomainRids[i]; } dwTotalNumDomainEntries += dwNumDomainEntries; dwNumDomainEntries = 0; if (ppwszDomainAliases) { SamrFreeMemory(ppwszDomainAliases); ppwszDomainAliases = NULL; } if (pdwDomainRids) { SamrFreeMemory(pdwDomainRids); pdwDomainRids = NULL; } } while (status == STATUS_MORE_ENTRIES); dwSamrResume = 0; do { status = SamrEnumDomainAliases(hSamrBinding, hBtinDomain, &dwSamrResume, dwAccountFlags, &ppwszBtinDomainAliases, &pdwBtinDomainRids, &dwNumBtinDomainEntries); if (status != STATUS_SUCCESS && status != STATUS_MORE_ENTRIES) { BAIL_ON_NT_STATUS(status); } for (i = 0; i < dwNumBtinDomainEntries; i++) { err = LwAllocateWc16String(&ppwszAliases[dwTotalNumDomainEntries + dwTotalNumBtinDomainEntries + i], ppwszBtinDomainAliases[i]); BAIL_ON_WIN_ERROR(err); pdwRids[dwTotalNumDomainEntries + dwTotalNumBtinDomainEntries + i] = pdwBtinDomainRids[i]; } dwTotalNumBtinDomainEntries += dwNumBtinDomainEntries; dwNumBtinDomainEntries = 0; if (ppwszBtinDomainAliases) { SamrFreeMemory(ppwszBtinDomainAliases); ppwszBtinDomainAliases = NULL; } if (pdwBtinDomainRids) { SamrFreeMemory(pdwBtinDomainRids); pdwBtinDomainRids = NULL; } } while (status == STATUS_MORE_ENTRIES); for (i = dwResume; i < dwTotalNumEntries; i++) { if (dwLevel == 0) { pSourceBuffer = ppwszAliases[i]; } else { DOMAIN_HANDLE hDom = NULL; DWORD dwRid = 0; hDom = (i < dwTotalNumDomainEntries) ? hDomain : hBtinDomain; dwRid = pdwRids[i]; status = SamrOpenAlias(hSamrBinding, hDom, dwAliasAccessFlags, dwRid, &hAlias); BAIL_ON_NT_STATUS(status); status = SamrQueryAliasInfo(hSamrBinding, hAlias, wInfoLevel, &pSamrAliasInfo); BAIL_ON_NT_STATUS(status); ppAliasInfo[i - dwResume] = &pSamrAliasInfo->all; pSourceBuffer = &pSamrAliasInfo->all; status = SamrClose(hSamrBinding, hAlias); BAIL_ON_NT_STATUS(status); } dwSize = 0; err = NetAllocateLocalGroupInfo(NULL, NULL, dwLevel, pSourceBuffer, &dwSize, eValidation); BAIL_ON_WIN_ERROR(err); dwTotalSize += dwSize; dwNumEntries++; if (dwTotalSize > dwMaxBufferSize) { dwTotalSize -= dwSize; dwNumEntries--; break; } } if (dwTotalNumEntries > 0 && dwNumEntries == 0) { err = ERROR_INSUFFICIENT_BUFFER; BAIL_ON_WIN_ERROR(err); } if (dwTotalSize) { status = NetAllocateMemory(OUT_PPVOID(&pBuffer), dwTotalSize); BAIL_ON_NT_STATUS(status); } dwSize = 0; pBufferCursor = pBuffer; dwSpaceAvailable = dwTotalSize; for (i = 0; i < dwNumEntries; i++) { if (dwLevel == 0) { pSourceBuffer = ppwszAliases[dwResume + i]; } else { pSourceBuffer = ppAliasInfo[i]; } pBufferCursor = pBuffer + (i * dwInfoLevelSize); err = NetAllocateLocalGroupInfo(pBufferCursor, &dwSpaceAvailable, dwLevel, pSourceBuffer, &dwSize, eValidation); BAIL_ON_WIN_ERROR(err); } if (dwResume + dwNumEntries < dwTotalNumEntries) { err = ERROR_MORE_DATA; } *ppBuffer = pBuffer; *pdwNumEntries = dwNumEntries; *pdwTotalNumEntries = dwTotalNumEntries; *pdwResume = dwResume + dwNumEntries; cleanup: NetDisconnectSamr(&pConn); if (pdwRids) { NetFreeMemory(pdwRids); } if (ppwszAliases) { for (i = 0; i < dwTotalNumEntries; i++) { LW_SAFE_FREE_MEMORY(ppwszAliases[i]); } NetFreeMemory(ppwszAliases); } if (ppAliasInfo) { for (i = 0; i < dwNumEntries; i++) { if (ppAliasInfo[i]) { SamrFreeMemory(ppAliasInfo[i]); } } NetFreeMemory(ppAliasInfo); } if (ppwszDomainAliases) { SamrFreeMemory(ppwszDomainAliases); } if (pdwDomainRids) { SamrFreeMemory(pdwDomainRids); } if (ppwszBtinDomainAliases) { SamrFreeMemory(ppwszBtinDomainAliases); } if (pdwBtinDomainRids) { SamrFreeMemory(pdwBtinDomainRids); } if (pCreds) { LwIoDeleteCreds(pCreds); } if (err == ERROR_SUCCESS && status != STATUS_SUCCESS) { err = NtStatusToWin32Error(status); } return err; error: if (pBuffer) { NetFreeMemory(pBuffer); } *ppBuffer = NULL; *pdwNumEntries = 0; *pdwTotalNumEntries = 0; *pdwResume = 0; goto cleanup; }
static DWORD ProcessAddRemoveAccountRights( IN PRPC_PARAMETERS pRpcParams, IN BOOLEAN Add, IN PSTR AccountRights, IN BOOLEAN RemoveAll, 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_CREATE_SPECIAL_ACCOUNTS; POLICY_HANDLE hPolicy = NULL; PSID pAccountSid = NULL; PSTR *ppszAccountRightNames = NULL; DWORD numAccountRightNames = 0; PWSTR *ppwszAccountRightNames = NULL; DWORD i = 0; 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); if (AccountRights) { err = GetStringListFromString( AccountRights, SEPARATOR_CHAR, &ppszAccountRightNames, &numAccountRightNames); BAIL_ON_LSA_ERROR(err); err = LwAllocateMemory( sizeof(ppwszAccountRightNames[0]) * numAccountRightNames, OUT_PPVOID(&ppwszAccountRightNames)); BAIL_ON_LSA_ERROR(err); for (i = 0; i < numAccountRightNames; i++) { err = LwMbsToWc16s(ppszAccountRightNames[i], &ppwszAccountRightNames[i]); BAIL_ON_LSA_ERROR(err); } } if (Add) { ntStatus = LsaAddAccountRights( hLsa, hPolicy, pAccountSid, ppwszAccountRightNames, numAccountRightNames); BAIL_ON_NT_STATUS(ntStatus); fprintf(stdout, "Successfully added account rights to %s\n", AccountName); } else { ntStatus = LsaRemoveAccountRights( hLsa, hPolicy, pAccountSid, RemoveAll, ppwszAccountRightNames, numAccountRightNames); BAIL_ON_NT_STATUS(ntStatus); fprintf(stdout, "Successfully removed account rights from %s\n", AccountName); } 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); } for (i = 0; i < numAccountRightNames; i++) { LW_SAFE_FREE_MEMORY(ppwszAccountRightNames[i]); LW_SAFE_FREE_MEMORY(ppszAccountRightNames[i]); } LW_SAFE_FREE_MEMORY(ppwszAccountRightNames); LW_SAFE_FREE_MEMORY(ppszAccountRightNames); if (err == ERROR_SUCCESS && ntStatus != STATUS_SUCCESS) { err = LwNtStatusToWin32Error(ntStatus); } return err; }
NET_API_STATUS NetJoinDomain( IN PCWSTR pwszServerName, IN PCWSTR pwszDomainName, IN PCWSTR pwszAccountOu, IN PCWSTR pwszAccountName, IN PCWSTR pwszPassword, IN DWORD dwJoinFlags ) { WINERROR err = ERROR_SUCCESS; NTSTATUS ntStatus = STATUS_SUCCESS; PNET_CONN pConn = NULL; WKSS_BINDING hWkssBinding = NULL; PWSTR pwszServer = NULL; PWSTR pwszDomain = NULL; PWSTR pwszAccount = NULL; PWSTR pwszOu = NULL; PIO_CREDS pCreds = NULL; ENC_JOIN_PASSWORD_BUFFER PasswordBuffer; BAIL_ON_INVALID_PTR(pwszDomainName, err); BAIL_ON_INVALID_PTR(pwszAccountName, err); BAIL_ON_INVALID_PTR(pwszPassword, err); memset(&PasswordBuffer, 0, sizeof(PasswordBuffer)); ntStatus = LwIoGetActiveCreds(NULL, &pCreds); BAIL_ON_NT_STATUS(ntStatus); ntStatus = NetConnectWkssvc(&pConn, pwszServerName, pCreds); BAIL_ON_NT_STATUS(ntStatus); hWkssBinding = pConn->Rpc.WksSvc.hBinding; if (pwszServerName) { err = LwAllocateWc16String(&pwszServer, pwszServerName); BAIL_ON_WIN_ERROR(err); } err = LwAllocateWc16String(&pwszDomain, pwszDomainName); BAIL_ON_WIN_ERROR(err); err = LwAllocateWc16String(&pwszAccount, pwszAccountName); BAIL_ON_WIN_ERROR(err); if (pwszAccountOu) { err = LwAllocateWc16String(&pwszOu, pwszAccountOu); BAIL_ON_WIN_ERROR(err); } err = NetEncryptJoinPasswordBuffer(pConn, pwszPassword, &PasswordBuffer); BAIL_ON_WIN_ERROR(err); err = NetrJoinDomain2(hWkssBinding, pwszServer, pwszDomain, pwszOu, pwszAccount, &PasswordBuffer, dwJoinFlags); BAIL_ON_WIN_ERROR(err); cleanup: if (pConn) { NetDisconnectWkssvc(&pConn); } memset(&PasswordBuffer, 0, sizeof(PasswordBuffer)); LW_SAFE_FREE_MEMORY(pwszServer); LW_SAFE_FREE_MEMORY(pwszDomain); LW_SAFE_FREE_MEMORY(pwszOu); LW_SAFE_FREE_MEMORY(pwszAccount); if (pCreds) { LwIoDeleteCreds(pCreds); } if (err == ERROR_SUCCESS && ntStatus != STATUS_SUCCESS) { err = LwNtStatusToWin32Error(ntStatus); } return (NET_API_STATUS)err; error: goto cleanup; }
static DWORD ProcessGetAccountSystemAccessRights( IN PRPC_PARAMETERS pRpcParams, IN PSTR pszAccountName ) { DWORD err = ERROR_SUCCESS; NTSTATUS ntStatus = STATUS_SUCCESS; LSA_BINDING hLsa = NULL; LW_PIO_CREDS pCreds = NULL; PSID pAccountSid = NULL; WCHAR wszSysName[] = {'\\', '\\', '\0'}; DWORD policyAccessMask = LSA_ACCESS_LOOKUP_NAMES_SIDS | LSA_ACCESS_CREATE_PRIVILEGE | LSA_ACCESS_CREATE_SPECIAL_ACCOUNTS; POLICY_HANDLE hPolicy = NULL; DWORD accountAccessMask = LSA_ACCOUNT_VIEW; LSAR_ACCOUNT_HANDLE hAccount = NULL; DWORD systemAccess = 0; err = CreateRpcCredentials(pRpcParams, &pCreds); BAIL_ON_LSA_ERROR(err); err = CreateLsaRpcBinding(pRpcParams, pCreds, &hLsa); BAIL_ON_LSA_ERROR(err); err = ResolveAccountNameToSid( hLsa, pszAccountName, &pAccountSid); BAIL_ON_LSA_ERROR(err); ntStatus = LsaOpenPolicy2(hLsa, wszSysName, NULL, policyAccessMask, &hPolicy); BAIL_ON_NT_STATUS(ntStatus); ntStatus = LsaOpenAccount(hLsa, hPolicy, pAccountSid, accountAccessMask, &hAccount); BAIL_ON_NT_STATUS(ntStatus); ntStatus = LsaGetSystemAccessAccount( hLsa, hAccount, &systemAccess); BAIL_ON_NT_STATUS(ntStatus); fprintf(stdout, "Account: %s:\n" "==================================================================" "==============\n", pszAccountName); fprintf(stdout, "System Access Rights 0x%08x\n", systemAccess); 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 (hAccount) { LsaClose(hLsa, hAccount); } if (hPolicy) { LsaClose(hLsa, hPolicy); } if (hLsa) { LsaFreeBinding(&hLsa); } if (pCreds) { LwIoDeleteCreds(pCreds); } RTL_FREE(&pAccountSid); if (err == ERROR_SUCCESS && ntStatus != STATUS_SUCCESS) { err = LwNtStatusToWin32Error(ntStatus); } return err; }
DWORD LsaSetSMBCreds( IN PCSTR pszUserPrincipalName, IN PCSTR pszPassword, IN BOOLEAN bSetDefaultCachePath, OUT PLSA_CREDS_FREE_INFO* ppFreeInfo ) { DWORD dwError = 0; krb5_error_code ret = 0; PSTR pszNewCachePath = NULL; PCSTR pszCacheName = NULL; PCSTR pszCacheType = NULL; krb5_context ctx = 0; krb5_ccache cc = 0; LW_PIO_CREDS pNewCreds = NULL; LW_PIO_CREDS pOldCreds = NULL; PLSA_CREDS_FREE_INFO pFreeInfo = NULL; PSTR pszOldCachePath = NULL; BOOLEAN bSwitchedPath = FALSE; BAIL_ON_INVALID_POINTER(ppFreeInfo); BAIL_ON_INVALID_STRING(pszUserPrincipalName); ret = krb5_init_context(&ctx); BAIL_ON_KRB_ERROR(ctx, ret); /* Generates a new filed based credentials cache in /tmp. The file will * be owned by root and only accessible by root. */ ret = krb5_cc_new_unique( ctx, "FILE", "hint", &cc); BAIL_ON_KRB_ERROR(ctx, ret); pszCacheType = krb5_cc_get_type(ctx, cc); pszCacheName = krb5_cc_get_name(ctx, cc); dwError = LwAllocateStringPrintf(&pszNewCachePath, "%s:%s", pszCacheType, pszCacheName); BAIL_ON_LSA_ERROR(dwError); dwError = LwKrb5GetTgt( pszUserPrincipalName, pszPassword, pszNewCachePath, NULL); BAIL_ON_LSA_ERROR(dwError); if (bSetDefaultCachePath) { LSA_LOG_DEBUG("Switching default credentials path for new access token"); dwError = LwKrb5SetThreadDefaultCachePath( pszNewCachePath, &pszOldCachePath); BAIL_ON_LSA_ERROR(dwError); bSwitchedPath = TRUE; } dwError = LwIoCreateKrb5CredsA( pszUserPrincipalName, pszNewCachePath, &pNewCreds); BAIL_ON_LSA_ERROR(dwError); dwError = LwAllocateMemory(sizeof(*pFreeInfo), (PVOID*)&pFreeInfo); BAIL_ON_LSA_ERROR(dwError); dwError = LwIoGetThreadCreds(&pOldCreds); BAIL_ON_LSA_ERROR(dwError); dwError = LwIoSetThreadCreds(pNewCreds); BAIL_ON_LSA_ERROR(dwError); pFreeInfo->ctx = ctx; pFreeInfo->cc = cc; pFreeInfo->pRestoreCreds = pOldCreds; pFreeInfo->pszRestoreCache = pszOldCachePath; pFreeInfo->bKrbCreds = TRUE; pOldCreds = NULL; cleanup: *ppFreeInfo = pFreeInfo; if (pOldCreds != NULL) { LwIoDeleteCreds(pOldCreds); } if (pNewCreds != NULL) { LwIoDeleteCreds(pNewCreds); } LW_SAFE_FREE_STRING(pszNewCachePath); return dwError; error: if (ctx != NULL) { if (cc != NULL) { krb5_cc_destroy(ctx, cc); } krb5_free_context(ctx); } if (pFreeInfo) { LwFreeMemory(pFreeInfo); pFreeInfo = NULL; } if (bSwitchedPath) { LwKrb5SetThreadDefaultCachePath( pszOldCachePath, NULL); LW_SAFE_FREE_STRING(pszOldCachePath); } goto cleanup; }
static DWORD ProcessDeleteAccount( 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; DWORD accountAccessMask = DELETE; POLICY_HANDLE hPolicy = NULL; LSAR_ACCOUNT_HANDLE hAccount = NULL; PSID pAccountSid = 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 = LsaOpenAccount( hLsa, hPolicy, pAccountSid, accountAccessMask, &hAccount); BAIL_ON_NT_STATUS(ntStatus); ntStatus = LsaRpcDeleteObject( hLsa, hAccount); BAIL_ON_NT_STATUS(ntStatus); 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 (err == ERROR_SUCCESS && ntStatus != STATUS_SUCCESS) { err = LwNtStatusToWin32Error(ntStatus); } return err; }
static NTSTATUS LwIoCreateDefaultKrb5Creds( PIO_CREDS* ppCreds ) { NTSTATUS Status = STATUS_SUCCESS; krb5_context pKrb5Context = NULL; krb5_error_code krb5Error = 0; krb5_ccache pKrb5Cache = NULL; krb5_principal pKrb5Principal = NULL; char* pszPrincipalName = NULL; const char* pszCredCachePath = NULL; PIO_CREDS pCreds = NULL; *ppCreds = NULL; krb5Error = krb5_init_context(&pKrb5Context); if (krb5Error) { Status = STATUS_INSUFFICIENT_RESOURCES; BAIL_ON_NT_STATUS(Status); } pszCredCachePath = krb5_cc_default_name(pKrb5Context); if (!pszCredCachePath) { /* If there is no default path, give up */ goto cleanup; } krb5Error = krb5_cc_resolve(pKrb5Context, pszCredCachePath, &pKrb5Cache); if (krb5Error) { /* If we can't access the cache, give up */ goto cleanup; } krb5Error = krb5_cc_get_principal(pKrb5Context, pKrb5Cache, &pKrb5Principal); if (krb5Error) { /* If there is no principal, give up */ goto cleanup; } krb5Error = krb5_unparse_name(pKrb5Context, pKrb5Principal, &pszPrincipalName); if (krb5Error) { Status = STATUS_UNSUCCESSFUL; BAIL_ON_NT_STATUS(Status); } Status = LwIoAllocateMemory(sizeof(*pCreds), OUT_PPVOID(&pCreds)); BAIL_ON_NT_STATUS(Status); pCreds->type = IO_CREDS_TYPE_KRB5_CCACHE; Status = LwRtlWC16StringAllocateFromCString( &pCreds->payload.krb5Ccache.pwszPrincipal, pszPrincipalName ); BAIL_ON_NT_STATUS(Status); Status = LwRtlWC16StringAllocateFromCString( &pCreds->payload.krb5Ccache.pwszCachePath, pszCredCachePath ); BAIL_ON_NT_STATUS(Status); *ppCreds = pCreds; cleanup: if (pszPrincipalName) { krb5_free_unparsed_name(pKrb5Context, pszPrincipalName); } if (pKrb5Principal) { krb5_free_principal(pKrb5Context, pKrb5Principal); } if (pKrb5Cache) { krb5_cc_close(pKrb5Context, pKrb5Cache); } if (pKrb5Context) { krb5_free_context(pKrb5Context); } return Status; error: if (pCreds) { LwIoDeleteCreds(pCreds); } goto cleanup; }
static NTSTATUS LwIoCredentialCacheToTgt( PIO_CREDS pCacheToken, PIO_CREDS* ppCreds ) { NTSTATUS Status = STATUS_SUCCESS; krb5_context pContext = NULL; krb5_error_code krb5Error = 0; krb5_ccache pCache = NULL; PSTR pszClientPrincipalName = NULL; PSTR pszServerPrincipalName = NULL; PSTR pszDesiredPrincipal = NULL; PSTR pszCredCachePath = NULL; PIO_CREDS pCreds = NULL; BOOLEAN bFoundTgt = FALSE; BOOLEAN bStartSeq = FALSE; krb5_creds creds; krb5_cc_cursor cursor; Status = LwRtlCStringAllocateFromWC16String( &pszDesiredPrincipal, pCacheToken->payload.krb5Ccache.pwszPrincipal); BAIL_ON_NT_STATUS(Status); Status = LwRtlCStringAllocateFromWC16String( &pszCredCachePath, pCacheToken->payload.krb5Ccache.pwszCachePath); BAIL_ON_NT_STATUS(Status); /* Open credentials cache */ krb5Error = krb5_init_context(&pContext); if (krb5Error) { Status = STATUS_INSUFFICIENT_RESOURCES; BAIL_ON_NT_STATUS(Status); } krb5Error = krb5_cc_resolve(pContext, pszCredCachePath, &pCache); if (krb5Error) { Status = STATUS_UNSUCCESSFUL; BAIL_ON_NT_STATUS(Status); } /* Look for a TGT */ krb5Error = krb5_cc_start_seq_get(pContext, pCache, &cursor); if (krb5Error) { Status = STATUS_UNSUCCESSFUL; BAIL_ON_NT_STATUS(Status); } bStartSeq = TRUE; while ((krb5Error = krb5_cc_next_cred(pContext, pCache, &cursor, &creds)) == 0) { /* Look tickets with the intial flag set */ if (creds.ticket_flags & TKT_FLG_INITIAL) { /* Extract and compare client principal with desired principal */ krb5Error = krb5_unparse_name(pContext, creds.client, &pszClientPrincipalName); if (krb5Error) { Status = STATUS_UNSUCCESSFUL; BAIL_ON_NT_STATUS(Status); } if (!strcmp(pszClientPrincipalName, pszDesiredPrincipal)) { bFoundTgt = TRUE; break; } krb5_free_unparsed_name(pContext, pszClientPrincipalName); pszClientPrincipalName = NULL; } krb5_free_cred_contents(pContext, &creds); } if (!bFoundTgt) { Status = STATUS_UNSUCCESSFUL; BAIL_ON_NT_STATUS(Status); } /* Extract server principal name */ krb5Error = krb5_unparse_name(pContext, creds.server, &pszServerPrincipalName); if (krb5Error) { Status = STATUS_UNSUCCESSFUL; BAIL_ON_NT_STATUS(Status); } /* Construct token from krb5 credential data */ Status = LwIoAllocateMemory(sizeof(*pCreds), OUT_PPVOID(&pCreds)); BAIL_ON_NT_STATUS(Status); pCreds->type = IO_CREDS_TYPE_KRB5_TGT; /* Copy principal names */ Status = LwRtlWC16StringAllocateFromCString( &pCreds->payload.krb5Tgt.pwszClientPrincipal, pszClientPrincipalName); BAIL_ON_NT_STATUS(Status); Status = LwRtlWC16StringAllocateFromCString( &pCreds->payload.krb5Tgt.pwszServerPrincipal, pszServerPrincipalName); BAIL_ON_NT_STATUS(Status); /* Set time fields */ pCreds->payload.krb5Tgt.authTime = creds.times.authtime; pCreds->payload.krb5Tgt.startTime = creds.times.starttime; pCreds->payload.krb5Tgt.endTime = creds.times.endtime; pCreds->payload.krb5Tgt.renewTillTime = creds.times.renew_till; /* Copy encryption key */ pCreds->payload.krb5Tgt.keyType = creds.keyblock.enctype; pCreds->payload.krb5Tgt.ulKeySize = creds.keyblock.length; Status = LwIoAllocateMemory( creds.keyblock.length, OUT_PPVOID(&pCreds->payload.krb5Tgt.pKeyData)); BAIL_ON_NT_STATUS(Status); memcpy( pCreds->payload.krb5Tgt.pKeyData, creds.keyblock.contents, creds.keyblock.length); /* Copy tgt */ pCreds->payload.krb5Tgt.tgtFlags = creds.ticket_flags; pCreds->payload.krb5Tgt.ulTgtSize = creds.ticket.length; Status = LwIoAllocateMemory( creds.ticket.length, OUT_PPVOID(&pCreds->payload.krb5Tgt.pTgtData)); BAIL_ON_NT_STATUS(Status); memcpy( pCreds->payload.krb5Tgt.pTgtData, creds.ticket.data, creds.ticket.length); *ppCreds = pCreds; cleanup: LWIO_SAFE_FREE_MEMORY(pszDesiredPrincipal); LWIO_SAFE_FREE_MEMORY(pszCredCachePath); if (pszClientPrincipalName) { krb5_free_unparsed_name(pContext, pszClientPrincipalName); } if (pszServerPrincipalName) { krb5_free_unparsed_name(pContext, pszServerPrincipalName); } if (bFoundTgt) { krb5_free_cred_contents(pContext, &creds); } if (bStartSeq) { krb5_cc_end_seq_get(pContext, pCache, &cursor); } if (pCache) { krb5_cc_close(pContext, pCache); } if (pContext) { krb5_free_context(pContext); } return Status; error: *ppCreds = NULL; if (pCreds) { LwIoDeleteCreds(pCreds); } goto cleanup; }
LW_NTSTATUS LwIoSetPathCreds( IN LW_PUNICODE_STRING PathPrefix, IN OPTIONAL LW_PIO_CREDS pCreds ) { LW_NTSTATUS Status = STATUS_SUCCESS; PIO_PATH_CREDS pPathCreds = NULL; PIO_CREDS pCredCopy = NULL; BOOL bInLock = FALSE; LWIO_LOCK_MUTEX(bInLock, &gLock); Status = LwIoFindPathCreds(PathPrefix, TRUE, &pPathCreds); BAIL_ON_NT_STATUS(Status); if (pPathCreds) { Status = LwIoCopyCreds(pCreds, &pCredCopy); BAIL_ON_NT_STATUS(Status); if (pPathCreds->pCreds) { LwIoDeleteCreds(pPathCreds->pCreds); } pPathCreds->pCreds = pCredCopy; pCredCopy = NULL; pPathCreds = NULL; } else if (pCreds) { Status = RTL_ALLOCATE(&pPathCreds, IO_PATH_CREDS, sizeof(IO_PATH_CREDS)); BAIL_ON_NT_STATUS(Status); LwListInit(&pPathCreds->link); Status = LwIoNormalizePath(PathPrefix, &pPathCreds->PathPrefix); BAIL_ON_NT_STATUS(Status); Status = LwIoCopyCreds(pCreds, &pPathCreds->pCreds); BAIL_ON_NT_STATUS(Status); LwListInsertBefore(&gPathCreds, &pPathCreds->link); pPathCreds = NULL; } cleanup: LWIO_UNLOCK_MUTEX(bInLock, &gLock); if (pCredCopy) { LwIoDeleteCreds(pCredCopy); } if (pPathCreds) { LwIoDeletePathCreds(pPathCreds); } return Status; error: goto cleanup; }
NTSTATUS LwNtCreateFile( OUT PIO_FILE_HANDLE FileHandle, IN OUT OPTIONAL PIO_ASYNC_CONTROL_BLOCK AsyncControlBlock, OUT PIO_STATUS_BLOCK IoStatusBlock, IN PIO_FILE_NAME FileName, IN OPTIONAL PSECURITY_DESCRIPTOR_RELATIVE SecurityDescriptor, IN OPTIONAL PVOID SecurityQualityOfService, // TBD IN ACCESS_MASK DesiredAccess, IN OPTIONAL LONG64 AllocationSize, IN FILE_ATTRIBUTES FileAttributes, IN FILE_SHARE_FLAGS ShareAccess, IN FILE_CREATE_DISPOSITION CreateDisposition, IN FILE_CREATE_OPTIONS CreateOptions, IN OPTIONAL PVOID EaBuffer, // PFILE_FULL_EA_INFORMATION IN ULONG EaLength, IN OPTIONAL PIO_ECP_LIST EcpList, IN OPTIONAL LW_PIO_CREDS pCreds ) { NTSTATUS status = 0; int EE = 0; PIO_CREDS pActiveCreds = NULL; PCREATEFILE_CONTEXT pCreateContext = NULL; if (!pCreds) { status = LwIoGetActiveCreds(FileName->FileName, &pActiveCreds); GOTO_CLEANUP_ON_STATUS_EE(status, EE); pCreds = pActiveCreds; } status = NtpAllocAsyncContext(OUT_PPVOID(&pCreateContext), sizeof(*pCreateContext)); GOTO_CLEANUP_ON_STATUS_EE(status, EE); pCreateContext->IoStatusBlock = IoStatusBlock; pCreateContext->FileHandle = FileHandle; status = LwIoResolveCreds(pCreds, &pCreateContext->Request.pSecurityToken); GOTO_CLEANUP_ON_STATUS_EE(status, EE); pCreateContext->Request.FileName = *FileName; pCreateContext->Request.DesiredAccess = DesiredAccess; pCreateContext->Request.AllocationSize = AllocationSize; pCreateContext->Request.FileAttributes = FileAttributes; pCreateContext->Request.ShareAccess = ShareAccess; pCreateContext->Request.CreateDisposition = CreateDisposition; pCreateContext->Request.CreateOptions = CreateOptions; pCreateContext->Request.EaBuffer = EaBuffer; pCreateContext->Request.EaLength = EaLength; if (SecurityDescriptor) { pCreateContext->Request.SecurityDescriptor = SecurityDescriptor; pCreateContext->Request.SecDescLength = RtlLengthSecurityDescriptorRelative(SecurityDescriptor); } pCreateContext->Request.EcpCount = IoRtlEcpListGetCount(EcpList); if (pCreateContext->Request.EcpCount) { PCSTR pszType = NULL; ULONG ecpIndex = 0; status = RTL_ALLOCATE( &pCreateContext->Request.EcpList, NT_IPC_HELPER_ECP, sizeof(*pCreateContext->Request.EcpList) * pCreateContext->Request.EcpCount); GOTO_CLEANUP_ON_STATUS_EE(status, EE); while (ecpIndex < pCreateContext->Request.EcpCount) { status = IoRtlEcpListGetNext( EcpList, pszType, &pCreateContext->Request.EcpList[ecpIndex].pszType, &pCreateContext->Request.EcpList[ecpIndex].pData, &pCreateContext->Request.EcpList[ecpIndex].Size); GOTO_CLEANUP_ON_STATUS_EE(status, EE); pszType = pCreateContext->Request.EcpList[ecpIndex].pszType; ecpIndex++; } assert(ecpIndex == pCreateContext->Request.EcpCount); status = STATUS_SUCCESS; } status = NtpCtxCallAsync( &pCreateContext->Base, NT_IPC_MESSAGE_TYPE_CREATE_FILE, &pCreateContext->Request, NT_IPC_MESSAGE_TYPE_CREATE_FILE_RESULT, AsyncControlBlock, LwNtCreateFileComplete); GOTO_CLEANUP_ON_STATUS_EE(status, EE); cleanup: if (pActiveCreds) { LwIoDeleteCreds(pActiveCreds); } if (status != STATUS_PENDING) { if (pCreateContext) { LwNtCreateFileComplete(&pCreateContext->Base, status); status = IoStatusBlock->Status; NtpFreeClientAsyncContext(&pCreateContext->Base); } else { IoStatusBlock->Status = status; } } LOG_LEAVE_IF_STATUS_EE(status, EE); return status; }
NTSTATUS LsaSrvGetSystemCreds( OUT LW_PIO_CREDS *ppCreds ) { NTSTATUS ntStatus = STATUS_SUCCESS; DWORD dwError = ERROR_SUCCESS; LW_PIO_CREDS pCreds = NULL; PSTR pszMachinePrincipal = NULL; PSTR pszCachePath = NULL; PLSA_MACHINE_ACCOUNT_INFO_A pAccountInfo = NULL; dwError = LsaSrvProviderGetMachineAccountInfoA( LSA_PROVIDER_TAG_AD, NULL, &pAccountInfo); BAIL_ON_LSA_ERROR(dwError); dwError = LwAllocateStringPrintf( &pszMachinePrincipal, "%s@%s", pAccountInfo->SamAccountName, pAccountInfo->DnsDomainName); BAIL_ON_LSA_ERROR(dwError); dwError = LwAllocateStringPrintf( &pszCachePath, "%s.%s", LSASS_KRB5_CACHE_PATH, pAccountInfo->DnsDomainName); BAIL_ON_LSA_ERROR(dwError); dwError = LwIoCreateKrb5CredsA( pszMachinePrincipal, pszCachePath, &pCreds); BAIL_ON_LSA_ERROR(dwError); *ppCreds = pCreds; cleanup: LW_SAFE_FREE_STRING(pszMachinePrincipal); LW_SAFE_FREE_STRING(pszCachePath); LsaSrvFreeMachineAccountInfoA(pAccountInfo); if (ntStatus == STATUS_SUCCESS && dwError != ERROR_SUCCESS) { ntStatus = LwWin32ErrorToNtStatus(dwError); } return ntStatus; error: if (pCreds) { LwIoDeleteCreds(pCreds); } *ppCreds = NULL; goto cleanup; }
NET_API_STATUS NetLocalGroupGetMembers( IN PCWSTR pwszHostname, IN PCWSTR pwszAliasname, IN DWORD dwLevel, OUT PVOID *ppBuffer, IN DWORD dwMaxBufferSize, OUT PDWORD pdwNumEntries, OUT PDWORD pdwTotalEntries, OUT PDWORD pdwResume ) { const DWORD dwLsaAccessFlags = LSA_ACCESS_LOOKUP_NAMES_SIDS; const DWORD dwAliasAccessFlags = ALIAS_ACCESS_GET_MEMBERS; const WORD wLookupLevel = 1; NTSTATUS status = STATUS_SUCCESS; WINERROR err = ERROR_SUCCESS; PNET_CONN pConn = NULL; SAMR_BINDING hSamrBinding = NULL; LSA_BINDING hLsaBinding = NULL; ACCOUNT_HANDLE hAlias = NULL; PSID *ppSids = NULL; DWORD dwInfoLevelSize = 0; DWORD dwTotalNumEntries = 0; DWORD dwResume = 0; DWORD dwAliasRid = 0; DWORD i = 0; DWORD dwNumSids = 0; DWORD dwCount = 0; POLICY_HANDLE hLsaPolicy = NULL; SID_ARRAY Sids = {0}; RefDomainList *pDomains = NULL; TranslatedName *pNames = NULL; PNET_RESOLVED_NAME pResolvedNames = NULL; PVOID pSourceBuffer = NULL; PVOID pBuffer = NULL; PVOID pBufferCursor = NULL; DWORD dwSize = 0; DWORD dwTotalSize = 0; DWORD dwNumEntries = 0; DWORD dwSpaceAvailable = 0; PIO_CREDS pCreds = NULL; NET_VALIDATION_LEVEL eValidation = NET_VALIDATION_NONE; BAIL_ON_INVALID_PTR(pwszAliasname, err); BAIL_ON_INVALID_PTR(ppBuffer, err); BAIL_ON_INVALID_PTR(pdwNumEntries, err); BAIL_ON_INVALID_PTR(pdwTotalEntries, err); BAIL_ON_INVALID_PTR(pdwResume, err); switch (dwLevel) { case 0: dwInfoLevelSize = sizeof(LOCALGROUP_MEMBERS_INFO_0); break; case 3: dwInfoLevelSize = sizeof(LOCALGROUP_MEMBERS_INFO_3); break; case 1: case 2: default: err = ERROR_INVALID_LEVEL; BAIL_ON_WIN_ERROR(err); } dwResume = *pdwResume; status = LwIoGetActiveCreds(NULL, &pCreds); BAIL_ON_NT_STATUS(status); status = NetConnectSamr(&pConn, pwszHostname, 0, 0, pCreds); BAIL_ON_NT_STATUS(status); hSamrBinding = pConn->Rpc.Samr.hBinding; status = NetOpenAlias(pConn, pwszAliasname, dwAliasAccessFlags, &hAlias, &dwAliasRid); if (status == STATUS_NONE_MAPPED) { /* No such alias in host's domain. Try to look in builtin domain. */ status = NetOpenAlias(pConn, pwszAliasname, dwAliasAccessFlags, &hAlias, &dwAliasRid); BAIL_ON_NT_STATUS(status); } else if (status != STATUS_SUCCESS) { BAIL_ON_NT_STATUS(status); } status = SamrGetMembersInAlias(hSamrBinding, hAlias, &ppSids, &dwNumSids); BAIL_ON_NT_STATUS(status); status = SamrClose(hSamrBinding, hAlias); BAIL_ON_NT_STATUS(status); dwTotalNumEntries = dwNumSids; if (dwLevel == 0) { for (i = 0; i + dwResume < dwNumSids; i++) { pSourceBuffer = ppSids[i + dwResume]; err = NetAllocateLocalGroupMembersInfo(NULL, NULL, dwLevel, pSourceBuffer, &dwSize, eValidation); BAIL_ON_WIN_ERROR(err); dwTotalSize += dwSize; dwNumEntries++; if (dwTotalSize > dwMaxBufferSize) { dwTotalSize -= dwSize; dwNumEntries--; break; } } } else { status = NetConnectLsa(&pConn, pwszHostname, dwLsaAccessFlags, pCreds); BAIL_ON_NT_STATUS(status); hLsaBinding = pConn->Rpc.Lsa.hBinding; hLsaPolicy = pConn->Rpc.Lsa.hPolicy; Sids.dwNumSids = dwNumSids; status = NetAllocateMemory(OUT_PPVOID(&Sids.pSids), sizeof(Sids.pSids[0]) * Sids.dwNumSids); BAIL_ON_NT_STATUS(status); for (i = 0; i < Sids.dwNumSids; i++) { Sids.pSids[i].pSid = ppSids[i]; } status = LsaLookupSids(hLsaBinding, hLsaPolicy, &Sids, &pDomains, &pNames, wLookupLevel, &dwCount); if (status != STATUS_SUCCESS && status != LW_STATUS_SOME_NOT_MAPPED) { BAIL_ON_NT_STATUS(status); } status = NetAllocateMemory(OUT_PPVOID(&pResolvedNames), sizeof(*pResolvedNames) * dwCount); BAIL_ON_NT_STATUS(status); for (i = 0; i + dwResume < dwCount; i++) { DWORD iDomain = pNames[i + dwResume].sid_index; pResolvedNames[i].AccountName = pNames[i + dwResume].name; pResolvedNames[i].usType = pNames[i + dwResume].type; pResolvedNames[i].DomainName = pDomains->domains[iDomain].name; pSourceBuffer = pResolvedNames; err = NetAllocateLocalGroupMembersInfo(NULL, NULL, dwLevel, pSourceBuffer, &dwSize, eValidation); BAIL_ON_WIN_ERROR(err); dwTotalSize += dwSize; dwNumEntries++; if (dwTotalSize > dwMaxBufferSize) { dwTotalSize -= dwSize; dwNumEntries--; break; } } } if (dwTotalNumEntries > 0 && dwNumEntries == 0) { err = ERROR_INSUFFICIENT_BUFFER; BAIL_ON_WIN_ERROR(err); } if (dwTotalSize) { status = NetAllocateMemory(OUT_PPVOID(&pBuffer), dwTotalSize); BAIL_ON_NT_STATUS(status); } dwSize = 0; pBufferCursor = pBuffer; dwSpaceAvailable = dwTotalSize; for (i = 0; i < dwNumEntries; i++) { if (dwLevel == 0) { pSourceBuffer = ppSids[i + dwResume]; } else { pSourceBuffer = &(pResolvedNames[i]); } pBufferCursor = pBuffer + (i * dwInfoLevelSize); err = NetAllocateLocalGroupMembersInfo(pBufferCursor, &dwSpaceAvailable, dwLevel, pSourceBuffer, &dwSize, eValidation); BAIL_ON_WIN_ERROR(err); } if (dwResume + dwNumEntries < dwTotalNumEntries) { err = ERROR_MORE_DATA; } *ppBuffer = pBuffer; *pdwResume = dwResume + dwNumEntries; *pdwNumEntries = dwNumEntries; *pdwTotalEntries = dwTotalNumEntries; cleanup: NetDisconnectSamr(&pConn); if (Sids.pSids) { NetFreeMemory(Sids.pSids); } if (ppSids) { SamrFreeMemory(ppSids); } if (pNames) { SamrFreeMemory(pNames); } if (pDomains) { SamrFreeMemory(pDomains); } if (pCreds) { LwIoDeleteCreds(pCreds); } if (err == ERROR_SUCCESS && status != STATUS_SUCCESS) { err = LwNtStatusToWin32Error(status); } return err; error: if (pBuffer) { NetFreeMemory(pBuffer); } *ppBuffer = NULL; goto cleanup; }
NET_API_STATUS NetGetDomainName( IN PCWSTR pwszHostname, OUT PWSTR *ppwszDomainName ) { const DWORD dwConnAccess = SAMR_ACCESS_OPEN_DOMAIN | SAMR_ACCESS_ENUM_DOMAINS; NTSTATUS ntStatus = STATUS_SUCCESS; WINERROR err = ERROR_SUCCESS; PNET_CONN pConn = NULL; size_t sDomainNameLen = 0; PWSTR pwszDomainName = NULL; PIO_CREDS pCreds = NULL; BAIL_ON_INVALID_PTR(ppwszDomainName, err); ntStatus = LwIoGetActiveCreds(NULL, &pCreds); BAIL_ON_NT_STATUS(ntStatus); ntStatus = NetConnectSamr(&pConn, pwszHostname, dwConnAccess, 0, pCreds); BAIL_ON_NT_STATUS(ntStatus); err = LwWc16sLen(pConn->Rpc.Samr.pwszDomainName, &sDomainNameLen); BAIL_ON_WIN_ERROR(err); ntStatus = NetAllocateMemory( OUT_PPVOID(&pwszDomainName), sizeof(pwszDomainName[0]) * (sDomainNameLen + 1)); BAIL_ON_NT_STATUS(ntStatus); err = LwWc16snCpy(pwszDomainName, pConn->Rpc.Samr.pwszDomainName, sDomainNameLen); BAIL_ON_WIN_ERROR(err); *ppwszDomainName = pwszDomainName; cleanup: NetDisconnectSamr(&pConn); if (pCreds) { LwIoDeleteCreds(pCreds); } if (err == ERROR_SUCCESS && ntStatus != STATUS_SUCCESS) { err = NtStatusToWin32Error(ntStatus); } return err; error: if (pwszDomainName) { NetFreeMemory(pwszDomainName); } *ppwszDomainName = NULL; goto cleanup; }
NET_API_STATUS NetUserSetInfo( PCWSTR pwszHostname, PCWSTR pwszUsername, DWORD dwLevel, PVOID pBuffer, PDWORD pdwParmErr ) { /* This is necessary to be able to set account password. Otherwise we get access denied. Don't ask... */ const DWORD dwDomainAccess = DOMAIN_ACCESS_LOOKUP_INFO_1; const DWORD dwUserAccess = USER_ACCESS_GET_NAME_ETC | USER_ACCESS_GET_LOCALE | USER_ACCESS_GET_LOGONINFO | USER_ACCESS_GET_ATTRIBUTES | USER_ACCESS_GET_GROUPS | USER_ACCESS_GET_GROUP_MEMBERSHIP | USER_ACCESS_SET_LOC_COM | USER_ACCESS_SET_ATTRIBUTES | USER_ACCESS_CHANGE_PASSWORD | USER_ACCESS_SET_PASSWORD; NTSTATUS status = STATUS_SUCCESS; WINERROR err = ERROR_SUCCESS; PNET_CONN pConn = NULL; SAMR_BINDING hSamrBinding = NULL; ACCOUNT_HANDLE hUser = NULL; DWORD dwUserRid = 0; DWORD dwSamrInfoLevel = 0; DWORD dwSamrPasswordInfoLevel = 0; DWORD dwParmErr = 0; UserInfo *pSamrUserInfo = NULL; UserInfo *pSamrPasswordUserInfo = NULL; DWORD dwSize = 0; DWORD dwSpaceLeft = 0; PIO_CREDS pCreds = NULL; NET_VALIDATION_LEVEL eValidation = NET_VALIDATION_USER_SET; if (!(dwLevel == 0 || dwLevel == 1 || dwLevel == 2 || dwLevel == 3 || dwLevel == 4 || dwLevel == 1003 || dwLevel == 1007 || dwLevel == 1008 || dwLevel == 1011)) { err = ERROR_INVALID_LEVEL; BAIL_ON_WIN_ERROR(err); } BAIL_ON_INVALID_PTR(pwszUsername, err); BAIL_ON_INVALID_PTR(pBuffer, err); status = LwIoGetActiveCreds(NULL, &pCreds); BAIL_ON_NT_STATUS(status); err = NetAllocateSamrUserInfo(NULL, &dwSamrInfoLevel, NULL, dwLevel, pBuffer, pConn, &dwSize, eValidation, &dwParmErr); BAIL_ON_WIN_ERROR(err); dwSpaceLeft = dwSize; dwSize = 0; if (dwSpaceLeft) { status = NetAllocateMemory(OUT_PPVOID(&pSamrUserInfo), dwSpaceLeft); BAIL_ON_NT_STATUS(status); err = NetAllocateSamrUserInfo(&pSamrUserInfo->info21, &dwSamrInfoLevel, &dwSpaceLeft, dwLevel, pBuffer, pConn, &dwSize, eValidation, &dwParmErr); BAIL_ON_WIN_ERROR(err); } status = NetConnectSamr(&pConn, pwszHostname, dwDomainAccess, 0, pCreds); BAIL_ON_NT_STATUS(status); hSamrBinding = pConn->Rpc.Samr.hBinding; status = NetOpenUser(pConn, pwszUsername, dwUserAccess, &hUser, &dwUserRid); BAIL_ON_NT_STATUS(status); /* * Check if there's password to be set (if it's NULL * the function returns ERROR_INVALID_PASSWORD) */ dwSamrPasswordInfoLevel = 26; dwSize = 0; err = NetAllocateSamrUserInfo(NULL, &dwSamrPasswordInfoLevel, NULL, dwLevel, pBuffer, pConn, &dwSize, eValidation, &dwParmErr); if (err == ERROR_SUCCESS) { dwSpaceLeft = dwSize; dwSize = 0; if (dwSpaceLeft) { status = NetAllocateMemory(OUT_PPVOID(&pSamrPasswordUserInfo), dwSpaceLeft); BAIL_ON_NT_STATUS(status); } err = NetAllocateSamrUserInfo(&pSamrPasswordUserInfo->info26, &dwSamrPasswordInfoLevel, &dwSpaceLeft, dwLevel, pBuffer, pConn, &dwSize, eValidation, &dwParmErr); BAIL_ON_WIN_ERROR(err); status = SamrSetUserInfo(hSamrBinding, hUser, dwSamrPasswordInfoLevel, pSamrPasswordUserInfo); BAIL_ON_NT_STATUS(status); } else if (err == ERROR_INVALID_LEVEL || (err == ERROR_INVALID_PASSWORD && dwLevel != 1003)) { /* This error only means we're not going to try set the password. Either it's set to NULL in infolevel where it's optional or called infolevel doesn't support setting password */ err = ERROR_SUCCESS; } else { BAIL_ON_WIN_ERROR(err); } if (dwSamrInfoLevel) { status = SamrSetUserInfo(hSamrBinding, hUser, dwSamrInfoLevel, pSamrUserInfo); BAIL_ON_NT_STATUS(status); } status = SamrClose(hSamrBinding, hUser); BAIL_ON_NT_STATUS(status); cleanup: NetDisconnectSamr(&pConn); if (pdwParmErr) { *pdwParmErr = dwParmErr; } if (pSamrUserInfo) { NetFreeMemory(pSamrUserInfo); } if (pCreds) { LwIoDeleteCreds(pCreds); } if (err == ERROR_SUCCESS && status != STATUS_SUCCESS) { err = LwNtStatusToWin32Error(status); } return err; error: goto cleanup; }
BOOLEAN CreateRpcBinding( PVOID *phBinding, RPC_BINDING_TYPE eBindingType, PCWSTR pwszHostname, PCWSTR pwszBinding, PCREDENTIALS pCredentials ) { PCSTR pszNtlmsspAuth = "ntlmssp"; PCSTR pszSign = "sign"; PCSTR pszSeal = "seal"; BOOLEAN bRet = TRUE; NTSTATUS ntStatus = STATUS_SUCCESS; DWORD dwError = ERROR_SUCCESS; unsigned32 rpcStatus = RPC_S_OK; LSA_BINDING hBinding = NULL; LW_PIO_CREDS pIoCreds = NULL; PWSTR pwszBindingString = NULL; size_t sBindingStringLen = 0; PSTR pszBindingString = NULL; PSTR *ppszOptions = NULL; DWORD iOpt = 0; DWORD i = 0; DWORD dwNumValidOptions = 0; unsigned32 AuthType = 0; unsigned32 ProtectionLevel = 0; SEC_WINNT_AUTH_IDENTITY *pNtlmSspAuthInfo = NULL; PVOID pAuthInfo = NULL; unsigned char *pszUuid = NULL; unsigned char *pszProtSeq = NULL; unsigned char *pszNetworkAddr = NULL; unsigned char *pszEndpoint = NULL; unsigned char *pszOptions = NULL; PSTR pszHostname = NULL; if (phBinding == NULL) { ntStatus = STATUS_INVALID_PARAMETER; BAIL_ON_NT_STATUS(ntStatus); } if (pwszBinding) { dwError = LwAllocateWc16String(&pwszBindingString, pwszBinding); BAIL_ON_WIN_ERROR(dwError); dwError = LwWc16sLen(pwszBindingString, &sBindingStringLen); BAIL_ON_WIN_ERROR(dwError); dwError = LwWc16sToMbs(pwszBindingString, &pszBindingString); BAIL_ON_WIN_ERROR(dwError); ppszOptions = get_string_list(pszBindingString, ':'); if (ppszOptions == NULL) { ntStatus = STATUS_INVALID_PARAMETER; BAIL_ON_NT_STATUS(ntStatus); } /* * Find and identify valid options */ while (ppszOptions[iOpt]) { if (!strcasecmp(pszNtlmsspAuth, ppszOptions[iOpt])) { AuthType = rpc_c_authn_winnt; dwNumValidOptions++; } else if (!strcasecmp(pszSign, ppszOptions[iOpt])) { ProtectionLevel = rpc_c_authn_level_pkt_integrity; dwNumValidOptions++; } else if (!strcasecmp(pszSeal, ppszOptions[iOpt])) { ProtectionLevel = rpc_c_authn_level_pkt_privacy; dwNumValidOptions++; } iOpt++; } } /* * Cut off the options from the binding string so it can * be passed to rpc routines */ if (dwNumValidOptions > 0) { i = sBindingStringLen; while (dwNumValidOptions && pwszBindingString[--i]) { if (pwszBindingString[i] == (WCHAR)':') { dwNumValidOptions--; } } pwszBindingString[i] = (WCHAR)'\0'; pszBindingString[i] = '\0'; } ntStatus = LwIoGetActiveCreds(NULL, &pIoCreds); BAIL_ON_NT_STATUS(ntStatus); if (pwszBindingString) { ntStatus = RpcInitBindingFromBindingString( (handle_t*)&hBinding, pwszBindingString, pIoCreds); } else { switch (eBindingType) { case RPC_LSA_BINDING: ntStatus = LsaInitBindingDefault(&hBinding, pwszHostname, pIoCreds); break; case RPC_SAMR_BINDING: ntStatus = SamrInitBindingDefault(&hBinding, pwszHostname, pIoCreds); break; case RPC_NETLOGON_BINDING: ntStatus = NetrInitBindingDefault(&hBinding, pwszHostname, pIoCreds); break; case RPC_DSSETUP_BINDING: ntStatus = DsrInitBindingDefault(&hBinding, pwszHostname, pIoCreds); break; case RPC_WKSSVC_BINDING: ntStatus = WkssInitBindingDefault(&hBinding, pwszHostname, pIoCreds); break; default: ntStatus = STATUS_NOT_IMPLEMENTED; break; } } BAIL_ON_NT_STATUS(ntStatus); switch (AuthType) { case rpc_c_authn_winnt: dwError = LwAllocateMemory(sizeof(*pNtlmSspAuthInfo), OUT_PPVOID(&pNtlmSspAuthInfo)); BAIL_ON_WIN_ERROR(dwError); if (pCredentials->Ntlm.pwszDomain) { dwError = LwWc16sToMbs(pCredentials->Ntlm.pwszDomain, &pNtlmSspAuthInfo->Domain); BAIL_ON_WIN_ERROR(dwError); pNtlmSspAuthInfo->DomainLength = strlen(pNtlmSspAuthInfo->Domain); } dwError = LwWc16sToMbs(pCredentials->Ntlm.pwszUsername, &pNtlmSspAuthInfo->User); BAIL_ON_WIN_ERROR(dwError); pNtlmSspAuthInfo->UserLength = strlen(pNtlmSspAuthInfo->User); dwError = LwWc16sToMbs(pCredentials->Ntlm.pwszPassword, &pNtlmSspAuthInfo->Password); BAIL_ON_WIN_ERROR(dwError); pNtlmSspAuthInfo->PasswordLength = strlen(pNtlmSspAuthInfo->Password); pAuthInfo = (PVOID)pNtlmSspAuthInfo; break; default: pAuthInfo = NULL; break; } if (pwszHostname) { dwError = LwWc16sToMbs(pwszHostname, &pszHostname); BAIL_ON_WIN_ERROR(dwError); } else { rpc_string_binding_parse((unsigned char*)pszBindingString, &pszUuid, &pszProtSeq, &pszNetworkAddr, &pszEndpoint, &pszOptions, &rpcStatus); if (rpcStatus) { ntStatus = LwRpcStatusToNtStatus(rpcStatus); BAIL_ON_NT_STATUS(ntStatus); } dwError = LwAllocateString((PSTR)pszNetworkAddr, &pszHostname); BAIL_ON_WIN_ERROR(dwError); } if (AuthType) { rpc_binding_set_auth_info(hBinding, (unsigned char*)pszHostname, ProtectionLevel, AuthType, (rpc_auth_identity_handle_t)pAuthInfo, rpc_c_authz_name, /* authz_protocol */ &rpcStatus); if (rpcStatus) { ntStatus = LwRpcStatusToNtStatus(rpcStatus); BAIL_ON_NT_STATUS(ntStatus); } } *phBinding = hBinding; cleanup: if (pIoCreds) { LwIoDeleteCreds(pIoCreds); } LW_SAFE_FREE_MEMORY(pwszBindingString); LW_SAFE_FREE_MEMORY(pszBindingString); LW_SAFE_FREE_MEMORY(pszHostname); rpc_string_free(&pszUuid, &rpcStatus); rpc_string_free(&pszProtSeq, &rpcStatus); rpc_string_free(&pszNetworkAddr, &rpcStatus); rpc_string_free(&pszEndpoint, &rpcStatus); rpc_string_free(&pszOptions, &rpcStatus); if (ppszOptions) { free_string_list(ppszOptions); } if (ntStatus == STATUS_SUCCESS && dwError != ERROR_SUCCESS) { ntStatus = LwWin32ErrorToNtStatus(dwError); } if (ntStatus != STATUS_SUCCESS) { bRet = FALSE; } return bRet; error: *phBinding = NULL; bRet = FALSE; 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; }