Index: include/curl/curl.h
===================================================================
RCS file: /cvsroot/curl/curl/include/curl/curl.h,v
retrieving revision 1.321
diff -u -r1.321 curl.h
--- include/curl/curl.h	1 Jul 2007 22:01:19 -0000	1.321
+++ include/curl/curl.h	16 Aug 2007 11:18:10 -0000
@@ -1507,6 +1507,7 @@
   CURL_LOCK_DATA_DNS,
   CURL_LOCK_DATA_SSL_SESSION,
   CURL_LOCK_DATA_CONNECT,
+  CURL_LOCK_DATA_SSL_CTX,
   CURL_LOCK_DATA_LAST
 } curl_lock_data;
 
Index: lib/share.c
===================================================================
RCS file: /cvsroot/curl/curl/lib/share.c,v
retrieving revision 1.22
diff -u -r1.22 share.c
--- lib/share.c	5 Dec 2004 23:59:32 -0000	1.22
+++ lib/share.c	16 Aug 2007 11:18:11 -0000
@@ -27,11 +27,17 @@
 #include <string.h>
 #include <curl/curl.h>
 #include "urldata.h"
+#include "sslgen.h"
 #include "share.h"
 #include "memory.h"
 
 /* The last #include file should be: */
 #include "memdebug.h"
+static void ssl_ctx_cache_dtor(void* user,void* ptr)
+{
+
+}
+
 
 CURLSH *
 curl_share_init(void)
@@ -52,6 +58,7 @@
   struct Curl_share *share = (struct Curl_share *)sh;
   va_list param;
   int type;
+  int size;
   curl_lock_function lockfunc;
   curl_unlock_function unlockfunc;
   void *ptr;
@@ -87,9 +94,17 @@
       break;
 #endif   /* CURL_DISABLE_HTTP */
 
+    case CURL_LOCK_DATA_SSL_CTX:
+      if ( !share->ssl_ctx_cache ) {
+        share->ssl_ctx_cache = Curl_llist_alloc(ssl_ctx_cache_dtor);
+        if(!share->ssl_ctx_cache)
+          return CURLSHE_NOMEM;
+      }
+      break;
     case CURL_LOCK_DATA_SSL_SESSION: /* not supported (yet) */
     case CURL_LOCK_DATA_CONNECT:     /* not supported (yet) */
 
+
     default:
       return CURLSHE_BAD_OPTION;
     }
@@ -175,6 +190,8 @@
   if(share->cookies)
     Curl_cookie_cleanup(share->cookies);
 #endif   /* CURL_DISABLE_HTTP */
+  if ( share->ssl_ctx_cache )
+    Curl_ssl_ctx_cleanup(share->ssl_ctx_cache);
 
   if(share->unlockfunc)
     share->unlockfunc(NULL, CURL_LOCK_DATA_SHARE, share->clientdata);
Index: lib/share.h
===================================================================
RCS file: /cvsroot/curl/curl/lib/share.h,v
retrieving revision 1.11
diff -u -r1.11 share.h
--- lib/share.h	26 Apr 2006 17:11:05 -0000	1.11
+++ lib/share.h	16 Aug 2007 11:18:11 -0000
@@ -47,6 +47,7 @@
 
   struct curl_hash *hostcache;
   struct CookieInfo *cookies;
+  struct curl_llist *ssl_ctx_cache;
 };
 
 CURLSHcode Curl_share_lock (struct SessionHandle *, curl_lock_data,
Index: lib/sslgen.c
===================================================================
RCS file: /cvsroot/curl/curl/lib/sslgen.c,v
retrieving revision 1.27
diff -u -r1.27 sslgen.c
--- lib/sslgen.c	1 Aug 2007 21:20:01 -0000	1.27
+++ lib/sslgen.c	16 Aug 2007 11:18:11 -0000
@@ -741,3 +741,11 @@
   return FALSE; /* nothing pending */
 
 }
