diff options
author | Daniel Stenberg <daniel@haxx.se> | 2004-01-12 15:26:32 +0000 |
---|---|---|
committer | Daniel Stenberg <daniel@haxx.se> | 2004-01-12 15:26:32 +0000 |
commit | 3a61c98b6537b69db9b225caa30ec52fc7101aa6 (patch) | |
tree | da43293dbeb5051f54426e1eb6e487e9e66e8ff0 | |
parent | 5173bab0bbd69bbbfea5cd7f23925690a75c54a9 (diff) | |
download | curl-3a61c98b6537b69db9b225caa30ec52fc7101aa6.tar.gz |
Peter Sylvester brought code that now allows a callback to modified the URL
even when the multi interface is used, and then libcurl will simulate a
"follow location" to that new URL. Test 509 was added to test this feature.
-rw-r--r-- | CHANGES | 4 | ||||
-rw-r--r-- | lib/multi.c | 318 | ||||
-rw-r--r-- | tests/data/Makefile.am | 2 | ||||
-rw-r--r-- | tests/data/test509 | 51 | ||||
-rw-r--r-- | tests/libtest/Makefile.am | 6 | ||||
-rw-r--r-- | tests/libtest/lib509.c | 260 | ||||
-rw-r--r-- | tests/stunnel.pem | 159 |
7 files changed, 623 insertions, 177 deletions
@@ -7,6 +7,10 @@ Changelog Daniel (12 January 2004) +- Peter Sylvester brought code that now allows a callback to modified the URL + even when the multi interface is used, and then libcurl will simulate a + "follow location" to that new URL. Test 509 was added to test this feature. + - Extended the time we retry servers in the test script, and I also made it retry the https and ftps servers before they are considered bad. I believe the previous approach could turn problematic on really slow hosts. diff --git a/lib/multi.c b/lib/multi.c index e7a6a1d5b..a16359ce8 100644 --- a/lib/multi.c +++ b/lib/multi.c @@ -320,45 +320,62 @@ CURLMcode curl_multi_perform(CURLM *multi_handle, int *running_handles) easy=multi->easy.next; while(easy) { - #ifdef CURLDEBUG fprintf(stderr, "HANDLE %p: State: %x\n", (char *)easy, easy->state); #endif + do { + if (CURLM_STATE_WAITCONNECT <= easy->state && + easy->state <= CURLM_STATE_DO && + easy->easy_handle->change.url_changed) { + char *gotourl; + Curl_posttransfer(easy->easy_handle); - switch(easy->state) { - case CURLM_STATE_INIT: - /* init this transfer. */ - easy->result=Curl_pretransfer(easy->easy_handle); - - if(CURLE_OK == easy->result) { - /* after init, go CONNECT */ - easy->state = CURLM_STATE_CONNECT; - result = CURLM_CALL_MULTI_PERFORM; - - easy->easy_handle->state.used_interface = Curl_if_multi; + gotourl = strdup(easy->easy_handle->change.url); + easy->easy_handle->change.url_changed = FALSE; + easy->result = Curl_follow(easy->easy_handle, gotourl); + if(CURLE_OK == easy->result) + easy->state = CURLM_STATE_CONNECT; + else + free(gotourl); } - break; + + easy->easy_handle->change.url_changed = FALSE; - case CURLM_STATE_CONNECT: - /* Connect. We get a connection identifier filled in. */ - Curl_pgrsTime(easy->easy_handle, TIMER_STARTSINGLE); - easy->result = Curl_connect(easy->easy_handle, &easy->easy_conn, &async); + switch(easy->state) { + case CURLM_STATE_INIT: + /* init this transfer. */ + easy->result=Curl_pretransfer(easy->easy_handle); - if(CURLE_OK == easy->result) { - if(async) - /* We're now waiting for an asynchronous name lookup */ - easy->state = CURLM_STATE_WAITRESOLVE; - else { - /* after the connect has been sent off, go WAITCONNECT */ - easy->state = CURLM_STATE_WAITCONNECT; - result = CURLM_CALL_MULTI_PERFORM; + if(CURLE_OK == easy->result) { + /* after init, go CONNECT */ + easy->state = CURLM_STATE_CONNECT; + result = CURLM_CALL_MULTI_PERFORM; + + easy->easy_handle->state.used_interface = Curl_if_multi; } - } - break; + break; - case CURLM_STATE_WAITRESOLVE: - /* awaiting an asynch name resolve to complete */ + case CURLM_STATE_CONNECT: + /* Connect. We get a connection identifier filled in. */ + Curl_pgrsTime(easy->easy_handle, TIMER_STARTSINGLE); + easy->result = Curl_connect(easy->easy_handle, &easy->easy_conn, + &async); + + if(CURLE_OK == easy->result) { + if(async) + /* We're now waiting for an asynchronous name lookup */ + easy->state = CURLM_STATE_WAITRESOLVE; + else { + /* after the connect has been sent off, go WAITCONNECT */ + easy->state = CURLM_STATE_WAITCONNECT; + result = CURLM_CALL_MULTI_PERFORM; + } + } + break; + + case CURLM_STATE_WAITRESOLVE: + /* awaiting an asynch name resolve to complete */ { struct Curl_dns_entry *dns; @@ -387,146 +404,149 @@ CURLMcode curl_multi_perform(CURLM *multi_handle, int *running_handles) } break; - case CURLM_STATE_WAITCONNECT: - /* awaiting a completion of an asynch connect */ - easy->result = Curl_is_connected(easy->easy_conn, - easy->easy_conn->sock[FIRSTSOCKET], - &connected); - if(connected) - easy->result = Curl_protocol_connect(easy->easy_conn, NULL); - - if(CURLE_OK != easy->result) { - /* failure detected */ - Curl_disconnect(easy->easy_conn); /* close the connection */ - easy->easy_conn = NULL; /* no more connection */ - break; - } + case CURLM_STATE_WAITCONNECT: + /* awaiting a completion of an asynch connect */ + easy->result = Curl_is_connected(easy->easy_conn, + easy->easy_conn->sock[FIRSTSOCKET], + &connected); + if(connected) + easy->result = Curl_protocol_connect(easy->easy_conn, NULL); - if(connected) { - /* after the connect has completed, go DO */ - easy->state = CURLM_STATE_DO; - result = CURLM_CALL_MULTI_PERFORM; - } - break; + if(CURLE_OK != easy->result) { + /* failure detected */ + Curl_disconnect(easy->easy_conn); /* close the connection */ + easy->easy_conn = NULL; /* no more connection */ + break; + } - case CURLM_STATE_DO: - /* Do the fetch or put request */ - easy->result = Curl_do(&easy->easy_conn); - if(CURLE_OK == easy->result) { - - /* after do, go PERFORM... or DO_MORE */ - if(easy->easy_conn->bits.do_more) { - /* we're supposed to do more, but we need to sit down, relax - and wait a little while first */ - easy->state = CURLM_STATE_DO_MORE; - result = CURLM_OK; + if(connected) { + /* after the connect has completed, go DO */ + easy->state = CURLM_STATE_DO; + result = CURLM_CALL_MULTI_PERFORM; } - else { - /* we're done with the DO, now PERFORM */ - easy->result = Curl_readwrite_init(easy->easy_conn); - if(CURLE_OK == easy->result) { - easy->state = CURLM_STATE_PERFORM; - result = CURLM_CALL_MULTI_PERFORM; + break; + + case CURLM_STATE_DO: + /* Do the fetch or put request */ + easy->result = Curl_do(&easy->easy_conn); + if(CURLE_OK == easy->result) { + + /* after do, go PERFORM... or DO_MORE */ + if(easy->easy_conn->bits.do_more) { + /* we're supposed to do more, but we need to sit down, relax + and wait a little while first */ + easy->state = CURLM_STATE_DO_MORE; + result = CURLM_OK; + } + else { + /* we're done with the DO, now PERFORM */ + easy->result = Curl_readwrite_init(easy->easy_conn); + if(CURLE_OK == easy->result) { + easy->state = CURLM_STATE_PERFORM; + result = CURLM_CALL_MULTI_PERFORM; + } } } - } - break; + break; - case CURLM_STATE_DO_MORE: - /* - * First, check if we really are ready to do more. - */ - easy->result = Curl_is_connected(easy->easy_conn, - easy->easy_conn->sock[SECONDARYSOCKET], - &connected); - if(connected) { + case CURLM_STATE_DO_MORE: /* - * When we are connected, DO MORE and then go PERFORM + * First, check if we really are ready to do more. */ - easy->result = Curl_do_more(easy->easy_conn); - - if(CURLE_OK == easy->result) - easy->result = Curl_readwrite_init(easy->easy_conn); + easy->result = + Curl_is_connected(easy->easy_conn, + easy->easy_conn->sock[SECONDARYSOCKET], + &connected); + if(connected) { + /* + * When we are connected, DO MORE and then go PERFORM + */ + easy->result = Curl_do_more(easy->easy_conn); + + if(CURLE_OK == easy->result) + easy->result = Curl_readwrite_init(easy->easy_conn); - if(CURLE_OK == easy->result) { - easy->state = CURLM_STATE_PERFORM; - result = CURLM_CALL_MULTI_PERFORM; + if(CURLE_OK == easy->result) { + easy->state = CURLM_STATE_PERFORM; + result = CURLM_CALL_MULTI_PERFORM; + } } - } - break; + break; - case CURLM_STATE_PERFORM: - /* read/write data if it is ready to do so */ - easy->result = Curl_readwrite(easy->easy_conn, &done); - - if(easy->result) { - /* The transfer phase returned error, we mark the connection to get - * closed to prevent being re-used. This is becasue we can't - * possibly know if the connection is in a good shape or not now. */ - easy->easy_conn->bits.close = TRUE; - - if(-1 !=easy->easy_conn->sock[SECONDARYSOCKET]) { - /* if we failed anywhere, we must clean up the secondary socket if - it was used */ - sclose(easy->easy_conn->sock[SECONDARYSOCKET]); - easy->easy_conn->sock[SECONDARYSOCKET]=-1; + case CURLM_STATE_PERFORM: + /* read/write data if it is ready to do so */ + easy->result = Curl_readwrite(easy->easy_conn, &done); + + if(easy->result) { + /* The transfer phase returned error, we mark the connection to get + * closed to prevent being re-used. This is becasue we can't + * possibly know if the connection is in a good shape or not now. */ + easy->easy_conn->bits.close = TRUE; + + if(-1 !=easy->easy_conn->sock[SECONDARYSOCKET]) { + /* if we failed anywhere, we must clean up the secondary socket if + it was used */ + sclose(easy->easy_conn->sock[SECONDARYSOCKET]); + easy->easy_conn->sock[SECONDARYSOCKET]=-1; + } + Curl_posttransfer(easy->easy_handle); + Curl_done(easy->easy_conn); } - Curl_posttransfer(easy->easy_handle); - Curl_done(easy->easy_conn); - } - /* after the transfer is done, go DONE */ - else if(TRUE == done) { - - /* call this even if the readwrite function returned error */ - Curl_posttransfer(easy->easy_handle); - - /* When we follow redirects, must to go back to the CONNECT state */ - if(easy->easy_conn->newurl) { - char *newurl = easy->easy_conn->newurl; - easy->easy_conn->newurl = NULL; - easy->result = Curl_follow(easy->easy_handle, newurl); - if(CURLE_OK == easy->result) { - easy->state = CURLM_STATE_CONNECT; - result = CURLM_CALL_MULTI_PERFORM; + /* after the transfer is done, go DONE */ + else if(TRUE == done) { + + /* call this even if the readwrite function returned error */ + Curl_posttransfer(easy->easy_handle); + + /* When we follow redirects, must to go back to the CONNECT state */ + if(easy->easy_conn->newurl) { + char *newurl = easy->easy_conn->newurl; + easy->easy_conn->newurl = NULL; + easy->result = Curl_follow(easy->easy_handle, newurl); + if(CURLE_OK == easy->result) { + easy->state = CURLM_STATE_CONNECT; + result = CURLM_CALL_MULTI_PERFORM; + } + } + else { + easy->state = CURLM_STATE_DONE; + result = CURLM_CALL_MULTI_PERFORM; } } - else { - easy->state = CURLM_STATE_DONE; - result = CURLM_CALL_MULTI_PERFORM; - } - } - break; - case CURLM_STATE_DONE: - /* post-transfer command */ - easy->result = Curl_done(easy->easy_conn); + break; + case CURLM_STATE_DONE: + /* post-transfer command */ + easy->result = Curl_done(easy->easy_conn); - /* after we have DONE what we're supposed to do, go COMPLETED, and - it doesn't matter what the Curl_done() returned! */ - easy->state = CURLM_STATE_COMPLETED; - break; + /* after we have DONE what we're supposed to do, go COMPLETED, and + it doesn't matter what the Curl_done() returned! */ + easy->state = CURLM_STATE_COMPLETED; + break; - case CURLM_STATE_COMPLETED: - /* this is a completed transfer, it is likely to still be connected */ + case CURLM_STATE_COMPLETED: + /* this is a completed transfer, it is likely to still be connected */ - /* This node should be delinked from the list now and we should post - an information message that we are complete. */ - break; - default: - return CURLM_INTERNAL_ERROR; - } + /* This node should be delinked from the list now and we should post + an information message that we are complete. */ + break; + default: + return CURLM_INTERNAL_ERROR; + } - if(CURLM_STATE_COMPLETED != easy->state) { - if(CURLE_OK != easy->result) { - /* - * If an error was returned, and we aren't in completed state now, - * then we go to completed and consider this transfer aborted. */ - easy->state = CURLM_STATE_COMPLETED; + if(CURLM_STATE_COMPLETED != easy->state) { + if(CURLE_OK != easy->result) { + /* + * If an error was returned, and we aren't in completed state now, + * then we go to completed and consider this transfer aborted. */ + easy->state = CURLM_STATE_COMPLETED; + } + else + /* this one still lives! */ + (*running_handles)++; } - else - /* this one still lives! */ - (*running_handles)++; - } + + } while (easy->easy_handle->change.url_changed); if ((CURLM_STATE_COMPLETED == easy->state) && !easy->msg) { /* clear out the usage of the shared DNS cache */ diff --git a/tests/data/Makefile.am b/tests/data/Makefile.am index d0d32099f..ec90fed54 100644 --- a/tests/data/Makefile.am +++ b/tests/data/Makefile.am @@ -24,4 +24,4 @@ test62 test63 test64 test65 test66 test144 test145 test67 test68 test41 \ test40 test42 test69 test70 test71 test72 test73 test146 test505 \ test74 test75 test76 test77 test78 test147 test148 test506 test79 test80 \ test81 test82 test83 test84 test85 test86 test87 test507 test149 test88 \ -test89 test90 test508 test91 test92 test203 test93 test94 test95 +test89 test90 test508 test91 test92 test203 test93 test94 test95 test509 diff --git a/tests/data/test509 b/tests/data/test509 new file mode 100644 index 000000000..27bda4c26 --- /dev/null +++ b/tests/data/test509 @@ -0,0 +1,51 @@ +# +# Server-side +<reply> +<data> +HTTP/1.1 200 OK +Date: Thu, 09 Nov 2010 14:49:00 GMT +Server: localhost:8433 +Content-length:6 + +Hello +</data> +<datacheck> +Hello +</datacheck> +</reply> + +# +# Client-side +<client> +<server> +https +</server> +<features> +SSL +</features> +<tool> +lib509 +</tool> + + <name> +simple HTTPS GET and URL redirect in certificate + </name> + <command> +https://localhost:%HTTPSPORT/dvcs +</command> +</client> + +# +# Verify data after the test has been "shot" +<verify> +<strip> +^User-Agent:.* +</strip> +<protocol> +GET /509 HTTP/1.1 +Host: localhost:8433 +Pragma: no-cache +Accept: image/gif, image/x-xbitmap, image/jpeg, image/pjpeg, */* + +</protocol> +</verify> diff --git a/tests/libtest/Makefile.am b/tests/libtest/Makefile.am index 52f9e6e57..9a358f09d 100644 --- a/tests/libtest/Makefile.am +++ b/tests/libtest/Makefile.am @@ -12,7 +12,7 @@ SUPPORTFILES = first.c test.h # here are all tools used for running libcurl tests noinst_PROGRAMS = lib500 lib501 lib502 lib503 lib504 lib505 lib506 lib507 \ - lib508 + lib508 lib509 lib500_SOURCES = lib500.c $(SUPPORTFILES) lib500_LDADD = $(LIBDIR)/libcurl.la @@ -49,3 +49,7 @@ lib507_DEPENDENCIES = $(LIBDIR)/libcurl.la lib508_SOURCES = lib508.c $(SUPPORTFILES) lib508_LDADD = $(LIBDIR)/libcurl.la lib508_DEPENDENCIES = $(LIBDIR)/libcurl.la + +lib509_SOURCES = lib509.c $(SUPPORTFILES) +lib509_LDADD = $(LIBDIR)/libcurl.la +lib509_DEPENDENCIES = $(LIBDIR)/libcurl.la diff --git a/tests/libtest/lib509.c b/tests/libtest/lib509.c new file mode 100644 index 000000000..d9774d129 --- /dev/null +++ b/tests/libtest/lib509.c @@ -0,0 +1,260 @@ +#include "test.h" + +#ifdef USE_SSLEAY + +#ifdef HAVE_SYS_SOCKET_H +#include <sys/socket.h> +#endif +#include <sys/time.h> +#include <sys/types.h> + +#include <openssl/opensslv.h> +#include <openssl/x509v3.h> +#include <openssl/x509_vfy.h> +#include <openssl/crypto.h> +#include <openssl/lhash.h> +#include <openssl/objects.h> +#include <openssl/err.h> +#include <openssl/evp.h> +#include <openssl/x509.h> +#include <openssl/pkcs12.h> +#include <openssl/bio.h> +#include <openssl/ssl.h> + + +typedef struct sslctxparm_st { + CURL* curl; + int accesstype ; + unsigned char * accessinfoURL ; + +} sslctxparm; + + +static unsigned char *i2s_ASN1_IA5STRING( ASN1_IA5STRING *ia5) +{ + unsigned char *tmp; + if(!ia5 || !ia5->length) return NULL; + tmp = OPENSSL_malloc(ia5->length + 1); + memcpy(tmp, ia5->data, ia5->length); + tmp[ia5->length] = 0; + return tmp; +} + +/* A conveniance routine to get an access URI. */ + +static unsigned char *my_get_ext(X509 * cert, const int type, + int extensiontype) +{ + int i; + STACK_OF(ACCESS_DESCRIPTION) * accessinfo ; + accessinfo = X509_get_ext_d2i(cert, extensiontype, NULL, NULL) ; + + if (!sk_ACCESS_DESCRIPTION_num(accessinfo)) + return NULL; + + for (i = 0; i < sk_ACCESS_DESCRIPTION_num(accessinfo); i++) { + ACCESS_DESCRIPTION * ad = sk_ACCESS_DESCRIPTION_value(accessinfo, i); + if (OBJ_obj2nid(ad->method) == type) { + if (ad->location->type == GEN_URI) { + return i2s_ASN1_IA5STRING(ad->location->d.ia5); + } + return NULL; + } + } + return NULL; +} + +void * globalparm = NULL; + +static int ssl_app_verify_callback(X509_STORE_CTX *ctx, void *arg) +{ + sslctxparm * p = (sslctxparm *) arg; + int ok, err; + + fprintf(stderr,"ssl_app_verify_callback sslctxparm=%p ctx=%p\n", + (void *)p, (void*)ctx); + +#if OPENSSL_VERSION_NUMBER<0x00907000L +/* not necessary in openssl 0.9.7 or later */ + + fprintf(stderr,"This version %s of openssl does not support a parm (%p)" + ", getting a global static %p \n", + OPENSSL_VERSION_TEXT, (void *)p, (void *)globalparm); + + p = globalparm; +#endif + +/* The following error should not occur. We test this to avoid segfault. */ + if (!p || !ctx) { + fprintf(stderr,"Internal error in ssl_app_verify_callback " + "sslctxparm=%p ctx=%p\n",(void *)p,(void*)ctx); + return 0; + } + + ok= X509_verify_cert(ctx); + err=X509_STORE_CTX_get_error(ctx); + +/* The following seems to be a problem in 0.9.7/8 openssl versions */ + +#if 1 + if (err == X509_V_ERR_DEPTH_ZERO_SELF_SIGNED_CERT || + err == X509_V_ERR_UNABLE_TO_GET_ISSUER_CERT_LOCALLY) { + fprintf(stderr,"X509_verify_cert: repairing self signed\n") ; + X509_STORE_CTX_set_error(ctx,X509_V_OK); + ok = 1; + } +#endif + + if (ok && ctx->cert) { + unsigned char * accessinfoURL ; + + accessinfoURL = my_get_ext(ctx->cert,p->accesstype ,NID_info_access); + if (accessinfoURL) { + + if (strcmp((char *)p->accessinfoURL, (char *)accessinfoURL)) { + fprintf(stderr, "Setting URL <%s>, was <%s>\n", + accessinfoURL,p->accessinfoURL); + OPENSSL_free(p->accessinfoURL); + p->accessinfoURL = accessinfoURL; + curl_easy_setopt(p->curl, CURLOPT_URL,p->accessinfoURL); + } + else + OPENSSL_free(accessinfoURL); + } + } + return(ok); +} + + +static CURLcode sslctxfun(CURL * curl, void * sslctx, void * parm) +{ + sslctxparm * p = (sslctxparm *) parm; + + SSL_CTX * ctx = (SSL_CTX *) sslctx ; + fprintf(stderr,"sslctxfun start curl=%p ctx=%p parm=%p\n", + (void *)curl,(void *)ctx,(void *)p); + + SSL_CTX_set_quiet_shutdown(ctx,1); + SSL_CTX_set_cipher_list(ctx,"RC4-MD5"); + SSL_CTX_set_mode(ctx, SSL_MODE_AUTO_RETRY); + +/* one might assume that the cert validaton would not fail when setting this, + but it still does, see the error handling in the call back */ + + SSL_CTX_set_verify_depth(ctx,0); + SSL_CTX_set_verify(ctx,SSL_VERIFY_NONE,NULL); + +#if OPENSSL_VERSION_NUMBER<0x00907000L +/* in newer openssl versions we can set a parameter for the call back. */ + fprintf(stderr,"This version %s of openssl does not support a parm," + " setting global one\n", OPENSSL_VERSION_TEXT); + /* this is only done to support 0.9.6 version */ + globalparm = parm; + +/* in 0.9.6 the parm is not taken */ +#endif + SSL_CTX_set_cert_verify_callback(ctx, ssl_app_verify_callback, parm); + fprintf(stderr,"sslctxfun end\n"); + + return CURLE_OK ; +} + + +CURLcode test(char *URL) +{ + CURLM* multi; + sslctxparm p; + + int i; + CURLMsg *msg; + + curl_global_init(CURL_GLOBAL_ALL); + + p.curl = curl_easy_init(); + + p.accessinfoURL = (unsigned char *) strdup(URL); + p.accesstype = OBJ_obj2nid(OBJ_txt2obj("AD_DVCS",0)) ; + + curl_easy_setopt(p.curl, CURLOPT_URL, p.accessinfoURL); + + curl_easy_setopt(p.curl, CURLOPT_SSL_CTX_FUNCTION, sslctxfun) ; + curl_easy_setopt(p.curl, CURLOPT_SSL_CTX_DATA, &p); + + curl_easy_setopt(p.curl, CURLOPT_SSL_VERIFYPEER, FALSE); + curl_easy_setopt(p.curl, CURLOPT_SSL_VERIFYHOST, 1); + + fprintf(stderr,"Going to perform %s\n",p.accessinfoURL); + + { + CURLMcode res; + int running; + char done=FALSE; + + multi = curl_multi_init(); + + res = curl_multi_add_handle(multi, p.curl); + + while(!done) { + fd_set rd, wr, exc; + int max_fd; + struct timeval interval; + + interval.tv_sec = 1; + interval.tv_usec = 0; + + while (res == CURLM_CALL_MULTI_PERFORM) { + res = curl_multi_perform(multi, &running); + fprintf(stderr, "running=%d res=%d\n",running,res); + if (running <= 0) { + done = TRUE; + break; + } + } + if(done) + break; + + if (res != CURLM_OK) { + fprintf(stderr, "not okay???\n"); + return 80; + } + + FD_ZERO(&rd); + FD_ZERO(&wr); + FD_ZERO(&exc); + max_fd = 0; + + if (curl_multi_fdset(multi, &rd, &wr, &exc, &max_fd) != CURLM_OK) { + fprintf(stderr, "unexpected failured of fdset.\n"); + return 89; + } + + if (select(max_fd+1, &rd, &wr, &exc, &interval) == -1) { + fprintf(stderr, "bad select??\n"); + return 95; + } + + res = CURLM_CALL_MULTI_PERFORM; + } + msg = curl_multi_info_read(multi, &running); + /* this should now contain a result code from the easy handle, get it */ + i = msg->data.result; + } + + fprintf(stderr, "all done\n"); + + curl_multi_remove_handle(multi, p.curl); + curl_easy_cleanup(p.curl); + curl_multi_cleanup(multi); + + curl_global_cleanup(); + free(p.accessinfoURL); + + return i; +} +#else /* USE_SSLEAY */ +CURLcode test(char *URL) +{ + (void)URL; + return CURLE_FAILED_INIT; +} +#endif /* USE_SSLEAY */ diff --git a/tests/stunnel.pem b/tests/stunnel.pem index 2668a4bd1..1e09cd2d0 100644 --- a/tests/stunnel.pem +++ b/tests/stunnel.pem @@ -1,31 +1,138 @@ +# +# This file contains a private key and a certificate used for stunnel. +# The certificate contains a number of extensions essentially being +# used in the 509 test. The certificate has been generated using +# openssl with the parameters listed below up to the line +# contain [something], after that you find the result. +# +# +extensions = x509v3 +[ x509v3 ] +subjectAltName = DNS:localhost +nsCertType = server +nsComment = "CURL stunnel server test certificate" +keyUsage = digitalSignature,keyEncipherment +extendedKeyUsage = serverAuth +basicConstraints = CA:false +subjectKeyIdentifier = hash +subjectInfoAccess = AD_DVCS;URI:"https://localhost:8433/509" +authorityInfoAccess = AD_DVCS;URI:"https://localhost:8433/509" +[ req ] +default_bits = 1234 +distinguished_name = req_DN +default_md = sha1 +string_mask = pkix +[ req_DN ] +countryName = "1. Country Name (2 letter code)" +countryName_value = SE +stateOrProvinceName = "2. State or Province Name (full name) " +stateOrProvinceName_value = Solna +localityName = "3. Locality Name (eg, city) " +localityName_value = Mooo +0.organizationName = "4. Organization Name (eg, company) " +0.organizationName_value = Haxx +organizationalUnitName = "5. Organizational Unit Name (eg, section) " +organizationalUnitName_value = Coolx +commonName = "6. Common Name (eg, FQDN) " +commonName_value = "storbror" +1.commonName = "6. Common Name (eg, FQDN) " +1.commonName_value = "localhost" +[something] -----BEGIN RSA PRIVATE KEY----- -MIICXQIBAAKBgQDQPvaAU+Pdd5B0XlR71lDw0LyMridewzGaN6H3T+vRKYkvxyZw -nrxhYSLWn4g9wcu/EWcTN23A07Oa4HSZ/wHQ/yO+Yv01OmfGHylWZNN0eb/qemv8 -wp/bFRaubeuIGz9hl4r1HM5Mn3cNjhDjIjDqzGorObUItigCHY4ZDNHOOQIDAQAB -AoGAfK4V3ANeHEznuiR4JKTOVUBEg14JyFzJp/HDEVVSdSqPLoHn6+m+E/eaajGd -2ovbNwxuUD0Rgy+9Cu90IHdjV+8i7xo/ttnzg8UDUUhT0BMuOsbEPGGABqPxXEoM -+c58smG9r30K+5ToctRlsYuH4xQvHL3fc2DHRDEwPDD+KdkCQQD3kO9D6sV9/So3 -wWLamW0AFK/spK0i1MqSdPi/gnor37WNqOxBz2MVYDmTWeDWtq9HuG2QRKCNiqGB -tAUyKSVjAkEA11ccOxGleOM+scugobGkktnCniyMJSxQijMpIDmO/S0DBH5SiTee -BywwtcadjUWn4uQGJ0CQCJo2mjsmY13OswJBAKJgPJ7WWKyXJV6mh9kLMrQP3Yeg -RzMGUMuYzyKFSO6H74O3nSZZCQsXLwxXsiICdpra+3nZmVjc6aux0Iqi9DMCQQCh -DXaAux7t/c9q/CeEJy814YWL9TdPqggGhGLyxfmqYprKJowmMiGPrb40hXpaKUl6 -CR6NBt1ygZvq1+hLEuK/AkBYJ0ikl3YHkWqSFgiw/yDsVa3CDpChLGxjlheX5gop -LKrKE8RO3rtT3CdWyI/IBWPyc0h+qCTEqUdqKW1vRYeS +MIIC1AIBAAKBmwNZN+oG6vJ8DAze+FvOKSS49X4xGMxALhKRLhQQb7qvM+7BcMgR +v+RKxkX7SNgcxKPLcIHf7QQ6DBIlLXuAuVHQtWW9b06q64kBElkEwh6gP5Ia9JrR +ysGbu2U6NRP+xBU33dVwZjF07ocN9Pp392W4VxEc+g3+FkRzUEaahDGOabmjgKuq +DdlKdZLzgJj7+9sEKpb7+FdG56rZAgMBAAECgZsCkK1Z1XTUz5x3m7PMuHEiVaKS +yk/B4ISq6pbO/gxpieARzhR038wNug6L+8VA8UDebXHBvGYYr9Mhb2OZUfIlr+nW +h7kmHZ+T88M3eH/hQc3jtnvnu1dGmMlIXjTLQOrKgrAn6fYaw2HAGPdGKjpatAy/ +3vRjguv/22pNJLRQmMHdozJdc8mEYY+AhqrQxXCWQT/1peZzlq/IAQJOAfhE2YWf +qB9iYNmuhxJ1PolPW4I63atXuoavqadbaRoaLm/pqLVB1QjMeyak8O/0TmO6CXk6 +878ps85fLFgARRjSYX+rYwoYNzqxK3cBAk4Bsy4oofReVT8xB+7rFZFMV4McyL7e +sOABFqecLuNIGT6CdeEU1z7TUfq8sKM1MQ25e0J1PMmoWTqDwzhnxK+ckeFsZ8Te +dgqVW+Oyy9kCTgHqyc/P/uEZkp1ioDu0WkpAR+1vZa2jeyH+vm9nhE9Z6Uty/r6F +k4otIx9lMDmTwXqeE03vINJlJshqvjShfbnCe9gK8xrUk1cFl7QPAQJOATD3LQRq +At2MniioFtiTbUN6n2ZS1C5xnHGq3fnBzxnZw4UmSfuZjG/L3gWPKkyJCK3HYe9K +ho6ZQhNB6P5d7sQQjG6f+SIRwp+VjwvpAk4AnM4do54FETeLHhY4zy47dM/zdy3u +iDjiFwoMTR+PfF03evsWe5pW3EaXolGi3FRAZ/idFA+L3Gi2y4xR44z71HkbF32L +WKaLdOuBQvI= -----END RSA PRIVATE KEY----- +Certificate: + Data: + Version: 3 (0x2) + Serial Number: + 09:c2:f9:ca:9a:d8 + Signature Algorithm: md5WithRSAEncryption + Issuer: C=SE, ST=Solna, L=Mooo, O=Haxx, OU=Coolx, CN=storbror, CN=localhost + Validity + Not Before: Jan 5 11:25:13 2004 GMT + Not After : Feb 13 11:25:13 2008 GMT + Subject: C=SE, ST=Solna, L=Mooo, O=Haxx, OU=Coolx, CN=storbror, CN=localhost + Subject Public Key Info: + Public Key Algorithm: rsaEncryption + RSA Public Key: (1234 bit) + Modulus (1234 bit): + 03:59:37:ea:06:ea:f2:7c:0c:0c:de:f8:5b:ce:29: + 24:b8:f5:7e:31:18:cc:40:2e:12:91:2e:14:10:6f: + ba:af:33:ee:c1:70:c8:11:bf:e4:4a:c6:45:fb:48: + d8:1c:c4:a3:cb:70:81:df:ed:04:3a:0c:12:25:2d: + 7b:80:b9:51:d0:b5:65:bd:6f:4e:aa:eb:89:01:12: + 59:04:c2:1e:a0:3f:92:1a:f4:9a:d1:ca:c1:9b:bb: + 65:3a:35:13:fe:c4:15:37:dd:d5:70:66:31:74:ee: + 87:0d:f4:fa:77:f7:65:b8:57:11:1c:fa:0d:fe:16: + 44:73:50:46:9a:84:31:8e:69:b9:a3:80:ab:aa:0d: + d9:4a:75:92:f3:80:98:fb:fb:db:04:2a:96:fb:f8: + 57:46:e7:aa:d9 + Exponent: 65537 (0x10001) + X509v3 extensions: + X509v3 Subject Alternative Name: + DNS:localhost + Netscape Cert Type: + SSL Server + Netscape Comment: + CURL stunnel server test certificate + X509v3 Key Usage: + Digital Signature, Key Encipherment + X509v3 Extended Key Usage: + TLS Web Server Authentication + X509v3 Basic Constraints: + CA:FALSE + X509v3 Subject Key Identifier: + 35:77:35:3B:9B:98:3C:B6:C7:9A:E7:A8:04:B9:7C:70:AD:FA:37:A9 + Subject Information Access: + ad dvcs - URI:https://localhost:8433/509 + + Authority Information Access: + ad dvcs - URI:https://localhost:8433/509 + + Signature Algorithm: md5WithRSAEncryption + 02:47:57:18:5f:54:3f:1d:29:0a:05:7a:d1:0f:e6:b9:2c:8b: + 29:38:50:bf:c1:a1:7f:73:4a:9d:f1:1b:bf:2e:ea:87:91:dd: + ff:75:73:57:78:cf:75:52:57:0b:5b:bb:d4:77:b2:dd:e8:0c: + 06:ce:1b:c0:3d:9f:68:c0:0b:66:b8:f9:46:db:04:a9:2f:a3: + 5e:9c:c6:70:ff:1d:af:1f:17:9c:38:3d:12:aa:af:7b:72:44: + a0:44:41:6b:9a:9b:60:8c:50:94:f1:d7:a5:77:6b:d3:0e:66: + 88:a1:52:63:23:f6:66:a6:ea:f9:d0:df:4d:8a:14:f0:73:c6: + b6:b6:b6:68:4f:3d:9a:b6:31:ba:19:f3:66:9f:16:6d:87:64: + 32:53:d2:90:e5:8c:1e:f5:18:61:1a -----BEGIN CERTIFICATE----- -MIICcTCCAdqgAwIBAgIBADANBgkqhkiG9w0BAQQFADBzMQswCQYDVQQGEwJTRTEO -MAwGA1UECBMFU29sbmExDTALBgNVBAcTBE1vb28xDTALBgNVBAoTBEhheHgxDjAM -BgNVBAsTBUNvb2x4MRIwEAYDVQQDEwlzdG9yZWJyb3IxEjAQBgNVBAMTCWxvY2Fs -aG9zdDAeFw0wMTA0MjAxODI2MjhaFw0wMjA0MjAxODI2MjhaMHMxCzAJBgNVBAYT +MIIDujCCAwigAwIBAgIGCcMA3QkhMA0GCSqGSIb3DQEBBAUAMHIxCzAJBgNVBAYT AlNFMQ4wDAYDVQQIEwVTb2xuYTENMAsGA1UEBxMETW9vbzENMAsGA1UEChMESGF4 -eDEOMAwGA1UECxMFQ29vbHgxEjAQBgNVBAMTCXN0b3JlYnJvcjESMBAGA1UEAxMJ -bG9jYWxob3N0MIGfMA0GCSqGSIb3DQEBAQUAA4GNADCBiQKBgQDQPvaAU+Pdd5B0 -XlR71lDw0LyMridewzGaN6H3T+vRKYkvxyZwnrxhYSLWn4g9wcu/EWcTN23A07Oa -4HSZ/wHQ/yO+Yv01OmfGHylWZNN0eb/qemv8wp/bFRaubeuIGz9hl4r1HM5Mn3cN -jhDjIjDqzGorObUItigCHY4ZDNHOOQIDAQABoxUwEzARBglghkgBhvhCAQEEBAMC -BkAwDQYJKoZIhvcNAQEEBQADgYEASTzH6Af6xmkpPGAdL/lecdkeuChfgb7tVkOE -rTzgxE5fVcW9NK79HXZ3OND2uHyu9WMieIr7QKyzfK1uskxQcY6mPApn/Z+yD1vn -TYBuyP8I+khaLKA69QzVv+5yVBR0xlAaXGwTKxNzBTXznSmshgvYt5nsmcMw2Xfg -CMkSsOU= +eDEOMAwGA1UECxMFQ29vbHgxETAPBgNVBAMTCHN0b3Jicm9yMRIwEAYDVQQDEwls +b2NhbGhvc3QwHhcNMDQwMTA1MTQ0MjU2WhcNMDgwMjEzMTQ0MjU2WjByMQswCQYD +VQQGEwJTRTEOMAwGA1UECBMFU29sbmExDTALBgNVBAcTBE1vb28xDTALBgNVBAoT +BEhheHgxDjAMBgNVBAsTBUNvb2x4MREwDwYDVQQDEwhzdG9yYnJvcjESMBAGA1UE +AxMJbG9jYWxob3N0MIG5MA0GCSqGSIb3DQEBAQUAA4GnADCBowKBmwNZN+oG6vJ8 +DAze+FvOKSS49X4xGMxALhKRLhQQb7qvM+7BcMgRv+RKxkX7SNgcxKPLcIHf7QQ6 +DBIlLXuAuVHQtWW9b06q64kBElkEwh6gP5Ia9JrRysGbu2U6NRP+xBU33dVwZjF0 +7ocN9Pp392W4VxEc+g3+FkRzUEaahDGOabmjgKuqDdlKdZLzgJj7+9sEKpb7+FdG +56rZAgMBAAGjggEkMIIBIDARBglghkgBhvhCAQEEBAMCBkAwMwYJYIZIAYb4QgEN +BCYWJENVUkwgc3R1bm5lbCBzZXJ2ZXIgdGVzdCBjZXJ0aWZpY2F0ZTALBgNVHQ8E +BAMCBaAwEwYDVR0lBAwwCgYIKwYBBQUHAwEwCQYDVR0TBAIwADAdBgNVHQ4EFgQU +NXc1O5uYPLbHmueoBLl8cK36N6kwNgYIKwYBBQUHAQsEKjAoMCYGCCsGAQUFBzAE +hhpodHRwczovL2xvY2FsaG9zdDo4NDMzLzUwOTA2BggrBgEFBQcBAQQqMCgwJgYI +KwYBBQUHMASGGmh0dHBzOi8vbG9jYWxob3N0Ojg0MzMvNTA5MBoGA1UdEQQTMBGH +BH8AAAGCCWxvY2FsaG9zdDANBgkqhkiG9w0BAQQFAAOBnAAAIHkvI0V6padfc8Lv +onuNqBwCMIg4SugCslkN597Yb8ZDEAUe3ArkOvzAHUngsD5D0gfbKblKP/P0bN6Y +Ft896NmH4QFsDAetZcCFf24AM4DbUQo5jtG+dkanI/7IxxNYJ1PQ64/yscdQFvHW +xhIX3Q6FqABjcN5nc80Rog+b6eS8QRX1BRnQqbGtocuptUgW5mWsSb+DR6pZbA== -----END CERTIFICATE----- |