OpenSSL::SSL::SSLError while testing the net/smtp library - ruby

I am trying to send emails using the net/smtp library but I receive the following error message:
SSL_connect returned=1 errno=0 state=unknown state: unknown protocol (OpenSSL::SSL::SSLError)
The code I am using is an extract from Peter Cooper's Beginning Ruby book, modified to use SSL, as required by yahoo servers:
require 'net/smtp'
message = %q{
From: Private Person <me#privacy.net>
To: myself <username#yahoo.com>
Subject: SMTP e-mail test
This is a test e-mail message.
}
smtp = Net::SMTP.new('smtp.mail.yahoo.com', 587)
smtp.enable_ssl
smtp.start('example.org', 'username#yahoo.com', 'password', :login) do |s|
s.send_message message, 'me#privacy.net', 'username#yahoo.com'
end
I tested the above code with Ruby 2.3.1 and Ruby 2.5.1 but I keep receiving the same error message.

By using Net::SMTP#enable_ssl (which is an alias to Net::SMTP#enable_tls), you are instructing the Ruby SMTP client to open a TLS tunnel as the very first step after connecting to the server. This requires the server to also support this on the used server port.
With Yahoos SMTP servers, they support this mode on port 465. With many other providers, you will see that they only support opportunistic TLS on port 587.
What happens there is that the client first starts with plain text SMTP and then negotiates with the server whether they support to update the connection to a TLS tunnel by using the STARTTLS command.
With net/smtp in Ruby, you can use Net::SMTP#enable_starttls instead.
If you are not sure of the server supports STARTTLS and you want to gracefully fallbvack to plaintext transfer of your password and the email to the server, you can also use Net::SMTP#enable_starttls_auto.
Thus, with Yahoo, you have two options:
you can use Net::SMTP#enable_tls on port 465
or you can use Net::SMTP#enable_starttls on port 587

Related

Not able to make connection with rest API of Salesforce using Faraday gem

Why we are getting this error when trying to make connection with Salesforce rest API through Faraday gem using ROR?
Faraday::Error::ConnectionFailed:
SSL_connect returned=1 errno=0 state=SSLv3 read server certificate B: certificate verify failed
Faraday requires a valid root certificate to establish a connection.
If you're on a Windows machine, install the certificate with these instructions: https://gist.github.com/867550
For Mac, perform the following:
sudo port install curl-ca-bundle
Next, in your Faraday request, include this line immediately above where you actually send your request (e.g. https.request_get('/foo')):
https.ca_file = '/opt/local/share/curl/curl-ca-bundle.crt'
This will tell the http object Faraday uses to include the certificate in its request. If your system spits out an error, you may have to adjust the inclusion based on the file's location in your system.
All in all, your request will look something like this:
require 'net/https'
https = Net::HTTP.new('encrypted.google.com', 443)
https.use_ssl = true
https.ca_file = '/opt/local/share/curl/curl-ca-bundle.crt' if File.exists('/opt/local/share/curl/curl-ca-bundle.crt') # Mac OS X
https.request_get('/foo')

How do I get the peer_cert for a https request using Ruby?

How can I get access to the peer_cert when making a SSL request?
I've updated my ruby ssl certs with rvm osx-ssl-certs update all
What I'm trying is
require 'httpclient'
c = HTTPClient.new
r = c.get( "https://gmail.com" )
puts r.peer_cert
But I keep getting either
OpenSSL::SSL::SSLError: SSL_connect returned=1 errno=0 state=SSLv3 read server hello A: sslv3 alert handshake failure
or
OpenSSL::SSL::SSLError: hostname "gmail.com" does not match the server certificate
What does the first error mean? Is there a way to get it to set the property version automatically?
I'm able to load up the data on the URL using HTTParty and Farday, but in that case I don't know here to access the actual SSL cert that was used.
You can't get the peer cert until you succesfully make the connection, and you're getting an error in succesfully making the connection. Have you upgraded to the latest httpclient? Many servers changed their SSL handshake configurations in response to recent vulnerabilties, and a new httpclient was released in response to same, which perhaps is neccesary to be compatible with new server configurations.

