1 /* $OpenBSD: tls_client.c,v 1.17 2015/03/31 12:21:27 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 #include <netinet/in.h> 23 24 #include <limits.h> 25 #include <netdb.h> 26 #include <stdlib.h> 27 #include <unistd.h> 28 29 #include <openssl/x509.h> 30 31 #include <tls.h> 32 #include "tls_internal.h" 33 34 struct tls * 35 tls_client(void) 36 { 37 struct tls *ctx; 38 39 if ((ctx = tls_new()) == NULL) 40 return (NULL); 41 42 ctx->flags |= TLS_CLIENT; 43 44 return (ctx); 45 } 46 47 static int 48 tls_connect_host(struct tls *ctx, const char *host, const char *port, 49 int af, int flag) 50 { 51 struct addrinfo hints, *res, *res0; 52 int s = -1; 53 54 memset(&hints, 0, sizeof(hints)); 55 hints.ai_family = af; 56 hints.ai_socktype = SOCK_STREAM; 57 hints.ai_flags = flag; 58 59 if ((s = getaddrinfo(host, port, &hints, &res0)) != 0) { 60 tls_set_error(ctx, "%s", gai_strerror(s)); 61 return (-1); 62 } 63 for (res = res0; res; res = res->ai_next) { 64 s = socket(res->ai_family, res->ai_socktype, res->ai_protocol); 65 if (s == -1) { 66 tls_set_error(ctx, "socket"); 67 continue; 68 } 69 if (connect(s, res->ai_addr, res->ai_addrlen) == -1) { 70 tls_set_error(ctx, "connect"); 71 close(s); 72 s = -1; 73 continue; 74 } 75 76 break; /* Connected. */ 77 } 78 freeaddrinfo(res0); 79 80 return (s); 81 } 82 83 int 84 tls_connect(struct tls *ctx, const char *host, const char *port) 85 { 86 return tls_connect_servername(ctx, host, port, NULL); 87 } 88 89 int 90 tls_connect_servername(struct tls *ctx, const char *host, const char *port, 91 const char *servername) 92 { 93 const char *h = NULL, *p = NULL; 94 char *hs = NULL, *ps = NULL; 95 int rv = -1, s = -1, ret; 96 97 if ((ctx->flags & TLS_CLIENT) == 0) { 98 tls_set_error(ctx, "not a client context"); 99 goto err; 100 } 101 102 if (host == NULL) { 103 tls_set_error(ctx, "host not specified"); 104 goto err; 105 } 106 107 /* 108 * If port is NULL try to extract a port from the specified host, 109 * otherwise use the default. 110 */ 111 if ((p = (char *)port) == NULL) { 112 ret = tls_host_port(host, &hs, &ps); 113 if (ret == -1) { 114 tls_set_error(ctx, "memory allocation failure"); 115 goto err; 116 } 117 if (ret != 0) 118 port = HTTPS_PORT; 119 } 120 121 h = (hs != NULL) ? hs : host; 122 p = (ps != NULL) ? ps : port; 123 124 /* 125 * First check if the host is specified as a numeric IP address, 126 * either IPv4 or IPv6, before trying to resolve the host. 127 * The AI_ADDRCONFIG resolver option will not return IPv4 or IPv6 128 * records if it is not configured on an interface; not considering 129 * loopback addresses. Checking the numeric addresses first makes 130 * sure that connection attempts to numeric addresses and especially 131 * 127.0.0.1 or ::1 loopback addresses are always possible. 132 */ 133 if ((s = tls_connect_host(ctx, h, p, AF_INET, AI_NUMERICHOST)) == -1 && 134 (s = tls_connect_host(ctx, h, p, AF_INET6, AI_NUMERICHOST)) == -1 && 135 (s = tls_connect_host(ctx, h, p, AF_UNSPEC, AI_ADDRCONFIG)) == -1) 136 goto err; 137 138 if (servername == NULL) 139 servername = h; 140 141 if (tls_connect_socket(ctx, s, servername) != 0) { 142 close(s); 143 goto err; 144 } 145 146 rv = 0; 147 148 err: 149 free(hs); 150 free(ps); 151 152 return (rv); 153 } 154 155 int 156 tls_connect_socket(struct tls *ctx, int s, const char *servername) 157 { 158 ctx->socket = s; 159 160 return tls_connect_fds(ctx, s, s, servername); 161 } 162 163 int 164 tls_connect_fds(struct tls *ctx, int fd_read, int fd_write, 165 const char *servername) 166 { 167 union { struct in_addr ip4; struct in6_addr ip6; } addrbuf; 168 X509 *cert = NULL; 169 int ret, err; 170 171 if (ctx->flags & TLS_CONNECTING) 172 goto connecting; 173 174 if ((ctx->flags & TLS_CLIENT) == 0) { 175 tls_set_error(ctx, "not a client context"); 176 goto err; 177 } 178 179 if (fd_read < 0 || fd_write < 0) { 180 tls_set_error(ctx, "invalid file descriptors"); 181 return (-1); 182 } 183 184 if ((ctx->ssl_ctx = SSL_CTX_new(SSLv23_client_method())) == NULL) { 185 tls_set_error(ctx, "ssl context failure"); 186 goto err; 187 } 188 189 if (tls_configure_ssl(ctx) != 0) 190 goto err; 191 192 if (ctx->config->verify_name) { 193 if (servername == NULL) { 194 tls_set_error(ctx, "server name not specified"); 195 goto err; 196 } 197 } 198 199 if (ctx->config->verify_cert) { 200 SSL_CTX_set_verify(ctx->ssl_ctx, SSL_VERIFY_PEER, NULL); 201 202 if (ctx->config->ca_mem != NULL) { 203 if (ctx->config->ca_len > INT_MAX) { 204 tls_set_error(ctx, "ca too long"); 205 goto err; 206 } 207 208 if (SSL_CTX_load_verify_mem(ctx->ssl_ctx, 209 ctx->config->ca_mem, ctx->config->ca_len) != 1) { 210 tls_set_error(ctx, 211 "ssl verify memory setup failure"); 212 goto err; 213 } 214 } else if (SSL_CTX_load_verify_locations(ctx->ssl_ctx, 215 ctx->config->ca_file, ctx->config->ca_path) != 1) { 216 tls_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 tls_set_error(ctx, "ssl connection failure"); 226 goto err; 227 } 228 if (SSL_set_rfd(ctx->ssl_conn, fd_read) != 1 || 229 SSL_set_wfd(ctx->ssl_conn, fd_write) != 1) { 230 tls_set_error(ctx, "ssl file descriptor failure"); 231 goto err; 232 } 233 234 /* 235 * RFC4366 (SNI): Literal IPv4 and IPv6 addresses are not 236 * permitted in "HostName". 237 */ 238 if (servername != NULL && 239 inet_pton(AF_INET, servername, &addrbuf) != 1 && 240 inet_pton(AF_INET6, servername, &addrbuf) != 1) { 241 if (SSL_set_tlsext_host_name(ctx->ssl_conn, servername) == 0) { 242 tls_set_error(ctx, "server name indication failure"); 243 goto err; 244 } 245 } 246 247 connecting: 248 if ((ret = SSL_connect(ctx->ssl_conn)) != 1) { 249 err = tls_ssl_error(ctx, ctx->ssl_conn, ret, "connect"); 250 if (err == TLS_READ_AGAIN || err == TLS_WRITE_AGAIN) { 251 ctx->flags |= TLS_CONNECTING; 252 return (err); 253 } 254 goto err; 255 } 256 ctx->flags &= ~TLS_CONNECTING; 257 258 if (ctx->config->verify_name) { 259 cert = SSL_get_peer_certificate(ctx->ssl_conn); 260 if (cert == NULL) { 261 tls_set_error(ctx, "no server certificate"); 262 goto err; 263 } 264 if ((ret = tls_check_servername(ctx, cert, servername)) != 0) { 265 if (ret != -2) 266 tls_set_error(ctx, "name `%s' not present in" 267 " server certificate", servername); 268 goto err; 269 } 270 X509_free(cert); 271 } 272 273 return (0); 274 275 err: 276 X509_free(cert); 277 278 return (-1); 279 } 280