diff --git a/deps/openssl/openssl.gypi b/deps/openssl/openssl.gypi index 63286a1a64138c..3620e45c410746 100644 --- a/deps/openssl/openssl.gypi +++ b/deps/openssl/openssl.gypi @@ -214,10 +214,6 @@ 'openssl/crypto/cms/cms_pwri.c', 'openssl/crypto/cms/cms_sd.c', 'openssl/crypto/cms/cms_smime.c', - 'openssl/crypto/comp/c_rle.c', - 'openssl/crypto/comp/c_zlib.c', - 'openssl/crypto/comp/comp_err.c', - 'openssl/crypto/comp/comp_lib.c', 'openssl/crypto/conf/conf_api.c', 'openssl/crypto/conf/conf_def.c', 'openssl/crypto/conf/conf_err.c', @@ -1248,10 +1244,17 @@ 'openssl/include', ], 'openssl_default_defines_all': [ - # No clue what these are for. - 'PURIFY', '_REENTRANT', + # PURIFY makes OpenSSL zero out some buffers. It also stops RAND_bytes() + # from using the existing contents of the destination buffer as a source + # of entropy, which according to some papers, is a possible attack vector + # for reducing the overall entropy. + 'PURIFY', + + # Compression is not used and considered insecure (CRIME.) + 'OPENSSL_NO_COMP', + # SSLv3 is susceptible to downgrade attacks (POODLE.) 'OPENSSL_NO_SSL3', diff --git a/src/node.cc b/src/node.cc index eb8805b2195ad6..0d85ce77c96cd3 100644 --- a/src/node.cc +++ b/src/node.cc @@ -69,7 +69,6 @@ #if defined(_MSC_VER) #include #include -#define strcasecmp _stricmp #define getpid GetCurrentProcessId #define umask _umask typedef int mode_t; @@ -1381,27 +1380,27 @@ enum encoding ParseEncoding(const char* encoding, break; } - if (strcasecmp(encoding, "utf8") == 0) { + if (StringEqualNoCase(encoding, "utf8")) { return UTF8; - } else if (strcasecmp(encoding, "utf-8") == 0) { + } else if (StringEqualNoCase(encoding, "utf-8")) { return UTF8; - } else if (strcasecmp(encoding, "ascii") == 0) { + } else if (StringEqualNoCase(encoding, "ascii")) { return ASCII; - } else if (strcasecmp(encoding, "base64") == 0) { + } else if (StringEqualNoCase(encoding, "base64")) { return BASE64; - } else if (strcasecmp(encoding, "ucs2") == 0) { + } else if (StringEqualNoCase(encoding, "ucs2")) { return UCS2; - } else if (strcasecmp(encoding, "ucs-2") == 0) { + } else if (StringEqualNoCase(encoding, "ucs-2")) { return UCS2; - } else if (strcasecmp(encoding, "utf16le") == 0) { + } else if (StringEqualNoCase(encoding, "utf16le")) { return UCS2; - } else if (strcasecmp(encoding, "utf-16le") == 0) { + } else if (StringEqualNoCase(encoding, "utf-16le")) { return UCS2; - } else if (strcasecmp(encoding, "binary") == 0) { + } else if (StringEqualNoCase(encoding, "binary")) { return BINARY; - } else if (strcasecmp(encoding, "buffer") == 0) { + } else if (StringEqualNoCase(encoding, "buffer")) { return BUFFER; - } else if (strcasecmp(encoding, "hex") == 0) { + } else if (StringEqualNoCase(encoding, "hex")) { return HEX; } else { return default_encoding; diff --git a/src/node_crypto.cc b/src/node_crypto.cc index a143576227b80f..71799d0bfa3ef3 100644 --- a/src/node_crypto.cc +++ b/src/node_crypto.cc @@ -24,16 +24,6 @@ #include #include -#if defined(_MSC_VER) -#define strcasecmp _stricmp -#endif - -#if OPENSSL_VERSION_NUMBER >= 0x10000000L -#define OPENSSL_CONST const -#else -#define OPENSSL_CONST -#endif - #define THROW_AND_RETURN_IF_NOT_STRING_OR_BUFFER(val, prefix) \ do { \ if (!Buffer::HasInstance(val) && !val->IsString()) { \ @@ -351,7 +341,7 @@ void SecureContext::Init(const FunctionCallbackInfo& args) { SecureContext* sc = Unwrap(args.Holder()); Environment* env = sc->env(); - OPENSSL_CONST SSL_METHOD *method = SSLv23_method(); + const SSL_METHOD* method = SSLv23_method(); if (args.Length() == 1 && args[0]->IsString()) { const node::Utf8Value sslmethod(env->isolate(), args[0]); @@ -1969,7 +1959,7 @@ void SSLWrap::GetCurrentCipher(const FunctionCallbackInfo& args) { Base* w = Unwrap(args.Holder()); Environment* env = w->ssl_env(); - OPENSSL_CONST SSL_CIPHER* c = SSL_get_current_cipher(w->ssl_); + const SSL_CIPHER* c = SSL_get_current_cipher(w->ssl_); if (c == nullptr) return; @@ -4452,7 +4442,7 @@ void DiffieHellman::DiffieHellmanGroup( for (size_t i = 0; i < arraysize(modp_groups); ++i) { const modp_group* it = modp_groups + i; - if (strcasecmp(*group_name, it->name) != 0) + if (!StringEqualNoCase(*group_name, it->name)) continue; initialized = diffieHellman->Init(it->prime, @@ -5721,15 +5711,8 @@ void InitCryptoOnce() { // Turn off compression. Saves memory and protects against CRIME attacks. -#if !defined(OPENSSL_NO_COMP) -#if OPENSSL_VERSION_NUMBER < 0x00908000L - STACK_OF(SSL_COMP)* comp_methods = SSL_COMP_get_compression_method(); -#else - STACK_OF(SSL_COMP)* comp_methods = SSL_COMP_get_compression_methods(); -#endif - sk_SSL_COMP_zero(comp_methods); - CHECK_EQ(sk_SSL_COMP_num(comp_methods), 0); -#endif + // No-op with OPENSSL_NO_COMP builds of OpenSSL. + sk_SSL_COMP_zero(SSL_COMP_get_compression_methods()); #ifndef OPENSSL_NO_ENGINE ERR_load_ENGINE_strings(); diff --git a/src/node_http_parser.cc b/src/node_http_parser.cc index d1a130d7eead04..4a0dd580a40af6 100644 --- a/src/node_http_parser.cc +++ b/src/node_http_parser.cc @@ -15,12 +15,6 @@ #include // free() #include // strdup() -#if defined(_MSC_VER) -#define strcasecmp _stricmp -#else -#include // strcasecmp() -#endif - // This is a binding to http_parser (https://github.com/joyent/http-parser) // The goal is to decouple sockets from parsing for more javascript-level // agility. A Buffer is read from a socket and passed to parser.execute(). diff --git a/src/util-inl.h b/src/util-inl.h index 7ff6e51937bde7..355dfcdbee3257 100644 --- a/src/util-inl.h +++ b/src/util-inl.h @@ -203,7 +203,19 @@ void SwapBytes(uint16_t* dst, const uint16_t* src, size_t buflen) { dst[i] = (src[i] << 8) | (src[i] >> 8); } +char ToLower(char c) { + return c >= 'A' && c <= 'Z' ? c + ('a' - 'A') : c; +} +bool StringEqualNoCase(const char* a, const char* b) { + do { + if (*a == '\0') + return *b == '\0'; + if (*b == '\0') + return *a == '\0'; + } while (ToLower(*a++) == ToLower(*b++)); + return false; +} } // namespace node diff --git a/src/util.h b/src/util.h index 1f9f81cfd38e16..dce6c343b1b443 100644 --- a/src/util.h +++ b/src/util.h @@ -178,6 +178,12 @@ inline TypeName* Unwrap(v8::Local object); inline void SwapBytes(uint16_t* dst, const uint16_t* src, size_t buflen); +// tolower() is locale-sensitive. Use ToLower() instead. +inline char ToLower(char c); + +// strcasecmp() is locale-sensitive. Use StringEqualNoCase() instead. +inline bool StringEqualNoCase(const char* a, const char* b); + // Allocates an array of member type T. For up to kStackStorageSize items, // the stack is used, otherwise malloc(). template diff --git a/test/cctest/util.cc b/test/cctest/util.cc index fe966d9b34073c..37133aca562b72 100644 --- a/test/cctest/util.cc +++ b/test/cctest/util.cc @@ -56,3 +56,21 @@ TEST(UtilTest, ListHead) { EXPECT_TRUE(list.IsEmpty()); EXPECT_FALSE(list.begin() != list.end()); } + +TEST(UtilTest, StringEqualNoCase) { + using node::StringEqualNoCase; + EXPECT_FALSE(StringEqualNoCase("a", "b")); + EXPECT_TRUE(StringEqualNoCase("", "")); + EXPECT_TRUE(StringEqualNoCase("equal", "equal")); + EXPECT_TRUE(StringEqualNoCase("equal", "EQUAL")); + EXPECT_TRUE(StringEqualNoCase("EQUAL", "EQUAL")); + EXPECT_FALSE(StringEqualNoCase("equal", "equals")); + EXPECT_FALSE(StringEqualNoCase("equals", "equal")); +} + +TEST(UtilTest, ToLower) { + using node::ToLower; + EXPECT_EQ('0', ToLower('0')); + EXPECT_EQ('a', ToLower('a')); + EXPECT_EQ('a', ToLower('A')); +}