diff options
Diffstat (limited to 'src')
| -rw-r--r-- | src/lib/libtls/tls.h | 3 | ||||
| -rw-r--r-- | src/lib/libtls/tls_conninfo.c | 14 | ||||
| -rw-r--r-- | src/lib/libtls/tls_internal.h | 5 | ||||
| -rw-r--r-- | src/lib/libtls/tls_peer.c | 10 | ||||
| -rw-r--r-- | src/lib/libtls/tls_verify.c | 97 |
5 files changed, 105 insertions, 24 deletions
diff --git a/src/lib/libtls/tls.h b/src/lib/libtls/tls.h index 6b36886dc3..5a3a6254ab 100644 --- a/src/lib/libtls/tls.h +++ b/src/lib/libtls/tls.h | |||
| @@ -1,4 +1,4 @@ | |||
| 1 | /* $OpenBSD: tls.h,v 1.67 2024/08/02 15:00:01 tb Exp $ */ | 1 | /* $OpenBSD: tls.h,v 1.68 2024/12/10 08:40:30 tb Exp $ */ |
| 2 | /* | 2 | /* |
| 3 | * Copyright (c) 2014 Joel Sing <jsing@openbsd.org> | 3 | * Copyright (c) 2014 Joel Sing <jsing@openbsd.org> |
| 4 | * | 4 | * |
| @@ -200,6 +200,7 @@ int tls_close(struct tls *_ctx); | |||
| 200 | int tls_peer_cert_provided(struct tls *_ctx); | 200 | int tls_peer_cert_provided(struct tls *_ctx); |
| 201 | int tls_peer_cert_contains_name(struct tls *_ctx, const char *_name); | 201 | int tls_peer_cert_contains_name(struct tls *_ctx, const char *_name); |
| 202 | 202 | ||
| 203 | const char *tls_peer_cert_common_name(struct tls *_ctx); | ||
| 203 | const char *tls_peer_cert_hash(struct tls *_ctx); | 204 | const char *tls_peer_cert_hash(struct tls *_ctx); |
| 204 | const char *tls_peer_cert_issuer(struct tls *_ctx); | 205 | const char *tls_peer_cert_issuer(struct tls *_ctx); |
| 205 | const char *tls_peer_cert_subject(struct tls *_ctx); | 206 | const char *tls_peer_cert_subject(struct tls *_ctx); |
diff --git a/src/lib/libtls/tls_conninfo.c b/src/lib/libtls/tls_conninfo.c index bf525170f1..8fb56c92b7 100644 --- a/src/lib/libtls/tls_conninfo.c +++ b/src/lib/libtls/tls_conninfo.c | |||
| @@ -1,4 +1,4 @@ | |||
| 1 | /* $OpenBSD: tls_conninfo.c,v 1.27 2024/03/26 06:31:22 jsing Exp $ */ | 1 | /* $OpenBSD: tls_conninfo.c,v 1.28 2024/12/10 08:40:30 tb Exp $ */ |
| 2 | /* | 2 | /* |
| 3 | * Copyright (c) 2015 Joel Sing <jsing@openbsd.org> | 3 | * Copyright (c) 2015 Joel Sing <jsing@openbsd.org> |
| 4 | * Copyright (c) 2015 Bob Beck <beck@openbsd.org> | 4 | * Copyright (c) 2015 Bob Beck <beck@openbsd.org> |
| @@ -119,6 +119,14 @@ tls_get_peer_cert_subject(struct tls *ctx, char **subject) | |||
| 119 | } | 119 | } |
| 120 | 120 | ||
| 121 | static int | 121 | static int |
| 122 | tls_get_peer_cert_common_name(struct tls *ctx, char **common_name) | ||
| 123 | { | ||
| 124 | if (ctx->ssl_peer_cert == NULL) | ||
| 125 | return (-1); | ||
| 126 | return tls_get_common_name(ctx, ctx->ssl_peer_cert, NULL, common_name); | ||
| 127 | } | ||
| 128 | |||
| 129 | static int | ||
| 122 | tls_get_peer_cert_times(struct tls *ctx, time_t *notbefore, | 130 | tls_get_peer_cert_times(struct tls *ctx, time_t *notbefore, |
| 123 | time_t *notafter) | 131 | time_t *notafter) |
| 124 | { | 132 | { |
| @@ -158,6 +166,9 @@ tls_get_peer_cert_info(struct tls *ctx) | |||
| 158 | goto err; | 166 | goto err; |
| 159 | if (tls_get_peer_cert_issuer(ctx, &ctx->conninfo->issuer) == -1) | 167 | if (tls_get_peer_cert_issuer(ctx, &ctx->conninfo->issuer) == -1) |
| 160 | goto err; | 168 | goto err; |
| 169 | if (tls_get_peer_cert_common_name(ctx, | ||
| 170 | &ctx->conninfo->common_name) == -1) | ||
| 171 | goto err; | ||
| 161 | if (tls_get_peer_cert_times(ctx, &ctx->conninfo->notbefore, | 172 | if (tls_get_peer_cert_times(ctx, &ctx->conninfo->notbefore, |
| 162 | &ctx->conninfo->notafter) == -1) | 173 | &ctx->conninfo->notafter) == -1) |
| 163 | goto err; | 174 | goto err; |
| @@ -298,6 +309,7 @@ tls_conninfo_free(struct tls_conninfo *conninfo) | |||
| 298 | free(conninfo->servername); | 309 | free(conninfo->servername); |
| 299 | free(conninfo->version); | 310 | free(conninfo->version); |
| 300 | 311 | ||
| 312 | free(conninfo->common_name); | ||
| 301 | free(conninfo->hash); | 313 | free(conninfo->hash); |
| 302 | free(conninfo->issuer); | 314 | free(conninfo->issuer); |
| 303 | free(conninfo->subject); | 315 | free(conninfo->subject); |
diff --git a/src/lib/libtls/tls_internal.h b/src/lib/libtls/tls_internal.h index 5ff48ed7c9..8e566a34e0 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.85 2024/03/26 06:24:52 joshua Exp $ */ | 1 | /* $OpenBSD: tls_internal.h,v 1.86 2024/12/10 08:40:30 tb 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> |
| @@ -129,6 +129,7 @@ struct tls_conninfo { | |||
| 129 | int session_resumed; | 129 | int session_resumed; |
| 130 | char *version; | 130 | char *version; |
| 131 | 131 | ||
| 132 | char *common_name; | ||
| 132 | char *hash; | 133 | char *hash; |
| 133 | char *issuer; | 134 | char *issuer; |
| 134 | char *subject; | 135 | char *subject; |
| @@ -238,6 +239,8 @@ struct tls_config *tls_config_new_internal(void); | |||
| 238 | struct tls *tls_new(void); | 239 | struct tls *tls_new(void); |
| 239 | struct tls *tls_server_conn(struct tls *ctx); | 240 | struct tls *tls_server_conn(struct tls *ctx); |
| 240 | 241 | ||
| 242 | int tls_get_common_name(struct tls *_ctx, X509 *_cert, const char *_in_name, | ||
| 243 | char **_out_common_name); | ||
| 241 | int tls_check_name(struct tls *ctx, X509 *cert, const char *servername, | 244 | int tls_check_name(struct tls *ctx, X509 *cert, const char *servername, |
| 242 | int *match); | 245 | int *match); |
| 243 | int tls_configure_server(struct tls *ctx); | 246 | int tls_configure_server(struct tls *ctx); |
diff --git a/src/lib/libtls/tls_peer.c b/src/lib/libtls/tls_peer.c index ec97a30838..6d63a529f2 100644 --- a/src/lib/libtls/tls_peer.c +++ b/src/lib/libtls/tls_peer.c | |||
| @@ -1,4 +1,4 @@ | |||
| 1 | /* $OpenBSD: tls_peer.c,v 1.8 2017/04/10 17:11:13 jsing Exp $ */ | 1 | /* $OpenBSD: tls_peer.c,v 1.9 2024/12/10 08:40:30 tb Exp $ */ |
| 2 | /* | 2 | /* |
| 3 | * Copyright (c) 2015 Joel Sing <jsing@openbsd.org> | 3 | * Copyright (c) 2015 Joel Sing <jsing@openbsd.org> |
| 4 | * Copyright (c) 2015 Bob Beck <beck@openbsd.org> | 4 | * Copyright (c) 2015 Bob Beck <beck@openbsd.org> |
| @@ -24,6 +24,14 @@ | |||
| 24 | #include "tls_internal.h" | 24 | #include "tls_internal.h" |
| 25 | 25 | ||
| 26 | const char * | 26 | const char * |
| 27 | tls_peer_cert_common_name(struct tls *ctx) | ||
| 28 | { | ||
| 29 | if (ctx->conninfo == NULL) | ||
| 30 | return (NULL); | ||
| 31 | return (ctx->conninfo->common_name); | ||
| 32 | } | ||
| 33 | |||
| 34 | const char * | ||
| 27 | tls_peer_cert_hash(struct tls *ctx) | 35 | tls_peer_cert_hash(struct tls *ctx) |
| 28 | { | 36 | { |
| 29 | if (ctx->conninfo == NULL) | 37 | if (ctx->conninfo == NULL) |
diff --git a/src/lib/libtls/tls_verify.c b/src/lib/libtls/tls_verify.c index 6b2a4fb82a..2935278383 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.31 2024/11/12 22:50:06 tb Exp $ */ | 1 | /* $OpenBSD: tls_verify.c,v 1.32 2024/12/10 08:40:30 tb 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 | * |
| @@ -210,19 +210,22 @@ tls_check_subject_altname(struct tls *ctx, X509 *cert, const char *name, | |||
| 210 | } | 210 | } |
| 211 | 211 | ||
| 212 | static int | 212 | static int |
| 213 | tls_check_common_name(struct tls *ctx, X509 *cert, const char *name, | 213 | tls_get_common_name_internal(X509 *cert, char **out_common_name, |
| 214 | int *cn_match) | 214 | unsigned int *out_tlserr, const char **out_errstr) |
| 215 | { | 215 | { |
| 216 | unsigned char *utf8_bytes = NULL; | 216 | unsigned char *utf8_bytes = NULL; |
| 217 | X509_NAME *subject_name; | 217 | X509_NAME *subject_name; |
| 218 | char *common_name = NULL; | 218 | char *common_name = NULL; |
| 219 | union tls_addr addrbuf; | ||
| 220 | int common_name_len; | 219 | int common_name_len; |
| 221 | ASN1_STRING *data; | 220 | ASN1_STRING *data; |
| 222 | int lastpos = -1; | 221 | int lastpos = -1; |
| 223 | int rv = -1; | 222 | int rv = -1; |
| 224 | 223 | ||
| 225 | *cn_match = 0; | 224 | *out_tlserr = TLS_ERROR_UNKNOWN; |
| 225 | *out_errstr = "unknown"; | ||
| 226 | |||
| 227 | free(*out_common_name); | ||
| 228 | *out_common_name = NULL; | ||
| 226 | 229 | ||
| 227 | subject_name = X509_get_subject_name(cert); | 230 | subject_name = X509_get_subject_name(cert); |
| 228 | if (subject_name == NULL) | 231 | if (subject_name == NULL) |
| @@ -244,10 +247,10 @@ tls_check_common_name(struct tls *ctx, X509 *cert, const char *name, | |||
| 244 | * more than one CN fed to us in the subject, treating the | 247 | * more than one CN fed to us in the subject, treating the |
| 245 | * certificate as hostile. | 248 | * certificate as hostile. |
| 246 | */ | 249 | */ |
| 247 | tls_set_errorx(ctx, TLS_ERROR_UNKNOWN, | 250 | *out_tlserr = TLS_ERROR_UNKNOWN; |
| 248 | "error verifying name '%s': " | 251 | *out_errstr = "error getting common name: " |
| 249 | "Certificate subject contains multiple Common Name fields, " | 252 | "Certificate subject contains multiple Common Name fields, " |
| 250 | "probably a malicious or malformed certificate", name); | 253 | "probably a malicious or malformed certificate"; |
| 251 | goto err; | 254 | goto err; |
| 252 | } | 255 | } |
| 253 | 256 | ||
| @@ -257,10 +260,10 @@ tls_check_common_name(struct tls *ctx, X509 *cert, const char *name, | |||
| 257 | * Fail if we cannot encode the CN bytes as UTF-8. | 260 | * Fail if we cannot encode the CN bytes as UTF-8. |
| 258 | */ | 261 | */ |
| 259 | if ((common_name_len = ASN1_STRING_to_UTF8(&utf8_bytes, data)) < 0) { | 262 | if ((common_name_len = ASN1_STRING_to_UTF8(&utf8_bytes, data)) < 0) { |
| 260 | tls_set_errorx(ctx, TLS_ERROR_UNKNOWN, | 263 | *out_tlserr = TLS_ERROR_UNKNOWN; |
| 261 | "error verifying name '%s': " | 264 | *out_errstr = "error getting common name: " |
| 262 | "Common Name field cannot be encoded as a UTF-8 string, " | 265 | "Common Name field cannot be encoded as a UTF-8 string, " |
| 263 | "probably a malicious certificate", name); | 266 | "probably a malicious certificate"; |
| 264 | goto err; | 267 | goto err; |
| 265 | } | 268 | } |
| 266 | /* | 269 | /* |
| @@ -268,30 +271,85 @@ tls_check_common_name(struct tls *ctx, X509 *cert, const char *name, | |||
| 268 | * must be between 1 and 64 bytes long. | 271 | * must be between 1 and 64 bytes long. |
| 269 | */ | 272 | */ |
| 270 | if (common_name_len < 1 || common_name_len > 64) { | 273 | if (common_name_len < 1 || common_name_len > 64) { |
| 271 | tls_set_errorx(ctx, TLS_ERROR_UNKNOWN, | 274 | *out_tlserr = TLS_ERROR_UNKNOWN; |
| 272 | "error verifying name '%s': " | 275 | *out_errstr = "error getting common name: " |
| 273 | "Common Name field has invalid length, " | 276 | "Common Name field has invalid length, " |
| 274 | "probably a malicious certificate", name); | 277 | "probably a malicious certificate"; |
| 275 | goto err; | 278 | goto err; |
| 276 | } | 279 | } |
| 277 | /* | 280 | /* |
| 278 | * Fail if the resulting text contains a NUL byte. | 281 | * Fail if the resulting text contains a NUL byte. |
| 279 | */ | 282 | */ |
| 280 | if (memchr(utf8_bytes, 0, common_name_len) != NULL) { | 283 | if (memchr(utf8_bytes, 0, common_name_len) != NULL) { |
| 281 | tls_set_errorx(ctx, TLS_ERROR_UNKNOWN, | 284 | *out_tlserr = TLS_ERROR_UNKNOWN; |
| 282 | "error verifying name '%s': " | 285 | *out_errstr = "error getting common name: " |
| 283 | "NUL byte in Common Name field, " | 286 | "NUL byte in Common Name field, " |
| 284 | "probably a malicious certificate", name); | 287 | "probably a malicious certificate"; |
| 285 | goto err; | 288 | goto err; |
| 286 | } | 289 | } |
| 287 | 290 | ||
| 288 | common_name = strndup(utf8_bytes, common_name_len); | 291 | common_name = strndup(utf8_bytes, common_name_len); |
| 289 | if (common_name == NULL) { | 292 | if (common_name == NULL) { |
| 290 | tls_set_error(ctx, TLS_ERROR_OUT_OF_MEMORY, | 293 | *out_tlserr = TLS_ERROR_OUT_OF_MEMORY; |
| 291 | "out of memory"); | 294 | *out_errstr = "out of memory"; |
| 295 | goto err; | ||
| 296 | } | ||
| 297 | |||
| 298 | *out_common_name = common_name; | ||
| 299 | common_name = NULL; | ||
| 300 | |||
| 301 | done: | ||
| 302 | if (*out_common_name == NULL) | ||
| 303 | *out_common_name = strdup(""); | ||
| 304 | if (*out_common_name == NULL) { | ||
| 305 | *out_tlserr = TLS_ERROR_OUT_OF_MEMORY; | ||
| 306 | *out_errstr = "out of memory"; | ||
| 292 | goto err; | 307 | goto err; |
| 293 | } | 308 | } |
| 294 | 309 | ||
| 310 | rv = 0; | ||
| 311 | |||
| 312 | err: | ||
| 313 | free(utf8_bytes); | ||
| 314 | free(common_name); | ||
| 315 | return rv; | ||
| 316 | } | ||
| 317 | |||
| 318 | int | ||
| 319 | tls_get_common_name(struct tls *ctx, X509 *cert, const char *in_name, | ||
| 320 | char **out_common_name) | ||
| 321 | { | ||
| 322 | unsigned int errcode = TLS_ERROR_UNKNOWN; | ||
| 323 | const char *errstr = "unknown"; | ||
| 324 | |||
| 325 | if (tls_get_common_name_internal(cert, out_common_name, &errcode, | ||
| 326 | &errstr) == -1) { | ||
| 327 | const char *name = in_name; | ||
| 328 | const char *space = " "; | ||
| 329 | |||
| 330 | if (name == NULL) | ||
| 331 | name = space = ""; | ||
| 332 | |||
| 333 | tls_set_errorx(ctx, errcode, "%s%s%s", name, space, errstr); | ||
| 334 | return -1; | ||
| 335 | } | ||
| 336 | |||
| 337 | return 0; | ||
| 338 | } | ||
| 339 | |||
| 340 | static int | ||
| 341 | tls_check_common_name(struct tls *ctx, X509 *cert, const char *name, | ||
| 342 | int *cn_match) | ||
| 343 | { | ||
| 344 | char *common_name = NULL; | ||
| 345 | union tls_addr addrbuf; | ||
| 346 | int rv = -1; | ||
| 347 | |||
| 348 | if (tls_get_common_name(ctx, cert, name, &common_name) == -1) | ||
| 349 | goto err; | ||
| 350 | if (strlen(common_name) == 0) | ||
| 351 | goto done; | ||
| 352 | |||
| 295 | /* | 353 | /* |
| 296 | * We don't want to attempt wildcard matching against IP addresses, | 354 | * We don't want to attempt wildcard matching against IP addresses, |
| 297 | * so perform a simple comparison here. | 355 | * so perform a simple comparison here. |
| @@ -310,7 +368,6 @@ tls_check_common_name(struct tls *ctx, X509 *cert, const char *name, | |||
| 310 | rv = 0; | 368 | rv = 0; |
| 311 | 369 | ||
| 312 | err: | 370 | err: |
| 313 | free(utf8_bytes); | ||
| 314 | free(common_name); | 371 | free(common_name); |
| 315 | return rv; | 372 | return rv; |
| 316 | } | 373 | } |
