fixed OpenSSL 1.1.0 compatibility issues
authorVictor Kirhenshtein <victor@netxms.org>
Tue, 16 May 2017 13:32:05 +0000 (16:32 +0300)
committerVictor Kirhenshtein <victor@netxms.org>
Tue, 16 May 2017 13:32:05 +0000 (16:32 +0300)
include/nms_util.h
include/nxcpapi.h
src/agent/core/tunnel.cpp
src/agent/subagents/portCheck/http.cpp
src/libnetxms/crypto.cpp
src/server/core/cert.cpp
src/server/core/session.cpp
src/server/core/tunnel.cpp

index 5f1e50d..7fdbab9 100644 (file)
@@ -666,6 +666,32 @@ public:
 };
 
 /**
+ * Template class for dynamic array which holds references to objects with inaccessible destructors
+ */
+template <class T> class ObjectRefArray : public Array
+{
+private:
+       static void destructor(void *object) { }
+
+public:
+       ObjectRefArray(int initial = 0, int grow = 16) : Array(initial, grow, false) { m_objectDestructor = destructor; }
+       virtual ~ObjectRefArray() { }
+
+       int add(T *object) { return Array::add((void *)object); }
+       T *get(int index) const { return (T*)Array::get(index); }
+   int indexOf(T *object) const { return Array::indexOf((void *)object); }
+   bool contains(T *object) const { return indexOf(object) >= 0; }
+       void set(int index, T *object) { Array::set(index, (void *)object); }
+       void replace(int index, T *object) { Array::replace(index, (void *)object); }
+       void remove(int index) { Array::remove(index); }
+   void remove(T *object) { Array::remove((void *)object); }
+       void unlink(int index) { Array::unlink(index); }
+   void unlink(T *object) { Array::unlink((void *)object); }
+
+   Iterator<T> *iterator() { return new Iterator<T>(new ArrayIterator(this)); }
+};
+
+/**
  * Template class for dynamic array which holds scalar values
  */
 template <class T> class IntegerArray : public Array
index b094872..6db943d 100644 (file)
@@ -262,8 +262,8 @@ private:
 #ifdef _WITH_ENCRYPTION
    MUTEX m_encryptorLock;
 #if WITH_OPENSSL
-   EVP_CIPHER_CTX m_encryptor;
-   EVP_CIPHER_CTX m_decryptor;
+   EVP_CIPHER_CTX *m_encryptor;
+   EVP_CIPHER_CTX *m_decryptor;
 #elif WITH_COMMONCRYPTO
    CCCryptorRef m_encryptor;
    CCCryptorRef m_decryptor;
