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