mirror of
https://github.com/curl/curl.git
synced 2026-05-30 13:57:28 +03:00
writeout: add %{certs} and %{num_certs}
Let users get the server certificate chain using the command line Closes #10019
This commit is contained in:
parent
db5f833cc7
commit
c6aa19c1da
7 changed files with 77 additions and 2 deletions
|
|
@ -37,6 +37,10 @@ occurrences of % must be doubled when using this option.
|
|||
The variables available are:
|
||||
.RS
|
||||
.TP 15
|
||||
.B certs
|
||||
Output the certificate chain with details. Supported only by the OpenSSL,
|
||||
GnuTLS, Schannel, NSS, GSKit and Secure Transport backends (Added in 7.88.0)
|
||||
.TP
|
||||
.B content_type
|
||||
The Content-Type of the requested document, if there was any.
|
||||
.TP
|
||||
|
|
@ -89,6 +93,11 @@ The local port number of the most recently done connection. (Added in 7.29.0)
|
|||
.B method
|
||||
The http method used in the most recent HTTP request. (Added in 7.72.0)
|
||||
.TP
|
||||
.B num_certs
|
||||
Number of server certificates received in the TLS handshake. Supported only by
|
||||
the OpenSSL, GnuTLS, Schannel, NSS, GSKit and Secure Transport backends (Added
|
||||
in 7.88.0)
|
||||
.TP
|
||||
.B num_connects
|
||||
Number of new connects made in the recent transfer. (Added in 7.12.3)
|
||||
.TP
|
||||
|
|
|
|||
|
|
@ -1553,6 +1553,9 @@ static CURLcode single_transfer(struct GlobalConfig *global,
|
|||
if(config->ssl_ec_curves)
|
||||
my_setopt_str(curl, CURLOPT_SSL_EC_CURVES, config->ssl_ec_curves);
|
||||
|
||||
if(config->writeout)
|
||||
my_setopt_str(curl, CURLOPT_CERTINFO, 1L);
|
||||
|
||||
if(feature_ssl) {
|
||||
/* Check if config->cert is a PKCS#11 URI and set the
|
||||
* config->cert_type if necessary */
|
||||
|
|
|
|||
|
|
@ -33,6 +33,7 @@ struct per_transfer {
|
|||
struct per_transfer *next;
|
||||
struct per_transfer *prev;
|
||||
struct OperationConfig *config; /* for this transfer */
|
||||
struct curl_certinfo *certinfo;
|
||||
CURL *curl;
|
||||
long retry_numretries;
|
||||
long retry_sleep_default;
|
||||
|
|
|
|||
|
|
@ -28,6 +28,7 @@
|
|||
#include "tool_cfgable.h"
|
||||
#include "tool_writeout.h"
|
||||
#include "tool_writeout_json.h"
|
||||
#include "dynbuf.h"
|
||||
|
||||
#include "memdebug.h" /* keep this as LAST include */
|
||||
|
||||
|
|
@ -72,6 +73,7 @@ static const struct httpmap http_version[] = {
|
|||
Variable names should be in alphabetical order.
|
||||
*/
|
||||
static const struct writeoutvar variables[] = {
|
||||
{"certs", VAR_CERT, CURLINFO_NONE, writeString},
|
||||
{"content_type", VAR_CONTENT_TYPE, CURLINFO_CONTENT_TYPE, writeString},
|
||||
{"errormsg", VAR_ERRORMSG, CURLINFO_NONE, writeString},
|
||||
{"exitcode", VAR_EXITCODE, CURLINFO_NONE, writeLong},
|
||||
|
|
@ -85,6 +87,7 @@ static const struct writeoutvar variables[] = {
|
|||
{"local_ip", VAR_LOCAL_IP, CURLINFO_LOCAL_IP, writeString},
|
||||
{"local_port", VAR_LOCAL_PORT, CURLINFO_LOCAL_PORT, writeLong},
|
||||
{"method", VAR_EFFECTIVE_METHOD, CURLINFO_EFFECTIVE_METHOD, writeString},
|
||||
{"num_certs", VAR_NUM_CERTS, CURLINFO_NONE, writeLong},
|
||||
{"num_connects", VAR_NUM_CONNECTS, CURLINFO_NUM_CONNECTS, writeLong},
|
||||
{"num_headers", VAR_NUM_HEADERS, CURLINFO_NONE, writeLong},
|
||||
{"num_redirects", VAR_REDIRECT_COUNT, CURLINFO_REDIRECT_COUNT, writeLong},
|
||||
|
|
@ -168,6 +171,8 @@ static int writeString(FILE *stream, const struct writeoutvar *wovar,
|
|||
{
|
||||
bool valid = false;
|
||||
const char *strinfo = NULL;
|
||||
struct dynbuf buf;
|
||||
curlx_dyn_init(&buf, 256*1024);
|
||||
|
||||
DEBUGASSERT(wovar->writefunc == writeString);
|
||||
|
||||
|
|
@ -193,6 +198,51 @@ static int writeString(FILE *stream, const struct writeoutvar *wovar,
|
|||
}
|
||||
else {
|
||||
switch(wovar->id) {
|
||||
case VAR_CERT:
|
||||
if(per->certinfo) {
|
||||
int i;
|
||||
bool error = FALSE;
|
||||
for(i = 0; (i < per->certinfo->num_of_certs) && !error; i++) {
|
||||
struct curl_slist *slist;
|
||||
|
||||
for(slist = per->certinfo->certinfo[i]; slist; slist = slist->next) {
|
||||
size_t len;
|
||||
if(curl_strnequal(slist->data, "cert:", 5)) {
|
||||
if(curlx_dyn_add(&buf, &slist->data[5])) {
|
||||
error = TRUE;
|
||||
break;
|
||||
}
|
||||
}
|
||||
else {
|
||||
if(curlx_dyn_add(&buf, slist->data)) {
|
||||
error = TRUE;
|
||||
break;
|
||||
}
|
||||
}
|
||||
len = curlx_dyn_len(&buf);
|
||||
if(len) {
|
||||
char *ptr = curlx_dyn_ptr(&buf);
|
||||
if(ptr[len -1] != '\n') {
|
||||
/* add a newline to make things look better */
|
||||
if(curlx_dyn_addn(&buf, "\n", 1)) {
|
||||
error = TRUE;
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
if(!error) {
|
||||
strinfo = curlx_dyn_ptr(&buf);
|
||||
if(!strinfo)
|
||||
/* maybe not a TLS protocol */
|
||||
strinfo = "";
|
||||
valid = true;
|
||||
}
|
||||
}
|
||||
else
|
||||
strinfo = ""; /* no cert info */
|
||||
break;
|
||||
case VAR_ERRORMSG:
|
||||
if(per_result) {
|
||||
strinfo = (per->errorbuffer && per->errorbuffer[0]) ?
|
||||
|
|
@ -232,6 +282,7 @@ static int writeString(FILE *stream, const struct writeoutvar *wovar,
|
|||
fprintf(stream, "\"%s\":null", wovar->name);
|
||||
}
|
||||
|
||||
curlx_dyn_free(&buf);
|
||||
return 1; /* return 1 if anything was written */
|
||||
}
|
||||
|
||||
|
|
@ -250,6 +301,10 @@ static int writeLong(FILE *stream, const struct writeoutvar *wovar,
|
|||
}
|
||||
else {
|
||||
switch(wovar->id) {
|
||||
case VAR_NUM_CERTS:
|
||||
longinfo = per->certinfo ? per->certinfo->num_of_certs : 0;
|
||||
valid = true;
|
||||
break;
|
||||
case VAR_NUM_HEADERS:
|
||||
longinfo = per->num_headers;
|
||||
valid = true;
|
||||
|
|
@ -327,6 +382,11 @@ void ourWriteOut(const char *writeinfo, struct per_transfer *per,
|
|||
FILE *stream = stdout;
|
||||
const char *ptr = writeinfo;
|
||||
bool done = FALSE;
|
||||
struct curl_certinfo *certinfo;
|
||||
CURLcode res = curl_easy_getinfo(per->curl, CURLINFO_CERTINFO, &certinfo);
|
||||
|
||||
if(!res && certinfo)
|
||||
per->certinfo = certinfo;
|
||||
|
||||
while(ptr && *ptr && !done) {
|
||||
if('%' == *ptr && ptr[1]) {
|
||||
|
|
|
|||
|
|
@ -29,6 +29,7 @@
|
|||
typedef enum {
|
||||
VAR_NONE, /* must be the first */
|
||||
VAR_APPCONNECT_TIME,
|
||||
VAR_CERT,
|
||||
VAR_CONNECT_TIME,
|
||||
VAR_CONTENT_TYPE,
|
||||
VAR_EFFECTIVE_FILENAME,
|
||||
|
|
@ -47,6 +48,7 @@ typedef enum {
|
|||
VAR_LOCAL_IP,
|
||||
VAR_LOCAL_PORT,
|
||||
VAR_NAMELOOKUP_TIME,
|
||||
VAR_NUM_CERTS,
|
||||
VAR_NUM_CONNECTS,
|
||||
VAR_NUM_HEADERS,
|
||||
VAR_ONERROR,
|
||||
|
|
|
|||
|
|
@ -59,7 +59,7 @@ Accept: */*
|
|||
|
||||
</protocol>
|
||||
<stdout nonewline="yes">
|
||||
{"content_type":"text/html","errormsg":null,"exitcode":0,"filename_effective":"log/out%TESTNUMBER","ftp_entry_path":null,"http_code":200,"http_connect":0,"http_version":"1.1","local_ip":"127.0.0.1","local_port":13,"method":"GET","num_connects":1,"num_headers":9,"num_redirects":0,"proxy_ssl_verify_result":0,"redirect_url":null,"referer":null,"remote_ip":"%HOSTIP","remote_port":%HTTPPORT,"response_code":200,"scheme":"HTTP","size_download":445,"size_header":4019,"size_request":4019,"size_upload":0,"speed_download":13,"speed_upload":13,"ssl_verify_result":0,"time_appconnect":0.000013,"time_connect":0.000013,"time_namelookup":0.000013,"time_pretransfer":0.000013,"time_redirect":0.000013,"time_starttransfer":0.000013,"time_total":0.000013,"url":"http://%HOSTIP:%HTTPPORT/%TESTNUMBER","url_effective":"http://%HOSTIP:%HTTPPORT/%TESTNUMBER","urlnum":0,"curl_version":"curl-unit-test-fake-version"}
|
||||
{"certs":"","content_type":"text/html","errormsg":null,"exitcode":0,"filename_effective":"log/out%TESTNUMBER","ftp_entry_path":null,"http_code":200,"http_connect":0,"http_version":"1.1","local_ip":"127.0.0.1","local_port":13,"method":"GET","num_certs":0,"num_connects":1,"num_headers":9,"num_redirects":0,"proxy_ssl_verify_result":0,"redirect_url":null,"referer":null,"remote_ip":"%HOSTIP","remote_port":%HTTPPORT,"response_code":200,"scheme":"HTTP","size_download":445,"size_header":4019,"size_request":4019,"size_upload":0,"speed_download":13,"speed_upload":13,"ssl_verify_result":0,"time_appconnect":0.000013,"time_connect":0.000013,"time_namelookup":0.000013,"time_pretransfer":0.000013,"time_redirect":0.000013,"time_starttransfer":0.000013,"time_total":0.000013,"url":"http://%HOSTIP:%HTTPPORT/%TESTNUMBER","url_effective":"http://%HOSTIP:%HTTPPORT/%TESTNUMBER","urlnum":0,"curl_version":"curl-unit-test-fake-version"}
|
||||
</stdout>
|
||||
</verify>
|
||||
</testcase>
|
||||
|
|
|
|||
|
|
@ -60,7 +60,7 @@ Accept: */*
|
|||
|
||||
</protocol>
|
||||
<stdout mode="text">
|
||||
{"content_type":"text/html","errormsg":null,"exitcode":0,"filename_effective":"log/out972","ftp_entry_path":null,"http_code":200,"http_connect":0,"http_version":"1.1","local_ip":"%HOSTIP","local_port":13,"method":"GET","num_connects":1,"num_headers":9,"num_redirects":0,"proxy_ssl_verify_result":0,"redirect_url":null,"referer":null,"remote_ip":"%HOSTIP","remote_port":%HTTPPORT,"response_code":200,"scheme":"HTTP","size_download":445,"size_header":4019,"size_request":4019,"size_upload":0,"speed_download":13,"speed_upload":13,"ssl_verify_result":0,"time_appconnect":0.000013,"time_connect":0.000013,"time_namelookup":0.000013,"time_pretransfer":0.000013,"time_redirect":0.000013,"time_starttransfer":0.000013,"time_total":0.000013,"url":"http://%HOSTIP:%HTTPPORT/%TESTNUMBER","url_effective":"http://%HOSTIP:%HTTPPORT/%TESTNUMBER","urlnum":0,"curl_version":"curl-unit-test-fake-version"}
|
||||
{"certs":"","content_type":"text/html","errormsg":null,"exitcode":0,"filename_effective":"log/out972","ftp_entry_path":null,"http_code":200,"http_connect":0,"http_version":"1.1","local_ip":"%HOSTIP","local_port":13,"method":"GET","num_certs":0,"num_connects":1,"num_headers":9,"num_redirects":0,"proxy_ssl_verify_result":0,"redirect_url":null,"referer":null,"remote_ip":"%HOSTIP","remote_port":%HTTPPORT,"response_code":200,"scheme":"HTTP","size_download":445,"size_header":4019,"size_request":4019,"size_upload":0,"speed_download":13,"speed_upload":13,"ssl_verify_result":0,"time_appconnect":0.000013,"time_connect":0.000013,"time_namelookup":0.000013,"time_pretransfer":0.000013,"time_redirect":0.000013,"time_starttransfer":0.000013,"time_total":0.000013,"url":"http://%HOSTIP:%HTTPPORT/%TESTNUMBER","url_effective":"http://%HOSTIP:%HTTPPORT/%TESTNUMBER","urlnum":0,"curl_version":"curl-unit-test-fake-version"}
|
||||
</stdout>
|
||||
</verify>
|
||||
</testcase>
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue