STARTTLS connection with Ruby and OpenSSL - ruby

Using openssl s_client on the command line I am able to establish a comection to a POP3 server which requires STARTTLS.
openssl s_client -connect pop3.example.com:110 -starttls pop3
How can I accomplish the same (especially the -starttls pop part) utilizing Ruby's OpenSSL library:
tcp_socket = TCPSocket.new host, port
ssl_context = OpenSSL::SSL::SSLContext.new
ssl_client = OpenSSL::SSL::SSLSocket.new tcp_socket, ssl_context
ssl_client.connect

The POP3 specification states that you need to send STLS in order to initiate the TLS handshake. Therefore you should send STLS on the unencrypted socket first, and after that you should be able to call connect on the OpenSSL layer, which will then perform the actual handshake.
If you call connect before sending STLS, the server won't know what is going on, and will interpret it as garbage input.
Working example:
tcp = TCPSocket.new(host, port)
puts tcp.gets
tcp.puts 'STLS'
puts tcp.gets
ssl_context = OpenSSL::SSL::SSLContext.new
ssl_client = OpenSSL::SSL::SSLSocket.new(tcp, ssl_context)
ssl_client.connect
puts ssl_client.state
ssl_client.puts "NOOP"
puts ssl_client.gets
Output:
+OK POP3 ready <2067986403.1526483285#....>
+OK
SSLOK
+OK

Related

How to read server certificate from wss endpoint?

I have websocket endpoint wss://http-testnet.hecochain.com/ to connect to,
but I cannot get its certificate to use within code.
While to certificate for HTTP URL you can just use browser (See 1) and 2) below),
there is no way for WS as it is not displayed in browser
Links
https://superuser.com/questions/97201/how-to-save-a-remote-server-ssl-certificate-locally-as-a-file, e.g.
openssl s_client -connect google.com:443 -showcerts
https://medium.com/#menakajain/export-download-ssl-certificate-from-server-site-url-bcfc41ea46a2
Well, because wss actually works over htttps port 443, so certificate is the same for wss:
openssl s_client -connect http-testnet.hecochain.com:443 -showcerts
openssl s_client -connect ws-testnet.hecochain.com:443 -showcerts

dtls handshake failed with alert decrypt error

I'm implementing a dtls-srtp handshake from client (openssl with VS C++), but it failed. The message flow on wireshark turned out like this:
Client Hello
Server Hello, Certificate (Fragment), Certificate (Fragment), Certificate (Fragment), Certificate (Reassembled), Certificate Request, Server Hello Done
Certificate (Fragment), Certificate (Fragment), Certificate (Fragment), Certificate (Reassembled), Client Key Exchange, Certificate Verify (Fragment)
Server Hello, Certificate[Reassembly error, protocol DTLS: New fragment overlaps old data (retransmission?)]
Client Hello
Server Hello, Certificate[Reassembly error, protocol DTLS: New fragment overlaps old data (retransmission?)]
Client Hello, Certificate[Reassembly error, protocol DTLS: New fragment overlaps old data (retransmission?)]
Server Hello, Certificate[Reassembly error, protocol DTLS: New fragment overlaps old data (retransmission?)]
Certificate Verify (Reassembled), Change Cipher Spec, Certificate[Reassembly error, protocol DTLS: New fragment overlaps old data (retransmission?)]
Alert (Level: Fatal, Description: Decrypt Error)
Does anyone has any idea what's going on here? Is it the problem of certificate/key, or did I miss any SSL option / parameter?
I tried to change the mtu value but it didn't work.
Modified: logs from client
*SSL_CB_HANDSHAKE_START unknown: before/connect initialization
SSL_CB_LOOP SSL_connect: before/connect initialization
SSL_CB_LOOP SSL_connect: SSLv3 write client hello A
SSL_CB_EXIT SSL_connect: SSLv3 read server hello A
SSL_CB_EXIT SSL_connect: SSLv3 read server hello A
-> connect err=-1 errRet=SSL_ERROR_WANT_READ
SSL_CB_LOOP SSL_connect: SSLv3 read server hello A
SSL_CB_LOOP SSL_connect: SSLv3 read server certificate A
SSL_CB_LOOP SSL_connect: SSLv3 read server certificate request A
SSL_CB_LOOP SSL_connect: SSLv3 read server done A
SSL_CB_LOOP SSL_connect: SSLv3 write client certificate A
SSL_CB_LOOP SSL_connect: SSLv3 write client key exchange A
SSL_CB_LOOP SSL_connect: SSLv3 write certificate verify A
SSL_CB_EXIT SSL_connect: error
-> connect err=-1 errRet=SSL_ERROR_SYSCALL*

traefik's tls: client didn't provide a certificate when accessing https endpoint

