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 xok,X509_STORE_CTX *xctx);
	STACK_OF(X509) *sktmp=NULL;
	if (ctx->cert == NULL)
		{
		X509err(X509_F_X509_VERIFY_CERT,X509_R_NO_CERT_SET_FOR_US_TO_VERIFY);
		return -1;
		}
	cb=ctx->verify_cb;
	if (ctx->chain == NULL)
		{
		if (	((ctx->chain=sk_X509_new_null()) == NULL) ||
			(!sk_X509_push(ctx->chain,ctx->cert)))
			{
			X509err(X509_F_X509_VERIFY_CERT,ERR_R_MALLOC_FAILURE);
			goto end;
			}
		CRYPTO_add(&ctx->cert->references,1,CRYPTO_LOCK_X509);
		ctx->last_untrusted=1;
		}
	if (ctx->untrusted != NULL
	    && (sktmp=sk_X509_dup(ctx->untrusted)) == NULL)
		{
		X509err(X509_F_X509_VERIFY_CERT,ERR_R_MALLOC_FAILURE);
		goto end;
		}
	num=sk_X509_num(ctx->chain);
	x=sk_X509_value(ctx->chain,num-1);
	depth=param->depth;
	for (;;)
		{
		if (depth < num) break;
		xn=X509_get_issuer_name(x);
		if (ctx->check_issued(ctx, x,x)) break;
		if (ctx->untrusted != NULL)
			{
			xtmp=find_issuer(ctx, sktmp,x);
			if (xtmp != NULL)
				{
				if (!sk_X509_push(ctx->chain,xtmp))
					{
					X509err(X509_F_X509_VERIFY_CERT,ERR_R_MALLOC_FAILURE);
					goto end;
					}
				CRYPTO_add(&xtmp->references,1,CRYPTO_LOCK_X509);
				(void)sk_X509_delete_ptr(sktmp,xtmp);
				ctx->last_untrusted++;
				x=xtmp;
				num++;
				continue;
				}
			}
		break;
		}
	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))
		{
		if (sk_X509_num(ctx->chain) == 1)
			{
			ok = ctx->get_issuer(&xtmp, ctx, x);
			if ((ok <= 0) || X509_cmp(x, xtmp))
				{
				ctx->error=X509_V_ERR_DEPTH_ZERO_SELF_SIGNED_CERT;
				ctx->current_cert=x;
				ctx->error_depth=i-1;
				if (ok == 1) X509_free(xtmp);
				bad_chain = 1;
				ok=cb(0,ctx);
				if (!ok) goto end;
				}
			else
				{
				X509_free(x);
				x = xtmp;
				(void)sk_X509_set(ctx->chain, i - 1, x);
				ctx->last_untrusted=0;
				}
			}
		else
			{
			chain_ss=sk_X509_pop(ctx->chain);
			ctx->last_untrusted--;
			num--;
			x=sk_X509_value(ctx->chain,num-1);
			}
		}
	for (;;)
		{
		if (depth < num) break;
		xn=X509_get_issuer_name(x);
		if (ctx->check_issued(ctx,x,x)) break;
		ok = ctx->get_issuer(&xtmp, ctx, x);
		if (ok < 0) return ok;
		if (ok == 0) break;
		x = xtmp;
		if (!sk_X509_push(ctx->chain,x))
			{
			X509_free(xtmp);
			X509err(X509_F_X509_VERIFY_CERT,ERR_R_MALLOC_FAILURE);
			return 0;
			}
		num++;
		}
	xn=X509_get_issuer_name(x);
	if (!ctx->check_issued(ctx,x,x))
		{
		if ((chain_ss == NULL) || !ctx->check_issued(ctx, x, chain_ss))
			{
			if (ctx->last_untrusted >= num)
				ctx->error=X509_V_ERR_UNABLE_TO_GET_ISSUER_CERT_LOCALLY;
			else
				ctx->error=X509_V_ERR_UNABLE_TO_GET_ISSUER_CERT;
			ctx->current_cert=x;
			}
		else
			{
			sk_X509_push(ctx->chain,chain_ss);
			num++;
			ctx->last_untrusted=num;
			ctx->current_cert=chain_ss;
			ctx->error=X509_V_ERR_SELF_SIGNED_CERT_IN_CHAIN;
			chain_ss=NULL;
			}
		ctx->error_depth=num-1;
		bad_chain = 1;
		ok=cb(0,ctx);
		if (!ok) goto end;
		}
	ok = check_chain_extensions(ctx);
	if (!ok) goto end;
	ok = check_name_constraints(ctx);
	if (!ok) goto end;
	if (param->trust > 0) ok = check_trust(ctx);
	if (!ok) goto end;
	X509_get_pubkey_parameters(NULL,ctx->chain);
	ok = ctx->check_revocation(ctx);
	if(!ok) goto end;
	if (ctx->verify != NULL)
		ok=ctx->verify(ctx);
	else
		ok=internal_verify(ctx);
	if(!ok) goto end;
