From 45fc760985fa11ef98149418cbad02dadf748f31 Mon Sep 17 00:00:00 2001 From: Daniel Stenberg Date: Fri, 4 Jul 2003 16:29:23 +0000 Subject: [PATCH] Peter Sylvester's patch was applied that introduces the following: CURLOPT_SSL_CTX_FUNCTION to set a callback that gets called with the OpenSSL's ssl_ctx pointer passed in and allow a callback to act on it. If anything but CURLE_OK is returned, that will also be returned by libcurl all the way back. If this function changes the CURLOPT_URL, libcurl will detect this and instead go use the new URL. CURLOPT_SSL_CTX_DATA is a pointer you set to get passed to the callback set with CURLOPT_SSL_CTX_FUNCTION. --- include/curl/curl.h | 16 +++++++++++++++- lib/http.c | 3 +++ lib/ssluse.c | 9 +++++++++ lib/transfer.c | 26 +++++++++++++++++++++++--- lib/url.c | 13 +++++++++++++ lib/urldata.h | 6 ++++++ 6 files changed, 69 insertions(+), 4 deletions(-) diff --git a/include/curl/curl.h b/include/curl/curl.h index 00074d561..ae73c1dde 100644 --- a/include/curl/curl.h +++ b/include/curl/curl.h @@ -147,7 +147,7 @@ typedef int (*curl_debug_callback) curl_infotype type, /* what kind of data */ char *data, /* points to the data */ size_t size, /* size of the data pointed to */ - void *userp); /* whatever the user please */ + void *userptr); /* whatever the user please */ /* All possible error codes from all sorts of curl functions. Future versions may return other values, stay prepared. @@ -224,6 +224,11 @@ typedef enum { CURL_LAST /* never use! */ } CURLcode; +typedef CURLcode (*curl_ssl_ctx_callback)(CURL *curl, /* easy handle */ + void *ssl_ctx, /* actually an + OpenSSL SSL_CTX */ + void *userptr); + /* Make a spelling correction for the operation timed-out define */ #define CURLE_OPERATION_TIMEDOUT CURLE_OPERATION_TIMEOUTED #define CURLE_HTTP_NOT_FOUND CURLE_HTTP_RETURNED_ERROR @@ -659,6 +664,15 @@ typedef enum { Note that setting multiple bits may cause extra network round-trips. */ CINIT(HTTPAUTH, LONG, 107), + /* Set the ssl context callback function, currently only for OpenSSL ssl_ctx + in second argument. The function must be matching the + curl_ssl_ctx_callback proto. */ + CINIT(SSL_CTX_FUNCTION, FUNCTIONPOINT, 108), + + /* Set the userdata for the ssl context callback function's third + argument */ + CINIT(SSL_CTX_DATA, OBJECTPOINT, 109), + CURLOPT_LASTENTRY /* the last unused */ } CURLoption; diff --git a/lib/http.c b/lib/http.c index aa5a64dc0..d710ff5f4 100644 --- a/lib/http.c +++ b/lib/http.c @@ -617,6 +617,9 @@ CURLcode Curl_http_done(struct connectdata *conn) conn->fread = data->set.fread; /* restore */ conn->fread_in = data->set.in; /* restore */ + if (http == NULL) + return CURLE_OK; + if(http->send_buffer) { send_buffer *buff = http->send_buffer; diff --git a/lib/ssluse.c b/lib/ssluse.c index b4af2ba0d..8e8f5eeb2 100644 --- a/lib/ssluse.c +++ b/lib/ssluse.c @@ -831,6 +831,15 @@ Curl_SSLConnect(struct connectdata *conn) else SSL_CTX_set_verify(conn->ssl.ctx, SSL_VERIFY_NONE, cert_verify_callback); + /* give application a chance to interfere with SSL set up. */ + if (data->set.ssl.fsslctx) { + CURLcode callbackresult = (*data->set.ssl.fsslctx)(data, conn->ssl.ctx, + data->set.ssl.fsslctxp); + if (callbackresult != CURLE_OK) { + failf(data,"error signaled by ssl ctx callback"); + return callbackresult; + } + } /* Lets make an SSL structure */ conn->ssl.handle = SSL_new (conn->ssl.ctx); diff --git a/lib/transfer.c b/lib/transfer.c index e98e1e01b..98cf70c1d 100644 --- a/lib/transfer.c +++ b/lib/transfer.c @@ -1889,9 +1889,29 @@ CURLcode Curl_perform(struct SessionHandle *data) * performed after this do-while loop. */ - do { - Curl_pgrsTime(data, TIMER_STARTSINGLE); - res = Curl_connect(data, &conn); + do { + int urlchanged = FALSE; + do { + Curl_pgrsTime(data, TIMER_STARTSINGLE); + data->change.url_changed = FALSE; + res = Curl_connect(data, &conn); + + /* If a callback (or something) has altered the URL we should use within + the Curl_connect(), we detect it here and act as if we are redirected + to the new URL */ + urlchanged = data->change.url_changed; + if ((CURLE_OK == res) && urlchanged) { + char *newurl; + res = Curl_done(conn); + if(CURLE_OK == res) { + newurl = strdup(data->change.url); + res = Curl_follow(data, newurl); + if(res) + free(newurl); + } + } + } while (urlchanged && res == CURLE_OK) ; + if(res == CURLE_OK) { res = Curl_do(&conn); diff --git a/lib/url.c b/lib/url.c index 9ec92dfab..3b6a73b90 100644 --- a/lib/url.c +++ b/lib/url.c @@ -723,6 +723,7 @@ CURLcode Curl_setopt(struct SessionHandle *data, CURLoption option, ...) } data->set.set_url = va_arg(param, char *); data->change.url = data->set.set_url; + data->change.url_changed = TRUE; break; case CURLOPT_PORT: /* @@ -1091,6 +1092,18 @@ CURLcode Curl_setopt(struct SessionHandle *data, CURLoption option, ...) */ data->set.ssl.verifyhost = va_arg(param, long); break; + case CURLOPT_SSL_CTX_FUNCTION: + /* + * Set a SSL_CTX callback + */ + data->set.ssl.fsslctx = va_arg(param, curl_ssl_ctx_callback); + break; + case CURLOPT_SSL_CTX_DATA: + /* + * Set a SSL_CTX callback parameter pointer + */ + data->set.ssl.fsslctxp = va_arg(param, void *); + break; case CURLOPT_CAINFO: /* * Set CA info for SSL connection. Specify file name of the CA certificate diff --git a/lib/urldata.h b/lib/urldata.h index f892968e9..dab214ce3 100644 --- a/lib/urldata.h +++ b/lib/urldata.h @@ -145,6 +145,8 @@ struct ssl_config_data { char *egdsocket; /* path to file containing the EGD daemon socket */ char *cipher_list; /* list of ciphers to use */ long numsessions; /* SSL session id cache size */ + curl_ssl_ctx_callback fsslctx; /* function to initialize ssl ctx */ + void *fsslctxp; /*parameter for call back */ }; /* information stored about one single SSL session */ @@ -677,6 +679,10 @@ struct UrlState { struct DynamicStatic { char *url; /* work URL, copied from UserDefined */ bool url_alloc; /* URL string is malloc()'ed */ + bool url_changed; /* set on CURL_OPT_URL, used to detect if the URL was + changed after the connect phase, as we allow callback + to change it and if so, we reconnect to use the new + URL instead */ char *proxy; /* work proxy, copied from UserDefined */ bool proxy_alloc; /* http proxy string is malloc()'ed */ char *referer; /* referer string */