HANDLE NetlibInitSecurityProvider(const TCHAR* szProvider, const TCHAR* szPrincipal) { HANDLE hSecurity = NULL; if (mir_tstrcmpi(szProvider, _T("Basic")) == 0) { NtlmHandleType* hNtlm = (NtlmHandleType*)mir_calloc(sizeof(NtlmHandleType)); hNtlm->szProvider = mir_tstrdup(szProvider); SecInvalidateHandle(&hNtlm->hClientContext); SecInvalidateHandle(&hNtlm->hClientCredential); ntlmCnt++; return hNtlm; } mir_cslock lck(csSec); PSecPkgInfo ntlmSecurityPackageInfo; bool isGSSAPI = mir_tstrcmpi(szProvider, _T("GSSAPI")) == 0; const TCHAR *szProviderC = isGSSAPI ? _T("Kerberos") : szProvider; SECURITY_STATUS sc = QuerySecurityPackageInfo((LPTSTR)szProviderC, &ntlmSecurityPackageInfo); if (sc == SEC_E_OK) { NtlmHandleType* hNtlm; hSecurity = hNtlm = (NtlmHandleType*)mir_calloc(sizeof(NtlmHandleType)); hNtlm->cbMaxToken = ntlmSecurityPackageInfo->cbMaxToken; FreeContextBuffer(ntlmSecurityPackageInfo); hNtlm->szProvider = mir_tstrdup(szProvider); hNtlm->szPrincipal = mir_tstrdup(szPrincipal ? szPrincipal : _T("")); SecInvalidateHandle(&hNtlm->hClientContext); SecInvalidateHandle(&hNtlm->hClientCredential); ntlmCnt++; } return hSecurity; }
GSSAPISession::GSSAPISession(QString authMethod) : _authMethod(authMethod), _first(true) { #ifdef Q_OS_WIN SECURITY_STATUS status; LPWSTR methodName = new WCHAR[_authMethod.length()+1]; _authMethod.toWCharArray(methodName); methodName[_authMethod.length()] = 0; status = QuerySecurityPackageInfo(methodName, &_info); TimeStamp serverLifetime; status = AcquireCredentialsHandle(NULL, methodName, SECPKG_CRED_BOTH, NULL, NULL, NULL, NULL, &_serverHandle, &serverLifetime); _outSecBufDesc.ulVersion = 0; _outSecBufDesc.cBuffers = 1; _outSecBufDesc.pBuffers = &_outSecBuf; _outSecBuf.cbBuffer = _info->cbMaxToken; _outSecBuf.BufferType = SECBUFFER_TOKEN; _outSecBuf.pvBuffer = static_cast<PBYTE>(malloc (_info->cbMaxToken)); _inSecBufDesc.ulVersion = 0; _inSecBufDesc.cBuffers = 1; _inSecBufDesc.pBuffers = &_inSecBuf; _inSecBuf.BufferType = SECBUFFER_TOKEN; delete methodName; #endif }
static int init(const struct plugin_interface *plugin) { if(QuerySecurityPackageInfo( "SChannel", &secPackInfo ) != SEC_E_OK) return -1; if(!secPackInfo) return -1; g_sslBufferIn = (BYTE*)malloc(SSL_BUFFER_SIZE); g_sslBufferOut = (BYTE*)malloc(SSL_BUFFER_SIZE); return 0; }
void test_QuerySecurityPackageInfo(void) { SECURITY_STATUS status; SecPkgInfo* pPackageInfo; status = QuerySecurityPackageInfo("NTLM", &pPackageInfo); if (status == SEC_E_OK) { printf("\nQuerySecurityPackageInfo:\n"); printf("\"%s\", \"%s\"\n", pPackageInfo->Name, pPackageInfo->Comment); } }
int TestQuerySecurityPackageInfo(int argc, char* argv[]) { SECURITY_STATUS status; SecPkgInfo* pPackageInfo; sspi_GlobalInit(); status = QuerySecurityPackageInfo(NTLM_SSP_NAME, &pPackageInfo); if (status != SEC_E_OK) { sspi_GlobalFinish(); return -1; } _tprintf(_T("\nQuerySecurityPackageInfo:\n")); _tprintf(_T("\"%s\", \"%s\"\n"), pPackageInfo->Name, pPackageInfo->Comment); sspi_GlobalFinish(); return 0; }
BOOL AcquireCreds() { SECURITY_STATUS ss; TimeStamp Lifetime; PSecPkgInfo pkgInfo; // Set the default package to negotiate. tstrcpy_s(g_lpPackageName, 1024, TEXT("Negotiate")); // Initialize the security package. ss = QuerySecurityPackageInfo(g_lpPackageName, &pkgInfo); // get the max token size g_cbMaxMessage = pkgInfo->cbMaxToken; FreeContextBuffer(pkgInfo); // set the max token sizes g_pInBuf = (PBYTE)malloc(g_cbMaxMessage); g_pOutBuf = (PBYTE)malloc(g_cbMaxMessage); // get the security handles ss = AcquireCredentialsHandle( NULL, g_lpPackageName, SECPKG_CRED_INBOUND, NULL, NULL, NULL, NULL, &hcred, &Lifetime); if (!SEC_SUCCESS(ss)) { fprintf(stderr, "AcquireCreds failed: 0x%08x\n", ss); return(FALSE); } return (TRUE); }
int credssp_server_authenticate(rdpCredssp* credssp) { uint32 cbMaxToken; uint32 fContextReq; uint32 pfContextAttr; SECURITY_STATUS status; CredHandle credentials; TimeStamp expiration; SecPkgInfo* pPackageInfo; PSecBuffer p_buffer; SecBuffer input_buffer; SecBuffer output_buffer; SecBufferDesc input_buffer_desc; SecBufferDesc output_buffer_desc; boolean have_context; boolean have_input_buffer; boolean have_pub_key_auth; sspi_GlobalInit(); if (credssp_ntlm_server_init(credssp) == 0) return 0; credssp->table = InitSecurityInterface(); status = QuerySecurityPackageInfo(NTLM_PACKAGE_NAME, &pPackageInfo); if (status != SEC_E_OK) { printf("QuerySecurityPackageInfo status: 0x%08X\n", status); return 0; } cbMaxToken = pPackageInfo->cbMaxToken; status = credssp->table->AcquireCredentialsHandle(NULL, NTLM_PACKAGE_NAME, SECPKG_CRED_INBOUND, NULL, &credssp->identity, NULL, NULL, &credentials, &expiration); if (status != SEC_E_OK) { printf("AcquireCredentialsHandle status: 0x%08X\n", status); return 0; } have_context = false; have_input_buffer = false; have_pub_key_auth = false; memset(&input_buffer, 0, sizeof(SecBuffer)); memset(&output_buffer, 0, sizeof(SecBuffer)); memset(&credssp->ContextSizes, 0, sizeof(SecPkgContext_Sizes)); fContextReq = ISC_REQ_REPLAY_DETECT | ISC_REQ_SEQUENCE_DETECT | ISC_REQ_CONFIDENTIALITY | ISC_REQ_DELEGATE; while (true) { input_buffer_desc.ulVersion = SECBUFFER_VERSION; input_buffer_desc.cBuffers = 1; input_buffer_desc.pBuffers = &input_buffer; input_buffer.BufferType = SECBUFFER_TOKEN; /* receive authentication token */ input_buffer_desc.ulVersion = SECBUFFER_VERSION; input_buffer_desc.cBuffers = 1; input_buffer_desc.pBuffers = &input_buffer; input_buffer.BufferType = SECBUFFER_TOKEN; if (credssp_recv(credssp) < 0) return -1; #ifdef WITH_DEBUG_CREDSSP printf("Receiving Authentication Token\n"); credssp_buffer_print(credssp); #endif p_buffer = &input_buffer_desc.pBuffers[0]; p_buffer->pvBuffer = credssp->negoToken.pvBuffer; p_buffer->cbBuffer = credssp->negoToken.cbBuffer; output_buffer_desc.ulVersion = SECBUFFER_VERSION; output_buffer_desc.cBuffers = 1; output_buffer_desc.pBuffers = &output_buffer; output_buffer.BufferType = SECBUFFER_TOKEN; output_buffer.cbBuffer = cbMaxToken; output_buffer.pvBuffer = xmalloc(output_buffer.cbBuffer); status = credssp->table->AcceptSecurityContext(&credentials, have_context? &credssp->context: NULL, &input_buffer_desc, 0, SECURITY_NATIVE_DREP, &credssp->context, &output_buffer_desc, &pfContextAttr, &expiration); if (input_buffer.pvBuffer != NULL) { xfree(input_buffer.pvBuffer); input_buffer.pvBuffer = NULL; } p_buffer = &output_buffer_desc.pBuffers[0]; credssp->negoToken.pvBuffer = p_buffer->pvBuffer; credssp->negoToken.cbBuffer = p_buffer->cbBuffer; if ((status == SEC_I_COMPLETE_AND_CONTINUE) || (status == SEC_I_COMPLETE_NEEDED)) { if (credssp->table->CompleteAuthToken != NULL) credssp->table->CompleteAuthToken(&credssp->context, &output_buffer_desc); have_pub_key_auth = true; sspi_SecBufferFree(&credssp->negoToken); credssp->negoToken.pvBuffer = NULL; credssp->negoToken.cbBuffer = 0; if (credssp->table->QueryContextAttributes(&credssp->context, SECPKG_ATTR_SIZES, &credssp->ContextSizes) != SEC_E_OK) { printf("QueryContextAttributes SECPKG_ATTR_SIZES failure\n"); return 0; } if (have_pub_key_auth) { uint8* p; SecBuffer Buffers[2]; SecBufferDesc Message; Buffers[0].BufferType = SECBUFFER_DATA; /* TLS Public Key */ Buffers[1].BufferType = SECBUFFER_TOKEN; /* Signature */ Buffers[0].cbBuffer = credssp->PublicKey.cbBuffer; Buffers[0].pvBuffer = xmalloc(Buffers[0].cbBuffer); memcpy(Buffers[0].pvBuffer, credssp->PublicKey.pvBuffer, Buffers[0].cbBuffer); Buffers[1].cbBuffer = credssp->ContextSizes.cbMaxSignature; Buffers[1].pvBuffer = xzalloc(Buffers[1].cbBuffer); Message.cBuffers = 2; Message.ulVersion = SECBUFFER_VERSION; Message.pBuffers = (PSecBuffer) &Buffers; p = (uint8*) Buffers[0].pvBuffer; p[0]++; /* Public Key +1 */ sspi_SecBufferAlloc(&credssp->pubKeyAuth, Buffers[0].cbBuffer + Buffers[1].cbBuffer); credssp->table->EncryptMessage(&credssp->context, 0, &Message, 0); p = (uint8*) credssp->pubKeyAuth.pvBuffer; memcpy(p, Buffers[1].pvBuffer, Buffers[1].cbBuffer); /* Message Signature */ memcpy(&p[Buffers[1].cbBuffer], Buffers[0].pvBuffer, Buffers[0].cbBuffer); /* Encrypted Public Key */ } if (status == SEC_I_COMPLETE_NEEDED) status = SEC_E_OK; else if (status == SEC_I_COMPLETE_AND_CONTINUE) status = SEC_I_CONTINUE_NEEDED; } /* send authentication token */ #ifdef WITH_DEBUG_CREDSSP printf("Sending Authentication Token\n"); credssp_buffer_print(credssp); #endif credssp_send(credssp); credssp_buffer_free(credssp); if (status != SEC_I_CONTINUE_NEEDED) break; have_context = true; } /* Receive encrypted credentials */ if (credssp_recv(credssp) < 0) return -1; if (status != SEC_E_OK) { printf("AcceptSecurityContext status: 0x%08X\n", status); return 0; } status = credssp->table->ImpersonateSecurityContext(&credssp->context); if (status != SEC_E_OK) { printf("ImpersonateSecurityContext status: 0x%08X\n", status); return 0; } else { status = credssp->table->RevertSecurityContext(&credssp->context); if (status != SEC_E_OK) { printf("RevertSecurityContext status: 0x%08X\n", status); return 0; } } FreeContextBuffer(pPackageInfo); return 1; }
void test_InitializeSecurityContext(void) { uint32 cbMaxLen; uint32 fContextReq; void* output_buffer; CtxtHandle context; uint32 pfContextAttr; SECURITY_STATUS status; CredHandle credentials; TimeStamp expiration; SecPkgInfo* pPackageInfo; SEC_WINNT_AUTH_IDENTITY identity; SecurityFunctionTable* table; SecBuffer* p_SecBuffer; SecBuffer output_SecBuffer; SecBufferDesc output_SecBuffer_desc; table = InitSecurityInterface(); status = QuerySecurityPackageInfo(NTLM_PACKAGE_NAME, &pPackageInfo); if (status != SEC_E_OK) { printf("QuerySecurityPackageInfo status: 0x%08X\n", status); return; } cbMaxLen = pPackageInfo->cbMaxToken; identity.User = (uint16*) xstrdup(test_User); identity.UserLength = sizeof(test_User); identity.Domain = (uint16*) xstrdup(test_Domain); identity.DomainLength = sizeof(test_Domain); identity.Password = (uint16*) xstrdup(test_Password); identity.PasswordLength = sizeof(test_Password); identity.Flags = SEC_WINNT_AUTH_IDENTITY_ANSI; status = table->AcquireCredentialsHandle(NULL, NTLM_PACKAGE_NAME, SECPKG_CRED_OUTBOUND, NULL, &identity, NULL, NULL, &credentials, &expiration); if (status != SEC_E_OK) { printf("AcquireCredentialsHandle status: 0x%08X\n", status); return; } fContextReq = ISC_REQ_REPLAY_DETECT | ISC_REQ_SEQUENCE_DETECT | ISC_REQ_CONFIDENTIALITY | ISC_REQ_DELEGATE; output_buffer = xmalloc(cbMaxLen); output_SecBuffer_desc.ulVersion = 0; output_SecBuffer_desc.cBuffers = 1; output_SecBuffer_desc.pBuffers = &output_SecBuffer; output_SecBuffer.cbBuffer = cbMaxLen; output_SecBuffer.BufferType = SECBUFFER_TOKEN; output_SecBuffer.pvBuffer = output_buffer; status = table->InitializeSecurityContext(&credentials, NULL, NULL, fContextReq, 0, 0, NULL, 0, &context, &output_SecBuffer_desc, &pfContextAttr, &expiration); if (status != SEC_I_CONTINUE_NEEDED) { printf("InitializeSecurityContext status: 0x%08X\n", status); return; } printf("cBuffers: %d ulVersion: %d\n", output_SecBuffer_desc.cBuffers, output_SecBuffer_desc.ulVersion); p_SecBuffer = &output_SecBuffer_desc.pBuffers[0]; printf("BufferType: 0x%04X cbBuffer:%d\n", p_SecBuffer->BufferType, p_SecBuffer->cbBuffer); freerdp_hexdump((uint8*) p_SecBuffer->pvBuffer, p_SecBuffer->cbBuffer); table->FreeCredentialsHandle(&credentials); FreeContextBuffer(pPackageInfo); }
int credssp_client_authenticate(rdpCredssp* credssp) { uint32 cbMaxLen; uint32 fContextReq; uint32 pfContextAttr; SECURITY_STATUS status; CRED_HANDLE credentials; SEC_TIMESTAMP expiration; SEC_PKG_INFO* pPackageInfo; SEC_AUTH_IDENTITY identity; SEC_BUFFER* p_sec_buffer; SEC_BUFFER input_sec_buffer; SEC_BUFFER output_sec_buffer; SEC_BUFFER_DESC input_sec_buffer_desc; SEC_BUFFER_DESC output_sec_buffer_desc; boolean have_context; boolean have_input_buffer; boolean have_pub_key_auth; rdpSettings* settings = credssp->settings; sspi_GlobalInit(); if (credssp_ntlmssp_client_init(credssp) == 0) return 0; credssp->table = InitSecurityInterface(); status = QuerySecurityPackageInfo(NTLM_PACKAGE_NAME, &pPackageInfo); if (status != SEC_E_OK) { printf("QuerySecurityPackageInfo status: 0x%08X\n", status); return 0; } cbMaxLen = pPackageInfo->cbMaxToken; identity.User = (uint16*) xstrdup(settings->username); identity.UserLength = strlen(settings->username); if (settings->domain) { identity.Domain = (uint16*) xstrdup(settings->domain); identity.DomainLength = strlen(settings->domain); } else { identity.Domain = (uint16*) NULL; identity.DomainLength = 0; } identity.Password = (uint16*) xstrdup(settings->password); identity.PasswordLength = strlen(settings->password); identity.Flags = SEC_AUTH_IDENTITY_ANSI; status = credssp->table->AcquireCredentialsHandle(NULL, NTLM_PACKAGE_NAME, SECPKG_CRED_OUTBOUND, NULL, &identity, NULL, NULL, &credentials, &expiration); if (status != SEC_E_OK) { printf("AcquireCredentialsHandle status: 0x%08X\n", status); return 0; } have_context = false; have_input_buffer = false; have_pub_key_auth = false; memset(&input_sec_buffer, 0, sizeof(SEC_BUFFER)); memset(&output_sec_buffer, 0, sizeof(SEC_BUFFER)); memset(&credssp->ContextSizes, 0, sizeof(SEC_PKG_CONTEXT_SIZES)); fContextReq = ISC_REQ_REPLAY_DETECT | ISC_REQ_SEQUENCE_DETECT | ISC_REQ_CONFIDENTIALITY | ISC_REQ_DELEGATE; while (true) { output_sec_buffer_desc.ulVersion = SECBUFFER_VERSION; output_sec_buffer_desc.cBuffers = 1; output_sec_buffer_desc.pBuffers = &output_sec_buffer; output_sec_buffer.BufferType = SECBUFFER_TOKEN; output_sec_buffer.cbBuffer = cbMaxLen; output_sec_buffer.pvBuffer = xmalloc(output_sec_buffer.cbBuffer); status = credssp->table->InitializeSecurityContext(&credentials, (have_context) ? &credssp->context : NULL, NULL, fContextReq, 0, SECURITY_NATIVE_DREP, (have_input_buffer) ? &input_sec_buffer_desc : NULL, 0, &credssp->context, &output_sec_buffer_desc, &pfContextAttr, &expiration); if (input_sec_buffer.pvBuffer != NULL) { xfree(input_sec_buffer.pvBuffer); input_sec_buffer.pvBuffer = NULL; } if ((status == SEC_I_COMPLETE_AND_CONTINUE) || (status == SEC_I_COMPLETE_NEEDED)) { if (credssp->table->CompleteAuthToken != NULL) credssp->table->CompleteAuthToken(&credssp->context, &output_sec_buffer_desc); have_pub_key_auth = true; if (credssp->table->QueryContextAttributes(&credssp->context, SECPKG_ATTR_SIZES, &credssp->ContextSizes) != SEC_E_OK) { printf("QueryContextAttributes SECPKG_ATTR_SIZES failure\n"); return 0; } if (have_pub_key_auth) { uint8* p; SEC_BUFFER Buffers[2]; SEC_BUFFER_DESC Message; Buffers[0].BufferType = SECBUFFER_DATA; /* TLS Public Key */ Buffers[1].BufferType = SECBUFFER_PADDING; /* Signature */ Buffers[0].cbBuffer = credssp->PublicKey.cbBuffer; Buffers[0].pvBuffer = xmalloc(Buffers[0].cbBuffer); memcpy(Buffers[0].pvBuffer, credssp->PublicKey.pvBuffer, Buffers[0].cbBuffer); Buffers[1].cbBuffer = credssp->ContextSizes.cbMaxSignature; Buffers[1].pvBuffer = xzalloc(Buffers[1].cbBuffer); Message.cBuffers = 2; Message.ulVersion = SECBUFFER_VERSION; Message.pBuffers = (SEC_BUFFER*) &Buffers; sspi_SecBufferAlloc(&credssp->pubKeyAuth, Buffers[0].cbBuffer + Buffers[1].cbBuffer); credssp->table->EncryptMessage(&credssp->context, 0, &Message, 0); p = (uint8*) credssp->pubKeyAuth.pvBuffer; memcpy(p, Buffers[1].pvBuffer, Buffers[1].cbBuffer); /* Message Signature */ memcpy(&p[Buffers[1].cbBuffer], Buffers[0].pvBuffer, Buffers[0].cbBuffer); /* Encrypted Public Key */ } if (status == SEC_I_COMPLETE_NEEDED) status = SEC_E_OK; else if (status == SEC_I_COMPLETE_AND_CONTINUE) status = SEC_I_CONTINUE_NEEDED; } /* send authentication token to server */ if (output_sec_buffer.cbBuffer > 0) { p_sec_buffer = &output_sec_buffer_desc.pBuffers[0]; credssp->negoToken.pvBuffer = p_sec_buffer->pvBuffer; credssp->negoToken.cbBuffer = p_sec_buffer->cbBuffer; #ifdef WITH_DEBUG_CREDSSP printf("Sending Authentication Token\n"); freerdp_hexdump(credssp->negoToken.data, credssp->negoToken.length); #endif credssp_send(credssp, &credssp->negoToken, NULL, (have_pub_key_auth) ? &credssp->pubKeyAuth : NULL); if (have_pub_key_auth) { have_pub_key_auth = false; sspi_SecBufferFree(&credssp->pubKeyAuth); } xfree(output_sec_buffer.pvBuffer); output_sec_buffer.pvBuffer = NULL; } if (status != SEC_I_CONTINUE_NEEDED) break; /* receive server response and place in input buffer */ input_sec_buffer_desc.ulVersion = SECBUFFER_VERSION; input_sec_buffer_desc.cBuffers = 1; input_sec_buffer_desc.pBuffers = &input_sec_buffer; input_sec_buffer.BufferType = SECBUFFER_TOKEN; if (credssp_recv(credssp, &credssp->negoToken, NULL, NULL) < 0) return -1; #ifdef WITH_DEBUG_CREDSSP printf("Receiving Authentication Token\n"); freerdp_hexdump(credssp->negoToken.data, credssp->negoToken.length); #endif p_sec_buffer = &input_sec_buffer_desc.pBuffers[0]; p_sec_buffer->pvBuffer = credssp->negoToken.pvBuffer; p_sec_buffer->cbBuffer = credssp->negoToken.cbBuffer; have_input_buffer = true; have_context = true; } /* Encrypted Public Key +1 */ if (credssp_recv(credssp, &credssp->negoToken, NULL, &credssp->pubKeyAuth) < 0) return -1; /* Verify Server Public Key Echo */ status = credssp_verify_public_key_echo(credssp); if (status != SEC_E_OK) return 0; /* Send encrypted credentials */ status = credssp_encrypt_ts_credentials(credssp); if (status != SEC_E_OK) return 0; credssp_send(credssp, NULL, &credssp->authInfo, NULL); /* Free resources */ //sspi_SecBufferFree(&credssp->negoToken); sspi_SecBufferFree(&credssp->authInfo); FreeCredentialsHandle(&credentials); FreeContextBuffer(pPackageInfo); return 1; }
int TestInitializeSecurityContext(int argc, char* argv[]) { UINT32 cbMaxLen; UINT32 fContextReq; void* output_buffer; CtxtHandle context; ULONG pfContextAttr; SECURITY_STATUS status; CredHandle credentials; TimeStamp expiration; PSecPkgInfo pPackageInfo; SEC_WINNT_AUTH_IDENTITY identity; SecurityFunctionTable* table; PSecBuffer p_SecBuffer; SecBuffer output_SecBuffer; SecBufferDesc output_SecBuffer_desc; sspi_GlobalInit(); table = InitSecurityInterface(); status = QuerySecurityPackageInfo(NTLMSP_NAME, &pPackageInfo); if (status != SEC_E_OK) { printf("QuerySecurityPackageInfo status: 0x%08X\n", status); return -1; } cbMaxLen = pPackageInfo->cbMaxToken; identity.User = (UINT16*) _strdup(test_User); identity.UserLength = sizeof(test_User); identity.Domain = (UINT16*) _strdup(test_Domain); identity.DomainLength = sizeof(test_Domain); identity.Password = (UINT16*) _strdup(test_Password); identity.PasswordLength = sizeof(test_Password); identity.Flags = SEC_WINNT_AUTH_IDENTITY_ANSI; status = table->AcquireCredentialsHandle(NULL, NTLMSP_NAME, SECPKG_CRED_OUTBOUND, NULL, &identity, NULL, NULL, &credentials, &expiration); if (status != SEC_E_OK) { printf("AcquireCredentialsHandle status: 0x%08X\n", status); sspi_GlobalFinish(); return -1; } fContextReq = ISC_REQ_REPLAY_DETECT | ISC_REQ_SEQUENCE_DETECT | ISC_REQ_CONFIDENTIALITY | ISC_REQ_DELEGATE; output_buffer = malloc(cbMaxLen); if (!output_buffer) { printf("Memory allocation failed\n"); sspi_GlobalFinish(); return -1; } output_SecBuffer_desc.ulVersion = 0; output_SecBuffer_desc.cBuffers = 1; output_SecBuffer_desc.pBuffers = &output_SecBuffer; output_SecBuffer.cbBuffer = cbMaxLen; output_SecBuffer.BufferType = SECBUFFER_TOKEN; output_SecBuffer.pvBuffer = output_buffer; status = table->InitializeSecurityContext(&credentials, NULL, NULL, fContextReq, 0, 0, NULL, 0, &context, &output_SecBuffer_desc, &pfContextAttr, &expiration); if (status != SEC_I_CONTINUE_NEEDED) { printf("InitializeSecurityContext status: 0x%08X\n", status); sspi_GlobalFinish(); return -1; } printf("cBuffers: %d ulVersion: %d\n", output_SecBuffer_desc.cBuffers, output_SecBuffer_desc.ulVersion); p_SecBuffer = &output_SecBuffer_desc.pBuffers[0]; printf("BufferType: 0x%04X cbBuffer: %d\n", p_SecBuffer->BufferType, p_SecBuffer->cbBuffer); table->FreeCredentialsHandle(&credentials); FreeContextBuffer(pPackageInfo); sspi_GlobalFinish(); return 0; }
void LSSLContext::Handshake(LSockByteStream* SockByteStream, const TCHAR* TargetName) { SecPkgInfo* PkgInfo; /*VERIFY(SEC_E_OK==*/QuerySecurityPackageInfo(UNISP_NAME, &PkgInfo)/*)*/; std::vector<BYTE> SockDataBuf(PkgInfo->cbMaxToken); FreeContextBuffer(PkgInfo); //SSPI:HandShake SecBufferDesc InBufferDesc; SecBuffer InBuffers[2]; InBufferDesc.ulVersion = SECBUFFER_VERSION; InBufferDesc.pBuffers = InBuffers; InBufferDesc.cBuffers = 2; SecBufferDesc OutBufferDesc; SecBuffer OutBuffers[1]; OutBufferDesc.ulVersion = SECBUFFER_VERSION; OutBufferDesc.pBuffers = OutBuffers; OutBufferDesc.cBuffers = 1; //первичное обращение об инициализации контекста OutBuffers[0].BufferType = SECBUFFER_TOKEN; OutBuffers[0].pvBuffer = NULL; OutBuffers[0].cbBuffer = 0; SECURITY_STATUS sec_s = InitializeSecurityContext(&m_hUserCred, 0, const_cast<TCHAR*>(TargetName), m_ReqContextAttr, 0, 0, NULL, 0, &m_hContext, &OutBufferDesc, &m_ContextAttr, &m_ContextExpiry); //ASSERT(SEC_E_OK==sec_s||SEC_I_CONTINUE_NEEDED==sec_s); unsigned int SockDataSize=0; bool WasExtra=false; while(SEC_I_CONTINUE_NEEDED==sec_s){ //оба поля должны быть либо указаны либо не указаны, т.к. иначе не совсем понятно что это означает //ASSERT((OutBuffers[0].pvBuffer&&OutBuffers[0].cbBuffer)||(!OutBuffers[0].pvBuffer&&!OutBuffers[0].cbBuffer)); //отсылаем только если есть что отсылать if(OutBuffers[0].pvBuffer&&OutBuffers[0].cbBuffer){ //ASSERT(OutBuffers[0].pvBuffer); //ASSERT(OutBuffers[0].cbBuffer); //WS: отправим обработанные SCHANNEL данные SockByteStream->RawSend(OutBuffers[0].pvBuffer, OutBuffers[0].cbBuffer); //SSPI:освободим выделенную SCHANNEL память FreeContextBuffer(OutBuffers[0].pvBuffer); } //OutBuffers[0].BufferType=SECBUFFER_EMPTY; OutBuffers[0].pvBuffer=0; OutBuffers[0].cbBuffer=0;//нет необходимости do{ //ASSERT(SockDataBuf.size()>SockDataSize); //WS:получим ответ сервера (или его часть) if(!WasExtra){ SockDataSize+= SockByteStream->RawRecv(&SockDataBuf[SockDataSize], SockDataBuf.size()-SockDataSize); } else{ //пропустим 1 получение данных, т.к. в SECBUFFER_EXTRA может быть полный пакет, //и как следствие сервер ничего уже посылать не будет. //если же пакет все же не полный то получим SEC_E_INCOMPLETE_MESSAGE, //и просто выполним лишнюю итерацию. WasExtra=false; } //SSPI:передадим этот ответ в InitializeSecurityContext, и в случае если он скажет что надо еще данных - //опять запросим данные с сервера. и так до тех пор пока SCHANNEL не скажет "хватит". InBuffers[0].BufferType = SECBUFFER_TOKEN; InBuffers[0].pvBuffer = &SockDataBuf[0]; InBuffers[0].cbBuffer = SockDataSize; InBuffers[1].BufferType = SECBUFFER_EMPTY; InBuffers[1].pvBuffer = NULL; InBuffers[1].cbBuffer = 0; sec_s = InitializeSecurityContext(&m_hUserCred, &m_hContext, const_cast<TCHAR*>(TargetName), m_ReqContextAttr, 0, 0, &InBufferDesc, 0, 0, &OutBufferDesc, &m_ContextAttr, &m_ContextExpiry); }while(SEC_E_INCOMPLETE_MESSAGE==sec_s); //ASSERT(SEC_E_OK==sec_s||SEC_I_CONTINUE_NEEDED==sec_s); //может быть SECBUFFER_EXTRA //ASSERT(SECBUFFER_EXTRA!=InBuffers[0].BufferType);//такого вроде не должно быть if(SECBUFFER_EXTRA==InBuffers[1].BufferType){ WasExtra=true; if(SEC_I_CONTINUE_NEEDED==sec_s){ //Handshake еще не завершен. просто сервер выслал больше данных чем нужно было на данном шаге. //переносим эти данные на следующую итерацию memmove(&SockDataBuf[0], ((BYTE*)InBuffers[0].pvBuffer)+InBuffers[0].cbBuffer-InBuffers[1].cbBuffer, InBuffers[1].cbBuffer); SockDataSize=InBuffers[1].cbBuffer; } else{ //если Handshake уже завершен, значит SECBUFFER_EXTRA относится уже к основному протоколу обмена. //значит нужно сохранить эту информацию во временном хранилище. m_HandshakeExtra.insert(m_HandshakeExtra.end(), ((BYTE*)InBuffers[0].pvBuffer)+InBuffers[0].cbBuffer-InBuffers[1].cbBuffer, ((BYTE*)InBuffers[0].pvBuffer)+InBuffers[0].cbBuffer); SockDataSize=0; } } else{ SockDataSize=0; } } //ASSERT(0==OutBuffers[0].pvBuffer);//по идее не должно быть выделенной памяти. }