Beispiel #1
0
VOID
SepRmCommandServerThread(
    IN PVOID StartContext
)

/*++

Routine Description:

    This function is executed indefinitely by a dedicated permanent thread
    of the Sysinit Process, called the Reference Monitor Server Thread.
    This thread updates Reference Monitor Global State Data by dispatching
    commands sent from the LSA through the the Reference Monitor LPC Command
    Port.  The following steps are repeated indefinitely:

    o  Initialize RM Command receive and reply buffer headers
    o  Perform remaining Reference Monitor initialization involving LSA
    o  Wait for RM command sent from LSA, send reply to previous command
       (if any)
    o  Validate command
    o  Dispatch to command worker routine to execute command.

Arguments:

    None.

Return Value:

    None.

--*/

{
    NTSTATUS Status;
    PRM_REPLY_MESSAGE Reply;
    RM_COMMAND_MESSAGE CommandMessage;
    RM_REPLY_MESSAGE ReplyMessage;

    PAGED_CODE();

    //
    // Perform the rest of the Reference Monitor initialization, involving
    // synchronization with the LSA or dependency on the LSA having run.
    //

    if (!SepRmCommandServerThreadInit()) {

        KdPrint(("Security: Terminating Rm Command Server Thread\n"));
        return;
    }

    //
    // Initialize LPC port message header type and length fields for the
    // received command message.
    //

    CommandMessage.MessageHeader.u2.ZeroInit = 0;
    CommandMessage.MessageHeader.u1.s1.TotalLength =
        (CSHORT) sizeof(RM_COMMAND_MESSAGE);
    CommandMessage.MessageHeader.u1.s1.DataLength =
    CommandMessage.MessageHeader.u1.s1.TotalLength -
        (CSHORT) sizeof(PORT_MESSAGE);

    //
    // Initialize the LPC port message header type and data sizes for
    // for the reply message.
    //

    ReplyMessage.MessageHeader.u2.ZeroInit = 0;
    ReplyMessage.MessageHeader.u1.s1.TotalLength =
        (CSHORT) sizeof(RM_COMMAND_MESSAGE);
    ReplyMessage.MessageHeader.u1.s1.DataLength =
    ReplyMessage.MessageHeader.u1.s1.TotalLength -
        (CSHORT) sizeof(PORT_MESSAGE);

    //
    // First time through, there is no reply.
    //

    Reply = NULL;

    //
    // Now loop indefinitely, processing incoming Rm commands from the LSA.
    //

    for(;;) {

        //
        // Wait for Command, send reply to previous command (if any)
        //

        Status = ZwReplyWaitReceivePort(
                    SepRmState.RmCommandPortHandle,
                    NULL,
                    (PPORT_MESSAGE) Reply,
                    (PPORT_MESSAGE) &CommandMessage
                    );

        if (!NT_SUCCESS(Status)) {

            //
            // malicious user apps can try to connect to this port.  We will
            // fail later, but if their thread vanishes, we'll get a failure
            // here.  Ignore it:
            //

            if ( Status == STATUS_UNSUCCESSFUL )
            {
                //
                // skip it:
                //

                Reply = NULL ;
                continue;
            }

            KdPrint(("Security: RM message receive from Lsa failed %lx\n",
                Status));

        }

        //
        // Now dispatch to a routine to handle the command.  Allow
        // command errors to occur without bringing system down just now.
        //

        if ( CommandMessage.MessageHeader.u2.s2.Type == LPC_REQUEST ) {
            (*(SepRmCommandDispatch[CommandMessage.CommandNumber]))
                (&CommandMessage, &ReplyMessage);

            //
            // Initialize the client thread info and message id for the
            // reply message.  First time through, the reply message structure
            // is not used.
            //

            ReplyMessage.MessageHeader.ClientId =
                CommandMessage.MessageHeader.ClientId;
            ReplyMessage.MessageHeader.MessageId =
                CommandMessage.MessageHeader.MessageId;

            Reply = &ReplyMessage;

        } else {

            Reply = NULL;
        }
    }  // end_for

    //
    // Make compiler ferme la bouche
    //

    StartContext;
}
Beispiel #2
0
VOID
SepRmCommandServerThread(
    IN PVOID StartContext
)

/*++

Routine Description:

    This function is executed indefinitely by a dedicated permanent thread
    of the Sysinit Process, called the Reference Monitor Server Thread.
    This thread updates Reference Monitor Global State Data by dispatching
    commands sent from the LSA through the the Reference Monitor LPC Command
    Port.  The following steps are repeated indefinitely:

    o  Initialize RM Command receive and reply buffer headers
    o  Perform remaining Reference Monitor initialization involving LSA
    o  Wait for RM command sent from LSA, send reply to previous command
       (if any)
    o  Validate command
    o  Dispatch to command worker routine to execute command.

Arguments:

    None.

Return Value:

    None.

--*/