Here's my configuration
[entryPoints]
[entryPoints.http]
address = ":801"
[entryPoints.https]
address = ":802"
[entryPoints.https.tls]
[entryPoints.https.tls.ClientCA]
files = ["/etc/ssl/comodo/bundle.crt"]
[[entryPoints.https.tls.certificates]]
certFile = "/etc/ssl/comodo/www.crt"
keyFile = "/etc/ssl/comodo/www.key"
[frontends]
[frontends.http] # default
entryPoints = ["http", "https"]
backend = "fallback"
passHostHeader = true
Now I'm trying to access https://mydomain:802 and I get following error in traefik debug output
http: TLS handshake error from 111.111.111.111:64463: tls: client didn't provide a certificate
curl error message
error:14094412:SSL routines:SSL3_READ_BYTES:sslv3 alert bad certificate
I can't figure out what I'm doing wrong.
Why would you want to use Mutual authentication (two-way handshake)? For normal SSL connections your server certificates are enough.
In your traefik.toml you're configuring Mutual authentication. If you really want so, you have to provide the certificate within your curl request:
curl --cert client.pem:<password> --key key.pem --cacert ca.pem
If you only want to provide "normal" SSL, you should delete following lines:
[entryPoints.https.tls.ClientCA]
files = ["/etc/ssl/comodo/bundle.crt"]

Ruby TCP chat server

Recently Iv'e been trying to program a simple TCP server to later build into a chat room. But every time I launch the server (server.rb), and then I try to use the client (client.rb) I get this error:
Sam#ANDERSAMERPC C:\Users\Sam\Documents\Coding
> client.rb
C:/Users/Sam/Documents/Coding/client.rb:6:in `initialize': No connection could be made because the target machine actively refused it. - connect(2) for "localhost" port 2001 (Errno::ECONNREFUSED)
from C:/Users/Sam/Documents/Coding/client.rb:6:in `open'
from C:/Users/Sam/Documents/Coding/client.rb:6:in `<main>'
I am using CMD to run this and I've tried turning off firewall briefly.
Here is the code for both of the programs...
This is server.rb
require 'socket'
server = TCPServer.open(2000) # Socket to listen on port 2000
loop {
Thread.start(server.accept) do |client|
client.puts(Time.now.ctime) # Send time to the client
client.puts "Closing connection. Bye!"
client.close
end
}
Here's client.rb:
require 'socket'
hostname = "localhost"
port = 2000
s = TCPSocket.open(hostname, port)
while line = s.gets # Reads lines from socket
puts line.chop # And print with platform line terminator
end
s.close # Close socket when done
(This code is from http://www.tutorialspoint.com/ruby/ruby_socket_programming.htm just so you know.)
I guess there are 2 options:
Run your server.rb before client.rb.
Are you sure those are the exact same files that you are running. Because the error message says it can not connect to port 2001, whereas in both of your files they refer to 2000. Is it possible that you are editing and running different files? You will be surprised, how common this is here on SO :)

cURL - Unkown SSL protocol error - OS X 10.9

I am trying to use cURL and get the following error on every https request I make. The error is always the same. HTTP requests work flawlessly. The verbose output is quite useless.
bash:$ curl https://google.com -vv
* Adding handle: conn: 0x7fe09b803a00
* Adding handle: send: 0
* Adding handle: recv: 0
* Curl_addHandleToPipeline: length: 1
* - Conn 0 (0x7fe09b803a00) send_pipe: 1, recv_pipe: 0
* About to connect() to google.com port 443 (#0)
* Trying 74.125.226.129...
* Connected to google.com (74.125.226.129) port 443 (#0)
* Unknown SSL protocol error in connection to google.com:-9805
* Closing connection 0
curl: (35) Unknown SSL protocol error in connection to google.com:-9805
bash:$ curl https://google.com -V
curl 7.30.0 (x86_64-apple-darwin13.0) libcurl/7.30.0 SecureTransport zlib/1.2.5
Protocols: dict file ftp ftps gopher http https imap imaps ldap ldaps pop3 pop3s rtsp smtp smtps telnet tftp
Features: AsynchDNS GSS-Negotiate IPv6 Largefile NTLM NTLM_WB SSL libz
bash:$ openssl s_client -connect google.com:443 < /dev/null
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
24255:error:140790E5:SSL routines:SSL23_WRITE:ssl handshake failure:/SourceCache/OpenSSL098/OpenSSL098-50/src/ssl/s23_lib.c:182:
The results are the same on two different networks, so it does not appear to be network-specific. Attempting to connect using openssl s_client fails similarly so it is not library-dependent either (curl on the Mac uses SecureTransport). The debug output of s_client shows that the SSL handshake proceeds normally to the point where the client sends ChangeCipherSpec and the Finished messages but does not receive ChangeCipherSpec back from the server.
I have tried running these commands on a Debian VM on my Mac, and everything there runs correctly. In addition, using curl to connect to a local OpenSSL server (openssl s_server with a self-signed certificate) also works correctly.
I have looked through other answers on this forum and other places on the internet, but haven't found an answer. Most people's issues involve particular servers and the configuration of SSL on these servers. Mine however is problematic anytime HTTPS is used (with any website).
It was suggested that the issue might be in the certificate store. But if I understand it correctly, if the issue was with the certificate store, it would cause certificates to be rejected by all apps. However, all my browsers (chrome, safari, firefox) negotiate SSL with no problems. There is nothing suspicious in the environment variables for GUI applications or the shell.
Can someone please suggest what I should be looking into to solve the problem? Can it be that something is not properly configured? What should I be looking for?

Resources