diff options
| author | bcook <> | 2014-12-07 15:00:32 +0000 |
|---|---|---|
| committer | bcook <> | 2014-12-07 15:00:32 +0000 |
| commit | a761ebff2cb2a2b78b88a343ed309d18ed93993e (patch) | |
| tree | 094ce4813a37514a96f893ee676a60374f36f28b /src/lib/libtls | |
| parent | 0eaa29b6532ab032e411dcff4650b06dc3747dd0 (diff) | |
| download | openbsd-a761ebff2cb2a2b78b88a343ed309d18ed93993e.tar.gz openbsd-a761ebff2cb2a2b78b88a343ed309d18ed93993e.tar.bz2 openbsd-a761ebff2cb2a2b78b88a343ed309d18ed93993e.zip | |
Allow specific libtls hostname validation errors to propagate.
Remove direct calls to printf from the tls_check_hostname() path. This allows
NUL byte error messages to bubble up to the caller, to be logged in a
program-appropriate way. It also removes non-portable calls to getprogname().
The semantics of tls_error() are changed slightly: the last error message is
not necessarily preserved between subsequent calls into the library.
When the previous call to libtls succeeds, client programs should treat the
return value of tls_error() as undefined.
ok tedu@
Diffstat (limited to '')
| -rw-r--r-- | src/lib/libtls/tls.c | 13 | ||||
| -rw-r--r-- | src/lib/libtls/tls_client.c | 10 | ||||
| -rw-r--r-- | src/lib/libtls/tls_internal.h | 5 | ||||
| -rw-r--r-- | src/lib/libtls/tls_verify.c | 35 |
4 files changed, 36 insertions, 27 deletions
diff --git a/src/lib/libtls/tls.c b/src/lib/libtls/tls.c index a7f612e40b..d3bb79b3fe 100644 --- a/src/lib/libtls/tls.c +++ b/src/lib/libtls/tls.c | |||
| @@ -1,4 +1,4 @@ | |||
| 1 | /* $OpenBSD: tls.c,v 1.1 2014/10/31 13:46:17 jsing Exp $ */ | 1 | /* $OpenBSD: tls.c,v 1.2 2014/12/07 15:00:32 bcook Exp $ */ |
| 2 | /* | 2 | /* |
| 3 | * Copyright (c) 2014 Joel Sing <jsing@openbsd.org> | 3 | * Copyright (c) 2014 Joel Sing <jsing@openbsd.org> |
| 4 | * | 4 | * |
| @@ -56,15 +56,22 @@ tls_error(struct tls *ctx) | |||
| 56 | return ctx->errmsg; | 56 | return ctx->errmsg; |
| 57 | } | 57 | } |
| 58 | 58 | ||
| 59 | void | ||
| 60 | tls_clear_error(struct tls *ctx) | ||
| 61 | { | ||
| 62 | ctx->err = 0; | ||
| 63 | free(ctx->errmsg); | ||
| 64 | ctx->errmsg = NULL; | ||
| 65 | } | ||
| 66 | |||
| 59 | int | 67 | int |
| 60 | tls_set_error(struct tls *ctx, char *fmt, ...) | 68 | tls_set_error(struct tls *ctx, char *fmt, ...) |
| 61 | { | 69 | { |
| 62 | va_list ap; | 70 | va_list ap; |
| 63 | int rv; | 71 | int rv; |
| 64 | 72 | ||
| 73 | tls_clear_error(ctx); | ||
| 65 | ctx->err = errno; | 74 | ctx->err = errno; |
| 66 | free(ctx->errmsg); | ||
| 67 | ctx->errmsg = NULL; | ||
| 68 | 75 | ||
| 69 | va_start(ap, fmt); | 76 | va_start(ap, fmt); |
| 70 | rv = vasprintf(&ctx->errmsg, fmt, ap); | 77 | rv = vasprintf(&ctx->errmsg, fmt, ap); |
diff --git a/src/lib/libtls/tls_client.c b/src/lib/libtls/tls_client.c index a4528b9b87..c5849a6897 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.2 2014/11/02 14:45:05 jsing Exp $ */ | 1 | /* $OpenBSD: tls_client.c,v 1.3 2014/12/07 15:00:32 bcook Exp $ */ |
| 2 | /* | 2 | /* |
| 3 | * Copyright (c) 2014 Joel Sing <jsing@openbsd.org> | 3 | * Copyright (c) 2014 Joel Sing <jsing@openbsd.org> |
| 4 | * | 4 | * |
| @@ -209,9 +209,11 @@ tls_connect_fds(struct tls *ctx, int fd_read, int fd_write, | |||
| 209 | tls_set_error(ctx, "no server certificate"); | 209 | tls_set_error(ctx, "no server certificate"); |
| 210 | goto err; | 210 | goto err; |
| 211 | } | 211 | } |
| 212 | if (tls_check_hostname(cert, hostname) != 0) { | 212 | tls_clear_error(ctx); |
| 213 | tls_set_error(ctx, "host `%s' not present in" | 213 | if (tls_check_hostname(ctx, cert, hostname) != 0) { |
| 214 | " server certificate", hostname); | 214 | if (tls_error(ctx) == NULL) |
| 215 | tls_set_error(ctx, "host `%s' not present in" | ||
| 216 | " server certificate", hostname); | ||
| 215 | goto err; | 217 | goto err; |
| 216 | } | 218 | } |
| 217 | } | 219 | } |
diff --git a/src/lib/libtls/tls_internal.h b/src/lib/libtls/tls_internal.h index da696e228d..e6f2d4ac71 100644 --- a/src/lib/libtls/tls_internal.h +++ b/src/lib/libtls/tls_internal.h | |||
| @@ -1,4 +1,4 @@ | |||
| 1 | /* $OpenBSD: tls_internal.h,v 1.1 2014/10/31 13:46:17 jsing Exp $ */ | 1 | /* $OpenBSD: tls_internal.h,v 1.2 2014/12/07 15:00:32 bcook Exp $ */ |
| 2 | /* | 2 | /* |
| 3 | * Copyright (c) 2014 Jeremie Courreges-Anglas <jca@openbsd.org> | 3 | * Copyright (c) 2014 Jeremie Courreges-Anglas <jca@openbsd.org> |
| 4 | * Copyright (c) 2014 Joel Sing <jsing@openbsd.org> | 4 | * Copyright (c) 2014 Joel Sing <jsing@openbsd.org> |
| @@ -62,11 +62,12 @@ struct tls { | |||
| 62 | struct tls *tls_new(void); | 62 | struct tls *tls_new(void); |
| 63 | struct tls *tls_server_conn(struct tls *ctx); | 63 | struct tls *tls_server_conn(struct tls *ctx); |
| 64 | 64 | ||
| 65 | int tls_check_hostname(X509 *cert, const char *host); | 65 | int tls_check_hostname(struct tls *ctx, X509 *cert, const char *host); |
| 66 | int tls_configure_keypair(struct tls *ctx); | 66 | int tls_configure_keypair(struct tls *ctx); |
| 67 | int tls_configure_server(struct tls *ctx); | 67 | int tls_configure_server(struct tls *ctx); |
| 68 | int tls_configure_ssl(struct tls *ctx); | 68 | int tls_configure_ssl(struct tls *ctx); |
| 69 | int tls_host_port(const char *hostport, char **host, char **port); | 69 | int tls_host_port(const char *hostport, char **host, char **port); |
| 70 | void tls_clear_error(struct tls *ctx); | ||
| 70 | int tls_set_error(struct tls *ctx, char *fmt, ...); | 71 | int tls_set_error(struct tls *ctx, char *fmt, ...); |
| 71 | 72 | ||
| 72 | #endif /* HEADER_TLS_INTERNAL_H */ | 73 | #endif /* HEADER_TLS_INTERNAL_H */ |
diff --git a/src/lib/libtls/tls_verify.c b/src/lib/libtls/tls_verify.c index fa0010922f..0252e20575 100644 --- a/src/lib/libtls/tls_verify.c +++ b/src/lib/libtls/tls_verify.c | |||
| @@ -1,4 +1,4 @@ | |||
| 1 | /* $OpenBSD: tls_verify.c,v 1.1 2014/10/31 13:46:17 jsing Exp $ */ | 1 | /* $OpenBSD: tls_verify.c,v 1.2 2014/12/07 15:00:32 bcook Exp $ */ |
| 2 | /* | 2 | /* |
| 3 | * Copyright (c) 2014 Jeremie Courreges-Anglas <jca@openbsd.org> | 3 | * Copyright (c) 2014 Jeremie Courreges-Anglas <jca@openbsd.org> |
| 4 | * | 4 | * |
| @@ -27,8 +27,8 @@ | |||
| 27 | #include "tls_internal.h" | 27 | #include "tls_internal.h" |
| 28 | 28 | ||
| 29 | int tls_match_hostname(const char *cert_hostname, const char *hostname); | 29 | int tls_match_hostname(const char *cert_hostname, const char *hostname); |
| 30 | int tls_check_subject_altname(X509 *cert, const char *host); | 30 | int tls_check_subject_altname(struct tls *ctx, X509 *cert, const char *host); |
| 31 | int tls_check_common_name(X509 *cert, const char *host); | 31 | int tls_check_common_name(struct tls *ctx, X509 *cert, const char *host); |
| 32 | 32 | ||
| 33 | int | 33 | int |
| 34 | tls_match_hostname(const char *cert_hostname, const char *hostname) | 34 | tls_match_hostname(const char *cert_hostname, const char *hostname) |
| @@ -80,7 +80,7 @@ tls_match_hostname(const char *cert_hostname, const char *hostname) | |||
| 80 | } | 80 | } |
| 81 | 81 | ||
| 82 | int | 82 | int |
| 83 | tls_check_subject_altname(X509 *cert, const char *host) | 83 | tls_check_subject_altname(struct tls *ctx, X509 *cert, const char *host) |
| 84 | { | 84 | { |
| 85 | STACK_OF(GENERAL_NAME) *altname_stack = NULL; | 85 | STACK_OF(GENERAL_NAME) *altname_stack = NULL; |
| 86 | union { struct in_addr ip4; struct in6_addr ip6; } addrbuf; | 86 | union { struct in_addr ip4; struct in6_addr ip6; } addrbuf; |
| @@ -123,10 +123,11 @@ tls_check_subject_altname(X509 *cert, const char *host) | |||
| 123 | 123 | ||
| 124 | if (ASN1_STRING_length(altname->d.dNSName) != | 124 | if (ASN1_STRING_length(altname->d.dNSName) != |
| 125 | (int)strlen(data)) { | 125 | (int)strlen(data)) { |
| 126 | fprintf(stdout, "%s: NUL byte in " | 126 | tls_set_error(ctx, |
| 127 | "subjectAltName, probably a " | 127 | "error verifying host '%s': " |
| 128 | "malicious certificate.\n", | 128 | "NUL byte in subjectAltName, " |
| 129 | getprogname()); | 129 | "probably a malicious certificate", |
| 130 | host); | ||
| 130 | rv = -2; | 131 | rv = -2; |
| 131 | break; | 132 | break; |
| 132 | } | 133 | } |
| @@ -135,10 +136,7 @@ tls_check_subject_altname(X509 *cert, const char *host) | |||
| 135 | rv = 0; | 136 | rv = 0; |
| 136 | break; | 137 | break; |
| 137 | } | 138 | } |
| 138 | } else | 139 | } |
| 139 | fprintf(stdout, "%s: unhandled subjectAltName " | ||
| 140 | "dNSName encoding (%d)\n", getprogname(), | ||
| 141 | format); | ||
| 142 | 140 | ||
| 143 | } else if (type == GEN_IPADD) { | 141 | } else if (type == GEN_IPADD) { |
| 144 | unsigned char *data; | 142 | unsigned char *data; |
| @@ -160,7 +158,7 @@ tls_check_subject_altname(X509 *cert, const char *host) | |||
| 160 | } | 158 | } |
| 161 | 159 | ||
| 162 | int | 160 | int |
| 163 | tls_check_common_name(X509 *cert, const char *host) | 161 | tls_check_common_name(struct tls *ctx, X509 *cert, const char *host) |
| 164 | { | 162 | { |
| 165 | X509_NAME *name; | 163 | X509_NAME *name; |
| 166 | char *common_name = NULL; | 164 | char *common_name = NULL; |
| @@ -186,8 +184,9 @@ tls_check_common_name(X509 *cert, const char *host) | |||
| 186 | 184 | ||
| 187 | /* NUL bytes in CN? */ | 185 | /* NUL bytes in CN? */ |
| 188 | if (common_name_len != (int)strlen(common_name)) { | 186 | if (common_name_len != (int)strlen(common_name)) { |
| 189 | fprintf(stdout, "%s: NUL byte in Common Name field, " | 187 | tls_set_error(ctx, "error verifying host '%s': " |
| 190 | "probably a malicious certificate.\n", getprogname()); | 188 | "NUL byte in Common Name field, " |
| 189 | "probably a malicious certificate.", host); | ||
| 191 | rv = -2; | 190 | rv = -2; |
| 192 | goto out; | 191 | goto out; |
| 193 | } | 192 | } |
| @@ -213,13 +212,13 @@ out: | |||
| 213 | } | 212 | } |
| 214 | 213 | ||
| 215 | int | 214 | int |
| 216 | tls_check_hostname(X509 *cert, const char *host) | 215 | tls_check_hostname(struct tls *ctx, X509 *cert, const char *host) |
| 217 | { | 216 | { |
| 218 | int rv; | 217 | int rv; |
| 219 | 218 | ||
| 220 | rv = tls_check_subject_altname(cert, host); | 219 | rv = tls_check_subject_altname(ctx, cert, host); |
| 221 | if (rv == 0 || rv == -2) | 220 | if (rv == 0 || rv == -2) |
| 222 | return rv; | 221 | return rv; |
| 223 | 222 | ||
| 224 | return tls_check_common_name(cert, host); | 223 | return tls_check_common_name(ctx, cert, host); |
| 225 | } | 224 | } |
