curl_easy_getinfo: Added CURLINFO_TLS_SESSION for accessing TLS internals
authorChristian Grothoff <christian@grothoff.org>
Sun, 17 Nov 2013 19:49:16 +0000 (20:49 +0100)
committerSteve Holme <steve_holme@hotmail.com>
Thu, 21 Nov 2013 20:40:04 +0000 (20:40 +0000)
Added new API for returning a SSL backend type and pointer, in order to
allow access to the TLS internals, that may then be used to obtain X509
certificate information for example.

docs/libcurl/curl_easy_getinfo.3
include/curl/curl.h
lib/getinfo.c
lib/urldata.h

index db0f4d6..8d000c0 100644 (file)
@@ -221,6 +221,18 @@ provided in a series of data in the format "name:content" where the content is
 for the specific named data. See also the certinfo.c example. NOTE: this
 option is only available in libcurl built with OpenSSL, NSS, GSKit or QsoSSL
 support. (Added in 7.19.1)
+.IP CURLINFO_TLS_SESSION
+Pass a pointer to a 'struct curl_tlsinfo *'.  The pointer will be initialized
+to refer to a 'struct curl_tlsinfo *' that will contain an enum indicating the
+SSL library used for the handshake and the respective internal TLS session
+structure of this underlying SSL library.
+
+This may then be used to extract certificate information in a format
+convenient for further processing, such as manual validation. NOTE: this
+option may not be available for all SSL backends; unsupported SSL backends
+will return 'CURLSSLBACKEND_NONE' to indicate that they are not supported;
+this does not mean that no SSL backend was used. (Added in 7.34.0)
+
 .IP CURLINFO_CONDITION_UNMET
 Pass a pointer to a long to receive the number 1 if the condition provided in
 the previous request didn't match (see \fICURLOPT_TIMECONDITION\fP). Alas, if
index 14ff7c7..b58939b 100644 (file)
@@ -1388,8 +1388,7 @@ typedef enum {
   CINIT(ADDRESS_SCOPE, LONG, 171),
 
   /* Collect certificate chain info and allow it to get retrievable with
-     CURLINFO_CERTINFO after the transfer is complete. (Unfortunately) only
-     working with OpenSSL-powered builds. */
+     CURLINFO_CERTINFO after the transfer is complete. */
   CINIT(CERTINFO, LONG, 172),
 
   /* "name" and "pwd" to use when fetching. */
@@ -1986,6 +1985,28 @@ struct curl_certinfo {
                                    format "name: value" */
 };
 
+/* enum for the different supported SSL backends */
+typedef enum {
+  CURLSSLBACKEND_NONE = 0,
+  CURLSSLBACKEND_OPENSSL = 1,
+  CURLSSLBACKEND_GNUTLS = 2,
+  CURLSSLBACKEND_NSS = 3,
+  CURLSSLBACKEND_QSOSSL = 4,
+  CURLSSLBACKEND_GSKIT = 5,
+  CURLSSLBACKEND_POLARSSL = 6,
+  CURLSSLBACKEND_CYASSL = 7,
+  CURLSSLBACKEND_SCHANNEL = 8,
+  CURLSSLBACKEND_DARWINSSL = 9
+} curl_ssl_backend;
+
+/* Information about the SSL library used and the respective internal SSL
+   handle, which can be used to obtain further information regarding the
+   connection. Asked for with CURLINFO_TLS_SESSION. */
+struct curl_tlsinfo {
+  curl_ssl_backend ssl_backend;
+  void *internals;
+};
+
 #define CURLINFO_STRING   0x100000
 #define CURLINFO_LONG     0x200000
 #define CURLINFO_DOUBLE   0x300000
@@ -2037,9 +2058,10 @@ typedef enum {
   CURLINFO_PRIMARY_PORT     = CURLINFO_LONG   + 40,
   CURLINFO_LOCAL_IP         = CURLINFO_STRING + 41,
   CURLINFO_LOCAL_PORT       = CURLINFO_LONG   + 42,
+  CURLINFO_TLS_SESSION      = CURLINFO_SLIST  + 43,
   /* Fill in new entries below here! */
 
-  CURLINFO_LASTONE          = 42
+  CURLINFO_LASTONE          = 43
 } CURLINFO;
 
 /* CURLINFO_RESPONSE_CODE is the new name for the option previously known as
index 3d09dc6..6a4e72e 100644 (file)
@@ -277,7 +277,53 @@ static CURLcode getinfo_slist(struct SessionHandle *data, CURLINFO info,
     ptr.to_certinfo = &data->info.certs;
     *param_slistp = ptr.to_slist;
     break;
+  case CURLINFO_TLS_SESSION:
+    {
+      struct curl_tlsinfo **tlsinfop = (struct curl_tlsinfo **) param_slistp;
+      struct curl_tlsinfo *tlsinfo = &data->tlsinfo;
+      struct connectdata *conn = data->easy_conn;
+      unsigned int sockindex = 0;
 
+      *tlsinfop = tlsinfo;
+      tlsinfo->ssl_backend = CURLSSLBACKEND_NONE;
+      tlsinfo->internals = NULL;
+
+      /* Find the active ("in use") SSL connection, if any */
+      while((sockindex < sizeof(conn->ssl) / sizeof(conn->ssl[0])) &&
+            (!conn->ssl[sockindex].use))
+        sockindex++;
+
+      if(sockindex == sizeof(conn->ssl) / sizeof(conn->ssl[0]))
+        break; /* no SSL session found */
+
+      /* Return the TLS session information from the relevant backend */
+#ifdef USE_SSLEAY
+      tlsinfo->ssl_backend = CURLSSLBACKEND_OPENSSL;
+      tlsinfo->internals = conn->ssl[sockindex].ctx;
+#endif
+#ifdef USE_GNUTLS
+      tlsinfo->ssl_backend = CURLSSLBACKEND_GNUTLS;
+      tlsinfo->internals = conn->ssl[sockindex].session;
+#endif
+#ifdef USE_NSS
+      tlsinfo->ssl_backend = CURLSSLBACKEND_NSS;
+      tlsinfo->internals = conn->ssl[sockindex].handle;
+#endif
+#ifdef USE_QSOSSL
+      tlsinfo->ssl_backend = CURLSSLBACKEND_QSOSSL;
+      tlsinfo->internals = conn->ssl[sockindex].handle;
+#endif
+#ifdef USE_GSKIT
+      tlsinfo->ssl_backend = CURLSSLBACKEND_GSKIT;
+      tlsinfo->internals = conn->ssl[sockindex].handle;
+#endif
+      /* NOTE: For other SSL backends, it is not immediately clear what data
+         to return from 'struct ssl_connect_data'; thus, for now we keep the
+         backend as CURLSSLBACKEND_NONE in those cases, which should be
+         interpreted as "not supported" */
+      break;
+    }
+    break;
   default:
     return CURLE_BAD_FUNCTION_ARGUMENT;
   }
index 98686bb..29cf960 100644 (file)
@@ -1637,6 +1637,8 @@ struct SessionHandle {
                                   other dynamic purposes */
   struct WildcardData wildcard; /* wildcard download state info */
   struct PureInfo info;        /* stats, reports and info data */
+  struct curl_tlsinfo tlsinfo; /* Information about the TLS session, only
+                                  valid after a client has asked for it */
 #if defined(CURL_DOES_CONVERSIONS) && defined(HAVE_ICONV)
   iconv_t outbound_cd;         /* for translating to the network encoding */
   iconv_t inbound_cd;          /* for translating from the network encoding */