Oh, wasn't aware of that.
Is there some automation to test this or should I manually verify this?


On Sun, Jul 5, 2020 at 2:13 PM Илья Шипицин <chipits...@gmail.com> wrote:

> I recall some issues with LibreSSL and chaining trust. Like it was
> declared but never worked.
> we'll see that in runtime if there are such issues
>
> вс, 5 июл. 2020 г. в 16:06, Илья Шипицин <chipits...@gmail.com>:
>
>> nice, all ssl variants build well
>> https://travis-ci.com/github/chipitsine/haproxy/builds/174323866
>>
>> вс, 5 июл. 2020 г. в 15:48, Gersner <gers...@gmail.com>:
>>
>>>
>>>
>>> On Sun, Jul 5, 2020 at 1:42 PM Илья Шипицин <chipits...@gmail.com>
>>> wrote:
>>>
>>>> do you have your patches on github fork ?
>>>> (I could not find your fork)
>>>>
>>> Yes. See branch
>>> https://github.com/Azure/haproxy/tree/wip/sgersner/ca-sign-extra
>>>
>>>>
>>>> вс, 5 июл. 2020 г. в 15:13, Gersner <gers...@gmail.com>:
>>>>
>>>>>
>>>>>
>>>>> On Sun, Jul 5, 2020 at 12:28 PM Илья Шипицин <chipits...@gmail.com>
>>>>> wrote:
>>>>>
>>>>>> does it clearly applies to current master ? either gmail scrambled
>>>>>> patch or it is not.
>>>>>> can you try please ?
>>>>>>
>>>>> Exporting the eml and running 'git am' it works cleanly.
>>>>>
>>>>> I've reproduced the exact same output when copy-pasting from gmail. It
>>>>> seems gmail converts the tabs to spaces and this fails the patch (Not sure
>>>>> why).
>>>>> Running patch with '-l' will resolve this, but it's probably safer to
>>>>> run git am on the email.
>>>>>
>>>>>
>>>>>>
>>>>>> $ 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