Esempio n. 1
0
NTSTATUS
SrvSessionCreate(
    USHORT            uid,
    PLWIO_SRV_SESSION* ppSession
    )
{
    NTSTATUS ntStatus = 0;
    PLWIO_SRV_SESSION pSession = NULL;

    LWIO_LOG_DEBUG("Creating session [uid:%u]", uid);

    ntStatus = SrvAllocateMemory(
                    sizeof(LWIO_SRV_SESSION),
                    (PVOID*)&pSession);
    BAIL_ON_NT_STATUS(ntStatus);

    pSession->refcount = 1;

    pthread_rwlock_init(&pSession->mutex, NULL);
    pSession->pMutex = &pSession->mutex;

    pSession->uid = uid;

    ntStatus = WireGetCurrentNTTime(&pSession->llBirthTime);
    BAIL_ON_NT_STATUS(ntStatus);

    pSession->llLastActivityTime = pSession->llBirthTime;

    LWIO_LOG_DEBUG("Associating session [object:0x%x][uid:%u]", pSession, uid);

    ntStatus = LwRtlRBTreeCreate(
                    &SrvSessionTreeCompare,
                    NULL,
                    &SrvSessionTreeRelease,
                    &pSession->pTreeCollection);
    BAIL_ON_NT_STATUS(ntStatus);

    ntStatus = SrvFinderCreateRepository(
                    &pSession->hFinderRepository);
    BAIL_ON_NT_STATUS(ntStatus);

    SRV_ELEMENTS_INCREMENT_SESSIONS;

    *ppSession = pSession;

cleanup:

    return ntStatus;

error:

    *ppSession = NULL;

    if (pSession)
    {
        SrvSessionRelease(pSession);
    }

    goto cleanup;
}
Esempio n. 2
0
NTSTATUS
RdrCreateContext(
    PIRP pIrp,
    PRDR_OP_CONTEXT* ppContext
    )
{
    NTSTATUS status = STATUS_SUCCESS;
    PRDR_OP_CONTEXT pContext = NULL;

    status = LW_RTL_ALLOCATE_AUTO(&pContext);
    BAIL_ON_NT_STATUS(status);

    LwListInit(&pContext->Link);

    pContext->pIrp = pIrp;
    
    if (pIrp)
    {
        LWIO_LOG_DEBUG("Created op context %p for IRP %p", pContext, pIrp);
    }
    else
    {
        LWIO_LOG_DEBUG("Created op context %p", pContext);
    }

    *ppContext = pContext;

error:

    return status;
}
Esempio n. 3
0
static
VOID
SrvSession2Free(
    PLWIO_SRV_SESSION_2 pSession
    )
{
    LWIO_LOG_DEBUG("Freeing session [object:0x%x][uid:%u]",
                    pSession,
                    pSession->ullUid);

    if (pSession->pMutex)
    {
        pthread_rwlock_destroy(&pSession->mutex);
        pSession->pMutex = NULL;
    }

    if (pSession->pTreeCollection)
    {
        LwRtlRBTreeFree(pSession->pTreeCollection);
    }

    if (pSession->hFinderRepository)
    {
        SrvFinderCloseRepository(pSession->hFinderRepository);
    }

    SRV_SAFE_FREE_MEMORY(pSession->pwszClientPrincipalName);

    if (pSession->pIoSecurityContext) {
        IoSecurityDereferenceSecurityContext(&pSession->pIoSecurityContext);
    }

    SrvFreeMemory(pSession);
}
Esempio n. 4
0
PLWIO_SRV_SESSION_2
SrvSession2Acquire(
    PLWIO_SRV_SESSION_2 pSession
    )
{
    LWIO_LOG_DEBUG("Acquiring session [uid:%u]", pSession->ullUid);

    InterlockedIncrement(&pSession->refcount);

    return pSession;
}
Esempio n. 5
0
PLWIO_SRV_TREE_2
SrvTree2Acquire(
    PLWIO_SRV_TREE_2 pTree
    )
{
    LWIO_LOG_DEBUG("Acquring tree [tid:%u]", pTree->ulTid);

    InterlockedIncrement(&pTree->refcount);

    return pTree;
}
Esempio n. 6
0
VOID
RdrFreeContext(
    PRDR_OP_CONTEXT pContext
    )
{
    if (pContext)
    {
        LWIO_LOG_DEBUG("Freed op context %p", pContext);
        RTL_FREE(&pContext->Packet.pRawBuffer);
        RTL_FREE(&pContext);
    }
}
Esempio n. 7
0
static
VOID
SrvTree2Free(
    PLWIO_SRV_TREE_2 pTree
    )
{
    LWIO_LOG_DEBUG("Freeing tree [object:0x%x][tid:%u]",
                    pTree,
                    pTree->ulTid);

    // Cannot be in the parent since parent would have a reference.
    LWIO_ASSERT(!SrvTree2IsInParent_inlock(pTree));

    if (pTree->pMutex)
    {
        pthread_rwlock_destroy(&pTree->mutex);
        pTree->pMutex = NULL;
    }

    if (pTree->pFileCollection)
    {
        LwRtlRBTreeFree(pTree->pFileCollection);
    }

    if (pTree->hFile)
    {
        IoCloseFile(pTree->hFile);
    }

    if (pTree->pShareInfo)
    {
        SrvShareReleaseInfo(pTree->pShareInfo);
    }

    if (pTree->resource.ulResourceId)
    {
        PSRV_RESOURCE pResource = NULL;

        SrvElementsUnregisterResource(pTree->resource.ulResourceId,
                                      &pResource);
        pTree->resource.ulResourceId = 0;
    }

    // Release parent at the end
    if (pTree->pSession)
    {
        SrvSession2Release(pTree->pSession);
    }

    SrvFreeMemory(pTree);
}
Esempio n. 8
0
VOID
SrvTree2Release(
    PLWIO_SRV_TREE_2 pTree
    )
{
    LWIO_LOG_DEBUG("Releasing tree [tid:%u]", pTree->ulTid);

    if (InterlockedDecrement(&pTree->refcount) == 0)
    {
        SRV_ELEMENTS_DECREMENT_TREE_CONNECTS;

        SrvTree2Free(pTree);
    }
}
Esempio n. 9
0
VOID
SrvSession2Release(
    PLWIO_SRV_SESSION_2 pSession
    )
{
    LWIO_LOG_DEBUG("Releasing session [uid:%u]", pSession->ullUid);

    if (InterlockedDecrement(&pSession->refcount) == 0)
    {
        SRV_ELEMENTS_DECREMENT_SESSIONS;

        SrvSession2Free(pSession);
    }
}
Esempio n. 10
0
BOOLEAN
RdrContinueContext(
    PRDR_OP_CONTEXT pContext,
    NTSTATUS status,
    PVOID pParam
    )
{
    if (pContext->Continue)
    {
        LWIO_LOG_DEBUG("Continuing context %p", pContext);
        return pContext->Continue(pContext, status, pParam);
    }
    else
    {
        return FALSE;
    }
}
Esempio n. 11
0
DWORD
SMBKrb5SetDefaultCachePath(
    PCSTR pszCachePath,
    PSTR* ppszOrigCachePath
    )
{
    DWORD dwError       = 0;
    DWORD dwMajorStatus = 0;
    DWORD dwMinorStatus = 0;
    PSTR  pszOrigCachePath = NULL;

    // Set the default for gss
    dwMajorStatus = gss_krb5_ccache_name(
                            (OM_uint32 *)&dwMinorStatus,
                            pszCachePath,
                            (ppszOrigCachePath) ? (const char**)&pszOrigCachePath : NULL);
    BAIL_ON_SEC_ERROR(dwMajorStatus);

    if (ppszOrigCachePath) {
        if (!IsNullOrEmptyString(pszOrigCachePath)) {
            dwError = SMBAllocateString(pszOrigCachePath, ppszOrigCachePath);
            BAIL_ON_LWIO_ERROR(dwError);
        } else {
            *ppszOrigCachePath = NULL;
        }
    }

    LWIO_LOG_DEBUG("Cache path set to [%s]", LWIO_SAFE_LOG_STRING(pszCachePath));

cleanup:

    return dwError;

sec_error:
error:

    if (ppszOrigCachePath) {
        *ppszOrigCachePath = NULL;
    }

    goto cleanup;
}
Esempio n. 12
0
static
VOID
SrvTreeFree(
    PLWIO_SRV_TREE pTree
    )
{
    LWIO_LOG_DEBUG("Freeing tree [object:0x%x][tid:%u]",
                    pTree,
                    pTree->tid);

    if (pTree->pMutex)
    {
        pthread_rwlock_destroy(&pTree->mutex);
        pTree->pMutex = NULL;
    }

    if (pTree->pFileCollection)
    {
        LwRtlRBTreeFree(pTree->pFileCollection);
    }

    if (pTree->pAsyncStateCollection)
    {
        LwRtlRBTreeFree(pTree->pAsyncStateCollection);
    }

    if (pTree->hFile)
    {
        IoCloseFile(pTree->hFile);
    }

    if (pTree->pShareInfo)
    {
        SrvShareReleaseInfo(pTree->pShareInfo);
    }

    SrvFreeMemory(pTree);
}
Esempio n. 13
0
NTSTATUS
RdrTreeConnect(
    PCWSTR pwszHostname,
    PCWSTR pwszSharename,
    PIO_CREDS pCreds,
    uid_t Uid,
    BOOLEAN bStopOnDfs,
    PRDR_OP_CONTEXT pContinue
    )
{
    NTSTATUS status = STATUS_SUCCESS;
    PRDR_OP_CONTEXT pContext = NULL;
    BOOLEAN bSocketLocked = FALSE;
    PRDR_SOCKET pSocket = NULL;

    status = RdrCreateContext(pContinue->pIrp, &pContext);
    BAIL_ON_NT_STATUS(status);

    LWIO_LOG_DEBUG("Tree connect context %p will continue %p\n", pContext, pContinue);

    pContext->State.TreeConnect.Uid = Uid;
    pContext->State.TreeConnect.bStopOnDfs = bStopOnDfs;
    pContext->State.TreeConnect.pContinue = pContinue;

    status = LwRtlWC16StringDuplicate(
        &pContext->State.TreeConnect.pwszSharename,
        pwszSharename);
    BAIL_ON_NT_STATUS(status);

    pContext->State.TreeConnect.pCreds = pCreds;

    status = RdrSocketFindOrCreate(
        pwszHostname,
        &pSocket);
    BAIL_ON_NT_STATUS(status);

    pContext->State.TreeConnect.pSocket = pSocket;

    LWIO_LOCK_MUTEX(bSocketLocked, &pSocket->mutex);

    switch (pSocket->state)
    {
    case RDR_SOCKET_STATE_NOT_READY:
        pSocket->state = RDR_SOCKET_STATE_CONNECTING;
        LWIO_UNLOCK_MUTEX(bSocketLocked, &pSocket->mutex);

        /* Add extra reference to socket for work item */
        RdrSocketRetain(pSocket);
        status = LwRtlQueueWorkItem(
            gRdrRuntime.pThreadPool,
            RdrSocketConnectWorkItem,
            pSocket,
            0);
        if (status)
        {
            /* Nevermind */
            RdrSocketRelease(pSocket);
        }
        BAIL_ON_NT_STATUS(status);

        pContext->Continue = RdrProcessNegotiateResponse;

        status = RdrTransceiveNegotiate(pContext, pSocket);
        BAIL_ON_NT_STATUS(status);
        break;
    case RDR_SOCKET_STATE_CONNECTING:
    case RDR_SOCKET_STATE_NEGOTIATING:
        pContext->Continue = RdrNegotiateComplete;
        LwListInsertTail(&pSocket->StateWaiters, &pContext->Link);
        status = STATUS_PENDING;
        BAIL_ON_NT_STATUS(status);
        break;
    case RDR_SOCKET_STATE_READY:
        LWIO_UNLOCK_MUTEX(bSocketLocked, &pSocket->mutex);
        RdrNegotiateComplete(pContext, STATUS_SUCCESS, pSocket);
        status = STATUS_PENDING;
        BAIL_ON_NT_STATUS(status);
        break;
    case RDR_SOCKET_STATE_ERROR:
        status = pSocket->error;
        BAIL_ON_NT_STATUS(status);
        break;
    }

cleanup:

    LWIO_UNLOCK_MUTEX(bSocketLocked, &pSocket->mutex);

    if (status != STATUS_PENDING)
    {
        RdrFreeTreeConnectContext(pContext);
    }

    return status;

error:

    if (status != STATUS_PENDING && pSocket)
    {
        LWIO_UNLOCK_MUTEX(bSocketLocked, &pSocket->mutex);
        RdrSocketInvalidate(pSocket, status);
        RdrSocketRelease(pSocket);
    }

    goto cleanup;
}
Esempio n. 14
0
static
PVOID
SrvTimerMain(
    IN  PVOID pData
    )
{
    NTSTATUS status = 0;
    PSRV_TIMER_CONTEXT pContext = (PSRV_TIMER_CONTEXT)pData;
    PSRV_TIMER_REQUEST pTimerRequest = NULL;
    LONG64 llCurTime = 0LL;
    BOOLEAN bInLock = FALSE;

    LWIO_LOG_DEBUG("Srv timer starting");

    LWIO_LOCK_MUTEX(bInLock, &pContext->mutex);

    while (!SrvTimerMustStop_inlock(pContext))
    {
        int errCode = 0;
        BOOLEAN bRetryWait = FALSE;

        // If we have a current timer request, check if it is time to service it
        if (pTimerRequest)
        {
            status = WireGetCurrentNTTime(&llCurTime);
            BAIL_ON_NT_STATUS(status);

            if (llCurTime >= pTimerRequest->llExpiry &&
                !pTimerRequest->bCanceled)
            {
                SrvTimerDetachRequest_inlock(pContext, pTimerRequest);

                LWIO_UNLOCK_MUTEX(bInLock, &pContext->mutex);

                if (pTimerRequest->pfnTimerExpiredCB)
                {
                    // Timer has not been canceled
                    pTimerRequest->pfnTimerExpiredCB(
                                        pTimerRequest,
                                        pTimerRequest->pUserData);
                }

                LWIO_LOCK_MUTEX(bInLock, &pContext->mutex);
            }

            SrvTimerRelease(pTimerRequest);
            pTimerRequest = NULL;
        }

        // Get the next timer request in queue
        status = SrvTimerGetNextRequest_inlock(pContext, &pTimerRequest);
        if (status == STATUS_NOT_FOUND)
        {
            // If the queue is empty wait for a day or until a request arrives
            struct timespec tsLong = { .tv_sec = time(NULL) + 86400,
                                       .tv_nsec = 0 };

            status = STATUS_SUCCESS;

            do
            {
                bRetryWait = FALSE;

                errCode = pthread_cond_timedwait(
                                &pContext->event,
                                &pContext->mutex,
                                &tsLong);

                if (errCode == ETIMEDOUT)
                {
                    if (time(NULL) < tsLong.tv_sec)
                    {
                        bRetryWait = TRUE;
                        continue;
                    }

                    break;
                }

                status = LwErrnoToNtStatus(errCode);
                BAIL_ON_NT_STATUS(status);

            } while (bRetryWait && !SrvTimerMustStop_inlock(pContext));

            continue;
        }
        BAIL_ON_NT_STATUS(status);

        // At this point, we have a timer request - wait for its specified time
        do
        {
            struct timespec ts = {.tv_sec = 0, .tv_nsec = 0};
            bRetryWait = FALSE;

            status = WireNTTimeToTimeSpec(pTimerRequest->llExpiry, &ts);
            BAIL_ON_NT_STATUS(status);

            errCode = pthread_cond_timedwait(
                            &pContext->event,
                            &pContext->mutex,
                            &ts);
            if (errCode == ETIMEDOUT)
            {
                status = WireGetCurrentNTTime(&llCurTime);
                BAIL_ON_NT_STATUS(status);

                if (llCurTime < pTimerRequest->llExpiry)
                {
                    bRetryWait = TRUE;
                    continue;
                }

                break;
            }

            status = LwErrnoToNtStatus(errCode);
            BAIL_ON_NT_STATUS(status);

        } while (bRetryWait && !SrvTimerMustStop_inlock(pContext));
    }

cleanup:

    LWIO_UNLOCK_MUTEX(bInLock, &pContext->mutex);

    if (pTimerRequest)
    {
        SrvTimerRelease(pTimerRequest);
    }

    LWIO_LOG_DEBUG("Srv timer stopping");

    return NULL;

error:

    LWIO_LOG_ERROR("Srv timer stopping due to error [%d]", status);

    goto cleanup;
}

