NativeConnectionInfoPtr
IceSSL::TransceiverI::getNativeConnectionInfo() const
{
    NativeConnectionInfoPtr info = new NativeConnectionInfo();
    IceInternal::fdToAddressAndPort(_stream->fd(), info->localAddress, info->localPort, info->remoteAddress, 
                                    info->remotePort);

    if(_ssl)
    {
        for(int i = 0, count = SecTrustGetCertificateCount(_trust); i < count; ++i)
        {
            SecCertificateRef cert = SecTrustGetCertificateAtIndex(_trust, i);
            CFRetain(cert);

            CertificatePtr certificate = new Certificate(cert);
            info->nativeCerts.push_back(certificate);
            info->certs.push_back(certificate->encode());
        }

        SSLCipherSuite cipher;
        SSLGetNegotiatedCipher(_ssl, &cipher);
        info->cipher = _engine->getCipherName(cipher);
    }

    info->adapterName = _adapterName;
    info->incoming = _incoming;
    return info;
}
Пример #2
0
NativeConnectionInfoPtr
IceSSL::TransceiverI::getNativeConnectionInfo() const
{
    NativeConnectionInfoPtr info = new NativeConnectionInfo();
    IceInternal::fdToAddressAndPort(_fd, info->localAddress, info->localPort, info->remoteAddress, info->remotePort);

    if(_ssl != 0)
    {
        //
        // On the client side, SSL_get_peer_cert_chain returns the entire chain of certs.
        // On the server side, the peer certificate must be obtained separately.
        //
        // Since we have no clear idea whether the connection is server or client side,
        // the peer certificate is obtained separately and compared against the first
        // certificate in the chain. If they are not the same, it is added to the chain.
        //
        X509* cert = SSL_get_peer_certificate(_ssl);
        STACK_OF(X509)* chain = SSL_get_peer_cert_chain(_ssl);
        if(cert != 0 && (chain == 0 || sk_X509_num(chain) == 0 || cert != sk_X509_value(chain, 0)))
        {
            CertificatePtr certificate = new Certificate(cert);
            info->nativeCerts.push_back(certificate);
            info->certs.push_back(certificate->encode());
        }
        else
        {
            X509_free(cert);
        }
        
        if(chain != 0)
        {
            for(int i = 0; i < sk_X509_num(chain); ++i)
            {
                //
                // Duplicate the certificate since the stack comes straight from the SSL connection.
                //
                CertificatePtr certificate = new Certificate(X509_dup(sk_X509_value(chain, i)));
                info->nativeCerts.push_back(certificate);
                info->certs.push_back(certificate->encode());
            }
        }

        info->cipher = SSL_get_cipher_name(_ssl); // Nothing needs to be free'd.
    }

    info->adapterName = _adapterName;
    info->incoming = _incoming;
    return info;
}
void
IceSSL::TransceiverI::fillConnectionInfo(const ConnectionInfoPtr& info, std::vector<CertificatePtr>& nativeCerts) const
{
    IceInternal::fdToAddressAndPort(_stream->fd(), info->localAddress, info->localPort, info->remoteAddress,
                                    info->remotePort);
    if(_stream->fd() != INVALID_SOCKET)
    {
        info->rcvSize = IceInternal::getRecvBufferSize(_stream->fd());
        info->sndSize = IceInternal::getSendBufferSize(_stream->fd());
    }

    if(_ssl)
    {
        for(int i = 0, count = SecTrustGetCertificateCount(_trust); i < count; ++i)
        {
            SecCertificateRef cert = SecTrustGetCertificateAtIndex(_trust, i);
            CFRetain(cert);

            CertificatePtr certificate = ICE_MAKE_SHARED(Certificate, cert);
            nativeCerts.push_back(certificate);
            info->certs.push_back(certificate->encode());
        }

        SSLCipherSuite cipher;
        SSLGetNegotiatedCipher(_ssl, &cipher);
        info->cipher = _engine->getCipherName(cipher);
        info->verified = _verified;
    }
    else
    {
        info->verified = false;
    }

    info->adapterName = _adapterName;
    info->incoming = _incoming;
}
Пример #4
0
void
IceSSL::TransceiverI::fillConnectionInfo(const ConnectionInfoPtr& info, vector<CertificatePtr>& nativeCerts) const
{
    IceInternal::fdToAddressAndPort(_stream->fd(), info->localAddress, info->localPort, info->remoteAddress,
                                    info->remotePort);
    if(_stream->fd() != INVALID_SOCKET)
    {
        info->rcvSize = IceInternal::getRecvBufferSize(_stream->fd());
        info->sndSize = IceInternal::getSendBufferSize(_stream->fd());
    }

    info->verified = _verified;

    if(_sslInitialized)
    {
        CtxtHandle* ssl = const_cast<CtxtHandle*>(&_ssl);
        PCCERT_CONTEXT cert = 0;
        PCCERT_CHAIN_CONTEXT certChain = 0;
        SECURITY_STATUS err = QueryContextAttributes(ssl, SECPKG_ATTR_REMOTE_CERT_CONTEXT, &cert);
        if(err == SEC_E_OK)
        {
            assert(cert);
            CERT_CHAIN_PARA chainP;
            memset(&chainP, 0, sizeof(chainP));
            chainP.cbSize = sizeof(chainP);

            if(CertGetCertificateChain(_engine->chainEngine(), cert, 0, 0, &chainP,
                                       CERT_CHAIN_REVOCATION_CHECK_CACHE_ONLY, 0, &certChain))
            {
                CERT_SIMPLE_CHAIN* simpleChain = certChain->rgpChain[0];
                for(DWORD i = 0; i < simpleChain->cElement; ++i)
                {
                    PCCERT_CONTEXT c = simpleChain->rgpElement[i]->pCertContext;
                    PCERT_SIGNED_CONTENT_INFO cc;

                    DWORD length = 0;
                    if(!CryptDecodeObjectEx(X509_ASN_ENCODING | PKCS_7_ASN_ENCODING, X509_CERT, c->pbCertEncoded,
                                            c->cbCertEncoded, CRYPT_DECODE_ALLOC_FLAG, 0, &cc, &length))
                    {
                        CertFreeCertificateChain(certChain);
                        CertFreeCertificateContext(cert);
                        throw SecurityException(__FILE__, __LINE__,
                                                "IceSSL: error decoding peer certificate chain:\n" +
                                                IceUtilInternal::lastErrorToString());
                    }

                    CertificatePtr certificate = ICE_MAKE_SHARED(Certificate, cc);
                    nativeCerts.push_back(certificate);
                    info->certs.push_back(certificate->encode());
                }
                CertFreeCertificateChain(certChain);
            }
            CertFreeCertificateContext(cert);
        }
        else if(err != SEC_E_NO_CREDENTIALS)
        {
            throw SecurityException(__FILE__, __LINE__, "IceSSL: error reading peer certificate:" +
                                    IceUtilInternal::lastErrorToString());
        }

        SecPkgContext_ConnectionInfo connInfo;
        if(QueryContextAttributes(ssl, SECPKG_ATTR_CONNECTION_INFO, &connInfo) == SEC_E_OK)
        {
            info->cipher = _engine->getCipherName(connInfo.aiCipher);
        }
        else
        {
            throw SecurityException(__FILE__, __LINE__, "IceSSL: error reading cipher info:" +
                                    IceUtilInternal::lastErrorToString());
        }
    }

    info->adapterName = _adapterName;
    info->incoming = _incoming;
}
Пример #5
0
void
IceSSL::SSLEngine::verifyPeerCertName(const string& address, const ConnectionInfoPtr& info)
{
    //
    // For an outgoing connection, we compare the proxy address (if any) against
    // fields in the server's certificate (if any).
    //
    if(_checkCertName && !info->certs.empty() && !address.empty())
    {
        const CertificatePtr cert = info->certs[0];

        //
        // Extract the IP addresses and the DNS names from the subject
        // alternative names.
        //
        vector<pair<int, string> > subjectAltNames = cert->getSubjectAlternativeNames();
        vector<string> ipAddresses;
        vector<string> dnsNames;
        for(vector<pair<int, string> >::const_iterator p = subjectAltNames.begin(); p != subjectAltNames.end(); ++p)
        {
            if(p->first == AltNAmeIP)
            {
                ipAddresses.push_back(IceUtilInternal::toLower(p->second));
            }
            else if(p->first == AltNameDNS)
            {
                dnsNames.push_back(IceUtilInternal::toLower(p->second));
            }
        }

        bool certNameOK = false;
        string addrLower = IceUtilInternal::toLower(address);
        bool isIpAddress = IceInternal::isIpAddress(address);

        //
        // If address is an IP address, compare it to the subject alternative names IP adddress
        //
        if(isIpAddress)
        {
            certNameOK = find(ipAddresses.begin(), ipAddresses.end(), addrLower) != ipAddresses.end();
        }
        else
        {
            //
            // If subjectAlt is empty compare it ot the subject CN, othewise
            // compare it to the to the subject alt name dnsNames
            //
            if(dnsNames.empty())
            {
                DistinguishedName d = cert->getSubjectDN();
                string dn = IceUtilInternal::toLower(string(d));
                string cn = "cn=" + addrLower;
                string::size_type pos = dn.find(cn);
                if(pos != string::npos)
                {
                    //
                    // Ensure we match the entire common name.
                    //
                    certNameOK = (pos + cn.size() == dn.size()) || (dn[pos + cn.size()] == ',');
                }
            }
            else
            {
                certNameOK = find(dnsNames.begin(), dnsNames.end(), addrLower) != dnsNames.end();
            }
        }

        if(!certNameOK)
        {
            ostringstream ostr;
            ostr << "IceSSL: certificate validation failure: "
                 << (isIpAddress ? "IP address mismatch" : "Hostname mismatch");
            string msg = ostr.str();
            if(_securityTraceLevel >= 1)
            {
                Trace out(_logger, _securityTraceCategory);
                out << msg;
            }

            if(_verifyPeer > 0)
            {
                throw SecurityException(__FILE__, __LINE__, msg);
            }
        }
    }
}
Пример #6
0
void
IceSSL::SSLEngine::verifyPeer(const string& address, const NativeConnectionInfoPtr& info, const string& desc)
{
    const CertificateVerifierPtr verifier = getCertificateVerifier();

#if !defined(ICE_USE_SECURE_TRANSPORT_IOS)
    //
    // For an outgoing connection, we compare the proxy address (if any) against
    // fields in the server's certificate (if any).
    //
    if(!info->nativeCerts.empty() && !address.empty())
    {
        const CertificatePtr cert = info->nativeCerts[0];
        //
        // Extract the IP addresses and the DNS names from the subject
        // alternative names.
        //
        vector<pair<int, string> > subjectAltNames = cert->getSubjectAlternativeNames();
        vector<string> ipAddresses;
        vector<string> dnsNames;
        for(vector<pair<int, string> >::const_iterator p = subjectAltNames.begin(); p != subjectAltNames.end(); ++p)
        {
            if(p->first == AltNAmeIP)
            {
                ipAddresses.push_back(IceUtilInternal::toLower(p->second));
            }
            else if(p->first == AltNameDNS)
            {
                dnsNames.push_back(IceUtilInternal::toLower(p->second));
            }
        }

        //
        // Compare the peer's address against the common name.
        //
        bool certNameOK = false;
        string dn;
        string addrLower = IceUtilInternal::toLower(address);
        {
            DistinguishedName d = cert->getSubjectDN();
            dn = IceUtilInternal::toLower(string(d));
            string cn = "cn=" + addrLower;
            string::size_type pos = dn.find(cn);
            if(pos != string::npos)
            {
                //
                // Ensure we match the entire common name.
                //
                certNameOK = (pos + cn.size() == dn.size()) || (dn[pos + cn.size()] == ',');
            }
        }

        //
        // Compare the peer's address against the dnsName and ipAddress
        // values in the subject alternative name.
        //
        if(!certNameOK)
        {
            certNameOK = find(ipAddresses.begin(), ipAddresses.end(), addrLower) != ipAddresses.end();
        }
        if(!certNameOK)
        {
            certNameOK = find(dnsNames.begin(), dnsNames.end(), addrLower) != dnsNames.end();
        }

        //
        // Log a message if the name comparison fails. If CheckCertName is defined,
        // we also raise an exception to abort the connection. Don't log a message if
        // CheckCertName is not defined and a verifier is present.
        //
        if(!certNameOK && (_checkCertName || (_securityTraceLevel >= 1 && !verifier)))
        {
            ostringstream ostr;
            ostr << "IceSSL: ";
            if(!_checkCertName)
            {
                ostr << "ignoring ";
            }
            ostr << "certificate validation failure:\npeer certificate does not have `" << address
                 << "' as its commonName or in its subjectAltName extension";
            if(!dn.empty())
            {
                ostr << "\nSubject DN: " << dn;
            }
            if(!dnsNames.empty())
            {
                ostr << "\nDNS names found in certificate: ";
                for(vector<string>::const_iterator p = dnsNames.begin(); p != dnsNames.end(); ++p)
                {
                    if(p != dnsNames.begin())
                    {
                        ostr << ", ";
                    }
                    ostr << *p;
                }
            }
            if(!ipAddresses.empty())
            {
                ostr << "\nIP addresses found in certificate: ";
                for(vector<string>::const_iterator p = ipAddresses.begin(); p != ipAddresses.end(); ++p)
                {
                    if(p != ipAddresses.begin())
                    {
                        ostr << ", ";
                    }
                    ostr << *p;
                }
            }
            string msg = ostr.str();
            if(_securityTraceLevel >= 1)
            {
                Trace out(_logger, _securityTraceCategory);
                out << msg;
            }
            if(_checkCertName)
            {
                SecurityException ex(__FILE__, __LINE__);
                ex.reason = msg;
                throw ex;
            }
        }
    }
#endif

    if(_verifyDepthMax > 0 && static_cast<int>(info->certs.size()) > _verifyDepthMax)
    {
        ostringstream ostr;
        ostr << (info->incoming ? "incoming" : "outgoing") << " connection rejected:\n"
             << "length of peer's certificate chain (" << info->certs.size() << ") exceeds maximum of "
             << _verifyDepthMax;
        string msg = ostr.str();
        if(_securityTraceLevel >= 1)
        {
            _logger->trace(_securityTraceCategory, msg + "\n" + desc);
        }
        SecurityException ex(__FILE__, __LINE__);
        ex.reason = msg;
        throw ex;
    }

    if(!_trustManager->verify(info, desc))
    {
        string msg = string(info->incoming ? "incoming" : "outgoing") + " connection rejected by trust manager";
        if(_securityTraceLevel >= 1)
        {
            _logger->trace(_securityTraceCategory, msg + "\n" + desc);
        }
        SecurityException ex(__FILE__, __LINE__);
        ex.reason = msg;
        throw ex;
    }

    if(verifier && !verifier->verify(info))
    {
        string msg = string(info->incoming ? "incoming" : "outgoing") + " connection rejected by certificate verifier";
        if(_securityTraceLevel >= 1)
        {
            _logger->trace(_securityTraceCategory, msg + "\n" + desc);
        }
        SecurityException ex(__FILE__, __LINE__);
        ex.reason = msg;
        throw ex;
    }
}