/*++ Copyright (C) Microsoft Corporation, 1995 - 1999 Module Name: util.c Abstract: Various helper and debug functions shared between platforms. Author: Mario Goertzel [MarioGo] Revision History: MarioGo 95/10/21 Bits 'n pieces --*/ #include #include #include #ifdef DEBUGRPC BOOL ValidateError( IN unsigned int Status, IN unsigned int Count, IN const int ErrorList[]) /*++ Routine Description Tests that 'Status' is one of an expected set of error codes. Used on debug builds as part of the VALIDATE() macro. Example: VALIDATE(EventStatus) { RPC_P_CONNECTION_CLOSED, RPC_P_RECEIVE_FAILED, RPC_P_CONNECTION_SHUTDOWN // more error codes here } END_VALIDATE; This function is called with the RpcStatus and expected errors codes as parameters. If RpcStatus is not one of the expected error codes and it not zero a message will be printed to the debugger and the function will return false. The VALIDATE macro ASSERT's the return value. Arguments: Status - Status code in question. Count - number of variable length arguments ... - One or more expected status codes. Terminated with 0 (RPC_S_OK). Return Value: TRUE - Status code is in the list or the status is 0. FALSE - Status code is not in the list. --*/ { unsigned i; for (i = 0; i < Count; i++) { if (ErrorList[i] == (int) Status) { return TRUE; } } PrintToDebugger("RPC Assertion: unexpected failure %lu (0lx%08x)\n", (unsigned long)Status, (unsigned long)Status); return(FALSE); } #endif // DEBUGRPC //------------------------------------------------------------------------ #ifdef RPC_ENABLE_WMI_TRACE #include #include #include "wmlum.h" // private header from clustering extern "C" { DWORD __stdcall I_RpcEnableWmiTrace( PWML_TRACE fn, WMILIB_REG_STRUCT ** pHandle ); } typedef DWORD (*WMI_TRACE_FN)(); PWML_TRACE WmiTraceFn = 0; WMILIB_REG_STRUCT WmiTraceData; GUID WmiMessageGuid = { /* 41de81c0-aa28-460b-a455-c23809e7c170 */ 0x41de81c0, 0xaa28, 0x460b, {0xa4, 0x55, 0xc2, 0x38, 0x09, 0xe7, 0xc1, 0x70} }; DWORD __stdcall I_RpcEnableWmiTrace( PWML_TRACE fn, WMILIB_REG_STRUCT ** pHandle ) { WmiTraceFn = fn; *pHandle = &WmiTraceData; return 0; } #endif BOOL fEnableLog = TRUE; C_ASSERT(sizeof(LUID) == sizeof(__int64)); struct RPC_EVENT * RpcEvents; long EventArrayLength = MAX_RPC_EVENT; long NextEvent = 0; BOOL DisableEvents = 0; /* boolean SubjectExceptions[256]; boolean VerbExceptions[256]; */ #define LOG_VAR( x ) &(x), sizeof(x) HANDLE hLogFile = 0; struct RPC_EVENT_LOG { DWORD Thread; union { struct { unsigned char Subject; unsigned char Verb; }; DWORD ZeroSet; }; void * SubjectPointer; void * ObjectPointer; ULONG_PTR Data; void * EventStackTrace[STACKTRACE_DEPTH]; }; void TrulyLogEvent( IN unsigned char Subject, IN unsigned char Verb, IN void * SubjectPointer, IN void * ObjectPointer, IN ULONG_PTR Data, IN BOOL fCaptureStackTrace, IN int AdditionalFramesToSkip ) { /* if (DisableEvents != SubjectExceptions[Subject] || DisableEvents != VerbExceptions[Verb]) { return; } */ // // Allocate the event table if it isn't already there. // if (!RpcEvents) { struct RPC_EVENT * Temp = (struct RPC_EVENT *) HeapAlloc( GetProcessHeap(), HEAP_ZERO_MEMORY, EventArrayLength * sizeof(RPC_EVENT) ); HANDLE LocalFile; if (!Temp) { return; } if (InterlockedCompareExchangePointer((void **) &RpcEvents, Temp, 0) != 0) { HeapFree(GetProcessHeap(), 0, Temp); } /* if (wcsstr(GetCommandLine(), L"fs.exe") != NULL) { LocalFile = CreateFile(L"d:\\rpcclnt.log", GENERIC_READ | GENERIC_WRITE, FILE_SHARE_READ, NULL, CREATE_ALWAYS, FILE_ATTRIBUTE_NORMAL, NULL); if (LocalFile != INVALID_HANDLE_VALUE) { hLogFile = LocalFile; } else { if (hLogFile == 0) { DbgPrint("ERROR: Could not create RPC log file: %d\n", GetLastError()); } // else // somebody already set it - ignore } } else if (wcsstr(GetCommandLine(), L"fssvr.exe") != NULL) { LocalFile = CreateFile(L"d:\\rpcsvr.log", GENERIC_READ | GENERIC_WRITE, FILE_SHARE_READ, NULL, CREATE_ALWAYS, FILE_ATTRIBUTE_NORMAL, NULL); if (LocalFile != INVALID_HANDLE_VALUE) { hLogFile = LocalFile; } else { if (hLogFile == 0) { DbgPrint("ERROR: Could not create RPC log file: %d\n", GetLastError()); } // else // somebody already set it - ignore } } */ /* DisableEvents = TRUE; SubjectExceptions[SU_ADDRESS] = TRUE; VerbExceptions[EV_CREATE] = TRUE; VerbExceptions[EV_DELETE] = TRUE; */ /* SubjectExceptions[SU_HEAP] = TRUE; SubjectExceptions[SU_EVENT] = TRUE; SubjectExceptions[SU_BCACHE] = TRUE; */ /* DisableEvents = TRUE; SubjectExceptions['a'] = TRUE; SubjectExceptions['g'] = TRUE; SubjectExceptions['G'] = TRUE; SubjectExceptions['W'] = TRUE; SubjectExceptions['X'] = TRUE; SubjectExceptions['Y'] = TRUE; SubjectExceptions['Z'] = TRUE; SubjectExceptions['w'] = TRUE; SubjectExceptions['x'] = TRUE; SubjectExceptions['y'] = TRUE; SubjectExceptions['z'] = TRUE; VerbExceptions['t'] = TRUE; VerbExceptions['G'] = TRUE; VerbExceptions['g'] = TRUE; VerbExceptions['w'] = TRUE; VerbExceptions['x'] = TRUE; VerbExceptions['y'] = TRUE; VerbExceptions['z'] = TRUE; VerbExceptions['W'] = TRUE; VerbExceptions['X'] = TRUE; VerbExceptions['Y'] = TRUE; VerbExceptions['Z'] = TRUE; */ } unsigned index = InterlockedIncrement(&NextEvent); index %= EventArrayLength; RpcEvents[index].Time = GetTickCount(); RpcEvents[index].Verb = Verb; RpcEvents[index].Subject = Subject; RpcEvents[index].Thread = (short) GetCurrentThreadId(); RpcEvents[index].SubjectPointer = SubjectPointer; RpcEvents[index].ObjectPointer = ObjectPointer; RpcEvents[index].Data = Data; RpcEvents[index].EventStackTrace[0] = NULL; RpcEvents[index].EventStackTrace[1] = NULL; RpcEvents[index].EventStackTrace[2] = NULL; RpcEvents[index].EventStackTrace[3] = NULL; CallTestHook( TH_RPC_LOG_EVENT, &RpcEvents[index], 0 ); #ifdef RPC_ENABLE_WMI_TRACE if (WmiTraceData.EnableFlags) { TraceMessage( WmiTraceData.LoggerHandle, TRACE_MESSAGE_SEQUENCE | TRACE_MESSAGE_GUID | TRACE_MESSAGE_SYSTEMINFO | TRACE_MESSAGE_TIMESTAMP, &WmiMessageGuid, Verb, LOG_VAR(Subject), LOG_VAR(SubjectPointer), LOG_VAR(ObjectPointer), LOG_VAR(Data), 0 ); } #endif if (fCaptureStackTrace) { ULONG ignore; RtlCaptureStackBackTrace( 1 + AdditionalFramesToSkip, STACKTRACE_DEPTH, (void **) &RpcEvents[index].EventStackTrace, &ignore); } else { RpcEvents[index].EventStackTrace[0] = 0; } if (hLogFile) { DWORD BytesWritten; /* RPC_EVENT_LOG logEntry; RPC_EVENT *CurrentEvent = &RpcEvents[index]; logEntry.Thread = CurrentEvent->Thread; logEntry.ZeroSet = 0; logEntry.Subject = CurrentEvent->Subject; logEntry.Verb = CurrentEvent->Verb; logEntry.Data = CurrentEvent->Data; logEntry.ObjectPointer = CurrentEvent->ObjectPointer; logEntry.SubjectPointer = CurrentEvent->SubjectPointer; memcpy(logEntry.EventStackTrace, CurrentEvent->EventStackTrace, sizeof(logEntry.EventStackTrace)); WriteFile(hLogFile, &logEntry, sizeof(logEntry), &BytesWritten, NULL); */ WriteFile(hLogFile, &RpcEvents[index], sizeof(RpcEvents[index]), &BytesWritten, NULL); } } void RPC_ENTRY I_RpcLogEvent ( IN unsigned char Subject, IN unsigned char Verb, IN void * SubjectPointer, IN void * ObjectPointer, IN unsigned Data, IN BOOL fCaptureStackTrace, IN int AdditionalFramesToSkip ) { LogEvent(Subject, Verb, SubjectPointer, ObjectPointer, Data, fCaptureStackTrace, AdditionalFramesToSkip); } #if 0 BOOL IsLoggingEnabled() { RPC_CHAR ModulePath[ MAX_PATH ]; RPC_CHAR * ModuleName; // // Find out the .EXE name. // if (!GetModuleFileName( NULL, ModulePath, sizeof(ModulePath))) { return FALSE; } signed i; for (i=RpcpStringLength(ModulePath)-1; i >= 0; --i) { if (ModulePath[i] == '\\') { break; } } ModuleName = ModulePath + i + 1; // // See whether logging should be enabled. // HANDLE hImeo; HANDLE hMyProcessOptions; DWORD Error; DWORD Value; DWORD Length = sizeof(Value); DWORD Type; Error = RegOpenKeyEx( HKEY_LOCAL_MACHINE, RPC_CONST_STRING("Software\\Microsoft\\Windows NT\\CurrentVersion\\Image File Execution Options"), 0, KEY_READ, &hImeo ); if (Error) { return FALSE; } Error = RegOpenKeyEx( hImeo, ModuleName, 0, KEY_READ, &hMyProcessOptions ); RegCloseKey( hImeo ); if (Error) { return FALSE; } Error = RegQueryValueEx( hMyProcessOptions, RPC_CONST_STRING("Enable RPC Logging"), 0, &Type, &Value, &Length ); RegCloseKey( hMyProcessOptions ); if (Error) { return FALSE; } if (Type == REG_DWORD && Value) { return TRUE; } if (Type == REG_SZ && 0 == RpcpStringCompare((RPC_CHAR *) Value, RPC_CONST_CHAR('Y'))) { return TRUE; } return FALSE; } #endif extern "C" int __cdecl _purecall(void) { #ifdef DEBUGRPC ASSERT(!"PureVirtualCalled"); #endif return 0; } PUNICODE_STRING FastGetImageBaseNameUnicodeString ( void ) /*++ Routine Description Retrieves the image base name with touching minimal amount of other memory. Returns a UNICODE_STRING structure. Arguments: Return Value: A pointer to LDR private UNICODE_STRING string with the image name. Don't write or delete it! --*/ { PLIST_ENTRY Module; PLDR_DATA_TABLE_ENTRY Entry; Module = NtCurrentPeb()->Ldr->InLoadOrderModuleList.Flink; Entry = CONTAINING_RECORD(Module, LDR_DATA_TABLE_ENTRY, InLoadOrderLinks); return &(Entry->BaseDllName); } const RPC_CHAR * FastGetImageBaseName ( void ) /*++ Routine Description Retrieves the image base name with touching minimal amount of other memory. Arguments: Return Value: A pointer to LDR private string with the image name. Don't write or delete it! --*/ { return (FastGetImageBaseNameUnicodeString())->Buffer; } // // RPC Verifier utility functions // unsigned int RndInteger ( void ) /*++ Routine Description: A private fast implementation of a congruential random number generator. We do not really care about its being "good" and use the results for fault injeciton. Return Value: A "random" integer between 0 and UINT_MAX --*/ { static BOOL fInit; static unsigned short nCalls; static unsigned long seed; RPC_STATUS Status; if (fInit == false || nCalls > 1000) { fInit = true; nCalls = 0; // Get a seed as a "true" random number. Status = GenerateRandomNumber((unsigned char *)&seed, sizeof(unsigned long)); if (Status != RPC_S_OK) { // On failure, still try to get some entropy. ASSERT(Status == RPC_S_OUT_OF_MEMORY); seed = GetTickCount(); } } // Use a simple Pi-enspired congruence f-la. seed = 3141592653 * seed + 2718281829; VERIFIER_DBG_PRINT_1("RndInteger() returned 0x%x\n", seed); return seed; } inline BOOL RndBool( unsigned int Prob ) /*++ Routine Description: Generates a boolean with probability of True Prob/10000 Return Value: A boolean with the given probability of truth --*/ { BOOL ret = RndInteger() < Prob*(0xffffffff/10000); VERIFIER_DBG_PRINT_1("RndBool() returned %d\n", ret); return (ret); } // Rounding of an unsigned float. #define URound(f) (unsigned int)(f+0.5) inline unsigned int RndIntegerInRange( unsigned int min, unsigned int max ) /*++ Routine Description: Returns a random integer from min to max. The distribution of the possible value is uniform. Return Value: A random integer within a given range --*/ { unsigned int ret = min + URound( (float)(max-min) * ((float)RndInteger() / (float)0xffffffff) ); VERIFIER_DBG_PRINT_3("RndIntegerInRange(0x%x, 0x%x) returned 0x%x\n", min, max, ret); return (ret); } #define BitFlip(arg,pos) ((arg) ^ (1L << (pos))) inline void RndBitFlip( unsigned char *addr, unsigned int len ) /*++ Routine Description: Flips one bit in each of len bytes starting at addr Return Value: None --*/ { for (unsigned int d = 0; dCorruptionSizeType == FixedSize) { Size = pRpcVerifierSettings->CorruptionSize; } else if (pRpcVerifierSettings->CorruptionSizeType == RandomSize) { Size = RndIntegerInRange(1, min(pRpcVerifierSettings->CorruptionSize,BufferLength)); } else { ASSERT(0 && "Unexpected CorruptionSizeType\n"); } // Determine the start of the corruption. Start = RndIntegerInRange(0, BufferLength-Size); VERIFIER_DBG_PRINT_2("CorruptBuffer() Size=%d Start=%d\n", Size, Start); if (pRpcVerifierSettings->CorruptionPattern == ZeroOut) { // For localized corruption, zero out random block of size Size. if (pRpcVerifierSettings->CorruptionDistributionType == LocalizedDistribution) { RtlZeroMemory((PVOID)(Buffer+Start), Size); } // For randomized corruption, zero out Size random bytes from the buffer. else { for (unsigned int i=0; iCorruptionPattern == Negate) { // For localized corruption, negate random block of size Size. if (pRpcVerifierSettings->CorruptionDistributionType == LocalizedDistribution) { for (unsigned int i = 0; iCorruptionPattern == BitFlip) { // For localized corruption, flip bits on Size consecutive bytes. if (pRpcVerifierSettings->CorruptionDistributionType == LocalizedDistribution) { RndBitFlip(Buffer+Start, Size); } // For randomized corruption, flip random bits in Size bytes all over the buffer. else { for (unsigned int i=0; iCorruptionPattern == IncDec) { // For localized corruption, increment or decrement Size consecutive bytes. if (pRpcVerifierSettings->CorruptionDistributionType == LocalizedDistribution) { RndIncDec(Buffer+Start, Size); } // For randomized corruption, inc/dec Size bytes all over the buffer. else { for (unsigned int i=0; iCorruptionPattern == Randomize) { // For localized corruption distribution, randomize block of size Size. if (pRpcVerifierSettings->CorruptionDistributionType == LocalizedDistribution) { for (unsigned int i = 0; iCorruptionPattern == AllPatterns) { // Choose a random pattern of corrupion only for the duration of this call. // This may affect other corruptions taking place, but it's OK since the overal // bahavior is correct. pRpcVerifierSettings->CorruptionPattern = (tCorruptionPattern)RndIntegerInRange(MIN_CORRUPTION_PATTERN_ID, MAX_CORRUPTION_PATTERN_ID); CorruptBuffer(BufferLength, Buffer); pRpcVerifierSettings->CorruptionPattern = AllPatterns; } else { ASSERT(0 && "Unexpected CorruptionPattern\n"); } } void CorruptionInject( tBufferType BufferType, unsigned int *pBufferLength, void **pBuffer ) /*++ Routine Description: Injects corruption into a buffer if necesssary. Injection is done according to the RPC verifier settings for this buffer type. Return Value: none --*/ { BOOL fSecure = false; void *Buffer = *pBuffer; unsigned int BufferLength = *pBufferLength; VERIFIER_DBG_PRINT_3("CorruptionInject() type=%d length=%d buffer=0x%x\n", BufferType, *pBufferLength, *pBuffer); // Check if there is a buffer to corrupt and if // this type of buffer should have corruption injected into it. if (*pBuffer && ((BufferType == ServerReceive && pRpcVerifierSettings->fCorruptionInjectServerReceives) || (BufferType == ClientReceive && pRpcVerifierSettings->fCorruptionInjectClientReceives))) { // If yes, corrupt the buffer if necessary. // First, we will try to truncate the buffer. if (pRpcVerifierSettings->ProbBufferTruncation && RndBool(pRpcVerifierSettings->ProbBufferTruncation)) { VERIFIER_DBG_PRINT_0("CorruptionInject() - truncating the buffer\n"); // We truncate OSF buffers only. The scenario is not interesting // for DG. The way we can tell the difference between the two types of packets // is by the header. // For OSF the packet header will look like: // rpcconn_common // +0x000 rpc_vers : 5 // +0x001 rpc_vers_minor : 0 // For DG it will be: // NCA_PACKET_HEADER // +0x000 RpcVersion : 0x4 // +0x001 PacketType : 0 // So we just want the first 2 bytes to be 5,0. if (BufferLength >= sizeof(rpcconn_common) && ((unsigned short)*((unsigned char*)Buffer + 0x0) == 5 && (unsigned short)*((unsigned char*)Buffer + 0x1) == 0 ) ) { unsigned short NewBufferLength = BufferLength - RndIntegerInRange(1, pRpcVerifierSettings->MaxBufferTruncationSize); NewBufferLength = max(NewBufferLength, sizeof(rpcconn_common)); // We have a connection-oriented buffer - truncate it. I_RpcTransConnectionReallocPacket( NULL, // The connection argument is ignored by the realloc routine. pBuffer, *pBufferLength, NewBufferLength); VERIFIER_DBG_PRINT_3("CorruptionInject() - truncated buffer 0x%x from 0x%x to 0x%x\n", *pBuffer, *pBufferLength, NewBufferLength); // Update the buffer size so that the right value is seen by the caller. Buffer = *pBuffer; *pBufferLength = NewBufferLength; BufferLength = NewBufferLength; // Adjust the frag_length so that it is equal to the new packetlength. // We need to do this since the runtime relies on these being in agreement and the // transports guarantee it. *((unsigned int*)((unsigned char*)Buffer + 0x8)) = BufferLength; } } // After the buffer has been truncated, we may corrupt it. // Check if we can corrupt the RPC header section. if (RndBool(pRpcVerifierSettings->ProbRpcHeaderCorruption)) { // Corrupt it if we can. CorruptBuffer( min(sizeof(rpcconn_common),BufferLength), // This will mostly whack the common RPC header. (unsigned char *)Buffer); } // // Determine whether this is a secure buffer. // The way we tell is by looking for the signature of rpcconn_common.auth_length != 0. // We will query this field directly, using the following offsets: // // rpcconn_common // +0x000 rpc_vers : UChar // ... // +0x008 frag_length : Uint2B // +0x00a auth_length : Uint2B // +0x00c call_id : Uint4B // // This may falsely count some packets as secure occasionally, // say in the case of fragmentation, but we can take this downside and the benefits of // a compact check outweigh it. // fSecure = ( (BufferLength > sizeof(rpcconn_common)) && ((unsigned short)*((unsigned char*)Buffer + 0xa) != 0) ); VERIFIER_DBG_PRINT_1("CorruptionInject() fSecure=%d\n", fSecure); // Check if we can corrupt the Data section. if ((!fSecure && RndBool(pRpcVerifierSettings->ProbDataCorruption)) || (fSecure && RndBool(pRpcVerifierSettings->ProbSecureDataCorruption))) { // Corrupt it if we can. CorruptBuffer( BufferLength, (unsigned char *)Buffer); } } } #define MAX_STACK_TRACE 8 PVOID LastEventStackTrace[MAX_STACK_TRACE]; void PrintCurrentStackTrace( unsigned int FramesToSkip, unsigned int Size ) /*++ Routine Description: Prints a stack trace of Size frames after the first FramesToSkip frames. Only the addresses are printed since there is no way to get to the symbolic information from here. Return Value: none --*/ { Size = min (Size, MAX_STACK_TRACE); PVOID *EventStackTrace = (PVOID *)alloca(Size*sizeof(PVOID)); // Capture and print the stack trace. RtlCaptureStackBackTrace(FramesToSkip, Size, EventStackTrace, NULL); for (unsigned int i=0; iData1, Uuid->Data2, Uuid->Data3, Uuid->Data4[0], Uuid->Data4[1], Uuid->Data4[2], Uuid->Data4[3], Uuid->Data4[4], Uuid->Data4[5], Uuid->Data4[6], Uuid->Data4[7] ); } } // // Per-interface security check exemption settings. // // The structure mapping an interface onto a flag. // An array of these defines interfaces exempt from some of the rpc verifier checks. typedef struct _tRpcVerifierIfExemption { GUID IfUuid; // An interface UUID. DWORD ExemptionFlags; // Which security checks are to be disabled. } tRpcVerifierIfExemption; // // This is a list of interface UUID's exempt from some or all checks. // We match the interfaces by their syntax GUIDs. // const tRpcVerifierIfExemption RpcVerifierExemptInterfaces[] = { // 000001A0-0000-0000-C000-000000000046 // ok to be remotely accessible, not secured, clear text traffic and no mutual authentication. {{0x000001A0, 0x0000, 0x0000, {0xC0, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x46}}, ALLOW_EVERYTHING}, // 12345678-1234-ABCD-EF00-01234567CFFB // Netlogon implements its own authentication protocol via the NetrServerReqChallenge // and NetrServerAuthenticate3 rpc calls. These rpc calls happen without packet privacy and result // in the servers being mutually authenticated and a key exchange between client and server. // After that all calls use privacy via the netlogon package. {{0x12345678, 0x1234, 0xABCD, {0xEF, 0x00, 0x01, 0x23, 0x45, 0x67, 0xCF, 0xFB}}, ALLOW_NO_MUTUAL_AUTH_REMOTE_ACCESS|ALLOW_UNENCRYPTED_REMOTE_ACCESS}, // 338cd001-2244-31f1-aaaa-900038001003 // ok to be remotely accessible, not secured. It uses an access check in the server routine instead // of a callback because it must support downlevel clients which used native named pipes transport security. {{0x338cd001, 0x2244, 0x31f1, {0xaa, 0xaa, 0x90, 0x00, 0x38, 0x00, 0x10, 0x03}}, ALLOW_EVERYTHING}, // 4d9f4ab8-7d1c-11cf-861e-0020af6e7c57 // ok to be remotely accessible, not secured, clear text traffic and no mutual authentication. {{0x4d9f4ab8, 0x7d1c, 0x11cf, {0x86, 0x1e, 0x00, 0x20, 0xaf, 0x6e, 0x7c, 0x57}}, ALLOW_EVERYTHING}, // 99fcfec4-5260-101b-bbcb-00aa0021347a // ok to be remotely accessible, not secured, clear text traffic and no mutual authentication. {{0x99fcfec4, 0x5260, 0x101b, {0xbb, 0xcb, 0x00, 0xaa, 0x00, 0x21, 0x34, 0x7a}}, ALLOW_EVERYTHING}, // e1af8308-5d1f-11c9-91a4-08002b14a0fa // ok to be remotely accessible, not secured, clear text traffic and no mutual authentication. {{0xe1af8308, 0x5d1f, 0x11c9, {0x91, 0xa4, 0x08, 0x00, 0x2b, 0x14, 0xa0, 0xfa}}, ALLOW_EVERYTHING}, // e60c73e6-88f9-11cf-9af1-0020af6e72f4 // ok to be remotely accessible, not secured, clear text traffic and no mutual authentication. {{0xe60c73e6, 0x88f9, 0x11cf, {0x9a, 0xf1, 0x00, 0x20, 0xaf, 0x6e, 0x72, 0xf4}}, ALLOW_EVERYTHING}, // We make all of the locator interfaces exempt. There will be a message // on locator start-up giving a warning for the service as a whole. // Also, the locator server manager routines will be protected in the user code. // e33c0cc4-0482-101a-bc0c-02608c6ba218 - LocToLoc {{0xe33c0cc4, 0x0482, 0x101a, {0xbc, 0x0c, 0x02, 0x60, 0x8c, 0x6b, 0xa2, 0x18}}, ALLOW_EVERYTHING}, // d3fbb514-0e3b-11cb-8fad-08002b1d29c3 - NsiC {{0xd3fbb514, 0x0e3b, 0x11cb, {0x8f, 0xad, 0x08, 0x00, 0x2b, 0x1d, 0x29, 0xc3}}, ALLOW_EVERYTHING}, // d6d70ef0-0e3b-11cb-acc3-08002b1d29c4 - NsiM {{0xd6d70ef0, 0x0e3b, 0x11cb, {0xac, 0xc3, 0x08, 0x00, 0x2b, 0x1d, 0x29, 0xc4}}, ALLOW_EVERYTHING}, // d6d70ef0-0e3b-11cb-acc3-08002b1d29c3 - NsiS {{0xd6d70ef0, 0x0e3b, 0x11cb, {0xac, 0xc3, 0x08, 0x00, 0x2b, 0x1d, 0x29, 0xc3}}, ALLOW_EVERYTHING}, // The following lsa and sam interfaces are secure in virtue of using a well-known // endpoint and relying on the transport np security. // They can't use RPC security because of backward compatibility. // 12345778-1234-ABCD-EF00-0123456789AC - SAM {{0x12345778, 0x1234, 0xABCD, {0xEF, 0x00, 0x01, 0x23, 0x45, 0x67, 0x89, 0xAC}}, ALLOW_EVERYTHING}, // 12345778-1234-ABCD-EF00-0123456789AB - LSA {{0x12345778, 0x1234, 0xABCD, {0xEF, 0x00, 0x01, 0x23, 0x45, 0x67, 0x89, 0xAB}}, ALLOW_EVERYTHING}, // 3919286a-b10c-11d0-9ba8-00c04fd92ef5 - dsrole. {{0x3919286a, 0xb10c, 0x11d0, {0x9b, 0xa8, 0x00, 0xc0, 0x4f, 0xd9, 0x2e, 0xf5}}, ALLOW_EVERYTHING}, // The DFS interface can't use RPC security because of the compatibility considerations. // 4fc742e0-4a10-11cf-8273-00aa004ae673 - DFS {{0x4fc742e0, 0x4a10, 0x11cf, {0x82, 0x73, 0x00, 0xaa, 0x00, 0x4a, 0xe6, 0x73}}, ALLOW_EVERYTHING}, // The licensing server is listening on the following interface. // This is a temp fix to be removed after .NET RC1 after which point the underlying bug will be fixed. // 2f59a331-bf7d-48cb-9e5c-7c090d76e8b8 {{0x2f59a331, 0xbf7d, 0x48cb, {0x9e, 0x5c, 0x7c, 0x09, 0x0d, 0x76, 0xe8, 0xb8}}, ALLOW_EVERYTHING}, // srvsvc.dll has backwards compatibility reasons preventing it from using encryption. // 4B324FC8-1670-01D3-1278-5A47BF6EE188 {{0x4B324FC8, 0x1670, 0x01D3, {0x12, 0x78, 0x5A, 0x47, 0xBF, 0x6E, 0xE1, 0x88}}, ALLOW_UNENCRYPTED_REMOTE_ACCESS}, // EFS has backwards compatibility considerations and were not able to fix the code on time. // c681d488-d850-11d0-8c52-00c04fd90f7e {{0xc681d488, 0xd850, 0x11d0, {0x8c, 0x52, 0x00, 0xc0, 0x4f, 0xd9, 0x0f, 0x7e}}, ALLOW_EVERYTHING} }; BOOL IsInterfaceExempt ( IN GUID *IfUuid, IN DWORD CheckFlag ) /*++ Function Name: IsInterfaceExempt Parameters: If - A UUID for the interface for which we want to look-up the exemption. CheckFlag - Flag for the check being tested for exemption. Description: Verifies whether an interface is exempt from a particular security check. Returns: TRUE - If an interface is exempt from a given check. FALSE - Otherwise. --*/ { // Go through all exempt interfaces. for (int i=0; i