On Fri, Nov 06, 2015 at 12:24:30AM -0500, Toyam Cox wrote:
> I'm running 5.8-release.

ikectl ca in 5.8 is non-functional as LibreSSL removed support for
environment variables in openssl cnf files and this was not
noticed/fixed until after 5.8.

Here is a patch against 5.8 that adds the changes to cope with that.

Index: Makefile
===================================================================
RCS file: /cvs/src/usr.sbin/ikectl/Makefile,v
retrieving revision 1.3
retrieving revision 1.4
diff -u -p -r1.3 -r1.4
--- Makefile    18 Jan 2014 05:54:51 -0000      1.3
+++ Makefile    19 Aug 2015 12:25:59 -0000      1.4
@@ -1,9 +1,9 @@
-# $OpenBSD: Makefile,v 1.3 2014/01/18 05:54:51 martynas Exp $
+# $OpenBSD: Makefile,v 1.4 2015/08/19 12:25:59 reyk Exp $
 
 .PATH:         ${.CURDIR}/../../sbin/iked
 
 PROG=          ikectl
-SRCS=          log.c ikeca.c ikectl.c parser.c
+SRCS=          log.c ikeca.c ikectl.c parser.c util.c
 
 MAN=           ikectl.8
 
Index: ikeca.c
===================================================================
RCS file: /cvs/src/usr.sbin/ikectl/ikeca.c,v
retrieving revision 1.30
retrieving revision 1.33
diff -u -p -r1.30 -r1.33
--- ikeca.c     16 Jan 2015 06:40:17 -0000      1.30
+++ ikeca.c     19 Aug 2015 12:25:59 -0000      1.33
@@ -1,4 +1,4 @@
-/*     $OpenBSD: ikeca.c,v 1.30 2015/01/16 06:40:17 deraadt Exp $      */
+/*     $OpenBSD: ikeca.c,v 1.33 2015/08/19 12:25:59 reyk Exp $ */
 
 /*
  * Copyright (c) 2010 Jonathan Gray <j...@openbsd.org>
@@ -82,13 +82,39 @@ struct {
        { "/private",   0700 }
 };
 
-int             ca_sign(struct ca *, char *, int, char *);
+/* explicitly list allowed variables */
+const char *ca_env[][2] = {
+       { "$ENV::CADB", NULL },
+       { "$ENV::CERTFQDN", NULL },
+       { "$ENV::CERTIP", NULL },
+       { "$ENV::CERTPATHLEN", NULL },
+       { "$ENV::CERTUSAGE", NULL },
+       { "$ENV::CERT_C", NULL },
+       { "$ENV::CERT_CN", NULL },
+       { "$ENV::CERT_EMAIL", NULL },
+       { "$ENV::CERT_L", NULL },
+       { "$ENV::CERT_O", NULL },
+       { "$ENV::CERT_OU", NULL },
+       { "$ENV::CERT_ST", NULL },
+       { "$ENV::EXTCERTUSAGE", NULL },
+       { "$ENV::NSCERTTYPE", NULL },
+       { NULL }
+};
+
+int             ca_sign(struct ca *, char *, int);
 int             ca_request(struct ca *, char *);
 int             ca_newpass(char *, char *);
 char *          ca_readpass(char *, size_t *);
 int             fcopy(char *, char *, mode_t);
+int             fcopy_env(const char *, const char *, mode_t);
 int             rm_dir(char *);
 int             ca_hier(char *);
+void            ca_setenv(const char *, const char *);
+void            ca_clrenv(void);
+void            ca_setcnf(struct ca *, const char *);
+
+/* util.c */
+int             expand_string(char *, size_t, const char *, const char *);
 
 int
 ca_delete(struct ca *ca)
@@ -173,10 +199,13 @@ ca_request(struct ca *ca, char *keyname)
        char            cmd[PATH_MAX * 2];
        char            path[PATH_MAX];
 
+       ca_setenv("$ENV::CERT_CN", keyname);
+       ca_setcnf(ca, keyname);
+
        snprintf(path, sizeof(path), "%s/private/%s.csr", ca->sslpath, keyname);
-       snprintf(cmd, sizeof(cmd), "env CERT_CN=%s %s req %s-new"
+       snprintf(cmd, sizeof(cmd), "%s req %s-new"
            " -key %s/private/%s.key -out %s -config %s",
-           keyname, PATH_OPENSSL, ca->batch, ca->sslpath, keyname,
+           PATH_OPENSSL, ca->batch, ca->sslpath, keyname,
            path, ca->sslcnf);
 
        system(cmd);
@@ -186,40 +215,40 @@ ca_request(struct ca *ca, char *keyname)
 }
 
 int
