Esempio n. 1
0
NTSTATUS
SmpHandleConnectionRequest(
    IN HANDLE ConnectionPort,
    IN PSBAPIMSG Message
    )

/*++

Routine Description:

    This routine handles connection requests from either known subsystems,
    or other clients. Other clients are admin processes.

    The protocol for connection from a known subsystem is:

        capture the name of the sub systems Sb API port

        Accept the connection

        Connect to the subsystems Sb API port

        Store the communication port handle in the known subsystem database

        signal the event associated with the known subsystem

    The protocol for others is to simply validate and accept the connection
    request.

Arguments:

Return Value:

    None.

--*/

{
    NTSTATUS st;
    HANDLE CommunicationPort;
    REMOTE_PORT_VIEW ClientView;
    PSBCONNECTINFO ConnectInfo;
    ULONG ConnectInfoLength;
    PSMPKNOWNSUBSYS KnownSubSys;
    BOOLEAN Accept;
    UNICODE_STRING SubSystemPort;
    SECURITY_QUALITY_OF_SERVICE DynamicQos;
    PSMP_CLIENT_CONTEXT ClientContext;

    //
    // Set up the security quality of service parameters to use over the
    // sb API port.  Use the most efficient (least overhead) - which is dynamic
    // rather than static tracking.
    //

    DynamicQos.ImpersonationLevel = SecurityIdentification;
    DynamicQos.ContextTrackingMode = SECURITY_DYNAMIC_TRACKING;
    DynamicQos.EffectiveOnly = TRUE;


    ConnectInfo = &Message->ConnectionRequest;
    KnownSubSys = SmpLocateKnownSubSysByCid(&Message->h.ClientId);

    if ( KnownSubSys ) {

        if ( SmpLocateKnownSubSysByType(ConnectInfo->SubsystemImageType) ==
             KnownSubSys ) {
            Accept = FALSE;
            KdPrint(("SMSS: Connection from SubSystem rejected\n"));
            KdPrint(("SMSS: Image type already being served\n"));
        } else {
            Accept = TRUE;
            KnownSubSys->ImageType = ConnectInfo->SubsystemImageType;
        }
    } else {

        //
        // Authenticate the SOB
        //

        Accept = TRUE;

    }

    if (Accept) {
        ClientContext = RtlAllocateHeap(SmpHeap, MAKE_TAG( SM_TAG ), sizeof(SMP_CLIENT_CONTEXT));
        ClientContext->KnownSubSys = KnownSubSys;
    }

    ClientView.Length = sizeof(ClientView);
    st = NtAcceptConnectPort(
            &CommunicationPort,
            ClientContext,
            (PPORT_MESSAGE)Message,
            Accept,
            NULL,
            &ClientView
            );
    ASSERT( NT_SUCCESS(st) );

    if ( Accept ) {

        if ( KnownSubSys ) {
            KnownSubSys->SmApiCommunicationPort = CommunicationPort;
        }

        st = NtCompleteConnectPort(CommunicationPort);
        ASSERT( NT_SUCCESS(st) );

        //
        // Connect Back to subsystem
        //

        if ( KnownSubSys ) {
            RtlCreateUnicodeString( &SubSystemPort,
                                    ConnectInfo->EmulationSubSystemPortName
                                  );
            ConnectInfoLength = sizeof( *ConnectInfo );

            st = NtConnectPort(
                    &KnownSubSys->SbApiCommunicationPort,
                    &SubSystemPort,
                    &DynamicQos,
                    NULL,
                    NULL,
                    NULL,
                    NULL,
                    NULL
                    );
            if ( !NT_SUCCESS(st) ) {
                KdPrint(("SMSS: Connect back to Sb %wZ failed %lx\n",&SubSystemPort,st));
            }

            RtlFreeUnicodeString( &SubSystemPort );
            NtSetEvent(KnownSubSys->Active,NULL);
        }
    }

    return st;
}
Esempio n. 2
0
NTSTATUS
NTAPI
SmpHandleConnectionRequest(IN HANDLE SmApiPort,
                           IN PSB_API_MSG SbApiMsg)
{
    BOOLEAN Accept = TRUE;
    HANDLE PortHandle, ProcessHandle;
    ULONG SessionId;
    UNICODE_STRING SubsystemPort;
    SMP_CLIENT_CONTEXT *ClientContext;
    NTSTATUS Status;
    OBJECT_ATTRIBUTES ObjectAttributes;
    REMOTE_PORT_VIEW PortView;
    SECURITY_QUALITY_OF_SERVICE SecurityQos;
    PSMP_SUBSYSTEM CidSubsystem, TypeSubsystem;

    /* Initialize QoS data */
    SecurityQos.ImpersonationLevel = SecurityIdentification;
    SecurityQos.ContextTrackingMode = SECURITY_DYNAMIC_TRACKING;
    SecurityQos.EffectiveOnly = TRUE;

    /* Check if this is SM connecting to itself */
    if (SbApiMsg->h.ClientId.UniqueProcess == SmUniqueProcessId)
    {
        /* No need to get any handle -- assume session 0 */
        ProcessHandle = NULL;
        SessionId = 0;
    }
    else
    {
        /* Reference the foreign process */
        InitializeObjectAttributes(&ObjectAttributes, NULL, 0, NULL, NULL);
        Status = NtOpenProcess(&ProcessHandle,
                               PROCESS_QUERY_INFORMATION,
                               &ObjectAttributes,
                               &SbApiMsg->h.ClientId);
        if (!NT_SUCCESS(Status)) Accept = FALSE;

        /* Get its session ID */
        SmpGetProcessMuSessionId(ProcessHandle, &SessionId);
    }

    /* See if we already know about the caller's subystem */
    CidSubsystem = SmpLocateKnownSubSysByCid(&SbApiMsg->h.ClientId);
    if ((CidSubsystem) && (Accept))
    {
        /* Check if we already have a subsystem for this kind of image */
        TypeSubsystem = SmpLocateKnownSubSysByType(SessionId,
                                                   SbApiMsg->ConnectionInfo.SubsystemType);
        if (TypeSubsystem == CidSubsystem)
        {
            /* Someone is trying to take control of an existing subsystem, fail */
            Accept = FALSE;
            DPRINT1("SMSS: Connection from SubSystem rejected\n");
            DPRINT1("SMSS: Image type already being served\n");
        }
        else
        {
            /* Set this image type as the type for this subsystem */
            CidSubsystem->ImageType = SbApiMsg->ConnectionInfo.SubsystemType;
        }

        /* Drop the reference we had acquired */
        if (TypeSubsystem) SmpDereferenceSubsystem(TypeSubsystem);
    }

    /* Check if we'll be accepting the connection */
    if (Accept)
    {
        /* We will, so create a client context for it */
        ClientContext = RtlAllocateHeap(SmpHeap, 0, sizeof(SMP_CLIENT_CONTEXT));
        if (ClientContext)
        {
            ClientContext->ProcessHandle = ProcessHandle;
            ClientContext->Subsystem = CidSubsystem;
            ClientContext->dword10 = 0;
            ClientContext->PortHandle = NULL;
        }
        else
        {
            /* Failed to allocate a client context, so reject the connection */
            DPRINT1("Rejecting connectiond due to lack of memory\n");
            Accept = FALSE;
        }
    }
    else
    {
        /* Use a bogus context since we're going to reject the message */
        ClientContext = (PSMP_CLIENT_CONTEXT)SbApiMsg;
    }

    /* Now send the actual accept reply (which could be a rejection) */
    PortView.Length = sizeof(PortView);
    Status = NtAcceptConnectPort(&PortHandle,
                                 ClientContext,
                                 &SbApiMsg->h,
                                 Accept,
                                 NULL,
                                 &PortView);
    if (!(Accept) || !(NT_SUCCESS(Status)))
    {
        /* Close the process handle, reference the subsystem, and exit */
        DPRINT1("Accept failed or rejected: %lx\n", Status);
        if (ClientContext != (PVOID)SbApiMsg) RtlFreeHeap(SmpHeap, 0, ClientContext);
        if (ProcessHandle) NtClose(ProcessHandle);
        if (CidSubsystem) SmpDereferenceSubsystem(CidSubsystem);
        return Status;
    }

    /* Save the port handle now that we've accepted it */
    if (ClientContext) ClientContext->PortHandle = PortHandle;
    if (CidSubsystem) CidSubsystem->PortHandle = PortHandle;

    /* Complete the port connection */
    Status = NtCompleteConnectPort(PortHandle);
    if ((NT_SUCCESS(Status)) && (CidSubsystem))
    {
        /* This was an actual subsystem, so connect back to it */
        SbApiMsg->ConnectionInfo.SbApiPortName[119] = UNICODE_NULL;
        RtlCreateUnicodeString(&SubsystemPort,
                               SbApiMsg->ConnectionInfo.SbApiPortName);
        Status = NtConnectPort(&CidSubsystem->SbApiPort,
                               &SubsystemPort,
                               &SecurityQos,
                               NULL,
                               NULL,
                               NULL,
                               NULL,
                               NULL);
        if (!NT_SUCCESS(Status))
        {
            DPRINT1("SMSS: Connect back to Sb %wZ failed %lx\n", &SubsystemPort, Status);
        }
        RtlFreeUnicodeString(&SubsystemPort);

        /* Now that we're connected, signal the event handle */
        NtSetEvent(CidSubsystem->Event, NULL);
    }
    else if (CidSubsystem)
    {
        /* We failed to complete the connection, so clear the port handle */
        DPRINT1("Completing the connection failed: %lx\n", Status);
        CidSubsystem->PortHandle = NULL;
    }

    /* Dereference the subsystem and return the result */
    if (CidSubsystem) SmpDereferenceSubsystem(CidSubsystem);
    return Status;
}