Commit 2c04e8d8 authored by Christian Grothoff's avatar Christian Grothoff Committed by Steve Holme
Browse files

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.
parent 925df535
Loading
Loading
Loading
Loading
+12 −0
Original line number Original line Diff line number Diff line
@@ -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
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
option is only available in libcurl built with OpenSSL, NSS, GSKit or QsoSSL
support. (Added in 7.19.1)
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
.IP CURLINFO_CONDITION_UNMET
Pass a pointer to a long to receive the number 1 if the condition provided in
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
the previous request didn't match (see \fICURLOPT_TIMECONDITION\fP). Alas, if
+25 −3
Original line number Original line Diff line number Diff line
@@ -1388,8 +1388,7 @@ typedef enum {
  CINIT(ADDRESS_SCOPE, LONG, 171),
  CINIT(ADDRESS_SCOPE, LONG, 171),


  /* Collect certificate chain info and allow it to get retrievable with
  /* Collect certificate chain info and allow it to get retrievable with
     CURLINFO_CERTINFO after the transfer is complete. (Unfortunately) only
     CURLINFO_CERTINFO after the transfer is complete. */
     working with OpenSSL-powered builds. */
  CINIT(CERTINFO, LONG, 172),
  CINIT(CERTINFO, LONG, 172),


  /* "name" and "pwd" to use when fetching. */
  /* "name" and "pwd" to use when fetching. */
@@ -1986,6 +1985,28 @@ struct curl_certinfo {
                                   format "name: value" */
                                   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_STRING   0x100000
#define CURLINFO_LONG     0x200000
#define CURLINFO_LONG     0x200000
#define CURLINFO_DOUBLE   0x300000
#define CURLINFO_DOUBLE   0x300000
@@ -2037,9 +2058,10 @@ typedef enum {
  CURLINFO_PRIMARY_PORT     = CURLINFO_LONG   + 40,
  CURLINFO_PRIMARY_PORT     = CURLINFO_LONG   + 40,
  CURLINFO_LOCAL_IP         = CURLINFO_STRING + 41,
  CURLINFO_LOCAL_IP         = CURLINFO_STRING + 41,
  CURLINFO_LOCAL_PORT       = CURLINFO_LONG   + 42,
  CURLINFO_LOCAL_PORT       = CURLINFO_LONG   + 42,
  CURLINFO_TLS_SESSION      = CURLINFO_SLIST  + 43,
  /* Fill in new entries below here! */
  /* Fill in new entries below here! */


  CURLINFO_LASTONE          = 42
  CURLINFO_LASTONE          = 43
} CURLINFO;
} CURLINFO;


/* CURLINFO_RESPONSE_CODE is the new name for the option previously known as
/* CURLINFO_RESPONSE_CODE is the new name for the option previously known as
+46 −0
Original line number Original line Diff line number Diff line
@@ -277,7 +277,53 @@ static CURLcode getinfo_slist(struct SessionHandle *data, CURLINFO info,
    ptr.to_certinfo = &data->info.certs;
    ptr.to_certinfo = &data->info.certs;
    *param_slistp = ptr.to_slist;
    *param_slistp = ptr.to_slist;
    break;
    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:
  default:
    return CURLE_BAD_FUNCTION_ARGUMENT;
    return CURLE_BAD_FUNCTION_ARGUMENT;
  }
  }
+2 −0
Original line number Original line Diff line number Diff line
@@ -1637,6 +1637,8 @@ struct SessionHandle {
                                  other dynamic purposes */
                                  other dynamic purposes */
  struct WildcardData wildcard; /* wildcard download state info */
  struct WildcardData wildcard; /* wildcard download state info */
  struct PureInfo info;        /* stats, reports and info data */
  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)
#if defined(CURL_DOES_CONVERSIONS) && defined(HAVE_ICONV)
  iconv_t outbound_cd;         /* for translating to the network encoding */
  iconv_t outbound_cd;         /* for translating to the network encoding */
  iconv_t inbound_cd;          /* for translating from the network encoding */
  iconv_t inbound_cd;          /* for translating from the network encoding */