From 29dc39fce1126265d8526be15beec3e3fdc1c11d Mon Sep 17 00:00:00 2001 From: Daniel Stenberg Date: Mon, 11 Sep 2006 17:18:18 +0000 Subject: [PATCH] - Fixed my breakage from earlier today so that doing curl_easy_cleanup() on a handle that is part of a multi handle first removes the handle from the stack. - Added CURLOPT_SSL_SESSIONID_CACHE and --no-sessionid to disable SSL session-ID re-use on demand since there obviously are broken servers out there that misbehave with session-IDs used. --- CHANGES | 8 ++++++++ RELEASE-NOTES | 1 + docs/curl.1 | 9 +++++++++ docs/libcurl/curl_easy_setopt.3 | 6 ++++++ include/curl/curl.h | 4 ++++ lib/multi.c | 6 +++++- lib/sslgen.c | 8 ++++++++ lib/url.c | 11 +++++++++-- lib/urldata.h | 5 +++-- src/main.c | 18 +++++++++++++++--- tests/libtest/lib526.c | 3 +++ 11 files changed, 71 insertions(+), 8 deletions(-) diff --git a/CHANGES b/CHANGES index 28a506a98..c55b21909 100644 --- a/CHANGES +++ b/CHANGES @@ -7,6 +7,14 @@ Changelog Daniel (11 September 2006) +- Fixed my breakage from earlier today so that doing curl_easy_cleanup() on a + handle that is part of a multi handle first removes the handle from the + stack. + +- Added CURLOPT_SSL_SESSIONID_CACHE and --no-sessionid to disable SSL + session-ID re-use on demand since there obviously are broken servers out + there that misbehave with session-IDs used. + - Jeff Pohlmeyer presented a *multi_socket()-using program that exposed a problem with it (SIGSEGV-style). It clearly showed that the existing socket-state and state-difference function wasn't good enough so I rewrote diff --git a/RELEASE-NOTES b/RELEASE-NOTES index 9d32c39a2..b0a4e29bf 100644 --- a/RELEASE-NOTES +++ b/RELEASE-NOTES @@ -11,6 +11,7 @@ Curl and libcurl 7.16.0 This release includes the following changes: + o CURLOPT_SSL_SESSIONID_CACHE and --no-sessionid added o CURLMOPT_PIPELINING added for enabling pipelined transfers o Added support for other MS-DOS compilers (besides djgpp) o CURLOPT_SOCKOPTFUNCTION and CURLOPT_SOCKOPTDATA were added diff --git a/docs/curl.1 b/docs/curl.1 index 59f2c67fb..99b298eff 100644 --- a/docs/curl.1 +++ b/docs/curl.1 @@ -705,6 +705,15 @@ will output the data in chunks, not necessarily exactly when the data arrives. Using this option will disable that buffering. If this option is used twice, the second will again switch on buffering. +.IP "--no-sessionid" +(SSL) Disable curl's use of SSL session-ID caching. By default all transfers +are done using the cache. Note that while nothing ever should get hurt by +attempting to reuse SSL session-IDs, there seem to be broken SSL +implementations in the wild that may require you to disable this in order for +you to succeed. (Added in 7.16.0) + +If this option is used twice, the second will again switch on use of the +session cache. .IP "--ntlm" (HTTP) Enables NTLM authentication. The NTLM authentication method was designed by Microsoft and is used by IIS web servers. It is a proprietary diff --git a/docs/libcurl/curl_easy_setopt.3 b/docs/libcurl/curl_easy_setopt.3 index b4a128508..5e11cf38c 100644 --- a/docs/libcurl/curl_easy_setopt.3 +++ b/docs/libcurl/curl_easy_setopt.3 @@ -1302,6 +1302,12 @@ compile OpenSSL. You'll find more details about cipher lists on this URL: \fIhttp://www.openssl.org/docs/apps/ciphers.html\fP +.IP CURLOPT_SSL_SESSIONID_CACHE +Pass a long set to 0 to disable libcurl's use of SSL session-ID caching. Set +this to 1 to enable it. By default all transfers are done using the +cache. Note that while nothing ever should get hurt by attempting to reuse SSL +session-IDs, there seem to be broken SSL implementations in the wild that may +require you to disable this in order for you to succeed. (Added in 7.16.0) .IP CURLOPT_KRB4LEVEL Pass a char * as parameter. Set the krb4 security level, this also enables krb4 awareness. This is a string, 'clear', 'safe', 'confidential' or diff --git a/include/curl/curl.h b/include/curl/curl.h index af56f7aec..fbb9d32c1 100644 --- a/include/curl/curl.h +++ b/include/curl/curl.h @@ -1037,6 +1037,10 @@ typedef enum { CINIT(SOCKOPTFUNCTION, FUNCTIONPOINT, 148), CINIT(SOCKOPTDATA, OBJECTPOINT, 149), + /* set to 0 to disable session ID re-use for this transfer, default is + enabled (== 1) */ + CINIT(SSL_SESSIONID_CACHE, LONG, 150), + CURLOPT_LASTENTRY /* the last unused */ } CURLoption; diff --git a/lib/multi.c b/lib/multi.c index 9e7782af8..312e577d7 100644 --- a/lib/multi.c +++ b/lib/multi.c @@ -705,6 +705,9 @@ static CURLMcode multi_runsingle(struct Curl_multi *multi, do { + if(!GOOD_EASY_HANDLE(easy->easy_handle)) + return CURLE_BAD_FUNCTION_ARGUMENT; + if (easy->easy_handle->state.pipe_broke) { infof(easy->easy_handle, "Pipe broke: handle 0x%x\n", easy); if(easy->easy_handle->state.is_in_pipeline) { @@ -1231,8 +1234,9 @@ CURLMcode curl_multi_perform(CURLM *multi_handle, int *running_handles) if (easy->easy_handle->state.cancelled && easy->state == CURLM_STATE_CANCELLED) { /* Remove cancelled handles once it's safe to do so */ - easy = easy->next; Curl_multi_rmeasy(multi_handle, easy->easy_handle); + easy->easy_handle = NULL; + easy = easy->next; continue; } diff --git a/lib/sslgen.c b/lib/sslgen.c index 641131571..fec358c51 100644 --- a/lib/sslgen.c +++ b/lib/sslgen.c @@ -246,6 +246,10 @@ int Curl_ssl_getsessionid(struct connectdata *conn, struct SessionHandle *data = conn->data; long i; + if(!conn->ssl_config.sessionid) + /* session ID re-use is disabled */ + return TRUE; + for(i=0; i< data->set.ssl.numsessions; i++) { check = &data->state.session[i]; if(!check->sessionid) @@ -311,6 +315,10 @@ CURLcode Curl_ssl_addsessionid(struct connectdata *conn, long oldest_age=data->state.session[0].age; /* zero if unused */ char *clone_host; + /* Even though session ID re-use might be disabled, that only disables USING + IT. We still store it here in case the re-using is again enabled for an + upcoming transfer */ + clone_host = strdup(conn->host.name); if(!clone_host) return CURLE_OUT_OF_MEMORY; /* bail out */ diff --git a/lib/url.c b/lib/url.c index e9c4e5f9f..14def325a 100644 --- a/lib/url.c +++ b/lib/url.c @@ -214,13 +214,15 @@ CURLcode Curl_close(struct SessionHandle *data) { struct Curl_multi *m = data->multi; - data->magic = 0; /* force a clear */ - if(m) /* This handle is still part of a multi handle, take care of this first and detach this handle from there. */ Curl_multi_rmeasy(data->multi, data); + data->magic = 0; /* force a clear AFTER the possibly enforced removal from + the multi handle, since that function uses the magic + field! */ + if(data->state.connc && (data->state.connc->type == CONNCACHE_PRIVATE)) { /* close all connections still alive that are in the private connection cache, as we no longer have the pointer left to the shared one. */ @@ -455,6 +457,7 @@ CURLcode Curl_open(struct SessionHandle **curl) */ data->set.ssl.verifypeer = TRUE; data->set.ssl.verifyhost = 2; + data->set.ssl.sessionid = TRUE; /* session ID caching enabled by default */ #ifdef CURL_CA_BUNDLE /* This is our preferred CA cert bundle since install time */ data->set.ssl.CAfile = (char *)CURL_CA_BUNDLE; @@ -1632,6 +1635,10 @@ CURLcode Curl_setopt(struct SessionHandle *data, CURLoption option, data->set.sockopt_client = va_arg(param, void *); break; + case CURLOPT_SSL_SESSIONID_CACHE: + data->set.ssl.sessionid = va_arg(param, long)?TRUE:FALSE; + break; + default: /* unknown tag and its companion, just ignore: */ result = CURLE_FAILED_INIT; /* correct this */ diff --git a/lib/urldata.h b/lib/urldata.h index 1479cd7e3..9f8e6de80 100644 --- a/lib/urldata.h +++ b/lib/urldata.h @@ -178,8 +178,9 @@ 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 */ + curl_ssl_ctx_callback fsslctx; /* function to initialize ssl ctx */ + void *fsslctxp; /* parameter for call back */ + bool sessionid; /* cache session IDs or not */ }; /* information stored about one single SSL session */ diff --git a/src/main.c b/src/main.c index f0d2fd4ee..6d4820268 100644 --- a/src/main.c +++ b/src/main.c @@ -358,6 +358,7 @@ struct Configurable { int ftp_filemethod; bool ignorecl; /* --ignore-content-length */ + bool disable_sessionid; }; #define WARN_PREFIX "Warning: " @@ -547,6 +548,7 @@ static void help(void) " --netrc-optional Use either .netrc or URL; overrides -n", " --ntlm Use HTTP NTLM authentication (H)", " -N/--no-buffer Disable buffering of the output stream", + " --no-sessionid Disable SSL session-ID reusing (SSL)", " -o/--output Write output to instead of stdout", " -O/--remote-name Write output to a file named as the remote file", " -p/--proxytunnel Operate through a HTTP proxy tunnel (using CONNECT)", @@ -1348,6 +1350,7 @@ static ParameterError getparameter(char *flag, /* f or -long-flag */ {"$t", "socks4", TRUE}, {"$u", "ftp-alternative-to-user", TRUE}, {"$v", "ftp-ssl-reqd", FALSE}, + {"$w", "no-sessionid", FALSE}, {"0", "http1.0", FALSE}, {"1", "tlsv1", FALSE}, @@ -1790,6 +1793,9 @@ static ParameterError getparameter(char *flag, /* f or -long-flag */ case 'v': /* --ftp-ssl-reqd */ config->ftp_ssl_reqd ^= TRUE; break; + case 'w': /* --no-sessionid */ + config->disable_sessionid ^= TRUE; + break; } break; case '#': /* --progress-bar */ @@ -4013,11 +4019,17 @@ operate(struct Configurable *config, int argc, char *argv[]) /* curl 7.15.2 */ if(config->localport) { curl_easy_setopt(curl, CURLOPT_LOCALPORT, config->localport); - curl_easy_setopt(curl, CURLOPT_LOCALPORTRANGE, config->localportrange); + curl_easy_setopt(curl, CURLOPT_LOCALPORTRANGE, + config->localportrange); } - /* curl x.xx.x */ - curl_easy_setopt(curl, CURLOPT_FTP_ALTERNATIVE_TO_USER, config->ftp_alternative_to_user); + /* curl 7.15.5 */ + curl_easy_setopt(curl, CURLOPT_FTP_ALTERNATIVE_TO_USER, + config->ftp_alternative_to_user); + + /* curl 7.16.0 */ + curl_easy_setopt(curl, CURLOPT_SSL_SESSIONID_CACHE, + !config->disable_sessionid); retry_numretries = config->req_retry; diff --git a/tests/libtest/lib526.c b/tests/libtest/lib526.c index de3a36d02..04240808f 100644 --- a/tests/libtest/lib526.c +++ b/tests/libtest/lib526.c @@ -71,6 +71,9 @@ int test(char *URL) res = (int)curl_multi_perform(m, &running); if (running <= 0) { #ifdef LIB527 + /* NOTE: this code does not remove the handle from the multi handle + here, which would be the nice, sane and documented way of working. + This however tests that the API survives this abuse gracefully. */ curl_easy_cleanup(curl[current]); #endif if(++current < NUM_HANDLES) {