int TestEnumerateSecurityPackages(int argc, char* argv[]) { int index; ULONG cPackages; SECURITY_STATUS status; SecPkgInfo* pPackageInfo; sspi_GlobalInit(); status = EnumerateSecurityPackages(&cPackages, &pPackageInfo); if (status != SEC_E_OK) { sspi_GlobalFinish(); return -1; } _tprintf(_T("\nEnumerateSecurityPackages (%")_T(PRIu32)_T("):\n"), cPackages); for (index = 0; index < (int) cPackages; index++) { _tprintf(_T("\"%s\", \"%s\"\n"), pPackageInfo[index].Name, pPackageInfo[index].Comment); } FreeContextBuffer(pPackageInfo); sspi_GlobalFinish(); return 0; }
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; }
void InitializeSspiModule(DWORD flags) { BOOL status = FALSE; if (g_Initialized) return; g_Initialized = TRUE; sspi_GlobalInit(); g_Log = WLog_Get("com.winpr.sspi"); #if defined(WITH_NATIVE_SSPI) if (flags && (flags & SSPI_INTERFACE_NATIVE)) { status = InitializeSspiModule_Native(); } else if (flags && (flags & SSPI_INTERFACE_WINPR)) { g_SspiW = winpr_InitSecurityInterfaceW(); g_SspiA = winpr_InitSecurityInterfaceA(); status = TRUE; } if (!status && ShouldUseNativeSspi()) { status = InitializeSspiModule_Native(); } #endif if (!status) { g_SspiW = winpr_InitSecurityInterfaceW(); g_SspiA = winpr_InitSecurityInterfaceA(); } }
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; }
BOOL ntlm_client_init(rdpNtlm* ntlm, BOOL http, char* user, char* domain, char* password, SecPkgContext_Bindings* Bindings) { SECURITY_STATUS status; sspi_GlobalInit(); ntlm->http = http; ntlm->Bindings = Bindings; #ifdef WITH_NATIVE_SSPI { HMODULE hSSPI; INIT_SECURITY_INTERFACE InitSecurityInterface; PSecurityFunctionTable pSecurityInterface = NULL; hSSPI = LoadLibrary(_T("secur32.dll")); #ifdef UNICODE InitSecurityInterface = (INIT_SECURITY_INTERFACE) GetProcAddress(hSSPI, "InitSecurityInterfaceW"); #else InitSecurityInterface = (INIT_SECURITY_INTERFACE) GetProcAddress(hSSPI, "InitSecurityInterfaceA"); #endif ntlm->table = (*InitSecurityInterface)(); } #else ntlm->table = InitSecurityInterface(); #endif sspi_SetAuthIdentity(&(ntlm->identity), user, domain, password); status = ntlm->table->QuerySecurityPackageInfo(NTLMSP_NAME, &ntlm->pPackageInfo); if (status != SEC_E_OK) { DEBUG_WARN( "QuerySecurityPackageInfo status: 0x%08X\n", status); return FALSE; } ntlm->cbMaxToken = ntlm->pPackageInfo->cbMaxToken; status = ntlm->table->AcquireCredentialsHandle(NULL, NTLMSP_NAME, SECPKG_CRED_OUTBOUND, NULL, &ntlm->identity, NULL, NULL, &ntlm->credentials, &ntlm->expiration); if (status != SEC_E_OK) { DEBUG_WARN( "AcquireCredentialsHandle status: 0x%08X\n", status); return FALSE; } ntlm->haveContext = FALSE; ntlm->haveInputBuffer = FALSE; ZeroMemory(&ntlm->inputBuffer, sizeof(SecBuffer)); ZeroMemory(&ntlm->outputBuffer, sizeof(SecBuffer)); ZeroMemory(&ntlm->ContextSizes, sizeof(SecPkgContext_Sizes)); ntlm->fContextReq = 0; if (ntlm->http) { /* flags for HTTP authentication */ ntlm->fContextReq |= ISC_REQ_CONFIDENTIALITY; } else { /** * flags for RPC authentication: * RPC_C_AUTHN_LEVEL_PKT_INTEGRITY: * ISC_REQ_USE_DCE_STYLE | ISC_REQ_DELEGATE | ISC_REQ_MUTUAL_AUTH | * ISC_REQ_REPLAY_DETECT | ISC_REQ_SEQUENCE_DETECT */ ntlm->fContextReq |= ISC_REQ_USE_DCE_STYLE; ntlm->fContextReq |= ISC_REQ_DELEGATE | ISC_REQ_MUTUAL_AUTH; ntlm->fContextReq |= ISC_REQ_REPLAY_DETECT | ISC_REQ_SEQUENCE_DETECT; } return TRUE; }
int init_sspi_suite(void) { sspi_GlobalInit(); return 0; }
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; }
boolean ntlm_client_init(rdpNtlm* ntlm, boolean confidentiality, char* user, char* domain, char* password) { size_t size; SECURITY_STATUS status; sspi_GlobalInit(); ntlm->confidentiality = confidentiality; #ifdef WITH_NATIVE_SSPI { HMODULE hSSPI; INIT_SECURITY_INTERFACE InitSecurityInterface; PSecurityFunctionTable pSecurityInterface = NULL; hSSPI = LoadLibrary(_T("secur32.dll")); #ifdef UNICODE InitSecurityInterface = (INIT_SECURITY_INTERFACE) GetProcAddress(hSSPI, "InitSecurityInterfaceW"); #else InitSecurityInterface = (INIT_SECURITY_INTERFACE) GetProcAddress(hSSPI, "InitSecurityInterfaceA"); #endif ntlm->table = (*InitSecurityInterface)(); } #else ntlm->table = InitSecurityInterface(); #endif ntlm->identity.Flags = SEC_WINNT_AUTH_IDENTITY_UNICODE; ntlm->identity.User = (uint16*) freerdp_uniconv_out(ntlm->uniconv, user, &size); ntlm->identity.UserLength = (uint32) size; if (domain) { ntlm->identity.Domain = (uint16*) freerdp_uniconv_out(ntlm->uniconv, domain, &size); ntlm->identity.DomainLength = (uint32) size; } else { ntlm->identity.Domain = (uint16*) NULL; ntlm->identity.DomainLength = 0; } ntlm->identity.Password = (uint16*) freerdp_uniconv_out(ntlm->uniconv, (char*) password, &size); ntlm->identity.PasswordLength = (uint32) size; status = ntlm->table->QuerySecurityPackageInfo(NTLMSP_NAME, &ntlm->pPackageInfo); if (status != SEC_E_OK) { printf("QuerySecurityPackageInfo status: 0x%08X\n", status); return false; } ntlm->cbMaxToken = ntlm->pPackageInfo->cbMaxToken; status = ntlm->table->AcquireCredentialsHandle(NULL, NTLMSP_NAME, SECPKG_CRED_OUTBOUND, NULL, &ntlm->identity, NULL, NULL, &ntlm->credentials, &ntlm->expiration); if (status != SEC_E_OK) { printf("AcquireCredentialsHandle status: 0x%08X\n", status); return false; } ntlm->haveContext = false; ntlm->haveInputBuffer = false; memset(&ntlm->inputBuffer, 0, sizeof(SecBuffer)); memset(&ntlm->outputBuffer, 0, sizeof(SecBuffer)); memset(&ntlm->ContextSizes, 0, sizeof(SecPkgContext_Sizes)); ntlm->fContextReq = ISC_REQ_REPLAY_DETECT | ISC_REQ_SEQUENCE_DETECT | ISC_REQ_DELEGATE; if (ntlm->confidentiality) ntlm->fContextReq |= ISC_REQ_CONFIDENTIALITY; return true; }
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; }
int credssp_server_authenticate(rdpCredssp* credssp) { UINT32 cbMaxToken; ULONG fContextReq; ULONG pfContextAttr; SECURITY_STATUS status; CredHandle credentials; TimeStamp expiration; PSecPkgInfo pPackageInfo; SecBuffer input_buffer; SecBuffer output_buffer; SecBufferDesc input_buffer_desc; SecBufferDesc output_buffer_desc; BOOL have_context; BOOL have_input_buffer; BOOL have_pub_key_auth; sspi_GlobalInit(); if (credssp_ntlm_server_init(credssp) == 0) return 0; #ifdef WITH_NATIVE_SSPI if (!credssp->SspiModule) credssp->SspiModule = _tcsdup(_T("secur32.dll")); #endif if (credssp->SspiModule) { HMODULE hSSPI; INIT_SECURITY_INTERFACE pInitSecurityInterface; hSSPI = LoadLibrary(credssp->SspiModule); if (!hSSPI) { _tprintf(_T("Failed to load SSPI module: %s\n"), credssp->SspiModule); return 0; } #ifdef UNICODE pInitSecurityInterface = (INIT_SECURITY_INTERFACE) GetProcAddress(hSSPI, "InitSecurityInterfaceW"); #else pInitSecurityInterface = (INIT_SECURITY_INTERFACE) GetProcAddress(hSSPI, "InitSecurityInterfaceA"); #endif credssp->table = (*pInitSecurityInterface)(); } #ifndef WITH_NATIVE_SSPI else { credssp->table = InitSecurityInterface(); } #endif status = credssp->table->QuerySecurityPackageInfo(NLA_PKG_NAME, &pPackageInfo); if (status != SEC_E_OK) { fprintf(stderr, "QuerySecurityPackageInfo status: 0x%08X\n", status); return 0; } cbMaxToken = pPackageInfo->cbMaxToken; status = credssp->table->AcquireCredentialsHandle(NULL, NLA_PKG_NAME, SECPKG_CRED_INBOUND, NULL, NULL, NULL, NULL, &credentials, &expiration); if (status != SEC_E_OK) { fprintf(stderr, "AcquireCredentialsHandle status: 0x%08X\n", status); return 0; } have_context = FALSE; have_input_buffer = FALSE; have_pub_key_auth = FALSE; ZeroMemory(&input_buffer, sizeof(SecBuffer)); ZeroMemory(&output_buffer, sizeof(SecBuffer)); ZeroMemory(&input_buffer_desc, sizeof(SecBufferDesc)); ZeroMemory(&output_buffer_desc, sizeof(SecBufferDesc)); ZeroMemory(&credssp->ContextSizes, sizeof(SecPkgContext_Sizes)); /* * from tspkg.dll: 0x00000112 * ASC_REQ_MUTUAL_AUTH * ASC_REQ_CONFIDENTIALITY * ASC_REQ_ALLOCATE_MEMORY */ fContextReq = 0; fContextReq |= ASC_REQ_MUTUAL_AUTH; fContextReq |= ASC_REQ_CONFIDENTIALITY; fContextReq |= ASC_REQ_CONNECTION; fContextReq |= ASC_REQ_USE_SESSION_KEY; fContextReq |= ASC_REQ_REPLAY_DETECT; fContextReq |= ASC_REQ_SEQUENCE_DETECT; fContextReq |= ASC_REQ_EXTENDED_ERROR; 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 fprintf(stderr, "Receiving Authentication Token\n"); credssp_buffer_print(credssp); #endif input_buffer.pvBuffer = credssp->negoToken.pvBuffer; input_buffer.cbBuffer = credssp->negoToken.cbBuffer; if (credssp->negoToken.cbBuffer < 1) { fprintf(stderr, "CredSSP: invalid negoToken!\n"); return -1; } 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 = malloc(output_buffer.cbBuffer); status = credssp->table->AcceptSecurityContext(&credentials, have_context? &credssp->context: NULL, &input_buffer_desc, fContextReq, SECURITY_NATIVE_DREP, &credssp->context, &output_buffer_desc, &pfContextAttr, &expiration); credssp->negoToken.pvBuffer = output_buffer.pvBuffer; credssp->negoToken.cbBuffer = output_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); if (status == SEC_I_COMPLETE_NEEDED) status = SEC_E_OK; else if (status == SEC_I_COMPLETE_AND_CONTINUE) status = SEC_I_CONTINUE_NEEDED; } if (status == SEC_E_OK) { have_pub_key_auth = TRUE; if (credssp->table->QueryContextAttributes(&credssp->context, SECPKG_ATTR_SIZES, &credssp->ContextSizes) != SEC_E_OK) { fprintf(stderr, "QueryContextAttributes SECPKG_ATTR_SIZES failure\n"); return 0; } if (credssp_decrypt_public_key_echo(credssp) != SEC_E_OK) { fprintf(stderr, "Error: could not verify client's public key echo\n"); return -1; } sspi_SecBufferFree(&credssp->negoToken); credssp->negoToken.pvBuffer = NULL; credssp->negoToken.cbBuffer = 0; credssp_encrypt_public_key_echo(credssp); } if ((status != SEC_E_OK) && (status != SEC_I_CONTINUE_NEEDED)) { fprintf(stderr, "AcceptSecurityContext status: 0x%08X\n", status); return -1; } /* send authentication token */ #ifdef WITH_DEBUG_CREDSSP fprintf(stderr, "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 (credssp_decrypt_ts_credentials(credssp) != SEC_E_OK) { fprintf(stderr, "Could not decrypt TSCredentials status: 0x%08X\n", status); return 0; } if (status != SEC_E_OK) { fprintf(stderr, "AcceptSecurityContext status: 0x%08X\n", status); return 0; } status = credssp->table->ImpersonateSecurityContext(&credssp->context); if (status != SEC_E_OK) { fprintf(stderr, "ImpersonateSecurityContext status: 0x%08X\n", status); return 0; } else { status = credssp->table->RevertSecurityContext(&credssp->context); if (status != SEC_E_OK) { fprintf(stderr, "RevertSecurityContext status: 0x%08X\n", status); return 0; } } credssp->table->FreeContextBuffer(pPackageInfo); return 1; }
int credssp_client_authenticate(rdpCredssp* credssp) { ULONG cbMaxToken; ULONG fContextReq; ULONG pfContextAttr; SECURITY_STATUS status; CredHandle credentials; TimeStamp expiration; PSecPkgInfo pPackageInfo; SecBuffer input_buffer; SecBuffer output_buffer; SecBufferDesc input_buffer_desc; SecBufferDesc output_buffer_desc; BOOL have_context; BOOL have_input_buffer; BOOL have_pub_key_auth; sspi_GlobalInit(); if (credssp_ntlm_client_init(credssp) == 0) return 0; #ifdef WITH_NATIVE_SSPI { HMODULE hSSPI; INIT_SECURITY_INTERFACE InitSecurityInterface; PSecurityFunctionTable pSecurityInterface = NULL; hSSPI = LoadLibrary(_T("secur32.dll")); #ifdef UNICODE InitSecurityInterface = (INIT_SECURITY_INTERFACE) GetProcAddress(hSSPI, "InitSecurityInterfaceW"); #else InitSecurityInterface = (INIT_SECURITY_INTERFACE) GetProcAddress(hSSPI, "InitSecurityInterfaceA"); #endif credssp->table = (*InitSecurityInterface)(); } #else credssp->table = InitSecurityInterface(); #endif status = credssp->table->QuerySecurityPackageInfo(NLA_PKG_NAME, &pPackageInfo); if (status != SEC_E_OK) { fprintf(stderr, "QuerySecurityPackageInfo status: 0x%08X\n", status); return 0; } cbMaxToken = pPackageInfo->cbMaxToken; status = credssp->table->AcquireCredentialsHandle(NULL, NLA_PKG_NAME, SECPKG_CRED_OUTBOUND, NULL, &credssp->identity, NULL, NULL, &credentials, &expiration); if (status != SEC_E_OK) { fprintf(stderr, "AcquireCredentialsHandle status: 0x%08X\n", status); return 0; } have_context = FALSE; have_input_buffer = FALSE; have_pub_key_auth = FALSE; ZeroMemory(&input_buffer, sizeof(SecBuffer)); ZeroMemory(&output_buffer, sizeof(SecBuffer)); ZeroMemory(&credssp->ContextSizes, sizeof(SecPkgContext_Sizes)); /* * from tspkg.dll: 0x00000132 * ISC_REQ_MUTUAL_AUTH * ISC_REQ_CONFIDENTIALITY * ISC_REQ_USE_SESSION_KEY * ISC_REQ_ALLOCATE_MEMORY */ fContextReq = ISC_REQ_MUTUAL_AUTH | ISC_REQ_CONFIDENTIALITY | ISC_REQ_USE_SESSION_KEY; while (TRUE) { 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 = malloc(output_buffer.cbBuffer); status = credssp->table->InitializeSecurityContext(&credentials, (have_context) ? &credssp->context : NULL, credssp->ServicePrincipalName, fContextReq, 0, SECURITY_NATIVE_DREP, (have_input_buffer) ? &input_buffer_desc : NULL, 0, &credssp->context, &output_buffer_desc, &pfContextAttr, &expiration); if (have_input_buffer && (input_buffer.pvBuffer != NULL)) { free(input_buffer.pvBuffer); input_buffer.pvBuffer = NULL; } if ((status == SEC_I_COMPLETE_AND_CONTINUE) || (status == SEC_I_COMPLETE_NEEDED) || (status == SEC_E_OK)) { if (credssp->table->CompleteAuthToken != NULL) credssp->table->CompleteAuthToken(&credssp->context, &output_buffer_desc); have_pub_key_auth = TRUE; if (credssp->table->QueryContextAttributes(&credssp->context, SECPKG_ATTR_SIZES, &credssp->ContextSizes) != SEC_E_OK) { fprintf(stderr, "QueryContextAttributes SECPKG_ATTR_SIZES failure\n"); return 0; } credssp_encrypt_public_key_echo(credssp); 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_buffer.cbBuffer > 0) { credssp->negoToken.pvBuffer = output_buffer.pvBuffer; credssp->negoToken.cbBuffer = output_buffer.cbBuffer; #ifdef WITH_DEBUG_CREDSSP fprintf(stderr, "Sending Authentication Token\n"); winpr_HexDump(credssp->negoToken.pvBuffer, credssp->negoToken.cbBuffer); #endif credssp_send(credssp); credssp_buffer_free(credssp); } if (status != SEC_I_CONTINUE_NEEDED) break; /* receive server response and place in input buffer */ 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 fprintf(stderr, "Receiving Authentication Token (%d)\n", (int) credssp->negoToken.cbBuffer); winpr_HexDump(credssp->negoToken.pvBuffer, credssp->negoToken.cbBuffer); #endif input_buffer.pvBuffer = credssp->negoToken.pvBuffer; input_buffer.cbBuffer = credssp->negoToken.cbBuffer; have_input_buffer = TRUE; have_context = TRUE; } /* Encrypted Public Key +1 */ if (credssp_recv(credssp) < 0) return -1; /* Verify Server Public Key Echo */ status = credssp_decrypt_public_key_echo(credssp); credssp_buffer_free(credssp); if (status != SEC_E_OK) { fprintf(stderr, "Could not verify public key echo!\n"); return -1; } /* Send encrypted credentials */ status = credssp_encrypt_ts_credentials(credssp); if (status != SEC_E_OK) { fprintf(stderr, "credssp_encrypt_ts_credentials status: 0x%08X\n", status); return 0; } credssp_send(credssp); credssp_buffer_free(credssp); /* Free resources */ credssp->table->FreeCredentialsHandle(&credentials); credssp->table->FreeContextBuffer(pPackageInfo); return 1; }
BOOL ntlm_client_init(rdpNtlm* ntlm, BOOL http, char* user, char* domain, char* password) { SECURITY_STATUS status; sspi_GlobalInit(); #ifdef WITH_NATIVE_SSPI { HMODULE hSSPI; INIT_SECURITY_INTERFACE InitSecurityInterface; PSecurityFunctionTable pSecurityInterface = NULL; hSSPI = LoadLibrary(_T("secur32.dll")); #ifdef UNICODE InitSecurityInterface = (INIT_SECURITY_INTERFACE) GetProcAddress(hSSPI, "InitSecurityInterfaceW"); #else InitSecurityInterface = (INIT_SECURITY_INTERFACE) GetProcAddress(hSSPI, "InitSecurityInterfaceA"); #endif ntlm->table = (*InitSecurityInterface)(); } #else ntlm->table = InitSecurityInterface(); #endif sspi_SetAuthIdentity(&(ntlm->identity), user, domain, password); if (http) { DWORD status; DWORD SpnLength; SpnLength = 0; status = DsMakeSpn(_T("HTTP"), _T("LAB1-W2K8R2-GW.lab1.awake.local"), NULL, 0, NULL, &SpnLength, NULL); if (status != ERROR_BUFFER_OVERFLOW) { _tprintf(_T("DsMakeSpn: expected ERROR_BUFFER_OVERFLOW\n")); return -1; } ntlm->ServicePrincipalName = (LPTSTR) malloc(SpnLength * sizeof(TCHAR)); status = DsMakeSpn(_T("HTTP"), _T("LAB1-W2K8R2-GW.lab1.awake.local"), NULL, 0, NULL, &SpnLength, ntlm->ServicePrincipalName); } status = ntlm->table->QuerySecurityPackageInfo(NTLMSP_NAME, &ntlm->pPackageInfo); if (status != SEC_E_OK) { printf("QuerySecurityPackageInfo status: 0x%08X\n", status); return FALSE; } ntlm->cbMaxToken = ntlm->pPackageInfo->cbMaxToken; status = ntlm->table->AcquireCredentialsHandle(NULL, NTLMSP_NAME, SECPKG_CRED_OUTBOUND, NULL, &ntlm->identity, NULL, NULL, &ntlm->credentials, &ntlm->expiration); if (status != SEC_E_OK) { printf("AcquireCredentialsHandle status: 0x%08X\n", status); return FALSE; } ntlm->haveContext = FALSE; ntlm->haveInputBuffer = FALSE; ZeroMemory(&ntlm->inputBuffer, sizeof(SecBuffer)); ZeroMemory(&ntlm->outputBuffer, sizeof(SecBuffer)); ZeroMemory(&ntlm->ContextSizes, sizeof(SecPkgContext_Sizes)); ntlm->fContextReq = 0; if (http) { /* flags for HTTP authentication */ ntlm->fContextReq |= ISC_REQ_CONFIDENTIALITY; } else { /** * flags for RPC authentication: * RPC_C_AUTHN_LEVEL_PKT_INTEGRITY: * ISC_REQ_USE_DCE_STYLE | ISC_REQ_DELEGATE | ISC_REQ_MUTUAL_AUTH | * ISC_REQ_REPLAY_DETECT | ISC_REQ_SEQUENCE_DETECT */ ntlm->fContextReq |= ISC_REQ_USE_DCE_STYLE; ntlm->fContextReq |= ISC_REQ_DELEGATE | ISC_REQ_MUTUAL_AUTH; ntlm->fContextReq |= ISC_REQ_REPLAY_DETECT | ISC_REQ_SEQUENCE_DETECT; } return TRUE; }