index be8437f..8e0a331 100644 (file)
@@ -646,13 +646,31 @@ void Tunnel::checkConnection()
  */
 X509_REQ *Tunnel::createCertificateRequest(const char *country, const char *org, const char *cn, EVP_PKEY **pkey)
 {
-   RSA *key = RSA_generate_key(NETXMS_RSA_KEYLEN, 17, NULL, NULL);
+   RSA *key = RSA_new();
    if (key == NULL)
    {
-      debugPrintf(4, _T("call to RSA_generate_key() failed"));
+      debugPrintf(4, _T("call to RSA_new() failed"));
       return NULL;
    }
 
+   BIGNUM *bn = BN_new();
+   if (bn == NULL)
+   {
+      debugPrintf(4, _T("call to BN_new() failed"));
+      RSA_free(key);
+      return NULL;
+   }
+
+   BN_set_word(bn, RSA_F4);
+   if (RSA_generate_key_ex(key, NETXMS_RSA_KEYLEN, bn, NULL) == -1)
+   {
+      debugPrintf(4, _T("call to RSA_generate_key_ex() failed"));
+      RSA_free(key);
+      BN_free(bn);
+      return NULL;
+   }
+   BN_free(bn);
+
    X509_REQ *req = X509_REQ_new();
    if (req != NULL)
    {
index bb19265..1831153 100644 (file)
@@ -226,11 +226,22 @@ int CheckHTTPS(char *szAddr, const InetAddress& addr, short nPort, char *szURI,
                }
                else
                {
+#if OPENSSL_VERSION_NUMBER >= 0x10100000L
+                  char addrText[128];
+                  BIO_set_conn_hostname(out, addr.toStringA(addrText));
+#else            
                   UINT32 addrV4 = htonl(addr.getAddressV4());
                   BIO_set_conn_ip(out, &addrV4);
+#endif
                }
+#if OPENSSL_VERSION_NUMBER >= 0x10100000L
+              char portText[32];
+              snprintf(portText, 32, "%d", (int)nPort);
+               BIO_set_conn_port(out, portText);
+#else
                int intPort = nPort;
                BIO_set_conn_int_port(out, &intPort);
+#endif
                out = BIO_push(ssl_bio, out);
 
                if (BIO_do_connect(out) > 0)
index a6e5407..1bf0d2e 100644 (file)
@@ -186,7 +186,9 @@ bool LIBNETXMS_EXPORTABLE InitCryptoLib(UINT32 dwEnabledCiphers)
    BYTE random[8192];
    int i;
 
+#if OPENSSL_VERSION_NUMBER < 0x10100000L
    CRYPTO_malloc_init();
+#endif
    ERR_load_CRYPTO_strings();
    OpenSSL_add_all_algorithms();
    RAND_seed(random, 8192);
@@ -557,8 +559,15 @@ NXCPEncryptionContext::NXCPEncryptionContext()
    m_keyLength = 0;
    m_cipher = -1;
 #ifdef _WITH_ENCRYPTION
-   EVP_CIPHER_CTX_init(&m_encryptor);
-   EVP_CIPHER_CTX_init(&m_decryptor);
+#if OPENSSL_VERSION_NUMBER >= 0x10100000L
+   m_encryptor = EVP_CIPHER_CTX_new();
+   m_decryptor = EVP_CIPHER_CTX_new();
+#else
+   m_encryptor = (EVP_CIPHER_CTX *)malloc(sizeof(EVP_CIPHER_CTX));
+   m_decryptor = (EVP_CIPHER_CTX *)malloc(sizeof(EVP_CIPHER_CTX));
+   EVP_CIPHER_CTX_init(m_encryptor);
+   EVP_CIPHER_CTX_init(m_decryptor);
+#endif
    m_encryptorLock = MutexCreate();
 #endif
 }
@@ -570,8 +579,15 @@ NXCPEncryptionContext::~NXCPEncryptionContext()
 {
    free(m_sessionKey);
 #ifdef _WITH_ENCRYPTION
-   EVP_CIPHER_CTX_cleanup(&m_encryptor);
-   EVP_CIPHER_CTX_cleanup(&m_decryptor);
+#if OPENSSL_VERSION_NUMBER >= 0x10100000L
+   EVP_CIPHER_CTX_free(m_encryptor);
+   EVP_CIPHER_CTX_free(m_decryptor);
+#else
+   EVP_CIPHER_CTX_cleanup(m_encryptor);
+   EVP_CIPHER_CTX_cleanup(m_decryptor);
+   free(m_encryptor);
+   free(m_decryptor);
+#endif
    MutexDestroy(m_encryptorLock);
 #endif
 }
@@ -650,9 +666,9 @@ bool NXCPEncryptionContext::initCipher(int cipher)
    if (s_ciphers[cipher] == NULL)
       return false;   // Unsupported cipher
 
-   if (!EVP_EncryptInit_ex(&m_encryptor, s_ciphers[cipher](), NULL, NULL, NULL))
+   if (!EVP_EncryptInit_ex(m_encryptor, s_ciphers[cipher](), NULL, NULL, NULL))
       return false;
-   if (!EVP_DecryptInit_ex(&m_decryptor, s_ciphers[cipher](), NULL, NULL, NULL))
+   if (!EVP_DecryptInit_ex(m_decryptor, s_ciphers[cipher](), NULL, NULL, NULL))
       return false;
 
    switch(cipher)
@@ -679,12 +695,12 @@ bool NXCPEncryptionContext::initCipher(int cipher)
          return false;
    }
 
-   if (!EVP_CIPHER_CTX_set_key_length(&m_encryptor, m_keyLength) || !EVP_CIPHER_CTX_set_key_length(&m_decryptor, m_keyLength))
+   if (!EVP_CIPHER_CTX_set_key_length(m_encryptor, m_keyLength) || !EVP_CIPHER_CTX_set_key_length(m_decryptor, m_keyLength))
       return false;
 
    // This check is needed because at least some OpenSSL versions return no error
    // from EVP_CIPHER_CTX_set_key_length but still not change key length
