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

📄 context.cxx

📁 安全支持提供器接口(SSPI)源码
💻 CXX
📖 第 1 页 / 共 5 页
字号:
//      Context->SessionKey has the session key to be used for the rest of the session
//      if (DatagramSessionKey != NULL) then if KEY_EXCH then it has the encrypted session key
//      to send to the server, else it is zero length
//
--*/

{
    NTSTATUS Status;
    UCHAR LocalSessionKey[MSV1_0_USER_SESSION_KEY_LENGTH];

    // if we don't need to make any keys, just return
// RDR/SRV expect session key but don't ask for it! work-around this...
//    if ((Context->NegotiateFlags & (NTLMSSP_NEGOTIATE_SIGN| NTLMSSP_NEGOTIATE_SEAL)) == 0)
//        return(SEC_E_OK);

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

        RtlCopyMemory(
            Context->SessionKey,
            NtUserSessionKey,
            sizeof(LocalSessionKey)
            );

        return SEC_E_OK;
    }

    if (Context->NegotiateFlags & NTLMSSP_NEGOTIATE_NTLM2)
    {
        //
        // when using NTLM2, LSA gets passed flags that cause
        //  it to make good session keys -- nothing for us to do
        //

        RtlCopyMemory(
            LocalSessionKey,
            NtUserSessionKey,
            sizeof(LocalSessionKey)
            );
    }
    else if( Context->NegotiateFlags & NTLMSSP_NEGOTIATE_LM_KEY )
    {
        LM_OWF_PASSWORD LmKey;
        LM_RESPONSE LmResponseKey;

        BYTE TemporaryResponse[ LM_RESPONSE_LENGTH ];

        RtlZeroMemory(
            LocalSessionKey,
            MSV1_0_USER_SESSION_KEY_LENGTH
            );

        if (LmChallengeResponse->Length > LM_RESPONSE_LENGTH)
            return(SEC_E_UNSUPPORTED_FUNCTION);

        ZeroMemory( TemporaryResponse, sizeof(TemporaryResponse) );
        CopyMemory( TemporaryResponse, LmChallengeResponse->Buffer, LmChallengeResponse->Length );

        //
        // The LM session key is made by taking the LM sesion key
        // given to us by the LSA, extending it to LM_OWF_LENGTH
        // with our salt, and then producing a new challenge-response
        // with it and the original challenge response.  The key is
        // made from the first 8 bytes of the key.
        //

        RtlCopyMemory(  &LmKey,
                        LanmanSessionKey,
                        MSV1_0_LANMAN_SESSION_KEY_LENGTH );

        memset( (PUCHAR)(&LmKey) + MSV1_0_LANMAN_SESSION_KEY_LENGTH,
                NTLMSSP_KEY_SALT,
                LM_OWF_PASSWORD_LENGTH - MSV1_0_LANMAN_SESSION_KEY_LENGTH );

        Status = RtlCalculateLmResponse(
                    (PLM_CHALLENGE) TemporaryResponse,
                    &LmKey,
                    &LmResponseKey
                    );

        ZeroMemory( TemporaryResponse, sizeof(TemporaryResponse) );
        if (!NT_SUCCESS(Status))
            return(SspNtStatusToSecStatus(Status, SEC_E_NO_CREDENTIALS));

        RtlCopyMemory(
            LocalSessionKey,
            &LmResponseKey,
            MSV1_0_USER_SESSION_KEY_LENGTH
            );
    } else {

        RtlCopyMemory(
            LocalSessionKey,
            NtUserSessionKey,
            MSV1_0_USER_SESSION_KEY_LENGTH
            );
    }


    //
    // If we aren't doing key exchange, store the session key in the
    // context.  Otherwise encrypt the session key to send to the
    // server.
    //

    if (Context->NegotiateFlags & NTLMSSP_NEGOTIATE_KEY_EXCH) {

        struct RC4_KEYSTRUCT Rc4Key;

        //
        // make a key schedule from the temp key to form key exchange key
        //

        rc4_key(
            &Rc4Key,
            MSV1_0_USER_SESSION_KEY_LENGTH,
            LocalSessionKey
            );

        if (DatagramSessionKey == NULL)
        {
            //
            // decrypt what's in Context->SessionKey, leave it there
            //

            rc4(
                &Rc4Key,
                MSV1_0_USER_SESSION_KEY_LENGTH,
                Context->SessionKey
                );
        } else {

            //
            // set the proper length so client will send something (length was 0)
            //

            DatagramSessionKey->Length =
                DatagramSessionKey->MaximumLength =
                    MSV1_0_USER_SESSION_KEY_LENGTH;

            //
            // copy randomly generated key to buffer to send to server
            //

            RtlCopyMemory(
                DatagramSessionKey->Buffer,
                Context->SessionKey,
                MSV1_0_USER_SESSION_KEY_LENGTH
                );

            //
            // encrypt it with the key exchange key
            //

            rc4(
                &Rc4Key,
                MSV1_0_USER_SESSION_KEY_LENGTH,
                (unsigned char*)DatagramSessionKey->Buffer
                );
        }


    } else {

        //
        // just make the temp key into the real one
        //

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

    }
    return(SEC_E_OK);
}



