Add trust setting support to the verify code. It now checks the
[openssl.git] / crypto / x509 / x509_vfy.c
index 3d1b38a0194c99b0b43da00523656cf39559e2b1..75ab96e506ee3b8888c669f3e264034fd687e92a 100644 (file)
@@ -72,6 +72,7 @@
 
 static int null_callback(int ok,X509_STORE_CTX *e);
 static int check_chain_purpose(X509_STORE_CTX *ctx);
+static int check_trust(X509_STORE_CTX *ctx);
 static int internal_verify(X509_STORE_CTX *ctx);
 const char *X509_version="X.509" OPENSSL_VERSION_PTEXT;
 
@@ -297,6 +298,12 @@ int X509_verify_cert(X509_STORE_CTX *ctx)
 
        if(!ok) goto end;
 
+       /* The chain extensions are OK: check trust */
+
+       if(ctx->trust_purpose > 0) ok = check_trust(ctx);
+
+       if(!ok) goto end;
+
        /* We may as well copy down any DSA parameters that are required */
        X509_get_pubkey_parameters(NULL,ctx->chain);
 
@@ -356,6 +363,30 @@ static int check_chain_purpose(X509_STORE_CTX *ctx)
 #endif
 }
 
+static int check_trust(X509_STORE_CTX *ctx)
+{
+#ifdef NO_CHAIN_VERIFY
+       return 1;
+#else
+       int i, ok;
+       X509 *x;
+       int (*cb)();
+       cb=ctx->ctx->verify_cb;
+       if (cb == NULL) cb=null_callback;
+/* For now just check the last certificate in the chain */
+       i = sk_X509_num(ctx->chain) - 1;
+       x = sk_X509_value(ctx->chain, i);
+       ok = X509_check_trust(x, ctx->trust_purpose, 0);
+       if(ok == X509_TRUST_TRUSTED) return 1;
+       ctx->error_depth = sk_X509_num(ctx->chain) - 1;
+       ctx->current_cert = x;
+       if(ok == X509_TRUST_REJECTED) ctx->error = X509_V_ERR_CERT_REJECTED;
+       else ctx->error = X509_V_ERR_CERT_UNTRUSTED;
+       ok = cb(0, ctx);
+       return(ok);
+#endif
+}
+
 static int internal_verify(X509_STORE_CTX *ctx)
        {
        int i,ok=0,n;
@@ -696,9 +727,10 @@ void X509_STORE_CTX_set_chain(X509_STORE_CTX *ctx, STACK_OF(X509) *sk)
        ctx->untrusted=sk;
        }
 
-void X509_STORE_CTX_chain_purpose(X509_STORE_CTX *ctx, int purpose)
+int X509_STORE_CTX_chain_purpose(X509_STORE_CTX *ctx, int purpose)
        {
-       ctx->chain_purpose = purpose;
+               return X509_set_purpose_and_trust(purpose,
+                               &ctx->chain_purpose, &ctx->trust_purpose);
        }
 
 void X509_STORE_CTX_trust_purpose(X509_STORE_CTX *ctx, int purpose)
@@ -706,6 +738,22 @@ void X509_STORE_CTX_trust_purpose(X509_STORE_CTX *ctx, int purpose)
        ctx->trust_purpose = purpose;
        }
 
+int X509_set_purpose_and_trust(int id, int *purp, int *trust)
+{
+       X509_PURPOSE *ptmp;
+       int idx;
+       idx = X509_PURPOSE_get_by_id(id);
+       if(idx == -1) {
+               X509err(X509_F_X509_SET_PURPOSE_AND_TRUST,
+                                       X509_R_UNKNOWN_TRUST_ID);
+               return 0;
+       }
+       ptmp = X509_PURPOSE_iget(idx);
+       if(purp) *purp = id;
+       if(trust) *trust = ptmp->trust_id;
+       return 1;
+}
+
 IMPLEMENT_STACK_OF(X509)
 IMPLEMENT_ASN1_SET_OF(X509)