diff options
Diffstat (limited to 'lib/vtls/schannel.c')
-rw-r--r-- | lib/vtls/schannel.c | 137 |
1 files changed, 73 insertions, 64 deletions
diff --git a/lib/vtls/schannel.c b/lib/vtls/schannel.c index 0668f98..2bcf11d 100644 --- a/lib/vtls/schannel.c +++ b/lib/vtls/schannel.c @@ -117,6 +117,10 @@ #define SP_PROT_TLS1_2_CLIENT 0x00000800 #endif +#ifndef SCH_USE_STRONG_CRYPTO +#define SCH_USE_STRONG_CRYPTO 0x00400000 +#endif + #ifndef SECBUFFER_ALERT #define SECBUFFER_ALERT 17 #endif @@ -324,17 +328,22 @@ get_alg_id_by_name(char *name) } static CURLcode -set_ssl_ciphers(SCHANNEL_CRED *schannel_cred, char *ciphers) +set_ssl_ciphers(SCHANNEL_CRED *schannel_cred, char *ciphers, + ALG_ID *algIds) { char *startCur = ciphers; int algCount = 0; - static ALG_ID algIds[45]; /*There are 45 listed in the MS headers*/ - while(startCur && (0 != *startCur) && (algCount < 45)) { + while(startCur && (0 != *startCur) && (algCount < NUMOF_CIPHERS)) { long alg = strtol(startCur, 0, 0); if(!alg) alg = get_alg_id_by_name(startCur); if(alg) algIds[algCount++] = alg; + else if(!strncmp(startCur, "USE_STRONG_CRYPTO", + sizeof("USE_STRONG_CRYPTO") - 1) || + !strncmp(startCur, "SCH_USE_STRONG_CRYPTO", + sizeof("SCH_USE_STRONG_CRYPTO") - 1)) + schannel_cred->dwFlags |= SCH_USE_STRONG_CRYPTO; else return CURLE_SSL_CIPHER; startCur = strchr(startCur, ':'); @@ -358,7 +367,7 @@ get_cert_location(TCHAR *path, DWORD *store_name, TCHAR **store_path, size_t store_name_len; sep = _tcschr(path, TEXT('\\')); - if(sep == NULL) + if(!sep) return CURLE_SSL_CERTPROBLEM; store_name_len = sep - path; @@ -388,7 +397,7 @@ get_cert_location(TCHAR *path, DWORD *store_name, TCHAR **store_path, store_path_start = sep + 1; sep = _tcschr(store_path_start, TEXT('\\')); - if(sep == NULL) + if(!sep) return CURLE_SSL_CERTPROBLEM; *thumbprint = sep + 1; @@ -398,7 +407,7 @@ get_cert_location(TCHAR *path, DWORD *store_name, TCHAR **store_path, *sep = TEXT('\0'); *store_path = _tcsdup(store_path_start); *sep = TEXT('\\'); - if(*store_path == NULL) + if(!*store_path) return CURLE_OUT_OF_MEMORY; return CURLE_OK; @@ -428,12 +437,7 @@ schannel_connect_step1(struct Curl_easy *data, struct connectdata *conn, #endif TCHAR *host_name; CURLcode result; -#ifndef CURL_DISABLE_PROXY - char * const hostname = SSL_IS_PROXY() ? conn->http_proxy.host.name : - conn->host.name; -#else - char * const hostname = conn->host.name; -#endif + char * const hostname = SSL_HOST_NAME(); DEBUGF(infof(data, "schannel: SSL/TLS connection with %s port %hu (step 1/3)\n", @@ -469,7 +473,7 @@ schannel_connect_step1(struct Curl_easy *data, struct connectdata *conn, #endif #else #ifdef HAS_MANUAL_VERIFY_API - if(SSL_CONN_CONFIG(CAfile)) { + if(SSL_CONN_CONFIG(CAfile) || SSL_CONN_CONFIG(ca_info_blob)) { if(curlx_verify_windows_version(6, 1, PLATFORM_WINNT, VERSION_GREATER_THAN_EQUAL)) { BACKEND->use_manual_cred_validation = true; @@ -483,7 +487,7 @@ schannel_connect_step1(struct Curl_easy *data, struct connectdata *conn, else BACKEND->use_manual_cred_validation = false; #else - if(SSL_CONN_CONFIG(CAfile)) { + if(SSL_CONN_CONFIG(CAfile) || SSL_CONN_CONFIG(ca_info_blob)) { failf(data, "schannel: CA cert support not built in"); return CURLE_NOT_BUILT_IN; } @@ -496,6 +500,7 @@ schannel_connect_step1(struct Curl_easy *data, struct connectdata *conn, if(SSL_SET_OPTION(primary.sessionid)) { Curl_ssl_sessionid_lock(data); if(!Curl_ssl_getsessionid(data, conn, + SSL_IS_PROXY() ? TRUE : FALSE, (void **)&old_cred, NULL, sockindex)) { BACKEND->cred = old_cred; DEBUGF(infof(data, "schannel: re-using existing credential handle\n")); @@ -522,14 +527,14 @@ schannel_connect_step1(struct Curl_easy *data, struct connectdata *conn, #endif schannel_cred.dwFlags = SCH_CRED_AUTO_CRED_VALIDATION; - if(data->set.ssl.no_revoke) { + if(SSL_SET_OPTION(no_revoke)) { schannel_cred.dwFlags |= SCH_CRED_IGNORE_NO_REVOCATION_CHECK | SCH_CRED_IGNORE_REVOCATION_OFFLINE; DEBUGF(infof(data, "schannel: disabled server certificate revocation " "checks\n")); } - else if(data->set.ssl.revoke_best_effort) { + else if(SSL_SET_OPTION(revoke_best_effort)) { schannel_cred.dwFlags |= SCH_CRED_IGNORE_NO_REVOCATION_CHECK | SCH_CRED_IGNORE_REVOCATION_OFFLINE | SCH_CRED_REVOCATION_CHECK_CHAIN; @@ -557,6 +562,14 @@ schannel_connect_step1(struct Curl_easy *data, struct connectdata *conn, "names in server certificates.\n")); } + if(!SSL_SET_OPTION(auto_client_cert)) { + schannel_cred.dwFlags &= ~SCH_CRED_USE_DEFAULT_CREDS; + schannel_cred.dwFlags |= SCH_CRED_NO_DEFAULT_CREDS; + infof(data, "schannel: disabled automatic use of client certificate\n"); + } + else + infof(data, "schannel: enabled automatic use of client certificate\n"); + switch(conn->ssl_config.version) { case CURL_SSLVERSION_DEFAULT: case CURL_SSLVERSION_TLSv1: @@ -571,18 +584,17 @@ schannel_connect_step1(struct Curl_easy *data, struct connectdata *conn, break; } case CURL_SSLVERSION_SSLv3: - schannel_cred.grbitEnabledProtocols = SP_PROT_SSL3_CLIENT; - break; case CURL_SSLVERSION_SSLv2: - schannel_cred.grbitEnabledProtocols = SP_PROT_SSL2_CLIENT; - break; + failf(data, "SSL versions not supported"); + return CURLE_NOT_BUILT_IN; default: failf(data, "Unrecognized parameter passed via CURLOPT_SSLVERSION"); return CURLE_SSL_CONNECT_ERROR; } if(SSL_CONN_CONFIG(cipher_list)) { - result = set_ssl_ciphers(&schannel_cred, SSL_CONN_CONFIG(cipher_list)); + result = set_ssl_ciphers(&schannel_cred, SSL_CONN_CONFIG(cipher_list), + BACKEND->algIds); if(CURLE_OK != result) { failf(data, "Unable to set ciphers to passed via SSL_CONN_CONFIG"); return result; @@ -699,7 +711,7 @@ schannel_connect_step1(struct Curl_easy *data, struct connectdata *conn, } if(!blob) free(certdata); - if(cert_store == NULL) { + if(!cert_store) { DWORD errorcode = GetLastError(); if(errorcode == ERROR_INVALID_PASSWORD) failf(data, "schannel: Failed to import cert file %s, " @@ -716,7 +728,7 @@ schannel_connect_step1(struct Curl_easy *data, struct connectdata *conn, cert_store, X509_ASN_ENCODING | PKCS_7_ASN_ENCODING, 0, CERT_FIND_ANY, NULL, NULL); - if(client_certs[0] == NULL) { + if(!client_certs[0]) { failf(data, "schannel: Failed to get certificate from file %s" ", last error is 0x%x", cert_showfilename_error, GetLastError()); @@ -860,11 +872,11 @@ schannel_connect_step1(struct Curl_easy *data, struct connectdata *conn, list_start_index = cur; -#ifdef USE_NGHTTP2 - if(data->set.httpversion >= CURL_HTTP_VERSION_2) { - memcpy(&alpn_buffer[cur], NGHTTP2_PROTO_ALPN, NGHTTP2_PROTO_ALPN_LEN); - cur += NGHTTP2_PROTO_ALPN_LEN; - infof(data, "schannel: ALPN, offering %s\n", NGHTTP2_PROTO_VERSION_ID); +#ifdef USE_HTTP2 + if(data->state.httpwant >= CURL_HTTP_VERSION_2) { + memcpy(&alpn_buffer[cur], ALPN_H2, ALPN_H2_LENGTH); + cur += ALPN_H2_LENGTH; + infof(data, "schannel: ALPN, offering %s\n", ALPN_H2); } #endif @@ -892,11 +904,15 @@ schannel_connect_step1(struct Curl_easy *data, struct connectdata *conn, InitSecBuffer(&outbuf, SECBUFFER_EMPTY, NULL, 0); InitSecBufferDesc(&outbuf_desc, &outbuf, 1); - /* setup request flags */ + /* security request flags */ BACKEND->req_flags = ISC_REQ_SEQUENCE_DETECT | ISC_REQ_REPLAY_DETECT | ISC_REQ_CONFIDENTIALITY | ISC_REQ_ALLOCATE_MEMORY | ISC_REQ_STREAM; + if(!SSL_SET_OPTION(auto_client_cert)) { + BACKEND->req_flags |= ISC_REQ_USE_SUPPLIED_CREDS; + } + /* allocate memory for the security context handle */ BACKEND->ctxt = (struct Curl_schannel_ctxt *) calloc(1, sizeof(struct Curl_schannel_ctxt)); @@ -996,12 +1012,7 @@ schannel_connect_step2(struct Curl_easy *data, struct connectdata *conn, SECURITY_STATUS sspi_status = SEC_E_OK; CURLcode result; bool doread; -#ifndef CURL_DISABLE_PROXY - char * const hostname = SSL_IS_PROXY() ? conn->http_proxy.host.name : - conn->host.name; -#else - char * const hostname = conn->host.name; -#endif + char * const hostname = SSL_HOST_NAME(); const char *pubkey_ptr; doread = (connssl->connecting_state != ssl_connect_2_writing) ? TRUE : FALSE; @@ -1014,23 +1025,23 @@ schannel_connect_step2(struct Curl_easy *data, struct connectdata *conn, return CURLE_SSL_CONNECT_ERROR; /* buffer to store previously received and decrypted data */ - if(BACKEND->decdata_buffer == NULL) { + if(!BACKEND->decdata_buffer) { BACKEND->decdata_offset = 0; BACKEND->decdata_length = CURL_SCHANNEL_BUFFER_INIT_SIZE; BACKEND->decdata_buffer = malloc(BACKEND->decdata_length); - if(BACKEND->decdata_buffer == NULL) { + if(!BACKEND->decdata_buffer) { failf(data, "schannel: unable to allocate memory"); return CURLE_OUT_OF_MEMORY; } } /* buffer to store previously received and encrypted data */ - if(BACKEND->encdata_buffer == NULL) { + if(!BACKEND->encdata_buffer) { BACKEND->encdata_is_incomplete = false; BACKEND->encdata_offset = 0; BACKEND->encdata_length = CURL_SCHANNEL_BUFFER_INIT_SIZE; BACKEND->encdata_buffer = malloc(BACKEND->encdata_length); - if(BACKEND->encdata_buffer == NULL) { + if(!BACKEND->encdata_buffer) { failf(data, "schannel: unable to allocate memory"); return CURLE_OUT_OF_MEMORY; } @@ -1045,7 +1056,7 @@ schannel_connect_step2(struct Curl_easy *data, struct connectdata *conn, reallocated_buffer = realloc(BACKEND->encdata_buffer, reallocated_length); - if(reallocated_buffer == NULL) { + if(!reallocated_buffer) { failf(data, "schannel: unable to re-allocate memory"); return CURLE_OUT_OF_MEMORY; } @@ -1100,7 +1111,7 @@ schannel_connect_step2(struct Curl_easy *data, struct connectdata *conn, InitSecBuffer(&outbuf[2], SECBUFFER_EMPTY, NULL, 0); InitSecBufferDesc(&outbuf_desc, outbuf, 3); - if(inbuf[0].pvBuffer == NULL) { + if(!inbuf[0].pvBuffer) { failf(data, "schannel: unable to allocate memory"); return CURLE_OUT_OF_MEMORY; } @@ -1250,9 +1261,7 @@ schannel_connect_step2(struct Curl_easy *data, struct connectdata *conn, DEBUGF(infof(data, "schannel: SSL/TLS handshake complete\n")); } - pubkey_ptr = SSL_IS_PROXY() ? - data->set.str[STRING_SSL_PINNEDPUBLICKEY_PROXY] : - data->set.str[STRING_SSL_PINNEDPUBLICKEY_ORIG]; + pubkey_ptr = SSL_PINNED_PUB_KEY(); if(pubkey_ptr) { result = pkp_pin_peer_pubkey(data, conn, sockindex, pubkey_ptr); if(result) { @@ -1337,9 +1346,9 @@ schannel_connect_step3(struct Curl_easy *data, struct connectdata *conn, struct ssl_connect_data *connssl = &conn->ssl[sockindex]; SECURITY_STATUS sspi_status = SEC_E_OK; CERT_CONTEXT *ccert_context = NULL; + bool isproxy = SSL_IS_PROXY(); #ifdef DEBUGBUILD - const char * const hostname = SSL_IS_PROXY() ? conn->http_proxy.host.name : - conn->host.name; + const char * const hostname = SSL_HOST_NAME(); #endif #ifdef HAS_ALPN SecPkgContext_ApplicationProtocol alpn_result; @@ -1387,10 +1396,9 @@ schannel_connect_step3(struct Curl_easy *data, struct connectdata *conn, infof(data, "schannel: ALPN, server accepted to use %.*s\n", alpn_result.ProtocolIdSize, alpn_result.ProtocolId); -#ifdef USE_NGHTTP2 - if(alpn_result.ProtocolIdSize == NGHTTP2_PROTO_VERSION_ID_LEN && - !memcmp(NGHTTP2_PROTO_VERSION_ID, alpn_result.ProtocolId, - NGHTTP2_PROTO_VERSION_ID_LEN)) { +#ifdef USE_HTTP2 + if(alpn_result.ProtocolIdSize == ALPN_H2_LENGTH && + !memcmp(ALPN_H2, alpn_result.ProtocolId, ALPN_H2_LENGTH)) { conn->negnpn = CURL_HTTP_VERSION_2; } else @@ -1414,8 +1422,8 @@ schannel_connect_step3(struct Curl_easy *data, struct connectdata *conn, struct Curl_schannel_cred *old_cred = NULL; Curl_ssl_sessionid_lock(data); - incache = !(Curl_ssl_getsessionid(data, conn, (void **)&old_cred, NULL, - sockindex)); + incache = !(Curl_ssl_getsessionid(data, conn, isproxy, (void **)&old_cred, + NULL, sockindex)); if(incache) { if(old_cred != BACKEND->cred) { DEBUGF(infof(data, @@ -1426,7 +1434,7 @@ schannel_connect_step3(struct Curl_easy *data, struct connectdata *conn, } } if(!incache) { - result = Curl_ssl_addsessionid(data, conn, (void *)BACKEND->cred, + result = Curl_ssl_addsessionid(data, conn, isproxy, BACKEND->cred, sizeof(struct Curl_schannel_cred), sockindex); if(result) { @@ -1451,7 +1459,7 @@ schannel_connect_step3(struct Curl_easy *data, struct connectdata *conn, SECPKG_ATTR_REMOTE_CERT_CONTEXT, &ccert_context); - if((sspi_status != SEC_E_OK) || (ccert_context == NULL)) { + if((sspi_status != SEC_E_OK) || !ccert_context) { failf(data, "schannel: failed to retrieve remote cert context"); return CURLE_PEER_FAILED_VERIFICATION; } @@ -1803,7 +1811,7 @@ schannel_recv(struct Curl_easy *data, int sockindex, } reallocated_buffer = realloc(BACKEND->encdata_buffer, reallocated_length); - if(reallocated_buffer == NULL) { + if(!reallocated_buffer) { *err = CURLE_OUT_OF_MEMORY; failf(data, "schannel: unable to re-allocate memory"); goto cleanup; @@ -1892,7 +1900,7 @@ schannel_recv(struct Curl_easy *data, int sockindex, } reallocated_buffer = realloc(BACKEND->decdata_buffer, reallocated_length); - if(reallocated_buffer == NULL) { + if(!reallocated_buffer) { *err = CURLE_OUT_OF_MEMORY; failf(data, "schannel: unable to re-allocate memory"); goto cleanup; @@ -2126,12 +2134,7 @@ static int schannel_shutdown(struct Curl_easy *data, struct connectdata *conn, * Shutting Down an Schannel Connection */ struct ssl_connect_data *connssl = &conn->ssl[sockindex]; -#ifndef CURL_DISABLE_PROXY - char * const hostname = SSL_IS_PROXY() ? conn->http_proxy.host.name : - conn->host.name; -#else - char * const hostname = conn->host.name; -#endif + char * const hostname = SSL_HOST_NAME(); DEBUGASSERT(data); @@ -2294,7 +2297,7 @@ static CURLcode pkp_pin_peer_pubkey(struct Curl_easy *data, SECPKG_ATTR_REMOTE_CERT_CONTEXT, &pCertContextServer); - if((sspi_status != SEC_E_OK) || (pCertContextServer == NULL)) { + if((sspi_status != SEC_E_OK) || !pCertContextServer) { char buffer[STRERROR_LEN]; failf(data, "schannel: Failed to read remote certificate context: %s", Curl_sspi_strerror(sspi_status, buffer, sizeof(buffer))); @@ -2404,6 +2407,9 @@ const struct Curl_ssl Curl_ssl_schannel = { { CURLSSLBACKEND_SCHANNEL, "schannel" }, /* info */ SSLSUPP_CERTINFO | +#ifdef HAS_MANUAL_VERIFY_API + SSLSUPP_CAINFO_BLOB | +#endif SSLSUPP_PINNEDPUBKEY, sizeof(struct ssl_backend_data), @@ -2418,6 +2424,7 @@ const struct Curl_ssl Curl_ssl_schannel = { Curl_none_cert_status_request, /* cert_status_request */ schannel_connect, /* connect */ schannel_connect_nonblocking, /* connect_nonblocking */ + Curl_ssl_getsock, /* getsock */ schannel_get_internals, /* get_internals */ schannel_close, /* close_one */ Curl_none_close_all, /* close_all */ @@ -2426,7 +2433,9 @@ const struct Curl_ssl Curl_ssl_schannel = { Curl_none_set_engine_default, /* set_engine_default */ Curl_none_engines_list, /* engines_list */ Curl_none_false_start, /* false_start */ - schannel_sha256sum /* sha256sum */ + schannel_sha256sum, /* sha256sum */ + NULL, /* associate_connection */ + NULL /* disassociate_connection */ }; #endif /* USE_SCHANNEL */ |