diff options
author | Sebastian Benoit <benno@cvs.openbsd.org> | 2017-01-21 08:41:43 +0000 |
---|---|---|
committer | Sebastian Benoit <benno@cvs.openbsd.org> | 2017-01-21 08:41:43 +0000 |
commit | 43e607fe8411e74d215bd7af59fc367cefea5c32 (patch) | |
tree | 404c4e892e528ee6a6f6077c1b5a3de14f5effed /usr.sbin | |
parent | 97f5422ef61ccb1b3307b8d097087eac5a9c5c1a (diff) |
acme-client use configuration file [1 of 5]
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.
ok florian
Diffstat (limited to 'usr.sbin')
-rw-r--r-- | usr.sbin/acme-client/Makefile | 4 | ||||
-rw-r--r-- | usr.sbin/acme-client/acme-client.1 | 69 | ||||
-rw-r--r-- | usr.sbin/acme-client/chngproc.c | 5 | ||||
-rw-r--r-- | usr.sbin/acme-client/extern.h | 19 | ||||
-rw-r--r-- | usr.sbin/acme-client/main.c | 195 | ||||
-rw-r--r-- | usr.sbin/acme-client/netproc.c | 9 | ||||
-rw-r--r-- | usr.sbin/acme-client/parse.h | 5 | ||||
-rw-r--r-- | usr.sbin/acme-client/parse.y | 22 |
8 files changed, 112 insertions, 216 deletions
diff --git a/usr.sbin/acme-client/Makefile b/usr.sbin/acme-client/Makefile index 55e0b0ed99a..31d5b2bf605 100644 --- a/usr.sbin/acme-client/Makefile +++ b/usr.sbin/acme-client/Makefile @@ -1,4 +1,4 @@ -# $OpenBSD: Makefile,v 1.6 2016/09/18 20:18:25 benno Exp $ +# $OpenBSD: Makefile,v 1.7 2017/01/21 08:41:42 benno Exp $ PROG= acme-client SRCS= acctproc.c base64.c certproc.c chngproc.c dbg.c dnsproc.c SRCS+= fileproc.c http.c jsmn.c json.c keyproc.c main.c netproc.c @@ -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 a/usr.sbin/acme-client/acme-client.1 b/usr.sbin/acme-client/acme-client.1 index 526c11f3a3e..81a77ec4e6a 100644 --- a/usr.sbin/acme-client/acme-client.1 +++ b/usr.sbin/acme-client/acme-client.1 @@ -1,4 +1,4 @@ -.\" $OpenBSD: acme-client.1,v 1.11 2016/09/15 20:44:24 jmc Exp $ +.\" $OpenBSD: acme-client.1,v 1.12 2017/01/21 08:41:42 benno Exp $ .\" .\" Copyright (c) 2016 Kristaps Dzonsons <kristaps@bsd.lv> .\" @@ -14,7 +14,7 @@ .\" ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF .\" OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. .\" -.Dd $Mdocdate: September 15 2016 $ +.Dd $Mdocdate: January 21 2017 $ .Dt ACME-CLIENT 1 .Os .Sh NAME @@ -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 a/usr.sbin/acme-client/chngproc.c b/usr.sbin/acme-client/chngproc.c index 4cb7f330f5a..5959534a081 100644 --- a/usr.sbin/acme-client/chngproc.c +++ b/usr.sbin/acme-client/chngproc.c @@ -1,4 +1,4 @@ -/* $Id: chngproc.c,v 1.7 2016/09/13 17:13:37 deraadt Exp $ */ +/* $Id: chngproc.c,v 1.8 2017/01/21 08:41:42 benno Exp $ */ /* * Copyright (c) 2016 Kristaps Dzonsons <kristaps@bsd.lv> * @@ -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 a/usr.sbin/acme-client/extern.h b/usr.sbin/acme-client/extern.h index 55d0153af6a..b8503a7a750 100644 --- a/usr.sbin/acme-client/extern.h +++ b/usr.sbin/acme-client/extern.h @@ -1,4 +1,4 @@ -/* $Id: extern.h,v 1.5 2016/09/01 12:17:00 florian Exp $ */ +/* $Id: extern.h,v 1.6 2017/01/21 08:41:42 benno Exp $ */ /* * Copyright (c) 2016 Kristaps Dzonsons <kristaps@bsd.lv> * @@ -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 a/usr.sbin/acme-client/main.c b/usr.sbin/acme-client/main.c index 7252cdbd606..9c62ca7ebbd 100644 --- a/usr.sbin/acme-client/main.c +++ b/usr.sbin/acme-client/main.c @@ -1,4 +1,4 @@ -/* $Id: main.c,v 1.14 2016/09/18 20:18:25 benno Exp $ */ +/* $Id: main.c,v 1.15 2017/01/21 08:41:42 benno Exp $ */ /* * Copyright (c) 2016 Kristaps Dzonsons <kristaps@bsd.lv> * @@ -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 a/usr.sbin/acme-client/netproc.c b/usr.sbin/acme-client/netproc.c index 24ab4bfea49..fd86d482867 100644 --- a/usr.sbin/acme-client/netproc.c +++ b/usr.sbin/acme-client/netproc.c @@ -1,4 +1,4 @@ -/* $Id: netproc.c,v 1.10 2016/10/04 15:49:42 jsing Exp $ */ +/* $Id: netproc.c,v 1.11 2017/01/21 08:41:42 benno Exp $ */ /* * Copyright (c) 2016 Kristaps Dzonsons <kristaps@bsd.lv> * @@ -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 a/usr.sbin/acme-client/parse.h b/usr.sbin/acme-client/parse.h index c727b85a37a..c5d3b65d596 100644 --- a/usr.sbin/acme-client/parse.h +++ b/usr.sbin/acme-client/parse.h @@ -1,4 +1,4 @@ -/* $OpenBSD: parse.h,v 1.1 2016/09/18 20:18:25 benno Exp $ */ +/* $OpenBSD: parse.h,v 1.2 2017/01/21 08:41:42 benno Exp $ */ /* * Copyright (c) 2016 Sebastian Benoit <benno@openbsd.org> * @@ -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 a/usr.sbin/acme-client/parse.y b/usr.sbin/acme-client/parse.y index f23219e97e5..d46c1220476 100644 --- a/usr.sbin/acme-client/parse.y +++ b/usr.sbin/acme-client/parse.y @@ -1,4 +1,4 @@ -/* $OpenBSD: parse.y,v 1.4 2017/01/05 13:53:09 krw Exp $ */ +/* $OpenBSD: parse.y,v 1.5 2017/01/21 08:41:42 benno Exp $ */ /* * Copyright (c) 2016 Kristaps Dzonsons <kristaps@bsd.lv> @@ -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)) { @@ -918,7 +920,7 @@ domain_valid(const char *cp) } int -conf_check_file(char *s) +conf_check_file(char *s, int dontstat) { struct stat st; @@ -926,6 +928,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); |