ts.c 29.1 KB
Newer Older
	
	/* Clean up. */
	BIO_free_all(in_bio);
	PKCS7_free(token);
	TS_RESP_free(response);
	TS_VERIFY_CTX_free(verify_ctx);
	return ret;
	}

static TS_VERIFY_CTX *create_verify_ctx(char *data, char *digest, 
					char *queryfile, 
					char *ca_path, char *ca_file,
					char *untrusted)
	{
	TS_VERIFY_CTX *ctx = NULL;
	BIO *input = NULL;
	TS_REQ *request = NULL;
	int ret = 0;

	if (data != NULL || digest != NULL)
		{
		if (!(ctx = TS_VERIFY_CTX_new())) goto err;
		ctx->flags = TS_VFY_VERSION | TS_VFY_SIGNER;
		if (data != NULL)
			{
			ctx->flags |= TS_VFY_DATA;
			if (!(ctx->data = BIO_new_file(data, "rb"))) goto err;
			}
		else if (digest != NULL)
			{
			long imprint_len;
			ctx->flags |= TS_VFY_IMPRINT;
			if (!(ctx->imprint = string_to_hex(digest,
							   &imprint_len)))
				{
				BIO_printf(bio_err, "invalid digest string\n");
				goto err;
				}
			ctx->imprint_len = imprint_len;
			}
		
		}
	else if (queryfile != NULL)
		{
		/* The request has just to be read, decoded and converted to
		   a verify context object. */
		if (!(input = BIO_new_file(queryfile, "rb"))) goto err;
		if (!(request = d2i_TS_REQ_bio(input, NULL))) goto err;
		if (!(ctx = TS_REQ_to_TS_VERIFY_CTX(request, NULL))) goto err;
		}
	else
		return NULL;

	/* Add the signature verification flag and arguments. */
	ctx->flags |= TS_VFY_SIGNATURE;

	/* Initialising the X509_STORE object. */
	if (!(ctx->store = create_cert_store(ca_path, ca_file))) goto err;

	/* Loading untrusted certificates. */
	if (untrusted && !(ctx->certs = TS_CONF_load_certs(untrusted))) 
		goto err;

	ret = 1;
 err:
	if (!ret)
		{
		TS_VERIFY_CTX_free(ctx);
		ctx = NULL;
		}
	BIO_free_all(input);
	TS_REQ_free(request);
	return ctx;
	}

static X509_STORE *create_cert_store(char *ca_path, char *ca_file)
	{
	X509_STORE *cert_ctx = NULL;
	X509_LOOKUP *lookup = NULL;
	int i;

	/* Creating the X509_STORE object. */
	cert_ctx = X509_STORE_new();

	/* Setting the callback for certificate chain verification. */
	X509_STORE_set_verify_cb(cert_ctx, verify_cb);

	/* Adding a trusted certificate directory source. */
	if (ca_path)
		{
		lookup = X509_STORE_add_lookup(cert_ctx,
					       X509_LOOKUP_hash_dir());
		if (lookup == NULL)
			{
			BIO_printf(bio_err, "memory allocation failure\n");
			goto err;
			}
		i = X509_LOOKUP_add_dir(lookup, ca_path, X509_FILETYPE_PEM);
		if (!i)
			{
			BIO_printf(bio_err, "Error loading directory %s\n",
				   ca_path);
			goto err;
			}
		}

	/* Adding a trusted certificate file source. */
	if (ca_file)
		{
		lookup = X509_STORE_add_lookup(cert_ctx, X509_LOOKUP_file());
		if (lookup == NULL)
			{
			BIO_printf(bio_err, "memory allocation failure\n");
			goto err;
			}
		i = X509_LOOKUP_load_file(lookup, ca_file, X509_FILETYPE_PEM);
		if (!i)
			{
			BIO_printf(bio_err, "Error loading file %s\n", ca_file);
			goto err;
			}
		}

	return cert_ctx;
 err:
	X509_STORE_free(cert_ctx);
	return NULL;
	}

static int MS_CALLBACK verify_cb(int ok, X509_STORE_CTX *ctx)
	{
	/*
	char buf[256];

	if (!ok)
		{
		X509_NAME_oneline(X509_get_subject_name(ctx->current_cert),
				  buf, sizeof(buf));
		printf("%s\n", buf);
		printf("error %d at %d depth lookup: %s\n",
		       ctx->error, ctx->error_depth,
			X509_verify_cert_error_string(ctx->error));
		}
	*/

	return ok;
	}