]> jfr.im git - solanum.git/commitdiff
Add ability to change CertFP hash.
authorElizabeth Myers <redacted>
Wed, 27 May 2015 21:46:46 +0000 (16:46 -0500)
committerWilliam Pitcock <redacted>
Mon, 7 Dec 2015 07:14:02 +0000 (01:14 -0600)
Presently this only supports SHA1, as the machinery to actually change
the cipher is not hooked up to anything yet.

libratbox/include/rb_commio.h
libratbox/src/gnutls.c
libratbox/src/mbedtls.c
libratbox/src/nossl.c
libratbox/src/openssl.c
src/sslproc.c
ssld/ssld.c

index 016c2d27ebc10a946c108cf05ba5aecfe58b1154..f37677a440c5be364652502e504156e91cfbebf4 100644 (file)
@@ -97,10 +97,19 @@ void rb_note(rb_fde_t *, const char *);
 #define        RB_SELECT_READ          0x1
 #define        RB_SELECT_WRITE         0x2
 
-#define RB_SELECT_ACCEPT               RB_SELECT_READ
-#define RB_SELECT_CONNECT              RB_SELECT_WRITE
+#define RB_SELECT_ACCEPT       RB_SELECT_READ
+#define RB_SELECT_CONNECT      RB_SELECT_WRITE
 
-#define RB_SSL_CERTFP_LEN 20
+#define RB_SSL_CERTFP_LEN      64
+
+/* Methods for certfp */
+#define RB_SSL_CERTFP_METH_SHA1                0
+#define RB_SSL_CERTFP_METH_SHA256      1
+#define RB_SSL_CERTFP_METH_SHA512      2
+
+#define RB_SSL_CERTFP_LEN_SHA1         20
+#define RB_SSL_CERTFP_LEN_SHA256       32
+#define RB_SSL_CERTFP_LEN_SHA512       64
 
 int rb_set_nb(rb_fde_t *);
 int rb_set_buffers(rb_fde_t *, int);
@@ -143,7 +152,7 @@ int rb_select(unsigned long);
 int rb_fd_ssl(rb_fde_t *F);
 int rb_get_fd(rb_fde_t *F);
 const char *rb_get_ssl_strerror(rb_fde_t *F);
-int rb_get_ssl_certfp(rb_fde_t *F, uint8_t certfp[RB_SSL_CERTFP_LEN]);
+int rb_get_ssl_certfp(rb_fde_t *F, uint8_t certfp[RB_SSL_CERTFP_LEN], int method);
 
 rb_fde_t *rb_get_fde(int fd);
 
index ff3e132498b362915d8791c2b513eb1c90ea497f..77ad47ef2d0e7a6e11beb98582c244c55cc58e1e 100644 (file)
@@ -559,13 +559,15 @@ rb_get_ssl_strerror(rb_fde_t *F)
 }
 
 int
-rb_get_ssl_certfp(rb_fde_t *F, uint8_t certfp[RB_SSL_CERTFP_LEN])
+rb_get_ssl_certfp(rb_fde_t *F, uint8_t certfp[RB_SSL_CERTFP_LEN], int method)
 {
        gnutls_x509_crt_t cert;
+       gnutls_digest_algorithm_t algo;
        unsigned int cert_list_size;
        const gnutls_datum_t *cert_list;
        uint8_t digest[RB_SSL_CERTFP_LEN * 2];
        size_t digest_size;
+       int len;
 
        if (gnutls_certificate_type_get(SSL_P(F)) != GNUTLS_CRT_X509)
                return 0;
@@ -587,16 +589,34 @@ rb_get_ssl_certfp(rb_fde_t *F, uint8_t certfp[RB_SSL_CERTFP_LEN])
                return 0;
        }
 
-       if (gnutls_x509_crt_get_fingerprint(cert, GNUTLS_DIG_SHA1, digest, &digest_size) < 0)
+       switch(method)
+       {
+       case RB_SSL_CERTFP_METH_SHA1:
+               algo = GNUTLS_DIG_SHA1;
+               len = RB_SSL_CERTFP_LEN_SHA1;
+               break;
+       case RB_SSL_CERTFP_METH_SHA256:
+               algo = GNUTLS_DIG_SHA256;
+               len = RB_SSL_CERTFP_LEN_SHA256;
+               break;
+       case RB_SSL_CERTFP_METH_SHA512:
+               algo = GNUTLS_DIG_SHA512;
+               len = RB_SSL_CERTFP_LEN_SHA512;
+               break;
+       default:
+               return 0;
+       }
+
+       if (gnutls_x509_crt_get_fingerprint(cert, algo, digest, &digest_size) < 0)
        {
                gnutls_x509_crt_deinit(cert);
                return 0;
        }
 
-       memcpy(certfp, digest, RB_SSL_CERTFP_LEN);
+       memcpy(certfp, digest, len);
 
        gnutls_x509_crt_deinit(cert);
-       return 1;
+       return len;
 }
 
 int
