MINOR: ssl: extract full pkey info in load_certificate

Private key information is used in switchctx to implement native multicert
selection (ecdsa/rsa/anonymous). This patch extract and store full pkey
information: dsa type and pkey size in bits. This can be used for switchctx
or to report pkey informations in ppv2 and log.
This commit is contained in:
Emmanuel Hocdet 2017-10-27 18:43:29 +02:00 committed by Willy Tarreau
parent 8c0c34b6e7
commit ddc090bc55
2 changed files with 25 additions and 16 deletions

View File

@ -27,11 +27,16 @@
#include <common/hathreads.h>
struct pkey_info {
uint8_t sig; /* TLSEXT_signature_[rsa,ecdsa,...] */
uint16_t bits; /* key size in bits */
};
struct sni_ctx {
SSL_CTX *ctx; /* context associated to the certificate */
int order; /* load order for the certificate */
uint8_t neg; /* reject if match */
uint8_t key_sig; /* TLSEXT_signature_[rsa,ecdsa,...] */
struct pkey_info kinfo; /* pkey info */
struct ssl_bind_conf *conf; /* ssl "bind" conf for the certificate */
struct ebmb_node name; /* node holding the servername value */
};

View File

@ -2226,7 +2226,7 @@ static int ssl_sock_switchctx_cbk(SSL *ssl, int *al, void *arg)
/* lookup a not neg filter */
for (n = node; n; n = ebmb_next_dup(n)) {
if (!container_of(n, struct sni_ctx, name)->neg) {
switch(container_of(n, struct sni_ctx, name)->key_sig) {
switch(container_of(n, struct sni_ctx, name)->kinfo.sig) {
case TLSEXT_signature_ecdsa:
if (has_ecdsa) {
node_ecdsa = n;
@ -2240,7 +2240,7 @@ static int ssl_sock_switchctx_cbk(SSL *ssl, int *al, void *arg)
goto find_one;
}
break;
default: /* TLSEXT_signature_anonymous */
default: /* TLSEXT_signature_anonymous|dsa */
if (!node_anonymous)
node_anonymous = n;
break;
@ -2252,7 +2252,7 @@ static int ssl_sock_switchctx_cbk(SSL *ssl, int *al, void *arg)
node = ebst_lookup(&s->sni_w_ctx, wildp);
for (n = node; n; n = ebmb_next_dup(n)) {
if (!container_of(n, struct sni_ctx, name)->neg) {
switch(container_of(n, struct sni_ctx, name)->key_sig) {
switch(container_of(n, struct sni_ctx, name)->kinfo.sig) {
case TLSEXT_signature_ecdsa:
if (has_ecdsa) {
node_ecdsa = n;
@ -2266,7 +2266,7 @@ static int ssl_sock_switchctx_cbk(SSL *ssl, int *al, void *arg)
goto find_one;
}
break;
default: /* TLSEXT_signature_anonymous */
default: /* TLSEXT_signature_anonymous|dsa */
if (!node_anonymous)
node_anonymous = n;
break;
@ -2659,7 +2659,7 @@ end:
#endif
static int ssl_sock_add_cert_sni(SSL_CTX *ctx, struct bind_conf *s, struct ssl_bind_conf *conf,
uint8_t key_sig, char *name, int order)
struct pkey_info kinfo, char *name, int order)
{
struct sni_ctx *sc;
int wild = 0, neg = 0;
@ -2692,8 +2692,7 @@ static int ssl_sock_add_cert_sni(SSL_CTX *ctx, struct bind_conf *s, struct ssl_b
node = ebst_lookup(&s->sni_ctx, trash.str);
for (; node; node = ebmb_next_dup(node)) {
sc = ebmb_entry(node, struct sni_ctx, name);
if (sc->ctx == ctx && sc->conf == conf &&
sc->key_sig == key_sig && sc->neg == neg)
if (sc->ctx == ctx && sc->conf == conf && sc->neg == neg)
return order;
}
@ -2703,7 +2702,7 @@ static int ssl_sock_add_cert_sni(SSL_CTX *ctx, struct bind_conf *s, struct ssl_b
memcpy(sc->name.key, trash.str, len + 1);
sc->ctx = ctx;
sc->conf = conf;
sc->key_sig = key_sig;
sc->kinfo = kinfo;
sc->order = order++;
sc->neg = neg;
if (wild)
@ -3073,6 +3072,7 @@ static int ssl_sock_load_multi_cert(const char *path, struct bind_conf *bind_con
while (node) {
SSL_CTX *cur_ctx;
char cur_file[MAXPATHLEN+1];
const struct pkey_info kinfo = { .sig = TLSEXT_signature_anonymous, .bits = 0 };
str = (char *)container_of(node, struct sni_keytype, name)->name.key;
i = container_of(node, struct sni_keytype, name)->keytypes;
@ -3136,7 +3136,7 @@ static int ssl_sock_load_multi_cert(const char *path, struct bind_conf *bind_con
/* Update SNI Tree */
key_combos[i-1].order = ssl_sock_add_cert_sni(cur_ctx, bind_conf, ssl_conf,
TLSEXT_signature_anonymous, str, key_combos[i-1].order);
kinfo, str, key_combos[i-1].order);
node = ebmb_next(node);
}
@ -3197,7 +3197,7 @@ static int ssl_sock_load_cert_chain_file(SSL_CTX *ctx, const char *file, struct
pem_password_cb *passwd_cb;
void *passwd_cb_userdata;
EVP_PKEY *pkey;
uint8_t key_sig = TLSEXT_signature_anonymous;
struct pkey_info kinfo = { .sig = TLSEXT_signature_anonymous, .bits = 0 };
#ifdef SSL_CTRL_SET_TLSEXT_HOSTNAME
STACK_OF(GENERAL_NAME) *names;
@ -3220,12 +3220,16 @@ static int ssl_sock_load_cert_chain_file(SSL_CTX *ctx, const char *file, struct
pkey = X509_get_pubkey(x);
if (pkey) {
kinfo.bits = EVP_PKEY_bits(pkey);
switch(EVP_PKEY_base_id(pkey)) {
case EVP_PKEY_RSA:
key_sig = TLSEXT_signature_rsa;
kinfo.sig = TLSEXT_signature_rsa;
break;
case EVP_PKEY_EC:
key_sig = TLSEXT_signature_ecdsa;
kinfo.sig = TLSEXT_signature_ecdsa;
break;
case EVP_PKEY_DSA:
kinfo.sig = TLSEXT_signature_dsa;
break;
}
EVP_PKEY_free(pkey);
@ -3233,7 +3237,7 @@ static int ssl_sock_load_cert_chain_file(SSL_CTX *ctx, const char *file, struct
if (fcount) {
while (fcount--)
order = ssl_sock_add_cert_sni(ctx, s, ssl_conf, key_sig, sni_filter[fcount], order);
order = ssl_sock_add_cert_sni(ctx, s, ssl_conf, kinfo, sni_filter[fcount], order);
}
else {
#ifdef SSL_CTRL_SET_TLSEXT_HOSTNAME
@ -3243,7 +3247,7 @@ static int ssl_sock_load_cert_chain_file(SSL_CTX *ctx, const char *file, struct
GENERAL_NAME *name = sk_GENERAL_NAME_value(names, i);
if (name->type == GEN_DNS) {
if (ASN1_STRING_to_UTF8((unsigned char **)&str, name->d.dNSName) >= 0) {
order = ssl_sock_add_cert_sni(ctx, s, ssl_conf, key_sig, str, order);
order = ssl_sock_add_cert_sni(ctx, s, ssl_conf, kinfo, str, order);
OPENSSL_free(str);
}
}
@ -3259,7 +3263,7 @@ static int ssl_sock_load_cert_chain_file(SSL_CTX *ctx, const char *file, struct
value = X509_NAME_ENTRY_get_data(entry);
if (ASN1_STRING_to_UTF8((unsigned char **)&str, value) >= 0) {
order = ssl_sock_add_cert_sni(ctx, s, ssl_conf, key_sig, str, order);
order = ssl_sock_add_cert_sni(ctx, s, ssl_conf, kinfo, str, order);
OPENSSL_free(str);
}
}