ssmtp via Gmail -- SSL error?

I upgraded four FreeBSD servers from 9.3 to 10.0 a couple of weeks ago -- using freebsd-update() for the first time. All four servers had been configured identically with ssmtp as a sendmail() replacement. The upgrading went relatively well, however I'm now experiencing a weird side effect: ssmtp is broken on two out of the four servers.

On all servers I'm using the base SSL, not from ports, 1.0.1-e, patched via the 10.0-RELEASE branch. We're using Gmail as our mailhub, over port 465. This setup has worked fine for several years, and two of the four machines continue to function without issue. On the problem servers, running mail or ssmtp from the command line generates the following error:
Code:
SSL_connect: Connection reset by peer
ssmtp: Cannot open smtp.gmail.com:465

My ssmtp.conf is as follows:
Code:
root=mygmailaddress@mydomain.tld
mailhub=smtp.gmail.com:465
rewriteDomain=mydomain.tld
hostname=myFQDN
FromLineOverride=YES
UseTLS=YES
AuthUser=myusername@mydomain.tld
AuthPass=mypassword

and revaliases looks like this:
Code:
root:mygmailaddress@mydomain.tld:smtp.gmail.com:465

I've tried the above with port 587 instead of 465 and a UseSTARTTLS=YES line, which generates a different error (it times out). But since the above IDENTICAL configuration files work on two of the servers, and ssmtp is so simple to configure, I'm assuming this is an OpenSSL error. And I'm a total SSL noob, but I ran some OpenSSL tests and it looks like maybe OpenSSL can't properly auto-negotiate the right protocol (SSLv2/SSLv3/TLS1 etc.)? If I denote the protocol/cipher set (-ssl2, -ssl3, -tls1) as a switch to the openssl command, things look pretty normal, unless I specify TLS1_2, which fails. If I don't specify anything it sort of throws its hands up in the air; so it looks like it might be defaulting to TLS1_2:
Code:
# openssl s_client -connect smtp.gmail.com:465 
CONNECTED(00000003)
write:errno=54
---
no peer certificate available
---
No client certificate CA names sent
---
SSL handshake has read 0 bytes and written 321 bytes
---
New, (NONE), Cipher is (NONE)
Secure Renegotiation IS NOT supported
Compression: NONE
Expansion: NONE
---

Included below are examples of somewhat more successful connection attempts using SSLv3 and TLS1. Any help or pointers much appreciated -- I'm clearly out of my depth here!

Code:
root@willis:~ # openssl s_client -ssl3 -connect smtp.gmail.com:465
CONNECTED(00000003)
depth=2 C = US, O = GeoTrust Inc., CN = GeoTrust Global CA
verify error:num=20:unable to get local issuer certificate
verify return:0
---
Certificate chain
 0 s:/C=US/ST=California/L=Mountain View/O=Google Inc/CN=smtp.gmail.com
   i:/C=US/O=Google Inc/CN=Google Internet Authority G2
 1 s:/C=US/O=Google Inc/CN=Google Internet Authority G2
   i:/C=US/O=GeoTrust Inc./CN=GeoTrust Global CA
 2 s:/C=US/O=GeoTrust Inc./CN=GeoTrust Global CA
   i:/C=US/O=Equifax/OU=Equifax Secure Certificate Authority
---
Server certificate
-----BEGIN CERTIFICATE-----
[snip]
----END CERTIFICATE-----
subject=/C=US/ST=California/L=Mountain View/O=Google Inc/CN=smtp.gmail.com
issuer=/C=US/O=Google Inc/CN=Google Internet Authority G2
---
No client certificate CA names sent
---
SSL handshake has read 3598 bytes and written 298 bytes
---
New, TLSv1/SSLv3, Cipher is ECDHE-RSA-RC4-SHA
Server public key is 2048 bit
Secure Renegotiation IS supported
Compression: NONE
Expansion: NONE
SSL-Session:
    Protocol  : SSLv3
    Cipher    : ECDHE-RSA-RC4-SHA
    Session-ID: 83A982D3A2063692B5F5612CC7CC67CCE682BAC2D2332A1058C24AAF4EF0A4E3
    Session-ID-ctx: 
    Master-Key: 4A797541813B43CC9FAF0F1EA5B9F6EFDE6165D755A524731571325D79952C610F05F6CAA4B9EB65074F232486EF7127
    Key-Arg   : None
    PSK identity: None
    PSK identity hint: None
    SRP username: None
    Start Time: 1406172436
    Timeout   : 7200 (sec)
    Verify return code: 20 (unable to get local issuer certificate)
---
220 mx.google.com ESMTP r3sm5317269pdd.8 - gsmtp

