diff --git a/.gitignore b/.gitignore index cdcc8b5..176bd6c 100644 --- a/.gitignore +++ b/.gitignore @@ -34,3 +34,24 @@ /node-v0.10.36-stripped.tar.gz /node-v0.10.42-stripped.tar.gz /node-v0.10.46-stripped.tar.gz +/node-v4.2.2-stripped.tar.gz +/node-v4.2.3-stripped.tar.gz +/node-v4.2.4-stripped.tar.gz +/node-v4.2.6-stripped.tar.gz +/node-v4.3.0-stripped.tar.gz +/node-v4.3.1-stripped.tar.gz +/node-v5.7.1-stripped.tar.gz +/node-v5.8.0-stripped.tar.gz +/node-v5.9.0.tar.gz +/node-v5.9.1-stripped.tar.gz +/node-v5.10.0-stripped.tar.gz +/node-v5.10.1-stripped.tar.gz +/node-v5.11.0-stripped.tar.gz +/node-v6.1.0-stripped.tar.gz +/node-v6.2.0-stripped.tar.gz +/node-v6.2.1-stripped.tar.gz +/node-v6.2.2-stripped.tar.gz +/node-v6.3.0-stripped.tar.gz +/node-v6.3.1-stripped.tar.gz +/node-v6.4.0-stripped.tar.gz +/node-v6.5.0-stripped.tar.gz diff --git a/0001-disable-running-gyp-files-for-bundled-deps.patch b/0001-disable-running-gyp-files-for-bundled-deps.patch new file mode 100644 index 0000000..4e46de4 --- /dev/null +++ b/0001-disable-running-gyp-files-for-bundled-deps.patch @@ -0,0 +1,25 @@ +From da4ed485ddd52cd156406f939225146e8539cabb Mon Sep 17 00:00:00 2001 +From: Stephen Gallagher +Date: Tue, 1 Dec 2015 16:35:29 -0500 +Subject: [PATCH 1/3] disable running gyp files for bundled deps + +--- + Makefile | 2 +- + 1 file changed, 1 insertion(+), 1 deletion(-) + +diff --git a/Makefile b/Makefile +index a8870a5..f7fc4a9 100644 +--- a/Makefile ++++ b/Makefile +@@ -70,7 +70,7 @@ $(NODE_G_EXE): config.gypi out/Makefile + $(MAKE) -C out BUILDTYPE=Debug V=$(V) + ln -fs out/Debug/$(NODE_EXE) $@ + +-out/Makefile: common.gypi deps/uv/uv.gyp deps/http_parser/http_parser.gyp deps/zlib/zlib.gyp deps/v8/build/toolchain.gypi deps/v8/build/features.gypi deps/v8/tools/gyp/v8.gyp node.gyp config.gypi ++out/Makefile: common.gypi deps/v8/build/toolchain.gypi deps/v8/build/features.gypi deps/v8/tools/gyp/v8.gyp node.gyp config.gypi + $(PYTHON) tools/gyp_node.py -f make + + config.gypi: configure +-- +2.9.0 + diff --git a/0002-Use-openssl-1.0.1.patch b/0002-Use-openssl-1.0.1.patch new file mode 100644 index 0000000..700e8fc --- /dev/null +++ b/0002-Use-openssl-1.0.1.patch @@ -0,0 +1,524 @@ +From 6cf8243a70e26843c7770f7b29b1a33b822d1c26 Mon Sep 17 00:00:00 2001 +From: Haikel Guemar +Date: Tue, 26 Jul 2016 22:50:22 +0200 +Subject: [PATCH 2/3] Use openssl 1.0.1 + +Based on Solaris patches from upstream #2783 +https://github.com/nodejs/node/issues/2783 +--- + doc/api/tls.md | 6 ++ + src/node_constants.cc | 5 ++ + src/node_crypto.cc | 201 ++++++++++++++++++++++++++++++++++++++++++++++---- + src/node_crypto.h | 16 ++++ + src/tls_wrap.cc | 8 ++ + 5 files changed, 223 insertions(+), 13 deletions(-) + +diff --git a/doc/api/tls.md b/doc/api/tls.md +index 7feaff2..97ad7a5 100644 +--- a/doc/api/tls.md ++++ b/doc/api/tls.md +@@ -114,6 +114,12 @@ handshake extensions: + * SNI - Allows the use of one TLS server for multiple hostnames with different + SSL certificates. + ++ **NOTE**: dueto a design flaw in node **SNI cannot be ++ used on the server side**, even so all parameters in related functions are ++ accepted for compatibility reasons. And thus the related events will not ++ fire unless one aranges this explicitly. This may change, when the OS ++ provides OpenSSL v1.0.2 or better and node gets linked to this version. ++ + *Note*: Use of ALPN is recommended over NPN. The NPN extension has never been + formally defined or documented and generally not recommended for use. + +diff --git a/src/node_constants.cc b/src/node_constants.cc +index 2e6be8d..239eadb 100644 +--- a/src/node_constants.cc ++++ b/src/node_constants.cc +@@ -14,7 +14,10 @@ + #include + + #if HAVE_OPENSSL ++# include ++# ifndef OPENSSL_NO_EC + # include ++# endif + # include + # ifndef OPENSSL_NO_ENGINE + # include +@@ -976,12 +979,14 @@ void DefineOpenSSLConstants(Local target) { + + #if HAVE_OPENSSL + // NOTE: These are not defines ++# ifndef OPENSSL_NO_EC + NODE_DEFINE_CONSTANT(target, POINT_CONVERSION_COMPRESSED); + + NODE_DEFINE_CONSTANT(target, POINT_CONVERSION_UNCOMPRESSED); + + NODE_DEFINE_CONSTANT(target, POINT_CONVERSION_HYBRID); + #endif ++#endif + } + + void DefineSystemConstants(Local target) { +diff --git a/src/node_crypto.cc b/src/node_crypto.cc +index 9cf216f..888a0f8 100644 +--- a/src/node_crypto.cc ++++ b/src/node_crypto.cc +@@ -24,6 +24,82 @@ + #include + #include + ++#ifndef SSL_get_server_tmp_key ++/* ++ 1.0.2 SSL_get_server_tmp_key(s, pk) "backport". BAD HACK!!! ++ NOTE: This imports "foreign" knowledge and thus will break, when SESS_CERT ++ or CERT_PKEY change, which is definitely the case for the later for ++ all OpenSSL lib vers != 1.0.1. So don't try to bind to something else! ++ */ ++# define SSL_PKEY_NUM 8 ++typedef struct cert_pkey_st { ++ X509 *x509; ++ EVP_PKEY *privatekey; ++ /* Digest to use when signing */ ++ const EVP_MD *digest; ++} CERT_PKEY; ++ ++typedef struct sess_cert_st { ++ STACK_OF(X509) *cert_chain; /* as received from peer (not for SSL2) */ ++ /* The 'peer_...' members are used only by clients. */ ++ int peer_cert_type; ++ CERT_PKEY *peer_key; /* points to an element of peer_pkeys (never ++ * NULL!) */ ++ CERT_PKEY peer_pkeys[SSL_PKEY_NUM]; ++ /* ++ * Obviously we don't have the private keys of these, so maybe we ++ * shouldn't even use the CERT_PKEY type here. ++ */ ++# ifndef OPENSSL_NO_RSA ++ RSA *peer_rsa_tmp; /* not used for SSL 2 */ ++# endif ++# ifndef OPENSSL_NO_DH ++ DH *peer_dh_tmp; /* not used for SSL 2 */ ++# endif ++# ifndef OPENSSL_NO_ECDH ++ EC_KEY *peer_ecdh_tmp; ++# endif ++ int references; /* actually always 1 at the moment */ ++} SESS_CERT; ++ ++static long SSL_get_server_tmp_key(SSL *s, void *parg) { ++ if (s->server || !s->session || !s->session->sess_cert) ++ return 0; ++ else { ++ SESS_CERT *sc; ++ EVP_PKEY *ptmp; ++ int rv = 0; ++ sc = s->session->sess_cert; ++#if !defined(OPENSSL_NO_RSA) && !defined(OPENSSL_NO_DH) && !defined(OPENSSL_NO_EC) && !defined(OPENSSL_NO_ECDH) ++ if (!sc->peer_rsa_tmp && !sc->peer_dh_tmp && !sc->peer_ecdh_tmp) ++ return 0; ++#endif ++ ptmp = EVP_PKEY_new(); ++ if (!ptmp) ++ return 0; ++ if (0) ; ++#ifndef OPENSSL_NO_RSA ++ else if (sc->peer_rsa_tmp) ++ rv = EVP_PKEY_set1_RSA(ptmp, sc->peer_rsa_tmp); ++#endif ++#ifndef OPENSSL_NO_DH ++ else if (sc->peer_dh_tmp) ++ rv = EVP_PKEY_set1_DH(ptmp, sc->peer_dh_tmp); ++#endif ++#ifndef OPENSSL_NO_ECDH ++ else if (sc->peer_ecdh_tmp) ++ rv = EVP_PKEY_set1_EC_KEY(ptmp, sc->peer_ecdh_tmp); ++#endif ++ if (rv) { ++ *(EVP_PKEY **)parg = ptmp; ++ return 1; ++ } ++ EVP_PKEY_free(ptmp); ++ return 0; ++ } ++} ++#endif /* SSL_get_server_tmp_key */ ++ + #define THROW_AND_RETURN_IF_NOT_STRING_OR_BUFFER(val, prefix) \ + do { \ + if (!Buffer::HasInstance(val) && !val->IsString()) { \ +@@ -160,7 +236,11 @@ template int SSLWrap::TLSExtStatusCallback(SSL* s, void* arg); + #endif + + template void SSLWrap::DestroySSL(); ++#if OPENSSL_VERSION_NUMBER >= 0x10002000L + template int SSLWrap::SSLCertCallback(SSL* s, void* arg); ++#else ++template int SSLWrap::SSLCertCallback(SSL* s, X509 **x509, EVP_PKEY **pkey); ++#endif + template void SSLWrap::WaitForCertCb(CertCb cb, void* arg); + + #ifdef TLSEXT_TYPE_application_layer_protocol_negotiation +@@ -280,8 +360,12 @@ void SecureContext::Initialize(Environment* env, Local target) { + env->SetProtoMethod(t, "addCRL", SecureContext::AddCRL); + env->SetProtoMethod(t, "addRootCerts", SecureContext::AddRootCerts); + env->SetProtoMethod(t, "setCiphers", SecureContext::SetCiphers); ++#ifndef OPENSSL_NO_ECDH + env->SetProtoMethod(t, "setECDHCurve", SecureContext::SetECDHCurve); ++#endif ++#ifndef OPENSSL_NO_DH + env->SetProtoMethod(t, "setDHParam", SecureContext::SetDHParam); ++#endif + env->SetProtoMethod(t, "setOptions", SecureContext::SetOptions); + env->SetProtoMethod(t, "setSessionIdContext", + SecureContext::SetSessionIdContext); +@@ -515,8 +599,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; +@@ -795,6 +891,7 @@ void SecureContext::SetCiphers(const FunctionCallbackInfo& args) { + } + + ++#ifndef OPENSSL_NO_ECDH + void SecureContext::SetECDHCurve(const FunctionCallbackInfo& args) { + SecureContext* sc; + ASSIGN_OR_RETURN_UNWRAP(&sc, args.Holder()); +@@ -822,8 +919,10 @@ void SecureContext::SetECDHCurve(const FunctionCallbackInfo& args) { + + EC_KEY_free(ecdh); + } ++#endif + + ++#ifndef OPENSSL_NO_DH + void SecureContext::SetDHParam(const FunctionCallbackInfo& args) { + SecureContext* sc; + ASSIGN_OR_RETURN_UNWRAP(&sc, args.This()); +@@ -862,6 +961,7 @@ void SecureContext::SetDHParam(const FunctionCallbackInfo& args) { + if (!r) + return env->ThrowTypeError("Error setting temp DH parameter"); + } ++#endif + + + void SecureContext::SetOptions(const FunctionCallbackInfo& args) { +@@ -1872,6 +1972,7 @@ void SSLWrap::GetEphemeralKeyInfo( + info->Set(env->size_string(), + Integer::New(env->isolate(), EVP_PKEY_bits(key))); + break; ++#ifndef OPENSSL_NO_ECDH + case EVP_PKEY_EC: + { + EC_KEY* ec = EVP_PKEY_get1_EC_KEY(key); +@@ -1884,6 +1985,7 @@ void SSLWrap::GetEphemeralKeyInfo( + info->Set(env->size_string(), + Integer::New(env->isolate(), EVP_PKEY_bits(key))); + } ++#endif + } + EVP_PKEY_free(key); + } +@@ -2301,7 +2403,12 @@ void SSLWrap::WaitForCertCb(CertCb cb, void* arg) { + + + template ++#if OPENSSL_VERSION_NUMBER >= 0x10002000L + int SSLWrap::SSLCertCallback(SSL* s, void* arg) { ++#else ++/* NOTE: For now this callback gets usually never called dueto design flaws */ ++int SSLWrap::SSLCertCallback(SSL* s, X509 **x509, EVP_PKEY **pkey) { ++#endif + Base* w = static_cast(SSL_get_app_data(s)); + + if (!w->is_server()) +@@ -2375,19 +2482,53 @@ void SSLWrap::CertCbDone(const FunctionCallbackInfo& args) { + w->sni_context_.Reset(env->isolate(), ctx); + + int rv; ++ X509* x509; ++ EVP_PKEY* pkey; ++ STACK_OF(X509)* chain; + + // NOTE: reference count is not increased by this API methods +- X509* x509 = SSL_CTX_get0_certificate(sc->ctx_); +- EVP_PKEY* pkey = SSL_CTX_get0_privatekey(sc->ctx_); +- STACK_OF(X509)* chain; ++#if OPENSSL_VERSION_NUMBER >= 0x10002000L ++ x509 = SSL_CTX_get0_certificate(sc->ctx_); ++ pkey = SSL_CTX_get0_privatekey(sc->ctx_); ++ rv = SSL_CTX_get0_chain_certs(sc->ctx_, &chain); ++#else ++ SSL *ssl = SSL_new(sc->ctx_); ++ rv = SSL_CTX_get_extra_chain_certs(sc->ctx_, &chain); ++ if (ssl) { ++ SSL_set_connect_state(ssl); /* just cleanup/reset state - cheap */ ++ x509 = SSL_get_certificate(ssl); ++ SSL_free(ssl); ++ } else { ++ x509 = NULL; ++ pkey = NULL; ++ } ++#endif + +- rv = SSL_CTX_get0_chain_certs(sc->ctx_, &chain); +- if (rv) +- rv = SSL_use_certificate(w->ssl_, x509); +- if (rv) +- rv = SSL_use_PrivateKey(w->ssl_, pkey); +- if (rv && chain != nullptr) +- rv = SSL_set1_chain(w->ssl_, chain); ++ if (rv) ++ rv = SSL_use_certificate(w->ssl_, x509); ++ if (rv) ++ rv = SSL_use_PrivateKey(w->ssl_, pkey); ++ if (rv && chain != nullptr) { ++#if OPENSSL_VERSION_NUMBER >= 0x10002000L ++ // replaces w->ssl_->cert->key->chain with a copy of the given chain, ++ // which is allowed to be NULL ++ rv = SSL_set1_chain(w->ssl_, chain); ++#else ++ // just replace the extra chain with the given chain - 1.0.1- does not ++ // support chain per cert ++ SSL_CTX_clear_extra_chain_certs(w->ssl_->ctx); ++ if (chain != NULL) { ++ int i; ++ SSL_CTX* ctx = w->ssl_->ctx; ++ for (i = 0; i < sk_X509_num(chain); i++) { ++ // can't do anything: however others might be ok and still ++ // satisfy requirements ++ SSL_CTX_add_extra_chain_cert(ctx, sk_X509_value(chain,i)); ++ } ++ } ++ rv = 1; ++#endif ++ } + if (rv) + rv = w->SetCACerts(sc); + if (!rv) { +@@ -2451,10 +2592,14 @@ void SSLWrap::SetSNIContext(SecureContext* sc) { + + template + int SSLWrap::SetCACerts(SecureContext* sc) { ++#if OPENSSL_VERSION_NUMBER >= 0x10002000L + int err = SSL_set1_verify_cert_store(ssl_, SSL_CTX_get_cert_store(sc->ctx_)); + if (err != 1) + return err; +- ++#else ++ // there is no ssl_->cert->verify_store in <= 1.0.1. So no need to: free the ++ // old store, set the new one to it and increment its ref count. ++#endif + STACK_OF(X509_NAME)* list = SSL_dup_CA_list( + SSL_CTX_get_client_CA_list(sc->ctx_)); + +@@ -2732,7 +2877,11 @@ inline int VerifyCallback(int preverify_ok, X509_STORE_CTX* ctx) { + SSL* ssl = static_cast( + X509_STORE_CTX_get_ex_data(ctx, SSL_get_ex_data_X509_STORE_CTX_idx())); + ++#if OPENSSL_VERSION_NUMBER >= 0x10002000L + if (SSL_is_server(ssl)) ++#else ++ if (ssl->server) ++#endif + return 1; + + // Client needs to check if the server cert is listed in the +@@ -2815,7 +2964,21 @@ void Connection::New(const FunctionCallbackInfo& args) { + + InitNPN(sc); + ++#if OPENSSL_VERSION_NUMBER >= 0x10002000L + SSL_set_cert_cb(conn->ssl_, SSLWrap::SSLCertCallback, conn); ++#else ++ /* 1.0.1 and less have no general cert callback. The closest for a client is ++ SSL_CTX_set_client_cert_cb(conn->ssl_->ctx, SSLWrap::SSLCertCallback); ++ but on the client it is not needed/used by this implementation. Since this ++ the SSLCertCallback actually calls lib/_tls_wrap.js:oncertcb(), which in ++ turn loadSNI() and this the actual SNICallback of the JSON object, sets ++ the context and finally requestOCSP() and certCbDone(). Not sure, why ++ the SNICallback of the JSON object, doesn't get invoked via ++ SelectSNIContextCallback_() - design flaw because lets do 2 things at once ++ (i.e. do SNICallback and attach the certs ca chain), however, this means ++ no server side support for the SNI TLS/OCSP_state extension anymore. ++ */ ++#endif + + #ifdef SSL_CTRL_SET_TLSEXT_SERVERNAME_CB + if (is_server) { +@@ -4404,6 +4567,7 @@ void PublicKeyCipher::Cipher(const FunctionCallbackInfo& args) { + } + + ++#ifndef OPENSSL_NO_DH + void DiffieHellman::Initialize(Environment* env, Local target) { + Local t = env->NewFunctionTemplate(New); + +@@ -4805,8 +4969,10 @@ bool DiffieHellman::VerifyContext() { + verifyError_ = codes; + return true; + } ++#endif + + ++#ifndef OPENSSL_NO_ECDH + void ECDH::Initialize(Environment* env, Local target) { + HandleScope scope(env->isolate()); + +@@ -5034,6 +5200,7 @@ void ECDH::SetPrivateKey(const FunctionCallbackInfo& args) { + + EC_POINT_free(pub); + } ++#endif + + + void ECDH::SetPublicKey(const FunctionCallbackInfo& args) { +@@ -5587,6 +5754,7 @@ void GetHashes(const FunctionCallbackInfo& args) { + } + + ++# ifndef OPENSSL_NO_EC + void GetCurves(const FunctionCallbackInfo& args) { + Environment* env = Environment::GetCurrent(args); + const size_t num_curves = EC_get_builtin_curves(nullptr, 0); +@@ -5611,6 +5779,7 @@ void GetCurves(const FunctionCallbackInfo& args) { + + args.GetReturnValue().Set(arr); + } ++#endif + + + bool VerifySpkac(const char* data, unsigned int len) { +@@ -5886,8 +6055,12 @@ void InitCrypto(Local target, + SecureContext::Initialize(env, target); + Connection::Initialize(env, target); + CipherBase::Initialize(env, target); ++# ifndef OPENSSL_NO_EC + DiffieHellman::Initialize(env, target); ++#endif ++#ifndef OPENSSL_NO_ECDH + ECDH::Initialize(env, target); ++#endif + Hmac::Initialize(env, target); + Hash::Initialize(env, target); + Sign::Initialize(env, target); +@@ -5906,7 +6079,9 @@ void InitCrypto(Local target, + env->SetMethod(target, "getSSLCiphers", GetSSLCiphers); + env->SetMethod(target, "getCiphers", GetCiphers); + env->SetMethod(target, "getHashes", GetHashes); ++# ifndef OPENSSL_NO_EC + env->SetMethod(target, "getCurves", GetCurves); ++#endif + env->SetMethod(target, "publicEncrypt", + PublicKeyCipher::Cipher ++# ifndef OPENSSL_NO_EC + #include ++# endif ++# ifndef OPENSSL_NO_ECDH + #include ++# endif + #ifndef OPENSSL_NO_ENGINE + # include + #endif // !OPENSSL_NO_ENGINE +@@ -101,8 +105,12 @@ class SecureContext : public BaseObject { + static void AddCRL(const v8::FunctionCallbackInfo& args); + static void AddRootCerts(const v8::FunctionCallbackInfo& args); + static void SetCiphers(const v8::FunctionCallbackInfo& args); ++#ifndef OPENSSL_NO_ECDH + static void SetECDHCurve(const v8::FunctionCallbackInfo& args); ++#endif ++# ifndef OPENSSL_NO_DH + static void SetDHParam(const v8::FunctionCallbackInfo& args); ++#endif + static void SetOptions(const v8::FunctionCallbackInfo& args); + static void SetSessionIdContext( + const v8::FunctionCallbackInfo& args); +@@ -283,7 +291,11 @@ class SSLWrap { + unsigned int inlen, + void* arg); + static int TLSExtStatusCallback(SSL* s, void* arg); ++#if OPENSSL_VERSION_NUMBER >= 0x10002000L + static int SSLCertCallback(SSL* s, void* arg); ++#else ++ static int SSLCertCallback(SSL* s, X509 **x509, EVP_PKEY **pkey); ++#endif + static void SSLGetter(v8::Local property, + const v8::PropertyCallbackInfo& info); + +@@ -645,6 +657,7 @@ class PublicKeyCipher { + static void Cipher(const v8::FunctionCallbackInfo& args); + }; + ++#ifndef OPENSSL_NO_DH + class DiffieHellman : public BaseObject { + public: + ~DiffieHellman() override { +@@ -690,7 +703,9 @@ class DiffieHellman : public BaseObject { + int verifyError_; + DH* dh; + }; ++#endif + ++# ifndef OPENSSL_NO_ECDH + class ECDH : public BaseObject { + public: + ~ECDH() override { +@@ -727,6 +742,7 @@ class ECDH : public BaseObject { + EC_KEY* key_; + const EC_GROUP* group_; + }; ++#endif + + bool EntropySource(unsigned char* buffer, size_t length); + #ifndef OPENSSL_NO_ENGINE +diff --git a/src/tls_wrap.cc b/src/tls_wrap.cc +index 7c5df11..3e06621 100644 +--- a/src/tls_wrap.cc ++++ b/src/tls_wrap.cc +@@ -142,7 +142,15 @@ void TLSWrap::InitSSL() { + + InitNPN(sc_); + ++#if OPENSSL_VERSION_NUMBER >= 0x10002000L + SSL_set_cert_cb(ssl_, SSLWrap::SSLCertCallback, this); ++#else ++ /* 1.0.1 and less have at most for the client side the function ++ SSL_CTX_set_client_cert_cb(ssl_->ctx, SSLWrap::SSLCertCallback); ++ but on the client it is not needed/used by this implementation. ++ For more info see comments in src/node_crypto.cc Connection::New(). ++ */ ++#endif + + if (is_server()) { + SSL_set_accept_state(ssl_); +-- +2.9.0 + diff --git a/0003-CA-Certificates-are-provided-by-Fedora.patch b/0003-CA-Certificates-are-provided-by-Fedora.patch new file mode 100644 index 0000000..1c82a0f --- /dev/null +++ b/0003-CA-Certificates-are-provided-by-Fedora.patch @@ -0,0 +1,82 @@ +From 08305ba6b7fddab1f35c59dc82a3c6b11ceceae3 Mon Sep 17 00:00:00 2001 +From: Haikel Guemar +Date: Tue, 26 Jul 2016 22:00:25 +0200 +Subject: [PATCH 3/3] CA Certificates are provided by Fedora. +MIME-Version: 1.0 +Content-Type: text/plain; charset=UTF-8 +Content-Transfer-Encoding: 8bit + +Forwarded: need some feedback before submitting the matter upstream +Author: Jérémy Lal +Last-Update: 2014-03-02 + +Modified 2014-05-02 by T.C. Hollingsworth with the +correct path for Fedora + +Modified 2015-12-01 by Stephen Gallagher to update for +Node.js 4.2 + +Modified 2016-03-04 by Stephen Gallagher to update for +Node.js 5.4.1 + +Modified 2016-07-26 by Haikel Guemar to update for +Node.js 4.4.7 +--- + src/node_crypto.cc | 30 +++++++++--------------------- + 1 file changed, 9 insertions(+), 21 deletions(-) + +diff --git a/src/node_crypto.cc b/src/node_crypto.cc +index 888a0f8..3feff0e 100644 +--- a/src/node_crypto.cc ++++ b/src/node_crypto.cc +@@ -192,8 +192,8 @@ static X509_NAME *cnnic_ev_name = + + static Mutex* mutexes; + +-const char* const root_certs[] = { +-#include "node_root_certs.h" // NOLINT(build/include_order) ++const char* root_certs[] = { ++ NULL + }; + + X509_STORE* root_cert_store; +@@ -847,29 +847,17 @@ void SecureContext::AddRootCerts(const FunctionCallbackInfo& args) { + CHECK_EQ(sc->ca_store_, nullptr); + + if (!root_cert_store) { +- root_cert_store = X509_STORE_new(); +- +- for (size_t i = 0; i < arraysize(root_certs); i++) { +- BIO* bp = NodeBIO::NewFixed(root_certs[i], strlen(root_certs[i])); +- if (bp == nullptr) { +- return; +- } +- +- X509 *x509 = PEM_read_bio_X509(bp, nullptr, CryptoPemCallback, nullptr); +- if (x509 == nullptr) { +- BIO_free_all(bp); +- return; +- } +- +- X509_STORE_add_cert(root_cert_store, x509); +- +- BIO_free_all(bp); +- X509_free(x509); ++ if (SSL_CTX_load_verify_locations(sc->ctx_, "/etc/pki/tls/certs/ca-bundle.crt", NULL) == 1) { ++ root_cert_store = SSL_CTX_get_cert_store(sc->ctx_); ++ } else { ++ // empty store ++ root_cert_store = X509_STORE_new(); + } ++ } else { ++ SSL_CTX_set_cert_store(sc->ctx_, root_cert_store); + } + + sc->ca_store_ = root_cert_store; +- SSL_CTX_set_cert_store(sc->ctx_, sc->ca_store_); + } + + +-- +2.9.0 + diff --git a/nodejs-disable-gyp-deps.patch b/nodejs-disable-gyp-deps.patch deleted file mode 100644 index ae48d24..0000000 --- a/nodejs-disable-gyp-deps.patch +++ /dev/null @@ -1,26 +0,0 @@ -From 4464455834276c845a63fede515cb62655afb2da Mon Sep 17 00:00:00 2001 -From: "T.C. Hollingsworth" -Date: Tue, 12 Nov 2013 14:51:03 -0700 -Subject: [PATCH] disable running gyp files for bundled deps - -these aren't used in Fedora ---- - Makefile | 2 +- - 1 file changed, 1 insertion(+), 1 deletion(-) - -diff --git a/Makefile b/Makefile -index 8177017..81d150f 100644 ---- a/Makefile -+++ b/Makefile -@@ -43,7 +43,7 @@ node_g: config.gypi out/Makefile - ln -fs out/Debug/node $@ - endif - --out/Makefile: common.gypi deps/uv/uv.gyp deps/http_parser/http_parser.gyp deps/zlib/zlib.gyp deps/v8/build/common.gypi deps/v8/tools/gyp/v8.gyp node.gyp config.gypi -+out/Makefile: common.gypi node.gyp config.gypi - ifeq ($(USE_NINJA),1) - touch out/Makefile - $(PYTHON) tools/gyp_node.py -f ninja --- -1.8.4.2 - diff --git a/nodejs-use-system-certs.patch b/nodejs-use-system-certs.patch deleted file mode 100644 index fe2abab..0000000 --- a/nodejs-use-system-certs.patch +++ /dev/null @@ -1,58 +0,0 @@ -Description: do not bundle CA certificates, openssl on Debian have them - As a consequence, nodejs must depend on ca-certificates. -Forwarded: need some feedback before submitting the matter upstream -Author: Jérémy Lal -Last-Update: 2014-03-02 - -Modified 2014-05-02 by T.C. Hollingsworth with the -correct path for Fedora ---- a/src/node_crypto.cc -+++ b/src/node_crypto.cc -@@ -64,7 +64,6 @@ - namespace node { - - const char* root_certs[] = { --#include "node_root_certs.h" // NOLINT(build/include_order) - NULL - }; - -@@ -561,32 +560,16 @@ - assert(sc->ca_store_ == NULL); - - if (!root_cert_store) { -- root_cert_store = X509_STORE_new(); -- -- for (int i = 0; root_certs[i]; i++) { -- BIO *bp = BIO_new(BIO_s_mem()); -- -- if (!BIO_write(bp, root_certs[i], strlen(root_certs[i]))) { -- BIO_free(bp); -- return False(); -- } -- -- X509 *x509 = PEM_read_bio_X509(bp, NULL, NULL, NULL); -- -- if (x509 == NULL) { -- BIO_free(bp); -- return False(); -- } -- -- X509_STORE_add_cert(root_cert_store, x509); -- -- BIO_free(bp); -- X509_free(x509); -+ if (SSL_CTX_load_verify_locations(sc->ctx_, "/etc/pki/tls/certs/ca-bundle.crt", NULL) == 1) { -+ root_cert_store = SSL_CTX_get_cert_store(sc->ctx_); -+ } else { -+ // empty store -+ root_cert_store = X509_STORE_new(); - } -+ } else { -+ SSL_CTX_set_cert_store(sc->ctx_, root_cert_store); - } -- - sc->ca_store_ = root_cert_store; -- SSL_CTX_set_cert_store(sc->ctx_, sc->ca_store_); - - return True(); - } diff --git a/nodejs.spec b/nodejs.spec index 873675f..cee55f5 100644 --- a/nodejs.spec +++ b/nodejs.spec @@ -1,7 +1,6 @@ %global with_debug 1 -# We don't have pkgdocdir on EPEL6 (yet?) -%global _pkgdocdir %{_docdir}/%{name}-%{version} +%{?!_pkgdocdir:%global _pkgdocdir %{_docdir}/%{name}-%{version}} # ARM builds currently break on the Debug builds, so we'll just # build the standard runtime until that gets sorted out. @@ -10,55 +9,74 @@ %endif # == Node.js Version == -%global nodejs_major 0 -%global nodejs_minor 10 -%global nodejs_patch 46 +# Note: Fedora should only ship LTS versions of Node.js (currently expected +# to be major versions with even numbers). The odd-numbered versions are new +# feature releases that are only supported for nine months, which is shorter +# than a Fedora release lifecycle. +%global nodejs_major 6 +%global nodejs_minor 5 +%global nodejs_patch 0 %global nodejs_abi %{nodejs_major}.%{nodejs_minor} %global nodejs_version %{nodejs_major}.%{nodejs_minor}.%{nodejs_patch} # == Bundled Dependency Versions == -# v8 - from deps/v8/src/version.cc -%global v8_major 3 -%global v8_minor 14 -%global v8_build 5 -%global v8_patch 9 +# v8 - from deps/v8/include/v8-version.h +%global v8_major 5 +%global v8_minor 1 +%global v8_build 281 +%global v8_patch 81 # V8 presently breaks ABI at least every x.y release while never bumping SONAME %global v8_abi %{v8_major}.%{v8_minor} %global v8_version %{v8_major}.%{v8_minor}.%{v8_build}.%{v8_patch} # c-ares - from deps/cares/include/ares_version.h %global c_ares_major 1 -%global c_ares_minor 9 -%global c_ares_patch 0 +%global c_ares_minor 10 +%global c_ares_patch 1 %global c_ares_version %{c_ares_major}.%{c_ares_minor}.%{c_ares_patch} -# http-parser - from deps/http-parser/http_parser.h -%global http_parser_major 1 -%global http_parser_minor 2 -%global http_parser_version %{http_parser_major}.%{http_parser_minor} +# http-parser - from deps/http_parser/http_parser.h +%global http_parser_major 2 +%global http_parser_minor 7 +%global http_parser_patch 0 +%global http_parser_version %{http_parser_major}.%{http_parser_minor}.%{http_parser_patch} # punycode - from lib/punycode.js # Note: this was merged into the mainline since 0.6.x -%global punycode_major 1 -%global punycode_minor 2 +# Note: this will be unmerged in v7 or v8 +%global punycode_major 2 +%global punycode_minor 0 %global punycode_patch 0 %global punycode_version %{punycode_major}.%{punycode_minor}.%{punycode_patch} +# npm - from deps/npm/package.json +%global npm_epoch 1 +%global npm_major 3 +%global npm_minor 10 +%global npm_patch 3 +%global npm_version %{npm_major}.%{npm_minor}.%{npm_patch} + +# Filter out the NPM bundled dependencies so we aren't providing them +%global __provides_exclude_from ^%{_prefix}/lib/node_modules/npm/.*$ +%global __requires_exclude_from ^%{_prefix}/lib/node_modules/npm/.*$ + + Name: nodejs +Epoch: 1 Version: %{nodejs_version} -Release: 1%{?dist} +# Keep this release > 100 for F25+ due to a complicated npm upgrade bug +Release: 104%{?dist} Summary: JavaScript runtime License: MIT and ASL 2.0 and ISC and BSD Group: Development/Languages URL: http://nodejs.org/ -# Exclusive archs must match v8 ExclusiveArch: %{nodejs_arches} # nodejs bundles openssl, but we use the system version in Fedora # because openssl contains prohibited code, we remove openssl completely from # the tarball, using the script in Source100 -Source0: node-v%{version}-stripped.tar.gz +Source0: node-v%{nodejs_version}-stripped.tar.gz Source100: %{name}-tarball.sh # The native module Requires generator remains in the nodejs SRPM, so it knows @@ -67,35 +85,47 @@ Source100: %{name}-tarball.sh Source7: nodejs_native.attr # Disable running gyp on bundled deps we don't use -Patch1: nodejs-disable-gyp-deps.patch +Patch1: 0001-disable-running-gyp-files-for-bundled-deps.patch + +# EPEL only has OpenSSL 1.0.1, so we need to carry a patch on that platform +Patch2: 0002-Use-openssl-1.0.1.patch # use system certificates instead of the bundled ones # modified version of Debian patch: # http://patch-tracker.debian.org/patch/series/view/nodejs/0.10.26~dfsg1-1/2014_donotinclude_root_certs.patch -Patch2: nodejs-use-system-certs.patch +Patch3: 0003-CA-Certificates-are-provided-by-Fedora.patch BuildRequires: python-devel -BuildRequires: libuv-devel +BuildRequires: libuv-devel >= 1:1.9.1 +Requires: libuv >= 1:1.9.1 +BuildRequires: libicu-devel BuildRequires: zlib-devel -# Node.js requires some features from openssl 1.0.1 for SPDY support +BuildRequires: gcc >= 4.8.0 +BuildRequires: gcc-c++ >= 4.8.0 + +%if 0%{?epel} BuildRequires: openssl-devel >= 1:1.0.1 +%else +BuildRequires: openssl-devel >= 1:1.0.2 +%endif # we need the system certificate store when Patch2 is applied Requires: ca-certificates #we need ABI virtual provides where SONAMEs aren't enough/not present so deps #break when binary compatibility is broken -%global nodejs_abi 0.10 Provides: nodejs(abi) = %{nodejs_abi} +Provides: nodejs(abi%{nodejs_major}) = %{nodejs_abi} Provides: nodejs(v8-abi) = %{v8_abi} +Provides: nodejs(v8-abi%{v8_major}) = %{v8_abi} #this corresponds to the "engine" requirement in package.json -Provides: nodejs(engine) = %{version} +Provides: nodejs(engine) = %{nodejs_version} # Node.js currently has a conflict with the 'node' package in Fedora # The ham-radio group has agreed to rename their binary for us, but # in the meantime, we're setting an explicit Conflicts: here -Conflicts: node <= 0.3.2-11 +Conflicts: node <= 0.3.2-12 # The punycode module was absorbed into the standard library in v0.6. # It still exists as a seperate package for the benefit of users of older @@ -103,13 +133,16 @@ Conflicts: node <= 0.3.2-11 # we don't need the seperate nodejs-punycode package, so we Provide it here so # dependent packages don't need to override the dependency generator. # See also: RHBZ#11511811 +# UPDATE: punycode will be deprecated and so we should unbundle it in Node v8 +# and use upstream module instead +# https://github.com/nodejs/node/commit/29e49fc286080215031a81effbd59eac092fff2f Provides: nodejs-punycode = %{punycode_version} Provides: npm(punycode) = %{punycode_version} + # Node.js has forked c-ares from upstream in an incompatible way, so we need # to carry the bundled version internally. # See https://github.com/nodejs/node/commit/766d063e0578c0f7758c3a965c971763f43fec85 -# Keep this in sync with deps/cares/include/ares_version.h Provides: bundled(c-ares) = %{c_ares_version} # Node.js is closely tied to the version of v8 that is used with it. It makes @@ -123,6 +156,15 @@ Provides: bundled(v8) = %{v8_version} # do releases often and is almost always far behind the bundled version Provides: bundled(http-parser) = %{http_parser_version} +# Make sure we keep NPM up to date when we update Node.js +%if 0%{?epel} +# EPEL doesn't support Recommends, so make it strict +Requires: npm = %{npm_epoch}:%{npm_version}-%{release} +%else +Recommends: npm = %{npm_epoch}:%{npm_version}-%{release} +Conflicts: npm < %{npm_epoch}:%{npm_version}-%{release} +%endif + %description Node.js is a platform built on Chrome's JavaScript runtime @@ -134,40 +176,71 @@ real-time applications that run across distributed devices. %package devel Summary: JavaScript runtime - development headers Group: Development/Languages -Requires: %{name}%{?_isa} == %{version}-%{release} +Requires: %{name}%{?_isa} = %{epoch}:%{nodejs_version}-%{release} Requires: libuv-devel%{?_isa} -Requires: v8-devel%{?_isa} -Requires: openssl-devel%{?_isa} zlib-devel%{?_isa} +Requires: openssl-devel%{?_isa} +Requires: zlib-devel%{?_isa} Requires: nodejs-packaging %description devel Development headers for the Node.js JavaScript runtime. +%package -n npm +Summary: Node.js Package Manager +Epoch: %{npm_epoch} +Version: %{npm_version} + +# We used to ship npm separately, but it is so tightly integrated with Node.js +# (and expected to be present on all Node.js systems) that we ship it bundled +# now. +Obsoletes: npm < 0:3.5.4-6 +Provides: npm = %{npm_epoch}:%{npm_version} +Requires: nodejs = %{epoch}:%{nodejs_version}-%{release} + +# Do not add epoch to the virtual NPM provides or it will break +# the automatic dependency-generation script. +Provides: npm(npm) = %{npm_version} + +%description -n npm +npm is a package manager for node.js. You can use it to install and publish +your node programs. It manages dependencies and does other cool stuff. + %package docs Summary: Node.js API documentation Group: Documentation BuildArch: noarch +# We don't require that the main package be installed to +# use the docs, but if it is installed, make sure the +# version always matches +Conflicts: %{name} > %{epoch}:%{nodejs_version}-%{release} +Conflicts: %{name} < %{epoch}:%{nodejs_version}-%{release} + %description docs The API documentation for the Node.js JavaScript runtime. %prep -%setup -q -n node-v%{version} +%setup -q -n node-v%{nodejs_version} -# remove bundled dependencies +# remove bundled dependencies that we aren't building %patch1 -p1 -rm -rf deps/npm \ - deps/uv \ +rm -rf deps/uv \ deps/zlib # remove bundled CA certificates -%patch2 -p1 rm -f src/node_root_certs.h +%patch3 -p1 + +%if 0%{?epel} +%patch2 -p1 +%endif %build # build with debugging symbols and add defines from libuv (#892601) +# Node's v8 breaks with GCC 6 because of incorrect usage of methods on +# NULL objects. We need to pass -fno-delete-null-pointer-checks export CFLAGS='%{optflags} -g -D_LARGEFILE_SOURCE -D_FILE_OFFSET_BITS=64 -fno-delete-null-pointer-checks' export CXXFLAGS='%{optflags} -g -D_LARGEFILE_SOURCE -D_FILE_OFFSET_BITS=64 -fno-delete-null-pointer-checks' @@ -175,8 +248,8 @@ export CXXFLAGS='%{optflags} -g -D_LARGEFILE_SOURCE -D_FILE_OFFSET_BITS=64 -fno- --shared-openssl \ --shared-zlib \ --shared-libuv \ - --without-npm \ - --without-dtrace + --without-dtrace \ + --with-intl=system-icu %if %{?with_debug} == 1 # Setting BUILDTYPE=Debug builds both release and debug binaries @@ -189,7 +262,7 @@ make BUILDTYPE=Release %{?_smp_mflags} %install rm -rf %{buildroot} -./tools/install.py install %{buildroot} +./tools/install.py install %{buildroot} %{_prefix} # and remove dtrace file again rm -rf %{buildroot}/%{_prefix}/lib/dtrace @@ -210,8 +283,8 @@ mkdir -p %{buildroot}%{_prefix}/lib/node_modules install -Dpm0644 %{SOURCE7} %{buildroot}%{_rpmconfigdir}/fileattrs/nodejs_native.attr cat << EOF > %{buildroot}%{_rpmconfigdir}/nodejs_native.req #!/bin/sh -echo 'nodejs(abi) = %nodejs_abi' -echo 'nodejs(v8-abi) = %v8_abi' +echo 'nodejs(abi%{nodejs_major}) >= %nodejs_abi' +echo 'nodejs(v8-abi%{v8_major}) >= %v8_abi' EOF chmod 0755 %{buildroot}%{_rpmconfigdir}/nodejs_native.req @@ -219,13 +292,47 @@ chmod 0755 %{buildroot}%{_rpmconfigdir}/nodejs_native.req mkdir -p %{buildroot}%{_pkgdocdir}/html cp -pr doc/* %{buildroot}%{_pkgdocdir}/html rm -f %{buildroot}%{_pkgdocdir}/html/nodejs.1 -cp -p LICENSE %{buildroot}%{_pkgdocdir}/html -cp -p ChangeLog LICENSE README.md AUTHORS %{buildroot}%{_pkgdocdir} #node-gyp needs common.gypi too mkdir -p %{buildroot}%{_datadir}/node cp -p common.gypi %{buildroot}%{_datadir}/node +# Install the GDB init tool into the documentation directory +mv %{buildroot}/%{_datadir}/doc/node/gdbinit %{buildroot}/%{_pkgdocdir}/gdbinit + +# Since the old version of NPM was unbundled, there are a lot of symlinks in +# it's node_modules directory. We need to keep these as symlinks to ensure we +# can backtrack on this if we decide to. + +# Rename the npm node_modules directory to node_modules.bundled +mv %{buildroot}/%{_prefix}/lib/node_modules/npm/node_modules \ + %{buildroot}/%{_prefix}/lib/node_modules/npm/node_modules.bundled + +# Recreate all the symlinks +mkdir -p %{buildroot}/%{_prefix}/lib/node_modules/npm/node_modules +FILES=%{buildroot}/%{_prefix}/lib/node_modules/npm/node_modules.bundled/* +for f in $FILES +do + module=`basename $f` + ln -s ../node_modules.bundled/$module %{buildroot}%{_prefix}/lib/node_modules/npm/node_modules/$module +done + +# install NPM docs to mandir +mkdir -p %{buildroot}%{_mandir} \ + %{buildroot}%{_pkgdocdir}/npm + +cp -pr deps/npm/man/* %{buildroot}%{_mandir}/ +rm -rf %{buildroot}%{_prefix}/lib/node_modules/npm/man +ln -sf %{_mandir} %{buildroot}%{_prefix}/lib/node_modules/npm/man + +# Install Markdown and HTML documentation to %{_pkgdocdir} +cp -pr deps/npm/html deps/npm/doc %{buildroot}%{_pkgdocdir}/npm/ +rm -rf %{buildroot}%{_prefix}/lib/node_modules/npm/html \ + %{buildroot}%{_prefix}/lib/node_modules/npm/doc + +ln -sf %{_pkgdocdir} %{buildroot}%{_prefix}/lib/node_modules/npm/html +ln -sf %{_pkgdocdir}/npm/html %{buildroot}%{_prefix}/lib/node_modules/npm/doc + %check # Fail the build if the versions don't match @@ -237,19 +344,26 @@ cp -p common.gypi %{buildroot}%{_datadir}/node # Ensure we have punycode and that the version matches %{buildroot}/%{_bindir}/node -e "require(\"assert\").equal(require(\"punycode\").version, '%{punycode_version}')" +# Ensure we have npm and that the version matches +NODE_PATH=%{buildroot}%{_prefix}/lib/node_modules %{buildroot}/%{_bindir}/node -e "require(\"assert\").equal(require(\"npm\").version, '%{npm_version}')" %files %{_bindir}/node -%{_mandir}/man1/node.* %dir %{_prefix}/lib/node_modules %dir %{_datadir}/node +%dir %{_datadir}/systemtap +%dir %{_datadir}/systemtap/tapset +%{_datadir}/systemtap/tapset/node.stp %{_rpmconfigdir}/fileattrs/nodejs_native.attr %{_rpmconfigdir}/nodejs_native.req -%dir %{_pkgdocdir} -%{_pkgdocdir}/ChangeLog -%{_pkgdocdir}/LICENSE -%{_pkgdocdir}/README.md -%{_pkgdocdir}/AUTHORS +%license LICENSE +%doc AUTHORS CHANGELOG.md COLLABORATOR_GUIDE.md GOVERNANCE.md README.md +%doc ROADMAP.md WORKING_GROUPS.md +%{_prefix}/lib/node_modules/npm +%ghost %{_sysconfdir}/npmrc +%ghost %{_sysconfdir}/npmignore +%{_mandir}/man*/* + %files devel %if %{?with_debug} == 1 @@ -257,12 +371,25 @@ cp -p common.gypi %{buildroot}%{_datadir}/node %endif %{_includedir}/node %{_datadir}/node/common.gypi +%{_pkgdocdir}/gdbinit + + +%files -n npm +%{_bindir}/npm + %files docs %dir %{_pkgdocdir} %{_pkgdocdir}/html +%{_pkgdocdir}/npm/html +%{_pkgdocdir}/npm/doc %changelog +* Mon Sep 12 2016 Stephen Gallagher - 1:6.5.0-104 +- Update to 6.5.0 +- Add support for building on EPEL 7 against OpenSSL 1.0.1 +- Modify v8_abi autorequires to avoid unnecessary rebuilds + * Fri Jun 24 2016 Zuzana Svetlikova - 0.10.46-1 - Update to 0.10.46(security fix) - https://github.com/nodejs/node/blob/v0.10.46/ChangeLog diff --git a/sources b/sources index 18989dd..7a5ef30 100644 --- a/sources +++ b/sources @@ -1 +1 @@ -af86e8807e760f348b58acaa9317226b node-v0.10.46-stripped.tar.gz +563d1513c33a047f0b5bb8bd82d8663f node-v6.5.0-stripped.tar.gz