Browse Source

Merge pull request #187 from seriyps/update-test-certificates

Update test certificates
Sergey Prokhorov 6 years ago
parent
commit
20ece6fbcb

+ 33 - 0
generate_test_certs.sh

@@ -0,0 +1,33 @@
+#!/bin/sh
+# https://www.postgresql.org/docs/current/ssl-tcp.html#SSL-CERTIFICATE-CREATION
+
+DATADIR=test/data
+CA_SUBJ="/CN=epgsql CA"
+CLIENT_SUBJ="/CN=epgsql_test_cert"
+SERVER_SUBJ="/CN=epgsql server"
+set -x
+
+# generate root key
+openssl genrsa -out ${DATADIR}/root.key 2048
+# generate root cert
+openssl req -new -x509 -text -days 3650 -key ${DATADIR}/root.key -out ${DATADIR}/root.crt -subj "$CA_SUBJ"
+
+# generate server key
+openssl genrsa -out ${DATADIR}/server.key 2048
+# generate server signature request
+openssl req -new -key ${DATADIR}/server.key -out ${DATADIR}/server.csr -subj "$SERVER_SUBJ"
+# create signed server cert
+openssl x509 -req -text -days 3650 -in ${DATADIR}/server.csr -CA ${DATADIR}/root.crt -CAkey ${DATADIR}/root.key -CAcreateserial -out ${DATADIR}/server.crt
+
+# generate client key
+openssl genrsa -out ${DATADIR}/client.key 2048
+# generate client signature request
+openssl req -new -key ${DATADIR}/client.key -out ${DATADIR}/client.csr -subj "$CLIENT_SUBJ"
+# create signed client cert
+openssl x509 -req -text -days 3650 -in ${DATADIR}/client.csr -CA ${DATADIR}/root.crt -CAkey ${DATADIR}/root.key -CAcreateserial -out ${DATADIR}/client.crt
+
+# generate bad client key and cert
+openssl genrsa -out ${DATADIR}/bad-client.key 2048
+openssl req -new -x509 -text -days 3650 -key ${DATADIR}/bad-client.key -out ${DATADIR}/bad-client.crt -subj "$CLIENT_SUBJ"
+
+rm ${DATADIR}/*.{csr,srl}

+ 30 - 26
src/commands/epgsql_cmd_connect.erl

@@ -45,39 +45,47 @@
 init(#{host := _, username := _} = Opts) ->
     #connect{opts = Opts}.
 
-execute(PgSock, #connect{opts = Opts, stage = connect} = State) ->
-    #{host := Host,
-      username := Username} = Opts,
+execute(PgSock, #connect{opts = #{host := Host} = Opts, stage = connect} = State) ->
     Timeout = maps:get(timeout, Opts, 5000),
     Port = maps:get(port, Opts, 5432),
     SockOpts = [{active, false}, {packet, raw}, binary, {nodelay, true}, {keepalive, true}],
     case gen_tcp:connect(Host, Port, SockOpts, Timeout) of
         {ok, Sock} ->
+            client_handshake(Sock, PgSock, State);
+        {error, Reason} = Error ->
+            {stop, Reason, Error, PgSock}
+    end;
+execute(PgSock, #connect{stage = auth, auth_send = {PacketId, Data}} = St) ->
+    epgsql_sock:send(PgSock, PacketId, Data),
+    {ok, PgSock, St#connect{auth_send = undefined}}.
 
-            %% Increase the buffer size.  Following the recommendation in the inet man page:
-            %%
-            %%    It is recommended to have val(buffer) >=
-            %%    max(val(sndbuf),val(recbuf)).
-
-            {ok, [{recbuf, RecBufSize}, {sndbuf, SndBufSize}]} =
-                inet:getopts(Sock, [recbuf, sndbuf]),
-            inet:setopts(Sock, [{buffer, max(RecBufSize, SndBufSize)}]),
+client_handshake(Sock, PgSock, #connect{opts = #{username := Username} = Opts} = State) ->
+    %% Increase the buffer size.  Following the recommendation in the inet man page:
+    %%
+    %%    It is recommended to have val(buffer) >=
+    %%    max(val(sndbuf),val(recbuf)).
 
-            PgSock1 = maybe_ssl(Sock, maps:get(ssl, Opts, false), Opts, PgSock),
+    {ok, [{recbuf, RecBufSize}, {sndbuf, SndBufSize}]} =
+        inet:getopts(Sock, [recbuf, sndbuf]),
+    inet:setopts(Sock, [{buffer, max(RecBufSize, SndBufSize)}]),
 
+    case maybe_ssl(Sock, maps:get(ssl, Opts, false), Opts, PgSock) of
+        {error, Reason} ->
+            {stop, Reason, {error, Reason}, PgSock};
+        PgSock1 ->
             Opts2 = ["user", 0, Username, 0],
             Opts3 = case maps:find(database, Opts) of
-                error -> Opts2;
-                {ok, Database}  -> [Opts2 | ["database", 0, Database, 0]]
-            end,
+                        error -> Opts2;
+                        {ok, Database}  -> [Opts2 | ["database", 0, Database, 0]]
+                    end,
 
             {Opts4, PgSock2} =
                 case Opts of
                     #{replication := Replication}  ->
                         {[Opts3 | ["replication", 0, Replication, 0]],
                          epgsql_sock:init_replication_state(PgSock1)};
-                        _ -> {Opts3, PgSock1}
-                    end,
+                    _ -> {Opts3, PgSock1}
+                end,
 
             epgsql_sock:send(PgSock2, [<<196608:?int32>>, Opts4, 0]),
             PgSock3 = case Opts of
@@ -85,13 +93,8 @@ execute(PgSock, #connect{opts = Opts, stage = connect} = State) ->
                               epgsql_sock:set_attr(async, Async, PgSock2);
                           _ -> PgSock2
                       end,
-            {ok, PgSock3, State#connect{stage = maybe_auth}};
-        {error, Reason} = Error ->
-            {stop, Reason, Error, PgSock}
-    end;
-execute(PgSock, #connect{stage = auth, auth_send = {PacketId, Data}} = St) ->
-    epgsql_sock:send(PgSock, PacketId, Data),
-    {ok, PgSock, St#connect{auth_send = undefined}}.
+            {ok, PgSock3, State#connect{stage = maybe_auth}}
+    end.
 
 
 %% @doc Replace `password' in Opts map with obfuscated one
@@ -127,14 +130,15 @@ maybe_ssl(S, Flag, Opts, PgSock) ->
                 {ok, S2}        ->
                     epgsql_sock:set_net_socket(ssl, S2, PgSock);
                 {error, Reason} ->
-                    exit({ssl_negotiation_failed, Reason})
+                    Err = {ssl_negotiation_failed, Reason},
+                    {error, Err}
             end;
         $N ->
             case Flag of
                 true ->
                     epgsql_sock:set_net_socket(gen_tcp, S, PgSock);
                 required ->
-                    exit(ssl_not_available)
+                    {error, ssl_not_available}
             end
     end.
 

+ 77 - 0
test/data/bad-client.crt

@@ -0,0 +1,77 @@
+Certificate:
+    Data:
+        Version: 3 (0x2)
+        Serial Number:
+            69:9e:78:95:59:48:52:4a:05:f7:ee:2a:ab:a8:ac:43:d7:d5:39:01
+        Signature Algorithm: sha256WithRSAEncryption
+        Issuer: CN = epgsql_test_cert
+        Validity
+            Not Before: Feb 17 04:48:03 2019 GMT
+            Not After : Feb 14 04:48:03 2029 GMT
+        Subject: CN = epgsql_test_cert
+        Subject Public Key Info:
+            Public Key Algorithm: rsaEncryption
+                RSA Public-Key: (2048 bit)
+                Modulus:
+                    00:b9:3e:95:d3:09:b6:b9:e7:66:5c:1a:24:96:b6:
+                    64:17:d1:2a:a8:3d:27:aa:ea:9f:07:a1:3e:41:91:
+                    8d:1f:e3:15:4d:43:9b:d9:93:73:25:66:8f:28:0a:
+                    5b:99:8f:e0:d6:67:a7:be:7f:ea:1e:f8:0c:c9:38:
+                    c3:fc:cb:b0:4a:ed:b4:56:96:49:2d:4b:95:c0:25:
+                    56:9f:13:03:ef:e6:4f:dd:89:97:86:b9:b4:c7:7e:
+                    e7:28:cf:34:13:f0:a2:82:7d:97:93:de:08:a6:0e:
+                    95:02:ea:67:5d:fa:82:4a:5b:c5:1e:48:43:22:f3:
+                    2a:1c:ca:8e:45:2e:2b:37:76:b5:6f:de:64:b5:36:
+                    98:e7:ed:bf:be:3a:ea:ba:50:f5:b3:25:c2:ee:8b:
+                    b4:47:fe:f8:fc:f7:ea:40:24:4f:e8:9e:f0:95:07:
+                    d5:23:ed:b5:31:0f:fc:f3:39:f9:ff:fc:df:37:5d:
+                    b6:bb:d5:9a:65:cb:4b:1e:1b:e4:1f:b0:d8:87:0f:
+                    03:da:f4:b1:bb:71:ba:51:44:5f:9b:79:d8:34:1f:
+                    09:8b:c7:79:6d:09:e5:4b:a9:39:7e:2d:34:38:c7:
+                    df:08:e5:ba:91:65:ee:a4:44:88:5a:4b:70:2e:14:
+                    08:14:1a:1c:e6:b9:92:9a:47:ba:2a:c7:ec:25:ea:
+                    59:ad
+                Exponent: 65537 (0x10001)
+        X509v3 extensions:
+            X509v3 Subject Key Identifier: 
+                78:6A:6B:3A:64:BB:48:4B:E2:E3:5F:E8:47:D7:E4:6E:44:03:A6:09
+            X509v3 Authority Key Identifier: 
+                keyid:78:6A:6B:3A:64:BB:48:4B:E2:E3:5F:E8:47:D7:E4:6E:44:03:A6:09
+
+            X509v3 Basic Constraints: critical
+                CA:TRUE
+    Signature Algorithm: sha256WithRSAEncryption
+         40:88:d3:37:de:8d:3f:40:a3:2d:96:79:00:ba:8a:03:75:43:
+         d9:15:a4:01:eb:69:2a:9f:48:34:ed:e0:88:e3:e3:cb:70:d9:
+         47:a3:c5:65:7e:21:9f:80:6e:91:a7:bf:b0:1b:bb:b2:64:0c:
+         c3:63:20:8a:a4:bf:fc:3d:c2:2f:ef:e8:8b:f6:4b:d6:47:95:
+         30:86:f7:d0:f0:ba:90:2c:12:1a:12:5d:38:8e:02:31:75:36:
+         e2:1d:8c:2a:4b:b1:d0:d4:94:8e:8b:8c:82:43:cb:a2:b0:77:
+         cf:7c:8d:ae:a2:3d:da:ad:87:c3:00:50:9a:84:01:03:d6:bf:
+         50:90:0f:3f:17:89:9e:13:01:1a:88:17:a1:e0:95:3d:38:ca:
+         30:dd:2d:fa:15:a5:09:6c:2c:a0:63:4e:4a:3f:12:37:71:05:
+         2e:9b:eb:4c:4a:f4:9c:ad:93:6e:c7:4a:3d:ca:6d:85:38:0e:
+         e3:43:e8:ca:71:0f:71:39:28:e0:7a:5b:41:4a:a4:7c:ef:f2:
+         1a:70:80:44:f3:47:4f:2c:86:87:00:b6:ec:3b:d3:67:3d:0f:
+         d1:e4:92:4a:d3:93:0c:7a:34:77:fb:c9:10:16:4d:af:4b:ce:
+         10:35:9b:d6:13:35:12:6b:6c:57:cb:c0:32:08:b1:23:b0:ec:
+         76:c5:bc:6d
+-----BEGIN CERTIFICATE-----
+MIIDFzCCAf+gAwIBAgIUaZ54lVlIUkoF9+4qq6isQ9fVOQEwDQYJKoZIhvcNAQEL
+BQAwGzEZMBcGA1UEAwwQZXBnc3FsX3Rlc3RfY2VydDAeFw0xOTAyMTcwNDQ4MDNa
+Fw0yOTAyMTQwNDQ4MDNaMBsxGTAXBgNVBAMMEGVwZ3NxbF90ZXN0X2NlcnQwggEi
+MA0GCSqGSIb3DQEBAQUAA4IBDwAwggEKAoIBAQC5PpXTCba552ZcGiSWtmQX0Sqo
+PSeq6p8HoT5BkY0f4xVNQ5vZk3MlZo8oCluZj+DWZ6e+f+oe+AzJOMP8y7BK7bRW
+lkktS5XAJVafEwPv5k/diZeGubTHfucozzQT8KKCfZeT3gimDpUC6mdd+oJKW8Ue
+SEMi8yocyo5FLis3drVv3mS1Npjn7b++Ouq6UPWzJcLui7RH/vj89+pAJE/onvCV
+B9Uj7bUxD/zzOfn//N83Xba71Zply0seG+QfsNiHDwPa9LG7cbpRRF+bedg0HwmL
+x3ltCeVLqTl+LTQ4x98I5bqRZe6kRIhaS3AuFAgUGhzmuZKaR7oqx+wl6lmtAgMB
+AAGjUzBRMB0GA1UdDgQWBBR4ams6ZLtIS+LjX+hH1+RuRAOmCTAfBgNVHSMEGDAW
+gBR4ams6ZLtIS+LjX+hH1+RuRAOmCTAPBgNVHRMBAf8EBTADAQH/MA0GCSqGSIb3
+DQEBCwUAA4IBAQBAiNM33o0/QKMtlnkAuooDdUPZFaQB62kqn0g07eCI4+PLcNlH
+o8VlfiGfgG6Rp7+wG7uyZAzDYyCKpL/8PcIv7+iL9kvWR5UwhvfQ8LqQLBIaEl04
+jgIxdTbiHYwqS7HQ1JSOi4yCQ8uisHfPfI2uoj3arYfDAFCahAED1r9QkA8/F4me
+EwEaiBeh4JU9OMow3S36FaUJbCygY05KPxI3cQUum+tMSvScrZNux0o9ym2FOA7j
+Q+jKcQ9xOSjgeltBSqR87/IacIBE80dPLIaHALbsO9NnPQ/R5JJK05MMejR3+8kQ
+Fk2vS84QNZvWEzUSa2xXy8AyCLEjsOx2xbxt
+-----END CERTIFICATE-----

+ 27 - 0
test/data/bad-client.key

@@ -0,0 +1,27 @@
+-----BEGIN RSA PRIVATE KEY-----
+MIIEowIBAAKCAQEAuT6V0wm2uedmXBoklrZkF9EqqD0nquqfB6E+QZGNH+MVTUOb
+2ZNzJWaPKApbmY/g1menvn/qHvgMyTjD/MuwSu20VpZJLUuVwCVWnxMD7+ZP3YmX
+hrm0x37nKM80E/Cign2Xk94Ipg6VAupnXfqCSlvFHkhDIvMqHMqORS4rN3a1b95k
+tTaY5+2/vjrqulD1syXC7ou0R/74/PfqQCRP6J7wlQfVI+21MQ/88zn5//zfN122
+u9WaZctLHhvkH7DYhw8D2vSxu3G6UURfm3nYNB8Ji8d5bQnlS6k5fi00OMffCOW6
+kWXupESIWktwLhQIFBoc5rmSmke6KsfsJepZrQIDAQABAoIBAFzbtpb3g5VlHbaF
+lFnITBx0SYHURhIzUkys01xi7e9SEdeNUI6cj1fsNU7JAmnT6c0QYNHppR6pER+9
+SOFr6Y9l4MSWyU/fV83d6bIMAik7tkVDN6XdaXWnc5DNbTmhopTvCBCjeIplPOUd
+Q3ukm7NSlVk8uArJAg80qmSbZCaEi9RkmsH3JDLPQuhdAfE9xjYDM3ylrMZK8dTb
+EL+LrK5syBmEBtP8W7G59D/NSaocgq+cBSje2W/T9wA8JTLsI1J7XxoFypVuBB86
+4mbyYDkFeS8QNS/rHEThAcCF/5K4pcZccEsDiiCQd5I7OYCEJTfMptN9KUCkpGm5
+VfcF9wECgYEA75hsQajRcrO09BJ+TlRBtGr6LSPdXfEaAACrSYIgEWCC05L8N0yw
+y33vgNpY63VHLSiwVUa37Sx2nqNvjbYAoVjXyE9q8QGGjzFCVWhFbC/GQ6WZ39oO
+Yt0jd1g2bLoqSCE1Smq6oaKI2lCbxtBj7PCryGjwYvcd3mfkFm0u0h0CgYEAxe2C
+ydHPy+OWyo04zkjTAeoucOsur0SZij1gILzMMtuSalK2bQ85zGIyTHShxSQUsh5l
+pv20BfHA19XSOq3A38JYonU2nhI4BZYmfwLik2O2y8k9znAJ2KX20rAMqPE570+n
+yIXFObYwEWMXZdKIIecaLnZ2BLu19bUhXfabENECgYEAy54t4l8mIOS4k/Rjgw34
+COwhUNt59axA/F+VMhN0TVBH3qa70gNK/KU6NbdaekBhDO/Xa6F+DgILjSY4V6al
+QnnOaF2V9NvnDyo9xXeoCBlR1YuXCba3Iy3sRjChkCVmaYZPU78AfP00cNSwjnXr
+diHS267THEgHCkwgey6u68ECgYBmTXc2fZ3cEsyT8R6VcQqviK1sbAL7UIfT7hlL
+kooxF1C8Z/gmsqH7RB4faoFa9mVEE3YTNDrif6xfYwOAlOKGRVuuzMroNR6DtLI9
+H+6go/+NoXyywTI1qsLC73/7qoN5cECW4p2oUMTTl9Y2KPV4II1lypEBrUxFrdOL
+T7WioQKBgHH+GgdFi15Fde3J/VmRa7nPFrfo3utvcVXX0WBwKVJ/4AjP+ajI5059
++YZiopTZWPBCxOvGzcHCUVKiNdnYAvRMSVc21SU9+2/YDau5VtLuEq7+BXnDEVWY
+6d2FCGSOykrexS3VC5jzZb5ZzZrRtP3wYG3WktP3VxFLVVa211NP
+-----END RSA PRIVATE KEY-----

+ 52 - 0
test/data/client.crt

@@ -0,0 +1,52 @@
+Certificate:
+    Data:
+        Version: 1 (0x0)
+        Serial Number:
+            57:18:af:40:a5:9e:d6:44:ff:98:b0:68:8d:15:f9:af:14:e0:8e:c0
+        Signature Algorithm: NULL
+        Issuer: CN = epgsql_test_cert
+        Validity
+            Not Before: Feb 17 04:16:41 2019 GMT
+            Not After : Feb 14 04:16:41 2029 GMT
+        Subject: CN = epgsql_test_cert
+        Subject Public Key Info:
+            Public Key Algorithm: rsaEncryption
+                RSA Public-Key: (2048 bit)
+                Modulus:
+                    00:bc:79:66:ea:6b:ef:93:e5:f3:cd:aa:0d:62:57:
+                    d7:fb:a5:2a:62:49:43:13:40:02:11:82:25:b9:cd:
+                    8f:67:48:13:03:2a:a0:3b:30:67:bf:1c:9c:c8:7f:
+                    a5:10:63:c9:37:2b:bf:02:c5:d4:06:c3:63:4a:18:
+                    5d:05:97:64:5e:ff:ec:38:72:d8:84:33:1a:b5:26:
+                    f3:43:50:d2:07:0d:7b:ff:38:0a:60:1f:41:0e:1c:
+                    e3:7f:78:3c:2c:53:ec:0f:4d:e0:06:2b:ab:7f:2e:
+                    7a:8a:51:6e:7d:a3:17:35:0f:8e:b5:cb:c9:8d:af:
+                    6d:8f:ed:2d:ea:fb:c2:08:89:10:2d:98:33:60:4e:
+                    9f:b3:27:11:98:9d:f3:42:2b:73:dd:9c:ec:52:08:
+                    c9:f0:f5:19:96:3c:ff:48:9e:0d:16:ed:59:c3:5a:
+                    46:11:cb:b4:68:e8:70:95:ec:1f:be:f5:e1:a9:4e:
+                    17:95:87:76:2f:e6:90:3d:4a:ae:b0:3c:95:78:fc:
+                    27:81:40:f6:ed:a5:7c:a2:df:a9:fb:a4:77:76:5f:
+                    c9:d0:5c:4f:93:2d:ab:81:48:2f:0e:ae:07:d5:17:
+                    9c:2b:c1:f9:ca:ce:b2:f8:cd:ce:c0:7c:36:23:dc:
+                    1c:e0:7d:04:42:61:3f:ed:d2:cf:85:f8:77:44:ea:
+                    1d:c5
+                Exponent: 65537 (0x10001)
+    Signature Algorithm: NULL
+-----BEGIN CERTIFICATE-----
+MIICtjCCAZ4CFHY6YOsnigyFmdlh+oVOANI9KmmJMA0GCSqGSIb3DQEBCwUAMBQx
+EjAQBgNVBAMMCWVwZ3NxbCBDQTAeFw0xOTAyMTcwNDE2NDFaFw0yOTAyMTQwNDE2
+NDFaMBsxGTAXBgNVBAMMEGVwZ3NxbF90ZXN0X2NlcnQwggEiMA0GCSqGSIb3DQEB
+AQUAA4IBDwAwggEKAoIBAQC8eWbqa++T5fPNqg1iV9f7pSpiSUMTQAIRgiW5zY9n
+SBMDKqA7MGe/HJzIf6UQY8k3K78CxdQGw2NKGF0Fl2Re/+w4ctiEMxq1JvNDUNIH
+DXv/OApgH0EOHON/eDwsU+wPTeAGK6t/LnqKUW59oxc1D461y8mNr22P7S3q+8II
+iRAtmDNgTp+zJxGYnfNCK3PdnOxSCMnw9RmWPP9Ing0W7VnDWkYRy7Ro6HCV7B++
+9eGpTheVh3Yv5pA9Sq6wPJV4/CeBQPbtpXyi36n7pHd2X8nQXE+TLauBSC8OrgfV
+F5wrwfnKzrL4zc7AfDYj3BzgfQRCYT/t0s+F+HdE6h3FAgMBAAEwDQYJKoZIhvcN
+AQELBQADggEBAEtXSn7A97ZRa98Ca89JyzNTw9Huj47hP6noDHh4bcwoFcsKbAOI
+7h0/goY78XJSdl1/NLnYRG4Bv+xCWr6LhrYIQXkUtaq+buGIb1sO1PqXLoVU7YtA
+gpd9v9luqBIMi30YT5HHS1nKG/tNTVhqrcs1SfQ05M7KQM8wZPPaZtNm3xz6notH
+rPP/1sfymjKo8mE9EZc4t6sDp1ahT34w8bSdfvqolSllsbh1dGn1jKmGg694517T
+HbwMv4zACqZnR2ed2Ska3FPgL/y3TwlQfxiVHO2Fpomn5b9TOG54W/1pwKnLlKa8
+yTZx7H2jDHvsEaLHqdOytD9B6RlaL3tiDe8=
+-----END CERTIFICATE-----

+ 27 - 0
test/data/client.key

@@ -0,0 +1,27 @@
+-----BEGIN RSA PRIVATE KEY-----
+MIIEowIBAAKCAQEAvHlm6mvvk+XzzaoNYlfX+6UqYklDE0ACEYIluc2PZ0gTAyqg
+OzBnvxycyH+lEGPJNyu/AsXUBsNjShhdBZdkXv/sOHLYhDMatSbzQ1DSBw17/zgK
+YB9BDhzjf3g8LFPsD03gBiurfy56ilFufaMXNQ+OtcvJja9tj+0t6vvCCIkQLZgz
+YE6fsycRmJ3zQitz3ZzsUgjJ8PUZljz/SJ4NFu1Zw1pGEcu0aOhwlewfvvXhqU4X
+lYd2L+aQPUqusDyVePwngUD27aV8ot+p+6R3dl/J0FxPky2rgUgvDq4H1RecK8H5
+ys6y+M3OwHw2I9wc4H0EQmE/7dLPhfh3ROodxQIDAQABAoIBAQCih/7cQWBFJpRs
+0yzflelHtVMrlwok25ntB1MJO99iraDXpjavVDrjcAU0Uf9CdwrabPs3pOoHOw+w
+ofn2DGweEIzg0QkuV/O8LG6zqkq0kkhP+z/XTJyJUxhMoJ8jiuuS9xEtwRMPhkFe
+boLeDXrB4zyqQab6bEILT/m9HoZhXHRqF/yER02unfOBHCLWXCvk98Ohqog1XEWL
+81U+xqmIhNtrveI5UTnQkccXXrROVEuqQYj06NpdhZecpeCCAbZSqnUzIEMGsTmI
+CqMU24HI9UIR9NYgdzUhqcpxXsGSPvII9dLrtc2UDzDYyxmt9SnCBJS0Z8VGn1Vp
+81cj8nyBAoGBAPS8uvrX/RHum/ijuug9/khgBjXribzVulIBvhQmzoBPCZgyXrqX
++2p2cnP0yNPBfu3nJUM2C0OxVUurY9i6FEdZi30HQgNtsfYSVZ6lD74QHyuQ19rT
+8ZvFU9rMCPlkTpwhhUcckbY7PVFbQelYbNM62wM5HtVWSqJxOZKTlUMZAoGBAMUl
+1SDHEI2Kp9MBGb5qwFH83+Q3XA4tBSKJBcoFAJiUcI6rA2rm5B1d6DDg9k815uGA
+VB5ucWt8OvaKVuUlRje+kttMp/irG+lOXmZxDxF4/dY4dL8npaHbqsjbvix+u/iz
+ywodZMCKoQvYX2oD889CKxitO2o3/Ss1gEB3q5GNAoGALukmJgLUnWVRPD2WDAIm
+BZVyW0+EnU+SYTm4R4CQwINl4Wh2Q+nx5RxDH/rhq8VBITTXLaTkT9tj8BcwElDI
+pkyBsjt76dBS9knZY4lcFSBd+SnQVj+d5i/SvPOzHKqfbsn2FAVj4LxGKpwFbEbo
+xSxY4qtGP7pEoBJ36KKlT7ECgYAvqi72Rsq8vepHfLuhqyOmbvIetje+gan9KI3K
+wxzaxwDTrYsc/IfohbzOnIVQr2KL4L/1v5QSfa2vz9CkhDeO4LeW59iwqYYNCVKP
+iAQxoEQW1/15/fbwxDBtcZtwHJAL2ERdxK+IUbwQJhcjhaMb2A6dX7y+uJywJrZE
+X+qOPQKBgHnEQsL2MH+vVqblYTkdJRT+suCWhzugJr6lCHMIEyuxT70JFcLBxe0B
+O85WOr0OGMsRguJUr8Zaw4Iy4Inq5p3Egl0fb1tSoMgV0kwa4BZ0EEFL8bO54sm7
+fQfu1BGD+TSh1yvwPEJ/lcGp4kcIfcuhRxdur0euOpeUBuZEp+t/
+-----END RSA PRIVATE KEY-----

+ 0 - 18
test/data/epgsql.crt

@@ -1,18 +0,0 @@
------BEGIN CERTIFICATE-----
-MIIC6jCCAlOgAwIBAgIJAKwIWpOFC5EWMA0GCSqGSIb3DQEBBQUAMGQxCzAJBgNV
-BAYTAlVTMRMwEQYDVQQIEwpDYWxpZm9ybmlhMRYwFAYDVQQHEw1TYW4gRnJhbmNp
-c2NvMRQwEgYDVQQKEwtsYW1iZGFXb3JrczESMBAGA1UEAxMJZXBnc3FsIENBMB4X
-DTA5MDMyNzA0MzAxM1oXDTE5MDIwMzA0MzAxM1owazELMAkGA1UEBhMCVVMxEzAR
-BgNVBAgTCkNhbGlmb3JuaWExFjAUBgNVBAcTDVNhbiBGcmFuY2lzY28xFDASBgNV
-BAoTC2xhbWJkYVdvcmtzMRkwFwYDVQQDFBBlcGdzcWxfdGVzdF9jZXJ0MIGfMA0G
-CSqGSIb3DQEBAQUAA4GNADCBiQKBgQCxnVk30edKqkIWWzTeWJHlc5Zco5MASAqz
-J6fC4HmR4y+StFB88NZE/ESKbWXNOD464fku72m5i4DI1NftGgZLVjjrFmLEE05S
-hymkqWtVb+H9RBD2SHl4VjwDUsMDHZGiXL3n02uWF+NtpeQHkacfav10ZQO0nnub
-njCUV3EHoQIDAQABo4GcMIGZMIGWBgNVHSMEgY4wgYuAFO5OzTWlO3ao7YAytIBW
-A3A1GXDaoWikZjBkMQswCQYDVQQGEwJVUzETMBEGA1UECBMKQ2FsaWZvcm5pYTEW
-MBQGA1UEBxMNU2FuIEZyYW5jaXNjbzEUMBIGA1UEChMLbGFtYmRhV29ya3MxEjAQ
-BgNVBAMTCWVwZ3NxbCBDQYIJAIFM8k/soL/qMA0GCSqGSIb3DQEBBQUAA4GBAHhy
-nE3/U1DiqHNf+AaCktVoHlsjfXvfrhouqR7T84kxCjAHzM6q183ga4S9NhLeyhCT
-oiDnIoUlUg7v1h9wTvXAoO2NwkCpSbIUncj6Q2h6J8obWq/BDSJwbdPcCHe4un8P
-hEpkiEK1QMMm5h9d+jgE8mrgGZXMnvzw40ovJHON
------END CERTIFICATE-----

+ 0 - 15
test/data/epgsql.key

@@ -1,15 +0,0 @@
------BEGIN RSA PRIVATE KEY-----
-MIICXgIBAAKBgQCxnVk30edKqkIWWzTeWJHlc5Zco5MASAqzJ6fC4HmR4y+StFB8
-8NZE/ESKbWXNOD464fku72m5i4DI1NftGgZLVjjrFmLEE05ShymkqWtVb+H9RBD2
-SHl4VjwDUsMDHZGiXL3n02uWF+NtpeQHkacfav10ZQO0nnubnjCUV3EHoQIDAQAB
-AoGARXSemvF+XPhPd6aa+gfwpaWZuwhMR+PkK0Lqm45ke+Q3ikrw3qrfX4K22tsE
-4EeKLkSHyQ7ebSxcZCy3c4SlyNES88wk7epGYbui4L0Iv/1WXfg1zIRqdNgBMr6M
-ZUZoUJx1gyRY2S3zGjTBn8b4Wh9EwsD0KTluvtH74DtLPQECQQDiLhIVasTsgKpn
-SoLVJ+UqpQ8oe17m4gHbwMOK2s+o479oKuAbmwgUX8U2waoncq06vG+x3gziVIOF
-Qkj6s6rZAkEAyQgfN01SoNOwp61Nis8TWeltqZdh0VHYqpu/ARfUpsTAWHGhc4eK
-Ee+J1DmxrUAP+s25Z640Ps9jNTugrWB2CQJBAJ+XyHTKQKdsZlC517VWEDLWAusa
-mi0pvgv0aUW5/Zr7EJ0M29M+wiW2Ke7oGgr5tNfkDKAhwU+WOLM3wUz8p4kCQQCr
-5zcSShtzDTINYCNjpElO5E3y7FEn9g4Jbd7550/fP3We66P8r5VAWw4IHUGy/Yns
-lIiLgSqJ3ztdZNy0BT1JAkEAhPz9yMZN7NBfdTjM1ebp4VirL8uQAdod/d3oRN87
-dqVxywRm4dZ4hMD2Fr6CuLsZylCQKEt1jNEfjZzRC4hR2g==
------END RSA PRIVATE KEY-----

+ 62 - 48
test/data/root.crt

@@ -2,62 +2,76 @@ Certificate:
     Data:
         Version: 3 (0x2)
         Serial Number:
-            81:4c:f2:4f:ec:a0:bf:ea
-        Signature Algorithm: sha1WithRSAEncryption
-        Issuer: C=US, ST=California, L=San Francisco, O=lambdaWorks, CN=epgsql CA
+            7a:3d:30:e0:8a:4f:f3:f9:40:8b:2b:75:e8:33:fa:e4:4a:3b:7c:a8
+        Signature Algorithm: sha256WithRSAEncryption
+        Issuer: CN = epgsql CA
         Validity
-            Not Before: Mar 27 03:52:34 2009 GMT
-            Not After : Feb  3 03:52:34 2019 GMT
-        Subject: C=US, ST=California, L=San Francisco, O=lambdaWorks, CN=epgsql CA
+            Not Before: Feb 17 04:16:40 2019 GMT
+            Not After : Feb 14 04:16:40 2029 GMT
+        Subject: CN = epgsql CA
         Subject Public Key Info:
             Public Key Algorithm: rsaEncryption
-            RSA Public Key: (1024 bit)
-                Modulus (1024 bit):
-                    00:bd:03:59:e5:ce:5d:24:45:ae:bf:cd:a4:4a:d4:
-                    33:7a:48:08:79:8a:20:4c:b6:28:51:f8:f0:9a:1d:
-                    1e:fb:b8:de:a3:b7:10:95:d7:a3:58:b7:94:b4:7e:
-                    36:0a:0c:68:1c:e8:21:a5:5d:9d:0a:3a:5d:26:dd:
-                    bb:5b:62:59:e0:1f:b8:48:a7:3d:28:dd:f3:b9:de:
-                    27:d7:25:4b:f6:8a:ac:ef:a3:0e:b3:fb:1b:b8:dd:
-                    db:01:72:01:1f:79:5b:f8:c3:54:7e:1a:94:68:1d:
-                    81:2c:05:11:05:2c:5b:81:05:21:19:c0:c7:94:4f:
-                    77:f5:76:4c:98:8d:ab:68:5b
+                RSA Public-Key: (2048 bit)
+                Modulus:
+                    00:a6:f4:7a:8e:90:38:4d:6e:06:00:ca:96:f6:81:
+                    d6:ec:2d:a2:56:8e:4e:72:dc:b7:45:03:d8:b7:e1:
+                    a5:b4:f6:29:94:b8:1d:5e:c9:24:8a:3d:c2:b3:f9:
+                    ae:a2:02:03:d8:94:3b:ef:5b:c1:4b:54:bc:af:a3:
+                    53:2d:84:59:82:11:d1:82:46:5c:7f:3f:65:f9:8e:
+                    ff:50:aa:f9:11:aa:62:cd:d3:8c:6e:a5:e3:c3:d1:
+                    8e:23:5a:b4:63:90:11:fc:11:17:62:a2:46:d5:19:
+                    cf:f0:4c:55:3c:74:8c:6a:d8:34:57:46:5d:e8:6b:
+                    2f:a6:15:a9:4d:a3:dc:48:0b:29:ff:7e:8c:21:4b:
+                    f1:81:fc:62:91:2a:76:42:ad:63:e6:d1:f3:37:cc:
+                    b3:04:99:65:a5:97:47:62:fc:11:fe:d2:38:49:98:
+                    7c:1a:28:5b:25:47:c3:78:b4:48:16:94:db:56:4d:
+                    c1:5a:76:1d:64:f5:af:84:47:96:38:a0:25:08:88:
+                    84:ea:2d:84:aa:d9:80:80:e0:b0:16:de:a2:0e:88:
+                    5a:61:42:50:f1:e4:39:d9:7a:5c:55:26:b8:ae:15:
+                    77:a8:a2:88:2a:2e:2d:de:90:a1:59:34:c3:1c:b9:
+                    ed:3f:b0:95:8c:fc:23:ad:10:31:bc:76:9c:f7:17:
+                    58:f9
                 Exponent: 65537 (0x10001)
         X509v3 extensions:
             X509v3 Subject Key Identifier: 
-                EE:4E:CD:35:A5:3B:76:A8:ED:80:32:B4:80:56:03:70:35:19:70:DA
+                3C:2E:F9:C6:93:9E:90:CF:F8:81:52:24:C1:7B:D4:C4:E2:8A:43:22
             X509v3 Authority Key Identifier: 
-                keyid:EE:4E:CD:35:A5:3B:76:A8:ED:80:32:B4:80:56:03:70:35:19:70:DA
-                DirName:/C=US/ST=California/L=San Francisco/O=lambdaWorks/CN=epgsql CA
-                serial:81:4C:F2:4F:EC:A0:BF:EA
+                keyid:3C:2E:F9:C6:93:9E:90:CF:F8:81:52:24:C1:7B:D4:C4:E2:8A:43:22
 
-            X509v3 Basic Constraints: 
+            X509v3 Basic Constraints: critical
                 CA:TRUE
-    Signature Algorithm: sha1WithRSAEncryption
-        27:4c:04:ee:27:46:23:9b:6f:7c:8f:5b:9e:c6:65:74:33:40:
-        06:be:ca:e0:55:91:1c:9e:1c:77:27:82:03:4e:67:91:5d:14:
-        e4:74:b7:88:9e:49:d6:02:5b:71:94:b3:62:2a:5e:58:00:7d:
-        8c:42:09:db:ca:27:20:71:33:16:09:d2:17:36:d4:4f:63:09:
-        0a:48:80:d7:36:13:24:57:e3:7a:7e:25:4e:b8:f0:71:c6:34:
-        69:4e:e1:4b:5a:ec:b3:be:14:78:1e:af:85:b2:56:91:62:03:
-        6b:b2:85:2e:8e:ef:4b:5a:bf:ac:54:43:24:cb:0e:c6:f8:58:
-        b5:a1
+    Signature Algorithm: sha256WithRSAEncryption
+         8c:f8:96:3e:af:f6:fe:34:77:13:8f:c4:7d:1b:51:70:6f:aa:
+         d9:0d:5f:c5:50:6b:b9:86:6c:35:d2:38:18:89:37:9f:75:96:
+         05:8c:7a:20:d0:cc:3c:18:d4:f1:c6:8a:5d:c2:b0:fc:fe:3a:
+         20:dd:71:ea:12:a3:e8:53:06:31:00:75:54:b3:06:69:a8:71:
+         36:e1:9d:e9:9d:1f:be:06:69:ea:03:16:a1:75:c6:bf:34:3d:
+         18:b6:03:b9:c5:63:f7:06:21:e0:16:46:d2:d9:b4:ea:b0:1a:
+         fc:10:95:09:e4:b5:3c:bd:40:d8:c4:3b:2c:57:db:45:c7:ae:
+         6a:8b:40:e6:2c:b1:c3:72:ce:64:10:7d:1e:e4:f7:96:04:38:
+         18:b4:17:7d:4c:44:61:a6:1d:d2:cd:3a:85:c2:2e:0a:39:2c:
+         28:0a:f8:97:88:51:cf:1b:7e:d5:6d:7b:93:5a:30:19:ca:13:
+         34:5a:9d:ee:c1:00:95:63:21:e6:11:21:62:90:0e:8e:c9:8f:
+         18:a4:40:ae:59:f8:ec:dc:7d:a5:6d:91:b2:d1:85:c2:c0:d3:
+         52:3c:f3:fe:f8:27:c8:37:61:be:0e:80:2b:d2:26:1b:4d:75:
+         81:22:9c:ff:21:0c:a0:64:ce:85:d4:0e:60:1e:0b:6d:04:a8:
+         60:30:2b:5f
 -----BEGIN CERTIFICATE-----
-MIIDEDCCAnmgAwIBAgIJAIFM8k/soL/qMA0GCSqGSIb3DQEBBQUAMGQxCzAJBgNV
-BAYTAlVTMRMwEQYDVQQIEwpDYWxpZm9ybmlhMRYwFAYDVQQHEw1TYW4gRnJhbmNp
-c2NvMRQwEgYDVQQKEwtsYW1iZGFXb3JrczESMBAGA1UEAxMJZXBnc3FsIENBMB4X
-DTA5MDMyNzAzNTIzNFoXDTE5MDIwMzAzNTIzNFowZDELMAkGA1UEBhMCVVMxEzAR
-BgNVBAgTCkNhbGlmb3JuaWExFjAUBgNVBAcTDVNhbiBGcmFuY2lzY28xFDASBgNV
-BAoTC2xhbWJkYVdvcmtzMRIwEAYDVQQDEwllcGdzcWwgQ0EwgZ8wDQYJKoZIhvcN
-AQEBBQADgY0AMIGJAoGBAL0DWeXOXSRFrr/NpErUM3pICHmKIEy2KFH48JodHvu4
-3qO3EJXXo1i3lLR+NgoMaBzoIaVdnQo6XSbdu1tiWeAfuEinPSjd87neJ9clS/aK
-rO+jDrP7G7jd2wFyAR95W/jDVH4alGgdgSwFEQUsW4EFIRnAx5RPd/V2TJiNq2hb
-AgMBAAGjgckwgcYwHQYDVR0OBBYEFO5OzTWlO3ao7YAytIBWA3A1GXDaMIGWBgNV
-HSMEgY4wgYuAFO5OzTWlO3ao7YAytIBWA3A1GXDaoWikZjBkMQswCQYDVQQGEwJV
-UzETMBEGA1UECBMKQ2FsaWZvcm5pYTEWMBQGA1UEBxMNU2FuIEZyYW5jaXNjbzEU
-MBIGA1UEChMLbGFtYmRhV29ya3MxEjAQBgNVBAMTCWVwZ3NxbCBDQYIJAIFM8k/s
-oL/qMAwGA1UdEwQFMAMBAf8wDQYJKoZIhvcNAQEFBQADgYEAJ0wE7idGI5tvfI9b
-nsZldDNABr7K4FWRHJ4cdyeCA05nkV0U5HS3iJ5J1gJbcZSzYipeWAB9jEIJ28on
-IHEzFgnSFzbUT2MJCkiA1zYTJFfjen4lTrjwccY0aU7hS1rss74UeB6vhbJWkWID
-a7KFLo7vS1q/rFRDJMsOxvhYtaE=
+MIIDCTCCAfGgAwIBAgIUej0w4IpP8/lAiyt16DP65Eo7fKgwDQYJKoZIhvcNAQEL
+BQAwFDESMBAGA1UEAwwJZXBnc3FsIENBMB4XDTE5MDIxNzA0MTY0MFoXDTI5MDIx
+NDA0MTY0MFowFDESMBAGA1UEAwwJZXBnc3FsIENBMIIBIjANBgkqhkiG9w0BAQEF
+AAOCAQ8AMIIBCgKCAQEApvR6jpA4TW4GAMqW9oHW7C2iVo5Octy3RQPYt+GltPYp
+lLgdXskkij3Cs/muogID2JQ771vBS1S8r6NTLYRZghHRgkZcfz9l+Y7/UKr5Eapi
+zdOMbqXjw9GOI1q0Y5AR/BEXYqJG1RnP8ExVPHSMatg0V0Zd6GsvphWpTaPcSAsp
+/36MIUvxgfxikSp2Qq1j5tHzN8yzBJllpZdHYvwR/tI4SZh8GihbJUfDeLRIFpTb
+Vk3BWnYdZPWvhEeWOKAlCIiE6i2EqtmAgOCwFt6iDohaYUJQ8eQ52XpcVSa4rhV3
+qKKIKi4t3pChWTTDHLntP7CVjPwjrRAxvHac9xdY+QIDAQABo1MwUTAdBgNVHQ4E
+FgQUPC75xpOekM/4gVIkwXvUxOKKQyIwHwYDVR0jBBgwFoAUPC75xpOekM/4gVIk
+wXvUxOKKQyIwDwYDVR0TAQH/BAUwAwEB/zANBgkqhkiG9w0BAQsFAAOCAQEAjPiW
+Pq/2/jR3E4/EfRtRcG+q2Q1fxVBruYZsNdI4GIk3n3WWBYx6INDMPBjU8caKXcKw
+/P46IN1x6hKj6FMGMQB1VLMGaahxNuGd6Z0fvgZp6gMWoXXGvzQ9GLYDucVj9wYh
+4BZG0tm06rAa/BCVCeS1PL1A2MQ7LFfbRceuaotA5iyxw3LOZBB9HuT3lgQ4GLQX
+fUxEYaYd0s06hcIuCjksKAr4l4hRzxt+1W17k1owGcoTNFqd7sEAlWMh5hEhYpAO
+jsmPGKRArln47Nx9pW2RstGFwsDTUjzz/vgnyDdhvg6AK9ImG011gSKc/yEMoGTO
+hdQOYB4LbQSoYDArXw==
 -----END CERTIFICATE-----

+ 25 - 13
test/data/root.key

@@ -1,15 +1,27 @@
 -----BEGIN RSA PRIVATE KEY-----
-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
+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
 -----END RSA PRIVATE KEY-----

+ 52 - 0
test/data/server.crt

@@ -0,0 +1,52 @@
+Certificate:
+    Data:
+        Version: 1 (0x0)
+        Serial Number:
+            0e:9f:3c:e6:3c:ca:ee:bd:d6:81:62:b0:40:50:ee:29:c2:3c:d2:45
+        Signature Algorithm: NULL
+        Issuer: CN = epgsql server
+        Validity
+            Not Before: Feb 17 04:16:40 2019 GMT
+            Not After : Feb 14 04:16:40 2029 GMT
+        Subject: CN = epgsql server
+        Subject Public Key Info:
+            Public Key Algorithm: rsaEncryption
+                RSA Public-Key: (2048 bit)
+                Modulus:
+                    00:ab:77:8d:54:16:e7:50:70:e1:e5:f1:e0:6f:c7:
+                    9d:78:85:be:91:4a:63:41:71:08:de:23:8c:98:44:
+                    8f:cf:75:f9:20:d7:62:95:c2:61:5d:19:78:d3:10:
+                    a5:1c:f0:39:9e:a6:00:b0:98:aa:02:2a:ee:c4:9d:
+                    07:05:3b:c6:35:b5:a4:f5:d2:32:73:d9:62:21:17:
+                    3e:10:2f:e9:e9:06:11:5e:36:43:1f:95:e8:aa:55:
+                    56:6b:ed:32:b6:f1:49:ff:13:42:78:e6:95:4f:c0:
+                    57:77:e0:9f:1c:aa:83:f4:09:fe:af:d3:25:bf:ef:
+                    b6:2d:35:79:b1:47:ed:ae:2b:c8:2f:42:7c:2f:ef:
+                    f3:1b:59:d0:69:b4:76:33:f2:7a:2f:0b:a5:4a:0d:
+                    c9:2d:f8:e3:01:0f:b3:6e:53:c5:a9:32:43:86:1d:
+                    af:73:c7:bd:61:94:dc:58:f9:96:01:6b:26:1e:65:
+                    e5:4d:b8:5b:eb:17:62:a5:29:d9:84:fc:a9:e7:22:
+                    13:ea:23:5b:76:c2:50:b2:d6:4a:29:9f:21:92:57:
+                    79:de:54:e8:9a:86:be:fd:58:5e:9d:9b:90:47:e1:
+                    82:1e:35:73:52:ae:41:9e:96:93:a3:8c:39:3f:35:
+                    b7:61:80:07:35:73:d0:ce:88:46:ea:ae:c4:2a:ba:
+                    2f:97
+                Exponent: 65537 (0x10001)
+    Signature Algorithm: NULL
+-----BEGIN CERTIFICATE-----
+MIICszCCAZsCFHY6YOsnigyFmdlh+oVOANI9KmmIMA0GCSqGSIb3DQEBCwUAMBQx
+EjAQBgNVBAMMCWVwZ3NxbCBDQTAeFw0xOTAyMTcwNDE2NDBaFw0yOTAyMTQwNDE2
+NDBaMBgxFjAUBgNVBAMMDWVwZ3NxbCBzZXJ2ZXIwggEiMA0GCSqGSIb3DQEBAQUA
+A4IBDwAwggEKAoIBAQCrd41UFudQcOHl8eBvx514hb6RSmNBcQjeI4yYRI/Pdfkg
+12KVwmFdGXjTEKUc8DmepgCwmKoCKu7EnQcFO8Y1taT10jJz2WIhFz4QL+npBhFe
+NkMfleiqVVZr7TK28Un/E0J45pVPwFd34J8cqoP0Cf6v0yW/77YtNXmxR+2uK8gv
+Qnwv7/MbWdBptHYz8novC6VKDckt+OMBD7NuU8WpMkOGHa9zx71hlNxY+ZYBayYe
+ZeVNuFvrF2KlKdmE/KnnIhPqI1t2wlCy1kopnyGSV3neVOiahr79WF6dm5BH4YIe
+NXNSrkGelpOjjDk/NbdhgAc1c9DOiEbqrsQqui+XAgMBAAEwDQYJKoZIhvcNAQEL
+BQADggEBABViHTwaK/0W6QgV3ogywia5XQHqvm8tMhFXQD2m+6IcuzHCDq8xu8f1
+n7+V7+c3Nc3jLIg8CuiFtI8oeoxuH/ccLAURDV7Rxgiv7+pqbNqSQzvlvzU/ogGI
+eUITW+fHujoOjoq07gayyZDogFIRjIyMty+YLQWg+9IjxySx8324R7QvM8Tl6EhB
+5AmyOHZPqzl3ZMaZxRWSDYu2ZbzYn9i036Gnuxoyg4bxgz0hOkedOMOffqOOLHCi
+fDjzbqMhy0vhTxGLRIoqE16/kFi5snYD5/y20yAldjGCUSD0BU08AvdC8djYlDpv
+K6dFasYmHFa2E2fifxixS2Dl6YksWq8=
+-----END CERTIFICATE-----

+ 27 - 0
test/data/server.key

@@ -0,0 +1,27 @@
+-----BEGIN RSA PRIVATE KEY-----
+MIIEowIBAAKCAQEAq3eNVBbnUHDh5fHgb8edeIW+kUpjQXEI3iOMmESPz3X5INdi
+lcJhXRl40xClHPA5nqYAsJiqAiruxJ0HBTvGNbWk9dIyc9liIRc+EC/p6QYRXjZD
+H5XoqlVWa+0ytvFJ/xNCeOaVT8BXd+CfHKqD9An+r9Mlv++2LTV5sUftrivIL0J8
+L+/zG1nQabR2M/J6LwulSg3JLfjjAQ+zblPFqTJDhh2vc8e9YZTcWPmWAWsmHmXl
+Tbhb6xdipSnZhPyp5yIT6iNbdsJQstZKKZ8hkld53lTomoa+/VhenZuQR+GCHjVz
+Uq5BnpaTo4w5PzW3YYAHNXPQzohG6q7EKrovlwIDAQABAoIBAAbq59TAp8xjAXoZ
+bAiWcQ/vtWR/L8nwGX98x6tM+NBR3h8pEV0hXnQ3FtzNCxxDxM9Vuylkv1cfDEr6
+WtInOzPnhCQ2urpZxs+29FYK2NEB4al/Xu3jSmO01au9AhLHYUjdKg1eoB97jwvT
+EBhD+NbboF7PkfJQZXUldydj0373TEiLfZ8RcOeej0qc9ishNcj4+xWiWOpZWnL+
+Ei/UD0TdSI9zitgeVL5jJzo8BoGJCP9yCPaE1pQURtvq+xDDOehBBcr5j0MPJ7Hx
+zI8ov2DCWbv/cx1+Bckxf75UQMITmV3OtqRaipDXUhISFfg7tvRP4bYXCoKJY6MB
+uImZ70ECgYEA3pjA9U4z7a2kNFEz2FQJiHkpxETEuSP0ZossHDIdMsLa3IhhM4gL
+u80MjsHl02Sq+fz3buHm9bbNyh+bFn56uwu/thcWfVpj9EuVIkbyMILRdUCaTWBP
+1eHyyDfnK7bWKTkkfZsUifF+4LSpkltDt6MNKI3K+9R1a7YQJ8mlAXkCgYEAxTKb
+RAURnYgY3KjwFMOyon3YMO/YgElQUXAHfqbjZLj5iingqtDlwA7tOt2i/I4T+C/a
+3WMfhqXf98bU9ckX8Z5LtJP7/1umhJNC2Y9IAATmNllzbjXYGAuWS6qkmiyzfGOz
+91tPdkiZ7zdLN4NYtcTCEZYolIibXCKsNc//BY8CgYEAzGspoN0dcSMqjeUYoIyk
+aJEkmxqwMnnjYxxh+M7I46nwReB0q1c/t0raQmusfNKQ9ZyrOkf4yyQCnqEh0ql6
+WjWy7C0NuTZ+XoXewii3F3e7lVsrmO1ew8OJKvezswBoclkIutTlKrz9UKx4oXBw
+or75QYndpCD7aFw9P9y9TLkCgYAbj98zuqGjqwoOjW5A+LlXDM/SxzMzewvG1im2
+Ag12XoRCU2gbd+ck2PE/cQr+0bzoy4eDuf8GCtkrAJdzYw/9rWpXavel0WGM1ihZ
+0DT4C7dBkW8Y0F3LvpLbMJahFe5gTG8y+4g3uB4L2Wah87HKdh3J53r0h8NvNUls
+nA3A8QKBgCHe5zbtGI0w/ls2ZMKMm3R7Cobu0CKmhfn8Z2I76x5vyJ1Qig+XvWQM
+BJMFZgwylWY5/qwW26UhV0dYRTuWiDbi40Wz9RWrH4QV554CGTdwrkI8UxXGmVoP
+2jEYBpH7JVql7Cs2hzudJHtvbMTEUq43w1XDMSRzknzdXSryp2vw
+-----END RSA PRIVATE KEY-----

+ 27 - 5
test/epgsql_SUITE.erl

@@ -45,6 +45,7 @@ groups() ->
             connect_with_other_error,
             connect_with_ssl,
             connect_with_client_cert,
+            connect_with_invalid_client_cert,
             connect_to_closed_port,
             connect_map,
             connect_proplist
@@ -269,7 +270,7 @@ connect_with_client_cert(Config) ->
     Module = ?config(module, Config),
     Dir = filename:join(code:lib_dir(epgsql), ?TEST_DATA_DIR),
     File = fun(Name) -> filename:join(Dir, Name) end,
-    {ok, Pem} = file:read_file(File("epgsql.crt")),
+    {ok, Pem} = file:read_file(File("client.crt")),
     [{'Certificate', Der, not_encrypted}] = public_key:pem_decode(Pem),
     Cert = public_key:pkix_decode_cert(Der, plain),
     #'TBSCertificate'{serialNumber = Serial} = Cert#'Certificate'.tbsCertificate,
@@ -277,12 +278,33 @@ connect_with_client_cert(Config) ->
 
     epgsql_ct:with_connection(Config,
          fun(C) ->
-             {ok, _, [{true}]} = Module:equery(C, "select ssl_is_used()"),
-             {ok, _, [{Serial2}]} = Module:equery(C, "select ssl_client_serial()")
+             ?assertMatch({ok, _, [{true}]}, Module:equery(C, "select ssl_is_used()")),
+             ?assertMatch({ok, _, [{Serial2}]}, Module:equery(C, "select ssl_client_serial()"))
          end,
          "epgsql_test_cert",
-        [{ssl, true}, {ssl_opts, [{keyfile, File("epgsql.key")},
-                                  {certfile, File("epgsql.crt")}]}]).
+        [{ssl, true}, {ssl_opts, [{keyfile, File("client.key")},
+                                  {certfile, File("client.crt")}]}]).
+
+connect_with_invalid_client_cert(Config) ->
+    {Host, Port} = epgsql_ct:connection_data(Config),
+    Module = ?config(module, Config),
+    Dir = filename:join(code:lib_dir(epgsql), ?TEST_DATA_DIR),
+    File = fun(Name) -> filename:join(Dir, Name) end,
+    Trap = process_flag(trap_exit, true),
+    ?assertMatch(
+       {error, {ssl_negotiation_failed, _}},
+       Module:connect(
+         #{username => "epgsql_test_cert",
+           database => "epgsql_test_db1",
+           host => Host,
+           port => Port,
+           ssl => true,
+           ssl_opts =>
+               [{keyfile, File("bad-client.key")},
+                {certfile, File("bad-client.crt")}]}
+        )),
+    ?assertMatch({'EXIT', _, {ssl_negotiation_failed, _}}, receive Stop -> Stop end),
+    process_flag(trap_exit, Trap).
 
 connect_map(Config) ->
     {Host, Port} = epgsql_ct:connection_data(Config),

+ 2 - 2
test/epgsql_cth.erl

@@ -182,8 +182,8 @@ copy_certs(Config) ->
     PgDataDir = ?config(datadir, Config),
 
     Files = [
-        {"epgsql.crt", "server.crt", 8#00660},
-        {"epgsql.key", "server.key", 8#00600},
+        {"server.crt", "server.crt", 8#00660},
+        {"server.key", "server.key", 8#00600},
         {"root.crt", "root.crt", 8#00660},
         {"root.key", "root.key", 8#00660}
     ],