static int check_cert(X509_STORE_CTX *ctx);
static int check_policy(X509_STORE_CTX *ctx);
static int internal_verify(X509_STORE_CTX *ctx);
-const char *X509_version="X.509" OPENSSL_VERSION_PTEXT;
+const char X509_version[]="X.509" OPENSSL_VERSION_PTEXT;
static int null_callback(int ok, X509_STORE_CTX *e)
int X509_verify_cert(X509_STORE_CTX *ctx)
{
X509 *x,*xtmp,*chain_ss=NULL;
- X509_NAME *xn;
int bad_chain = 0;
X509_VERIFY_PARAM *param = ctx->param;
int depth,i,ok=0;
int num;
- int (*cb)();
+ int (*cb)(int xok,X509_STORE_CTX *xctx);
STACK_OF(X509) *sktmp=NULL;
if (ctx->cert == NULL)
{
*/
/* If we are self signed, we break */
- xn=X509_get_issuer_name(x);
if (ctx->check_issued(ctx, x,x)) break;
/* If we were passed a cert chain, use it first */
goto end;
}
CRYPTO_add(&xtmp->references,1,CRYPTO_LOCK_X509);
- sk_X509_delete_ptr(sktmp,xtmp);
+ (void)sk_X509_delete_ptr(sktmp,xtmp);
ctx->last_untrusted++;
x=xtmp;
num++;
i=sk_X509_num(ctx->chain);
x=sk_X509_value(ctx->chain,i-1);
- xn = X509_get_subject_name(x);
if (ctx->check_issued(ctx, x, x))
{
/* we have a self signed certificate */
*/
X509_free(x);
x = xtmp;
- sk_X509_set(ctx->chain, i - 1, x);
+ (void)sk_X509_set(ctx->chain, i - 1, x);
ctx->last_untrusted=0;
}
}
if (depth < num) break;
/* If we are self signed, we break */
- xn=X509_get_issuer_name(x);
if (ctx->check_issued(ctx,x,x)) break;
ok = ctx->get_issuer(&xtmp, ctx, x);
}
/* we now have our chain, lets check it... */
- xn=X509_get_issuer_name(x);
/* Is last certificate looked up self signed? */
if (!ctx->check_issued(ctx,x,x))
ok=internal_verify(ctx);
if(!ok) goto end;
+#ifndef OPENSSL_NO_RFC3779
+ /* RFC 3779 path validation, now that CRL check has been done */
+ ok = v3_asid_validate_path(ctx);
+ if (!ok) goto end;
+ ok = v3_addr_validate_path(ctx);
+ if (!ok) goto end;
+#endif
+
/* If we get this far evaluate policies */
if (!bad_chain && (ctx->param->flags & X509_V_FLAG_POLICY_CHECK))
ok = ctx->check_policy(ctx);
#ifdef OPENSSL_NO_CHAIN_VERIFY
return 1;
#else
- int i, ok=0, must_be_ca;
+ int i, ok=0, must_be_ca, plen = 0;
X509 *x;
- int (*cb)();
+ int (*cb)(int xok,X509_STORE_CTX *xctx);
int proxy_path_length = 0;
+ int allow_proxy_certs =
+ !!(ctx->param->flags & X509_V_FLAG_ALLOW_PROXY_CERTS);
cb=ctx->verify_cb;
- /* must_be_ca can have 1 of 3 values:
- -1: we accept both CA and non-CA certificates, to allow direct
- use of self-signed certificates (which are marked as CA).
- 0: we only accept non-CA certificates. This is currently not
- used, but the possibility is present for future extensions.
- 1: we only accept CA certificates. This is currently used for
- all certificates in the chain except the leaf certificate.
- */
+ /*-
+ * must_be_ca can have 1 of 3 values:
+ * -1: we accept both CA and non-CA certificates, to allow direct
+ * use of self-signed certificates (which are marked as CA).
+ * 0: we only accept non-CA certificates. This is currently not
+ * used, but the possibility is present for future extensions.
+ * 1: we only accept CA certificates. This is currently used for
+ * all certificates in the chain except the leaf certificate.
+ */
must_be_ca = -1;
+
+ /* A hack to keep people who don't want to modify their software
+ happy */
+ if (getenv("OPENSSL_ALLOW_PROXY_CERTS"))
+ allow_proxy_certs = 1;
+
/* Check all untrusted certificates */
for (i = 0; i < ctx->last_untrusted; i++)
{
ok=cb(0,ctx);
if (!ok) goto end;
}
+ if (!allow_proxy_certs && (x->ex_flags & EXFLAG_PROXY))
+ {
+ ctx->error = X509_V_ERR_PROXY_CERTIFICATES_NOT_ALLOWED;
+ ctx->error_depth = i;
+ ctx->current_cert = x;
+ ok=cb(0,ctx);
+ if (!ok) goto end;
+ }
ret = X509_check_ca(x);
switch(must_be_ca)
{
if (!ok) goto end;
}
}
- /* Check pathlen */
- if ((i > 1) && (x->ex_pathlen != -1)
- && (i > (x->ex_pathlen + proxy_path_length + 1)))
+ /* Check pathlen if not self issued */
+ if ((i > 1) && !(x->ex_flags & EXFLAG_SI)
+ && (x->ex_pathlen != -1)
+ && (plen > (x->ex_pathlen + proxy_path_length + 1)))
{
ctx->error = X509_V_ERR_PATH_LENGTH_EXCEEDED;
ctx->error_depth = i;
ok=cb(0,ctx);
if (!ok) goto end;
}
+ /* Increment path length if not self issued */
+ if (!(x->ex_flags & EXFLAG_SI))
+ plen++;
/* If this certificate is a proxy certificate, the next
certificate must be another proxy certificate or a EE
certificate. If not, the next certificate must be a
#else
int i, ok;
X509 *x;
- int (*cb)();
+ 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;
}
}
- if (!check_crl_time(ctx, crl, 1))
+ ok = check_crl_time(ctx, crl, 1);
+ if (!ok)
goto err;
ok = 1;
ctx->param->policies, ctx->param->flags);
if (ret == 0)
{
- X509err(X509_F_X509_VERIFY_CERT,ERR_R_MALLOC_FAILURE);
+ X509err(X509_F_CHECK_POLICY,ERR_R_MALLOC_FAILURE);
return 0;
}
/* Invalid or inconsistent extensions */
int ok=0,n;
X509 *xs,*xi;
EVP_PKEY *pkey=NULL;
- int (*cb)();
+ int (*cb)(int xok,X509_STORE_CTX *xctx);
cb=ctx->verify_cb;
while (n >= 0)
{
ctx->error_depth=n;
- if (!xs->valid)
+
+ /* Skip signature check for self signed certificates unless
+ * explicitly asked for. It doesn't add any security and
+ * just wastes time.
+ */
+ if (!xs->valid && (xs != xi || (ctx->param->flags & X509_V_FLAG_CHECK_SS_SIGNATURE)))
{
if ((pkey=X509_get_pubkey(xi)) == NULL)
{
if (!ok) goto end;
}
else if (X509_verify(xs,pkey) <= 0)
- /* XXX For the final trusted self-signed cert,
- * this is a waste of time. That check should
- * optional so that e.g. 'openssl x509' can be
- * used to detect invalid self-signatures, but
- * we don't verify again and again in SSL
- * handshakes and the like once the cert has
- * been declared trusted. */
{
ctx->error=X509_V_ERR_CERT_SIGNATURE_FAILURE;
ctx->current_cert=xs;
xs->valid = 1;
- if (!check_cert_time(ctx, xs))
+ ok = check_cert_time(ctx, xs);
+ if (!ok)
goto end;
/* The last error (if any) is still in the error value */
offset=0;
else
{
- if ((*str != '+') && (str[5] != '-'))
+ if ((*str != '+') && (*str != '-'))
return 0;
offset=((str[1]-'0')*10+(str[2]-'0'))*60;
offset+=(str[3]-'0')*10+(str[4]-'0');
atm.length=sizeof(buff2);
atm.data=(unsigned char *)buff2;
- if (X509_time_adj(&atm,-offset*60, cmp_time) == NULL)
+ if (X509_time_adj(&atm, offset*60, cmp_time) == NULL)
return 0;
if (ctm->type == V_ASN1_UTCTIME)
if (store)
ret = X509_VERIFY_PARAM_inherit(ctx->param, store->param);
else
- ctx->param->flags |= X509_VP_FLAG_DEFAULT|X509_VP_FLAG_ONCE;
+ ctx->param->inh_flags |= X509_VP_FLAG_DEFAULT|X509_VP_FLAG_ONCE;
if (store)
{
void X509_STORE_CTX_cleanup(X509_STORE_CTX *ctx)
{
if (ctx->cleanup) ctx->cleanup(ctx);
- X509_VERIFY_PARAM_free(ctx->param);
- if (ctx->tree)
+ if (ctx->param != NULL)
+ {
+ X509_VERIFY_PARAM_free(ctx->param);
+ ctx->param=NULL;
+ }
+ if (ctx->tree != NULL)
+ {
X509_policy_tree_free(ctx->tree);
+ ctx->tree=NULL;
+ }
if (ctx->chain != NULL)
{
sk_X509_pop_free(ctx->chain,X509_free);