+
+void Curl_ssl_ctx_cleanup(struct curl_llist* ssl_ctx_cache) {
+#ifdef USE_SSLEAY
+  Curl_ossl_ctx_cleanup(ssl_ctx_cache);
+#else
+  (void)ssl_ctx_cache;
+#endif
+}
Index: lib/sslgen.h
===================================================================
RCS file: /cvsroot/curl/curl/lib/sslgen.h,v
retrieving revision 1.10
diff -u -r1.10 sslgen.h
--- lib/sslgen.h	29 Jul 2007 12:54:05 -0000	1.10
+++ lib/sslgen.h	16 Aug 2007 11:18:11 -0000
@@ -74,6 +74,8 @@
 bool Curl_ssl_data_pending(struct connectdata *conn,
                            int connindex);
 
+void Curl_ssl_ctx_cleanup(struct curl_llist* ssl_ctx_cache);
+
 #if !defined(USE_SSL) && !defined(SSLGEN_C)
 /* set up blank macros for none-SSL builds */
 #define Curl_ssl_close_all(x)
Index: lib/ssluse.c
===================================================================
RCS file: /cvsroot/curl/curl/lib/ssluse.c,v
retrieving revision 1.181
diff -u -r1.181 ssluse.c
--- lib/ssluse.c	7 Aug 2007 12:44:41 -0000	1.181
+++ lib/ssluse.c	16 Aug 2007 11:18:14 -0000
@@ -50,6 +50,7 @@
 #include "strequal.h"
 #include "select.h"
 #include "sslgen.h"
+#include "share.h"
 
 #define _MPRINTF_REPLACE /* use the internal *printf() functions */
 #include <curl/mprintf.h>
@@ -112,6 +113,78 @@
 #define SSL_METHOD_QUAL
 #endif
 