#ifndef OPENSSL_NO_RFC3779
	ok = v3_asid_validate_path(ctx);
	if (!ok) goto end;
	ok = v3_addr_validate_path(ctx);
	if (!ok) goto end;
#endif
	if (!bad_chain && (ctx->param->flags & X509_V_FLAG_POLICY_CHECK))
		ok = ctx->check_policy(ctx);
	if(!ok) goto end;
	if (0)
		{
end:
		X509_get_pubkey_parameters(NULL,ctx->chain);
		}
	if (sktmp != NULL) sk_X509_free(sktmp);
	if (chain_ss != NULL) X509_free(chain_ss);
	return ok;
	}
['int X509_verify_cert(X509_STORE_CTX *ctx)\n\t{\n\tX509 *x,*xtmp,*chain_ss=NULL;\n\tX509_NAME *xn;\n\tint bad_chain = 0;\n\tX509_VERIFY_PARAM *param = ctx->param;\n\tint depth,i,ok=0;\n\tint num;\n\tint (*cb)(int xok,X509_STORE_CTX *xctx);\n\tSTACK_OF(X509) *sktmp=NULL;\n\tif (ctx->cert == NULL)\n\t\t{\n\t\tX509err(X509_F_X509_VERIFY_CERT,X509_R_NO_CERT_SET_FOR_US_TO_VERIFY);\n\t\treturn -1;\n\t\t}\n\tcb=ctx->verify_cb;\n\tif (ctx->chain == NULL)\n\t\t{\n\t\tif (\t((ctx->chain=sk_X509_new_null()) == NULL) ||\n\t\t\t(!sk_X509_push(ctx->chain,ctx->cert)))\n\t\t\t{\n\t\t\tX509err(X509_F_X509_VERIFY_CERT,ERR_R_MALLOC_FAILURE);\n\t\t\tgoto end;\n\t\t\t}\n\t\tCRYPTO_add(&ctx->cert->references,1,CRYPTO_LOCK_X509);\n\t\tctx->last_untrusted=1;\n\t\t}\n\tif (ctx->untrusted != NULL\n\t    && (sktmp=sk_X509_dup(ctx->untrusted)) == NULL)\n\t\t{\n\t\tX509err(X509_F_X509_VERIFY_CERT,ERR_R_MALLOC_FAILURE);\n\t\tgoto end;\n\t\t}\n\tnum=sk_X509_num(ctx->chain);\n\tx=sk_X509_value(ctx->chain,num-1);\n\tdepth=param->depth;\n\tfor (;;)\n\t\t{\n\t\tif (depth < num) break;\n\t\txn=X509_get_issuer_name(x);\n\t\tif (ctx->check_issued(ctx, x,x)) break;\n\t\tif (ctx->untrusted != NULL)\n\t\t\t{\n\t\t\txtmp=find_issuer(ctx, sktmp,x);\n\t\t\tif (xtmp != NULL)\n\t\t\t\t{\n\t\t\t\tif (!sk_X509_push(ctx->chain,xtmp))\n\t\t\t\t\t{\n\t\t\t\t\tX509err(X509_F_X509_VERIFY_CERT,ERR_R_MALLOC_FAILURE);\n\t\t\t\t\tgoto end;\n\t\t\t\t\t}\n\t\t\t\tCRYPTO_add(&xtmp->references,1,CRYPTO_LOCK_X509);\n\t\t\t\t(void)sk_X509_delete_ptr(sktmp,xtmp);\n\t\t\t\tctx->last_untrusted++;\n\t\t\t\tx=xtmp;\n\t\t\t\tnum++;\n\t\t\t\tcontinue;\n\t\t\t\t}\n\t\t\t}\n\t\tbreak;\n\t\t}\n\ti=sk_X509_num(ctx->chain);\n\tx=sk_X509_value(ctx->chain,i-1);\n\txn = X509_get_subject_name(x);\n\tif (ctx->check_issued(ctx, x, x))\n\t\t{\n\t\tif (sk_X509_num(ctx->chain) == 1)\n\t\t\t{\n\t\t\tok = ctx->get_issuer(&xtmp, ctx, x);\n\t\t\tif ((ok <= 0) || X509_cmp(x, xtmp))\n\t\t\t\t{\n\t\t\t\tctx->error=X509_V_ERR_DEPTH_ZERO_SELF_SIGNED_CERT;\n\t\t\t\tctx->current_cert=x;\n\t\t\t\tctx->error_depth=i-1;\n\t\t\t\tif (ok == 1) X509_free(xtmp);\n\t\t\t\tbad_chain = 1;\n\t\t\t\tok=cb(0,ctx);\n\t\t\t\tif (!ok) goto end;\n\t\t\t\t}\n\t\t\telse\n\t\t\t\t{\n\t\t\t\tX509_free(x);\n\t\t\t\tx = xtmp;\n\t\t\t\t(void)sk_X509_set(ctx->chain, i - 1, x);\n\t\t\t\tctx->last_untrusted=0;\n\t\t\t\t}\n\t\t\t}\n\t\telse\n\t\t\t{\n\t\t\tchain_ss=sk_X509_pop(ctx->chain);\n\t\t\tctx->last_untrusted--;\n\t\t\tnum--;\n\t\t\tx=sk_X509_value(ctx->chain,num-1);\n\t\t\t}\n\t\t}\n\tfor (;;)\n\t\t{\n\t\tif (depth < num) break;\n\t\txn=X509_get_issuer_name(x);\n\t\tif (ctx->check_issued(ctx,x,x)) break;\n\t\tok = ctx->get_issuer(&xtmp, ctx, x);\n\t\tif (ok < 0) return ok;\n\t\tif (ok == 0) break;\n\t\tx = xtmp;\n\t\tif (!sk_X509_push(ctx->chain,x))\n\t\t\t{\n\t\t\tX509_free(xtmp);\n\t\t\tX509err(X509_F_X509_VERIFY_CERT,ERR_R_MALLOC_FAILURE);\n\t\t\treturn 0;\n\t\t\t}\n\t\tnum++;\n\t\t}\n\txn=X509_get_issuer_name(x);\n\tif (!ctx->check_issued(ctx,x,x))\n\t\t{\n\t\tif ((chain_ss == NULL) || !ctx->check_issued(ctx, x, chain_ss))\n\t\t\t{\n\t\t\tif (ctx->last_untrusted >= num)\n\t\t\t\tctx->error=X509_V_ERR_UNABLE_TO_GET_ISSUER_CERT_LOCALLY;\n\t\t\telse\n\t\t\t\tctx->error=X509_V_ERR_UNABLE_TO_GET_ISSUER_CERT;\n\t\t\tctx->current_cert=x;\n\t\t\t}\n\t\telse\n\t\t\t{\n\t\t\tsk_X509_push(ctx->chain,chain_ss);\n\t\t\tnum++;\n\t\t\tctx->last_untrusted=num;\n\t\t\tctx->current_cert=chain_ss;\n\t\t\tctx->error=X509_V_ERR_SELF_SIGNED_CERT_IN_CHAIN;\n\t\t\tchain_ss=NULL;\n\t\t\t}\n\t\tctx->error_depth=num-1;\n\t\tbad_chain = 1;\n\t\tok=cb(0,ctx);\n\t\tif (!ok) goto end;\n\t\t}\n\tok = check_chain_extensions(ctx);\n\tif (!ok) goto end;\n\tok = check_name_constraints(ctx);\n\tif (!ok) goto end;\n\tif (param->trust > 0) ok = check_trust(ctx);\n\tif (!ok) goto end;\n\tX509_get_pubkey_parameters(NULL,ctx->chain);\n\tok = ctx->check_revocation(ctx);\n\tif(!ok) goto end;\n\tif (ctx->verify != NULL)\n\t\tok=ctx->verify(ctx);\n\telse\n\t\tok=internal_verify(ctx);\n\tif(!ok) goto end;\n#ifndef OPENSSL_NO_RFC3779\n\tok = v3_asid_validate_path(ctx);\n\tif (!ok) goto end;\n\tok = v3_addr_validate_path(ctx);\n\tif (!ok) goto end;\n#endif\n\tif (!bad_chain && (ctx->param->flags & X509_V_FLAG_POLICY_CHECK))\n\t\tok = ctx->check_policy(ctx);\n\tif(!ok) goto end;\n\tif (0)\n\t\t{\nend:\n\t\tX509_get_pubkey_parameters(NULL,ctx->chain);\n\t\t}\n\tif (sktmp != NULL) sk_X509_free(sktmp);\n\tif (chain_ss != NULL) X509_free(chain_ss);\n\treturn ok;\n\t}', 'int sk_num(const _STACK *st)\n{\n\tif(st == NULL) return -1;\n\treturn st->num;\n}', 'void *sk_value(const _STACK *st, int i)\n{\n\tif(!st || (i < 0) || (i >= st->num)) return NULL;\n\treturn st->data[i];\n}', 'X509_NAME *X509_get_issuer_name(X509 *a)\n\t{\n\treturn(a->cert_info->issuer);\n\t}', 'X509_NAME *X509_get_subject_name(X509 *a)\n\t{\n\treturn(a->cert_info->subject);\n\t}']