Windows NT 4.0 source code leak
You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
 
 
 
 
 
 

1860 lines
45 KiB

/********************************************************************/
/** Copyright(c) 1989 Microsoft Corporation. **/
/********************************************************************/
//***
//
// Filename: srvrhlpr.c
//
// Description: This module will contain code to process specific security
// information requests by the server. This is done because
// the api's required to obtain this information cannot be
// called from kernel mode. The following functionality is
// supported:
//
// 1) Name to Sid Lookup.
// 2) Sid to Name lookup.
// 3) Enumerate Posix offsets of all domains.
// 4) Change password.
// 5) Log an event.
//
// History: August 18,1992. NarenG Created original version.
//
#include <afpsvcp.h>
#include <lm.h>
#include <logonmsv.h> // prototype of I_NetGetDCList
#include <seposix.h>
static PPOLICY_ACCOUNT_DOMAIN_INFO pAccountDomainInfo = NULL;
static PPOLICY_PRIMARY_DOMAIN_INFO pPrimaryDomainInfo = NULL;
static PLSA_TRUST_INFORMATION pTrustedDomainInfo = NULL;
static ULONG ulTrustedDomainCount = 0;
static HANDLE hmutexThreadCount = NULL;
NTSTATUS
AfpNameToSid(
IN LSA_HANDLE hLsa,
IN PAFP_FSD_CMD_PKT pAfpFsdCmd,
OUT PAFP_FSD_CMD_PKT *ppAfpFsdCmdResponse,
OUT LPDWORD pcbResponse
);
NTSTATUS
AfpSidToName(
IN LSA_HANDLE hLsa,
IN PPOLICY_ACCOUNT_DOMAIN_INFO pAccountDomainInfo,
IN PPOLICY_PRIMARY_DOMAIN_INFO pPrimaryDomainInfo,
IN PAFP_FSD_CMD_PKT pAfpFsdCmd,
OUT PAFP_FSD_CMD_PKT *ppAfpFsdCmdResponse,
OUT LPDWORD pcbResponse
);
NTSTATUS
AfpChangePassword(
IN PPOLICY_ACCOUNT_DOMAIN_INFO pAccountDomainInfo,
IN PPOLICY_PRIMARY_DOMAIN_INFO pPrimaryDomainInfo,
IN PLSA_TRUST_INFORMATION pLsaTrustInfo,
IN DWORD dwTrustInfoCount,
IN PAFP_FSD_CMD_PKT pAfpFsdCmd,
OUT PAFP_FSD_CMD_PKT *ppAfpFsdCmdResponse,
OUT LPDWORD pcbResponse
);
NTSTATUS
AfpChangePasswordOnDomain(
IN PAFP_PASSWORD_DESC pPassword,
IN PUNICODE_STRING pDomainName,
IN PSID pDomainSid
);
NTSTATUS
AfpCreateWellknownSids(
OUT AFP_SID_OFFSET pWellKnownSids[]
);
NTSTATUS
AfpInsertSidOffset(
IN PAFP_SID_OFFSET pSidOffset,
IN LPBYTE pbVariableData,
IN PSID pSid,
IN DWORD Offset,
IN AFP_SID_TYPE SidType
);
DWORD
AfpGetDomainInfo(
IN LSA_HANDLE hLsa,
IN OUT PLSA_HANDLE phLsaController,
IN OUT PPOLICY_ACCOUNT_DOMAIN_INFO* ppAccountDomainInfo,
IN OUT PPOLICY_PRIMARY_DOMAIN_INFO* ppPrimaryDomainInfo,
IN OUT PLSA_TRUST_INFORMATION* ppLsaTrustInfo,
IN OUT PULONG pLsaTrustInfoCount
);
DWORD
AfpIOCTLDomainOffsets(
IN LSA_HANDLE hLsa,
IN PPOLICY_ACCOUNT_DOMAIN_INFO pAccountDomainInfo,
IN PPOLICY_PRIMARY_DOMAIN_INFO pPrimaryDomainInfo,
IN PLSA_TRUST_INFORMATION pLsaTrustInfo,
IN DWORD dwTrustInfoCount
);
DWORD
AfpOpenLsa(
IN PUNICODE_STRING pSystem OPTIONAL,
IN OUT PLSA_HANDLE phLsa
);
//**
//
// Call: AfpServerHelper
//
// Returns: NO_ERROR
//
// Description: This is the main function for each helper thread. If sits
// in a loop processing commands from the server. It is terminated
// by command from the server.
//
DWORD
AfpServerHelper(
IN LPVOID fFirstThread
)
{
NTSTATUS ntStatus;
DWORD dwRetCode;
PAFP_FSD_CMD_PKT pAfpFsdCmdResponse;
AFP_FSD_CMD_HEADER AfpCmdHeader;
PAFP_FSD_CMD_PKT pAfpFsdCmd;
PBYTE pOutputBuffer;
DWORD cbOutputBuffer;
PBYTE pInputBuffer;
DWORD cbInputBuffer;
IO_STATUS_BLOCK IoStatus;
BYTE OutputBuffer[MAX_FSD_CMD_SIZE];
HANDLE hFSD = NULL;
LSA_HANDLE hLsa = NULL;
AFP_PRINT( ( "AFPSVC_srvrhlpr: This is a new thread.\n"));
// Open the AFP Server FSD and obtain a handle to it
//
if ( ( dwRetCode = AfpFSDOpen( &hFSD ) ) != NO_ERROR ) {
AfpGlobals.dwSrvrHlprCode = dwRetCode;
AfpLogEvent( AFPLOG_OPEN_FSD, 0, NULL, dwRetCode, EVENTLOG_ERROR_TYPE );
SetEvent( AfpGlobals.heventSrvrHlprThread );
return( dwRetCode );
}
// Open the Local LSA
//
if ( ( dwRetCode = AfpOpenLsa( NULL, &hLsa ) ) != NO_ERROR ) {
AfpFSDClose( hFSD );
AfpGlobals.dwSrvrHlprCode = dwRetCode;
AfpLogEvent( AFPLOG_OPEN_LSA, 0, NULL, dwRetCode, EVENTLOG_ERROR_TYPE );
SetEvent( AfpGlobals.heventSrvrHlprThread );
return( dwRetCode );
}
// If this is the first server helper thread then enumerate and
// IOCTL down the list of domains and their offsets.
//
if ( (BOOL)fFirstThread ) {
LSA_HANDLE hLsaController = NULL;
// Create the event object for mutual exclusion around the thread
// count
//
if ( (hmutexThreadCount = CreateMutex( NULL, FALSE, NULL ) ) == NULL)
return( GetLastError() );
// Get the account, primary and all trusted domain info
//
if ( ( dwRetCode = AfpGetDomainInfo( hLsa,
&hLsaController,
&pAccountDomainInfo,
&pPrimaryDomainInfo,
&pTrustedDomainInfo,
&ulTrustedDomainCount )) != NO_ERROR ){
AFP_PRINT( ( "AFPSVC_srvrhlpr: Get Domain Info failed.\n"));
AfpLogEvent( AFPLOG_CANT_GET_DOMAIN_INFO, 0, NULL,
dwRetCode, EVENTLOG_ERROR_TYPE );
AfpFSDClose( hFSD );
LsaClose( hLsa );
AfpGlobals.dwSrvrHlprCode = dwRetCode;
SetEvent( AfpGlobals.heventSrvrHlprThread );
return( dwRetCode );
}
// IOCTL all the domain offsets
// if hLsaController is NULL, the server is in a WorkGroup, not domain
//
if ( ( dwRetCode = AfpIOCTLDomainOffsets(
hLsaController,
pAccountDomainInfo,
pPrimaryDomainInfo,
pTrustedDomainInfo,
ulTrustedDomainCount ) ) != NO_ERROR ) {
AFP_PRINT( ( "AFPSVC_srvrhlpr: Ioctl Domain Offsets failed.\n"));
AfpLogEvent( AFPLOG_CANT_INIT_DOMAIN_INFO, 0, NULL,
dwRetCode, EVENTLOG_ERROR_TYPE );
// First clean up
//
AfpFSDClose( hFSD );
// If the local machine is not a controller
//
if ( (hLsaController != NULL) && (hLsa != hLsaController) )
LsaClose( hLsaController );
LsaClose( hLsa );
if ( pAccountDomainInfo != NULL )
LsaFreeMemory( pAccountDomainInfo );
if ( pPrimaryDomainInfo != NULL )
LsaFreeMemory( pPrimaryDomainInfo );
if ( pTrustedDomainInfo != NULL )
LsaFreeMemory( pTrustedDomainInfo );
AfpGlobals.dwSrvrHlprCode = dwRetCode;
SetEvent( AfpGlobals.heventSrvrHlprThread );
return( dwRetCode );
}
// If the local machine is not a controller, then close the handle
// since we have all the information we need.
//
if ( (hLsaController != NULL) && (hLsa != hLsaController) )
LsaClose( hLsaController );
}
// OK everything initialize OK. Tell parent (init) thread that it may
// continue.
//
AfpGlobals.dwSrvrHlprCode = dwRetCode;
SetEvent( AfpGlobals.heventSrvrHlprThread );
WaitForSingleObject( hmutexThreadCount, INFINITE );
AfpGlobals.nThreadCount++;
ReleaseMutex( hmutexThreadCount );
pOutputBuffer = OutputBuffer;
cbOutputBuffer = sizeof( OutputBuffer );
pAfpFsdCmd = (PAFP_FSD_CMD_PKT)pOutputBuffer;
pInputBuffer = NULL;
cbInputBuffer = 0;
pAfpFsdCmdResponse = (PAFP_FSD_CMD_PKT)NULL;
while( TRUE ) {
AFP_PRINT( ( "AFPSVC_srvrhlpr: Issuing FSCTL \n"));
// IOCTL the FSD
//
ntStatus = NtFsControlFile( hFSD,
NULL,
NULL,
NULL,
&IoStatus,
OP_GET_FSD_COMMAND,
pInputBuffer,
cbInputBuffer,
pOutputBuffer,
cbOutputBuffer
);
if (!NT_SUCCESS(ntStatus))
AFP_PRINT(("AFPSVC_srvrhlpr: NtFsControlFile Returned %lx\n",
ntStatus));
ASSERT( NT_SUCCESS( ntStatus ));
// Free previous call's input buffer
//
if ( pAfpFsdCmdResponse != NULL )
LocalFree( pAfpFsdCmdResponse );
// Process the command
//
switch( pAfpFsdCmd->Header.FsdCommand ) {
case AFP_FSD_CMD_NAME_TO_SID:
AFP_PRINT( ( "AFPSVC_srvrhlpr: Processing Name to Sid request\n"));
ntStatus = AfpNameToSid( hLsa,
pAfpFsdCmd,
&pAfpFsdCmdResponse,
&cbInputBuffer );
if ( NT_SUCCESS( ntStatus ))
pInputBuffer = (PBYTE)pAfpFsdCmdResponse;
else {
pInputBuffer = (PBYTE)&AfpCmdHeader;
cbInputBuffer = sizeof( AFP_FSD_CMD_HEADER );
pAfpFsdCmdResponse = NULL;
}
break;
case AFP_FSD_CMD_SID_TO_NAME:
AFP_PRINT( ( "AFPSVC_srvrhlpr: Processing Sid to Name request\n"));
ntStatus = AfpSidToName( hLsa,
pAccountDomainInfo,
pPrimaryDomainInfo,
pAfpFsdCmd,
&pAfpFsdCmdResponse,
&cbInputBuffer );
if ( NT_SUCCESS( ntStatus ))
pInputBuffer = (PBYTE)pAfpFsdCmdResponse;
else {
pInputBuffer = (PBYTE)&AfpCmdHeader;
cbInputBuffer = sizeof( AFP_FSD_CMD_HEADER );
pAfpFsdCmdResponse = NULL;
}
break;
case AFP_FSD_CMD_CHANGE_PASSWORD:
AFP_PRINT(("AFPSVC_srvrhlpr:Processing change password request\n"));
ntStatus = AfpChangePassword(
pAccountDomainInfo,
pPrimaryDomainInfo,
pTrustedDomainInfo,
ulTrustedDomainCount,
pAfpFsdCmd,
&pAfpFsdCmdResponse,
&cbInputBuffer );
pInputBuffer = (PBYTE)&AfpCmdHeader;
cbInputBuffer = sizeof( AFP_FSD_CMD_HEADER );
pAfpFsdCmdResponse = NULL;
break;
case AFP_FSD_CMD_LOG_EVENT:
AFP_PRINT(("AFPSVC_srvrhlpr:Processing event log request\n"));
AfpLogServerEvent(pAfpFsdCmd);
pInputBuffer = (PBYTE)&AfpCmdHeader;
cbInputBuffer = sizeof( AFP_FSD_CMD_HEADER );
pAfpFsdCmdResponse = NULL;
ntStatus = STATUS_SUCCESS;
break;
case AFP_FSD_CMD_TERMINATE_THREAD:
AFP_PRINT(("AFPSVC_srvrhlpr:Terminating thread\n"));
// Do clean up
//
LsaClose( hLsa );
AfpFSDClose( hFSD );
WaitForSingleObject( hmutexThreadCount, INFINITE );
AfpGlobals.nThreadCount --;
// This is the last thread so clean up all the global stuff.
//
if ( AfpGlobals.nThreadCount == 0 ) {
AFP_PRINT( ( "AFPSVC_srvrhlpr: Freeing global memory\n"));
if ( pAccountDomainInfo != NULL )
LsaFreeMemory( pAccountDomainInfo );
if ( pPrimaryDomainInfo != NULL )
LsaFreeMemory( pPrimaryDomainInfo );
if ( pTrustedDomainInfo != NULL )
LsaFreeMemory( pTrustedDomainInfo );
SetEvent(AfpGlobals.heventSrvrHlprThreadTerminate);
}
ReleaseMutex( hmutexThreadCount );
return( NO_ERROR );
break;
default:
ntStatus = STATUS_NOT_SUPPORTED;
pInputBuffer = (PBYTE)&AfpCmdHeader;
cbInputBuffer = sizeof( AFP_FSD_CMD_HEADER );
pAfpFsdCmdResponse = NULL;
break;
}
CopyMemory( pInputBuffer, pAfpFsdCmd, sizeof( AFP_FSD_CMD_HEADER ) );
((PAFP_FSD_CMD_HEADER)pInputBuffer)->ntStatus = ntStatus;
AFP_PRINT( ( "AFPSVC_srvrhlpr: Result of call =0x%x\n", ntStatus));
}
return( NO_ERROR );
}
//**
//
// Call: AfpGetDomainInfo
//
// Returns: Returns from LsaEnumerateTrustedDomains,
// LsaQueryInformationPolicy, I_NetGetDCList and AfpOpenLsa
//
// Description: Will retrieve information regarding the account, primary and
// trusted domains.
//
DWORD
AfpGetDomainInfo(
IN LSA_HANDLE hLsa,
IN OUT PLSA_HANDLE phLsaController,
IN OUT PPOLICY_ACCOUNT_DOMAIN_INFO* ppAccountDomainInfo,
IN OUT PPOLICY_PRIMARY_DOMAIN_INFO* ppPrimaryDomainInfo,
IN OUT PLSA_TRUST_INFORMATION* ppLsaTrustInfo,
IN OUT PULONG pLsaTrustInfoCount
)
{
DWORD dwRetCode = 0;
NTSTATUS ntStatus = STATUS_SUCCESS;
LSA_ENUMERATION_HANDLE hLsaEnum = 0;
// This is not a loop.
//
do {
*phLsaController = NULL;
*ppAccountDomainInfo = NULL;
*ppPrimaryDomainInfo = NULL;
*ppLsaTrustInfo = NULL;
*pLsaTrustInfoCount = 0;
// Get the account domain
//
ntStatus = LsaQueryInformationPolicy(
hLsa,
PolicyAccountDomainInformation,
(PVOID*)ppAccountDomainInfo
);
if ( !NT_SUCCESS( ntStatus ) )
break;
// Get the primary domain
//
ntStatus = LsaQueryInformationPolicy(
hLsa,
PolicyPrimaryDomainInformation,
(PVOID*)ppPrimaryDomainInfo
);
if ( !NT_SUCCESS( ntStatus ) )
break;
// If this machine is part of a domain (not standalone), then we need
// to get a list of trusted domains. Note that a workstation and a
// member server can both join a domain, but they don't have to.
//
if ( (*ppPrimaryDomainInfo)->Sid != NULL ){
// To obtain a list of trusted domains, we need to first open
// the LSA on a domain controller. If we are an PDC/BDC
// (NtProductLanManNt) then the local LSA will do, otherwise we need
// to search for domain controllers (NtProductServer, NtProductWinNt).
//
if ( AfpGlobals.NtProductType != NtProductLanManNt ) {
ULONG ulCount;
ULONG ControllerCount = 0;
PUNICODE_STRING ControllerNames = NULL;
PUNICODE_STRING DomainController = NULL;
LPWSTR DomainName;
DomainName = (LPWSTR)LocalAlloc(
LPTR,
(*ppPrimaryDomainInfo)->Name.Length+sizeof(WCHAR));
if ( DomainName == NULL ) {
dwRetCode = ERROR_NOT_ENOUGH_MEMORY;
break;
}
CopyMemory( DomainName,
(*ppPrimaryDomainInfo)->Name.Buffer,
(*ppPrimaryDomainInfo)->Name.Length );
dwRetCode = I_NetGetDCList( NULL,
(LPWSTR)DomainName,
&ControllerCount,
&ControllerNames );
LocalFree( DomainName );
if ( dwRetCode != NO_ERROR )
{
dwRetCode = ERROR_CANT_ACCESS_DOMAIN_INFO;
break;
}
for( ulCount = 0, DomainController = ControllerNames;
ulCount < ControllerCount;
ulCount++, DomainController++ ) {
if ( DomainController->Length == 0 )
continue;
dwRetCode = AfpOpenLsa( DomainController, phLsaController );
if ( dwRetCode == NO_ERROR )
break;
}
NetApiBufferFree( ControllerNames );
if ( dwRetCode != NO_ERROR )
break;
}
else {
*phLsaController = hLsa;
// Since the local server is an PDC/BDC, it's account
// domain is the same as it's primary domain so set the
// account domain info to NULL
//
LsaFreeMemory( *ppAccountDomainInfo );
*ppAccountDomainInfo = NULL;
}
// Enumerate all the trusted domains.
//
ntStatus = LsaEnumerateTrustedDomains(
*phLsaController,
&hLsaEnum,
(PVOID*)ppLsaTrustInfo,
(ULONG)-1,
pLsaTrustInfoCount
);
if ( !NT_ERROR( ntStatus ) )
ntStatus = STATUS_SUCCESS;
}
else {
LsaFreeMemory( *ppPrimaryDomainInfo );
*ppPrimaryDomainInfo = NULL;
}
} while( FALSE );
if ( !NT_SUCCESS( ntStatus ) || ( dwRetCode != NO_ERROR ) ) {
if ( *ppAccountDomainInfo != NULL )
LsaFreeMemory( *ppAccountDomainInfo );
if ( *ppPrimaryDomainInfo != NULL )
LsaFreeMemory( *ppPrimaryDomainInfo );
if ( *ppLsaTrustInfo != NULL )
LsaFreeMemory( *ppLsaTrustInfo );
if ( *phLsaController != NULL )
LsaClose( *phLsaController );
if ( dwRetCode == NO_ERROR )
dwRetCode = RtlNtStatusToDosError( ntStatus );
}
return( dwRetCode );
}
//**
//
// Call: AfpOpenLsa
//
// Returns: Returns from LsaOpenPolicy.
//
// Description: The LSA will be opened.
//
DWORD
AfpOpenLsa(
IN PUNICODE_STRING pSystem OPTIONAL,
IN OUT PLSA_HANDLE phLsa
)
{
SECURITY_QUALITY_OF_SERVICE QOS;
OBJECT_ATTRIBUTES ObjectAttributes;
NTSTATUS ntStatus;
// Open the LSA and obtain a handle to it.
//
QOS.Length = sizeof( QOS );
QOS.ImpersonationLevel = SecurityImpersonation;
QOS.ContextTrackingMode = SECURITY_DYNAMIC_TRACKING;
QOS.EffectiveOnly = FALSE;
InitializeObjectAttributes( &ObjectAttributes,
NULL,
0L,
NULL,
NULL );
ObjectAttributes.SecurityQualityOfService = &QOS;
ntStatus = LsaOpenPolicy( pSystem,
&ObjectAttributes,
POLICY_VIEW_LOCAL_INFORMATION |
POLICY_LOOKUP_NAMES,
phLsa );
if ( !NT_SUCCESS( ntStatus ))
return( RtlNtStatusToDosError( ntStatus ) );
return( NO_ERROR );
}
//
// Call: AfpNameToSid
//
// Returns: NT_SUCCESS
// error return codes from LSA apis.
//
// Description: Will use LSA API's to translate a name to a SID. On a
// successful return, the pSid should be freed using LocalFree.
//
NTSTATUS
AfpNameToSid(
IN LSA_HANDLE hLsa,
IN PAFP_FSD_CMD_PKT pAfpFsdCmd,
OUT PAFP_FSD_CMD_PKT *ppAfpFsdCmdResponse,
OUT LPDWORD pcbResponse
)
{
NTSTATUS ntStatus;
UNICODE_STRING Name;
PLSA_REFERENCED_DOMAIN_LIST pDomainList;
PLSA_TRANSLATED_SID pSids;
UCHAR AuthCount;
PSID pDomainSid;
PSID pSid;
// This do - while(FALSE) loop facilitates a single exit and clean-up point.
//
do {
*ppAfpFsdCmdResponse = NULL;
pDomainList = NULL;
pSids = NULL;
RtlInitUnicodeString( &Name, (LPWSTR)(pAfpFsdCmd->Data.Name) );
ntStatus = LsaLookupNames( hLsa, 1, &Name, &pDomainList, &pSids );
if ( !NT_SUCCESS( ntStatus ) )
return( ntStatus );
if ( pSids->Use == SidTypeDeletedAccount ){
ntStatus = STATUS_NO_SUCH_USER;
break;
}
if ( ( pDomainList->Entries == 0 ) ||
( pSids->Use == SidTypeDomain ) ||
( pSids->Use == SidTypeInvalid ) ||
( pSids->Use == SidTypeUnknown ) ||
( pSids->DomainIndex == -1 )) {
ntStatus = STATUS_NONE_MAPPED;
break;
}
pDomainSid = pDomainList->Domains[pSids->DomainIndex].Sid;
AuthCount = *RtlSubAuthorityCountSid( pDomainSid ) + 1;
*pcbResponse = sizeof(AFP_FSD_CMD_PKT)+RtlLengthRequiredSid(AuthCount);
*ppAfpFsdCmdResponse = (PAFP_FSD_CMD_PKT)LocalAlloc(LPTR,*pcbResponse);
if ( *ppAfpFsdCmdResponse == NULL ) {
ntStatus = STATUS_NO_MEMORY ;
break;
}
pSid = (*ppAfpFsdCmdResponse)->Data.Sid;
// Copy the Domain Sid.
//
RtlCopySid( RtlLengthRequiredSid(AuthCount), pSid, pDomainSid );
// Append the Relative Id.
//
*RtlSubAuthorityCountSid( pSid ) += 1;
*RtlSubAuthoritySid( pSid, AuthCount - 1) = pSids->RelativeId;
} while( FALSE );
if ( (!NT_SUCCESS( ntStatus )) && ( *ppAfpFsdCmdResponse != NULL ) )
LocalFree( *ppAfpFsdCmdResponse );
if ( pSids != NULL )
LsaFreeMemory( pSids );
if ( pDomainList != NULL )
LsaFreeMemory( pDomainList );
return( ntStatus );
}
//**
//
// Call: AfpSidToName
//
// Returns: NT_SUCCESS
// error return codes from LSA apis.
//
// Description: Given a SID, this routine will find the corresponding
// UNICODE name.
//
NTSTATUS
AfpSidToName(
IN LSA_HANDLE hLsa,
IN PPOLICY_ACCOUNT_DOMAIN_INFO pAccountDomainInfo,
IN PPOLICY_PRIMARY_DOMAIN_INFO pPrimaryDomainInfo,
IN PAFP_FSD_CMD_PKT pAfpFsdCmd,
OUT PAFP_FSD_CMD_PKT *ppAfpFsdCmdResponse,
OUT LPDWORD pcbResponse
)
{
NTSTATUS ntStatus;
PLSA_REFERENCED_DOMAIN_LIST pDomainList = NULL;
PLSA_TRANSLATED_NAME pNames = NULL;
PSID pSid = (PSID)&(pAfpFsdCmd->Data.Sid);
WCHAR * pWchar;
BOOL fDoNotCopyDomainName = TRUE;
DWORD cbResponse;
DWORD dwUse;
SID AfpBuiltInSid = { 1, 1, SECURITY_NT_AUTHORITY,
SECURITY_BUILTIN_DOMAIN_RID };
do {
*ppAfpFsdCmdResponse = NULL;
ntStatus = LsaLookupSids( hLsa, 1, &pSid, &pDomainList, &pNames );
if ( !NT_SUCCESS( ntStatus ) ) {
if ( ntStatus == STATUS_NONE_MAPPED ) {
dwUse = SidTypeUnknown;
ntStatus = STATUS_SUCCESS;
}
else
break;
}
else
dwUse = pNames->Use;
cbResponse = sizeof( AFP_FSD_CMD_PKT );
switch( dwUse ){
case SidTypeInvalid:
cbResponse += ((wcslen(AfpGlobals.wchInvalid)+1) * sizeof(WCHAR));
break;
case SidTypeDeletedAccount:
cbResponse += ((wcslen(AfpGlobals.wchDeleted)+1) * sizeof(WCHAR));
break;
case SidTypeUnknown:
cbResponse += ((wcslen(AfpGlobals.wchUnknown)+1) * sizeof(WCHAR));
break;
case SidTypeWellKnownGroup:
cbResponse += ( pNames->Name.Length + sizeof(WCHAR) );
break;
case SidTypeDomain:
cbResponse += ( pDomainList->Domains->Name.Length + sizeof(WCHAR) );
break;
default:
if ((pNames->DomainIndex == -1) || (pNames->Name.Buffer == NULL)){
ntStatus = STATUS_NONE_MAPPED;
break;
}
// Do not copy the domain name if the name is either a well known
// group or if the SID belongs to the ACCOUNT or BUILTIN domains.
// Note, the pAccountDomainInfo is NULL is this is an advanced
// server, in that case we check to see if the domain name is
// the primary domain name.
//
if (( RtlEqualSid( &AfpBuiltInSid, pDomainList->Domains->Sid )) ||
(( pAccountDomainInfo != NULL ) &&
(RtlEqualUnicodeString( &(pAccountDomainInfo->DomainName),
&(pDomainList->Domains->Name),
TRUE ))) ||
((pAccountDomainInfo == NULL) && (pPrimaryDomainInfo != NULL) &&
(RtlEqualUnicodeString( &(pPrimaryDomainInfo->Name),
&(pDomainList->Domains->Name),
TRUE )))){
cbResponse += ( pNames->Name.Length + sizeof(WCHAR) );
fDoNotCopyDomainName = TRUE;
}
else {
fDoNotCopyDomainName = FALSE;
cbResponse += ( pDomainList->Domains->Name.Length +
sizeof(TEXT('\\')) +
pNames->Name.Length +
sizeof(WCHAR) );
}
}
if ( !NT_SUCCESS( ntStatus ) )
break;
*pcbResponse = cbResponse;
*ppAfpFsdCmdResponse = (PAFP_FSD_CMD_PKT)LocalAlloc(LPTR,cbResponse);
if ( *ppAfpFsdCmdResponse == NULL ){
ntStatus = STATUS_NO_MEMORY ;
break;
}
pWchar = (WCHAR*)((*ppAfpFsdCmdResponse)->Data.Name);
switch( dwUse ){
case SidTypeInvalid:
wcscpy( pWchar, AfpGlobals.wchInvalid );
break;
case SidTypeDeletedAccount:
wcscpy( pWchar, AfpGlobals.wchDeleted );
break;
case SidTypeUnknown:
wcscpy( pWchar, AfpGlobals.wchUnknown );
break;
case SidTypeWellKnownGroup:
CopyMemory( pWchar, pNames->Name.Buffer, pNames->Name.Length );
break;
case SidTypeDomain:
CopyMemory( pWchar,
pDomainList->Domains->Name.Buffer,
pDomainList->Domains->Name.Length );
break;
default:
if ( !fDoNotCopyDomainName ) {
CopyMemory( pWchar,
pDomainList->Domains->Name.Buffer,
pDomainList->Domains->Name.Length );
pWchar += wcslen( pWchar );
CopyMemory( pWchar, TEXT("\\"), sizeof(TEXT("\\")) );
pWchar += wcslen( pWchar );
}
CopyMemory( pWchar, pNames->Name.Buffer, pNames->Name.Length );
}
} while( FALSE );
if ( (!NT_SUCCESS( ntStatus )) && ( *ppAfpFsdCmdResponse != NULL ) )
LocalFree( *ppAfpFsdCmdResponse );
if ( pNames != NULL )
LsaFreeMemory( pNames );
if ( pDomainList != NULL )
LsaFreeMemory( pDomainList );
return( ntStatus );
}
//**
//
// Call: AfpChangePassword
//
// Returns: NT_SUCCESS
// error return codes from LSA apis.
//
// Description: Given the AFP_PASSWORD_DESC data structure, this procedure
// will change the password of a given user.
// If the passwords are supplied in clear text, then it calculate
// the OWF's (encrypt OWF = One Way Function) them.
// If the domain name that the user
// belongs to is not supplied then a list of domains are tried
// in sequence. The sequence is 1) ACCOUNT domain
// 2) PRIMARY domain
// 3) All trusted domains.
//
NTSTATUS
AfpChangePassword(
IN PPOLICY_ACCOUNT_DOMAIN_INFO pAccountDomainInfo,
IN PPOLICY_PRIMARY_DOMAIN_INFO pPrimaryDomainInfo,
IN PLSA_TRUST_INFORMATION pTrustedDomainInfo,
IN DWORD dwTrustedDomainCount,
IN PAFP_FSD_CMD_PKT pAfpFsdCmd,
OUT PAFP_FSD_CMD_PKT *ppAfpFsdCmdResponse,
OUT LPDWORD pcbResponse
)
{
PAFP_PASSWORD_DESC pPassword = &(pAfpFsdCmd->Data.Password);
NTSTATUS ntStatus;
DWORD cDomains;
PUNICODE_STRING pDomainName;
PSID pDomainSid;
UNICODE_STRING TargetDomainName;
// Was the domain on which the account name exists specified ??
// If not we need to try a list of domains.
//
if ( pPassword->DomainName[0] != TEXT('\0') ) {
RtlInitUnicodeString(&TargetDomainName, (LPWSTR)pPassword->DomainName);
ntStatus = STATUS_NO_SUCH_DOMAIN;
}
for( cDomains = 0; cDomains < dwTrustedDomainCount+2; cDomains++ ) {
if ( cDomains == 0 ) {
// If this is an advanced server then there is no account domain
//
if ( pAccountDomainInfo == NULL )
continue;
else {
pDomainName = &(pAccountDomainInfo->DomainName);
pDomainSid = pAccountDomainInfo->DomainSid;
}
}
if ( cDomains == 1 ) {
// If this machine does not belong to a domain
//
if ( pPrimaryDomainInfo == NULL ) {
return( STATUS_NO_SUCH_USER );
}
pDomainName = &(pPrimaryDomainInfo->Name);
pDomainSid = pPrimaryDomainInfo->Sid;
}
if ( cDomains > 1 ) {
pDomainName = &((pTrustedDomainInfo+(cDomains-2))->Name);
pDomainSid = (pTrustedDomainInfo+(cDomains-2))->Sid;
}
// If a domain name was supplied, we make sure that it is a
// valid domain and we need the Sid
//
if ( pPassword->DomainName[0] != TEXT('\0') ) {
if ( RtlEqualUnicodeString(pDomainName, &TargetDomainName, TRUE)) {
// If it is the account domain then send NULL instead
//
if ( cDomains == 0 )
pDomainName = NULL;
ntStatus = AfpChangePasswordOnDomain(
pPassword,
pDomainName,
pDomainSid );
break;
}
}
else {
// If it is the account domain then send NULL instead
//
if ( cDomains == 0 )
pDomainName = NULL;
// Otherwise we try all the domains
//
ntStatus = AfpChangePasswordOnDomain(
pPassword,
pDomainName,
pDomainSid );
if ( ( ntStatus == STATUS_NONE_MAPPED ) ||
( ntStatus == STATUS_NO_SUCH_USER ) )
continue;
else
break;
}
}
return( ntStatus );
}
//**
//
// Call: AfpChangePasswordOnDomain
//
// Returns: NT_SUCCESS
// STATUS_NONE_MAPPED - If the user account does not
// exist in the specified domain.
// error return codes from LSA apis.
//
// Description: This procedure will try to change the user's password on a
// specified domain. It is assumed that this procedure will be
// called with either the pDomainName pointing to the domain, or
// the pPassword->DomainName field containing the domain.
//
NTSTATUS
AfpChangePasswordOnDomain(
IN PAFP_PASSWORD_DESC pPassword,
IN PUNICODE_STRING pDomainName,
IN PSID pDomainSid
)
{
LPBYTE DCName = (LPBYTE)NULL;
SAM_HANDLE hServer = (SAM_HANDLE)NULL;
SAM_HANDLE hDomain = (SAM_HANDLE)NULL;
SAM_HANDLE hUser = (SAM_HANDLE)NULL;
PULONG pUserId = (PULONG)NULL;
PSID_NAME_USE pUse = (PSID_NAME_USE)NULL;
OBJECT_ATTRIBUTES ObjectAttributes;
UNICODE_STRING UserName;
SECURITY_QUALITY_OF_SERVICE QOS;
PPOLICY_ACCOUNT_DOMAIN_INFO pDomainInfo = NULL;
NTSTATUS ntStatus;
UNICODE_STRING PDCServerName;
PUNICODE_STRING pPDCServerName = &PDCServerName;
PDOMAIN_PASSWORD_INFORMATION pPasswordInfo = NULL;
BYTE EncryptedPassword[LM_OWF_PASSWORD_LENGTH];
WCHAR wchDomain[DNLEN+1];
PUSER_INFO_1 pUserInfo = NULL;
InitializeObjectAttributes( &ObjectAttributes,
NULL,
0L,
NULL,
NULL );
QOS.Length = sizeof( QOS );
QOS.ImpersonationLevel = SecurityImpersonation;
QOS.ContextTrackingMode = SECURITY_DYNAMIC_TRACKING;
QOS.EffectiveOnly = FALSE;
ObjectAttributes.SecurityQualityOfService = &QOS;
// If the domain was not the account domain then we try to get the
// primary domain controller for the domain.
//
if ( pDomainName != NULL ) {
ZeroMemory( wchDomain, sizeof( wchDomain ) );
CopyMemory( wchDomain, pDomainName->Buffer, pDomainName->Length );
// Get the PDC for the domain if this is not the account domain
//
if ( NetGetDCName( NULL, wchDomain, &DCName ))
return( STATUS_CANT_ACCESS_DOMAIN_INFO );
RtlInitUnicodeString( pPDCServerName, (PCWSTR)DCName );
}
else
pPDCServerName = NULL;
do {
// Connect to the PDC of that domain
//
ntStatus = SamConnect( pPDCServerName,
&hServer,
SAM_SERVER_EXECUTE,
&ObjectAttributes
);
if ( !NT_SUCCESS( ntStatus ))
break;
// Get Sid of Domain and open the domain
//
ntStatus = SamOpenDomain(
hServer,
DOMAIN_EXECUTE,
pDomainSid,
&hDomain
);
if ( !NT_SUCCESS( ntStatus ))
break;
// Get this user's ID
//
RtlInitUnicodeString( &UserName, pPassword->UserName );
ntStatus = SamLookupNamesInDomain(
hDomain,
1,
&UserName,
&pUserId,
&pUse
);
if ( !NT_SUCCESS( ntStatus ))
break;
// Open the user account for this user
//
ntStatus = SamOpenUser( hDomain,
USER_EXECUTE | USER_READ,
*pUserId,
&hUser
);
if ( !NT_SUCCESS( ntStatus ))
break;
// First get the minimum password length requred
//
ntStatus = SamQueryInformationDomain(
hDomain,
DomainPasswordInformation,
&pPasswordInfo
);
if ( !NT_SUCCESS( ntStatus ) )
break;
if ( NetUserGetInfo( (LPWSTR)DCName,
pPassword->UserName,
1,
(LPBYTE*)&pUserInfo ) == NO_ERROR ){
if ( ( pUserInfo->usri1_flags & UF_PASSWD_CANT_CHANGE ) ||
( pUserInfo->usri1_flags & UF_LOCKOUT ) )
{
ntStatus = STATUS_PASSWORD_RESTRICTION;
break;
}
else if ( pUserInfo->usri1_flags & UF_ACCOUNTDISABLE )
{
ntStatus = STATUS_ACCOUNT_DISABLED;
break;
}
}
else {
ntStatus = STATUS_PASSWORD_RESTRICTION;
break;
}
// First we check to see if the passwords passed are in cleartext.
// If they are, we need to calculate the OWF's for them.
// (OWF = "One Way Function")
//
if ( pPassword->IsClearText ) {
// First check to see if the new password is long enough
//
if ( strlen( pPassword->NewPassword )
< pPasswordInfo->MinPasswordLength ) {
ntStatus = STATUS_PWD_TOO_SHORT;
break;
}
ZeroMemory( EncryptedPassword, sizeof( EncryptedPassword ) );
// Do OWF encryption
//
ntStatus = RtlCalculateLmOwfPassword(
(PLM_PASSWORD)(pPassword->OldPassword),
(PLM_OWF_PASSWORD)EncryptedPassword
);
if ( !NT_SUCCESS( ntStatus ) )
break;
CopyMemory( pPassword->OldPassword,
EncryptedPassword,
LM_OWF_PASSWORD_LENGTH);
ZeroMemory( EncryptedPassword, sizeof( EncryptedPassword ) );
ntStatus = RtlCalculateLmOwfPassword(
(PLM_PASSWORD)(pPassword->NewPassword),
(PLM_OWF_PASSWORD)EncryptedPassword
);
if ( !NT_SUCCESS( ntStatus ) )
break;
CopyMemory( pPassword->NewPassword,
EncryptedPassword,
LM_OWF_PASSWORD_LENGTH);
}
else {
if (pPassword->bPasswordLength < pPasswordInfo->MinPasswordLength){
ntStatus = STATUS_PWD_TOO_SHORT;
break;
}
}
// Change the password for this user
//
ntStatus = SamiChangePasswordUser(
hUser,
TRUE,
(PLM_OWF_PASSWORD)(pPassword->OldPassword),
(PLM_OWF_PASSWORD)(pPassword->NewPassword),
FALSE,
NULL,
NULL
);
} while( FALSE );
if ( pUserInfo != NULL )
NetApiBufferFree( pUserInfo );
if ( hServer != (SAM_HANDLE)NULL )
SamCloseHandle( hServer );
if ( hDomain != (SAM_HANDLE)NULL )
SamCloseHandle( hDomain );
if ( hUser != (SAM_HANDLE)NULL )
SamCloseHandle( hUser );
if ( pDomainInfo != NULL )
LsaFreeMemory( pDomainInfo );
if ( DCName != NULL )
NetApiBufferFree( DCName );
if ( pUserId != (PULONG)NULL )
SamFreeMemory( pUserId );
if ( pUse != (PSID_NAME_USE)NULL )
SamFreeMemory( pUse );
if ( pPasswordInfo != (PDOMAIN_PASSWORD_INFORMATION)NULL )
SamFreeMemory( pPasswordInfo );
return( ntStatus );
}
//**
//
// Call: AfpIOCTLDomainOffsets
//
// Returns: NT_SUCCESS
// error return codes from LSA apis.
//
// Description: Will IOCTL a list of SIDs and corresponding POSIX offsets
// of all trusted domains and other well known domains.
//
//
DWORD
AfpIOCTLDomainOffsets(
IN LSA_HANDLE hLsa,
IN PPOLICY_ACCOUNT_DOMAIN_INFO pAccountDomainInfo,
IN PPOLICY_PRIMARY_DOMAIN_INFO pPrimaryDomainInfo,
IN PLSA_TRUST_INFORMATION pLsaTrustInfo,
IN DWORD dwTrustInfoCount
)
{
NTSTATUS ntStatus;
PLSA_TRUST_INFORMATION pLsaTrustInfoIter;
LSA_HANDLE hLsaDomain;
PTRUSTED_POSIX_OFFSET_INFO pPosixOffset;
PAFP_SID_OFFSET pSidOffset;
ULONG cbSids;
PBYTE pbVariableData;
AFP_SID_OFFSET pWellKnownSids[20];
DWORD dwIndex;
DWORD dwCount;
AFP_REQUEST_PACKET AfpRequestPkt;
PAFP_SID_OFFSET_DESC pAfpSidOffsets = NULL;
DWORD cbSidOffsets;
DWORD dwRetCode;
// Null this array out.
//
ZeroMemory( pWellKnownSids, sizeof(AFP_SID_OFFSET)*20 );
// This is a dummy loop used only so that the break statement may
// be used to localize all the clean up in one place.
//
do {
// Create all the well known SIDs
//
ntStatus = AfpCreateWellknownSids( pWellKnownSids );
if ( !NT_SUCCESS( ntStatus ) )
break;
// Add the size of the all the well known SIDS
//
for( dwCount = 0, cbSids = 0;
pWellKnownSids[dwCount].pSid != (PBYTE)NULL;
dwCount++ )
cbSids += RtlLengthSid( (PSID)(pWellKnownSids[dwCount].pSid) );
// Insert the SID of the Account domain if is is not an advanced server
//
if ( pAccountDomainInfo != NULL ) {
cbSids += RtlLengthSid( pAccountDomainInfo->DomainSid );
dwCount++;
}
// Add the primary and trusted domain Sids only if this machine
// is a member of a domain.
//
if ( pPrimaryDomainInfo != NULL ) {
cbSids += RtlLengthSid( pPrimaryDomainInfo->Sid );
dwCount++;
// Run through all the SIDs of the trusted domains to calculate the
// amount of memory needed to store all the Sid/Offset pairs
//
for ( dwIndex = 0, pLsaTrustInfoIter = pLsaTrustInfo;
dwIndex < dwTrustInfoCount;
dwIndex++, dwCount++ )
cbSids += RtlLengthSid( (pLsaTrustInfoIter++)->Sid );
}
// OK, now allocate space for all these SIDS plus their offsets
//
cbSidOffsets = (dwCount * sizeof(AFP_SID_OFFSET)) + cbSids +
AFP_FIELD_SIZE( AFP_SID_OFFSET_DESC,CountOfSidOffsets);
pAfpSidOffsets = (PAFP_SID_OFFSET_DESC)LocalAlloc( LPTR, cbSidOffsets );
if ( pAfpSidOffsets == NULL ){
ntStatus = STATUS_NO_MEMORY ;
break;
}
// First insert all the well known SIDS
//
for( dwIndex = 0,
pAfpSidOffsets->CountOfSidOffsets = dwCount,
pSidOffset = pAfpSidOffsets->SidOffsetPairs,
pbVariableData = (LPBYTE)pAfpSidOffsets + cbSidOffsets;
pWellKnownSids[dwIndex].pSid != (PBYTE)NULL;
dwIndex++ ) {
pbVariableData-=RtlLengthSid((PSID)(pWellKnownSids[dwIndex].pSid));
ntStatus = AfpInsertSidOffset(
pSidOffset++,
pbVariableData,
(PSID)(pWellKnownSids[dwIndex].pSid),
pWellKnownSids[dwIndex].Offset,
pWellKnownSids[dwIndex].SidType );
if ( !NT_SUCCESS( ntStatus ) )
break;
}
if ( !NT_SUCCESS( ntStatus ) )
break;
// Now insert the Account domain's SID/OFFSET pair if there is one
//
if ( pAccountDomainInfo != NULL ) {
pbVariableData -= RtlLengthSid( pAccountDomainInfo->DomainSid );
ntStatus = AfpInsertSidOffset(
pSidOffset++,
pbVariableData,
pAccountDomainInfo->DomainSid,
SE_ACCOUNT_DOMAIN_POSIX_OFFSET,
AFP_SID_TYPE_DOMAIN );
if ( !NT_SUCCESS( ntStatus ) )
break;
// Construct the "None" sid if we are a standalone server (i.e. not
// a PDC or BDC). This will be used when querying the group ID of
// a directory so the the UI will never show this group to the user.
//
if ( AfpGlobals.NtProductType != NtProductLanManNt )
{
ULONG SubAuthCount, SizeNoneSid = 0;
SubAuthCount = *RtlSubAuthorityCountSid(pAccountDomainInfo->DomainSid);
SizeNoneSid = RtlLengthRequiredSid(SubAuthCount + 1);
if ((AfpGlobals.pSidNone = (PSID)LocalAlloc(LPTR,SizeNoneSid)) == NULL)
{
ntStatus = STATUS_INSUFFICIENT_RESOURCES;
break;
}
RtlCopySid(SizeNoneSid, AfpGlobals.pSidNone, pAccountDomainInfo->DomainSid);
// Add the relative ID
*RtlSubAuthorityCountSid(AfpGlobals.pSidNone) = (UCHAR)(SubAuthCount+1);
// Note that the "None" sid on standalone is the same as the
// "Domain Users" Sid on PDC/BDC. (On PDC/BDC the primary
// domain is the same as the account domain).
*RtlSubAuthoritySid(AfpGlobals.pSidNone, SubAuthCount) = DOMAIN_GROUP_RID_USERS;
}
}
// Now insert the primary domain and trusted domains if this machine
// is a member of a domain
//
if ( pPrimaryDomainInfo != NULL ) {
// Insert the primary domain's SID/OFFSET pair
//
pbVariableData -= RtlLengthSid( pPrimaryDomainInfo->Sid );
ntStatus = AfpInsertSidOffset(
pSidOffset++,
pbVariableData,
pPrimaryDomainInfo->Sid,
SE_PRIMARY_DOMAIN_POSIX_OFFSET,
AFP_SID_TYPE_PRIMARY_DOMAIN );
if ( !NT_SUCCESS( ntStatus ) )
break;
// Now insert all the trusted domains
//
for ( dwIndex = 0,
pLsaTrustInfoIter = pLsaTrustInfo;
dwIndex < dwTrustInfoCount;
dwIndex++,
pLsaTrustInfoIter++
){
// Get the Posix offset of the Sid
//
ntStatus = LsaOpenTrustedDomain(
hLsa,
pLsaTrustInfoIter->Sid,
TRUSTED_QUERY_POSIX,
&hLsaDomain
);
if ( !NT_SUCCESS( ntStatus ) )
break;
ntStatus = LsaQueryInfoTrustedDomain(
hLsaDomain,
TrustedPosixOffsetInformation,
(PVOID*)&pPosixOffset
);
LsaClose( hLsaDomain );
if ( !NT_SUCCESS( ntStatus ) )
break;
pbVariableData -= RtlLengthSid( pLsaTrustInfoIter->Sid );
ntStatus = AfpInsertSidOffset(
pSidOffset++,
pbVariableData,
pLsaTrustInfoIter->Sid,
pPosixOffset->Offset,
AFP_SID_TYPE_DOMAIN );
LsaFreeMemory( pPosixOffset );
if ( !NT_SUCCESS( ntStatus ) )
break;
}
}
} while( FALSE );
// IOCTL down the information if all was OK
//
if ( NT_SUCCESS( ntStatus ) ) {
AfpRequestPkt.dwRequestCode = OP_SERVER_ADD_SID_OFFSETS;
AfpRequestPkt.dwApiType = AFP_API_TYPE_ADD;
AfpRequestPkt.Type.SetInfo.pInputBuf = pAfpSidOffsets;
AfpRequestPkt.Type.Add.cbInputBufSize = cbSidOffsets;
dwRetCode = AfpServerIOCtrl( &AfpRequestPkt );
}
else
dwRetCode = RtlNtStatusToDosError( ntStatus );
if ( pAfpSidOffsets != NULL )
LocalFree( pAfpSidOffsets );
// Free all the well known SIDS
//
for( dwIndex = 0;
pWellKnownSids[dwIndex].pSid != (PBYTE)NULL;
dwIndex++ )
RtlFreeSid( (PSID)(pWellKnownSids[dwIndex].pSid) );
return( dwRetCode );
}
//**
//
// Call: AfpInsertSidOffset
//
// Returns: NT_SUCCESS
// error return codes from RtlCopySid
//
// Description: Will insert a SID/OFFSET pair in the slot pointed to by
// pSidOffset. The pbVariableData will point to where the
// SID will be stored.
//
NTSTATUS
AfpInsertSidOffset(
IN PAFP_SID_OFFSET pSidOffset,
IN LPBYTE pbVariableData,
IN PSID pSid,
IN DWORD Offset,
IN AFP_SID_TYPE afpSidType
)
{
NTSTATUS ntStatus;
// Copy the offset
//
pSidOffset->Offset = Offset;
// Set the SID type
//
pSidOffset->SidType = afpSidType;
// Copy Sid at the end of the buffer and set the offset to it
//
ntStatus = RtlCopySid( RtlLengthSid( pSid ), pbVariableData, pSid );
if ( !NT_SUCCESS( ntStatus ) )
return( ntStatus );
pSidOffset->pSid = pbVariableData;
POINTER_TO_OFFSET( (pSidOffset->pSid), pSidOffset );
return( STATUS_SUCCESS );
}
//**
//
// Call: AfpCreateWellknownSids
//
// Returns: NT_SUCCESS
// STATUS_NO_MEMORY
// non-zero returns from RtlAllocateAndInitializeSid
//
// Description: Will allocate and initialize all well known SIDs.
// The array is terminated by a NULL pointer.
//
NTSTATUS
AfpCreateWellknownSids(
OUT AFP_SID_OFFSET pWellKnownSids[]
)
{
PSID pSid;
DWORD dwIndex = 0;
NTSTATUS ntStatus;
SID_IDENTIFIER_AUTHORITY NullSidAuthority = SECURITY_NULL_SID_AUTHORITY;
SID_IDENTIFIER_AUTHORITY WorldSidAuthority = SECURITY_WORLD_SID_AUTHORITY;
SID_IDENTIFIER_AUTHORITY LocalSidAuthority = SECURITY_LOCAL_SID_AUTHORITY;
SID_IDENTIFIER_AUTHORITY CreatorSidAuthority= SECURITY_CREATOR_SID_AUTHORITY;
SID_IDENTIFIER_AUTHORITY NtAuthority = SECURITY_NT_AUTHORITY;
do {
//
// OK, create all the well known SIDS
//
// Create NULL SID
//
ntStatus = RtlAllocateAndInitializeSid(
&NullSidAuthority,
1,
SECURITY_NULL_RID,
0,0,0,0,0,0,0,
&pSid );
if ( !NT_SUCCESS( ntStatus ) )
break;
pWellKnownSids[dwIndex].pSid = (PBYTE)pSid;
pWellKnownSids[dwIndex].Offset = SE_NULL_POSIX_ID;
pWellKnownSids[dwIndex].SidType = AFP_SID_TYPE_WELL_KNOWN;
dwIndex++;
// Create WORLD SID
//
ntStatus = RtlAllocateAndInitializeSid(
&WorldSidAuthority,
1,
SECURITY_WORLD_RID,
0,0,0,0,0,0,0,
&pSid );
if ( !NT_SUCCESS( ntStatus ) )
break;
pWellKnownSids[dwIndex].pSid = (PBYTE)pSid;
pWellKnownSids[dwIndex].Offset = SE_WORLD_POSIX_ID;
pWellKnownSids[dwIndex].SidType = AFP_SID_TYPE_WELL_KNOWN;
dwIndex++;
// Create LOCAL SID
//
ntStatus = RtlAllocateAndInitializeSid(
&LocalSidAuthority,
1,
SECURITY_LOCAL_RID,
0,0,0,0,0,0,0,
&pSid );
if ( !NT_SUCCESS( ntStatus ) )
break;
pWellKnownSids[dwIndex].pSid = (PBYTE)pSid;
pWellKnownSids[dwIndex].Offset = SE_LOCAL_POSIX_ID;
pWellKnownSids[dwIndex].SidType = AFP_SID_TYPE_WELL_KNOWN;
dwIndex++;
// Create CREATOR OWNER SID
//
ntStatus = RtlAllocateAndInitializeSid(
&CreatorSidAuthority,
1,
SECURITY_CREATOR_OWNER_RID,
0,0,0,0,0,0,0,
&pSid );
if ( !NT_SUCCESS( ntStatus ) )
break;
pWellKnownSids[dwIndex].pSid = (PBYTE)pSid;
pWellKnownSids[dwIndex].Offset = SE_CREATOR_OWNER_POSIX_ID;
pWellKnownSids[dwIndex].SidType = AFP_SID_TYPE_WELL_KNOWN;
dwIndex++;
// Create CREATOR GROUP SID
//
ntStatus = RtlAllocateAndInitializeSid(
&CreatorSidAuthority,
1,
SECURITY_CREATOR_GROUP_RID,
0,0,0,0,0,0,0,
&pSid );
if ( !NT_SUCCESS( ntStatus ) )
break;
pWellKnownSids[dwIndex].pSid = (PBYTE)pSid;
pWellKnownSids[dwIndex].Offset = SE_CREATOR_GROUP_POSIX_ID;
pWellKnownSids[dwIndex].SidType = AFP_SID_TYPE_WELL_KNOWN;
dwIndex++;
// Create SECURITY_NT_AUTHORITY Sid
//
ntStatus = RtlAllocateAndInitializeSid(
&NtAuthority,
0,0,0,0,0,0,0,0,0,
&pSid );
if ( !NT_SUCCESS( ntStatus ) )
break;
pWellKnownSids[dwIndex].pSid = (PBYTE)pSid;
pWellKnownSids[dwIndex].Offset = SE_AUTHORITY_POSIX_ID;
pWellKnownSids[dwIndex].SidType = AFP_SID_TYPE_WELL_KNOWN;
dwIndex++;
// Create SECURITY_DIALUP Sid
//
ntStatus = RtlAllocateAndInitializeSid(
&NtAuthority,
1,
SECURITY_DIALUP_RID,
0,0,0,0,0,0,0,
&pSid );
if ( !NT_SUCCESS( ntStatus ) )
break;
pWellKnownSids[dwIndex].pSid = (PBYTE)pSid;
pWellKnownSids[dwIndex].Offset = SE_DIALUP_POSIX_ID;
pWellKnownSids[dwIndex].SidType = AFP_SID_TYPE_WELL_KNOWN;
dwIndex++;
// Create SECURITY_NETWORK Sid
//
ntStatus = RtlAllocateAndInitializeSid(
&NtAuthority,
1,
SECURITY_NETWORK_RID,
0,0,0,0,0,0,0,
&pSid );
if ( !NT_SUCCESS( ntStatus ) )
break;
pWellKnownSids[dwIndex].pSid = (PBYTE)pSid;
pWellKnownSids[dwIndex].Offset = SE_NETWORK_POSIX_ID;
pWellKnownSids[dwIndex].SidType = AFP_SID_TYPE_WELL_KNOWN;
dwIndex++;
// Create SECURITY_BATCH Sid
//
ntStatus = RtlAllocateAndInitializeSid(
&NtAuthority,
1,
SECURITY_BATCH_RID,
0,0,0,0,0,0,0,
&pSid );
if ( !NT_SUCCESS( ntStatus ) )
break;
pWellKnownSids[dwIndex].pSid = (PBYTE)pSid;
pWellKnownSids[dwIndex].Offset = SE_NETWORK_POSIX_ID;
pWellKnownSids[dwIndex].SidType = AFP_SID_TYPE_WELL_KNOWN;
dwIndex++;
// Create SECURITY_INTERACTIVE Sid
//
ntStatus = RtlAllocateAndInitializeSid(
&NtAuthority,
1,
SECURITY_INTERACTIVE_RID,
0,0,0,0,0,0,0,
&pSid );
if ( !NT_SUCCESS( ntStatus ) )
break;
pWellKnownSids[dwIndex].pSid = (PBYTE)pSid;
pWellKnownSids[dwIndex].Offset = SE_INTERACTIVE_POSIX_ID;
pWellKnownSids[dwIndex].SidType = AFP_SID_TYPE_WELL_KNOWN;
dwIndex++;
// Create SECURITY_SERVICE Sid
//
ntStatus = RtlAllocateAndInitializeSid(
&NtAuthority,
1,
SECURITY_SERVICE_RID,
0,0,0,0,0,0,0,
&pSid );
if ( !NT_SUCCESS( ntStatus ) )
break;
pWellKnownSids[dwIndex].pSid = (PBYTE)pSid;
pWellKnownSids[dwIndex].Offset = SE_SERVICE_POSIX_ID;
pWellKnownSids[dwIndex].SidType = AFP_SID_TYPE_WELL_KNOWN;
dwIndex++;
// Create the built in domain SID
//
ntStatus = RtlAllocateAndInitializeSid(
&NtAuthority,
1,
SECURITY_BUILTIN_DOMAIN_RID,
0,0,0,0,0,0,0,
&pSid );
if ( !NT_SUCCESS( ntStatus ) )
break;
pWellKnownSids[dwIndex].pSid = (PBYTE)pSid;
pWellKnownSids[dwIndex].Offset = SE_BUILT_IN_DOMAIN_POSIX_OFFSET;
pWellKnownSids[dwIndex].SidType = AFP_SID_TYPE_DOMAIN;
dwIndex++;
pWellKnownSids[dwIndex].pSid = (PBYTE)NULL;
} while( FALSE );
if ( !NT_SUCCESS( ntStatus ) ) {
while( dwIndex > 0 )
RtlFreeSid( pWellKnownSids[--dwIndex].pSid );
}
return( ntStatus );
}