From: djm Date: Sat, 29 Apr 2017 04:12:25 +0000 (+0000) Subject: allow ssh-keygen to include arbitrary string or flag certificate X-Git-Url: http://artulab.com/gitweb/?a=commitdiff_plain;h=c65d2f6f6fd37f5b939417ca74062bfb771c54e8;p=openbsd allow ssh-keygen to include arbitrary string or flag certificate extensions and critical options. ok markus@ dtucker@ --- diff --git a/usr.bin/ssh/ssh-keygen.1 b/usr.bin/ssh/ssh-keygen.1 index ce2213c7802..cfbd4cfa527 100644 --- a/usr.bin/ssh/ssh-keygen.1 +++ b/usr.bin/ssh/ssh-keygen.1 @@ -1,4 +1,4 @@ -.\" $OpenBSD: ssh-keygen.1,v 1.133 2016/06/16 06:10:45 jmc Exp $ +.\" $OpenBSD: ssh-keygen.1,v 1.134 2017/04/29 04:12:25 djm Exp $ .\" .\" Author: Tatu Ylonen .\" Copyright (c) 1995 Tatu Ylonen , Espoo, Finland @@ -35,7 +35,7 @@ .\" (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF .\" THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. .\" -.Dd $Mdocdate: June 16 2016 $ +.Dd $Mdocdate: April 29 2017 $ .Dt SSH-KEYGEN 1 .Os .Sh NAME @@ -474,9 +474,29 @@ The .Ar address_list is a comma-separated list of one or more address/netmask pairs in CIDR format. +.It Ic extension Ns : Ns Ar name Ns Op Ns = Ns Ar contents +Includes an arbitrary certificate extension. +.It Ic critical Ns : Ns Ar name Ns Op Ns = Ns Ar contents +Includes an arbitrary certificate critical option. .El .Pp -At present, no options are valid for host keys. +At present, no standard options are valid for host keys. +.Pp +For non-standard certificate extension or options included using +.Ic extension +or +.Ic option , +the specified +.Ar name +should include a domain suffix, e.g. +.Dq name@example.com . +If a +.Ar contents +is specified then it is included as the contents of the extension/option +encoded as a string, otherwise the extension/option is created with no +contents (usually indicating a flag). +Extensions may be ignored by a client or server that does not recognise them, +whereas unknown critical options will cause the certificate to be refused. .It Fl o Causes .Nm diff --git a/usr.bin/ssh/ssh-keygen.c b/usr.bin/ssh/ssh-keygen.c index 8784e41c868..09a75bbfb34 100644 --- a/usr.bin/ssh/ssh-keygen.c +++ b/usr.bin/ssh/ssh-keygen.c @@ -1,4 +1,4 @@ -/* $OpenBSD: ssh-keygen.c,v 1.299 2017/03/10 04:26:06 djm Exp $ */ +/* $OpenBSD: ssh-keygen.c,v 1.300 2017/04/29 04:12:25 djm Exp $ */ /* * Author: Tatu Ylonen * Copyright (c) 1994 Tatu Ylonen , Espoo, Finland @@ -143,6 +143,15 @@ u_int32_t certflags_flags = CERTOPT_DEFAULT; char *certflags_command = NULL; char *certflags_src_addr = NULL; +/* Arbitrary extensions specified by user */ +struct cert_userext { + char *key; + char *val; + int crit; +}; +struct cert_userext *cert_userext; +size_t ncert_userext; + /* Conversion to/from various formats */ int convert_to = 0; int convert_from = 0; @@ -1515,6 +1524,8 @@ add_string_option(struct sshbuf *c, const char *name, const char *value) static void prepare_options_buf(struct sshbuf *c, int which) { + size_t i; + sshbuf_reset(c); if ((which & OPTIONS_CRITICAL) != 0 && certflags_command != NULL) @@ -1537,6 +1548,17 @@ prepare_options_buf(struct sshbuf *c, int which) if ((which & OPTIONS_CRITICAL) != 0 && certflags_src_addr != NULL) add_string_option(c, "source-address", certflags_src_addr); + for (i = 0; i < ncert_userext; i++) { + if ((cert_userext[i].crit && (which & OPTIONS_EXTENSIONS)) || + (!cert_userext[i].crit && (which & OPTIONS_CRITICAL))) + continue; + if (cert_userext[i].val == NULL) + add_flag_option(c, cert_userext[i].key); + else { + add_string_option(c, cert_userext[i].key, + cert_userext[i].val); + } + } } static struct sshkey * @@ -1773,7 +1795,8 @@ parse_cert_times(char *timespec) static void add_cert_option(char *opt) { - char *val; + char *val, *cp; + int iscrit = 0; if (strcasecmp(opt, "clear") == 0) certflags_flags = 0; @@ -1813,6 +1836,18 @@ add_cert_option(char *opt) if (addr_match_cidr_list(NULL, val) != 0) fatal("Invalid source-address list"); certflags_src_addr = xstrdup(val); + } else if (strncasecmp(opt, "extension:", 10) == 0 || + (iscrit = (strncasecmp(opt, "critical:", 9) == 0))) { + val = xstrdup(strchr(opt, ':') + 1); + if ((cp = strchr(val, '=')) != NULL) + *cp++ = '\0'; + cert_userext = xreallocarray(cert_userext, ncert_userext + 1, + sizeof(*cert_userext)); + cert_userext[ncert_userext].key = val; + cert_userext[ncert_userext].val = cp == NULL ? + NULL : xstrdup(cp); + cert_userext[ncert_userext].crit = iscrit; + ncert_userext++; } else fatal("Unsupported certificate option \"%s\"", opt); }