diff options
author | Reyk Floeter <reyk@cvs.openbsd.org> | 2010-10-07 12:23:15 +0000 |
---|---|---|
committer | Reyk Floeter <reyk@cvs.openbsd.org> | 2010-10-07 12:23:15 +0000 |
commit | 6a36f6dbb48252c868a2ca2d3596e1fd4cf8fb5e (patch) | |
tree | cc23eff6fc4990352eac993e6d11b9379b07bdc0 /usr.sbin/ikectl | |
parent | 14ffeff175a8de445d01cb7dc7e3ddd49b610b9b (diff) |
- add a -q (quiet) command line option that will be used by ikeca to
set openssl batch mode: don't ask for x509 options, use the defaults.
- allow to specify the initial ca password on the command line to also
make it scriptable.
- allow to create certificates for clientAuth or serverAuth only
(eg. ikectl ca foo certificate bar server).
- cosmetics: move double declarations of ca_*() functions to parser.h.
ok phessler@
Diffstat (limited to 'usr.sbin/ikectl')
-rw-r--r-- | usr.sbin/ikectl/ikeca.c | 106 | ||||
-rw-r--r-- | usr.sbin/ikectl/ikectl.8 | 26 | ||||
-rw-r--r-- | usr.sbin/ikectl/ikectl.c | 33 | ||||
-rw-r--r-- | usr.sbin/ikectl/parser.c | 34 | ||||
-rw-r--r-- | usr.sbin/ikectl/parser.h | 26 |
5 files changed, 152 insertions, 73 deletions
diff --git a/usr.sbin/ikectl/ikeca.c b/usr.sbin/ikectl/ikeca.c index 9acf82b2309..99db0c35914 100644 --- a/usr.sbin/ikectl/ikeca.c +++ b/usr.sbin/ikectl/ikeca.c @@ -1,4 +1,4 @@ -/* $OpenBSD: ikeca.c,v 1.11 2010/10/07 10:56:22 phessler Exp $ */ +/* $OpenBSD: ikeca.c,v 1.12 2010/10/07 12:23:14 reyk Exp $ */ /* $vantronix: ikeca.c,v 1.13 2010/06/03 15:52:52 reyk Exp $ */ /* @@ -52,25 +52,13 @@ struct ca { char passfile[PATH_MAX]; char sslcnf[PATH_MAX]; char extcnf[PATH_MAX]; + char batch[PATH_MAX]; char *caname; }; -struct ca *ca_setup(char *, int); -int ca_create(struct ca *); -int ca_delete(struct ca *); -int ca_delkey(struct ca *, char *); -int ca_sign(struct ca *, char *, int); -int ca_request(char *, char *, char *); -int ca_certificate(struct ca *, char *, int); -int ca_cert_install(struct ca *, char *); -int ca_key_install(struct ca *, char *); -int ca_key_create(struct ca *, char *); -int ca_key_delete(struct ca *, char *); -int ca_key_import(struct ca *, char *, char *); -int ca_newpass(char *); -int ca_export(struct ca *, char *, char *); -int ca_revoke(struct ca *, char *); -int ca_install(struct ca *); +int ca_sign(struct ca *, char *, int, char *); +int ca_request(struct ca *, char *); +int ca_newpass(char *, char *); int ca_show_certs(struct ca *); char * ca_readpass(char *, size_t *); int fcopy(char *, char *, mode_t); @@ -154,15 +142,17 @@ ca_delkey(struct ca *ca, char *keyname) } int -ca_request(char *sslpath, char *sslcnf, char *keyname) +ca_request(struct ca *ca, char *keyname) { char cmd[PATH_MAX * 2]; char path[PATH_MAX]; - snprintf(path, sizeof(path), "%s/private/%s.csr", sslpath, keyname); - snprintf(cmd, sizeof(cmd), "env CERT_CN=%s %s req -new" + snprintf(path, sizeof(path), "%s/private/%s.csr", ca->sslpath, keyname); + snprintf(cmd, sizeof(cmd), "env CERT_CN=%s %s req %s-new" " -key %s/private/%s.key -out %s -config %s", - keyname, PATH_OPENSSL, sslpath, keyname, path, sslcnf); + keyname, PATH_OPENSSL, ca->batch, ca->sslpath, keyname, + path, ca->sslcnf); + system(cmd); chmod(path, 0600); @@ -170,7 +160,7 @@ ca_request(char *sslpath, char *sslcnf, char *keyname) } int -ca_sign(struct ca *ca, char *keyname, int type) +ca_sign(struct ca *ca, char *keyname, int type, char *envargs) { char cmd[PATH_MAX * 2]; char hostname[MAXHOSTNAMELEN]; @@ -178,27 +168,30 @@ ca_sign(struct ca *ca, char *keyname, int type) strlcpy(name, keyname, sizeof(name)); + if (envargs == NULL) + envargs = ""; + if (type == HOST_IPADDR) { - snprintf(cmd, sizeof(cmd), "env CERTIP=%s %s x509 -req" + 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, PATH_OPENSSL, ca->sslpath, - keyname, ca->sslpath, ca->sslpath, ca->extcnf, ca->sslpath, - keyname, ca->passfile); + " -passin file:%s", name, envargs, PATH_OPENSSL, + ca->sslpath, keyname, ca->sslpath, ca->sslpath, + ca->extcnf, ca->sslpath, keyname, ca->passfile); } 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 x509 -req" + 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, PATH_OPENSSL, ca->sslpath, - keyname, ca->sslpath, ca->sslpath, ca->extcnf, ca->sslpath, - keyname, ca->passfile); + " -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); @@ -208,11 +201,24 @@ ca_sign(struct ca *ca, char *keyname, int type) } int -ca_certificate(struct ca *ca, char *keyname, int type) +ca_certificate(struct ca *ca, char *keyname, int type, int action) { + char *envargs = ""; + + switch (action) { + case CA_SERVER: + envargs = " EXTCERTUSAGE=serverAuth"; + break; + case CA_CLIENT: + envargs = " EXTCERTUSAGE=clientAuth"; + break; + default: + break; + } + ca_key_create(ca, keyname); - ca_request(ca->sslpath, ca->sslcnf, keyname); - ca_sign(ca, keyname, type); + ca_request(ca, keyname); + ca_sign(ca, keyname, type, envargs); return (0); } @@ -264,12 +270,17 @@ ca_cert_install(struct ca *ca, char *keyname) } int -ca_newpass(char *passfile) +ca_newpass(char *passfile, char *password) { FILE *f; char *pass; char prev[_PASSWORD_LEN + 1]; + if (password != NULL) { + pass = password; + goto done; + } + pass = getpass("CA passphrase:"); if (pass == NULL || *pass == '\0') err(1, "password not set"); @@ -279,6 +290,7 @@ ca_newpass(char *passfile) if (pass == NULL || strcmp(prev, pass) != 0) errx(1, "passphrase does not match!"); + done: if ((f = fopen(passfile, "wb")) == NULL) err(1, "could not open passfile %s", passfile); chmod(passfile, 0600); @@ -304,10 +316,10 @@ ca_create(struct ca *ca) chmod(path, 0600); snprintf(path, sizeof(path), "%s/private/ca.csr", ca->sslpath); - snprintf(cmd, sizeof(cmd), "env CERT_CN='VPN CA' %s req -new" + snprintf(cmd, sizeof(cmd), "env CERT_CN='VPN CA' %s req %s-new" " -key %s/private/ca.key" - " -config %s -out %s -passin file:%s", - PATH_OPENSSL, ca->sslpath, ca->sslcnf, path, ca->passfile); + " -config %s -out %s -passin file:%s", PATH_OPENSSL, + ca->batch, ca->sslpath, ca->sslcnf, path, ca->passfile); system(cmd); chmod(path, 0600); @@ -682,26 +694,26 @@ ca_revoke(struct ca *ca, char *keyname) if (keyname) { snprintf(cmd, sizeof(cmd), "env CADB='%s/index.txt' " - " %s ca -config %s -keyfile %s/private/ca.key" + " %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->sslcnf, ca->sslpath, pass, - ca->sslpath, ca->sslpath, keyname); + ca->sslpath, 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 -config %s -keyfile %s/private/ca.key" + " %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->sslcnf, ca->sslpath, pass, - ca->sslpath, ca->sslpath); + ca->sslpath, PATH_OPENSSL, ca->batch, ca->sslcnf, ca->sslpath, + pass, ca->sslpath, ca->sslpath); system(cmd); bzero(pass, len); @@ -711,7 +723,7 @@ ca_revoke(struct ca *ca, char *keyname) } struct ca * -ca_setup(char *caname, int create) +ca_setup(char *caname, int create, int quiet, char *pass) { struct stat st; struct ca *ca; @@ -727,10 +739,12 @@ ca_setup(char *caname, int create) ca->caname = strdup(caname); strlcpy(ca->sslpath, "/etc/ssl/", sizeof(ca->sslpath)); strlcat(ca->sslpath, caname, sizeof(ca->sslpath)); - strlcpy(ca->passfile, ca->sslpath, sizeof(ca->passfile)); strlcat(ca->passfile, "/ikeca.passwd", sizeof(ca->passfile)); + 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)); @@ -753,7 +767,7 @@ ca_setup(char *caname, int create) err(1, "failed to create dir %s", path); if (stat(ca->passfile, &st) == -1 && errno == ENOENT) - ca_newpass(ca->passfile); + ca_newpass(ca->passfile, pass); arc4random_buf(rnd, sizeof(rnd)); RAND_seed(rnd, sizeof(rnd)); diff --git a/usr.sbin/ikectl/ikectl.8 b/usr.sbin/ikectl/ikectl.8 index 57d88121a2d..2bbe19c0c46 100644 --- a/usr.sbin/ikectl/ikectl.8 +++ b/usr.sbin/ikectl/ikectl.8 @@ -1,4 +1,4 @@ -.\" $OpenBSD: ikectl.8,v 1.9 2010/10/01 07:08:25 jmc Exp $ +.\" $OpenBSD: ikectl.8,v 1.10 2010/10/07 12:23:14 reyk Exp $ .\" $vantronix: ikectl.8,v 1.11 2010/06/03 15:55:51 reyk Exp $ .\" .\" Copyright (c) 2007, 2008, 2009, 2010 Reyk Floeter <reyk@vantronix.net> @@ -15,7 +15,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: October 1 2010 $ +.Dd $Mdocdate: October 7 2010 $ .Dt IKECTL 8 .Os .Sh NAME @@ -23,6 +23,7 @@ .Nd control the IKEv2 daemon .Sh SYNOPSIS .Nm +.Op Fl q .Op Fl s Ar socket .Ar command .Op Ar arg ... @@ -36,6 +37,8 @@ authority (CA) for IKEv2 peers. .Pp The options are as follows: .Bl -tag -width Ds +.It Fl q +Don't ask for confirmation of any default options. .It Fl s Ar socket Use .Ar socket @@ -99,9 +102,16 @@ and its peers. .Pp The following commands are available to control the CA: .Bl -tag -width Ds -.It Cm ca Ar name Cm create +.It Cm ca Ar name Cm create Op Ar password Create a new certificate authority with the specified .Ar name . +The command will prompt for a CA password unless it is specified with +the optional +.Ar password +argument. +The password will be saved in a protected file +.Pa ikeca.passwd +in the CA directory and used for subsequent commands. .It Cm ca Ar name Cm delete Delete the certificate authority with the specified .Ar name . @@ -126,11 +136,19 @@ and included in the archives. Install the certificate and Certificate Revocation List (CRL) for CA .Ar name as the currently active CA. -.It Cm ca Ar name Cm certificate Ar host Cm create +.It Cm ca Ar name Cm certificate Ar host Cm create Op Ic server \*(Ba client Create a private key and certificate for .Ar host and sign then with the key of certificate authority with the specified .Ar name . +.Pp +The certificate will be valid for client and server authentication by +default by setting both flags as the extended key usage in the certificate; +this can be restricted using the optional +.Ic server +or +.Ic client +argument. .It Cm ca Ar name Cm certificate Ar host Cm delete Deletes the private key and and certificates associated with .Ar host . diff --git a/usr.sbin/ikectl/ikectl.c b/usr.sbin/ikectl/ikectl.c index c1a169ec08f..3e82584180e 100644 --- a/usr.sbin/ikectl/ikectl.c +++ b/usr.sbin/ikectl/ikectl.c @@ -1,4 +1,4 @@ -/* $OpenBSD: ikectl.c,v 1.5 2010/06/23 16:01:01 jsg Exp $ */ +/* $OpenBSD: ikectl.c,v 1.6 2010/10/07 12:23:14 reyk Exp $ */ /* * Copyright (c) 2007, 2008 Reyk Floeter <reyk@vantronix.net> @@ -50,20 +50,6 @@ void monitor_id(struct imsg *); int monitor(struct imsg *); int ca_opt(struct parse_result *); -struct ca *ca_setup(char *, int); -int ca_create(struct ca *); -int ca_certificate(struct ca *, char *, int); -int ca_export(struct ca *, char *, char *); -int ca_revoke(struct ca *, char *); -int ca_delete(struct ca *); -int ca_delkey(struct ca *, char *); -int ca_install(struct ca *); -int ca_cert_install(struct ca *, char *); -int ca_show_certs(struct ca *); -int ca_key_create(struct ca *, char *); -int ca_key_delete(struct ca *, char *); -int ca_key_install(struct ca *, char *); -int ca_key_import(struct ca *, char *, char *); struct imsgname imsgs[] = { { IMSG_CTL_OK, "ok", NULL }, @@ -95,7 +81,8 @@ ca_opt(struct parse_result *res) { struct ca *ca; - ca = ca_setup(res->caname, (res->action == CA_CREATE)); + ca = ca_setup(res->caname, (res->action == CA_CREATE), + res->quiet, res->pass); if (ca == NULL) errx(1, "ca_setup failed"); @@ -113,7 +100,9 @@ ca_opt(struct parse_result *res) ca_export(ca, NULL, res->peer); break; case CA_CERT_CREATE: - ca_certificate(ca, res->host, res->htype); + case CA_SERVER: + case CA_CLIENT: + ca_certificate(ca, res->host, res->htype, res->action); break; case CA_CERT_DELETE: ca_delkey(ca, res->host); @@ -160,13 +149,17 @@ main(int argc, char *argv[]) int n; int ch; int v = 0; + int quiet = 0; const char *sock = IKED_SOCKET; if ((env = calloc(1, sizeof(struct snmpd *))) == NULL) err(1, "calloc"); - while ((ch = getopt(argc, argv, "s:")) != -1) { + while ((ch = getopt(argc, argv, "qs:")) != -1) { switch (ch) { + case 'q': + quiet = 1; + break; case 's': sock = optarg; break; @@ -182,12 +175,16 @@ main(int argc, char *argv[]) if ((res = parse(argc, argv)) == NULL) exit(1); + res->quiet = quiet; + switch (res->action) { case CA_CREATE: case CA_DELETE: case CA_INSTALL: case CA_EXPORT: case CA_CERT_CREATE: + case CA_CLIENT: + case CA_SERVER: case CA_CERT_DELETE: case CA_CERT_INSTALL: case CA_CERT_EXPORT: diff --git a/usr.sbin/ikectl/parser.c b/usr.sbin/ikectl/parser.c index c82e3d071b4..752c775c4d4 100644 --- a/usr.sbin/ikectl/parser.c +++ b/usr.sbin/ikectl/parser.c @@ -1,4 +1,4 @@ -/* $OpenBSD: parser.c,v 1.5 2010/06/23 16:01:01 jsg Exp $ */ +/* $OpenBSD: parser.c,v 1.6 2010/10/07 12:23:14 reyk Exp $ */ /* * Copyright (c) 2010 Reyk Floeter <reyk@vantronix.net> @@ -44,7 +44,8 @@ enum token_type { CANAME, PEER, ADDRESS, - FQDN + FQDN, + PASSWORD }; struct token { @@ -59,9 +60,11 @@ static const struct token t_reset[]; static const struct token t_log[]; static const struct token t_load[]; static const struct token t_ca[]; +static const struct token t_ca_pass[]; static const struct token t_ca_ex_peer[]; static const struct token t_ca_modifiers[]; static const struct token t_ca_cert[]; +static const struct token t_ca_cert_extusage[]; static const struct token t_ca_cert_ex_peer[]; static const struct token t_ca_cert_modifiers[]; static const struct token t_ca_key[]; @@ -112,7 +115,7 @@ static const struct token t_ca[] = { }; static const struct token t_ca_modifiers[] = { - { KEYWORD, "create", CA_CREATE, NULL }, + { KEYWORD, "create", CA_CREATE, t_ca_pass }, { KEYWORD, "delete", CA_DELETE, NULL }, { KEYWORD, "install", CA_INSTALL, NULL }, { KEYWORD, "certificate", CA_CERTIFICATE, t_ca_cert }, @@ -121,6 +124,12 @@ static const struct token t_ca_modifiers[] = { { ENDTOKEN, "", NONE, NULL } }; +static const struct token t_ca_pass[] = { + { NOTOKEN, "", NONE, NULL }, + { PASSWORD, "", NONE, NULL }, + { ENDTOKEN, "", NONE, NULL }, +}; + static const struct token t_ca_ex_peer[] = { { NOTOKEN, "", NONE, NULL}, { PEER, "", NONE, NULL }, @@ -134,7 +143,7 @@ static const struct token t_ca_cert[] = { }; static const struct token t_ca_cert_modifiers[] = { - { KEYWORD, "create", CA_CERT_CREATE, NULL }, + { KEYWORD, "create", CA_CERT_CREATE, t_ca_cert_extusage }, { KEYWORD, "delete", CA_CERT_DELETE, NULL }, { KEYWORD, "install", CA_CERT_INSTALL, NULL }, { KEYWORD, "export", CA_CERT_EXPORT, t_ca_cert_ex_peer }, @@ -148,6 +157,13 @@ static const struct token t_ca_cert_ex_peer[] = { { ENDTOKEN, "", NONE, NULL }, }; +static const struct token t_ca_cert_extusage[] = { + { NOTOKEN, "", NONE, NULL}, + { KEYWORD, "server", CA_SERVER, NULL }, + { KEYWORD, "client", CA_CLIENT, NULL }, + { ENDTOKEN, "", NONE, NULL }, +}; + static const struct token t_ca_key[] = { { ADDRESS, "", NONE, t_ca_key_modifiers }, { FQDN, "", NONE, t_ca_key_modifiers }, @@ -294,6 +310,13 @@ match_token(char *word, const struct token table[]) t = &table[i]; } break; + case PASSWORD: + if (!match && word != NULL && strlen(word) > 0) { + res.pass = strdup(word); + match++; + t = &table[i]; + } + break; case ENDTOKEN: break; } @@ -331,6 +354,9 @@ show_valid_args(const struct token table[]) case CANAME: fprintf(stderr, " <caname>\n"); break; + case PASSWORD: + fprintf(stderr, " <password>\n"); + break; case PEER: fprintf(stderr, " <peer>\n"); break; diff --git a/usr.sbin/ikectl/parser.h b/usr.sbin/ikectl/parser.h index e2e9eb6742a..f89a7b20929 100644 --- a/usr.sbin/ikectl/parser.h +++ b/usr.sbin/ikectl/parser.h @@ -1,4 +1,4 @@ -/* $OpenBSD: parser.h,v 1.5 2010/06/23 16:01:01 jsg Exp $ */ +/* $OpenBSD: parser.h,v 1.6 2010/10/07 12:23:14 reyk Exp $ */ /* * Copyright (c) 2007, 2008 Reyk Floeter <reyk@vantronix.net> @@ -16,6 +16,9 @@ * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. */ +#ifndef _IKECTL_PARSER_H +#define _IKECTL_PARSER_H + enum actions { NONE, LOAD, @@ -39,6 +42,8 @@ enum actions { CA_EXPORT, CA_CERTIFICATE, CA_CERT_CREATE, + CA_SERVER, + CA_CLIENT, CA_CERT_DELETE, CA_CERT_INSTALL, CA_CERT_EXPORT, @@ -56,12 +61,31 @@ struct parse_result { struct imsgbuf *ibuf; char *filename; char *caname; + char *pass; char *host; char *peer; int htype; + int quiet; }; #define HOST_IPADDR 1 #define HOST_FQDN 2 struct parse_result *parse(int, char *[]); + +struct ca *ca_setup(char *, int, int, char *); +int ca_create(struct ca *); +int ca_certificate(struct ca *, char *, int, int); +int ca_export(struct ca *, char *, char *); +int ca_revoke(struct ca *, char *); +int ca_delete(struct ca *); +int ca_delkey(struct ca *, char *); +int ca_install(struct ca *); +int ca_cert_install(struct ca *, char *); +int ca_show_certs(struct ca *); +int ca_key_create(struct ca *, char *); +int ca_key_delete(struct ca *, char *); +int ca_key_install(struct ca *, char *); +int ca_key_import(struct ca *, char *, char *); + +#endif /* _IKECTL_PARSER_H */ |