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

📄 userapi.cxx

📁 安全支持提供器接口(SSPI)源码
💻 CXX
📖 第 1 页 / 共 5 页
字号:
    SspPrint(( SSP_API, "Entering SpDeleteUserModeContext 0x%lx\n", ContextHandle ));
    PNTLM_CLIENT_CONTEXT pContext = NULL;
    NTSTATUS Status = STATUS_SUCCESS, SaveStatus = STATUS_SUCCESS;

    //
    // Find the currently existing user context and delink it    // so that another context cannot Reference it before we
    // Dereference this one.
    //

    pContext = ReferenceUserContext(ContextHandle, TRUE);

    if (pContext == NULL)
    {
        //
        // pContext is legally NULL when we are dealing with an incomplete
        // context.  This can often be the case when the second call to
        // InitializeSecurityContext() fails.
        //
///        Status = STATUS_INVALID_HANDLE;
        Status = STATUS_SUCCESS;
        SspPrint(( SSP_API_MORE, "SpDeleteUserModeContext, local pContext is NULL\n" ));
        goto CleanUp;
    }

    RtlEnterCriticalSection(&NtLmUserContextLock);

    if ((pContext->NegotiateFlags & NTLMSSP_NEGOTIATE_EXPORTED_CONTEXT) != 0)
    {
        // Ignore all other errors and pass back
        SaveStatus = SEC_I_NO_LSA_CONTEXT;
    }

    RtlLeaveCriticalSection(&NtLmUserContextLock);

CleanUp:

    if (pContext != NULL)
    {
        Status = DereferenceUserContext(pContext);
    }

    if (SaveStatus == SEC_I_NO_LSA_CONTEXT)
    {
        Status = SaveStatus;
    }

    SspPrint(( SSP_API, "Leaving SpDeleteUserModeContext: 0x%lx\n", Status ));
    return(SspNtStatusToSecStatus(Status, SEC_E_INTERNAL_ERROR));
}


VOID
SspRc4Key(
    IN ULONG                NegotiateFlags,
    OUT struct RC4_KEYSTRUCT *pRc4Key,
    IN PUCHAR               pSessionKey
    )
/*++

RoutineDescription:

    Create an RC4 key schedule, making sure key length is OK for export

Arguments:

    NegotiateFlags  negotiate feature flags; NTLM2 bit is only one looked at
    pRc4Key         pointer to RC4 key schedule structure; filled in by this routine
    pSessionKey     pointer to session key -- must be full 16 bytes

Return Value:

--*/
{
    //
    // For NTLM2, effective length was already cut down
    //

    if ((NegotiateFlags & NTLMSSP_NEGOTIATE_NTLM2) != 0) {

        rc4_key(pRc4Key, MSV1_0_USER_SESSION_KEY_LENGTH, pSessionKey);

    } else if( NegotiateFlags & NTLMSSP_NEGOTIATE_LM_KEY ) {
        UCHAR Key[MSV1_0_LANMAN_SESSION_KEY_LENGTH];
        ULONG KeyLen;

        ASSERT(MSV1_0_LANMAN_SESSION_KEY_LENGTH == 8);

        // prior to Win2k, negotiated key strength had no bearing on
        // key size.  So, to allow proper interop to NT4, we don't
        // worry about 128bit.  56bit and 40bit are the only supported options.
        // 56bit is enabled because this was introduced in Win2k, and
        // Win2k -> Win2k interops correctly.
        //
#if 0
        if( NegotiateFlags & NTLMSSP_NEGOTIATE_128 ) {
            KeyLen = 8;

        } else
#endif
        if( NegotiateFlags & NTLMSSP_NEGOTIATE_56 ) {
            KeyLen = 7;

            //
            // Put a well-known salt at the end of the key to
            // limit the changing part to 56 bits.
            //

            Key[7] = 0xa0;
        } else {
            KeyLen = 5;

            //
            // Put a well-known salt at the end of the key to
            // limit the changing part to 40 bits.
            //

            Key[5] = 0xe5;
            Key[6] = 0x38;
            Key[7] = 0xb0;
        }

        SspPrint(( SSP_SESSION_KEYS, "Non NTLMv2 LM_KEY session key size: %lu\n", KeyLen));

        RtlCopyMemory(Key,pSessionKey,KeyLen);

        rc4_key(pRc4Key, MSV1_0_LANMAN_SESSION_KEY_LENGTH, Key);

    } else {

        SspPrint(( SSP_SESSION_KEYS, "Non NTLMv2 (not LM_KEY) session key size: %lu\n", 16));
        rc4_key(pRc4Key, MSV1_0_USER_SESSION_KEY_LENGTH, pSessionKey);
    }
}



