]> git.ipfire.org Git - thirdparty/gnutls.git/commitdiff
src: replace autoopts/libopts with minimal config parser
authorDaiki Ueno <ueno@gnu.org>
Mon, 3 Jan 2022 09:30:34 +0000 (10:30 +0100)
committerDaiki Ueno <ueno@gnu.org>
Sat, 15 Jan 2022 08:25:55 +0000 (09:25 +0100)
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>
33 files changed:
.gitignore
src/Makefile.am
src/certtool-cfg.c
src/cfg.c [new file with mode: 0644]
src/cfg.h [new file with mode: 0644]
tests/Makefile.am
tests/cfg-test.sh [new file with mode: 0644]
tests/fixtures/templates/arb-extensions.tmpl.exp [new file with mode: 0644]
tests/fixtures/templates/crit-extensions.tmpl.exp [new file with mode: 0644]
tests/fixtures/templates/inhibit-anypolicy.tmpl.exp [new file with mode: 0644]
tests/fixtures/templates/simple-policy.tmpl.exp [new file with mode: 0644]
tests/fixtures/templates/template-crq.tmpl.exp [new file with mode: 0644]
tests/fixtures/templates/template-date.tmpl.exp [new file with mode: 0644]
tests/fixtures/templates/template-dates-after2038.tmpl.exp [new file with mode: 0644]
tests/fixtures/templates/template-dn-err.tmpl.exp [new file with mode: 0644]
tests/fixtures/templates/template-dn.tmpl.exp [new file with mode: 0644]
tests/fixtures/templates/template-generalized.tmpl.exp [new file with mode: 0644]
tests/fixtures/templates/template-krb5name.tmpl.exp [new file with mode: 0644]
tests/fixtures/templates/template-long-dns.tmpl.exp [new file with mode: 0644]
tests/fixtures/templates/template-long-serial.tmpl.exp [new file with mode: 0644]
tests/fixtures/templates/template-nc.tmpl.exp [new file with mode: 0644]
tests/fixtures/templates/template-no-ca-explicit.tmpl.exp [new file with mode: 0644]
tests/fixtures/templates/template-no-ca-honor.tmpl.exp [new file with mode: 0644]
tests/fixtures/templates/template-no-ca.tmpl.exp [new file with mode: 0644]
tests/fixtures/templates/template-othername-xmpp.tmpl.exp [new file with mode: 0644]
tests/fixtures/templates/template-othername.tmpl.exp [new file with mode: 0644]
tests/fixtures/templates/template-overflow.tmpl.exp [new file with mode: 0644]
tests/fixtures/templates/template-overflow2.tmpl.exp [new file with mode: 0644]
tests/fixtures/templates/template-test.tmpl.exp [new file with mode: 0644]
tests/fixtures/templates/template-tlsfeature-crq.tmpl.exp [new file with mode: 0644]
tests/fixtures/templates/template-tlsfeature.tmpl.exp [new file with mode: 0644]
tests/fixtures/templates/template-unique.tmpl.exp [new file with mode: 0644]
tests/fixtures/templates/template-utf8.tmpl.exp [new file with mode: 0644]

index 43a5a0074747268e7ee824d348bc52b794e03777..34142c91fc1188bbbbbb2ec85edfba8de0f3fb8c 100644 (file)
@@ -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
index ff9c09dd0494313792c949bd61b79d17596d6af8..d867b02013953d18e56a176d1feb943b1b1c24c9 100644 (file)
@@ -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
index 8c658c86672233a432b3dceada170139982c63e3..a8a135a4a44c2c6129dfbe310755c6df9f71088f 100644 (file)
@@ -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 (file)
index 0000000..b8925f9
--- /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 (file)
index 0000000..20e8fc9
--- /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_ */
index fb7cc84c8b42a69733e01e0f3f723f583d14215d..3f9f4bcd5673637cea81b412fc9a3675673daeb9 100644 (file)
@@ -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 (file)
index 0000000..75b7e68
--- /dev/null
@@ -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 (file)
index 0000000..852b77a
--- /dev/null
@@ -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 (file)
index 0000000..cfb46a0
--- /dev/null
@@ -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 (file)
index 0000000..23d962d
--- /dev/null
@@ -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 (file)
index 0000000..c197d52
--- /dev/null
@@ -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 (file)
index 0000000..1ec355d
--- /dev/null
@@ -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 (file)
index 0000000..28485a2
--- /dev/null
@@ -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 (file)
index 0000000..d53ad5a
--- /dev/null
@@ -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 (file)
index 0000000..5353e24
--- /dev/null
@@ -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 (file)
index 0000000..173eb94
--- /dev/null
@@ -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 (file)
index 0000000..997eb24
--- /dev/null
@@ -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 (file)
index 0000000..c428424
--- /dev/null
@@ -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 (file)
index 0000000..c3e02a1
--- /dev/null
@@ -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 (file)
index 0000000..4650f7c
--- /dev/null
@@ -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 (file)
index 0000000..5dc8b9e
--- /dev/null
@@ -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 (file)
index 0000000..935a6a8
--- /dev/null
@@ -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 (file)
index 0000000..4da60e4
--- /dev/null
@@ -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 (file)
index 0000000..06e845b
--- /dev/null
@@ -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 (file)
index 0000000..9e6c37b
--- /dev/null
@@ -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 (file)
index 0000000..a022590
--- /dev/null
@@ -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 (file)
index 0000000..2753b00
--- /dev/null
@@ -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 (file)
index 0000000..8e6ac7b
--- /dev/null
@@ -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 (file)
index 0000000..b4a8d2d
--- /dev/null
@@ -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 (file)
index 0000000..7323cf7
--- /dev/null
@@ -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 (file)
index 0000000..a204db9
--- /dev/null
@@ -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 (file)
index 0000000..55ae48c
--- /dev/null
@@ -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 (file)
index 0000000..4cd7ffa
--- /dev/null
@@ -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