summaryrefslogtreecommitdiff
path: root/src/lib/libtls/tls_client.c
diff options
context:
space:
mode:
authorjsing <>2014-10-31 13:46:17 +0000
committerjsing <>2014-10-31 13:46:17 +0000
commitcd85e00508e178758948e7a759609d0f1e7764df (patch)
tree44ea21a19ccf529a3e38fb107d3a2d1330f58d8e /src/lib/libtls/tls_client.c
parente83bdb8edcd9388f13b71372b277fdcce386a9b0 (diff)
downloadopenbsd-cd85e00508e178758948e7a759609d0f1e7764df.tar.gz
openbsd-cd85e00508e178758948e7a759609d0f1e7764df.tar.bz2
openbsd-cd85e00508e178758948e7a759609d0f1e7764df.zip
Rename libressl to libtls to avoid confusion and to make it easier to
distinguish between LibreSSL (the project) and libressl (the library). Discussed with many.
Diffstat (limited to 'src/lib/libtls/tls_client.c')
-rw-r--r--src/lib/libtls/tls_client.c212
1 files changed, 212 insertions, 0 deletions
diff --git a/src/lib/libtls/tls_client.c b/src/lib/libtls/tls_client.c
new file mode 100644
index 0000000000..853766f87b
--- /dev/null
+++ b/src/lib/libtls/tls_client.c
@@ -0,0 +1,212 @@
1/* $OpenBSD: tls_client.c,v 1.1 2014/10/31 13:46:17 jsing Exp $ */
2/*
3 * Copyright (c) 2014 Joel Sing <jsing@openbsd.org>
4 *
5 * Permission to use, copy, modify, and distribute this software for any
6 * purpose with or without fee is hereby granted, provided that the above
7 * copyright notice and this permission notice appear in all copies.
8 *
9 * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
10 * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
11 * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
12 * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
13 * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
14 * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
15 * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
16 */
17
18#include <sys/types.h>
19#include <sys/socket.h>
20
21#include <arpa/inet.h>
22
23#include <netdb.h>
24#include <stdlib.h>
25#include <unistd.h>
26
27#include <openssl/x509.h>
28
29#include <tls.h>
30#include "tls_internal.h"
31
32struct tls *
33tls_client(void)
34{
35 struct tls *ctx;
36
37 if ((ctx = tls_new()) == NULL)
38 return (NULL);
39
40 ctx->flags |= TLS_CLIENT;
41
42 return (ctx);
43}
44
45int
46tls_connect(struct tls *ctx, const char *host, const char *port)
47{
48 struct addrinfo hints, *res, *res0;
49 const char *h = NULL, *p = NULL;
50 char *hs = NULL, *ps = NULL;
51 int rv = -1, s = -1, ret;
52
53 if ((ctx->flags & TLS_CLIENT) == 0) {
54 tls_set_error(ctx, "not a client context");
55 goto err;
56 }
57
58 if (host == NULL) {
59 tls_set_error(ctx, "host not specified");
60 goto err;
61 }
62
63 /*
64 * If port is NULL try to extract a port from the specified host,
65 * otherwise use the default.
66 */
67 if ((p = (char *)port) == NULL) {
68 ret = tls_host_port(host, &hs, &ps);
69 if (ret == -1) {
70 tls_set_error(ctx, "memory allocation failure");
71 goto err;
72 }
73 if (ret != 0)
74 port = HTTPS_PORT;
75 }
76
77 h = (hs != NULL) ? hs : host;
78 p = (ps != NULL) ? ps : port;
79
80 memset(&hints, 0, sizeof(hints));
81 hints.ai_family = AF_UNSPEC;
82 hints.ai_socktype = SOCK_STREAM;
83
84 if ((ret = getaddrinfo(h, p, &hints, &res0)) != 0) {
85 tls_set_error(ctx, "%s", gai_strerror(ret));
86 goto err;
87 }
88 for (res = res0; res; res = res->ai_next) {
89 s = socket(res->ai_family, res->ai_socktype, res->ai_protocol);
90 if (s == -1) {
91 tls_set_error(ctx, "socket");
92 continue;
93 }
94 if (connect(s, res->ai_addr, res->ai_addrlen) == -1) {
95 tls_set_error(ctx, "connect");
96 close(s);
97 s = -1;
98 continue;
99 }
100
101 break; /* Connected. */
102 }
103 freeaddrinfo(res0);
104
105 if (s == -1)
106 goto err;
107
108 if (tls_connect_socket(ctx, s, h) != 0) {
109 close(s);
110 goto err;
111 }
112
113 rv = 0;
114
115err:
116
117 free(hs);
118 free(ps);
119
120 return (rv);
121}
122
123int
124tls_connect_socket(struct tls *ctx, int socket, const char *hostname)
125{
126 union { struct in_addr ip4; struct in6_addr ip6; } addrbuf;
127 X509 *cert = NULL;
128 int ret;
129
130 if ((ctx->flags & TLS_CLIENT) == 0) {
131 tls_set_error(ctx, "not a client context");
132 goto err;
133 }
134
135 ctx->socket = socket;
136
137 if ((ctx->ssl_ctx = SSL_CTX_new(SSLv23_client_method())) == NULL) {
138 tls_set_error(ctx, "ssl context failure");
139 goto err;
140 }
141
142 if (tls_configure_ssl(ctx) != 0)
143 goto err;
144
145 if (ctx->config->verify_host) {
146 if (hostname == NULL) {
147 tls_set_error(ctx, "server name not specified");
148 goto err;
149 }
150 }
151
152 if (ctx->config->verify_cert) {
153 SSL_CTX_set_verify(ctx->ssl_ctx, SSL_VERIFY_PEER, NULL);
154
155 if (SSL_CTX_load_verify_locations(ctx->ssl_ctx,
156 ctx->config->ca_file, ctx->config->ca_path) != 1) {
157 tls_set_error(ctx, "ssl verify setup failure");
158 goto err;
159 }
160 if (ctx->config->verify_depth >= 0)
161 SSL_CTX_set_verify_depth(ctx->ssl_ctx,
162 ctx->config->verify_depth);
163 }
164
165 if ((ctx->ssl_conn = SSL_new(ctx->ssl_ctx)) == NULL) {
166 tls_set_error(ctx, "ssl connection failure");
167 goto err;
168 }
169 if (SSL_set_fd(ctx->ssl_conn, ctx->socket) != 1) {
170 tls_set_error(ctx, "ssl file descriptor failure");
171 goto err;
172 }
173
174 /*
175 * RFC4366 (SNI): Literal IPv4 and IPv6 addresses are not
176 * permitted in "HostName".
177 */
178 if (hostname != NULL &&
179 inet_pton(AF_INET, hostname, &addrbuf) != 1 &&
180 inet_pton(AF_INET6, hostname, &addrbuf) != 1) {
181 if (SSL_set_tlsext_host_name(ctx->ssl_conn, hostname) == 0) {
182 tls_set_error(ctx, "SNI host name failed");
183 goto err;
184 }
185 }
186
187 if ((ret = SSL_connect(ctx->ssl_conn)) != 1) {
188 tls_set_error(ctx, "SSL connect failed: %i",
189 SSL_get_error(ctx->ssl_conn, ret));
190 goto err;
191 }
192
193 if (ctx->config->verify_host) {
194 cert = SSL_get_peer_certificate(ctx->ssl_conn);
195 if (cert == NULL) {
196 tls_set_error(ctx, "no server certificate");
197 goto err;
198 }
199 if (tls_check_hostname(cert, hostname) != 0) {
200 tls_set_error(ctx, "host `%s' not present in"
201 " server certificate", hostname);
202 goto err;
203 }
204 }
205
206 return (0);
207
208err:
209 X509_free(cert);
210
211 return (-1);
212}