view patches/0002-Add-CURLOPT_PEERCERT-option-to-pin-a-peer-cert.patch @ 1119:5349e2354c48

(issue54) Merge branch runafterinstall There is now an NSIS Plugin that executes the Software after installation using COM in the shell of the current user. With the way over the shell there is no inheritance / token management required. As it is impossible to drop all privileges of a token granted by UAC and still be able to reelevate the Token again with another RunAs call later this round trip over the Shell was necessary.
author Andre Heinecke <andre.heinecke@intevation.de>
date Tue, 16 Sep 2014 19:48:22 +0200
parents 93325618ac7b
children
line wrap: on
line source
From e5c7feec5151299975fe03184cc322ea51fb45c2 Mon Sep 17 00:00:00 2001
From: Andre Heinecke <aheinecke@intevation.de>
Date: Fri, 12 Sep 2014 13:01:07 +0200
Subject: [PATCH 2/2] Add CURLOPT_PEERCERT option to pin a peer cert

    This is only implemented for a specific usecase with polarssl
---
 include/curl/curl.h          |  3 +++
 include/curl/typecheck-gcc.h |  1 +
 lib/url.c                    |  8 ++++++++
 lib/urldata.h                |  1 +
 lib/vtls/polarssl.c          | 41 +++++++++++++++++++++++++++++++++++++++++
 5 files changed, 54 insertions(+)

diff --git a/include/curl/curl.h b/include/curl/curl.h
index d40b2db..20a9d82 100644
--- a/include/curl/curl.h
+++ b/include/curl/curl.h
@@ -1611,6 +1611,9 @@ typedef enum {
   /* Pass in a bitmask of "header options" */
   CINIT(HEADEROPT, LONG, 229),
 
+  /* Peer certificate */
+  CINIT(PEERCERT, OBJECTPOINT, 230),
+
   CURLOPT_LASTENTRY /* the last unused */
 } CURLoption;
 
diff --git a/include/curl/typecheck-gcc.h b/include/curl/typecheck-gcc.h
index 69d41a2..241529d 100644
--- a/include/curl/typecheck-gcc.h
+++ b/include/curl/typecheck-gcc.h
@@ -258,6 +258,7 @@ _CURL_WARNING(_curl_easy_getinfo_err_curl_slist,
    (option) == CURLOPT_SSH_PRIVATE_KEYFILE ||                                 \
    (option) == CURLOPT_CRLFILE ||                                             \
    (option) == CURLOPT_ISSUERCERT ||                                          \
+   (option) == CURLOPT_PEERCERT ||                                            \
    (option) == CURLOPT_SOCKS5_GSSAPI_SERVICE ||                               \
    (option) == CURLOPT_SSH_KNOWNHOSTS ||                                      \
    (option) == CURLOPT_MAIL_FROM ||                                           \
diff --git a/lib/url.c b/lib/url.c
index 67126ab3..5721ee2 100644
--- a/lib/url.c
+++ b/lib/url.c
@@ -2015,6 +2015,14 @@ CURLcode Curl_setopt(struct SessionHandle *data, CURLoption option,
     result = setstropt(&data->set.str[STRING_SSL_ISSUERCERT],
                        va_arg(param, char *));
     break;
+  case CURLOPT_PEERCERT:
+    /*
+     * Set peer certificate file
+     * to check peer certificate against
+     */
+    result = setstropt(&data->set.str[STRING_SSL_PEERCERT],
+                       va_arg(param, char *));
+    break;
   case CURLOPT_TELNETOPTIONS:
     /*
      * Set a linked list of telnet options
diff --git a/lib/urldata.h b/lib/urldata.h
index 8594c2f..a6dc1ae 100644
--- a/lib/urldata.h
+++ b/lib/urldata.h
@@ -1391,6 +1391,7 @@ enum dupstring {
   STRING_USERAGENT,       /* User-Agent string */
   STRING_SSL_CRLFILE,     /* crl file to check certificate */
   STRING_SSL_ISSUERCERT,  /* issuer cert file to check certificate */
+  STRING_SSL_PEERCERT,  /* issuer cert file to check certificate */
   STRING_USERNAME,        /* <username>, if used */
   STRING_PASSWORD,        /* <password>, if used */
   STRING_OPTIONS,         /* <options>, if used */
diff --git a/lib/vtls/polarssl.c b/lib/vtls/polarssl.c
index 08dc4c6..8f34901 100644
--- a/lib/vtls/polarssl.c
+++ b/lib/vtls/polarssl.c
@@ -403,6 +403,44 @@ polarssl_connect_step1(struct connectdata *conn,
   return CURLE_OK;
 }
 
+static int
+pinned_verify(void *pinned_cert_file_name, x509_crt *crt,
+              int depth, int *flags)
+{
+  x509_crt pinned_cert;
+  x509_crt *leaf = crt;
+  unsigned int i;
+  int ret;
+
+  if (pinned_cert_file_name == NULL || crt == NULL) {
+    *flags |= BADCERT_NOT_TRUSTED;
+    return *flags;
+  }
+
+  x509_crt_init(&pinned_cert);
+  ret = x509_crt_parse_file(&pinned_cert, pinned_cert_file_name);
+
+  if(ret) {
+    x509_crt_free(&pinned_cert);
+    *flags |= BADCERT_NOT_TRUSTED;
+    return *flags;
+  }
+
+  while (leaf->next) {
+    leaf = leaf->next;
+  }
+
+  ret = memcmp(pinned_cert.raw.p, leaf->raw.p, pinned_cert.raw.len);
+  x509_crt_free(&pinned_cert);
+  if (ret == 0) {
+    *flags = 0;
+    return 0;
+  }
+
+  *flags |= BADCERT_NOT_TRUSTED;
+  return *flags;
+}
+
 static CURLcode
 polarssl_connect_step2(struct connectdata *conn,
                      int sockindex)
@@ -422,6 +460,9 @@ polarssl_connect_step2(struct connectdata *conn,
   conn->recv[sockindex] = polarssl_recv;
   conn->send[sockindex] = polarssl_send;
 
+  if(data->set.str[STRING_SSL_PEERCERT])
+    ssl_set_verify (&connssl->ssl, pinned_verify, data->set.str[STRING_SSL_PEERCERT]);
+
   for(;;) {
     if(!(ret = ssl_handshake(&connssl->ssl)))
       break;
-- 
1.9.1

http://wald.intevation.org/projects/trustbridge/