⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 context.cxx

📁 安全支持提供器接口(SSPI)源码
💻 CXX
📖 第 1 页 / 共 5 页
字号:
    // capabilities in the challenge message.
    //

    if ((ContextReqFlags & ISC_REQ_DATAGRAM) == 0) {

        BOOLEAN CheckForLocal;

        if ( (Credential->DomainName.Buffer == NULL &&
              Credential->UserName.Buffer == NULL &&
              Credential->Password.Buffer == NULL ) &&
             (Credential->ClientTokenHandle != NULL) )
        {
            CheckForLocal = TRUE;
        } else {
            CheckForLocal = FALSE;
        }


        if( CheckForLocal ) {

            //
            // snap up a copy of the globals so we can just take the critsect once.
            // the old way took the critsect twice, once to read sizes, second time
            // to grab buffers - bad news if the global got bigger in between.
            //

            EnterCriticalSection (&NtLmGlobalCritSect);

            if( NtLmGlobalOemComputerNameString.Buffer == NULL ||
                NtLmGlobalOemPrimaryDomainNameString.Buffer == NULL ) {

                //
                // user has picked a computer name or domain name
                // that failed to convert to OEM.  disable the loopback
                // detection.
                // Sometime beyond Win2k, Negotiate package should have
                // a general, robust scheme for detecting loopback.
                //

                CheckForLocal = FALSE;

            } else {

                Status = NtLmDuplicateString(
                                        &NtLmLocalOemComputerNameString,
                                        &NtLmGlobalOemComputerNameString
                                        );

                if( NT_SUCCESS(Status) ) {
                    Status = NtLmDuplicateString(
                                            &NtLmLocalOemPrimaryDomainNameString,
                                            &NtLmGlobalOemPrimaryDomainNameString
                                            );
                }

            }

            LeaveCriticalSection (&NtLmGlobalCritSect);


            if (!NT_SUCCESS(Status)) {
                SspPrint(( SSP_CRITICAL,
                "SsprHandleFirstCall: NtLmDuplicateUnicodeString (GlobalOemComputerName or GlobalOemPrimaryDomainName) returned %d\n", Status ));
                goto Cleanup;
            }
        }


        //
        // Allocate a Negotiate message
        //

        NegotiateMessageSize = sizeof(*NegotiateMessage) +
                               NtLmLocalOemComputerNameString.Length +
                               NtLmLocalOemPrimaryDomainNameString.Length;

        if ((ContextReqFlags & ISC_REQ_ALLOCATE_MEMORY) == 0)
        {
            if ( NegotiateMessageSize > *OutputTokenSize ) {
                Status = SEC_E_BUFFER_TOO_SMALL;
                SspPrint(( SSP_CRITICAL,
                "SsprHandleFirstCall: OutputTokenSize is %d\n", *OutputTokenSize));
                goto Cleanup;
            }
        }

        NegotiateMessage = (PNEGOTIATE_MESSAGE)
                           NtLmAllocate( NegotiateMessageSize );

        if ( NegotiateMessage == NULL) {
            Status = STATUS_NO_MEMORY;
            SspPrint(( SSP_CRITICAL, "SsprHandleFirstCall: Error allocating NegotiateMessage.\n"));
            goto Cleanup;
        }

        //
        // If this is the first call,
        //  build a Negotiate message.
        //

        strcpy( (char *) NegotiateMessage->Signature, NTLMSSP_SIGNATURE );
        NegotiateMessage->MessageType = NtLmNegotiate;
        NegotiateMessage->NegotiateFlags = Context->NegotiateFlags;

        IF_DEBUG( REQUEST_TARGET ) {
            NegotiateMessage->NegotiateFlags |= NTLMSSP_REQUEST_TARGET;
        }

        //
        // Copy the DomainName and ComputerName into the negotiate message so
        // the other side can determine if this is a call from the local system.
        //
        // Pass the names in the OEM character set since the character set
        // hasn't been negotiated yet.
        //
        // Skip passing the workstation name if credentials were specified. This
        // ensures the other side doesn't fall into the case that this is the
        // local system.  We wan't to ensure the new credentials are
        // authenticated.
        //

        Where = (PCHAR)(NegotiateMessage+1);

        if ( CheckForLocal ) {

            SspContextCopyString( NegotiateMessage,
                                  &NegotiateMessage->OemWorkstationName,
                                  &NtLmLocalOemComputerNameString,
                                  &Where );

            NegotiateMessage->NegotiateFlags |=
                              NTLMSSP_NEGOTIATE_OEM_WORKSTATION_SUPPLIED;


            //
            // OEM_DOMAIN_SUPPLIED used to always be supplied - but the
            // only case it is ever used is when NTLMSSP_NEGOTIATE_LOCAL_CALL
            // is set.
            //

            SspContextCopyString( NegotiateMessage,
                                  &NegotiateMessage->OemDomainName,
                                  &NtLmLocalOemPrimaryDomainNameString,
                                  &Where );

            NegotiateMessage->NegotiateFlags |=
                                  NTLMSSP_NEGOTIATE_OEM_DOMAIN_SUPPLIED;

        }

        if ((ContextReqFlags & ISC_REQ_ALLOCATE_MEMORY) == 0)
        {
            RtlCopyMemory( *OutputToken,
                       NegotiateMessage,
                       NegotiateMessageSize );

        }
        else
        {
            *OutputToken = NegotiateMessage;
            NegotiateMessage = NULL;
            *ContextAttributes |= ISC_RET_ALLOCATED_MEMORY;
        }

        *OutputTokenSize = NegotiateMessageSize;

    }

    //
    // Save a reference to the credential in the context.
    //

    Context->Credential = Credential;
    Credential = NULL;

    //
    // Check for a caller requesting datagram security.
    //

    if ((ContextReqFlags & ISC_REQ_DATAGRAM) != 0) {
        Context->NegotiateFlags |= NTLMSSP_NEGOTIATE_DATAGRAM;
        Context->NegotiateFlags &= ~NTLMSSP_NEGOTIATE_NT_ONLY;
        Context->ContextFlags |= ISC_RET_DATAGRAM;
        *ContextAttributes |= ISC_RET_DATAGRAM;

        // If datagram security is required, then we don't send back a token

        *OutputTokenSize = 0;



        //
        // Generate a session key for this context if sign or seal was
        // requested.
        //

        if ((Context->NegotiateFlags & (NTLMSSP_NEGOTIATE_SIGN |
                                       NTLMSSP_NEGOTIATE_SEAL)) != 0) {

            Status = SspGenerateRandomBits(
                                Context->SessionKey,
                                MSV1_0_USER_SESSION_KEY_LENGTH
                                );

            if( !NT_SUCCESS( Status ) ) {
                SspPrint(( SSP_CRITICAL,
                "SsprHandleFirstCall: SspGenerateRandomBits failed\n"));
                goto Cleanup;
            }
        }
        RtlCopyMemory(
            SessionKey,
            Context->SessionKey,
            MSV1_0_USER_SESSION_KEY_LENGTH
            );


        //
        // Unless client wants to force its use,
        // Turn off strong crypt, because we can't negotiate it.
        //

        if (!NtLmGlobalDatagramUse128BitEncryption) {
            Context->NegotiateFlags &= ~NTLMSSP_NEGOTIATE_128;
        }

        //
        // likewise for 56bit.  note that package init handles turning
        // off 56bit if 128bit is configured for datagram.
        //

        if(!NtLmGlobalDatagramUse56BitEncryption) {
            Context->NegotiateFlags &= ~NTLMSSP_NEGOTIATE_56;
        }

        //
        //  Unless client wants to require NTLM2, can't use its
        //  message processing features because we start using
        //  MD5 sigs, full duplex mode, and datagram rekey before
        //  we know if the server supports NTLM2.
        //

        if (!NtLmGlobalRequireNtlm2) {
            Context->NegotiateFlags &= ~NTLMSSP_NEGOTIATE_NTLM2;
        }

        //
        // done fiddling with the negotiate flags, output them.
        //

        *NegotiateFlags = Context->NegotiateFlags;

        //
        // send back the negotiate flags to control signing and sealing
        //

        *NegotiateFlags |= NTLMSSP_APP_SEQ;

    }

    if( Context->NegotiateFlags & NTLMSSP_NEGOTIATE_KEY_EXCH )
    {
        Status = SspGenerateRandomBits(
                            Context->SessionKey,
                            MSV1_0_USER_SESSION_KEY_LENGTH
                            );

        if( !NT_SUCCESS( Status ) ) {
            SspPrint(( SSP_CRITICAL,
            "SsprHandleFirstCall: SspGenerateRandomBits failed\n"));
            goto Cleanup;
        }

        RtlCopyMemory(
            SessionKey,
            Context->SessionKey,
            MSV1_0_USER_SESSION_KEY_LENGTH
            );
    }

    //
    // Return output parameters to the caller.
    //

    *ExpirationTime = SspContextGetTimeStamp( Context, TRUE );

    Status = SEC_I_CONTINUE_NEEDED;
    Context->State = NegotiateSentState;


    SspPrint(( SSP_NEGOTIATE_FLAGS,
        "SsprHandleFirstCall: NegotiateFlags = %lx\n", Context->NegotiateFlags));


    //
    // Check that caller asked for minimum security required.
    //

    if (!SsprCheckMinimumSecurity(
                        Context->NegotiateFlags,
                        NtLmGlobalMinimumClientSecurity)) {

        Status = SEC_E_UNSUPPORTED_FUNCTION;

        SspPrint(( SSP_CRITICAL,
                  "SsprHandleFirstCall: "
                  "Caller didn't request minimum security requirements (caller=0x%lx wanted=0x%lx).\n",
                    Context->NegotiateFlags, NtLmGlobalMinimumClientSecurity ));
        goto Cleanup;
    }


    //
    // Free and locally used resources.
    //
