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 > > >