Beispiel #1
0
 bool SSLManager::_setupPEM(const std::string& keyFile , const std::string& password) {
     _password = password;
     
     if ( SSL_CTX_use_certificate_chain_file( _context , keyFile.c_str() ) != 1 ) {
         error() << "cannot read certificate file: " << keyFile << ' ' <<
             _getSSLErrorMessage(ERR_get_error()) << endl;
         return false;
     }
     
     // If password is empty, use default OpenSSL callback, which uses the terminal
     // to securely request the password interactively from the user.
     if (!password.empty()) {
         SSL_CTX_set_default_passwd_cb_userdata( _context , this );
         SSL_CTX_set_default_passwd_cb( _context, &SSLManager::password_cb );
     }
     
     if ( SSL_CTX_use_PrivateKey_file( _context , keyFile.c_str() , SSL_FILETYPE_PEM ) != 1 ) {
         error() << "cannot read key file: " << keyFile << ' ' <<
             _getSSLErrorMessage(ERR_get_error()) << endl;
         return false;
     }
     
     // Verify that the certificate and the key go together.
     if (SSL_CTX_check_private_key(_context) != 1) {
         error() << "SSL certificate validation: " << _getSSLErrorMessage(ERR_get_error()) 
                 << endl;
         return false;
     }
     return true;
 }
Beispiel #2
0
 bool SSLManager::_setupPEM(const std::string& keyFile , const std::string& password) {
     _password = password;
     
     if ( SSL_CTX_use_certificate_chain_file( _context , keyFile.c_str() ) != 1 ) {
         error() << "cannot read certificate file: " << keyFile << ' ' <<
             _getSSLErrorMessage(ERR_get_error()) << endl;
         return false;
     }
     
     SSL_CTX_set_default_passwd_cb_userdata( _context , this );
     SSL_CTX_set_default_passwd_cb( _context, &SSLManager::password_cb );
     
     if ( SSL_CTX_use_PrivateKey_file( _context , keyFile.c_str() , SSL_FILETYPE_PEM ) != 1 ) {
         error() << "cannot read key file: " << keyFile << ' ' <<
             _getSSLErrorMessage(ERR_get_error()) << endl;
         return false;
     }
     
     // Verify that the certificate and the key go together.
     if (SSL_CTX_check_private_key(_context) != 1) {
         error() << "SSL certificate validation: " << _getSSLErrorMessage(ERR_get_error()) 
                 << endl;
         return false;
     }
     return true;
 }
Beispiel #3
0
    SSL* SSLManager::_secure(int fd) {
        // This just ensures that SSL multithreading support is set up for this thread,
        // if it's not already.
        SSLThreadInfo::get();

        SSL * ssl = SSL_new(_context);
        massert(15861,
                _getSSLErrorMessage(ERR_get_error()),
                ssl);
        
        int status = SSL_set_fd( ssl , fd );
        massert(16510,
                _getSSLErrorMessage(ERR_get_error()), 
                status == 1);

        return ssl;
    }
Beispiel #4
0
    SSLManager::SSLManager(const Params& params) :
        _validateCertificates(false),
        _weakValidation(params.weakCertificateValidation) {

        SSL_library_init();
        SSL_load_error_strings();
        ERR_load_crypto_strings();

        if (params.fipsMode) {
            _setupFIPS();
        }

        // Add all digests and ciphers to OpenSSL's internal table
        // so that encryption/decryption is backwards compatible
        OpenSSL_add_all_algorithms();

        _context = SSL_CTX_new(SSLv23_method());
        massert(15864,
                mongoutils::str::stream() << "can't create SSL Context: " <<
                _getSSLErrorMessage(ERR_get_error()),
                _context);

        // Activate all bug workaround options, to support buggy client SSL's.
        SSL_CTX_set_options(_context, SSL_OP_ALL);

        // If renegotiation is needed, don't return from recv() or send() until it's successful.
        // Note: this is for blocking sockets only.
        SSL_CTX_set_mode(_context, SSL_MODE_AUTO_RETRY);

        // Set context within which session can be reused
        int status = SSL_CTX_set_session_id_context(
            _context,
            static_cast<unsigned char*>(static_cast<void*>(&_context)),
            sizeof(_context));
        if (!status) {
            uasserted(16768,"ssl initialization problem");
        }

        SSLThreadInfo::init();
        SSLThreadInfo::get();

        if (!params.pemfile.empty()) {
            if (!_setupPEM(params.pemfile, params.pempwd)) {
                uasserted(16562, "ssl initialization problem"); 
            }
        }
        if (!params.cafile.empty()) {
            // Set up certificate validation with a certificate authority
            if (!_setupCA(params.cafile)) {
                uasserted(16563, "ssl initialization problem"); 
            }
        }
        if (!params.crlfile.empty()) {
            if (!_setupCRL(params.crlfile)) {
                uasserted(16582, "ssl initialization problem");
            }
        }
    }
