curl_easy_getinfo: Added CURLINFO_TLS_SESSION for accessing TLS internals

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.
This commit is contained in:
Christian Grothoff 2013-11-17 20:49:16 +01:00 committed by Steve Holme
parent 925df53580
commit 2c04e8d80c
4 changed files with 85 additions and 3 deletions

View 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

View 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

View 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;
}

View 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 */