curl-library
[PATCH] Implement SSL-backend independent API to access TLS internals, in particular the X509 certificate information.
From: Christian Grothoff <christian_at_grothoff.org>
Date: Sun, 17 Nov 2013 20:49:16 +0100
Date: Sun, 17 Nov 2013 20:49:16 +0100
The new API returns an SSL-backend dependent pointer and
an enum on the backend type, as discussed on the mailinglist.
Sample use:
struct curl_tlsinfo *tlsinfo;
if (CURLE_OK !=
curl_easy_getinfo (s5r->curl,
CURLINFO_TLS_SESSION,
&tlsinfo))
return SYSERR;
if (CURLSSLBACKEND_GNUTLS != tlsinfo->ssl_backend)
{
// error: Unsupported SSL backend
return SYSERR;
}
... = gnutls_certificate_get_peers (tlsinfo->internals, ...);
--- docs/libcurl/curl_easy_getinfo.3 | 12 +++++++++++ include/curl/curl.h | 31 +++++++++++++++++++++++++--- lib/getinfo.c | 42 ++++++++++++++++++++++++++++++++++++++ lib/urldata.h | 2 ++ 4 files changed, 84 insertions(+), 3 deletions(-) diff --git a/docs/libcurl/curl_easy_getinfo.3 b/docs/libcurl/curl_easy_getinfo.3 index db0f4d6..f7be3f6 100644 --- a/docs/libcurl/curl_easy_getinfo.3 +++ b/docs/libcurl/curl_easy_getinfo.3 @@ -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 *' which will contain the type of the SSL +library used for the handshake, and the respective internal TLS session +structure of this underlying SSL library. +This can 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 +may 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 diff --git a/include/curl/curl.h b/include/curl/curl.h index 14ff7c7..735de4a 100644 --- a/include/curl/curl.h +++ b/include/curl/curl.h @@ -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,31 @@ struct curl_certinfo { format "name: value" */ }; + +/* enum for the different SSL backends supported by cURL. */ +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; + + +/* info about the SSL library used, and the respective internal + SSL handle that can be used to extract further information about + 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 +2061,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 diff --git a/lib/getinfo.c b/lib/getinfo.c index 3d09dc6..fd519e2 100644 --- a/lib/getinfo.c +++ b/lib/getinfo.c @@ -277,7 +277,49 @@ 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; + unsigned int sockindex; + *tlsinfop = tlsinfo; + tlsinfo->ssl_backend = CURLSSLBACKEND_NONE; + conn = data->easy_conn; + sockindex = 0; + /* find 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 */ +#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 member(s) to return from 'struct ssl_connect_data'; + thus, for now we keep the backend on CURLSSLBACKEND_NONE in + those cases, which should be interpreted as "not supported" */ + break; + } + break; default: return CURLE_BAD_FUNCTION_ARGUMENT; } diff --git a/lib/urldata.h b/lib/urldata.h index 98686bb..f2c2b43 100644 --- a/lib/urldata.h +++ b/lib/urldata.h @@ -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 TLS session, only + initialized after a client 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 */ -- 1.7.10.4 --------------070401000804020307090802 Content-Type: text/plain; charset="us-ascii" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit Content-Disposition: inline ------------------------------------------------------------------- List admin: http://cool.haxx.se/list/listinfo/curl-library Etiquette: http://curl.haxx.se/mail/etiquette.html --------------070401000804020307090802--Received on 2001-09-17