我想构建新版本的 Open Pegasus Client (2.14.1)。不幸的是,我正面临一些构建问题。有人知道这些问题的一些解决方法吗?

我的环境是:

  • 操作系统:Windows 8.1 企业版
  • Make 版本:GNU Make 3.81
  • Pegasus 源版本:2.14.1
  • OpenSSL 版本:1.0.2a

  • 我的场景很简单:
  • 我已经下载了 Open Pegasus 2.14.1 的源代码
  • 我已经下载了 OpenSSL 二进制文件(实际版本 v1.0.2a)。
  • 提取 Pegasus 源代码后,我将环境设置为
    这些设置:
    call "C:\Program Files (x86)\Microsoft Visual Studio 12.0\VC\bin\vcvars32.bat"
    set PEGASUS_ROOT=D:/Dev/pegasus-2.14.1/pegasus
    set PEGASUS_HOME=%PEGASUS_ROOT%
    set PEGASUS_PLATFORM=WIN32_IX86_MSVC
    set path=%path%;%PEGASUS_HOME%\bin
    set OPENSSL_HOME=D:/Dev/OpenSSL-Win32
    set PEGASUS_HAS_SSL=true
    
  • 下一步是构建 mu.exe 工具。所以,我已经执行了“make
    buildmu"=> 成功构建并复制到 "/bin"文件夹。我会
    喜欢构建 Pegasus 所以:“make build” => 一段时间后我得到了这个
    错误:

    Message.cpp(433):错误 C2065:'magic':未声明的标识符
  • 我试图解决这个问题。我发现定义了魔法常数
    在\pegasus-2.14.1\pegasus\src\Pegasus\Common\Linkable.h 文件中,所以我
    有两个选项:a) 将构建配置切换到 DEBUG(设置
    PEGASUS_DEBUG=true) b) 从第 62 行中删除 DEBUG 条件
    Linkable.h 文件然后,不幸的是,我再次尝试构建 Pegasus
    我收到此错误:

    错误 LNK2005:_OPENSSL_Applink 已在 SSLContext.obj 中定义

  • 在这一点上,我不知道如何解决这个问题。我只是试图删除这些行:
    # ifdef PEGASUS_OS_TYPE_WINDOWS
     # include<openssl/applink.c>
    # endif
    

    来自 SSLContextRep.h 文件。在此修改后,我能够获得 Pegasus 客户端二进制文件。但是这些二进制文件只在没有 SSL 的情况下工作,当我想使用 SSL 通信时,我总是遇到错误:“
    Pegasus 异常:'无法连接到 10.199.1.139:5989。连接失败。'。”,所以我认为这是因为我在 SSLContextRep.h 中修改了代码。

    Pegasus Tracer 的输出:

    SSL:未连接 1 错误:140740BF:SSL 例程:SSL23_CLIENT_HELLO:无可用协议(protocol)
    SSL:删除的 SSL 套接字

    有谁知道有什么问题?有人拥有一些(更好的)Windows 环境配置步骤来构建 OpenPegasus 吗?

    非常感谢您提供任何帮助。

    编辑:

    我需要能够在没有证书的情况下工作。因为我使用 SSL 与各种存储阵列通信,但我没有它们的证书。因此我使用 SSLContext 的这个构造函数:
    SSLContext sslContext(String::EMPTY, NULL, String::EMPTY);
    

    这种方法在 OpenPegasus 2.13 版本中对我很有效。

    最佳答案

    Outputs from Pegasus Tracer:
    
        SSL: Not connected 1 error:140740BF:SSL routines:SSL23_CLIENT_HELLO:no protocols available SSL: Deleted SSL socket
    

    这是消息的来源:
    $ grep -nR "Deleted SSL socket" *
    src/Pegasus/Common/TLS.cpp:172:    PEG_TRACE_CSTRING(TRC_SSL, Tracer::LEVEL3, "---> SSL: Deleted SSL socket");
    

    以及第 172 行附近的代码:
    SSLSocket::~SSLSocket()
    {
        PEG_METHOD_ENTER(TRC_SSL, "SSLSocket::~SSLSocket()");
    
        close();
        delete static_cast<SharedPtr<X509_STORE, FreeX509STOREPtr>*>(_crlStore);
        SSL_free(static_cast<SSL*>(_SSLConnection));
    
        PEG_TRACE_CSTRING(TRC_SSL, Tracer::LEVEL3, "---> SSL: Deleted SSL socket");
    
        PEG_METHOD_EXIT();
    }
    

    如果你查看 .../src/Pegasus/Common/SSLContext.cpp ,你会看到:
    SSL_CTX* SSLContextRep::_makeSSLContext()
    {
        PEG_METHOD_ENTER(TRC_SSL, "SSLContextRep::_makeSSLContext()");
    
        //
        // create SSL Context Area
        //
        SSL_CTX *sslContext = NULL;
        if (!(sslContext = SSL_CTX_new(SSLv23_method())))
        {
            PEG_METHOD_EXIT();
            MessageLoaderParms parms(
                "Common.SSLContext.COULD_NOT_GET",
                "Could not get SSL CTX");
            throw SSLException(parms);
        }
    
        int options = SSL_OP_ALL;
    
        SSL_CTX_set_options(sslContext, options);
        if ( _sslCompatibility == false )
        {
    
    #ifdef TLS1_2_VERSION
            // Enable only TLSv1.2 and disable all other protocol (SSL v2, SSL v3,
            // TLS v1.0, TLSv1.1)
    
            options = SSL_OP_NO_TLSv1 | SSL_OP_NO_TLSv1_1 | SSL_OP_NO_SSLv3;
    #else
            PEG_METHOD_EXIT();
            MessageLoaderParms parms(
                " Common.SSLContext.TLS_1_2_PROTO_NOT_SUPPORTED",
                "TLSv1.2 protocol support is not detected on this system. "
                " To run in less secured mode, set sslBackwardCompatibility=true"
                " in planned config file and start cimserver.");
            throw SSLException(parms);
    #endif
        }
    
        // sslv2 is off permanently even if sslCompatibility is true
        options |= SSL_OP_NO_SSLv2;
        SSL_CTX_set_options(sslContext, options);
    
    #ifdef PEGASUS_SSL_WEAKENCRYPTION
        if (!(SSL_CTX_set_cipher_list(sslContext, SSL_TXT_EXP40)))
        {
            SSL_CTX_free(sslContext);
            sslContext = NULL;
    
            MessageLoaderParms parms(
                "Common.SSLContext.COULD_NOT_SET_CIPHER_LIST",
                "Could not set the cipher list");
            throw SSLException(parms);
        }
    #endif
    
        if (_cipherSuite.size() != 0)
        {
            if (!(SSL_CTX_set_cipher_list(sslContext, _cipherSuite.getCString())))
            {
                SSL_CTX_free(sslContext);
                sslContext = NULL;
    
                PEG_TRACE_CSTRING(TRC_SSL, Tracer::LEVEL3,
                    "---> SSL: Cipher Suite could not be specified");
                MessageLoaderParms parms(
                    "Common.SSLContext.COULD_NOT_SET_CIPHER_LIST",
                    "Could not set the cipher list");
                throw SSLException(parms);
            }
            else
            {
               PEG_TRACE((TRC_SSL, Tracer::LEVEL3,
                    "---> SSL: Cipher suite set to %s",
                    (const char *)_cipherSuite.getCString()));
            }
        }
        ...
    }
    

    我会出于两个原因放弃该功能,并添加如下内容。

    首先,它是编写为客户端和服务器的非晶例程之一。我从使用 OpenSSL 的经验中发现,您对 SSL_CTX* GetClientContext()SSL_CTX* GetServerContext() 有单独的函数。

    其次,从安全工程的角度来看,您不允许人们因 PEGASUS_SSL_WEAKENCRYPTION 或空密码列表之类的东西而进入不良状态。你把枪拿走,这样他们就不能用脚开枪了。
    SSL_CTX* SSLContextRep::_makeSSLContext()
    {
        PEG_METHOD_ENTER(TRC_SSL, "SSLContextRep::_makeSSLContext()");
    
        SSL_CTX *sslContext = NULL;
        if (!(sslContext = SSL_CTX_new(SSLv23_method())))
        {
            PEG_METHOD_EXIT();
            MessageLoaderParms parms(
                "Common.SSLContext.COULD_NOT_GET",
                "Could not get SSL CTX");
            throw SSLException(parms);
        }
    
        // TLS 1.0 and above. No compression because it leaks information.
        static const long options = SSL_OP_NO_SSLv2 | SSL_OP_NO_SSLv3 | SSL_OP_NO_COMPRESSION;
        SSL_CTX_set_options(sslContext, options);
    
        const char* const PREFERRED_CIPHERS = "HIGH:!aNULL:!kRSA:!PSK:!SRP:!MD5:!RC4";
        int res = SSL_set_cipher_list(sslContext, PREFERRED_CIPHERS);
        if(res != 1)
        {
            PEG_TRACE_CSTRING(TRC_SSL, Tracer::LEVEL3,
                "---> SSL: Cipher Suite could not be specified");
            MessageLoaderParms parms(
                "Common.SSLContext.COULD_NOT_SET_CIPHER_LIST",
                "Could not set the cipher list");
            throw SSLException(parms);
        }
    
        // Keep this stuff
        SSL_CTX_set_quiet_shutdown(sslContext, 1);
        SSL_CTX_set_mode(sslContext, SSL_MODE_AUTO_RETRY);
        SSL_CTX_set_mode(sslContext, SSL_MODE_ENABLE_PARTIAL_WRITE);
        SSL_CTX_set_session_cache_mode(sslContext, SSL_SESS_CACHE_OFF);
        SSL_CTX_set_mode(sslContext, SSL_MODE_RELEASE_BUFFERS);
    
        // Back to gutting. We don't allow VERIFY_PEER_NONE.
        {
            PEG_TRACE_CSTRING(TRC_SSL, Tracer::LEVEL4,
                "---> SSL: certificate verification callback specified");
            SSL_CTX_set_verify(sslContext,
                SSL_VERIFY_PEER, prepareForCallback);
        }
    
        // Some more gutting. Certificates have to be verified.
        if(_trustStore.size() == 0)
        {
            PEG_TRACE((TRC_SSL, Tracer::LEVEL1,
                    "---> SSL: Could not load certificates from the "
                    "trust store: %s",
                    (const char*)_trustStore.getCString()));
            MessageLoaderParms parms(
                    "Common.SSLContext.COULD_NOT_LOAD_CERTIFICATES",
                    "Could not load certificates in to trust store.");
            SSL_CTX_free(sslContext);
            sslContext = NULL;
    
            PEG_METHOD_EXIT();
            throw SSLException(parms);
        }
    
        if ( !SSL_CTX_load_verify_locations(
            sslContext, _trustStore.getCString(), NULL) )
            {
                PEG_TRACE((TRC_SSL, Tracer::LEVEL1,
                    "---> SSL: Could not load certificates from the "
                    "trust store: %s",
                    (const char*)_trustStore.getCString()));
                MessageLoaderParms parms(
                    "Common.SSLContext.COULD_NOT_LOAD_CERTIFICATES",
                    "Could not load certificates in to trust store.");
                SSL_CTX_free(sslContext);
                sslContext = NULL;
    
                PEG_METHOD_EXIT();
                throw SSLException(parms);
            }
    
         // I'm not sure what to do with CRLs. They are usually a DoS waiting to happen....
         if (_crlPath.size() != 0)
         {
            // need to save this -- can we make it static since there's only
            // one CRL for cimserver?
            X509_LOOKUP* pLookup;
    
            _crlStore.reset(X509_STORE_new());
            if (_crlStore.get() == NULL)
            {
                SSL_CTX_free(sslContext);
                sslContext = NULL;
                PEG_METHOD_EXIT();
                throw PEGASUS_STD(bad_alloc)();
            }
    
            // the validity of the crlstore was checked in ConfigManager
            // during server startup
            if (FileSystem::isDirectory(_crlPath))
            {
                PEG_TRACE((TRC_SSL, Tracer::LEVEL4,
                    "---> SSL: CRL store is a directory in %s",
                    (const char*)_crlPath.getCString()));
    
                if ((pLookup = X509_STORE_add_lookup(
                         _crlStore.get(), X509_LOOKUP_hash_dir())) == NULL)
                {
                    MessageLoaderParms parms(
                        "Common.SSLContext.COULD_NOT_LOAD_CRLS",
                        "Could not load certificate revocation list.");
                    _crlStore.reset();
                    SSL_CTX_free(sslContext);
                    sslContext = NULL;
                    PEG_METHOD_EXIT();
                    throw SSLException(parms);
                }
    
                X509_LOOKUP_add_dir(
                    pLookup, (const char*)_crlPath.getCString(), X509_FILETYPE_PEM);
    
                PEG_TRACE_CSTRING(TRC_SSL, Tracer::LEVEL3,
                    "---> SSL: Successfully configured CRL directory");
            }
            else
            {
                PEG_TRACE((TRC_SSL, Tracer::LEVEL4,
                    "---> SSL: CRL store is the file %s",
                    (const char*)_crlPath.getCString()));
    
                if ((pLookup = X509_STORE_add_lookup(
                       _crlStore.get(), X509_LOOKUP_file())) == NULL)
                {
                    MessageLoaderParms parms(
                        "Common.SSLContext.COULD_NOT_LOAD_CRLS",
                        "Could not load certificate revocation list.");
                    _crlStore.reset();
                    SSL_CTX_free(sslContext);
                    sslContext = NULL;
                    PEG_METHOD_EXIT();
                    throw SSLException(parms);
                }
    
                X509_LOOKUP_load_file(
                    pLookup, (const char*)_crlPath.getCString(), X509_FILETYPE_PEM);
    
                PEG_TRACE_CSTRING(TRC_SSL, Tracer::LEVEL4,
                    "---> SSL: Successfully configured CRL file");
            }
        }
    
        Boolean keyLoaded = false;
    
        // Gut server specific certificate and key routines since this is a client.
    
        PEG_METHOD_EXIT();
        return sslContext;
    }
    

    TLS 1.2 和 AEAD 密码套件是一个非常好的选择。但是,对于大多数意图和目的,TLS 1.0 及更高版本没问题。

    我认为这可能是客户端中 0x140740BF 的原因。它来自 SSLContext.cpp 824 行:
    SSL_CTX_set_verify(sslContext,
        SSL_VERIFY_PEER | SSL_VERIFY_CLIENT_ONCE, prepareForCallback);
    

    看起来服务器需要证书。

    ...但通常您会收到不同的 TLS 警报。

    并且来源没有调用 SSL_set_tlsext_host_name ,所以 SNI 似乎被破坏了。您可能应该为此提交一份错误报告...
    $ grep -nR SSL_set_tlsext_host_name *
    $
    

    您必须弄清楚客户端在哪里建立连接,并将其设置为 SSL* 选项:
    SSL_set_tlsext_host_name(ssl, hostname);
    
    SSLSocket::SSLSocket 附近的某个地方可能是一个不错的选择,因为它的构造函数接受一个字符串,并且 sslConnection 在 ctor 中可用。
    SSLSocket::SSLSocket(
        SocketHandle socket,
        SSLContext * sslcontext,
        ReadWriteSem * sslContextObjectLock,
        const String& ipAddress)
    

    但我很确定您需要的是 DNS 名称而不是 IP 地址,因为同一 IP 上不同服务器的多路复用首先导致需要 SNI。

    但我可能是错的。 const String& ipAddress 实际上可以是一个 DNS 名称。

    关于c++ - 打开 Pegasus 2.14.1 客户端连接问题,我们在Stack Overflow上找到一个类似的问题:https://stackoverflow.com/questions/30567717/

    10-11 18:40