Apache WEB server still responds to requests used SSLv2 protocol. When SSLv2 protocol was disabled

Here is my configuration ...
SSLProtocol -ALL +SSLv3 TLSv1
but Apache WEB server still responds to requests used SSLv2 protocol.
The following is my test log.( Sorry, I cannot attach image because my reputation is under the 10 )
SSLv2 Record Layer: Server Hello[Version: SSL 2.0 (0x0002)]Length: 955Handshake Message Type: Server Hello (4)Session ID Hit: FalseCertificate Type X.509 Certificate (1)Version: SSL 2.0 (0x0002)Certificate Length: 928Cipher Spec Length: 0Connection ID Length: 16Certificate blah~blah~Connection ID
thank you
The configuration should set as:
SSLProtocol= "ALL:-SSLv2"
If that does not work also set the cipher suite as:
SSLCipherSuite="ALL:+HIGH:+MEDIUM:+LOW:!SSLv2"

Connecting using https to a server with a certificate signed by a CA I created

I have a test environment that uses Ruby to drive a server over an https connection. Since the latest versions of Ruby refuse to connect to an https server with an invalid certificate (see this earlier question of mine) and I would like to start using a newer version of Ruby, I am trying to set up a valid certificate.
I have created a CA certificate to use (there are multiple servers being tested so this seems the easier way), and have successfully used it to sign a new certificate which has been installed on a server and is being used. I have added the CA certificate to the browser store and it (the browser) will now connect to the server without complaint. So I am confident my certificates are valid and set up correctly.
I know that Ruby does not use the same store as the browser. I have used the CA file available here to test connecting to other (public) servers (set using the Net::HTTP#ca_file= method) and this also works.
What I cannot get to work is Ruby connecting to my server using my certificate. I have tried various ways of pointing it at my certificate (including adding my certificate to the file linked above) and it always gives the same error:
SSL_connect SYSCALL returned=5 errno=0 state=SSLv2/v3 read server hello A (OpenSSL::SSL::SSLError)
What do I have to do to convince Ruby to accept my certificate and connect to my server?
The code I am using is:
require 'net/https'
uri = URI.parse("https://hostname/index.html")
http = Net::HTTP.new(uri.host, uri.port)
http.use_ssl = true
http.verify_mode = OpenSSL::SSL::VERIFY_PEER
http.ca_file = "My CA cert file"
request = Net::HTTP::Get.new(uri.path)
response = http.request(request)
I'm assuming this is wrong somehow. What I want to know is, what should I do to use my CA certificate?
I assume that your Tomcat doesn't like the protocol version that Ruby tries to negotiate. Ruby uses SSLv23 by default, but I've heard other cases where this was a problem for Java-based web servers. The error message you are getting indicates that the handshake fails while setting up the connection and trying to read the server's response. Try adding either
http.ssl_version = :TLSv1
or
http.ssl_version = :SSLv3
and see if that already helps.
If this does not fix the problem yet, it would be very interesting to see why your server rejects the connection attempt. Try running your Tomcat with -Djavax.net.debug=ssl and please post the relevant parts (connection information, exception stacktrace) as to why the attempt fails.
I am using ruby 1.9.3 and faced the same error while using nokogiri to parse some secure urls.
OpenSSL::SSL::SSLError: SSL_connect returned=1 errno=0 state=SSLv2/v3 read server hello A: (null)
The above answer provided by emboss is correct but make sure the ssl error generated is this one that is mentioned above. I have followed the same and found a solution like this mentioned below.
uri = URI(url)
http = Net::HTTP.new(uri.host, uri.port)
http.use_ssl = true
http.ssl_version = :SSLv3
http.verify_mode = OpenSSL::SSL::VERIFY_PEER
response = http.get(url)
now the response is having the correct html parsed for the secured url that is passed to the codes in the url .
Make sure that the your certificate file is in PEM format, not CRT (so the documentation for Net::HTTP in Ruby 1.9.3 says).
Update it looks like the documentation is not up to date, Ruby 1.9.3 will accept any kind of certificate.

(Ruby) Getting Net::SMTP working with Gmail...?

Does anyone have any quality (and up-to-date) information regarding sending mail via Gmail using Ruby's Net::SMTP? I've seen several examples -- most dating from 2007 to mid-2008 and none of them work for me. I need more current examples that use the most recent 1.8.7 release. I'd also appreciate if the documentation didn't only cover simple examples that no one ever really uses.
Currently I'm receiving an error:
SSL_connect returned=1 errno=0 state=SSLv2/v3 read server hello A: unknown protocol
I'm not terribly familiar with SSL as regards the SMTP protocol, so this is all lost on me. Unfortunately the Net::SMTP documentation only covers the bases and doesn't provide a full list of the various potential OpenSSL::SSL contexts either so I can't try various ones.
Anyway, if anyone has any quality info on getting this to work with Gmail it would be most appreciated.
Best.
Actually the below works for gmail without a plugin or a gem, at least with Ruby 1.9.1p376, but good luck finding documentation that'll tell you so:
require 'net/smtp'
msg = "Subject: Hi There!\n\nThis works, and this part is in the body."
smtp = Net::SMTP.new 'smtp.gmail.com', 587
smtp.enable_starttls
smtp.start(YourDomain, YourAccountName, YourPassword, :login) do
smtp.send_message(msg, FromAddress, ToAddress)
end
YourAccountName looks like you#example.com & YourDomain can probably be anything you like, but I use the actual domain name.
I actually just got this working. Wrote a quick script to test it.
I was getting a different error than you were (requiring STARTTLS), I also found I had to use port 587 instead of 465.
I found the trick to get it working in a Rails plugin I found. (agilewebdevelopment.com/plugins/net_smtp_tls_support)
if you 'eval' this file (it adds tls support to the standard Net::SMTP library):
http://happiness-is-slavery.net/wp-content/rails-plugins/smtp_add_tls_support/lib/smtp_add_tls_support.rb
then run 'Net::SMTP.enable_tls()'
everything seems to work fine.
Here's my code:
require 'rubygems'
require 'net/smtp'
eval File.read("smtp_tls.rb")
Net::SMTP.enable_tls()
FROM_EMAIL = "REMOVED"
PASSWORD = "REMOVED"
TO_EMAIL = "REMOVED"
msgstr = <<END_OF_MESSAGE
From: Your Name <#{FROM_EMAIL}>
To: my phone <#{TO_EMAIL}>
Subject: text message
Date: Sat, 23 Jun 2001 16:26:43 +0900
Message-Id: <unique.message.id.string#example.com>
This is a test message.
END_OF_MESSAGE
Net::SMTP.start('smtp.gmail.com', 587, 'gmail.com',
FROM_EMAIL, PASSWORD, :plain) do |smtp|
smtp.send_message msgstr, FROM_EMAIL, TO_EMAIL
end
obviously, i downloaded the above mentioned file to the same directory and named it 'smtp_tls.rb'
Hope this helps!
Are you connecting to smtp.gmail.com port 465 I am assuming?
.
openssl s_client -connect smtp.gmail.com:587
CONNECTED(00000003)
8298:error:140770FC:SSL routines:SSL23_GET_SERVER_HELLO:unknown protocol:s23_clnt.c:601:
The error looks very similar to yours. The following command does work:
openssl s_client -starttls smtp -connect smtp.gmail.com:587
So I think what is happening is that you do not have STARTTLS support enabled. I am not sure how to do it in ruby buy what I did find out is that the action_mailer_tls plugin allows this by patching Net::SMTP. As of Ruby 1.8.7, Net::SMTP has this support built-in.
If you are using Ruby < 1.8.7 here is the patch.
You also need to have two newline characters between the subject and the body of the message. Otherwise, only the subject will be transmitted, and the message body will be left blank.
msg = "Subject: My Subject Goes Here\n\nMy message goes here"

Resources