dotConnect for PostgreSQL Documentation
In This Topic
    Using Secure Connections
    In This Topic

    dotConnect for PostgreSQL allows you to establish secure network connections. You can do it using SSL or SSH protocol. This article describes basic concepts for these technologies and how to use it in dotConnect for PostgreSQL.
    The article consists of following sections:

    Why Using Secure Connections?

    When PostgreSQL client communicates with PostgreSQL server, all communication (with the exception of the user password) is done in plain text. This means that anyone who gets between your client and the server can have full access to all information transmitted, and even change the data while it is in transit. In order to protect your information you need to encrypt communications between the PostgreSQL server and the client application.

    Using SSL Connections

    The Secure Sockets Layer protocol enables two parties to negotiate a 'secure' communications channel, ensuring the privacy, authenticity, and integrity of message data. The negotiation mechanism follows:

    1. The client requests a SSL connection from the server.
    2. The two parties negotiate a common ciphersuite, which consists of a key exchange algorithm, a certificate verification algorithm, an encryption algorithm, and an integrity check.
    3. The server provides its certificate so it can be authenticated by the client. Optionally, the client may provide its certificate to be authenticated by the server.
    4. The two parties compute the cryptographic parameters used in the ciphersuite, such as the secret keys needed for data encryption.
    5. The two parties exchange application data, using the generated session key, negotiated algorithms and computed cryptographic parameters.
    Once the cryptographic parameters are established, the application data is transparently encrypted and checked for integrity in both directions.

    To check whether your PostgreSQL server supports SSL you can examine the value of the 'ssl' system variable:

        SHOW VARIABLES LIKE 'have_openssl'
    
    If server returns YES, you can go on to setup client. If the response is NO, or if something refuses to work in the existing configuration, please visit the please visit PostgreSQL documentation topic Secure TCP/IP Connections with SSL.

    Setting Up SSL Connection

    Once server is ready to use SSL connections you only have to setup client properly. You must have 3 additional files reachable:

    Please refer to OpenSSL site for information about these files. The later part assumes you have valid certificates and private key.

    The property SslOptions.CipherList by default is empty, which means that client agrees to use any of available ciphers. The following ciphers are allowed in dotConnect for PostgreSQL:

    You can use ALL keyword to indicate whole set of ciphers. To exclude certain cipher from the set use "-" sign. For instance, value of SslOptions.CipherList property "ALL:-RC4" means that any cipher but RC4 can be used. This property allows you to control performance-security trade-off using this property. To gain better performance you can use RC2 cipher. To achieve maximal traffic security pay attention at 3DES or AES ciphers. By default dotConnect for PostgreSQL tries to use ciphers beginning with most secure rather than fast ones.

    PgSqlConnection.SslOptions property points to object that holds all information necessary to establish SSL connection. Here is brief explanation on what you have to specify in this object:

    Property Meaning
    SslOptions.CACert Location of authority certificate
    SslOptions.Cert Location of client certificate
    SslOptions.Key Location of client's private key
    SslOptions.CipherList List of allowed ciphers separated by colons.
    SslOptions.TlsProtocol The preferred TLS protocol version reported to a server when establishing a secure connection.

    You may store and load the necessary keys or certificates in various ways in your applications: as files or as compiled resources or in a certificate store. dotConnect for PostgreSQL also offers a convenient way to store certificates and keys in memory, so you can load them once, during application start, and then use these certificates from the in memory storage. For this, you can use the MemCryptStorage class.

    You can add certificates to a memory storage in the following way:

    MemCryptStorage.AddCa("my_ca", File.ReadAllBytes("D:\\Temp\\root.crt"));  
    MemCryptStorage.AddCert("my_cert", File.ReadAllBytes("D:\\Temp\\postgresql.crt"));  
    MemCryptStorage.AddKey("my_key", File.ReadAllBytes("D:\\Temp\\postgresql.key"));
    
    
    MemCryptStorage.AddCa("my_ca", File.ReadAllBytes("D:\Temp\root.crt"))
    MemCryptStorage.AddCert("my_cert", File.ReadAllBytes("D:\Temp\postgresql.crt"))
    MemCryptStorage.AddKey("my_key", File.ReadAllBytes("D:\Temp\postgresql.key"))
    
    

    The first parameter here is the certificate or key id, that will be used to reference the certificate.

    Certificates and keys are passed to the MemCryptStorage class in the PEM format as binary raw or string. They can contain LF, CR/LF, or no line break. We don't recommend changing the original format of certificates. It is better to pass them as is.

    Here is how you can specify the locations of certificates:

    Private key can be specified only as file in the system, as a compiled resource, or via the MemCryptStorage class.

    The sample code below illustrates establishment of SSL connection.

    PgSqlConnection conn = new PgSqlConnection("user id=postgres;password=postgres;host=localhost;");
    conn.SslOptions.CACert = "E:\\Test\\root.crt";
    conn.SslOptions.Cert = "E:\\Test\\client.crt";
    conn.SslOptions.Key = "E:\\Test\\client.key";
    conn.SslOptions.SslMode = SslMode.Require;
    conn.Open(); 
    
    
    Dim conn As PgSqlConnection = New PgSqlConnection("user id=postgres;password=postgres;host=localhost;")
    conn.SslOptions.CACert = "E:\Test\root.crt"
    conn.SslOptions.Cert = "E:\Test\client.crt"
    conn.SslOptions.Key = "E:\Test\client.key"
    conn.SslOptions.SslMode = SslMode.Require
    conn.Open() 
    
    

    Using SSL Connection without authentication

    You can use SSL connection without authentication on both server and client side. If you don't want server to verify the client certificate, you need to configure PostgreSQL server without the root.crt, and if you don't want client to verify the server sertificate, don't set the SslOptions.CACert property of the connection.

    Remember, when you disable authentication, the security of the connection between the client and server decreases.

    Using SSH Connections

    SSH connection is established between client and SSH server. SSH server in turn communicates with PostgreSQL server in an unencrypted mode. This is called SSH tunneling. A benefit of SSH tunneling is that it allows you to connect to a PostgreSQL server from behind a firewall when the PostgreSQL server port is blocked. PostgreSQL server does not need to be attuned for this type of connection and functions as usual. To connect to PostgreSQL server a client must first be authorized on SSH server.

    You can download free SSH server at www.openssh.org. The server can run either on the same machine with PostgreSQL server or on a different one. Note that you have to create a user on SSH server to be authorized.

    Setting Up SSH Connection

    To set up an SSH conecton, set up the corresponding SSH options as described below. When any of SSH options are set for a connection, it automatically switches to the SSH protocol.

    PgSqlConnection.SshOptions property points to object that holds all information necessary to connect to SSH server. Alternatively, you may specify the corresponding parameters in the connection string. Here is brief explanation on what you have to specify in this object:

    Property Connection String Parameter Meaning
    SshOptions.AuthenticationType SSH Authentication Type Client authentication methods
    SshOptions.CipherList SSH Cipher List List of ciphers that client agrees to use, by colons.
    SshOptions.Host SSH Host Name or ip address of SSH server
    SshOptions.Passphrase SSH Passphrase Passphrase for the client key
    SshOptions.Password SSH Password User password on SSH server
    SshOptions.Port SSH Port Number of port on SSH server to connect
    SshOptions.PrivateKey SSH Private Key Location of private key to use.
    SshOptions.User SSH User User id on SSH server

    Locations of private key can be specified in three ways:

    PostgreSQL server address that you specify in connection string is the address for SSH server to refer. For instance, if both servers are running on the same machine you have to specify "host=localhost" in the connection string.

    The property SshOptions.CipherList contains the list of the ciphers that client agrees to use, separated by colons. By default it is empty, which means that client agrees to use any of available ciphers. The appropriate values for the CipherList property are listed below, highlighted in bold.

    dotConnect for PostgreSQL supports two modes of block ciphering: Cipher-block chaining (CBC) and Counter (CTR). The following ciphers are available for SSH connections in the CBC mode:

    In the CTR mode the AES ciphers are used.

          // Password Authentication
          PgSqlConnection myConn = new PgSqlConnection("host=server;database=test;user id=postgres;");
          myConn.SshOptions.AuthenticationType = SshAuthenticationType.Password;
          myConn.SshOptions.User = "sshUser";
          myConn.SshOptions.Host = "sshServer";
          myConn.SshOptions.Password = "sshPassword";
          PgSqlCommand myCommand = new PgSqlCommand("select count(*) from dept", myConn);
          myConn.Open();
          Int64 count = Convert.ToInt64(myCommand.ExecuteScalar());
          Console.WriteLine(count);
          myConn.Close();
    
          // Public Key Authentication
          PgSqlConnection myConn = new PgSqlConnection("host=server;database=test;user id=postgres;");
          myConn.SshOptions.AuthenticationType = SshAuthenticationType.PublicKey;
          myConn.SshOptions.User = "sshUser";
          myConn.SshOptions.Host = "sshServer";
          myConn.SshOptions.PrivateKey = "E:\\WORK\\client.key";
          PgSqlCommand myCommand = new PgSqlCommand("select count(*) from dept", myConn);
          myConn.Open();
          Int64 count = Convert.ToInt64(myCommand.ExecuteScalar());
          Console.WriteLine(count);
          myConn.Close();
    
          // Keyboard-Interactive Authentication
          PgSqlConnection connection = new PgSqlConnection("host=server;database=test;user id=postgres;");
    	    connection.Protocol = PgSqlProtocol.Ssh;
    	    // sets ssh options
    	    connection.SshOptions.Host = "ssh_host";
    	    connection.SshOptions.Port = 22;
    	    connection.SshOptions.User = "ssh_user";
    	    connection.SshOptions.AuthenticationType = SshAuthenticationType.KeyboardInteractive;
    	    // Associate the AuthenticationPrompt event with your event handle
    	    connection.AuthenticationPrompt += new PgSqlAuthenticationPromptHandler(connection_AuthenticationPrompt);
    
    	    connection.Open();
    	    Console.WriteLine(connection.State);
    
    	    connection.Close();
    	    Console.ReadKey();
          
          ...
    
          static void connection_AuthenticationPrompt(object sender, PgSqlAuthenticationPrompEventArgs e) {
    
    	      foreach (string prompt in e.Prompts) {
    		      if (prompt.Contains("Password"))
    			      e.Responses[0] = "testPassword";
          		else
    	  	    	if (prompt.Contains("UserId"))
    		  	    e.Responses[1] = "testUserId";
    	      }
          }
    
    
    	    ' Password Authentication
    	    Dim myConn As PgSqlConnection = New PgSqlConnection("host=server;database=test;user id=postgres;")
    	    myConn.SshOptions.AuthenticationType = SshAuthenticationType.Password
    	    myConn.SshOptions.User = "sshUser"
    	    myConn.SshOptions.Host = "sshServer"
    	    myConn.SshOptions.Password = "sshPassword"
    	    Dim myCommand As PgSqlCommand = New PgSqlCommand("select count(*) from dept", myConn)
    	    myConn.Open()
    	    Dim count As Int64 = Convert.ToInt64(myCommand.ExecuteScalar())
    	    Console.WriteLine(count)
    	    myConn.Close()
    
    	    ' Public Key Authentication
    	    Dim myConn As PgSqlConnection = New PgSqlConnection("host=server;database=test;user id=postgres;")
    	    myConn.SshOptions.AuthenticationType = SshAuthenticationType.PublicKey
    	    myConn.SshOptions.User = "sshUser"
    	    myConn.SshOptions.Host = "sshServer"
    	    myConn.SshOptions.PrivateKey = "E:\WORK\client.key"
    	    Dim myCommand As PgSqlCommand = New PgSqlCommand("select count(*) from dept", myConn)
    	    myConn.Open()
    	    Dim count As Int64 = Convert.ToInt64(myCommand.ExecuteScalar())
    	    Console.WriteLine(count)
    	    myConn.Close()
    
    	    ' Keyboard-Interactive Authentication
    	    Dim connection As PgSqlConnection = New PgSqlConnection("host=server;database=test;user id=postgres;")
    	    connection.Protocol = PgSqlProtocol.Ssh
    	    ' sets ssh options
    	    connection.SshOptions.Host = "ssh_host"
    	    connection.SshOptions.Port = 22
    	    connection.SshOptions.User = "ssh_user"
    	    connection.SshOptions.AuthenticationType = SshAuthenticationType.KeyboardInteractive
    	    ' Associate the AuthenticationPrompt event with your event handle
    	    AddHandler connection.AuthenticationPrompt, AddressOf connection_AuthenticationPrompt
    
    	    connection.Open()
    	    Console.WriteLine(connection.State.ToString)
    
    	    connection.Close()
    	    Console.ReadKey()
    
          ...
    
    	    Sub connection_AuthenticationPrompt(ByVal sender As Object, ByVal e As PgSqlAuthenticationPrompEventArgs)
    
    	    	For Each prompt As String In e.Prompts
    			    If prompt.Contains("Password") Then
    				    e.Responses(0) = "testPassword"
    			    ElseIf prompt.Contains("UserId") Then
    				    e.Responses(1) = "testUserId"
    			    End If
    		    Next
    	    End Sub
    
    

    See Also

     PgSqlConnection Class  | SslOptions ClassSshOptions Class