////////////////////////////////////////////////////////////////////////////// // // // Global Definitions // // // ////////////////////////////////////////////////////////////////////////////// ////////////////////////////////////////////////////////////////////////////// // // // Global Variables // // // ////////////////////////////////////////////////////////////////////////////// NTSTATUS Status; OBJECT_ATTRIBUTES ObjectAttributes; STRING EventName; UNICODE_STRING UnicodeEventName; HANDLE EventHandle; UNICODE_STRING PortName; HANDLE EarPort; HANDLE TalkPort; PORT_MESSAGE RequestMessage; SECURITY_QUALITY_OF_SERVICE SecurityQos; ULONG RequestCount; HANDLE ClientToken; TOKEN_STATISTICS ClientTokenStatistics; ULONG IgnoreLength; HANDLE SepServerThread; ////////////////////////////////////////////////////////////////////////////// // // // Test Routine Definitions // // // ////////////////////////////////////////////////////////////////////////////// BOOLEAN SepClientTestStatic(VOID); BOOLEAN SepClientTestDynamic(VOID); BOOLEAN SepClientTestEffectiveOnly( BOOLEAN StaticTest ); BOOLEAN SepClientTestNotEffectiveOnly( BOOLEAN StaticTest ); BOOLEAN SepClientTestAnonymous( BOOLEAN StaticTest, BOOLEAN EffectiveOnly ); BOOLEAN SepClientTestIdentification( BOOLEAN StaticTest, BOOLEAN EffectiveOnly ); BOOLEAN SepClientTestImpersonation( BOOLEAN StaticTest, BOOLEAN EffectiveOnly ); VOID SepClientConnect( SECURITY_IMPERSONATION_LEVEL ImpersonationLevel, SECURITY_CONTEXT_TRACKING_MODE TrackingMode, BOOLEAN EffectiveOnly ); VOID SepClientMakeRemoteCall( VOID ); VOID SepClientDropConnection( VOID ); BOOLEAN SepClientTest(VOID); NTSTATUS SepClientInitialize( ); BOOLEAN SepServerTestStatic(VOID); BOOLEAN SepServerTestDynamic(VOID); BOOLEAN SepServerTestEffectiveOnly( BOOLEAN StaticTest ); BOOLEAN SepServerTestNotEffectiveOnly( BOOLEAN StaticTest ); BOOLEAN SepServerTestAnonymous( BOOLEAN StaticTest, BOOLEAN EffectiveOnly ); BOOLEAN SepServerTestIdentification( BOOLEAN StaticTest, BOOLEAN EffectiveOnly ); BOOLEAN SepServerTestImpersonation( BOOLEAN StaticTest, BOOLEAN EffectiveOnly ); VOID SepServerWaitForNextConnect( VOID ); VOID SepServerGetNextMessage( VOID ); VOID SepServerCompleteMessage( VOID ); VOID SepServerDropConnection( VOID ); BOOLEAN SepServerTest(VOID); NTSTATUS SepServerInitialize( ); VOID SepServerSpawnClientProcess(VOID); BOOLEAN CtLpcQos (VOID); ////////////////////////////////////////////////////////////////////////////// // // // Client-Side Test Routines // // // ////////////////////////////////////////////////////////////////////////////// VOID SepClientConnect( SECURITY_IMPERSONATION_LEVEL ImpersonationLevel, SECURITY_CONTEXT_TRACKING_MODE TrackingMode, BOOLEAN EffectiveOnly ) { SecurityQos.ImpersonationLevel = ImpersonationLevel; SecurityQos.ContextTrackingMode = TrackingMode; SecurityQos.EffectiveOnly = EffectiveOnly; Status = NtConnectPort( &TalkPort, &PortName, &SecurityQos, 0L, NULL, NULL, NULL, NULL, NULL ); SEASSERT_SUCCESS(Status); return; } VOID SepClientMakeRemoteCall( VOID ) { PORT_MESSAGE ReplyMessage; Status = NtRequestWaitReplyPort( TalkPort, &RequestMessage, &ReplyMessage ); RequestCount += 1; return; } VOID SepClientDropConnection( VOID ) { Status = NtClose( TalkPort ); SEASSERT_SUCCESS(Status); return; } BOOLEAN SepClientTestStatic(VOID) { BOOLEAN CompletionStatus; // // Static Context Tracking ... Suite // CompletionStatus = SepClientTestEffectiveOnly( TRUE ); if (CompletionStatus == TRUE) { CompletionStatus = SepClientTestNotEffectiveOnly( TRUE ); } return CompletionStatus; } BOOLEAN SepClientTestDynamic(VOID) { BOOLEAN CompletionStatus; // // Dynamic Context Tracking ... Suite // CompletionStatus = SepClientTestEffectiveOnly( FALSE ); if (CompletionStatus == TRUE) { CompletionStatus = SepClientTestNotEffectiveOnly( FALSE ); } return CompletionStatus; } BOOLEAN SepClientTestEffectiveOnly( BOOLEAN StaticTest ) { BOOLEAN CompletionStatus; // // Effective Only ... Test // CompletionStatus = SepClientTestAnonymous( StaticTest, TRUE ); if (CompletionStatus == TRUE) { CompletionStatus = SepClientTestIdentification( StaticTest, TRUE ); } if (CompletionStatus == TRUE) { CompletionStatus = SepClientTestImpersonation( StaticTest, TRUE ); } return CompletionStatus; } BOOLEAN SepClientTestNotEffectiveOnly( BOOLEAN StaticTest ) { BOOLEAN CompletionStatus; // // Not Effective Only ... Test // CompletionStatus = SepClientTestAnonymous( StaticTest, FALSE ); if (CompletionStatus == TRUE) { CompletionStatus = SepClientTestIdentification( StaticTest, FALSE ); } if (CompletionStatus == TRUE) { CompletionStatus = SepClientTestImpersonation( StaticTest, FALSE ); } return CompletionStatus; } BOOLEAN SepClientTestAnonymous( BOOLEAN StaticTest, BOOLEAN EffectiveOnly ) { ////////////////////////////////////////////////////////////////////////// // // // Anonymous Use Test // // // ////////////////////////////////////////////////////////////////////////// SECURITY_CONTEXT_TRACKING_MODE TrackingMode; if (StaticTest) { TrackingMode = SECURITY_STATIC_TRACKING; } else { TrackingMode = SECURITY_DYNAMIC_TRACKING; } if (!StaticTest) { // // No action for dynamic test // return TRUE; } // // Anonymous Use ... Test // SepClientConnect( SecurityAnonymous, TrackingMode, EffectiveOnly ); SepClientMakeRemoteCall(); SepClientDropConnection(); return TRUE; } BOOLEAN SepClientTestIdentification( BOOLEAN StaticTest, BOOLEAN EffectiveOnly ) { ////////////////////////////////////////////////////////////////////////// // // // Identification Use Test // // // ////////////////////////////////////////////////////////////////////////// SECURITY_CONTEXT_TRACKING_MODE TrackingMode; if (StaticTest) { TrackingMode = SECURITY_STATIC_TRACKING; } else { TrackingMode = SECURITY_DYNAMIC_TRACKING; } // // Identification Use ... Test // SepClientConnect( SecurityIdentification, TrackingMode, EffectiveOnly ); SepClientMakeRemoteCall(); SepClientDropConnection(); return TRUE; } BOOLEAN SepClientTestImpersonation( BOOLEAN StaticTest, BOOLEAN EffectiveOnly ) { ////////////////////////////////////////////////////////////////////////// // // // Impersonation Use Test // // // ////////////////////////////////////////////////////////////////////////// SECURITY_CONTEXT_TRACKING_MODE TrackingMode; if (StaticTest) { TrackingMode = SECURITY_STATIC_TRACKING; } else { TrackingMode = SECURITY_DYNAMIC_TRACKING; } // // Impersonation Use ... Test // SepClientConnect( SecurityImpersonation, TrackingMode, EffectiveOnly ); SepClientMakeRemoteCall(); SepClientDropConnection(); return TRUE; } BOOLEAN SepClientTest(VOID) // // Tests: // // Static Context Tracking Tests // Effective Only // Anonymous // Identification // Impersonation // Not Effective Only // Anonymous // Identification // Impersonation // // Dynamic Context Tracking Tests // Effective Only // Identification // Impersonation // Not Effective Only // Identification // Impersonation // { BOOLEAN CompletionStatus; // // Run the static test suite... // CompletionStatus = SepClientTestStatic(); // // Run the dynamic test suite... // if (CompletionStatus == TRUE) { CompletionStatus = SepClientTestDynamic(); } DbgPrint("Se: Client Test Complete.\n"); return CompletionStatus; } NTSTATUS SepClientInitialize( ) { DbgPrint("Se: Client Initializing ...\n"); // // Initialize global variables // RequestMessage.u1.s1.DataLength = 0; RequestMessage.u1.s1.TotalLength = (CSHORT)sizeof(PORT_MESSAGE); RequestMessage.u2.ZeroInit = 0; RequestCount = 0; // // Signal the named event to start the test // DbgPrint("Se: Client Starting Test ...\n"); Status = NtSetEvent( EventHandle, NULL ); SEASSERT_SUCCESS(Status); Status = NtClose( EventHandle ); SEASSERT_SUCCESS(Status); return STATUS_SUCCESS; } ////////////////////////////////////////////////////////////////////////////// // // // Server-Side Test Routines // // // ////////////////////////////////////////////////////////////////////////////// VOID SepServerWaitForNextConnect( VOID ) { CONNECTION_REQUEST ConnectionRequest; ConnectionRequest.Length = (ULONG)sizeof(CONNECTION_REQUEST); // // Wait for the client to connect to the port // Status = NtListenPort( EarPort, &ConnectionRequest, NULL, 0L ); SEASSERT_SUCCESS(Status); Status = NtAcceptConnectPort( &TalkPort, NULL, &ConnectionRequest, TRUE, NULL, NULL, NULL, 0L ); SEASSERT_SUCCESS(Status); Status = NtCompleteConnectPort( TalkPort ); SEASSERT_SUCCESS(Status); return; } VOID SepServerGetNextMessage( VOID ) { // // Wait for the next message to come in... // Status = NtReplyWaitReceivePort( EarPort, NULL, NULL, &RequestMessage ); SEASSERT_SUCCESS(Status); RequestCount += 1; return; } VOID SepServerCompleteMessage( VOID ) { PORT_MESSAGE ReplyMessage; ReplyMessage.u1.s1.DataLength = 0; ReplyMessage.u1.s1.TotalLength = (CSHORT)sizeof(PORT_MESSAGE); ReplyMessage.u2.ZeroInit = 0; ReplyMessage.ClientId = RequestMessage.ClientId; ReplyMessage.MessageId = RequestMessage.MessageId; // // Send the response message // Status = NtReplyPort( EarPort, &ReplyMessage ); SEASSERT_SUCCESS(Status); return; } VOID SepServerImpersonateClient( VOID ) { Status = NtImpersonateClientOfPort( TalkPort, &RequestMessage ); SEASSERT_SUCCESS(Status); } VOID SepServerRevertToSelf( VOID ) { NTSTATUS TmpStatus; HANDLE NullHandle; NullHandle = NULL; TmpStatus = NtSetInformationThread( SepServerThread, ThreadImpersonationToken, (PVOID)&NullHandle, (ULONG)sizeof(HANDLE) ); SEASSERT_SUCCESS(TmpStatus); } VOID SepServerDropConnection( VOID ) { Status = NtClose( TalkPort ); SEASSERT_SUCCESS(Status); return; } BOOLEAN SepServerTestStatic(VOID) { BOOLEAN CompletionStatus; DbgPrint("Se: Static Context Tracking ... Suite\n"); CompletionStatus = SepServerTestEffectiveOnly( TRUE ); if (CompletionStatus == TRUE) { CompletionStatus = SepServerTestNotEffectiveOnly( TRUE ); } return CompletionStatus; } BOOLEAN SepServerTestDynamic(VOID) { BOOLEAN CompletionStatus; DbgPrint("Se: Dynamic Context Tracking ... Suite\n"); CompletionStatus = SepServerTestEffectiveOnly( FALSE ); if (CompletionStatus == TRUE) { CompletionStatus = SepServerTestNotEffectiveOnly( FALSE ); } return CompletionStatus; } BOOLEAN SepServerTestEffectiveOnly( BOOLEAN StaticTest ) { BOOLEAN CompletionStatus; DbgPrint("Se: Effective Only ... Test\n"); CompletionStatus = SepServerTestAnonymous( StaticTest, TRUE ); if (CompletionStatus == TRUE) { CompletionStatus = SepServerTestIdentification( StaticTest, TRUE ); } if (CompletionStatus == TRUE) { CompletionStatus = SepServerTestImpersonation( StaticTest, TRUE ); } return CompletionStatus; } BOOLEAN SepServerTestNotEffectiveOnly( BOOLEAN StaticTest ) { BOOLEAN CompletionStatus; DbgPrint("Se: Not Effective Only ... Test\n"); CompletionStatus = SepServerTestAnonymous( StaticTest, FALSE ); if (CompletionStatus == TRUE) { CompletionStatus = SepServerTestIdentification( StaticTest, FALSE ); } if (CompletionStatus == TRUE) { CompletionStatus = SepServerTestImpersonation( StaticTest, FALSE ); } return CompletionStatus; } BOOLEAN SepServerTestAnonymous( BOOLEAN StaticTest, BOOLEAN EffectiveOnly ) { BOOLEAN CompletionStatus = TRUE; ////////////////////////////////////////////////////////////////////////// // // // Anonymous Use Test // // // ////////////////////////////////////////////////////////////////////////// if (!StaticTest) { // // No action for dynamic test // return TRUE; } DbgPrint("Se: Anonymous Use ... "); SepServerWaitForNextConnect(); SepServerGetNextMessage(); SepServerImpersonateClient(); Status = NtOpenThreadToken( SepServerThread, TOKEN_ALL_ACCESS, TRUE, &ClientToken ); SepServerRevertToSelf(); if (Status == STATUS_CANT_OPEN_ANONYMOUS) { DbgPrint(" Succeeded\n"); } else { DbgPrint("* ! FAILED (srvr) ! *\n"); DbgPrint("Status is: 0x%lx \n", Status ); CompletionStatus = FALSE; } SepServerCompleteMessage(); SepServerDropConnection(); // // Appease the compiler Gods.. // if (EffectiveOnly) {;} return CompletionStatus; } BOOLEAN SepServerTestIdentification( BOOLEAN StaticTest, BOOLEAN EffectiveOnly ) { BOOLEAN CompletionStatus = TRUE; ////////////////////////////////////////////////////////////////////////// // // // Identification Use Test // // // ////////////////////////////////////////////////////////////////////////// DbgPrint("Se: Identification Use ... "); SepServerWaitForNextConnect(); SepServerGetNextMessage(); SepServerImpersonateClient(); Status = NtOpenThreadToken( SepServerThread, TOKEN_ALL_ACCESS, TRUE, &ClientToken ); SEASSERT_SUCCESS(Status); SepServerRevertToSelf(); Status = NtQueryInformationToken( ClientToken, TokenStatistics, &ClientTokenStatistics, (ULONG)sizeof(TOKEN_STATISTICS), &IgnoreLength ); SEASSERT_SUCCESS(Status); if ( (ClientTokenStatistics.TokenType == TokenImpersonation) && (ClientTokenStatistics.ImpersonationLevel == SecurityIdentification) ) { DbgPrint(" Succeeded\n"); } else { DbgPrint("* ! FAILED (srvr) ! *\n"); CompletionStatus = FALSE; } SepServerCompleteMessage(); SepServerDropConnection(); // // Appease the compiler Gods.. // if (StaticTest) {;} if (EffectiveOnly) {;} return CompletionStatus; } BOOLEAN SepServerTestImpersonation( BOOLEAN StaticTest, BOOLEAN EffectiveOnly ) { BOOLEAN CompletionStatus = TRUE; ////////////////////////////////////////////////////////////////////////// // // // Impersonation Use Test // // // ////////////////////////////////////////////////////////////////////////// DbgPrint("Se: Impersonation Use ... "); SepServerWaitForNextConnect(); SepServerGetNextMessage(); SepServerImpersonateClient(); Status = NtOpenThreadToken( SepServerThread, TOKEN_ALL_ACCESS, TRUE, &ClientToken ); SEASSERT_SUCCESS(Status); SepServerRevertToSelf(); Status = NtQueryInformationToken( ClientToken, TokenStatistics, &ClientTokenStatistics, (ULONG)sizeof(TOKEN_STATISTICS), &IgnoreLength ); SEASSERT_SUCCESS(Status); if ( (ClientTokenStatistics.TokenType == TokenImpersonation) && (ClientTokenStatistics.ImpersonationLevel == SecurityImpersonation) ) { DbgPrint(" Succeeded\n"); } else { DbgPrint("* ! FAILED (srvr) ! *\n"); CompletionStatus = FALSE; } SepServerCompleteMessage(); SepServerDropConnection(); // // Appease the compiler gods // if (StaticTest) {;} if (EffectiveOnly) {;} return CompletionStatus; } BOOLEAN SepServerTest(VOID) // // Tests: // // Static Context Tracking Tests // Effective Only // Anonymous // Identification // Impersonation // Not Effective Only // Anonymous // Identification // Impersonation // // Dynamic Context Tracking Tests // Effective Only // Identification // Impersonation // Not Effective Only // Identification // Impersonation // { BOOLEAN CompletionStatus; DbgPrint("Se: Server Starting Test ...\n"); // // Run the static test suite... // CompletionStatus = SepServerTestStatic(); // // Run the dynamic test suite... // if (CompletionStatus == TRUE) { CompletionStatus = SepServerTestDynamic(); } DbgPrint("Se: Server Test Complete.\n"); // // Print test results // DbgPrint("\n"); DbgPrint("\n"); DbgPrint("**********************\n"); DbgPrint("** **\n"); if (CompletionStatus == TRUE) { DbgPrint("** Test Succeeded **\n"); } else { DbgPrint("** Test Failed !! **\n"); } DbgPrint("** **\n"); DbgPrint("**********************\n"); return CompletionStatus; } NTSTATUS SepServerInitialize( ) { NTSTATUS Status; OBJECT_ATTRIBUTES ThreadAttributes; PTEB CurrentTeb; DbgPrint("Se: Server Initializing ...\n"); // // Initialize global variables // RequestCount = 0; // // Get a handle to our thread to so that we can access our thread // even when impersonating an anonymous client (which we can't do // using NtCurrentThread()). // CurrentTeb = NtCurrentTeb(); InitializeObjectAttributes(&ThreadAttributes, NULL, 0, NULL, NULL); Status = NtOpenThread( &SepServerThread, // TargetHandle THREAD_ALL_ACCESS, // DesiredAccess &ThreadAttributes, // ObjectAttributes &CurrentTeb->ClientId // ClientId ); ASSERT( NT_SUCCESS(Status) ); // // Create the server's port // InitializeObjectAttributes( &ObjectAttributes, &PortName, 0, NULL, NULL ); Status = NtCreatePort( &EarPort, &ObjectAttributes, 0, 4, 4 * 256 ); SEASSERT_SUCCESS(Status); // // Spawn a copy of ourselves... // DbgPrint("Se: Server Spawning client process ...\n"); SepServerSpawnClientProcess(); DbgPrint("Se: Server waiting for start of test signal ...\n"); Status = NtWaitForSingleObject( EventHandle, TRUE, NULL ); SEASSERT_SUCCESS(Status); Status = NtClose( EventHandle ); SEASSERT_SUCCESS(Status); return STATUS_SUCCESS; } VOID SepServerSpawnClientProcess(VOID) { RTL_USER_PROCESS_INFORMATION ProcessInformation; STRING ImagePathName, ProgramName; UNICODE_STRING UnicodeImagePathName, UnicodeProgramName; PRTL_USER_PROCESS_PARAMETERS ProcessParameters; RtlInitString( &ProgramName, "\\SystemRoot\\Bin\\utlpcqos.exe" ); Status = RtlAnsiStringToUnicodeString( &UnicodeProgramName, &ProgramName, TRUE ); SEASSERT_SUCCESS( NT_SUCCESS(Status) ); RtlInitString( &ImagePathName, "utlpcqos.exe"); Status = RtlAnsiStringToUnicodeString( &UnicodeImagePathName, &ImagePathName, TRUE ); SEASSERT_SUCCESS( NT_SUCCESS(Status) ); Status = RtlCreateProcessParameters( &ProcessParameters, &ImagePathName, //UNICODEFIX &UnicodeImagePathName, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL ); SEASSERT_SUCCESS(Status); Status = RtlCreateUserProcess( &ProgramName, // UNICODEFIX &UnicodeProgramName, ProcessParameters, // ProcessParameters NULL, // ProcessSecurityDescriptor NULL, // ThreadSecurityDescriptor NtCurrentProcess(), // ParentProcess FALSE, // InheritHandles NULL, // DebugPort NULL, // ExceptionPort &ProcessInformation // ProcessInformation ); SEASSERT_SUCCESS(Status); Status = NtResumeThread( ProcessInformation.Thread, NULL ); SEASSERT_SUCCESS(Status); RtlDestroyProcessParameters( ProcessParameters ); RtlFreeUnicodeString( &UnicodeProgramName ); RtlFreeUnicodeString( &UnicodeImagePathName ); } ////////////////////////////////////////////////////////////////////////////// // // // Main Program Entry Routine // // // ////////////////////////////////////////////////////////////////////////////// BOOLEAN CtLpcQos (VOID) { BOOLEAN Result = TRUE; RtlInitUnicodeString( &PortName, L"\\TestLpcQosServerPort" ); // // Determine whether we are the client or server side of the test. // This is done by creating or opening a named event object. If the // event does not yet exist, then we are the client, and must create // the server process. Otherwise, we are the server and the client // is waiting for us to signal the event. // RtlInitString( &EventName, "\\TestLpcQosEvent" ); Status = RtlAnsiStringToUnicodeString( &UnicodeEventName, &EventName, TRUE ); SEASSERT_SUCCESS( NT_SUCCESS(Status) ); InitializeObjectAttributes( &ObjectAttributes, &UnicodeEventName, OBJ_OPENIF, NULL, NULL ); Status = NtCreateEvent( &EventHandle, EVENT_ALL_ACCESS, &ObjectAttributes, SynchronizationEvent, FALSE ); if (Status == STATUS_OBJECT_NAME_EXISTS) { // // Server is already running, therefore, this process gets to be // the client. // Status = SepClientInitialize(); SEASSERT_SUCCESS(Status); Result = SepClientTest(); } else { SEASSERT_SUCCESS(Status); // // Event wasn't yet there, so we must be the server. // DbgPrint("Se: Starting LPC Impersonation Test.\n"); Status = SepServerInitialize(); SEASSERT_SUCCESS(Status); Result = SepServerTest(); DbgPrint("Se: End Test.\n"); } Status = NtTerminateThread( NtCurrentThread(), STATUS_SUCCESS); SEASSERT_SUCCESS(Status); return Result; }