From: Dr. Stephen Henson Date: Sun, 28 Jun 2009 16:23:05 +0000 (+0000) Subject: PR: 1942 X-Git-Tag: OpenSSL_0_9_8m-beta1~184 X-Git-Url: https://git.librecmc.org/?a=commitdiff_plain;h=ab8fe43fa23e920c9ac535f7ca7d9a5e2aa92ebc;p=oweals%2Fopenssl.git PR: 1942 Submitted by: David Woodhouse Approved by: steve@openssl.org Replace ad-hoc chain builder with X509_verify_cert(). --- diff --git a/CHANGES b/CHANGES index e60f704aac..3ef82e6eb1 100644 --- a/CHANGES +++ b/CHANGES @@ -9,6 +9,11 @@ clash. [Guenter ] + *) Fix the server certificate chain building code to use X509_verify_cert(), + it used to have an ad-hoc builder which was unable to cope with anything + other than a simple chain. + [David Woodhouse , Steve Henson] + *) Don't check self signed certificate signatures in X509_verify_cert() by default (a flag can override this): it just wastes time without adding any security. As a useful side effect self signed root CAs diff --git a/ssl/d1_both.c b/ssl/d1_both.c index 69b6b10ba2..996f3a77b3 100644 --- a/ssl/d1_both.c +++ b/ssl/d1_both.c @@ -815,14 +815,30 @@ int dtls1_send_change_cipher_spec(SSL *s, int a, int b) return(dtls1_do_write(s,SSL3_RT_CHANGE_CIPHER_SPEC)); } +static int dtls1_add_cert_to_buf(BUF_MEM *buf, unsigned long *l, X509 *x) + { + int n; + unsigned char *p; + + n=i2d_X509(x,NULL); + if (!BUF_MEM_grow_clean(buf,(int)(n+(*l)+3))) + { + SSLerr(SSL_F_DTLS1_OUTPUT_CERT_CHAIN,ERR_R_BUF_LIB); + return 0; + } + p=(unsigned char *)&(buf->data[*l]); + l2n3(n,p); + i2d_X509(x,&p); + *l+=n+3; + + return 1; + } unsigned long dtls1_output_cert_chain(SSL *s, X509 *x) { unsigned char *p; - int n,i; + int i; unsigned long l= 3 + DTLS1_HM_HEADER_LENGTH; BUF_MEM *buf; - X509_STORE_CTX xs_ctx; - X509_OBJECT obj; /* TLSv1 sends a chain with nothing in it, instead of an alert */ buf=s->init_buf; @@ -833,54 +849,33 @@ unsigned long dtls1_output_cert_chain(SSL *s, X509 *x) } if (x != NULL) { - if(!X509_STORE_CTX_init(&xs_ctx,s->ctx->cert_store,NULL,NULL)) - { - SSLerr(SSL_F_DTLS1_OUTPUT_CERT_CHAIN,ERR_R_X509_LIB); - return(0); - } - - for (;;) - { - n=i2d_X509(x,NULL); - if (!BUF_MEM_grow_clean(buf,(int)(n+l+3))) - { - SSLerr(SSL_F_DTLS1_OUTPUT_CERT_CHAIN,ERR_R_BUF_LIB); - return(0); - } - p=(unsigned char *)&(buf->data[l]); - l2n3(n,p); - i2d_X509(x,&p); - l+=n+3; - if (X509_NAME_cmp(X509_get_subject_name(x), - X509_get_issuer_name(x)) == 0) break; - - i=X509_STORE_get_by_subject(&xs_ctx,X509_LU_X509, - X509_get_issuer_name(x),&obj); - if (i <= 0) break; - x=obj.data.x509; - /* Count is one too high since the X509_STORE_get uped the - * ref count */ - X509_free(x); - } - - X509_STORE_CTX_cleanup(&xs_ctx); - } - + X509_STORE_CTX xs_ctx; + + if (!X509_STORE_CTX_init(&xs_ctx,s->ctx->cert_store,x,NULL)) + { + SSLerr(SSL_F_DTLS1_OUTPUT_CERT_CHAIN,ERR_R_X509_LIB); + return(0); + } + + X509_verify_cert(&xs_ctx); + for (i=0; i < sk_X509_num(xs_ctx.chain); i++) + { + x = sk_X509_value(xs_ctx.chain, i); + + if (!dtls1_add_cert_to_buf(buf, &l, x)) + { + X509_STORE_CTX_cleanup(&xs_ctx); + return 0; + } + } + X509_STORE_CTX_cleanup(&xs_ctx); + } /* Thawte special :-) */ - if (s->ctx->extra_certs != NULL) for (i=0; ictx->extra_certs); i++) { x=sk_X509_value(s->ctx->extra_certs,i); - n=i2d_X509(x,NULL); - if (!BUF_MEM_grow_clean(buf,(int)(n+l+3))) - { - SSLerr(SSL_F_DTLS1_OUTPUT_CERT_CHAIN,ERR_R_BUF_LIB); - return(0); - } - p=(unsigned char *)&(buf->data[l]); - l2n3(n,p); - i2d_X509(x,&p); - l+=n+3; + if (!dtls1_add_cert_to_buf(buf, &l, x)) + return 0; } l-= (3 + DTLS1_HM_HEADER_LENGTH); diff --git a/ssl/s3_both.c b/ssl/s3_both.c index 2ecfbb77cb..399fa2c298 100644 --- a/ssl/s3_both.c +++ b/ssl/s3_both.c @@ -264,15 +264,31 @@ int ssl3_send_change_cipher_spec(SSL *s, int a, int b) return(ssl3_do_write(s,SSL3_RT_CHANGE_CIPHER_SPEC)); } +static int ssl3_add_cert_to_buf(BUF_MEM *buf, unsigned long *l, X509 *x) + { + int n; + unsigned char *p; + + n=i2d_X509(x,NULL); + if (!BUF_MEM_grow_clean(buf,(int)(n+(*l)+3))) + { + SSLerr(SSL_F_SSL3_OUTPUT_CERT_CHAIN,ERR_R_BUF_LIB); + return(-1); + } + p=(unsigned char *)&(buf->data[*l]); + l2n3(n,p); + i2d_X509(x,&p); + *l+=n+3; + + return(0); + } + unsigned long ssl3_output_cert_chain(SSL *s, X509 *x) { unsigned char *p; - int n,i; + int i; unsigned long l=7; BUF_MEM *buf; - X509_STORE_CTX xs_ctx; - X509_OBJECT obj; - int no_chain; if ((s->mode & SSL_MODE_NO_AUTO_CHAIN) || s->ctx->extra_certs) @@ -289,58 +305,40 @@ unsigned long ssl3_output_cert_chain(SSL *s, X509 *x) } if (x != NULL) { - if(!no_chain && !X509_STORE_CTX_init(&xs_ctx,s->ctx->cert_store,NULL,NULL)) + if (no_chain) { - SSLerr(SSL_F_SSL3_OUTPUT_CERT_CHAIN,ERR_R_X509_LIB); - return(0); + if (ssl3_add_cert_to_buf(buf, &l, x)) + return(0); } - - for (;;) + else { - n=i2d_X509(x,NULL); - if (!BUF_MEM_grow_clean(buf,(int)(n+l+3))) + X509_STORE_CTX xs_ctx; + + if (!X509_STORE_CTX_init(&xs_ctx,s->ctx->cert_store,x,NULL)) { - SSLerr(SSL_F_SSL3_OUTPUT_CERT_CHAIN,ERR_R_BUF_LIB); + SSLerr(SSL_F_SSL3_OUTPUT_CERT_CHAIN,ERR_R_X509_LIB); return(0); } - p=(unsigned char *)&(buf->data[l]); - l2n3(n,p); - i2d_X509(x,&p); - l+=n+3; - - if (no_chain) - break; - - if (X509_NAME_cmp(X509_get_subject_name(x), - X509_get_issuer_name(x)) == 0) break; - - i=X509_STORE_get_by_subject(&xs_ctx,X509_LU_X509, - X509_get_issuer_name(x),&obj); - if (i <= 0) break; - x=obj.data.x509; - /* Count is one too high since the X509_STORE_get uped the - * ref count */ - X509_free(x); - } - if (!no_chain) + X509_verify_cert(&xs_ctx); + for (i=0; i < sk_X509_num(xs_ctx.chain); i++) + { + x = sk_X509_value(xs_ctx.chain, i); + + if (ssl3_add_cert_to_buf(buf, &l, x)) + { + X509_STORE_CTX_cleanup(&xs_ctx); + return 0; + } + } X509_STORE_CTX_cleanup(&xs_ctx); + } } - /* Thawte special :-) */ - if (s->ctx->extra_certs != NULL) for (i=0; ictx->extra_certs); i++) { x=sk_X509_value(s->ctx->extra_certs,i); - n=i2d_X509(x,NULL); - if (!BUF_MEM_grow_clean(buf,(int)(n+l+3))) - { - SSLerr(SSL_F_SSL3_OUTPUT_CERT_CHAIN,ERR_R_BUF_LIB); + if (ssl3_add_cert_to_buf(buf, &l, x)) return(0); - } - p=(unsigned char *)&(buf->data[l]); - l2n3(n,p); - i2d_X509(x,&p); - l+=n+3; } l-=7;