Commit 93e45079 authored by Travis Burtrum's avatar Travis Burtrum Committed by Daniel Stenberg
Browse files

SSL: implement public key pinning

Option --pinnedpubkey takes a path to a public key in DER format and
only connect if it matches (currently only implemented with OpenSSL).

Provides CURLOPT_PINNEDPUBLICKEY for curl_easy_setopt().

Extract a public RSA key from a website like so:
openssl s_client -connect google.com:443 2>&1 < /dev/null | \
sed -n '/-----BEGIN/,/-----END/p' | openssl x509 -noout -pubkey \
| openssl rsa -pubin -outform DER > google.com.der
parent d1b56d00
Loading
Loading
Loading
Loading
+15 −0
Original line number Diff line number Diff line
@@ -530,6 +530,19 @@ OpenSSL-powered curl to make SSL-connections much more efficiently than using

If this option is set, the default capath value will be ignored, and if it is
used several times, the last one will be used.
.IP "--pinnedpubkey <pinned public key>"
(SSL) Tells curl to use the specified public key file to verify the peer. The
file must contain a single public key in DER format.

When negotiating a TLS or SSL connection, the server sends a certificate
indicating its identity. A public key is extracted from this certificate
and if it does not exactly match the public key provided to this option,
curl will abort the connection before sending or receiving any data.

This is currently only implemented in the OpenSSL backend, with more backends
expected to follow shortly.

If this option is used several times, the last one will be used.
.IP "-f, --fail"
(HTTP) Fail silently (no output at all) on server errors. This is mostly done
to better enable scripts etc to better deal with failed attempts. In
@@ -2180,6 +2193,8 @@ unable to parse FTP file list
FTP chunk callback reported error
.IP 89
No connection available, the session will be queued
.IP 90
SSL public key does not matched pinned public key
.IP XX
More error codes will appear here in future releases. The existing ones
are meant to never change.
+51 −0
Original line number Diff line number Diff line
.\" **************************************************************************
.\" *                                  _   _ ____  _
.\" *  Project                     ___| | | |  _ \| |
.\" *                             / __| | | | |_) | |
.\" *                            | (__| |_| |  _ <| |___
.\" *                             \___|\___/|_| \_\_____|
.\" *
.\" * Copyright (C) 1998 - 2014, Daniel Stenberg, <daniel@haxx.se>, et al.
.\" *
.\" * This software is licensed as described in the file COPYING, which
.\" * you should have received as part of this distribution. The terms
.\" * are also available at http://curl.haxx.se/docs/copyright.html.
.\" *
.\" * You may opt to use, copy, modify, merge, publish, distribute and/or sell
.\" * copies of the Software, and permit persons to whom the Software is
.\" * furnished to do so, under the terms of the COPYING file.
.\" *
.\" * This software is distributed on an "AS IS" basis, WITHOUT WARRANTY OF ANY
.\" * KIND, either express or implied.
.\" *
.\" **************************************************************************
.\"
.TH CURLOPT_PINNEDPUBLICKEY 3 "27 Aug 2014" "libcurl 7.38.0" "curl_easy_setopt options"
.SH NAME
CURLOPT_PINNEDPUBLICKEY \- set pinned public key
.SH SYNOPSIS
#include <curl/curl.h>

CURLcode curl_easy_setopt(CURL *handle, CURLOPT_PINNEDPUBLICKEY, char *pinnedpubkey);
.SH DESCRIPTION
Pass a pointer to a zero terminated string as parameter. The string should be
the file name of your pinned public key. The format expected is "DER".

When negotiating a TLS or SSL connection, the server sends a certificate
indicating its identity. A public key is extracted from this certificate
and if it does not exactly match the public key provided to this option,
curl will abort the connection before sending or receiving any data.