Beispiel #5
0
 void SSLManager::_setupFIPS() {
     // Turn on FIPS mode if requested.
     int status = FIPS_mode_set(1);
     if (!status) {
         error() << "can't activate FIPS mode: " << 
             _getSSLErrorMessage(ERR_get_error()) << endl;
         fassertFailed(16703);
     }
     log() << "FIPS 140-2 mode activated" << endl;
 }
Beispiel #6
0
 bool SSLManager::_setupCA(const std::string& caFile) {
     // Load trusted CA
     if (SSL_CTX_load_verify_locations(_context, caFile.c_str(), NULL) != 1) {
         error() << "cannot read certificate authority file: " << caFile << " " <<
             _getSSLErrorMessage(ERR_get_error()) << endl;
         return false;
     }
     // Set SSL to require peer (client) certificate verification
     // if a certificate is presented
     SSL_CTX_set_verify(_context, SSL_VERIFY_PEER, &SSLManager::verify_cb);
     _validateCertificates = true;
     return true;
 }
Beispiel #7
0
 void SSLManager::_setupFIPS() {
     // Turn on FIPS mode if requested.
     scoped_lock lk(fipsMtx);
     if (fipsActivated) {
         return;
     }
     int status = FIPS_mode_set(1);
     if (!status) {
         error() << "can't activate FIPS mode: " << 
             _getSSLErrorMessage(ERR_get_error()) << endl;
         fassertFailed(16703);
     }
     log() << "FIPS 140-2 mode activated" << endl;
     fipsActivated = true;
 }
Beispiel #8
0
    bool SSLManager::_setupCRL(const std::string& crlFile) {
        X509_STORE *store = SSL_CTX_get_cert_store(_context);
        fassert(16583, store);
        
        X509_STORE_set_flags(store, X509_V_FLAG_CRL_CHECK);
        X509_LOOKUP *lookup = X509_STORE_add_lookup(store, X509_LOOKUP_file());
        fassert(16584, lookup);

        int status = X509_load_crl_file(lookup, crlFile.c_str(), X509_FILETYPE_PEM);
        if (status == 0) {
            error() << "cannot read CRL file: " << crlFile << ' ' <<
                _getSSLErrorMessage(ERR_get_error()) << endl;
            return false;
        }
        log() << "ssl imported " << status << " revoked certificate" << 
            ((status == 1) ? "" : "s") << " from the revocation list." << 
            endl;
        return true;
    }
Beispiel #9
0
    void SSLManager::_handleSSLError(int code) {
        switch (code) {
        case SSL_ERROR_WANT_READ:
        case SSL_ERROR_WANT_WRITE:
            // should not happen because we turned on AUTO_RETRY
            // However, it turns out this CAN happen during a connect, if the other side
            // accepts the socket connection but fails to do the SSL handshake in a timely
            // manner.
            error() << "SSL error: " << code << ", possibly timed out during connect" << endl;
            throw SocketException(SocketException::CONNECT_ERROR, "");
            break;

        case SSL_ERROR_SYSCALL:
            if (code < 0) {
                error() << "socket error: " << errnoWithDescription() << endl;
                throw SocketException(SocketException::CONNECT_ERROR, "");
            }
            error() << "could not negotiate SSL connection: EOF detected" << endl;
            throw SocketException(SocketException::CONNECT_ERROR, "");
            break;

        case SSL_ERROR_SSL:
        {
            int ret = ERR_get_error();
            error() << _getSSLErrorMessage(ret) << endl;
            throw SocketException(SocketException::CONNECT_ERROR, "");
            break;
        }
        case SSL_ERROR_ZERO_RETURN:
            error() << "could not negotiate SSL connection: EOF detected" << endl;
            throw SocketException(SocketException::CONNECT_ERROR, "");
            break;
        
        default:
            error() << "unrecognized SSL error" << endl;
            throw SocketException(SocketException::CONNECT_ERROR, "");
            break;
        }
    }
Beispiel #10
0
    void SSLManager::_handleSSLError(int code) {
        switch (code) {
        case SSL_ERROR_WANT_READ:
        case SSL_ERROR_WANT_WRITE:
            // should not happen because we turned on AUTO_RETRY
            error() << "SSL error: " << code << endl;
            fassertFailed( 16676 );
            break;

        case SSL_ERROR_SYSCALL:
            if (code < 0) {
                error() << "socket error: " << errnoWithDescription() << endl;
                throw SocketException(SocketException::CONNECT_ERROR, "");
            }
            error() << "could not negotiate SSL connection: EOF detected" << endl;
            throw SocketException(SocketException::CONNECT_ERROR, "");
            break;

        case SSL_ERROR_SSL:
        {
            int ret = ERR_get_error();
            error() << _getSSLErrorMessage(ret) << endl;
            throw SocketException(SocketException::CONNECT_ERROR, "");
            break;
        }
        case SSL_ERROR_ZERO_RETURN:
            error() << "could not negotiate SSL connection: EOF detected" << endl;
            throw SocketException(SocketException::CONNECT_ERROR, "");
            break;
        
        default:
            error() << "unrecognized SSL error" << endl;
            throw SocketException(SocketException::CONNECT_ERROR, "");
            break;
        }
    }