static
NTSTATUS
SrvTimerGetNextRequest_inlock(
    IN  PSRV_TIMER_CONTEXT  pContext,
    OUT PSRV_TIMER_REQUEST* ppTimerRequest
    )
{
    NTSTATUS status = STATUS_SUCCESS;
    PSRV_TIMER_REQUEST pTimerRequest = NULL;

    if (!pContext->pRequests)
    {
        status = STATUS_NOT_FOUND;
        BAIL_ON_NT_STATUS(status);
    }

    pTimerRequest = pContext->pRequests;

    InterlockedIncrement(&pTimerRequest->refCount);

    *ppTimerRequest = pTimerRequest;

cleanup:

    return status;

error:

    *ppTimerRequest = NULL;

    goto cleanup;
}

static
NTSTATUS
SrvTimerDetachRequest_inlock(
    IN OUT PSRV_TIMER_CONTEXT pContext,
    IN OUT PSRV_TIMER_REQUEST pTimerRequest
    )
{
    if (pTimerRequest->pPrev)
    {
        pTimerRequest->pPrev->pNext = pTimerRequest->pNext;

        if (pTimerRequest->pNext)
        {
            pTimerRequest->pNext->pPrev = pTimerRequest->pPrev;
        }
    }
    else
    {
        pContext->pRequests = pTimerRequest->pNext;

        if (pTimerRequest->pNext)
        {
            pTimerRequest->pNext->pPrev = NULL;
        }
    }

    pTimerRequest->pPrev = NULL;
    pTimerRequest->pNext = NULL;

    // Removed from timer queue
    InterlockedDecrement(&pTimerRequest->refCount);

    return STATUS_SUCCESS;
}

