]> git.ipfire.org Git - thirdparty/haproxy.git/commitdiff
MINOR: ssl: add ssl_sock_get_pkey_algo function
authorEmmanuel Hocdet <manu@gandi.net>
Tue, 31 Oct 2017 14:46:07 +0000 (15:46 +0100)
committerWilly Tarreau <w@1wt.eu>
Thu, 1 Mar 2018 10:34:05 +0000 (11:34 +0100)
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).

include/proto/ssl_sock.h
src/ssl_sock.c

index ef03de69d4fc1abc198f0880375f4c536d9ae7fd..91456e2204e35237b5219d259a4b16855e39a1ea 100644 (file)
@@ -56,6 +56,7 @@ void ssl_sock_set_servername(struct connection *conn, const char *hostname);
 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);
index 1f52f18682eb82b32b1f853350347fabff27cb1a..555c7c4eca96326a99959e646a5fd9ae6fa7ca3f 100644 (file)
@@ -262,6 +262,8 @@ struct ssl_capture {
 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 struct {
 
 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 @@ static int ssl_sock_add_cert_sni(SSL_CTX *ctx, struct bind_conf *s, struct ssl_b
                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 @@ static void ssl_sock_shutw(struct connection *conn, int clean)
        }
 }
 
+/* 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 @@ static void __ssl_sock_init(void)
        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);