NTSTATUS
SsprHandleFirstCall(
    IN LSA_SEC_HANDLE CredentialHandle,
    IN OUT PLSA_SEC_HANDLE ContextHandle,
    IN ULONG ContextReqFlags,
    IN ULONG InputTokenSize,
    IN PVOID InputToken,
    IN OUT PULONG OutputTokenSize,
    OUT PVOID *OutputToken,
    OUT PULONG ContextAttributes,
    OUT PTimeStamp ExpirationTime,
    OUT PUCHAR SessionKey,
    OUT PULONG NegotiateFlags
    )

/*++

Routine Description:

    Handle the First Call part of InitializeSecurityContext.

Arguments:

    All arguments same as for InitializeSecurityContext

Return Value:

    STATUS_SUCCESS -- All OK
    SEC_I_CONTINUE_NEEDED -- Caller should call again later

    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

--*/

{

    SspPrint(( SSP_API_MORE, "Entering SsprHandleFirstCall\n" ));
    NTSTATUS Status = STATUS_SUCCESS;
    PSSP_CONTEXT Context      = NULL;
    PSSP_CREDENTIAL Credential = NULL;

    PNEGOTIATE_MESSAGE NegotiateMessage = NULL;
    ULONG NegotiateMessageSize = 0;
    PCHAR Where = NULL;

    ULONG NegotiateFlagsKeyStrength;

    STRING NtLmLocalOemComputerNameString;
    STRING NtLmLocalOemPrimaryDomainNameString;

    INC_CLIENT_AUTH();

    //
    // Initialization
    //

    *ContextAttributes = 0;
    *NegotiateFlags = 0;

    RtlInitString( &NtLmLocalOemComputerNameString, NULL );
    RtlInitString( &NtLmLocalOemPrimaryDomainNameString, NULL );

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

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

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

    if ( (Credential->CredentialUseFlags & SECPKG_CRED_OUTBOUND) == 0 ) {
        Status = SEC_E_INVALID_CREDENTIAL_USE;
        SspPrint(( SSP_CRITICAL, "SsprHandleFirstCall: invalid credential use.\n" ));
        goto Cleanup;
    }

    //
    // Allocate a new context
    //

    Context = SspContextAllocateContext( );

    if ( Context == NULL) {
        Status = STATUS_NO_MEMORY;
        SspPrint(( SSP_CRITICAL, "SsprHandleFirstCall: SspContextAllocateContext returned NULL\n"));
        goto Cleanup;
    }

    //
    // Build a handle to the newly created context.
    //

    *ContextHandle = (LSA_SEC_HANDLE) Context;

    //
    // We don't support any options.
    //
    // Complain about those that require we do something.
    //

    if ( (ContextReqFlags & ISC_REQ_PROMPT_FOR_CREDS) != 0 ) {

        Status = SEC_E_INVALID_CONTEXT_REQ;
        SspPrint(( SSP_CRITICAL,
                   "SsprHandleFirstCall: invalid ContextReqFlags 0x%lx.\n",
                   ContextReqFlags ));
        goto Cleanup;
    }

    //
    // Capture the default credentials from the credential structure.
    //

    if ( Credential->DomainName.Buffer != NULL ) {
        Status = NtLmDuplicateUnicodeString(
                        &Context->DomainName,
                        &Credential->DomainName
                        );
        if (!NT_SUCCESS(Status)) {
            SspPrint(( SSP_CRITICAL,
            "SsprHandleFirstCall: NtLmDuplicateUnicodeString (DomainName) returned %d\n",Status));
            goto Cleanup;
        }
    }
    if ( Credential->UserName.Buffer != NULL ) {
        Status = NtLmDuplicateUnicodeString(
                        &Context->UserName,
                        &Credential->UserName
                        );
        if (!NT_SUCCESS(Status)) {
            SspPrint(( SSP_CRITICAL,
            "SsprHandleFirstCall: NtLmDuplicateUnicodeString (UserName) returned %d\n", Status ));
            goto Cleanup;
        }
    }

    Status = SspCredentialGetPassword(
                    Credential,
                    &Context->Password
                    );

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

    //
    // Compute the negotiate flags
    //


    //
    // Supported key strength(s)
    //

    NegotiateFlagsKeyStrength = NTLMSSP_NEGOTIATE_56;

    if( NtLmSecPkg.MachineState & SECPKG_STATE_STRONG_ENCRYPTION_PERMITTED )
    {
        NegotiateFlagsKeyStrength |= NTLMSSP_NEGOTIATE_128;
    }


    Context->NegotiateFlags = NTLMSSP_NEGOTIATE_UNICODE |
                              NTLMSSP_NEGOTIATE_OEM |
                              NTLMSSP_NEGOTIATE_NTLM |
                              ((NtLmGlobalLmProtocolSupported != 0)
                               ? NTLMSSP_NEGOTIATE_NTLM2 : 0 ) |
                              NTLMSSP_REQUEST_TARGET |
                              NTLMSSP_NEGOTIATE_ALWAYS_SIGN |
                              NegotiateFlagsKeyStrength;


    //
    // If the caller specified INTEGRITY, SEQUENCE_DETECT or REPLAY_DETECT,
    // that means they want to use the MakeSignature/VerifySignature
    // calls.  Add this to the negotiate.
    //

    if (ContextReqFlags &
        (ISC_REQ_INTEGRITY | ISC_REQ_SEQUENCE_DETECT | ISC_REQ_REPLAY_DETECT))
    {
        Context->NegotiateFlags |= NTLMSSP_NEGOTIATE_SIGN |
                                   NTLMSSP_NEGOTIATE_KEY_EXCH |
                                   NTLMSSP_NEGOTIATE_LM_KEY ;
    }


    if ((ContextReqFlags & ISC_REQ_INTEGRITY) != 0)
    {
        *ContextAttributes |= ISC_RET_INTEGRITY;
        Context->ContextFlags |= ISC_RET_INTEGRITY;
    }


    if ((ContextReqFlags & ISC_REQ_SEQUENCE_DETECT) != 0)
    {
        *ContextAttributes |= ISC_RET_SEQUENCE_DETECT;
        Context->ContextFlags |= ISC_RET_SEQUENCE_DETECT;
    }

    if ((ContextReqFlags & ISC_REQ_REPLAY_DETECT) != 0)
    {
        *ContextAttributes |= ISC_RET_REPLAY_DETECT;
        Context->ContextFlags |= ISC_RET_REPLAY_DETECT;
    }

    if ( (ContextReqFlags & ISC_REQ_NULL_SESSION ) != 0) {

        *ContextAttributes |= ISC_RET_NULL_SESSION;
        Context->ContextFlags |= ISC_RET_NULL_SESSION;
    }

    if ( (ContextReqFlags & ISC_REQ_CONNECTION ) != 0) {

        *ContextAttributes |= ISC_RET_CONNECTION;
        Context->ContextFlags |= ISC_RET_CONNECTION;
    }



    if ((ContextReqFlags & ISC_REQ_CONFIDENTIALITY) != 0) {
        if (NtLmGlobalEncryptionEnabled) {
            Context->NegotiateFlags |= NTLMSSP_NEGOTIATE_SEAL |
                                       NTLMSSP_NEGOTIATE_LM_KEY |
                                       NTLMSSP_NEGOTIATE_KEY_EXCH ;

            *ContextAttributes |= ISC_RET_CONFIDENTIALITY;
            Context->ContextFlags |= ISC_RET_CONFIDENTIALITY;
        } else {
            Status = STATUS_NOT_SUPPORTED;
            SspPrint(( SSP_CRITICAL,
            "SsprHandleFirstCall: NtLmGlobalEncryptionEnabled is FALSE\n"));
            goto Cleanup;
        }
    }

    //
    // Check if the caller wants identify level
    //

    if ((ContextReqFlags & ISC_REQ_IDENTIFY)!= 0)  {
        Context->NegotiateFlags |= NTLMSSP_NEGOTIATE_IDENTIFY;
        *ContextAttributes |= ISC_RET_IDENTIFY;
        Context->ContextFlags |= ISC_RET_IDENTIFY;
    }

    IF_DEBUG( USE_OEM ) {
        Context->NegotiateFlags &= ~NTLMSSP_NEGOTIATE_UNICODE;
    }

    if ( ((ContextReqFlags & ISC_REQ_MUTUAL_AUTH) != 0 ) &&
         (NtLmGlobalMutualAuthLevel < 2 ) ) {

        *ContextAttributes |= ISC_RET_MUTUAL_AUTH ;

        if ( NtLmGlobalMutualAuthLevel == 0 )
        {
            Context->ContextFlags |= ISC_RET_MUTUAL_AUTH ;
        }

    }
    //
    // For connection oriented security, we send a negotiate message to
    // the server.  For datagram, we get back the server's

⌨️ 快捷键说明

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