Description of problem: When handling a certificate chain, such as multiple certificates in a single PEM encoded file, the following backtrace is observed: (gdb) bt #0 0x00007f825e5823f0 in asn1_enc_restore (<snip>) at tasn_utl.c:189 #1 0x00007f825e57f5d3 in ASN1_item_ex_i2d (<snip>) at tasn_enc.c:198 #2 0x00007f825e57fc79 in asn1_template_ex_i2d (<snip>) at tasn_enc.c:402 #3 0x00007f825e57f737 in ASN1_item_ex_i2d (<snip>) at tasn_enc.c:225 #4 0x00007f825e57f93f in asn1_item_flags_i2d (<snip>) at tasn_enc.c:119 #5 0x00007f825e57f9e7 in ASN1_item_i2d (<snip>) at tasn_enc.c:91 #6 0x00007f825e57abfc in i2d_X509 (<snip>) at x_x509.c:143 #7 0x00007f825e8db9dd in ssl_add_cert_to_buf (<snip>) at ssl_cert.c:1059 #8 0x00007f825e8dd388 in ssl_add_cert_chain (<snip>) at ssl_cert.c:1143 #9 0x00007f825e8c2135 in ssl3_output_cert_chain (<snip>) at s3_both.c:327 #10 0x00007f825e8ba944 in ssl3_send_client_certificate (<snip>) at s3_clnt.c:3488 #11 0x00007f825e8baf7f in ssl3_connect (<snip>) at s3_clnt.c:421 #12 0x00007f825e8c023e in ssl3_write_bytes (<snip>) at s3_pkt.c:655 #13 0x0000000000b9ac38 in node::TLSWrap::ClearIn (<snip>) at ../src/tls_wrap.cc:485 #14 0x0000000000b9b7eb in Cycle (<snip>) at ../src/tls_wrap.h:100 #15 node::TLSWrap::DoRead (<snip>) at ../src/tls_wrap.cc:728 #16 0x0000000000b73985 in OnRead (<snip>) at ../src/stream_base.h:169 #17 node::StreamWrap::OnReadCommon (<snip>) at ../src/stream_wrap.cc:251 #18 0x00007f825f359954 in uv__read (<snip>) at ../src/unix/stream.c:1178 #19 0x00007f825f359e8c in uv__stream_io (<snip>) at ../src/unix/stream.c:1241 #20 0x00007f825f35e436 in uv__io_poll (<snip>) at ../src/unix/linux-core.c:345 #21 0x00007f825f3520f0 in uv_run (<snip>) at ../src/unix/core.c:341 #22 0x0000000000b3ccf0 in node::Start (<snip>) at ../src/node.cc:4230 #23 0x00007f825d872c05 in __libc_start_main (<snip>) at ../csu/libc-start.c:274 #24 0x0000000000655e59 in _start (<snip>) Version-Release number of selected component (if applicable): rh-nodejs4-nodejs-4.6.2-6.el7 rh-nodejs6-nodejs-6.11.3-2.el7 openssl-1.0.2k-8.el7.x86_64 How reproducible: Simply Steps to Reproduce: 1. Generate a client certificate, validity not necessary as the problem is observed in valid use-cases and invalid. # # openssl req -x509 -nodes -out client.crt -newkey rsa:4096 -keyout test.key -subj "/CN=Test" 2. Duplicate the client certificate # cat client.crt client.crt > test.crt 3. Start a nodejs4 https server in the following fashion: # cat server.js var fs = require('fs'); var constants = require('constants'); var https = require('https'); var httpsPort = 8443; var sslOptions = { key: fs.readFileSync('./client.key'), cert: fs.readFileSync('./test.crt'), secureProtocol: 'SSLv23_method', secureOptions: constants.SSL_OP_NO_SSLv3 | constants.SSL_OP_NO_SSLv2, }; https.createServer(sslOptions).listen(httpsPort); console.log("Listening: "+httpsPort); # scl enable rh-nodejs4 -- node server.js 4. Connect to the above via s_client # echo "" | openssl s_client -connect localhost:8443 Actual results: # scl enable rh-nodejs4 -- node server.js Listening: 8443 /var/tmp/sclIfAGVI: line 8: 773 Segmentation fault (core dumped) "node" "server.js" Expected results: # scl enable rh-nodejs4 -- node server.js Listening: 8443 <No SEGFAULT> Additional info: This seems to be due to the presence of the *-Disable-openssl.patch and lack of BuildRequires/Requires dependencies within the rh-nodejs4 and rh-nodejs6 RPMs. The rh-nodejs8 package does not include this patch and does not suffer from the same failure.
Just to elaborate, the end failure is specifically in the following code snippet when a connection is accepted. ssl_add_cert_chain() <snip> 1141 for (i = 0; i < sk_X509_num(extra_certs); i++) { 1142 x = sk_X509_value(extra_certs, i); 1143 if (!ssl_add_cert_to_buf(buf, l, x)) 1144 return 0; 1145 } <snip> (gdb) f #11 0x00007ffff6d329dd in ssl_add_cert_to_buf (buf=buf@entry=0x11e4610, l=l@entry=0x7fffffff7200, x=0x12431f0) at ssl_cert.c:1059 1059 n = i2d_X509(x, NULL); (gdb) p *x $11 = { cert_info = 0x7ffff6f5a710 <ssl3_ciphers+10384>, sig_alg = 0x7ffff6f5a5b0 <ssl3_ciphers+10032>, signature = 0x7ffff6f5a768 <ssl3_ciphers+10472>, valid = -151673336, references = 32767, name = 0x7ffff6f596e8 <ssl3_ciphers+6248> "\001", ex_data = { sk = 0x7ffff6f5a450 <ssl3_ciphers+9680>, dummy = -151679760 }, ex_pathlen = 140737336681640, ex_pcpathlen = 140737336675920, ex_flags = 140737336681288, ex_kusage = 140737336680672, ex_xkusage = 140737336679792, ex_nscert = 140737336678736, skid = 0x7ffff6f598a0 <ssl3_ciphers+6688>, akid = 0x7ffff6f597f0 <ssl3_ciphers+6512>, policy_cache = 0x7ffff6f59740 <ssl3_ciphers+6336>, crldp = 0x7ffff6f58df8 <ssl3_ciphers+3960>, altname = 0x7ffff6f58da0 <ssl3_ciphers+3872>, nc = 0x7ffff6f58d48 <ssl3_ciphers+3784>, rfc3779_addr = 0x7ffff6f58820 <ssl3_ciphers+2464>, rfc3779_asid = 0x7ffff6f587c8 <ssl3_ciphers+2376>, sha1_hash = "p\207\365\366\377\177\000\000\030\207\365\366\377\177\000\000\030\250\365\366", aux = 0x7ffff6f5a6b8 <ssl3_ciphers+10296> } The upstream node revision does not suffer from the same issue as the openssl libraries are statically linked in and presumed to be a specific version/API. Therefore, they do not need to override the SSL_CTX_use_certificate_chain() behaviour as the indicated *-Disable-openssl.patch does below: @@ -521,9 +621,20 @@ int SSL_CTX_use_certificate_chain(SSL_CTX* ctx, for (int i = 0; i < sk_X509_num(extra_certs); i++) { X509* ca = sk_X509_value(extra_certs, i); - // NOTE: Increments reference count on `ca` - r = SSL_CTX_add1_chain_cert(ctx, ca); - +#if OPENSSL_VERSION_NUMBER >= 0x10002000L + // If ctx->cert->key != NULL create ctx->cert->key->chain if not + // already there, push 'ca' to this chain and finally increment the ca + // reference count by 1 (this is the diff between *_add1_* and *_add0_* + // - the later increments by 0 ;-)) and return 1. Otherwise or if + // something fails in between, return 0. + r = SSL_CTX_add1_chain_cert(ctx, ca); +#else + // Create ctx->extra_certs if not already there, just push 'ca' to this + // chain and return 1. If something fails, return 0. + // NOTE: 1.0.1- does not support multiple certs having its own chain in + // a single context. There is just one: extra_chain! + r = SSL_CTX_add_extra_chain_cert(ctx, ca); +#endif if (!r) { ret = 0; *issuer = nullptr; Kyle Walker Senior Software Maintenance Engineer - SEG North America
Since the problem described in this bug report should be resolved in a recent advisory, it has been closed with a resolution of ERRATA. For information on the advisory, and where to find the updated files, follow the link below. If the solution does not work for you, open a new bug report. https://access.redhat.com/errata/RHBA-2017:3249