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; }
void LSSLContext::Shutdown(LSockByteStream* SockByteStream, const TCHAR* TargetName) { //SSPI: отключение от сервера //сначала выставим нужный статус у контекста DWORD ShutdownToken = SCHANNEL_SHUTDOWN; SecBufferDesc ShutDownBufferDesc; SecBuffer ShutDownBuffers[1]; ShutDownBufferDesc.cBuffers = 1; ShutDownBufferDesc.pBuffers = ShutDownBuffers; ShutDownBufferDesc.ulVersion = SECBUFFER_VERSION; ShutDownBuffers[0].pvBuffer = &ShutdownToken; ShutDownBuffers[0].BufferType = SECBUFFER_TOKEN; ShutDownBuffers[0].cbBuffer = sizeof(ShutdownToken); //VERIFY(SEC_E_OK==ApplyControlToken(GetContextHandle(), &ShutDownBufferDesc)); //затем получим данные для отправки ShutDownBuffers[0].BufferType = SECBUFFER_TOKEN; ShutDownBuffers[0].pvBuffer = 0; ShutDownBuffers[0].cbBuffer = 0; /*VERIFY(SEC_E_OK==*/InitializeSecurityContext(&m_hUserCred, GetContextHandle(), const_cast<TCHAR*>(TargetName), m_ReqContextAttr, 0, 0, 0, 0, 0, &ShutDownBufferDesc, &m_ContextAttr, &m_ContextExpiry)/*)*/; //ASSERT(ShutDownBuffers[0].pvBuffer&&ShutDownBuffers[0].cbBuffer); //WS: отправим обработанные SCHANNEL данные SockByteStream->RawSend(ShutDownBuffers[0].pvBuffer, ShutDownBuffers[0].cbBuffer); FreeContextBuffer(ShutDownBuffers[0].pvBuffer); ShutDownBuffers[0].pvBuffer=0; ShutDownBuffers[0].cbBuffer=0; }
SECURITY_STATUS WINAPI EnumerateSecurityPackagesA( PULONG pcPackages, PSecPkgInfoA* ppPackageInfo ) { SECURITY_STATUS ret; PSecPkgInfoW info = NULL; ret = EnumerateSecurityPackagesW(pcPackages, &info); if (ret == SEC_E_OK && *pcPackages && info) { /* *ppPackageInfo = thunk_PSecPkgInfoWToA(*pcPackages, info); if (*pcPackages && !*ppPackageInfo) { *pcPackages = 0; ret = SEC_E_INSUFFICIENT_MEMORY; } */ FreeContextBuffer(info); } *ppPackageInfo = NULL; UNIMPLEMENTED; return ret; }
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; }
static apr_status_t cleanup_sec_buffer(void *data) { FreeContextBuffer(data); return APR_SUCCESS; }
BOOLEAN SrvIsKerberosAvailable( VOID ) /*++ Routine Description: Checks whether Kerberos is one of the supported security packages. Arguments: Return Value: TRUE if Kerberos is available, FALSE if otherwise or error. --*/ { NTSTATUS Status; ULONG PackageCount, Index; PSecPkgInfoW Packages; BOOLEAN FoundKerberos = FALSE; // // Get the list of packages from the security driver // Status = EnumerateSecurityPackages( &PackageCount, &Packages ); if (!NT_SUCCESS(Status)) { return(FALSE); } // // Loop through the list looking for Kerberos // for (Index = 0; Index < PackageCount ; Index++ ) { if (!_wcsicmp(Packages[Index].Name, MICROSOFT_KERBEROS_NAME_W)) { FoundKerberos = TRUE; break; } } FreeContextBuffer(Packages); return(FoundKerberos); }
int SSL_SOCKET :: ClientOff() { // Client wants to disconnect SECURITY_STATUS ss; Z<SecBuffer> OutBuffers(100); DWORD dwType = SCHANNEL_SHUTDOWN; OutBuffers[0].pvBuffer = &dwType; OutBuffers[0].BufferType = SECBUFFER_TOKEN; OutBuffers[0].cbBuffer = sizeof(dwType); sbout.cBuffers = 1; sbout.pBuffers = OutBuffers; sbout.ulVersion = SECBUFFER_VERSION; for(;;) { ss = ApplyControlToken(&hCtx, &sbout); if (FAILED(ss)) return -1; DWORD dwSSPIFlags; DWORD dwSSPIOutFlags; dwSSPIFlags = ISC_REQ_SEQUENCE_DETECT | ISC_REQ_REPLAY_DETECT | ISC_REQ_CONFIDENTIALITY | ISC_RET_EXTENDED_ERROR | ISC_REQ_ALLOCATE_MEMORY | ISC_REQ_STREAM; OutBuffers[0].pvBuffer = NULL; OutBuffers[0].BufferType = SECBUFFER_TOKEN; OutBuffers[0].cbBuffer = 0; sbout.cBuffers = 1; sbout.pBuffers = OutBuffers; sbout.ulVersion = SECBUFFER_VERSION; ss = InitializeSecurityContext(&hCred,&hCtx,NULL,dwSSPIFlags,0,SECURITY_NATIVE_DREP, NULL,0,&hCtx,&sbout,&dwSSPIOutFlags,0); if (FAILED(ss)) return -1; PBYTE pbMessage; DWORD cbMessage; pbMessage = (BYTE *)(OutBuffers[0].pvBuffer); cbMessage = OutBuffers[0].cbBuffer; if (pbMessage != NULL && cbMessage != 0) { int rval = ssend_p((char*)pbMessage, cbMessage); FreeContextBuffer(pbMessage); return rval; } break; } return 1; }
static int destroy(const struct plugin_interface *plugin) { protocol_interface *protocol = (protocol_interface*)plugin; free(protocol->auth_username); free(protocol->auth_password); free(protocol->auth_repository); free(g_sslBufferIn); free(g_sslBufferOut); FreeContextBuffer( secPackInfo ); return 0; }
static void test_kerberos(void) { SecPkgInfoA *info; TimeStamp ttl; CredHandle cred; SECURITY_STATUS status; SEC_CHAR provider[] = {'K','e','r','b','e','r','o','s',0}; static const ULONG expected_flags = SECPKG_FLAG_INTEGRITY | SECPKG_FLAG_PRIVACY | SECPKG_FLAG_TOKEN_ONLY | SECPKG_FLAG_DATAGRAM | SECPKG_FLAG_CONNECTION | SECPKG_FLAG_MULTI_REQUIRED | SECPKG_FLAG_EXTENDED_ERROR | SECPKG_FLAG_IMPERSONATION | SECPKG_FLAG_ACCEPT_WIN32_NAME | SECPKG_FLAG_NEGOTIABLE | SECPKG_FLAG_GSS_COMPATIBLE | SECPKG_FLAG_LOGON | SECPKG_FLAG_MUTUAL_AUTH | SECPKG_FLAG_DELEGATION | SECPKG_FLAG_READONLY_WITH_CHECKSUM; static const ULONG optional_mask = SECPKG_FLAG_RESTRICTED_TOKENS | SECPKG_FLAG_APPCONTAINER_CHECKS; status = QuerySecurityPackageInfoA(provider, &info); ok(status == SEC_E_OK, "Kerberos package not installed, skipping test\n"); if(status != SEC_E_OK) return; ok( (info->fCapabilities & ~optional_mask) == expected_flags, "got %08x, expected %08x\n", info->fCapabilities, expected_flags ); ok( info->wVersion == 1, "got %u\n", info->wVersion ); ok( info->wRPCID == RPC_C_AUTHN_GSS_KERBEROS, "got %u\n", info->wRPCID ); ok( info->cbMaxToken >= 12000, "got %u\n", info->cbMaxToken ); ok( !lstrcmpA( info->Name, "Kerberos" ), "got %s\n", info->Name ); ok( !lstrcmpA( info->Comment, "Microsoft Kerberos V1.0" ), "got %s\n", info->Comment ); FreeContextBuffer( info ); status = AcquireCredentialsHandleA( NULL, provider, SECPKG_CRED_OUTBOUND, NULL, NULL, NULL, NULL, &cred, &ttl ); todo_wine ok( status == SEC_E_OK, "AcquireCredentialsHandleA returned %08x\n", status ); if(status == SEC_E_OK) FreeCredentialHandle( &cred ); }
void RPC_ENTRY kull_m_rpc_drsr_RpcSecurityCallback(void *Context) { RPC_STATUS rpcStatus; SECURITY_STATUS secStatus; PCtxtHandle data = NULL; rpcStatus = I_RpcBindingInqSecurityContext(Context, (LPVOID *) &data); if(rpcStatus == RPC_S_OK) { if(kull_m_rpc_drsr_g_sKey.SessionKey) { FreeContextBuffer(kull_m_rpc_drsr_g_sKey.SessionKey); kull_m_rpc_drsr_g_sKey.SessionKeyLength = 0; kull_m_rpc_drsr_g_sKey.SessionKey = NULL; } secStatus = QueryContextAttributes(data, SECPKG_ATTR_SESSION_KEY, (LPVOID) &kull_m_rpc_drsr_g_sKey); if(secStatus != SEC_E_OK) PRINT_ERROR(L"QueryContextAttributes %08x\n", secStatus); } else PRINT_ERROR(L"I_RpcBindingInqSecurityContext %08x\n", rpcStatus); }
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); }
static int tls_client_handshake(URLContext *h) { TLSContext *c = h->priv_data; TLSShared *s = &c->tls_shared; SecBuffer outbuf; SecBufferDesc outbuf_desc; SECURITY_STATUS sspi_ret; int ret; init_sec_buffer(&outbuf, SECBUFFER_EMPTY, NULL, 0); init_sec_buffer_desc(&outbuf_desc, &outbuf, 1); c->request_flags = ISC_REQ_SEQUENCE_DETECT | ISC_REQ_REPLAY_DETECT | ISC_REQ_CONFIDENTIALITY | ISC_REQ_ALLOCATE_MEMORY | ISC_REQ_STREAM; sspi_ret = InitializeSecurityContext(&c->cred_handle, NULL, s->host, c->request_flags, 0, 0, NULL, 0, &c->ctxt_handle, &outbuf_desc, &c->context_flags, &c->ctxt_timestamp); if (sspi_ret != SEC_I_CONTINUE_NEEDED) { av_log(h, AV_LOG_ERROR, "Unable to create initial security context (0x%lx)\n", sspi_ret); ret = AVERROR_UNKNOWN; goto fail; } ret = ffurl_write(s->tcp, outbuf.pvBuffer, outbuf.cbBuffer); FreeContextBuffer(outbuf.pvBuffer); if (ret < 0 || ret != outbuf.cbBuffer) { av_log(h, AV_LOG_ERROR, "Failed to send initial handshake data\n"); ret = AVERROR(EIO); goto fail; } return tls_client_handshake_loop(h, 1); fail: DeleteSecurityContext(&c->ctxt_handle); return ret; }
static int tls_shutdown_client(URLContext *h) { TLSContext *c = h->priv_data; TLSShared *s = &c->tls_shared; int ret; if (c->connected) { SecBufferDesc BuffDesc; SecBuffer Buffer; SECURITY_STATUS sspi_ret; SecBuffer outbuf; SecBufferDesc outbuf_desc; DWORD dwshut = SCHANNEL_SHUTDOWN; init_sec_buffer(&Buffer, SECBUFFER_TOKEN, &dwshut, sizeof(dwshut)); init_sec_buffer_desc(&BuffDesc, &Buffer, 1); sspi_ret = ApplyControlToken(&c->ctxt_handle, &BuffDesc); if (sspi_ret != SEC_E_OK) av_log(h, AV_LOG_ERROR, "ApplyControlToken failed\n"); init_sec_buffer(&outbuf, SECBUFFER_EMPTY, NULL, 0); init_sec_buffer_desc(&outbuf_desc, &outbuf, 1); sspi_ret = InitializeSecurityContext(&c->cred_handle, &c->ctxt_handle, s->host, c->request_flags, 0, 0, NULL, 0, &c->ctxt_handle, &outbuf_desc, &c->context_flags, &c->ctxt_timestamp); if (sspi_ret == SEC_E_OK || sspi_ret == SEC_I_CONTEXT_EXPIRED) { ret = ffurl_write(s->tcp, outbuf.pvBuffer, outbuf.cbBuffer); FreeContextBuffer(outbuf.pvBuffer); if (ret < 0 || ret != outbuf.cbBuffer) av_log(h, AV_LOG_ERROR, "Failed to send close message\n"); } c->connected = 0; } return 0; }
void test_EnumerateSecurityPackages(void) { uint32 cPackages; SECURITY_STATUS status; SecPkgInfo* pPackageInfo; status = EnumerateSecurityPackages(&cPackages, &pPackageInfo); if (status == SEC_E_OK) { int index; printf("\nEnumerateSecurityPackages (%d):\n", cPackages); for (index = 0; index < cPackages; index++) { printf("\"%s\", \"%s\"\n", pPackageInfo[index].Name, pPackageInfo[index].Comment); } } FreeContextBuffer(pPackageInfo); }
/* Copies the data from a SecBufferDesc to dstBuf */ static sqInt sqCopyDescToken(sqSSL *ssl, SecBufferDesc sbd, char *dstBuf, sqInt dstLen) { unsigned int i; int result = 0; if(ssl->loglevel) printf("sqCopyDescToken: \n"); for(i = 0; i < sbd.cBuffers; i++) { SecBuffer *buf = sbd.pBuffers + i; if(ssl->loglevel) printf("\t type=%d, size=%d\n", buf->BufferType, buf->cbBuffer); if(buf->BufferType == SECBUFFER_TOKEN) { int count = buf->cbBuffer; if(count > dstLen) return SQSSL_BUFFER_TOO_SMALL; memcpy(dstBuf, buf->pvBuffer, count); result += count; dstBuf += count; dstLen -= count; FreeContextBuffer(buf->pvBuffer); } if(buf->BufferType == SECBUFFER_EXTRA) { /* XXXX: Preserve contents for the next round */ if(ssl->loglevel) printf("sqCopyDescToken: Unexpectedly encountered SECBUFFER_EXTRA\n"); } } return result; }
/* * '_sspiConnect()' - Make an SSL connection. This function * assumes a TCP/IP connection has already * been successfully made */ BOOL /* O - 1 on success, 0 on failure */ _sspiConnect(_sspi_struct_t *conn, /* I - Client connection */ const CHAR *hostname) /* I - Server hostname */ { PCCERT_CONTEXT serverCert; /* Server certificate */ DWORD dwSSPIFlags; /* SSL connection attributes we want */ DWORD dwSSPIOutFlags; /* SSL connection attributes we got */ TimeStamp tsExpiry; /* Time stamp */ SECURITY_STATUS scRet; /* Status */ DWORD cbData; /* Data count */ SecBufferDesc inBuffer; /* Array of SecBuffer structs */ SecBuffer inBuffers[2]; /* Security package buffer */ SecBufferDesc outBuffer; /* Array of SecBuffer structs */ SecBuffer outBuffers[1]; /* Security package buffer */ BOOL ok = TRUE; /* Return value */ serverCert = NULL; dwSSPIFlags = ISC_REQ_SEQUENCE_DETECT | ISC_REQ_REPLAY_DETECT | ISC_REQ_CONFIDENTIALITY | ISC_RET_EXTENDED_ERROR | ISC_REQ_ALLOCATE_MEMORY | ISC_REQ_STREAM; /* * Initiate a ClientHello message and generate a token. */ outBuffers[0].pvBuffer = NULL; outBuffers[0].BufferType = SECBUFFER_TOKEN; outBuffers[0].cbBuffer = 0; outBuffer.cBuffers = 1; outBuffer.pBuffers = outBuffers; outBuffer.ulVersion = SECBUFFER_VERSION; scRet = InitializeSecurityContext(&conn->creds, NULL, TEXT(""), dwSSPIFlags, 0, SECURITY_NATIVE_DREP, NULL, 0, &conn->context, &outBuffer, &dwSSPIOutFlags, &tsExpiry); if (scRet != SEC_I_CONTINUE_NEEDED) { DEBUG_printf(("_sspiConnect: InitializeSecurityContext(1) failed: %x", scRet)); ok = FALSE; goto cleanup; } /* * Send response to server if there is one. */ if (outBuffers[0].cbBuffer && outBuffers[0].pvBuffer) { cbData = send(conn->sock, outBuffers[0].pvBuffer, outBuffers[0].cbBuffer, 0); if ((cbData == SOCKET_ERROR) || !cbData) { DEBUG_printf(("_sspiConnect: send failed: %d", WSAGetLastError())); FreeContextBuffer(outBuffers[0].pvBuffer); DeleteSecurityContext(&conn->context); ok = FALSE; goto cleanup; } DEBUG_printf(("_sspiConnect: %d bytes of handshake data sent", cbData)); /* * Free output buffer. */ FreeContextBuffer(outBuffers[0].pvBuffer); outBuffers[0].pvBuffer = NULL; } dwSSPIFlags = ISC_REQ_MANUAL_CRED_VALIDATION | ISC_REQ_SEQUENCE_DETECT | ISC_REQ_REPLAY_DETECT | ISC_REQ_CONFIDENTIALITY | ISC_RET_EXTENDED_ERROR | ISC_REQ_ALLOCATE_MEMORY | ISC_REQ_STREAM; conn->decryptBufferUsed = 0; /* * Loop until the handshake is finished or an error occurs. */ scRet = SEC_I_CONTINUE_NEEDED; while(scRet == SEC_I_CONTINUE_NEEDED || scRet == SEC_E_INCOMPLETE_MESSAGE || scRet == SEC_I_INCOMPLETE_CREDENTIALS) { if ((conn->decryptBufferUsed == 0) || (scRet == SEC_E_INCOMPLETE_MESSAGE)) { if (conn->decryptBufferLength <= conn->decryptBufferUsed) { conn->decryptBufferLength += 4096; conn->decryptBuffer = (BYTE*) realloc(conn->decryptBuffer, conn->decryptBufferLength); if (!conn->decryptBuffer) { DEBUG_printf(("_sspiConnect: unable to allocate %d byte decrypt buffer", conn->decryptBufferLength)); SetLastError(E_OUTOFMEMORY); ok = FALSE; goto cleanup; } } cbData = recv(conn->sock, conn->decryptBuffer + conn->decryptBufferUsed, (int) (conn->decryptBufferLength - conn->decryptBufferUsed), 0); if (cbData == SOCKET_ERROR) { DEBUG_printf(("_sspiConnect: recv failed: %d", WSAGetLastError())); ok = FALSE; goto cleanup; } else if (cbData == 0) { DEBUG_printf(("_sspiConnect: server unexpectedly disconnected")); ok = FALSE; goto cleanup; } DEBUG_printf(("_sspiConnect: %d bytes of handshake data received", cbData)); conn->decryptBufferUsed += cbData; } /* * Set up the input buffers. Buffer 0 is used to pass in data * received from the server. Schannel will consume some or all * of this. Leftover data (if any) will be placed in buffer 1 and * given a buffer type of SECBUFFER_EXTRA. */ inBuffers[0].pvBuffer = conn->decryptBuffer; inBuffers[0].cbBuffer = (unsigned long) conn->decryptBufferUsed; inBuffers[0].BufferType = SECBUFFER_TOKEN; inBuffers[1].pvBuffer = NULL; inBuffers[1].cbBuffer = 0; inBuffers[1].BufferType = SECBUFFER_EMPTY; inBuffer.cBuffers = 2; inBuffer.pBuffers = inBuffers; inBuffer.ulVersion = SECBUFFER_VERSION; /* * Set up the output buffers. These are initialized to NULL * so as to make it less likely we'll attempt to free random * garbage later. */ outBuffers[0].pvBuffer = NULL; outBuffers[0].BufferType= SECBUFFER_TOKEN; outBuffers[0].cbBuffer = 0; outBuffer.cBuffers = 1; outBuffer.pBuffers = outBuffers; outBuffer.ulVersion = SECBUFFER_VERSION; /* * Call InitializeSecurityContext. */ scRet = InitializeSecurityContext(&conn->creds, &conn->context, NULL, dwSSPIFlags, 0, SECURITY_NATIVE_DREP, &inBuffer, 0, NULL, &outBuffer, &dwSSPIOutFlags, &tsExpiry); /* * If InitializeSecurityContext was successful (or if the error was * one of the special extended ones), send the contends of the output * buffer to the server. */ if (scRet == SEC_E_OK || scRet == SEC_I_CONTINUE_NEEDED || FAILED(scRet) && (dwSSPIOutFlags & ISC_RET_EXTENDED_ERROR)) { if (outBuffers[0].cbBuffer && outBuffers[0].pvBuffer) { cbData = send(conn->sock, outBuffers[0].pvBuffer, outBuffers[0].cbBuffer, 0); if ((cbData == SOCKET_ERROR) || !cbData) { DEBUG_printf(("_sspiConnect: send failed: %d", WSAGetLastError())); FreeContextBuffer(outBuffers[0].pvBuffer); DeleteSecurityContext(&conn->context); ok = FALSE; goto cleanup; } DEBUG_printf(("_sspiConnect: %d bytes of handshake data sent", cbData)); /* * Free output buffer. */ FreeContextBuffer(outBuffers[0].pvBuffer); outBuffers[0].pvBuffer = NULL; } } /* * If InitializeSecurityContext returned SEC_E_INCOMPLETE_MESSAGE, * then we need to read more data from the server and try again. */ if (scRet == SEC_E_INCOMPLETE_MESSAGE) continue; /* * If InitializeSecurityContext returned SEC_E_OK, then the * handshake completed successfully. */ if (scRet == SEC_E_OK) { /* * If the "extra" buffer contains data, this is encrypted application * protocol layer stuff. It needs to be saved. The application layer * will later decrypt it with DecryptMessage. */ DEBUG_printf(("_sspiConnect: Handshake was successful")); if (inBuffers[1].BufferType == SECBUFFER_EXTRA) { if (conn->decryptBufferLength < inBuffers[1].cbBuffer) { conn->decryptBuffer = realloc(conn->decryptBuffer, inBuffers[1].cbBuffer); if (!conn->decryptBuffer) { DEBUG_printf(("_sspiConnect: unable to allocate %d bytes for decrypt buffer", inBuffers[1].cbBuffer)); SetLastError(E_OUTOFMEMORY); ok = FALSE; goto cleanup; } } memmove(conn->decryptBuffer, conn->decryptBuffer + (conn->decryptBufferUsed - inBuffers[1].cbBuffer), inBuffers[1].cbBuffer); conn->decryptBufferUsed = inBuffers[1].cbBuffer; DEBUG_printf(("_sspiConnect: %d bytes of app data was bundled with handshake data", conn->decryptBufferUsed)); } else conn->decryptBufferUsed = 0; /* * Bail out to quit */ break; } /* * Check for fatal error. */ if (FAILED(scRet)) { DEBUG_printf(("_sspiConnect: InitializeSecurityContext(2) failed: %x", scRet)); ok = FALSE; break; } /* * If InitializeSecurityContext returned SEC_I_INCOMPLETE_CREDENTIALS, * then the server just requested client authentication. */ if (scRet == SEC_I_INCOMPLETE_CREDENTIALS) { /* * Unimplemented */ DEBUG_printf(("_sspiConnect: server requested client credentials")); ok = FALSE; break; } /* * Copy any leftover data from the "extra" buffer, and go around * again. */ if (inBuffers[1].BufferType == SECBUFFER_EXTRA) { memmove(conn->decryptBuffer, conn->decryptBuffer + (conn->decryptBufferUsed - inBuffers[1].cbBuffer), inBuffers[1].cbBuffer); conn->decryptBufferUsed = inBuffers[1].cbBuffer; } else { conn->decryptBufferUsed = 0; } } if (ok) { conn->contextInitialized = TRUE; /* * Get the server cert */ scRet = QueryContextAttributes(&conn->context, SECPKG_ATTR_REMOTE_CERT_CONTEXT, (VOID*) &serverCert ); if (scRet != SEC_E_OK) { DEBUG_printf(("_sspiConnect: QueryContextAttributes failed(SECPKG_ATTR_REMOTE_CERT_CONTEXT): %x", scRet)); ok = FALSE; goto cleanup; } scRet = sspi_verify_certificate(serverCert, hostname, conn->certFlags); if (scRet != SEC_E_OK) { DEBUG_printf(("_sspiConnect: sspi_verify_certificate failed: %x", scRet)); ok = FALSE; goto cleanup; } /* * Find out how big the header/trailer will be: */ scRet = QueryContextAttributes(&conn->context, SECPKG_ATTR_STREAM_SIZES, &conn->streamSizes); if (scRet != SEC_E_OK) { DEBUG_printf(("_sspiConnect: QueryContextAttributes failed(SECPKG_ATTR_STREAM_SIZES): %x", scRet)); ok = FALSE; } } cleanup: if (serverCert) CertFreeCertificateContext(serverCert); return (ok); }
static DWORD ServerEstablishContext( IN INT nSocket, IN CredHandle *pServerCreds, OUT CtxtHandle *pContext, IN ULONG AscFlags ) { DWORD dwError = ERROR_SUCCESS; DWORD dwLoopError = ERROR_SUCCESS; ULONG nRetFlags = 0; SecBufferDesc InputDesc; SecBufferDesc OutputDesc; SecBuffer SendTokenBuffer; SecBuffer RecvTokenBuffer; TimeStamp Expiry; PCtxtHandle pContextHandle = NULL; INT nContextAcquired = 0; memset(&InputDesc, 0, sizeof(SecBufferDesc)); memset(&OutputDesc, 0, sizeof(SecBufferDesc)); memset(&SendTokenBuffer, 0, sizeof(SecBuffer)); memset(&RecvTokenBuffer, 0, sizeof(SecBuffer)); memset(&Expiry, 0, sizeof(TimeStamp)); memset(pContext, 0, sizeof(CtxtHandle)); InputDesc.cBuffers = 1; InputDesc.ulVersion = SECBUFFER_VERSION; InputDesc.pBuffers = &RecvTokenBuffer; OutputDesc.cBuffers = 1; OutputDesc.ulVersion = SECBUFFER_VERSION; OutputDesc.pBuffers = &SendTokenBuffer; printf("ASC flags requested (0x%08x):\n", AscFlags); DumpAscReqFlags(AscFlags); do { dwError = RecvToken(nSocket, &RecvTokenBuffer); BAIL_ON_ERROR(dwError); printf("RECEIVED:\n"); DumpBuffer(RecvTokenBuffer.pvBuffer, RecvTokenBuffer.cbBuffer); DumpNtlmMessage(RecvTokenBuffer.pvBuffer, RecvTokenBuffer.cbBuffer); printf("\n"); RecvTokenBuffer.BufferType = SECBUFFER_TOKEN; SendTokenBuffer.cbBuffer = 0; SendTokenBuffer.pvBuffer = NULL; SendTokenBuffer.BufferType = SECBUFFER_TOKEN; // we need to use dwLoopErr in this case because we may get // back a "continue" command. In those cases, we still // need dwError to be used and set seperatly based on other // calls. dwLoopError = AcceptSecurityContext( pServerCreds, pContextHandle, &InputDesc, AscFlags, SECURITY_NATIVE_DREP, pContext, &OutputDesc, &nRetFlags, &Expiry ); if (SEC_E_OK != dwLoopError && SEC_I_CONTINUE_NEEDED != dwLoopError) { dwError = dwLoopError; BAIL_ON_ERROR(dwError); } if (SEC_I_CONTINUE_NEEDED == dwLoopError) { printf("Context partially accepted...\n"); DumpBuffer(SendTokenBuffer.pvBuffer, SendTokenBuffer.cbBuffer); DumpNtlmMessage(SendTokenBuffer.pvBuffer, SendTokenBuffer.cbBuffer); if (nRetFlags) { printf("ASC flags returned (0x%08x):\n", nRetFlags); DumpAscRetFlags(nRetFlags); } printf("\n"); } else { printf("Context FULLY accepted!\n"); printf("ASC flags returned (0x%08x):\n", nRetFlags); DumpAscRetFlags(nRetFlags); printf("\n"); } nContextAcquired = 1; pContextHandle = pContext; free(RecvTokenBuffer.pvBuffer); RecvTokenBuffer.pvBuffer = NULL; if (SendTokenBuffer.cbBuffer != 0) { dwError = SendToken(nSocket, &SendTokenBuffer); BAIL_ON_ERROR(dwError); FreeContextBuffer(SendTokenBuffer.pvBuffer); SendTokenBuffer.pvBuffer = NULL; } } while (dwLoopError == SEC_I_CONTINUE_NEEDED); finish: return dwError; error: if (RecvTokenBuffer.pvBuffer) { free(RecvTokenBuffer.pvBuffer); RecvTokenBuffer.pvBuffer = NULL; } if (SendTokenBuffer.cbBuffer) { FreeContextBuffer(SendTokenBuffer.pvBuffer); SendTokenBuffer.pvBuffer = NULL; SendTokenBuffer.cbBuffer = 0; } if (nContextAcquired) { DeleteSecurityContext(pContext); } goto finish; }
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; }
int sserver_auth_protocol_connect(const struct protocol_interface *protocol, const char *auth_string) { CScramble scramble; char *tmp; int certonly; char *client_version = NULL; char keyfile[256]; const char *hostname = NULL; if (!strcmp (auth_string, "BEGIN SSL VERIFICATION REQUEST")) sserver_protocol_interface.verify_only = 1; else if (!strcmp (auth_string, "BEGIN SSL AUTH REQUEST")) sserver_protocol_interface.verify_only = 0; else return CVSPROTO_NOTME; write(current_server()->out_fd,SSERVER_INIT_STRING,sizeof(SSERVER_INIT_STRING)-1); if(!CGlobalSettings::GetGlobalValue("cvsnt","PServer","CertificatesOnly",keyfile,sizeof(keyfile))) certonly = atoi(keyfile); if(!CGlobalSettings::GetGlobalValue("cvsnt","PServer","ServerDnsName",keyfile,sizeof(keyfile))) hostname = keyfile; if(!ServerAuthenticate(hostname)) return CVSPROTO_AUTHFAIL; QueryContextAttributes(&contextHandle,SECPKG_ATTR_STREAM_SIZES,&secSizes); g_sslBufferInPos=g_sslBufferOutPos=0; g_sslBufferInLen=g_sslBufferOutLen=0; set_encrypted_channel(1); /* Error must go through us now */ PCERT_CONTEXT sc; PCCERT_CHAIN_CONTEXT pcc; CERT_SIMPLE_CHAIN *psc; CERT_CHAIN_PARA para = { sizeof(CERT_CHAIN_PARA) }; DWORD trust,rc; BOOL cert = FALSE; rc = QueryContextAttributes(&contextHandle,SECPKG_ATTR_REMOTE_CERT_CONTEXT,&sc); if(rc && rc!=SEC_E_NO_CREDENTIALS) server_error(1,"Couldn't get client certificate"); if(rc!=SEC_E_NO_CREDENTIALS) /* The client doesn't have to send us a cert. as cvs uses passwords normally */ { if(!CertGetCertificateChain(NULL, sc, NULL, NULL, ¶, 0, NULL, &pcc)) server_error(1,"Couldn't get client certificate chain"); psc = pcc->rgpChain[0]; trust = psc->TrustStatus.dwErrorStatus; if (trust) { if (trust & (CERT_TRUST_IS_PARTIAL_CHAIN | CERT_TRUST_IS_UNTRUSTED_ROOT)) server_error(1,"Client sent self signed certificate"); else if (trust & (CERT_TRUST_IS_NOT_TIME_VALID)) server_error(1,"Client certificate expired"); else server_error(1,"Client certificate verification failed - %08x",trust); } CertFreeCertificateChain(pcc); FreeContextBuffer(sc); cert = TRUE; } /* Get the three important pieces of information in order. */ /* See above comment about error handling. */ /* get version, if sent. 1.0 clients didn't have this handshake so we have to handle that. */ server_getline (protocol, &client_version, MAX_PATH); if(strncmp(client_version,"SSERVER-CLIENT ",15)) { sserver_protocol_interface.auth_repository = client_version; client_version = NULL; } else server_getline (protocol, &sserver_protocol_interface.auth_repository, MAX_PATH); server_getline (protocol, &sserver_protocol_interface.auth_username, MAX_PATH); server_getline (protocol, &sserver_protocol_interface.auth_password, MAX_PATH); if(client_version) free(client_version); client_version = NULL; /* ... and make sure the protocol ends on the right foot. */ /* See above comment about error handling. */ server_getline(protocol, &tmp, MAX_PATH); if (strcmp (tmp, sserver_protocol_interface.verify_only ? "END SSL VERIFICATION REQUEST" : "END SSL AUTH REQUEST") != 0) { server_printf ("bad auth protocol end: %s\n", tmp); free(tmp); return CVSPROTO_FAIL; } strcpy(sserver_protocol_interface.auth_password, scramble.Unscramble(sserver_protocol_interface.auth_password)); free(tmp); switch(certonly) { case 0: break; case 1: if(!cert) { server_error(0,"E Login requires a valid client certificate.\n"); return CVSPROTO_AUTHFAIL; } free(sserver_protocol_interface.auth_password); sserver_protocol_interface.auth_password = NULL; break; case 2: if(!cert) { server_error(0,"E Login requires a valid client certificate.\n"); return CVSPROTO_AUTHFAIL; } break; }; return CVSPROTO_SUCCESS; }
int sserver_connect(const struct protocol_interface *protocol, int verify_only) { char crypt_password[64]; char server_version[128]; char tmp_keyname[256]; const char *begin_request = "BEGIN SSL AUTH REQUEST"; const char *end_request = "END SSL AUTH REQUEST"; const char *username = NULL; const char *cert = current_server()->current_root->optional_3; int l; int sserver_version = 0; int strict = 0; CScramble scramble; bool send_client_version = false; if(current_server()->current_root->optional_1) { sserver_version = atoi(current_server()->current_root->optional_1); if(sserver_version != 0 && sserver_version != 1) { server_error(0,"version must be one of:"); server_error(0,"0 - All CVSNT-type servers"); server_error(0,"1 - Unix server using Corey Minards' sserver patches"); server_error(1,"Please specify a valid value"); } } if(!CGlobalSettings::GetUserValue("cvsnt","sserver","StrictChecking",server_version,sizeof(server_version))) { strict = atoi(server_version); } if(!cert && !CGlobalSettings::GetUserValue("cvsnt","sserver","ClientCert",tmp_keyname,sizeof(tmp_keyname))) { cert = tmp_keyname; } if(current_server()->current_root->optional_2) strict = atoi(current_server()->current_root->optional_2); if(sserver_version == 1) /* Old sserver */ { begin_request = verify_only?"BEGIN SSL VERIFICATION REQUEST":"BEGIN SSL REQUEST"; end_request = verify_only?"END SSL VERIFICATION REQUEST":"END SSL REQUEST"; } else if(verify_only) { begin_request = "BEGIN SSL VERIFICATION REQUEST"; end_request = "END SSL VERIFICATION REQUEST"; } username = get_username(current_server()->current_root); if(!username || !current_server()->current_root->hostname || !current_server()->current_root->directory) return CVSPROTO_BADPARMS; if(tcp_connect(current_server()->current_root)) return CVSPROTO_FAIL; if(current_server()->current_root->password) strncpy(crypt_password,scramble.Scramble(current_server()->current_root->password),sizeof(crypt_password)); else { if(sserver_get_user_password(username,current_server()->current_root->hostname,current_server()->current_root->port,current_server()->current_root->directory,crypt_password,sizeof(crypt_password))) { /* Using null password - trace something out here */ server_error(0,"Using an empty password; you may need to do 'cvs login' with a real password\n"); strncpy(crypt_password,scramble.Scramble(""),sizeof(crypt_password)); } } if(sserver_version == 0) /* Pre-CVSNT had no version check */ { if(tcp_printf("%s\n",begin_request)<0) return CVSPROTO_FAIL; for(;;) { *server_version='\0'; if((l=tcp_readline(server_version,sizeof(server_version))<0)) return CVSPROTO_FAIL; if(*server_version) break; #ifdef _WIN32 Sleep(10); #else usleep(10); #endif } if(strncmp(server_version,"SSERVER ",8)) { server_error(0,"%s\n",server_version); return CVSPROTO_FAIL; } if(strncmp(server_version+8,"1.0 ",4)) send_client_version = true; } if(!ClientAuthenticate(cert,current_server()->current_root->hostname)) return CVSPROTO_AUTHFAIL; QueryContextAttributes(&contextHandle,SECPKG_ATTR_STREAM_SIZES,&secSizes); PCERT_CONTEXT sc; PCCERT_CHAIN_CONTEXT pcc; CERT_SIMPLE_CHAIN *psc; CERT_CHAIN_PARA para = { sizeof(CERT_CHAIN_PARA) }; DWORD trust,rc; rc = QueryContextAttributes(&contextHandle,SECPKG_ATTR_REMOTE_CERT_CONTEXT,&sc); if(rc) server_error(1,"Couldn't get server certificate"); if(!CertGetCertificateChain(NULL, sc, NULL, NULL, ¶, 0, NULL, &pcc)) server_error(1,"Couldn't get server certificate chain"); psc = pcc->rgpChain[0]; trust = psc->TrustStatus.dwErrorStatus; if (trust) { if (trust & (CERT_TRUST_IS_PARTIAL_CHAIN | CERT_TRUST_IS_UNTRUSTED_ROOT)) ; // Seld signed else if (trust & (CERT_TRUST_IS_NOT_TIME_VALID)) server_error(1,"Server certificate expired"); else server_error(1,"Server certificate verification failed - %08x",trust); } if(strict) { char certname[256]; CertGetNameString(sc, CERT_NAME_DNS_TYPE, 0, NULL, certname, sizeof(certname)); if(strcasecmp(certname,current_server()->current_root->hostname)) server_error(1, "Certificate CommonName '%s' does not match server name '%s'\n",certname,current_server()->current_root->hostname); } CertFreeCertificateChain(pcc); FreeContextBuffer(sc); g_sslBufferInPos=g_sslBufferOutPos=0; g_sslBufferInLen=g_sslBufferOutLen=0; if(sserver_version == 1) { if(sserver_printf("%s\n",begin_request)<0) return CVSPROTO_FAIL; } // For server versions 1.1+ send CLIENT_VERSION_STRING if(send_client_version && sserver_printf(SSERVER_CLIENT_VERSION_STRING)<0) return CVSPROTO_FAIL; if(sserver_printf("%s\n%s\n",current_server()->current_root->directory,username)<0) return CVSPROTO_FAIL; if(sserver_printf("%s\n",crypt_password)<0) return CVSPROTO_FAIL; if(sserver_printf("%s\n",end_request)<0) return CVSPROTO_FAIL; return CVSPROTO_SUCCESS; }
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 _mongoc_sspi_auth_sspi_client_step (mongoc_sspi_client_state_t *state, SEC_CHAR *challenge) { SecBufferDesc inbuf; SecBuffer inBufs[1]; SecBufferDesc outbuf; SecBuffer outBufs[1]; ULONG ignored; SECURITY_STATUS status = MONGOC_SSPI_AUTH_GSS_CONTINUE; DWORD len; if (state->response != NULL) { free (state->response); state->response = NULL; } inbuf.ulVersion = SECBUFFER_VERSION; inbuf.cBuffers = 1; inbuf.pBuffers = inBufs; inBufs[0].pvBuffer = NULL; inBufs[0].cbBuffer = 0; inBufs[0].BufferType = SECBUFFER_TOKEN; if (state->haveCtx) { inBufs[0].pvBuffer = _mongoc_sspi_base64_decode (challenge, &len); if (!inBufs[0].pvBuffer) { return MONGOC_SSPI_AUTH_GSS_ERROR; } inBufs[0].cbBuffer = len; } outbuf.ulVersion = SECBUFFER_VERSION; outbuf.cBuffers = 1; outbuf.pBuffers = outBufs; outBufs[0].pvBuffer = NULL; outBufs[0].cbBuffer = 0; outBufs[0].BufferType = SECBUFFER_TOKEN; status = InitializeSecurityContextW (/* CredHandle */ &state->cred, /* CtxtHandle (NULL on first call) */ state->haveCtx ? &state->ctx : NULL, /* Service Principal Name */ state->spn, /* Flags */ ISC_REQ_ALLOCATE_MEMORY | state->flags, /* Always 0 */ 0, /* Target data representation */ SECURITY_NETWORK_DREP, /* Challenge (NULL on first call) */ state->haveCtx ? &inbuf : NULL, /* Always 0 */ 0, /* CtxtHandle (Set on first call) */ &state->ctx, /* Output */ &outbuf, /* Context attributes */ &ignored, /* Expiry (We don't use this) */ NULL); if (status != SEC_E_OK && status != SEC_I_CONTINUE_NEEDED) { _mongoc_sspi_set_gsserror (status, "InitializeSecurityContext"); status = MONGOC_SSPI_AUTH_GSS_ERROR; goto done; } state->haveCtx = 1; if (outBufs[0].cbBuffer) { state->response = _mongoc_sspi_base64_encode (outBufs[0].pvBuffer, outBufs[0].cbBuffer); if (!state->response) { status = MONGOC_SSPI_AUTH_GSS_ERROR; goto done; } } if (status == SEC_E_OK) { /* Get authenticated username. */ SecPkgContext_NamesW names; status = QueryContextAttributesW (&state->ctx, SECPKG_ATTR_NAMES, &names); if (status != SEC_E_OK) { _mongoc_sspi_set_gsserror (status, "QueryContextAttributesW"); status = MONGOC_SSPI_AUTH_GSS_ERROR; goto done; } state->username = _mongoc_sspi_wide_to_utf8 (names.sUserName); if (state->username == NULL) { FreeContextBuffer (names.sUserName); status = MONGOC_SSPI_AUTH_GSS_ERROR; goto done; } FreeContextBuffer (names.sUserName); status = MONGOC_SSPI_AUTH_GSS_COMPLETE; } else { status = MONGOC_SSPI_AUTH_GSS_CONTINUE; } done: if (inBufs[0].pvBuffer) { free (inBufs[0].pvBuffer); } if (outBufs[0].pvBuffer) { FreeContextBuffer (outBufs[0].pvBuffer); } return status; }
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); }
/* * '_sspiAccept()' - Accept an SSL/TLS connection */ BOOL /* O - 1 on success, 0 on failure */ _sspiAccept(_sspi_struct_t *conn) /* I - Client connection */ { DWORD dwSSPIFlags; /* SSL connection attributes we want */ DWORD dwSSPIOutFlags; /* SSL connection attributes we got */ TimeStamp tsExpiry; /* Time stamp */ SECURITY_STATUS scRet; /* SSPI Status */ SecBufferDesc inBuffer; /* Array of SecBuffer structs */ SecBuffer inBuffers[2]; /* Security package buffer */ SecBufferDesc outBuffer; /* Array of SecBuffer structs */ SecBuffer outBuffers[1]; /* Security package buffer */ DWORD num = 0; /* 32 bit status value */ BOOL fInitContext = TRUE; /* Has the context been init'd? */ BOOL ok = TRUE; /* Return value */ if (!conn) return (FALSE); dwSSPIFlags = ASC_REQ_SEQUENCE_DETECT | ASC_REQ_REPLAY_DETECT | ASC_REQ_CONFIDENTIALITY | ASC_REQ_EXTENDED_ERROR | ASC_REQ_ALLOCATE_MEMORY | ASC_REQ_STREAM; conn->decryptBufferUsed = 0; /* * Set OutBuffer for AcceptSecurityContext call */ outBuffer.cBuffers = 1; outBuffer.pBuffers = outBuffers; outBuffer.ulVersion = SECBUFFER_VERSION; scRet = SEC_I_CONTINUE_NEEDED; while (scRet == SEC_I_CONTINUE_NEEDED || scRet == SEC_E_INCOMPLETE_MESSAGE || scRet == SEC_I_INCOMPLETE_CREDENTIALS) { if ((conn->decryptBufferUsed == 0) || (scRet == SEC_E_INCOMPLETE_MESSAGE)) { if (conn->decryptBufferLength <= conn->decryptBufferUsed) { conn->decryptBufferLength += 4096; conn->decryptBuffer = (BYTE*) realloc(conn->decryptBuffer, conn->decryptBufferLength); if (!conn->decryptBuffer) { DEBUG_printf(("_sspiAccept: unable to allocate %d byte decrypt buffer", conn->decryptBufferLength)); ok = FALSE; goto cleanup; } } for (;;) { num = recv(conn->sock, conn->decryptBuffer + conn->decryptBufferUsed, (int)(conn->decryptBufferLength - conn->decryptBufferUsed), 0); if ((num == SOCKET_ERROR) && (WSAGetLastError() == WSAEWOULDBLOCK)) Sleep(1); else break; } if (num == SOCKET_ERROR) { DEBUG_printf(("_sspiAccept: recv failed: %d", WSAGetLastError())); ok = FALSE; goto cleanup; } else if (num == 0) { DEBUG_printf(("_sspiAccept: client disconnected")); ok = FALSE; goto cleanup; } DEBUG_printf(("_sspiAccept: received %d (handshake) bytes from client", num)); conn->decryptBufferUsed += num; } /* * InBuffers[1] is for getting extra data that * SSPI/SCHANNEL doesn't proccess on this * run around the loop. */ inBuffers[0].pvBuffer = conn->decryptBuffer; inBuffers[0].cbBuffer = (unsigned long) conn->decryptBufferUsed; inBuffers[0].BufferType = SECBUFFER_TOKEN; inBuffers[1].pvBuffer = NULL; inBuffers[1].cbBuffer = 0; inBuffers[1].BufferType = SECBUFFER_EMPTY; inBuffer.cBuffers = 2; inBuffer.pBuffers = inBuffers; inBuffer.ulVersion = SECBUFFER_VERSION; /* * Initialize these so if we fail, pvBuffer contains NULL, * so we don't try to free random garbage at the quit */ outBuffers[0].pvBuffer = NULL; outBuffers[0].BufferType = SECBUFFER_TOKEN; outBuffers[0].cbBuffer = 0; scRet = AcceptSecurityContext(&conn->creds, (fInitContext?NULL:&conn->context), &inBuffer, dwSSPIFlags, SECURITY_NATIVE_DREP, (fInitContext?&conn->context:NULL), &outBuffer, &dwSSPIOutFlags, &tsExpiry); fInitContext = FALSE; if (scRet == SEC_E_OK || scRet == SEC_I_CONTINUE_NEEDED || (FAILED(scRet) && ((dwSSPIOutFlags & ISC_RET_EXTENDED_ERROR) != 0))) { if (outBuffers[0].cbBuffer && outBuffers[0].pvBuffer) { /* * Send response to server if there is one */ num = send(conn->sock, outBuffers[0].pvBuffer, outBuffers[0].cbBuffer, 0); if ((num == SOCKET_ERROR) || (num == 0)) { DEBUG_printf(("_sspiAccept: handshake send failed: %d", WSAGetLastError())); ok = FALSE; goto cleanup; } DEBUG_printf(("_sspiAccept: send %d handshake bytes to client", outBuffers[0].cbBuffer)); FreeContextBuffer(outBuffers[0].pvBuffer); outBuffers[0].pvBuffer = NULL; } } if (scRet == SEC_E_OK) { /* * If there's extra data then save it for * next time we go to decrypt */ if (inBuffers[1].BufferType == SECBUFFER_EXTRA) { memcpy(conn->decryptBuffer, (LPBYTE) (conn->decryptBuffer + (conn->decryptBufferUsed - inBuffers[1].cbBuffer)), inBuffers[1].cbBuffer); conn->decryptBufferUsed = inBuffers[1].cbBuffer; } else { conn->decryptBufferUsed = 0; } ok = TRUE; break; } else if (FAILED(scRet) && (scRet != SEC_E_INCOMPLETE_MESSAGE)) { DEBUG_printf(("_sspiAccept: AcceptSecurityContext failed: %x", scRet)); ok = FALSE; break; } if (scRet != SEC_E_INCOMPLETE_MESSAGE && scRet != SEC_I_INCOMPLETE_CREDENTIALS) { if (inBuffers[1].BufferType == SECBUFFER_EXTRA) { memcpy(conn->decryptBuffer, (LPBYTE) (conn->decryptBuffer + (conn->decryptBufferUsed - inBuffers[1].cbBuffer)), inBuffers[1].cbBuffer); conn->decryptBufferUsed = inBuffers[1].cbBuffer; } else { conn->decryptBufferUsed = 0; } } } if (ok) { conn->contextInitialized = TRUE; /* * Find out how big the header will be: */ scRet = QueryContextAttributes(&conn->context, SECPKG_ATTR_STREAM_SIZES, &conn->streamSizes); if (scRet != SEC_E_OK) { DEBUG_printf(("_sspiAccept: QueryContextAttributes failed: %x", scRet)); ok = FALSE; } } cleanup: return (ok); }
/* * '_sspiFree()' - Close a connection and free resources */ void _sspiFree(_sspi_struct_t *conn) /* I - Client connection */ { if (!conn) return; if (conn->contextInitialized) { SecBufferDesc message; /* Array of SecBuffer struct */ SecBuffer buffers[1] = { 0 }; /* Security package buffer */ DWORD dwType; /* Type */ DWORD status; /* Status */ /* * Notify schannel that we are about to close the connection. */ dwType = SCHANNEL_SHUTDOWN; buffers[0].pvBuffer = &dwType; buffers[0].BufferType = SECBUFFER_TOKEN; buffers[0].cbBuffer = sizeof(dwType); message.cBuffers = 1; message.pBuffers = buffers; message.ulVersion = SECBUFFER_VERSION; status = ApplyControlToken(&conn->context, &message); if (SUCCEEDED(status)) { PBYTE pbMessage; /* Message buffer */ DWORD cbMessage; /* Message buffer count */ DWORD cbData; /* Data count */ DWORD dwSSPIFlags; /* SSL attributes we requested */ DWORD dwSSPIOutFlags; /* SSL attributes we received */ TimeStamp tsExpiry; /* Time stamp */ dwSSPIFlags = ASC_REQ_SEQUENCE_DETECT | ASC_REQ_REPLAY_DETECT | ASC_REQ_CONFIDENTIALITY | ASC_REQ_EXTENDED_ERROR | ASC_REQ_ALLOCATE_MEMORY | ASC_REQ_STREAM; buffers[0].pvBuffer = NULL; buffers[0].BufferType = SECBUFFER_TOKEN; buffers[0].cbBuffer = 0; message.cBuffers = 1; message.pBuffers = buffers; message.ulVersion = SECBUFFER_VERSION; status = AcceptSecurityContext(&conn->creds, &conn->context, NULL, dwSSPIFlags, SECURITY_NATIVE_DREP, NULL, &message, &dwSSPIOutFlags, &tsExpiry); if (SUCCEEDED(status)) { pbMessage = buffers[0].pvBuffer; cbMessage = buffers[0].cbBuffer; /* * Send the close notify message to the client. */ if (pbMessage && cbMessage) { cbData = send(conn->sock, pbMessage, cbMessage, 0); if ((cbData == SOCKET_ERROR) || (cbData == 0)) { status = WSAGetLastError(); DEBUG_printf(("_sspiFree: sending close notify failed: %d", status)); } else { FreeContextBuffer(pbMessage); } } } else { DEBUG_printf(("_sspiFree: AcceptSecurityContext failed: %x", status)); } } else { DEBUG_printf(("_sspiFree: ApplyControlToken failed: %x", status)); } DeleteSecurityContext(&conn->context); conn->contextInitialized = FALSE; } if (conn->decryptBuffer) { free(conn->decryptBuffer); conn->decryptBuffer = NULL; } if (conn->readBuffer) { free(conn->readBuffer); conn->readBuffer = NULL; } if (conn->sock != INVALID_SOCKET) { closesocket(conn->sock); conn->sock = INVALID_SOCKET; } free(conn); }
/* * Continue SSPI authentication with next token as needed. */ static int pg_SSPI_continue(PGconn *conn) { SECURITY_STATUS r; CtxtHandle newContext; ULONG contextAttr; SecBufferDesc inbuf; SecBufferDesc outbuf; SecBuffer OutBuffers[1]; SecBuffer InBuffers[1]; if (conn->sspictx != NULL) { /* * On runs other than the first we have some data to send. Put this * data in a SecBuffer type structure. */ inbuf.ulVersion = SECBUFFER_VERSION; inbuf.cBuffers = 1; inbuf.pBuffers = InBuffers; InBuffers[0].pvBuffer = conn->ginbuf.value; InBuffers[0].cbBuffer = conn->ginbuf.length; InBuffers[0].BufferType = SECBUFFER_TOKEN; } OutBuffers[0].pvBuffer = NULL; OutBuffers[0].BufferType = SECBUFFER_TOKEN; OutBuffers[0].cbBuffer = 0; outbuf.cBuffers = 1; outbuf.pBuffers = OutBuffers; outbuf.ulVersion = SECBUFFER_VERSION; r = InitializeSecurityContext(conn->sspicred, conn->sspictx, conn->sspitarget, ISC_REQ_ALLOCATE_MEMORY, 0, SECURITY_NETWORK_DREP, (conn->sspictx == NULL) ? NULL : &inbuf, 0, &newContext, &outbuf, &contextAttr, NULL); if (r != SEC_E_OK && r != SEC_I_CONTINUE_NEEDED) { pg_SSPI_error(conn, libpq_gettext("SSPI continuation error"), r); return STATUS_ERROR; } if (conn->sspictx == NULL) { /* On first run, transfer retreived context handle */ conn->sspictx = malloc(sizeof(CtxtHandle)); if (conn->sspictx == NULL) { printfPQExpBuffer(&conn->errorMessage, libpq_gettext("out of memory\n")); return STATUS_ERROR; } memcpy(conn->sspictx, &newContext, sizeof(CtxtHandle)); } else { /* * On subsequent runs when we had data to send, free buffers that * contained this data. */ free(conn->ginbuf.value); conn->ginbuf.value = NULL; conn->ginbuf.length = 0; } /* * If SSPI returned any data to be sent to the server (as it normally * would), send this data as a password packet. */ if (outbuf.cBuffers > 0) { if (outbuf.cBuffers != 1) { /* * This should never happen, at least not for Kerberos * authentication. Keep check in case it shows up with other * authentication methods later. */ printfPQExpBuffer(&conn->errorMessage, "SSPI returned invalid number of output buffers\n"); return STATUS_ERROR; } /* * If the negotiation is complete, there may be zero bytes to send. * The server is at this point not expecting any more data, so don't * send it. */ if (outbuf.pBuffers[0].cbBuffer > 0) { if (pqPacketSend(conn, 'p', outbuf.pBuffers[0].pvBuffer, outbuf.pBuffers[0].cbBuffer)) { FreeContextBuffer(outbuf.pBuffers[0].pvBuffer); return STATUS_ERROR; } } FreeContextBuffer(outbuf.pBuffers[0].pvBuffer); } /* Cleanup is handled by the code in freePGconn() */ return STATUS_OK; }
int SSL_SOCKET :: ServerLoop() { // Loop AcceptSecurityContext SECURITY_STATUS ss = SEC_I_CONTINUE_NEEDED; Z<char> t(0x11000); Z<SecBuffer> bufsi(100); Z<SecBuffer> bufso(100); int pt = 0; // Loop using InitializeSecurityContext until success for(;;) { if (ss != SEC_I_CONTINUE_NEEDED && ss != SEC_E_INCOMPLETE_MESSAGE && ss != SEC_I_INCOMPLETE_CREDENTIALS) break; DWORD dwSSPIFlags = ISC_REQ_SEQUENCE_DETECT | ISC_REQ_REPLAY_DETECT | ISC_REQ_CONFIDENTIALITY | ISC_RET_EXTENDED_ERROR | ISC_REQ_ALLOCATE_MEMORY | ISC_REQ_STREAM; dwSSPIFlags |= ISC_REQ_MANUAL_CRED_VALIDATION; // Get Some data from the remote site int rval = recv(X,t + pt,0x10000,0); if (rval == 0 || rval == -1) return -1; pt += rval; // Put this data into the buffer so InitializeSecurityContext will do bufsi[0].BufferType = SECBUFFER_TOKEN; bufsi[0].cbBuffer = pt; bufsi[0].pvBuffer = t; bufsi[1].BufferType = SECBUFFER_EMPTY; bufsi[1].cbBuffer = 0; bufsi[1].pvBuffer = 0; sbin.ulVersion = SECBUFFER_VERSION; sbin.pBuffers = bufsi; sbin.cBuffers = 2; bufso[0].pvBuffer = NULL; bufso[0].BufferType= SECBUFFER_TOKEN; bufso[0].cbBuffer = 0; bufso[1].BufferType = SECBUFFER_EMPTY; bufso[1].cbBuffer = 0; bufso[1].pvBuffer = 0; sbout.cBuffers = 2; sbout.pBuffers = bufso; sbout.ulVersion = SECBUFFER_VERSION; SEC_E_INTERNAL_ERROR; DWORD flg = 0; ss = AcceptSecurityContext( &hCred, InitContext ? &hCtx : 0, &sbin, ASC_REQ_ALLOCATE_MEMORY,0, InitContext ? 0 : &hCtx, &sbout, &flg, 0); InitContext = true; if (ss == SEC_E_INCOMPLETE_MESSAGE) continue; // allow more pt = 0; if (FAILED(ss)) return -1; if (InitContext == 0 && ss != SEC_I_CONTINUE_NEEDED) return -1; // Pass data to the remote site rval = ssend_p((char*)bufso[0].pvBuffer,bufso[0].cbBuffer); FreeContextBuffer(bufso[0].pvBuffer); if (rval != bufso[0].cbBuffer) return -1; if (ss == S_OK) break; // wow!! } return 0; }
int SSL_SOCKET :: ClientLoop() { SECURITY_STATUS ss = SEC_I_CONTINUE_NEEDED; Z<char> t(0x11000); Z<SecBuffer> bufsi(100); Z<SecBuffer> bufso(100); int pt = 0; // Loop using InitializeSecurityContext until success for(;;) { if (ss != SEC_I_CONTINUE_NEEDED && ss != SEC_E_INCOMPLETE_MESSAGE && ss != SEC_I_INCOMPLETE_CREDENTIALS) break; DWORD dwSSPIFlags = ISC_REQ_SEQUENCE_DETECT | ISC_REQ_REPLAY_DETECT | ISC_REQ_CONFIDENTIALITY | ISC_RET_EXTENDED_ERROR | ISC_REQ_ALLOCATE_MEMORY | ISC_REQ_STREAM; dwSSPIFlags |= ISC_REQ_MANUAL_CRED_VALIDATION; if (InitContext == 0) { // Initialize sbout bufso[0].pvBuffer = NULL; bufso[0].BufferType = SECBUFFER_TOKEN; bufso[0].cbBuffer = 0; sbout.ulVersion = SECBUFFER_VERSION; sbout.cBuffers = 1; sbout.pBuffers = bufso; } else { // Get Some data from the remote site // Add also extradata? if (ExtraDataSize) { memcpy(t,ExtraData,ExtraDataSize); pt += ExtraDataSize; ExtraDataSize = 0; } int rval = recv(X,t + pt,0x10000,0); if (rval == 0 || rval == -1) return rval; pt += rval; // Put this data into the buffer so InitializeSecurityContext will do bufsi[0].BufferType = SECBUFFER_TOKEN; bufsi[0].cbBuffer = pt; bufsi[0].pvBuffer = t; bufsi[1].BufferType = SECBUFFER_EMPTY; bufsi[1].cbBuffer = 0; bufsi[1].pvBuffer = 0; sbin.ulVersion = SECBUFFER_VERSION; sbin.pBuffers = bufsi; sbin.cBuffers = 2; bufso[0].pvBuffer = NULL; bufso[0].BufferType= SECBUFFER_TOKEN; bufso[0].cbBuffer = 0; sbout.cBuffers = 1; sbout.pBuffers = bufso; sbout.ulVersion = SECBUFFER_VERSION; } DWORD dwSSPIOutFlags = 0; SEC_E_INTERNAL_ERROR; ss = InitializeSecurityContext( &hCred, InitContext ? &hCtx : 0, dn, dwSSPIFlags, 0, 0,//SECURITY_NATIVE_DREP, InitContext ? &sbin : 0, 0, InitContext ? 0 : &hCtx, &sbout, &dwSSPIOutFlags, 0); if (ss == SEC_E_INCOMPLETE_MESSAGE) continue; // allow more pt = 0; if (FAILED(ss)) return -1; if (InitContext == 0 && ss != SEC_I_CONTINUE_NEEDED) return -1; // Handle possible ExtraData /* if (bufsi[1].BufferType == SECBUFFER_EXTRA) { ExtraDataSize = bufsi[1].cbBuffer; ExtraData.Resize(ExtraDataSize + 10); memcpy(ExtraData,bufsi[1].pvBuffer,ExtraDataSize); } */ if (!InitContext) { // Send the data we got to the remote part //cbData = Send(OutBuffers[0].pvBuffer,OutBuffers[0].cbBuffer); int rval = ssend_p((char*)bufso[0].pvBuffer,bufso[0].cbBuffer); FreeContextBuffer(bufso[0].pvBuffer); if (rval != bufso[0].cbBuffer) return -1; InitContext = true; continue; } // Pass data to the remote site int rval = ssend_p((char*)bufso[0].pvBuffer,bufso[0].cbBuffer); FreeContextBuffer(bufso[0].pvBuffer); if (rval != bufso[0].cbBuffer) return -1; if (ss == S_OK) break; // wow!! } return 0; }
static DWORD netcon_secure_connect_setup(netconn_t *connection, BOOL compat_mode) { SecBuffer out_buf = {0, SECBUFFER_TOKEN, NULL}, in_bufs[2] = {{0, SECBUFFER_TOKEN}, {0, SECBUFFER_EMPTY}}; SecBufferDesc out_desc = {SECBUFFER_VERSION, 1, &out_buf}, in_desc = {SECBUFFER_VERSION, 2, in_bufs}; SecHandle *cred = &cred_handle; BYTE *read_buf; SIZE_T read_buf_size = 2048; ULONG attrs = 0; CtxtHandle ctx; SSIZE_T size; int bits; const CERT_CONTEXT *cert; SECURITY_STATUS status; DWORD res = ERROR_SUCCESS; const DWORD isc_req_flags = ISC_REQ_ALLOCATE_MEMORY|ISC_REQ_USE_SESSION_KEY|ISC_REQ_CONFIDENTIALITY |ISC_REQ_SEQUENCE_DETECT|ISC_REQ_REPLAY_DETECT|ISC_REQ_MANUAL_CRED_VALIDATION; if(!ensure_cred_handle()) return ERROR_INTERNET_SECURITY_CHANNEL_ERROR; if(compat_mode) { if(!have_compat_cred_handle) return ERROR_INTERNET_SECURITY_CHANNEL_ERROR; cred = &compat_cred_handle; } read_buf = heap_alloc(read_buf_size); if(!read_buf) return ERROR_OUTOFMEMORY; status = InitializeSecurityContextW(cred, NULL, connection->server->name, isc_req_flags, 0, 0, NULL, 0, &ctx, &out_desc, &attrs, NULL); assert(status != SEC_E_OK); while(status == SEC_I_CONTINUE_NEEDED || status == SEC_E_INCOMPLETE_MESSAGE) { if(out_buf.cbBuffer) { assert(status == SEC_I_CONTINUE_NEEDED); TRACE("sending %lu bytes\n", out_buf.cbBuffer); size = sock_send(connection->socket, out_buf.pvBuffer, out_buf.cbBuffer, 0); if(size != out_buf.cbBuffer) { ERR("send failed\n"); status = ERROR_INTERNET_SECURITY_CHANNEL_ERROR; break; } FreeContextBuffer(out_buf.pvBuffer); out_buf.pvBuffer = NULL; out_buf.cbBuffer = 0; } if(status == SEC_I_CONTINUE_NEEDED) { assert(in_bufs[1].cbBuffer < read_buf_size); memmove(read_buf, (BYTE*)in_bufs[0].pvBuffer+in_bufs[0].cbBuffer-in_bufs[1].cbBuffer, in_bufs[1].cbBuffer); in_bufs[0].cbBuffer = in_bufs[1].cbBuffer; in_bufs[1].BufferType = SECBUFFER_EMPTY; in_bufs[1].cbBuffer = 0; in_bufs[1].pvBuffer = NULL; } assert(in_bufs[0].BufferType == SECBUFFER_TOKEN); assert(in_bufs[1].BufferType == SECBUFFER_EMPTY); if(in_bufs[0].cbBuffer + 1024 > read_buf_size) { BYTE *new_read_buf; new_read_buf = heap_realloc(read_buf, read_buf_size + 1024); if(!new_read_buf) { status = E_OUTOFMEMORY; break; } in_bufs[0].pvBuffer = read_buf = new_read_buf; read_buf_size += 1024; } size = sock_recv(connection->socket, read_buf+in_bufs[0].cbBuffer, read_buf_size-in_bufs[0].cbBuffer, 0); if(size < 1) { WARN("recv error\n"); res = ERROR_INTERNET_SECURITY_CHANNEL_ERROR; break; } TRACE("recv %tu bytes\n", size); in_bufs[0].cbBuffer += size; in_bufs[0].pvBuffer = read_buf; status = InitializeSecurityContextW(cred, &ctx, connection->server->name, isc_req_flags, 0, 0, &in_desc, 0, NULL, &out_desc, &attrs, NULL); TRACE("InitializeSecurityContext ret %08x\n", status); if(status == SEC_E_OK) { if(SecIsValidHandle(&connection->ssl_ctx)) DeleteSecurityContext(&connection->ssl_ctx); connection->ssl_ctx = ctx; if(in_bufs[1].BufferType == SECBUFFER_EXTRA) FIXME("SECBUFFER_EXTRA not supported\n"); status = QueryContextAttributesW(&ctx, SECPKG_ATTR_STREAM_SIZES, &connection->ssl_sizes); if(status != SEC_E_OK) { WARN("Could not get sizes\n"); break; } status = QueryContextAttributesW(&ctx, SECPKG_ATTR_REMOTE_CERT_CONTEXT, (void*)&cert); if(status == SEC_E_OK) { res = netconn_verify_cert(connection, cert, cert->hCertStore); CertFreeCertificateContext(cert); if(res != ERROR_SUCCESS) { WARN("cert verify failed: %u\n", res); break; } }else { WARN("Could not get cert\n"); break; } connection->ssl_buf = heap_alloc(connection->ssl_sizes.cbHeader + connection->ssl_sizes.cbMaximumMessage + connection->ssl_sizes.cbTrailer); if(!connection->ssl_buf) { res = GetLastError(); break; } } } heap_free(read_buf); if(status != SEC_E_OK || res != ERROR_SUCCESS) { WARN("Failed to establish SSL connection: %08x (%u)\n", status, res); heap_free(connection->ssl_buf); connection->ssl_buf = NULL; return res ? res : ERROR_INTERNET_SECURITY_CHANNEL_ERROR; } TRACE("established SSL connection\n"); connection->secure = TRUE; connection->security_flags |= SECURITY_FLAG_SECURE; bits = NETCON_GetCipherStrength(connection); if (bits >= 128) connection->security_flags |= SECURITY_FLAG_STRENGTH_STRONG; else if (bits >= 56) connection->security_flags |= SECURITY_FLAG_STRENGTH_MEDIUM; else connection->security_flags |= SECURITY_FLAG_STRENGTH_WEAK; if(connection->mask_errors) connection->server->security_flags = connection->security_flags; return ERROR_SUCCESS; }
BOOL netconn_secure_connect( netconn_t *conn, WCHAR *hostname ) { SecBuffer out_buf = {0, SECBUFFER_TOKEN, NULL}, in_bufs[2] = {{0, SECBUFFER_TOKEN}, {0, SECBUFFER_EMPTY}}; SecBufferDesc out_desc = {SECBUFFER_VERSION, 1, &out_buf}, in_desc = {SECBUFFER_VERSION, 2, in_bufs}; BYTE *read_buf; SIZE_T read_buf_size = 2048; ULONG attrs = 0; CtxtHandle ctx; SSIZE_T size; const CERT_CONTEXT *cert; SECURITY_STATUS status; DWORD res = ERROR_SUCCESS; const DWORD isc_req_flags = ISC_REQ_ALLOCATE_MEMORY|ISC_REQ_USE_SESSION_KEY|ISC_REQ_CONFIDENTIALITY |ISC_REQ_SEQUENCE_DETECT|ISC_REQ_REPLAY_DETECT|ISC_REQ_MANUAL_CRED_VALIDATION; if(!ensure_cred_handle()) return FALSE; read_buf = heap_alloc(read_buf_size); if(!read_buf) return FALSE; status = InitializeSecurityContextW(&cred_handle, NULL, hostname, isc_req_flags, 0, 0, NULL, 0, &ctx, &out_desc, &attrs, NULL); assert(status != SEC_E_OK); while(status == SEC_I_CONTINUE_NEEDED || status == SEC_E_INCOMPLETE_MESSAGE) { if(out_buf.cbBuffer) { assert(status == SEC_I_CONTINUE_NEEDED); TRACE("sending %u bytes\n", out_buf.cbBuffer); size = sock_send(conn->socket, out_buf.pvBuffer, out_buf.cbBuffer, 0); if(size != out_buf.cbBuffer) { ERR("send failed\n"); res = ERROR_WINHTTP_SECURE_CHANNEL_ERROR; break; } FreeContextBuffer(out_buf.pvBuffer); out_buf.pvBuffer = NULL; out_buf.cbBuffer = 0; } if(status == SEC_I_CONTINUE_NEEDED) { assert(in_bufs[1].cbBuffer < read_buf_size); memmove(read_buf, (BYTE*)in_bufs[0].pvBuffer+in_bufs[0].cbBuffer-in_bufs[1].cbBuffer, in_bufs[1].cbBuffer); in_bufs[0].cbBuffer = in_bufs[1].cbBuffer; in_bufs[1].BufferType = SECBUFFER_EMPTY; in_bufs[1].cbBuffer = 0; in_bufs[1].pvBuffer = NULL; } assert(in_bufs[0].BufferType == SECBUFFER_TOKEN); assert(in_bufs[1].BufferType == SECBUFFER_EMPTY); if(in_bufs[0].cbBuffer + 1024 > read_buf_size) { BYTE *new_read_buf; new_read_buf = heap_realloc(read_buf, read_buf_size + 1024); if(!new_read_buf) { status = E_OUTOFMEMORY; break; } in_bufs[0].pvBuffer = read_buf = new_read_buf; read_buf_size += 1024; } size = sock_recv(conn->socket, read_buf+in_bufs[0].cbBuffer, read_buf_size-in_bufs[0].cbBuffer, 0); if(size < 1) { WARN("recv error\n"); status = ERROR_WINHTTP_SECURE_CHANNEL_ERROR; break; } TRACE("recv %lu bytes\n", size); in_bufs[0].cbBuffer += size; in_bufs[0].pvBuffer = read_buf; status = InitializeSecurityContextW(&cred_handle, &ctx, hostname, isc_req_flags, 0, 0, &in_desc, 0, NULL, &out_desc, &attrs, NULL); TRACE("InitializeSecurityContext ret %08x\n", status); if(status == SEC_E_OK) { if(in_bufs[1].BufferType == SECBUFFER_EXTRA) FIXME("SECBUFFER_EXTRA not supported\n"); status = QueryContextAttributesW(&ctx, SECPKG_ATTR_STREAM_SIZES, &conn->ssl_sizes); if(status != SEC_E_OK) { WARN("Could not get sizes\n"); break; } status = QueryContextAttributesW(&ctx, SECPKG_ATTR_REMOTE_CERT_CONTEXT, (void*)&cert); if(status == SEC_E_OK) { res = netconn_verify_cert(cert, hostname, conn->security_flags); CertFreeCertificateContext(cert); if(res != ERROR_SUCCESS) { WARN("cert verify failed: %u\n", res); break; } } else { WARN("Could not get cert\n"); break; } conn->ssl_buf = heap_alloc(conn->ssl_sizes.cbHeader + conn->ssl_sizes.cbMaximumMessage + conn->ssl_sizes.cbTrailer); if(!conn->ssl_buf) { res = GetLastError(); break; } } } heap_free(read_buf); if(status != SEC_E_OK || res != ERROR_SUCCESS) { WARN("Failed to initialize security context failed: %08x\n", status); heap_free(conn->ssl_buf); conn->ssl_buf = NULL; DeleteSecurityContext(&ctx); set_last_error(res ? res : ERROR_WINHTTP_SECURE_CHANNEL_ERROR); return FALSE; } TRACE("established SSL connection\n"); conn->secure = TRUE; conn->ssl_ctx = ctx; return TRUE; }