On Sun, Jul 5, 2020 at 12:28 PM Илья Шипицин <[email protected]> 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, <[email protected]>:
>
>> From: Shimi Gersner <[email protected]>
>>
>> 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