Cleanup:

    if ( Context != NULL ) {

        //
        // If we failed,
        //  deallocate the context we allocated above.
        //
        // Delinking is a side effect of referencing, so do that.
        //

        if ( !NT_SUCCESS(Status) ) {

            PSSP_CONTEXT LocalContext;
            LocalContext = SspContextReferenceContext( *ContextHandle, TRUE );

            ASSERT( LocalContext != NULL );
            if ( LocalContext != NULL ) {
                SspContextDereferenceContext( LocalContext );
            }
        }

        // Always dereference it.

        SspContextDereferenceContext( Context );
    }

    if ( NegotiateMessage != NULL ) {
        (VOID) NtLmFree( NegotiateMessage );
    }

    if ( Credential != NULL ) {
        SspCredentialDereferenceCredential( Credential );
    }

    if ( NtLmLocalOemComputerNameString.Buffer != NULL ) {
        (VOID) NtLmFree( NtLmLocalOemComputerNameString.Buffer );
    }

    if ( NtLmLocalOemPrimaryDomainNameString.Buffer != NULL ) {
        (VOID) NtLmFree( NtLmLocalOemPrimaryDomainNameString.Buffer );
    }

    SspPrint(( SSP_API_MORE, "Leaving SsprHandleFirstCall: 0x%lx\n", Status ));
    return Status;

    UNREFERENCED_PARAMETER( InputToken );
    UNREFERENCED_PARAMETER( InputTokenSize );

}