-ca_sign(struct ca *ca, char *keyname, int type, char *envargs)
+ca_sign(struct ca *ca, char *keyname, int type)
 {
        char            cmd[PATH_MAX * 2];
        char            hostname[HOST_NAME_MAX+1];
        char            name[128];
+       const char      *extensions = NULL;
 
        strlcpy(name, keyname, sizeof(name));
 
-       if (envargs == NULL)
-               envargs = "";
-
        if (type == HOST_IPADDR) {
-               snprintf(cmd, sizeof(cmd), "env CERTIP=%s%s %s x509 -req"
-                   " -days 365 -in %s/private/%s.csr"
-                   " -CA %s/ca.crt -CAkey %s/private/ca.key -CAcreateserial"
-                   " -extfile %s -extensions x509v3_IPAddr -out %s/%s.crt"
-                   " -passin file:%s", name, envargs, PATH_OPENSSL,
-                   ca->sslpath, keyname, ca->sslpath, ca->sslpath,
-                   ca->extcnf, ca->sslpath, keyname, ca->passfile);
+               ca_setenv("$ENV::CERTIP", name);
+               extensions = "x509v3_IPAddr";
        } else if (type == HOST_FQDN) {
                if (!strcmp(keyname, "local")) {
                        if (gethostname(hostname, sizeof(hostname)))
                                err(1, "gethostname");
                        strlcpy(name, hostname, sizeof(name));
                }
-               snprintf(cmd, sizeof(cmd), "env CERTFQDN=%s%s %s x509 -req"
-                   " -days 365 -in %s/private/%s.csr"
-                   " -CA %s/ca.crt -CAkey %s/private/ca.key -CAcreateserial"
-                   " -extfile %s -extensions x509v3_FQDN -out %s/%s.crt"
-                   " -passin file:%s", name, envargs, PATH_OPENSSL,
-                   ca->sslpath, keyname, ca->sslpath, ca->sslpath,
-                   ca->extcnf, ca->sslpath, keyname, ca->passfile);
-       } else
-               err(1, "unknown host type %d", type);
+               ca_setenv("$ENV::CERTFQDN", name);
+               extensions = "x509v3_FQDN";
+       } else {
+               errx(1, "unknown host type %d", type);
+       }
+
+       ca_setcnf(ca, keyname);
+
+       snprintf(cmd, sizeof(cmd), "%s x509 -req"
+           " -days 365 -in %s/private/%s.csr"
+           " -CA %s/ca.crt -CAkey %s/private/ca.key -CAcreateserial"
+           " -extfile %s -extensions %s -out %s/%s.crt"
+           " -passin file:%s",
+           PATH_OPENSSL,
+           ca->sslpath, keyname, ca->sslpath, ca->sslpath,
+           ca->extcnf, extensions, ca->sslpath, keyname, ca->passfile);
 
        system(cmd);
 