//+-------------------------------------------------------------------------
//
//  Function:   SpInitUserModeContext
//
//  Synopsis:   Creates a user-mode context from a packed LSA mode context
//
//  Effects:
//
//  Arguments:  ContextHandle - Lsa mode context handle for the context
//              PackedContext - A marshalled buffer containing the LSA
//                  mode context.
//
//  Requires:
//
//  Returns:    STATUS_SUCCESS or STATUS_INSUFFICIENT_RESOURCES
//
//  Notes:
//
//
//--------------------------------------------------------------------------


NTSTATUS NTAPI
SpInitUserModeContext(
    IN ULONG_PTR ContextHandle,
    IN PSecBuffer PackedContext
    )
{
    ASSERT(PackedContext);


    SspPrint(( SSP_API, "Entering SpInitUserModeContext 0x%lx\n", ContextHandle ));
    NTSTATUS Status = STATUS_SUCCESS;
    PNTLM_CLIENT_CONTEXT pContext = NULL;
    UINT Length = 0;
    PNTLM_CLIENT_CONTEXT pTmpContext  = (PNTLM_CLIENT_CONTEXT) PackedContext->pvBuffer;

    if (PackedContext->cbBuffer < sizeof(NTLM_CLIENT_CONTEXT))
    {
        Status = STATUS_INVALID_PARAMETER;
        SspPrint(( SSP_CRITICAL, "SpInitUserModeContext, ContextData size < NTLM_CLIENT_CONTEXT\n" ));
        goto Cleanup;
    }

    pContext = (PNTLM_CLIENT_CONTEXT) NtLmAllocate( sizeof(NTLM_CLIENT_CONTEXT) );

    if (!pContext)
    {
        Status = STATUS_INSUFFICIENT_RESOURCES;
        SspPrint(( SSP_CRITICAL, "SpInitUserModeContext, NtLmAllocate returns NULL\n" ));
        goto Cleanup;
    }

    //
    // If ClientTokenHandle is NULL, we are being called as
    // as an effect of InitializeSecurityContext, else we are
    // being called because of AcceptSecurityContext
    //

    if (pTmpContext->ClientTokenHandle != NULL)
    {
        pContext->ClientTokenHandle = pTmpContext->ClientTokenHandle;
        if (FAILED(SspCreateTokenDacl(pTmpContext->ClientTokenHandle)))
        {
            Status = STATUS_INVALID_HANDLE;
            SspPrint(( SSP_CRITICAL, "SpInitUserModeContext, SspCreateTokenDacl failed\n" ));
            goto Cleanup;
        }
    }

    // Copy contents of PackedContext->pvBuffer to pContext

    pContext->LsaContext = ContextHandle;
    pContext->NegotiateFlags = pTmpContext->NegotiateFlags;

    pContext->References = 1;


    //
    // keep all 128 bits here, so signing can be strong even if encrypt can't be
    //

    RtlCopyMemory(  pContext->SessionKey,
                        pTmpContext->SessionKey,
                        MSV1_0_USER_SESSION_KEY_LENGTH);

    //
    // if doing full duplex as part of NTLM2, generate different sign
    // and seal keys for each direction
    //  all we do is MD5 the base session key with a different magic constant
    //

    if ( pContext->NegotiateFlags & NTLMSSP_NEGOTIATE_NTLM2 ) {
        MD5_CTX Md5Context;
        ULONG KeyLen;

        ASSERT(MD5DIGESTLEN == MSV1_0_USER_SESSION_KEY_LENGTH);

        if( pContext->NegotiateFlags & NTLMSSP_NEGOTIATE_128 )
            KeyLen = 16;
        else if( pContext->NegotiateFlags & NTLMSSP_NEGOTIATE_56 )
            KeyLen = 7;
        else
            KeyLen = 5;

        SspPrint(( SSP_SESSION_KEYS, "NTLMv2 session key size: %lu\n", KeyLen));

        //
        // make client to server encryption key
        //

        MD5Init(&Md5Context);
        MD5Update(&Md5Context, pContext->SessionKey, KeyLen);
        MD5Update(&Md5Context, (unsigned char*)CSSEALMAGIC, sizeof(CSSEALMAGIC));
        MD5Final(&Md5Context);

        //
        // if TokenHandle == NULL, this is the client side
        //  put key in the right place: for client it's seal, for server it's unseal
        //

        if (pContext->ClientTokenHandle == NULL)
            RtlCopyMemory(pContext->SealSessionKey, Md5Context.digest, MSV1_0_USER_SESSION_KEY_LENGTH);
        else
            RtlCopyMemory(pContext->UnsealSessionKey, Md5Context.digest, MSV1_0_USER_SESSION_KEY_LENGTH);

        //
        // make server to client encryption key
        //

        MD5Init(&Md5Context);
        MD5Update(&Md5Context, pContext->SessionKey, KeyLen);
        MD5Update(&Md5Context, (unsigned char*)SCSEALMAGIC, sizeof(SCSEALMAGIC));
        MD5Final(&Md5Context);
        ASSERT(MD5DIGESTLEN == MSV1_0_USER_SESSION_KEY_LENGTH);
        if (pContext->ClientTokenHandle == NULL)
            RtlCopyMemory(pContext->UnsealSessionKey, Md5Context.digest, MSV1_0_USER_SESSION_KEY_LENGTH);
        else
            RtlCopyMemory(pContext->SealSessionKey, Md5Context.digest, MSV1_0_USER_SESSION_KEY_LENGTH);

        //
        // make client to server signing key -- always 128 bits!
        //

        MD5Init(&Md5Context);
        MD5Update(&Md5Context, pContext->SessionKey, MSV1_0_USER_SESSION_KEY_LENGTH);
        MD5Update(&Md5Context, (unsigned char*)CSSIGNMAGIC, sizeof(CSSIGNMAGIC));
        MD5Final(&Md5Context);
        if (pContext->ClientTokenHandle == NULL)
            RtlCopyMemory(pContext->SignSessionKey, Md5Context.digest, MSV1_0_USER_SESSION_KEY_LENGTH);
        else
            RtlCopyMemory(pContext->VerifySessionKey, Md5Context.digest, MSV1_0_USER_SESSION_KEY_LENGTH);

        //
        // make server to client signing key
        //

        MD5Init(&Md5Context);
        MD5Update(&Md5Context, pContext->SessionKey, MSV1_0_USER_SESSION_KEY_LENGTH);
        MD5Update(&Md5Context, (unsigned char*)SCSIGNMAGIC, sizeof(SCSIGNMAGIC));
        MD5Final(&Md5Context);
        if (pContext->ClientTokenHandle == NULL)
            RtlCopyMemory(pContext->VerifySessionKey, Md5Context.digest, MSV1_0_USER_SESSION_KEY_LENGTH);
        else
            RtlCopyMemory(pContext->SignSessionKey, Md5Context.digest, MSV1_0_USER_SESSION_KEY_LENGTH);

        //
        // set pointers to different key schedule and nonce for each direction
        //  key schedule will be filled in later...
        //

        pContext->pSealRc4Sched = &pContext->SealRc4Sched;
        pContext->pUnsealRc4Sched = &pContext->UnsealRc4Sched;
        pContext->pSendNonce = &pContext->SendNonce;
        pContext->pRecvNonce = &pContext->RecvNonce;
   } else {

        //
        // just copy session key to all four keys
        //  leave them 128 bits -- they get cut to 40 bits later
        //

        RtlCopyMemory(  pContext->SealSessionKey,
                        pContext->SessionKey,
                        MSV1_0_USER_SESSION_KEY_LENGTH);
        RtlCopyMemory(  pContext->UnsealSessionKey,
                        pContext->SessionKey,
                        MSV1_0_USER_SESSION_KEY_LENGTH);
        RtlCopyMemory(  pContext->SignSessionKey,
                        pContext->SessionKey,
                        MSV1_0_USER_SESSION_KEY_LENGTH);
        RtlCopyMemory(  pContext->VerifySessionKey,
                        pContext->SessionKey,
                        MSV1_0_USER_SESSION_KEY_LENGTH);

        //
        // set pointers to share a key schedule and nonce for each direction
        //  (OK because half duplex!)
        //

        pContext->pSealRc4Sched = &pContext->SealRc4Sched;
        pContext->pUnsealRc4Sched = &pContext->SealRc4Sched;
        pContext->pSendNonce = &pContext->SendNonce;
        pContext->pRecvNonce = &pContext->SendNonce;
    }



    Length = (UINT) (PackedContext->cbBuffer -
                     sizeof(NTLM_CLIENT_CONTEXT));

    if (Length == 0)
    {
        //There's no string after the NTLM_CLIENT_CONTEXT struct
        pContext->ContextNames = NULL;
    }
    else
    {
        pContext->ContextNames = (LPWSTR) NtLmAllocate(Length + sizeof(WCHAR));
        if (!pContext->ContextNames)

        {
            Status = STATUS_INSUFFICIENT_RESOURCES;
            goto Cleanup;
        }

        RtlCopyMemory(pContext->ContextNames, pTmpContext + 1, Length );

        // null terminate the string

        *(pContext->ContextNames + (Length/2)) = L'\0';

    }

    pContext->SendNonce = pTmpContext->SendNonce;
    pContext->RecvNonce = pTmpContext->RecvNonce;

    SspRc4Key(pContext->NegotiateFlags, &pContext->SealRc4Sched, pContext->SealSessionKey);
    SspRc4Key(pContext->NegotiateFlags, &pContext->UnsealRc4Sched, pContext->UnsealSessionKey);


    pContext->PasswordExpiry = pTmpContext->PasswordExpiry;
    pContext->UserFlags = pTmpContext->UserFlags;

    RtlEnterCriticalSection(&NtLmUserContextLock);

    InsertHeadList ( &NtLmUserContextList, &pContext->Next );

    RtlLeaveCriticalSection(&NtLmUserContextLock);

Cleanup:

    if (!NT_SUCCESS(Status))
    {
        if (pContext != NULL)
        {
            FreeUserContext(pContext);
        }
    }

    // Let FreeContextBuffer handle freeing the virtual allocs

    if (PackedContext->pvBuffer != NULL)
    {
        FreeContextBuffer(PackedContext->pvBuffer);
        PackedContext->pvBuffer = NULL;
    }

    SspPrint(( SSP_API, "Leaving SpInitUserModeContext: 0x%lx\n", Status ));
    return(SspNtStatusToSecStatus(Status, SEC_E_INTERNAL_ERROR));
}


//
// Bogus add-shift check sum
//

void
SspGenCheckSum(
    IN  PSecBuffer  pMessage,
    OUT PNTLMSSP_MESSAGE_SIGNATURE  pSig
    )

/*++

RoutineDescription:

    Generate a crc-32 checksum for a buffer

Arguments:

Return Value:
Notes: This was stolen from net\svcdlls\ntlmssp\client\sign.c ,
       routine SspGenCheckSum. It's possible that
       bugs got copied too

--*/

{

⌨️ 快捷键说明

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