Bug 1510641
| Summary: | rh-nodejs4 encounters a SEGFAULT in SSL_CTX_use_certificate_chain [rhscl-3.1.0] | |||
|---|---|---|---|---|
| Product: | Red Hat Software Collections | Reporter: | Kyle Walker <kwalker> | |
| Component: | nodejs | Assignee: | Zuzana Svetlikova <zsvetlik> | |
| Status: | CLOSED ERRATA | QA Contact: | Mirek Długosz <mzalewsk> | |
| Severity: | high | Docs Contact: | ||
| Priority: | urgent | |||
| Version: | rh-nodejs4 | CC: | glamb, jorton, mzalewsk, zsvetlik | |
| Target Milestone: | alpha | Flags: | zsvetlik:
needinfo+
|
|
| Target Release: | 3.1 | |||
| Hardware: | Unspecified | |||
| OS: | Unspecified | |||
| Whiteboard: | ||||
| Fixed In Version: | Doc Type: | Bug Fix | ||
| Doc Text: |
Prior to this update, the Node.js server was unable to correctly handle certificate chains. As a consequence, the Node.js server terminated unexpectedly with a segmentation fault. This bug has been fixed, and users are now able to authenticate using certificate chains.
|
Story Points: | --- | |
| Clone Of: | ||||
| : | 1513065 1513067 1589027 (view as bug list) | Environment: | ||
| Last Closed: | 2017-11-20 14:04:45 UTC | Type: | Bug | |
| Regression: | --- | Mount Type: | --- | |
| Documentation: | --- | CRM: | ||
| Verified Versions: | Category: | --- | ||
| oVirt Team: | --- | RHEL 7.3 requirements from Atomic Host: | ||
| Cloudforms Team: | --- | Target Upstream Version: | ||
| Embargoed: | ||||
| Bug Depends On: | ||||
| Bug Blocks: | 1513065 | |||
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 |
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.