NTSTATUS
SrvTimerPostRequestSpecific(
    IN  PSRV_TIMER             pTimer,
    IN  LONG64                 llExpiry,
    IN  PVOID                  pUserData,
    IN  PFN_SRV_TIMER_CALLBACK pfnTimerExpiredCB,
    OUT PSRV_TIMER_REQUEST*    ppTimerRequest
    )
{
    NTSTATUS status = STATUS_SUCCESS;
    PSRV_TIMER_REQUEST pTimerRequest = NULL;
    PSRV_TIMER_REQUEST pTimerIter = NULL;
    PSRV_TIMER_REQUEST pPrev = NULL;
    BOOLEAN bInLock = FALSE;

    if (!llExpiry)
    {
        status = STATUS_INVALID_PARAMETER_1;
        BAIL_ON_NT_STATUS(status);
    }
    if (!pfnTimerExpiredCB)
    {
        status = STATUS_INVALID_PARAMETER_3;
        BAIL_ON_NT_STATUS(status);
    }

    status = SrvAllocateMemory(
                    sizeof(SRV_TIMER_REQUEST),
                    (PVOID*)&pTimerRequest);
    BAIL_ON_NT_STATUS(status);

    pTimerRequest->refCount = 1;

    pTimerRequest->llExpiry = llExpiry;
    pTimerRequest->pUserData = pUserData;
    pTimerRequest->pfnTimerExpiredCB = pfnTimerExpiredCB;
    pTimerRequest->bCanceled = FALSE;

    LWIO_LOCK_MUTEX(bInLock, &pTimer->context.mutex);

    for (pTimerIter = pTimer->context.pRequests;
         pTimerIter && (pTimerIter->llExpiry <= llExpiry);
         pPrev = pTimerIter, pTimerIter = pTimerIter->pNext);

    if (!pPrev)
    {
        pTimerRequest->pNext = pTimer->context.pRequests;
        if (pTimer->context.pRequests)
        {
            pTimer->context.pRequests->pPrev = pTimerRequest;
        }
        pTimer->context.pRequests = pTimerRequest;
    }
    else
    {
        pTimerRequest->pNext = pPrev->pNext;
        pTimerRequest->pPrev = pPrev;
        pPrev->pNext = pTimerRequest;
        if (pTimerRequest->pNext)
        {
            pTimerRequest->pNext->pPrev = pTimerRequest;
        }
    }

    // +1 for timer queue
    InterlockedIncrement(&pTimerRequest->refCount);

    LWIO_UNLOCK_MUTEX(bInLock, &pTimer->context.mutex);

    pthread_cond_signal(&pTimer->context.event);

    // +1 for caller
    InterlockedIncrement(&pTimerRequest->refCount);

    *ppTimerRequest = pTimerRequest;

cleanup:

    LWIO_UNLOCK_MUTEX(bInLock, &pTimer->context.mutex);

    if (pTimerRequest)
    {
        SrvTimerRelease(pTimerRequest);
    }

    return status;

error:

    *ppTimerRequest = NULL;

    goto cleanup;
}
Esempio n. 15
0
NTSTATUS
SrvTreeCreate(
    USHORT          tid,
    PSRV_SHARE_INFO pShareInfo,
    PLWIO_SRV_TREE* ppTree
    )
{
    NTSTATUS ntStatus = 0;
    PLWIO_SRV_TREE pTree = NULL;

    LWIO_LOG_DEBUG("Creating Tree [tid: %u]", tid);

    ntStatus = SrvAllocateMemory(sizeof(LWIO_SRV_TREE), (PVOID*)&pTree);
    BAIL_ON_NT_STATUS(ntStatus);

    pTree->refcount = 1;

    pthread_rwlock_init(&pTree->mutex, NULL);
    pTree->pMutex = &pTree->mutex;

    pTree->tid = tid;

    LWIO_LOG_DEBUG("Associating Tree [object:0x%x][tid:%u]",
                    pTree,
                    tid);

    pTree->pShareInfo = SrvShareAcquireInfo(pShareInfo);

    ntStatus = LwRtlRBTreeCreate(
                    &SrvTreeFileCompare,
                    NULL,
                    &SrvTreeFileRelease,
                    &pTree->pFileCollection);
    BAIL_ON_NT_STATUS(ntStatus);

    ntStatus = LwRtlRBTreeCreate(
                    &SrvTreeAsyncStateCompare,
                    NULL,
                    &SrvTreeAsyncStateRelease,
                    &pTree->pAsyncStateCollection);
    BAIL_ON_NT_STATUS(ntStatus);

    SRV_ELEMENTS_INCREMENT_TREE_CONNECTS;

    *ppTree = pTree;

cleanup:

    return ntStatus;

error:

    *ppTree = NULL;

    if (pTree)
    {
        SrvTreeRelease(pTree);
    }

    goto cleanup;
}
Esempio n. 16
0
NTSTATUS
SrvTree2Create(
    PLWIO_SRV_SESSION_2 pSession,
    ULONG             ulTid,
    PSRV_SHARE_INFO   pShareInfo,
    PLWIO_SRV_TREE_2* ppTree
    )
{
    NTSTATUS ntStatus = 0;
    PLWIO_SRV_TREE_2 pTree = NULL;

    LWIO_LOG_DEBUG("Creating Tree [tid: %u]", ulTid);

    ntStatus = SrvAllocateMemory(sizeof(LWIO_SRV_TREE_2), (PVOID*)&pTree);
    BAIL_ON_NT_STATUS(ntStatus);

    pTree->refcount = 1;

    pthread_rwlock_init(&pTree->mutex, NULL);
    pTree->pMutex = &pTree->mutex;

    pTree->pSession = pSession;;
    SrvSession2Acquire(pSession);

    pTree->ulTid = ulTid;
    pTree->ullUid = pSession->ullUid;

    pTree->resource.resourceType                  = SRV_RESOURCE_TYPE_TREE;
    pTree->resource.pAttributes                   = &pTree->resourceAttrs;
    pTree->resource.pAttributes->protocolVersion  = SMB_PROTOCOL_VERSION_2;
    pTree->resource.pAttributes->treeId.ulTid     = pTree->ulTid;
    pTree->resource.pAttributes->sessionId.ullUid = pTree->ullUid;
    pTree->resource.pAttributes->ulConnectionResourceId =
                                             pSession->ulConnectionResourceId;

    LWIO_LOG_DEBUG("Associating Tree [object:0x%x][tid:%u]",
                    pTree,
                    ulTid);

    pTree->pShareInfo = pShareInfo;
    SrvShareAcquireInfo(pShareInfo);

    pTree->ullNextAvailableFid = 0xFFFFFFFF00000001LL;

    ntStatus = LwRtlRBTreeCreate(
                    &SrvTree2FileCompare,
                    NULL,
                    &SrvTree2FileRelease,
                    &pTree->pFileCollection);
    BAIL_ON_NT_STATUS(ntStatus);

    SRV_ELEMENTS_INCREMENT_TREE_CONNECTS;

    *ppTree = pTree;

cleanup:

    return ntStatus;

error:

    *ppTree = NULL;

    if (pTree)
    {
        SrvTree2Release(pTree);
    }

    goto cleanup;
}
Esempio n. 17
0
DWORD
SMBGSSContextBuild(
    PCWSTR     pwszServerName,
    PIO_CREDS  pCreds,
    PHANDLE    phSMBGSSContext
    )
{
    DWORD dwError = 0;
    DWORD dwMajorStatus = 0;
    DWORD dwMinorStatus = 0;
    PSMB_GSS_SEC_CONTEXT pContext = NULL;
    PSTR pszTargetName = NULL;
    PSTR pszServerName = NULL;
    PSTR pszUsername = NULL;
    PSTR pszDomain = NULL;
    PSTR pszPassword = NULL;
    gss_buffer_desc usernameBuffer = {0};
    gss_buffer_desc inputNameBuffer = {0};
    gss_buffer_desc authDataBuffer = {0};
    gss_name_t pUsername = NULL;
    gss_OID_set_desc desiredMechs;
    gss_OID_set actualMechs;
    OM_uint32 timeRec = 0;
    SEC_WINNT_AUTH_IDENTITY authData;
    static gss_OID_desc gssCredOptionPasswordOidDesc =
    {
        .length = GSS_CRED_OPT_PW_LEN,
        .elements = GSS_CRED_OPT_PW
    };
    static gss_OID_desc gssNtlmOidDesc =
    {
        .length = GSS_MECH_NTLM_LEN,
        .elements = GSS_MECH_NTLM
    };
    size_t sCopyServerChars = 0;

    dwError = LwRtlCStringAllocateFromWC16String(&pszServerName, pwszServerName);
    BAIL_ON_LWIO_ERROR(dwError);
    
    LWIO_LOG_DEBUG("Build GSS Context for server [%s]", LWIO_SAFE_LOG_STRING(pszServerName));

    dwError = LwIoAllocateMemory(
        sizeof(SMB_GSS_SEC_CONTEXT),
        (PVOID*)&pContext);
    BAIL_ON_LWIO_ERROR(dwError);

    pContext->state = SMB_GSS_SEC_CONTEXT_STATE_INITIAL;
    
    if (pCreds)
    {
        switch (pCreds->type)
        {
        case IO_CREDS_TYPE_KRB5_CCACHE:
            dwError = STATUS_ACCESS_DENIED;
            BAIL_ON_LWIO_ERROR(dwError);
            break;
        case IO_CREDS_TYPE_KRB5_TGT:
            sCopyServerChars = strlen(pszServerName);
            if (sCopyServerChars > 0 &&
                    pszServerName[sCopyServerChars - 1] == '.')
            {
                // Strip the trailing dot
                sCopyServerChars --;
            }
            
            if (sCopyServerChars > INT_MAX)
            {
                dwError = STATUS_INTEGER_OVERFLOW;
                BAIL_ON_LWIO_ERROR(dwError);
            }

            dwError = SMBAllocateStringPrintf(
                            &pszTargetName,
                            "cifs/%.*s@",
                            (int)sCopyServerChars,
                            pszServerName);
            BAIL_ON_LWIO_ERROR(dwError);

            inputNameBuffer.value = pszTargetName;
            inputNameBuffer.length = strlen(pszTargetName) + 1;
            
            dwMajorStatus = gss_import_name(
                (OM_uint32 *)&dwMinorStatus,
                &inputNameBuffer,
                (gss_OID) gss_nt_krb5_name,
                &pContext->target_name);

            smb_display_status("gss_import_name", dwMajorStatus, dwMinorStatus);

            BAIL_ON_SEC_ERROR(dwMajorStatus);

            dwError = LwRtlCStringAllocateFromWC16String(
                &pszUsername,
                pCreds->payload.krb5Tgt.pwszClientPrincipal);
            BAIL_ON_NT_STATUS(dwError);

            usernameBuffer.value = pszUsername;
            usernameBuffer.length = strlen(pszUsername) + 1;

            dwMajorStatus = gss_import_name(
                (OM_uint32 *)&dwMinorStatus,
                &usernameBuffer,
                GSS_C_NT_USER_NAME,
                &pUsername);
            BAIL_ON_SEC_ERROR(dwMajorStatus);

            desiredMechs.count = 1;
            desiredMechs.elements = (gss_OID) gss_mech_krb5;

            dwMajorStatus = gss_acquire_cred(
                (OM_uint32 *)&dwMinorStatus,
                pUsername,
                0,
                &desiredMechs,
                GSS_C_INITIATE,
                &pContext->credHandle,
                &actualMechs,
                &timeRec);
            BAIL_ON_SEC_ERROR(dwMajorStatus);
            break;

        case IO_CREDS_TYPE_PLAIN:
            inputNameBuffer.value = (void*) "unset";
            inputNameBuffer.length = strlen("unset");
            
            dwMajorStatus = gss_import_name(
                (OM_uint32 *)&dwMinorStatus,
                &inputNameBuffer,
                (gss_OID) gss_nt_krb5_name,
                &pContext->target_name);

            smb_display_status("gss_import_name", dwMajorStatus, dwMinorStatus);
            
            BAIL_ON_SEC_ERROR(dwMajorStatus);
            
            if (pCreds->payload.plain.pwszUsername)
            {
                dwError = LwRtlCStringAllocateFromWC16String(&pszUsername, pCreds->payload.plain.pwszUsername);
                BAIL_ON_LWIO_ERROR(dwError);
                
                usernameBuffer.value = pszUsername;
                usernameBuffer.length = strlen(pszUsername);
                
                // If "" is passed in, that means to use anonymous
                // authentication. gss_import_name fails on "" though
                if (usernameBuffer.length)
                {
                    dwMajorStatus = gss_import_name(
                        (OM_uint32 *)&dwMinorStatus,
                        &usernameBuffer,
                        GSS_C_NT_USER_NAME,
                        &pUsername);
                    BAIL_ON_SEC_ERROR(dwMajorStatus);
                }
            }
            
            desiredMechs.count = 1;
            desiredMechs.elements = (gss_OID) &gssNtlmOidDesc;
            
            dwMajorStatus = gss_acquire_cred(
                (OM_uint32 *)&dwMinorStatus,
                pUsername,
                0,
                &desiredMechs,
                GSS_C_INITIATE,
                &pContext->credHandle,
                &actualMechs,
                &timeRec);
            BAIL_ON_SEC_ERROR(dwMajorStatus);

            if (pCreds->payload.plain.pwszUsername &&
                pCreds->payload.plain.pwszPassword &&
                pCreds->payload.plain.pwszDomain)
            {
                dwError = LwRtlCStringAllocateFromWC16String(&pszDomain, pCreds->payload.plain.pwszDomain);
                BAIL_ON_LWIO_ERROR(dwError);
                
                dwError = LwRtlCStringAllocateFromWC16String(&pszPassword, pCreds->payload.plain.pwszPassword);
                BAIL_ON_LWIO_ERROR(dwError);
                
                authData.User = pszUsername;
                authData.UserLength = strlen(pszUsername);
                authData.Domain = pszDomain;
                authData.DomainLength = strlen(pszDomain);
                authData.Password = pszPassword;
                authData.PasswordLength = strlen(pszPassword);
                authData.Flags = 0;
                
                authDataBuffer.value = &authData;
                authDataBuffer.length = sizeof(authData);
                
                dwMajorStatus = gssspi_set_cred_option(
                    (OM_uint32 *)&dwMinorStatus,
                    pContext->credHandle,
                    (gss_OID) &gssCredOptionPasswordOidDesc,
                    &authDataBuffer);
                BAIL_ON_SEC_ERROR(dwMajorStatus);
            }
            break;
        }
    }
    
    dwError = LwIoAllocateMemory(
        sizeof(CtxtHandle),
        (PVOID*)&pContext->pGSSContext);
    BAIL_ON_LWIO_ERROR(dwError);
    
    *pContext->pGSSContext = GSS_C_NO_CONTEXT;
    
    *phSMBGSSContext = (HANDLE)pContext;
    
cleanup:
    
    if (pUsername != NULL)
    {
        gss_release_name((OM_uint32 *)&dwMinorStatus, &pUsername);
    }

    LWIO_SAFE_FREE_STRING(pszTargetName);
    LWIO_SAFE_FREE_STRING(pszServerName);
    LWIO_SAFE_FREE_STRING(pszUsername);
    LWIO_SAFE_FREE_STRING(pszDomain);
    LWIO_SAFE_FREE_STRING(pszPassword);
    
    return dwError;
    
sec_error:
    
    dwError = LWIO_ERROR_GSS;

error:

    *phSMBGSSContext = NULL;

    if (pContext)
    {
        SMBGSSContextFree(pContext);
    }

    goto cleanup;
}