MINOR: ssl: add ssl_sock_get_pkey_algo function
ssl_sock_get_pkey_algo can be used to report pkey algorithm to log
and ppv2 (RSA2048, EC256,...).
Extract pkey information is not free in ssl api (lock/alloc/free):
haproxy can use the pkey information computed in load_certificate.
Store and use this information in a SSL ex_data when available,
compute it if not (SSL multicert bundled and generated cert).
diff --git a/include/proto/ssl_sock.h b/include/proto/ssl_sock.h
index ef03de6..91456e2 100644
--- a/include/proto/ssl_sock.h
+++ b/include/proto/ssl_sock.h
@@ -56,6 +56,7 @@
int ssl_sock_get_cert_used_sess(struct connection *conn);
int ssl_sock_get_cert_used_conn(struct connection *conn);
int ssl_sock_get_remote_common_name(struct connection *conn, struct chunk *out);
+int ssl_sock_get_pkey_algo(struct connection *conn, struct chunk *out);
unsigned int ssl_sock_get_verify_result(struct connection *conn);
#if (defined SSL_CTRL_SET_TLSEXT_STATUS_REQ_CB && !defined OPENSSL_NO_OCSP)
int ssl_sock_update_ocsp_response(struct chunk *ocsp_response, char **err);
diff --git a/src/ssl_sock.c b/src/ssl_sock.c
index 1f52f18..555c7c4 100644
--- a/src/ssl_sock.c
+++ b/src/ssl_sock.c
@@ -262,6 +262,8 @@
struct pool_head *pool_head_ssl_capture = NULL;
static int ssl_capture_ptr_index = -1;
+static int ssl_pkey_info_index = -1;
+
#if (defined SSL_CTRL_SET_TLSEXT_TICKET_KEY_CB && TLS_TICKETS_NO > 0)
struct list tlskeys_reference = LIST_HEAD_INIT(tlskeys_reference);
#endif
@@ -2059,6 +2061,11 @@
static void ssl_sock_switchctx_set(SSL *ssl, SSL_CTX *ctx)
{
+ struct pkey_info *pkinfo;
+
+ pkinfo = SSL_CTX_get_ex_data(ctx, ssl_pkey_info_index);
+ if (pkinfo)
+ SSL_set_ex_data(ssl, ssl_pkey_info_index, pkinfo);
SSL_set_verify(ssl, SSL_CTX_get_verify_mode(ctx), ssl_sock_bind_verifycbk);
SSL_set_client_CA_list(ssl, SSL_dup_CA_list(SSL_CTX_get_client_CA_list(ctx)));
SSL_set_SSL_CTX(ssl, ctx);
@@ -2705,6 +2712,8 @@
sc->kinfo = kinfo;
sc->order = order++;
sc->neg = neg;
+ if (kinfo.sig != TLSEXT_signature_anonymous)
+ SSL_CTX_set_ex_data(ctx, ssl_pkey_info_index, &sc->kinfo);
if (wild)
ebst_insert(&s->sni_w_ctx, &sc->name);
else
@@ -5701,6 +5710,64 @@
}
}
+/* used for ppv2 pkey alog (can be used for logging) */
+int ssl_sock_get_pkey_algo(struct connection *conn, struct chunk *out)
+{
+ struct pkey_info *pkinfo;
+ int bits = 0;
+ int sig = TLSEXT_signature_anonymous;
+ int len = -1;
+
+ if (!ssl_sock_is_ssl(conn))
+ return 0;
+
+ pkinfo = SSL_get_ex_data(conn->xprt_ctx, ssl_pkey_info_index);
+ if (pkinfo) {
+ sig = pkinfo->sig;
+ bits = pkinfo->bits;
+ } else {
+ /* multicert and generated cert have no pkey info */
+ X509 *crt;
+ EVP_PKEY *pkey;
+ crt = SSL_get_certificate(conn->xprt_ctx);
+ if (!crt)
+ return 0;
+ pkey = X509_get_pubkey(crt);
+ if (pkey) {
+ bits = EVP_PKEY_bits(pkey);
+ switch(EVP_PKEY_base_id(pkey)) {
+ case EVP_PKEY_RSA:
+ sig = TLSEXT_signature_rsa;
+ break;
+ case EVP_PKEY_EC:
+ sig = TLSEXT_signature_ecdsa;
+ break;
+ case EVP_PKEY_DSA:
+ sig = TLSEXT_signature_dsa;
+ break;
+ }
+ EVP_PKEY_free(pkey);
+ }
+ }
+
+ switch(sig) {
+ case TLSEXT_signature_rsa:
+ len = chunk_printf(out, "RSA%d", bits);
+ break;
+ case TLSEXT_signature_ecdsa:
+ len = chunk_printf(out, "EC%d", bits);
+ break;
+ case TLSEXT_signature_dsa:
+ len = chunk_printf(out, "DSA%d", bits);
+ break;
+ default:
+ return 0;
+ }
+ if (len < 0)
+ return 0;
+ return 1;
+}
+
/* used for logging/ppv2, may be changed for a sample fetch later */
const char *ssl_sock_get_cipher_name(struct connection *conn)
{
@@ -8813,6 +8880,7 @@
sctl_ex_index = SSL_CTX_get_ex_new_index(0, NULL, NULL, NULL, ssl_sock_sctl_free_func);
#endif
ssl_capture_ptr_index = SSL_CTX_get_ex_new_index(0, NULL, NULL, NULL, ssl_sock_capture_free_func);
+ ssl_pkey_info_index = SSL_CTX_get_ex_new_index(0, NULL, NULL, NULL, NULL);
sample_register_fetches(&sample_fetch_keywords);
acl_register_keywords(&acl_kws);
bind_register_keywords(&bind_kws);