Move the client code into a separate file.
authorjsing <jsing@openbsd.org>
Sun, 13 Jul 2014 22:42:01 +0000 (22:42 +0000)
committerjsing <jsing@openbsd.org>
Sun, 13 Jul 2014 22:42:01 +0000 (22:42 +0000)
lib/libressl/Makefile
lib/libressl/ressl.c
lib/libressl/ressl_client.c [new file with mode: 0644]

index 167379e..397fefd 100644 (file)
@@ -1,4 +1,4 @@
-#      $OpenBSD: Makefile,v 1.2 2014/07/13 22:13:52 jsing Exp $
+#      $OpenBSD: Makefile,v 1.3 2014/07/13 22:42:01 jsing Exp $
 
 CFLAGS+= -Wall -Werror -Wimplicit
 CFLAGS+= -DLIBRESSL_INTERNAL
@@ -10,6 +10,7 @@ DPADD=        ${LIBCRYPTO} ${LIBSSL}
 HDRS=  ressl.h
 
 SRCS=  ressl.c \
+       ressl_client.c \
        ressl_config.c \
        ressl_util.c \
        ressl_verify.c
index 7295c52..dc82f32 100644 (file)
  * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
  */
 
-#include <sys/types.h>
 #include <sys/socket.h>
 
-#include <arpa/inet.h>
-
 #include <errno.h>
-#include <netdb.h>
 #include <stdlib.h>
 #include <unistd.h>
 
-#include <openssl/x509.h>
-
 #include <ressl.h>
 #include "ressl_internal.h"
 
@@ -116,160 +110,6 @@ ressl_reset(struct ressl *ctx)
        ctx->errmsg = NULL;
 }
 
