Beispiel #1
0
BOOLEAN
RdrNegotiateComplete2(
    PRDR_OP_CONTEXT pContext,
    NTSTATUS status,
    PVOID pParam
    )
{
    PRDR_SOCKET pSocket = pParam;
    PRDR_SESSION2 pSession = NULL;
    BOOLEAN bSessionLocked = FALSE;
    BOOLEAN bFreeContext = FALSE;
    PIO_CREDS pCreds = pContext->State.TreeConnect.pCreds;

    BAIL_ON_NT_STATUS(status);

    if (pContext->State.TreeConnect.bStopOnDfs &&
        pSocket->capabilities & RDR_SMB2_CAP_DFS)
    {
        status = STATUS_DFS_EXIT_PATH_FOUND;
        BAIL_ON_NT_STATUS(status);
    }

    status = RdrSession2FindOrCreate(
        &pSocket,
        pContext->State.TreeConnect.pCreds,
        pContext->State.TreeConnect.Uid,
        &pSession);
    BAIL_ON_NT_STATUS(status);

    pContext->State.TreeConnect.pSession2 = pSession;

    LWIO_LOCK_MUTEX(bSessionLocked, &pSession->mutex);

    switch (pSession->state)
    {
    case RDR_SESSION_STATE_NOT_READY:
        pSession->state = RDR_SESSION_STATE_INITIALIZING;

        switch (pCreds->type)
        {
        case IO_CREDS_TYPE_KRB5_TGT:
            status = SMBCredTokenToKrb5CredCache(
                pCreds,
                &pContext->State.TreeConnect.pszCachePath);
            BAIL_ON_NT_STATUS(status);
            break;
        case IO_CREDS_TYPE_PLAIN:
            break;
        default:
            status = STATUS_ACCESS_DENIED;
            BAIL_ON_NT_STATUS(status);
        }

        LWIO_UNLOCK_MUTEX(bSessionLocked, &pSession->mutex);
        RdrProcessSessionSetupResponse2(pContext, STATUS_SUCCESS, NULL);
        status = STATUS_PENDING;
        BAIL_ON_NT_STATUS(status);
        break;
    case RDR_SESSION_STATE_INITIALIZING:
        pContext->Continue = RdrSessionSetupComplete2;
        LwListInsertTail(&pSession->StateWaiters, &pContext->Link);
        status = STATUS_PENDING;
        BAIL_ON_NT_STATUS(status);
        break;
    case RDR_SESSION_STATE_READY:
        LWIO_UNLOCK_MUTEX(bSessionLocked, &pSession->mutex);
        RdrSessionSetupComplete2(pContext, status, pSession);
        status = STATUS_PENDING;
        BAIL_ON_NT_STATUS(status);
        break;
    case RDR_SESSION_STATE_ERROR:
        status = pSession->error;
        BAIL_ON_NT_STATUS(status);
        break;
    }

 cleanup:

     LWIO_UNLOCK_MUTEX(bSessionLocked, &pSession->mutex);

     if (status != STATUS_PENDING)
     {
         RdrContinueContext(pContext->State.TreeConnect.pContinue, status, NULL);
         bFreeContext = TRUE;
     }

     if (bFreeContext)
     {
         RdrFreeTreeConnectContext(pContext);
     }

     return FALSE;

 error:

     if (status != STATUS_PENDING && pSession)
     {
         LWIO_UNLOCK_MUTEX(bSessionLocked, &pSession->mutex);
         if (status != STATUS_DFS_EXIT_PATH_FOUND)
         {
             RdrSession2Invalidate(pSession, status);
         }
         RdrSession2Release(pSession);
     }

     if (status != STATUS_PENDING && pSocket)
     {
         if (status != STATUS_DFS_EXIT_PATH_FOUND)
         {
             RdrSocketInvalidate(pSocket, status);
         }
         RdrSocketRelease(pSocket);
     }

     goto cleanup;
}
Beispiel #2
0
static
BOOLEAN
RdrNegotiateComplete(
    PRDR_OP_CONTEXT pContext,
    NTSTATUS status,
    PVOID pParam
    )
{
    PRDR_SOCKET pSocket = pParam;
    PRDR_SESSION pSession = NULL;
    BOOLEAN bSessionLocked = FALSE;
    BOOLEAN bFreeContext = FALSE;
    PIO_CREDS pCreds = pContext->State.TreeConnect.pCreds;

    BAIL_ON_NT_STATUS(status);

    /* Several op contexts could be queued with this function
     * as the continue routine before we transition to SMB2 mode,
     * so we need to hand off to the correct function in this case.
     * Subsequent attempts should go straight to connect2.c
     */
    if (pSocket->version == SMB_PROTOCOL_VERSION_2)
    {
        /* Short circuit to SMB2 session setup logic in connect2.c */
        return RdrNegotiateComplete2(pContext, status, pParam);
    }

    if (pContext->State.TreeConnect.bStopOnDfs &&
        pSocket->capabilities & CAP_DFS)
    {
        /* Abort tree connect because we need to do DFS referral processing first */
        status = STATUS_DFS_EXIT_PATH_FOUND;
        BAIL_ON_NT_STATUS(status);
    }

    status = RdrSessionFindOrCreate(
        &pSocket,
        pContext->State.TreeConnect.pCreds,
        pContext->State.TreeConnect.Uid,
        &pSession);
    BAIL_ON_NT_STATUS(status);

    pContext->State.TreeConnect.pSession = pSession;

    LWIO_LOCK_MUTEX(bSessionLocked, &pSession->mutex);

    switch (pSession->state)
    {
    case RDR_SESSION_STATE_NOT_READY:
        pSession->state = RDR_SESSION_STATE_INITIALIZING;

        switch (pCreds->type)
        {
        case IO_CREDS_TYPE_KRB5_TGT:
            status = SMBCredTokenToKrb5CredCache(
                pCreds,
                &pContext->State.TreeConnect.pszCachePath);
            BAIL_ON_NT_STATUS(status);
            break;
        case IO_CREDS_TYPE_PLAIN:
            break;
        default:
            status = STATUS_ACCESS_DENIED;
            BAIL_ON_NT_STATUS(status);
        }

        LWIO_UNLOCK_MUTEX(bSessionLocked, &pSession->mutex);
        RdrProcessSessionSetupResponse(pContext, STATUS_SUCCESS, NULL);
        status = STATUS_PENDING;
        BAIL_ON_NT_STATUS(status);
        break;
    case RDR_SESSION_STATE_INITIALIZING:
        pContext->Continue = RdrSessionSetupComplete;
        LwListInsertTail(&pSession->StateWaiters, &pContext->Link);
        status = STATUS_PENDING;
        BAIL_ON_NT_STATUS(status);
        break;
    case RDR_SESSION_STATE_READY:
        LWIO_UNLOCK_MUTEX(bSessionLocked, &pSession->mutex);
        RdrSessionSetupComplete(pContext, status, pSession);
        status = STATUS_PENDING;
        BAIL_ON_NT_STATUS(status);
        break;
    case RDR_SESSION_STATE_ERROR:
        status = pSession->error;
        BAIL_ON_NT_STATUS(status);
        break;
    }

cleanup:

    LWIO_UNLOCK_MUTEX(bSessionLocked, &pSession->mutex);

    if (status != STATUS_PENDING)
    {
        RdrContinueContext(pContext->State.TreeConnect.pContinue, status, NULL);
        bFreeContext = TRUE;
    }

    if (bFreeContext)
    {
        RdrFreeTreeConnectContext(pContext);
    }

    return FALSE;

error:

    if (status != STATUS_PENDING && pSession)
    {
        LWIO_UNLOCK_MUTEX(bSessionLocked, &pSession->mutex);
        if (status != STATUS_DFS_EXIT_PATH_FOUND)
        {
            RdrSessionInvalidate(pSession, status);
        }
        RdrSessionRelease(pSession);
    }

    if (status != STATUS_PENDING && pSocket)
    {
        if (status != STATUS_DFS_EXIT_PATH_FOUND)
        {
            RdrSocketInvalidate(pSocket, status);
        }
        RdrSocketRelease(pSocket);
    }

    goto cleanup;
}