View | Details | Raw Unified | Return to bug 3198
Collapse All | Expand All

(-)a/ssh-keygen.c (-66 / +81 lines)
Lines 127-139 static char *certflags_command = NULL; Link Here
127
static char *certflags_src_addr = NULL;
127
static char *certflags_src_addr = NULL;
128
128
129
/* Arbitrary extensions specified by user */
129
/* Arbitrary extensions specified by user */
130
struct cert_userext {
130
struct cert_ext {
131
	char *key;
131
	char *key;
132
	char *val;
132
	char *val;
133
	int crit;
133
	int crit;
134
};
134
};
135
static struct cert_userext *cert_userext;
135
static struct cert_ext *cert_ext;
136
static size_t ncert_userext;
136
static size_t ncert_ext;
137
137
138
/* Conversion to/from various formats */
138
/* Conversion to/from various formats */
139
enum {
139
enum {
Lines 1579-1609 do_change_comment(struct passwd *pw, const char *identity_comment) Link Here
1579
}
1579
}
1580
1580
1581
static void
1581
static void
1582
add_flag_option(struct sshbuf *c, const char *name)
1582
cert_ext_add(const char *key, const char *value, int iscrit)
1583
{
1583
{
1584
	int r;
1584
	cert_ext = xreallocarray(cert_ext, ncert_ext + 1, sizeof(*cert_ext));
1585
1585
	cert_ext[ncert_ext].key = xstrdup(key);
1586
	debug3("%s: %s", __func__, name);
1586
	cert_ext[ncert_ext].val = value == NULL ? NULL : xstrdup(value);
1587
	if ((r = sshbuf_put_cstring(c, name)) != 0 ||
1587
	cert_ext[ncert_ext].crit = iscrit;
1588
	    (r = sshbuf_put_string(c, NULL, 0)) != 0)
1588
	ncert_ext++;
1589
		fatal("%s: buffer error: %s", __func__, ssh_err(r));
1590
}
1589
}
1591
1590
1592
static void
1591
/* qsort(3) comparison function for certificate extensions */
1593
add_string_option(struct sshbuf *c, const char *name, const char *value)
1592
static int
1593
cert_ext_cmp(const void *_a, const void *_b)
1594
{
1594
{
1595
	struct sshbuf *b;
1595
	const struct cert_ext *a = (const struct cert_ext *)_a;
1596
	const struct cert_ext *b = (const struct cert_ext *)_b;
1596
	int r;
1597
	int r;
1597
1598
1598
	debug3("%s: %s=%s", __func__, name, value);
1599
	if (a->crit != b->crit)
1599
	if ((b = sshbuf_new()) == NULL)
1600
		return (a->crit < b->crit) ? -1 : 1;
1600
		fatal("%s: sshbuf_new failed", __func__);
1601
	if ((r = strcmp(a->key, b->key)) != 0)
1601
	if ((r = sshbuf_put_cstring(b, value)) != 0 ||
1602
		return r;
1602
	    (r = sshbuf_put_cstring(c, name)) != 0 ||
1603
	if ((a->val == NULL) != (b->val == NULL))
1603
	    (r = sshbuf_put_stringb(c, b)) != 0)
1604
		return (a->val == NULL) ? -1 : 1;
1604
		fatal("%s: buffer error: %s", __func__, ssh_err(r));
1605
	if (a->val != NULL && (r = strcmp(a->val, b->val)) != 0)
1605
1606
		return r;
1606
	sshbuf_free(b);
1607
	return 0;
1607
}
1608
}
1608
1609
1609
#define OPTIONS_CRITICAL	1
1610
#define OPTIONS_CRITICAL	1
Lines 1611-1654 add_string_option(struct sshbuf *c, const char *name, const char *value) Link Here
1611
static void
1612
static void
1612
prepare_options_buf(struct sshbuf *c, int which)
1613
prepare_options_buf(struct sshbuf *c, int which)
1613
{
1614
{
1615
	struct sshbuf *b;
1614
	size_t i;
1616
	size_t i;
1617
	int r;
1618
	const struct cert_ext *ext;
1615
1619
1620
	if ((b = sshbuf_new()) == NULL)
1621
		fatal("%s: sshbuf_new failed", __func__);
1616
	sshbuf_reset(c);
1622
	sshbuf_reset(c);
1617
	if ((which & OPTIONS_CRITICAL) != 0 &&
1623
	for (i = 0; i < ncert_ext; i++) {
1618
	    certflags_command != NULL)
1624
		ext = &cert_ext[i];
1619
		add_string_option(c, "force-command", certflags_command);
1625
		if ((ext->crit && (which & OPTIONS_EXTENSIONS)) ||
1620
	if ((which & OPTIONS_EXTENSIONS) != 0 &&
1626
		    (!ext->crit && (which & OPTIONS_CRITICAL)))
1621
	    (certflags_flags & CERTOPT_X_FWD) != 0)
1622
		add_flag_option(c, "permit-X11-forwarding");
1623
	if ((which & OPTIONS_EXTENSIONS) != 0 &&
1624
	    (certflags_flags & CERTOPT_AGENT_FWD) != 0)
1625
		add_flag_option(c, "permit-agent-forwarding");
1626
	if ((which & OPTIONS_EXTENSIONS) != 0 &&
1627
	    (certflags_flags & CERTOPT_PORT_FWD) != 0)
1628
		add_flag_option(c, "permit-port-forwarding");
1629
	if ((which & OPTIONS_EXTENSIONS) != 0 &&
1630
	    (certflags_flags & CERTOPT_PTY) != 0)
1631
		add_flag_option(c, "permit-pty");
1632
	if ((which & OPTIONS_EXTENSIONS) != 0 &&
1633
	    (certflags_flags & CERTOPT_USER_RC) != 0)
1634
		add_flag_option(c, "permit-user-rc");
1635
	if ((which & OPTIONS_EXTENSIONS) != 0 &&
1636
	    (certflags_flags & CERTOPT_NO_REQUIRE_USER_PRESENCE) != 0)
1637
		add_flag_option(c, "no-touch-required");
1638
	if ((which & OPTIONS_CRITICAL) != 0 &&
1639
	    certflags_src_addr != NULL)
1640
		add_string_option(c, "source-address", certflags_src_addr);
1641
	for (i = 0; i < ncert_userext; i++) {
1642
		if ((cert_userext[i].crit && (which & OPTIONS_EXTENSIONS)) ||
1643
		    (!cert_userext[i].crit && (which & OPTIONS_CRITICAL)))
1644
			continue;
1627
			continue;
1645
		if (cert_userext[i].val == NULL)
1628
		if (ext->val == NULL) {
1646
			add_flag_option(c, cert_userext[i].key);
1629
			/* flag option */
1647
		else {
1630
			debug3("%s: %s", __func__, ext->key);
1648
			add_string_option(c, cert_userext[i].key,
1631
			if ((r = sshbuf_put_cstring(c, ext->key)) != 0 ||
1649
			    cert_userext[i].val);
1632
			    (r = sshbuf_put_string(c, NULL, 0)) != 0)
1633
				fatal("%s: buffer: %s", __func__, ssh_err(r));
1634
		} else {
1635
			/* key/value option */
1636
			debug3("%s: %s=%s", __func__, ext->key, ext->val);
1637
			sshbuf_reset(b);
1638
			if ((r = sshbuf_put_cstring(c, ext->key)) != 0 ||
1639
			    (r = sshbuf_put_cstring(b, ext->val)) != 0 ||
1640
			    (r = sshbuf_put_stringb(c, b)) != 0)
1641
				fatal("%s: buffer: %s", __func__, ssh_err(r));
1650
		}
1642
		}
1651
	}
1643
	}
1644
	sshbuf_free(b);
1645
}
1646
1647
static void
1648
finalise_cert_exts(void)
1649
{
1650
	if (certflags_command != NULL)
1651
		cert_ext_add("force-command", certflags_command, 1);
1652
	if ((certflags_flags & CERTOPT_X_FWD) != 0)
1653
		cert_ext_add("permit-X11-forwarding", NULL, 0);
1654
	if ((certflags_flags & CERTOPT_AGENT_FWD) != 0)
1655
		cert_ext_add("permit-agent-forwarding", NULL, 0);
1656
	if ((certflags_flags & CERTOPT_PORT_FWD) != 0)
1657
		cert_ext_add("permit-port-forwarding", NULL, 0);
1658
	if ((certflags_flags & CERTOPT_PTY) != 0)
1659
		cert_ext_add("permit-pty", NULL, 0);
1660
	if ((certflags_flags & CERTOPT_USER_RC) != 0)
1661
		cert_ext_add("permit-user-rc", NULL, 0);
1662
	if ((certflags_flags & CERTOPT_NO_REQUIRE_USER_PRESENCE) != 0)
1663
		cert_ext_add("no-touch-required", NULL, 0);
1664
	if (certflags_src_addr != NULL)
1665
		cert_ext_add("source-address", certflags_src_addr, 0);
1666
	if (ncert_ext > 0)
1667
		qsort(cert_ext, ncert_ext, sizeof(*cert_ext), cert_ext_cmp);
1652
}
1668
}
1653
1669
1654
static struct sshkey *
1670
static struct sshkey *
Lines 1765-1770 do_ca_sign(struct passwd *pw, const char *ca_key_path, int prefer_agent, Link Here
1765
	}
