TLS: Partially backport the SubjectPublicKeyInfo digesting functionality
This backports the code responsible for SPKI digests from release/4. It also adjusts doc/reference.conf to note that SPKI digests are now supported, and how to generate them. It does NOT backport the mkfingerprint program -- the instructions in reference.conf are sufficient. I am ofcourse open to anyone else backporting the program, but I don't see the need.
This commit is contained in:
parent
0a9598655c
commit
2afd965b21
10 changed files with 282 additions and 118 deletions
|
@ -1316,11 +1316,25 @@ general {
|
||||||
away_interval = 30;
|
away_interval = 30;
|
||||||
|
|
||||||
/* certfp_method: the method that should be used for computing certificate fingerprints.
|
/* certfp_method: the method that should be used for computing certificate fingerprints.
|
||||||
* Acceptable options are sha1, sha256 and sha512. Networks running versions of charybdis
|
* Acceptable options are sha1, sha256, spki_sha256, sha512 and spki_sha512. Networks
|
||||||
* prior to charybdis 3.5 MUST use sha1 for certfp_method.
|
* running versions of charybdis prior to charybdis 3.5 MUST use sha1 for certfp_method.
|
||||||
|
*
|
||||||
|
* The spki_* variants operate on the SubjectPublicKeyInfo of the certificate, which does
|
||||||
|
* not change unless the private key is changed. This allows the fingerprint to stay
|
||||||
|
* constant even if the certificate is reissued. These fingerprints will be prefixed with
|
||||||
|
* "SPKI:SHA2-256:" or "SPKI:SHA2-512:" depending on the hash type. These fingerprints
|
||||||
|
* are not supported on servers running charybdis 3.5.3 or earlier.
|
||||||
*
|
*
|
||||||
* To generate a fingerprint from a certificate file, run the following:
|
* To generate a fingerprint from a certificate file, run the following:
|
||||||
* $ openssl x509 -outform DER < your.crt | sha1sum (or sha256sum, or sha512sum)
|
* $ openssl x509 -outform DER < your.crt | sha1sum (or sha256sum, or sha512sum)
|
||||||
|
*
|
||||||
|
* To generate a SPKI SHA-256 fingerprint, run the following:
|
||||||
|
* $ openssl x509 -pubkey -noout < your.crt | grep -v 'PUBLIC KEY' | base64 -d | \
|
||||||
|
* sha256sum | awk '{ print $1 }' | sed -r -e 's/^/SPKI:SHA2-256:/'
|
||||||
|
*
|
||||||
|
* To generate a SPKI SHA-512 fingerprint, run the following:
|
||||||
|
* $ openssl x509 -pubkey -noout < your.crt | grep -v 'PUBLIC KEY' | base64 -d | \
|
||||||
|
* sha512sum | awk '{ print $1 }' | sed -r -e 's/^/SPKI:SHA2-512:/'
|
||||||
*/
|
*/
|
||||||
certfp_method = sha1;
|
certfp_method = sha1;
|
||||||
};
|
};
|
||||||
|
|
|
@ -32,7 +32,7 @@ int start_ssldaemon(int count, const char *ssl_cert, const char *ssl_private_key
|
||||||
ssl_ctl_t *start_ssld_accept(rb_fde_t *sslF, rb_fde_t *plainF, uint32_t id);
|
ssl_ctl_t *start_ssld_accept(rb_fde_t *sslF, rb_fde_t *plainF, uint32_t id);
|
||||||
ssl_ctl_t *start_ssld_connect(rb_fde_t *sslF, rb_fde_t *plainF, uint32_t id);
|
ssl_ctl_t *start_ssld_connect(rb_fde_t *sslF, rb_fde_t *plainF, uint32_t id);
|
||||||
void start_zlib_session(void *data);
|
void start_zlib_session(void *data);
|
||||||
void send_new_ssl_certs(const char *ssl_cert, const char *ssl_private_key, const char *ssl_dh_params, const char *ssl_cipher_list);
|
void send_new_ssl_certs(const char *ssl_cert, const char *ssl_private_key, const char *ssl_dh_params, const char *ssl_cipher_list, const int method);
|
||||||
void ssld_decrement_clicount(ssl_ctl_t *ctl);
|
void ssld_decrement_clicount(ssl_ctl_t *ctl);
|
||||||
int get_ssld_count(void);
|
int get_ssld_count(void);
|
||||||
|
|
||||||
|
|
|
@ -103,9 +103,27 @@ void rb_note(rb_fde_t *, const char *);
|
||||||
#define RB_SSL_CERTFP_LEN 64
|
#define RB_SSL_CERTFP_LEN 64
|
||||||
|
|
||||||
/* Methods for certfp */
|
/* Methods for certfp */
|
||||||
#define RB_SSL_CERTFP_METH_SHA1 0
|
/* Digest of full X.509 certificate */
|
||||||
#define RB_SSL_CERTFP_METH_SHA256 1
|
#define RB_SSL_CERTFP_METH_CERT_SHA1 0x0000
|
||||||
#define RB_SSL_CERTFP_METH_SHA512 2
|
#define RB_SSL_CERTFP_METH_CERT_SHA256 0x0001
|
||||||
|
#define RB_SSL_CERTFP_METH_CERT_SHA512 0x0002
|
||||||
|
/* Digest of SubjectPublicKeyInfo (RFC 5280), used by DANE (RFC 6698) */
|
||||||
|
#define RB_SSL_CERTFP_METH_SPKI_SHA256 0x1001
|
||||||
|
#define RB_SSL_CERTFP_METH_SPKI_SHA512 0x1002
|
||||||
|
|
||||||
|
/* Names for certfp */
|
||||||
|
#define CERTFP_NAME_CERT_SHA1 "sha1"
|
||||||
|
#define CERTFP_PREFIX_CERT_SHA1 ""
|
||||||
|
#define CERTFP_NAME_CERT_SHA256 "sha256"
|
||||||
|
#define CERTFP_PREFIX_CERT_SHA256 ""
|
||||||
|
#define CERTFP_NAME_CERT_SHA512 "sha512"
|
||||||
|
#define CERTFP_PREFIX_CERT_SHA512 ""
|
||||||
|
/* These prefixes are copied from RFC 7218 */
|
||||||
|
#define CERTFP_NAME_SPKI_SHA256 "spki_sha256"
|
||||||
|
#define CERTFP_PREFIX_SPKI_SHA256 "SPKI:SHA2-256:"
|
||||||
|
#define CERTFP_NAME_SPKI_SHA512 "spki_sha512"
|
||||||
|
#define CERTFP_PREFIX_SPKI_SHA512 "SPKI:SHA2-512:"
|
||||||
|
|
||||||
|
|
||||||
#define RB_SSL_CERTFP_LEN_SHA1 20
|
#define RB_SSL_CERTFP_LEN_SHA1 20
|
||||||
#define RB_SSL_CERTFP_LEN_SHA256 32
|
#define RB_SSL_CERTFP_LEN_SHA256 32
|
||||||
|
|
|
@ -367,6 +367,73 @@ rb_load_file_into_datum_t(const char *const file)
|
||||||
return datum;
|
return datum;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static int
|
||||||
|
make_certfp(gnutls_x509_crt_t cert, uint8_t certfp[const RB_SSL_CERTFP_LEN], const int method)
|
||||||
|
{
|
||||||
|
int hashlen;
|
||||||
|
gnutls_digest_algorithm_t md_type;
|
||||||
|
|
||||||
|
int spki = 0;
|
||||||
|
|
||||||
|
switch(method)
|
||||||
|
{
|
||||||
|
case RB_SSL_CERTFP_METH_CERT_SHA1:
|
||||||
|
hashlen = RB_SSL_CERTFP_LEN_SHA1;
|
||||||
|
md_type = GNUTLS_DIG_SHA1;
|
||||||
|
break;
|
||||||
|
case RB_SSL_CERTFP_METH_SPKI_SHA256:
|
||||||
|
spki = 1;
|
||||||
|
case RB_SSL_CERTFP_METH_CERT_SHA256:
|
||||||
|
hashlen = RB_SSL_CERTFP_LEN_SHA256;
|
||||||
|
md_type = GNUTLS_DIG_SHA256;
|
||||||
|
break;
|
||||||
|
case RB_SSL_CERTFP_METH_SPKI_SHA512:
|
||||||
|
spki = 1;
|
||||||
|
case RB_SSL_CERTFP_METH_CERT_SHA512:
|
||||||
|
hashlen = RB_SSL_CERTFP_LEN_SHA512;
|
||||||
|
md_type = GNUTLS_DIG_SHA512;
|
||||||
|
break;
|
||||||
|
default:
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
if(! spki)
|
||||||
|
{
|
||||||
|
size_t digest_size = (size_t) hashlen;
|
||||||
|
|
||||||
|
if(gnutls_x509_crt_get_fingerprint(cert, md_type, certfp, &digest_size) != 0)
|
||||||
|
return 0;
|
||||||
|
|
||||||
|
return hashlen;
|
||||||
|
}
|
||||||
|
|
||||||
|
gnutls_pubkey_t pubkey;
|
||||||
|
|
||||||
|
if(gnutls_pubkey_init(&pubkey) != 0)
|
||||||
|
return 0;
|
||||||
|
|
||||||
|
if(gnutls_pubkey_import_x509(pubkey, cert, 0) != 0)
|
||||||
|
{
|
||||||
|
gnutls_pubkey_deinit(pubkey);
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
unsigned char derkey[262144]; // Should be big enough to hold any SubjectPublicKeyInfo structure
|
||||||
|
size_t derkey_len = sizeof derkey;
|
||||||
|
|
||||||
|
if(gnutls_pubkey_export(pubkey, GNUTLS_X509_FMT_DER, derkey, &derkey_len) != 0)
|
||||||
|
{
|
||||||
|
gnutls_pubkey_deinit(pubkey);
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
gnutls_pubkey_deinit(pubkey);
|
||||||
|
|
||||||
|
if(gnutls_hash_fast(md_type, derkey, derkey_len, certfp) != 0)
|
||||||
|
return 0;
|
||||||
|
|
||||||
|
return hashlen;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
/*
|
/*
|
||||||
|
@ -589,53 +656,29 @@ rb_get_ssl_certfp(rb_fde_t *const F, uint8_t certfp[const RB_SSL_CERTFP_LEN], co
|
||||||
if(F == NULL || F->ssl == NULL)
|
if(F == NULL || F->ssl == NULL)
|
||||||
return 0;
|
return 0;
|
||||||
|
|
||||||
gnutls_digest_algorithm_t md_type;
|
|
||||||
|
|
||||||
switch(method)
|
|
||||||
{
|
|
||||||
case RB_SSL_CERTFP_METH_SHA1:
|
|
||||||
md_type = GNUTLS_DIG_SHA1;
|
|
||||||
break;
|
|
||||||
case RB_SSL_CERTFP_METH_SHA256:
|
|
||||||
md_type = GNUTLS_DIG_SHA256;
|
|
||||||
break;
|
|
||||||
case RB_SSL_CERTFP_METH_SHA512:
|
|
||||||
md_type = GNUTLS_DIG_SHA512;
|
|
||||||
break;
|
|
||||||
default:
|
|
||||||
return 0;
|
|
||||||
}
|
|
||||||
|
|
||||||
if(gnutls_certificate_type_get(SSL_P(F)) != GNUTLS_CRT_X509)
|
if(gnutls_certificate_type_get(SSL_P(F)) != GNUTLS_CRT_X509)
|
||||||
return 0;
|
return 0;
|
||||||
|
|
||||||
unsigned int cert_list_size = 0;
|
unsigned int cert_list_size = 0;
|
||||||
const gnutls_datum_t *const cert_list = gnutls_certificate_get_peers(SSL_P(F), &cert_list_size);
|
const gnutls_datum_t *const cert_list = gnutls_certificate_get_peers(SSL_P(F), &cert_list_size);
|
||||||
if(cert_list == NULL || cert_list_size <= 0)
|
if(cert_list == NULL || cert_list_size < 1)
|
||||||
return 0;
|
return 0;
|
||||||
|
|
||||||
gnutls_x509_crt_t peer_cert;
|
gnutls_x509_crt_t peer_cert;
|
||||||
if(gnutls_x509_crt_init(&peer_cert) != GNUTLS_E_SUCCESS)
|
if(gnutls_x509_crt_init(&peer_cert) != 0)
|
||||||
return 0;
|
return 0;
|
||||||
|
|
||||||
if(gnutls_x509_crt_import(peer_cert, &cert_list[0], GNUTLS_X509_FMT_DER) != GNUTLS_E_SUCCESS)
|
if(gnutls_x509_crt_import(peer_cert, &cert_list[0], GNUTLS_X509_FMT_DER) < 0)
|
||||||
{
|
{
|
||||||
gnutls_x509_crt_deinit(peer_cert);
|
gnutls_x509_crt_deinit(peer_cert);
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
int ret;
|
const int len = make_certfp(peer_cert, certfp, method);
|
||||||
size_t hashlen;
|
|
||||||
if((ret = gnutls_x509_crt_get_fingerprint(peer_cert, md_type, certfp, &hashlen)) != 0)
|
|
||||||
{
|
|
||||||
rb_lib_log("%s: gnutls_x509_crt_get_fingerprint: %s", __func__, rb_ssl_strerror(ret));
|
|
||||||
gnutls_x509_crt_deinit(peer_cert);
|
|
||||||
return 0;
|
|
||||||
}
|
|
||||||
|
|
||||||
gnutls_x509_crt_deinit(peer_cert);
|
gnutls_x509_crt_deinit(peer_cert);
|
||||||
|
|
||||||
return (int) hashlen;
|
return len;
|
||||||
}
|
}
|
||||||
|
|
||||||
void
|
void
|
||||||
|
|
|
@ -325,6 +325,65 @@ rb_ssl_strerror(const int err)
|
||||||
return errbuf;
|
return errbuf;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static int
|
||||||
|
rb_make_certfp(const mbedtls_x509_crt *const peer_cert, uint8_t certfp[const RB_SSL_CERTFP_LEN], const int method)
|
||||||
|
{
|
||||||
|
size_t hashlen = 0;
|
||||||
|
mbedtls_md_type_t md_type;
|
||||||
|
int spki = 0;
|
||||||
|
|
||||||
|
switch(method)
|
||||||
|
{
|
||||||
|
case RB_SSL_CERTFP_METH_CERT_SHA1:
|
||||||
|
md_type = MBEDTLS_MD_SHA1;
|
||||||
|
hashlen = RB_SSL_CERTFP_LEN_SHA1;
|
||||||
|
break;
|
||||||
|
case RB_SSL_CERTFP_METH_SPKI_SHA256:
|
||||||
|
spki = 1;
|
||||||
|
case RB_SSL_CERTFP_METH_CERT_SHA256:
|
||||||
|
md_type = MBEDTLS_MD_SHA256;
|
||||||
|
hashlen = RB_SSL_CERTFP_LEN_SHA256;
|
||||||
|
break;
|
||||||
|
case RB_SSL_CERTFP_METH_SPKI_SHA512:
|
||||||
|
spki = 1;
|
||||||
|
case RB_SSL_CERTFP_METH_CERT_SHA512:
|
||||||
|
md_type = MBEDTLS_MD_SHA512;
|
||||||
|
hashlen = RB_SSL_CERTFP_LEN_SHA512;
|
||||||
|
break;
|
||||||
|
default:
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
const mbedtls_md_info_t *const md_info = mbedtls_md_info_from_type(md_type);
|
||||||
|
if(md_info == NULL)
|
||||||
|
return 0;
|
||||||
|
|
||||||
|
int ret;
|
||||||
|
void* data = peer_cert->raw.p;
|
||||||
|
size_t datalen = peer_cert->raw.len;
|
||||||
|
|
||||||
|
if(spki)
|
||||||
|
{
|
||||||
|
unsigned char der_pubkey[8192];
|
||||||
|
if((ret = mbedtls_pk_write_pubkey_der((mbedtls_pk_context *)&peer_cert->pk,
|
||||||
|
der_pubkey, sizeof der_pubkey)) < 0)
|
||||||
|
{
|
||||||
|
rb_lib_log("%s: pk_write_pubkey_der: %s", __func__, rb_ssl_strerror(ret));
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
data = der_pubkey + (sizeof(der_pubkey) - (size_t)ret);
|
||||||
|
datalen = (size_t)ret;
|
||||||
|
}
|
||||||
|
|
||||||
|
if((ret = mbedtls_md(md_info, data, datalen, certfp)) != 0)
|
||||||
|
{
|
||||||
|
rb_lib_log("%s: mbedtls_md: %s", __func__, rb_ssl_strerror(ret));
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
return (int) hashlen;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
/*
|
/*
|
||||||
|
@ -560,43 +619,12 @@ rb_get_ssl_certfp(rb_fde_t *const F, uint8_t certfp[const RB_SSL_CERTFP_LEN], co
|
||||||
if(F == NULL || F->ssl == NULL)
|
if(F == NULL || F->ssl == NULL)
|
||||||
return 0;
|
return 0;
|
||||||
|
|
||||||
mbedtls_md_type_t md_type;
|
|
||||||
int hashlen;
|
|
||||||
|
|
||||||
switch(method)
|
|
||||||
{
|
|
||||||
case RB_SSL_CERTFP_METH_SHA1:
|
|
||||||
md_type = MBEDTLS_MD_SHA1;
|
|
||||||
hashlen = RB_SSL_CERTFP_LEN_SHA1;
|
|
||||||
break;
|
|
||||||
case RB_SSL_CERTFP_METH_SHA256:
|
|
||||||
md_type = MBEDTLS_MD_SHA256;
|
|
||||||
hashlen = RB_SSL_CERTFP_LEN_SHA256;
|
|
||||||
break;
|
|
||||||
case RB_SSL_CERTFP_METH_SHA512:
|
|
||||||
md_type = MBEDTLS_MD_SHA512;
|
|
||||||
hashlen = RB_SSL_CERTFP_LEN_SHA512;
|
|
||||||
break;
|
|
||||||
default:
|
|
||||||
return 0;
|
|
||||||
}
|
|
||||||
|
|
||||||
const mbedtls_x509_crt *const peer_cert = mbedtls_ssl_get_peer_cert(SSL_P(F));
|
const mbedtls_x509_crt *const peer_cert = mbedtls_ssl_get_peer_cert(SSL_P(F));
|
||||||
|
|
||||||
if(peer_cert == NULL)
|
if(peer_cert == NULL)
|
||||||
return 0;
|
return 0;
|
||||||
|
|
||||||
const mbedtls_md_info_t *const md_info = mbedtls_md_info_from_type(md_type);
|
return rb_make_certfp(peer_cert, certfp, method);
|
||||||
if(md_info == NULL)
|
|
||||||
return 0;
|
|
||||||
|
|
||||||
int ret;
|
|
||||||
if((ret = mbedtls_md(md_info, peer_cert->raw.p, peer_cert->raw.len, certfp)) != 0)
|
|
||||||
{
|
|
||||||
rb_lib_log("%s: mbedtls_md: %s", __func__, rb_ssl_strerror(ret));
|
|
||||||
return 0;
|
|
||||||
}
|
|
||||||
|
|
||||||
return hashlen;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
void
|
void
|
||||||
|
|
|
@ -245,6 +245,59 @@ rb_ssl_read_or_write(const int r_or_w, rb_fde_t *const F, void *const rbuf, cons
|
||||||
return ret;
|
return ret;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static int
|
||||||
|
make_certfp(X509 *const cert, uint8_t certfp[const RB_SSL_CERTFP_LEN], const int method)
|
||||||
|
{
|
||||||
|
unsigned int hashlen = 0;
|
||||||
|
const EVP_MD *md_type = NULL;
|
||||||
|
const ASN1_ITEM *item = NULL;
|
||||||
|
void *data = NULL;
|
||||||
|
|
||||||
|
switch(method)
|
||||||
|
{
|
||||||
|
case RB_SSL_CERTFP_METH_CERT_SHA1:
|
||||||
|
hashlen = RB_SSL_CERTFP_LEN_SHA1;
|
||||||
|
md_type = EVP_sha1();
|
||||||
|
item = ASN1_ITEM_rptr(X509);
|
||||||
|
data = cert;
|
||||||
|
break;
|
||||||
|
case RB_SSL_CERTFP_METH_CERT_SHA256:
|
||||||
|
hashlen = RB_SSL_CERTFP_LEN_SHA256;
|
||||||
|
md_type = EVP_sha256();
|
||||||
|
item = ASN1_ITEM_rptr(X509);
|
||||||
|
data = cert;
|
||||||
|
break;
|
||||||
|
case RB_SSL_CERTFP_METH_CERT_SHA512:
|
||||||
|
hashlen = RB_SSL_CERTFP_LEN_SHA512;
|
||||||
|
md_type = EVP_sha512();
|
||||||
|
item = ASN1_ITEM_rptr(X509);
|
||||||
|
data = cert;
|
||||||
|
break;
|
||||||
|
case RB_SSL_CERTFP_METH_SPKI_SHA256:
|
||||||
|
hashlen = RB_SSL_CERTFP_LEN_SHA256;
|
||||||
|
md_type = EVP_sha256();
|
||||||
|
item = ASN1_ITEM_rptr(X509_PUBKEY);
|
||||||
|
data = X509_get_X509_PUBKEY(cert);
|
||||||
|
break;
|
||||||
|
case RB_SSL_CERTFP_METH_SPKI_SHA512:
|
||||||
|
hashlen = RB_SSL_CERTFP_LEN_SHA512;
|
||||||
|
md_type = EVP_sha512();
|
||||||
|
item = ASN1_ITEM_rptr(X509_PUBKEY);
|
||||||
|
data = X509_get_X509_PUBKEY(cert);
|
||||||
|
break;
|
||||||
|
default:
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
if(ASN1_item_digest(item, md_type, data, certfp, &hashlen) != 1)
|
||||||
|
{
|
||||||
|
rb_lib_log("%s: ASN1_item_digest: %s", __func__, rb_ssl_strerror(rb_ssl_last_err()));
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
return (int) hashlen;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
/*
|
/*
|
||||||
|
@ -470,31 +523,12 @@ rb_get_ssl_certfp(rb_fde_t *const F, uint8_t certfp[const RB_SSL_CERTFP_LEN], co
|
||||||
if(F == NULL || F->ssl == NULL)
|
if(F == NULL || F->ssl == NULL)
|
||||||
return 0;
|
return 0;
|
||||||
|
|
||||||
const EVP_MD *md_type;
|
|
||||||
unsigned int hashlen;
|
|
||||||
|
|
||||||
switch(method)
|
|
||||||
{
|
|
||||||
case RB_SSL_CERTFP_METH_SHA1:
|
|
||||||
md_type = EVP_sha1();
|
|
||||||
hashlen = RB_SSL_CERTFP_LEN_SHA1;
|
|
||||||
break;
|
|
||||||
case RB_SSL_CERTFP_METH_SHA256:
|
|
||||||
md_type = EVP_sha256();
|
|
||||||
hashlen = RB_SSL_CERTFP_LEN_SHA256;
|
|
||||||
break;
|
|
||||||
case RB_SSL_CERTFP_METH_SHA512:
|
|
||||||
md_type = EVP_sha512();
|
|
||||||
hashlen = RB_SSL_CERTFP_LEN_SHA512;
|
|
||||||
break;
|
|
||||||
default:
|
|
||||||
return 0;
|
|
||||||
}
|
|
||||||
|
|
||||||
X509 *const peer_cert = SSL_get_peer_certificate(SSL_P(F));
|
X509 *const peer_cert = SSL_get_peer_certificate(SSL_P(F));
|
||||||
if(peer_cert == NULL)
|
if(peer_cert == NULL)
|
||||||
return 0;
|
return 0;
|
||||||
|
|
||||||
|
int len = 0;
|
||||||
|
|
||||||
switch(SSL_get_verify_result(SSL_P(F)))
|
switch(SSL_get_verify_result(SSL_P(F)))
|
||||||
{
|
{
|
||||||
case X509_V_OK:
|
case X509_V_OK:
|
||||||
|
@ -503,16 +537,11 @@ rb_get_ssl_certfp(rb_fde_t *const F, uint8_t certfp[const RB_SSL_CERTFP_LEN], co
|
||||||
case X509_V_ERR_DEPTH_ZERO_SELF_SIGNED_CERT:
|
case X509_V_ERR_DEPTH_ZERO_SELF_SIGNED_CERT:
|
||||||
case X509_V_ERR_UNABLE_TO_GET_ISSUER_CERT_LOCALLY:
|
case X509_V_ERR_UNABLE_TO_GET_ISSUER_CERT_LOCALLY:
|
||||||
case X509_V_ERR_CERT_UNTRUSTED:
|
case X509_V_ERR_CERT_UNTRUSTED:
|
||||||
break;
|
len = make_certfp(peer_cert, certfp, method);
|
||||||
default:
|
default:
|
||||||
X509_free(peer_cert);
|
X509_free(peer_cert);
|
||||||
return 0;
|
return len;
|
||||||
}
|
}
|
||||||
|
|
||||||
X509_digest(peer_cert, md_type, certfp, &hashlen);
|
|
||||||
X509_free(peer_cert);
|
|
||||||
|
|
||||||
return (int) hashlen;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
void
|
void
|
||||||
|
|
|
@ -1650,15 +1650,19 @@ conf_set_general_certfp_method(void *data)
|
||||||
{
|
{
|
||||||
char *method = data;
|
char *method = data;
|
||||||
|
|
||||||
if (!strcasecmp(method, "sha1"))
|
if (!strcasecmp(method, CERTFP_NAME_CERT_SHA1))
|
||||||
ConfigFileEntry.certfp_method = RB_SSL_CERTFP_METH_SHA1;
|
ConfigFileEntry.certfp_method = RB_SSL_CERTFP_METH_CERT_SHA1;
|
||||||
else if (!strcasecmp(method, "sha256"))
|
else if (!strcasecmp(method, CERTFP_NAME_CERT_SHA256))
|
||||||
ConfigFileEntry.certfp_method = RB_SSL_CERTFP_METH_SHA256;
|
ConfigFileEntry.certfp_method = RB_SSL_CERTFP_METH_CERT_SHA256;
|
||||||
else if (!strcasecmp(method, "sha512"))
|
else if (!strcasecmp(method, CERTFP_NAME_CERT_SHA512))
|
||||||
ConfigFileEntry.certfp_method = RB_SSL_CERTFP_METH_SHA512;
|
ConfigFileEntry.certfp_method = RB_SSL_CERTFP_METH_CERT_SHA512;
|
||||||
|
else if (!strcasecmp(method, CERTFP_NAME_SPKI_SHA256))
|
||||||
|
ConfigFileEntry.certfp_method = RB_SSL_CERTFP_METH_SPKI_SHA256;
|
||||||
|
else if (!strcasecmp(method, CERTFP_NAME_SPKI_SHA512))
|
||||||
|
ConfigFileEntry.certfp_method = RB_SSL_CERTFP_METH_SPKI_SHA512;
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
ConfigFileEntry.certfp_method = RB_SSL_CERTFP_METH_SHA1;
|
ConfigFileEntry.certfp_method = RB_SSL_CERTFP_METH_CERT_SHA1;
|
||||||
conf_report_error("Ignoring general::certfp_method -- bogus certfp method %s", method);
|
conf_report_error("Ignoring general::certfp_method -- bogus certfp method %s", method);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -822,7 +822,7 @@ set_default_conf(void)
|
||||||
ServerInfo.default_max_clients = MAXCONNECTIONS;
|
ServerInfo.default_max_clients = MAXCONNECTIONS;
|
||||||
|
|
||||||
ConfigFileEntry.nicklen = NICKLEN;
|
ConfigFileEntry.nicklen = NICKLEN;
|
||||||
ConfigFileEntry.certfp_method = RB_SSL_CERTFP_METH_SHA1;
|
ConfigFileEntry.certfp_method = RB_SSL_CERTFP_METH_CERT_SHA1;
|
||||||
|
|
||||||
if (!alias_dict)
|
if (!alias_dict)
|
||||||
alias_dict = irc_dictionary_create(strcasecmp);
|
alias_dict = irc_dictionary_create(strcasecmp);
|
||||||
|
@ -877,7 +877,7 @@ validate_conf(void)
|
||||||
ircd_ssl_ok = 0;
|
ircd_ssl_ok = 0;
|
||||||
} else {
|
} else {
|
||||||
ircd_ssl_ok = 1;
|
ircd_ssl_ok = 1;
|
||||||
send_new_ssl_certs(ServerInfo.ssl_cert, ServerInfo.ssl_private_key, ServerInfo.ssl_dh_params, ServerInfo.ssl_cipher_list);
|
send_new_ssl_certs(ServerInfo.ssl_cert, ServerInfo.ssl_private_key, ServerInfo.ssl_dh_params, ServerInfo.ssl_cipher_list, ConfigFileEntry.certfp_method);
|
||||||
}
|
}
|
||||||
|
|
||||||
if(ServerInfo.ssld_count > get_ssld_count())
|
if(ServerInfo.ssld_count > get_ssld_count())
|
||||||
|
|
|
@ -409,24 +409,50 @@ ssl_process_certfp(ssl_ctl_t * ctl, ssl_ctl_buf_t * ctl_buf)
|
||||||
{
|
{
|
||||||
struct Client *client_p;
|
struct Client *client_p;
|
||||||
uint32_t fd;
|
uint32_t fd;
|
||||||
|
uint32_t certfp_method;
|
||||||
uint32_t len;
|
uint32_t len;
|
||||||
uint8_t *certfp;
|
uint8_t *certfp;
|
||||||
char *certfp_string;
|
char *certfp_string;
|
||||||
int i;
|
const char *method_string;
|
||||||
|
int method_len;
|
||||||
|
|
||||||
if(ctl_buf->buflen > 9 + RB_SSL_CERTFP_LEN)
|
if(ctl_buf->buflen > 13 + RB_SSL_CERTFP_LEN)
|
||||||
return; /* bogus message..drop it.. XXX should warn here */
|
return; /* bogus message..drop it.. XXX should warn here */
|
||||||
|
|
||||||
fd = buf_to_uint32(&ctl_buf->buf[1]);
|
fd = buf_to_uint32(&ctl_buf->buf[1]);
|
||||||
len = buf_to_uint32(&ctl_buf->buf[5]);
|
certfp_method = buf_to_uint32(&ctl_buf->buf[5]);
|
||||||
certfp = (uint8_t *)&ctl_buf->buf[9];
|
len = buf_to_uint32(&ctl_buf->buf[9]);
|
||||||
|
certfp = (uint8_t *)&ctl_buf->buf[13];
|
||||||
client_p = find_cli_connid_hash(fd);
|
client_p = find_cli_connid_hash(fd);
|
||||||
if(client_p == NULL)
|
if(client_p == NULL)
|
||||||
return;
|
return;
|
||||||
|
|
||||||
|
switch (certfp_method) {
|
||||||
|
case RB_SSL_CERTFP_METH_CERT_SHA1:
|
||||||
|
method_string = CERTFP_PREFIX_CERT_SHA1;
|
||||||
|
break;
|
||||||
|
case RB_SSL_CERTFP_METH_CERT_SHA256:
|
||||||
|
method_string = CERTFP_PREFIX_CERT_SHA256;
|
||||||
|
break;
|
||||||
|
case RB_SSL_CERTFP_METH_CERT_SHA512:
|
||||||
|
method_string = CERTFP_PREFIX_CERT_SHA512;
|
||||||
|
break;
|
||||||
|
case RB_SSL_CERTFP_METH_SPKI_SHA256:
|
||||||
|
method_string = CERTFP_PREFIX_SPKI_SHA256;
|
||||||
|
break;
|
||||||
|
case RB_SSL_CERTFP_METH_SPKI_SHA512:
|
||||||
|
method_string = CERTFP_PREFIX_SPKI_SHA512;
|
||||||
|
break;
|
||||||
|
default:
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
method_len = strlen(method_string);
|
||||||
|
|
||||||
rb_free(client_p->certfp);
|
rb_free(client_p->certfp);
|
||||||
certfp_string = rb_malloc(len * 2 + 1);
|
certfp_string = rb_malloc(method_len + len * 2 + 1);
|
||||||
for(i = 0; i < len; i++)
|
rb_strlcpy(certfp_string, method_string, method_len + len * 2 + 1);
|
||||||
rb_snprintf(certfp_string + 2 * i, 3, "%02x",
|
for(uint32_t i = 0; i < len; i++)
|
||||||
|
rb_snprintf(certfp_string + method_len + 2 * i, 3, "%02x",
|
||||||
certfp[i]);
|
certfp[i]);
|
||||||
client_p->certfp = certfp_string;
|
client_p->certfp = certfp_string;
|
||||||
}
|
}
|
||||||
|
@ -674,7 +700,7 @@ send_certfp_method(ssl_ctl_t *ctl, int method)
|
||||||
}
|
}
|
||||||
|
|
||||||
void
|
void
|
||||||
send_new_ssl_certs(const char *ssl_cert, const char *ssl_private_key, const char *ssl_dh_params, const char *ssl_cipher_list)
|
send_new_ssl_certs(const char *ssl_cert, const char *ssl_private_key, const char *ssl_dh_params, const char *ssl_cipher_list, const int method)
|
||||||
{
|
{
|
||||||
rb_dlink_node *ptr;
|
rb_dlink_node *ptr;
|
||||||
if(ssl_cert == NULL)
|
if(ssl_cert == NULL)
|
||||||
|
@ -685,6 +711,7 @@ send_new_ssl_certs(const char *ssl_cert, const char *ssl_private_key, const char
|
||||||
RB_DLINK_FOREACH(ptr, ssl_daemons.head)
|
RB_DLINK_FOREACH(ptr, ssl_daemons.head)
|
||||||
{
|
{
|
||||||
ssl_ctl_t *ctl = ptr->data;
|
ssl_ctl_t *ctl = ptr->data;
|
||||||
|
send_certfp_method(ctl, method);
|
||||||
send_new_ssl_certs_one(ctl, ssl_cert, ssl_private_key, ssl_dh_params, ssl_cipher_list);
|
send_new_ssl_certs_one(ctl, ssl_cert, ssl_private_key, ssl_dh_params, ssl_cipher_list);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
11
ssld/ssld.c
11
ssld/ssld.c
|
@ -154,7 +154,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 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 const char *remote_closed = "Remote host closed the connection";
|
||||||
static int ssld_ssl_ok;
|
static int ssld_ssl_ok;
|
||||||
static int certfp_method = RB_SSL_CERTFP_METH_SHA1;
|
static int certfp_method = RB_SSL_CERTFP_METH_CERT_SHA1;
|
||||||
#ifdef HAVE_LIBZ
|
#ifdef HAVE_LIBZ
|
||||||
static int ssld_zlib_ok = 1;
|
static int ssld_zlib_ok = 1;
|
||||||
#else
|
#else
|
||||||
|
@ -688,17 +688,18 @@ ssl_send_cipher(conn_t *conn)
|
||||||
static void
|
static void
|
||||||
ssl_send_certfp(conn_t *conn)
|
ssl_send_certfp(conn_t *conn)
|
||||||
{
|
{
|
||||||
uint8_t buf[9 + RB_SSL_CERTFP_LEN];
|
uint8_t buf[13 + RB_SSL_CERTFP_LEN];
|
||||||
|
|
||||||
int len = rb_get_ssl_certfp(conn->mod_fd, &buf[9], certfp_method);
|
int len = rb_get_ssl_certfp(conn->mod_fd, &buf[13], certfp_method);
|
||||||
if (!len)
|
if (!len)
|
||||||
return;
|
return;
|
||||||
|
|
||||||
lrb_assert(len <= RB_SSL_CERTFP_LEN);
|
lrb_assert(len <= RB_SSL_CERTFP_LEN);
|
||||||
buf[0] = 'F';
|
buf[0] = 'F';
|
||||||
uint32_to_buf(&buf[1], conn->id);
|
uint32_to_buf(&buf[1], conn->id);
|
||||||
uint32_to_buf(&buf[5], len);
|
uint32_to_buf(&buf[5], certfp_method);
|
||||||
mod_cmd_write_queue(conn->ctl, buf, 9 + len);
|
uint32_to_buf(&buf[9], len);
|
||||||
|
mod_cmd_write_queue(conn->ctl, buf, 13 + len);
|
||||||
}
|
}
|
||||||
|
|
||||||
static void
|
static void
|
||||||
|
|
Loading…
Reference in a new issue