{
    NTSTATUS Status;
    PRM_REPLY_MESSAGE Reply;
    RM_COMMAND_MESSAGE CommandMessage;
    RM_REPLY_MESSAGE ReplyMessage;

    PAGED_CODE();

    //
    // Perform the rest of the Reference Monitor initialization, involving
    // synchronization with the LSA or dependency on the LSA having run.
    //

    if (!SepRmCommandServerThreadInit()) {

        KdPrint(("Security: Terminating Rm Command Server Thread\n"));
        return;
    }

    Status = PoRequestShutdownEvent (NULL);
    if (!NT_SUCCESS (Status)) {
        ZwClose (SepRmState.RmCommandPortHandle);
        ZwClose (SepRmState.RmCommandServerPortHandle);
        ZwClose (SepRmState.LsaCommandPortHandle);
        ZwClose (SepLsaHandle);
        SepRmState.RmCommandPortHandle = NULL;
        SepRmState.RmCommandServerPortHandle = NULL;
        SepRmState.LsaCommandPortHandle = NULL;
        SepLsaHandle = NULL;
        return;
    }

    //
    // Initialize LPC port message header type and length fields for the
    // received command message.
    //

    CommandMessage.MessageHeader.u2.ZeroInit = 0;
    CommandMessage.MessageHeader.u1.s1.TotalLength =
        (CSHORT) sizeof(RM_COMMAND_MESSAGE);
    CommandMessage.MessageHeader.u1.s1.DataLength =
    CommandMessage.MessageHeader.u1.s1.TotalLength -
        (CSHORT) sizeof(PORT_MESSAGE);

    //
    // Initialize the LPC port message header type and data sizes for
    // for the reply message.
    //

    ReplyMessage.MessageHeader.u2.ZeroInit = 0;
    ReplyMessage.MessageHeader.u1.s1.TotalLength =
        (CSHORT) sizeof(RM_COMMAND_MESSAGE);
    ReplyMessage.MessageHeader.u1.s1.DataLength =
    ReplyMessage.MessageHeader.u1.s1.TotalLength -
        (CSHORT) sizeof(PORT_MESSAGE);

    //
    // First time through, there is no reply.
    //

    Reply = NULL;

    //
    // Now loop indefinitely, processing incoming Rm commands from the LSA.
    //

    for(;;) {

        //
        // Wait for Command, send reply to previous command (if any)
        //

        Status = ZwReplyWaitReceivePort(
                    SepRmState.RmCommandPortHandle,
                    NULL,
                    (PPORT_MESSAGE) Reply,
                    (PPORT_MESSAGE) &CommandMessage
                    );

        if (!NT_SUCCESS(Status)) {

            //
            // malicious user apps can try to connect to this port.  We will
            // fail later, but if their thread vanishes, we'll get a failure
            // here.  Ignore it:
            //

            if (Status == STATUS_UNSUCCESSFUL ||
                Status == STATUS_INVALID_CID ||
                Status == STATUS_REPLY_MESSAGE_MISMATCH)
            {
                //
                // skip it:
                //

                Reply = NULL ;
                continue;
            }

            KdPrint(("Security: RM message receive from Lsa failed %lx\n",
                Status));

        }

        //
        // Now dispatch to a routine to handle the command.  Allow
        // command errors to occur without bringing system down just now.
        //

        CommandMessage.MessageHeader.u2.s2.Type &= ~LPC_KERNELMODE_MESSAGE;

        if ( CommandMessage.MessageHeader.u2.s2.Type == LPC_REQUEST ) {

            if ( (CommandMessage.CommandNumber >= RmAuditSetCommand) &&
                 (CommandMessage.CommandNumber <= RmDeleteLogonSession) ) {

                (*(SepRmCommandDispatch[CommandMessage.CommandNumber]))
                    (&CommandMessage, &ReplyMessage);
                
                //
                // Initialize the client thread info and message id for the
                // reply message.  First time through, the reply message structure
                // is not used.
                //

                ReplyMessage.MessageHeader.ClientId =
                    CommandMessage.MessageHeader.ClientId;
                ReplyMessage.MessageHeader.MessageId =
                    CommandMessage.MessageHeader.MessageId;

                Reply = &ReplyMessage;
                
            } else {

                ASSERT( (CommandMessage.CommandNumber >= RmAuditSetCommand) &&
                        (CommandMessage.CommandNumber <= RmDeleteLogonSession) );
                Reply = NULL;
            }

        } else if (CommandMessage.MessageHeader.u2.s2.Type == LPC_PORT_CLOSED ) {
            KEVENT Event;
            BOOLEAN Wait;

            KeInitializeEvent (&Event, NotificationEvent, FALSE);

            SepLockLsaQueue();

            SepAdtLsaDeadEvent = &Event;
            
            Wait = !SepWorkListEmpty ();

            SepUnlockLsaQueue();

            if (Wait) {
                KeWaitForSingleObject (&Event,
                                       Executive,
                                       KernelMode,
                                       FALSE,
                                       NULL);
            }
            //
            // Our only client closed its handle. Tidy up and exit.
            //
            ZwClose (SepRmState.LsaCommandPortHandle);
            ZwClose (SepRmState.RmCommandPortHandle);
            ZwClose (SepRmState.RmCommandServerPortHandle);
            ZwClose (SepLsaHandle);
            SepRmState.LsaCommandPortHandle = NULL;
            SepRmState.RmCommandPortHandle = NULL;
            SepRmState.RmCommandServerPortHandle = NULL;
            SepLsaHandle = NULL;
            break;
        } else if (CommandMessage.MessageHeader.u2.s2.Type == LPC_CONNECTION_REQUEST) {
            HANDLE tmp;
            //
            // Reject extra connection attempts
            //
            Status = ZwAcceptConnectPort(&tmp,
                                         NULL,
                                         (PPORT_MESSAGE) &CommandMessage,
                                         FALSE,
                                         NULL,
                                         NULL);
        } else {

            Reply = NULL;
        }
    }  // end_for

    UNREFERENCED_PARAMETER( StartContext );

}