Commit d65b8b21 authored by Ben Laurie's avatar Ben Laurie
Browse files

Backport OCSP fixes.

parent 5dca1e33
Loading
Loading
Loading
Loading
+10 −0
Original line number Diff line number Diff line
@@ -4,6 +4,16 @@

 Changes between 1.0.1 and 1.0.2 [xx XXX xxxx]

  *) Fix OCSP checking.
     [Rob Stradling <rob.stradling@comodo.com> and Ben Laurie]

  *) Backport support for partial chain verification: if an intermediate
     certificate is explicitly trusted (using -addtrust option to x509
     utility for example) the verification is sucessful even if the chain
     is not complete.
     The OCSP checking fix depends on this backport.
     [Steve Henson and Rob Stradling <rob.stradling@comodo.com>]

  *) Add -trusted_first option which attempts to find certificates in the
     trusted store even if an untrusted chain is also supplied.
     [Steve Henson]
+5 −5
Original line number Diff line number Diff line
@@ -866,6 +866,8 @@ int MAIN(int argc, char **argv)
		goto end;
		}

	ret = 0;

	if (!noverify)
		{
		if (req && ((i = OCSP_check_nonce(req, bs)) <= 0))
@@ -875,17 +877,17 @@ int MAIN(int argc, char **argv)
			else
				{
				BIO_printf(bio_err, "Nonce Verify error\n");
				ret = 1;
				goto end;
				}
			}

		i = OCSP_basic_verify(bs, verify_other, store, verify_flags);
                if (i < 0) i = OCSP_basic_verify(bs, NULL, store, 0);

		if(i <= 0)
			{
			BIO_printf(bio_err, "Response Verify Failure\n");
			ERR_print_errors(bio_err);
			ret = 1;
			}
		else
			BIO_printf(bio_err, "Response verify OK\n");
@@ -893,9 +895,7 @@ int MAIN(int argc, char **argv)
		}

	if (!print_ocsp_summary(out, bs, req, reqnames, ids, nsec, maxage))
		goto end;

	ret = 0;
		ret = 1;

end:
	ERR_print_errors(bio_err);
