diff options
author | joshua <> | 2024-03-26 06:24:52 +0000 |
---|---|---|
committer | joshua <> | 2024-03-26 06:24:52 +0000 |
commit | 936498dd6ef929653cff09dd6b3303e39c8ad08d (patch) | |
tree | c0d04141b5fceb9e1cb05bec1e7e8fe3d0ac35f9 /src/lib/libtls/tls_client.c | |
parent | 7e79cc7d135c6ac69536ff44c870a4af9ecee499 (diff) | |
download | openbsd-936498dd6ef929653cff09dd6b3303e39c8ad08d.tar.gz openbsd-936498dd6ef929653cff09dd6b3303e39c8ad08d.tar.bz2 openbsd-936498dd6ef929653cff09dd6b3303e39c8ad08d.zip |
Add error code support to libtls
This adds tls_config_error_code() and tls_error_code(), which will become
public API at a later date.
Additional error codes will be added in follow-up commits.
ok jsing@ beck@
Diffstat (limited to 'src/lib/libtls/tls_client.c')
-rw-r--r-- | src/lib/libtls/tls_client.c | 87 |
1 files changed, 54 insertions, 33 deletions
diff --git a/src/lib/libtls/tls_client.c b/src/lib/libtls/tls_client.c index deb24ebc23..40ef9a02e2 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.49 2023/05/14 07:26:25 op Exp $ */ | 1 | /* $OpenBSD: tls_client.c,v 1.50 2024/03/26 06:24:52 joshua Exp $ */ |
2 | /* | 2 | /* |
3 | * Copyright (c) 2014 Joel Sing <jsing@openbsd.org> | 3 | * Copyright (c) 2014 Joel Sing <jsing@openbsd.org> |
4 | * | 4 | * |
@@ -66,12 +66,12 @@ tls_connect_servername(struct tls *ctx, const char *host, const char *port, | |||
66 | int rv = -1, s = -1, ret; | 66 | int rv = -1, s = -1, ret; |
67 | 67 | ||
68 | if ((ctx->flags & TLS_CLIENT) == 0) { | 68 | if ((ctx->flags & TLS_CLIENT) == 0) { |
69 | tls_set_errorx(ctx, "not a client context"); | 69 | tls_set_errorx(ctx, TLS_ERROR_UNKNOWN, "not a client context"); |
70 | goto err; | 70 | goto err; |
71 | } | 71 | } |
72 | 72 | ||
73 | if (host == NULL) { | 73 | if (host == NULL) { |
74 | tls_set_errorx(ctx, "host not specified"); | 74 | tls_set_errorx(ctx, TLS_ERROR_UNKNOWN, "host not specified"); |
75 | goto err; | 75 | goto err; |
76 | } | 76 | } |
77 | 77 | ||
@@ -79,11 +79,11 @@ tls_connect_servername(struct tls *ctx, const char *host, const char *port, | |||
79 | if (port == NULL) { | 79 | if (port == NULL) { |
80 | ret = tls_host_port(host, &hs, &ps); | 80 | ret = tls_host_port(host, &hs, &ps); |
81 | if (ret == -1) { | 81 | if (ret == -1) { |
82 | tls_set_errorx(ctx, "memory allocation failure"); | 82 | tls_set_errorx(ctx, TLS_ERROR_OUT_OF_MEMORY, "out of memory"); |
83 | goto err; | 83 | goto err; |
84 | } | 84 | } |
85 | if (ret != 0) { | 85 | if (ret != 0) { |
86 | tls_set_errorx(ctx, "no port provided"); | 86 | tls_set_errorx(ctx, TLS_ERROR_UNKNOWN, "no port provided"); |
87 | goto err; | 87 | goto err; |
88 | } | 88 | } |
89 | } | 89 | } |
@@ -114,7 +114,8 @@ tls_connect_servername(struct tls *ctx, const char *host, const char *port, | |||
114 | hints.ai_family = AF_UNSPEC; | 114 | hints.ai_family = AF_UNSPEC; |
115 | hints.ai_flags = AI_ADDRCONFIG; | 115 | hints.ai_flags = AI_ADDRCONFIG; |
116 | if ((s = getaddrinfo(h, p, &hints, &res0)) != 0) { | 116 | if ((s = getaddrinfo(h, p, &hints, &res0)) != 0) { |
117 | tls_set_error(ctx, "%s", gai_strerror(s)); | 117 | tls_set_error(ctx, TLS_ERROR_UNKNOWN, |
118 | "%s", gai_strerror(s)); | ||
118 | goto err; | 119 | goto err; |
119 | } | 120 | } |
120 | } | 121 | } |
@@ -125,11 +126,13 @@ tls_connect_servername(struct tls *ctx, const char *host, const char *port, | |||
125 | for (res = res0; res; res = res->ai_next) { | 126 | for (res = res0; res; res = res->ai_next) { |
126 | s = socket(res->ai_family, res->ai_socktype, res->ai_protocol); | 127 | s = socket(res->ai_family, res->ai_socktype, res->ai_protocol); |
127 | if (s == -1) { | 128 | if (s == -1) { |
128 | tls_set_error(ctx, "socket"); | 129 | tls_set_error(ctx, TLS_ERROR_UNKNOWN, |
130 | "socket"); | ||
129 | continue; | 131 | continue; |
130 | } | 132 | } |
131 | if (connect(s, res->ai_addr, res->ai_addrlen) == -1) { | 133 | if (connect(s, res->ai_addr, res->ai_addrlen) == -1) { |
132 | tls_set_error(ctx, "connect"); | 134 | tls_set_error(ctx, TLS_ERROR_UNKNOWN, |
135 | "connect"); | ||
133 | close(s); | 136 | close(s); |
134 | s = -1; | 137 | s = -1; |
135 | continue; | 138 | continue; |
@@ -174,11 +177,13 @@ tls_client_read_session(struct tls *ctx) | |||
174 | int rv = -1; | 177 | int rv = -1; |
175 | 178 | ||
176 | if (fstat(sfd, &sb) == -1) { | 179 | if (fstat(sfd, &sb) == -1) { |
177 | tls_set_error(ctx, "failed to stat session file"); | 180 | tls_set_error(ctx, TLS_ERROR_UNKNOWN, |
181 | "failed to stat session file"); | ||
178 | goto err; | 182 | goto err; |
179 | } | 183 | } |
180 | if (sb.st_size < 0 || sb.st_size > INT_MAX) { | 184 | if (sb.st_size < 0 || sb.st_size > INT_MAX) { |
181 | tls_set_errorx(ctx, "invalid session file size"); | 185 | tls_set_errorx(ctx, TLS_ERROR_UNKNOWN, |
186 | "invalid session file size"); | ||
182 | goto err; | 187 | goto err; |
183 | } | 188 | } |
184 | session_len = (size_t)sb.st_size; | 189 | session_len = (size_t)sb.st_size; |
@@ -192,19 +197,22 @@ tls_client_read_session(struct tls *ctx) | |||
192 | 197 | ||
193 | n = pread(sfd, session, session_len, 0); | 198 | n = pread(sfd, session, session_len, 0); |
194 | if (n < 0 || (size_t)n != session_len) { | 199 | if (n < 0 || (size_t)n != session_len) { |
195 | tls_set_error(ctx, "failed to read session file"); | 200 | tls_set_error(ctx, TLS_ERROR_UNKNOWN, |
201 | "failed to read session file"); | ||
196 | goto err; | 202 | goto err; |
197 | } | 203 | } |
198 | if ((bio = BIO_new_mem_buf(session, session_len)) == NULL) | 204 | if ((bio = BIO_new_mem_buf(session, session_len)) == NULL) |
199 | goto err; | 205 | goto err; |
200 | if ((ss = PEM_read_bio_SSL_SESSION(bio, NULL, tls_password_cb, | 206 | if ((ss = PEM_read_bio_SSL_SESSION(bio, NULL, tls_password_cb, |
201 | NULL)) == NULL) { | 207 | NULL)) == NULL) { |
202 | tls_set_errorx(ctx, "failed to parse session"); | 208 | tls_set_errorx(ctx, TLS_ERROR_UNKNOWN, |
209 | "failed to parse session"); | ||
203 | goto err; | 210 | goto err; |
204 | } | 211 | } |
205 | 212 | ||
206 | if (SSL_set_session(ctx->ssl_conn, ss) != 1) { | 213 | if (SSL_set_session(ctx->ssl_conn, ss) != 1) { |
207 | tls_set_errorx(ctx, "failed to set session"); | 214 | tls_set_errorx(ctx, TLS_ERROR_UNKNOWN, |
215 | "failed to set session"); | ||
208 | goto err; | 216 | goto err; |
209 | } | 217 | } |
210 | 218 | ||
@@ -234,7 +242,8 @@ tls_client_write_session(struct tls *ctx) | |||
234 | 242 | ||
235 | if ((ss = SSL_get1_session(ctx->ssl_conn)) == NULL) { | 243 | if ((ss = SSL_get1_session(ctx->ssl_conn)) == NULL) { |
236 | if (ftruncate(sfd, 0) == -1) { | 244 | if (ftruncate(sfd, 0) == -1) { |
237 | tls_set_error(ctx, "failed to truncate session file"); | 245 | tls_set_error(ctx, TLS_ERROR_UNKNOWN, |
246 | "failed to truncate session file"); | ||
238 | goto err; | 247 | goto err; |
239 | } | 248 | } |
240 | goto done; | 249 | goto done; |
@@ -251,12 +260,14 @@ tls_client_write_session(struct tls *ctx) | |||
251 | offset = 0; | 260 | offset = 0; |
252 | 261 | ||
253 | if (ftruncate(sfd, len) == -1) { | 262 | if (ftruncate(sfd, len) == -1) { |
254 | tls_set_error(ctx, "failed to truncate session file"); | 263 | tls_set_error(ctx, TLS_ERROR_UNKNOWN, |
264 | "failed to truncate session file"); | ||
255 | goto err; | 265 | goto err; |
256 | } | 266 | } |
257 | while (len > 0) { | 267 | while (len > 0) { |
258 | if ((n = pwrite(sfd, data + offset, len, offset)) == -1) { | 268 | if ((n = pwrite(sfd, data + offset, len, offset)) == -1) { |
259 | tls_set_error(ctx, "failed to write session file"); | 269 | tls_set_error(ctx, TLS_ERROR_UNKNOWN, |
270 | "failed to write session file"); | ||
260 | goto err; | 271 | goto err; |
261 | } | 272 | } |
262 | offset += n; | 273 | offset += n; |
@@ -281,13 +292,14 @@ tls_connect_common(struct tls *ctx, const char *servername) | |||
281 | int rv = -1; | 292 | int rv = -1; |
282 | 293 | ||
283 | if ((ctx->flags & TLS_CLIENT) == 0) { | 294 | if ((ctx->flags & TLS_CLIENT) == 0) { |
284 | tls_set_errorx(ctx, "not a client context"); | 295 | tls_set_errorx(ctx, TLS_ERROR_UNKNOWN, "not a client context"); |
285 | goto err; | 296 | goto err; |
286 | } | 297 | } |
287 | 298 | ||
288 | if (servername != NULL) { | 299 | if (servername != NULL) { |
289 | if ((ctx->servername = strdup(servername)) == NULL) { | 300 | if ((ctx->servername = strdup(servername)) == NULL) { |
290 | tls_set_errorx(ctx, "out of memory"); | 301 | tls_set_errorx(ctx, TLS_ERROR_OUT_OF_MEMORY, |
302 | "out of memory"); | ||
291 | goto err; | 303 | goto err; |
292 | } | 304 | } |
293 | 305 | ||
@@ -304,7 +316,7 @@ tls_connect_common(struct tls *ctx, const char *servername) | |||
304 | } | 316 | } |
305 | 317 | ||
306 | if ((ctx->ssl_ctx = SSL_CTX_new(SSLv23_client_method())) == NULL) { | 318 | if ((ctx->ssl_ctx = SSL_CTX_new(SSLv23_client_method())) == NULL) { |
307 | tls_set_errorx(ctx, "ssl context failure"); | 319 | tls_set_errorx(ctx, TLS_ERROR_UNKNOWN, "ssl context failure"); |
308 | goto err; | 320 | goto err; |
309 | } | 321 | } |
310 | 322 | ||
@@ -317,7 +329,8 @@ tls_connect_common(struct tls *ctx, const char *servername) | |||
317 | 329 | ||
318 | if (ctx->config->verify_name) { | 330 | if (ctx->config->verify_name) { |
319 | if (ctx->servername == NULL) { | 331 | if (ctx->servername == NULL) { |
320 | tls_set_errorx(ctx, "server name not specified"); | 332 | tls_set_errorx(ctx, TLS_ERROR_UNKNOWN, |
333 | "server name not specified"); | ||
321 | goto err; | 334 | goto err; |
322 | } | 335 | } |
323 | } | 336 | } |
@@ -328,23 +341,26 @@ tls_connect_common(struct tls *ctx, const char *servername) | |||
328 | if (ctx->config->ecdhecurves != NULL) { | 341 | if (ctx->config->ecdhecurves != NULL) { |
329 | if (SSL_CTX_set1_groups(ctx->ssl_ctx, ctx->config->ecdhecurves, | 342 | if (SSL_CTX_set1_groups(ctx->ssl_ctx, ctx->config->ecdhecurves, |
330 | ctx->config->ecdhecurves_len) != 1) { | 343 | ctx->config->ecdhecurves_len) != 1) { |
331 | tls_set_errorx(ctx, "failed to set ecdhe curves"); | 344 | tls_set_errorx(ctx, TLS_ERROR_UNKNOWN, |
345 | "failed to set ecdhe curves"); | ||
332 | goto err; | 346 | goto err; |
333 | } | 347 | } |
334 | } | 348 | } |
335 | 349 | ||
336 | if (SSL_CTX_set_tlsext_status_cb(ctx->ssl_ctx, tls_ocsp_verify_cb) != 1) { | 350 | if (SSL_CTX_set_tlsext_status_cb(ctx->ssl_ctx, tls_ocsp_verify_cb) != 1) { |
337 | tls_set_errorx(ctx, "ssl OCSP verification setup failure"); | 351 | tls_set_errorx(ctx, TLS_ERROR_UNKNOWN, |
352 | "ssl OCSP verification setup failure"); | ||
338 | goto err; | 353 | goto err; |
339 | } | 354 | } |
340 | 355 | ||
341 | if ((ctx->ssl_conn = SSL_new(ctx->ssl_ctx)) == NULL) { | 356 | if ((ctx->ssl_conn = SSL_new(ctx->ssl_ctx)) == NULL) { |
342 | tls_set_errorx(ctx, "ssl connection failure"); | 357 | tls_set_errorx(ctx, TLS_ERROR_UNKNOWN, "ssl connection failure"); |
343 | goto err; | 358 | goto err; |
344 | } | 359 | } |
345 | 360 | ||
346 | if (SSL_set_app_data(ctx->ssl_conn, ctx) != 1) { | 361 | if (SSL_set_app_data(ctx->ssl_conn, ctx) != 1) { |
347 | tls_set_errorx(ctx, "ssl application data failure"); | 362 | tls_set_errorx(ctx, TLS_ERROR_UNKNOWN, |
363 | "ssl application data failure"); | ||
348 | goto err; | 364 | goto err; |
349 | } | 365 | } |
350 | 366 | ||
@@ -355,7 +371,8 @@ tls_connect_common(struct tls *ctx, const char *servername) | |||
355 | } | 371 | } |
356 | 372 | ||
357 | if (SSL_set_tlsext_status_type(ctx->ssl_conn, TLSEXT_STATUSTYPE_ocsp) != 1) { | 373 | if (SSL_set_tlsext_status_type(ctx->ssl_conn, TLSEXT_STATUSTYPE_ocsp) != 1) { |
358 | tls_set_errorx(ctx, "ssl OCSP extension setup failure"); | 374 | tls_set_errorx(ctx, TLS_ERROR_UNKNOWN, |
375 | "ssl OCSP extension setup failure"); | ||
359 | goto err; | 376 | goto err; |
360 | } | 377 | } |
361 | 378 | ||
@@ -368,7 +385,8 @@ tls_connect_common(struct tls *ctx, const char *servername) | |||
368 | inet_pton(AF_INET6, ctx->servername, &addrbuf) != 1) { | 385 | inet_pton(AF_INET6, ctx->servername, &addrbuf) != 1) { |
369 | if (SSL_set_tlsext_host_name(ctx->ssl_conn, | 386 | if (SSL_set_tlsext_host_name(ctx->ssl_conn, |
370 | ctx->servername) == 0) { | 387 | ctx->servername) == 0) { |
371 | tls_set_errorx(ctx, "server name indication failure"); | 388 | tls_set_errorx(ctx, TLS_ERROR_UNKNOWN, |
389 | "server name indication failure"); | ||
372 | goto err; | 390 | goto err; |
373 | } | 391 | } |
374 | } | 392 | } |
@@ -393,7 +411,7 @@ tls_connect_fds(struct tls *ctx, int fd_read, int fd_write, | |||
393 | int rv = -1; | 411 | int rv = -1; |
394 | 412 | ||
395 | if (fd_read < 0 || fd_write < 0) { | 413 | if (fd_read < 0 || fd_write < 0) { |
396 | tls_set_errorx(ctx, "invalid file descriptors"); | 414 | tls_set_errorx(ctx, TLS_ERROR_UNKNOWN, "invalid file descriptors"); |
397 | goto err; | 415 | goto err; |
398 | } | 416 | } |
399 | 417 | ||
@@ -402,7 +420,8 @@ tls_connect_fds(struct tls *ctx, int fd_read, int fd_write, | |||
402 | 420 | ||
403 | if (SSL_set_rfd(ctx->ssl_conn, fd_read) != 1 || | 421 | if (SSL_set_rfd(ctx->ssl_conn, fd_read) != 1 || |
404 | SSL_set_wfd(ctx->ssl_conn, fd_write) != 1) { | 422 | SSL_set_wfd(ctx->ssl_conn, fd_write) != 1) { |
405 | tls_set_errorx(ctx, "ssl file descriptor failure"); | 423 | tls_set_errorx(ctx, TLS_ERROR_UNKNOWN, |
424 | "ssl file descriptor failure"); | ||
406 | goto err; | 425 | goto err; |
407 | } | 426 | } |
408 | 427 | ||
@@ -437,12 +456,12 @@ tls_handshake_client(struct tls *ctx) | |||
437 | int rv = -1; | 456 | int rv = -1; |
438 | 457 | ||
439 | if ((ctx->flags & TLS_CLIENT) == 0) { | 458 | if ((ctx->flags & TLS_CLIENT) == 0) { |
440 | tls_set_errorx(ctx, "not a client context"); | 459 | tls_set_errorx(ctx, TLS_ERROR_UNKNOWN, "not a client context"); |
441 | goto err; | 460 | goto err; |
442 | } | 461 | } |
443 | 462 | ||
444 | if ((ctx->state & TLS_CONNECTED) == 0) { | 463 | if ((ctx->state & TLS_CONNECTED) == 0) { |
445 | tls_set_errorx(ctx, "context not connected"); | 464 | tls_set_errorx(ctx, TLS_ERROR_UNKNOWN, "context not connected"); |
446 | goto err; | 465 | goto err; |
447 | } | 466 | } |
448 | 467 | ||
@@ -457,14 +476,16 @@ tls_handshake_client(struct tls *ctx) | |||
457 | if (ctx->config->verify_name) { | 476 | if (ctx->config->verify_name) { |
458 | cert = SSL_get_peer_certificate(ctx->ssl_conn); | 477 | cert = SSL_get_peer_certificate(ctx->ssl_conn); |
459 | if (cert == NULL) { | 478 | if (cert == NULL) { |
460 | tls_set_errorx(ctx, "no server certificate"); | 479 | tls_set_errorx(ctx, TLS_ERROR_UNKNOWN, |
480 | "no server certificate"); | ||
461 | goto err; | 481 | goto err; |
462 | } | 482 | } |
463 | if (tls_check_name(ctx, cert, ctx->servername, &match) == -1) | 483 | if (tls_check_name(ctx, cert, ctx->servername, &match) == -1) |
464 | goto err; | 484 | goto err; |
465 | if (!match) { | 485 | if (!match) { |
466 | tls_set_errorx(ctx, "name `%s' not present in" | 486 | tls_set_errorx(ctx, TLS_ERROR_UNKNOWN, |
467 | " server certificate", ctx->servername); | 487 | "name `%s' not present in server certificate", |
488 | ctx->servername); | ||
468 | goto err; | 489 | goto err; |
469 | } | 490 | } |
470 | } | 491 | } |