there are regression tests written using vtest from varnish

https://github.com/haproxy/haproxy/tree/master/reg-tests

all important part of haproxy are supposed to be covered with reg-tests
(test coverage is getting better and better, but not yet complete)

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

> 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