-int
-ressl_connect(struct ressl *ctx, const char *host, const char *port)
-{
-       struct addrinfo hints, *res, *res0;
-       const char *h = NULL, *p = NULL;
-       char *hs = NULL, *ps = NULL;
-       int rv = -1, s = -1, ret;
-
-       if (host == NULL) {
-               ressl_set_error(ctx, "host not specified");
-               goto err;
-       }
-
-       /*
-        * If port is NULL try to extract a port from the specified host,
-        * otherwise use the default.
-        */
-       if ((p = (char *)port) == NULL) {
-               ret = ressl_host_port(host, &hs, &ps);
-               if (ret == -1) {
-                       ressl_set_error(ctx, "memory allocation failure");
-                       goto err;
-               }
-               if (ret != 0)
-                       port = HTTPS_PORT;
-       }
-
-       h = (hs != NULL) ? hs : host;
-       p = (ps != NULL) ? ps : port;
-
-       memset(&hints, 0, sizeof(hints));
-       hints.ai_family = AF_UNSPEC;
-       hints.ai_socktype = SOCK_STREAM;
-
-       if ((ret = getaddrinfo(h, p, &hints, &res0)) != 0) {
-               ressl_set_error(ctx, "%s", gai_strerror(ret));
-               goto err;
-       }
-       for (res = res0; res; res = res->ai_next) {
-               s = socket(res->ai_family, res->ai_socktype, res->ai_protocol);
-               if (s == -1) {
-                       ressl_set_error(ctx, "socket");
-                       continue;
-               }
-               if (connect(s, res->ai_addr, res->ai_addrlen) == -1) {
-                       ressl_set_error(ctx, "connect");
-                       close(s);
-                       s = -1;
-                       continue;
-               }
-
-               break;  /* Connected. */
-       }
-       freeaddrinfo(res0);
-
-       if (s == -1)
-               goto err;
-
-       if (ressl_connect_socket(ctx, s, h) != 0) {
-               close(s);
-               goto err;
-       }
-
-       rv = 0;
-
-err:
-
-       free(hs);
-       free(ps);
-
-       return (rv);
-}
-
-int
-ressl_connect_socket(struct ressl *ctx, int socket, const char *hostname)
-{
-       union { struct in_addr ip4; struct in6_addr ip6; } addrbuf;
-       X509 *cert = NULL;
-       int ret;
-
-       ctx->socket = socket;
-
-       /* XXX - add a configuration option to control versions. */
-       if ((ctx->ssl_ctx = SSL_CTX_new(SSLv23_client_method())) == NULL) {
-               ressl_set_error(ctx, "ssl context failure");
-               goto err;
-       }
-       if (ctx->config->verify) {
-               if (hostname == NULL) {
-                       ressl_set_error(ctx, "server name not specified");
-                       goto err;
-               }
-
-               SSL_CTX_set_verify(ctx->ssl_ctx, SSL_VERIFY_PEER, NULL);
-
-               if (SSL_CTX_load_verify_locations(ctx->ssl_ctx,
-                   ctx->config->ca_file, ctx->config->ca_path) != 1) {
-                       ressl_set_error(ctx, "ssl verify setup failure");
-                       goto err;
-               }
-               if (ctx->config->verify_depth >= 0)
-                       SSL_CTX_set_verify_depth(ctx->ssl_ctx,
-                           ctx->config->verify_depth);
-       }
-
-       if ((ctx->ssl_conn = SSL_new(ctx->ssl_ctx)) == NULL) {
-               ressl_set_error(ctx, "ssl connection failure");
-               goto err;
-       }
-       if (SSL_set_fd(ctx->ssl_conn, ctx->socket) != 1) {
-               ressl_set_error(ctx, "ssl file descriptor failure");
-               goto err;
-       }
-
-       /*
-        * RFC4366 (SNI): Literal IPv4 and IPv6 addresses are not
-        * permitted in "HostName".
-        */
-       if (hostname != NULL &&
-           inet_pton(AF_INET, hostname, &addrbuf) != 1 &&
-           inet_pton(AF_INET6, hostname, &addrbuf) != 1) {
-               if (SSL_set_tlsext_host_name(ctx->ssl_conn, hostname) == 0) {
-                       ressl_set_error(ctx, "SNI host name failed");
-                       goto err;
-               }
-       }
-
-       if ((ret = SSL_connect(ctx->ssl_conn)) != 1) {
-               ressl_set_error(ctx, "SSL connect failed: %i",
-                   SSL_get_error(ctx->ssl_conn, ret));
-               goto err;
-       }
-
-       if (ctx->config->verify) {
-               cert = SSL_get_peer_certificate(ctx->ssl_conn);
-               if (cert == NULL) {
-                       ressl_set_error(ctx, "no server certificate");
-                       goto err;
-               }
-               if (ressl_check_hostname(cert, hostname) != 0) {
-                       ressl_set_error(ctx, "host `%s' not present in"
-                           " server certificate", hostname);
-                       goto err;
-               }
-       }
-
-       return (0);
-
-err:
-       X509_free(cert);
-
-       return (-1);
-}
-
 int
 ressl_read(struct ressl *ctx, char *buf, size_t buflen, size_t *outlen)
 {
diff --git a/lib/libressl/ressl_client.c b/lib/libressl/ressl_client.c
new file mode 100644 (file)
index 0000000..2e4f253
--- /dev/null
@@ -0,0 +1,183 @@
+/*
+ * Copyright (c) 2014 Joel Sing <jsing@openbsd.org>
+ *
+ * Permission to use, copy, modify, and distribute this software for any
+ * purpose with or without fee is hereby granted, provided that the above
+ * copyright notice and this permission notice appear in all copies.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
+ * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
+ * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
+ * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
+ * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
+ * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
+ * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
+ */
+
+#include <sys/types.h>
+#include <sys/socket.h>
+
+#include <arpa/inet.h>
+
+#include <netdb.h>
+#include <stdlib.h>
+#include <unistd.h>
+
+#include <openssl/x509.h>
+
+#include <ressl.h>
+#include "ressl_internal.h"
+
+int
+ressl_connect(struct ressl *ctx, const char *host, const char *port)
+{
+       struct addrinfo hints, *res, *res0;
+       const char *h = NULL, *p = NULL;
+       char *hs = NULL, *ps = NULL;
+       int rv = -1, s = -1, ret;
+
+       if (host == NULL) {
+               ressl_set_error(ctx, "host not specified");
+               goto err;
+       }
+
+       /*
+        * If port is NULL try to extract a port from the specified host,
+        * otherwise use the default.
+        */
+       if ((p = (char *)port) == NULL) {
+               ret = ressl_host_port(host, &hs, &ps);
+               if (ret == -1) {
+                       ressl_set_error(ctx, "memory allocation failure");
+                       goto err;
+               }
+               if (ret != 0)
+                       port = HTTPS_PORT;
+       }
+
+       h = (hs != NULL) ? hs : host;
+       p = (ps != NULL) ? ps : port;
+
+       memset(&hints, 0, sizeof(hints));
+       hints.ai_family = AF_UNSPEC;
+       hints.ai_socktype = SOCK_STREAM;
+
+       if ((ret = getaddrinfo(h, p, &hints, &res0)) != 0) {
+               ressl_set_error(ctx, "%s", gai_strerror(ret));
+               goto err;
+       }
+       for (res = res0; res; res = res->ai_next) {
+               s = socket(res->ai_family, res->ai_socktype, res->ai_protocol);
+               if (s == -1) {
+                       ressl_set_error(ctx, "socket");
+                       continue;
+               }
+               if (connect(s, res->ai_addr, res->ai_addrlen) == -1) {
+                       ressl_set_error(ctx, "connect");
+                       close(s);
+                       s = -1;
+                       continue;
+               }
+
+               break;  /* Connected. */
+       }
+       freeaddrinfo(res0);
+
+       if (s == -1)
+               goto err;
+
+       if (ressl_connect_socket(ctx, s, h) != 0) {
+               close(s);
+               goto err;
+       }
+
+       rv = 0;
+
+err:
+
+       free(hs);
+       free(ps);
+
+       return (rv);
+}
+
+int
+ressl_connect_socket(struct ressl *ctx, int socket, const char *hostname)
+{
+       union { struct in_addr ip4; struct in6_addr ip6; } addrbuf;
+       X509 *cert = NULL;
+       int ret;
+
+       ctx->socket = socket;
+
+       /* XXX - add a configuration option to control versions. */
+       if ((ctx->ssl_ctx = SSL_CTX_new(SSLv23_client_method())) == NULL) {
+               ressl_set_error(ctx, "ssl context failure");
+               goto err;
+       }
+       if (ctx->config->verify) {
+               if (hostname == NULL) {
+                       ressl_set_error(ctx, "server name not specified");
+                       goto err;
+               }
+
+               SSL_CTX_set_verify(ctx->ssl_ctx, SSL_VERIFY_PEER, NULL);
+
+               if (SSL_CTX_load_verify_locations(ctx->ssl_ctx,
+                   ctx->config->ca_file, ctx->config->ca_path) != 1) {
+                       ressl_set_error(ctx, "ssl verify setup failure");
+                       goto err;
+               }
+               if (ctx->config->verify_depth >= 0)
+                       SSL_CTX_set_verify_depth(ctx->ssl_ctx,
+                           ctx->config->verify_depth);
+       }
+
+       if ((ctx->ssl_conn = SSL_new(ctx->ssl_ctx)) == NULL) {
+               ressl_set_error(ctx, "ssl connection failure");
+               goto err;
+       }
+       if (SSL_set_fd(ctx->ssl_conn, ctx->socket) != 1) {
+               ressl_set_error(ctx, "ssl file descriptor failure");
+               goto err;
+       }
+
+       /*
+        * RFC4366 (SNI): Literal IPv4 and IPv6 addresses are not
+        * permitted in "HostName".
+        */
+       if (hostname != NULL &&
+           inet_pton(AF_INET, hostname, &addrbuf) != 1 &&
+           inet_pton(AF_INET6, hostname, &addrbuf) != 1) {
+               if (SSL_set_tlsext_host_name(ctx->ssl_conn, hostname) == 0) {
+                       ressl_set_error(ctx, "SNI host name failed");
+                       goto err;
+               }
+       }
+
+       if ((ret = SSL_connect(ctx->ssl_conn)) != 1) {
+               ressl_set_error(ctx, "SSL connect failed: %i",
+                   SSL_get_error(ctx->ssl_conn, ret));
+               goto err;
+       }
+
+       if (ctx->config->verify) {
+               cert = SSL_get_peer_certificate(ctx->ssl_conn);
+               if (cert == NULL) {
+                       ressl_set_error(ctx, "no server certificate");
+                       goto err;
+               }
+               if (ressl_check_hostname(cert, hostname) != 0) {
+                       ressl_set_error(ctx, "host `%s' not present in"
+                           " server certificate", hostname);
+                       goto err;
+               }
+       }
+
+       return (0);
+
+err:
+       X509_free(cert);
+
+       return (-1);
+}