From 46b04df6d6d47c2e2dc6a96e40e8382808733874 Mon Sep 17 00:00:00 2001 From: Jonathan Gray Date: Thu, 10 Jun 2010 16:14:05 +0000 Subject: Add a command to revoke a certificate and generate a CRL; make the ca install command install the CRL as well. discussed with reyk@ --- usr.sbin/ikectl/ikeca.c | 113 ++++++++++++++++++++++++++++++++++++++++++++-- usr.sbin/ikectl/ikeca.cnf | 10 +++- usr.sbin/ikectl/ikectl.8 | 8 +++- usr.sbin/ikectl/ikectl.c | 7 ++- usr.sbin/ikectl/parser.c | 3 +- usr.sbin/ikectl/parser.h | 3 +- 6 files changed, 134 insertions(+), 10 deletions(-) diff --git a/usr.sbin/ikectl/ikeca.c b/usr.sbin/ikectl/ikeca.c index ed25f1c1931..8fd9865a4f0 100644 --- a/usr.sbin/ikectl/ikeca.c +++ b/usr.sbin/ikectl/ikeca.c @@ -1,4 +1,4 @@ -/* $OpenBSD: ikeca.c,v 1.3 2010/06/07 14:15:27 jsg Exp $ */ +/* $OpenBSD: ikeca.c,v 1.4 2010/06/10 16:14:04 jsg Exp $ */ /* $vantronix: ikeca.c,v 1.13 2010/06/03 15:52:52 reyk Exp $ */ /* @@ -73,8 +73,10 @@ int ca_certificate(struct ca *, char *, int); int ca_cert_install(struct ca *, char *); int ca_newpass(char *); int ca_export(struct ca *, char *); +int ca_revoke(struct ca *, char *); int ca_install(struct ca *); int ca_show_certs(struct ca *); +char * ca_readpass(char *, size_t *); int fcopy(char *, char *, mode_t); int rm_dir(char *); @@ -290,8 +292,16 @@ ca_install(struct ca *ca) snprintf(dst, sizeof(dst), "%s/ca/ca.crt", KEYBASE); if (fcopy(src, dst, 0644) == 0) - printf("certificate for CA '%s' installed into %s\n", ca->caname, - dst); + printf("certificate for CA '%s' installed into %s\n", + ca->caname, dst); + + snprintf(src, sizeof(src), "%s/ca.crl", ca->sslpath); + if (stat(src, &st) == 0) { + snprintf(dst, sizeof(dst), "%s/crls/ca.crl", KEYBASE); + if (fcopy(src, dst, 0644) == 0) + printf("CRL for CA '%s' installed to %s\n", + ca->caname, dst); + } return (0); } @@ -400,7 +410,8 @@ ca_export(struct ca *ca, char *keyname) char dst[PATH_MAX]; char *p; char tpl[] = "/tmp/ikectl.XXXXXXXXXX"; - const char *exdirs[] = { "/ca", "/certs", "/private", "/export" }; + const char *exdirs[] = { "/ca", "/certs", "/crls", "/private", + "/export" }; u_int i; /* colons are not valid characters in windows filenames... */ @@ -464,6 +475,12 @@ ca_export(struct ca *ca, char *keyname) snprintf(dst, sizeof(dst), "%s/certs/%s.crt", p, keyname); fcopy(src, dst, 0644); + snprintf(src, sizeof(src), "%s/ca.crl", ca->sslpath); + if (stat(src, &st) == 0) { + snprintf(dst, sizeof(dst), "%s/crls/ca.crl", p); + fcopy(src, dst, 0644); + } + snprintf(cmd, sizeof(cmd), "%s rsa -out %s/local.pub" " -in %s/private/%s.key -pubout", PATH_OPENSSL, p, ca->sslpath, keyname); @@ -500,6 +517,94 @@ ca_export(struct ca *ca, char *keyname) return (0); } +char * +ca_readpass(char *path, size_t *len) +{ + FILE *f; + char *p, *r; + + if ((f = fopen(path, "r")) == NULL) { + warn("fopen %s", path); + return (NULL); + } + + if ((p = fgetln(f, len)) != NULL) { + if ((r = malloc(*len + 1)) == NULL) + err(1, "malloc"); + memcpy(r, p, *len); + if (r[*len - 1] == '\n') + r[*len - 1] = '\0'; + else + r[*len] = '\0'; + } else + r = NULL; + + fclose(f); + + return (r); +} + +int +ca_revoke(struct ca *ca, char *keyname) +{ + struct stat st; + char cmd[PATH_MAX * 2]; + char path[PATH_MAX]; + int fd; + char *pass; + size_t len; + + snprintf(path, sizeof(path), "%s/%s.crt", + ca->sslpath, keyname); + if (stat(path, &st) != 0) { + warn("Problem with certificate for '%s'", keyname); + return (1); + } + + snprintf(path, sizeof(path), "%s/ikeca.passwd", ca->sslpath); + pass = ca_readpass(path, &len); + if (pass == NULL) + err(1, "could not open passphrase file"); + + /* create index if it doesn't already exist */ + snprintf(path, sizeof(path), "%s/index.txt", ca->sslpath); + if (stat(path, &st) != 0) { + if (errno == ENOENT) { + if ((fd = open(path, O_WRONLY | O_CREAT, 0644)) == -1) + err(1, "could not create file %s", path); + close(fd); + } else + err(1, "could not access %s", path); + } + + snprintf(cmd, sizeof(cmd), "env CADB='%s/index.txt' " + " %s ca -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); + system(cmd); + + snprintf(cmd, sizeof(cmd), "env CADB='%s/index.txt' " + " %s ca -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); + system(cmd); + + bzero(pass, len); + free(pass); + + return (0); +} + struct ca * ca_setup(char *caname, int create) { diff --git a/usr.sbin/ikectl/ikeca.cnf b/usr.sbin/ikectl/ikeca.cnf index b3651db2f97..8423518a93b 100644 --- a/usr.sbin/ikectl/ikeca.cnf +++ b/usr.sbin/ikectl/ikeca.cnf @@ -1,4 +1,4 @@ -# $OpenBSD: ikeca.cnf,v 1.1 2010/06/03 16:49:00 reyk Exp $ +# $OpenBSD: ikeca.cnf,v 1.2 2010/06/10 16:14:04 jsg Exp $ # $vantronix: ikeca.cnf,v 1.3 2010/05/31 12:26:26 reyk Exp $ RANDFILE = /dev/arandom @@ -17,6 +17,7 @@ CERTUSAGE = digitalSignature,keyCertSign,cRLSign EXTCERTUSAGE = serverAuth,clientAuth CERTIP = 0.0.0.0 CERTFQDN = nohost.nodomain +CADB = index.txt [ req ] default_bits = 2048 @@ -79,3 +80,10 @@ extendedKeyUsage=$ENV::EXTCERTUSAGE [x509v3_FQDN] subjectAltName=DNS:$ENV::CERTFQDN extendedKeyUsage=$ENV::EXTCERTUSAGE + +[ca] +default_ca = CA_default + +[CA_default] +database=$ENV::CADB + diff --git a/usr.sbin/ikectl/ikectl.8 b/usr.sbin/ikectl/ikectl.8 index 1f1d8390457..75d34fdda45 100644 --- a/usr.sbin/ikectl/ikectl.8 +++ b/usr.sbin/ikectl/ikectl.8 @@ -1,4 +1,4 @@ -.\" $OpenBSD: ikectl.8,v 1.2 2010/06/10 14:08:37 reyk Exp $ +.\" $OpenBSD: ikectl.8,v 1.3 2010/06/10 16:14:04 jsg Exp $ .\" $vantronix: ikectl.8,v 1.11 2010/06/03 15:55:51 reyk Exp $ .\" .\" Copyright (c) 2007, 2008, 2009, 2010 Reyk Floeter @@ -106,7 +106,7 @@ Create a new certificate authority with the specified Delete the certificate authority with the specified .Ar name . .It Cm ca Ar name Cm install -Install the certificate for CA +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 @@ -127,6 +127,10 @@ into the current directory for transport to other systems. Install the private and public key for .Ar host into the active configuration. +.It Cm ca Ar name Cm certificate Ar host Cm revoke +Revoke the certificate specified by +.Ar host +and generate a new Certificate Revocation List (CRL). .It Cm show Cm ca Ar name Cm certificates Display a listing of certificates associated with CA .Ar name . diff --git a/usr.sbin/ikectl/ikectl.c b/usr.sbin/ikectl/ikectl.c index 1900db3ef98..6c47bfd7cbd 100644 --- a/usr.sbin/ikectl/ikectl.c +++ b/usr.sbin/ikectl/ikectl.c @@ -1,4 +1,4 @@ -/* $OpenBSD: ikectl.c,v 1.2 2010/06/10 14:08:37 reyk Exp $ */ +/* $OpenBSD: ikectl.c,v 1.3 2010/06/10 16:14:04 jsg Exp $ */ /* * Copyright (c) 2007, 2008 Reyk Floeter @@ -54,6 +54,7 @@ struct ca *ca_setup(char *, int); int ca_create(struct ca *); int ca_certificate(struct ca *, char *, int); int ca_export(struct ca *, char *); +int ca_revoke(struct ca *, char *); int ca_delete(struct ca *); int ca_delkey(struct ca *, char *); int ca_install(struct ca *); @@ -116,6 +117,9 @@ ca_opt(struct parse_result *res) case CA_CERT_EXPORT: ca_export(ca, res->host); break; + case CA_CERT_REVOKE: + ca_revoke(ca, res->host); + break; case SHOW_CA_CERTIFICATES: ca_show_certs(ca); break; @@ -167,6 +171,7 @@ main(int argc, char *argv[]) case CA_CERT_DELETE: case CA_CERT_INSTALL: case CA_CERT_EXPORT: + case CA_CERT_REVOKE: case SHOW_CA: case SHOW_CA_CERTIFICATES: ca_opt(res); diff --git a/usr.sbin/ikectl/parser.c b/usr.sbin/ikectl/parser.c index 4aba2efa886..2a5b28535f5 100644 --- a/usr.sbin/ikectl/parser.c +++ b/usr.sbin/ikectl/parser.c @@ -1,4 +1,4 @@ -/* $OpenBSD: parser.c,v 1.2 2010/06/10 14:08:37 reyk Exp $ */ +/* $OpenBSD: parser.c,v 1.3 2010/06/10 16:14:04 jsg Exp $ */ /* * Copyright (c) 2010 Reyk Floeter @@ -124,6 +124,7 @@ static const struct token t_ca_cert_modifiers[] = { { KEYWORD, "delete", CA_CERT_DELETE, NULL }, { KEYWORD, "install", CA_CERT_INSTALL, NULL }, { KEYWORD, "export", CA_CERT_EXPORT, NULL }, + { KEYWORD, "revoke", CA_CERT_REVOKE, NULL }, { ENDTOKEN, "", NONE, NULL } }; diff --git a/usr.sbin/ikectl/parser.h b/usr.sbin/ikectl/parser.h index 851bda3f5ed..e274e0af073 100644 --- a/usr.sbin/ikectl/parser.h +++ b/usr.sbin/ikectl/parser.h @@ -1,4 +1,4 @@ -/* $OpenBSD: parser.h,v 1.2 2010/06/10 14:08:37 reyk Exp $ */ +/* $OpenBSD: parser.h,v 1.3 2010/06/10 16:14:04 jsg Exp $ */ /* * Copyright (c) 2007, 2008 Reyk Floeter @@ -41,6 +41,7 @@ enum actions { CA_CERT_DELETE, CA_CERT_INSTALL, CA_CERT_EXPORT, + CA_CERT_REVOKE, SHOW_CA, SHOW_CA_CERTIFICATES }; -- cgit v1.2.3