|
Forums -> Security Library Forum
PostgreSQL SSL communication |
|
|
by Angel Todorov [atodorov at acm dot org] posted on 2003/09/28 |
|
Hello, i am adding SSL support to the Npgsql driver for .NET that allows support for the PostgreSQL database. I am using a SecureTcpClient for communication. The protocol that i use when creating the SecureTcpClient instance is Ssl3. The Exception that i get back is the following: (shown below). I am configuring PostgreSQL with SSL support as described in http://developer.postgresql.org/docs/postgres/ssl-tcp.html Do you have any idea what could be the problem, and how can i possibly check, i.e protocol mismatch ??
Unhandled Exception: Npgsql.NpgsqlException: Error in Open() ---> System.IO.IOEx
ception: An I/O exception occurred. ---> Org.Mentalis.Security.SecurityException
: An error occurs while communicating with the remote host. ---> Org.Mentalis.Se
curity.Ssl.Shared.SslException: The server hello message uses a protocol that wa
s not recognized.
at Org.Mentalis.Security.Ssl.Shared.CompatibilityLayer.ProcessServerHello(Byt
e[] bytes, Int32 offset, Int32 size)
at Org.Mentalis.Security.Ssl.Shared.CompatibilityLayer.ProcessHello(Byte[] by
tes, Int32 offset, Int32 size)
at Org.Mentalis.Security.Ssl.Shared.SocketController.OnReceive(IAsyncResult a
r)
--- End of inner exception stack trace ---
at Org.Mentalis.Security.Ssl.SecureSocket.EndSend(IAsyncResult asyncResult)
at Org.Mentalis.Security.Ssl.SecureSocket.Send(Byte[] buffer, Int32 offset, I
nt32 size, SocketFlags socketFlags)
at Org.Mentalis.Security.Ssl.SecureNetworkStream.Write(Byte[] buffer, Int32 o
ffset, Int32 size)
--- End of inner exception stack trace ---
at Org.Mentalis.Security.Ssl.SecureNetworkStream.Write(Byte[] buffer, Int32 o
ffset, Int32 size)
at Npgsql.NpgsqlStartupPacket.WriteToStream(Stream output_stream, Encoding en
coding)
at Npgsql.NpgsqlConnectedState.Startup(NpgsqlConnection context)
at Npgsql.NpgsqlClosedState.Open(NpgsqlConnection context)
at Npgsql.NpgsqlConnection.Open()
--- End of inner exception stack trace ---
at Npgsql.NpgsqlConnection.Open()
at npgsqltest.NpgsqlTest.Main(String[] args) in c:\documents and settings\ang
el todorov\my documents\visual studio projects\npgsqltest\npgsqltest.cs:line 21 |
by Pieter Philippaerts [Pieter at mentalis dot org] posted on 2003/09/29 |
|
The error you're seeing is an error that can only be thrown if the SecureSocket is using SSL and the server is not or if the server doesn't support the SSL version of the SecureSocket.
First of all, try using
SecureProtocol.Ssl3 | SecureProtocol.Tls1
when creating your SecurityOptions instance. This will enable support for both SSL3 and TLS1. If this still doesn't work, make sure your server isn't configured to only accept SSL2 connections. |
by Angel Todorov [atodorov at acm dot org] posted on 2003/09/29 |
|
Hello,
I am configuring PostgreSQL in the normal way as described in the manual. The log says, though,
LOG: database system was shut down at 2003-09-29 08:25:57 CEST
LOG: checkpoint record is at 0/80DB78
LOG: redo record is at 0/80DB78; undo record is at 0/0; shutdown TRUE
LOG: next transaction id: 488; next oid: 16977
LOG: database system is ready
FATAL: invalid length of startup packet
I am worried about this invalid length of startup packet. There should be a difference between SSL 2 and 3, assuming my server uses ssl2 (i think it should use v3 anyway) ? |
by Angel Todorov [atodorov at acm dot org] posted on 2003/09/29 |
|
remark: Tom Lane from postgreSQL replied to me , that "Specifically, you need to eat the initial "S" or "N" response byte from the server before firing up the SSL startup handshake." |
by Pieter Philippaerts [Pieter at mentalis dot org] posted on 2003/09/29 |
|
In that case you have to first initialize the SecureSocket as a normal unencrypted socket [SecureProtocol.None]. If the socket is connected to the server, call the Receive method and make sure you read only one byte [reading more bytes will corrupt the SSL/TLS handshake]. After that, call the ChangeSecurityProtocol method of the SecureSocket class and pass it a SecurityOptions structure with the correct parameters [ie, SecureProtocol.Ssl3|SecureProtocol.Tls1, SslAlgorithms.SECURE_CIPHERS and CredentialVerification.Manual]. |
by Angel Todorov [atodorov at acm dot org] posted on 2003/09/29 |
|
Hello,
thanks a lot for your feedback. It seems that now i am not getting the old exception. I have one question: Do i have to create a new socket when i change the security protocol, or i just call the method for the non-secured Socket? I have implemented that as you said, and it obviously doesn't get the previous error, but instead i get this Exception:
Unhandled Exception: System.InvalidOperationException: Operation is not valid du e to the current state of the object.
at Org.Mentalis.Security.Ssl.SecureTcpClient.GetStream()
at Npgsql.NpgsqlConnectedState.Startup(NpgsqlConnection context)
at Npgsql.NpgsqlClosedState.Open(NpgsqlConnection context)
at Npgsql.NpgsqlConnection.Open()
That is, my application goes from Closed to Connected State, but then when i have to get the Stream for teh SecureTcpClient, it complains. What i meant was, it is the same if you create a new instance of SecureTcpClient with the parameters, and when you create an instance using the default constructor and then just set the existing Socket?
|
by Pieter Philippaerts [Pieter at mentalis dot org] posted on 2003/09/29 |
|
The InvalidOperationException is thrown if the GetStream method is called on a disconnected socket.
The ChangeSecurityProtocol method I mentioned before is currently not supported in the SecureNetworkStream class [this is an oversight, there's no technical reason for it]. You'll either have to use a Socket object or construct the SecureNetworkStream object yourself giving the constructor a connected socket where you've already read the first byte and changed the secure protocol. Your code could look something like this:
SecureSocket ss = new SecureSocket(AddressFamily.InterNetwork, SocketType.Stream, ProtocolType.Tcp);
ss.Connect(...);
// read the first byte
ss.Receive(new byte[1], 0, 1);
// start the SSL/TLS negotiation
SecurityOptions options = new SecurityOptions(...);
ss.ChangeSecurityProtocol(options);
// create a SecureNetworkStream instance
SecureNetworkStream stream = new SecureNetworkStream(ss, true);
If you post your code, I may be able to help you further. |
|
|