index 297151dafd2bae3e62259d84816b2ca4d965f12c..6a8c6b5e6246319a48dedac9834b531049449b2d 100644 (file)
@@ -536,18 +536,35 @@ rb_get_ssl_strerror(rb_fde_t *F)
 }
 
 int
-rb_get_ssl_certfp(rb_fde_t *F, uint8_t certfp[RB_SSL_CERTFP_LEN])
+rb_get_ssl_certfp(rb_fde_t *F, uint8_t certfp[RB_SSL_CERTFP_LEN], int method)
 {
        const mbedtls_x509_crt *peer_cert;
        uint8_t hash[RB_SSL_CERTFP_LEN];
+       size_t hashlen;
        const mbedtls_md_info_t *md_info;
+       mbedtls_md_type_t md_type;
        int ret;
 
+       switch (method)
+       {
+       case RB_SSL_CERTFP_METH_SHA1:
+               md_type = MBEDTLS_MD_SHA1;
+               hashlen = RB_SSL_CERTFP_LEN_SHA1;
+       case RB_SSL_CERTFP_METH_SHA256:
+               md_type = MBEDTLS_MD_SHA256;
+               hashlen = RB_SSL_CERTFP_LEN_SHA256;
+       case RB_SSL_CERTFP_METH_SHA512:
+               md_type = MBEDTLS_MD_SHA512;
+               hashlen = RB_SSL_CERTFP_LEN_SHA512;
+       default:
+               return 0;
+       }
+
        peer_cert = mbedtls_ssl_get_peer_cert(SSL_P(F));
        if (peer_cert == NULL)
                return 0;
 
-       md_info = mbedtls_md_info_from_type(MBEDTLS_MD_SHA1);
+       md_info = mbedtls_md_info_from_type(md_type);
        if (md_info == NULL)
                return 0;
 
@@ -557,7 +574,7 @@ rb_get_ssl_certfp(rb_fde_t *F, uint8_t certfp[RB_SSL_CERTFP_LEN])
                return 0;
        }
 
-       memcpy(certfp, hash, RB_SSL_CERTFP_LEN);
+       memcpy(certfp, hash, hashlen);
 
        return 1;
 }
index 2d0d146284705a1bfd00da7f3704a607bace7c84..2133800f6cee596ba6ea48259db7547567ecce56 100644 (file)
@@ -94,7 +94,7 @@ rb_get_ssl_strerror(rb_fde_t *F)
 }
 
 int
-rb_get_ssl_certfp(rb_fde_t *F, uint8_t certfp[RB_SSL_CERTFP_LEN])
+rb_get_ssl_certfp(rb_fde_t *F, uint8_t certfp[RB_SSL_CERTFP_LEN], int method)
 {
        return 0;
 }
index d088f7bb256ad0c2c42e716ebbbc7b9136fcda94..59e4a16f876d78b658d9179c0e68989b62cb79e7 100644 (file)
@@ -681,7 +681,7 @@ rb_get_ssl_strerror(rb_fde_t *F)
 }
 
 int
-rb_get_ssl_certfp(rb_fde_t *F, uint8_t certfp[RB_SSL_CERTFP_LEN])
+rb_get_ssl_certfp(rb_fde_t *F, uint8_t certfp[RB_SSL_CERTFP_LEN], int method)
 {
        X509 *cert;
        int res;
@@ -700,10 +700,30 @@ rb_get_ssl_certfp(rb_fde_t *F, uint8_t certfp[RB_SSL_CERTFP_LEN])
                        res == X509_V_ERR_DEPTH_ZERO_SELF_SIGNED_CERT ||
                        res == X509_V_ERR_UNABLE_TO_GET_ISSUER_CERT_LOCALLY)
                {
-                       unsigned int certfp_length = RB_SSL_CERTFP_LEN;
-                       X509_digest(cert, EVP_sha1(), certfp, &certfp_length);
+                       const EVP_MD *evp;
+                       unsigned int len;
+
+                       switch(method)
+                       {
+                       case RB_SSL_CERTFP_METH_SHA1:
+                               evp = EVP_sha1();
+                               len = RB_SSL_CERTFP_LEN_SHA1;
+                               break;
+                       case RB_SSL_CERTFP_METH_SHA256:
+                               evp = EVP_sha256();
+                               len = RB_SSL_CERTFP_LEN_SHA256;
+                               break;
+                       case RB_SSL_CERTFP_METH_SHA512:
+                               evp = EVP_sha512();
+                               len = RB_SSL_CERTFP_LEN_SHA512;
+                               break;
+                       default:
+                               return 0;
+                       }
+
+                       X509_digest(cert, evp, certfp, &len);
                        X509_free(cert);
-                       return 1;
+                       return len;
                }
                X509_free(cert);
        }
