Hi! Here's an improved patch that makes this (presumably) SSL-backend independent. I only tested it with GnuTLS though, and some SSL backends are not supported by the patch. The patch would need to be applied on top of the 2nd patch I sent (#2 and #3 are independent of the first patch).
I hope you like this more general evolution of the API. While I did test this using code very much like the one supplied in the commit message, I cannot say what happens during SSL connection shutdown --- again, the patch expects that if the SSL connection is shut down, the "use" flag is cleared by libcurl and/or the handle(s) are reset to NULL. I toyed with the idea of returning a 'union' with the precise types from the various SSL backends instead of returning a 'void *', but that would have tied the public curl API to the various SSL APIs, which would have been ugly, so I think 'void *' should do nicely for now. Happy hacking! Christian On 10/12/2013 11:55 PM, Daniel Stenberg wrote: > On Fri, 20 Sep 2013, Christian Grothoff wrote: > >> Here is another patch which adds the CURLINFO_GNUTLS_SESSION option to >> curl_easy_getinfo. It exposes the GnuTLS session to clients, which is >> useful if clients need to inspect certificate chains or other >> properties of the TLS connection. Naturally, the option only works if >> cURL was compiled with GnuTLS support (hence the GNUTLS in the name). >> This patch should be completely independent from my previous patch to >> support CURLINFO_CERTINFO with GnuTLS, and I think it is generally >> more useful as it allows applications to access certificates via the >> nice GnuTLS X509 APIs instead of having to parse the strings. > > Hi! > > I can see why this option can be handy. I don't really like opening up > the API for even more SSL-library specific things so I would prefer if > you can think of a way that can return this information in an even more > generic way that will include information for what SSL library the > handle concerns so that we don't end up having to add a new such option > for every SSL library we want to allow this "extraction" for. > > Also, I found the code needing some comments to explain what the loop > does and I'm also a bit concerned if this really works properly in all > cases, like even if the SSL connection was completely shutdown previous > to this curl_easy_getinfo() call. How much testing have you done on this? >
From 2f2859dc000ad845c74df1e0ee6e4dd95c064093 Mon Sep 17 00:00:00 2001 From: Christian Grothoff <[email protected]> Date: Tue, 15 Oct 2013 15:17:43 +0200 Subject: [PATCH 3/3] Make the proposed certificate extraction API more SSL-backend independent by returning an enum on the backend type, as discussed on the mailinglist. Sample use: struct curl_tlsinfo tlsinfo; union { struct curl_tlsinfo *tlsinfo; struct curl_slist *to_slist; } gptr; memset (&tlsinfo, 0, sizeof (tlsinfo)); gptr.tlsinfo = &tlsinfo; if (CURLE_OK != curl_easy_getinfo (s5r->curl, CURLINFO_TLS_SESSION, &gptr)) 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 | 16 ++++++++------ include/curl/curl.h | 27 ++++++++++++++++++++++- lib/getinfo.c | 46 ++++++++++++++++++++++++++++------------ 3 files changed, 67 insertions(+), 22 deletions(-) diff --git a/docs/libcurl/curl_easy_getinfo.3 b/docs/libcurl/curl_easy_getinfo.3 index c5a509c..b88a9fb 100644 --- a/docs/libcurl/curl_easy_getinfo.3 +++ b/docs/libcurl/curl_easy_getinfo.3 @@ -222,13 +222,15 @@ for the specific named data. See also the certinfo.c example. NOTE: this option is only available in libcurl built with OpenSSL support. (Added in 7.19.1) -.IP CURLINFO_GNUTLS_SESSION -Pass a pointer to a 'gnutls_session' and you'll get it set to point to the -respective GnuTLS session used by this request. This can then be used to -extract certificate information in a format convenient for further -processing, such as manual validation. NOTE: this -option is only available in libcurl built with GnuTLS support. (Added in -7.33.0) +.IP CURLINFO_TLS_SESSION +Pass a pointer to a 'struct curl_tlsinfo *'. The struct will be initialized +to contain the type of the SSL library used for the handshake, and to 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 diff --git a/include/curl/curl.h b/include/curl/curl.h index a63ee67..45fedf8 100644 --- a/include/curl/curl.h +++ b/include/curl/curl.h @@ -1979,6 +1979,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 @@ -2030,7 +2055,7 @@ typedef enum { CURLINFO_PRIMARY_PORT = CURLINFO_LONG + 40, CURLINFO_LOCAL_IP = CURLINFO_STRING + 41, CURLINFO_LOCAL_PORT = CURLINFO_LONG + 42, - CURLINFO_GNUTLS_SESSION = CURLINFO_SLIST + 43, + CURLINFO_TLS_SESSION = CURLINFO_SLIST + 43, /* Fill in new entries below here! */ CURLINFO_LASTONE = 43 diff --git a/lib/getinfo.c b/lib/getinfo.c index 36197c2..bc792b1 100644 --- a/lib/getinfo.c +++ b/lib/getinfo.c @@ -277,30 +277,48 @@ static CURLcode getinfo_slist(struct SessionHandle *data, CURLINFO info, ptr.to_certinfo = &data->info.certs; *param_slistp = ptr.to_slist; break; -#ifdef USE_GNUTLS - case CURLINFO_GNUTLS_SESSION: + case CURLINFO_TLS_SESSION: { - union { - gnutls_session session; - struct curl_slist * to_slist; - } gptr; - struct connectdata *conn; + struct curl_tlsinfo * tlsinfo = (struct curl_tlsinfo *) *param_slistp; + struct connectdata * conn; unsigned int sockindex; + 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])) { - *param_slistp = NULL; - break; - } - gptr.session = conn->ssl[sockindex].session; - *param_slistp = gptr.to_slist; + if((sockindex == sizeof(conn->ssl)/sizeof(conn->ssl[0])) || + (NULL == conn->ssl[sockindex].session)) + 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; -#endif default: return CURLE_BAD_FUNCTION_ARGUMENT; } -- 1.8.4.rc3
0x48426C7E.asc
Description: application/pgp-keys
signature.asc
Description: OpenPGP digital signature
------------------------------------------------------------------- List admin: http://cool.haxx.se/list/listinfo/curl-library Etiquette: http://curl.haxx.se/mail/etiquette.html
