summaryrefslogtreecommitdiff
path: root/usr.sbin/ikectl
diff options
context:
space:
mode:
authorReyk Floeter <reyk@cvs.openbsd.org>2010-10-07 12:23:15 +0000
committerReyk Floeter <reyk@cvs.openbsd.org>2010-10-07 12:23:15 +0000
commit6a36f6dbb48252c868a2ca2d3596e1fd4cf8fb5e (patch)
treecc23eff6fc4990352eac993e6d11b9379b07bdc0 /usr.sbin/ikectl
parent14ffeff175a8de445d01cb7dc7e3ddd49b610b9b (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.c106
-rw-r--r--usr.sbin/ikectl/ikectl.826
-rw-r--r--usr.sbin/ikectl/ikectl.c33
-rw-r--r--usr.sbin/ikectl/parser.c34
-rw-r--r--usr.sbin/ikectl/parser.h26
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 */