No objection in principle.. although since some of us depend on this we
might either need warning and/or a small period of overlap where the old
stuff works and then we can move to the new stuff without things blowing
up.

On Sun, Jan 1, 2017 at 1:59 PM, Sebastian Benoit <[email protected]> wrote:

> start using the configuration file and delete command line arguments:
>
> -a agreement    -> agreement url ...
> -c certdir      -> domain certificate "path"
> -f accountkey   -> account key "path"
> -k domainkey    -> domain key "path"
> -s authority    -> sign with "name"
>
> new argument:
> -f configfile
>
> the changes needed to use the new configuration are local to main.c for
> now.
> While the configuration could be passed directly to netproc(), keyproc()
> etc,
> the diff is smaller this way.
>
> This also removes the multidir (-m) mode for now - specify different paths
> in
> each domain {} block instead.
>
> diff --git usr.sbin/acme-client/Makefile usr.sbin/acme-client/Makefile
> index 55e0b0e..eae13ed 100644
> --- usr.sbin/acme-client/Makefile
> +++ usr.sbin/acme-client/Makefile
> @@ -13,6 +13,6 @@ CFLAGS+=      -W -Wall -I${.CURDIR}
>  CFLAGS+=       -Wstrict-prototypes -Wmissing-prototypes
>  CFLAGS+=       -Wmissing-declarations
>  CFLAGS+=       -Wshadow -Wpointer-arith
> -CFLAGS+=       -Wsign-compare
> +CFLAGS+=       -Wsign-compare -Wunused
>
>  .include <bsd.prog.mk>
> diff --git usr.sbin/acme-client/acme-client.1 usr.sbin/acme-client/acme-
> client.1
> index 526c11f..6f38573 100644
> --- usr.sbin/acme-client/acme-client.1
> +++ usr.sbin/acme-client/acme-client.1
> @@ -22,15 +22,10 @@
>  .Nd ACME client
>  .Sh SYNOPSIS
>  .Nm acme-client
> -.Op Fl bFmNnrv
> -.Op Fl a Ar agreement
> +.Op Fl bFNnrv
>  .Op Fl C Ar challengedir
> -.Op Fl c Ar certdir
> -.Op Fl f Ar accountkey
> -.Op Fl k Ar domainkey
> -.Op Fl s Ar authority
> +.Op Fl f Ar configfile
>  .Ar domain
> -.Op Ar altnames
>  .Sh DESCRIPTION
>  The
>  .Nm
> @@ -39,8 +34,6 @@ Automatic Certificate Management Environment (ACME)
> client.
>  .Pp
>  The options are as follows:
>  .Bl -tag -width Ds
> -.It Fl a Ar agreement
> -Use an alternative user agreement URL.
>  .It Fl b
>  Back up all certificates in the certificate directory.
>  This only happens if a remove or replace operation is possible.
> @@ -58,67 +51,21 @@ Any given backup uses the same Epoch time for all
> three certificates.
>  If there are no certificates in place, this option does nothing.
>  .It Fl C Ar challengedir
>  The directory to register challenges.
> -.It Fl c Ar certdir
> -The directory to store public certificates.
>  .It Fl F
>  Force updating the certificate signature even if it's too soon.
> -.It Fl f Ar accountkey
> -The account private key.
> -This was either made with a previous client or with
> -.Fl n .
> -.It Fl k Ar domainkey
> -The private key for the domain.
> -This may also be created with
> -.Fl N .
> -.It Fl m
> -Append
> -.Ar domain
> -to all default paths except the challenge path
> -.Pq i.e. those that are overridden by Fl c , k , f .
> -Thus,
> -.Ar foo.com
> -as the initial domain would make the default domain private key into
> -.Pa /etc/ssl/acme/private/foo.com/privkey.pem .
> -This is useful in setups with multiple domain sets.
> +.It Fl f Ar configfile
> +Specify an alternative configuration file.
>  .It Fl N
>  Create a new RSA domain key if one does not already exist.
>  .It Fl n
>  Create a new RSA account key if one does not already exist.
>  .It Fl r
>  Revoke the X509 certificate found in the certificates.
> -.It Fl s Ar authority
> -ACME
> -.Ar authority
> -to talk to.
> -Currently the following authorities are available:
> -.Pp
> -.Bl -tag -width "letsencrypt-staging" -compact
> -.It Cm letsencrypt
> -Let's Encrypt authority
> -.It Cm letsencrypt-staging
> -Let's Encrypt staging authority
> -.El
> -.Pp
> -The default is
> -.Cm letsencrypt .
>  .It Fl v
>  Verbose operation.
>  Specify twice to also trace communication and data transfers.
>  .It Ar domain
>  The domain name.
> -The only difference between this and
> -.Ar altnames
> -is that it's put into the certificate's
> -.Li CN
> -field and it uses the
> -.Qq main
> -domain when specifying
> -.Fl m .
> -.It Ar altnames
> -Alternative names
> -.Pq Dq SAN
> -for the domain name.
> -The number of SAN entries is limited to 100 or so.
>  .El
>  .Pp
>  Public certificates are by default placed in
> @@ -175,7 +122,7 @@ as in the
>  .Sx Challenges
>  section:
>  .Pp
> -.Dl # acme-client -vNn foo.com www.foo.com smtp.foo.com
> +.Dl # acme-client -vNn www.foo.com
>  .Pp
>  A daily
>  .Xr cron 8
> @@ -183,7 +130,7 @@ job can renew the certificates:
>  .Bd -literal -offset indent
>  #! /bin/sh
>
> -acme-client foo.com www.foo.com smtp.foo.com
> +acme-client www.foo.com
>
>  if [ $? -eq 0 ]
>  then
> diff --git usr.sbin/acme-client/chngproc.c usr.sbin/acme-client/chngproc.c
> index 4cb7f33..3e931da 100644
> --- usr.sbin/acme-client/chngproc.c
> +++ usr.sbin/acme-client/chngproc.c
> @@ -27,7 +27,7 @@
>  #include "extern.h"
>
>  int
> -chngproc(int netsock, const char *root, int remote)
> +chngproc(int netsock, const char *root)
>  {
>         char             *tok = NULL, *th = NULL, *fmt = NULL, **fs = NULL;
>         size_t            i, fsz = 0;
> @@ -35,6 +35,7 @@ chngproc(int netsock, const char *root, int remote)
>         long              lval;
>         enum chngop       op;
>         void             *pp;
> +       int               remote = 0; /* XXX maybe remove */
>
>         if (chroot(root) == -1) {
>                 warn("chroot");
> diff --git usr.sbin/acme-client/extern.h usr.sbin/acme-client/extern.h
> index 55d0153..797c425 100644
> --- usr.sbin/acme-client/extern.h
> +++ usr.sbin/acme-client/extern.h
> @@ -17,6 +17,8 @@
>  #ifndef EXTERN_H
>  #define EXTERN_H
>
> +#include "parse.h"
> +
>  #define MAX_SERVERS_DNS 8
>
>  #define        CERT_PEM "cert.pem"
> @@ -145,14 +147,6 @@ enum       comm {
>         COMM__MAX
>  };
>
> -struct authority {
> -       char    *name;
> -       char    *agreement;
> -       char    *caurl;
> -};
> -
> -extern struct authority authorities[];
> -
>  /*
>   * This contains the URI and token of an ACME-issued challenge.
>   * A challenge consists of a token, which we must present on the
> @@ -187,15 +181,16 @@ __BEGIN_DECLS
>   */
>  int             acctproc(int, const char *, int);
>  int             certproc(int, int);
> -int             chngproc(int, const char *, int);
> +int             chngproc(int, const char *);
>  int             dnsproc(int);
>  int             revokeproc(int, const char *,
>                         int, int, const char *const *, size_t);
>  int             fileproc(int, int, const char *);
>  int             keyproc(int, const char *,
>                         const char **, size_t, int);
> -int             netproc(int, int, int, int, int, int, int, int, int,
> -                       const char *const *, size_t, const char *);
> +int             netproc(int, int, int, int, int, int, int, int,
> +                       struct authority_c *, const char *const *,
> +                       size_t, const char *);
>
>  /*
>   * Debugging functions.
> diff --git usr.sbin/acme-client/main.c usr.sbin/acme-client/main.c
> index 7252cdb..0d467f1 100644
> --- usr.sbin/acme-client/main.c
> +++ usr.sbin/acme-client/main.c
> @@ -28,127 +28,69 @@
>  #include "extern.h"
>  #include "parse.h"
>
> -#define SSL_DIR "/etc/ssl/acme"
> -#define SSL_PRIV_DIR "/etc/ssl/acme/private"
> -#define ETC_DIR "/etc/acme"
>  #define WWW_DIR "/var/www/acme"
> -#define PRIVKEY_FILE "privkey.pem"
> -
> -struct authority authorities[] = {
> -#define        DEFAULT_AUTHORITY 0
> -       {"letsencrypt",
> -           "https://letsencrypt.org/documents/LE-SA-v1.1.1-August-
> 1-2016.pdf",
> -           "https://acme-v01.api.letsencrypt.org/directory"},
> -       {"letsencrypt-staging",
> -           "https://letsencrypt.org/documents/LE-SA-v1.1.1-August-
> 1-2016.pdf",
> -           "https://acme-staging.api.letsencrypt.org/directory"},
> -};
> -
> -/*
> - * Wrap around asprintf(3), which sometimes nullifies the input values,
> - * sometimes not, but always returns <0 on error.
> - * Returns NULL on failure or the pointer on success.
> - */
> -static char *
> -doasprintf(const char *fmt, ...)
> -{
> -       int      c;
> -       char    *cp;
> -       va_list  ap;
> -
> -       va_start(ap, fmt);
> -       c = vasprintf(&cp, fmt, ap);
> -       va_end(ap);
> -       return (c < 0 ? NULL : cp);
> -}
> +#define CONF_FILE "/etc/acme-client.conf"
>
>  int
>  main(int argc, char *argv[])
>  {
> -       const char       *domain, *agreement = NULL, **alts = NULL;
> +       const char       **alts = NULL;
>         char             *certdir = NULL, *acctkey = NULL, *chngdir = NULL;
> -       char             *keyfile = NULL;
> +       char             *auth = NULL, *agreement = NULL;
> +       char             *conffile = CONF_FILE;
>         int               key_fds[2], acct_fds[2], chng_fds[2],
> cert_fds[2];
>         int               file_fds[2], dns_fds[2], rvk_fds[2];
> -       int               newacct = 0, remote = 0, backup = 0;
> -       int               force = 0, multidir = 0, newkey = 0;
> +       int               backup = 0;
> +       int               force = 0;
>         int               c, rc, revocate = 0;
> -       int               authority = DEFAULT_AUTHORITY;
> +       int               popts = 0;
>         pid_t             pids[COMP__MAX];
>         extern int        verbose;
>         extern enum comp  proccomp;
>         size_t            i, altsz, ne;
>
> -       while (-1 != (c = getopt(argc, argv, "bFmnNrs:tva:f:c:C:k:")))
> +       struct acme_conf        *conf = NULL;
> +       struct authority_c      *authority = NULL;
> +       struct domain_c         *domain = NULL;
> +       struct altname_c        *ac;
> +
> +       while (-1 != (c = getopt(argc, argv, "bFnNrvf:C:")))
>                 switch (c) {
> -               case 'a':
> -                       agreement = optarg;
> -                       break;
>                 case 'b':
>                         backup = 1;
>                         break;
> -               case 'c':
> -                       free(certdir);
> -                       if (NULL == (certdir = strdup(optarg)))
> -                               err(EXIT_FAILURE, "strdup");
> -                       break;
>                 case 'C':
>                         free(chngdir);
>                         if (NULL == (chngdir = strdup(optarg)))
>                                 err(EXIT_FAILURE, "strdup");
>                         break;
>                 case 'f':
> -                       free(acctkey);
> -                       if (NULL == (acctkey = strdup(optarg)))
> +                       if (NULL == (conffile = strdup(optarg)))
>                                 err(EXIT_FAILURE, "strdup");
>                         break;
>                 case 'F':
>                         force = 1;
>                         break;
> -               case 'k':
> -                       free(keyfile);
> -                       if (NULL == (keyfile = strdup(optarg)))
> -                               err(EXIT_FAILURE, "strdup");
> -                       break;
> -               case 'm':
> -                       multidir = 1;
> -                       break;
>                 case 'n':
> -                       newacct = 1;
> +                       popts |= ACME_OPT_NEWACCT;
>                         break;
>                 case 'N':
> -                       newkey = 1;
> +                       popts |= ACME_OPT_NEWDKEY;
>                         break;
>                 case 'r':
>                         revocate = 1;
>                         break;
> -               case 's':
> -                       authority = -1;
> -                       for (i = 0; i < nitems(authorities); i++) {
> -                               if (strcmp(authorities[i].name, optarg) ==
> 0) {
> -                                       authority = i;
> -                                       break;
> -                               }
> -                       }
> -                       if (-1 == authority)
> -                               errx(EXIT_FAILURE, "unknown acme
> authority");
> -                       break;
> -               case 't':
> -                       /*
> -                        / Undocumented feature.
> -                        * Don't use it.
> -                        */
> -                       remote = 1;
> -                       break;
>                 case 'v':
>                         verbose = verbose ? 2 : 1;
> +                       popts |= ACME_OPT_VERBOSE;
>                         break;
>                 default:
>                         goto usage;
>                 }
>
> -       if (NULL == agreement)
> -               agreement = authorities[authority].agreement;
> +       /* parse config file */
> +       if ((conf = parse_config(conffile, popts)) == NULL)
> +               exit(EXIT_FAILURE);
>
>         argc -= optind;
>         argv += optind;
> @@ -163,9 +105,13 @@ main(int argc, char *argv[])
>                 errx(EXIT_FAILURE, "%s: bad domain syntax", argv[i]);
>         }
>
> -       domain = argv[0];
> +       if ((domain = domain_find(conf, argv[0])) == NULL)
> +               errx(EXIT_FAILURE, "domain %s not found\n", argv[0]);
> +
>         argc--;
>         argv++;
> +       if (argc != 0)
> +               goto usage;
>
>         if (getuid() != 0)
>                 errx(EXIT_FAILURE, "must be run as root");
> @@ -173,51 +119,54 @@ main(int argc, char *argv[])
>         /*
>          * Now we allocate our directories and file paths IFF we haven't
>          * specified them on the command-line.
> -        * If we're in "multidir" (-m) mode, we use our initial domain
> -        * name when specifying the prefixes.
> -        * Otherwise, we put them all in a known location.
>          */
>
> -       if (NULL == certdir)
> -               certdir = multidir ?
> -                       doasprintf(SSL_DIR "/%s", domain) :
> -                       strdup(SSL_DIR);
> -       if (NULL == keyfile)
> -               keyfile = multidir ?
> -                       doasprintf(SSL_PRIV_DIR "/%s/"
> -                               PRIVKEY_FILE, domain) :
> -                       strdup(SSL_PRIV_DIR "/" PRIVKEY_FILE);
> -       if (NULL == acctkey)
> -               acctkey = multidir ?
> -                       doasprintf(ETC_DIR "/%s/"
> -                               PRIVKEY_FILE, domain) :
> -                       strdup(ETC_DIR "/" PRIVKEY_FILE);
> +       certdir = domain->cert;
> +
> +       if ((auth = domain->auth) == NULL) {
> +               /* use the first authority from the config as default XXX
> */
> +               authority = authority_find0(conf);
> +               if (authority == NULL)
> +                       errx(EXIT_FAILURE, "no authorities configured\n");
> +       } else {
> +               authority = authority_find(conf, auth);
> +               if (authority == NULL)
> +                       errx(EXIT_FAILURE, "authority %s not found\n",
> auth);
> +       }
> +
> +       agreement = authority->agreement;
> +       acctkey = authority->account;
> +
> +       if (NULL == acctkey) {
> +               /* XXX replace with existance check in parse.y */
> +               err(EXIT_FAILURE, "no account key in config?");
> +       }
>         if (NULL == chngdir)
>                 chngdir = strdup(WWW_DIR);
>
> -       if (NULL == certdir || NULL == keyfile ||
> -           NULL == acctkey || NULL == chngdir)
> +       if (NULL == chngdir)
>                 err(EXIT_FAILURE, "strdup");
>
>         /*
>          * Do some quick checks to see if our paths exist.
>          * This will be done in the children, but we might as well check
>          * now before the fork.
> +        * XXX maybe use conf_check_file() from parse.y
>          */
>
>         ne = 0;
>
>         if (-1 == access(certdir, R_OK)) {
> -               warnx("%s: -c directory must exist", certdir);
> +               warnx("%s: cert directory must exist", certdir);
>                 ne++;
>         }
>
> -       if (!newkey && -1 == access(keyfile, R_OK)) {
> -               warnx("%s: -k file must exist", keyfile);
> +       if (!(popts & ACME_OPT_NEWDKEY) && -1 == access(domain->key,
> R_OK)) {
> +               warnx("%s: -k file must exist", domain->key);
>                 ne++;
> -       } else if (newkey && -1 != access(keyfile, R_OK)) {
> -               dodbg("%s: domain key exists (not creating)", keyfile);
> -               newkey = 0;
> +       } else if ((popts & ACME_OPT_NEWDKEY) && -1 != access(domain->key,
> R_OK)) {
> +               dodbg("%s: domain key exists (not creating)", domain->key);
> +               popts |= ACME_OPT_NEWDKEY;
>         }
>
>         if (-1 == access(chngdir, R_OK)) {
> @@ -225,26 +174,27 @@ main(int argc, char *argv[])
>                 ne++;
>         }
>
> -       if (!newacct && -1 == access(acctkey, R_OK)) {
> +       if (!(popts & ACME_OPT_NEWACCT) && -1 == access(acctkey, R_OK)) {
>                 warnx("%s: -f file must exist", acctkey);
>                 ne++;
> -       } else if (newacct && -1 != access(acctkey, R_OK)) {
> +       } else if ((popts & ACME_OPT_NEWACCT) && -1 != access(acctkey,
> R_OK)) {
>                 dodbg("%s: account key exists (not creating)", acctkey);
> -               newacct = 0;
> +               popts |= ACME_OPT_NEWACCT;
>         }
>
>         if (ne > 0)
>                 exit(EXIT_FAILURE);
>
>         /* Set the zeroth altname as our domain. */
> -
> -       altsz = argc + 1;
> +       altsz = domain->altname_count + 1;
>         alts = calloc(altsz, sizeof(char *));
>         if (NULL == alts)
>                 err(EXIT_FAILURE, "calloc");
> -       alts[0] = domain;
> -       for (i = 0; i < (size_t)argc; i++)
> -               alts[i + 1] = argv[i];
> +       alts[0] = domain->domain;
> +       i = 1;
> +       /* XXX get rid of alts[] later */
> +       LIST_FOREACH(ac, &domain->altname_list, entry)
> +               alts[i++] = ac->domain;
>
>         /*
>          * Open channels between our components.
> @@ -283,7 +233,7 @@ main(int argc, char *argv[])
>                 c = netproc(key_fds[1], acct_fds[1],
>                     chng_fds[1], cert_fds[1],
>                     dns_fds[1], rvk_fds[1],
> -                   newacct, revocate, authority,
> +                   (popts & ACME_OPT_NEWACCT), revocate, authority,
>                     (const char *const *)alts, altsz,
>                     agreement);
>                 free(alts);
> @@ -311,8 +261,8 @@ main(int argc, char *argv[])
>                 close(chng_fds[0]);
>                 close(file_fds[0]);
>                 close(file_fds[1]);
> -               c = keyproc(key_fds[0], keyfile,
> -                   (const char **)alts, altsz, newkey);
> +               c = keyproc(key_fds[0], domain->key,
> +                   (const char **)alts, altsz, (popts &
> ACME_OPT_NEWDKEY));
>                 free(alts);
>                 exit(c ? EXIT_SUCCESS : EXIT_FAILURE);
>         }
> @@ -333,7 +283,7 @@ main(int argc, char *argv[])
>                 close(chng_fds[0]);
>                 close(file_fds[0]);
>                 close(file_fds[1]);
> -               c = acctproc(acct_fds[0], acctkey, newacct);
> +               c = acctproc(acct_fds[0], acctkey, (popts &
> ACME_OPT_NEWACCT));
>                 exit(c ? EXIT_SUCCESS : EXIT_FAILURE);
>         }
>
> @@ -352,7 +302,7 @@ main(int argc, char *argv[])
>                 close(rvk_fds[0]);
>                 close(file_fds[0]);
>                 close(file_fds[1]);
> -               c = chngproc(chng_fds[0], chngdir, remote);
> +               c = chngproc(chng_fds[0], chngdir);
>                 exit(c ? EXIT_SUCCESS : EXIT_FAILURE);
>         }
>
> @@ -447,8 +397,6 @@ main(int argc, char *argv[])
>             checkexit(pids[COMP_DNS], COMP_DNS) +
>             checkexit(pids[COMP_REVOKE], COMP_REVOKE);
>
> -       free(certdir);
> -       free(keyfile);
>         free(acctkey);
>         free(chngdir);
>         free(alts);
> @@ -456,11 +404,8 @@ main(int argc, char *argv[])
>             (2 == c ? EXIT_SUCCESS : 2));
>  usage:
>         fprintf(stderr,
> -           "usage: acme-client [-bFmnNrv] [-a agreement] [-C
> challengedir]\n"
> -           "                   [-c certdir] [-f accountkey] [-k
> domainkey]\n"
> -           "                   [-s authority] domain [altnames...]\n");
> -       free(certdir);
> -       free(keyfile);
> +           "usage: acme-client [-bFnNrv] [-C challengedir]\n"
> +           "                   [-f file] domain\n");
>         free(acctkey);
>         free(chngdir);
>         return (EXIT_FAILURE);
> diff --git usr.sbin/acme-client/netproc.c usr.sbin/acme-client/netproc.c
> index 24ab4bf..9e5a208 100644
> --- usr.sbin/acme-client/netproc.c
> +++ usr.sbin/acme-client/netproc.c
> @@ -25,6 +25,7 @@
>
>  #include "http.h"
>  #include "extern.h"
> +#include "parse.h"
>
>  #define        RETRY_DELAY 5
>  #define RETRY_MAX 10
> @@ -565,8 +566,8 @@ dofullchain(struct conn *c, const char *addr)
>   */
>  int
>  netproc(int kfd, int afd, int Cfd, int cfd, int dfd, int rfd,
> -    int newacct, int revocate, int authority, const char *const *alts,
> -    size_t altsz, const char *agreement)
> +    int newacct, int revocate, struct authority_c *authority,
> +    const char *const *alts,size_t altsz, const char *agreement)
>  {
>         int              rc = 0;
>         size_t           i;
> @@ -643,7 +644,7 @@ netproc(int kfd, int afd, int Cfd, int cfd, int dfd,
> int rfd,
>
>         c.dfd = dfd;
>         c.fd = afd;
> -       c.na = authorities[authority].caurl;
> +       c.na = authority->api;
>
>         /*
>          * Look up the domain of the ACME server.
> diff --git usr.sbin/acme-client/parse.h usr.sbin/acme-client/parse.h
> index c727b85..008a29b 100644
> --- usr.sbin/acme-client/parse.h
> +++ usr.sbin/acme-client/parse.h
> @@ -38,6 +38,7 @@ struct authority_c {
>  struct domain_c {
>         LIST_ENTRY(domain_c)     entry;
>         LIST_HEAD(, altname_c)  altname_list;
> +       int                     altname_count;
>         char                    *domain;
>         char                    *key;
>         char                    *cert;
> @@ -55,6 +56,8 @@ struct keyfile {
>  };
>
>  #define ACME_OPT_VERBOSE       0x00000001
> +#define ACME_OPT_NEWACCT       0x00000002
> +#define ACME_OPT_NEWDKEY       0x00000004
>
>  struct acme_conf {
>         int                      opts;
> diff --git usr.sbin/acme-client/parse.y usr.sbin/acme-client/parse.y
> index f562853..ef3a88b 100644
> --- usr.sbin/acme-client/parse.y
> +++ usr.sbin/acme-client/parse.y
> @@ -63,7 +63,7 @@ struct authority_c    *conf_new_authority(struct
> acme_conf *, char *);
>  struct domain_c                *conf_new_domain(struct acme_conf *, char
> *);
>  struct keyfile         *conf_new_keyfile(struct acme_conf *, char *);
>  void                    clear_config(struct acme_conf *xconf);
> -int                     conf_check_file(char *);
> +int                     conf_check_file(char *, int);
>
>  TAILQ_HEAD(symhead, sym)        symhead = TAILQ_HEAD_INITIALIZER(
> symhead);
>  struct sym {
> @@ -215,10 +215,6 @@ authorityoptsl     : AGREEMENT URL STRING {
>                         }
>                         if ((s = strdup($3)) == NULL)
>                                 err(EXIT_FAILURE, "strdup");
> -                       if (!conf_check_file(s)) {
> -                               free(s);
> -                               YYERROR;
> -                       }
>                         auth->account = s;
>                 }
>                 ;
> @@ -256,6 +252,11 @@ domainoptsl        : ALTERNATIVE NAMES '{' altname_l
> '}'
>                         }
>                         if ((s = strdup($3)) == NULL)
>                                 err(EXIT_FAILURE, "strdup");
> +                       if (!conf_check_file(s,
> +                           (conf->opts & ACME_OPT_NEWDKEY))) {
> +                               free(s);
> +                               YYERROR;
> +                       }
>                         if (((void *)conf_new_keyfile(conf, s)) == NULL) {
>                                 free(s);
>                                 yyerror("domain key file already used");
> @@ -264,7 +265,7 @@ domainoptsl : ALTERNATIVE NAMES '{' altname_l '}'
>                         domain->key = s;
>                 }
>                 | DOMAIN CERT STRING {
> -                       char            *s;
> +                       char *s;
>                         if (domain->cert != NULL) {
>                                 yyerror("duplicate cert");
>                                 YYERROR;
> @@ -318,6 +319,7 @@ altname             : STRING {
>                         }
>                         ac->domain = s;
>                         LIST_INSERT_HEAD(&domain->altname_list, ac,
> entry);
> +                       domain->altname_count++;
>                         /*
>                          * XXX we could check if altname is duplicate
>                          * or identical to domain->domain
> @@ -602,7 +604,7 @@ nodigits:
>         x != '!' && x != '=' && x != '#' && \
>         x != ','))
>
> -       if (isalnum(c) || c == ':' || c == '_' || c == '/') {
> +       if (isalnum(c) || c == ':' || c == '_') {
>                 do {
>                         *p++ = c;
>                         if ((unsigned)(p-buf) >= sizeof(buf)) {
> @@ -917,7 +919,7 @@ domain_valid(const char *cp)
>  }
>
>  int
> -conf_check_file(char *s)
> +conf_check_file(char *s, int dontstat)
>  {
>         struct stat st;
>
> @@ -925,6 +927,8 @@ conf_check_file(char *s)
>                 warnx("%s: not an absolute path", s);
>                 return (0);
>         }
> +       if (dontstat)
> +               return (1);
>         if (stat(s, &st)) {
>                 warn("cannot stat %s", s);
>                 return (0);
>
>

Reply via email to