summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorDaiki Ueno <ueno@gnu.org>2022-01-03 10:30:34 +0100
committerDaiki Ueno <ueno@gnu.org>2022-01-15 09:25:55 +0100
commitb8c1a61860e58e40dd57ef182e1d41a832aa52fd (patch)
tree36c1759781e369712e12a84dfae237e7972938a1
parent0da805e6d3b2b148f9689b3229ddbbf3f4cedb88 (diff)
downloadgnutls-b8c1a61860e58e40dd57ef182e1d41a832aa52fd.tar.gz
src: replace autoopts/libopts with minimal config parser
This replaces configuration file parsing code previously provided by <autoopts/options.h>, with a minimal compatible implementation. Signed-off-by: Daiki Ueno <ueno@gnu.org>
-rw-r--r--.gitignore9
-rw-r--r--src/Makefile.am34
-rw-r--r--src/certtool-cfg.c204
-rw-r--r--src/cfg.c464
-rw-r--r--src/cfg.h33
-rw-r--r--tests/Makefile.am30
-rw-r--r--tests/cfg-test.sh73
-rw-r--r--tests/fixtures/templates/arb-extensions.tmpl.exp17
-rw-r--r--tests/fixtures/templates/crit-extensions.tmpl.exp10
-rw-r--r--tests/fixtures/templates/inhibit-anypolicy.tmpl.exp25
-rw-r--r--tests/fixtures/templates/simple-policy.tmpl.exp9
-rw-r--r--tests/fixtures/templates/template-crq.tmpl.exp3
-rw-r--r--tests/fixtures/templates/template-date.tmpl.exp23
-rw-r--r--tests/fixtures/templates/template-dates-after2038.tmpl.exp23
-rw-r--r--tests/fixtures/templates/template-dn-err.tmpl.exp14
-rw-r--r--tests/fixtures/templates/template-dn.tmpl.exp14
-rw-r--r--tests/fixtures/templates/template-generalized.tmpl.exp23
-rw-r--r--tests/fixtures/templates/template-krb5name.tmpl.exp16
-rw-r--r--tests/fixtures/templates/template-long-dns.tmpl.exp14
-rw-r--r--tests/fixtures/templates/template-long-serial.tmpl.exp24
-rw-r--r--tests/fixtures/templates/template-nc.tmpl.exp27
-rw-r--r--tests/fixtures/templates/template-no-ca-explicit.tmpl.exp11
-rw-r--r--tests/fixtures/templates/template-no-ca-honor.tmpl.exp3
-rw-r--r--tests/fixtures/templates/template-no-ca.tmpl.exp2
-rw-r--r--tests/fixtures/templates/template-othername-xmpp.tmpl.exp15
-rw-r--r--tests/fixtures/templates/template-othername.tmpl.exp18
-rw-r--r--tests/fixtures/templates/template-overflow.tmpl.exp22
-rw-r--r--tests/fixtures/templates/template-overflow2.tmpl.exp22
-rw-r--r--tests/fixtures/templates/template-test.tmpl.exp24
-rw-r--r--tests/fixtures/templates/template-tlsfeature-crq.tmpl.exp6
-rw-r--r--tests/fixtures/templates/template-tlsfeature.tmpl.exp25
-rw-r--r--tests/fixtures/templates/template-unique.tmpl.exp16
-rw-r--r--tests/fixtures/templates/template-utf8.tmpl.exp14
33 files changed, 1138 insertions, 129 deletions
diff --git a/.gitignore b/.gitignore
index 43a5a00747..34142c91fc 100644
--- a/.gitignore
+++ b/.gitignore
@@ -279,12 +279,7 @@ src/benchmark-tls
src/certtool
src/certtool-options.c
src/certtool-options.h
-src/cfg/Makefile
-src/cfg/Makefile.in
-src/cfg/platon/Makefile
-src/cfg/platon/Makefile.in
-src/cfg/platon/str/Makefile
-src/cfg/platon/str/Makefile.in
+src/dumpcfg
src/gnutls-cli-options.c
src/gnutls-cli-options.h
src/gnutls-cli-debug-options.c
@@ -300,7 +295,7 @@ src/gnutls-cli
src/gnutls-cli-debug
src/gnutls-serv
src/invoke-*.menu
-src/libcfg.la
+src/libcerttool-cfg.la
src/libcmd-certtool.la
src/libcmd-cli-debug.la
src/libcmd-cli.la
diff --git a/src/Makefile.am b/src/Makefile.am
index ff9c09dd04..d867b02013 100644
--- a/src/Makefile.am
+++ b/src/Makefile.am
@@ -163,9 +163,8 @@ certtool_LDADD = ../lib/libgnutls.la
certtool_LDADD += libcmd-certtool.la ../gl/libgnu.la gl/libgnu_gpl.la
noinst_LTLIBRARIES += libcmd-certtool.la
-libcmd_certtool_la_SOURCES = certtool-options.c certtool-options.h \
- certtool-cfg.h certtool-cfg.c
-libcmd_certtool_la_LIBADD = ../lib/libgnutls.la gl/libgnu_gpl.la ../gl/libgnu.la
+libcmd_certtool_la_SOURCES = certtool-options.c certtool-options.h
+libcmd_certtool_la_LIBADD = libcerttool-cfg.la ../lib/libgnutls.la gl/libgnu_gpl.la ../gl/libgnu.la
libcmd_certtool_la_LIBADD += $(COMMON_LIBS)
libcmd_certtool_la_LIBADD += $(LTLIBREADLINE) gl/libgnu_gpl.la
libcmd_certtool_la_LIBADD += $(INET_PTON_LIB) $(LIB_CLOCK_GETTIME)
@@ -179,9 +178,8 @@ danetool_LDADD += ../libdane/libgnutls-dane.la
endif
noinst_LTLIBRARIES += libcmd-danetool.la
-libcmd_danetool_la_SOURCES = danetool-options.c danetool-options.h \
- certtool-cfg.h certtool-cfg.c
-libcmd_danetool_la_LIBADD = ../lib/libgnutls.la gl/libgnu_gpl.la ../gl/libgnu.la
+libcmd_danetool_la_SOURCES = danetool-options.c danetool-options.h
+libcmd_danetool_la_LIBADD = libcerttool-cfg.la ../lib/libgnutls.la gl/libgnu_gpl.la ../gl/libgnu.la
libcmd_danetool_la_LIBADD += $(COMMON_LIBS)
libcmd_danetool_la_LIBADD += $(LTLIBREADLINE)
libcmd_danetool_la_LIBADD += $(INET_PTON_LIB) $(LIB_CLOCK_GETTIME)
@@ -198,9 +196,8 @@ p11tool_LDADD += libcmd-p11tool.la ../gl/libgnu.la gl/libgnu_gpl.la
p11tool_LDADD += $(COMMON_LIBS)
noinst_LTLIBRARIES += libcmd-p11tool.la
-libcmd_p11tool_la_SOURCES = p11tool-options.c p11tool-options.h \
- certtool-cfg.h certtool-cfg.c
-libcmd_p11tool_la_LIBADD = ../lib/libgnutls.la gl/libgnu_gpl.la ../gl/libgnu.la
+libcmd_p11tool_la_SOURCES = p11tool-options.c p11tool-options.h
+libcmd_p11tool_la_LIBADD = libcerttool-cfg.la ../lib/libgnutls.la gl/libgnu_gpl.la ../gl/libgnu.la
libcmd_p11tool_la_LIBADD += $(LTLIBREADLINE) $(INET_PTON_LIB) $(LIB_CLOCK_GETTIME)
endif # ENABLE_PKCS11
@@ -213,9 +210,8 @@ tpmtool_LDADD += libcmd-tpmtool.la ../gl/libgnu.la gl/libgnu_gpl.la
tpmtool_LDADD += $(COMMON_LIBS)
noinst_LTLIBRARIES += libcmd-tpmtool.la
-libcmd_tpmtool_la_SOURCES = tpmtool-options.c tpmtool-options.h \
- certtool-cfg.h certtool-cfg.c
-libcmd_tpmtool_la_LIBADD = ../lib/libgnutls.la gl/libgnu_gpl.la ../gl/libgnu.la
+libcmd_tpmtool_la_SOURCES = tpmtool-options.c tpmtool-options.h
+libcmd_tpmtool_la_LIBADD = libcerttool-cfg.la ../lib/libgnutls.la gl/libgnu_gpl.la ../gl/libgnu.la
libcmd_tpmtool_la_LIBADD += $(LTLIBREADLINE) $(INET_PTON_LIB) $(LIB_CLOCK_GETTIME)
endif # ENABLE_TROUSERS
@@ -226,11 +222,19 @@ systemkey_LDADD += libcmd-systemkey.la ../gl/libgnu.la gl/libgnu_gpl.la
systemkey_LDADD += $(COMMON_LIBS)
noinst_LTLIBRARIES += libcmd-systemkey.la
-libcmd_systemkey_la_SOURCES = systemkey-tool-options.c systemkey-tool-options.h \
- certtool-cfg.h certtool-cfg.c
-libcmd_systemkey_la_LIBADD = ../lib/libgnutls.la gl/libgnu_gpl.la ../gl/libgnu.la
+libcmd_systemkey_la_SOURCES = systemkey-tool-options.c systemkey-tool-options.h
+libcmd_systemkey_la_LIBADD = libcerttool-cfg.la ../lib/libgnutls.la gl/libgnu_gpl.la ../gl/libgnu.la
libcmd_systemkey_la_LIBADD += $(LTLIBREADLINE) $(INET_PTON_LIB) $(LIB_CLOCK_GETTIME)
+noinst_LTLIBRARIES += libcerttool-cfg.la
+libcerttool_cfg_la_SOURCES = certtool-cfg.h certtool-cfg.c cfg.c cfg.h
+libcerttool_cfg_la_LIBADD = ../gl/libgnu.la gl/libgnu_gpl.la
+
+noinst_PROGRAMS = dumpcfg
+dumpcfg_SOURCES = cfg.c cfg.h
+dumpcfg_CFLAGS = -DTEST=1
+dumpcfg_LDADD = ../gl/libgnu.la gl/libgnu_gpl.la
+
SUFFIXES = .stamp .json
OPTIONS_STAMP: $(srcdir)/gen-getopt.py
diff --git a/src/certtool-cfg.c b/src/certtool-cfg.c
index 8c658c8667..a8a135a4a4 100644
--- a/src/certtool-cfg.c
+++ b/src/certtool-cfg.c
@@ -34,7 +34,7 @@
#include <time.h>
#include <timespec.h>
#include <parse-datetime.h>
-#include <autoopts/options.h>
+#include "cfg.h"
#include <intprops.h>
#include <gnutls/crypto.h>
#include <libtasn1.h>
@@ -244,29 +244,29 @@ void cfg_init(void)
cfg.skip_certs = -1;
}
-#define READ_MULTI_LINE(name, s_name) \
- val = optionGetValue(pov, name); \
- if (val != NULL && val->valType == OPARG_TYPE_STRING) \
+#define READ_MULTI_LINE(k_name, s_name) \
+ val = cfg_next(pov, k_name); \
+ if (val != NULL) \
{ \
if (s_name == NULL) { \
i = 0; \
s_name = malloc(sizeof(char*)*MAX_ENTRIES); \
CHECK_MALLOC(s_name); \
do { \
- if (val && strcmp(val->pzName, name)!=0) \
+ if (val && strcmp(val->name, k_name)!=0) \
continue; \
- s_name[i] = strdup(val->v.strVal); \
+ s_name[i] = strdup(val->value); \
i++; \
if (i>=MAX_ENTRIES) \
break; \
- } while((val = optionNextValue(pov, val)) != NULL); \
+ } while((val = cfg_next(val + 1, val->name)) != NULL); \
s_name[i] = NULL; \
} \
}
-#define READ_MULTI_LINE_TOKENIZED(name, s_name) \
- val = optionGetValue(pov, name); \
- if (val != NULL && val->valType == OPARG_TYPE_STRING) \
+#define READ_MULTI_LINE_TOKENIZED(k_name, s_name) \
+ val = cfg_next(pov, k_name); \
+ if (val != NULL) \
{ \
char *str; \
char *p; \
@@ -275,12 +275,12 @@ void cfg_init(void)
s_name = malloc(sizeof(char*)*MAX_ENTRIES); \
CHECK_MALLOC(s_name); \
do { \
- if (val && strcmp(val->pzName, name)!=0) \
+ if (val && strcmp(val->name, k_name)!=0) \
continue; \
- str = strdup(val->v.strVal); \
+ str = strdup(val->value); \
CHECK_MALLOC(str); \
if ((p=strchr(str, ' ')) == NULL && (p=strchr(str, '\t')) == NULL) { \
- fprintf(stderr, "Error parsing %s\n", name); \
+ fprintf(stderr, "Error parsing %s\n", k_name); \
exit(1); \
} \
p[0] = 0; \
@@ -288,7 +288,7 @@ void cfg_init(void)
s_name[i] = strdup(str); \
while(*p==' ' || *p == '\t') p++; \
if (p[0] == 0) { \
- fprintf(stderr, "Error (2) parsing %s\n", name); \
+ fprintf(stderr, "Error (2) parsing %s\n", k_name); \
exit(1); \
} \
s_name[i+1] = strdup(p); \
@@ -296,13 +296,13 @@ void cfg_init(void)
free(str); \
if (i>=MAX_ENTRIES) \
break; \
- } while((val = optionNextValue(pov, val)) != NULL); \
+ } while((val = cfg_next(val + 1, val->name)) != NULL); \
s_name[i] = NULL; \
} \
}
#define READ_BOOLEAN(name, s_name) \
- val = optionGetValue(pov, name); \
+ val = cfg_next(pov, name); \
if (val != NULL) \
{ \
s_name = 1; \
@@ -310,13 +310,10 @@ void cfg_init(void)
/* READ_NUMERIC only returns a long */
#define READ_NUMERIC(name, s_name) \
- val = optionGetValue(pov, name); \
+ val = cfg_next(pov, name); \
if (val != NULL) \
{ \
- if (val->valType == OPARG_TYPE_NUMERIC) \
- s_name = val->v.longVal; \
- else if (val->valType == OPARG_TYPE_STRING) \
- s_name = strtol(val->v.strVal, NULL, 10); \
+ s_name = strtol(val->value, NULL, 10); \
}
#define HEX_DECODE(hex, output, output_size) \
@@ -345,17 +342,17 @@ void cfg_init(void)
}
-static int handle_option(const tOptionValue* val)
+static int handle_option(cfg_option_t val)
{
-unsigned j;
-unsigned len, cmp;
+ unsigned j;
+ unsigned len, cmp;
for (j=0;j<sizeof(available_options)/sizeof(available_options[0]);j++) {
len = strlen(available_options[j].name);
if (len > 2 && available_options[j].name[len-1] == '*')
- cmp = strncasecmp(val->pzName, available_options[j].name, len-1);
+ cmp = strncasecmp(val->name, available_options[j].name, len-1);
else
- cmp = strcasecmp(val->pzName, available_options[j].name);
+ cmp = strcasecmp(val->name, available_options[j].name);
if (cmp == 0) {
if (available_options[j].type != OPTION_MULTI_LINE &&
@@ -375,24 +372,21 @@ int template_parse(const char *template)
/* Parsing return code */
unsigned int i;
int ret;
- tOptionValue const *pov;
- const tOptionValue *val, *prev;
+ cfg_option_t pov;
+ cfg_option_t val;
char tmpstr[256];
- pov = configFileLoad(template);
+ pov = cfg_load(template);
if (pov == NULL) {
perror("configFileLoad");
fprintf(stderr, "Error loading template: %s\n", template);
exit(1);
}
- val = optionGetValue(pov, NULL);
- while (val != NULL) {
+ for (val = pov; val->name; val++) {
if (handle_option(val) == 0) {
- fprintf(stderr, "Warning: skipping unknown option '%s'\n", val->pzName);
+ fprintf(stderr, "Warning: skipping unknown option '%s'\n", val->name);
}
- prev = val;
- val = optionNextValue(pov, prev);
}
/* Option variables */
@@ -406,92 +400,90 @@ int template_parse(const char *template)
READ_MULTI_LINE("o", cfg.organization);
}
- val = optionGetValue(pov, "locality");
- if (val != NULL && val->valType == OPARG_TYPE_STRING)
- cfg.locality = strdup(val->v.strVal);
+ val = cfg_next(pov, "locality");
+ if (val != NULL)
+ cfg.locality = strdup(val->value);
- val = optionGetValue(pov, "state");
- if (val != NULL && val->valType == OPARG_TYPE_STRING)
- cfg.state = strdup(val->v.strVal);
+ val = cfg_next(pov, "state");
+ if (val != NULL)
+ cfg.state = strdup(val->value);
- val = optionGetValue(pov, "dn");
- if (val != NULL && val->valType == OPARG_TYPE_STRING)
- cfg.dn = strdup(val->v.strVal);
+ val = cfg_next(pov, "dn");
+ if (val != NULL)
+ cfg.dn = strdup(val->value);
- val = optionGetValue(pov, "cn");
- if (val != NULL && val->valType == OPARG_TYPE_STRING)
- cfg.cn = strdup(val->v.strVal);
+ val = cfg_next(pov, "cn");
+ if (val != NULL)
+ cfg.cn = strdup(val->value);
- val = optionGetValue(pov, "uid");
- if (val != NULL && val->valType == OPARG_TYPE_STRING)
- cfg.uid = strdup(val->v.strVal);
+ val = cfg_next(pov, "uid");
+ if (val != NULL)
+ cfg.uid = strdup(val->value);
- val = optionGetValue(pov, "issuer_unique_id");
- if (val != NULL && val->valType == OPARG_TYPE_STRING)
- HEX_DECODE(val->v.strVal, cfg.issuer_unique_id, cfg.issuer_unique_id_size);
+ val = cfg_next(pov, "issuer_unique_id");
+ if (val != NULL)
+ HEX_DECODE(val->value, cfg.issuer_unique_id, cfg.issuer_unique_id_size);
- val = optionGetValue(pov, "subject_unique_id");
- if (val != NULL && val->valType == OPARG_TYPE_STRING)
- HEX_DECODE(val->v.strVal, cfg.subject_unique_id, cfg.subject_unique_id_size);
+ val = cfg_next(pov, "subject_unique_id");
+ if (val != NULL)
+ HEX_DECODE(val->value, cfg.subject_unique_id, cfg.subject_unique_id_size);
- val = optionGetValue(pov, "challenge_password");
- if (val != NULL && val->valType == OPARG_TYPE_STRING)
- cfg.challenge_password = strdup(val->v.strVal);
+ val = cfg_next(pov, "challenge_password");
+ if (val != NULL)
+ cfg.challenge_password = strdup(val->value);
- val = optionGetValue(pov, "password");
- if (val != NULL && val->valType == OPARG_TYPE_STRING)
- cfg.password = strdup(val->v.strVal);
+ val = cfg_next(pov, "password");
+ if (val != NULL)
+ cfg.password = strdup(val->value);
- val = optionGetValue(pov, "pkcs9_email");
- if (val != NULL && val->valType == OPARG_TYPE_STRING)
- cfg.pkcs9_email = strdup(val->v.strVal);
+ val = cfg_next(pov, "pkcs9_email");
+ if (val != NULL)
+ cfg.pkcs9_email = strdup(val->value);
- val = optionGetValue(pov, "country");
- if (val != NULL && val->valType == OPARG_TYPE_STRING)
- cfg.country = strdup(val->v.strVal);
+ val = cfg_next(pov, "country");
+ if (val != NULL)
+ cfg.country = strdup(val->value);
- val = optionGetValue(pov, "expiration_date");
- if (val != NULL && val->valType == OPARG_TYPE_STRING)
- cfg.expiration_date = strdup(val->v.strVal);
+ val = cfg_next(pov, "expiration_date");
+ if (val != NULL)
+ cfg.expiration_date = strdup(val->value);
- val = optionGetValue(pov, "activation_date");
- if (val != NULL && val->valType == OPARG_TYPE_STRING)
- cfg.activation_date = strdup(val->v.strVal);
+ val = cfg_next(pov, "activation_date");
+ if (val != NULL)
+ cfg.activation_date = strdup(val->value);
- val = optionGetValue(pov, "crl_revocation_date");
- if (val != NULL && val->valType == OPARG_TYPE_STRING)
- cfg.revocation_date = strdup(val->v.strVal);
+ val = cfg_next(pov, "crl_revocation_date");
+ if (val != NULL)
+ cfg.revocation_date = strdup(val->value);
- val = optionGetValue(pov, "crl_this_update_date");
- if (val != NULL && val->valType == OPARG_TYPE_STRING)
- cfg.this_update_date = strdup(val->v.strVal);
+ val = cfg_next(pov, "crl_this_update_date");
+ if (val != NULL)
+ cfg.this_update_date = strdup(val->value);
- val = optionGetValue(pov, "crl_next_update_date");
- if (val != NULL && val->valType == OPARG_TYPE_STRING)
- cfg.next_update_date = strdup(val->v.strVal);
+ val = cfg_next(pov, "crl_next_update_date");
+ if (val != NULL)
+ cfg.next_update_date = strdup(val->value);
READ_NUMERIC("inhibit_anypolicy_skip_certs", cfg.skip_certs);
for (i = 0; i < MAX_POLICIES; i++) {
snprintf(tmpstr, sizeof(tmpstr), "policy%d", i + 1);
- val = optionGetValue(pov, tmpstr);
- if (val != NULL && val->valType == OPARG_TYPE_STRING)
- cfg.policy_oid[i] = strdup(val->v.strVal);
+ val = cfg_next(pov, tmpstr);
+ if (val != NULL)
+ cfg.policy_oid[i] = strdup(val->value);
if (cfg.policy_oid[i] != NULL) {
snprintf(tmpstr, sizeof(tmpstr), "policy%d_url",
i + 1);
- val = optionGetValue(pov, tmpstr);
- if (val != NULL
- && val->valType == OPARG_TYPE_STRING)
- cfg.policy_url[i] = strdup(val->v.strVal);
+ val = cfg_next(pov, tmpstr);
+ if (val != NULL)
+ cfg.policy_url[i] = strdup(val->value);
snprintf(tmpstr, sizeof(tmpstr), "policy%d_txt",
i + 1);
- val = optionGetValue(pov, tmpstr);
- if (val != NULL
- && val->valType == OPARG_TYPE_STRING) {
- cfg.policy_txt[i] = strdup(val->v.strVal);
+ val = cfg_next(pov, tmpstr);
+ if (val != NULL) {
+ cfg.policy_txt[i] = strdup(val->value);
}
}
}
@@ -523,27 +515,27 @@ int template_parse(const char *template)
READ_MULTI_LINE("crl_dist_points", cfg.crl_dist_points);
- val = optionGetValue(pov, "pkcs12_key_name");
- if (val != NULL && val->valType == OPARG_TYPE_STRING)
- cfg.pkcs12_key_name = strdup(val->v.strVal);
+ val = cfg_next(pov, "pkcs12_key_name");
+ if (val != NULL)
+ cfg.pkcs12_key_name = strdup(val->value);
- val = optionGetValue(pov, "serial");
- if (val != NULL && val->valType == OPARG_TYPE_STRING)
- SERIAL_DECODE(val->v.strVal, cfg.serial, cfg.serial_size);
+ val = cfg_next(pov, "serial");
+ if (val != NULL)
+ SERIAL_DECODE(val->value, cfg.serial, cfg.serial_size);
READ_NUMERIC("expiration_days", cfg.expiration_days);
READ_NUMERIC("crl_next_update", cfg.crl_next_update);
- val = optionGetValue(pov, "crl_number");
- if (val != NULL && val->valType == OPARG_TYPE_STRING)
- SERIAL_DECODE(val->v.strVal, cfg.crl_number, cfg.crl_number_size);
+ val = cfg_next(pov, "crl_number");
+ if (val != NULL)
+ SERIAL_DECODE(val->value, cfg.crl_number, cfg.crl_number_size);
READ_NUMERIC("path_len", cfg.path_len);
- val = optionGetValue(pov, "proxy_policy_language");
- if (val != NULL && val->valType == OPARG_TYPE_STRING)
- cfg.proxy_policy_language = strdup(val->v.strVal);
+ val = cfg_next(pov, "proxy_policy_language");
+ if (val != NULL)
+ cfg.proxy_policy_language = strdup(val->value);
READ_MULTI_LINE("ocsp_uri", cfg.ocsp_uris);
READ_MULTI_LINE("ca_issuers_uri", cfg.ca_issuers_uris);
@@ -570,7 +562,7 @@ int template_parse(const char *template)
READ_MULTI_LINE("tls_feature", cfg.tls_features);
- optionUnloadNested(pov);
+ cfg_free(pov);
return 0;
}
diff --git a/src/cfg.c b/src/cfg.c
new file mode 100644
index 0000000000..b8925f9c7c
--- /dev/null
+++ b/src/cfg.c
@@ -0,0 +1,464 @@
+/*
+ * Copyright (C) 2021 Daiki Ueno
+ *
+ * This file is part of GnuTLS.
+ *
+ * GnuTLS is free software: you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License as published by
+ * the Free Software Foundation, either version 3 of the License, or
+ * (at your option) any later version.
+ *
+ * GnuTLS is distributed in the hope that it will be useful, but
+ * WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program. If not, see
+ * <https://www.gnu.org/licenses/>.
+ */
+
+#include "config.h"
+
+#include "cfg.h"
+
+#include <assert.h>
+#include <ctype.h>
+#include <errno.h>
+#include <stdbool.h>
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+#include "xsize.h"
+
+#define SIZEOF(x) (sizeof(x) / sizeof((x)[0]))
+
+struct options_st {
+ struct cfg_option_st *data;
+ size_t length;
+ size_t capacity;
+};
+
+struct parser_st
+{
+ FILE *fp;
+ char pushback[2];
+ size_t pushback_length;
+};
+
+static inline void
+clear_option(struct cfg_option_st *option)
+{
+ free(option->name);
+ free(option->value);
+ memset(option, 0, sizeof(*option));
+}
+
+void
+cfg_free(cfg_option_t options)
+{
+ for (size_t i = 0; options[i].name; i++) {
+ clear_option(&options[i]);
+ }
+ free(options);
+}
+
+#define HORIZONTAL_WHITESPACE "\t "
+#define WHITESPACE HORIZONTAL_WHITESPACE "\n\v\f\r\b"
+#define ALPHABETIC "abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ"
+#define DECIMAL "0123456789"
+#define NAME_FIRST_CHARS "_" ALPHABETIC
+#define VALUE_NAME_CHARS ":^-" NAME_FIRST_CHARS DECIMAL
+
+struct buffer_st {
+ char *data;
+ size_t length;
+ size_t capacity;
+};
+
+static int
+buffer_append(struct buffer_st *buffer, int c)
+{
+ size_t new_length = xsum(buffer->length, 1);
+ if (size_overflow_p(new_length)) {
+ return -EINVAL;
+ }
+ if (buffer->capacity < new_length) {
+ size_t new_capacity;
+ char *new_array;
+
+ new_capacity = xtimes(xsum(buffer->capacity, 1), 2);
+ if (size_overflow_p(new_capacity)) {
+ return -EINVAL;
+ }
+ new_array = realloc(buffer->data, new_capacity);
+ if (!new_array) {
+ return -errno;
+ }
+ buffer->capacity = new_capacity;
+ buffer->data = new_array;
+ }
+ assert(buffer->data);
+ buffer->data[buffer->length++] = c;
+ return 0;
+}
+
+static int
+parser_getc(struct parser_st *parser)
+{
+ if (parser->pushback_length > 0) {
+ return parser->pushback[--parser->pushback_length];
+ }
+ int c = getc(parser->fp);
+ return c;
+}
+
+static void
+parser_ungetc(struct parser_st *parser, int c)
+{
+ assert(parser->pushback_length < SIZEOF(parser->pushback));
+ parser->pushback[parser->pushback_length++] = c;
+}
+
+static void
+skip_comment(struct parser_st *parser)
+{
+ int c;
+
+ c = parser_getc(parser);
+ if (c == EOF) {
+ return;
+ }
+
+ if (c == '#') {
+ for (;;) {
+ c = parser_getc(parser);
+ if (c == EOF) {
+ return;
+ }
+ if (c == '\n') {
+ break;
+ }
+ }
+ }
+ parser_ungetc(parser, c);
+}
+
+static void
+skip_chars(struct parser_st *parser, const char *chars)
+{
+ int c;
+
+ for (;;) {
+ c = parser_getc(parser);
+ if (c == EOF) {
+ return;
+ }
+ if (!strchr(chars, c)) {
+ break;
+ }
+ }
+ parser_ungetc(parser, c);
+}
+
+static void
+skip_comments_and_whitespaces(struct parser_st *parser)
+{
+ int c;
+
+ for (;;) {
+ c = parser_getc(parser);
+ if (c == EOF) {
+ return;
+ }
+ parser_ungetc(parser, c);
+ if (c == '#') {
+ skip_comment(parser);
+ } else if (strchr(WHITESPACE, c)) {
+ skip_chars(parser, WHITESPACE);
+ } else {
+ break;
+ }
+ }
+}
+
+/* Read the name part of an option. Returns NULL if it fails. */
+static char *
+read_name(struct parser_st *parser)
+{
+ struct buffer_st buffer;
+ int c;
+
+ memset(&buffer, 0, sizeof(buffer));
+
+ skip_comments_and_whitespaces(parser);
+
+ c = parser_getc(parser);
+ if (c == EOF) {
+ return NULL;
+ }
+
+ if (!strchr(NAME_FIRST_CHARS, c)) {
+ parser_ungetc(parser, c);
+ return NULL;
+ }
+
+ buffer_append(&buffer, c);
+ for (;;) {
+ c = parser_getc(parser);
+ if (c == EOF) {
+ break;
+ }
+ if (!strchr(VALUE_NAME_CHARS, c)) {
+ parser_ungetc(parser, c);
+ break;
+ }
+ buffer_append(&buffer, c);
+ }
+ assert(buffer.data);
+ if (buffer.data[buffer.length - 1] == ':') {
+ buffer.data[buffer.length - 1] = '\0';
+ buffer.length--;
+ parser_ungetc(parser, ':');
+ }
+
+ /* NUL terminate */
+ buffer_append(&buffer, '\0');
+ return buffer.data;
+}
+
+static char *
+read_quoted_value(struct parser_st *parser)
+{
+ struct buffer_st buffer;
+ int c, quote_char;
+
+ memset(&buffer, 0, sizeof(buffer));
+
+ c = parser_getc(parser);
+ if (c == EOF) {
+ assert(false);
+ return NULL;
+ }
+
+ if (c == '"' || c == '\'') {
+ quote_char = c;
+ } else {
+ assert(false);
+ return NULL;
+ }
+
+ for (;;) {
+ c = parser_getc(parser);
+ if (c == EOF) {
+ break;
+ }
+ if (c == '\\') {
+ c = parser_getc(parser);
+ if (c == EOF) {
+ /* unmatched quote */
+ free(buffer.data);
+ return NULL;
+ }
+ if (c == '\n') {
+ buffer_append(&buffer, ' ');
+ } else if (c == quote_char) {
+ buffer_append(&buffer, c);
+ }
+ } else if (c == quote_char) {
+ break;
+ } else {
+ buffer_append(&buffer, c);
+ }
+ }
+
+ /* NUL terminate */
+ buffer_append(&buffer, '\0');
+ return buffer.data;
+}
+
+/* Read the value part of an option. Returns NULL if it fails. */
+static char *
+read_value(struct parser_st *parser)
+{
+ struct buffer_st buffer;
+ int c;
+
+ memset(&buffer, 0, sizeof(buffer));
+
+ skip_chars(parser, HORIZONTAL_WHITESPACE);
+
+ c = parser_getc(parser);
+ if (c == EOF) {
+ goto out;
+ }
+
+ /* skip delimiter if any, followed by horizontal whitespaces */
+ if (c == ':' || c == '=') {
+ c = parser_getc(parser);
+ if (c == EOF) {
+ goto out;
+ }
+ parser_ungetc(parser, c);
+ skip_chars(parser, HORIZONTAL_WHITESPACE);
+ c = parser_getc(parser);
+ if (c == EOF) {
+ goto out;
+ }
+ }
+
+ if (c == '\n') {
+ return strdup(""); /* empty value */
+ } else if (c == '"' || c == '\'') {
+ parser_ungetc(parser, c);
+ return read_quoted_value(parser);
+ }
+
+ buffer_append(&buffer, c);
+ for (;;) {
+ c = parser_getc(parser);
+ if (c == EOF) {
+ break;
+ }
+ if (c == '\\') {
+ c = parser_getc(parser);
+ if (c == EOF) {
+ break;
+ }
+ if (c == '\n') {
+ buffer_append(&buffer, c);
+ }
+ } else if (c == '\n') {
+ break;
+ } else {
+ buffer_append(&buffer, c);
+ }
+ }
+
+ out:
+ /* NUL terminate */
+ buffer_append(&buffer, '\0');
+ return buffer.data;
+}
+
+/* Append OPTION to OPTIONS. Take ownership of the fields of OPTION. */
+static int
+take_option(struct options_st *options, struct cfg_option_st *option)
+{
+ size_t new_length = xsum(options->length, 1);
+ if (size_overflow_p(new_length)) {
+ return -EINVAL;
+ }
+ if (options->capacity < new_length) {
+ size_t new_capacity;
+ struct cfg_option_st *new_array;
+
+ new_capacity = xtimes(xsum(options->capacity, 1), 2);
+ if (size_overflow_p(new_capacity)) {
+ return -EINVAL;
+ }
+ new_array = reallocarray(options->data, new_capacity,
+ sizeof(*option));
+ if (!new_array) {
+ return -errno;
+ }
+ options->capacity = new_capacity;
+ options->data = new_array;
+ }
+
+ assert(options->data);
+
+ options->data[options->length].name = option->name;
+ options->data[options->length].value = option->value;
+
+ options->length++;
+
+ option->name = NULL;
+ option->value = NULL;
+
+ return 0;
+}
+
+static void
+clear_options(struct options_st *options)
+{
+ for (size_t i = 0; options->length; i++) {
+ clear_option(&options->data[i]);
+ }
+}
+
+cfg_option_t
+cfg_load(const char *filename)
+{
+ struct parser_st parser;
+ struct options_st options;
+ struct cfg_option_st null_option = { NULL, NULL };
+
+ memset(&parser, 0, sizeof(parser));
+ memset(&options, 0, sizeof(options));
+
+ parser.fp = fopen(filename, "r");
+ if (!parser.fp) {
+ return NULL;
+ }
+
+ for (;;) {
+ struct cfg_option_st option;
+
+ option.name = read_name(&parser);
+ if (!option.name) {
+ break;
+ }
+
+ option.value = read_value(&parser);
+ if (!option.value) {
+ clear_option(&option);
+ goto error;
+ }
+
+ if (take_option(&options, &option) < 0) {
+ clear_option(&option);
+ goto error;
+ }
+ assert(!option.name && !option.value);
+ }
+
+ fclose(parser.fp);
+ /* NUL terminate */
+ take_option(&options, &null_option);
+ return options.data;
+
+error:
+ clear_options(&options);
+ fclose(parser.fp);
+ return NULL;
+}
+
+cfg_option_t
+cfg_next(const cfg_option_t options, const char *name)
+{
+ for (size_t i = 0; options[i].name; i++) {
+ if (strcmp(options[i].name, name) == 0) {
+ return &options[i];
+ }
+ }
+ return NULL;
+}
+
+#ifdef TEST
+int
+main(int argc, char **argv)
+{
+ cfg_option_t opts;
+
+ assert(argc == 2);
+
+ opts = cfg_load(argv[1]);
+ for (size_t i = 0; opts[i].name; i++) {
+ printf("%s: %s\n", opts[i].name, opts[i].value);
+ }
+ cfg_free(opts);
+
+ return 0;
+}
+#endif
diff --git a/src/cfg.h b/src/cfg.h
new file mode 100644
index 0000000000..20e8fc9faa
--- /dev/null
+++ b/src/cfg.h
@@ -0,0 +1,33 @@
+/*
+ * Copyright (C) 2021 Daiki Ueno
+ *
+ * This file is part of GnuTLS.
+ *
+ * GnuTLS is free software: you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License as published by
+ * the Free Software Foundation, either version 3 of the License, or
+ * (at your option) any later version.
+ *
+ * GnuTLS is distributed in the hope that it will be useful, but
+ * WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program. If not, see
+ * <https://www.gnu.org/licenses/>.
+ */
+
+#ifndef CFG_H_
+#define CFG_H_ 1
+
+typedef struct cfg_option_st {
+ char *name;
+ char *value;
+} *cfg_option_t;
+
+cfg_option_t cfg_load(const char *filename);
+void cfg_free(cfg_option_t options);
+cfg_option_t cfg_next(const cfg_option_t options, const char *name);
+
+#endif /* CFG_H_ */
diff --git a/tests/Makefile.am b/tests/Makefile.am
index fb7cc84c8b..3f9f4bcd56 100644
--- a/tests/Makefile.am
+++ b/tests/Makefile.am
@@ -515,7 +515,7 @@ dist_check_SCRIPTS += fastopen.sh pkgconfig.sh starttls.sh starttls-ftp.sh start
psktool.sh ocsp-tests/ocsp-load-chain.sh gnutls-cli-save-data.sh gnutls-cli-debug.sh \
sni-resume.sh ocsp-tests/ocsptool.sh cert-reencoding.sh pkcs7-cat.sh long-crl.sh \
serv-udp.sh logfile-option.sh gnutls-cli-resume.sh profile-tests.sh \
- server-weak-keys.sh ocsp-tests/ocsp-signer-verify.sh
+ server-weak-keys.sh ocsp-tests/ocsp-signer-verify.sh cfg-test.sh
if !DISABLE_SYSTEM_CONFIG
dist_check_SCRIPTS += system-override-sig.sh system-override-hash.sh \
@@ -635,3 +635,31 @@ LOG_COMPILER = $(LOG_VALGRIND)
distclean-local:
rm -rf softhsm-*.db softhsm-*.config *.tmp tmp-* x509-crt-list-import-url.config.db port.lock.d
+
+EXTRA_DIST += \
+ fixtures/templates/arb-extensions.tmpl.exp \
+ fixtures/templates/crit-extensions.tmpl.exp \
+ fixtures/templates/inhibit-anypolicy.tmpl.exp \
+ fixtures/templates/simple-policy.tmpl.exp \
+ fixtures/templates/template-crq.tmpl.exp \
+ fixtures/templates/template-dates-after2038.tmpl.exp \
+ fixtures/templates/template-date.tmpl.exp \
+ fixtures/templates/template-dn-err.tmpl.exp \
+ fixtures/templates/template-dn.tmpl.exp \
+ fixtures/templates/template-generalized.tmpl.exp \
+ fixtures/templates/template-krb5name.tmpl.exp \
+ fixtures/templates/template-long-dns.tmpl.exp \
+ fixtures/templates/template-long-serial.tmpl.exp \
+ fixtures/templates/template-nc.tmpl.exp \
+ fixtures/templates/template-no-ca-explicit.tmpl.exp \
+ fixtures/templates/template-no-ca-honor.tmpl.exp \
+ fixtures/templates/template-no-ca.tmpl.exp \
+ fixtures/templates/template-othername.tmpl.exp \
+ fixtures/templates/template-othername-xmpp.tmpl.exp \
+ fixtures/templates/template-overflow2.tmpl.exp \
+ fixtures/templates/template-overflow.tmpl.exp \
+ fixtures/templates/template-test.tmpl.exp \
+ fixtures/templates/template-tlsfeature-crq.tmpl.exp \
+ fixtures/templates/template-tlsfeature.tmpl.exp \
+ fixtures/templates/template-unique.tmpl.exp \
+ fixtures/templates/template-utf8.tmpl.exp
diff --git a/tests/cfg-test.sh b/tests/cfg-test.sh
new file mode 100644
index 0000000000..75b7e68cdd
--- /dev/null
+++ b/tests/cfg-test.sh
@@ -0,0 +1,73 @@
+#!/bin/sh
+
+# Copyright (C) 2021 Daiki Ueno
+#
+# This file is part of GnuTLS.
+#
+# GnuTLS is free software; you can redistribute it and/or modify it
+# under the terms of the GNU General Public License as published by the
+# Free Software Foundation; either version 3 of the License, or (at
+# your option) any later version.
+#
+# GnuTLS is distributed in the hope that it will be useful, but
+# WITHOUT ANY WARRANTY; without even the implied warranty of
+# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+# General Public License for more details.
+#
+# You should have received a copy of the GNU Lesser General Public License
+# along with this program. If not, see <https://www.gnu.org/licenses/>
+
+: ${top_builddir=..}
+: ${srcdir=.}
+
+: ${DUMPCFG=$top_builddir/src/dumpcfg${EXEEXT}}
+
+if ! test -x "${DUMPCFG}"; then
+ exit 77
+fi
+
+if test -n "$VALGRIND"; then
+ VALGRIND="${LIBTOOL:-libtool} --mode=execute ${VALGRIND} --error-exitcode=1"
+fi
+
+: ${DIFF=diff}
+
+. "$srcdir/scripts/common.sh"
+testdir=`create_testdir cfg`
+
+
+TEMPLATES="
+arb-extensions.tmpl
+crit-extensions.tmpl
+inhibit-anypolicy.tmpl
+template-crq.tmpl
+template-date.tmpl
+template-dates-after2038.tmpl
+template-dn-err.tmpl
+template-dn.tmpl
+template-generalized.tmpl
+template-krb5name.tmpl
+template-long-dns.tmpl
+template-long-serial.tmpl
+template-nc.tmpl
+template-no-ca-explicit.tmpl
+template-no-ca-honor.tmpl
+template-no-ca.tmpl
+template-othername-xmpp.tmpl
+template-othername.tmpl
+template-overflow.tmpl
+template-overflow2.tmpl
+template-test.tmpl
+template-tlsfeature-crq.tmpl
+template-tlsfeature.tmpl
+template-unique.tmpl
+template-utf8.tmpl
+simple-policy.tmpl
+"
+
+for template in $TEMPLATES; do
+ "$DUMPCFG" "$srcdir/cert-tests/templates/$template" > "$testdir/$template.out"
+ "$DIFF" "$srcdir/fixtures/templates/$template.exp" "$testdir/$template.out" || exit 1
+done
+
+rm -rf "$testdir"
diff --git a/tests/fixtures/templates/arb-extensions.tmpl.exp b/tests/fixtures/templates/arb-extensions.tmpl.exp
new file mode 100644
index 0000000000..852b77a904
--- /dev/null
+++ b/tests/fixtures/templates/arb-extensions.tmpl.exp
@@ -0,0 +1,17 @@
+organization: Koko inc.
+unit: sleeping dept.
+state: Attiki
+country: GR
+cn: Cindy Lauper
+uid: clauper
+serial: 9
+expiration_days: 2590
+email_protection_key:
+add_extension: 1.2.3.4 0001020304050607AAABCD
+add_extension: 1.6.7.8 0x0001020304050607AAABCD
+add_extension: 1.2.3.4.5.6.7 1d34cd5ad065dc27c17e9447b0aaaca7
+add_extension: 1.2.3.4294967295.7 178f0e413f041cc9d64af64bf3b66c7ceac6fa34a4d77ed64c968b26c761709445f40d9ca0a00091af7d212789c00b7387b1d0d7ab623dd4029d4b86db3653621d34cd5ad065dc27c17e9447b0aaaca7
+add_critical_extension: 1.10.11.12.13.14.15.16.17.1.5 CAFE
+add_extension: 1.2.6710656.7 d64af64bf3b66c7ceac6fa34a4d77ed64c968b26c761709445f40d9ca0a00091af7d212789c00b7387b1d0d7ab623dd4029d4b86db3653621d34cd5ad065dc27c17e9447b0aaaca7
+add_extension: 1.0.1.5 octet_string(CAFEBEAF)
+add_critical_extension: 1.0.1.5.1 octet_string(BEAFCAFEFAFA)
diff --git a/tests/fixtures/templates/crit-extensions.tmpl.exp b/tests/fixtures/templates/crit-extensions.tmpl.exp
new file mode 100644
index 0000000000..cfb46a010f
--- /dev/null
+++ b/tests/fixtures/templates/crit-extensions.tmpl.exp
@@ -0,0 +1,10 @@
+organization: Koko inc.
+unit: sleeping dept.
+state: Attiki
+country: GR
+cn: Cindy Lauper
+uid: clauper
+serial: 9
+expiration_days: 2590
+add_critical_extension: 1.10.11.12.13.14.15.16.17.1.5 CAFE
+add_critical_extension: 1.2.1.5.1 octet_string(BEAFCAFEFAFA)
diff --git a/tests/fixtures/templates/inhibit-anypolicy.tmpl.exp b/tests/fixtures/templates/inhibit-anypolicy.tmpl.exp
new file mode 100644
index 0000000000..23d962de02
--- /dev/null
+++ b/tests/fixtures/templates/inhibit-anypolicy.tmpl.exp
@@ -0,0 +1,25 @@
+organization: Koko inc.
+unit: sleeping dept.
+state: Attiki
+country: GR
+cn: Cindy Lauper
+uid: clauper
+dn_oid: 2.5.4.12 Dr.
+dn_oid: 2.5.4.65 jackal
+pkcs9_email: none@none.org
+serial: 7
+inhibit_anypolicy_skip_certs: 3
+expiration_days: 2590
+dns_name: www.none.org
+dns_name: www.morethanone.org
+ip_address: 192.168.1.1
+dns_name: www.evenmorethanone.org
+email: none@none.org
+crl_dist_points: http://www.getcrl.crl/getcrl1/
+crl_dist_points: http://www.getcrl.crl/getcrl2/
+crl_dist_points: http://www.getcrl.crl/getcrl3/
+email: where@none.org
+ca:
+signing_key:
+cert_signing_key:
+ocsp_signing_key:
diff --git a/tests/fixtures/templates/simple-policy.tmpl.exp b/tests/fixtures/templates/simple-policy.tmpl.exp
new file mode 100644
index 0000000000..c197d525fd
--- /dev/null
+++ b/tests/fixtures/templates/simple-policy.tmpl.exp
@@ -0,0 +1,9 @@
+organization: Koko inc.
+unit: sleeping dept.
+state: Attiki
+country: GR
+cn: Cindy Lauper
+uid: clauper
+serial: 10
+expiration_days: 2590
+policy1: 2.16.840.1.101.3.2.1.48.1
diff --git a/tests/fixtures/templates/template-crq.tmpl.exp b/tests/fixtures/templates/template-crq.tmpl.exp
new file mode 100644
index 0000000000..1ec355d227
--- /dev/null
+++ b/tests/fixtures/templates/template-crq.tmpl.exp
@@ -0,0 +1,3 @@
+serial: 567
+honor_crq_ext: 2.5.29.15
+honor_crq_ext: 2.5.29.37
diff --git a/tests/fixtures/templates/template-date.tmpl.exp b/tests/fixtures/templates/template-date.tmpl.exp
new file mode 100644
index 0000000000..28485a2b1e
--- /dev/null
+++ b/tests/fixtures/templates/template-date.tmpl.exp
@@ -0,0 +1,23 @@
+organization: Koko inc.
+unit: sleeping dept.
+state: Attiki
+country: GR
+cn: Cindy Lauper
+uid: clauper
+dn_oid: 2.5.4.12 Dr.
+dn_oid: 2.5.4.65 jackal
+pkcs9_email: none@none.org
+serial: 7
+expiration_date: 2015-05-24 14:29:12
+activation_date: 2029-01-12 11:36:11
+dns_name: www.none.org
+dns_name: www.morethanone.org
+ip_address: 192.168.1.1
+dns_name: www.evenmorethanone.org
+email: none@none.org
+crl_dist_points: http://www.getcrl.crl/getcrl/
+email: where@none.org
+ca:
+signing_key:
+cert_signing_key:
+ocsp_signing_key:
diff --git a/tests/fixtures/templates/template-dates-after2038.tmpl.exp b/tests/fixtures/templates/template-dates-after2038.tmpl.exp
new file mode 100644
index 0000000000..d53ad5a16f
--- /dev/null
+++ b/tests/fixtures/templates/template-dates-after2038.tmpl.exp
@@ -0,0 +1,23 @@
+organization: Koko inc.
+unit: sleeping dept.
+state: Attiki
+country: GR
+cn: Cindy Lauper
+uid: clauper
+dn_oid: 2.5.4.12 Dr.
+dn_oid: 2.5.4.65 jackal
+pkcs9_email: none@none.org
+serial: 7
+expiration_date: 2043-05-24 14:29:12
+activation_date: 2039-01-12 11:36:11
+dns_name: www.none.org
+dns_name: www.morethanone.org
+ip_address: 192.168.1.1
+dns_name: www.evenmorethanone.org
+email: none@none.org
+crl_dist_points: http://www.getcrl.crl/getcrl/
+email: where@none.org
+ca:
+signing_key:
+cert_signing_key:
+ocsp_signing_key:
diff --git a/tests/fixtures/templates/template-dn-err.tmpl.exp b/tests/fixtures/templates/template-dn-err.tmpl.exp
new file mode 100644
index 0000000000..5353e24346
--- /dev/null
+++ b/tests/fixtures/templates/template-dn-err.tmpl.exp
@@ -0,0 +1,14 @@
+dn: acn=Nik,st=Attiki,C=GR,surNameO=Mavrogiannopoulos,2.5.4.9=Arkadias
+serial: 7
+expiration_days: 2590
+dns_name: www.none.org
+dns_name: www.morethanone.org
+ip_address: 192.168.1.1
+dns_name: www.evenmorethanone.org
+email: none@none.org
+crl_dist_points: http://www.getcrl.crl/getcrl/
+email: where@none.org
+ca:
+signing_key:
+cert_signing_key:
+ocsp_signing_key:
diff --git a/tests/fixtures/templates/template-dn.tmpl.exp b/tests/fixtures/templates/template-dn.tmpl.exp
new file mode 100644
index 0000000000..173eb94a20
--- /dev/null
+++ b/tests/fixtures/templates/template-dn.tmpl.exp
@@ -0,0 +1,14 @@
+dn: 2.5.4.9=Arkadias,surName=Mavrogiannopoulos,C=GR,st=Attiki,cn=Nik
+serial: 7
+expiration_days: 2590
+dns_name: www.none.org
+dns_name: www.morethanone.org
+ip_address: 192.168.1.1
+dns_name: www.evenmorethanone.org
+email: none@none.org
+crl_dist_points: http://www.getcrl.crl/getcrl/
+email: where@none.org
+ca:
+signing_key:
+cert_signing_key:
+ocsp_signing_key:
diff --git a/tests/fixtures/templates/template-generalized.tmpl.exp b/tests/fixtures/templates/template-generalized.tmpl.exp
new file mode 100644
index 0000000000..997eb24c63
--- /dev/null
+++ b/tests/fixtures/templates/template-generalized.tmpl.exp
@@ -0,0 +1,23 @@
+organization: Koko inc.
+unit: sleeping dept.
+state: Attiki
+country: GR
+cn: Cindy Lauper
+uid: clauper
+dn_oid: 2.5.4.12 Dr.
+dn_oid: 2.5.4.65 jackal
+pkcs9_email: none@none.org
+serial: 7
+expiration_date: 2055-05-24 14:29:12
+activation_date: 2051-01-12 11:36:11
+dns_name: www.none.org
+dns_name: www.morethanone.org
+ip_address: 192.168.1.1
+dns_name: www.evenmorethanone.org
+email: none@none.org
+crl_dist_points: http://www.getcrl.crl/getcrl/
+email: where@none.org
+ca:
+signing_key:
+cert_signing_key:
+ocsp_signing_key:
diff --git a/tests/fixtures/templates/template-krb5name.tmpl.exp b/tests/fixtures/templates/template-krb5name.tmpl.exp
new file mode 100644
index 0000000000..c4284245d7
--- /dev/null
+++ b/tests/fixtures/templates/template-krb5name.tmpl.exp
@@ -0,0 +1,16 @@
+dn: 2.5.4.9=Arkadias,surName=Mavrogiannopoulos,C=GR,st=Attiki,cn=Nik
+serial: 7
+expiration_days: 2590
+krb5_principal: user@email.domain@KERBEROS.REALM
+krb5_principal: user@REALM.COM
+krb5_principal: HTTP/user@REALM.COM
+krb5_principal: comp1/comp2/user@REALM.COM
+ip_address: 192.168.1.1
+dns_name: www.evenmorethanone.org
+email: none@none.org
+crl_dist_points: http://www.getcrl.crl/getcrl/
+email: where@none.org
+ca:
+signing_key:
+cert_signing_key:
+ocsp_signing_key:
diff --git a/tests/fixtures/templates/template-long-dns.tmpl.exp b/tests/fixtures/templates/template-long-dns.tmpl.exp
new file mode 100644
index 0000000000..c3e02a103a
--- /dev/null
+++ b/tests/fixtures/templates/template-long-dns.tmpl.exp
@@ -0,0 +1,14 @@
+dn: cn=super-very-very-very-very-very-very-very-very-very-very-very-very-very-very-very-very-very-very-very-very-very-very-very-very-very-very-very-very-very-very-very-very-very-very-very-very-very-very-very-very-very-very-very-very-very-long.com
+serial: 7
+expiration_days: 2590
+o: super-very-very-very-very-very-very-very-very-very-very-very-very-very-very-very-very-very-very-very-very-very-very-very-very-very-very-very-very-very-very-very-very-very-very-very-very-very-very-very-very-very-very-very-very-very-long org
+ou: super-very-very-very-very-very-very-very-very-very-very-very-very-very-very-very-very-very-very-very-very-very-very-very-very-very-very-very-very-very-very-very-very-very-very-very-very-very-very-very-very-very-very-very-very-very-long dept
+dns_name: super-very-very-very-very-very-very-very-very-very-very-very-very-very-very-very-very-very-very-very-very-very-very-very-very-very-very-very-very-very-very-very-very-very-very-very-very-very-very-very-very-very-very-very-very-very-long.com
+dns_name: www.morethanone.org
+ip_address: 192.168.1.1
+dns_name: www.evenmorethanone.org
+email: none@none.org
+crl_dist_points: http://www.getcrl.crl/getcrl/
+email: where@none.org
+tls_www_server:
+signing_key:
diff --git a/tests/fixtures/templates/template-long-serial.tmpl.exp b/tests/fixtures/templates/template-long-serial.tmpl.exp
new file mode 100644
index 0000000000..4650f7cf43
--- /dev/null
+++ b/tests/fixtures/templates/template-long-serial.tmpl.exp
@@ -0,0 +1,24 @@
+organization: Koko inc.
+unit: sleeping dept.
+state: Attiki
+country: GR
+cn: Cindy Lauper
+uid: clauper
+dn_oid: 2.5.4.12 Dr.
+dn_oid: 2.5.4.65 jackal
+pkcs9_email: none@none.org
+serial: 0x1234567890abcdeffedcba0987654321abcdef12
+expiration_days: 2590
+dns_name: www.none.org
+dns_name: www.morethanone.org
+ip_address: 192.168.1.1
+dns_name: www.evenmorethanone.org
+email: none@none.org
+crl_dist_points: http://www.getcrl.crl/getcrl1/
+crl_dist_points: http://www.getcrl.crl/getcrl2/
+crl_dist_points: http://www.getcrl.crl/getcrl3/
+email: where@none.org
+ca:
+signing_key:
+cert_signing_key:
+ocsp_signing_key:
diff --git a/tests/fixtures/templates/template-nc.tmpl.exp b/tests/fixtures/templates/template-nc.tmpl.exp
new file mode 100644
index 0000000000..5dc8b9e058
--- /dev/null
+++ b/tests/fixtures/templates/template-nc.tmpl.exp
@@ -0,0 +1,27 @@
+dn: 2.5.4.9=Arkadias,surName=Mavrogiannopoulos,C=GR,st=Attiki,cn=Nik
+serial: 7
+expiration_days: 2590
+dns_name: www.none.org
+dns_name: www.morethanone.org
+dns_name: www.evenmorethanone.org
+email: none@none.org
+crl_dist_points: http://www.getcrl.crl/getcrl/
+email: where@none.org
+ca:
+signing_key:
+nc_permit_dns: example.com
+nc_exclude_dns: net
+nc_exclude_dns: org
+nc_exclude_dns:
+nc_permit_email: nmav@example.com
+nc_exclude_email: example.net
+nc_exclude_email: example.li
+nc_permit_ip: 192.168.5.0/24
+nc_permit_ip: 10.10.10.0/16
+nc_permit_ip: 172.23.122.0/23
+nc_exclude_ip: 10.10.100.0/24
+nc_exclude_ip: 10.10.101.5/24
+nc_permit_ip: fc4c:fe8f:7ffa:18bd::/64
+nc_exclude_ip: fc4c:fe8f:7ffa:18bd:72c8:64b9::/96
+cert_signing_key:
+ocsp_signing_key:
diff --git a/tests/fixtures/templates/template-no-ca-explicit.tmpl.exp b/tests/fixtures/templates/template-no-ca-explicit.tmpl.exp
new file mode 100644
index 0000000000..935a6a87bf
--- /dev/null
+++ b/tests/fixtures/templates/template-no-ca-explicit.tmpl.exp
@@ -0,0 +1,11 @@
+cn: No CA
+serial: 02
+email_protection_key:
+add_extension: 1.2.3.4 0001020304050607AAABCD
+add_extension: 1.6.7.8 0x0001020304050607AAABCD
+add_extension: 1.2.3.4.5.6.7 1d34cd5ad065dc27c17e9447b0aaaca7
+add_extension: 1.2.3.4294967295.7 178f0e413f041cc9d64af64bf3b66c7ceac6fa34a4d77ed64c968b26c761709445f40d9ca0a00091af7d212789c00b7387b1d0d7ab623dd4029d4b86db3653621d34cd5ad065dc27c17e9447b0aaaca7
+add_critical_extension: 1.10.11.12.13.14.15.16.17.1.5 CAFE
+add_extension: 1.2.6710656.7 d64af64bf3b66c7ceac6fa34a4d77ed64c968b26c761709445f40d9ca0a00091af7d212789c00b7387b1d0d7ab623dd4029d4b86db3653621d34cd5ad065dc27c17e9447b0aaaca7
+add_extension: 1.0.1.5 octet_string(CAFEBEAF)
+add_critical_extension: 1.0.1.5.1 octet_string(BEAFCAFEFAFA)
diff --git a/tests/fixtures/templates/template-no-ca-honor.tmpl.exp b/tests/fixtures/templates/template-no-ca-honor.tmpl.exp
new file mode 100644
index 0000000000..4da60e4be8
--- /dev/null
+++ b/tests/fixtures/templates/template-no-ca-honor.tmpl.exp
@@ -0,0 +1,3 @@
+cn: No CA
+serial: 02
+honor_crq_extensions:
diff --git a/tests/fixtures/templates/template-no-ca.tmpl.exp b/tests/fixtures/templates/template-no-ca.tmpl.exp
new file mode 100644
index 0000000000..06e845b4b5
--- /dev/null
+++ b/tests/fixtures/templates/template-no-ca.tmpl.exp
@@ -0,0 +1,2 @@
+cn: No CA
+serial: 02
diff --git a/tests/fixtures/templates/template-othername-xmpp.tmpl.exp b/tests/fixtures/templates/template-othername-xmpp.tmpl.exp
new file mode 100644
index 0000000000..9e6c37b978
--- /dev/null
+++ b/tests/fixtures/templates/template-othername-xmpp.tmpl.exp
@@ -0,0 +1,15 @@
+dn: 2.5.4.9=Arkadias,surName=Mavrogiannopoulos,C=GR,st=Attiki,cn=Nik
+serial: 7
+expiration_days: 2590
+dns_name: www.none.org
+dns_name: www.morethanone.org
+xmpp_name: juliet@im.example.com
+xmpp_name: hello@hello.org
+ip_address: 192.168.1.1
+dns_name: www.evenmorethanone.org
+email: none@none.org
+crl_dist_points: http://www.getcrl.crl/getcrl/
+email: where@none.org
+signing_key:
+cert_signing_key:
+ocsp_signing_key:
diff --git a/tests/fixtures/templates/template-othername.tmpl.exp b/tests/fixtures/templates/template-othername.tmpl.exp
new file mode 100644
index 0000000000..a022590122
--- /dev/null
+++ b/tests/fixtures/templates/template-othername.tmpl.exp
@@ -0,0 +1,18 @@
+dn: 2.5.4.9=Arkadias,surName=Mavrogiannopoulos,C=GR,st=Attiki,cn=Nik
+serial: 7
+expiration_days: 2590
+dns_name: www.none.org
+dns_name: www.morethanone.org
+other_name: 1.3.6.1.5.2.2 302ca00d1b0b56414e5245494e2e4f5247a11b3019a006020400000002a10f300d1b047269636b1b0561646d696e
+other_name_utf8: 1.3.6.1.5.5.7.8.7 nmav@gnutls.org
+other_name_utf8: 1.3.6.1.5.5.7.8.5 nmav@gnutls.org
+other_name_octet: 1.2.4.5.6 a test string
+ip_address: 192.168.1.1
+dns_name: www.evenmorethanone.org
+email: none@none.org
+crl_dist_points: http://www.getcrl.crl/getcrl/
+email: where@none.org
+ca:
+signing_key:
+cert_signing_key:
+ocsp_signing_key:
diff --git a/tests/fixtures/templates/template-overflow.tmpl.exp b/tests/fixtures/templates/template-overflow.tmpl.exp
new file mode 100644
index 0000000000..2753b00258
--- /dev/null
+++ b/tests/fixtures/templates/template-overflow.tmpl.exp
@@ -0,0 +1,22 @@
+organization: Koko inc.
+unit: sleeping dept.
+state: Attiki
+country: GR
+cn: Cindy Lauper
+uid: clauper
+dn_oid: 2.5.4.12 Dr.
+dn_oid: 2.5.4.65 jackal
+pkcs9_email: none@none.org
+serial: 7
+expiration_days: -1
+dns_name: www.none.org
+dns_name: www.morethanone.org
+ip_address: 192.168.1.1
+dns_name: www.evenmorethanone.org
+email: none@none.org
+crl_dist_points: http://www.getcrl.crl/getcrl/
+email: where@none.org
+ca:
+signing_key:
+cert_signing_key:
+ocsp_signing_key:
diff --git a/tests/fixtures/templates/template-overflow2.tmpl.exp b/tests/fixtures/templates/template-overflow2.tmpl.exp
new file mode 100644
index 0000000000..8e6ac7b3a9
--- /dev/null
+++ b/tests/fixtures/templates/template-overflow2.tmpl.exp
@@ -0,0 +1,22 @@
+organization: Koko inc.
+unit: sleeping dept.
+state: Attiki
+country: GR
+cn: Cindy Lauper
+uid: clauper
+dn_oid: 2.5.4.12 Dr.
+dn_oid: 2.5.4.65 jackal
+pkcs9_email: none@none.org
+serial: 7
+expiration_days: 99999
+dns_name: www.none.org
+dns_name: www.morethanone.org
+ip_address: 192.168.1.1
+dns_name: www.evenmorethanone.org
+email: none@none.org
+crl_dist_points: http://www.getcrl.crl/getcrl/
+email: where@none.org
+ca:
+signing_key:
+cert_signing_key:
+ocsp_signing_key:
diff --git a/tests/fixtures/templates/template-test.tmpl.exp b/tests/fixtures/templates/template-test.tmpl.exp
new file mode 100644
index 0000000000..b4a8d2d89a
--- /dev/null
+++ b/tests/fixtures/templates/template-test.tmpl.exp
@@ -0,0 +1,24 @@
+organization: Koko inc.
+unit: sleeping dept.
+state: Attiki
+country: GR
+cn: Cindy Lauper
+uid: clauper
+dn_oid: 2.5.4.12 Dr.
+dn_oid: 2.5.4.65 jackal
+pkcs9_email: none@none.org
+serial: 7
+expiration_days: 2590
+dns_name: www.none.org
+dns_name: www.morethanone.org
+ip_address: 192.168.1.1
+dns_name: www.evenmorethanone.org
+email: none@none.org
+crl_dist_points: http://www.getcrl.crl/getcrl1/
+crl_dist_points: http://www.getcrl.crl/getcrl2/
+crl_dist_points: http://www.getcrl.crl/getcrl3/
+email: where@none.org
+ca:
+signing_key:
+cert_signing_key:
+ocsp_signing_key:
diff --git a/tests/fixtures/templates/template-tlsfeature-crq.tmpl.exp b/tests/fixtures/templates/template-tlsfeature-crq.tmpl.exp
new file mode 100644
index 0000000000..7323cf7a09
--- /dev/null
+++ b/tests/fixtures/templates/template-tlsfeature-crq.tmpl.exp
@@ -0,0 +1,6 @@
+organization: Koko inc.
+unit: sleeping dept.
+state: Attiki
+country: GR
+cn: Cindy Lauper
+honor_crq_extensions:
diff --git a/tests/fixtures/templates/template-tlsfeature.tmpl.exp b/tests/fixtures/templates/template-tlsfeature.tmpl.exp
new file mode 100644
index 0000000000..a204db98d0
--- /dev/null
+++ b/tests/fixtures/templates/template-tlsfeature.tmpl.exp
@@ -0,0 +1,25 @@
+organization: Koko inc.
+unit: sleeping dept.
+state: Attiki
+country: GR
+cn: Cindy Lauper
+uid: clauper
+tls_feature: 5
+tls_feature: 17
+dn_oid: 2.5.4.12 Dr.
+dn_oid: 2.5.4.65 jackal
+pkcs9_email: none@none.org
+serial: 7
+expiration_days: 2590
+dns_name: www.none.org
+dns_name: www.morethanone.org
+ip_address: 192.168.1.1
+dns_name: www.evenmorethanone.org
+email: none@none.org
+crl_dist_points: http://www.getcrl.crl/getcrl1/
+crl_dist_points: http://www.getcrl.crl/getcrl2/
+crl_dist_points: http://www.getcrl.crl/getcrl3/
+email: where@none.org
+signing_key:
+cert_signing_key:
+ocsp_signing_key:
diff --git a/tests/fixtures/templates/template-unique.tmpl.exp b/tests/fixtures/templates/template-unique.tmpl.exp
new file mode 100644
index 0000000000..55ae48c816
--- /dev/null
+++ b/tests/fixtures/templates/template-unique.tmpl.exp
@@ -0,0 +1,16 @@
+dn: 2.5.4.9=Arkadias,surName=Mavrogiannopoulos,C=GR,st=Attiki,cn=Nik
+serial: 7
+expiration_days: 2590
+dns_name: www.none.org
+dns_name: www.morethanone.org
+ip_address: 192.168.1.1
+dns_name: www.evenmorethanone.org
+email: none@none.org
+subject_unique_id: 0015232425
+issuer_unique_id: 11142324251224
+crl_dist_points: http://www.getcrl.crl/getcrl/
+email: where@none.org
+ca:
+signing_key:
+cert_signing_key:
+ocsp_signing_key:
diff --git a/tests/fixtures/templates/template-utf8.tmpl.exp b/tests/fixtures/templates/template-utf8.tmpl.exp
new file mode 100644
index 0000000000..4cd7ffa174
--- /dev/null
+++ b/tests/fixtures/templates/template-utf8.tmpl.exp
@@ -0,0 +1,14 @@
+organization: Μεγάλη εταιρία
+cn: 🐨
+state: Αττική
+country: GR
+serial: 009
+policy1: 1.3.6.1.4.1.5484.1.10.99.1.0
+policy1_txt: Μια πολιτική που θέλει διάβασμα
+policy1_url: http://www.example.com/a-policy-to-read
+policy2: 1.3.6.1.4.1.5484.1.10.99.1.1
+policy2_txt: Another policy
+policy2_url: http://www.example.com/another-policy-to-read
+policy3: 1.3.6.1.4.1.5484.1.10.99.1.2
+policy3_txt: More policies
+policy3_url: http://example.com/a-policy-to-read