+66 −7
Original line number Diff line number Diff line
@@ -77,8 +77,10 @@ int OCSP_basic_verify(OCSP_BASICRESP *bs, STACK_OF(X509) *certs,
	{
	X509 *signer, *x;
	STACK_OF(X509) *chain = NULL;
	STACK_OF(X509) *tmpchain = NULL;
	X509_STORE *tmpstore = NULL;
	X509_STORE_CTX ctx;
	int i, ret = 0;
	int i, ret;
	ret = ocsp_find_signer(&signer, bs, certs, st, flags);
	if (!ret)
		{
@@ -86,7 +88,7 @@ int OCSP_basic_verify(OCSP_BASICRESP *bs, STACK_OF(X509) *certs,
		goto end;
		}
	if ((ret == 2) && (flags & OCSP_TRUSTOTHER))
		flags |= OCSP_NOVERIFY;
		chain = certs;
	if (!(flags & OCSP_NOSIGS))
		{
		EVP_PKEY *skey;
@@ -102,6 +104,60 @@ int OCSP_basic_verify(OCSP_BASICRESP *bs, STACK_OF(X509) *certs,
	if (!(flags & OCSP_NOVERIFY))
		{
		int init_res;

		/* If we trust the signer, we don't need to build a chain.
		 * (If the signer is a root certificate, X509_verify_cert()
		 * would fail anyway!)
		 */
		if (chain == certs) goto verified_chain;

		/* If we trust some "other" certificates, mark them as
		 * explicitly trusted (because some of them might be
		 * Intermediate CA Certificates), put them in a store and
		 * attempt to build a trusted chain.
		 */
		if ((flags & OCSP_TRUSTOTHER) && (certs != NULL))
			{
			ASN1_OBJECT *objtmp = OBJ_nid2obj(NID_OCSP_sign);
			tmpstore = X509_STORE_new();
			if (!tmpstore)
				{
				ret = -1;
				OCSPerr(OCSP_F_OCSP_BASIC_VERIFY, ERR_R_MALLOC_FAILURE);
				goto end;
				}
			for (i = 0; i < sk_X509_num(certs); i++)
				{
				X509 *xother = sk_X509_value(certs, i);
				X509_add1_trust_object(xother, objtmp);
				if (!X509_STORE_add_cert(tmpstore, xother))
					{
					ret = -1;
					goto end;
					}
				}

			init_res = X509_STORE_CTX_init(&ctx, tmpstore, signer, NULL);
			if (!init_res)
				{
				ret = -1;
				OCSPerr(OCSP_F_OCSP_BASIC_VERIFY,ERR_R_X509_LIB);
				goto end;
				}
			X509_STORE_CTX_set_purpose(&ctx, X509_PURPOSE_OCSP_HELPER);
			ret = X509_verify_cert(&ctx);
			if (ret == 1)
				{
				chain = tmpchain = X509_STORE_CTX_get1_chain(&ctx);
				X509_STORE_CTX_cleanup(&ctx);
				goto verified_chain;
				}
			X509_STORE_CTX_cleanup(&ctx);
			}

		/* Attempt to build a chain up to a Root Certificate in the
		 * trust store provided by the caller.
		 */
		if(flags & OCSP_NOCHAIN)
			init_res = X509_STORE_CTX_init(&ctx, st, signer, NULL);
		else
@@ -115,7 +171,7 @@ int OCSP_basic_verify(OCSP_BASICRESP *bs, STACK_OF(X509) *certs,

		X509_STORE_CTX_set_purpose(&ctx, X509_PURPOSE_OCSP_HELPER);
		ret = X509_verify_cert(&ctx);
		chain = X509_STORE_CTX_get1_chain(&ctx);
		chain = tmpchain = X509_STORE_CTX_get1_chain(&ctx);
		X509_STORE_CTX_cleanup(&ctx);
		if (ret <= 0)
			{
@@ -125,6 +181,8 @@ int OCSP_basic_verify(OCSP_BASICRESP *bs, STACK_OF(X509) *certs,
					X509_verify_cert_error_string(i));
			goto end;
			}

	verified_chain:
		if(flags & OCSP_NOCHECKS)
			{
			ret = 1;
@@ -155,7 +213,8 @@ int OCSP_basic_verify(OCSP_BASICRESP *bs, STACK_OF(X509) *certs,


	end:
	if(chain) sk_X509_pop_free(chain, X509_free);
	if(tmpchain) sk_X509_pop_free(tmpchain, X509_free);
	if(tmpstore) X509_STORE_free(tmpstore);
	return ret;
	}

+9 −0
Original line number Diff line number Diff line
@@ -114,6 +114,15 @@ int X509_check_trust(X509 *x, int id, int flags)
	X509_TRUST *pt;
	int idx;
	if(id == -1) return 1;
	/* We get this as a default value */
	if (id == 0)
		{
		int rv;
		rv = obj_trust(NID_anyExtendedKeyUsage, x, 0);
		if (rv != X509_TRUST_UNTRUSTED)
			return rv;
		return trust_compat(NULL, x, 0);
		}
	idx = X509_TRUST_get_by_id(id);
	if(idx == -1) return default_trust(id, x, flags);
	pt = X509_TRUST_get0(idx);
+33 −27
Original line number Diff line number Diff line
@@ -323,8 +323,13 @@ int X509_verify_cert(X509_STORE_CTX *ctx)

	/* we now have our chain, lets check it... */

	/* Is last certificate looked up self signed? */
	if (!ctx->check_issued(ctx,x,x))
	i = check_trust(ctx);

	/* If explicitly rejected error */
	if (i == X509_TRUST_REJECTED)
		goto end;
	/* If not explicitly trusted then indicate error */
	if (i != X509_TRUST_TRUSTED)
		{
		if ((chain_ss == NULL) || !ctx->check_issued(ctx, x, chain_ss))
			{
@@ -362,12 +367,6 @@ int X509_verify_cert(X509_STORE_CTX *ctx)
	
	if (!ok) goto end;

	/* The chain extensions are OK: check trust */

	if (param->trust > 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);

@@ -658,28 +657,35 @@ static int check_name_constraints(X509_STORE_CTX *ctx)

static int check_trust(X509_STORE_CTX *ctx)
{
#ifdef OPENSSL_NO_CHAIN_VERIFY
	return 1;
#else
	int i, ok;
	X509 *x;
	X509 *x = NULL;
	int (*cb)(int xok,X509_STORE_CTX *xctx);
	cb=ctx->verify_cb;
/* For now just check the last certificate in the chain */
	i = sk_X509_num(ctx->chain) - 1;
	/* Check all trusted certificates in chain */
	for (i = ctx->last_untrusted; i < sk_X509_num(ctx->chain); i++)
		{
		x = sk_X509_value(ctx->chain, i);
		ok = X509_check_trust(x, ctx->param->trust, 0);
		/* If explicitly trusted return trusted */
		if (ok == X509_TRUST_TRUSTED)
		return 1;
			return X509_TRUST_TRUSTED;
		/* If explicitly rejected notify callback and reject if
		 * not overridden.
		 */
		if (ok == X509_TRUST_REJECTED)
			{
			ctx->error_depth = i;
			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
			if (!ok)
				return X509_TRUST_REJECTED;
			}
		}
	/* If no trusted certs in chain at all return untrusted and
	 * allow standard (no issuer cert) etc errors to be indicated.
	 */
	return X509_TRUST_UNTRUSTED;
}

static int check_revocation(X509_STORE_CTX *ctx)
Loading