301 lines
9.1 KiB
C
301 lines
9.1 KiB
C
|
/*++
|
||
|
|
||
|
Copyright (c) 1992 Microsoft Corporation
|
||
|
|
||
|
Module Name:
|
||
|
|
||
|
DomainId.c
|
||
|
|
||
|
Abstract:
|
||
|
|
||
|
This file contains NetpGetLocalDomainId(). This will eventually
|
||
|
replace NetpGetDomainId().
|
||
|
|
||
|
Author:
|
||
|
|
||
|
John Rogers (JohnRo) 06-May-1992
|
||
|
|
||
|
Environment:
|
||
|
|
||
|
Interface is portable to any flat, 32-bit environment. (Uses Win32
|
||
|
typedefs.) Requires ANSI C extensions: slash-slash comments, long
|
||
|
external names. Code itself only runs under NT.
|
||
|
|
||
|
Revision History:
|
||
|
|
||
|
06-May-1992 JohnRo
|
||
|
Created. (Borrowed most code from DanHi's SDKTools/AddUser/AddUser.c.
|
||
|
08-May-1992 JohnRo
|
||
|
Use <prefix.h> equates.
|
||
|
09-Jun-1992 JohnRo
|
||
|
RAID 10139: PortUAS should add to admin group/alias.
|
||
|
|
||
|
--*/
|
||
|
|
||
|
|
||
|
// These must be included first:
|
||
|
|
||
|
#include <nt.h> // IN, LPVOID, etc.
|
||
|
#include <ntsam.h>
|
||
|
#include <ntlsa.h>
|
||
|
#include <ntrtl.h>
|
||
|
#include <nturtl.h> // (Needed for ntrtl.h and windows.h to coexist.)
|
||
|
#include <windows.h> // LocalAlloc(), LMEM_ equates, etc.
|
||
|
#include <lmcons.h> // NET_API_STATUS, needed by <netlibnt.h>
|
||
|
|
||
|
// These may be included in any order:
|
||
|
|
||
|
#include <debuglib.h> // IF_DEBUG().
|
||
|
#include <lmerr.h> // NO_ERROR, ERROR_, and NERR_ equates.
|
||
|
#include <netdebug.h> // NetpAssert, FORMAT_ equates, etc.
|
||
|
#include <netlib.h> // LOCAL_DOMAIN_TYPE, my prototype.
|
||
|
#include <netlibnt.h> // NetpNtStatusToApiStatus().
|
||
|
#include <prefix.h> // PREFIX_ equates.
|
||
|
|
||
|
|
||
|
static SID_IDENTIFIER_AUTHORITY NetpBuiltinIdentifierAuthority
|
||
|
= SECURITY_NT_AUTHORITY;
|
||
|
|
||
|
|
||
|
NET_API_STATUS
|
||
|
NetpGetLocalDomainId (
|
||
|
IN LOCAL_DOMAIN_TYPE TypeWanted,
|
||
|
OUT PSID *RetDomainId
|
||
|
)
|
||
|
|
||
|
/*++
|
||
|
|
||
|
Routine Description:
|
||
|
|
||
|
This routine obtains the domain id from LSA for the local domain.
|
||
|
The routine is a superset of NetpGetDomainId().
|
||
|
|
||
|
Arguments:
|
||
|
|
||
|
TypeWanted - Indicates which type of local domain ID is wanted:
|
||
|
the primary one or the accounts one.
|
||
|
|
||
|
RetDomainId - This is a pointer to the location where the pointer
|
||
|
to the domain id is to be placed. This must be freed via LocalFree().
|
||
|
|
||
|
Return Value:
|
||
|
|
||
|
NERR_Success - If the operation was successful.
|
||
|
|
||
|
It will return assorted Net or Win32 error messages if not.
|
||
|
|
||
|
--*/
|
||
|
{
|
||
|
NET_API_STATUS ApiStatus;
|
||
|
LSA_HANDLE LsaHandle = NULL;
|
||
|
NTSTATUS NtStatus;
|
||
|
LPVOID PolicyInfo = NULL;
|
||
|
DWORD SidSize;
|
||
|
|
||
|
if (RetDomainId == NULL) {
|
||
|
ApiStatus = ERROR_INVALID_PARAMETER;
|
||
|
goto cleanupandexit;
|
||
|
}
|
||
|
*RetDomainId = NULL; // make error paths easy to code.
|
||
|
|
||
|
//
|
||
|
// The type of domain the caller wants determines the information class
|
||
|
// we have to get LSA to deal with. So use one to get the other.
|
||
|
//
|
||
|
switch (TypeWanted) {
|
||
|
|
||
|
case LOCAL_DOMAIN_TYPE_ACCOUNTS : /*FALLTHROUGH*/
|
||
|
case LOCAL_DOMAIN_TYPE_PRIMARY :
|
||
|
{
|
||
|
OBJECT_ATTRIBUTES ObjectAttributes;
|
||
|
POLICY_INFORMATION_CLASS PolicyInfoClass;
|
||
|
LPVOID SourceDomainId;
|
||
|
|
||
|
if (TypeWanted == LOCAL_DOMAIN_TYPE_ACCOUNTS) {
|
||
|
PolicyInfoClass = PolicyAccountDomainInformation;
|
||
|
} else {
|
||
|
PolicyInfoClass = PolicyPrimaryDomainInformation;
|
||
|
}
|
||
|
//
|
||
|
// Get LSA to open its local policy database.
|
||
|
//
|
||
|
|
||
|
InitializeObjectAttributes( &ObjectAttributes, NULL, 0, 0, NULL );
|
||
|
NtStatus = LsaOpenPolicy(
|
||
|
NULL,
|
||
|
&ObjectAttributes,
|
||
|
POLICY_VIEW_LOCAL_INFORMATION,
|
||
|
&LsaHandle);
|
||
|
if ( !NT_SUCCESS(NtStatus)) {
|
||
|
ApiStatus = NetpNtStatusToApiStatus( NtStatus );
|
||
|
IF_DEBUG( DOMAINID ) {
|
||
|
NetpKdPrint((PREFIX_NETLIB "NetpGetLocalDomainId:\n"
|
||
|
" Couldn't _open Lsa Policy database, nt status = "
|
||
|
FORMAT_NTSTATUS "\n", NtStatus));
|
||
|
}
|
||
|
NetpAssert( ApiStatus != NO_ERROR );
|
||
|
goto cleanupandexit;
|
||
|
}
|
||
|
NetpAssert( LsaHandle != NULL );
|
||
|
|
||
|
//
|
||
|
// Get the appropriate domain SID from LSA
|
||
|
//
|
||
|
NtStatus = LsaQueryInformationPolicy(
|
||
|
LsaHandle,
|
||
|
PolicyInfoClass,
|
||
|
&PolicyInfo);
|
||
|
if ( !NT_SUCCESS(NtStatus)) {
|
||
|
ApiStatus = NetpNtStatusToApiStatus( NtStatus );
|
||
|
IF_DEBUG( DOMAINID ) {
|
||
|
NetpKdPrint((PREFIX_NETLIB "NetpGetLocalDomainId:\n"
|
||
|
" Couldn't query Lsa Policy database, nt status = "
|
||
|
FORMAT_NTSTATUS "\n", NtStatus));
|
||
|
}
|
||
|
NetpAssert( ApiStatus != NO_ERROR );
|
||
|
goto cleanupandexit;
|
||
|
}
|
||
|
|
||
|
//
|
||
|
// Find source domain ID in the appropriate structure.
|
||
|
//
|
||
|
if (TypeWanted == LOCAL_DOMAIN_TYPE_ACCOUNTS) {
|
||
|
PPOLICY_ACCOUNT_DOMAIN_INFO PolicyAccountDomainInfo
|
||
|
= PolicyInfo;
|
||
|
SourceDomainId = PolicyAccountDomainInfo->DomainSid;
|
||
|
NetpAssert( SourceDomainId != NULL );
|
||
|
NetpAssert( RtlValidSid( SourceDomainId ) );
|
||
|
} else {
|
||
|
|
||
|
PPOLICY_PRIMARY_DOMAIN_INFO PolicyPrimaryDomainInfo
|
||
|
= PolicyInfo;
|
||
|
NetpAssert( TypeWanted == LOCAL_DOMAIN_TYPE_PRIMARY );
|
||
|
SourceDomainId = PolicyPrimaryDomainInfo->Sid;
|
||
|
if ( SourceDomainId != NULL ) {
|
||
|
NetpAssert( RtlValidSid( SourceDomainId ) );
|
||
|
}
|
||
|
}
|
||
|
|
||
|
//
|
||
|
// If there was a domain ID, copy it now
|
||
|
//
|
||
|
|
||
|
if (SourceDomainId != NULL) {
|
||
|
|
||
|
//
|
||
|
// Compute size and alloc destination SID.
|
||
|
//
|
||
|
|
||
|
NetpAssert( sizeof(ULONG) <= sizeof(DWORD) );
|
||
|
|
||
|
SidSize = (DWORD) RtlLengthSid( SourceDomainId );
|
||
|
NetpAssert( SidSize != 0 );
|
||
|
|
||
|
*RetDomainId = LocalAlloc( LMEM_FIXED, SidSize );
|
||
|
|
||
|
if ( *RetDomainId == NULL ) {
|
||
|
IF_DEBUG( DOMAINID ) {
|
||
|
NetpKdPrint((PREFIX_NETLIB "NetpGetLocalDomainId:\n"
|
||
|
" not enough memory (need " FORMAT_DWORD
|
||
|
")\n", SidSize));
|
||
|
}
|
||
|
ApiStatus = ERROR_NOT_ENOUGH_MEMORY;
|
||
|
goto cleanupandexit;
|
||
|
}
|
||
|
|
||
|
//
|
||
|
// Copy the SID (domain ID).
|
||
|
//
|
||
|
|
||
|
NtStatus = RtlCopySid(
|
||
|
SidSize, // dest size in bytes
|
||
|
*RetDomainId, // dest sid
|
||
|
SourceDomainId); // src sid
|
||
|
if ( !NT_SUCCESS(NtStatus)) {
|
||
|
ApiStatus = NetpNtStatusToApiStatus( NtStatus );
|
||
|
IF_DEBUG( DOMAINID ) {
|
||
|
NetpKdPrint((PREFIX_NETLIB "NetpGetLocalDomainId:\n"
|
||
|
" RtlCopySid failed, nt status = "
|
||
|
FORMAT_NTSTATUS "\n", NtStatus));
|
||
|
}
|
||
|
NetpAssert( ApiStatus != NO_ERROR );
|
||
|
goto cleanupandexit;
|
||
|
}
|
||
|
|
||
|
NetpAssert( RtlValidSid( SourceDomainId ) );
|
||
|
NetpAssert( RtlEqualSid( SourceDomainId, *RetDomainId ) );
|
||
|
} else {
|
||
|
//
|
||
|
// Just return the NULL domain id.
|
||
|
//
|
||
|
|
||
|
*RetDomainId = NULL;
|
||
|
}
|
||
|
|
||
|
}
|
||
|
break;
|
||
|
|
||
|
case LOCAL_DOMAIN_TYPE_BUILTIN :
|
||
|
|
||
|
#define SUBAUTHORITIES_FOR_BUILTIN_DOMAIN 1
|
||
|
|
||
|
SidSize = (DWORD)
|
||
|
RtlLengthRequiredSid( SUBAUTHORITIES_FOR_BUILTIN_DOMAIN );
|
||
|
NetpAssert( SidSize != 0 );
|
||
|
|
||
|
*RetDomainId = LocalAlloc( LMEM_FIXED, SidSize );
|
||
|
|
||
|
if ( *RetDomainId == NULL ) {
|
||
|
IF_DEBUG( DOMAINID ) {
|
||
|
NetpKdPrint((PREFIX_NETLIB "NetpGetLocalDomainId:\n"
|
||
|
" not enough memory (need " FORMAT_DWORD
|
||
|
")\n", SidSize));
|
||
|
}
|
||
|
ApiStatus = ERROR_NOT_ENOUGH_MEMORY;
|
||
|
goto cleanupandexit;
|
||
|
}
|
||
|
|
||
|
NtStatus = RtlInitializeSid(
|
||
|
*RetDomainId, // SID being built
|
||
|
&NetpBuiltinIdentifierAuthority, // identifier authority
|
||
|
(UCHAR)SUBAUTHORITIES_FOR_BUILTIN_DOMAIN ); // subauth. count
|
||
|
NetpAssert( NT_SUCCESS( NtStatus ) );
|
||
|
|
||
|
|
||
|
NetpAssert( SUBAUTHORITIES_FOR_BUILTIN_DOMAIN == 1 );
|
||
|
*(RtlSubAuthoritySid(*RetDomainId, 0)) = SECURITY_BUILTIN_DOMAIN_RID;
|
||
|
|
||
|
NetpAssert( RtlValidSid( *RetDomainId ) );
|
||
|
break;
|
||
|
|
||
|
default :
|
||
|
ApiStatus = ERROR_INVALID_PARAMETER;
|
||
|
goto cleanupandexit;
|
||
|
}
|
||
|
|
||
|
|
||
|
|
||
|
ApiStatus = NO_ERROR;
|
||
|
|
||
|
cleanupandexit:
|
||
|
|
||
|
//
|
||
|
// Clean up (either error or success).
|
||
|
//
|
||
|
|
||
|
if (PolicyInfo) {
|
||
|
(VOID) LsaFreeMemory(PolicyInfo);
|
||
|
}
|
||
|
if (LsaHandle) {
|
||
|
(VOID) LsaClose(LsaHandle);
|
||
|
}
|
||
|
if ((ApiStatus!=NO_ERROR) && (RetDomainId!=NULL) && (*RetDomainId!=NULL)) {
|
||
|
(VOID) LocalFree( *RetDomainId );
|
||
|
*RetDomainId = NULL;
|
||
|
}
|
||
|
|
||
|
return (ApiStatus);
|
||
|
|
||
|
}
|
||
|
|