does it clearly applies to current master ? either gmail scrambled patch or
it is not.
can you try please ?

$ patch -p1 < 1.patch
patching file doc/configuration.txt
patching file include/haproxy/listener-t.h
Hunk #1 FAILED at 163.
1 out of 1 hunk FAILED -- saving rejects to file
include/haproxy/listener-t.h.rej
patching file src/cfgparse-ssl.c
Hunk #1 succeeded at 538 with fuzz 1.
Hunk #2 FAILED at 1720.
1 out of 2 hunks FAILED -- saving rejects to file src/cfgparse-ssl.c.rej
patching file src/ssl_sock.c
Hunk #1 FAILED at 1750.
Hunk #2 FAILED at 1864.
Hunk #3 FAILED at 1912.
Hunk #4 FAILED at 1943.
Hunk #5 FAILED at 1970.
Hunk #6 FAILED at 4823.
Hunk #7 FAILED at 4843.
7 out of 7 hunks FAILED -- saving rejects to file src/ssl_sock.c.rej

вс, 5 июл. 2020 г. в 11:46, <gers...@gmail.com>:

> From: Shimi Gersner <sgers...@microsoft.com>
>
> haproxy supports generating SSL certificates based on SNI using a provided
> CA signing certificate. Because CA certificates may be signed by multiple
> CAs, in some scenarios, it is neccesary for the server to attach the trust
> chain
> in addition to the generated certificate.
>
> The following patch adds the ability to optionally serve all public
> certificates provided in the `ca-sign-file` PEM file.
> Certificate loading was ported to use `ca_sign_use_chain` structure,
> instead of directly reading public/private keys.
> ---
>  doc/configuration.txt        |  8 +++
>  include/haproxy/listener-t.h |  4 +-
>  src/cfgparse-ssl.c           | 13 +++++
>  src/ssl_sock.c               | 98 ++++++++++++++++++++----------------
>  4 files changed, 78 insertions(+), 45 deletions(-)
>
> diff --git a/doc/configuration.txt b/doc/configuration.txt
> index 6d472134e..1d3878bc1 100644
> --- a/doc/configuration.txt
> +++ b/doc/configuration.txt
> @@ -12158,6 +12158,14 @@ ca-sign-pass <passphrase>
>    the dynamic generation of certificates is enabled. See
>    'generate-certificates' for details.
>
> +ca-sign-use-chain
> +  This setting is only available when support for OpenSSL was built in.
> It is
> +  the CA private key passphrase. This setting is optional and used only
> when
> +  the dynamic generation of certificates is enabled. See
> +  'generate-certificates' for details.
> +  Enabling this flag will attach all public certificates encoded in
> `ca-sign-file`
> +  to the served certificate to the client, enabling trust.
> +
>  ca-verify-file <cafile>
>    This setting designates a PEM file from which to load CA certificates
> used to
>    verify client's certificate. It designates CA certificates which must
> not be
> diff --git a/include/haproxy/listener-t.h b/include/haproxy/listener-t.h
> index 224e32513..38ca2839f 100644
> --- a/include/haproxy/listener-t.h
> +++ b/include/haproxy/listener-t.h
> @@ -163,8 +163,8 @@ struct bind_conf {
>         char *ca_sign_file;        /* CAFile used to generate and sign
> server certificates */
>         char *ca_sign_pass;        /* CAKey passphrase */
>
> -       X509     *ca_sign_cert;    /* CA certificate referenced by ca_file
> */
> -       EVP_PKEY *ca_sign_pkey;    /* CA private key referenced by ca_key
> */
> +       int ca_sign_use_chain;     /* Optionally attached the certificate
> chain to the served certificate */
> +       struct cert_key_and_chain * ca_sign_ckch;       /* CA and possible
> certificate chain for ca generation */
>  #endif
>         struct proxy *frontend;    /* the frontend all these listeners
> belong to, or NULL */
>         const struct mux_proto_list *mux_proto; /* the mux to use for all
> incoming connections (specified by the "proto" keyword) */
> diff --git a/src/cfgparse-ssl.c b/src/cfgparse-ssl.c
> index 144cef882..270c857f9 100644
> --- a/src/cfgparse-ssl.c
> +++ b/src/cfgparse-ssl.c
> @@ -538,6 +538,18 @@ static int bind_parse_ca_sign_file(char **args, int
> cur_arg, struct proxy *px, s
>         return 0;
>  }
>
> +/* parse the "ca-sign-use-chain" bind keyword */
> +static int bind_parse_ca_sign_use_chain(char **args, int cur_arg, struct
> proxy *px, struct bind_conf *conf, char **err)
> +{
> +#if (defined SSL_CTRL_SET_TLSEXT_HOSTNAME && !defined
> SSL_NO_GENERATE_CERTIFICATES && defined SSL_CTX_set1_chain)
> +       conf->ca_sign_use_chain = 1;
> +#else
> +       memprintf(err, "%sthis version of openssl cannot attach
> certificate chain for SSL certificate generation.\n",
> +                 err && *err ? *err : "");
> +#endif
> +       return 0;
> +}
> +
>  /* parse the "ca-sign-pass" bind keyword */
>  static int bind_parse_ca_sign_pass(char **args, int cur_arg, struct proxy
> *px, struct bind_conf *conf, char **err)
>  {
> @@ -1708,6 +1720,7 @@ static struct bind_kw_list bind_kws = { "SSL", { }, {
>         { "ca-ignore-err",         bind_parse_ignore_err,         1 }, /*
> set error IDs to ignore on verify depth > 0 */
>         { "ca-sign-file",          bind_parse_ca_sign_file,       1 }, /*
> set CAFile used to generate and sign server certs */
>         { "ca-sign-pass",          bind_parse_ca_sign_pass,       1 }, /*
> set CAKey passphrase */
> +       { "ca-sign-use-chain",     bind_parse_ca_sign_use_chain,  1 }, /*
> enable attaching ca chain to generated certificate */
>         { "ciphers",               bind_parse_ciphers,            1 }, /*
> set SSL cipher suite */
>  #if (HA_OPENSSL_VERSION_NUMBER >= 0x10101000L)
>         { "ciphersuites",          bind_parse_ciphersuites,       1 }, /*
> set TLS 1.3 cipher suite */
> diff --git a/src/ssl_sock.c b/src/ssl_sock.c
> index a32db1a28..54829eb98 100644
> --- a/src/ssl_sock.c
> +++ b/src/ssl_sock.c
> @@ -1750,8 +1750,8 @@ static int ssl_sock_advertise_alpn_protos(SSL *s,
> const unsigned char **out,
>  static SSL_CTX *
>  ssl_sock_do_create_cert(const char *servername, struct bind_conf
> *bind_conf, SSL *ssl)
>  {
> -       X509         *cacert  = bind_conf->ca_sign_cert;
> -       EVP_PKEY     *capkey  = bind_conf->ca_sign_pkey;
> +       X509         *cacert  = bind_conf->ca_sign_ckch->cert;
> +       EVP_PKEY     *capkey  = bind_conf->ca_sign_ckch->key;
>         SSL_CTX      *ssl_ctx = NULL;
>         X509         *newcrt  = NULL;
>         EVP_PKEY     *pkey    = NULL;
> @@ -1864,6 +1864,16 @@ ssl_sock_do_create_cert(const char *servername,
> struct bind_conf *bind_conf, SSL
>         if (!SSL_CTX_check_private_key(ssl_ctx))
>                 goto mkcert_error;
>
> +       /* Assign chain if any */
> +       if (bind_conf->ca_sign_use_chain &&
> bind_conf->ca_sign_ckch->chain) {
> +               if (!SSL_CTX_set1_chain(ssl_ctx,
> bind_conf->ca_sign_ckch->chain)) {
> +                       goto mkcert_error;
> +               }
> +               if (!SSL_CTX_add1_chain_cert(ssl_ctx,
> bind_conf->ca_sign_ckch->cert)) {
> +                       goto mkcert_error;
> +               }
> +       }
> +
>         if (newcrt) X509_free(newcrt);
>
>  #ifndef OPENSSL_NO_DH
> @@ -1912,7 +1922,7 @@ ssl_sock_assign_generated_cert(unsigned int key,
> struct bind_conf *bind_conf, SS
>
>         if (ssl_ctx_lru_tree) {
>                 HA_RWLOCK_WRLOCK(SSL_GEN_CERTS_LOCK, &ssl_ctx_lru_rwlock);
> -               lru = lru64_lookup(key, ssl_ctx_lru_tree,
> bind_conf->ca_sign_cert, 0);
> +               lru = lru64_lookup(key, ssl_ctx_lru_tree,
> bind_conf->ca_sign_ckch->cert, 0);
>                 if (lru && lru->domain) {
>                         if (ssl)
>                                 SSL_set_SSL_CTX(ssl, (SSL_CTX *)lru->data);
> @@ -1943,14 +1953,14 @@ ssl_sock_set_generated_cert(SSL_CTX *ssl_ctx,
> unsigned int key, struct bind_conf
>
>         if (ssl_ctx_lru_tree) {
>                 HA_RWLOCK_WRLOCK(SSL_GEN_CERTS_LOCK, &ssl_ctx_lru_rwlock);
> -               lru = lru64_get(key, ssl_ctx_lru_tree,
> bind_conf->ca_sign_cert, 0);
> +               lru = lru64_get(key, ssl_ctx_lru_tree,
> bind_conf->ca_sign_ckch->cert, 0);
>                 if (!lru) {
>                         HA_RWLOCK_WRUNLOCK(SSL_GEN_CERTS_LOCK,
> &ssl_ctx_lru_rwlock);
>                         return -1;
>                 }
>                 if (lru->domain && lru->data)
>                         lru->free((SSL_CTX *)lru->data);
> -               lru64_commit(lru, ssl_ctx, bind_conf->ca_sign_cert, 0,
> (void (*)(void *))SSL_CTX_free);
> +               lru64_commit(lru, ssl_ctx, bind_conf->ca_sign_ckch->cert,
> 0, (void (*)(void *))SSL_CTX_free);
>                 HA_RWLOCK_WRUNLOCK(SSL_GEN_CERTS_LOCK,
> &ssl_ctx_lru_rwlock);
>                 return 0;
>         }
> @@ -1970,7 +1980,7 @@ ssl_sock_generated_cert_key(const void *data, size_t
> len)
>  static int
>  ssl_sock_generate_certificate(const char *servername, struct bind_conf
> *bind_conf, SSL *ssl)
>  {
> -       X509         *cacert  = bind_conf->ca_sign_cert;
> +       X509         *cacert  = bind_conf->ca_sign_ckch->cert;
>         SSL_CTX      *ssl_ctx = NULL;
>         struct lru64 *lru     = NULL;
>         unsigned int  key;
> @@ -4823,13 +4833,12 @@ int
>  ssl_sock_load_ca(struct bind_conf *bind_conf)
>  {
>         struct proxy *px = bind_conf->frontend;
> -       FILE     *fp;
> -       X509     *cacert = NULL;
> -       EVP_PKEY *capkey = NULL;
> -       int       err    = 0;
> +       struct cert_key_and_chain *ckch = NULL;
> +       int ret = 0;
> +       char *err = NULL;
>
>         if (!bind_conf->generate_certs)
> -               return err;
> +               return ret;
>
>  #if (defined SSL_CTRL_SET_TLSEXT_HOSTNAME && !defined
> SSL_NO_GENERATE_CERTIFICATES)
>         if (global_ssl.ctx_cache) {
> @@ -4843,52 +4852,55 @@ ssl_sock_load_ca(struct bind_conf *bind_conf)
>                 ha_alert("Proxy '%s': cannot enable certificate
> generation, "
>                          "no CA certificate File configured at [%s:%d].\n",
>                          px->id, bind_conf->file, bind_conf->line);
> -               goto load_error;
> +               goto failed;
>         }
>
> -       /* read in the CA certificate */
> -       if (!(fp = fopen(bind_conf->ca_sign_file, "r"))) {
> -               ha_alert("Proxy '%s': Failed to read CA certificate file
> '%s' at [%s:%d].\n",
> -                        px->id, bind_conf->ca_sign_file, bind_conf->file,
> bind_conf->line);
> -               goto load_error;
> +       /* Allocate cert structure */
> +       ckch = calloc(1, sizeof(struct cert_key_and_chain));
> +       if (!ckch) {
> +               ha_alert("Proxy '%s': Failed to read CA certificate file
> '%s' at [%s:%d]. Chain allocation failure\n",
> +                       px->id, bind_conf->ca_sign_file, bind_conf->file,
> bind_conf->line);
>         }
> -       if (!(cacert = PEM_read_X509(fp, NULL, NULL, NULL))) {
> -               ha_alert("Proxy '%s': Failed to read CA certificate file
> '%s' at [%s:%d].\n",
> -                        px->id, bind_conf->ca_sign_file, bind_conf->file,
> bind_conf->line);
> -               goto read_error;
> +
> +       /* Try to parse file */
> +       if (ssl_sock_load_files_into_ckch(bind_conf->ca_sign_file, ckch,
> &err)) {
> +               ha_alert("Proxy '%s': Failed to read CA certificate file
> '%s' at [%s:%d]. Chain loading failed: %s\n",
> +                       px->id, bind_conf->ca_sign_file, bind_conf->file,
> bind_conf->line, err);
> +               if (err) free(err);
> +               goto failed;
>         }
> -       rewind(fp);
> -       if (!(capkey = PEM_read_PrivateKey(fp, NULL, NULL,
> bind_conf->ca_sign_pass))) {
> -               ha_alert("Proxy '%s': Failed to read CA private key file
> '%s' at [%s:%d].\n",
> -                        px->id, bind_conf->ca_sign_file, bind_conf->file,
> bind_conf->line);
> -               goto read_error;
> +
> +       /* Fail if missing cert or pkey */
> +       if ((!ckch->cert) || (!ckch->key)) {
> +               ha_alert("Proxy '%s': Failed to read CA certificate file
> '%s' at [%s:%d]. Chain missing certificate or private key\n",
> +                       px->id, bind_conf->ca_sign_file, bind_conf->file,
> bind_conf->line);
> +               goto failed;
>         }
>
> -       fclose (fp);
> -       bind_conf->ca_sign_cert = cacert;
> -       bind_conf->ca_sign_pkey = capkey;
> -       return err;
> +       /* Final assignment to bind */
> +       bind_conf->ca_sign_ckch = ckch;
> +       return ret;
> +
> + failed:
> +       if (ckch) {
> +               ssl_sock_free_cert_key_and_chain_contents(ckch);
> +               free(ckch);
> +       }
>
> - read_error:
> -       fclose (fp);
> -       if (capkey) EVP_PKEY_free(capkey);
> -       if (cacert) X509_free(cacert);
> - load_error:
>         bind_conf->generate_certs = 0;
> -       err++;
> -       return err;
> +       ret++;
> +       return ret;
>  }
>
>  /* Release CA cert and private key used to generate certificated */
>  void
>  ssl_sock_free_ca(struct bind_conf *bind_conf)
>  {
> -       if (bind_conf->ca_sign_pkey)
> -               EVP_PKEY_free(bind_conf->ca_sign_pkey);
> -       if (bind_conf->ca_sign_cert)
> -               X509_free(bind_conf->ca_sign_cert);
> -       bind_conf->ca_sign_pkey = NULL;
> -       bind_conf->ca_sign_cert = NULL;
> +       if (bind_conf->ca_sign_ckch) {
> +
>  ssl_sock_free_cert_key_and_chain_contents(bind_conf->ca_sign_ckch);
> +               free(bind_conf->ca_sign_ckch);
> +               bind_conf->ca_sign_ckch = NULL;
> +       }
>  }
>
>  /*
> --
> 2.27.0
>
>
>

Reply via email to