1781
	}
1766
	ca_fp = sshkey_fingerprint(ca, fingerprint_hash, SSH_FP_DEFAULT);
1782
	ca_fp = sshkey_fingerprint(ca, fingerprint_hash, SSH_FP_DEFAULT);
1767
1783
1784
	finalise_cert_exts();
1768
	for (i = 0; i < argc; i++) {
1785
	for (i = 0; i < argc; i++) {
1769
		/* Split list of principals */
1786
		/* Split list of principals */
1770
		n = 0;
1787
		n = 0;
Lines 1981-1993 add_cert_option(char *opt) Link Here
1981
		val = xstrdup(strchr(opt, ':') + 1);
1998
		val = xstrdup(strchr(opt, ':') + 1);
1982
		if ((cp = strchr(val, '=')) != NULL)
1999
		if ((cp = strchr(val, '=')) != NULL)
1983
			*cp++ = '\0';
2000
			*cp++ = '\0';
1984
		cert_userext = xreallocarray(cert_userext, ncert_userext + 1,
2001
		cert_ext_add(val, cp, iscrit);
1985
		    sizeof(*cert_userext));
2002
		free(val);
1986
		cert_userext[ncert_userext].key = val;
1987
		cert_userext[ncert_userext].val = cp == NULL ?
1988
		    NULL : xstrdup(cp);
1989
		cert_userext[ncert_userext].crit = iscrit;
1990
		ncert_userext++;
1991
	} else
2003
	} else
