Exemple #1
0
DWORD
NtlmCreateChallengeContext(
    IN const NTLM_NEGOTIATE_MESSAGE_V1* pNtlmNegMsg,
    IN NTLM_CRED_HANDLE hCred,
    OUT PNTLM_CONTEXT *ppNtlmContext,
    OUT PSecBuffer pOutput
    )
{
    DWORD dwError = LW_ERROR_SUCCESS;
    PNTLM_CREDENTIALS pCred = (PNTLM_CREDENTIALS)hCred;
    PNTLM_CONTEXT pNtlmContext = NULL;
    DWORD dwMessageSize = 0;
    PNTLM_CHALLENGE_MESSAGE pMessage = NULL;
    PSTR pServerName = NULL;
    PSTR pDomainName = NULL;
    PSTR pDnsServerName = NULL;
    PSTR pDnsDomainName = NULL;
    BOOLEAN bInLock = FALSE;

    *ppNtlmContext = NULL;

    dwError = NtlmCreateContext(hCred, &pNtlmContext);
    BAIL_ON_LSA_ERROR(dwError);

    if (pCred)
    {
        NTLM_LOCK_MUTEX(bInLock, &pCred->Mutex);

        dwError = NtlmGetNameInformation(
            pCred->pszDomainName,
            &pServerName,
            &pDomainName,
            &pDnsServerName,
            &pDnsDomainName);
        BAIL_ON_LSA_ERROR(dwError);

        NTLM_UNLOCK_MUTEX(bInLock, &pCred->Mutex);
    }
    else
    {
        dwError = NtlmGetNameInformation(
            NULL,
            &pServerName,
            &pDomainName,
            &pDnsServerName,
            &pDnsDomainName);
        BAIL_ON_LSA_ERROR(dwError);
    }

    dwError = NtlmGetRandomBuffer(
        pNtlmContext->Challenge,
        NTLM_CHALLENGE_SIZE
        );
    BAIL_ON_LSA_ERROR(dwError);

    dwError = NtlmCreateChallengeMessage(
        pNtlmNegMsg,
        pServerName,
        pDomainName,
        pDnsServerName,
        pDnsDomainName,
        (PBYTE)&gW2KSpoof,
        pNtlmContext->Challenge,
        &dwMessageSize,
        &pMessage
        );

    BAIL_ON_LSA_ERROR(dwError);

    pNtlmContext->NegotiatedFlags = LW_LTOH32(pMessage->NtlmFlags);
    pOutput->cbBuffer = dwMessageSize;
    pOutput->BufferType = SECBUFFER_TOKEN;
    pOutput->pvBuffer = pMessage;
    pNtlmContext->NtlmState = NtlmStateChallenge;

cleanup:
    *ppNtlmContext = pNtlmContext;

    LW_SAFE_FREE_STRING(pServerName);
    LW_SAFE_FREE_STRING(pDomainName);
    LW_SAFE_FREE_STRING(pDnsServerName);
    LW_SAFE_FREE_STRING(pDnsDomainName);

    if (pCred)
    {
        NTLM_UNLOCK_MUTEX(bInLock, &pCred->Mutex);
    }

    return dwError;

error:
    LW_SAFE_FREE_MEMORY(pMessage);

    if (pNtlmContext)
    {
        NtlmReleaseContext(&pNtlmContext);
        *ppNtlmContext = NULL;
    }
    pOutput->cbBuffer = 0;
    pOutput->BufferType = 0;
    pOutput->pvBuffer = NULL;
    goto cleanup;
}
Exemple #2
0
DWORD
NtlmServerAcceptSecurityContext(
    IN HANDLE Handle,
    IN NTLM_CRED_HANDLE hCred,
    IN OUT PNTLM_CONTEXT_HANDLE phContext,
    IN const SecBuffer* pInput,
    IN DWORD fContextReq,
    IN DWORD TargetDataRep,
    IN OUT PNTLM_CONTEXT_HANDLE phNewContext,
    OUT PSecBuffer pOutput,
    OUT PDWORD  pfContextAttr,
    OUT PTimeStamp ptsTimeStamp
    )
{
    DWORD dwError = LW_ERROR_SUCCESS;
    PNTLM_CONTEXT pNtlmContext = NULL;
    PNTLM_CONTEXT pNtlmCtxtOut = NULL;
    PNTLM_CONTEXT pNtlmCtxtChlng = NULL;
    NTLM_CONTEXT_HANDLE ContextHandle = NULL;
    const NTLM_NEGOTIATE_MESSAGE_V1* pNegMsg = NULL;
    PNTLM_RESPONSE_MESSAGE_V1 pRespMsg = NULL;
    DWORD dwMessageSize = 0;
    BYTE SessionKey[NTLM_SESSION_KEY_SIZE] = {0};
    DWORD dwRetFlags = 0;

    ptsTimeStamp = 0;

    pOutput->pvBuffer = NULL;

    if (phContext)
    {
        pNtlmContext = *phContext;
    }

    if (!pNtlmContext)
    {
        if (pInput->BufferType != SECBUFFER_TOKEN ||
           pInput->cbBuffer == 0)
        {
            dwError = LW_ERROR_INVALID_PARAMETER;
            BAIL_ON_LSA_ERROR(dwError);
        }

        pNegMsg = pInput->pvBuffer;
        dwMessageSize = pInput->cbBuffer;

        if (dwMessageSize < sizeof(*pNegMsg))
        {
            dwError = ERROR_INVALID_PARAMETER;
            BAIL_ON_LSA_ERROR(dwError);
        }

        dwError = NtlmCreateChallengeContext(
            pNegMsg,
            hCred,
            &pNtlmCtxtOut,
            pOutput);
        BAIL_ON_LSA_ERROR(dwError);

        dwError = LW_WARNING_CONTINUE_NEEDED;
    }
    else
    {
        // The only time we should get a context handle passed in is when
        // we are validating a challenge and we need to look up the original
        // challenge sent
        pNtlmCtxtChlng = pNtlmContext;

        // In this case we need to grab the response message sent in
        if (pInput->BufferType != SECBUFFER_TOKEN ||
           pInput->cbBuffer == 0)
        {
            dwError = LW_ERROR_INVALID_PARAMETER;
            BAIL_ON_LSA_ERROR(dwError);
        }

        pRespMsg = pInput->pvBuffer;
        dwMessageSize = pInput->cbBuffer;

        dwError = NtlmValidateResponse(
            Handle,
            hCred,
            pRespMsg,
            dwMessageSize,
            pNtlmCtxtChlng,
            SessionKey);
        switch(dwError)
        {
            case LW_ERROR_SUCCESS:
                // The response has been validated and contains all the information we
                // are looking for; retain it... the original (challenge) context will
                // be freed when we return.
                dwError = NtlmCreateValidatedContext(
                    pRespMsg,
                    dwMessageSize,
                    pNtlmCtxtChlng,
                    SessionKey,
                    NTLM_SESSION_KEY_SIZE,
                    hCred,
                    &pNtlmCtxtOut
                    );
                BAIL_ON_LSA_ERROR(dwError);

                pNtlmCtxtOut->pUserInfo = pNtlmCtxtChlng->pUserInfo;
                pNtlmCtxtChlng->pUserInfo = NULL;
                break;

            case LW_ERROR_NOT_HANDLED:
                // Attempt to fallback to Guest access
                dwError = NtlmCreateGuestContext(&pNtlmCtxtOut);

                // Restore previous error code on failure
                if (dwError != LW_ERROR_SUCCESS)
                {
                    dwError = LW_ERROR_NOT_HANDLED;
                }
                BAIL_ON_LSA_ERROR(dwError);

                break;

            default:
                BAIL_ON_LSA_ERROR(dwError);
                break;
        }
    }

    ContextHandle = pNtlmCtxtOut;

cleanup:
    *pfContextAttr = dwRetFlags;

    *phNewContext = ContextHandle;

    return(dwError);
error:
    LW_SAFE_FREE_MEMORY(pOutput->pvBuffer);
    pOutput->cbBuffer = 0;
    pOutput->BufferType = 0;
    dwRetFlags = 0;
    if (ContextHandle)
    {
        NtlmReleaseContext(&ContextHandle);
    }
    else if (pNtlmCtxtOut)
    {
        NtlmReleaseContext(&pNtlmCtxtOut);
    }
    goto cleanup;
}
Exemple #3
0
DWORD
NtlmServerInitializeSecurityContext(
    IN OPTIONAL NTLM_CRED_HANDLE hCredential,
    IN OPTIONAL const NTLM_CONTEXT_HANDLE hContext,
    IN OPTIONAL SEC_CHAR* pszTargetName,
    IN DWORD fContextReq,
    IN DWORD Reserved1,
    IN DWORD TargetDataRep,
    IN OPTIONAL const SecBuffer* pInput,
    IN DWORD Reserved2,
    IN OUT OPTIONAL PNTLM_CONTEXT_HANDLE phNewContext,
    OUT PSecBuffer pOutput,
    OUT PDWORD pfContextAttr,
    OUT OPTIONAL PTimeStamp ptsExpiry
)
{
    DWORD dwError = LW_ERROR_SUCCESS;
    PNTLM_CREDENTIALS pCred = (PNTLM_CREDENTIALS)hCredential;
    PNTLM_CONTEXT pNtlmContext = NULL;
    PSTR pWorkstation = NULL;
    PSTR pDomain = NULL;
    PNTLM_CHALLENGE_MESSAGE pMessage = NULL;
    DWORD dwMessageSize ATTRIBUTE_UNUSED = 0;
    BOOLEAN bInLock = FALSE;

    pOutput->pvBuffer = NULL;

    if (hContext)
    {
        pNtlmContext = hContext;
    }

    if (!pNtlmContext)
    {
        if (pCred)
        {
            NTLM_LOCK_MUTEX(bInLock, &pCred->Mutex);

            dwError = NtlmGetNameInformation(
                          pCred->pszDomainName,
                          &pWorkstation,
                          &pDomain,
                          NULL,
                          NULL);
            BAIL_ON_LSA_ERROR(dwError);

            NTLM_UNLOCK_MUTEX(bInLock, &pCred->Mutex);
        }
        else
        {
            dwError = NtlmGetNameInformation(
                          NULL,
                          &pWorkstation,
                          &pDomain,
                          NULL,
                          NULL);
            BAIL_ON_LSA_ERROR(dwError);
        }

        // If we start with a NULL context, create a negotiate message
        dwError = NtlmCreateNegotiateContext(
                      hCredential,
                      fContextReq,
                      pDomain,
                      pWorkstation,
                      (PBYTE)&gXpSpoof,  //for now add OS ver info... config later
                      &pNtlmContext,
                      pOutput);
        BAIL_ON_LSA_ERROR(dwError);

        dwError = LW_WARNING_CONTINUE_NEEDED;
    }
    else
    {
        if (pInput->BufferType != SECBUFFER_TOKEN ||
                pInput->cbBuffer == 0)
        {
            dwError = LW_ERROR_INVALID_PARAMETER;
            BAIL_ON_LSA_ERROR(dwError);
        }

        pMessage = pInput->pvBuffer;
        dwMessageSize = pInput->cbBuffer;

        dwError = NtlmCreateResponseContext(
                      pMessage,
                      hCredential,
                      pNtlmContext->bDoAnonymous,
                      &pNtlmContext,
                      pOutput);
        BAIL_ON_LSA_ERROR(dwError);
    }

    *phNewContext = pNtlmContext;

    if (pfContextAttr)
    {
        NtlmGetContextInfo(
            pNtlmContext,
            NULL,
            pfContextAttr,
            NULL,
            NULL,
            NULL);
    }


cleanup:
    if (pCred)
    {
        NTLM_UNLOCK_MUTEX(bInLock, &pCred->Mutex);
    }

    LW_SAFE_FREE_STRING(pWorkstation);
    LW_SAFE_FREE_STRING(pDomain);

    return dwError;

error:
    LW_SAFE_FREE_MEMORY(pOutput->pvBuffer);
    pOutput->cbBuffer = 0;
    pOutput->BufferType = 0;

    // If this function has already succeed once, we MUST make sure phNewContext
    // is set so the caller can cleanup whatever context is remaining.  It
    // could be the original negotiate context or a new response context but
    // either way it is vital that the caller get a context they can actually
    // cleanup ONCE they've received ANY context from this function.
    //
    // If hContext is NULL, that indicates this is the first time through this
    // call and we can safely release our context.
    if ( pNtlmContext && !hContext)
    {
        NtlmReleaseContext(&pNtlmContext);
        phNewContext = NULL;
    }

    goto cleanup;
}