Openssl::Ssl::Sslerror (Ssl_Connect Returned=1 Errno=0 State=Sslv3 Read Server Certificate B: Certificate Verify Failed) While Connecting to Paypal

SSL_connect returned=1 errno=0 state=SSLv3 read server certificate B: certificate verify failed MAC

  1. Download http://curl.haxx.se/ca/ca-bundle.crt
  2. Copy certificate into /usr/local/etc/openssl/certs/
  3. Make omniauth.rb look like this:

    options = {
    scope: "email",
    :prompt => "select_account",
    access_type: 'offline',
    :client_options => {
    :ssl => {
    :ca_file => "/usr/local/etc/openssl/certs/ca-bundle.crt",
    :ca_path => "/usr/local/etc/openssl/certs"
    }
    }
    }

    Rails.application.config.middleware.use OmniAuth::Builder do
    provider :google_oauth2, Rails.application.secrets.client_id, Rails.application.secrets.client_secret, options
    end

Heroku Rails Net::HTTP: OpenSSL::SSL::SSLError: SSL_connect returned=1 errno=0 state=SSLv3 read server certificate B: certificate verify failed

Heroku can't verify your server's certificate is validly signed by a CA root it recognizes. This can be because either:

  1. Your cert isn't signed by a CA or intermediate (ie, self-signed)
  2. Your cert is signed by a CA that Heroku doesn't know about (unlikely)
  3. The API server isn't providing the correct intermediate certs to help Heroku connect it to a valid CA root. (likely)

Try openssl s_client -showcerts -connect your-api-host.com:443 from your shell. You should see something like:

depth=3 C = SE, O = AddTrust AB, OU = AddTrust External TTP Network, CN = AddTrust External CA Root
verify return:1
depth=2 C = GB, ST = Greater Manchester, L = Salford, O = COMODO CA Limited, CN = COMODO RSA Certification Authority
verify return:1
depth=1 C = GB, ST = Greater Manchester, L = Salford, O = COMODO CA Limited, CN = COMODO RSA Domain Validation Secure Server CA
verify return:1
depth=0 OU = Domain Control Validated, OU = PositiveSSL, CN = www.coffeepowered.net
verify return:1

You're specifically looking to make sure that all certs in the chain return verify return: 1. If this works from your shell, then your machine likely has root certs installed that your Heroku instance doesn't.

Without knowing exactly what certs your API server is returning, it's hard to answer this definitively, but you probably need to be serving an intermediate cert bundle along with the SSL cert itself. This intermediate cert bundle will be provided by your SSL certificate signer, and can be provided in Apache via SSLCertificateChainFile, or in nginx by concatening the intermediates with your cert (per this documentation).

If you can't alter the configuration of the API server, then your "Manually overriding the certificate file location" solution is probably very close to correct (it's the same thing as the server providing the intermediate cert, except the client does it), but you are likely not providing the correct certificate chain bundle for your API server's certificates. Make sure that you have the correct intermediate certificate chain provided to OpenSSL, and it should work as desired.

OpenSSL::SSL::SSLError: SSL_connect returned=1 errno=0 state=SSLv3 read server certificate B: certificate verify failed

That sometimes happens if the default 'OpenSSL directory' is not set correctly with the native OpenSSL library. open-uri uses OpenSSL::X509::Store#set_default_paths in order to tell OpenSSL to look in the OpenSSL directory for the file that contains the trusted root certificates that OpenSSL trusts by default.

In your case, this lookup fails. You can make it succeed by setting an environment variable that overrides the default setting and tells OpenSSL to look in that directory instead:

export SSL_CERT_FILE=/etc/pki/tls/cert.pem

That's the default location for the root CA bundle on my Fedora 16 64 bit, other popular locations are /etc/ssl/ca-bundle.crt etc. In your case, the OpenSSL library used by RVM is located in $rvm_path/usr, so you should look around there for a suitable candidate for the default root CA file. After the environment variable is set correctly, the call to open-uri will succeed.

To make the environment variable permanent, use the usual ways such as defining the export in .bashrc, /etc/profile or whatever fits best in your situation.



Related Topics



Leave a reply



Submit