summaryrefslogtreecommitdiff
path: root/src/lib
diff options
context:
space:
mode:
authorjsing <>2014-07-13 22:42:01 +0000
committerjsing <>2014-07-13 22:42:01 +0000
commit02332d5d0dcdf23c14ec45f52fb95d580089f34a (patch)
treecc97d9a54751afd8dad5a5cf8447091489584a9c /src/lib
parent12562f20bce4aa5f48a40c04ebb898cff187e76c (diff)
downloadopenbsd-02332d5d0dcdf23c14ec45f52fb95d580089f34a.tar.gz
openbsd-02332d5d0dcdf23c14ec45f52fb95d580089f34a.tar.bz2
openbsd-02332d5d0dcdf23c14ec45f52fb95d580089f34a.zip
Move the client code into a separate file.
Diffstat (limited to 'src/lib')
-rw-r--r--src/lib/libressl/Makefile3
-rw-r--r--src/lib/libressl/ressl.c160
-rw-r--r--src/lib/libressl/ressl_client.c183
3 files changed, 185 insertions, 161 deletions
diff --git a/src/lib/libressl/Makefile b/src/lib/libressl/Makefile
index 167379edff..397fefdf69 100644
--- a/src/lib/libressl/Makefile
+++ b/src/lib/libressl/Makefile
@@ -1,4 +1,4 @@
1# $OpenBSD: Makefile,v 1.2 2014/07/13 22:13:52 jsing Exp $ 1# $OpenBSD: Makefile,v 1.3 2014/07/13 22:42:01 jsing Exp $
2 2
3CFLAGS+= -Wall -Werror -Wimplicit 3CFLAGS+= -Wall -Werror -Wimplicit
4CFLAGS+= -DLIBRESSL_INTERNAL 4CFLAGS+= -DLIBRESSL_INTERNAL
@@ -10,6 +10,7 @@ DPADD= ${LIBCRYPTO} ${LIBSSL}
10HDRS= ressl.h 10HDRS= ressl.h
11 11
12SRCS= ressl.c \ 12SRCS= ressl.c \
13 ressl_client.c \
13 ressl_config.c \ 14 ressl_config.c \
14 ressl_util.c \ 15 ressl_util.c \
15 ressl_verify.c 16 ressl_verify.c
diff --git a/src/lib/libressl/ressl.c b/src/lib/libressl/ressl.c
index 7295c520d2..dc82f321b1 100644
--- a/src/lib/libressl/ressl.c
+++ b/src/lib/libressl/ressl.c
@@ -14,18 +14,12 @@
14 * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. 14 * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
15 */ 15 */
16 16
17#include <sys/types.h>
18#include <sys/socket.h> 17#include <sys/socket.h>
19 18
20#include <arpa/inet.h>
21
22#include <errno.h> 19#include <errno.h>
23#include <netdb.h>
24#include <stdlib.h> 20#include <stdlib.h>
25#include <unistd.h> 21#include <unistd.h>
26 22
27#include <openssl/x509.h>
28
29#include <ressl.h> 23#include <ressl.h>
30#include "ressl_internal.h" 24#include "ressl_internal.h"
31 25
@@ -117,160 +111,6 @@ ressl_reset(struct ressl *ctx)
117} 111}
118 112
119int 113int
120ressl_connect(struct ressl *ctx, const char *host, const char *port)
121{
122 struct addrinfo hints, *res, *res0;
123 const char *h = NULL, *p = NULL;
124 char *hs = NULL, *ps = NULL;
125 int rv = -1, s = -1, ret;
126
127 if (host == NULL) {
128 ressl_set_error(ctx, "host not specified");
129 goto err;
130 }
131
132 /*
133 * If port is NULL try to extract a port from the specified host,
134 * otherwise use the default.
135 */
136 if ((p = (char *)port) == NULL) {
137 ret = ressl_host_port(host, &hs, &ps);
138 if (ret == -1) {
139 ressl_set_error(ctx, "memory allocation failure");
140 goto err;
141 }
142 if (ret != 0)
143 port = HTTPS_PORT;
144 }
145
146 h = (hs != NULL) ? hs : host;
147 p = (ps != NULL) ? ps : port;
148
149 memset(&hints, 0, sizeof(hints));
150 hints.ai_family = AF_UNSPEC;
151 hints.ai_socktype = SOCK_STREAM;
152
153 if ((ret = getaddrinfo(h, p, &hints, &res0)) != 0) {
154 ressl_set_error(ctx, "%s", gai_strerror(ret));
155 goto err;
156 }
157 for (res = res0; res; res = res->ai_next) {
158 s = socket(res->ai_family, res->ai_socktype, res->ai_protocol);
159 if (s == -1) {
160 ressl_set_error(ctx, "socket");
161 continue;
162 }
163 if (connect(s, res->ai_addr, res->ai_addrlen) == -1) {
164 ressl_set_error(ctx, "connect");
165 close(s);
166 s = -1;
167 continue;
168 }
169
170 break; /* Connected. */
171 }
172 freeaddrinfo(res0);
173
174 if (s == -1)
175 goto err;
176
177 if (ressl_connect_socket(ctx, s, h) != 0) {
178 close(s);
179 goto err;
180 }
181
182 rv = 0;
183
184err:
185
186 free(hs);
187 free(ps);
188
189 return (rv);
190}
191
192int
193ressl_connect_socket(struct ressl *ctx, int socket, const char *hostname)
194{
195 union { struct in_addr ip4; struct in6_addr ip6; } addrbuf;
196 X509 *cert = NULL;
197 int ret;
198
199 ctx->socket = socket;
200
201 /* XXX - add a configuration option to control versions. */
202 if ((ctx->ssl_ctx = SSL_CTX_new(SSLv23_client_method())) == NULL) {
203 ressl_set_error(ctx, "ssl context failure");
204 goto err;
205 }
206 if (ctx->config->verify) {
207 if (hostname == NULL) {
208 ressl_set_error(ctx, "server name not specified");
209 goto err;
210 }
211
212 SSL_CTX_set_verify(ctx->ssl_ctx, SSL_VERIFY_PEER, NULL);
213
214 if (SSL_CTX_load_verify_locations(ctx->ssl_ctx,
215 ctx->config->ca_file, ctx->config->ca_path) != 1) {
216 ressl_set_error(ctx, "ssl verify setup failure");
217 goto err;
218 }
219 if (ctx->config->verify_depth >= 0)
220 SSL_CTX_set_verify_depth(ctx->ssl_ctx,
221 ctx->config->verify_depth);
222 }
223
224 if ((ctx->ssl_conn = SSL_new(ctx->ssl_ctx)) == NULL) {
225 ressl_set_error(ctx, "ssl connection failure");
226 goto err;
227 }
228 if (SSL_set_fd(ctx->ssl_conn, ctx->socket) != 1) {
229 ressl_set_error(ctx, "ssl file descriptor failure");
230 goto err;
231 }
232
233 /*
234 * RFC4366 (SNI): Literal IPv4 and IPv6 addresses are not
235 * permitted in "HostName".
236 */
237 if (hostname != NULL &&
238 inet_pton(AF_INET, hostname, &addrbuf) != 1 &&
239 inet_pton(AF_INET6, hostname, &addrbuf) != 1) {
240 if (SSL_set_tlsext_host_name(ctx->ssl_conn, hostname) == 0) {
241 ressl_set_error(ctx, "SNI host name failed");
242 goto err;
243 }
244 }
245
246 if ((ret = SSL_connect(ctx->ssl_conn)) != 1) {
247 ressl_set_error(ctx, "SSL connect failed: %i",
248 SSL_get_error(ctx->ssl_conn, ret));
249 goto err;
250 }
251
252 if (ctx->config->verify) {
253 cert = SSL_get_peer_certificate(ctx->ssl_conn);
254 if (cert == NULL) {
255 ressl_set_error(ctx, "no server certificate");
256 goto err;
257 }
258 if (ressl_check_hostname(cert, hostname) != 0) {
259 ressl_set_error(ctx, "host `%s' not present in"
260 " server certificate", hostname);
261 goto err;
262 }
263 }
264
265 return (0);
266
267err:
268 X509_free(cert);
269
270 return (-1);
271}
272
273int
274ressl_read(struct ressl *ctx, char *buf, size_t buflen, size_t *outlen) 114ressl_read(struct ressl *ctx, char *buf, size_t buflen, size_t *outlen)
275{ 115{
276 int ret; 116 int ret;
diff --git a/src/lib/libressl/ressl_client.c b/src/lib/libressl/ressl_client.c
new file mode 100644
index 0000000000..2e4f253856
--- /dev/null
+++ b/src/lib/libressl/ressl_client.c
@@ -0,0 +1,183 @@
1/*
2 * Copyright (c) 2014 Joel Sing <jsing@openbsd.org>
3 *
4 * Permission to use, copy, modify, and distribute this software for any
5 * purpose with or without fee is hereby granted, provided that the above
6 * copyright notice and this permission notice appear in all copies.
7 *
8 * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
9 * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
10 * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
11 * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
12 * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
13 * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
14 * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
15 */
16
17#include <sys/types.h>
18#include <sys/socket.h>
19
20#include <arpa/inet.h>
21
22#include <netdb.h>
23#include <stdlib.h>
24#include <unistd.h>
25
26#include <openssl/x509.h>
27
28#include <ressl.h>
29#include "ressl_internal.h"
30
31int
32ressl_connect(struct ressl *ctx, const char *host, const char *port)
33{
34 struct addrinfo hints, *res, *res0;
35 const char *h = NULL, *p = NULL;
36 char *hs = NULL, *ps = NULL;
37 int rv = -1, s = -1, ret;
38
39 if (host == NULL) {
40 ressl_set_error(ctx, "host not specified");
41 goto err;
42 }
43
44 /*
45 * If port is NULL try to extract a port from the specified host,
46 * otherwise use the default.
47 */
48 if ((p = (char *)port) == NULL) {
49 ret = ressl_host_port(host, &hs, &ps);
50 if (ret == -1) {
51 ressl_set_error(ctx, "memory allocation failure");
52 goto err;
53 }
54 if (ret != 0)
55 port = HTTPS_PORT;
56 }
57
58 h = (hs != NULL) ? hs : host;
59 p = (ps != NULL) ? ps : port;
60
61 memset(&hints, 0, sizeof(hints));
62 hints.ai_family = AF_UNSPEC;
63 hints.ai_socktype = SOCK_STREAM;
64
65 if ((ret = getaddrinfo(h, p, &hints, &res0)) != 0) {
66 ressl_set_error(ctx, "%s", gai_strerror(ret));
67 goto err;
68 }
69 for (res = res0; res; res = res->ai_next) {
70 s = socket(res->ai_family, res->ai_socktype, res->ai_protocol);
71 if (s == -1) {
72 ressl_set_error(ctx, "socket");
73 continue;
74 }
75 if (connect(s, res->ai_addr, res->ai_addrlen) == -1) {
76 ressl_set_error(ctx, "connect");
77 close(s);
78 s = -1;
79 continue;
80 }
81
82 break; /* Connected. */
83 }
84 freeaddrinfo(res0);
85
86 if (s == -1)
87 goto err;
88
89 if (ressl_connect_socket(ctx, s, h) != 0) {
90 close(s);
91 goto err;
92 }
93
94 rv = 0;
95
96err:
97
98 free(hs);
99 free(ps);
100
101 return (rv);
102}
103
104int
105ressl_connect_socket(struct ressl *ctx, int socket, const char *hostname)
106{
107 union { struct in_addr ip4; struct in6_addr ip6; } addrbuf;
108 X509 *cert = NULL;
109 int ret;
110
111 ctx->socket = socket;
112
113 /* XXX - add a configuration option to control versions. */
114 if ((ctx->ssl_ctx = SSL_CTX_new(SSLv23_client_method())) == NULL) {
115 ressl_set_error(ctx, "ssl context failure");
116 goto err;
117 }
118 if (ctx->config->verify) {
119 if (hostname == NULL) {
120 ressl_set_error(ctx, "server name not specified");
121 goto err;
122 }
123
124 SSL_CTX_set_verify(ctx->ssl_ctx, SSL_VERIFY_PEER, NULL);
125
126 if (SSL_CTX_load_verify_locations(ctx->ssl_ctx,
127 ctx->config->ca_file, ctx->config->ca_path) != 1) {
128 ressl_set_error(ctx, "ssl verify setup failure");
129 goto err;
130 }
131 if (ctx->config->verify_depth >= 0)
132 SSL_CTX_set_verify_depth(ctx->ssl_ctx,
133 ctx->config->verify_depth);
134 }
135
136 if ((ctx->ssl_conn = SSL_new(ctx->ssl_ctx)) == NULL) {
137 ressl_set_error(ctx, "ssl connection failure");
138 goto err;
139 }
140 if (SSL_set_fd(ctx->ssl_conn, ctx->socket) != 1) {
141 ressl_set_error(ctx, "ssl file descriptor failure");
142 goto err;
143 }
144
145 /*
146 * RFC4366 (SNI): Literal IPv4 and IPv6 addresses are not
147 * permitted in "HostName".
148 */
149 if (hostname != NULL &&
150 inet_pton(AF_INET, hostname, &addrbuf) != 1 &&
151 inet_pton(AF_INET6, hostname, &addrbuf) != 1) {
152 if (SSL_set_tlsext_host_name(ctx->ssl_conn, hostname) == 0) {
153 ressl_set_error(ctx, "SNI host name failed");
154 goto err;
155 }
156 }
157
158 if ((ret = SSL_connect(ctx->ssl_conn)) != 1) {
159 ressl_set_error(ctx, "SSL connect failed: %i",
160 SSL_get_error(ctx->ssl_conn, ret));
161 goto err;
162 }
163
164 if (ctx->config->verify) {
165 cert = SSL_get_peer_certificate(ctx->ssl_conn);
166 if (cert == NULL) {
167 ressl_set_error(ctx, "no server certificate");
168 goto err;
169 }
170 if (ressl_check_hostname(cert, hostname) != 0) {
171 ressl_set_error(ctx, "host `%s' not present in"
172 " server certificate", hostname);
173 goto err;
174 }
175 }
176
177 return (0);
178
179err:
180 X509_free(cert);
181
182 return (-1);
183}