提交 51630a37 编写于 作者: D Dr. Stephen Henson

Add trust setting support to the verify code. It now checks the

trust settings of the root CA.

After a few fixes it seems to work OK.

Still need to add support to SSL and S/MIME code though.
上级 74ecf9e2
......@@ -12,15 +12,21 @@
DSA key was used because it didn't fix the digest.
[Steve Henson]
*) Very preliminary certificate chain verify code. Currently just tests
the untrusted certificates for consistency with the verify purpose
(which is set when the X509_STORE_CTX structure is set up) and checks
the pathlength. There is a NO_CHAIN_VERIFY compilation option to keep
the old behaviour: this is because when it is finally working it will
reject chains with invalid extensions whereas before it made no checks
at all.
Preliminary untested trust code.
*) Initial certificate chain verify code. Currently tests the untrusted
certificates for consistency with the verify purpose (which is set
when the X509_STORE_CTX structure is set up) and checks the pathlength.
There is a NO_CHAIN_VERIFY compilation option to keep the old behaviour:
this is because when it is finally working it will reject chains with
invalid extensions whereas every previous version of OpenSSL and SSLeay
made no checks at all.
Trust code: checks the root CA for the relevant trust settings. Trust
settings have an initial value consistent with the verify purpose: e.g.
if the verify purpose is for SSL client use it expects the CA to be
trusted for SSL client use. However the default value can be changed to
permit custom trust settings: one example of this would be to only trust
certificates from a specific "secure" set of CAs.
Also added X509_STORE_CTX_new() and X509_STORE_CTX_free() functions
which should be used for version portability: especially since the
......
......@@ -85,6 +85,7 @@ int MAIN(int argc, char **argv)
X509_LOOKUP *lookup=NULL;
X509_PURPOSE_add_standard();
X509_TRUST_add_standard();
X509V3_add_standard_extensions();
cert_ctx=X509_STORE_new();
if (cert_ctx == NULL) goto end;
......@@ -199,6 +200,7 @@ end:
sk_X509_pop_free(untrusted, X509_free);
X509V3_EXT_cleanup();
X509_PURPOSE_cleanup();
X509_TRUST_cleanup();
EXIT(ret);
}
......
......@@ -99,13 +99,13 @@ int X509_CERT_AUX_print(BIO *out, X509_CERT_AUX *aux, int indent)
int i;
if(!aux) return 1;
if(aux->trust) {
BIO_printf(out, "%*sTrusted for:\n", indent, "");
BIO_printf(out, "%*sTrusted Uses:\n", indent, "");
ASN1_BIT_STRING_name_print(out, aux->trust, tbits, indent + 2);
} else BIO_printf(out, "%*sNo Trust Settings\n", indent + 2, "");
} else BIO_printf(out, "%*sNo Trusted Uses.\n", indent, "");
if(aux->reject) {
BIO_printf(out, "%*sUntrusted for:\n", indent, "");
BIO_printf(out, "%*sRejected Uses:\n", indent, "");
ASN1_BIT_STRING_name_print(out, aux->reject, tbits, indent + 2);
} else BIO_printf(out, "%*sNo Untrusted Settings\n", indent + 2, "");
} else BIO_printf(out, "%*sNo Rejected Uses.\n", indent, "");
if(aux->othertrust) {
first = 1;
BIO_printf(out, "%*sOther Trusted Uses:\n%*s",
......@@ -121,7 +121,7 @@ int X509_CERT_AUX_print(BIO *out, X509_CERT_AUX *aux, int indent)
}
if(aux->otherreject) {
first = 1;
BIO_printf(out, "%*sOther Untrusted Uses:\n%*s",
BIO_printf(out, "%*sOther Rejected Uses:\n%*s",
indent, "", indent + 2, "");
for(i = 0; i < sk_ASN1_OBJECT_num(aux->otherreject); i++) {
if(!first) BIO_puts(out, ", ");
......
......@@ -1098,6 +1098,7 @@ int X509_TRUST_get_trust(X509_TRUST *xp);
#define X509_F_X509_REQ_PRINT 121
#define X509_F_X509_REQ_PRINT_FP 122
#define X509_F_X509_REQ_TO_X509 123
#define X509_F_X509_SET_PURPOSE_AND_TRUST 134
#define X509_F_X509_STORE_ADD_CERT 124
#define X509_F_X509_STORE_ADD_CRL 125
#define X509_F_X509_TO_X509_REQ 126
......@@ -1122,6 +1123,7 @@ int X509_TRUST_get_trust(X509_TRUST *xp);
#define X509_R_UNABLE_TO_GET_CERTS_PUBLIC_KEY 108
#define X509_R_UNKNOWN_KEY_TYPE 117
#define X509_R_UNKNOWN_NID 109
#define X509_R_UNKNOWN_TRUST_ID 120
#define X509_R_UNSUPPORTED_ALGORITHM 111
#define X509_R_WRONG_LOOKUP_TYPE 112
......
......@@ -91,10 +91,11 @@ static ERR_STRING_DATA X509_str_functs[]=
{ERR_PACK(0,X509_F_X509_REQ_PRINT,0), "X509_REQ_print"},
{ERR_PACK(0,X509_F_X509_REQ_PRINT_FP,0), "X509_REQ_print_fp"},
{ERR_PACK(0,X509_F_X509_REQ_TO_X509,0), "X509_REQ_to_X509"},
{ERR_PACK(0,X509_F_X509_SET_PURPOSE_AND_TRUST,0), "X509_set_purpose_and_trust"},
{ERR_PACK(0,X509_F_X509_STORE_ADD_CERT,0), "X509_STORE_add_cert"},
{ERR_PACK(0,X509_F_X509_STORE_ADD_CRL,0), "X509_STORE_add_crl"},
{ERR_PACK(0,X509_F_X509_TO_X509_REQ,0), "X509_to_X509_REQ"},
{ERR_PACK(0,X509_F_X509_TRUST_ADD,0), "X509_TRUST_ADD"},
{ERR_PACK(0,X509_F_X509_TRUST_ADD,0), "X509_TRUST_add"},
{ERR_PACK(0,X509_F_X509_VERIFY_CERT,0), "X509_verify_cert"},
{0,NULL}
};
......@@ -118,6 +119,7 @@ static ERR_STRING_DATA X509_str_reasons[]=
{X509_R_UNABLE_TO_GET_CERTS_PUBLIC_KEY ,"unable to get certs public key"},
{X509_R_UNKNOWN_KEY_TYPE ,"unknown key type"},
{X509_R_UNKNOWN_NID ,"unknown nid"},
{X509_R_UNKNOWN_TRUST_ID ,"unknown trust id"},
{X509_R_UNSUPPORTED_ALGORITHM ,"unsupported algorithm"},
{X509_R_WRONG_LOOKUP_TYPE ,"wrong lookup type"},
{0,NULL}
......
......@@ -126,6 +126,10 @@ const char *X509_verify_cert_error_string(long n)
return ("path length constraint exceeded");
case X509_V_ERR_INVALID_PURPOSE:
return ("unsupported certificate purpose");
case X509_V_ERR_CERT_UNTRUSTED:
return ("certificate not trusted");
case X509_V_ERR_CERT_REJECTED:
return ("certificate rejected");
case X509_V_ERR_APPLICATION_VERIFICATION:
return("application verification failure");
default:
......
......@@ -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)
......
......@@ -263,6 +263,8 @@ struct x509_store_state_st /* X509_STORE_CTX */
#define X509_V_ERR_INVALID_CA 24
#define X509_V_ERR_PATH_LENGTH_EXCEEDED 25
#define X509_V_ERR_INVALID_PURPOSE 26
#define X509_V_ERR_CERT_UNTRUSTED 27
#define X509_V_ERR_CERT_REJECTED 28
/* The application is not happy */
#define X509_V_ERR_APPLICATION_VERIFICATION 50
......@@ -347,8 +349,9 @@ X509 * X509_STORE_CTX_get_current_cert(X509_STORE_CTX *ctx);
STACK_OF(X509) *X509_STORE_CTX_get_chain(X509_STORE_CTX *ctx);
void X509_STORE_CTX_set_cert(X509_STORE_CTX *c,X509 *x);
void X509_STORE_CTX_set_chain(X509_STORE_CTX *c,STACK_OF(X509) *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);
void X509_STORE_CTX_trust_purpose(X509_STORE_CTX *ctx, int purpose);
int X509_set_purpose_and_trust(int id, int *purp, int *trust);
#ifdef __cplusplus
}
......
......@@ -128,10 +128,13 @@ int X509V3_EXT_add_alias(int nid_to, int nid_from)
return 1;
}
static int added_exts = 0;
void X509V3_EXT_cleanup(void)
{
sk_pop_free(ext_list, ext_list_free);
ext_list = NULL;
added_exts = 0;
}
static void ext_list_free(X509V3_EXT_METHOD *ext)
......@@ -147,6 +150,7 @@ extern X509V3_EXT_METHOD v3_crl_num, v3_crl_reason, v3_cpols, v3_crld;
int X509V3_add_standard_extensions(void)
{
if(added_exts) return 1;
X509V3_EXT_add_list(v3_ns_ia5_list);
X509V3_EXT_add_list(v3_alt);
X509V3_EXT_add(&v3_bcons);
......@@ -162,6 +166,7 @@ int X509V3_add_standard_extensions(void)
X509V3_EXT_add(&v3_crl_reason);
X509V3_EXT_add(&v3_cpols);
X509V3_EXT_add(&v3_crld);
added_exts = 1;
return 1;
}
......
......@@ -222,7 +222,7 @@ static void x509v3_cache_extensions(X509 *x)
if(x->ex_flags & EXFLAG_SET) return;
X509_digest(x, EVP_sha1(), x->sha1_hash, NULL);
/* Does subject name match issuer ? */
if(X509_NAME_cmp(X509_get_subject_name(x), X509_get_issuer_name(x)))
if(!X509_NAME_cmp(X509_get_subject_name(x), X509_get_issuer_name(x)))
x->ex_flags |= EXFLAG_SS;
/* V1 should mean no extensions ... */
if(!X509_get_version(x)) x->ex_flags |= EXFLAG_V1;
......
Markdown is supported
0% .
You are about to add 0 people to the discussion. Proceed with caution.
先完成此消息的编辑!
想要评论请 注册