SECURITY_STATUS ssl_recv (void) { SecBufferDesc msg; SecBuffer sb[4]; DWORD cbIoBuffer=0; SecBuffer *pData=NULL, *pExtra=NULL; int len, i; ss=SEC_E_INCOMPLETE_MESSAGE; do { if (cbIoBuffer==0 || ss==SEC_E_INCOMPLETE_MESSAGE) { len = recv (s, pbDataIn + cbIoBuffer, cbBufferLen - cbIoBuffer, 0); if (len<=0) break; cbIoBuffer += len; sb[0].pvBuffer = pbDataIn; sb[0].cbBuffer = cbIoBuffer; sb[0].BufferType = SECBUFFER_DATA; sb[1].BufferType = SECBUFFER_EMPTY; sb[2].BufferType = SECBUFFER_EMPTY; sb[3].BufferType = SECBUFFER_EMPTY; msg.ulVersion = SECBUFFER_VERSION; msg.cBuffers = 4; msg.pBuffers = sb; ss = sspi->DecryptMessage (&hContext, &msg, 0, NULL); if (ss == SEC_I_CONTEXT_EXPIRED) break; for (i=0; i<4; i++) { if (pData==NULL && sb[i].BufferType==SECBUFFER_DATA) pData=&sb[i]; if (pExtra==NULL && sb[i].BufferType==SECBUFFER_EXTRA) pExtra=&sb[i]; } if (pData!=NULL) { cbDataIn=pData->cbBuffer; if (cbDataIn!=0) { memcpy (pbDataIn, pData->pvBuffer, cbDataIn); break; } } } } while (1); return SEC_E_OK; }
int NetlibSslRead(SslHandle *ssl, char *buf, int num, int peek) { if (ssl == NULL) return SOCKET_ERROR; if (num <= 0) return 0; if (ssl->state != sockOpen || (ssl->cbRecDataBuf != 0 && (!peek || ssl->cbRecDataBuf >= num))) return NetlibSslReadSetResult(ssl, buf, num, peek); SECURITY_STATUS scRet = SEC_E_OK; while (true) { if (0 == ssl->cbIoBuffer || scRet == SEC_E_INCOMPLETE_MESSAGE) { if (ssl->sbIoBuffer <= ssl->cbIoBuffer) { ssl->sbIoBuffer += 2048; ssl->pbIoBuffer = (PUCHAR)mir_realloc(ssl->pbIoBuffer, ssl->sbIoBuffer); } if (peek) { static const TIMEVAL tv = { 0 }; fd_set fd; FD_ZERO(&fd); FD_SET(ssl->s, &fd); DWORD cbData = select(1, &fd, NULL, NULL, &tv); if (cbData == SOCKET_ERROR) { ssl->state = sockError; return NetlibSslReadSetResult(ssl, buf, num, peek); } if (cbData == 0 && ssl->cbRecDataBuf) return NetlibSslReadSetResult(ssl, buf, num, peek); } DWORD cbData = recv(ssl->s, (char*)ssl->pbIoBuffer + ssl->cbIoBuffer, ssl->sbIoBuffer - ssl->cbIoBuffer, 0); if (cbData == SOCKET_ERROR) { Netlib_Logf(NULL, "SSL failure recieving data (%d)", WSAGetLastError()); ssl->state = sockError; return NetlibSslReadSetResult(ssl, buf, num, peek); } if (cbData == 0) { Netlib_Logf(NULL, "SSL connection gracefully closed"); if (peek && ssl->cbRecDataBuf) { ssl->state = sockClosed; return NetlibSslReadSetResult(ssl, buf, num, peek); } // Server disconnected. if (ssl->cbIoBuffer) { ssl->state = sockError; return NetlibSslReadSetResult(ssl, buf, num, peek); } return 0; } ssl->cbIoBuffer += cbData; } // Attempt to decrypt the received data. SecBuffer Buffers[4]; Buffers[0].pvBuffer = ssl->pbIoBuffer; Buffers[0].cbBuffer = ssl->cbIoBuffer; Buffers[0].BufferType = SECBUFFER_DATA; Buffers[1].BufferType = SECBUFFER_EMPTY; Buffers[2].BufferType = SECBUFFER_EMPTY; Buffers[3].BufferType = SECBUFFER_EMPTY; SecBufferDesc Message; Message.ulVersion = SECBUFFER_VERSION; Message.cBuffers = _countof(Buffers); Message.pBuffers = Buffers; if (g_pSSPI->DecryptMessage != NULL && g_pSSPI->DecryptMessage != PVOID(0x80000000)) scRet = g_pSSPI->DecryptMessage(&ssl->hContext, &Message, 0, NULL); else scRet = ((DECRYPT_MESSAGE_FN)g_pSSPI->Reserved4)(&ssl->hContext, &Message, 0, NULL); // The input buffer contains only a fragment of an // encrypted record. Loop around and read some more // data. if (scRet == SEC_E_INCOMPLETE_MESSAGE) continue; if (scRet != SEC_E_OK && scRet != SEC_I_RENEGOTIATE && scRet != SEC_I_CONTEXT_EXPIRED) { ReportSslError(scRet, __LINE__); ssl->state = sockError; return NetlibSslReadSetResult(ssl, buf, num, peek); } // Locate data and (optional) extra buffers. SecBuffer *pDataBuffer = NULL; SecBuffer *pExtraBuffer = NULL; for (int i = 1; i < _countof(Buffers); i++) { if (pDataBuffer == NULL && Buffers[i].BufferType == SECBUFFER_DATA) pDataBuffer = &Buffers[i]; if (pExtraBuffer == NULL && Buffers[i].BufferType == SECBUFFER_EXTRA) pExtraBuffer = &Buffers[i]; } // Return decrypted data. DWORD resNum = 0; if (pDataBuffer) { DWORD bytes = peek ? 0 : min((DWORD)num, pDataBuffer->cbBuffer); DWORD rbytes = pDataBuffer->cbBuffer - bytes; if (rbytes > 0) { int nbytes = ssl->cbRecDataBuf + rbytes; if (ssl->sbRecDataBuf < nbytes) { ssl->sbRecDataBuf = nbytes; ssl->pbRecDataBuf = (PUCHAR)mir_realloc(ssl->pbRecDataBuf, nbytes); } memcpy(ssl->pbRecDataBuf + ssl->cbRecDataBuf, (char*)pDataBuffer->pvBuffer + bytes, rbytes); ssl->cbRecDataBuf = nbytes; } if (peek) { resNum = bytes = min(num, ssl->cbRecDataBuf); memcpy(buf, ssl->pbRecDataBuf, bytes); } else { resNum = bytes; memcpy(buf, pDataBuffer->pvBuffer, bytes); } } // Move any "extra" data to the input buffer. if (pExtraBuffer) { memmove(ssl->pbIoBuffer, pExtraBuffer->pvBuffer, pExtraBuffer->cbBuffer); ssl->cbIoBuffer = pExtraBuffer->cbBuffer; } else ssl->cbIoBuffer = 0; if (pDataBuffer && resNum) return resNum; // Server signaled end of session if (scRet == SEC_I_CONTEXT_EXPIRED) { Netlib_Logf(NULL, "SSL Server signaled SSL Shutdown"); ssl->state = sockClosed; return NetlibSslReadSetResult(ssl, buf, num, peek); } if (scRet == SEC_I_RENEGOTIATE) { // The server wants to perform another handshake // sequence. scRet = ClientHandshakeLoop(ssl, FALSE); if (scRet != SEC_E_OK) { ssl->state = sockError; return NetlibSslReadSetResult(ssl, buf, num, peek); } } } }
char* CompleteGssapi(HANDLE hSecurity, unsigned char *szChallenge, unsigned chlsz) { if (!szChallenge || !szChallenge[0]) return NULL; NtlmHandleType* hNtlm = (NtlmHandleType*)hSecurity; unsigned char inDataBuffer[1024]; SecBuffer inBuffers[2] = { { sizeof(inDataBuffer), SECBUFFER_DATA, inDataBuffer }, { chlsz, SECBUFFER_STREAM, szChallenge }, }; SecBufferDesc inBuffersDesc = { SECBUFFER_VERSION, 2, inBuffers }; unsigned long qop = 0; SECURITY_STATUS sc = g_pSSPI->DecryptMessage(&hNtlm->hClientContext, &inBuffersDesc, 0, &qop); if (sc != SEC_E_OK) { ReportSecError(sc, __LINE__); return NULL; } unsigned char LayerMask = inDataBuffer[0]; unsigned int MaxMessageSize = htonl(*(unsigned*)&inDataBuffer[1]); SecPkgContext_Sizes sizes; sc = g_pSSPI->QueryContextAttributes(&hNtlm->hClientContext, SECPKG_ATTR_SIZES, &sizes); if (sc != SEC_E_OK) { ReportSecError(sc, __LINE__); return NULL; } unsigned char *tokenBuffer = (unsigned char*)alloca(sizes.cbSecurityTrailer); unsigned char *paddingBuffer = (unsigned char*)alloca(sizes.cbBlockSize); unsigned char outDataBuffer[4] = { 1, 0, 16, 0 }; SecBuffer outBuffers[3] = { { sizes.cbSecurityTrailer, SECBUFFER_TOKEN, tokenBuffer }, { sizeof(outDataBuffer), SECBUFFER_DATA, outDataBuffer }, { sizes.cbBlockSize, SECBUFFER_PADDING, paddingBuffer } }; SecBufferDesc outBuffersDesc = { SECBUFFER_VERSION, 3, outBuffers }; sc = g_pSSPI->EncryptMessage(&hNtlm->hClientContext, SECQOP_WRAP_NO_ENCRYPT, &outBuffersDesc, 0); if (sc != SEC_E_OK) { ReportSecError(sc, __LINE__); return NULL; } unsigned i, ressz = 0; for (i = 0; i < outBuffersDesc.cBuffers; i++) ressz += outBuffersDesc.pBuffers[i].cbBuffer; unsigned char *response = (unsigned char*)alloca(ressz), *p = response; for (i = 0; i < outBuffersDesc.cBuffers; i++) { memcpy(p, outBuffersDesc.pBuffers[i].pvBuffer, outBuffersDesc.pBuffers[i].cbBuffer); p += outBuffersDesc.pBuffers[i].cbBuffer; } NETLIBBASE64 nlb64; nlb64.cbDecoded = ressz; nlb64.pbDecoded = response; nlb64.cchEncoded = Netlib_GetBase64EncodedBufferSize(nlb64.cbDecoded); nlb64.pszEncoded = (char*)alloca(nlb64.cchEncoded); if (!NetlibBase64Encode(0,(LPARAM)&nlb64)) return NULL; return mir_strdup(nlb64.pszEncoded); }
SECURITY_STATUS ReadDecrypt (void) // calls recv() - blocking socket read // http://msdn.microsoft.com/en-us/library/ms740121(VS.85).aspx // The encrypted message is decrypted in place, overwriting the original contents of its buffer. // http://msdn.microsoft.com/en-us/library/aa375211(VS.85).aspx { SecBuffer ExtraBuffer; SecBuffer *pDataBuffer, *pExtraBuffer; SECURITY_STATUS scRet; // unsigned long cbBuffer; // Size of the buffer, in bytes SecBufferDesc Message; // unsigned long BufferType; // Type of the buffer (below) SecBuffer Buffers[4]; // void SEC_FAR * pvBuffer; // Pointer to the buffer DWORD cbIoBuffer, cbData, length; PBYTE buff; int i; // Read data from server until done. cbIoBuffer = 0; scRet = 0; while(TRUE) // Read some data. { if( cbIoBuffer == 0 || scRet == SEC_E_INCOMPLETE_MESSAGE ) // get the data { cbDataIn = recv(s, pbBufferIn + cbIoBuffer, cbBufferLen - cbIoBuffer, 0); if(cbDataIn == SOCKET_ERROR) { printf("**** Error %d reading data from server\n", WSAGetLastError()); scRet = SEC_E_INTERNAL_ERROR; break; } else if(cbDataIn == 0) // Server disconnected. { if(cbIoBuffer) { printf("**** Server unexpectedly disconnected\n"); scRet = SEC_E_INTERNAL_ERROR; return scRet; } else break; // All Done } else // success { cbIoBuffer += cbDataIn; } } // Decrypt the received data. Buffers[0].pvBuffer = pbBufferIn; Buffers[0].cbBuffer = cbIoBuffer; Buffers[0].BufferType = SECBUFFER_DATA; // Initial Type of the buffer 1 Buffers[1].BufferType = SECBUFFER_EMPTY; // Initial Type of the buffer 2 Buffers[2].BufferType = SECBUFFER_EMPTY; // Initial Type of the buffer 3 Buffers[3].BufferType = SECBUFFER_EMPTY; // Initial Type of the buffer 4 Message.ulVersion = SECBUFFER_VERSION; // Version number Message.cBuffers = 4; // Number of buffers - must contain four SecBuffer structures. Message.pBuffers = Buffers; // Pointer to array of buffers scRet = sspi->DecryptMessage(&hContext, &Message, 0, NULL); if( scRet == SEC_I_CONTEXT_EXPIRED ) break; // Server signalled end of session // if( scRet == SEC_E_INCOMPLETE_MESSAGE - Input buffer has partial encrypted record, read more if( scRet != SEC_E_OK && scRet != SEC_I_RENEGOTIATE && scRet != SEC_I_CONTEXT_EXPIRED ) { printf("**** DecryptMessage "); return scRet; } // Locate data and (optional) extra buffers. pDataBuffer = NULL; pExtraBuffer = NULL; for(i = 1; i < 4; i++) { if( pDataBuffer == NULL && Buffers[i].BufferType == SECBUFFER_DATA ) pDataBuffer = &Buffers[i]; if( pExtraBuffer == NULL && Buffers[i].BufferType == SECBUFFER_EXTRA ) pExtraBuffer = &Buffers[i]; } if (pDataBuffer!=NULL) { cbDataIn=pDataBuffer->cbBuffer; if (cbDataIn!=0) { memcpy (pbDataIn, pDataBuffer->pvBuffer, cbDataIn); } } // Move any "extra" data to the input buffer. if(pExtraBuffer) { printf ("extra"); MoveMemory(pbBufferIn, pExtraBuffer->pvBuffer, pExtraBuffer->cbBuffer); cbIoBuffer = pExtraBuffer->cbBuffer; // printf("cbIoBuffer= %d \n", cbIoBuffer); } else cbIoBuffer = 0; printf ("\nhello"); } return SEC_E_OK; }