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; }
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; }
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); }
PLWIO_SRV_SESSION_2 SrvSession2Acquire( PLWIO_SRV_SESSION_2 pSession ) { LWIO_LOG_DEBUG("Acquiring session [uid:%u]", pSession->ullUid); InterlockedIncrement(&pSession->refcount); return pSession; }
PLWIO_SRV_TREE_2 SrvTree2Acquire( PLWIO_SRV_TREE_2 pTree ) { LWIO_LOG_DEBUG("Acquring tree [tid:%u]", pTree->ulTid); InterlockedIncrement(&pTree->refcount); return pTree; }
VOID RdrFreeContext( PRDR_OP_CONTEXT pContext ) { if (pContext) { LWIO_LOG_DEBUG("Freed op context %p", pContext); RTL_FREE(&pContext->Packet.pRawBuffer); RTL_FREE(&pContext); } }
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); }
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); } }
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); } }
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; } }
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; }
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); }
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; }
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; }
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; }
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; }
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; }