summaryrefslogtreecommitdiff
path: root/src/lib/libcrypto/x509/x509_vfy.c
diff options
context:
space:
mode:
Diffstat (limited to 'src/lib/libcrypto/x509/x509_vfy.c')
-rw-r--r--src/lib/libcrypto/x509/x509_vfy.c206
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
74static int null_callback(int ok,X509_STORE_CTX *e); 73static int null_callback(int ok,X509_STORE_CTX *e);
74static int check_chain_purpose(X509_STORE_CTX *ctx);
75static int check_trust(X509_STORE_CTX *ctx);
75static int internal_verify(X509_STORE_CTX *ctx); 76static int internal_verify(X509_STORE_CTX *ctx);
76const char *X509_version="X.509" OPENSSL_VERSION_PTEXT; 77const char *X509_version="X.509" OPENSSL_VERSION_PTEXT;
77 78
78static STACK *x509_store_ctx_method=NULL; 79static STACK_OF(CRYPTO_EX_DATA_FUNCS) *x509_store_ctx_method=NULL;
79static int x509_store_ctx_num=0; 80static int x509_store_ctx_num=0;
80#if 0 81#if 0
81static int x509_store_num=1; 82static 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
329static 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
366static 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
293static int internal_verify(X509_STORE_CTX *ctx) 390static 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
579int X509_STORE_CTX_get_ex_new_index(long argl, char *argp, int (*new_func)(), 676int 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
720STACK_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
623void X509_STORE_CTX_set_cert(X509_STORE_CTX *ctx, X509 *x) 733void 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
743int 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
748int 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
763int 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
633IMPLEMENT_STACK_OF(X509) 799IMPLEMENT_STACK_OF(X509)
634IMPLEMENT_ASN1_SET_OF(X509) 800IMPLEMENT_ASN1_SET_OF(X509)
635 801