NTSTATUS
SsprHandleNegotiateMessage(
    IN ULONG_PTR CredentialHandle,
    IN OUT PULONG_PTR ContextHandle,
    IN ULONG ContextReqFlags,
    IN ULONG InputTokenSize,
    IN PVOID InputToken,
    IN OUT PULONG OutputTokenSize,
    OUT PVOID *OutputToken,
    OUT PULONG ContextAttributes,
    OUT PTimeStamp ExpirationTime
    )

/*++

Routine Description:

    Handle the Negotiate message part of AcceptSecurityContext.

Arguments:

    All arguments same as for AcceptSecurityContext

Return Value:

    STATUS_SUCCESS - Message handled
    SEC_I_CONTINUE_NEEDED -- Caller should call again later

    SEC_E_INVALID_TOKEN -- Token improperly formatted
    SEC_E_INVALID_HANDLE -- Credential/Context Handle is invalid
    SEC_E_BUFFER_TOO_SMALL -- Buffer for output token isn't big enough
    SEC_E_INSUFFICIENT_MEMORY -- Not enough memory

--*/

{
    NTSTATUS Status = STATUS_SUCCESS;
    PSSP_CONTEXT Context = NULL;
    PSSP_CREDENTIAL Credential = NULL;
    STRING TargetName;
    ULONG TargetFlags = 0;

    PNEGOTIATE_MESSAGE NegotiateMessage = NULL;

    PCHALLENGE_MESSAGE ChallengeMessage = NULL;
    ULONG ChallengeMessageSize = 0;
    PCHAR Where = NULL;

    ULONG NegotiateFlagsKeyStrength;

    UNICODE_STRING NtLmLocalUnicodeTargetName;
    UNICODE_STRING TargetInfo;
    STRING NtLmLocalOemTargetName;
    STRING OemWorkstationName;
    STRING OemDomainName;

    SspPrint(( SSP_API_MORE, "Entering SsprNegotiateMessage\n" ));
    //
    // Initialization
    //

    *ContextAttributes = 0;

    RtlInitString( &TargetName, NULL );

    RtlInitUnicodeString( &NtLmLocalUnicodeTargetName, NULL );
    RtlInitString( &NtLmLocalOemTargetName, NULL );

    RtlInitUnicodeString( &TargetInfo, NULL );

    //
    // Get a pointer to the credential
    //

    Status = SspCredentialReferenceCredential(
                    CredentialHandle,
                    FALSE,
                    FALSE,
                    &Credential );

    if ( !NT_SUCCESS( Status ) ) {
        SspPrint(( SSP_CRITICAL,
                "SsprHandleNegotiateMessage: invalid credential handle.\n" ));
        goto Cleanup;
    }

    if ( (Credential->CredentialUseFlags & SECPKG_CRED_INBOUND) == 0 ) {
        Status = SEC_E_INVALID_CREDENTIAL_USE;
        SspPrint(( SSP_CRITICAL,
            "SsprHandleNegotiateMessage: invalid credential use.\n" ));

⌨️ 快捷键说明

复制代码 Ctrl + C
搜索代码 Ctrl + F
全屏模式 F11
切换主题 Ctrl + Shift + D
显示快捷键 ?
增大字号 Ctrl + =
减小字号 Ctrl + -