From 95538ee3e112abd86c963c246d994a533d2b366d Mon Sep 17 00:00:00 2001 From: dartraiden Date: Wed, 22 Mar 2023 14:58:20 +0300 Subject: libcurl: update to 8.0.1 --- libs/libcurl/src/vtls/nss.c | 32 +-------- libs/libcurl/src/vtls/openssl.c | 59 +--------------- libs/libcurl/src/vtls/schannel.c | 141 ++++++++++++++++++++------------------ libs/libcurl/src/vtls/sectransp.c | 107 +++++++++++------------------ libs/libcurl/src/vtls/vtls.c | 48 ++++++++++--- libs/libcurl/src/vtls/wolfssl.c | 39 +++++++++-- libs/libcurl/src/vtls/x509asn1.c | 4 +- 7 files changed, 189 insertions(+), 241 deletions(-) (limited to 'libs/libcurl/src/vtls') diff --git a/libs/libcurl/src/vtls/nss.c b/libs/libcurl/src/vtls/nss.c index a327255a7e..2bbf96ab96 100644 --- a/libs/libcurl/src/vtls/nss.c +++ b/libs/libcurl/src/vtls/nss.c @@ -1536,36 +1536,6 @@ static void nss_cleanup(void) initialized = 0; } -/* - * This function uses SSL_peek to determine connection status. - * - * Return codes: - * 1 means the connection is still in place - * 0 means the connection has been closed - * -1 means the connection status is unknown - */ -static int nss_check_cxn(struct Curl_cfilter *cf, struct Curl_easy *data) -{ - struct ssl_connect_data *connssl = cf->ctx; - struct ssl_backend_data *backend = connssl->backend; - int rc; - char buf; - - (void)data; - DEBUGASSERT(backend); - - rc = - PR_Recv(backend->handle, (void *)&buf, 1, PR_MSG_PEEK, - PR_SecondsToInterval(1)); - if(rc > 0) - return 1; /* connection still in place */ - - if(rc == 0) - return 0; /* connection has been closed */ - - return -1; /* connection status unknown */ -} - static void close_one(struct ssl_connect_data *connssl) { /* before the cleanup, check whether we are using a client certificate */ @@ -2524,7 +2494,7 @@ const struct Curl_ssl Curl_ssl_nss = { nss_init, /* init */ nss_cleanup, /* cleanup */ nss_version, /* version */ - nss_check_cxn, /* check_cxn */ + Curl_none_check_cxn, /* check_cxn */ /* NSS has no shutdown function provided and thus always fail */ Curl_none_shutdown, /* shutdown */ nss_data_pending, /* data_pending */ diff --git a/libs/libcurl/src/vtls/openssl.c b/libs/libcurl/src/vtls/openssl.c index 9d100a6d0d..c9cc52a184 100644 --- a/libs/libcurl/src/vtls/openssl.c +++ b/libs/libcurl/src/vtls/openssl.c @@ -1780,63 +1780,6 @@ static void ossl_cleanup(void) Curl_tls_keylog_close(); } -/* - * This function is used to determine connection status. - * - * Return codes: - * 1 means the connection is still in place - * 0 means the connection has been closed - * -1 means the connection status is unknown - */ -static int ossl_check_cxn(struct Curl_cfilter *cf, struct Curl_easy *data) -{ - /* SSL_peek takes data out of the raw recv buffer without peeking so we use - recv MSG_PEEK instead. Bug #795 */ -#ifdef MSG_PEEK - char buf; - ssize_t nread; - curl_socket_t sock = Curl_conn_cf_get_socket(cf, data); - if(sock == CURL_SOCKET_BAD) - return 0; /* no socket, consider closed */ - nread = recv((RECV_TYPE_ARG1)sock, - (RECV_TYPE_ARG2)&buf, (RECV_TYPE_ARG3)1, - (RECV_TYPE_ARG4)MSG_PEEK); - if(nread == 0) - return 0; /* connection has been closed */ - if(nread == 1) - return 1; /* connection still in place */ - else if(nread == -1) { - int err = SOCKERRNO; - if(err == EINPROGRESS || -#if defined(EAGAIN) && (EAGAIN != EWOULDBLOCK) - err == EAGAIN || -#endif - err == EWOULDBLOCK) - return 1; /* connection still in place */ - if(err == ECONNRESET || -#ifdef ECONNABORTED - err == ECONNABORTED || -#endif -#ifdef ENETDOWN - err == ENETDOWN || -#endif -#ifdef ENETRESET - err == ENETRESET || -#endif -#ifdef ESHUTDOWN - err == ESHUTDOWN || -#endif -#ifdef ETIMEDOUT - err == ETIMEDOUT || -#endif - err == ENOTCONN) - return 0; /* connection has been closed */ - } -#endif - (void)data; - return -1; /* connection status unknown */ -} - /* Selects an OpenSSL crypto engine */ static CURLcode ossl_set_engine(struct Curl_easy *data, const char *engine) @@ -4820,7 +4763,7 @@ const struct Curl_ssl Curl_ssl_openssl = { ossl_init, /* init */ ossl_cleanup, /* cleanup */ ossl_version, /* version */ - ossl_check_cxn, /* check_cxn */ + Curl_none_check_cxn, /* check_cxn */ ossl_shutdown, /* shutdown */ ossl_data_pending, /* data_pending */ ossl_random, /* random */ diff --git a/libs/libcurl/src/vtls/schannel.c b/libs/libcurl/src/vtls/schannel.c index 63e5c7670d..63f9b07690 100644 --- a/libs/libcurl/src/vtls/schannel.c +++ b/libs/libcurl/src/vtls/schannel.c @@ -264,128 +264,133 @@ set_ssl_version_min_max(DWORD *enabled_protocols, /* longest is 26, buffer is slightly bigger */ #define LONGEST_ALG_ID 32 -#define CIPHEROPTION(X) \ - if(strcmp(#X, tmp) == 0) \ - return X +#define CIPHEROPTION(x) {#x, x} -static int -get_alg_id_by_name(char *name) -{ - char tmp[LONGEST_ALG_ID] = { 0 }; - char *nameEnd = strchr(name, ':'); - size_t n = nameEnd ? (size_t)(nameEnd - name) : strlen(name); +struct algo { + const char *name; + int id; +}; - /* reject too-long alg names */ - if(n > (LONGEST_ALG_ID - 1)) - return 0; - - strncpy(tmp, name, n); - tmp[n] = 0; - CIPHEROPTION(CALG_MD2); - CIPHEROPTION(CALG_MD4); - CIPHEROPTION(CALG_MD5); - CIPHEROPTION(CALG_SHA); - CIPHEROPTION(CALG_SHA1); - CIPHEROPTION(CALG_MAC); - CIPHEROPTION(CALG_RSA_SIGN); - CIPHEROPTION(CALG_DSS_SIGN); +static const struct algo algs[]= { + CIPHEROPTION(CALG_MD2), + CIPHEROPTION(CALG_MD4), + CIPHEROPTION(CALG_MD5), + CIPHEROPTION(CALG_SHA), + CIPHEROPTION(CALG_SHA1), + CIPHEROPTION(CALG_MAC), + CIPHEROPTION(CALG_RSA_SIGN), + CIPHEROPTION(CALG_DSS_SIGN), /* ifdefs for the options that are defined conditionally in wincrypt.h */ #ifdef CALG_NO_SIGN - CIPHEROPTION(CALG_NO_SIGN); + CIPHEROPTION(CALG_NO_SIGN), #endif - CIPHEROPTION(CALG_RSA_KEYX); - CIPHEROPTION(CALG_DES); + CIPHEROPTION(CALG_RSA_KEYX), + CIPHEROPTION(CALG_DES), #ifdef CALG_3DES_112 - CIPHEROPTION(CALG_3DES_112); + CIPHEROPTION(CALG_3DES_112), #endif - CIPHEROPTION(CALG_3DES); - CIPHEROPTION(CALG_DESX); - CIPHEROPTION(CALG_RC2); - CIPHEROPTION(CALG_RC4); - CIPHEROPTION(CALG_SEAL); + CIPHEROPTION(CALG_3DES), + CIPHEROPTION(CALG_DESX), + CIPHEROPTION(CALG_RC2), + CIPHEROPTION(CALG_RC4), + CIPHEROPTION(CALG_SEAL), #ifdef CALG_DH_SF - CIPHEROPTION(CALG_DH_SF); + CIPHEROPTION(CALG_DH_SF), #endif - CIPHEROPTION(CALG_DH_EPHEM); + CIPHEROPTION(CALG_DH_EPHEM), #ifdef CALG_AGREEDKEY_ANY - CIPHEROPTION(CALG_AGREEDKEY_ANY); + CIPHEROPTION(CALG_AGREEDKEY_ANY), #endif #ifdef CALG_HUGHES_MD5 - CIPHEROPTION(CALG_HUGHES_MD5); + CIPHEROPTION(CALG_HUGHES_MD5), #endif - CIPHEROPTION(CALG_SKIPJACK); + CIPHEROPTION(CALG_SKIPJACK), #ifdef CALG_TEK - CIPHEROPTION(CALG_TEK); + CIPHEROPTION(CALG_TEK), #endif - CIPHEROPTION(CALG_CYLINK_MEK); - CIPHEROPTION(CALG_SSL3_SHAMD5); + CIPHEROPTION(CALG_CYLINK_MEK), + CIPHEROPTION(CALG_SSL3_SHAMD5), #ifdef CALG_SSL3_MASTER - CIPHEROPTION(CALG_SSL3_MASTER); + CIPHEROPTION(CALG_SSL3_MASTER), #endif #ifdef CALG_SCHANNEL_MASTER_HASH - CIPHEROPTION(CALG_SCHANNEL_MASTER_HASH); + CIPHEROPTION(CALG_SCHANNEL_MASTER_HASH), #endif #ifdef CALG_SCHANNEL_MAC_KEY - CIPHEROPTION(CALG_SCHANNEL_MAC_KEY); + CIPHEROPTION(CALG_SCHANNEL_MAC_KEY), #endif #ifdef CALG_SCHANNEL_ENC_KEY - CIPHEROPTION(CALG_SCHANNEL_ENC_KEY); + CIPHEROPTION(CALG_SCHANNEL_ENC_KEY), #endif #ifdef CALG_PCT1_MASTER - CIPHEROPTION(CALG_PCT1_MASTER); + CIPHEROPTION(CALG_PCT1_MASTER), #endif #ifdef CALG_SSL2_MASTER - CIPHEROPTION(CALG_SSL2_MASTER); + CIPHEROPTION(CALG_SSL2_MASTER), #endif #ifdef CALG_TLS1_MASTER - CIPHEROPTION(CALG_TLS1_MASTER); + CIPHEROPTION(CALG_TLS1_MASTER), #endif #ifdef CALG_RC5 - CIPHEROPTION(CALG_RC5); + CIPHEROPTION(CALG_RC5), #endif #ifdef CALG_HMAC - CIPHEROPTION(CALG_HMAC); + CIPHEROPTION(CALG_HMAC), #endif #ifdef CALG_TLS1PRF - CIPHEROPTION(CALG_TLS1PRF); + CIPHEROPTION(CALG_TLS1PRF), #endif #ifdef CALG_HASH_REPLACE_OWF - CIPHEROPTION(CALG_HASH_REPLACE_OWF); + CIPHEROPTION(CALG_HASH_REPLACE_OWF), #endif #ifdef CALG_AES_128 - CIPHEROPTION(CALG_AES_128); + CIPHEROPTION(CALG_AES_128), #endif #ifdef CALG_AES_192 - CIPHEROPTION(CALG_AES_192); + CIPHEROPTION(CALG_AES_192), #endif #ifdef CALG_AES_256 - CIPHEROPTION(CALG_AES_256); + CIPHEROPTION(CALG_AES_256), #endif #ifdef CALG_AES - CIPHEROPTION(CALG_AES); + CIPHEROPTION(CALG_AES), #endif #ifdef CALG_SHA_256 - CIPHEROPTION(CALG_SHA_256); + CIPHEROPTION(CALG_SHA_256), #endif #ifdef CALG_SHA_384 - CIPHEROPTION(CALG_SHA_384); + CIPHEROPTION(CALG_SHA_384), #endif #ifdef CALG_SHA_512 - CIPHEROPTION(CALG_SHA_512); + CIPHEROPTION(CALG_SHA_512), #endif #ifdef CALG_ECDH - CIPHEROPTION(CALG_ECDH); + CIPHEROPTION(CALG_ECDH), #endif #ifdef CALG_ECMQV - CIPHEROPTION(CALG_ECMQV); + CIPHEROPTION(CALG_ECMQV), #endif #ifdef CALG_ECDSA - CIPHEROPTION(CALG_ECDSA); + CIPHEROPTION(CALG_ECDSA), #endif #ifdef CALG_ECDH_EPHEM - CIPHEROPTION(CALG_ECDH_EPHEM); + CIPHEROPTION(CALG_ECDH_EPHEM), #endif - return 0; + {NULL, 0}, +}; + +static int +get_alg_id_by_name(char *name) +{ + char *nameEnd = strchr(name, ':'); + size_t n = nameEnd ? (size_t)(nameEnd - name) : strlen(name); + int i; + + for(i = 0; algs[i].name; i++) { + if((n == strlen(algs[i].name) && !strncmp(algs[i].name, name, n))) + return algs[i].id; + } + return 0; /* not found */ } #define NUM_CIPHERS 47 /* There are 47 options listed above */ @@ -1201,18 +1206,18 @@ schannel_connect_step1(struct Curl_cfilter *cf, struct Curl_easy *data) /* The first four bytes will be an unsigned int indicating number of bytes of data in the rest of the buffer. */ extension_len = (unsigned int *)(void *)(&alpn_buffer[cur]); - cur += sizeof(unsigned int); + cur += (int)sizeof(unsigned int); /* The next four bytes are an indicator that this buffer will contain ALPN data, as opposed to NPN, for example. */ *(unsigned int *)(void *)&alpn_buffer[cur] = SecApplicationProtocolNegotiationExt_ALPN; - cur += sizeof(unsigned int); + cur += (int)sizeof(unsigned int); /* The next two bytes will be an unsigned short indicating the number of bytes used to list the preferred protocols. */ list_len = (unsigned short*)(void *)(&alpn_buffer[cur]); - cur += sizeof(unsigned short); + cur += (int)sizeof(unsigned short); list_start_index = cur; @@ -1225,7 +1230,9 @@ schannel_connect_step1(struct Curl_cfilter *cf, struct Curl_easy *data) cur += proto.len; *list_len = curlx_uitous(cur - list_start_index); - *extension_len = *list_len + sizeof(unsigned int) + sizeof(unsigned short); + *extension_len = *list_len + + (unsigned short)sizeof(unsigned int) + + (unsigned short)sizeof(unsigned short); InitSecBuffer(&inbuf, SECBUFFER_APPLICATION_PROTOCOLS, alpn_buffer, cur); InitSecBufferDesc(&inbuf_desc, &inbuf, 1); diff --git a/libs/libcurl/src/vtls/sectransp.c b/libs/libcurl/src/vtls/sectransp.c index 953b624f2b..81ab9ab061 100644 --- a/libs/libcurl/src/vtls/sectransp.c +++ b/libs/libcurl/src/vtls/sectransp.c @@ -2150,50 +2150,39 @@ static long pem_to_der(const char *in, unsigned char **out, size_t *outlen) return sep_end - in; } +#define MAX_CERTS_SIZE (50*1024*1024) /* arbitrary - to catch mistakes */ + static int read_cert(const char *file, unsigned char **out, size_t *outlen) { int fd; - ssize_t n, len = 0, cap = 512; - unsigned char buf[512], *data; + ssize_t n; + unsigned char buf[512]; + struct dynbuf certs; + + Curl_dyn_init(&certs, MAX_CERTS_SIZE); fd = open(file, 0); if(fd < 0) return -1; - data = malloc(cap); - if(!data) { - close(fd); - return -1; - } - for(;;) { n = read(fd, buf, sizeof(buf)); + if(!n) + break; if(n < 0) { close(fd); - free(data); + Curl_dyn_free(&certs); return -1; } - else if(n == 0) { + if(Curl_dyn_addn(&certs, buf, n)) { close(fd); - break; - } - - if(len + n >= cap) { - cap *= 2; - data = Curl_saferealloc(data, cap); - if(!data) { - close(fd); - return -1; - } + return -1; } - - memcpy(data + len, buf, n); - len += n; } - data[len] = '\0'; + close(fd); - *out = data; - *outlen = len; + *out = Curl_dyn_uptr(&certs); + *outlen = Curl_dyn_len(&certs); return 0; } @@ -2202,16 +2191,18 @@ static int append_cert_to_array(struct Curl_easy *data, const unsigned char *buf, size_t buflen, CFMutableArrayRef array) { - CFDataRef certdata = CFDataCreate(kCFAllocatorDefault, buf, buflen); char *certp; CURLcode result; + SecCertificateRef cacert; + CFDataRef certdata; + + certdata = CFDataCreate(kCFAllocatorDefault, buf, buflen); if(!certdata) { failf(data, "SSL: failed to allocate array for CA certificate"); return CURLE_OUT_OF_MEMORY; } - SecCertificateRef cacert = - SecCertificateCreateWithData(kCFAllocatorDefault, certdata); + cacert = SecCertificateCreateWithData(kCFAllocatorDefault, certdata); CFRelease(certdata); if(!cacert) { failf(data, "SSL: failed to create SecCertificate from CA certificate"); @@ -2425,11 +2416,15 @@ static CURLcode pkp_pin_peer_pubkey(struct Curl_easy *data, do { SecTrustRef trust; - OSStatus ret = SSLCopyPeerTrust(ctx, &trust); + OSStatus ret; + SecKeyRef keyRef; + OSStatus success; + + ret = SSLCopyPeerTrust(ctx, &trust); if(ret != noErr || !trust) break; - SecKeyRef keyRef = SecTrustCopyPublicKey(trust); + keyRef = SecTrustCopyPublicKey(trust); CFRelease(trust); if(!keyRef) break; @@ -2443,8 +2438,8 @@ static CURLcode pkp_pin_peer_pubkey(struct Curl_easy *data, #elif SECTRANSP_PINNEDPUBKEY_V2 - OSStatus success = SecItemExport(keyRef, kSecFormatOpenSSL, 0, NULL, - &publicKeyBits); + success = SecItemExport(keyRef, kSecFormatOpenSSL, 0, NULL, + &publicKeyBits); CFRelease(keyRef); if(success != errSecSuccess || !publicKeyBits) break; @@ -2987,12 +2982,13 @@ static CURLcode sectransp_connect_step3(struct Curl_cfilter *cf, struct Curl_easy *data) { struct ssl_connect_data *connssl = cf->ctx; + CURLcode result; DEBUGF(LOG_CF(data, cf, "connect_step3")); /* There is no step 3! * Well, okay, let's collect server certificates, and if verbose mode is on, * let's print the details of the server certificates. */ - const CURLcode result = collect_server_cert(cf, data); + result = collect_server_cert(cf, data); if(result) return result; @@ -3237,35 +3233,6 @@ static size_t sectransp_version(char *buffer, size_t size) return msnprintf(buffer, size, "SecureTransport"); } -/* - * This function uses SSLGetSessionState to determine connection status. - * - * Return codes: - * 1 means the connection is still in place - * 0 means the connection has been closed - * -1 means the connection status is unknown - */ -static int sectransp_check_cxn(struct Curl_cfilter *cf, - struct Curl_easy *data) -{ - struct ssl_connect_data *connssl = cf->ctx; - struct ssl_backend_data *backend = connssl->backend; - OSStatus err; - SSLSessionState state; - - (void)data; - DEBUGASSERT(backend); - - if(backend->ssl_ctx) { - DEBUGF(LOG_CF(data, cf, "check connection")); - err = SSLGetSessionState(backend->ssl_ctx, &state); - if(err == noErr) - return state == kSSLConnected || state == kSSLHandshake; - return -1; - } - return 0; -} - static bool sectransp_data_pending(struct Curl_cfilter *cf, const struct Curl_easy *data) { @@ -3410,13 +3377,15 @@ static ssize_t sectransp_recv(struct Curl_cfilter *cf, DEBUGASSERT(backend); again: + *curlcode = CURLE_OK; err = SSLRead(backend->ssl_ctx, buf, buffersize, &processed); if(err != noErr) { switch(err) { case errSSLWouldBlock: /* return how much we read (if anything) */ - if(processed) + if(processed) { return (ssize_t)processed; + } *curlcode = CURLE_AGAIN; return -1L; break; @@ -3428,7 +3397,7 @@ static ssize_t sectransp_recv(struct Curl_cfilter *cf, case errSSLClosedGraceful: case errSSLClosedNoNotify: *curlcode = CURLE_OK; - return -1L; + return 0; break; /* The below is errSSLPeerAuthCompleted; it's not defined in @@ -3439,8 +3408,10 @@ static ssize_t sectransp_recv(struct Curl_cfilter *cf, CURLcode result = verify_cert(cf, data, conn_config->CAfile, conn_config->ca_info_blob, backend->ssl_ctx); - if(result) - return result; + if(result) { + *curlcode = result; + return -1; + } } goto again; default: @@ -3477,7 +3448,7 @@ const struct Curl_ssl Curl_ssl_sectransp = { Curl_none_init, /* init */ Curl_none_cleanup, /* cleanup */ sectransp_version, /* version */ - sectransp_check_cxn, /* check_cxn */ + Curl_none_check_cxn, /* check_cxn */ sectransp_shutdown, /* shutdown */ sectransp_data_pending, /* data_pending */ sectransp_random, /* random */ diff --git a/libs/libcurl/src/vtls/vtls.c b/libs/libcurl/src/vtls/vtls.c index fd1d7fc075..1f618d9aac 100644 --- a/libs/libcurl/src/vtls/vtls.c +++ b/libs/libcurl/src/vtls/vtls.c @@ -1604,16 +1604,11 @@ static CURLcode ssl_cf_cntrl(struct Curl_cfilter *cf, struct Curl_easy *data, int event, int arg1, void *arg2) { - struct ssl_connect_data *connssl = cf->ctx; struct cf_call_data save; (void)arg1; (void)arg2; switch(event) { - case CF_CTRL_CONN_REPORT_STATS: - if(cf->sockindex == FIRSTSOCKET && !Curl_ssl_cf_is_proxy(cf)) - Curl_pgrsTimeWas(data, TIMER_APPCONNECT, connssl->handshake_done); - break; case CF_CTRL_DATA_ATTACH: if(Curl_ssl->attach_data) { CF_DATA_SAVE(save, cf, data); @@ -1634,10 +1629,32 @@ static CURLcode ssl_cf_cntrl(struct Curl_cfilter *cf, return CURLE_OK; } -static bool cf_ssl_is_alive(struct Curl_cfilter *cf, struct Curl_easy *data) +static CURLcode ssl_cf_query(struct Curl_cfilter *cf, + struct Curl_easy *data, + int query, int *pres1, void *pres2) +{ + struct ssl_connect_data *connssl = cf->ctx; + + switch(query) { + case CF_QUERY_TIMER_APPCONNECT: { + struct curltime *when = pres2; + if(cf->connected && !Curl_ssl_cf_is_proxy(cf)) + *when = connssl->handshake_done; + return CURLE_OK; + } + default: + break; + } + return cf->next? + cf->next->cft->query(cf->next, data, query, pres1, pres2) : + CURLE_UNKNOWN_OPTION; +} + +static bool cf_ssl_is_alive(struct Curl_cfilter *cf, struct Curl_easy *data, + bool *input_pending) { struct cf_call_data save; - bool result; + int result; /* * This function tries to determine connection status. * @@ -1647,9 +1664,20 @@ static bool cf_ssl_is_alive(struct Curl_cfilter *cf, struct Curl_easy *data) * -1 means the connection status is unknown */ CF_DATA_SAVE(save, cf, data); - result = Curl_ssl->check_cxn(cf, data) != 0; + result = Curl_ssl->check_cxn(cf, data); CF_DATA_RESTORE(cf, save); - return result; + if(result > 0) { + *input_pending = TRUE; + return TRUE; + } + if(result == 0) { + *input_pending = FALSE; + return FALSE; + } + /* ssl backend does not know */ + return cf->next? + cf->next->cft->is_alive(cf->next, data, input_pending) : + FALSE; /* pessimistic in absence of data */ } struct Curl_cftype Curl_cft_ssl = { @@ -1667,7 +1695,7 @@ struct Curl_cftype Curl_cft_ssl = { ssl_cf_cntrl, cf_ssl_is_alive, Curl_cf_def_conn_keep_alive, - Curl_cf_def_query, + ssl_cf_query, }; struct Curl_cftype Curl_cft_ssl_proxy = { diff --git a/libs/libcurl/src/vtls/wolfssl.c b/libs/libcurl/src/vtls/wolfssl.c index b3e6cf4d19..8918e3554a 100644 --- a/libs/libcurl/src/vtls/wolfssl.c +++ b/libs/libcurl/src/vtls/wolfssl.c @@ -94,6 +94,7 @@ struct ssl_backend_data { SSL_CTX* ctx; SSL* handle; + CURLcode io_result; /* result of last BIO cfilter operation */ }; #ifdef OPENSSL_EXTRA @@ -279,12 +280,16 @@ static long bio_cf_ctrl(WOLFSSL_BIO *bio, int cmd, long num, void *ptr) static int bio_cf_out_write(WOLFSSL_BIO *bio, const char *buf, int blen) { struct Curl_cfilter *cf = wolfSSL_BIO_get_data(bio); + struct ssl_connect_data *connssl = cf->ctx; struct Curl_easy *data = CF_DATA_CURRENT(cf); ssize_t nwritten; CURLcode result = CURLE_OK; DEBUGASSERT(data); nwritten = Curl_conn_cf_send(cf->next, data, buf, blen, &result); + connssl->backend->io_result = result; + DEBUGF(LOG_CF(data, cf, "bio_write(len=%d) -> %zd, %d", + blen, nwritten, result)); wolfSSL_BIO_clear_retry_flags(bio); if(nwritten < 0 && CURLE_AGAIN == result) BIO_set_retry_read(bio); @@ -294,6 +299,7 @@ static int bio_cf_out_write(WOLFSSL_BIO *bio, const char *buf, int blen) static int bio_cf_in_read(WOLFSSL_BIO *bio, char *buf, int blen) { struct Curl_cfilter *cf = wolfSSL_BIO_get_data(bio); + struct ssl_connect_data *connssl = cf->ctx; struct Curl_easy *data = CF_DATA_CURRENT(cf); ssize_t nread; CURLcode result = CURLE_OK; @@ -304,6 +310,9 @@ static int bio_cf_in_read(WOLFSSL_BIO *bio, char *buf, int blen) return 0; nread = Curl_conn_cf_recv(cf->next, data, buf, blen, &result); + connssl->backend->io_result = result; + DEBUGF(LOG_CF(data, cf, "bio_read(len=%d) -> %zd, %d", + blen, nread, result)); wolfSSL_BIO_clear_retry_flags(bio); if(nread < 0 && CURLE_AGAIN == result) BIO_set_retry_read(bio); @@ -789,6 +798,9 @@ wolfssl_connect_step2(struct Curl_cfilter *cf, struct Curl_easy *data) } } #endif + else if(backend->io_result == CURLE_AGAIN) { + return CURLE_OK; + } else { failf(data, "SSL_connect failed with error %d: %s", detail, ERR_error_string(detail, error_buffer)); @@ -948,7 +960,6 @@ static ssize_t wolfssl_send(struct Curl_cfilter *cf, ERR_clear_error(); rc = SSL_write(backend->handle, mem, memlen); - if(rc <= 0) { int err = SSL_get_error(backend->handle, rc); @@ -956,9 +967,17 @@ static ssize_t wolfssl_send(struct Curl_cfilter *cf, case SSL_ERROR_WANT_READ: case SSL_ERROR_WANT_WRITE: /* there's data pending, re-invoke SSL_write() */ + DEBUGF(LOG_CF(data, cf, "wolfssl_send(len=%zu) -> AGAIN", len)); *curlcode = CURLE_AGAIN; return -1; default: + if(backend->io_result == CURLE_AGAIN) { + DEBUGF(LOG_CF(data, cf, "wolfssl_send(len=%zu) -> AGAIN", len)); + *curlcode = CURLE_AGAIN; + return -1; + } + DEBUGF(LOG_CF(data, cf, "wolfssl_send(len=%zu) -> %d, %d", + len, rc, err)); failf(data, "SSL write: %s, errno %d", ERR_error_string(err, error_buffer), SOCKERRNO); @@ -966,6 +985,7 @@ static ssize_t wolfssl_send(struct Curl_cfilter *cf, return -1; } } + DEBUGF(LOG_CF(data, cf, "wolfssl_send(len=%zu) -> %d", len, rc)); return rc; } @@ -995,19 +1015,19 @@ static void wolfssl_close(struct Curl_cfilter *cf, struct Curl_easy *data) static ssize_t wolfssl_recv(struct Curl_cfilter *cf, struct Curl_easy *data, - char *buf, - size_t buffersize, + char *buf, size_t blen, CURLcode *curlcode) { struct ssl_connect_data *connssl = cf->ctx; struct ssl_backend_data *backend = connssl->backend; char error_buffer[WOLFSSL_MAX_ERROR_SZ]; - int buffsize = (buffersize > (size_t)INT_MAX) ? INT_MAX : (int)buffersize; + int buffsize = (blen > (size_t)INT_MAX) ? INT_MAX : (int)blen; int nread; DEBUGASSERT(backend); ERR_clear_error(); + *curlcode = CURLE_OK; nread = SSL_read(backend->handle, buf, buffsize); @@ -1016,22 +1036,31 @@ static ssize_t wolfssl_recv(struct Curl_cfilter *cf, switch(err) { case SSL_ERROR_ZERO_RETURN: /* no more data */ - break; + DEBUGF(LOG_CF(data, cf, "wolfssl_recv(len=%zu) -> CLOSED", blen)); + *curlcode = CURLE_OK; + return 0; case SSL_ERROR_NONE: /* FALLTHROUGH */ case SSL_ERROR_WANT_READ: /* FALLTHROUGH */ case SSL_ERROR_WANT_WRITE: /* there's data pending, re-invoke SSL_read() */ + DEBUGF(LOG_CF(data, cf, "wolfssl_recv(len=%zu) -> AGAIN", blen)); *curlcode = CURLE_AGAIN; return -1; default: + if(backend->io_result == CURLE_AGAIN) { + DEBUGF(LOG_CF(data, cf, "wolfssl_recv(len=%zu) -> AGAIN", blen)); + *curlcode = CURLE_AGAIN; + return -1; + } failf(data, "SSL read: %s, errno %d", ERR_error_string(err, error_buffer), SOCKERRNO); *curlcode = CURLE_RECV_ERROR; return -1; } } + DEBUGF(LOG_CF(data, cf, "wolfssl_recv(len=%zu) -> %d", blen, nread)); return nread; } diff --git a/libs/libcurl/src/vtls/x509asn1.c b/libs/libcurl/src/vtls/x509asn1.c index 31b84dc448..cf673b349f 100644 --- a/libs/libcurl/src/vtls/x509asn1.c +++ b/libs/libcurl/src/vtls/x509asn1.c @@ -1118,7 +1118,7 @@ CURLcode Curl_extract_certinfo(struct Curl_easy *data, for(ccp = cert.version.beg; ccp < cert.version.end; ccp++) version = (version << 8) | *(const unsigned char *) ccp; if(data->set.ssl.certinfo) { - ccp = curl_maprintf("%lx", version); + ccp = curl_maprintf("%x", version); if(!ccp) return CURLE_OUT_OF_MEMORY; result = Curl_ssl_push_certinfo(data, certnum, "Version", ccp); @@ -1127,7 +1127,7 @@ CURLcode Curl_extract_certinfo(struct Curl_easy *data, return result; } if(!certnum) - infof(data, " Version: %lu (0x%lx)", version + 1, version); + infof(data, " Version: %u (0x%x)", version + 1, version); /* Serial number. */ ccp = ASN1tostr(&cert.serialNumber, 0); -- cgit v1.2.3