summaryrefslogtreecommitdiff
path: root/src/lib/libtls/tls_client.c
diff options
context:
space:
mode:
Diffstat (limited to 'src/lib/libtls/tls_client.c')
-rw-r--r--src/lib/libtls/tls_client.c58
1 files changed, 37 insertions, 21 deletions
diff --git a/src/lib/libtls/tls_client.c b/src/lib/libtls/tls_client.c
index 81e47da0e1..fb7f3a6f75 100644
--- a/src/lib/libtls/tls_client.c
+++ b/src/lib/libtls/tls_client.c
@@ -1,4 +1,4 @@
1/* $OpenBSD: tls_client.c,v 1.25 2015/09/09 19:49:07 jsing Exp $ */ 1/* $OpenBSD: tls_client.c,v 1.26 2015/09/10 10:14:20 jsing Exp $ */
2/* 2/*
3 * Copyright (c) 2014 Joel Sing <jsing@openbsd.org> 3 * Copyright (c) 2014 Joel Sing <jsing@openbsd.org>
4 * 4 *
@@ -166,20 +166,23 @@ tls_connect_fds(struct tls *ctx, int fd_read, int fd_write,
166 const char *servername) 166 const char *servername)
167{ 167{
168 union { struct in_addr ip4; struct in6_addr ip6; } addrbuf; 168 union { struct in_addr ip4; struct in6_addr ip6; } addrbuf;
169 X509 *cert = NULL; 169 int rv = -1;
170 int ret, err;
171 170
172 if ((ctx->flags & TLS_CLIENT) == 0) { 171 if ((ctx->flags & TLS_CLIENT) == 0) {
173 tls_set_errorx(ctx, "not a client context"); 172 tls_set_errorx(ctx, "not a client context");
174 goto err; 173 goto err;
175 } 174 }
176 175
177 if (ctx->state & TLS_STATE_CONNECTING)
178 goto connecting;
179
180 if (fd_read < 0 || fd_write < 0) { 176 if (fd_read < 0 || fd_write < 0) {
181 tls_set_errorx(ctx, "invalid file descriptors"); 177 tls_set_errorx(ctx, "invalid file descriptors");
182 return (-1); 178 goto err;
179 }
180
181 if (servername != NULL) {
182 if ((ctx->servername = strdup(servername)) == NULL) {
183 tls_set_errorx(ctx, "out of memory");
184 goto err;
185 }
183 } 186 }
184 187
185 if ((ctx->ssl_ctx = SSL_CTX_new(SSLv23_client_method())) == NULL) { 188 if ((ctx->ssl_ctx = SSL_CTX_new(SSLv23_client_method())) == NULL) {
@@ -230,16 +233,28 @@ tls_connect_fds(struct tls *ctx, int fd_read, int fd_write,
230 } 233 }
231 } 234 }
232 235
233 connecting: 236 rv = 0;
234 if ((ret = SSL_connect(ctx->ssl_conn)) != 1) { 237
235 err = tls_ssl_error(ctx, ctx->ssl_conn, ret, "connect"); 238 err:
236 if (err == TLS_READ_AGAIN || err == TLS_WRITE_AGAIN) { 239 return (rv);
237 ctx->state |= TLS_STATE_CONNECTING; 240}
238 return (err); 241
239 } 242int
243tls_handshake_client(struct tls *ctx)
244{
245 X509 *cert = NULL;
246 int ssl_ret;
247 int rv = -1;
248
249 if ((ctx->flags & TLS_CLIENT) == 0) {
250 tls_set_errorx(ctx, "not a client context");
251 goto err;
252 }
253
254 if ((ssl_ret = SSL_connect(ctx->ssl_conn)) != 1) {
255 rv = tls_ssl_error(ctx, ctx->ssl_conn, ssl_ret, "handshake");
240 goto err; 256 goto err;
241 } 257 }
242 ctx->state &= ~TLS_STATE_CONNECTING;
243 258
244 if (ctx->config->verify_name) { 259 if (ctx->config->verify_name) {
245 cert = SSL_get_peer_certificate(ctx->ssl_conn); 260 cert = SSL_get_peer_certificate(ctx->ssl_conn);
@@ -247,19 +262,20 @@ tls_connect_fds(struct tls *ctx, int fd_read, int fd_write,
247 tls_set_errorx(ctx, "no server certificate"); 262 tls_set_errorx(ctx, "no server certificate");
248 goto err; 263 goto err;
249 } 264 }
250 if ((ret = tls_check_servername(ctx, cert, servername)) != 0) { 265 if ((rv = tls_check_servername(ctx, cert,
251 if (ret != -2) 266 ctx->servername)) != 0) {
267 if (rv != -2)
252 tls_set_errorx(ctx, "name `%s' not present in" 268 tls_set_errorx(ctx, "name `%s' not present in"
253 " server certificate", servername); 269 " server certificate", ctx->servername);
254 goto err; 270 goto err;
255 } 271 }
256 X509_free(cert);
257 } 272 }
258 273
259 return (0); 274 ctx->state |= TLS_HANDSHAKE_COMPLETE;
275 rv = 0;
260 276
261 err: 277 err:
262 X509_free(cert); 278 X509_free(cert);
263 279
264 return (-1); 280 return (rv);
265} 281}