diff options
author | beck <> | 2000-03-19 11:13:58 +0000 |
---|---|---|
committer | beck <> | 2000-03-19 11:13:58 +0000 |
commit | 796d609550df3a33fc11468741c5d2f6d3df4c11 (patch) | |
tree | 6c6d539061caa20372dad0ac4ddb1dfae2fbe7fe /src/lib/libcrypto/x509/x509_vfy.c | |
parent | 5be3114c1fd7e0dfea1e38d3abb4cbba75244419 (diff) | |
download | openbsd-796d609550df3a33fc11468741c5d2f6d3df4c11.tar.gz openbsd-796d609550df3a33fc11468741c5d2f6d3df4c11.tar.bz2 openbsd-796d609550df3a33fc11468741c5d2f6d3df4c11.zip |
OpenSSL 0.9.5 merge
*warning* this bumps shared lib minors for libssl and libcrypto from 2.1 to 2.2
if you are using the ssl26 packages for ssh and other things to work you will
need to get new ones (see ~beck/libsslsnap/<arch>) on cvs or ~beck/src-patent.tar.gz on cvs
Diffstat (limited to 'src/lib/libcrypto/x509/x509_vfy.c')
-rw-r--r-- | src/lib/libcrypto/x509/x509_vfy.c | 206 |
1 files changed, 186 insertions, 20 deletions
diff --git a/src/lib/libcrypto/x509/x509_vfy.c b/src/lib/libcrypto/x509/x509_vfy.c index c72ee4a385..4fdff54124 100644 --- a/src/lib/libcrypto/x509/x509_vfy.c +++ b/src/lib/libcrypto/x509/x509_vfy.c | |||
@@ -59,23 +59,24 @@ | |||
59 | #include <stdio.h> | 59 | #include <stdio.h> |
60 | #include <time.h> | 60 | #include <time.h> |
61 | #include <errno.h> | 61 | #include <errno.h> |
62 | #include <sys/types.h> | ||
63 | #include <sys/stat.h> | ||
64 | 62 | ||
65 | #include <openssl/crypto.h> | ||
66 | #include "cryptlib.h" | 63 | #include "cryptlib.h" |
64 | #include <openssl/crypto.h> | ||
67 | #include <openssl/lhash.h> | 65 | #include <openssl/lhash.h> |
68 | #include <openssl/buffer.h> | 66 | #include <openssl/buffer.h> |
69 | #include <openssl/evp.h> | 67 | #include <openssl/evp.h> |
70 | #include <openssl/asn1.h> | 68 | #include <openssl/asn1.h> |
71 | #include <openssl/x509.h> | 69 | #include <openssl/x509.h> |
70 | #include <openssl/x509v3.h> | ||
72 | #include <openssl/objects.h> | 71 | #include <openssl/objects.h> |
73 | 72 | ||
74 | static int null_callback(int ok,X509_STORE_CTX *e); | 73 | static int null_callback(int ok,X509_STORE_CTX *e); |
74 | static int check_chain_purpose(X509_STORE_CTX *ctx); | ||
75 | static int check_trust(X509_STORE_CTX *ctx); | ||
75 | static int internal_verify(X509_STORE_CTX *ctx); | 76 | static int internal_verify(X509_STORE_CTX *ctx); |
76 | const char *X509_version="X.509" OPENSSL_VERSION_PTEXT; | 77 | const char *X509_version="X.509" OPENSSL_VERSION_PTEXT; |
77 | 78 | ||
78 | static STACK *x509_store_ctx_method=NULL; | 79 | static STACK_OF(CRYPTO_EX_DATA_FUNCS) *x509_store_ctx_method=NULL; |
79 | static int x509_store_ctx_num=0; | 80 | static int x509_store_ctx_num=0; |
80 | #if 0 | 81 | #if 0 |
81 | static int x509_store_num=1; | 82 | static int x509_store_num=1; |
@@ -127,7 +128,7 @@ int X509_verify_cert(X509_STORE_CTX *ctx) | |||
127 | ctx->last_untrusted=1; | 128 | ctx->last_untrusted=1; |
128 | } | 129 | } |
129 | 130 | ||
130 | /* We use a temporary so we can chop and hack at it */ | 131 | /* We use a temporary STACK so we can chop and hack at it */ |
131 | if (ctx->untrusted != NULL | 132 | if (ctx->untrusted != NULL |
132 | && (sktmp=sk_X509_dup(ctx->untrusted)) == NULL) | 133 | && (sktmp=sk_X509_dup(ctx->untrusted)) == NULL) |
133 | { | 134 | { |
@@ -184,17 +185,37 @@ int X509_verify_cert(X509_STORE_CTX *ctx) | |||
184 | 185 | ||
185 | i=sk_X509_num(ctx->chain); | 186 | i=sk_X509_num(ctx->chain); |
186 | x=sk_X509_value(ctx->chain,i-1); | 187 | x=sk_X509_value(ctx->chain,i-1); |
187 | if (X509_NAME_cmp(X509_get_subject_name(x),X509_get_issuer_name(x)) | 188 | xn = X509_get_subject_name(x); |
189 | if (X509_NAME_cmp(xn,X509_get_issuer_name(x)) | ||
188 | == 0) | 190 | == 0) |
189 | { | 191 | { |
190 | /* we have a self signed certificate */ | 192 | /* we have a self signed certificate */ |
191 | if (sk_X509_num(ctx->chain) == 1) | 193 | if (sk_X509_num(ctx->chain) == 1) |
192 | { | 194 | { |
193 | ctx->error=X509_V_ERR_DEPTH_ZERO_SELF_SIGNED_CERT; | 195 | /* We have a single self signed certificate: see if |
194 | ctx->current_cert=x; | 196 | * we can find it in the store. We must have an exact |
195 | ctx->error_depth=i-1; | 197 | * match to avoid possible impersonation. |
196 | ok=cb(0,ctx); | 198 | */ |
197 | if (!ok) goto end; | 199 | ok=X509_STORE_get_by_subject(ctx,X509_LU_X509,xn,&obj); |
200 | if ((ok != X509_LU_X509) || X509_cmp(x, obj.data.x509)) | ||
201 | { | ||
202 | ctx->error=X509_V_ERR_DEPTH_ZERO_SELF_SIGNED_CERT; | ||
203 | ctx->current_cert=x; | ||
204 | ctx->error_depth=i-1; | ||
205 | if(ok == X509_LU_X509) X509_OBJECT_free_contents(&obj); | ||
206 | ok=cb(0,ctx); | ||
207 | if (!ok) goto end; | ||
208 | } | ||
209 | else | ||
210 | { | ||
211 | /* We have a match: replace certificate with store version | ||
212 | * so we get any trust settings. | ||
213 | */ | ||
214 | X509_free(x); | ||
215 | x = obj.data.x509; | ||
216 | sk_X509_set(ctx->chain, i - 1, x); | ||
217 | ctx->last_untrusted=0; | ||
218 | } | ||
198 | } | 219 | } |
199 | else | 220 | else |
200 | { | 221 | { |
@@ -272,6 +293,17 @@ int X509_verify_cert(X509_STORE_CTX *ctx) | |||
272 | if (!ok) goto end; | 293 | if (!ok) goto end; |
273 | } | 294 | } |
274 | 295 | ||
296 | /* We have the chain complete: now we need to check its purpose */ | ||
297 | if(ctx->purpose > 0) ok = check_chain_purpose(ctx); | ||
298 | |||
299 | if(!ok) goto end; | ||
300 | |||
301 | /* The chain extensions are OK: check trust */ | ||
302 | |||
303 | if(ctx->trust > 0) ok = check_trust(ctx); | ||
304 | |||
305 | if(!ok) goto end; | ||
306 | |||
275 | /* We may as well copy down any DSA parameters that are required */ | 307 | /* We may as well copy down any DSA parameters that are required */ |
276 | X509_get_pubkey_parameters(NULL,ctx->chain); | 308 | X509_get_pubkey_parameters(NULL,ctx->chain); |
277 | 309 | ||
@@ -290,6 +322,71 @@ end: | |||
290 | return(ok); | 322 | return(ok); |
291 | } | 323 | } |
292 | 324 | ||
325 | /* Check a certificate chains extensions for consistency | ||
326 | * with the supplied purpose | ||
327 | */ | ||
328 | |||
329 | static int check_chain_purpose(X509_STORE_CTX *ctx) | ||
330 | { | ||
331 | #ifdef NO_CHAIN_VERIFY | ||
332 | return 1; | ||
333 | #else | ||
334 | int i, ok=0; | ||
335 | X509 *x; | ||
336 | int (*cb)(); | ||
337 | cb=ctx->ctx->verify_cb; | ||
338 | if (cb == NULL) cb=null_callback; | ||
339 | /* Check all untrusted certificates */ | ||
340 | for(i = 0; i < ctx->last_untrusted; i++) { | ||
341 | x = sk_X509_value(ctx->chain, i); | ||
342 | if(!X509_check_purpose(x, ctx->purpose, i)) { | ||
343 | if(i) ctx->error = X509_V_ERR_INVALID_CA; | ||
344 | else ctx->error = X509_V_ERR_INVALID_PURPOSE; | ||
345 | ctx->error_depth = i; | ||
346 | ctx->current_cert = x; | ||
347 | ok=cb(0,ctx); | ||
348 | if(!ok) goto end; | ||
349 | } | ||
350 | /* Check pathlen */ | ||
351 | if((i > 1) && (x->ex_pathlen != -1) | ||
352 | && (i > (x->ex_pathlen + 1))) { | ||
353 | ctx->error = X509_V_ERR_PATH_LENGTH_EXCEEDED; | ||
354 | ctx->error_depth = i; | ||
355 | ctx->current_cert = x; | ||
356 | ok=cb(0,ctx); | ||
357 | if(!ok) goto end; | ||
358 | } | ||
359 | } | ||
360 | ok = 1; | ||
361 | end: | ||
362 | return(ok); | ||
363 | #endif | ||
364 | } | ||
365 | |||
366 | static int check_trust(X509_STORE_CTX *ctx) | ||
367 | { | ||
368 | #ifdef NO_CHAIN_VERIFY | ||
369 | return 1; | ||
370 | #else | ||
371 | int i, ok; | ||
372 | X509 *x; | ||
373 | int (*cb)(); | ||
374 | cb=ctx->ctx->verify_cb; | ||
375 | if (cb == NULL) cb=null_callback; | ||
376 | /* For now just check the last certificate in the chain */ | ||
377 | i = sk_X509_num(ctx->chain) - 1; | ||
378 | x = sk_X509_value(ctx->chain, i); | ||
379 | ok = X509_check_trust(x, ctx->trust, 0); | ||
380 | if(ok == X509_TRUST_TRUSTED) return 1; | ||
381 | ctx->error_depth = sk_X509_num(ctx->chain) - 1; | ||
382 | ctx->current_cert = x; | ||
383 | if(ok == X509_TRUST_REJECTED) ctx->error = X509_V_ERR_CERT_REJECTED; | ||
384 | else ctx->error = X509_V_ERR_CERT_UNTRUSTED; | ||
385 | ok = cb(0, ctx); | ||
386 | return(ok); | ||
387 | #endif | ||
388 | } | ||
389 | |||
293 | static int internal_verify(X509_STORE_CTX *ctx) | 390 | static int internal_verify(X509_STORE_CTX *ctx) |
294 | { | 391 | { |
295 | int i,ok=0,n; | 392 | int i,ok=0,n; |
@@ -439,7 +536,7 @@ int X509_cmp_current_time(ASN1_UTCTIME *ctm) | |||
439 | atm.length=sizeof(buff2); | 536 | atm.length=sizeof(buff2); |
440 | atm.data=(unsigned char *)buff2; | 537 | atm.data=(unsigned char *)buff2; |
441 | 538 | ||
442 | X509_gmtime_adj(&atm,-offset); | 539 | X509_gmtime_adj(&atm,-offset*60); |
443 | 540 | ||
444 | i=(buff1[0]-'0')*10+(buff1[1]-'0'); | 541 | i=(buff1[0]-'0')*10+(buff1[1]-'0'); |
445 | if (i < 50) i+=100; /* cf. RFC 2459 */ | 542 | if (i < 50) i+=100; /* cf. RFC 2459 */ |
@@ -525,13 +622,13 @@ int X509_STORE_add_cert(X509_STORE *ctx, X509 *x) | |||
525 | 622 | ||
526 | X509_OBJECT_up_ref_count(obj); | 623 | X509_OBJECT_up_ref_count(obj); |
527 | 624 | ||
528 | r=(X509_OBJECT *)lh_insert(ctx->certs,(char *)obj); | 625 | r=(X509_OBJECT *)lh_insert(ctx->certs,obj); |
529 | if (r != NULL) | 626 | if (r != NULL) |
530 | { /* oops, put it back */ | 627 | { /* oops, put it back */ |
531 | lh_delete(ctx->certs,(char *)obj); | 628 | lh_delete(ctx->certs,obj); |
532 | X509_OBJECT_free_contents(obj); | 629 | X509_OBJECT_free_contents(obj); |
533 | Free(obj); | 630 | Free(obj); |
534 | lh_insert(ctx->certs,(char *)r); | 631 | lh_insert(ctx->certs,r); |
535 | X509err(X509_F_X509_STORE_ADD_CERT,X509_R_CERT_ALREADY_IN_HASH_TABLE); | 632 | X509err(X509_F_X509_STORE_ADD_CERT,X509_R_CERT_ALREADY_IN_HASH_TABLE); |
536 | ret=0; | 633 | ret=0; |
537 | } | 634 | } |
@@ -560,13 +657,13 @@ int X509_STORE_add_crl(X509_STORE *ctx, X509_CRL *x) | |||
560 | 657 | ||
561 | X509_OBJECT_up_ref_count(obj); | 658 | X509_OBJECT_up_ref_count(obj); |
562 | 659 | ||
563 | r=(X509_OBJECT *)lh_insert(ctx->certs,(char *)obj); | 660 | r=(X509_OBJECT *)lh_insert(ctx->certs,obj); |
564 | if (r != NULL) | 661 | if (r != NULL) |
565 | { /* oops, put it back */ | 662 | { /* oops, put it back */ |
566 | lh_delete(ctx->certs,(char *)obj); | 663 | lh_delete(ctx->certs,obj); |
567 | X509_OBJECT_free_contents(obj); | 664 | X509_OBJECT_free_contents(obj); |
568 | Free(obj); | 665 | Free(obj); |
569 | lh_insert(ctx->certs,(char *)r); | 666 | lh_insert(ctx->certs,r); |
570 | X509err(X509_F_X509_STORE_ADD_CRL,X509_R_CERT_ALREADY_IN_HASH_TABLE); | 667 | X509err(X509_F_X509_STORE_ADD_CRL,X509_R_CERT_ALREADY_IN_HASH_TABLE); |
571 | ret=0; | 668 | ret=0; |
572 | } | 669 | } |
@@ -576,8 +673,8 @@ int X509_STORE_add_crl(X509_STORE *ctx, X509_CRL *x) | |||
576 | return(ret); | 673 | return(ret); |
577 | } | 674 | } |
578 | 675 | ||
579 | int X509_STORE_CTX_get_ex_new_index(long argl, char *argp, int (*new_func)(), | 676 | int X509_STORE_CTX_get_ex_new_index(long argl, void *argp, CRYPTO_EX_new *new_func, |
580 | int (*dup_func)(), void (*free_func)()) | 677 | CRYPTO_EX_dup *dup_func, CRYPTO_EX_free *free_func) |
581 | { | 678 | { |
582 | x509_store_ctx_num++; | 679 | x509_store_ctx_num++; |
583 | return(CRYPTO_get_ex_new_index(x509_store_ctx_num-1, | 680 | return(CRYPTO_get_ex_new_index(x509_store_ctx_num-1, |
@@ -620,6 +717,19 @@ STACK_OF(X509) *X509_STORE_CTX_get_chain(X509_STORE_CTX *ctx) | |||
620 | return(ctx->chain); | 717 | return(ctx->chain); |
621 | } | 718 | } |
622 | 719 | ||
720 | STACK_OF(X509) *X509_STORE_CTX_get1_chain(X509_STORE_CTX *ctx) | ||
721 | { | ||
722 | int i; | ||
723 | X509 *x; | ||
724 | STACK_OF(X509) *chain; | ||
725 | if(!ctx->chain || !(chain = sk_X509_dup(ctx->chain))) return NULL; | ||
726 | for(i = 0; i < sk_X509_num(chain); i++) { | ||
727 | x = sk_X509_value(chain, i); | ||
728 | CRYPTO_add(&x->references, 1, CRYPTO_LOCK_X509); | ||
729 | } | ||
730 | return(chain); | ||
731 | } | ||
732 | |||
623 | void X509_STORE_CTX_set_cert(X509_STORE_CTX *ctx, X509 *x) | 733 | void X509_STORE_CTX_set_cert(X509_STORE_CTX *ctx, X509 *x) |
624 | { | 734 | { |
625 | ctx->cert=x; | 735 | ctx->cert=x; |
@@ -630,6 +740,62 @@ void X509_STORE_CTX_set_chain(X509_STORE_CTX *ctx, STACK_OF(X509) *sk) | |||
630 | ctx->untrusted=sk; | 740 | ctx->untrusted=sk; |
631 | } | 741 | } |
632 | 742 | ||
743 | int X509_STORE_CTX_set_purpose(X509_STORE_CTX *ctx, int purpose) | ||
744 | { | ||
745 | return X509_STORE_CTX_purpose_inherit(ctx, 0, purpose, 0); | ||
746 | } | ||
747 | |||
748 | int X509_STORE_CTX_set_trust(X509_STORE_CTX *ctx, int trust) | ||
749 | { | ||
750 | return X509_STORE_CTX_purpose_inherit(ctx, 0, 0, trust); | ||
751 | } | ||
752 | |||
753 | /* This function is used to set the X509_STORE_CTX purpose and trust | ||
754 | * values. This is intended to be used when another structure has its | ||
755 | * own trust and purpose values which (if set) will be inherited by | ||
756 | * the ctx. If they aren't set then we will usually have a default | ||
757 | * purpose in mind which should then be used to set the trust value. | ||
758 | * An example of this is SSL use: an SSL structure will have its own | ||
759 | * purpose and trust settings which the application can set: if they | ||
760 | * aren't set then we use the default of SSL client/server. | ||
761 | */ | ||
762 | |||
763 | int X509_STORE_CTX_purpose_inherit(X509_STORE_CTX *ctx, int def_purpose, | ||
764 | int purpose, int trust) | ||
765 | { | ||
766 | int idx; | ||
767 | /* If purpose not set use default */ | ||
768 | if(!purpose) purpose = def_purpose; | ||
769 | /* If we have a purpose then check it is valid */ | ||
770 | if(purpose) { | ||
771 | idx = X509_PURPOSE_get_by_id(purpose); | ||
772 | if(idx == -1) { | ||
773 | X509err(X509_F_X509_STORE_CTX_PURPOSE_INHERIT, | ||
774 | X509_R_UNKNOWN_PURPOSE_ID); | ||
775 | return 0; | ||
776 | } | ||
777 | /* If trust not set then get from purpose default */ | ||
778 | if(!trust) { | ||
779 | X509_PURPOSE *ptmp; | ||
780 | ptmp = X509_PURPOSE_get0(idx); | ||
781 | trust = ptmp->trust; | ||
782 | } | ||
783 | } | ||
784 | if(trust) { | ||
785 | idx = X509_TRUST_get_by_id(trust); | ||
786 | if(idx == -1) { | ||
787 | X509err(X509_F_X509_STORE_CTX_PURPOSE_INHERIT, | ||
788 | X509_R_UNKNOWN_TRUST_ID); | ||
789 | return 0; | ||
790 | } | ||
791 | } | ||
792 | |||
793 | if(purpose) ctx->purpose = purpose; | ||
794 | if(trust) ctx->trust = trust; | ||
795 | return 1; | ||
796 | } | ||
797 | |||
798 | |||
633 | IMPLEMENT_STACK_OF(X509) | 799 | IMPLEMENT_STACK_OF(X509) |
634 | IMPLEMENT_ASN1_SET_OF(X509) | 800 | IMPLEMENT_ASN1_SET_OF(X509) |
635 | 801 | ||