| Absolute File Name: | /home/opencoverage/opencoverage/guest-scripts/libressl/src/tls/tls_client.c |
| Source code | Switch to Preprocessed file |
| Line | Source | Count | ||||||||||||||||||||||||||||||
|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|
| 1 | /* $OpenBSD: tls_client.c,v 1.45 2018/03/19 16:34:47 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 | #include <sys/stat.h> | - | ||||||||||||||||||||||||||||||
| 21 | - | |||||||||||||||||||||||||||||||
| 22 | #include <arpa/inet.h> | - | ||||||||||||||||||||||||||||||
| 23 | #include <netinet/in.h> | - | ||||||||||||||||||||||||||||||
| 24 | - | |||||||||||||||||||||||||||||||
| 25 | #include <limits.h> | - | ||||||||||||||||||||||||||||||
| 26 | #include <netdb.h> | - | ||||||||||||||||||||||||||||||
| 27 | #include <stdlib.h> | - | ||||||||||||||||||||||||||||||
| 28 | #include <unistd.h> | - | ||||||||||||||||||||||||||||||
| 29 | - | |||||||||||||||||||||||||||||||
| 30 | #include <openssl/err.h> | - | ||||||||||||||||||||||||||||||
| 31 | #include <openssl/x509.h> | - | ||||||||||||||||||||||||||||||
| 32 | - | |||||||||||||||||||||||||||||||
| 33 | #include <tls.h> | - | ||||||||||||||||||||||||||||||
| 34 | #include "tls_internal.h" | - | ||||||||||||||||||||||||||||||
| 35 | - | |||||||||||||||||||||||||||||||
| 36 | struct tls * | - | ||||||||||||||||||||||||||||||
| 37 | tls_client(void) | - | ||||||||||||||||||||||||||||||
| 38 | { | - | ||||||||||||||||||||||||||||||
| 39 | struct tls *ctx; | - | ||||||||||||||||||||||||||||||
| 40 | - | |||||||||||||||||||||||||||||||
| 41 | if (tls_init() == -1)
| 0-30 | ||||||||||||||||||||||||||||||
| 42 | return (NULL); never executed: return ( ((void *)0) ); | 0 | ||||||||||||||||||||||||||||||
| 43 | - | |||||||||||||||||||||||||||||||
| 44 | if ((ctx = tls_new()) == NULL)
| 0-30 | ||||||||||||||||||||||||||||||
| 45 | return (NULL); never executed: return ( ((void *)0) ); | 0 | ||||||||||||||||||||||||||||||
| 46 | - | |||||||||||||||||||||||||||||||
| 47 | ctx->flags |= TLS_CLIENT; | - | ||||||||||||||||||||||||||||||
| 48 | - | |||||||||||||||||||||||||||||||
| 49 | return (ctx); executed 30 times by 2 tests: return (ctx);Executed by:
| 30 | ||||||||||||||||||||||||||||||
| 50 | } | - | ||||||||||||||||||||||||||||||
| 51 | - | |||||||||||||||||||||||||||||||
| 52 | int | - | ||||||||||||||||||||||||||||||
| 53 | tls_connect(struct tls *ctx, const char *host, const char *port) | - | ||||||||||||||||||||||||||||||
| 54 | { | - | ||||||||||||||||||||||||||||||
| 55 | return tls_connect_servername(ctx, host, port, NULL); never executed: return tls_connect_servername(ctx, host, port, ((void *)0) ); | 0 | ||||||||||||||||||||||||||||||
| 56 | } | - | ||||||||||||||||||||||||||||||
| 57 | - | |||||||||||||||||||||||||||||||
| 58 | int | - | ||||||||||||||||||||||||||||||
| 59 | tls_connect_servername(struct tls *ctx, const char *host, const char *port, | - | ||||||||||||||||||||||||||||||
| 60 | const char *servername) | - | ||||||||||||||||||||||||||||||
| 61 | { | - | ||||||||||||||||||||||||||||||
| 62 | struct addrinfo hints, *res, *res0; | - | ||||||||||||||||||||||||||||||
| 63 | const char *h = NULL, *p = NULL; | - | ||||||||||||||||||||||||||||||
| 64 | char *hs = NULL, *ps = NULL; | - | ||||||||||||||||||||||||||||||
| 65 | int rv = -1, s = -1, ret; | - | ||||||||||||||||||||||||||||||
| 66 | - | |||||||||||||||||||||||||||||||
| 67 | if ((ctx->flags & TLS_CLIENT) == 0) {
| 0 | ||||||||||||||||||||||||||||||
| 68 | tls_set_errorx(ctx, "not a client context"); | - | ||||||||||||||||||||||||||||||
| 69 | goto err; never executed: goto err; | 0 | ||||||||||||||||||||||||||||||
| 70 | } | - | ||||||||||||||||||||||||||||||
| 71 | - | |||||||||||||||||||||||||||||||
| 72 | if (host == NULL) {
| 0 | ||||||||||||||||||||||||||||||
| 73 | tls_set_errorx(ctx, "host not specified"); | - | ||||||||||||||||||||||||||||||
| 74 | goto err; never executed: goto err; | 0 | ||||||||||||||||||||||||||||||
| 75 | } | - | ||||||||||||||||||||||||||||||
| 76 | - | |||||||||||||||||||||||||||||||
| 77 | /* | - | ||||||||||||||||||||||||||||||
| 78 | * If port is NULL try to extract a port from the specified host, | - | ||||||||||||||||||||||||||||||
| 79 | * otherwise use the default. | - | ||||||||||||||||||||||||||||||
| 80 | */ | - | ||||||||||||||||||||||||||||||
| 81 | if ((p = (char *)port) == NULL) {
| 0 | ||||||||||||||||||||||||||||||
| 82 | ret = tls_host_port(host, &hs, &ps); | - | ||||||||||||||||||||||||||||||
| 83 | if (ret == -1) {
| 0 | ||||||||||||||||||||||||||||||
| 84 | tls_set_errorx(ctx, "memory allocation failure"); | - | ||||||||||||||||||||||||||||||
| 85 | goto err; never executed: goto err; | 0 | ||||||||||||||||||||||||||||||
| 86 | } | - | ||||||||||||||||||||||||||||||
| 87 | if (ret != 0) {
| 0 | ||||||||||||||||||||||||||||||
| 88 | tls_set_errorx(ctx, "no port provided"); | - | ||||||||||||||||||||||||||||||
| 89 | goto err; never executed: goto err; | 0 | ||||||||||||||||||||||||||||||
| 90 | } | - | ||||||||||||||||||||||||||||||
| 91 | } never executed: end of block | 0 | ||||||||||||||||||||||||||||||
| 92 | - | |||||||||||||||||||||||||||||||
| 93 | h = (hs != NULL) ? hs : host;
| 0 | ||||||||||||||||||||||||||||||
| 94 | p = (ps != NULL) ? ps : port;
| 0 | ||||||||||||||||||||||||||||||
| 95 | - | |||||||||||||||||||||||||||||||
| 96 | /* | - | ||||||||||||||||||||||||||||||
| 97 | * First check if the host is specified as a numeric IP address, | - | ||||||||||||||||||||||||||||||
| 98 | * either IPv4 or IPv6, before trying to resolve the host. | - | ||||||||||||||||||||||||||||||
| 99 | * The AI_ADDRCONFIG resolver option will not return IPv4 or IPv6 | - | ||||||||||||||||||||||||||||||
| 100 | * records if it is not configured on an interface; not considering | - | ||||||||||||||||||||||||||||||
| 101 | * loopback addresses. Checking the numeric addresses first makes | - | ||||||||||||||||||||||||||||||
| 102 | * sure that connection attempts to numeric addresses and especially | - | ||||||||||||||||||||||||||||||
| 103 | * 127.0.0.1 or ::1 loopback addresses are always possible. | - | ||||||||||||||||||||||||||||||
| 104 | */ | - | ||||||||||||||||||||||||||||||
| 105 | memset(&hints, 0, sizeof(hints)); | - | ||||||||||||||||||||||||||||||
| 106 | hints.ai_socktype = SOCK_STREAM; | - | ||||||||||||||||||||||||||||||
| 107 | - | |||||||||||||||||||||||||||||||
| 108 | /* try as an IPv4 literal */ | - | ||||||||||||||||||||||||||||||
| 109 | hints.ai_family = AF_INET; | - | ||||||||||||||||||||||||||||||
| 110 | hints.ai_flags = AI_NUMERICHOST; | - | ||||||||||||||||||||||||||||||
| 111 | if (getaddrinfo(h, p, &hints, &res0) != 0) {
| 0 | ||||||||||||||||||||||||||||||
| 112 | /* try again as an IPv6 literal */ | - | ||||||||||||||||||||||||||||||
| 113 | hints.ai_family = AF_INET6; | - | ||||||||||||||||||||||||||||||
| 114 | if (getaddrinfo(h, p, &hints, &res0) != 0) {
| 0 | ||||||||||||||||||||||||||||||
| 115 | /* last try, with name resolution and save the error */ | - | ||||||||||||||||||||||||||||||
| 116 | hints.ai_family = AF_UNSPEC; | - | ||||||||||||||||||||||||||||||
| 117 | hints.ai_flags = AI_ADDRCONFIG; | - | ||||||||||||||||||||||||||||||
| 118 | if ((s = getaddrinfo(h, p, &hints, &res0)) != 0) {
| 0 | ||||||||||||||||||||||||||||||
| 119 | tls_set_error(ctx, "%s", gai_strerror(s)); | - | ||||||||||||||||||||||||||||||
| 120 | goto err; never executed: goto err; | 0 | ||||||||||||||||||||||||||||||
| 121 | } | - | ||||||||||||||||||||||||||||||
| 122 | } never executed: end of block | 0 | ||||||||||||||||||||||||||||||
| 123 | } never executed: end of block | 0 | ||||||||||||||||||||||||||||||
| 124 | - | |||||||||||||||||||||||||||||||
| 125 | /* It was resolved somehow; now try connecting to what we got */ | - | ||||||||||||||||||||||||||||||
| 126 | s = -1; | - | ||||||||||||||||||||||||||||||
| 127 | for (res = res0; res; res = res->ai_next) {
| 0 | ||||||||||||||||||||||||||||||
| 128 | s = socket(res->ai_family, res->ai_socktype, res->ai_protocol); | - | ||||||||||||||||||||||||||||||
| 129 | if (s == -1) {
| 0 | ||||||||||||||||||||||||||||||
| 130 | tls_set_error(ctx, "socket"); | - | ||||||||||||||||||||||||||||||
| 131 | continue; never executed: continue; | 0 | ||||||||||||||||||||||||||||||
| 132 | } | - | ||||||||||||||||||||||||||||||
| 133 | if (connect(s, res->ai_addr, res->ai_addrlen) == -1) {
| 0 | ||||||||||||||||||||||||||||||
| 134 | tls_set_error(ctx, "connect"); | - | ||||||||||||||||||||||||||||||
| 135 | close(s); | - | ||||||||||||||||||||||||||||||
| 136 | s = -1; | - | ||||||||||||||||||||||||||||||
| 137 | continue; never executed: continue; | 0 | ||||||||||||||||||||||||||||||
| 138 | } | - | ||||||||||||||||||||||||||||||
| 139 | - | |||||||||||||||||||||||||||||||
| 140 | break; /* Connected. */ never executed: break; | 0 | ||||||||||||||||||||||||||||||
| 141 | } | - | ||||||||||||||||||||||||||||||
| 142 | freeaddrinfo(res0); | - | ||||||||||||||||||||||||||||||
| 143 | - | |||||||||||||||||||||||||||||||
| 144 | if (s == -1)
| 0 | ||||||||||||||||||||||||||||||
| 145 | goto err; never executed: goto err; | 0 | ||||||||||||||||||||||||||||||
| 146 | - | |||||||||||||||||||||||||||||||
| 147 | if (servername == NULL)
| 0 | ||||||||||||||||||||||||||||||
| 148 | servername = h; never executed: servername = h; | 0 | ||||||||||||||||||||||||||||||
| 149 | - | |||||||||||||||||||||||||||||||
| 150 | if (tls_connect_socket(ctx, s, servername) != 0) {
| 0 | ||||||||||||||||||||||||||||||
| 151 | close(s); | - | ||||||||||||||||||||||||||||||
| 152 | goto err; never executed: goto err; | 0 | ||||||||||||||||||||||||||||||
| 153 | } | - | ||||||||||||||||||||||||||||||
| 154 | - | |||||||||||||||||||||||||||||||
| 155 | ctx->socket = s; | - | ||||||||||||||||||||||||||||||
| 156 | - | |||||||||||||||||||||||||||||||
| 157 | rv = 0; | - | ||||||||||||||||||||||||||||||
| 158 | - | |||||||||||||||||||||||||||||||
| 159 | err: code before this statement never executed: err: | 0 | ||||||||||||||||||||||||||||||
| 160 | free(hs); | - | ||||||||||||||||||||||||||||||
| 161 | free(ps); | - | ||||||||||||||||||||||||||||||
| 162 | - | |||||||||||||||||||||||||||||||
| 163 | return (rv); never executed: return (rv); | 0 | ||||||||||||||||||||||||||||||
| 164 | } | - | ||||||||||||||||||||||||||||||
| 165 | - | |||||||||||||||||||||||||||||||
| 166 | static int | - | ||||||||||||||||||||||||||||||
| 167 | tls_client_read_session(struct tls *ctx) | - | ||||||||||||||||||||||||||||||
| 168 | { | - | ||||||||||||||||||||||||||||||
| 169 | int sfd = ctx->config->session_fd; | - | ||||||||||||||||||||||||||||||
| 170 | uint8_t *session = NULL; | - | ||||||||||||||||||||||||||||||
| 171 | size_t session_len = 0; | - | ||||||||||||||||||||||||||||||
| 172 | SSL_SESSION *ss = NULL; | - | ||||||||||||||||||||||||||||||
| 173 | BIO *bio = NULL; | - | ||||||||||||||||||||||||||||||
| 174 | struct stat sb; | - | ||||||||||||||||||||||||||||||
| 175 | ssize_t n; | - | ||||||||||||||||||||||||||||||
| 176 | int rv = -1; | - | ||||||||||||||||||||||||||||||
| 177 | - | |||||||||||||||||||||||||||||||
| 178 | if (fstat(sfd, &sb) == -1) {
| 0 | ||||||||||||||||||||||||||||||
| 179 | tls_set_error(ctx, "failed to stat session file"); | - | ||||||||||||||||||||||||||||||
| 180 | goto err; never executed: goto err; | 0 | ||||||||||||||||||||||||||||||
| 181 | } | - | ||||||||||||||||||||||||||||||
| 182 | if (sb.st_size < 0 || sb.st_size > INT_MAX) {
| 0 | ||||||||||||||||||||||||||||||
| 183 | tls_set_errorx(ctx, "invalid session file size"); | - | ||||||||||||||||||||||||||||||
| 184 | goto err; never executed: goto err; | 0 | ||||||||||||||||||||||||||||||
| 185 | } | - | ||||||||||||||||||||||||||||||
| 186 | session_len = (size_t)sb.st_size; | - | ||||||||||||||||||||||||||||||
| 187 | - | |||||||||||||||||||||||||||||||
| 188 | /* A zero size file means that we do not yet have a valid session. */ | - | ||||||||||||||||||||||||||||||
| 189 | if (session_len == 0)
| 0 | ||||||||||||||||||||||||||||||
| 190 | goto done; never executed: goto done; | 0 | ||||||||||||||||||||||||||||||
| 191 | - | |||||||||||||||||||||||||||||||
| 192 | if ((session = malloc(session_len)) == NULL)
| 0 | ||||||||||||||||||||||||||||||
| 193 | goto err; never executed: goto err; | 0 | ||||||||||||||||||||||||||||||
| 194 | - | |||||||||||||||||||||||||||||||
| 195 | n = pread(sfd, session, session_len, 0); | - | ||||||||||||||||||||||||||||||
| 196 | if (n < 0 || (size_t)n != session_len) {
| 0 | ||||||||||||||||||||||||||||||
| 197 | tls_set_error(ctx, "failed to read session file"); | - | ||||||||||||||||||||||||||||||
| 198 | goto err; never executed: goto err; | 0 | ||||||||||||||||||||||||||||||
| 199 | } | - | ||||||||||||||||||||||||||||||
| 200 | if ((bio = BIO_new_mem_buf(session, session_len)) == NULL)
| 0 | ||||||||||||||||||||||||||||||
| 201 | goto err; never executed: goto err; | 0 | ||||||||||||||||||||||||||||||
| 202 | if ((ss = PEM_read_bio_SSL_SESSION(bio, NULL, tls_password_cb,
| 0 | ||||||||||||||||||||||||||||||
| 203 | NULL)) == NULL) {
| 0 | ||||||||||||||||||||||||||||||
| 204 | tls_set_errorx(ctx, "failed to parse session"); | - | ||||||||||||||||||||||||||||||
| 205 | goto err; never executed: goto err; | 0 | ||||||||||||||||||||||||||||||
| 206 | } | - | ||||||||||||||||||||||||||||||
| 207 | - | |||||||||||||||||||||||||||||||
| 208 | if (SSL_set_session(ctx->ssl_conn, ss) != 1) {
| 0 | ||||||||||||||||||||||||||||||
| 209 | tls_set_errorx(ctx, "failed to set session"); | - | ||||||||||||||||||||||||||||||
| 210 | goto err; never executed: goto err; | 0 | ||||||||||||||||||||||||||||||
| 211 | } | - | ||||||||||||||||||||||||||||||
| 212 | - | |||||||||||||||||||||||||||||||
| 213 | done: code before this statement never executed: done: | 0 | ||||||||||||||||||||||||||||||
| 214 | rv = 0; | - | ||||||||||||||||||||||||||||||
| 215 | - | |||||||||||||||||||||||||||||||
| 216 | err: code before this statement never executed: err: | 0 | ||||||||||||||||||||||||||||||
| 217 | freezero(session, session_len); | - | ||||||||||||||||||||||||||||||
| 218 | SSL_SESSION_free(ss); | - | ||||||||||||||||||||||||||||||
| 219 | BIO_free(bio); | - | ||||||||||||||||||||||||||||||
| 220 | - | |||||||||||||||||||||||||||||||
| 221 | return rv; never executed: return rv; | 0 | ||||||||||||||||||||||||||||||
| 222 | } | - | ||||||||||||||||||||||||||||||
| 223 | - | |||||||||||||||||||||||||||||||
| 224 | static int | - | ||||||||||||||||||||||||||||||
| 225 | tls_client_write_session(struct tls *ctx) | - | ||||||||||||||||||||||||||||||
| 226 | { | - | ||||||||||||||||||||||||||||||
| 227 | int sfd = ctx->config->session_fd; | - | ||||||||||||||||||||||||||||||
| 228 | SSL_SESSION *ss = NULL; | - | ||||||||||||||||||||||||||||||
| 229 | BIO *bio = NULL; | - | ||||||||||||||||||||||||||||||
| 230 | long data_len; | - | ||||||||||||||||||||||||||||||
| 231 | char *data; | - | ||||||||||||||||||||||||||||||
| 232 | off_t offset; | - | ||||||||||||||||||||||||||||||
| 233 | size_t len; | - | ||||||||||||||||||||||||||||||
| 234 | ssize_t n; | - | ||||||||||||||||||||||||||||||
| 235 | int rv = -1; | - | ||||||||||||||||||||||||||||||
| 236 | - | |||||||||||||||||||||||||||||||
| 237 | if ((ss = SSL_get1_session(ctx->ssl_conn)) == NULL) {
| 0 | ||||||||||||||||||||||||||||||
| 238 | if (ftruncate(sfd, 0) == -1) {
| 0 | ||||||||||||||||||||||||||||||
| 239 | tls_set_error(ctx, "failed to truncate session file"); | - | ||||||||||||||||||||||||||||||
| 240 | goto err; never executed: goto err; | 0 | ||||||||||||||||||||||||||||||
| 241 | } | - | ||||||||||||||||||||||||||||||
| 242 | goto done; never executed: goto done; | 0 | ||||||||||||||||||||||||||||||
| 243 | } | - | ||||||||||||||||||||||||||||||
| 244 | - | |||||||||||||||||||||||||||||||
| 245 | if ((bio = BIO_new(BIO_s_mem())) == NULL)
| 0 | ||||||||||||||||||||||||||||||
| 246 | goto err; never executed: goto err; | 0 | ||||||||||||||||||||||||||||||
| 247 | if (PEM_write_bio_SSL_SESSION(bio, ss) == 0)
| 0 | ||||||||||||||||||||||||||||||
| 248 | goto err; never executed: goto err; | 0 | ||||||||||||||||||||||||||||||
| 249 | if ((data_len = BIO_get_mem_data(bio, &data)) <= 0)
| 0 | ||||||||||||||||||||||||||||||
| 250 | goto err; never executed: goto err; | 0 | ||||||||||||||||||||||||||||||
| 251 | - | |||||||||||||||||||||||||||||||
| 252 | len = (size_t)data_len; | - | ||||||||||||||||||||||||||||||
| 253 | offset = 0; | - | ||||||||||||||||||||||||||||||
| 254 | - | |||||||||||||||||||||||||||||||
| 255 | if (ftruncate(sfd, len) == -1) {
| 0 | ||||||||||||||||||||||||||||||
| 256 | tls_set_error(ctx, "failed to truncate session file"); | - | ||||||||||||||||||||||||||||||
| 257 | goto err; never executed: goto err; | 0 | ||||||||||||||||||||||||||||||
| 258 | } | - | ||||||||||||||||||||||||||||||
| 259 | while (len > 0) {
| 0 | ||||||||||||||||||||||||||||||
| 260 | if ((n = pwrite(sfd, data + offset, len, offset)) == -1) {
| 0 | ||||||||||||||||||||||||||||||
| 261 | tls_set_error(ctx, "failed to write session file"); | - | ||||||||||||||||||||||||||||||
| 262 | goto err; never executed: goto err; | 0 | ||||||||||||||||||||||||||||||
| 263 | } | - | ||||||||||||||||||||||||||||||
| 264 | offset += n; | - | ||||||||||||||||||||||||||||||
| 265 | len -= n; | - | ||||||||||||||||||||||||||||||
| 266 | } never executed: end of block | 0 | ||||||||||||||||||||||||||||||
| 267 | - | |||||||||||||||||||||||||||||||
| 268 | done: code before this statement never executed: done: | 0 | ||||||||||||||||||||||||||||||
| 269 | rv = 0; | - | ||||||||||||||||||||||||||||||
| 270 | - | |||||||||||||||||||||||||||||||
| 271 | err: code before this statement never executed: err: | 0 | ||||||||||||||||||||||||||||||
| 272 | SSL_SESSION_free(ss); | - | ||||||||||||||||||||||||||||||
| 273 | BIO_free_all(bio); | - | ||||||||||||||||||||||||||||||
| 274 | - | |||||||||||||||||||||||||||||||
| 275 | return (rv); never executed: return (rv); | 0 | ||||||||||||||||||||||||||||||
| 276 | } | - | ||||||||||||||||||||||||||||||
| 277 | - | |||||||||||||||||||||||||||||||
| 278 | static int | - | ||||||||||||||||||||||||||||||
| 279 | tls_connect_common(struct tls *ctx, const char *servername) | - | ||||||||||||||||||||||||||||||
| 280 | { | - | ||||||||||||||||||||||||||||||
| 281 | union tls_addr addrbuf; | - | ||||||||||||||||||||||||||||||
| 282 | int rv = -1; | - | ||||||||||||||||||||||||||||||
| 283 | - | |||||||||||||||||||||||||||||||
| 284 | if ((ctx->flags & TLS_CLIENT) == 0) {
| 0-4 | ||||||||||||||||||||||||||||||
| 285 | tls_set_errorx(ctx, "not a client context"); | - | ||||||||||||||||||||||||||||||
| 286 | goto err; never executed: goto err; | 0 | ||||||||||||||||||||||||||||||
| 287 | } | - | ||||||||||||||||||||||||||||||
| 288 | - | |||||||||||||||||||||||||||||||
| 289 | if (servername != NULL) {
| 0-4 | ||||||||||||||||||||||||||||||
| 290 | if ((ctx->servername = strdup(servername)) == NULL) { never executed: __retval = (char *) memcpy (__retval, servername , __len);
| 0-4 | ||||||||||||||||||||||||||||||
| 291 | tls_set_errorx(ctx, "out of memory"); | - | ||||||||||||||||||||||||||||||
| 292 | goto err; never executed: goto err; | 0 | ||||||||||||||||||||||||||||||
| 293 | } | - | ||||||||||||||||||||||||||||||
| 294 | } executed 4 times by 1 test: end of blockExecuted by:
| 4 | ||||||||||||||||||||||||||||||
| 295 | - | |||||||||||||||||||||||||||||||
| 296 | if ((ctx->ssl_ctx = SSL_CTX_new(SSLv23_client_method())) == NULL) {
| 0-4 | ||||||||||||||||||||||||||||||
| 297 | tls_set_errorx(ctx, "ssl context failure"); | - | ||||||||||||||||||||||||||||||
| 298 | goto err; never executed: goto err; | 0 | ||||||||||||||||||||||||||||||
| 299 | } | - | ||||||||||||||||||||||||||||||
| 300 | - | |||||||||||||||||||||||||||||||
| 301 | if (tls_configure_ssl(ctx, ctx->ssl_ctx) != 0)
| 0-4 | ||||||||||||||||||||||||||||||
| 302 | goto err; never executed: goto err; | 0 | ||||||||||||||||||||||||||||||
| 303 | - | |||||||||||||||||||||||||||||||
| 304 | if (tls_configure_ssl_keypair(ctx, ctx->ssl_ctx,
| 0-4 | ||||||||||||||||||||||||||||||
| 305 | ctx->config->keypair, 0) != 0)
| 0-4 | ||||||||||||||||||||||||||||||
| 306 | goto err; never executed: goto err; | 0 | ||||||||||||||||||||||||||||||
| 307 | - | |||||||||||||||||||||||||||||||
| 308 | if (ctx->config->verify_name) {
| 0-4 | ||||||||||||||||||||||||||||||
| 309 | if (servername == NULL) {
| 0 | ||||||||||||||||||||||||||||||
| 310 | tls_set_errorx(ctx, "server name not specified"); | - | ||||||||||||||||||||||||||||||
| 311 | goto err; never executed: goto err; | 0 | ||||||||||||||||||||||||||||||
| 312 | } | - | ||||||||||||||||||||||||||||||
| 313 | } never executed: end of block | 0 | ||||||||||||||||||||||||||||||
| 314 | - | |||||||||||||||||||||||||||||||
| 315 | if (tls_configure_ssl_verify(ctx, ctx->ssl_ctx, SSL_VERIFY_PEER) == -1)
| 0-4 | ||||||||||||||||||||||||||||||
| 316 | goto err; never executed: goto err; | 0 | ||||||||||||||||||||||||||||||
| 317 | - | |||||||||||||||||||||||||||||||
| 318 | if (ctx->config->ecdhecurves != NULL) {
| 0-4 | ||||||||||||||||||||||||||||||
| 319 | if (SSL_CTX_set1_groups(ctx->ssl_ctx, ctx->config->ecdhecurves,
| 0-4 | ||||||||||||||||||||||||||||||
| 320 | ctx->config->ecdhecurves_len) != 1) {
| 0-4 | ||||||||||||||||||||||||||||||
| 321 | tls_set_errorx(ctx, "failed to set ecdhe curves"); | - | ||||||||||||||||||||||||||||||
| 322 | goto err; never executed: goto err; | 0 | ||||||||||||||||||||||||||||||
| 323 | } | - | ||||||||||||||||||||||||||||||
| 324 | } executed 4 times by 1 test: end of blockExecuted by:
| 4 | ||||||||||||||||||||||||||||||
| 325 | - | |||||||||||||||||||||||||||||||
| 326 | if (SSL_CTX_set_tlsext_status_cb(ctx->ssl_ctx, tls_ocsp_verify_cb) != 1) {
| 0-4 | ||||||||||||||||||||||||||||||
| 327 | tls_set_errorx(ctx, "ssl OCSP verification setup failure"); | - | ||||||||||||||||||||||||||||||
| 328 | goto err; never executed: goto err; | 0 | ||||||||||||||||||||||||||||||
| 329 | } | - | ||||||||||||||||||||||||||||||
| 330 | - | |||||||||||||||||||||||||||||||
| 331 | if ((ctx->ssl_conn = SSL_new(ctx->ssl_ctx)) == NULL) {
| 0-4 | ||||||||||||||||||||||||||||||
| 332 | tls_set_errorx(ctx, "ssl connection failure"); | - | ||||||||||||||||||||||||||||||
| 333 | goto err; never executed: goto err; | 0 | ||||||||||||||||||||||||||||||
| 334 | } | - | ||||||||||||||||||||||||||||||
| 335 | - | |||||||||||||||||||||||||||||||
| 336 | if (SSL_set_app_data(ctx->ssl_conn, ctx) != 1) {
| 0-4 | ||||||||||||||||||||||||||||||
| 337 | tls_set_errorx(ctx, "ssl application data failure"); | - | ||||||||||||||||||||||||||||||
| 338 | goto err; never executed: goto err; | 0 | ||||||||||||||||||||||||||||||
| 339 | } | - | ||||||||||||||||||||||||||||||
| 340 | - | |||||||||||||||||||||||||||||||
| 341 | if (ctx->config->session_fd != -1) {
| 0-4 | ||||||||||||||||||||||||||||||
| 342 | SSL_clear_options(ctx->ssl_conn, SSL_OP_NO_TICKET); | - | ||||||||||||||||||||||||||||||
| 343 | if (tls_client_read_session(ctx) == -1)
| 0 | ||||||||||||||||||||||||||||||
| 344 | goto err; never executed: goto err; | 0 | ||||||||||||||||||||||||||||||
| 345 | } never executed: end of block | 0 | ||||||||||||||||||||||||||||||
| 346 | - | |||||||||||||||||||||||||||||||
| 347 | if (SSL_set_tlsext_status_type(ctx->ssl_conn, TLSEXT_STATUSTYPE_ocsp) != 1) {
| 0-4 | ||||||||||||||||||||||||||||||
| 348 | tls_set_errorx(ctx, "ssl OCSP extension setup failure"); | - | ||||||||||||||||||||||||||||||
| 349 | goto err; never executed: goto err; | 0 | ||||||||||||||||||||||||||||||
| 350 | } | - | ||||||||||||||||||||||||||||||
| 351 | - | |||||||||||||||||||||||||||||||
| 352 | /* | - | ||||||||||||||||||||||||||||||
| 353 | * RFC4366 (SNI): Literal IPv4 and IPv6 addresses are not | - | ||||||||||||||||||||||||||||||
| 354 | * permitted in "HostName". | - | ||||||||||||||||||||||||||||||
| 355 | */ | - | ||||||||||||||||||||||||||||||
| 356 | if (servername != NULL &&
| 0-4 | ||||||||||||||||||||||||||||||
| 357 | inet_pton(AF_INET, servername, &addrbuf) != 1 &&
| 0-4 | ||||||||||||||||||||||||||||||
| 358 | inet_pton(AF_INET6, servername, &addrbuf) != 1) {
| 0-4 | ||||||||||||||||||||||||||||||
| 359 | if (SSL_set_tlsext_host_name(ctx->ssl_conn, servername) == 0) {
| 0-4 | ||||||||||||||||||||||||||||||
| 360 | tls_set_errorx(ctx, "server name indication failure"); | - | ||||||||||||||||||||||||||||||
| 361 | goto err; never executed: goto err; | 0 | ||||||||||||||||||||||||||||||
| 362 | } | - | ||||||||||||||||||||||||||||||
| 363 | } executed 4 times by 1 test: end of blockExecuted by:
| 4 | ||||||||||||||||||||||||||||||
| 364 | - | |||||||||||||||||||||||||||||||
| 365 | ctx->state |= TLS_CONNECTED; | - | ||||||||||||||||||||||||||||||
| 366 | rv = 0; | - | ||||||||||||||||||||||||||||||
| 367 | - | |||||||||||||||||||||||||||||||
| 368 | err: code before this statement executed 4 times by 1 test: err:Executed by:
| 4 | ||||||||||||||||||||||||||||||
| 369 | return (rv); executed 4 times by 1 test: return (rv);Executed by:
| 4 | ||||||||||||||||||||||||||||||
| 370 | } | - | ||||||||||||||||||||||||||||||
| 371 | - | |||||||||||||||||||||||||||||||
| 372 | int | - | ||||||||||||||||||||||||||||||
| 373 | tls_connect_socket(struct tls *ctx, int s, const char *servername) | - | ||||||||||||||||||||||||||||||
| 374 | { | - | ||||||||||||||||||||||||||||||
| 375 | return tls_connect_fds(ctx, s, s, servername); executed 1 time by 1 test: return tls_connect_fds(ctx, s, s, servername);Executed by:
| 1 | ||||||||||||||||||||||||||||||
| 376 | } | - | ||||||||||||||||||||||||||||||
| 377 | - | |||||||||||||||||||||||||||||||
| 378 | int | - | ||||||||||||||||||||||||||||||
| 379 | tls_connect_fds(struct tls *ctx, int fd_read, int fd_write, | - | ||||||||||||||||||||||||||||||
| 380 | const char *servername) | - | ||||||||||||||||||||||||||||||
| 381 | { | - | ||||||||||||||||||||||||||||||
| 382 | int rv = -1; | - | ||||||||||||||||||||||||||||||
| 383 | - | |||||||||||||||||||||||||||||||
| 384 | if (fd_read < 0 || fd_write < 0) {
| 0-2 | ||||||||||||||||||||||||||||||
| 385 | tls_set_errorx(ctx, "invalid file descriptors"); | - | ||||||||||||||||||||||||||||||
| 386 | goto err; never executed: goto err; | 0 | ||||||||||||||||||||||||||||||
| 387 | } | - | ||||||||||||||||||||||||||||||
| 388 | - | |||||||||||||||||||||||||||||||
| 389 | if (tls_connect_common(ctx, servername) != 0)
| 0-2 | ||||||||||||||||||||||||||||||
| 390 | goto err; never executed: goto err; | 0 | ||||||||||||||||||||||||||||||
| 391 | - | |||||||||||||||||||||||||||||||
| 392 | if (SSL_set_rfd(ctx->ssl_conn, fd_read) != 1 ||
| 0-2 | ||||||||||||||||||||||||||||||
| 393 | SSL_set_wfd(ctx->ssl_conn, fd_write) != 1) {
| 0-2 | ||||||||||||||||||||||||||||||
| 394 | tls_set_errorx(ctx, "ssl file descriptor failure"); | - | ||||||||||||||||||||||||||||||
| 395 | goto err; never executed: goto err; | 0 | ||||||||||||||||||||||||||||||
| 396 | } | - | ||||||||||||||||||||||||||||||
| 397 | - | |||||||||||||||||||||||||||||||
| 398 | rv = 0; | - | ||||||||||||||||||||||||||||||
| 399 | err: code before this statement executed 2 times by 1 test: err:Executed by:
| 2 | ||||||||||||||||||||||||||||||
| 400 | return (rv); executed 2 times by 1 test: return (rv);Executed by:
| 2 | ||||||||||||||||||||||||||||||
| 401 | } | - | ||||||||||||||||||||||||||||||
| 402 | - | |||||||||||||||||||||||||||||||
| 403 | int | - | ||||||||||||||||||||||||||||||
| 404 | tls_connect_cbs(struct tls *ctx, tls_read_cb read_cb, | - | ||||||||||||||||||||||||||||||
| 405 | tls_write_cb write_cb, void *cb_arg, const char *servername) | - | ||||||||||||||||||||||||||||||
| 406 | { | - | ||||||||||||||||||||||||||||||
| 407 | int rv = -1; | - | ||||||||||||||||||||||||||||||
| 408 | - | |||||||||||||||||||||||||||||||
| 409 | if (tls_connect_common(ctx, servername) != 0)
| 0-2 | ||||||||||||||||||||||||||||||
| 410 | goto err; never executed: goto err; | 0 | ||||||||||||||||||||||||||||||
| 411 | - | |||||||||||||||||||||||||||||||
| 412 | if (tls_set_cbs(ctx, read_cb, write_cb, cb_arg) != 0)
| 0-2 | ||||||||||||||||||||||||||||||
| 413 | goto err; never executed: goto err; | 0 | ||||||||||||||||||||||||||||||
| 414 | - | |||||||||||||||||||||||||||||||
| 415 | rv = 0; | - | ||||||||||||||||||||||||||||||
| 416 | - | |||||||||||||||||||||||||||||||
| 417 | err: code before this statement executed 2 times by 1 test: err:Executed by:
| 2 | ||||||||||||||||||||||||||||||
| 418 | return (rv); executed 2 times by 1 test: return (rv);Executed by:
| 2 | ||||||||||||||||||||||||||||||
| 419 | } | - | ||||||||||||||||||||||||||||||
| 420 | - | |||||||||||||||||||||||||||||||
| 421 | int | - | ||||||||||||||||||||||||||||||
| 422 | tls_handshake_client(struct tls *ctx) | - | ||||||||||||||||||||||||||||||
| 423 | { | - | ||||||||||||||||||||||||||||||
| 424 | X509 *cert = NULL; | - | ||||||||||||||||||||||||||||||
| 425 | int match, ssl_ret; | - | ||||||||||||||||||||||||||||||
| 426 | int rv = -1; | - | ||||||||||||||||||||||||||||||
| 427 | - | |||||||||||||||||||||||||||||||
| 428 | if ((ctx->flags & TLS_CLIENT) == 0) {
| 0-17 | ||||||||||||||||||||||||||||||
| 429 | tls_set_errorx(ctx, "not a client context"); | - | ||||||||||||||||||||||||||||||
| 430 | goto err; never executed: goto err; | 0 | ||||||||||||||||||||||||||||||
| 431 | } | - | ||||||||||||||||||||||||||||||
| 432 | - | |||||||||||||||||||||||||||||||
| 433 | if ((ctx->state & TLS_CONNECTED) == 0) {
| 1-16 | ||||||||||||||||||||||||||||||
| 434 | tls_set_errorx(ctx, "context not connected"); | - | ||||||||||||||||||||||||||||||
| 435 | goto err; executed 1 time by 1 test: goto err;Executed by:
| 1 | ||||||||||||||||||||||||||||||
| 436 | } | - | ||||||||||||||||||||||||||||||
| 437 | - | |||||||||||||||||||||||||||||||
| 438 | ctx->state |= TLS_SSL_NEEDS_SHUTDOWN; | - | ||||||||||||||||||||||||||||||
| 439 | - | |||||||||||||||||||||||||||||||
| 440 | ERR_clear_error(); | - | ||||||||||||||||||||||||||||||
| 441 | if ((ssl_ret = SSL_connect(ctx->ssl_conn)) != 1) {
| 4-12 | ||||||||||||||||||||||||||||||
| 442 | rv = tls_ssl_error(ctx, ctx->ssl_conn, ssl_ret, "handshake"); | - | ||||||||||||||||||||||||||||||
| 443 | goto err; executed 12 times by 1 test: goto err;Executed by:
| 12 | ||||||||||||||||||||||||||||||
| 444 | } | - | ||||||||||||||||||||||||||||||
| 445 | - | |||||||||||||||||||||||||||||||
| 446 | if (ctx->config->verify_name) {
| 0-4 | ||||||||||||||||||||||||||||||
| 447 | cert = SSL_get_peer_certificate(ctx->ssl_conn); | - | ||||||||||||||||||||||||||||||
| 448 | if (cert == NULL) {
| 0 | ||||||||||||||||||||||||||||||
| 449 | tls_set_errorx(ctx, "no server certificate"); | - | ||||||||||||||||||||||||||||||
| 450 | goto err; never executed: goto err; | 0 | ||||||||||||||||||||||||||||||
| 451 | } | - | ||||||||||||||||||||||||||||||
| 452 | if (tls_check_name(ctx, cert, ctx->servername, &match) == -1)
| 0 | ||||||||||||||||||||||||||||||
| 453 | goto err; never executed: goto err; | 0 | ||||||||||||||||||||||||||||||
| 454 | if (!match) {
| 0 | ||||||||||||||||||||||||||||||
| 455 | tls_set_errorx(ctx, "name `%s' not present in" | - | ||||||||||||||||||||||||||||||
| 456 | " server certificate", ctx->servername); | - | ||||||||||||||||||||||||||||||
| 457 | goto err; never executed: goto err; | 0 | ||||||||||||||||||||||||||||||
| 458 | } | - | ||||||||||||||||||||||||||||||
| 459 | } never executed: end of block | 0 | ||||||||||||||||||||||||||||||
| 460 | - | |||||||||||||||||||||||||||||||
| 461 | ctx->state |= TLS_HANDSHAKE_COMPLETE; | - | ||||||||||||||||||||||||||||||
| 462 | - | |||||||||||||||||||||||||||||||
| 463 | if (ctx->config->session_fd != -1) {
| 0-4 | ||||||||||||||||||||||||||||||
| 464 | if (tls_client_write_session(ctx) == -1)
| 0 | ||||||||||||||||||||||||||||||
| 465 | goto err; never executed: goto err; | 0 | ||||||||||||||||||||||||||||||
| 466 | } never executed: end of block | 0 | ||||||||||||||||||||||||||||||
| 467 | - | |||||||||||||||||||||||||||||||
| 468 | rv = 0; | - | ||||||||||||||||||||||||||||||
| 469 | - | |||||||||||||||||||||||||||||||
| 470 | err: code before this statement executed 4 times by 1 test: err:Executed by:
| 4 | ||||||||||||||||||||||||||||||
| 471 | X509_free(cert); | - | ||||||||||||||||||||||||||||||
| 472 | - | |||||||||||||||||||||||||||||||
| 473 | return (rv); executed 17 times by 1 test: return (rv);Executed by:
| 17 | ||||||||||||||||||||||||||||||
| 474 | } | - | ||||||||||||||||||||||||||||||
| Source code | Switch to Preprocessed file |