index f7d0b9c6f8c2a046d9c21502943648693b05a817..ff38c2825f572622e570967c31d1daea22af202d 100644 (file)
@@ -384,6 +384,7 @@ ssl_process_certfp(ssl_ctl_t * ctl, ssl_ctl_buf_t * ctl_buf)
 {
        struct Client *client_p;
        int32_t fd;
+       int32_t len;
        uint8_t *certfp;
        char *certfp_string;
        int i;
@@ -392,13 +393,14 @@ ssl_process_certfp(ssl_ctl_t * ctl, ssl_ctl_buf_t * ctl_buf)
                return;         /* bogus message..drop it.. XXX should warn here */
 
        fd = buf_to_int32(&ctl_buf->buf[1]);
-       certfp = (uint8_t *)&ctl_buf->buf[5];
+       len = buf_to_int32(&ctl_buf->buf[5]);
+       certfp = (uint8_t *)&ctl_buf->buf[9];
        client_p = find_cli_fd_hash(fd);
        if(client_p == NULL)
                return;
        rb_free(client_p->certfp);
-       certfp_string = rb_malloc(RB_SSL_CERTFP_LEN * 2 + 1);
-       for(i = 0; i < RB_SSL_CERTFP_LEN; i++)
+       certfp_string = rb_malloc(len * 2 + 1);
+       for(i = 0; i < len; i++)
                rb_snprintf(certfp_string + 2 * i, 3, "%02x",
                                certfp[i]);
        client_p->certfp = certfp_string;
index cad491c2b7f281e17a63a5d8908a7877611d9c41..37c9e060cc4c649fe81510e993785b94b5016da7 100644 (file)
@@ -159,6 +159,7 @@ static void conn_plain_read_shutdown_cb(rb_fde_t *fd, void *data);
 static void mod_cmd_write_queue(mod_ctl_t * ctl, const void *data, size_t len);
 static const char *remote_closed = "Remote host closed the connection";
 static int ssl_ok;
+static int certfp_method = RB_SSL_CERTFP_METH_SHA1;
 #ifdef HAVE_LIBZ
 static int zlib_ok = 1;
 #else
@@ -663,15 +664,18 @@ static void
 ssl_process_accept_cb(rb_fde_t *F, int status, struct sockaddr *addr, rb_socklen_t len, void *data)
 {
        conn_t *conn = data;
-       uint8_t buf[5 + RB_SSL_CERTFP_LEN];
+       uint8_t buf[9 + RB_SSL_CERTFP_LEN];
 
        if(status == RB_OK)
        {
-               if(rb_get_ssl_certfp(F, &buf[5]))
+               int len = rb_get_ssl_certfp(F, &buf[9], certfp_method);
+               if(len)
                {
+                       lrb_assert(len <= RB_SSL_CERTFP_LEN);
                        buf[0] = 'F';
                        int32_to_buf(&buf[1], conn->id);
-                       mod_cmd_write_queue(conn->ctl, buf, sizeof buf);
+                       int32_to_buf(&buf[5], certfp_method);
+                       mod_cmd_write_queue(conn->ctl, buf, 9 + len);
                }
                conn_mod_read_cb(conn->mod_fd, conn);
                conn_plain_read_cb(conn->plain_fd, conn);
@@ -686,15 +690,18 @@ static void
 ssl_process_connect_cb(rb_fde_t *F, int status, void *data)
 {
        conn_t *conn = data;
-       uint8_t buf[5 + RB_SSL_CERTFP_LEN];
+       uint8_t buf[9 + RB_SSL_CERTFP_LEN];
 
        if(status == RB_OK)
        {
-               if(rb_get_ssl_certfp(F, &buf[5]))
+               int len = rb_get_ssl_certfp(F, &buf[9], certfp_method);
+               if(len)
                {
+                       lrb_assert(len <= RB_SSL_CERTFP_LEN);
                        buf[0] = 'F';
                        int32_to_buf(&buf[1], conn->id);
-                       mod_cmd_write_queue(conn->ctl, buf, sizeof buf);
+                       int32_to_buf(&buf[5], certfp_method);
+                       mod_cmd_write_queue(conn->ctl, buf, 9 + len);
                }
                conn_mod_read_cb(conn->mod_fd, conn);
                conn_plain_read_cb(conn->plain_fd, conn);
@@ -743,6 +750,12 @@ ssl_process_accept(mod_ctl_t * ctl, mod_ctl_buf_t * ctlb)
        rb_ssl_start_accepted(ctlb->F[0], ssl_process_accept_cb, conn, 10);
 }
 
+static void
+ssl_change_certfp_method(mod_ctl_t * ctl, mod_ctl_buf_t * ctlb)
+{
+       certfp_method = buf_to_int32(&ctlb->buf[1]);
+}
+
 static void
 ssl_process_connect(mod_ctl_t * ctl, mod_ctl_buf_t * ctlb)
 {
@@ -988,7 +1001,16 @@ mod_process_cmd_recv(mod_ctl_t * ctl)
                                ssl_process_connect(ctl, ctl_buf);
                                break;
                        }
-
+               case 'F':
+                       {
+                               if (ctl_buf->nfds != 2 || ctl_buf->buflen != 5)
+                               {
+                                       cleanup_bad_message(ctl, ctl_buf);
+                                       break;
+                               }
+                               ssl_change_certfp_method(ctl, ctl_buf);
+                               break;
+                       }
                case 'K':
                        {
                                if(!ssl_ok)