diff options
Diffstat (limited to 'Utilities/cmcurl/lib/vtls/gskit.c')
-rw-r--r-- | Utilities/cmcurl/lib/vtls/gskit.c | 223 |
1 files changed, 110 insertions, 113 deletions
diff --git a/Utilities/cmcurl/lib/vtls/gskit.c b/Utilities/cmcurl/lib/vtls/gskit.c index 4ee4edea6c..2074dcaa48 100644 --- a/Utilities/cmcurl/lib/vtls/gskit.c +++ b/Utilities/cmcurl/lib/vtls/gskit.c @@ -73,6 +73,7 @@ #include "sendf.h" #include "gskit.h" #include "vtls.h" +#include "vtls_int.h" #include "connect.h" /* for the connect timeout */ #include "select.h" #include "strcase.h" @@ -105,10 +106,8 @@ struct ssl_backend_data { gsk_handle handle; int iocport; -#ifndef CURL_DISABLE_PROXY int localfd; int remotefd; -#endif }; #define BACKEND connssl->backend @@ -295,11 +294,12 @@ static CURLcode set_numeric(struct Curl_easy *data, } -static CURLcode set_ciphers(struct Curl_easy *data, +static CURLcode set_ciphers(struct Curl_cfilter *cf, struct Curl_easy *data, gsk_handle h, unsigned int *protoflags) { + struct ssl_primary_config *conn_config = Curl_ssl_cf_get_primary_config(cf); struct connectdata *conn = data->conn; - const char *cipherlist = SSL_CONN_CONFIG(cipher_list); + const char *cipherlist = conn_config->cipher_list; const char *clp; const struct gskit_cipher *ctp; int i; @@ -324,7 +324,7 @@ static CURLcode set_ciphers(struct Curl_easy *data, GSKit tokens are always shorter than their cipher names, allocated buffers will always be large enough to accommodate the result. */ l = strlen(cipherlist) + 1; - memset((char *) ciphers, 0, sizeof(ciphers)); + memset(ciphers, 0, sizeof(ciphers)); for(i = 0; i < CURL_GSKPROTO_LAST; i++) { ciphers[i].buf = malloc(l); if(!ciphers[i].buf) { @@ -490,14 +490,16 @@ static CURLcode init_environment(struct Curl_easy *data, } -static void cancel_async_handshake(struct connectdata *conn, int sockindex) +static void cancel_async_handshake(struct Curl_cfilter *cf, + struct Curl_easy *data) { - struct ssl_connect_data *connssl = &conn->ssl[sockindex]; + struct ssl_connect_data *connssl = cf->ctx; Qso_OverlappedIO_t cstat; + (void)data; DEBUGASSERT(BACKEND); - if(QsoCancelOperation(conn->sock[sockindex], 0) > 0) + if(QsoCancelOperation(cf->conn->sock[cf->sockindex], 0) > 0) QsoWaitForIOCompletion(BACKEND->iocport, &cstat, (struct timeval *) NULL); } @@ -509,12 +511,12 @@ static void close_async_handshake(struct ssl_connect_data *connssl) BACKEND->iocport = -1; } -static int pipe_ssloverssl(struct connectdata *conn, int sockindex, - int directions) +static int pipe_ssloverssl(struct Curl_cfilter *cf, int directions) { -#ifndef CURL_DISABLE_PROXY - struct ssl_connect_data *connssl = &conn->ssl[sockindex]; - struct ssl_connect_data *connproxyssl = &conn->proxy_ssl[sockindex]; + struct ssl_connect_data *connssl = cf->ctx; + struct Curl_cfilter *cf_ssl_next = Curl_ssl_cf_get_ssl(cf->next); + struct ssl_connect_data *connssl_next = cf_ssl_next? + cf_ssl_next->ctx : NULL; struct pollfd fds[2]; int n; int m; @@ -523,14 +525,14 @@ static int pipe_ssloverssl(struct connectdata *conn, int sockindex, char buf[CURL_MAX_WRITE_SIZE]; DEBUGASSERT(BACKEND); - DEBUGASSERT(connproxyssl->backend); - if(!connssl->use || !connproxyssl->use) + if(!connssl_next) return 0; /* No SSL over SSL: OK. */ + DEBUGASSERT(connssl_next->backend); n = 1; fds[0].fd = BACKEND->remotefd; - fds[1].fd = conn->sock[sockindex]; + fds[1].fd = cf->conn->sock[cf->sockindex]; if(directions & SOS_READ) { fds[0].events |= POLLOUT; @@ -547,7 +549,7 @@ static int pipe_ssloverssl(struct connectdata *conn, int sockindex, if(fds[0].revents & POLLOUT) { /* Try getting data from HTTPS proxy and pipe it upstream. */ n = 0; - i = gsk_secure_soc_read(connproxyssl->backend->handle, + i = gsk_secure_soc_read(connssl_next->backend->handle, buf, sizeof(buf), &n); switch(i) { case GSK_OK: @@ -572,7 +574,7 @@ static int pipe_ssloverssl(struct connectdata *conn, int sockindex, if(n < 0) return -1; if(n) { - i = gsk_secure_soc_write(connproxyssl->backend->handle, buf, n, &m); + i = gsk_secure_soc_write(connssl_next->backend->handle, buf, n, &m); if(i != GSK_OK || n != m) return -1; ret = 1; @@ -580,24 +582,21 @@ static int pipe_ssloverssl(struct connectdata *conn, int sockindex, } return ret; /* OK */ -#else - return 0; -#endif } -static void close_one(struct ssl_connect_data *connssl, struct Curl_easy *data, - struct connectdata *conn, int sockindex) +static void close_one(struct Curl_cfilter *cf, struct Curl_easy *data) { + struct ssl_connect_data *connssl = cf->ctx; + DEBUGASSERT(BACKEND); if(BACKEND->handle) { gskit_status(data, gsk_secure_soc_close(&BACKEND->handle), "gsk_secure_soc_close()", 0); /* Last chance to drain output. */ - while(pipe_ssloverssl(conn, sockindex, SOS_WRITE) > 0) + while(pipe_ssloverssl(cf, SOS_WRITE) > 0) ; BACKEND->handle = (gsk_handle) NULL; -#ifndef CURL_DISABLE_PROXY if(BACKEND->localfd >= 0) { close(BACKEND->localfd); BACKEND->localfd = -1; @@ -606,30 +605,29 @@ static void close_one(struct ssl_connect_data *connssl, struct Curl_easy *data, close(BACKEND->remotefd); BACKEND->remotefd = -1; } -#endif } if(BACKEND->iocport >= 0) close_async_handshake(connssl); } -static ssize_t gskit_send(struct Curl_easy *data, int sockindex, +static ssize_t gskit_send(struct Curl_cfilter *cf, struct Curl_easy *data, const void *mem, size_t len, CURLcode *curlcode) { - struct connectdata *conn = data->conn; - struct ssl_connect_data *connssl = &conn->ssl[sockindex]; + struct connectdata *conn = cf->conn; + struct ssl_connect_data *connssl = cf->ctx; CURLcode cc = CURLE_SEND_ERROR; int written; DEBUGASSERT(BACKEND); - if(pipe_ssloverssl(conn, sockindex, SOS_WRITE) >= 0) { + if(pipe_ssloverssl(cf, SOS_WRITE) >= 0) { cc = gskit_status(data, gsk_secure_soc_write(BACKEND->handle, (char *) mem, (int) len, &written), "gsk_secure_soc_write()", CURLE_SEND_ERROR); if(cc == CURLE_OK) - if(pipe_ssloverssl(conn, sockindex, SOS_WRITE) < 0) + if(pipe_ssloverssl(cf, SOS_WRITE) < 0) cc = CURLE_SEND_ERROR; } if(cc != CURLE_OK) { @@ -640,17 +638,18 @@ static ssize_t gskit_send(struct Curl_easy *data, int sockindex, } -static ssize_t gskit_recv(struct Curl_easy *data, int num, char *buf, - size_t buffersize, CURLcode *curlcode) +static ssize_t gskit_recv(struct Curl_cfilter *cf, struct Curl_easy *data, + char *buf, size_t buffersize, CURLcode *curlcode) { - struct connectdata *conn = data->conn; - struct ssl_connect_data *connssl = &conn->ssl[num]; + struct connectdata *conn = cf->conn; + struct ssl_connect_data *connssl = cf->ctx; int nread; CURLcode cc = CURLE_RECV_ERROR; + (void)data; DEBUGASSERT(BACKEND); - if(pipe_ssloverssl(conn, num, SOS_READ) >= 0) { + if(pipe_ssloverssl(cf, SOS_READ) >= 0) { int buffsize = buffersize > (size_t) INT_MAX? INT_MAX: (int) buffersize; cc = gskit_status(data, gsk_secure_soc_read(BACKEND->handle, buf, buffsize, &nread), @@ -670,11 +669,14 @@ static ssize_t gskit_recv(struct Curl_easy *data, int num, char *buf, } static CURLcode -set_ssl_version_min_max(unsigned int *protoflags, struct Curl_easy *data) +set_ssl_version_min_max(unsigned int *protoflags, + struct Curl_cfilter *cf, + struct Curl_easy *data) { + struct ssl_primary_config *conn_config = Curl_ssl_cf_get_primary_config(cf); struct connectdata *conn = data->conn; - long ssl_version = SSL_CONN_CONFIG(version); - long ssl_version_max = SSL_CONN_CONFIG(version_max); + long ssl_version = conn_config->version; + long ssl_version_max = conn_config->version_max; long i = ssl_version; switch(ssl_version_max) { case CURL_SSLVERSION_MAX_NONE: @@ -702,35 +704,36 @@ set_ssl_version_min_max(unsigned int *protoflags, struct Curl_easy *data) return CURLE_OK; } -static CURLcode gskit_connect_step1(struct Curl_easy *data, - struct connectdata *conn, int sockindex) +static CURLcode gskit_connect_step1(struct Curl_cfilter *cf, + struct Curl_easy *data) { - struct ssl_connect_data *connssl = &conn->ssl[sockindex]; + struct ssl_connect_data *connssl = cf->ctx; + struct ssl_primary_config *conn_config = Curl_ssl_cf_get_primary_config(cf); + struct ssl_config_data *ssl_config = Curl_ssl_cf_get_config(cf, data); + struct Curl_cfilter *cf_ssl_next = Curl_ssl_cf_get_ssl(cf->next); + struct ssl_connect_data *connssl_next = cf_ssl_next? + cf_ssl_next->ctx : NULL; gsk_handle envir; CURLcode result; - const char * const keyringfile = SSL_CONN_CONFIG(CAfile); - const char * const keyringpwd = SSL_SET_OPTION(key_passwd); - const char * const keyringlabel = SSL_SET_OPTION(primary.clientcert); - const long int ssl_version = SSL_CONN_CONFIG(version); - const bool verifypeer = SSL_CONN_CONFIG(verifypeer); - const char * const hostname = SSL_HOST_NAME(); + const char * const keyringfile = conn_config->CAfile; + const char * const keyringpwd = conn_config->key_passwd; + const char * const keyringlabel = ssl_config->primary.clientcert; + const long int ssl_version = conn_config->version; + const bool verifypeer = conn_config->verifypeer; + const char *hostname = connssl->hostname; const char *sni; unsigned int protoflags = 0; Qso_OverlappedIO_t commarea; -#ifndef CURL_DISABLE_PROXY int sockpair[2]; static const int sobufsize = CURL_MAX_WRITE_SIZE; -#endif /* Create SSL environment, start (preferably asynchronous) handshake. */ DEBUGASSERT(BACKEND); BACKEND->handle = (gsk_handle) NULL; BACKEND->iocport = -1; -#ifndef CURL_DISABLE_PROXY BACKEND->localfd = -1; BACKEND->remotefd = -1; -#endif /* GSKit supports two ways of specifying an SSL context: either by * application identifier (that should have been defined at the system @@ -769,9 +772,8 @@ static CURLcode gskit_connect_step1(struct Curl_easy *data, if(result) return result; -#ifndef CURL_DISABLE_PROXY /* Establish a pipelining socket pair for SSL over SSL. */ - if(conn->proxy_ssl[sockindex].use) { + if(connssl_next) { if(Curl_socketpair(0, 0, 0, sockpair)) return CURLE_SSL_CONNECT_ERROR; BACKEND->localfd = sockpair[0]; @@ -787,7 +789,6 @@ static CURLcode gskit_connect_step1(struct Curl_easy *data, curlx_nonblock(BACKEND->localfd, TRUE); curlx_nonblock(BACKEND->remotefd, TRUE); } -#endif /* Determine which SSL/TLS version should be enabled. */ sni = hostname; @@ -809,7 +810,7 @@ static CURLcode gskit_connect_step1(struct Curl_easy *data, case CURL_SSLVERSION_TLSv1_1: case CURL_SSLVERSION_TLSv1_2: case CURL_SSLVERSION_TLSv1_3: - result = set_ssl_version_min_max(&protoflags, data); + result = set_ssl_version_min_max(&protoflags, cf, data); if(result != CURLE_OK) return result; break; @@ -845,15 +846,10 @@ static CURLcode gskit_connect_step1(struct Curl_easy *data, if(!result) result = set_numeric(data, BACKEND->handle, GSK_OS400_READ_TIMEOUT, 1); if(!result) -#ifndef CURL_DISABLE_PROXY result = set_numeric(data, BACKEND->handle, GSK_FD, BACKEND->localfd >= 0? - BACKEND->localfd: conn->sock[sockindex]); -#else - result = set_numeric(data, BACKEND->handle, GSK_FD, - conn->sock[sockindex]); -#endif + BACKEND->localfd: cf->conn->sock[cf->sockindex]); if(!result) - result = set_ciphers(data, BACKEND->handle, &protoflags); + result = set_ciphers(cf, data, BACKEND->handle, &protoflags); if(!protoflags) { failf(data, "No SSL protocol/cipher combination enabled"); result = CURLE_SSL_CIPHER; @@ -920,12 +916,10 @@ static CURLcode gskit_connect_step1(struct Curl_easy *data, else if(errno != ENOBUFS) result = gskit_status(data, GSK_ERROR_IO, "QsoCreateIOCompletionPort()", 0); -#ifndef CURL_DISABLE_PROXY - else if(conn->proxy_ssl[sockindex].use) { + else if(connssl_next) { /* Cannot pipeline while handshaking synchronously. */ result = CURLE_SSL_CONNECT_ERROR; } -#endif else { /* No more completion port available. Use synchronous IO. */ result = gskit_status(data, gsk_secure_soc_init(BACKEND->handle), @@ -943,11 +937,11 @@ static CURLcode gskit_connect_step1(struct Curl_easy *data, } -static CURLcode gskit_connect_step2(struct Curl_easy *data, - struct connectdata *conn, int sockindex, +static CURLcode gskit_connect_step2(struct Curl_cfilter *cf, + struct Curl_easy *data, bool nonblocking) { - struct ssl_connect_data *connssl = &conn->ssl[sockindex]; + struct ssl_connect_data *connssl = cf->ctx; Qso_OverlappedIO_t cstat; struct timeval stmv; CURLcode result; @@ -975,7 +969,7 @@ static CURLcode gskit_connect_step2(struct Curl_easy *data, char buffer[STRERROR_LEN]; failf(data, "QsoWaitForIOCompletion() I/O error: %s", Curl_strerror(errno, buffer, sizeof(buffer))); - cancel_async_handshake(conn, sockindex); + cancel_async_handshake(cf, data); close_async_handshake(connssl); return CURLE_SSL_CONNECT_ERROR; } @@ -983,7 +977,7 @@ static CURLcode gskit_connect_step2(struct Curl_easy *data, case 0: /* Handshake in progress, timeout occurred. */ if(nonblocking) return CURLE_OK; - cancel_async_handshake(conn, sockindex); + cancel_async_handshake(cf, data); close_async_handshake(connssl); return CURLE_OPERATION_TIMEDOUT; } @@ -998,15 +992,15 @@ static CURLcode gskit_connect_step2(struct Curl_easy *data, } -static CURLcode gskit_connect_step3(struct Curl_easy *data, - struct connectdata *conn, int sockindex) +static CURLcode gskit_connect_step3(struct Curl_cfilter *cf, + struct Curl_easy *data) { - struct ssl_connect_data *connssl = &conn->ssl[sockindex]; + struct ssl_connect_data *connssl = cf->ctx; const gsk_cert_data_elem *cdev; int cdec; const gsk_cert_data_elem *p; const char *cert = (const char *) NULL; - const char *certend; + const char *certend = (const char *) NULL; const char *ptr; CURLcode result; @@ -1044,7 +1038,7 @@ static CURLcode gskit_connect_step3(struct Curl_easy *data, } /* Verify host. */ - result = Curl_verifyhost(data, conn, cert, certend); + result = Curl_verifyhost(cf, data, cert, certend); if(result) return result; @@ -1066,7 +1060,9 @@ static CURLcode gskit_connect_step3(struct Curl_easy *data, } /* Check pinned public key. */ - ptr = SSL_PINNED_PUB_KEY(); + ptr = Curl_ssl_cf_is_proxy(cf)? + data->set.str[STRING_SSL_PINNEDPUBLICKEY_PROXY]: + data->set.str[STRING_SSL_PINNEDPUBLICKEY]; if(!result && ptr) { struct Curl_X509certificate x509; struct Curl_asn1Element *p; @@ -1087,11 +1083,11 @@ static CURLcode gskit_connect_step3(struct Curl_easy *data, } -static CURLcode gskit_connect_common(struct Curl_easy *data, - struct connectdata *conn, int sockindex, +static CURLcode gskit_connect_common(struct Curl_cfilter *cf, + struct Curl_easy *data, bool nonblocking, bool *done) { - struct ssl_connect_data *connssl = &conn->ssl[sockindex]; + struct ssl_connect_data *connssl = cf->ctx; timediff_t timeout_ms; CURLcode result = CURLE_OK; @@ -1110,12 +1106,12 @@ static CURLcode gskit_connect_common(struct Curl_easy *data, result = CURLE_OPERATION_TIMEDOUT; } else - result = gskit_connect_step1(data, conn, sockindex); + result = gskit_connect_step1(cf, data); } /* Handle handshake pipelining. */ if(!result) - if(pipe_ssloverssl(conn, sockindex, SOS_READ | SOS_WRITE) < 0) + if(pipe_ssloverssl(cf, SOS_READ | SOS_WRITE) < 0) result = CURLE_SSL_CONNECT_ERROR; /* Step 2: check if handshake is over. */ @@ -1129,25 +1125,23 @@ static CURLcode gskit_connect_common(struct Curl_easy *data, result = CURLE_OPERATION_TIMEDOUT; } else - result = gskit_connect_step2(data, conn, sockindex, nonblocking); + result = gskit_connect_step2(cf, data, nonblocking); } /* Handle handshake pipelining. */ if(!result) - if(pipe_ssloverssl(conn, sockindex, SOS_READ | SOS_WRITE) < 0) + if(pipe_ssloverssl(cf, SOS_READ | SOS_WRITE) < 0) result = CURLE_SSL_CONNECT_ERROR; /* Step 3: gather certificate info, verify host. */ if(!result && connssl->connecting_state == ssl_connect_3) - result = gskit_connect_step3(data, conn, sockindex); + result = gskit_connect_step3(cf, data); if(result) close_one(connssl, data, conn, sockindex); else if(connssl->connecting_state == ssl_connect_done) { connssl->state = ssl_connection_complete; connssl->connecting_state = ssl_connect_1; - conn->recv[sockindex] = gskit_recv; - conn->send[sockindex] = gskit_send; *done = TRUE; } @@ -1155,27 +1149,29 @@ static CURLcode gskit_connect_common(struct Curl_easy *data, } -static CURLcode gskit_connect_nonblocking(struct Curl_easy *data, - struct connectdata *conn, - int sockindex, bool *done) +static CURLcode gskit_connect_nonblocking(struct Curl_cfilter *cf, + struct Curl_easy *data, + bool *done) { + struct ssl_connect_data *connssl = cf->ctx; CURLcode result; - result = gskit_connect_common(data, conn, sockindex, TRUE, done); + result = gskit_connect_common(cf, data, TRUE, done); if(*done || result) - conn->ssl[sockindex].connecting_state = ssl_connect_1; + connssl->connecting_state = ssl_connect_1; return result; } -static CURLcode gskit_connect(struct Curl_easy *data, - struct connectdata *conn, int sockindex) +static CURLcode gskit_connect(struct Curl_cfilter *cf, + struct Curl_easy *data) { + struct ssl_connect_data *connssl = cf->ctx; CURLcode result; bool done; - conn->ssl[sockindex].connecting_state = ssl_connect_1; - result = gskit_connect_common(data, conn, sockindex, FALSE, &done); + connssl->connecting_state = ssl_connect_1; + result = gskit_connect_common(cf, data, FALSE, &done); if(result) return result; @@ -1185,20 +1181,16 @@ static CURLcode gskit_connect(struct Curl_easy *data, } -static void gskit_close(struct Curl_easy *data, struct connectdata *conn, - int sockindex) +static void gskit_close(struct Curl_cfilter *cf, struct Curl_easy *data) { - close_one(&conn->ssl[sockindex], data, conn, sockindex); -#ifndef CURL_DISABLE_PROXY - close_one(&conn->proxy_ssl[sockindex], data, conn, sockindex); -#endif + close_one(cf, data); } -static int gskit_shutdown(struct Curl_easy *data, - struct connectdata *conn, int sockindex) +static int gskit_shutdown(struct Curl_cfilter *cf, + struct Curl_easy *data) { - struct ssl_connect_data *connssl = &conn->ssl[sockindex]; + struct ssl_connect_data *connssl = cf->ctx; int what; int rc; char buf[120]; @@ -1214,9 +1206,9 @@ static int gskit_shutdown(struct Curl_easy *data, return 0; #endif - close_one(connssl, data, conn, sockindex); + close_one(cf, data); rc = 0; - what = SOCKET_READABLE(conn->sock[sockindex], + what = SOCKET_READABLE(cf->conn->sock[cf->sockindex], SSL_SHUTDOWN_TIMEOUT); while(loop--) { @@ -1238,7 +1230,7 @@ static int gskit_shutdown(struct Curl_easy *data, notify alert from the server. No way to gsk_secure_soc_read() now, so use read(). */ - nread = read(conn->sock[sockindex], buf, sizeof(buf)); + nread = read(cf->conn->sock[cf->sockindex], buf, sizeof(buf)); if(nread < 0) { char buffer[STRERROR_LEN]; @@ -1249,7 +1241,7 @@ static int gskit_shutdown(struct Curl_easy *data, if(nread <= 0) break; - what = SOCKET_READABLE(conn->sock[sockindex], 0); + what = SOCKET_READABLE(cf->conn->sock[cf->sockindex], 0); } return rc; @@ -1262,12 +1254,14 @@ static size_t gskit_version(char *buffer, size_t size) } -static int gskit_check_cxn(struct connectdata *cxn) +static int gskit_check_cxn(struct Curl_cfilter *cf, + struct Curl_easy *data) { - struct ssl_connect_data *connssl = &cxn->ssl[FIRSTSOCKET]; + struct ssl_connect_data *connssl = cf->ctx; int err; int errlen; + (void)data; /* The only thing that can be tested here is at the socket level. */ DEBUGASSERT(BACKEND); @@ -1311,7 +1305,7 @@ const struct Curl_ssl Curl_ssl_gskit = { Curl_none_cert_status_request, /* cert_status_request */ gskit_connect, /* connect */ gskit_connect_nonblocking, /* connect_nonblocking */ - Curl_ssl_getsock, /* getsock */ + Curl_ssl_get_select_socks, /* getsock */ gskit_get_internals, /* get_internals */ gskit_close, /* close_one */ Curl_none_close_all, /* close_all */ @@ -1323,7 +1317,10 @@ const struct Curl_ssl Curl_ssl_gskit = { Curl_none_false_start, /* false_start */ NULL, /* sha256sum */ NULL, /* associate_connection */ - NULL /* disassociate_connection */ + NULL, /* disassociate_connection */ + NULL, /* free_multi_ssl_backend_data */ + gskit_recv, /* recv decrypted data */ + gskit_send, /* send data to encrypt */ }; #endif /* USE_GSKIT */ |