+/* based on the ssl method we look for existing SSL_CTX objects. There is an
+ * underlying assumption that the following properties  are fixed across
+ * different SessionHandles:
+ * data->set.cert
+ * data->set.ssl.cipher_list
+ * data->set.ssl.CAfile || data->set.ssl.CApath
+ */
+
+static SSL_CTX* acquire_ssl_ctx(struct ssl_connect_data *connssl,
+								struct SessionHandle *data,
+                                SSL_METHOD_QUAL SSL_METHOD *req_method,
+                                bool* cached)
+{
+  struct Curl_share *share = data->share;
+  SSL_CTX* ctx = 0;
+
+  *cached = FALSE;
+  /* transfer the share handle to the connection cache, so it may be accessed
+   * after the data is freed */
+  if ( share )
+	connssl->share = share;
+
+  if ( share && share->ssl_ctx_cache && share->ssl_ctx_cache->head ) {
+    struct curl_llist_element* p;
+
+    Curl_share_lock(data, CURL_LOCK_DATA_SSL_CTX, CURL_LOCK_ACCESS_SINGLE);
+
+    p = share->ssl_ctx_cache->head;
+    for (; p; p = p->next)
+      if ( ((SSL_CTX*)p->ptr)->method==req_method )
+        break;
+    if ( p ) {
+      ctx = (SSL_CTX*)p->ptr;
+      *cached = TRUE;
+      infof(data, "using cached SSL_CTX\n");
+    }
+
+    Curl_share_unlock(data, CURL_LOCK_DATA_SSL_CTX);
+  }
+
+  if ( !ctx ) {
+    infof(data, "instantiating new SSL_CTX\n");
+	ctx = SSL_CTX_new(req_method);
+    if ( share && share->ssl_ctx_cache )
+	  Curl_llist_insert_next(share->ssl_ctx_cache,share->ssl_ctx_cache->tail,ctx);
+  }
+  return ctx;
+}
+
+static void release_ssl_ctx(struct Curl_share *share,
+							SSL_CTX* ctx)
+{
+  /* if we have a ctx_cache then there is nothing to do, otherwise
+   * we free the context object */
+  if ( !share || !share->ssl_ctx_cache )
+    SSL_CTX_free(ctx);
+}
+
+void Curl_ossl_ctx_cleanup(struct curl_llist* ssl_ctx_cache)
+{
+  if ( ssl_ctx_cache ) {
+    /* note that we can't call the lock/unlock functions, as no SessionHandle
+     * is available */
+    struct curl_llist_element* p = ssl_ctx_cache->head;
+    for (; p; p = p->next)
+      SSL_CTX_free((SSL_CTX*)p->ptr);
+
+    Curl_llist_destroy(ssl_ctx_cache,0);
+  }
+}
+
+
 /*
  * Number of bytes to read from the random number seed file. This must be
  * a finite value (because some entropy "files" like /dev/urandom have
@@ -718,7 +791,7 @@
     connssl->handle = NULL;
   }
   if(connssl->ctx) {
-    SSL_CTX_free (connssl->ctx);
+    release_ssl_ctx(connssl->share,connssl->ctx);
     connssl->ctx = NULL;
   }
 }
@@ -1275,6 +1348,7 @@
   void *ssl_sessionid=NULL;
   curl_socket_t sockfd = conn->sock[sockindex];
   struct ssl_connect_data *connssl = &conn->ssl[sockindex];
+  bool cached;
 
   DEBUGASSERT(ssl_connect_1 == connssl->connecting_state);
 
@@ -1299,9 +1373,8 @@
     break;
   }
 
-  if (connssl->ctx)
-    SSL_CTX_free(connssl->ctx);
-  connssl->ctx = SSL_CTX_new(req_method);
+  if ( !connssl->ctx )
+    connssl->ctx = acquire_ssl_ctx(connssl,data,req_method,&cached);
 
   if(!connssl->ctx) {
     failf(data, "SSL: couldn't create a context!");
@@ -1343,7 +1416,7 @@
     SSL_CTX_ctrl(connssl->ctx, BIO_C_SET_NBIO, 1, NULL);
 #endif
 
-  if(data->set.str[STRING_CERT]) {
+  if(!cached && data->set.str[STRING_CERT]) {
     if(!cert_stuff(conn,
                    connssl->ctx,
                    data->set.str[STRING_CERT],
@@ -1355,7 +1428,7 @@
     }
   }
 
-  if(data->set.str[STRING_SSL_CIPHER_LIST]) {
+  if(!cached && data->set.str[STRING_SSL_CIPHER_LIST]) {
     if(!SSL_CTX_set_cipher_list(connssl->ctx,
                                 data->set.str[STRING_SSL_CIPHER_LIST])) {
       failf(data, "failed setting cipher list");
@@ -1363,7 +1436,7 @@
     }
   }
 
-  if (data->set.str[STRING_SSL_CAFILE] || data->set.str[STRING_SSL_CAPATH]) {
+  if (!cached && (data->set.str[STRING_SSL_CAFILE] || data->set.str[STRING_SSL_CAPATH]) ) {
     /* tell SSL where to find CA certificates that are used to verify
        the servers certificate. */
     if (!SSL_CTX_load_verify_locations(connssl->ctx,
Index: lib/ssluse.h
===================================================================
RCS file: /cvsroot/curl/curl/lib/ssluse.h,v
retrieving revision 1.29
diff -u -r1.29 ssluse.h
--- lib/ssluse.h	29 Jul 2007 12:54:05 -0000	1.29
+++ lib/ssluse.h	16 Aug 2007 11:18:14 -0000
@@ -70,6 +70,7 @@
 int Curl_ossl_check_cxn(struct connectdata *cxn);
 int Curl_ossl_seed(struct SessionHandle *data);
 
+void Curl_ossl_ctx_cleanup(struct curl_llist* ssl_ctx_cache);
 int Curl_ossl_shutdown(struct connectdata *conn, int sockindex);
 
 #endif
Index: lib/urldata.h
===================================================================
RCS file: /cvsroot/curl/curl/lib/urldata.h,v
retrieving revision 1.340
diff -u -r1.340 urldata.h
--- lib/urldata.h	1 Aug 2007 21:20:01 -0000	1.340
+++ lib/urldata.h	16 Aug 2007 11:18:17 -0000
@@ -169,6 +169,7 @@
   bool use;        /* use ssl encrypted communications TRUE/FALSE, not
                       necessarily using it atm but at least asked to or
                       meaning to use it */
+  struct Curl_share *share; /* direct access to the share handle */
 #ifdef USE_SSLEAY
   /* these ones requires specific SSL-types */
   SSL_CTX* ctx;
