+ return ok;
+ }
+
+
+/* Given a STACK_OF(X509) find the issuer of cert (if any)
+ */
+
+static X509 *find_issuer(X509_STORE_CTX *ctx, STACK_OF(X509) *sk, X509 *x)
+{
+ int i;
+ X509 *issuer;
+ for (i = 0; i < sk_X509_num(sk); i++)
+ {
+ issuer = sk_X509_value(sk, i);
+ if (ctx->check_issued(ctx, x, issuer))
+ return issuer;
+ }
+ return NULL;
+}
+
+/* Given a possible certificate and issuer check them */
+
+static int check_issued(X509_STORE_CTX *ctx, X509 *x, X509 *issuer)
+{
+ int ret;
+ ret = X509_check_issued(issuer, x);
+ if (ret == X509_V_OK)
+ return 1;
+ /* If we haven't asked for issuer errors don't set ctx */
+ if (!(ctx->flags & X509_V_FLAG_CB_ISSUER_CHECK))
+ return 0;
+
+ ctx->error = ret;
+ ctx->current_cert = x;
+ ctx->current_issuer = issuer;
+ return ctx->verify_cb(0, ctx);
+ return 0;
+}
+
+/* Alternative lookup method: look from a STACK stored in other_ctx */
+
+static int get_issuer_sk(X509 **issuer, X509_STORE_CTX *ctx, X509 *x)
+{
+ *issuer = find_issuer(ctx, ctx->other_ctx, x);
+ if (*issuer)
+ {
+ CRYPTO_add(&(*issuer)->references,1,CRYPTO_LOCK_X509);
+ return 1;
+ }
+ else
+ return 0;
+}
+
+
+/* Check a certificate chains extensions for consistency
+ * with the supplied purpose
+ */
+
+static int check_chain_purpose(X509_STORE_CTX *ctx)
+{
+#ifdef OPENSSL_NO_CHAIN_VERIFY
+ return 1;
+#else
+ int i, ok=0;
+ X509 *x;
+ int (*cb)();
+ cb=ctx->verify_cb;
+ /* Check all untrusted certificates */
+ for (i = 0; i < ctx->last_untrusted; i++)
+ {
+ x = sk_X509_value(ctx->chain, i);
+ if (!X509_check_purpose(x, ctx->purpose, i))
+ {
+ if (i)
+ ctx->error = X509_V_ERR_INVALID_CA;
+ else
+ ctx->error = X509_V_ERR_INVALID_PURPOSE;
+ ctx->error_depth = i;
+ ctx->current_cert = x;
+ ok=cb(0,ctx);
+ if (!ok) goto end;
+ }
+ /* Check pathlen */
+ if ((i > 1) && (x->ex_pathlen != -1)
+ && (i > (x->ex_pathlen + 1)))
+ {
+ ctx->error = X509_V_ERR_PATH_LENGTH_EXCEEDED;
+ ctx->error_depth = i;
+ ctx->current_cert = x;
+ ok=cb(0,ctx);
+ if (!ok) goto end;
+ }
+ }
+ ok = 1;
+ end:
+ return ok;
+#endif
+}
+
+static int check_trust(X509_STORE_CTX *ctx)
+{
+#ifdef OPENSSL_NO_CHAIN_VERIFY
+ return 1;
+#else
+ int i, ok;
+ X509 *x;
+ int (*cb)();
+ cb=ctx->verify_cb;
+/* 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, 0);
+ if (ok == X509_TRUST_TRUSTED)
+ return 1;
+ 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
+}
+
+static int check_revocation(X509_STORE_CTX *ctx)
+ {
+ int i, last, ok;
+ if (!(ctx->flags & X509_V_FLAG_CRL_CHECK))
+ return 1;
+ if (ctx->flags & X509_V_FLAG_CRL_CHECK_ALL)
+ last = 0;
+ else
+ last = sk_X509_num(ctx->chain) - 1;
+ for(i = 0; i <= last; i++)
+ {
+ ctx->error_depth = i;
+ ok = check_cert(ctx);
+ if (!ok) return ok;
+ }
+ return 1;
+ }
+
+static int check_cert(X509_STORE_CTX *ctx)
+ {
+ X509_CRL *crl = NULL;
+ X509 *x;
+ int ok, cnum;
+ cnum = ctx->error_depth;
+ x = sk_X509_value(ctx->chain, cnum);
+ ctx->current_cert = x;
+ /* Try to retrieve relevant CRL */
+ ok = ctx->get_crl(ctx, &crl, x);
+ /* If error looking up CRL, nothing we can do except
+ * notify callback
+ */
+ if(!ok)
+ {
+ ctx->error = X509_V_ERR_UNABLE_TO_GET_CRL;
+ ok = ctx->verify_cb(0, ctx);
+ goto err;
+ }
+ ctx->current_crl = crl;
+ ok = ctx->check_crl(ctx, crl);
+ if (!ok) goto err;
+ ok = ctx->cert_crl(ctx, crl, x);
+ err:
+ ctx->current_crl = NULL;
+ X509_CRL_free(crl);
+ return ok;
+