]> granicus.if.org Git - pgbouncer/commitdiff
Sync with TLS API changes
authorMarko Kreen <markokr@gmail.com>
Tue, 15 Sep 2015 21:14:21 +0000 (00:14 +0300)
committerMarko Kreen <markokr@gmail.com>
Tue, 15 Sep 2015 21:14:21 +0000 (00:14 +0300)
lib
src/client.c
src/sbuf.c

diff --git a/lib b/lib
index fdbab1ce299803bdf59368626848df27e392d330..16249b5e76ceb04b46ed596e13001d9fee483e2f 160000 (submodule)
--- a/lib
+++ b/lib
@@ -1 +1 @@
-Subproject commit fdbab1ce299803bdf59368626848df27e392d330
+Subproject commit 16249b5e76ceb04b46ed596e13001d9fee483e2f
index 2b01ff2ccdb45089055fa35d22f79ffa17f4761e..5951d3964cddaa90dcdbdc04c52e4d1c711e7cc5 100644 (file)
@@ -118,41 +118,24 @@ static void start_auth_request(PgSocket *client, const char *username)
 static bool login_via_cert(PgSocket *client)
 {
        struct tls *tls = client->sbuf.tls;
-       struct tls_cert *cert;
-       struct tls_cert_dname *subj;
 
        if (!tls) {
                disconnect_client(client, true, "TLS connection required");
                return false;
        }
-       if (tls_get_peer_cert(client->sbuf.tls, &cert, NULL) < 0 || !cert) {
+       if (!tls_peer_cert_provided(client->sbuf.tls)) {
                disconnect_client(client, true, "TLS client certificate required");
                return false;
        }
 
-       subj = &cert->subject;
-       log_debug("TLS cert login: CN=%s/C=%s/L=%s/ST=%s/O=%s/OU=%s",
-                 subj->common_name ? subj->common_name : "(null)",
-                 subj->country_name ? subj->country_name : "(null)",
-                 subj->locality_name ? subj->locality_name : "(null)",
-                 subj->state_or_province_name ? subj->state_or_province_name : "(null)",
-                 subj->organization_name ? subj->organization_name : "(null)",
-                 subj->organizational_unit_name ? subj->organizational_unit_name : "(null)");
-       if (!subj->common_name) {
-               disconnect_client(client, true, "Invalid TLS certificate");
-               goto fail;
-       }
-       if (strcmp(subj->common_name, client->auth_user->name) != 0) {
+       log_debug("TLS cert login: %s", tls_peer_cert_subject(client->sbuf.tls));
+       if (!tls_peer_cert_contains_name(client->sbuf.tls, client->auth_user->name)) {
                disconnect_client(client, true, "TLS certificate name mismatch");
-               goto fail;
+               return false;
        }
-       tls_cert_free(cert);
 
        /* login successful */
        return finish_client_login(client);
-fail:
-       tls_cert_free(cert);
-       return false;
 }
 
 static bool login_as_unix_peer(PgSocket *client)
index 6b93bc2011980964a7e4789f140cad3e15b9db2f..ab69fbf0dbc89090aeadcb577f903f45de9f1e8a 100644 (file)
@@ -92,8 +92,7 @@ static const SBufIO tls_sbufio_ops = {
        tls_sbufio_send,
        tls_sbufio_close
 };
-static void sbuf_tls_accept_cb(int fd, short flags, void *_sbuf);
-static void sbuf_tls_connect_cb(int fd, short flags, void *_sbuf);
+static void sbuf_tls_handshake_cb(int fd, short flags, void *_sbuf);
 #endif
 
 /*********************************
@@ -863,13 +862,24 @@ static void setup_tls(struct tls_config *conf, const char *pfx, int sslmode,
                        log_error("Invalid %s_cert_file: %s", pfx, certfile);
        }
 
-       if (sslmode == SSLMODE_VERIFY_FULL) {
-               tls_config_verify(conf);
-       } else if (sslmode == SSLMODE_VERIFY_CA) {
-               tls_config_insecure_noverifyname(conf);
+       if (does_connect) {
+               /* TLS client, check server? */
+               if (sslmode == SSLMODE_VERIFY_FULL) {
+                       tls_config_verify(conf);
+               } else if (sslmode == SSLMODE_VERIFY_CA) {
+                       tls_config_verify(conf);
+                       tls_config_insecure_noverifyname(conf);
+               } else {
+                       tls_config_insecure_noverifycert(conf);
+                       tls_config_insecure_noverifyname(conf);
+               }
        } else {
-               tls_config_insecure_noverifycert(conf);
-               tls_config_insecure_noverifyname(conf);
+               /* TLS server, check client? */
+               if (sslmode == SSLMODE_VERIFY_FULL) {
+                       tls_config_verify_client_optional(conf);
+               } else if (sslmode == SSLMODE_VERIFY_CA) {
+                       tls_config_verify_client_optional(conf);
+               }
        }
 }
 
