1238384Sjkim/* crypto/ts/ts_conf.c */
2238384Sjkim/* Written by Zoltan Glozik (zglozik@stones.com) for the OpenSSL
3238384Sjkim * project 2002.
4238384Sjkim */
5238384Sjkim/* ====================================================================
6238384Sjkim * Copyright (c) 2006 The OpenSSL Project.  All rights reserved.
7238384Sjkim *
8238384Sjkim * Redistribution and use in source and binary forms, with or without
9238384Sjkim * modification, are permitted provided that the following conditions
10238384Sjkim * are met:
11238384Sjkim *
12238384Sjkim * 1. Redistributions of source code must retain the above copyright
13238384Sjkim *    notice, this list of conditions and the following disclaimer.
14238384Sjkim *
15238384Sjkim * 2. Redistributions in binary form must reproduce the above copyright
16238384Sjkim *    notice, this list of conditions and the following disclaimer in
17238384Sjkim *    the documentation and/or other materials provided with the
18238384Sjkim *    distribution.
19238384Sjkim *
20238384Sjkim * 3. All advertising materials mentioning features or use of this
21238384Sjkim *    software must display the following acknowledgment:
22238384Sjkim *    "This product includes software developed by the OpenSSL Project
23238384Sjkim *    for use in the OpenSSL Toolkit. (http://www.OpenSSL.org/)"
24238384Sjkim *
25238384Sjkim * 4. The names "OpenSSL Toolkit" and "OpenSSL Project" must not be used to
26238384Sjkim *    endorse or promote products derived from this software without
27238384Sjkim *    prior written permission. For written permission, please contact
28238384Sjkim *    licensing@OpenSSL.org.
29238384Sjkim *
30238384Sjkim * 5. Products derived from this software may not be called "OpenSSL"
31238384Sjkim *    nor may "OpenSSL" appear in their names without prior written
32238384Sjkim *    permission of the OpenSSL Project.
33238384Sjkim *
34238384Sjkim * 6. Redistributions of any form whatsoever must retain the following
35238384Sjkim *    acknowledgment:
36238384Sjkim *    "This product includes software developed by the OpenSSL Project
37238384Sjkim *    for use in the OpenSSL Toolkit (http://www.OpenSSL.org/)"
38238384Sjkim *
39238384Sjkim * THIS SOFTWARE IS PROVIDED BY THE OpenSSL PROJECT ``AS IS'' AND ANY
40238384Sjkim * EXPRESSED OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
41238384Sjkim * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
42238384Sjkim * PURPOSE ARE DISCLAIMED.  IN NO EVENT SHALL THE OpenSSL PROJECT OR
43238384Sjkim * ITS CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
44238384Sjkim * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
45238384Sjkim * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
46238384Sjkim * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
47238384Sjkim * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT,
48238384Sjkim * STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
49238384Sjkim * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED
50238384Sjkim * OF THE POSSIBILITY OF SUCH DAMAGE.
51238384Sjkim * ====================================================================
52238384Sjkim *
53238384Sjkim * This product includes cryptographic software written by Eric Young
54238384Sjkim * (eay@cryptsoft.com).  This product includes software written by Tim
55238384Sjkim * Hudson (tjh@cryptsoft.com).
56238384Sjkim *
57238384Sjkim */
58238384Sjkim
59238384Sjkim#include <string.h>
60238384Sjkim
61238384Sjkim#include <openssl/crypto.h>
62238384Sjkim#include "cryptlib.h"
63238384Sjkim#include <openssl/pem.h>
64238384Sjkim#ifndef OPENSSL_NO_ENGINE
65238384Sjkim#include <openssl/engine.h>
66238384Sjkim#endif
67238384Sjkim#include <openssl/ts.h>
68238384Sjkim
69238384Sjkim/* Macro definitions for the configuration file. */
70238384Sjkim
71238384Sjkim#define	BASE_SECTION			"tsa"
72238384Sjkim#define	ENV_DEFAULT_TSA			"default_tsa"
73238384Sjkim#define	ENV_SERIAL			"serial"
74238384Sjkim#define ENV_CRYPTO_DEVICE		"crypto_device"
75238384Sjkim#define	ENV_SIGNER_CERT			"signer_cert"
76238384Sjkim#define	ENV_CERTS			"certs"
77238384Sjkim#define	ENV_SIGNER_KEY			"signer_key"
78238384Sjkim#define	ENV_DEFAULT_POLICY		"default_policy"
79238384Sjkim#define	ENV_OTHER_POLICIES		"other_policies"
80238384Sjkim#define	ENV_DIGESTS			"digests"
81238384Sjkim#define	ENV_ACCURACY			"accuracy"
82238384Sjkim#define	ENV_ORDERING			"ordering"
83238384Sjkim#define	ENV_TSA_NAME			"tsa_name"
84238384Sjkim#define	ENV_ESS_CERT_ID_CHAIN		"ess_cert_id_chain"
85238384Sjkim#define	ENV_VALUE_SECS			"secs"
86238384Sjkim#define	ENV_VALUE_MILLISECS		"millisecs"
87238384Sjkim#define	ENV_VALUE_MICROSECS		"microsecs"
88238384Sjkim#define	ENV_CLOCK_PRECISION_DIGITS	"clock_precision_digits"
89238384Sjkim#define	ENV_VALUE_YES			"yes"
90238384Sjkim#define	ENV_VALUE_NO			"no"
91238384Sjkim
92238384Sjkim/* Function definitions for certificate and key loading. */
93238384Sjkim
94238384SjkimX509 *TS_CONF_load_cert(const char *file)
95238384Sjkim	{
96238384Sjkim	BIO *cert = NULL;
97238384Sjkim	X509 *x = NULL;
98238384Sjkim
99238384Sjkim	if ((cert = BIO_new_file(file, "r")) == NULL) goto end;
100238384Sjkim	x = PEM_read_bio_X509_AUX(cert, NULL, NULL, NULL);
101238384Sjkimend:
102238384Sjkim	if (x == NULL)
103238384Sjkim		fprintf(stderr, "unable to load certificate: %s\n", file);
104238384Sjkim	BIO_free(cert);
105238384Sjkim	return x;
106238384Sjkim	}
107238384Sjkim
108238384SjkimSTACK_OF(X509) *TS_CONF_load_certs(const char *file)
109238384Sjkim	{
110238384Sjkim	BIO *certs = NULL;
111238384Sjkim	STACK_OF(X509) *othercerts = NULL;
112238384Sjkim	STACK_OF(X509_INFO) *allcerts = NULL;
113238384Sjkim	int i;
114238384Sjkim
115238384Sjkim	if (!(certs = BIO_new_file(file, "r"))) goto end;
116238384Sjkim
117238384Sjkim	if (!(othercerts = sk_X509_new_null())) goto end;
118238384Sjkim	allcerts = PEM_X509_INFO_read_bio(certs, NULL, NULL, NULL);
119238384Sjkim	for(i = 0; i < sk_X509_INFO_num(allcerts); i++)
120238384Sjkim		{
121238384Sjkim		X509_INFO *xi = sk_X509_INFO_value(allcerts, i);
122238384Sjkim		if (xi->x509)
123238384Sjkim			{
124238384Sjkim			sk_X509_push(othercerts, xi->x509);
125238384Sjkim			xi->x509 = NULL;
126238384Sjkim			}
127238384Sjkim		}
128238384Sjkimend:
129238384Sjkim	if (othercerts == NULL)
130238384Sjkim		fprintf(stderr, "unable to load certificates: %s\n", file);
131238384Sjkim	sk_X509_INFO_pop_free(allcerts, X509_INFO_free);
132238384Sjkim	BIO_free(certs);
133238384Sjkim	return othercerts;
134238384Sjkim	}
135238384Sjkim
136238384SjkimEVP_PKEY *TS_CONF_load_key(const char *file, const char *pass)
137238384Sjkim	{
138238384Sjkim	BIO *key = NULL;
139238384Sjkim	EVP_PKEY *pkey = NULL;
140238384Sjkim
141238384Sjkim	if (!(key = BIO_new_file(file, "r"))) goto end;
142238384Sjkim	pkey = PEM_read_bio_PrivateKey(key, NULL, NULL, (char *) pass);
143238384Sjkim end:
144238384Sjkim	if (pkey == NULL)
145238384Sjkim		fprintf(stderr, "unable to load private key: %s\n", file);
146238384Sjkim	BIO_free(key);
147238384Sjkim	return pkey;
148238384Sjkim	}
149238384Sjkim
150238384Sjkim/* Function definitions for handling configuration options. */
151238384Sjkim
152238384Sjkimstatic void TS_CONF_lookup_fail(const char *name, const char *tag)
153238384Sjkim	{
154238384Sjkim	fprintf(stderr, "variable lookup failed for %s::%s\n", name, tag);
155238384Sjkim	}
156238384Sjkim
157238384Sjkimstatic void TS_CONF_invalid(const char *name, const char *tag)
158238384Sjkim	{
159238384Sjkim	fprintf(stderr, "invalid variable value for %s::%s\n", name, tag);
160238384Sjkim	}
161238384Sjkim
162238384Sjkimconst char *TS_CONF_get_tsa_section(CONF *conf, const char *section)
163238384Sjkim	{
164238384Sjkim	if (!section)
165238384Sjkim		{
166238384Sjkim		section = NCONF_get_string(conf, BASE_SECTION, ENV_DEFAULT_TSA);
167238384Sjkim		if (!section)
168238384Sjkim			TS_CONF_lookup_fail(BASE_SECTION, ENV_DEFAULT_TSA);
169238384Sjkim		}
170238384Sjkim	return section;
171238384Sjkim	}
172238384Sjkim
173238384Sjkimint TS_CONF_set_serial(CONF *conf, const char *section, TS_serial_cb cb,
174238384Sjkim		       TS_RESP_CTX *ctx)
175238384Sjkim	{
176238384Sjkim	int ret = 0;
177238384Sjkim	char *serial = NCONF_get_string(conf, section, ENV_SERIAL);
178238384Sjkim	if (!serial)
179238384Sjkim		{
180238384Sjkim		TS_CONF_lookup_fail(section, ENV_SERIAL);
181238384Sjkim		goto err;
182238384Sjkim		}
183238384Sjkim	TS_RESP_CTX_set_serial_cb(ctx, cb, serial);
184238384Sjkim
185238384Sjkim	ret = 1;
186238384Sjkim err:
187238384Sjkim	return ret;
188238384Sjkim	}
189238384Sjkim
190238384Sjkim#ifndef OPENSSL_NO_ENGINE
191238384Sjkim
192238384Sjkimint TS_CONF_set_crypto_device(CONF *conf, const char *section,
193238384Sjkim			      const char *device)
194238384Sjkim	{
195238384Sjkim	int ret = 0;
196238384Sjkim
197238384Sjkim	if (!device)
198238384Sjkim		device = NCONF_get_string(conf, section,
199238384Sjkim					  ENV_CRYPTO_DEVICE);
200238384Sjkim
201238384Sjkim	if (device && !TS_CONF_set_default_engine(device))
202238384Sjkim		{
203238384Sjkim		TS_CONF_invalid(section, ENV_CRYPTO_DEVICE);
204238384Sjkim		goto err;
205238384Sjkim		}
206238384Sjkim	ret = 1;
207238384Sjkim err:
208238384Sjkim	return ret;
209238384Sjkim	}
210238384Sjkim
211238384Sjkimint TS_CONF_set_default_engine(const char *name)
212238384Sjkim	{
213238384Sjkim	ENGINE *e = NULL;
214238384Sjkim	int ret = 0;
215238384Sjkim
216238384Sjkim	/* Leave the default if builtin specified. */
217238384Sjkim	if (strcmp(name, "builtin") == 0) return 1;
218238384Sjkim
219238384Sjkim	if (!(e = ENGINE_by_id(name))) goto err;
220238384Sjkim	/* Enable the use of the NCipher HSM for forked children. */
221238384Sjkim	if (strcmp(name, "chil") == 0)
222238384Sjkim		ENGINE_ctrl(e, ENGINE_CTRL_CHIL_SET_FORKCHECK, 1, 0, 0);
223238384Sjkim	/* All the operations are going to be carried out by the engine. */
224238384Sjkim	if (!ENGINE_set_default(e, ENGINE_METHOD_ALL)) goto err;
225238384Sjkim	ret = 1;
226238384Sjkim err:
227238384Sjkim	if (!ret)
228238384Sjkim		{
229238384Sjkim		TSerr(TS_F_TS_CONF_SET_DEFAULT_ENGINE,
230238384Sjkim		      TS_R_COULD_NOT_SET_ENGINE);
231238384Sjkim		ERR_add_error_data(2, "engine:", name);
232238384Sjkim		}
233238384Sjkim	if (e) ENGINE_free(e);
234238384Sjkim	return ret;
235238384Sjkim	}
236238384Sjkim
237238384Sjkim#endif
238238384Sjkim
239238384Sjkimint TS_CONF_set_signer_cert(CONF *conf, const char *section,
240238384Sjkim			    const char *cert, TS_RESP_CTX *ctx)
241238384Sjkim	{
242238384Sjkim	int ret = 0;
243238384Sjkim	X509 *cert_obj = NULL;
244238384Sjkim	if (!cert)
245238384Sjkim		cert = NCONF_get_string(conf, section, ENV_SIGNER_CERT);
246238384Sjkim	if (!cert)
247238384Sjkim		{
248238384Sjkim		TS_CONF_lookup_fail(section, ENV_SIGNER_CERT);
249238384Sjkim		goto err;
250238384Sjkim		}
251238384Sjkim	if (!(cert_obj = TS_CONF_load_cert(cert)))
252238384Sjkim		goto err;
253238384Sjkim	if (!TS_RESP_CTX_set_signer_cert(ctx, cert_obj))
254238384Sjkim		goto err;
255238384Sjkim
256238384Sjkim	ret = 1;
257238384Sjkim err:
258238384Sjkim	X509_free(cert_obj);
259238384Sjkim	return ret;
260238384Sjkim	}
261238384Sjkim
262238384Sjkimint TS_CONF_set_certs(CONF *conf, const char *section, const char *certs,
263238384Sjkim		      TS_RESP_CTX *ctx)
264238384Sjkim	{
265238384Sjkim	int ret = 0;
266238384Sjkim	STACK_OF(X509) *certs_obj = NULL;
267238384Sjkim	if (!certs)
268238384Sjkim		certs = NCONF_get_string(conf, section, ENV_CERTS);
269238384Sjkim	/* Certificate chain is optional. */
270238384Sjkim	if (!certs) goto end;
271238384Sjkim	if (!(certs_obj = TS_CONF_load_certs(certs))) goto err;
272238384Sjkim	if (!TS_RESP_CTX_set_certs(ctx, certs_obj)) goto err;
273238384Sjkim end:
274238384Sjkim	ret = 1;
275238384Sjkim err:
276238384Sjkim	sk_X509_pop_free(certs_obj, X509_free);
277238384Sjkim	return ret;
278238384Sjkim	}
279238384Sjkim
280238384Sjkimint TS_CONF_set_signer_key(CONF *conf, const char *section,
281238384Sjkim			   const char *key, const char *pass,
282238384Sjkim			   TS_RESP_CTX *ctx)
283238384Sjkim	{
284238384Sjkim	int ret = 0;
285238384Sjkim	EVP_PKEY *key_obj = NULL;
286238384Sjkim	if (!key)
287238384Sjkim		key = NCONF_get_string(conf, section, ENV_SIGNER_KEY);
288238384Sjkim	if (!key)
289238384Sjkim		{
290238384Sjkim		TS_CONF_lookup_fail(section, ENV_SIGNER_KEY);
291238384Sjkim		goto err;
292238384Sjkim		}
293238384Sjkim	if (!(key_obj = TS_CONF_load_key(key, pass))) goto err;
294238384Sjkim	if (!TS_RESP_CTX_set_signer_key(ctx, key_obj)) goto err;
295238384Sjkim
296238384Sjkim	ret = 1;
297238384Sjkim err:
298238384Sjkim	EVP_PKEY_free(key_obj);
299238384Sjkim	return ret;
300238384Sjkim	}
301238384Sjkim
302238384Sjkimint TS_CONF_set_def_policy(CONF *conf, const char *section,
303238384Sjkim			   const char *policy, TS_RESP_CTX *ctx)
304238384Sjkim	{
305238384Sjkim	int ret = 0;
306238384Sjkim	ASN1_OBJECT *policy_obj = NULL;
307238384Sjkim	if (!policy)
308238384Sjkim		policy = NCONF_get_string(conf, section,
309238384Sjkim					  ENV_DEFAULT_POLICY);
310238384Sjkim	if (!policy)
311238384Sjkim		{
312238384Sjkim		TS_CONF_lookup_fail(section, ENV_DEFAULT_POLICY);
313238384Sjkim		goto err;
314238384Sjkim		}
315238384Sjkim	if (!(policy_obj = OBJ_txt2obj(policy, 0)))
316238384Sjkim		{
317238384Sjkim		TS_CONF_invalid(section, ENV_DEFAULT_POLICY);
318238384Sjkim		goto err;
319238384Sjkim		}
320238384Sjkim	if (!TS_RESP_CTX_set_def_policy(ctx, policy_obj))
321238384Sjkim		goto err;
322238384Sjkim
323238384Sjkim	ret = 1;
324238384Sjkim err:
325238384Sjkim	ASN1_OBJECT_free(policy_obj);
326238384Sjkim	return ret;
327238384Sjkim	}
328238384Sjkim
329238384Sjkimint TS_CONF_set_policies(CONF *conf, const char *section,
330238384Sjkim			 TS_RESP_CTX *ctx)
331238384Sjkim	{
332238384Sjkim	int ret = 0;
333238384Sjkim	int i;
334238384Sjkim	STACK_OF(CONF_VALUE) *list = NULL;
335238384Sjkim	char *policies = NCONF_get_string(conf, section,
336238384Sjkim					  ENV_OTHER_POLICIES);
337238384Sjkim	/* If no other policy is specified, that's fine. */
338238384Sjkim	if (policies && !(list = X509V3_parse_list(policies)))
339238384Sjkim		{
340238384Sjkim		TS_CONF_invalid(section, ENV_OTHER_POLICIES);
341238384Sjkim		goto err;
342238384Sjkim		}
343238384Sjkim	for (i = 0; i < sk_CONF_VALUE_num(list); ++i)
344238384Sjkim		{
345238384Sjkim		CONF_VALUE *val = sk_CONF_VALUE_value(list, i);
346238384Sjkim		const char *extval = val->value ? val->value : val->name;
347238384Sjkim		ASN1_OBJECT *objtmp;
348238384Sjkim		if (!(objtmp = OBJ_txt2obj(extval, 0)))
349238384Sjkim			{
350238384Sjkim			TS_CONF_invalid(section, ENV_OTHER_POLICIES);
351238384Sjkim			goto err;
352238384Sjkim			}
353238384Sjkim		if (!TS_RESP_CTX_add_policy(ctx, objtmp))
354238384Sjkim			goto err;
355238384Sjkim		ASN1_OBJECT_free(objtmp);
356238384Sjkim		}
357238384Sjkim
358238384Sjkim	ret = 1;
359238384Sjkim err:
360238384Sjkim	sk_CONF_VALUE_pop_free(list, X509V3_conf_free);
361238384Sjkim	return ret;
362238384Sjkim	}
363238384Sjkim
364238384Sjkimint TS_CONF_set_digests(CONF *conf, const char *section,
365238384Sjkim			TS_RESP_CTX *ctx)
366238384Sjkim	{
367238384Sjkim	int ret = 0;
368238384Sjkim	int i;
369238384Sjkim	STACK_OF(CONF_VALUE) *list = NULL;
370238384Sjkim	char *digests = NCONF_get_string(conf, section, ENV_DIGESTS);
371238384Sjkim	if (!digests)
372238384Sjkim		{
373238384Sjkim		TS_CONF_lookup_fail(section, ENV_DIGESTS);
374238384Sjkim		goto err;
375238384Sjkim		}
376238384Sjkim	if (!(list = X509V3_parse_list(digests)))
377238384Sjkim		{
378238384Sjkim		TS_CONF_invalid(section, ENV_DIGESTS);
379238384Sjkim		goto err;
380238384Sjkim		}
381238384Sjkim	if (sk_CONF_VALUE_num(list) == 0)
382238384Sjkim		{
383238384Sjkim		TS_CONF_invalid(section, ENV_DIGESTS);
384238384Sjkim		goto err;
385238384Sjkim		}
386238384Sjkim	for (i = 0; i < sk_CONF_VALUE_num(list); ++i)
387238384Sjkim		{
388238384Sjkim		CONF_VALUE *val = sk_CONF_VALUE_value(list, i);
389238384Sjkim		const char *extval = val->value ? val->value : val->name;
390238384Sjkim		const EVP_MD *md;
391238384Sjkim		if (!(md = EVP_get_digestbyname(extval)))
392238384Sjkim			{
393238384Sjkim			TS_CONF_invalid(section, ENV_DIGESTS);
394238384Sjkim			goto err;
395238384Sjkim			}
396238384Sjkim		if (!TS_RESP_CTX_add_md(ctx, md))
397238384Sjkim			goto err;
398238384Sjkim		}
399238384Sjkim
400238384Sjkim	ret = 1;
401238384Sjkim err:
402238384Sjkim	sk_CONF_VALUE_pop_free(list, X509V3_conf_free);
403238384Sjkim	return ret;
404238384Sjkim	}
405238384Sjkim
406238384Sjkimint TS_CONF_set_accuracy(CONF *conf, const char *section, TS_RESP_CTX *ctx)
407238384Sjkim	{
408238384Sjkim	int ret = 0;
409238384Sjkim	int i;
410238384Sjkim	int secs = 0, millis = 0, micros = 0;
411238384Sjkim	STACK_OF(CONF_VALUE) *list = NULL;
412238384Sjkim	char *accuracy = NCONF_get_string(conf, section, ENV_ACCURACY);
413238384Sjkim
414238384Sjkim	if (accuracy && !(list = X509V3_parse_list(accuracy)))
415238384Sjkim		{
416238384Sjkim		TS_CONF_invalid(section, ENV_ACCURACY);
417238384Sjkim		goto err;
418238384Sjkim		}
419238384Sjkim	for (i = 0; i < sk_CONF_VALUE_num(list); ++i)
420238384Sjkim		{
421238384Sjkim		CONF_VALUE *val = sk_CONF_VALUE_value(list, i);
422238384Sjkim		if (strcmp(val->name, ENV_VALUE_SECS) == 0)
423238384Sjkim			{
424238384Sjkim			if (val->value) secs = atoi(val->value);
425238384Sjkim			}
426238384Sjkim		else if (strcmp(val->name, ENV_VALUE_MILLISECS) == 0)
427238384Sjkim			{
428238384Sjkim			if (val->value) millis = atoi(val->value);
429238384Sjkim			}
430238384Sjkim		else if (strcmp(val->name, ENV_VALUE_MICROSECS) == 0)
431238384Sjkim			{
432238384Sjkim			if (val->value) micros = atoi(val->value);
433238384Sjkim			}
434238384Sjkim		else
435238384Sjkim			{
436238384Sjkim			TS_CONF_invalid(section, ENV_ACCURACY);
437238384Sjkim			goto err;
438238384Sjkim			}
439238384Sjkim		}
440238384Sjkim	if (!TS_RESP_CTX_set_accuracy(ctx, secs, millis, micros))
441238384Sjkim		goto err;
442238384Sjkim
443238384Sjkim	ret = 1;
444238384Sjkim err:
445238384Sjkim	sk_CONF_VALUE_pop_free(list, X509V3_conf_free);
446238384Sjkim	return ret;
447238384Sjkim	}
448238384Sjkim
449238384Sjkimint TS_CONF_set_clock_precision_digits(CONF *conf, const char *section,
450238384Sjkim				       TS_RESP_CTX *ctx)
451238384Sjkim	{
452238384Sjkim	int ret = 0;
453238384Sjkim	long digits = 0;
454238384Sjkim
455238384Sjkim	/* If not specified, set the default value to 0, i.e. sec  precision */
456238384Sjkim	if (!NCONF_get_number_e(conf, section, ENV_CLOCK_PRECISION_DIGITS,
457238384Sjkim				&digits))
458238384Sjkim		digits = 0;
459238384Sjkim	if (digits < 0 || digits > TS_MAX_CLOCK_PRECISION_DIGITS)
460238384Sjkim		{
461238384Sjkim		TS_CONF_invalid(section, ENV_CLOCK_PRECISION_DIGITS);
462238384Sjkim		goto err;
463238384Sjkim		}
464238384Sjkim
465238384Sjkim	if (!TS_RESP_CTX_set_clock_precision_digits(ctx, digits))
466238384Sjkim		goto err;
467238384Sjkim
468238384Sjkim	return 1;
469238384Sjkim err:
470238384Sjkim	return ret;
471238384Sjkim	}
472238384Sjkim
473238384Sjkimstatic int TS_CONF_add_flag(CONF *conf, const char *section, const char *field,
474238384Sjkim			    int flag, TS_RESP_CTX *ctx)
475238384Sjkim	{
476238384Sjkim	/* Default is false. */
477238384Sjkim	const char *value = NCONF_get_string(conf, section, field);
478238384Sjkim	if (value)
479238384Sjkim		{
480238384Sjkim		if (strcmp(value, ENV_VALUE_YES) == 0)
481238384Sjkim			TS_RESP_CTX_add_flags(ctx, flag);
482238384Sjkim		else if (strcmp(value, ENV_VALUE_NO) != 0)
483238384Sjkim			{
484238384Sjkim			TS_CONF_invalid(section, field);
485238384Sjkim			return 0;
486238384Sjkim			}
487238384Sjkim		}
488238384Sjkim
489238384Sjkim	return 1;
490238384Sjkim	}
491238384Sjkim
492238384Sjkimint TS_CONF_set_ordering(CONF *conf, const char *section, TS_RESP_CTX *ctx)
493238384Sjkim	{
494238384Sjkim	return TS_CONF_add_flag(conf, section, ENV_ORDERING, TS_ORDERING, ctx);
495238384Sjkim	}
496238384Sjkim
497238384Sjkimint TS_CONF_set_tsa_name(CONF *conf, const char *section, TS_RESP_CTX *ctx)
498238384Sjkim	{
499238384Sjkim	return TS_CONF_add_flag(conf, section, ENV_TSA_NAME, TS_TSA_NAME, ctx);
500238384Sjkim	}
501238384Sjkim
502238384Sjkimint TS_CONF_set_ess_cert_id_chain(CONF *conf, const char *section,
503238384Sjkim				  TS_RESP_CTX *ctx)
504238384Sjkim	{
505238384Sjkim	return TS_CONF_add_flag(conf, section, ENV_ESS_CERT_ID_CHAIN,
506238384Sjkim				TS_ESS_CERT_ID_CHAIN, ctx);
507238384Sjkim	}
508