@@ -229,16 +258,20 @@ ca_sign(struct ca *ca, char *keyname, in
 int
 ca_certificate(struct ca *ca, char *keyname, int type, int action)
 {
-       char    *envargs = "";
+       ca_clrenv();
 
        switch (action) {
        case CA_SERVER:
-               envargs = " EXTCERTUSAGE=serverAuth NSCERTTYPE=server"
-                   " CERTUSAGE=digitalSignature,keyEncipherment";
+               ca_setenv("$ENV::EXTCERTUSAGE", "serverAuth");
+               ca_setenv("$ENV::NSCERTTYPE", "server");
+               ca_setenv("$ENV::CERTUSAGE",
+                   "digitalSignature,keyEncipherment");
                break;
        case CA_CLIENT:
-               envargs = " EXTCERTUSAGE=clientAuth NSCERTTYPE=client"
-                   " CERTUSAGE=digitalSignature,keyAgreement";
+               ca_setenv("$ENV::EXTCERTUSAGE", "clientAuth");
+               ca_setenv("$ENV::NSCERTTYPE", "client");
+               ca_setenv("$ENV::CERTUSAGE",
+                   "digitalSignature,keyAgreement");
                break;
        default:
                break;
@@ -246,7 +279,7 @@ ca_certificate(struct ca *ca, char *keyn
 
        ca_key_create(ca, keyname);
        ca_request(ca, keyname);
-       ca_sign(ca, keyname, type, envargs);
+       ca_sign(ca, keyname, type);
 
        return (0);
 }
@@ -352,6 +385,8 @@ ca_create(struct ca *ca)
        char                     cmd[PATH_MAX * 2];
        char                     path[PATH_MAX];
 
+       ca_clrenv();
+
        snprintf(path, sizeof(path), "%s/private/ca.key", ca->sslpath);
        snprintf(cmd, sizeof(cmd), "%s genrsa -aes256 -out"
            " %s -passout file:%s 2048", PATH_OPENSSL,
@@ -359,8 +394,11 @@ ca_create(struct ca *ca)
        system(cmd);
        chmod(path, 0600);
 
+       ca_setenv("$ENV::CERT_CN", "VPN CA");
+       ca_setcnf(ca, "ca");
+
        snprintf(path, sizeof(path), "%s/private/ca.csr", ca->sslpath);
-       snprintf(cmd, sizeof(cmd), "env CERT_CN='VPN CA' %s req %s-new"
+       snprintf(cmd, sizeof(cmd), "%s req %s-new"
            " -key %s/private/ca.key"
            " -config %s -out %s -passin file:%s", PATH_OPENSSL,
            ca->batch, ca->sslpath, ca->sslcnf, path, ca->passfile);
@@ -489,6 +527,47 @@ fcopy(char *src, char *dst, mode_t mode)
 }
 
 int
+fcopy_env(const char *src, const char *dst, mode_t mode)
+{
+       int              ofd = -1, i;
+       u_int8_t         buf[BUFSIZ];
+       ssize_t          r = -1, len;
+       FILE            *ifp = NULL;
+       int              saved_errno;
+
+       if ((ifp = fopen(src, "r")) == NULL)
+               err(1, "fopen %s", src);
+
+       if ((ofd = open(dst, O_WRONLY|O_CREAT|O_TRUNC, mode)) == -1)
+               goto done;
+
+       while (fgets(buf, sizeof(buf), ifp) != NULL) {
+               for (i = 0; ca_env[i][0] != NULL; i++) {
+                       if (ca_env[i][1] == NULL)
+                               continue;
+                       if (expand_string(buf, sizeof(buf),
+                           ca_env[i][0], ca_env[i][1]) == -1)
+                               errx(1, "env %s value too long", ca_env[i][0]);
+               }
+               len = strlen(buf);
+               if (write(ofd, buf, len) != len)
+                       goto done;
+       }
+
+       r = 0;
+
+ done:
+       saved_errno = errno;
+       close(ofd);
+       if (ifp != NULL)
+               fclose(ifp);
+       if (r == -1)
+               errc(1, saved_errno, "open %s", dst);
+
+       return (0);
+}
+
+int
 rm_dir(char *path)
 {
        FTS             *fts;
@@ -561,7 +640,7 @@ ca_export(struct ca *ca, char *keyname, 
 
        if (keyname != NULL) {
                if (strlcpy(oname, keyname, sizeof(oname)) >= sizeof(oname))
-                       err(1, "name too long");
+                       errx(1, "name too long");
        } else {
                strlcpy(oname, "ca", sizeof(oname));
        }
@@ -683,7 +762,7 @@ ca_export(struct ca *ca, char *keyname, 
                                    de->d_name);
                                snprintf(dst, sizeof(dst), "%s/export/%s", p,
                                    de->d_name);
-                               fcopy(src, dst, 644);
+                               fcopy(src, dst, 0644);
                        }
                        closedir(dexp);
                }
@@ -742,6 +821,7 @@ ca_revoke(struct ca *ca, char *keyname)
        struct stat      st;
        char             cmd[PATH_MAX * 2];
        char             path[PATH_MAX];
+       char             cadb[PATH_MAX];
        int              fd;
        char            *pass;
        size_t           len;
@@ -758,7 +838,7 @@ ca_revoke(struct ca *ca, char *keyname)
        snprintf(path, sizeof(path), "%s/ikeca.passwd", ca->sslpath);
        pass = ca_readpass(path, &len);
        if (pass == NULL)
-               err(1, "could not open passphrase file");
+               errx(1, "could not open passphrase file");
 
        /* create index if it doesn't already exist */
        snprintf(path, sizeof(path), "%s/index.txt", ca->sslpath);
@@ -771,27 +851,31 @@ ca_revoke(struct ca *ca, char *keyname)
                        err(1, "could not access %s", path);
        }
 
+       snprintf(cadb, sizeof(cadb), "%s/index.txt", ca->sslpath);
+       ca_setenv("$ENV::CADB", cadb);
+       ca_setcnf(ca, "ca-revoke");
+
        if (keyname) {
-               snprintf(cmd, sizeof(cmd), "env CADB='%s/index.txt' "
-                   " %s ca %s-config %s -keyfile %s/private/ca.key"
+               snprintf(cmd, sizeof(cmd),
+                   "%s ca %s-config %s -keyfile %s/private/ca.key"
                    " -key %s"
                    " -cert %s/ca.crt"
                    " -md sha1"
                    " -revoke %s/%s.crt",
-                   ca->sslpath, PATH_OPENSSL, ca->batch, ca->sslcnf,
+                   PATH_OPENSSL, ca->batch, ca->sslcnf,
                    ca->sslpath, pass, ca->sslpath, ca->sslpath, keyname);
                system(cmd);
        }
 
-       snprintf(cmd, sizeof(cmd), "env CADB='%s/index.txt' "
-           " %s ca %s-config %s -keyfile %s/private/ca.key"
+       snprintf(cmd, sizeof(cmd),
+           "%s ca %s-config %s -keyfile %s/private/ca.key"
            " -key %s"
            " -gencrl"
            " -cert %s/ca.crt"
            " -md sha1"
            " -crldays 365"
            " -out %s/ca.crl",
-           ca->sslpath, PATH_OPENSSL, ca->batch, ca->sslcnf, ca->sslpath,
+           PATH_OPENSSL, ca->batch, ca->sslcnf, ca->sslpath,
            pass, ca->sslpath, ca->sslpath);
        system(cmd);
 
@@ -801,6 +885,53 @@ ca_revoke(struct ca *ca, char *keyname)
        return (0);
 }
 
+void
+ca_clrenv(void)
+{
+       int      i;
+       for (i = 0; ca_env[i][0] != NULL; i++)
+               ca_env[i][1] = NULL;
+}
+
+void
+ca_setenv(const char *key, const char *value)
+{
+       int      i;
+
+       for (i = 0; ca_env[i][0] != NULL; i++) {
+               if (strcmp(ca_env[i][0], key) == 0) {
+                       if (ca_env[i][1] != NULL)
+                               errx(1, "env %s already set: %s", key, value);
+                       ca_env[i][1] = value;
+                       return;
+               }
+       }
+       errx(1, "env %s invalid", key);
+}
+
+void
+ca_setcnf(struct ca *ca, const char *keyname)
+{
+       struct stat      st;
+       const char      *extcnf, *sslcnf;
+
+       if (stat(IKECA_CNF, &st) == 0) {
+               extcnf = IKECA_CNF;
+               sslcnf = IKECA_CNF;
+       } else {
+               extcnf = X509_CNF;
+               sslcnf = SSL_CNF;
+       }
+
+       snprintf(ca->extcnf, sizeof(ca->extcnf), "%s/%s-ext.cnf",
+           ca->sslpath, keyname);
+       snprintf(ca->sslcnf, sizeof(ca->sslcnf), "%s/%s-ssl.cnf",
+           ca->sslpath, keyname);
+
+       fcopy_env(extcnf, ca->extcnf, 0400);
+       fcopy_env(sslcnf, ca->sslcnf, 0400);
+}
+
 struct ca *
 ca_setup(char *caname, int create, int quiet, char *pass)
 {
@@ -821,14 +952,6 @@ ca_setup(char *caname, int create, int q
 
        if (quiet)
                strlcpy(ca->batch, "-batch ", sizeof(ca->batch));
-
-       if (stat(IKECA_CNF, &st) == 0) {
-               strlcpy(ca->extcnf, IKECA_CNF, sizeof(ca->extcnf));
-               strlcpy(ca->sslcnf, IKECA_CNF, sizeof(ca->sslcnf));
-       } else {
-               strlcpy(ca->extcnf, X509_CNF, sizeof(ca->extcnf));
-               strlcpy(ca->sslcnf, SSL_CNF, sizeof(ca->sslcnf));
-       }
 
        if (create == 0 && stat(ca->sslpath, &st) == -1) {
                free(ca->caname);

Reply via email to