@@ -924,73 +934,60 @@ void sbuf_tls_setup(void)
 }
 
 /*
- * Accept TLS connection.
+ * TLS handshake
  */
 
-static bool handle_tls_accept(struct SBuf *sbuf)
+static bool handle_tls_handshake(SBuf *sbuf)
 {
        int err;
 
-       err = tls_accept_fds(client_accept_base, &sbuf->tls, sbuf->sock, sbuf->sock);
-       log_noise("tls_accept_fds: err=%d", err);
-       if (err == TLS_READ_AGAIN) {
-               return sbuf_use_callback_once(sbuf, EV_READ, sbuf_tls_accept_cb);
-       } else if (err == TLS_WRITE_AGAIN) {
-               return sbuf_use_callback_once(sbuf, EV_WRITE, sbuf_tls_accept_cb);
+       err = tls_handshake(sbuf->tls);
+       log_noise("tls_handshake: err=%d", err);
+       if (err == TLS_WANT_POLLIN) {
+               return sbuf_use_callback_once(sbuf, EV_READ, sbuf_tls_handshake_cb);
+       } else if (err == TLS_WANT_POLLOUT) {
+               return sbuf_use_callback_once(sbuf, EV_WRITE, sbuf_tls_handshake_cb);
        } else if (err == 0) {
                sbuf_call_proto(sbuf, SBUF_EV_TLS_READY);
                return true;
        } else {
-               log_warning("TLS accept error: %s", tls_error(sbuf->tls));
+               log_warning("TLS handshake error: %s", tls_error(sbuf->tls));
                return false;
        }
 }
 
-static void sbuf_tls_accept_cb(int fd, short flags, void *_sbuf)
+static void sbuf_tls_handshake_cb(int fd, short flags, void *_sbuf)
 {
        SBuf *sbuf = _sbuf;
        sbuf->wait_type = W_NONE;
-       if (!handle_tls_accept(sbuf))
+       if (!handle_tls_handshake(sbuf))
                sbuf_call_proto(sbuf, SBUF_EV_RECV_FAILED);
 }
 
-bool sbuf_tls_accept(SBuf *sbuf)
-{
-       sbuf->ops = &tls_sbufio_ops;
-       return handle_tls_accept(sbuf);
-}
-
 /*
- * Connect to remote TLS host.
+ * Accept TLS connection.
  */
 
-static bool handle_tls_connect(SBuf *sbuf)
+bool sbuf_tls_accept(SBuf *sbuf)
 {
        int err;
 
-       err = tls_connect_fds(sbuf->tls, sbuf->sock, sbuf->sock, sbuf->tls_host);
-       log_noise("tls_connect_fds: err=%d", err);
-       if (err == TLS_READ_AGAIN) {
-               return sbuf_use_callback_once(sbuf, EV_READ, sbuf_tls_connect_cb);
-       } else if (err == TLS_WRITE_AGAIN) {
-               return sbuf_use_callback_once(sbuf, EV_WRITE, sbuf_tls_connect_cb);
-       } else if (err == 0) {
-               sbuf_call_proto(sbuf, SBUF_EV_TLS_READY);
-               return true;
-       } else {
-               log_warning("TLS connect error: %s", tls_error(sbuf->tls));
+       sbuf->ops = &tls_sbufio_ops;
+
+       err = tls_accept_fds(client_accept_base, &sbuf->tls, sbuf->sock, sbuf->sock);
+       log_noise("tls_accept_fds: err=%d", err);
+       if (err < 0) {
+               log_warning("TLS accept error: %s", tls_error(sbuf->tls));
                return false;
        }
-}
 
-static void sbuf_tls_connect_cb(int fd, short flags, void *_sbuf)
-{
-       SBuf *sbuf = _sbuf;
-       sbuf->wait_type = W_NONE;
-       if (!handle_tls_connect(sbuf))
-               sbuf_call_proto(sbuf, SBUF_EV_RECV_FAILED);
+       return handle_tls_handshake(sbuf);
 }
 
+/*
+ * Connect to remote TLS host.
+ */
+
 bool sbuf_tls_connect(SBuf *sbuf, const char *hostname)
 {
        struct tls *ctls;
@@ -1003,7 +1000,7 @@ bool sbuf_tls_connect(SBuf *sbuf, const char *hostname)
        if (!ctls)
                return false;
        err = tls_configure(ctls, server_connect_conf);
-       if (err) {
+       if (err < 0) {
                log_error("tls client config failed: %s", tls_error(ctls));
                tls_free(ctls);
                return false;
@@ -1013,7 +1010,13 @@ bool sbuf_tls_connect(SBuf *sbuf, const char *hostname)
        sbuf->tls_host = hostname;
        sbuf->ops = &tls_sbufio_ops;
 
-       return handle_tls_connect(sbuf);
+       err = tls_connect_fds(sbuf->tls, sbuf->sock, sbuf->sock, sbuf->tls_host);
+       if (err < 0) {
+               log_warning("TLS connect error: %s", tls_error(sbuf->tls));
+               return false;
+       }
+
+       return handle_tls_handshake(sbuf);
 }
 
 /*
@@ -1022,17 +1025,16 @@ bool sbuf_tls_connect(SBuf *sbuf, const char *hostname)
 
 static int tls_sbufio_recv(struct SBuf *sbuf, void *dst, unsigned int len)
 {
-       int err;
-       size_t out = 0;
+       ssize_t out = 0;
 
-       err = tls_read(sbuf->tls, dst, len, &out);
-       log_noise("tls_read: req=%u err=%d out=%d", len, err, (int)out);
-       if (!err) {
+       out = tls_read(sbuf->tls, dst, len);
+       log_noise("tls_read: req=%u out=%d", len, (int)out);
+       if (out >= 0) {
                return out;
-       } else if (err == TLS_READ_AGAIN) {
+       } else if (out == TLS_WANT_POLLIN) {
                errno = EAGAIN;
-       } else if (err == TLS_WRITE_AGAIN) {
-               log_warning("tls_sbufio_recv: got TLS_WRITE_AGAIN");
+       } else if (out == TLS_WANT_POLLOUT) {
+               log_warning("tls_sbufio_recv: got TLS_WANT_POLLOUT");
                errno = EIO;
        } else {
                log_warning("tls_sbufio_recv: %s", tls_error(sbuf->tls));
@@ -1043,17 +1045,16 @@ static int tls_sbufio_recv(struct SBuf *sbuf, void *dst, unsigned int len)
 
 static int tls_sbufio_send(struct SBuf *sbuf, const void *data, unsigned int len)
 {
-       size_t out = 0;
-       int err;
+       ssize_t out;
 
-       err = tls_write(sbuf->tls, data, len, &out);
-       log_noise("tls_write: req=%u err=%d out=%d", len, err, (int)out);
-       if (!err) {
+       out = tls_write(sbuf->tls, data, len);
+       log_noise("tls_write: req=%u out=%d", len, (int)out);
+       if (out >= 0) {
                return out;
-       } else if (err == TLS_WRITE_AGAIN) {
+       } else if (out == TLS_WANT_POLLOUT) {
                errno = EAGAIN;
-       } else if (err == TLS_READ_AGAIN) {
-               log_warning("tls_sbufio_send: got TLS_READ_AGAIN");
+       } else if (out == TLS_WANT_POLLIN) {
+               log_warning("tls_sbufio_send: got TLS_WANT_POLLIN");
                errno = EIO;
        } else {
                log_warning("tls_sbufio_send: %s", tls_error(sbuf->tls));