1992
		fatal("Unsupported certificate option \"%s\"", opt);
2004
		fatal("Unsupported certificate option \"%s\"", opt);
1993
}
2005
}
Lines 1995-2001 add_cert_option(char *opt) Link Here
1995
static void
2007
static void
1996
show_options(struct sshbuf *optbuf, int in_critical)
2008
show_options(struct sshbuf *optbuf, int in_critical)
1997
{
2009
{
1998
	char *name, *arg;
2010
	char *name, *arg, *hex;
1999
	struct sshbuf *options, *option = NULL;
2011
	struct sshbuf *options, *option = NULL;
2000
	int r;
2012
	int r;
2001
2013
Lines 2024-2034 show_options(struct sshbuf *optbuf, int in_critical) Link Here
2024
				    __func__, ssh_err(r));
2036
				    __func__, ssh_err(r));
2025
			printf(" %s\n", arg);
2037
			printf(" %s\n", arg);
2026
			free(arg);
2038
			free(arg);
2027
		} else {
2039
		} else if (sshbuf_len(option) > 0) {
2028
			printf(" UNKNOWN OPTION (len %zu)\n",
2040
			hex = sshbuf_dtob16(option);
2029
			    sshbuf_len(option));
2041
			printf(" UNKNOWN OPTION: %s (len %zu)\n",
2042
			    hex, sshbuf_len(option));
2030
			sshbuf_reset(option);
2043
			sshbuf_reset(option);
2031
		}
2044
			free(hex);
2045
		} else
2046
			printf(" UNKNOWN FLAG OPTION\n");
2032
		free(name);
2047
		free(name);
2033
		if (sshbuf_len(option) != 0)
2048
		if (sshbuf_len(option) != 0)
2034
			fatal("Option corrupt: extra data at end");
2049
			fatal("Option corrupt: extra data at end");

Return to bug 3198