Reputation: 1204
I read that client side authentication is optional, so I am trying to connect to my SSL server without authenticating on the client side. When I do this I get the following error on the server:
, in accept_connection
ssl_version=ssl.PROTOCOL_SSLv23
File "/usr/lib/python2.7/ssl.py", line 933, in wrap_socket
ciphers=ciphers)
File "/usr/lib/python2.7/ssl.py", line 601, in __init__
self.do_handshake()
File "/usr/lib/python2.7/ssl.py", line 830, in do_handshake
self._sslobj.do_handshake()
SSLEOFError: EOF occurred in violation of protocol (_ssl.c:590)
Here is the working server and client code, everything works fine when I authenticate on the client side, but the error shows up when I comment that line out.
Server (python):
def accept_connection(self, sock):
client, (addr, port) = sock.accept()
sslclient = ssl.wrap_socket(
client,
server_side=True,
certfile=self.ssl_cert_file,
keyfile=self.ssl_key_file,
ssl_version=ssl.PROTOCOL_SSLv23
)
Client (C#):
public bool Connect()
{
try
{
client = new TcpClient(this.ServerAddress, this.ServerPort);
sslStream = new SslStream(
client.GetStream(),
false,
new RemoteCertificateValidationCallback(ValidateCert),
null
);
try
{
sslStream.AuthenticateAsClient(this.ServerAddress);
}
catch (AuthenticationException e)
{
sslStream = null;
client.Close();
client = null;
return false;
}
}
catch (Exception e)
{
return false;
}
return true;
}
The above is working code with no errors.
When I comment out the following code on the client:
//sslStream.AuthenticateAsClient(this.ServerAddress);
The python error mentioned above shows up, and the client connection doesn't throw any exceptions and continues running until its first read, then fails with:
This operation is only allowed using a successfully authenticated context.
How can I go about making this work if I do not call AuthenticateAsClient
?
This is how i generate certfile and keyfile
openssl req -x509 -newkey rsa:1024 -keyout my.key -out my.crt -days 365 -nodes -subj "/C=US/ST=VA/L=Junk/O=None/OU=Junk/CN=example.local"
Python is version 2.
Perhaps I have just been misinformed that the call to AuthenticateAsClient
is optional?
Upvotes: 3
Views: 3106
Reputation: 101463
Ssl client certificate authentication is indeed optional. It's when client sends its certificate to server, and server verifies this certificate is valid, is what server expects, and authenticates client with that certificate.
However, this is not what is performed by
sslStream.AuthenticateAsClient(this.ServerAddress);
As documentation states, this method is
Called by clients to authenticate the server and optionally the client in a client-server connection.
Authenticating the server (verifying its certificate is valid, was issued for the expected domain, was issued by trusted authority) is a required step in ssl handshake. For example, using description by this link we see that step 3 is:
The SSL or TLS client verifies the server's digital certificate
Server waits for the result of this step from client to proceed. For that reason, if you skip this step by commenting the call to AuthenticateAsClient
- your python server correctly complains about protocol violation.
To use client authentication you would use another overload:
X509CertificateCollection clientCerts = GetClientCerts();
sslStream.AuthenticateAsClient(this.ServerAddress, clientCerts, true);
Since you are not doing that - you are not performing (optional) client authentication.
Upvotes: 3