This is currently only implemented in the OpenSSL backend, with more backends
expected to follow shortly.
.SH DEFAULT
NULL
.SH PROTOCOLS
All TLS based protocols: HTTPS, FTPS, IMAPS, POP3, SMTPS etc.
.SH EXAMPLE
TODO
.SH AVAILABILITY
If built TLS enabled.
.SH RETURN VALUE
Returns CURLE_OK if TLS enabled, CURLE_UNKNOWN_OPTION if not, or
CURLE_OUT_OF_MEMORY if there was insufficient heap space.
+3 −1
Original line number Diff line number Diff line
@@ -74,12 +74,12 @@ CURLE_FTP_WEIRD_USER_REPLY 7.1 7.17.0
CURLE_FTP_WRITE_ERROR           7.1           7.17.0
CURLE_FUNCTION_NOT_FOUND        7.1
CURLE_GOT_NOTHING               7.9.1
CURLE_HTTP2                     7.38.0
CURLE_HTTP_NOT_FOUND            7.1
CURLE_HTTP_PORT_FAILED          7.3           7.12.0
CURLE_HTTP_POST_ERROR           7.1
CURLE_HTTP_RANGE_ERROR          7.1           7.17.0
CURLE_HTTP_RETURNED_ERROR       7.10.3
CURLE_HTTP2                     7.38.0
CURLE_INTERFACE_FAILED          7.12.0
CURLE_LDAP_CANNOT_BIND          7.1
CURLE_LDAP_INVALID_URL          7.10.8
@@ -120,6 +120,7 @@ CURLE_SSL_ENGINE_NOTFOUND 7.9.3
CURLE_SSL_ENGINE_SETFAILED      7.9.3
CURLE_SSL_ISSUER_ERROR          7.19.0
CURLE_SSL_PEER_CERTIFICATE      7.8           7.17.1
CURLE_SSL_PINNEDPUBKEYNOTMATCH  7.39.0
CURLE_SSL_SHUTDOWN_FAILED       7.16.1
CURLE_TELNET_OPTION_SYNTAX      7.7
CURLE_TFTP_DISKFULL             7.15.0        7.17.0
@@ -429,6 +430,7 @@ CURLOPT_PASSWDDATA 7.4.2 7.11.1 7.15.5
CURLOPT_PASSWDFUNCTION          7.4.2         7.11.1      7.15.5
CURLOPT_PASSWORD                7.19.1
CURLOPT_PASV_HOST               7.12.1        7.16.0      7.15.5
CURLOPT_PINNEDPUBLICKEY         7.39.0
CURLOPT_PORT                    7.1
CURLOPT_POST                    7.1
CURLOPT_POST301                 7.17.1        7.19.1
+6 −0
Original line number Diff line number Diff line
@@ -521,6 +521,8 @@ typedef enum {
  CURLE_CHUNK_FAILED,            /* 88 - chunk callback reported error */
  CURLE_NO_CONNECTION_AVAILABLE, /* 89 - No connection available, the
                                    session will be queued */
  CURLE_SSL_PINNEDPUBKEYNOTMATCH, /* 90 - specified pinned public key did not
                                     match */
  CURL_LAST /* never use! */
} CURLcode;

@@ -1611,6 +1613,10 @@ typedef enum {
  /* Pass in a bitmask of "header options" */
  CINIT(HEADEROPT, LONG, 229),

  /* The public key in DER form used to validate the peer public key
     this option is used only if SSL_VERIFYPEER is true */
  CINIT(PINNEDPUBLICKEY, OBJECTPOINT, 230),

  CURLOPT_LASTENTRY /* the last unused */
} CURLoption;

+3 −0
Original line number Diff line number Diff line
@@ -298,6 +298,9 @@ curl_easy_strerror(CURLcode error)
  case CURLE_NO_CONNECTION_AVAILABLE:
    return "The max connection limit is reached";

  case CURLE_SSL_PINNEDPUBKEYNOTMATCH:
    return "SSL public key does not matched pinned public key";

    /* error codes not used by current libcurl */
  case CURLE_OBSOLETE20:
  case CURLE_OBSOLETE24:
Loading