-   if ((EVP_CIPHER_CTX_key_length(&m_encryptor) != m_keyLength) || (EVP_CIPHER_CTX_key_length(&m_decryptor) != m_keyLength))
+   if ((EVP_CIPHER_CTX_key_length(m_encryptor) != m_keyLength) || (EVP_CIPHER_CTX_key_length(m_decryptor) != m_keyLength))
       return false;
 
    m_cipher = cipher;
@@ -761,7 +777,7 @@ NXCP_ENCRYPTED_MESSAGE *NXCPEncryptionContext::encryptMessage(NXCP_MESSAGE *msg)
 #ifdef _WITH_ENCRYPTION
    MutexLock(m_encryptorLock);
 
-   if (!EVP_EncryptInit_ex(&m_encryptor, NULL, NULL, m_sessionKey, m_iv))
+   if (!EVP_EncryptInit_ex(m_encryptor, NULL, NULL, m_sessionKey, m_iv))
    {
       MutexUnlock(m_encryptorLock);
       return NULL;
@@ -769,7 +785,7 @@ NXCP_ENCRYPTED_MESSAGE *NXCPEncryptionContext::encryptMessage(NXCP_MESSAGE *msg)
 
    UINT32 msgSize = ntohl(msg->size);
    NXCP_ENCRYPTED_MESSAGE *emsg = 
-      (NXCP_ENCRYPTED_MESSAGE *)malloc(msgSize + NXCP_ENCRYPTION_HEADER_SIZE + EVP_CIPHER_block_size(EVP_CIPHER_CTX_cipher(&m_encryptor)) + 8);
+      (NXCP_ENCRYPTED_MESSAGE *)malloc(msgSize + NXCP_ENCRYPTION_HEADER_SIZE + EVP_CIPHER_block_size(EVP_CIPHER_CTX_cipher(m_encryptor)) + 8);
    emsg->code = htons(CMD_ENCRYPTED_MESSAGE);
    emsg->reserved = 0;
 
@@ -778,11 +794,11 @@ NXCP_ENCRYPTED_MESSAGE *NXCPEncryptionContext::encryptMessage(NXCP_MESSAGE *msg)
    header.dwReserved = 0;
 
    int dataSize;
-   EVP_EncryptUpdate(&m_encryptor, emsg->data, &dataSize, (BYTE *)&header, NXCP_EH_ENCRYPTED_BYTES);
+   EVP_EncryptUpdate(m_encryptor, emsg->data, &dataSize, (BYTE *)&header, NXCP_EH_ENCRYPTED_BYTES);
    msgSize = dataSize;
-   EVP_EncryptUpdate(&m_encryptor, emsg->data + msgSize, &dataSize, (BYTE *)msg, ntohl(msg->size));
+   EVP_EncryptUpdate(m_encryptor, emsg->data + msgSize, &dataSize, (BYTE *)msg, ntohl(msg->size));
    msgSize += dataSize;
-   EVP_EncryptFinal_ex(&m_encryptor, emsg->data + msgSize, &dataSize);
+   EVP_EncryptFinal_ex(m_encryptor, emsg->data + msgSize, &dataSize);
    msgSize += dataSize + NXCP_EH_UNENCRYPTED_BYTES;
 
    MutexUnlock(m_encryptorLock);
@@ -810,14 +826,14 @@ NXCP_ENCRYPTED_MESSAGE *NXCPEncryptionContext::encryptMessage(NXCP_MESSAGE *msg)
 bool NXCPEncryptionContext::decryptMessage(NXCP_ENCRYPTED_MESSAGE *msg, BYTE *decryptionBuffer)
 {
 #ifdef _WITH_ENCRYPTION
-   if (!EVP_DecryptInit_ex(&m_decryptor, NULL, NULL, m_sessionKey, m_iv))
+   if (!EVP_DecryptInit_ex(m_decryptor, NULL, NULL, m_sessionKey, m_iv))
       return false;
 
    msg->size = ntohl(msg->size);
    int dataSize;
-   EVP_DecryptUpdate(&m_decryptor, decryptionBuffer, &dataSize, msg->data,
+   EVP_DecryptUpdate(m_decryptor, decryptionBuffer, &dataSize, msg->data,
                      msg->size - NXCP_EH_UNENCRYPTED_BYTES - msg->padding);
-   EVP_DecryptFinal(&m_decryptor, decryptionBuffer + dataSize, &dataSize);
+   EVP_DecryptFinal(m_decryptor, decryptionBuffer + dataSize, &dataSize);
 
    NXCP_MESSAGE *clearMsg = (NXCP_MESSAGE *)(decryptionBuffer + NXCP_EH_ENCRYPTED_BYTES);
    UINT32 msgSize = ntohl(clearMsg->size);
index e66e8e0..bab53c8 100644 (file)
@@ -46,7 +46,7 @@ char g_serverCertificatePassword[MAX_PASSWORD] = "";
 /**
  * Server certificate
  */
-static ObjectArray<X509> s_serverCACertificates(8, 8, false);
+static ObjectRefArray<X509> s_serverCACertificates(8, 8);
 static X509 *s_serverCertificate = NULL;
 static EVP_PKEY *s_serverCertificateKey = NULL;
 
@@ -85,10 +85,18 @@ X509 *IssueCertificate(X509_REQ *request, const char *ou, const char *cn, int da
       return NULL;
    }
 
+#if OPENSSL_VERSION_NUMBER >= 0x10100000L
+   ASN1_INTEGER *serial = ASN1_INTEGER_new();
+#else
    ASN1_INTEGER *serial = M_ASN1_INTEGER_new();
+#endif
    ASN1_INTEGER_set(serial, 0);
    int rc = X509_set_serialNumber(cert, serial);
+#if OPENSSL_VERSION_NUMBER >= 0x10100000L
+   ASN1_INTEGER_free(serial);
+#else
    M_ASN1_INTEGER_free(serial);
+#endif
    if (rc != 1)
    {
       nxlog_debug(4, _T("IssueCertificate: cannot set certificate serial number"));
@@ -348,14 +356,15 @@ static BOOL CheckCommonName(X509 *cert, const TCHAR *cn)
 BOOL ValidateUserCertificate(X509 *pCert, const TCHAR *pszLogin, BYTE *pChallenge, BYTE *pSignature,
                                                                          UINT32 dwSigLen, int nMappingMethod, const TCHAR *pszMappingData)
 {
-       EVP_PKEY *pKey;
-       BYTE hash[SHA1_DIGEST_SIZE];
-       BOOL bValid = FALSE;
+   BOOL bValid = FALSE;
 
+   char subjectName[1024];
+   X509_NAME_oneline(X509_get_subject_name(pCert), subjectName, 1024);
 #ifdef UNICODE
-       WCHAR *certSubject = WideStringFromMBString(CHECK_NULL_A(pCert->name));
+   WCHAR certSubject[1024];
+   MultiByteToWideChar(CP_UTF8, 0, subjectName, -1, certSubject, 1024);
 #else
-#define certSubject (CHECK_NULL(pCert->name))
+   const char *certSubject = subjectName;
 #endif
 
        DbgPrintf(3, _T("Validating certificate \"%s\" for user %s"), certSubject, pszLogin);
@@ -365,24 +374,22 @@ BOOL ValidateUserCertificate(X509 *pCert, const TCHAR *pszLogin, BYTE *pChalleng
        {
                DbgPrintf(3, _T("Cannot validate user certificate because certificate store is not initialized"));
                s_certificateStoreLock.unlock();
-#ifdef UNICODE
-               free(certSubject);
-#endif
                return FALSE;
        }
 
        // Validate signature
-       pKey = X509_get_pubkey(pCert);
+       EVP_PKEY *pKey = X509_get_pubkey(pCert);
        if (pKey != NULL)
        {
+      BYTE hash[SHA1_DIGEST_SIZE];
                CalculateSHA1Hash(pChallenge, CLIENT_CHALLENGE_SIZE, hash);
-               switch(pKey->type)
+               switch(EVP_PKEY_id(pKey))
                {
                        case EVP_PKEY_RSA:
-                               bValid = RSA_verify(NID_sha1, hash, SHA1_DIGEST_SIZE, pSignature, dwSigLen, pKey->pkey.rsa);
+                               bValid = RSA_verify(NID_sha1, hash, SHA1_DIGEST_SIZE, pSignature, dwSigLen, EVP_PKEY_get1_RSA(pKey));
                                break;
                        default:
-                               DbgPrintf(3, _T("Unknown key type %d in certificate \"%s\" for user %s"), pKey->type, certSubject, pszLogin);
+                               DbgPrintf(3, _T("Unknown key type %d in certificate \"%s\" for user %s"), EVP_PKEY_id(pKey), certSubject, pszLogin);
                                break;
                }
        }
@@ -431,12 +438,7 @@ BOOL ValidateUserCertificate(X509 *pCert, const TCHAR *pszLogin, BYTE *pChalleng
 
        s_certificateStoreLock.unlock();
 
-#ifdef UNICODE
-       free(certSubject);
-#endif
-
        return bValid;
-#undef certSubject
 }
 
 /**
@@ -662,8 +664,10 @@ static int CertVerifyCallback(int success, X509_STORE_CTX *ctx)
       X509 *cert = X509_STORE_CTX_get_current_cert(ctx);
       int error = X509_STORE_CTX_get_error(ctx);
       int depth = X509_STORE_CTX_get_error_depth(ctx);
+      char subjectName[1024];
+      X509_NAME_oneline(X509_get_subject_name(cert), subjectName, 1024);
       nxlog_debug(4, _T("Certificate \"%hs\" verification error %d (%hs) at depth %d"),
-               cert->name, error, X509_verify_cert_error_string(error), depth);
+             subjectName, error, X509_verify_cert_error_string(error), depth);
    }
    return success;
 }
index ff19753..9c670ca 100644 (file)
@@ -10171,12 +10171,14 @@ void ClientSession::addCACertificate(NXCPMessage *pRequest)
                        pCert = d2i_X509(NULL, &p, dwLen);
                        if (pCert != NULL)
                        {
+            char subjectName[1024];
+            X509_NAME_oneline(X509_get_subject_name(pCert), subjectName, 1024);
 #ifdef UNICODE
-                               WCHAR *wname = WideStringFromMBString(CHECK_NULL_A(pCert->name));
+                               WCHAR *wname = WideStringFromMBString(subjectName);
                                pszEscSubject = EncodeSQLString(wname);
                                free(wname);
 #else
-                               pszEscSubject = EncodeSQLString(CHECK_NULL(pCert->name));
+                               pszEscSubject = EncodeSQLString(subjectName);
 #endif
                                X509_free(pCert);
                                pszComments = pRequest->getFieldAsString(VID_COMMENTS);
index a2ab923..5135620 100644 (file)
@@ -28,7 +28,7 @@
  * Tunnel registration
  */
 static RefCountHashMap<UINT32, AgentTunnel> s_boundTunnels(true);
-static Array s_unboundTunnels(16, 16, false);
+static ObjectRefArray<AgentTunnel> s_unboundTunnels(16, 16);
 static Mutex s_tunnelListLock;
 
 /**
@@ -114,9 +114,9 @@ UINT32 BindAgentTunnel(UINT32 tunnelId, UINT32 nodeId)
    s_tunnelListLock.lock();
    for(int i = 0; i < s_unboundTunnels.size(); i++)
    {
-      if (((AgentTunnel *)s_unboundTunnels.get(i))->getId() == tunnelId)
+      if (s_unboundTunnels.get(i)->getId() == tunnelId)
       {
-         tunnel = (AgentTunnel *)s_unboundTunnels.get(i);
+         tunnel = s_unboundTunnels.get(i);
          tunnel->incRefCount();
          break;
       }
@@ -169,7 +169,7 @@ void GetAgentTunnels(NXCPMessage *msg)
 
    for(int i = 0; i < s_unboundTunnels.size(); i++)
    {
-      ((AgentTunnel *)s_unboundTunnels.get(i))->fillMessage(msg, fieldId);
+      s_unboundTunnels.get(i)->fillMessage(msg, fieldId);
       fieldId += 64;
    }
 
@@ -211,7 +211,7 @@ void ShowAgentTunnels(CONSOLE_CTX console)
             _T("-----+--------------------------+--------------------------+------------------+------------------------\n"));
    for(int i = 0; i < s_unboundTunnels.size(); i++)
    {
-      const AgentTunnel *t = (AgentTunnel *)s_unboundTunnels.get(i);
+      const AgentTunnel *t = s_unboundTunnels.get(i);
       TCHAR ipAddrBuffer[64];
       ConsolePrintf(console, _T("%4d | %-24s | %-24s | %-16s | %s\n"), t->getId(), t->getAddress().toString(ipAddrBuffer), t->getSystemName(), t->getPlatformName(), t->getAgentVersion());
    }
@@ -1194,7 +1194,7 @@ void CloseAgentTunnels()
    }
    delete it;
    for(int i = 0; i < s_unboundTunnels.size(); i++)
-      ((AgentTunnel *)s_unboundTunnels.get(i))->shutdown();
+      s_unboundTunnels.get(i)->shutdown();
    s_tunnelListLock.unlock();
 
    bool wait = true;