aboutsummaryrefslogtreecommitdiff
path: root/lib/gtls.c
diff options
context:
space:
mode:
Diffstat (limited to 'lib/gtls.c')
-rw-r--r--lib/gtls.c53
1 files changed, 49 insertions, 4 deletions
diff --git a/lib/gtls.c b/lib/gtls.c
index e9e410243..6e762f161 100644
--- a/lib/gtls.c
+++ b/lib/gtls.c
@@ -143,6 +143,32 @@ static void showtime(struct SessionHandle *data,
infof(data, "%s", data->state.buffer);
}
+static gnutls_datum load_file (const char *file)
+{
+ FILE *f;
+ gnutls_datum loaded_file = { NULL, 0 };
+ long filelen;
+ void *ptr;
+
+ if (!(f = fopen(file, "r"))
+ || fseek(f, 0, SEEK_END) != 0
+ || (filelen = ftell(f)) < 0
+ || fseek(f, 0, SEEK_SET) != 0
+ || !(ptr = malloc((size_t)filelen))
+ || fread(ptr, 1, (size_t)filelen, f) < (size_t)filelen) {
+ return loaded_file;
+ }
+
+ loaded_file.data = ptr;
+ loaded_file.size = (unsigned int)filelen;
+ return loaded_file;
+}
+
+static void unload_file(gnutls_datum data) {
+ free(data.data);
+}
+
+
/* this function does a BLOCKING SSL/TLS (re-)handshake */
static CURLcode handshake(struct connectdata *conn,
gnutls_session session,
@@ -221,7 +247,8 @@ Curl_gtls_connect(struct connectdata *conn,
unsigned int cert_list_size;
const gnutls_datum *chainp;
unsigned int verify_status;
- gnutls_x509_crt x509_cert;
+ gnutls_x509_crt x509_cert,x509_issuer;
+ gnutls_datum issuerp;
char certbuf[256]; /* big enough? */
size_t size;
unsigned int algo;
@@ -375,7 +402,9 @@ Curl_gtls_connect(struct connectdata *conn,
chainp = gnutls_certificate_get_peers(session, &cert_list_size);
if(!chainp) {
- if(data->set.ssl.verifypeer) {
+ if(data->set.ssl.verifypeer ||
+ data->set.ssl.verifyhost ||
+ data->set.ssl.issuercert) {
failf(data, "failed to get server cert");
return CURLE_PEER_FAILED_VERIFICATION;
}
@@ -399,8 +428,9 @@ Curl_gtls_connect(struct connectdata *conn,
/* verify_status is a bitmask of gnutls_certificate_status bits */
if(verify_status & GNUTLS_CERT_INVALID) {
if(data->set.ssl.verifypeer) {
- failf(data, "server certificate verification failed. CAfile: %s",
- data->set.ssl.CAfile?data->set.ssl.CAfile:"none");
+ failf(data, "server certificate verification failed. CAfile: %s "
+ "CRLfile: %s", data->set.ssl.CAfile?data->set.ssl.CAfile:"none",
+ data->set.ssl.CRLfile?data->set.ssl.CRLfile:"none");
return CURLE_SSL_CACERT;
}
else
@@ -419,6 +449,21 @@ Curl_gtls_connect(struct connectdata *conn,
gnutls_x509_crt_t format */
gnutls_x509_crt_import(x509_cert, chainp, GNUTLS_X509_FMT_DER);
+ if (data->set.ssl.issuercert) {
+ gnutls_x509_crt_init(&x509_issuer);
+ issuerp = load_file(data->set.ssl.issuercert);
+ gnutls_x509_crt_import(x509_issuer, &issuerp, GNUTLS_X509_FMT_PEM);
+ rc = gnutls_x509_crt_check_issuer(x509_cert,x509_issuer);
+ unload_file(issuerp);
+ if (rc <= 0) {
+ failf(data, "server certificate issuer check failed (IssuerCert: %s)",
+ data->set.ssl.issuercert?data->set.ssl.issuercert:"none");
+ return CURLE_SSL_ISSUER_ERROR;
+ }
+ infof(data,"\t server certificate issuer check OK (Issuer Cert: %s)\n",
+ data->set.ssl.issuercert?data->set.ssl.issuercert:"none");
+ }
+
size=sizeof(certbuf);
rc = gnutls_x509_crt_get_dn_by_oid(x509_cert, GNUTLS_OID_X520_COMMON_NAME,
0, /* the first and only one */