/*++ 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 equates. 09-Jun-1992 JohnRo RAID 10139: PortUAS should add to admin group/alias. --*/ // These must be included first: #include // IN, LPVOID, etc. #include #include #include #include // (Needed for ntrtl.h and windows.h to coexist.) #include // LocalAlloc(), LMEM_ equates, etc. #include // NET_API_STATUS, needed by // These may be included in any order: #include // IF_DEBUG(). #include // NO_ERROR, ERROR_, and NERR_ equates. #include // NetpAssert, FORMAT_ equates, etc. #include // LOCAL_DOMAIN_TYPE, my prototype. #include // NetpNtStatusToApiStatus(). #include // 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); }