• Home
  • Raw
  • Download

Lines Matching +full:- +full:- +full:with +full:- +full:schannel

9  * Copyright (C) Marc Hoersken, <info@marc-hoersken.de>
23 * SPDX-License-Identifier: curl
28 * Source file for all Schannel-specific code for the TLS/SSL layer. No code
37 # error "cannot compile SCHANNEL support without SSPI."
40 #include "schannel.h"
66 * Schannel recv decryption.
75 shipped with Visual Studio 2013, aka _MSC_VER 1800:
77 https://technet.microsoft.com/en-us/library/hh831771%28v=ws.11%29.aspx
139 /* Both schannel buffer sizes must be > 0 */
166 buffer->cbBuffer = BufByteSize; in InitSecBuffer()
167 buffer->BufferType = BufType; in InitSecBuffer()
168 buffer->pvBuffer = BufDataPtr; in InitSecBuffer()
174 desc->ulVersion = SECBUFFER_VERSION; in InitSecBufferDesc()
175 desc->pBuffers = BufArr; in InitSecBufferDesc()
176 desc->cBuffers = NumArrElem; in InitSecBufferDesc()
185 long ssl_version = conn_config->version; in schannel_set_ssl_version_min_max()
186 long ssl_version_max = (long)conn_config->version_max; in schannel_set_ssl_version_min_max()
194 built-in. Previous builds of Windows 10 had broken TLS 1.3 in schannel_set_ssl_version_min_max()
227 failf(data, "schannel: TLS 1.3 not supported on Windows prior to 11"); in schannel_set_ssl_version_min_max()
356 size_t n = nameEnd ? (size_t)(nameEnd - name) : strlen(name); in get_alg_id_by_name()
381 sizeof("USE_STRONG_CRYPTO") - 1) || in set_ssl_ciphers()
383 sizeof("SCH_USE_STRONG_CRYPTO") - 1)) in set_ssl_ciphers()
384 schannel_cred->dwFlags |= SCH_USE_STRONG_CRYPTO; in set_ssl_ciphers()
391 schannel_cred->palgSupportedAlgs = algIds; in set_ssl_ciphers()
392 schannel_cred->cSupportedAlgs = (DWORD)algCount; in set_ssl_ciphers()
411 store_name_len = sep - path; in get_cert_location()
459 struct ssl_connect_data *connssl = cf->ctx; in schannel_acquire_credential_handle()
470 /* setup Schannel API options */ in schannel_acquire_credential_handle()
475 (struct schannel_ssl_backend_data *)(connssl->backend); in schannel_acquire_credential_handle()
479 if(conn_config->verifypeer) { in schannel_acquire_credential_handle()
481 if(backend->use_manual_cred_validation) in schannel_acquire_credential_handle()
487 if(ssl_config->no_revoke) { in schannel_acquire_credential_handle()
491 DEBUGF(infof(data, "schannel: disabled server certificate revocation " in schannel_acquire_credential_handle()
494 else if(ssl_config->revoke_best_effort) { in schannel_acquire_credential_handle()
498 DEBUGF(infof(data, "schannel: ignore revocation offline errors")); in schannel_acquire_credential_handle()
504 "schannel: checking server certificate revocation")); in schannel_acquire_credential_handle()
512 "schannel: disabled server cert revocation checks")); in schannel_acquire_credential_handle()
515 if(!conn_config->verifyhost) { in schannel_acquire_credential_handle()
517 DEBUGF(infof(data, "schannel: verifyhost setting prevents Schannel from " in schannel_acquire_credential_handle()
518 "comparing the supplied target name with the subject " in schannel_acquire_credential_handle()
522 if(!ssl_config->auto_client_cert) { in schannel_acquire_credential_handle()
525 infof(data, "schannel: disabled automatic use of client certificate"); in schannel_acquire_credential_handle()
528 infof(data, "schannel: enabled automatic use of client certificate"); in schannel_acquire_credential_handle()
530 switch(conn_config->version) { in schannel_acquire_credential_handle()
554 if(data->set.ssl.primary.clientcert || data->set.ssl.primary.cert_blob) { in schannel_acquire_credential_handle()
564 bool blob = data->set.ssl.primary.cert_blob != NULL; in schannel_acquire_credential_handle()
567 certdata = data->set.ssl.primary.cert_blob->data; in schannel_acquire_credential_handle()
568 certsize = data->set.ssl.primary.cert_blob->len; in schannel_acquire_credential_handle()
572 data->set.ssl.primary.clientcert); in schannel_acquire_credential_handle()
579 if(result && (data->set.ssl.primary.clientcert[0]!='\0')) in schannel_acquire_credential_handle()
580 fInCert = fopen(data->set.ssl.primary.clientcert, "rb"); in schannel_acquire_credential_handle()
583 failf(data, "schannel: Failed to get certificate location" in schannel_acquire_credential_handle()
585 data->set.ssl.primary.clientcert); in schannel_acquire_credential_handle()
591 if((fInCert || blob) && (data->set.ssl.cert_type) && in schannel_acquire_credential_handle()
592 (!strcasecompare(data->set.ssl.cert_type, "P12"))) { in schannel_acquire_credential_handle()
593 failf(data, "schannel: certificate format compatibility error " in schannel_acquire_credential_handle()
595 blob ? "(memory blob)" : data->set.ssl.primary.clientcert); in schannel_acquire_credential_handle()
603 en-US/3e7bc95f-b21a-4bcd-bd2c-7f996718cae5 in schannel_acquire_credential_handle()
610 "(memory blob)" : data->set.ssl.primary.clientcert; in schannel_acquire_credential_handle()
630 failf(data, "schannel: Failed to read cert file %s", in schannel_acquire_credential_handle()
631 data->set.ssl.primary.clientcert); in schannel_acquire_credential_handle()
637 /* Convert key-pair data to the in-memory certificate store */ in schannel_acquire_credential_handle()
641 if(data->set.ssl.key_passwd) in schannel_acquire_credential_handle()
642 pwd_len = strlen(data->set.ssl.key_passwd); in schannel_acquire_credential_handle()
648 data->set.ssl.key_passwd, in schannel_acquire_credential_handle()
671 failf(data, "schannel: Failed to import cert file %s, " in schannel_acquire_credential_handle()
675 failf(data, "schannel: Failed to import cert file %s, " in schannel_acquire_credential_handle()
686 failf(data, "schannel: Failed to get certificate from file %s" in schannel_acquire_credential_handle()
702 failf(data, "schannel: Failed to open cert store %lx %s, " in schannel_acquire_credential_handle()
743 if(data->set.ssl.primary.clientcert || data->set.ssl.primary.cert_blob) { in schannel_acquire_credential_handle()
744 failf(data, "schannel: client cert support not built in"); in schannel_acquire_credential_handle()
750 backend->cred = (struct Curl_schannel_cred *) in schannel_acquire_credential_handle()
752 if(!backend->cred) { in schannel_acquire_credential_handle()
753 failf(data, "schannel: unable to allocate memory"); in schannel_acquire_credential_handle()
764 backend->cred->refcount = 1; in schannel_acquire_credential_handle()
770 backend->cred->client_cert_store = client_cert_store; in schannel_acquire_credential_handle()
776 if(!conn_config->cipher_list && in schannel_acquire_credential_handle()
794 credentials.pTlsParameters->grbitDisabledProtocols = in schannel_acquire_credential_handle()
805 Curl_pSecFn->AcquireCredentialsHandle(NULL, (TCHAR*)UNISP_NAME, in schannel_acquire_credential_handle()
808 &backend->cred->cred_handle, in schannel_acquire_credential_handle()
809 &backend->cred->time_stamp); in schannel_acquire_credential_handle()
812 /* Pre-Windows 10 1809 or the user set a legacy algorithm list. in schannel_acquire_credential_handle()
813 Schannel will not negotiate TLS 1.3 when SCHANNEL_CRED is used. */ in schannel_acquire_credential_handle()
815 char *ciphers = conn_config->cipher_list; in schannel_acquire_credential_handle()
823 infof(data, "schannel: WARNING: This version of Schannel " in schannel_acquire_credential_handle()
824 "negotiates a less-secure TLS version than TLS 1.3 because the " in schannel_acquire_credential_handle()
829 failf(data, "schannel: Failed setting algorithm cipher list"); in schannel_acquire_credential_handle()
845 Curl_pSecFn->AcquireCredentialsHandle(NULL, (TCHAR*)UNISP_NAME, in schannel_acquire_credential_handle()
848 &backend->cred->cred_handle, in schannel_acquire_credential_handle()
849 &backend->cred->time_stamp); in schannel_acquire_credential_handle()
859 failf(data, "schannel: AcquireCredentialsHandle failed: %s", in schannel_acquire_credential_handle()
861 Curl_safefree(backend->cred); in schannel_acquire_credential_handle()
881 ssize_t written = -1; in schannel_connect_step1()
882 struct ssl_connect_data *connssl = cf->ctx; in schannel_connect_step1()
884 (struct schannel_ssl_backend_data *)connssl->backend; in schannel_connect_step1()
900 "schannel: SSL/TLS connection with %s port %d (step 1/3)", in schannel_connect_step1()
901 connssl->peer.hostname, connssl->peer.port)); in schannel_connect_step1()
905 /* Schannel in Windows XP (OS version 5.1) uses legacy handshakes and in schannel_connect_step1()
907 infof(data, "schannel: Windows version is old and may not be able to " in schannel_connect_step1()
914 backend->use_alpn = connssl->alpn && in schannel_connect_step1()
920 backend->use_alpn = FALSE; in schannel_connect_step1()
927 backend->use_manual_cred_validation = TRUE; in schannel_connect_step1()
933 if(conn_config->CAfile || conn_config->ca_info_blob) { in schannel_connect_step1()
936 backend->use_manual_cred_validation = TRUE; in schannel_connect_step1()
939 failf(data, "schannel: this version of Windows is too old to support " in schannel_connect_step1()
945 backend->use_manual_cred_validation = FALSE; in schannel_connect_step1()
947 if(conn_config->CAfile || conn_config->ca_info_blob) { in schannel_connect_step1()
948 failf(data, "schannel: CA cert support not built in"); in schannel_connect_step1()
954 backend->cred = NULL; in schannel_connect_step1()
957 if(ssl_config->primary.cache_session) { in schannel_connect_step1()
959 if(Curl_ssl_scache_get_obj(cf, data, connssl->peer.scache_key, in schannel_connect_step1()
961 backend->cred = old_cred; in schannel_connect_step1()
962 DEBUGF(infof(data, "schannel: reusing existing credential handle")); in schannel_connect_step1()
965 backend->cred->refcount++; in schannel_connect_step1()
967 "schannel: incremented credential handle refcount = %d", in schannel_connect_step1()
968 backend->cred->refcount)); in schannel_connect_step1()
973 if(!backend->cred) { in schannel_connect_step1()
978 /* schannel_acquire_credential_handle() sets backend->cred accordingly or in schannel_connect_step1()
981 /* A hostname associated with the credential is needed by in schannel_connect_step1()
983 snihost = connssl->peer.sni ? connssl->peer.sni : connssl->peer.hostname; in schannel_connect_step1()
984 backend->cred->sni_hostname = curlx_convert_UTF8_to_tchar(snihost); in schannel_connect_step1()
985 if(!backend->cred->sni_hostname) in schannel_connect_step1()
990 if(connssl->peer.type != CURL_SSL_PEER_DNS) { in schannel_connect_step1()
991 infof(data, "schannel: using IP address, SNI is not supported by OS."); in schannel_connect_step1()
995 if(backend->use_alpn) { in schannel_connect_step1()
1020 result = Curl_alpn_to_proto_buf(&proto, connssl->alpn); in schannel_connect_step1()
1028 *list_len = curlx_uitous(cur - list_start_index); in schannel_connect_step1()
1035 Curl_alpn_to_proto_str(&proto, connssl->alpn); in schannel_connect_step1()
1052 backend->req_flags = ISC_REQ_SEQUENCE_DETECT | ISC_REQ_REPLAY_DETECT | in schannel_connect_step1()
1056 if(!ssl_config->auto_client_cert) { in schannel_connect_step1()
1057 backend->req_flags |= ISC_REQ_USE_SUPPLIED_CREDS; in schannel_connect_step1()
1061 backend->ctxt = (struct Curl_schannel_ctxt *) in schannel_connect_step1()
1063 if(!backend->ctxt) { in schannel_connect_step1()
1064 failf(data, "schannel: unable to allocate memory"); in schannel_connect_step1()
1068 /* Schannel InitializeSecurityContext: in schannel_connect_step1()
1069 https://msdn.microsoft.com/en-us/library/windows/desktop/aa375924.aspx in schannel_connect_step1()
1073 us problems with inbuf regardless. https://github.com/curl/curl/issues/983 in schannel_connect_step1()
1075 sspi_status = Curl_pSecFn->InitializeSecurityContext( in schannel_connect_step1()
1076 &backend->cred->cred_handle, NULL, backend->cred->sni_hostname, in schannel_connect_step1()
1077 backend->req_flags, 0, 0, in schannel_connect_step1()
1078 (backend->use_alpn ? &inbuf_desc : NULL), in schannel_connect_step1()
1079 0, &backend->ctxt->ctxt_handle, in schannel_connect_step1()
1080 &outbuf_desc, &backend->ret_flags, &backend->ctxt->time_stamp); in schannel_connect_step1()
1084 Curl_safefree(backend->ctxt); in schannel_connect_step1()
1087 failf(data, "schannel: initial InitializeSecurityContext failed: %s", in schannel_connect_step1()
1091 failf(data, "schannel: SNI or certificate check failed: %s", in schannel_connect_step1()
1106 failf(data, "schannel: initial InitializeSecurityContext failed: %s", in schannel_connect_step1()
1112 DEBUGF(infof(data, "schannel: sending initial handshake data: " in schannel_connect_step1()
1116 written = Curl_conn_cf_send(cf->next, data, in schannel_connect_step1()
1119 Curl_pSecFn->FreeContextBuffer(outbuf.pvBuffer); in schannel_connect_step1()
1121 failf(data, "schannel: failed to send initial handshake data: " in schannel_connect_step1()
1126 DEBUGF(infof(data, "schannel: sent initial handshake data: " in schannel_connect_step1()
1129 backend->recv_unrecoverable_err = CURLE_OK; in schannel_connect_step1()
1130 backend->recv_sspi_close_notify = FALSE; in schannel_connect_step1()
1131 backend->recv_connection_closed = FALSE; in schannel_connect_step1()
1132 backend->recv_renegotiating = FALSE; in schannel_connect_step1()
1133 backend->encdata_is_incomplete = FALSE; in schannel_connect_step1()
1136 connssl->connecting_state = ssl_connect_2; in schannel_connect_step1()
1144 struct ssl_connect_data *connssl = cf->ctx; in schannel_connect_step2()
1146 (struct schannel_ssl_backend_data *)connssl->backend; in schannel_connect_step2()
1149 ssize_t nread = -1, written = -1; in schannel_connect_step2()
1162 doread = (connssl->io_need & CURL_SSL_IO_NEED_SEND) ? FALSE : TRUE; in schannel_connect_step2()
1163 connssl->io_need = CURL_SSL_IO_NEED_NONE; in schannel_connect_step2()
1166 "schannel: SSL/TLS connection with %s port %d (step 2/3)", in schannel_connect_step2()
1167 connssl->peer.hostname, connssl->peer.port)); in schannel_connect_step2()
1169 if(!backend->cred || !backend->ctxt) in schannel_connect_step2()
1173 if(!backend->decdata_buffer) { in schannel_connect_step2()
1174 backend->decdata_offset = 0; in schannel_connect_step2()
1175 backend->decdata_length = CURL_SCHANNEL_BUFFER_INIT_SIZE; in schannel_connect_step2()
1176 backend->decdata_buffer = malloc(backend->decdata_length); in schannel_connect_step2()
1177 if(!backend->decdata_buffer) { in schannel_connect_step2()
1178 failf(data, "schannel: unable to allocate memory"); in schannel_connect_step2()
1184 if(!backend->encdata_buffer) { in schannel_connect_step2()
1185 backend->encdata_is_incomplete = FALSE; in schannel_connect_step2()
1186 backend->encdata_offset = 0; in schannel_connect_step2()
1187 backend->encdata_length = CURL_SCHANNEL_BUFFER_INIT_SIZE; in schannel_connect_step2()
1188 backend->encdata_buffer = malloc(backend->encdata_length); in schannel_connect_step2()
1189 if(!backend->encdata_buffer) { in schannel_connect_step2()
1190 failf(data, "schannel: unable to allocate memory"); in schannel_connect_step2()
1196 if(backend->encdata_length - backend->encdata_offset < in schannel_connect_step2()
1199 size_t reallocated_length = backend->encdata_offset + in schannel_connect_step2()
1201 reallocated_buffer = realloc(backend->encdata_buffer, in schannel_connect_step2()
1205 failf(data, "schannel: unable to re-allocate memory"); in schannel_connect_step2()
1209 backend->encdata_buffer = reallocated_buffer; in schannel_connect_step2()
1210 backend->encdata_length = reallocated_length; in schannel_connect_step2()
1217 nread = Curl_conn_cf_recv(cf->next, data, in schannel_connect_step2()
1218 (char *) (backend->encdata_buffer + in schannel_connect_step2()
1219 backend->encdata_offset), in schannel_connect_step2()
1220 backend->encdata_length - in schannel_connect_step2()
1221 backend->encdata_offset, in schannel_connect_step2()
1224 connssl->io_need = CURL_SSL_IO_NEED_RECV; in schannel_connect_step2()
1225 DEBUGF(infof(data, "schannel: failed to receive handshake, " in schannel_connect_step2()
1230 failf(data, "schannel: failed to receive handshake, " in schannel_connect_step2()
1236 backend->encdata_offset += nread; in schannel_connect_step2()
1237 backend->encdata_is_incomplete = FALSE; in schannel_connect_step2()
1238 SCH_DEV(infof(data, "schannel: encrypted data got %zd", nread)); in schannel_connect_step2()
1242 "schannel: encrypted data buffer: offset %zu length %zu", in schannel_connect_step2()
1243 backend->encdata_offset, backend->encdata_length)); in schannel_connect_step2()
1246 InitSecBuffer(&inbuf[0], SECBUFFER_TOKEN, malloc(backend->encdata_offset), in schannel_connect_step2()
1247 curlx_uztoul(backend->encdata_offset)); in schannel_connect_step2()
1258 failf(data, "schannel: unable to allocate memory"); in schannel_connect_step2()
1263 memcpy(inbuf[0].pvBuffer, backend->encdata_buffer, in schannel_connect_step2()
1264 backend->encdata_offset); in schannel_connect_step2()
1266 sspi_status = Curl_pSecFn->InitializeSecurityContext( in schannel_connect_step2()
1267 &backend->cred->cred_handle, &backend->ctxt->ctxt_handle, in schannel_connect_step2()
1268 backend->cred->sni_hostname, backend->req_flags, in schannel_connect_step2()
1270 &outbuf_desc, &backend->ret_flags, &backend->ctxt->time_stamp); in schannel_connect_step2()
1277 backend->encdata_is_incomplete = TRUE; in schannel_connect_step2()
1278 connssl->io_need = CURL_SSL_IO_NEED_RECV; in schannel_connect_step2()
1280 "schannel: received incomplete message, need more data")); in schannel_connect_step2()
1288 !(backend->req_flags & ISC_REQ_USE_SUPPLIED_CREDS)) { in schannel_connect_step2()
1289 backend->req_flags |= ISC_REQ_USE_SUPPLIED_CREDS; in schannel_connect_step2()
1290 connssl->io_need = CURL_SSL_IO_NEED_SEND; in schannel_connect_step2()
1292 "schannel: a client certificate has been requested")); in schannel_connect_step2()
1301 DEBUGF(infof(data, "schannel: sending next handshake data: " in schannel_connect_step2()
1305 written = Curl_conn_cf_send(cf->next, data, in schannel_connect_step2()
1310 failf(data, "schannel: failed to send next handshake data: " in schannel_connect_step2()
1318 Curl_pSecFn->FreeContextBuffer(outbuf[i].pvBuffer); in schannel_connect_step2()
1326 failf(data, "schannel: next InitializeSecurityContext failed: %s", in schannel_connect_step2()
1330 failf(data, "schannel: SNI or certificate check failed: %s", in schannel_connect_step2()
1334 failf(data, "schannel: %s", in schannel_connect_step2()
1349 failf(data, "schannel: next InitializeSecurityContext failed: %s", in schannel_connect_step2()
1357 SCH_DEV(infof(data, "schannel: encrypted data length: %lu", in schannel_connect_step2()
1371 if(backend->encdata_offset > inbuf[1].cbBuffer) { in schannel_connect_step2()
1372 memmove(backend->encdata_buffer, in schannel_connect_step2()
1373 (backend->encdata_buffer + backend->encdata_offset) - in schannel_connect_step2()
1375 backend->encdata_offset = inbuf[1].cbBuffer; in schannel_connect_step2()
1383 backend->encdata_offset = 0; in schannel_connect_step2()
1390 connssl->io_need = CURL_SSL_IO_NEED_RECV; in schannel_connect_step2()
1396 connssl->connecting_state = ssl_connect_3; in schannel_connect_step2()
1397 DEBUGF(infof(data, "schannel: SSL/TLS handshake complete")); in schannel_connect_step2()
1402 data->set.str[STRING_SSL_PINNEDPUBLICKEY_PROXY] : in schannel_connect_step2()
1403 data->set.str[STRING_SSL_PINNEDPUBLICKEY]; in schannel_connect_step2()
1405 pubkey_ptr = data->set.str[STRING_SSL_PINNEDPUBLICKEY]; in schannel_connect_step2()
1416 if(conn_config->verifypeer && backend->use_manual_cred_validation) { in schannel_connect_step2()
1423 because in that case Schannel will not verify it. */ in schannel_connect_step2()
1424 if(!conn_config->verifypeer && conn_config->verifyhost) in schannel_connect_step2()
1434 ((cert_context->dwCertEncodingType & X509_ASN_ENCODING) != 0) && in valid_cert_encoding()
1435 (cert_context->pbCertEncoded != NULL) && in valid_cert_encoding()
1436 (cert_context->cbCertEncoded > 0); in valid_cert_encoding()
1452 context->hCertStore, in traverse_cert_store()
1455 leaf-to-root order while all previous versions of Windows enumerate in traverse_cert_store()
1456 certificates in root-to-leaf order. Determine the order of enumeration in traverse_cert_store()
1457 by comparing SECPKG_ATTR_REMOTE_CERT_CONTEXT's pbCertContext with the in traverse_cert_store()
1459 if(first && context->pbCertEncoded != current_context->pbCertEncoded) in traverse_cert_store()
1492 args->result = CURLE_OK; in add_cert_to_certinfo()
1494 const char *beg = (const char *) ccert_context->pbCertEncoded; in add_cert_to_certinfo()
1495 const char *end = beg + ccert_context->cbCertEncoded; in add_cert_to_certinfo()
1496 int insert_index = reverse_order ? (args->certs_count - 1) - args->idx : in add_cert_to_certinfo()
1497 args->idx; in add_cert_to_certinfo()
1498 args->result = Curl_extract_certinfo(args->data, insert_index, in add_cert_to_certinfo()
1500 args->idx++; in add_cert_to_certinfo()
1502 return args->result == CURLE_OK; in add_cert_to_certinfo()
1511 cred->refcount--; in schannel_session_free()
1512 if(cred->refcount == 0) { in schannel_session_free()
1513 Curl_pSecFn->FreeCredentialsHandle(&cred->cred_handle); in schannel_session_free()
1514 curlx_unicodefree(cred->sni_hostname); in schannel_session_free()
1516 if(cred->client_cert_store) { in schannel_session_free()
1517 CertCloseStore(cred->client_cert_store, 0); in schannel_session_free()
1518 cred->client_cert_store = NULL; in schannel_session_free()
1529 struct ssl_connect_data *connssl = cf->ctx; in schannel_connect_step3()
1531 (struct schannel_ssl_backend_data *)connssl->backend; in schannel_connect_step3()
1540 DEBUGASSERT(ssl_connect_3 == connssl->connecting_state); in schannel_connect_step3()
1544 "schannel: SSL/TLS connection with %s port %d (step 3/3)", in schannel_connect_step3()
1545 connssl->peer.hostname, connssl->peer.port)); in schannel_connect_step3()
1547 if(!backend->cred) in schannel_connect_step3()
1551 if(backend->ret_flags != backend->req_flags) { in schannel_connect_step3()
1552 if(!(backend->ret_flags & ISC_RET_SEQUENCE_DETECT)) in schannel_connect_step3()
1553 failf(data, "schannel: failed to setup sequence detection"); in schannel_connect_step3()
1554 if(!(backend->ret_flags & ISC_RET_REPLAY_DETECT)) in schannel_connect_step3()
1555 failf(data, "schannel: failed to setup replay detection"); in schannel_connect_step3()
1556 if(!(backend->ret_flags & ISC_RET_CONFIDENTIALITY)) in schannel_connect_step3()
1557 failf(data, "schannel: failed to setup confidentiality"); in schannel_connect_step3()
1558 if(!(backend->ret_flags & ISC_RET_ALLOCATED_MEMORY)) in schannel_connect_step3()
1559 failf(data, "schannel: failed to setup memory allocation"); in schannel_connect_step3()
1560 if(!(backend->ret_flags & ISC_RET_STREAM)) in schannel_connect_step3()
1561 failf(data, "schannel: failed to setup stream orientation"); in schannel_connect_step3()
1566 if(backend->use_alpn) { in schannel_connect_step3()
1568 Curl_pSecFn->QueryContextAttributes(&backend->ctxt->ctxt_handle, in schannel_connect_step3()
1573 failf(data, "schannel: failed to retrieve ALPN result"); in schannel_connect_step3()
1579 unsigned char prev_alpn = cf->conn->alpn; in schannel_connect_step3()
1583 if(backend->recv_renegotiating) { in schannel_connect_step3()
1584 if(prev_alpn != cf->conn->alpn && in schannel_connect_step3()
1587 * deal with this */ in schannel_connect_step3()
1588 failf(data, "schannel: server selected an ALPN protocol too late"); in schannel_connect_step3()
1594 if(!backend->recv_renegotiating) in schannel_connect_step3()
1601 if(ssl_config->primary.cache_session) { in schannel_connect_step3()
1604 backend->cred->refcount++; in schannel_connect_step3()
1605 result = Curl_ssl_scache_add_obj(cf, data, connssl->peer.scache_key, in schannel_connect_step3()
1606 backend->cred, schannel_session_free); in schannel_connect_step3()
1612 if(data->set.ssl.certinfo) { in schannel_connect_step3()
1615 Curl_pSecFn->QueryContextAttributes(&backend->ctxt->ctxt_handle, in schannel_connect_step3()
1620 failf(data, "schannel: failed to retrieve remote cert context"); in schannel_connect_step3()
1640 connssl->connecting_state = ssl_connect_done; in schannel_connect_step3()
1651 struct ssl_connect_data *connssl = cf->ctx; in schannel_connect_common()
1657 if(ssl_connection_complete == connssl->state) { in schannel_connect_common()
1662 if(ssl_connect_1 == connssl->connecting_state) { in schannel_connect_common()
1677 while(ssl_connect_2 == connssl->connecting_state) { in schannel_connect_common()
1689 if(connssl->io_need) { in schannel_connect_common()
1691 curl_socket_t writefd = (connssl->io_need & CURL_SSL_IO_NEED_SEND) ? in schannel_connect_common()
1693 curl_socket_t readfd = (connssl->io_need & CURL_SSL_IO_NEED_RECV) ? in schannel_connect_common()
1725 if(result || (nonblocking && (ssl_connect_2 == connssl->connecting_state))) in schannel_connect_common()
1730 if(ssl_connect_3 == connssl->connecting_state) { in schannel_connect_common()
1736 if(ssl_connect_done == connssl->connecting_state) { in schannel_connect_common()
1737 connssl->state = ssl_connection_complete; in schannel_connect_common()
1740 /* When SSPI is used in combination with Schannel in schannel_connect_common()
1741 * we need the Schannel context to create the Schannel in schannel_connect_common()
1747 (struct schannel_ssl_backend_data *)connssl->backend; in schannel_connect_common()
1749 cf->conn->sslContext = &backend->ctxt->ctxt_handle; in schannel_connect_common()
1759 connssl->connecting_state = ssl_connect_1; in schannel_connect_common()
1768 ssize_t written = -1; in schannel_send()
1771 struct ssl_connect_data *connssl = cf->ctx; in schannel_send()
1777 (struct schannel_ssl_backend_data *)connssl->backend; in schannel_send()
1782 if(backend->stream_sizes.cbMaximumMessage == 0) { in schannel_send()
1783 sspi_status = Curl_pSecFn->QueryContextAttributes( in schannel_send()
1784 &backend->ctxt->ctxt_handle, in schannel_send()
1786 &backend->stream_sizes); in schannel_send()
1789 return -1; in schannel_send()
1794 if(len > backend->stream_sizes.cbMaximumMessage) { in schannel_send()
1795 len = backend->stream_sizes.cbMaximumMessage; in schannel_send()
1799 data_len = backend->stream_sizes.cbHeader + len + in schannel_send()
1800 backend->stream_sizes.cbTrailer; in schannel_send()
1804 return -1; in schannel_send()
1809 ptr, backend->stream_sizes.cbHeader); in schannel_send()
1811 ptr + backend->stream_sizes.cbHeader, curlx_uztoul(len)); in schannel_send()
1813 ptr + backend->stream_sizes.cbHeader + len, in schannel_send()
1814 backend->stream_sizes.cbTrailer); in schannel_send()
1821 /* https://msdn.microsoft.com/en-us/library/windows/desktop/aa375390.aspx */ in schannel_send()
1822 sspi_status = Curl_pSecFn->EncryptMessage(&backend->ctxt->ctxt_handle, 0, in schannel_send()
1842 Here's the catch with this - if we tell the client that all the in schannel_send()
1855 failf(data, "schannel: timed out sending data " in schannel_send()
1858 written = -1; in schannel_send()
1868 written = -1; in schannel_send()
1872 failf(data, "schannel: timed out sending data " in schannel_send()
1875 written = -1; in schannel_send()
1880 this_write = Curl_conn_cf_send(cf->next, data, in schannel_send()
1881 ptr + written, len - written, in schannel_send()
1887 written = -1; in schannel_send()
1916 ssize_t nread = -1; in schannel_recv()
1917 struct ssl_connect_data *connssl = cf->ctx; in schannel_recv()
1928 (struct schannel_ssl_backend_data *)connssl->backend; in schannel_recv()
1933 * Do not return or set backend->recv_unrecoverable_err unless in the in schannel_recv()
1940 * Schannel recv decryption. in schannel_recv()
1948 SCH_DEV(infof(data, "schannel: client wants to read %zu bytes", len)); in schannel_recv()
1951 if(len && len <= backend->decdata_offset) { in schannel_recv()
1953 "schannel: enough decrypted data is already available")); in schannel_recv()
1956 else if(backend->recv_unrecoverable_err) { in schannel_recv()
1957 *err = backend->recv_unrecoverable_err; in schannel_recv()
1958 infof(data, "schannel: an unrecoverable error occurred in a prior call"); in schannel_recv()
1961 else if(backend->recv_sspi_close_notify) { in schannel_recv()
1963 infof(data, "schannel: server indicated shutdown in a prior call"); in schannel_recv()
1970 else if(len && !backend->recv_connection_closed) { in schannel_recv()
1972 size = backend->encdata_length - backend->encdata_offset; in schannel_recv()
1974 backend->encdata_length < min_encdata_length) { in schannel_recv()
1975 reallocated_length = backend->encdata_offset + in schannel_recv()
1980 reallocated_buffer = realloc(backend->encdata_buffer, in schannel_recv()
1984 failf(data, "schannel: unable to re-allocate memory"); in schannel_recv()
1988 backend->encdata_buffer = reallocated_buffer; in schannel_recv()
1989 backend->encdata_length = reallocated_length; in schannel_recv()
1990 size = backend->encdata_length - backend->encdata_offset; in schannel_recv()
1991 SCH_DEV(infof(data, "schannel: encdata_buffer resized %zu", in schannel_recv()
1992 backend->encdata_length)); in schannel_recv()
1996 "schannel: encrypted data buffer: offset %zu length %zu", in schannel_recv()
1997 backend->encdata_offset, backend->encdata_length)); in schannel_recv()
2000 nread = Curl_conn_cf_recv(cf->next, data, in schannel_recv()
2001 (char *)(backend->encdata_buffer + in schannel_recv()
2002 backend->encdata_offset), in schannel_recv()
2005 nread = -1; in schannel_recv()
2007 SCH_DEV(infof(data, "schannel: recv returned CURLE_AGAIN")); in schannel_recv()
2009 infof(data, "schannel: recv returned CURLE_RECV_ERROR"); in schannel_recv()
2011 infof(data, "schannel: recv returned error %d", *err); in schannel_recv()
2014 backend->recv_connection_closed = TRUE; in schannel_recv()
2015 DEBUGF(infof(data, "schannel: server closed the connection")); in schannel_recv()
2018 backend->encdata_offset += (size_t)nread; in schannel_recv()
2019 backend->encdata_is_incomplete = FALSE; in schannel_recv()
2020 SCH_DEV(infof(data, "schannel: encrypted data got %zd", nread)); in schannel_recv()
2024 SCH_DEV(infof(data, "schannel: encrypted data buffer: offset %zu length %zu", in schannel_recv()
2025 backend->encdata_offset, backend->encdata_length)); in schannel_recv()
2028 while(backend->encdata_offset > 0 && sspi_status == SEC_E_OK && in schannel_recv()
2029 (!len || backend->decdata_offset < len || in schannel_recv()
2030 backend->recv_connection_closed)) { in schannel_recv()
2032 InitSecBuffer(&inbuf[0], SECBUFFER_DATA, backend->encdata_buffer, in schannel_recv()
2033 curlx_uztoul(backend->encdata_offset)); in schannel_recv()
2041 /* https://msdn.microsoft.com/en-us/library/windows/desktop/aa375348.aspx in schannel_recv()
2043 sspi_status = Curl_pSecFn->DecryptMessage(&backend->ctxt->ctxt_handle, in schannel_recv()
2053 SCH_DEV(infof(data, "schannel: decrypted data length: %lu", in schannel_recv()
2059 if(backend->decdata_length - backend->decdata_offset < size || in schannel_recv()
2060 backend->decdata_length < len) { in schannel_recv()
2062 reallocated_length = backend->decdata_offset + size; in schannel_recv()
2067 reallocated_buffer = realloc(backend->decdata_buffer, in schannel_recv()
2071 failf(data, "schannel: unable to re-allocate memory"); in schannel_recv()
2074 backend->decdata_buffer = reallocated_buffer; in schannel_recv()
2075 backend->decdata_length = reallocated_length; in schannel_recv()
2081 memcpy(backend->decdata_buffer + backend->decdata_offset, in schannel_recv()
2083 backend->decdata_offset += size; in schannel_recv()
2086 SCH_DEV(infof(data, "schannel: decrypted data added: %zu", size)); in schannel_recv()
2088 "schannel: decrypted cached: offset %zu length %zu", in schannel_recv()
2089 backend->decdata_offset, backend->decdata_length)); in schannel_recv()
2094 SCH_DEV(infof(data, "schannel: encrypted data length: %lu", in schannel_recv()
2100 if(backend->encdata_offset > inbuf[3].cbBuffer) { in schannel_recv()
2103 memmove(backend->encdata_buffer, in schannel_recv()
2104 (backend->encdata_buffer + backend->encdata_offset) - in schannel_recv()
2106 backend->encdata_offset = inbuf[3].cbBuffer; in schannel_recv()
2110 "schannel: encrypted cached: offset %zu length %zu", in schannel_recv()
2111 backend->encdata_offset, backend->encdata_length)); in schannel_recv()
2115 backend->encdata_offset = 0; in schannel_recv()
2120 infof(data, "schannel: remote party requests renegotiation"); in schannel_recv()
2122 infof(data, "schannel: cannot renegotiate, an error is pending"); in schannel_recv()
2127 infof(data, "schannel: renegotiating SSL/TLS connection"); in schannel_recv()
2128 connssl->state = ssl_connection_negotiating; in schannel_recv()
2129 connssl->connecting_state = ssl_connect_2; in schannel_recv()
2130 connssl->io_need = CURL_SSL_IO_NEED_SEND; in schannel_recv()
2131 backend->recv_renegotiating = TRUE; in schannel_recv()
2133 backend->recv_renegotiating = FALSE; in schannel_recv()
2135 infof(data, "schannel: renegotiation failed"); in schannel_recv()
2140 infof(data, "schannel: SSL/TLS connection renegotiated"); in schannel_recv()
2147 backend->recv_sspi_close_notify = TRUE; in schannel_recv()
2148 if(!backend->recv_connection_closed) in schannel_recv()
2149 backend->recv_connection_closed = TRUE; in schannel_recv()
2156 "schannel: server close notification received (close_notify)"); in schannel_recv()
2161 backend->encdata_is_incomplete = TRUE; in schannel_recv()
2164 SCH_DEV(infof(data, "schannel: failed to decrypt data, need more data")); in schannel_recv()
2170 failf(data, "schannel: failed to read data from server: %s", in schannel_recv()
2178 SCH_DEV(infof(data, "schannel: encrypted data buffer: offset %zu length %zu", in schannel_recv()
2179 backend->encdata_offset, backend->encdata_length)); in schannel_recv()
2181 SCH_DEV(infof(data, "schannel: decrypted data buffer: offset %zu length %zu", in schannel_recv()
2182 backend->decdata_offset, backend->decdata_length)); in schannel_recv()
2185 /* Warning- there is no guarantee the encdata state is valid at this point */ in schannel_recv()
2186 SCH_DEV(infof(data, "schannel: schannel_recv cleanup")); in schannel_recv()
2199 if(len && !backend->decdata_offset && backend->recv_connection_closed && in schannel_recv()
2200 !backend->recv_sspi_close_notify) { in schannel_recv()
2205 backend->recv_sspi_close_notify = TRUE; in schannel_recv()
2208 failf(data, "schannel: server closed abruptly (missing close_notify)"); in schannel_recv()
2214 backend->recv_unrecoverable_err = *err; in schannel_recv()
2216 size = len < backend->decdata_offset ? len : backend->decdata_offset; in schannel_recv()
2218 memcpy(buf, backend->decdata_buffer, size); in schannel_recv()
2219 memmove(backend->decdata_buffer, backend->decdata_buffer + size, in schannel_recv()
2220 backend->decdata_offset - size); in schannel_recv()
2221 backend->decdata_offset -= size; in schannel_recv()
2222 SCH_DEV(infof(data, "schannel: decrypted data returned %zu", size)); in schannel_recv()
2224 "schannel: decrypted data buffer: offset %zu length %zu", in schannel_recv()
2225 backend->decdata_offset, backend->decdata_length)); in schannel_recv()
2230 if(!*err && !backend->recv_connection_closed) in schannel_recv()
2240 return *err ? -1 : 0; in schannel_recv()
2268 const struct ssl_connect_data *connssl = cf->ctx; in schannel_data_pending()
2270 (struct schannel_ssl_backend_data *)connssl->backend; in schannel_data_pending()
2275 if(backend->ctxt) /* SSL/TLS is in use */ in schannel_data_pending()
2276 return backend->decdata_offset > 0 || in schannel_data_pending()
2277 (backend->encdata_offset > 0 && !backend->encdata_is_incomplete) || in schannel_data_pending()
2278 backend->recv_connection_closed || in schannel_data_pending()
2279 backend->recv_sspi_close_notify || in schannel_data_pending()
2280 backend->recv_unrecoverable_err; in schannel_data_pending()
2292 /* See https://msdn.microsoft.com/en-us/library/windows/desktop/aa380138.aspx in schannel_shutdown()
2293 * Shutting Down an Schannel Connection in schannel_shutdown()
2295 struct ssl_connect_data *connssl = cf->ctx; in schannel_shutdown()
2297 (struct schannel_ssl_backend_data *)connssl->backend; in schannel_shutdown()
2300 if(cf->shutdown) { in schannel_shutdown()
2308 /* Not supported in schannel */ in schannel_shutdown()
2312 if(backend->ctxt) { in schannel_shutdown()
2313 infof(data, "schannel: shutting down SSL/TLS connection with %s port %d", in schannel_shutdown()
2314 connssl->peer.hostname, connssl->peer.port); in schannel_shutdown()
2317 if(!backend->ctxt || cf->shutdown) { in schannel_shutdown()
2322 if(backend->cred && backend->ctxt && !backend->sent_shutdown) { in schannel_shutdown()
2333 sspi_status = Curl_pSecFn->ApplyControlToken(&backend->ctxt->ctxt_handle, in schannel_shutdown()
2338 failf(data, "schannel: ApplyControlToken failure: %s", in schannel_shutdown()
2348 sspi_status = Curl_pSecFn->InitializeSecurityContext( in schannel_shutdown()
2349 &backend->cred->cred_handle, in schannel_shutdown()
2350 &backend->ctxt->ctxt_handle, in schannel_shutdown()
2351 backend->cred->sni_hostname, in schannel_shutdown()
2352 backend->req_flags, in schannel_shutdown()
2357 &backend->ctxt->ctxt_handle, in schannel_shutdown()
2359 &backend->ret_flags, in schannel_shutdown()
2360 &backend->ctxt->time_stamp); in schannel_shutdown()
2364 ssize_t written = Curl_conn_cf_send(cf->next, data, in schannel_shutdown()
2367 Curl_pSecFn->FreeContextBuffer(outbuf.pvBuffer); in schannel_shutdown()
2371 failf(data, "schannel: failed to send close msg: %s" in schannel_shutdown()
2376 backend->sent_shutdown = TRUE; in schannel_shutdown()
2380 connssl->io_need = CURL_SSL_IO_NEED_SEND; in schannel_shutdown()
2385 if(!backend->recv_connection_closed) { in schannel_shutdown()
2386 failf(data, "schannel: error sending close msg: %d", result); in schannel_shutdown()
2400 if(backend->cred && backend->ctxt && in schannel_shutdown()
2401 !backend->recv_sspi_close_notify && !backend->recv_connection_closed) { in schannel_shutdown()
2411 backend->recv_connection_closed = TRUE; in schannel_shutdown()
2415 connssl->io_need = CURL_SSL_IO_NEED_RECV; in schannel_shutdown()
2424 cf->shutdown = (result || *done); in schannel_shutdown()
2430 struct ssl_connect_data *connssl = cf->ctx; in schannel_close()
2432 (struct schannel_ssl_backend_data *)connssl->backend; in schannel_close()
2437 /* free SSPI Schannel API security context handle */ in schannel_close()
2438 if(backend->ctxt) { in schannel_close()
2439 DEBUGF(infof(data, "schannel: clear security context handle")); in schannel_close()
2440 Curl_pSecFn->DeleteSecurityContext(&backend->ctxt->ctxt_handle); in schannel_close()
2441 Curl_safefree(backend->ctxt); in schannel_close()
2444 /* free SSPI Schannel API credential handle */ in schannel_close()
2445 if(backend->cred) { in schannel_close()
2447 schannel_session_free(backend->cred); in schannel_close()
2449 backend->cred = NULL; in schannel_close()
2453 if(backend->encdata_buffer) { in schannel_close()
2454 Curl_safefree(backend->encdata_buffer); in schannel_close()
2455 backend->encdata_length = 0; in schannel_close()
2456 backend->encdata_offset = 0; in schannel_close()
2457 backend->encdata_is_incomplete = FALSE; in schannel_close()
2461 if(backend->decdata_buffer) { in schannel_close()
2462 Curl_safefree(backend->decdata_buffer); in schannel_close()
2463 backend->decdata_length = 0; in schannel_close()
2464 backend->decdata_offset = 0; in schannel_close()
2480 return msnprintf(buffer, size, "Schannel"); in schannel_version()
2495 struct ssl_connect_data *connssl = cf->ctx; in schannel_pkp_pin_peer_pubkey()
2497 (struct schannel_ssl_backend_data *)connssl->backend; in schannel_pkp_pin_peer_pubkey()
2517 Curl_pSecFn->QueryContextAttributes(&backend->ctxt->ctxt_handle, in schannel_pkp_pin_peer_pubkey()
2523 failf(data, "schannel: Failed to read remote certificate context: %s", in schannel_pkp_pin_peer_pubkey()
2529 if(!(((pCertContextServer->dwCertEncodingType & X509_ASN_ENCODING) != 0) && in schannel_pkp_pin_peer_pubkey()
2530 (pCertContextServer->cbCertEncoded > 0))) in schannel_pkp_pin_peer_pubkey()
2533 x509_der = (const char *)pCertContextServer->pbCertEncoded; in schannel_pkp_pin_peer_pubkey()
2534 x509_der_len = pCertContextServer->cbCertEncoded; in schannel_pkp_pin_peer_pubkey()
2540 if(!pubkey->header || pubkey->end <= pubkey->header) { in schannel_pkp_pin_peer_pubkey()
2547 (const unsigned char *)pubkey->header, in schannel_pkp_pin_peer_pubkey()
2548 (size_t)(pubkey->end - pubkey->header)); in schannel_pkp_pin_peer_pubkey()
2631 (struct schannel_ssl_backend_data *)connssl->backend; in schannel_get_internals()
2634 return &backend->ctxt->ctxt_handle; in schannel_get_internals()
2641 struct Curl_multi *multi = data->multi; in Curl_schannel_get_cached_cert_store()
2642 const struct curl_blob *ca_info_blob = conn_config->ca_info_blob; in Curl_schannel_get_cached_cert_store()
2644 const struct ssl_general_config *cfg = &data->set.general_ssl; in Curl_schannel_get_cached_cert_store()
2656 share = Curl_hash_pick(&multi->proto_hash, in Curl_schannel_get_cached_cert_store()
2658 sizeof(MPROTO_SCHANNEL_CERT_SHARE_KEY)-1); in Curl_schannel_get_cached_cert_store()
2659 if(!share || !share->cert_store) { in Curl_schannel_get_cached_cert_store()
2664 if(!cfg->ca_cache_timeout) { in Curl_schannel_get_cached_cert_store()
2671 timeout_ms = cfg->ca_cache_timeout * (timediff_t)1000; in Curl_schannel_get_cached_cert_store()
2674 elapsed_ms = Curl_timediff(now, share->time); in Curl_schannel_get_cached_cert_store()
2681 if(share->CAinfo_blob_size != ca_info_blob->len) { in Curl_schannel_get_cached_cert_store()
2684 schannel_sha256sum((const unsigned char *)ca_info_blob->data, in Curl_schannel_get_cached_cert_store()
2685 ca_info_blob->len, in Curl_schannel_get_cached_cert_store()
2688 if(memcmp(share->CAinfo_blob_digest, info_blob_digest, in Curl_schannel_get_cached_cert_store()
2694 if(!conn_config->CAfile || !share->CAfile || in Curl_schannel_get_cached_cert_store()
2695 strcmp(share->CAfile, conn_config->CAfile)) { in Curl_schannel_get_cached_cert_store()
2700 return share->cert_store; in Curl_schannel_get_cached_cert_store()
2706 DEBUGASSERT(key_len == (sizeof(MPROTO_SCHANNEL_CERT_SHARE_KEY)-1)); in schannel_cert_share_free()
2710 if(share->cert_store) { in schannel_cert_share_free()
2711 CertCloseStore(share->cert_store, 0); in schannel_cert_share_free()
2713 free(share->CAfile); in schannel_cert_share_free()
2722 struct Curl_multi *multi = data->multi; in Curl_schannel_set_cached_cert_store()
2723 const struct curl_blob *ca_info_blob = conn_config->ca_info_blob; in Curl_schannel_set_cached_cert_store()
2734 share = Curl_hash_pick(&multi->proto_hash, in Curl_schannel_set_cached_cert_store()
2736 sizeof(MPROTO_SCHANNEL_CERT_SHARE_KEY)-1); in Curl_schannel_set_cached_cert_store()
2742 if(!Curl_hash_add2(&multi->proto_hash, in Curl_schannel_set_cached_cert_store()
2744 sizeof(MPROTO_SCHANNEL_CERT_SHARE_KEY)-1, in Curl_schannel_set_cached_cert_store()
2752 schannel_sha256sum((const unsigned char *)ca_info_blob->data, in Curl_schannel_set_cached_cert_store()
2753 ca_info_blob->len, in Curl_schannel_set_cached_cert_store()
2754 share->CAinfo_blob_digest, in Curl_schannel_set_cached_cert_store()
2756 CAinfo_blob_size = ca_info_blob->len; in Curl_schannel_set_cached_cert_store()
2759 if(conn_config->CAfile) { in Curl_schannel_set_cached_cert_store()
2760 CAfile = strdup(conn_config->CAfile); in Curl_schannel_set_cached_cert_store()
2768 if(share->cert_store) { in Curl_schannel_set_cached_cert_store()
2769 CertCloseStore(share->cert_store, 0); in Curl_schannel_set_cached_cert_store()
2771 free(share->CAfile); in Curl_schannel_set_cached_cert_store()
2773 share->time = Curl_now(); in Curl_schannel_set_cached_cert_store()
2774 share->cert_store = cert_store; in Curl_schannel_set_cached_cert_store()
2775 share->CAinfo_blob_size = CAinfo_blob_size; in Curl_schannel_set_cached_cert_store()
2776 share->CAfile = CAfile; in Curl_schannel_set_cached_cert_store()
2781 { CURLSSLBACKEND_SCHANNEL, "schannel" }, /* info */