#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);
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);
}
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;
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
}
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;
return 0;
}
- memcpy(certfp, hash, RB_SSL_CERTFP_LEN);
+ memcpy(certfp, hash, hashlen);
return 1;
}
}
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;
}
}
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;
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);
}
{
struct Client *client_p;
int32_t fd;
+ int32_t len;
uint8_t *certfp;
char *certfp_string;
int i;
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;
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
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);
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);
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)
{
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)