static VOID RdrNegotiateGssContextWorkItem2( PVOID pParam ) { NTSTATUS status = STATUS_SUCCESS; PRDR_OP_CONTEXT pContext = pParam; PRDR_SESSION2 pSession = pContext->State.TreeConnect.pSession2; PRDR_SOCKET pSocket = pSession->pSocket; PSMB_PACKET pPacket = pContext->State.TreeConnect.pPacket; PBYTE pInBlob = NULL; DWORD dwInBlobLength = 0; PBYTE pOutBlob = NULL; DWORD dwOutBlobLength = 0; BOOLEAN bSessionLocked = FALSE; if (pPacket) { /* Capture session id */ if (pSession->ullSessionId == 0) { pSession->ullSessionId = pPacket->pSMB2Header->ullSessionId; } else if (pSession->ullSessionId != pPacket->pSMB2Header->ullSessionId) { status = STATUS_INVALID_NETWORK_RESPONSE; BAIL_ON_NT_STATUS(status); } status = RdrSmb2DecodeSessionSetupResponse( pPacket, NULL, &pInBlob, &dwInBlobLength); BAIL_ON_NT_STATUS(status); } else { pInBlob = pSession->pSocket->pSecurityBlob; dwInBlobLength = pSession->pSocket->securityBlobLen; } if (pContext->State.TreeConnect.pszCachePath) { status = SMBKrb5SetDefaultCachePath( pContext->State.TreeConnect.pszCachePath, NULL); BAIL_ON_NT_STATUS(status); } if (!pContext->State.TreeConnect.hGssContext) { status = SMBGSSContextBuild( pSocket->pwszCanonicalName, pContext->State.TreeConnect.pCreds, &pContext->State.TreeConnect.hGssContext); BAIL_ON_NT_STATUS(status); } status = SMBGSSContextNegotiate( pContext->State.TreeConnect.hGssContext, pInBlob, dwInBlobLength, &pOutBlob, &dwOutBlobLength); BAIL_ON_NT_STATUS(status); if (!SMBGSSContextNegotiateComplete(pContext->State.TreeConnect.hGssContext)) { pContext->Continue = RdrProcessSessionSetupResponse2; status = RdrTransceiveSessionSetup2( pContext, pSession, pOutBlob, dwOutBlobLength); BAIL_ON_NT_STATUS(status); } else { LWIO_LOCK_MUTEX(bSessionLocked, &pSession->mutex); status = SMBGSSContextGetSessionKey( pContext->State.TreeConnect.hGssContext, &pSession->pSessionKey, &pSession->dwSessionKeyLength); BAIL_ON_NT_STATUS(status); if (!pSocket->pSessionKey && pSession->pSessionKey) { status = LwIoAllocateMemory( pSession->dwSessionKeyLength, OUT_PPVOID(&pSocket->pSessionKey)); BAIL_ON_NT_STATUS(status); memcpy(pSocket->pSessionKey, pSession->pSessionKey, pSession->dwSessionKeyLength); pSocket->dwSessionKeyLength = pSession->dwSessionKeyLength; } status = RdrSocketAddSession2ById(pSocket, pSession); BAIL_ON_NT_STATUS(status); pSession->state = RDR_SESSION_STATE_READY; RdrNotifyContextList( &pSession->StateWaiters, bSessionLocked, &pSession->mutex, status, pSession); LWIO_UNLOCK_MUTEX(bSessionLocked, &pSession->mutex); RdrSessionSetupComplete2(pContext, status, pSession); status = STATUS_PENDING; BAIL_ON_NT_STATUS(status); } cleanup: LWIO_UNLOCK_MUTEX(bSessionLocked, &pSession->mutex); RTL_FREE(&pOutBlob); if (status != STATUS_PENDING) { if (pSession) { RdrSession2Invalidate(pSession, status); RdrSession2Release(pSession); } RdrSessionSetupComplete2(pContext, status, NULL); } return; error: goto cleanup; }
static VOID RdrNegotiateGssContextWorkItem( PVOID pParam ) { NTSTATUS status = STATUS_SUCCESS; PRDR_OP_CONTEXT pContext = pParam; PRDR_SESSION pSession = pContext->State.TreeConnect.pSession; PRDR_SOCKET pSocket = pSession->pSocket; PSMB_PACKET pPacket = pContext->State.TreeConnect.pPacket; PWSTR pwszNativeOS = NULL; PWSTR pwszNativeLanman = NULL; PWSTR pwszNativeDomain = NULL; PBYTE pInBlob = NULL; DWORD dwInBlobLength = 0; PBYTE pOutBlob = NULL; DWORD dwOutBlobLength = 0; PSESSION_SETUP_RESPONSE_HEADER_WC_4 pResponseHeader = NULL; BOOLEAN bSessionLocked = FALSE; if (pPacket) { status = UnmarshallSessionSetupResponse_WC_4( pPacket->pParams, pPacket->bufferLen - pPacket->bufferUsed, 0, &pResponseHeader, &pInBlob, &pwszNativeOS, &pwszNativeLanman, &pwszNativeDomain); BAIL_ON_NT_STATUS(status); dwInBlobLength = pResponseHeader->securityBlobLength; } else { pInBlob = pSession->pSocket->pSecurityBlob; dwInBlobLength = pSession->pSocket->securityBlobLen; } if (pContext->State.TreeConnect.pszCachePath) { status = SMBKrb5SetDefaultCachePath( pContext->State.TreeConnect.pszCachePath, NULL); BAIL_ON_NT_STATUS(status); } if (!pContext->State.TreeConnect.hGssContext) { status = SMBGSSContextBuild( pSocket->pwszCanonicalName, pContext->State.TreeConnect.pCreds, &pContext->State.TreeConnect.hGssContext); BAIL_ON_NT_STATUS(status); } status = SMBGSSContextNegotiate( pContext->State.TreeConnect.hGssContext, pInBlob, dwInBlobLength, &pOutBlob, &dwOutBlobLength); BAIL_ON_NT_STATUS(status); if (!SMBGSSContextNegotiateComplete(pContext->State.TreeConnect.hGssContext)) { pContext->Continue = RdrProcessSessionSetupResponse; status = RdrTransceiveSessionSetup( pContext, pSession, pOutBlob, dwOutBlobLength); BAIL_ON_NT_STATUS(status); } else { LWIO_LOCK_MUTEX(bSessionLocked, &pSession->mutex); if (pContext->Packet.haveSignature && (!memcmp(pPacket->pSMBHeader->extra.securitySignature, pContext->Packet.pSMBHeader->extra.securitySignature, sizeof(pContext->Packet.pSMBHeader->extra.securitySignature)))) { LWIO_LOG_WARNING("Server is exhibiting signing bug; ignoring signatures from server"); RdrSocketSetIgnoreServerSignatures(pSocket, TRUE); } status = SMBGSSContextGetSessionKey( pContext->State.TreeConnect.hGssContext, &pSession->pSessionKey, &pSession->dwSessionKeyLength); BAIL_ON_NT_STATUS(status); if (!pSocket->pSessionKey && pSession->pSessionKey && !(pContext->State.TreeConnect.pCreds->type == IO_CREDS_TYPE_PLAIN && pContext->State.TreeConnect.pCreds->payload.plain.pwszUsername[0] == '\0')) { status = LwIoAllocateMemory( pSession->dwSessionKeyLength, OUT_PPVOID(&pSocket->pSessionKey)); BAIL_ON_NT_STATUS(status); memcpy(pSocket->pSessionKey, pSession->pSessionKey, pSession->dwSessionKeyLength); pSocket->dwSessionKeyLength = pSession->dwSessionKeyLength; RdrSocketBeginSequence(pSocket); } status = RdrSocketAddSessionByUID(pSocket, pSession); BAIL_ON_NT_STATUS(status); pSession->state = RDR_SESSION_STATE_READY; RdrNotifyContextList( &pSession->StateWaiters, bSessionLocked, &pSession->mutex, status, pSession); LWIO_UNLOCK_MUTEX(bSessionLocked, &pSession->mutex); RdrSessionSetupComplete(pContext, status, pSession); status = STATUS_PENDING; BAIL_ON_NT_STATUS(status); } cleanup: LWIO_UNLOCK_MUTEX(bSessionLocked, &pSession->mutex); RTL_FREE(&pOutBlob); if (status != STATUS_PENDING) { if (pContext->State.TreeConnect.hGssContext) { SMBGSSContextFree(pContext->State.TreeConnect.hGssContext); } RdrSessionInvalidate(pSession, status); RdrSessionRelease(pSession); RdrSessionSetupComplete(pContext, status, NULL); } return; error: goto cleanup; }