Code:
root@willis:~ # openssl s_client -tls1 -connect smtp.gmail.com:465
CONNECTED(00000003)
depth=2 C = US, O = GeoTrust Inc., CN = GeoTrust Global CA
verify error:num=20:unable to get local issuer certificate
verify return:0
---
Certificate chain
 0 s:/C=US/ST=California/L=Mountain View/O=Google Inc/CN=smtp.gmail.com
   i:/C=US/O=Google Inc/CN=Google Internet Authority G2
 1 s:/C=US/O=Google Inc/CN=Google Internet Authority G2
   i:/C=US/O=GeoTrust Inc./CN=GeoTrust Global CA
 2 s:/C=US/O=GeoTrust Inc./CN=GeoTrust Global CA
   i:/C=US/O=Equifax/OU=Equifax Secure Certificate Authority
---
Server certificate
-----BEGIN CERTIFICATE-----
[snip]
-----END CERTIFICATE-----
subject=/C=US/ST=California/L=Mountain View/O=Google Inc/CN=smtp.gmail.com
issuer=/C=US/O=Google Inc/CN=Google Internet Authority G2
---
No client certificate CA names sent
---
SSL handshake has read 3733 bytes and written 349 bytes
---
New, TLSv1/SSLv3, Cipher is ECDHE-RSA-RC4-SHA
Server public key is 2048 bit
Secure Renegotiation IS supported
Compression: NONE
Expansion: NONE
SSL-Session:
    Protocol  : TLSv1
    Cipher    : ECDHE-RSA-RC4-SHA
    Session-ID: BBEE129FA97BD020C9D7E341E76139F8AE7EF0090E261E7CF6A0A75F43905785
    Session-ID-ctx: 
    Master-Key: F5B4EA3707DE668ED6CBB08E58CE38EE9D818F54740FF6E8725BEE8F00428735F7905C6DA970B954C8CE559ADB04FB79
    Key-Arg   : None
    PSK identity: None
    PSK identity hint: None
    SRP username: None
    TLS session ticket lifetime hint: 100800 (seconds)
    TLS session ticket:
    0000 - 13 59 0c e8 14 55 eb 25-c7 f7 ea db b9 d1 dd 79   .Y...U.%.......y
    0010 - a9 ae 24 d1 61 55 dd 4f-25 a0 38 2a 0a 29 57 58   ..$.aU.O%.8*.)WX
    0020 - 5d 6c 3d 0c 5a 44 5b 81-d6 c8 8b 98 82 0d ae 25   ]l=.ZD[........%
    0030 - e4 76 10 0a 67 a1 77 18-15 77 69 a1 5b 7a 2c bb   .v..g.w..wi.[z,.
    0040 - 6e 17 42 74 4e 1a 5b 5d-a7 80 0e 57 68 35 24 a0   n.BtN.[]...Wh5$.
    0050 - 7c c2 35 c7 5b 76 f7 7d-1e 14 47 82 4c 3c f5 d8   |.5.[v.}..G.L<..
    0060 - d0 23 69 3b 79 b9 af cb-0f 26 e3 01 d6 c4 49 29   .#i;y....&....I)
    0070 - 66 5e 05 52 c9 b4 4f 7a-b5 ca d4 fd e5 b1 80 ac   f^.R..Oz........
    0080 - c8 12 63 ab 44 e9 25 1c-2c 19 eb ba 71 ae 65 7c   ..c.D.%.,...q.e|
    0090 - c8 04 13 bd 58 4c 87 6e-c6 e1 b4 e4 af bb 31 9e   ....XL.n......1.
    00a0 - bf d6 fb c0                                       ....

    Start Time: 1406173856
    Timeout   : 7200 (sec)
    Verify return code: 20 (unable to get local issuer certificate)
---
220 mx.google.com ESMTP pp2sm5362754pdb.59 - gsmtp
 
I think this
Code:
AuthUser=mygmailaddress@mydomain.tld
AuthPass=mypassword
should be this
Code:
AuthUser=mygmailaddress
AuthPass=mypassword
 
Thanks, but Gmail does want the entire email address as the username. Maybe I've written it misleadingly: Google hosts our email, so if we're at example.org, then our Gmail addresses are, e.g. admin@example.org, john@example.org. So in the ssmtp file, it's:
Code:
AuthUser=admin@example.org
AuthPass=<password>

I will correct the above post accordingly.
 
I only mentioned that because my ssmtp setup with Google as mailhost only needed the username bit before the @domain, although it was an @gmail.com address.

If I run your first command I get a successful connection.
Code:
 openssl s_client -connect smtp.gmail.com:465
CONNECTED(00000003)
depth=2 /C=US/O=GeoTrust Inc./CN=GeoTrust Global CA
verify error:num=20:unable to get local issuer certificate
verify return:0
---
Certificate chain
 0 s:/C=US/ST=California/L=Mountain View/O=Google Inc/CN=smtp.gmail.com
   i:/C=US/O=Google Inc/CN=Google Internet Authority G2
 1 s:/C=US/O=Google Inc/CN=Google Internet Authority G2
   i:/C=US/O=GeoTrust Inc./CN=GeoTrust Global CA
 2 s:/C=US/O=GeoTrust Inc./CN=GeoTrust Global CA
   i:/C=US/O=Equifax/OU=Equifax Secure Certificate Authority
---
Server certificate
-----BEGIN CERTIFICATE-----
<snip>
-----END CERTIFICATE-----
subject=/C=US/ST=California/L=Mountain View/O=Google Inc/CN=smtp.gmail.com
issuer=/C=US/O=Google Inc/CN=Google Internet Authority G2
---
No client certificate CA names sent
---
SSL handshake has read 3238 bytes and written 453 bytes
---
New, TLSv1/SSLv3, Cipher is RC4-SHA
Server public key is 2048 bit
Secure Renegotiation IS supported
Compression: NONE
Expansion: NONE
SSL-Session:
    Protocol  : TLSv1
    Cipher    : RC4-SHA
    Session-ID: A84153F1E8168B96E55F9924C0A511AF837D807EEC805898EFD2AEE322D38488
    Session-ID-ctx:
    Master-Key: F47F246F3446F0647CA76D2B2F8527D6C41A11B07B332B48FF0FF030FF9F7B77915BC97258759A5279392C87119498CA
    Key-Arg   : None
    Start Time: 1406317455
    Timeout   : 300 (sec)
    Verify return code: 20 (unable to get local issuer certificate)
---
220 mx.google.com ESMTP l2sm27811884wjw.31 - gsmtp
The other two give similar output to yours, which does suggest something's up with the OpenSSL setup, for which I've not got any pointers.
 
It looks like there is a known issue with openssl-1.0.1, or more accurately an issue with how some server implementations handle the TLS1.2 handshake. I'd assume that your working servers are either limiting TLS to 1.0 or the remote server has been patched to handle the issue, and on the broken ones its either the defaulting to TLS1.2 or the remote server hasn't been patched yet. I googled "openssl write:errno=54" and one of the top pages had the following
This is most likely another case of the frequently reported (and discussed) issue that 1.0.1 implements TLS1.2, which has more ciphersuites enabled by default and additional extensions, which together make the ClientHello bigger, and some server implementations apparently can’t cope. It appears in at least many cases the cutoff is 256 bytes, suggesting these servers don’t handle 2-byte length right.

It’s unlikely that this would be explicitly configured on a server, rather it would be an implementation flaw that previously did not cause a problem. It might occur in an older version of server software fixed in a newer version.

For many details see
http://rt.openssl.org/Ticket/Display.ht ... pass=guest

Short answer is that restricting to TLS1(.0), and/or a smaller list of ciphersuites (but still enough to intersect with the server), likely works. Both do for me using 1.0.1e to your example host. You can use -msg in s_client to see exactly how much (and what) is sent for different options.
 
anlashok said:
It looks like there is a known issue with openssl-1.0.1, or more accurately an issue with how some server implementations handle the TLS1.2 handshake. I'd assume that your working servers are either limiting TLS to 1.0 or the remote server has been patched to handle the issue, and on the broken ones its either the defaulting to TLS1.2 or the remote server hasn't been patched yet.
I concluded more or less the same -- running openssl _s_client tests showed successful handshakes when explicitly specifying TLS1.0 but failed with TLS1.2; and when no ciphersuite/protocol was specified, the results looked the same as with an explicit TLS1.2 connection.

Unfortunately with ssmtp there doesn't seem to be any facility for specifying anything related to encryption whatsoever; it seems to rely on openssl() to Do The Right Thing.

What I didn't get was why freebsd-update broke openssl() functionality on some, but not all, of my servers. My best guess is around the fact that the "broken" servers seem to have been originally set up with FBSD FreeBSD 8, then were upgraded to version 9 and then 10. The working servers started off with FreeBSD 9. Not very scientific, I know, but in most other respects the servers are quite similar. So I think something got screwed up or mixed-and-matched in the crypto/OpenSSL libraries on the bad servers. Pulling stable/10 src and then rebuilding world fixed it for me. Not really what I wanted to do, but I'm happy now.
 
Back
Top