diff options
author | jsing <> | 2022-07-03 14:58:00 +0000 |
---|---|---|
committer | jsing <> | 2022-07-03 14:58:00 +0000 |
commit | 75b104defc9fec997245749fc919fd66a679c40d (patch) | |
tree | 6210ecab1ffd76ddf1fb9ee395feb4d7bad0129d /src | |
parent | 1ffc21a41f265a4910719c37b047e1583145350d (diff) | |
download | openbsd-75b104defc9fec997245749fc919fd66a679c40d.tar.gz openbsd-75b104defc9fec997245749fc919fd66a679c40d.tar.bz2 openbsd-75b104defc9fec997245749fc919fd66a679c40d.zip |
Simplify certificate list handling code in legacy server.
A client is required to send an empty list if it does not have a suitable
certificate - handle this case up front, rather than going through the
normal code path and ending up with an empty certificate list. This matches
what we do in the TLSv1.3 stack and will allow for ruther clean up (in
addition to making the code more readable).
Also tidy up the CBS code and remove some unnecessary length checks. Use
'cert' and 'certs' for certificates, rather than 'x' and 'sk'.
ok tb@
Diffstat (limited to 'src')
-rw-r--r-- | src/lib/libssl/ssl_srvr.c | 112 |
1 files changed, 50 insertions, 62 deletions
diff --git a/src/lib/libssl/ssl_srvr.c b/src/lib/libssl/ssl_srvr.c index 526d9e678b..d665a568d1 100644 --- a/src/lib/libssl/ssl_srvr.c +++ b/src/lib/libssl/ssl_srvr.c | |||
@@ -1,4 +1,4 @@ | |||
1 | /* $OpenBSD: ssl_srvr.c,v 1.147 2022/07/02 16:00:12 tb Exp $ */ | 1 | /* $OpenBSD: ssl_srvr.c,v 1.148 2022/07/03 14:58:00 jsing Exp $ */ |
2 | /* Copyright (C) 1995-1998 Eric Young (eay@cryptsoft.com) | 2 | /* Copyright (C) 1995-1998 Eric Young (eay@cryptsoft.com) |
3 | * All rights reserved. | 3 | * All rights reserved. |
4 | * | 4 | * |
@@ -525,7 +525,7 @@ ssl3_accept(SSL *s) | |||
525 | 525 | ||
526 | case SSL3_ST_SR_CERT_A: | 526 | case SSL3_ST_SR_CERT_A: |
527 | case SSL3_ST_SR_CERT_B: | 527 | case SSL3_ST_SR_CERT_B: |
528 | if (s->s3->hs.tls12.cert_request) { | 528 | if (s->s3->hs.tls12.cert_request != 0) { |
529 | ret = ssl3_get_client_certificate(s); | 529 | ret = ssl3_get_client_certificate(s); |
530 | if (ret <= 0) | 530 | if (ret <= 0) |
531 | goto end; | 531 | goto end; |
@@ -2156,11 +2156,11 @@ ssl3_get_cert_verify(SSL *s) | |||
2156 | int | 2156 | int |
2157 | ssl3_get_client_certificate(SSL *s) | 2157 | ssl3_get_client_certificate(SSL *s) |
2158 | { | 2158 | { |
2159 | CBS cbs, client_certs; | 2159 | CBS cbs, cert_list, cert_data; |
2160 | X509 *x = NULL; | 2160 | STACK_OF(X509) *certs = NULL; |
2161 | const unsigned char *q; | 2161 | X509 *cert = NULL; |
2162 | STACK_OF(X509) *sk = NULL; | 2162 | const uint8_t *p; |
2163 | int i, al, ret; | 2163 | int al, ret; |
2164 | 2164 | ||
2165 | if ((ret = ssl3_get_message(s, SSL3_ST_SR_CERT_A, SSL3_ST_SR_CERT_B, | 2165 | if ((ret = ssl3_get_message(s, SSL3_ST_SR_CERT_A, SSL3_ST_SR_CERT_B, |
2166 | -1, s->internal->max_cert_list)) <= 0) | 2166 | -1, s->internal->max_cert_list)) <= 0) |
@@ -2175,13 +2175,8 @@ ssl3_get_client_certificate(SSL *s) | |||
2175 | al = SSL_AD_HANDSHAKE_FAILURE; | 2175 | al = SSL_AD_HANDSHAKE_FAILURE; |
2176 | goto fatal_err; | 2176 | goto fatal_err; |
2177 | } | 2177 | } |
2178 | /* | 2178 | if (s->s3->hs.tls12.cert_request != 0) { |
2179 | * If tls asked for a client cert, | 2179 | SSLerror(s, SSL_R_TLS_PEER_DID_NOT_RESPOND_WITH_CERTIFICATE_LIST); |
2180 | * the client must return a 0 list. | ||
2181 | */ | ||
2182 | if (s->s3->hs.tls12.cert_request) { | ||
2183 | SSLerror(s, SSL_R_TLS_PEER_DID_NOT_RESPOND_WITH_CERTIFICATE_LIST | ||
2184 | ); | ||
2185 | al = SSL_AD_UNEXPECTED_MESSAGE; | 2180 | al = SSL_AD_UNEXPECTED_MESSAGE; |
2186 | goto fatal_err; | 2181 | goto fatal_err; |
2187 | } | 2182 | } |
@@ -2200,77 +2195,70 @@ ssl3_get_client_certificate(SSL *s) | |||
2200 | 2195 | ||
2201 | CBS_init(&cbs, s->internal->init_msg, s->internal->init_num); | 2196 | CBS_init(&cbs, s->internal->init_msg, s->internal->init_num); |
2202 | 2197 | ||
2203 | if ((sk = sk_X509_new_null()) == NULL) { | 2198 | if (!CBS_get_u24_length_prefixed(&cbs, &cert_list)) |
2204 | SSLerror(s, ERR_R_MALLOC_FAILURE); | 2199 | goto decode_err; |
2205 | goto err; | 2200 | if (CBS_len(&cbs) != 0) |
2206 | } | ||
2207 | |||
2208 | if (!CBS_get_u24_length_prefixed(&cbs, &client_certs) || | ||
2209 | CBS_len(&cbs) != 0) | ||
2210 | goto decode_err; | 2201 | goto decode_err; |
2211 | 2202 | ||
2212 | while (CBS_len(&client_certs) > 0) { | 2203 | /* |
2213 | CBS cert; | 2204 | * A TLS client must send an empty certificate list, if no suitable |
2214 | 2205 | * certificate is available (rather than omitting the Certificate | |
2215 | if (!CBS_get_u24_length_prefixed(&client_certs, &cert)) { | 2206 | * handshake message) - see RFC 5246 section 7.4.6. |
2216 | al = SSL_AD_DECODE_ERROR; | 2207 | */ |
2217 | SSLerror(s, SSL_R_CERT_LENGTH_MISMATCH); | 2208 | if (CBS_len(&cert_list) == 0) { |
2209 | if ((s->verify_mode & SSL_VERIFY_PEER) && | ||
2210 | (s->verify_mode & SSL_VERIFY_FAIL_IF_NO_PEER_CERT)) { | ||
2211 | SSLerror(s, SSL_R_PEER_DID_NOT_RETURN_A_CERTIFICATE); | ||
2212 | al = SSL_AD_HANDSHAKE_FAILURE; | ||
2218 | goto fatal_err; | 2213 | goto fatal_err; |
2219 | } | 2214 | } |
2215 | /* No client certificate so free transcript. */ | ||
2216 | tls1_transcript_free(s); | ||
2217 | goto done; | ||
2218 | } | ||
2220 | 2219 | ||
2221 | q = CBS_data(&cert); | 2220 | if ((certs = sk_X509_new_null()) == NULL) { |
2222 | x = d2i_X509(NULL, &q, CBS_len(&cert)); | 2221 | SSLerror(s, ERR_R_MALLOC_FAILURE); |
2223 | if (x == NULL) { | 2222 | goto err; |
2223 | } | ||
2224 | |||
2225 | while (CBS_len(&cert_list) > 0) { | ||
2226 | if (!CBS_get_u24_length_prefixed(&cert_list, &cert_data)) | ||
2227 | goto decode_err; | ||
2228 | p = CBS_data(&cert_data); | ||
2229 | if ((cert = d2i_X509(NULL, &p, CBS_len(&cert_data))) == NULL) { | ||
2224 | SSLerror(s, ERR_R_ASN1_LIB); | 2230 | SSLerror(s, ERR_R_ASN1_LIB); |
2225 | goto err; | 2231 | goto err; |
2226 | } | 2232 | } |
2227 | if (q != CBS_data(&cert) + CBS_len(&cert)) { | 2233 | if (p != CBS_data(&cert_data) + CBS_len(&cert_data)) |
2228 | al = SSL_AD_DECODE_ERROR; | 2234 | goto decode_err; |
2229 | SSLerror(s, SSL_R_CERT_LENGTH_MISMATCH); | 2235 | if (!sk_X509_push(certs, cert)) { |
2230 | goto fatal_err; | ||
2231 | } | ||
2232 | if (!sk_X509_push(sk, x)) { | ||
2233 | SSLerror(s, ERR_R_MALLOC_FAILURE); | 2236 | SSLerror(s, ERR_R_MALLOC_FAILURE); |
2234 | goto err; | 2237 | goto err; |
2235 | } | 2238 | } |
2236 | x = NULL; | 2239 | cert = NULL; |
2237 | } | 2240 | } |
2238 | 2241 | ||
2239 | if (sk_X509_num(sk) <= 0) { | 2242 | if (ssl_verify_cert_chain(s, certs) <= 0) { |
2240 | /* | 2243 | al = ssl_verify_alarm_type(s->verify_result); |
2241 | * TLS does not mind 0 certs returned. | 2244 | SSLerror(s, SSL_R_NO_CERTIFICATE_RETURNED); |
2242 | * Fail for TLS only if we required a certificate. | 2245 | goto fatal_err; |
2243 | */ | ||
2244 | if ((s->verify_mode & SSL_VERIFY_PEER) && | ||
2245 | (s->verify_mode & SSL_VERIFY_FAIL_IF_NO_PEER_CERT)) { | ||
2246 | SSLerror(s, SSL_R_PEER_DID_NOT_RETURN_A_CERTIFICATE); | ||
2247 | al = SSL_AD_HANDSHAKE_FAILURE; | ||
2248 | goto fatal_err; | ||
2249 | } | ||
2250 | /* No client certificate so free transcript. */ | ||
2251 | tls1_transcript_free(s); | ||
2252 | } else { | ||
2253 | i = ssl_verify_cert_chain(s, sk); | ||
2254 | if (i <= 0) { | ||
2255 | al = ssl_verify_alarm_type(s->verify_result); | ||
2256 | SSLerror(s, SSL_R_NO_CERTIFICATE_RETURNED); | ||
2257 | goto fatal_err; | ||
2258 | } | ||
2259 | } | 2246 | } |
2260 | 2247 | ||
2261 | X509_free(s->session->peer_cert); | 2248 | X509_free(s->session->peer_cert); |
2262 | s->session->peer_cert = sk_X509_shift(sk); | 2249 | s->session->peer_cert = sk_X509_shift(certs); |
2263 | 2250 | ||
2264 | /* | 2251 | /* |
2265 | * Inconsistency alert: cert_chain does *not* include the | 2252 | * Inconsistency alert: cert_chain does *not* include the |
2266 | * peer's own certificate, while we do include it in s3_clnt.c | 2253 | * peer's own certificate, while we do include it in s3_clnt.c |
2267 | */ | 2254 | */ |
2268 | sk_X509_pop_free(s->session->cert_chain, X509_free); | 2255 | sk_X509_pop_free(s->session->cert_chain, X509_free); |
2269 | s->session->cert_chain = sk; | 2256 | s->session->cert_chain = certs; |
2270 | sk = NULL; | 2257 | certs = NULL; |
2271 | 2258 | ||
2272 | s->session->verify_result = s->verify_result; | 2259 | s->session->verify_result = s->verify_result; |
2273 | 2260 | ||
2261 | done: | ||
2274 | ret = 1; | 2262 | ret = 1; |
2275 | if (0) { | 2263 | if (0) { |
2276 | decode_err: | 2264 | decode_err: |
@@ -2280,8 +2268,8 @@ ssl3_get_client_certificate(SSL *s) | |||
2280 | ssl3_send_alert(s, SSL3_AL_FATAL, al); | 2268 | ssl3_send_alert(s, SSL3_AL_FATAL, al); |
2281 | } | 2269 | } |
2282 | err: | 2270 | err: |
2283 | X509_free(x); | 2271 | sk_X509_pop_free(certs, X509_free); |
2284 | sk_X509_pop_free(sk, X509_free); | 2272 | X509_free(cert); |
2285 | 2273 | ||
2286 | return (ret); | 2274 | return (ret); |
2287 | } | 2275 | } |