From 672839994eaadecc95f3fada1cf014487631f068 Mon Sep 17 00:00:00 2001 From: Damien Miller Date: Fri, 16 Apr 2010 15:53:02 +1000 Subject: - djm@cvs.openbsd.org 2010/04/10 00:04:30 [sshconnect.c] fix terminology: we didn't find a certificate in known_hosts, we found a CA key --- sshconnect.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) (limited to 'sshconnect.c') diff --git a/sshconnect.c b/sshconnect.c index 9de52224d..effe6dae8 100644 --- a/sshconnect.c +++ b/sshconnect.c @@ -1,4 +1,4 @@ -/* $OpenBSD: sshconnect.c,v 1.220 2010/03/04 10:36:03 djm Exp $ */ +/* $OpenBSD: sshconnect.c,v 1.221 2010/04/10 00:04:30 djm Exp $ */ /* * Author: Tatu Ylonen * Copyright (c) 1995 Tatu Ylonen , Espoo, Finland @@ -739,7 +739,7 @@ check_host_key(char *hostname, struct sockaddr *hostaddr, u_short port, debug("Host '%.200s' is known and matches the %s host %s.", host, type, want_cert ? "certificate" : "key"); debug("Found %s in %s:%d", - want_cert ? "certificate" : "key", host_file, host_line); + want_cert ? "CA key" : "key", host_file, host_line); if (want_cert && !check_host_cert(hostname, host_key)) goto fail; if (options.check_host_ip && ip_status == HOST_NEW) { -- cgit v1.2.3 From b1b17047e39b88f640a6e55141cd1073ee6e55e4 Mon Sep 17 00:00:00 2001 From: Damien Miller Date: Fri, 16 Apr 2010 15:54:19 +1000 Subject: - djm@cvs.openbsd.org 2010/04/14 22:27:42 [ssh_config.5 sshconnect.c] expand %r => remote username in ssh_config:ProxyCommand; ok deraadt markus --- ChangeLog | 4 ++++ ssh_config.5 | 12 +++++++----- sshconnect.c | 6 +++--- 3 files changed, 14 insertions(+), 8 deletions(-) (limited to 'sshconnect.c') diff --git a/ChangeLog b/ChangeLog index 4d3d2b788..afd69b039 100644 --- a/ChangeLog +++ b/ChangeLog @@ -32,6 +32,10 @@ - djm@cvs.openbsd.org 2010/04/10 05:48:16 [mux.c] fix NULL dereference; from matthew.haub AT alumni.adelaide.edu.au + - djm@cvs.openbsd.org 2010/04/14 22:27:42 + [ssh_config.5 sshconnect.c] + expand %r => remote username in ssh_config:ProxyCommand; + ok deraadt markus 20100410 - (dtucker) [configure.ac] Put the check for the existence of getaddrinfo diff --git a/ssh_config.5 b/ssh_config.5 index 2945e48b6..3f0f537a9 100644 --- a/ssh_config.5 +++ b/ssh_config.5 @@ -34,8 +34,8 @@ .\" (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF .\" THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. .\" -.\" $OpenBSD: ssh_config.5,v 1.131 2010/03/27 14:26:55 jmc Exp $ -.Dd $Mdocdate: March 27 2010 $ +.\" $OpenBSD: ssh_config.5,v 1.132 2010/04/14 22:27:42 djm Exp $ +.Dd $Mdocdate: April 14 2010 $ .Dt SSH_CONFIG 5 .Os .Sh NAME @@ -759,12 +759,14 @@ Specifies the command to use to connect to the server. The command string extends to the end of the line, and is executed with the user's shell. -In the command string, +In the command string, any occurance of .Ql %h will be substituted by the host name to -connect and +connect, .Ql %p -by the port. +by the port and +.Ql %u +by the remote user name. The command can be basically anything, and should read from its standard input and write to its standard output. It should eventually connect an diff --git a/sshconnect.c b/sshconnect.c index effe6dae8..ca83bc792 100644 --- a/sshconnect.c +++ b/sshconnect.c @@ -1,4 +1,4 @@ -/* $OpenBSD: sshconnect.c,v 1.221 2010/04/10 00:04:30 djm Exp $ */ +/* $OpenBSD: sshconnect.c,v 1.222 2010/04/14 22:27:42 djm Exp $ */ /* * Author: Tatu Ylonen * Copyright (c) 1995 Tatu Ylonen , Espoo, Finland @@ -101,8 +101,8 @@ ssh_proxy_connect(const char *host, u_short port, const char *proxy_command) * (e.g. Solaris) */ xasprintf(&tmp, "exec %s", proxy_command); - command_string = percent_expand(tmp, "h", host, - "p", strport, (char *)NULL); + command_string = percent_expand(tmp, "h", host, "p", strport, + "u", options.user, (char *)NULL); xfree(tmp); /* Create pipes for communicating with the proxy. */ -- cgit v1.2.3 From 4e270b05dd9d850fb9e2e0ac43f33cb4090d3ebc Mon Sep 17 00:00:00 2001 From: Damien Miller Date: Fri, 16 Apr 2010 15:56:21 +1000 Subject: - djm@cvs.openbsd.org 2010/04/16 01:47:26 [PROTOCOL.certkeys auth-options.c auth-options.h auth-rsa.c] [auth2-pubkey.c authfd.c key.c key.h myproposal.h ssh-add.c] [ssh-agent.c ssh-dss.c ssh-keygen.1 ssh-keygen.c ssh-rsa.c] [sshconnect.c sshconnect2.c sshd.c] revised certificate format ssh-{dss,rsa}-cert-v01@openssh.com with the following changes: move the nonce field to the beginning of the certificate where it can better protect against chosen-prefix attacks on the signature hash Rename "constraints" field to "critical options" Add a new non-critical "extensions" field Add a serial number The older format is still support for authentication and cert generation (use "ssh-keygen -t v00 -s ca_key ..." to generate a v00 certificate) ok markus@ --- ChangeLog | 21 +++++ PROTOCOL.certkeys | 73 ++++++++++------- auth-options.c | 21 ++--- auth-options.h | 4 +- auth-rsa.c | 4 +- auth2-pubkey.c | 9 +-- authfd.c | 6 +- key.c | 177 +++++++++++++++++++++++++++++++++------- key.h | 11 ++- myproposal.h | 11 ++- ssh-add.c | 4 +- ssh-agent.c | 5 +- ssh-dss.c | 12 ++- ssh-keygen.1 | 27 ++++--- ssh-keygen.c | 235 +++++++++++++++++++++++++++++++++--------------------- ssh-rsa.c | 12 ++- sshconnect.c | 8 +- sshconnect2.c | 7 +- sshd.c | 15 +++- 19 files changed, 449 insertions(+), 213 deletions(-) (limited to 'sshconnect.c') diff --git a/ChangeLog b/ChangeLog index fd4ce5db2..b058de0f8 100644 --- a/ChangeLog +++ b/ChangeLog @@ -41,6 +41,27 @@ retry lookup for private key if there's no matching key with CKA_SIGN attribute enabled; this fixes fixes MuscleCard support (bugzilla #1736) ok djm@ + - djm@cvs.openbsd.org 2010/04/16 01:47:26 + [PROTOCOL.certkeys auth-options.c auth-options.h auth-rsa.c] + [auth2-pubkey.c authfd.c key.c key.h myproposal.h ssh-add.c] + [ssh-agent.c ssh-dss.c ssh-keygen.1 ssh-keygen.c ssh-rsa.c] + [sshconnect.c sshconnect2.c sshd.c] + revised certificate format ssh-{dss,rsa}-cert-v01@openssh.com with the + following changes: + + move the nonce field to the beginning of the certificate where it can + better protect against chosen-prefix attacks on the signature hash + + Rename "constraints" field to "critical options" + + Add a new non-critical "extensions" field + + Add a serial number + + The older format is still support for authentication and cert generation + (use "ssh-keygen -t v00 -s ca_key ..." to generate a v00 certificate) + + ok markus@ 20100410 - (dtucker) [configure.ac] Put the check for the existence of getaddrinfo diff --git a/PROTOCOL.certkeys b/PROTOCOL.certkeys index 1ed9e2064..a2069f547 100644 --- a/PROTOCOL.certkeys +++ b/PROTOCOL.certkeys @@ -16,7 +16,7 @@ These protocol extensions build on the simple public key authentication system already in SSH to allow certificate-based authentication. The certificates used are not traditional X.509 certificates, with numerous options and complex encoding rules, but something rather -more minimal: a key, some identity information and usage constraints +more minimal: a key, some identity information and usage options that have been signed with some other trusted key. A sshd server may be configured to allow authentication via certified @@ -27,7 +27,7 @@ of acceptance of certified host keys, by adding a similar ability to specify CA keys in ~/.ssh/known_hosts. Certified keys are represented using two new key types: -ssh-rsa-cert-v00@openssh.com and ssh-dss-cert-v00@openssh.com that +ssh-rsa-cert-v01@openssh.com and ssh-dss-cert-v01@openssh.com that include certification information along with the public key that is used to sign challenges. ssh-keygen performs the CA signing operation. @@ -47,7 +47,7 @@ in RFC4252 section 7. New public key formats ---------------------- -The ssh-rsa-cert-v00@openssh.com and ssh-dss-cert-v00@openssh.com key +The ssh-rsa-cert-v01@openssh.com and ssh-dss-cert-v01@openssh.com key types take a similar high-level format (note: data types and encoding are as per RFC4251 section 5). The serialised wire encoding of these certificates is also used for storing them on disk. @@ -57,42 +57,55 @@ these certificates is also used for storing them on disk. RSA certificate - string "ssh-rsa-cert-v00@openssh.com" + string "ssh-rsa-cert-v01@openssh.com" + string nonce mpint e mpint n + uint64 serial uint32 type string key id string valid principals uint64 valid after uint64 valid before - string constraints - string nonce + string critical options + string extensions string reserved string signature key string signature DSA certificate - string "ssh-dss-cert-v00@openssh.com" + string "ssh-dss-cert-v01@openssh.com" + string nonce mpint p mpint q mpint g mpint y + uint64 serial uint32 type string key id string valid principals uint64 valid after uint64 valid before - string constraints - string nonce + string critical options + string extensions string reserved string signature key string signature +The nonce field is a CA-provided random bitstring of arbitrary length +(but typically 16 or 32 bytes) included to make attacks that depend on +inducing collisions in the signature hash infeasible. + e and n are the RSA exponent and public modulus respectively. p, q, g, y are the DSA parameters as described in FIPS-186-2. +serial is an optional certificate serial number set by the CA to +provide an abbreviated way to refer to certificates from that CA. +If a CA does not with to number its certificates it must set this +field to zero. + type specifies whether this certificate is for identification of a user or a host using a SSH_CERT_TYPE_... value. @@ -112,13 +125,15 @@ certificate. Each represents a time in seconds since 1970-01-01 00:00:00. A certificate is considered valid if: valid after <= current time < valid before -constraints is a set of zero or more key constraints encoded as below. +criticial options is a set of zero or more key options encoded as +below. All such options are "critical" in the sense that an implementation +must refuse to authorise a key that has an unrecognised option. -The nonce field is a CA-provided random bitstring of arbitrary length -(but typically 16 or 32 bytes) included to make attacks that depend on -inducing collisions in the signature hash infeasible. +extensions is a set of zero or more optional extensions. These extensions +are not critical, and an implementation that encounters one that it does +not recognise may safely ignore it. No extensions are defined at present. -The reserved field is current unused and is ignored in this version of +The reserved field is currently unused and is ignored in this version of the protocol. signature key contains the CA key used to sign the certificate. @@ -132,22 +147,22 @@ up to, and including the signature key. Signatures are computed and encoded according to the rules defined for the CA's public key algorithm (RFC4253 section 6.6 for ssh-rsa and ssh-dss). -Constraints ------------ +Critical options +---------------- -The constraints section of the certificate specifies zero or more -constraints on the certificates validity. The format of this field +The critical options section of the certificate specifies zero or more +options on the certificates validity. The format of this field is a sequence of zero or more tuples: string name string data -The name field identifies the constraint and the data field encodes -constraint-specific information (see below). All constraints are -"critical", if an implementation does not recognise a constraint +The name field identifies the option and the data field encodes +option-specific information (see below). All options are +"critical", if an implementation does not recognise a option then the validating party should refuse to accept the certificate. -The supported constraints and the contents and structure of their +The supported options and the contents and structure of their data fields are: Name Format Description @@ -159,35 +174,35 @@ force-command string Specifies a command that is executed permit-X11-forwarding empty Flag indicating that X11 forwarding should be permitted. X11 forwarding will - be refused if this constraint is absent. + be refused if this option is absent. permit-agent-forwarding empty Flag indicating that agent forwarding should be allowed. Agent forwarding must not be permitted unless this - constraint is present. + option is present. permit-port-forwarding empty Flag indicating that port-forwarding - should be allowed. If this constraint is + should be allowed. If this option is not present then no port forwarding will be allowed. permit-pty empty Flag indicating that PTY allocation should be permitted. In the absence of - this constraint PTY allocation will be + this option PTY allocation will be disabled. permit-user-rc empty Flag indicating that execution of ~/.ssh/rc should be permitted. Execution of this script will not be permitted if - this constraint is not present. + this option is not present. source-address string Comma-separated list of source addresses from which this certificate is accepted for authentication. Addresses are specified in CIDR format (nn.nn.nn.nn/nn or hhhh::hhhh/nn). - If this constraint is not present then + If this option is not present then certificates may be presented from any source address. -$OpenBSD: PROTOCOL.certkeys,v 1.3 2010/03/03 22:50:40 djm Exp $ +$OpenBSD: PROTOCOL.certkeys,v 1.4 2010/04/16 01:47:25 djm Exp $ diff --git a/auth-options.c b/auth-options.c index 69b314fbd..60d5f749b 100644 --- a/auth-options.c +++ b/auth-options.c @@ -1,4 +1,4 @@ -/* $OpenBSD: auth-options.c,v 1.49 2010/03/16 15:46:52 stevesk Exp $ */ +/* $OpenBSD: auth-options.c,v 1.50 2010/04/16 01:47:26 djm Exp $ */ /* * Author: Tatu Ylonen * Copyright (c) 1995 Tatu Ylonen , Espoo, Finland @@ -27,10 +27,10 @@ #include "canohost.h" #include "buffer.h" #include "channels.h" -#include "auth-options.h" #include "servconf.h" #include "misc.h" #include "key.h" +#include "auth-options.h" #include "hostfile.h" #include "auth.h" #ifdef GSSAPI @@ -377,11 +377,11 @@ bad_option: } /* - * Set options from certificate constraints. These supersede user key options - * so this must be called after auth_parse_options(). + * Set options from critical certificate options. These supersede user key + * options so this must be called after auth_parse_options(). */ int -auth_cert_constraints(Buffer *c_orig, struct passwd *pw) +auth_cert_options(Key *k, struct passwd *pw) { u_char *name = NULL, *data_blob = NULL; u_int nlen, dlen, clen; @@ -400,12 +400,13 @@ auth_cert_constraints(Buffer *c_orig, struct passwd *pw) /* Make copy to avoid altering original */ buffer_init(&c); - buffer_append(&c, buffer_ptr(c_orig), buffer_len(c_orig)); + buffer_append(&c, + buffer_ptr(&k->cert->critical), buffer_len(&k->cert->critical)); while (buffer_len(&c) > 0) { if ((name = buffer_get_string_ret(&c, &nlen)) == NULL || (data_blob = buffer_get_string_ret(&c, &dlen)) == NULL) { - error("Certificate constraints corrupt"); + error("Certificate options corrupt"); goto out; } buffer_append(&data, data_blob, dlen); @@ -439,7 +440,7 @@ auth_cert_constraints(Buffer *c_orig, struct passwd *pw) } if (cert_forced_command != NULL) { error("Certificate has multiple " - "force-command constraints"); + "force-command options"); xfree(command); goto out; } @@ -459,7 +460,7 @@ auth_cert_constraints(Buffer *c_orig, struct passwd *pw) } if (cert_source_address_done++) { error("Certificate has multiple " - "source-address constraints"); + "source-address options"); xfree(allowed); goto out; } @@ -502,7 +503,7 @@ auth_cert_constraints(Buffer *c_orig, struct passwd *pw) name = data_blob = NULL; } - /* successfully parsed all constraints */ + /* successfully parsed all options */ ret = 0; no_port_forwarding_flag |= cert_no_port_forwarding_flag; diff --git a/auth-options.h b/auth-options.h index 694edc842..20f0dbe3e 100644 --- a/auth-options.h +++ b/auth-options.h @@ -1,4 +1,4 @@ -/* $OpenBSD: auth-options.h,v 1.18 2010/02/26 20:29:54 djm Exp $ */ +/* $OpenBSD: auth-options.h,v 1.19 2010/04/16 01:47:26 djm Exp $ */ /* * Author: Tatu Ylonen @@ -34,6 +34,6 @@ extern int key_is_cert_authority; int auth_parse_options(struct passwd *, char *, char *, u_long); void auth_clear_options(void); -int auth_cert_constraints(Buffer *, struct passwd *); +int auth_cert_options(Key *, struct passwd *); #endif diff --git a/auth-rsa.c b/auth-rsa.c index 65571a890..326937ac0 100644 --- a/auth-rsa.c +++ b/auth-rsa.c @@ -1,4 +1,4 @@ -/* $OpenBSD: auth-rsa.c,v 1.74 2010/03/04 10:36:03 djm Exp $ */ +/* $OpenBSD: auth-rsa.c,v 1.75 2010/04/16 01:47:26 djm Exp $ */ /* * Author: Tatu Ylonen * Copyright (c) 1995 Tatu Ylonen , Espoo, Finland @@ -34,11 +34,11 @@ #include "uidswap.h" #include "match.h" #include "buffer.h" -#include "auth-options.h" #include "pathnames.h" #include "log.h" #include "servconf.h" #include "key.h" +#include "auth-options.h" #include "hostfile.h" #include "auth.h" #ifdef GSSAPI diff --git a/auth2-pubkey.c b/auth2-pubkey.c index c4cadf4e7..83ecd6590 100644 --- a/auth2-pubkey.c +++ b/auth2-pubkey.c @@ -1,4 +1,4 @@ -/* $OpenBSD: auth2-pubkey.c,v 1.22 2010/03/10 23:27:17 djm Exp $ */ +/* $OpenBSD: auth2-pubkey.c,v 1.23 2010/04/16 01:47:26 djm Exp $ */ /* * Copyright (c) 2000 Markus Friedl. All rights reserved. * @@ -235,7 +235,7 @@ user_key_allowed2(struct passwd *pw, Key *key, char *file) } if (auth_parse_options(pw, key_options, file, linenum) != 1) continue; - if (key->type == KEY_RSA_CERT || key->type == KEY_DSA_CERT) { + if (key_is_cert(key)) { if (!key_is_cert_authority) continue; if (!key_equal(found, key->cert->signature_key)) @@ -251,8 +251,7 @@ user_key_allowed2(struct passwd *pw, Key *key, char *file) auth_debug_add("%s", reason); continue; } - if (auth_cert_constraints(&key->cert->constraints, - pw) != 0) { + if (auth_cert_options(key, pw) != 0) { xfree(fp); continue; } @@ -307,7 +306,7 @@ user_cert_trusted_ca(struct passwd *pw, Key *key) auth_debug_add("%s", reason); goto out; } - if (auth_cert_constraints(&key->cert->constraints, pw) != 0) + if (auth_cert_options(key, pw) != 0) goto out; verbose("Accepted certificate ID \"%s\" signed by %s CA %s via %s", diff --git a/authfd.c b/authfd.c index 28a8cf2d7..739722fbf 100644 --- a/authfd.c +++ b/authfd.c @@ -1,4 +1,4 @@ -/* $OpenBSD: authfd.c,v 1.82 2010/02/26 20:29:54 djm Exp $ */ +/* $OpenBSD: authfd.c,v 1.83 2010/04/16 01:47:26 djm Exp $ */ /* * Author: Tatu Ylonen * Copyright (c) 1995 Tatu Ylonen , Espoo, Finland @@ -483,6 +483,7 @@ ssh_encode_identity_ssh2(Buffer *b, Key *key, const char *comment) buffer_put_bignum2(b, key->rsa->p); buffer_put_bignum2(b, key->rsa->q); break; + case KEY_RSA_CERT_V00: case KEY_RSA_CERT: if (key->cert == NULL || buffer_len(&key->cert->certblob) == 0) fatal("%s: no cert/certblob", __func__); @@ -500,6 +501,7 @@ ssh_encode_identity_ssh2(Buffer *b, Key *key, const char *comment) buffer_put_bignum2(b, key->dsa->pub_key); buffer_put_bignum2(b, key->dsa->priv_key); break; + case KEY_DSA_CERT_V00: case KEY_DSA_CERT: if (key->cert == NULL || buffer_len(&key->cert->certblob) == 0) fatal("%s: no cert/certblob", __func__); @@ -535,8 +537,10 @@ ssh_add_identity_constrained(AuthenticationConnection *auth, Key *key, break; case KEY_RSA: case KEY_RSA_CERT: + case KEY_RSA_CERT_V00: case KEY_DSA: case KEY_DSA_CERT: + case KEY_DSA_CERT_V00: type = constrained ? SSH2_AGENTC_ADD_ID_CONSTRAINED : SSH2_AGENTC_ADD_IDENTITY; diff --git a/key.c b/key.c index 66592c7ed..34f678b38 100644 --- a/key.c +++ b/key.c @@ -1,4 +1,4 @@ -/* $OpenBSD: key.c,v 1.86 2010/03/15 19:40:02 stevesk Exp $ */ +/* $OpenBSD: key.c,v 1.87 2010/04/16 01:47:26 djm Exp $ */ /* * read_bignum(): * Copyright (c) 1995 Tatu Ylonen , Espoo, Finland @@ -61,7 +61,8 @@ cert_new(void) cert = xcalloc(1, sizeof(*cert)); buffer_init(&cert->certblob); - buffer_init(&cert->constraints); + buffer_init(&cert->critical); + buffer_init(&cert->extensions); cert->key_id = NULL; cert->principals = NULL; cert->signature_key = NULL; @@ -82,6 +83,7 @@ key_new(int type) switch (k->type) { case KEY_RSA1: case KEY_RSA: + case KEY_RSA_CERT_V00: case KEY_RSA_CERT: if ((rsa = RSA_new()) == NULL) fatal("key_new: RSA_new failed"); @@ -92,6 +94,7 @@ key_new(int type) k->rsa = rsa; break; case KEY_DSA: + case KEY_DSA_CERT_V00: case KEY_DSA_CERT: if ((dsa = DSA_new()) == NULL) fatal("key_new: DSA_new failed"); @@ -124,6 +127,7 @@ key_add_private(Key *k) switch (k->type) { case KEY_RSA1: case KEY_RSA: + case KEY_RSA_CERT_V00: case KEY_RSA_CERT: if ((k->rsa->d = BN_new()) == NULL) fatal("key_new_private: BN_new failed"); @@ -139,6 +143,7 @@ key_add_private(Key *k) fatal("key_new_private: BN_new failed"); break; case KEY_DSA: + case KEY_DSA_CERT_V00: case KEY_DSA_CERT: if ((k->dsa->priv_key = BN_new()) == NULL) fatal("key_new_private: BN_new failed"); @@ -165,7 +170,8 @@ cert_free(struct KeyCert *cert) u_int i; buffer_free(&cert->certblob); - buffer_free(&cert->constraints); + buffer_free(&cert->critical); + buffer_free(&cert->extensions); if (cert->key_id != NULL) xfree(cert->key_id); for (i = 0; i < cert->nprincipals; i++) @@ -184,12 +190,14 @@ key_free(Key *k) switch (k->type) { case KEY_RSA1: case KEY_RSA: + case KEY_RSA_CERT_V00: case KEY_RSA_CERT: if (k->rsa != NULL) RSA_free(k->rsa); k->rsa = NULL; break; case KEY_DSA: + case KEY_DSA_CERT_V00: case KEY_DSA_CERT: if (k->dsa != NULL) DSA_free(k->dsa); @@ -238,11 +246,13 @@ key_equal_public(const Key *a, const Key *b) switch (a->type) { case KEY_RSA1: + case KEY_RSA_CERT_V00: case KEY_RSA_CERT: case KEY_RSA: return a->rsa != NULL && b->rsa != NULL && BN_cmp(a->rsa->e, b->rsa->e) == 0 && BN_cmp(a->rsa->n, b->rsa->n) == 0; + case KEY_DSA_CERT_V00: case KEY_DSA_CERT: case KEY_DSA: return a->dsa != NULL && b->dsa != NULL && @@ -304,6 +314,8 @@ key_fingerprint_raw(Key *k, enum fp_type dgst_type, u_int *dgst_raw_length) case KEY_RSA: key_to_blob(k, &blob, &len); break; + case KEY_DSA_CERT_V00: + case KEY_RSA_CERT_V00: case KEY_DSA_CERT: case KEY_RSA_CERT: /* We want a fingerprint of the _key_ not of the cert */ @@ -631,6 +643,8 @@ key_read(Key *ret, char **cpp) case KEY_UNSPEC: case KEY_RSA: case KEY_DSA: + case KEY_DSA_CERT_V00: + case KEY_RSA_CERT_V00: case KEY_DSA_CERT: case KEY_RSA_CERT: space = strchr(cp, ' '); @@ -757,11 +771,13 @@ key_write(const Key *key, FILE *f) error("key_write: failed for RSA key"); return 0; case KEY_DSA: + case KEY_DSA_CERT_V00: case KEY_DSA_CERT: if (key->dsa == NULL) return 0; break; case KEY_RSA: + case KEY_RSA_CERT_V00: case KEY_RSA_CERT: if (key->rsa == NULL) return 0; @@ -793,6 +809,10 @@ key_type(const Key *k) return "RSA"; case KEY_DSA: return "DSA"; + case KEY_RSA_CERT_V00: + return "RSA-CERT-V00"; + case KEY_DSA_CERT_V00: + return "DSA-CERT-V00"; case KEY_RSA_CERT: return "RSA-CERT"; case KEY_DSA_CERT: @@ -822,10 +842,14 @@ key_ssh_name(const Key *k) return "ssh-rsa"; case KEY_DSA: return "ssh-dss"; - case KEY_RSA_CERT: + case KEY_RSA_CERT_V00: return "ssh-rsa-cert-v00@openssh.com"; - case KEY_DSA_CERT: + case KEY_DSA_CERT_V00: return "ssh-dss-cert-v00@openssh.com"; + case KEY_RSA_CERT: + return "ssh-rsa-cert-v01@openssh.com"; + case KEY_DSA_CERT: + return "ssh-dss-cert-v01@openssh.com"; } return "ssh-unknown"; } @@ -836,9 +860,11 @@ key_size(const Key *k) switch (k->type) { case KEY_RSA1: case KEY_RSA: + case KEY_RSA_CERT_V00: case KEY_RSA_CERT: return BN_num_bits(k->rsa->n); case KEY_DSA: + case KEY_DSA_CERT_V00: case KEY_DSA_CERT: return BN_num_bits(k->dsa->p); } @@ -882,6 +908,8 @@ key_generate(int type, u_int bits) case KEY_RSA1: k->rsa = rsa_generate_private_key(bits); break; + case KEY_RSA_CERT_V00: + case KEY_DSA_CERT_V00: case KEY_RSA_CERT: case KEY_DSA_CERT: fatal("key_generate: cert keys cannot be generated directly"); @@ -912,9 +940,12 @@ key_cert_copy(const Key *from_key, struct Key *to_key) buffer_append(&to->certblob, buffer_ptr(&from->certblob), buffer_len(&from->certblob)); - buffer_append(&to->constraints, buffer_ptr(&from->constraints), - buffer_len(&from->constraints)); + buffer_append(&to->critical, + buffer_ptr(&from->critical), buffer_len(&from->critical)); + buffer_append(&to->extensions, + buffer_ptr(&from->extensions), buffer_len(&from->extensions)); + to->serial = from->serial; to->type = from->type; to->key_id = from->key_id == NULL ? NULL : xstrdup(from->key_id); to->valid_after = from->valid_after; @@ -940,6 +971,7 @@ key_from_private(const Key *k) Key *n = NULL; switch (k->type) { case KEY_DSA: + case KEY_DSA_CERT_V00: case KEY_DSA_CERT: n = key_new(k->type); if ((BN_copy(n->dsa->p, k->dsa->p) == NULL) || @@ -950,6 +982,7 @@ key_from_private(const Key *k) break; case KEY_RSA: case KEY_RSA1: + case KEY_RSA_CERT_V00: case KEY_RSA_CERT: n = key_new(k->type); if ((BN_copy(n->rsa->n, k->rsa->n) == NULL) || @@ -979,8 +1012,12 @@ key_type_from_name(char *name) } else if (strcmp(name, "ssh-dss") == 0) { return KEY_DSA; } else if (strcmp(name, "ssh-rsa-cert-v00@openssh.com") == 0) { - return KEY_RSA_CERT; + return KEY_RSA_CERT_V00; } else if (strcmp(name, "ssh-dss-cert-v00@openssh.com") == 0) { + return KEY_DSA_CERT_V00; + } else if (strcmp(name, "ssh-rsa-cert-v01@openssh.com") == 0) { + return KEY_RSA_CERT; + } else if (strcmp(name, "ssh-dss-cert-v01@openssh.com") == 0) { return KEY_DSA_CERT; } debug2("key_type_from_name: unknown key type '%s'", name); @@ -1012,26 +1049,31 @@ key_names_valid2(const char *names) static int cert_parse(Buffer *b, Key *key, const u_char *blob, u_int blen) { - u_char *principals, *constraints, *sig_key, *sig; - u_int signed_len, plen, clen, sklen, slen, kidlen; + u_char *principals, *critical, *exts, *sig_key, *sig; + u_int signed_len, plen, clen, sklen, slen, kidlen, elen; Buffer tmp; char *principal; int ret = -1; + int v00 = key->type == KEY_DSA_CERT_V00 || + key->type == KEY_RSA_CERT_V00; buffer_init(&tmp); /* Copy the entire key blob for verification and later serialisation */ buffer_append(&key->cert->certblob, blob, blen); - principals = constraints = sig_key = sig = NULL; - if (buffer_get_int_ret(&key->cert->type, b) != 0 || + elen = 0; /* Not touched for v00 certs */ + principals = exts = critical = sig_key = sig = NULL; + if ((!v00 && buffer_get_int64_ret(&key->cert->serial, b) != 0) || + buffer_get_int_ret(&key->cert->type, b) != 0 || (key->cert->key_id = buffer_get_string_ret(b, &kidlen)) == NULL || (principals = buffer_get_string_ret(b, &plen)) == NULL || buffer_get_int64_ret(&key->cert->valid_after, b) != 0 || buffer_get_int64_ret(&key->cert->valid_before, b) != 0 || - (constraints = buffer_get_string_ret(b, &clen)) == NULL || - /* skip nonce */ buffer_get_string_ptr_ret(b, NULL) == NULL || - /* skip reserved */ buffer_get_string_ptr_ret(b, NULL) == NULL || + (critical = buffer_get_string_ret(b, &clen)) == NULL || + (!v00 && (exts = buffer_get_string_ret(b, &elen)) == NULL) || + (v00 && buffer_get_string_ptr_ret(b, NULL) == NULL) || /* nonce */ + buffer_get_string_ptr_ret(b, NULL) == NULL || /* reserved */ (sig_key = buffer_get_string_ret(b, &sklen)) == NULL) { error("%s: parse error", __func__); goto out; @@ -1078,13 +1120,25 @@ cert_parse(Buffer *b, Key *key, const u_char *blob, u_int blen) buffer_clear(&tmp); - buffer_append(&key->cert->constraints, constraints, clen); - buffer_append(&tmp, constraints, clen); + buffer_append(&key->cert->critical, critical, clen); + buffer_append(&tmp, critical, clen); /* validate structure */ while (buffer_len(&tmp) != 0) { if (buffer_get_string_ptr_ret(&tmp, NULL) == NULL || buffer_get_string_ptr_ret(&tmp, NULL) == NULL) { - error("%s: Constraints data invalid", __func__); + error("%s: critical option data invalid", __func__); + goto out; + } + } + buffer_clear(&tmp); + + buffer_append(&key->cert->extensions, exts, elen); + buffer_append(&tmp, exts, elen); + /* validate structure */ + while (buffer_len(&tmp) != 0) { + if (buffer_get_string_ptr_ret(&tmp, NULL) == NULL || + buffer_get_string_ptr_ret(&tmp, NULL) == NULL) { + error("%s: extension data invalid", __func__); goto out; } } @@ -1121,8 +1175,10 @@ cert_parse(Buffer *b, Key *key, const u_char *blob, u_int blen) buffer_free(&tmp); if (principals != NULL) xfree(principals); - if (constraints != NULL) - xfree(constraints); + if (critical != NULL) + xfree(critical); + if (exts != NULL) + xfree(exts); if (sig_key != NULL) xfree(sig_key); if (sig != NULL) @@ -1151,8 +1207,11 @@ key_from_blob(const u_char *blob, u_int blen) type = key_type_from_name(ktype); switch (type) { - case KEY_RSA: case KEY_RSA_CERT: + (void)buffer_get_string_ptr_ret(&b, NULL); /* Skip nonce */ + /* FALLTHROUGH */ + case KEY_RSA: + case KEY_RSA_CERT_V00: key = key_new(type); if (buffer_get_bignum2_ret(&b, key->rsa->e) == -1 || buffer_get_bignum2_ret(&b, key->rsa->n) == -1) { @@ -1166,8 +1225,11 @@ key_from_blob(const u_char *blob, u_int blen) RSA_print_fp(stderr, key->rsa, 8); #endif break; - case KEY_DSA: case KEY_DSA_CERT: + (void)buffer_get_string_ptr_ret(&b, NULL); /* Skip nonce */ + /* FALLTHROUGH */ + case KEY_DSA: + case KEY_DSA_CERT_V00: key = key_new(type); if (buffer_get_bignum2_ret(&b, key->dsa->p) == -1 || buffer_get_bignum2_ret(&b, key->dsa->q) == -1 || @@ -1213,6 +1275,8 @@ key_to_blob(const Key *key, u_char **blobp, u_int *lenp) } buffer_init(&b); switch (key->type) { + case KEY_DSA_CERT_V00: + case KEY_RSA_CERT_V00: case KEY_DSA_CERT: case KEY_RSA_CERT: /* Use the existing blob */ @@ -1255,9 +1319,11 @@ key_sign( const u_char *data, u_int datalen) { switch (key->type) { + case KEY_DSA_CERT_V00: case KEY_DSA_CERT: case KEY_DSA: return ssh_dss_sign(key, sigp, lenp, data, datalen); + case KEY_RSA_CERT_V00: case KEY_RSA_CERT: case KEY_RSA: return ssh_rsa_sign(key, sigp, lenp, data, datalen); @@ -1281,9 +1347,11 @@ key_verify( return -1; switch (key->type) { + case KEY_DSA_CERT_V00: case KEY_DSA_CERT: case KEY_DSA: return ssh_dss_verify(key, signature, signaturelen, data, datalen); + case KEY_RSA_CERT_V00: case KEY_RSA_CERT: case KEY_RSA: return ssh_rsa_verify(key, signature, signaturelen, data, datalen); @@ -1306,6 +1374,7 @@ key_demote(const Key *k) pk->rsa = NULL; switch (k->type) { + case KEY_RSA_CERT_V00: case KEY_RSA_CERT: key_cert_copy(k, pk); /* FALLTHROUGH */ @@ -1318,6 +1387,7 @@ key_demote(const Key *k) if ((pk->rsa->n = BN_dup(k->rsa->n)) == NULL) fatal("key_demote: BN_dup failed"); break; + case KEY_DSA_CERT_V00: case KEY_DSA_CERT: key_cert_copy(k, pk); /* FALLTHROUGH */ @@ -1344,8 +1414,17 @@ key_demote(const Key *k) int key_is_cert(const Key *k) { - return k != NULL && - (k->type == KEY_RSA_CERT || k->type == KEY_DSA_CERT); + if (k == NULL) + return 0; + switch (k->type) { + case KEY_RSA_CERT_V00: + case KEY_DSA_CERT_V00: + case KEY_RSA_CERT: + case KEY_DSA_CERT: + return 1; + default: + return 0; + } } /* Return the cert-less equivalent to a certified key type */ @@ -1353,8 +1432,10 @@ int key_type_plain(int type) { switch (type) { + case KEY_RSA_CERT_V00: case KEY_RSA_CERT: return KEY_RSA; + case KEY_DSA_CERT_V00: case KEY_DSA_CERT: return KEY_DSA; default: @@ -1364,16 +1445,16 @@ key_type_plain(int type) /* Convert a KEY_RSA or KEY_DSA to their _CERT equivalent */ int -key_to_certified(Key *k) +key_to_certified(Key *k, int legacy) { switch (k->type) { case KEY_RSA: k->cert = cert_new(); - k->type = KEY_RSA_CERT; + k->type = legacy ? KEY_RSA_CERT_V00 : KEY_RSA_CERT; return 0; case KEY_DSA: k->cert = cert_new(); - k->type = KEY_DSA_CERT; + k->type = legacy ? KEY_DSA_CERT_V00 : KEY_DSA_CERT; return 0; default: error("%s: key has incorrect type %s", __func__, key_type(k)); @@ -1386,10 +1467,12 @@ int key_drop_cert(Key *k) { switch (k->type) { + case KEY_RSA_CERT_V00: case KEY_RSA_CERT: cert_free(k->cert); k->type = KEY_RSA; return 0; + case KEY_DSA_CERT_V00: case KEY_DSA_CERT: cert_free(k->cert); k->type = KEY_DSA; @@ -1430,13 +1513,21 @@ key_certify(Key *k, Key *ca) buffer_clear(&k->cert->certblob); buffer_put_cstring(&k->cert->certblob, key_ssh_name(k)); + /* -v01 certs put nonce first */ + if (k->type == KEY_DSA_CERT || k->type == KEY_RSA_CERT) { + arc4random_buf(&nonce, sizeof(nonce)); + buffer_put_string(&k->cert->certblob, nonce, sizeof(nonce)); + } + switch (k->type) { + case KEY_DSA_CERT_V00: case KEY_DSA_CERT: buffer_put_bignum2(&k->cert->certblob, k->dsa->p); buffer_put_bignum2(&k->cert->certblob, k->dsa->q); buffer_put_bignum2(&k->cert->certblob, k->dsa->g); buffer_put_bignum2(&k->cert->certblob, k->dsa->pub_key); break; + case KEY_RSA_CERT_V00: case KEY_RSA_CERT: buffer_put_bignum2(&k->cert->certblob, k->rsa->e); buffer_put_bignum2(&k->cert->certblob, k->rsa->n); @@ -1448,6 +1539,10 @@ key_certify(Key *k, Key *ca) return -1; } + /* -v01 certs have a serial number next */ + if (k->type == KEY_DSA_CERT || k->type == KEY_RSA_CERT) + buffer_put_int64(&k->cert->certblob, k->cert->serial); + buffer_put_int(&k->cert->certblob, k->cert->type); buffer_put_cstring(&k->cert->certblob, k->cert->key_id); @@ -1461,11 +1556,19 @@ key_certify(Key *k, Key *ca) buffer_put_int64(&k->cert->certblob, k->cert->valid_after); buffer_put_int64(&k->cert->certblob, k->cert->valid_before); buffer_put_string(&k->cert->certblob, - buffer_ptr(&k->cert->constraints), - buffer_len(&k->cert->constraints)); + buffer_ptr(&k->cert->critical), buffer_len(&k->cert->critical)); + + /* -v01 certs have non-critical options here */ + if (k->type == KEY_DSA_CERT || k->type == KEY_RSA_CERT) { + buffer_put_string(&k->cert->certblob, + buffer_ptr(&k->cert->extensions), + buffer_len(&k->cert->extensions)); + } + + /* -v00 certs put the nonce at the end */ + if (k->type == KEY_DSA_CERT_V00 || k->type == KEY_RSA_CERT_V00) + buffer_put_string(&k->cert->certblob, nonce, sizeof(nonce)); - arc4random_buf(&nonce, sizeof(nonce)); - buffer_put_string(&k->cert->certblob, nonce, sizeof(nonce)); buffer_put_string(&k->cert->certblob, NULL, 0); /* reserved */ buffer_put_string(&k->cert->certblob, ca_blob, ca_len); xfree(ca_blob); @@ -1536,3 +1639,15 @@ key_cert_check_authority(const Key *k, int want_host, int require_principal, } return 0; } + +int +key_cert_is_legacy(Key *k) +{ + switch (k->type) { + case KEY_DSA_CERT_V00: + case KEY_RSA_CERT_V00: + return 1; + default: + return 0; + } +} diff --git a/key.h b/key.h index 4f17777c0..11d30eae6 100644 --- a/key.h +++ b/key.h @@ -1,4 +1,4 @@ -/* $OpenBSD: key.h,v 1.29 2010/03/15 19:40:02 stevesk Exp $ */ +/* $OpenBSD: key.h,v 1.30 2010/04/16 01:47:26 djm Exp $ */ /* * Copyright (c) 2000, 2001 Markus Friedl. All rights reserved. @@ -37,6 +37,8 @@ enum types { KEY_DSA, KEY_RSA_CERT, KEY_DSA_CERT, + KEY_RSA_CERT_V00, + KEY_DSA_CERT_V00, KEY_UNSPEC }; enum fp_type { @@ -56,11 +58,13 @@ enum fp_rep { struct KeyCert { Buffer certblob; /* Kept around for use on wire */ u_int type; /* SSH2_CERT_TYPE_USER or SSH2_CERT_TYPE_HOST */ + u_int64_t serial; char *key_id; u_int nprincipals; char **principals; u_int64_t valid_after, valid_before; - Buffer constraints; + Buffer critical; + Buffer extensions; Key *signature_key; }; @@ -92,12 +96,13 @@ Key *key_from_private(const Key *); int key_type_from_name(char *); int key_is_cert(const Key *); int key_type_plain(int); -int key_to_certified(Key *); +int key_to_certified(Key *, int); int key_drop_cert(Key *); int key_certify(Key *, Key *); void key_cert_copy(const Key *, struct Key *); int key_cert_check_authority(const Key *, int, int, const char *, const char **); +int key_cert_is_legacy(Key *); Key *key_from_blob(const u_char *, u_int); int key_to_blob(const Key *, u_char **, u_int *); diff --git a/myproposal.h b/myproposal.h index 98f27fd15..7bedfab0a 100644 --- a/myproposal.h +++ b/myproposal.h @@ -1,4 +1,4 @@ -/* $OpenBSD: myproposal.h,v 1.24 2010/02/26 20:29:54 djm Exp $ */ +/* $OpenBSD: myproposal.h,v 1.25 2010/04/16 01:47:26 djm Exp $ */ /* * Copyright (c) 2000 Markus Friedl. All rights reserved. @@ -40,9 +40,12 @@ "diffie-hellman-group1-sha1" #endif -#define KEX_DEFAULT_PK_ALG "ssh-rsa-cert-v00@openssh.com," \ - "ssh-dss-cert-v00@openssh.com," \ - "ssh-rsa,ssh-dss" +#define KEX_DEFAULT_PK_ALG \ + "ssh-rsa-cert-v01@openssh.com," \ + "ssh-dss-cert-v01@openssh.com," \ + "ssh-rsa-cert-v00@openssh.com," \ + "ssh-dss-cert-v00@openssh.com," \ + "ssh-rsa,ssh-dss" #define KEX_DEFAULT_ENCRYPT \ "aes128-ctr,aes192-ctr,aes256-ctr," \ diff --git a/ssh-add.c b/ssh-add.c index ad9f7a83e..cba1078b4 100644 --- a/ssh-add.c +++ b/ssh-add.c @@ -1,4 +1,4 @@ -/* $OpenBSD: ssh-add.c,v 1.94 2010/03/01 11:07:06 otto Exp $ */ +/* $OpenBSD: ssh-add.c,v 1.95 2010/04/16 01:47:26 djm Exp $ */ /* * Author: Tatu Ylonen * Copyright (c) 1995 Tatu Ylonen , Espoo, Finland @@ -204,7 +204,7 @@ add_file(AuthenticationConnection *ac, const char *filename) xasprintf(&certpath, "%s-cert.pub", filename); if ((cert = key_load_public(certpath, NULL)) != NULL) { /* Graft with private bits */ - if (key_to_certified(private) != 0) + if (key_to_certified(private, key_cert_is_legacy(cert)) != 0) fatal("%s: key_to_certified failed", __func__); key_cert_copy(cert, private); key_free(cert); diff --git a/ssh-agent.c b/ssh-agent.c index b5c565271..2c0e28696 100644 --- a/ssh-agent.c +++ b/ssh-agent.c @@ -1,4 +1,4 @@ -/* $OpenBSD: ssh-agent.c,v 1.165 2010/02/26 20:29:54 djm Exp $ */ +/* $OpenBSD: ssh-agent.c,v 1.166 2010/04/16 01:47:26 djm Exp $ */ /* * Author: Tatu Ylonen * Copyright (c) 1995 Tatu Ylonen , Espoo, Finland @@ -500,6 +500,7 @@ process_add_identity(SocketEntry *e, int version) buffer_get_bignum2(&e->request, k->dsa->pub_key); buffer_get_bignum2(&e->request, k->dsa->priv_key); break; + case KEY_DSA_CERT_V00: case KEY_DSA_CERT: cert = buffer_get_string(&e->request, &len); if ((k = key_from_blob(cert, len)) == NULL) @@ -520,6 +521,7 @@ process_add_identity(SocketEntry *e, int version) /* Generate additional parameters */ rsa_generate_additional_parameters(k->rsa); break; + case KEY_RSA_CERT_V00: case KEY_RSA_CERT: cert = buffer_get_string(&e->request, &len); if ((k = key_from_blob(cert, len)) == NULL) @@ -540,6 +542,7 @@ process_add_identity(SocketEntry *e, int version) /* enable blinding */ switch (k->type) { case KEY_RSA: + case KEY_RSA_CERT_V00: case KEY_RSA_CERT: case KEY_RSA1: if (RSA_blinding_on(k->rsa, NULL) != 1) { diff --git a/ssh-dss.c b/ssh-dss.c index 449f493b4..175e4d030 100644 --- a/ssh-dss.c +++ b/ssh-dss.c @@ -1,4 +1,4 @@ -/* $OpenBSD: ssh-dss.c,v 1.25 2010/02/26 20:29:54 djm Exp $ */ +/* $OpenBSD: ssh-dss.c,v 1.26 2010/04/16 01:47:26 djm Exp $ */ /* * Copyright (c) 2000 Markus Friedl. All rights reserved. * @@ -53,9 +53,8 @@ ssh_dss_sign(const Key *key, u_char **sigp, u_int *lenp, u_int rlen, slen, len, dlen; Buffer b; - if (key == NULL || - (key->type != KEY_DSA && key->type != KEY_DSA_CERT) || - key->dsa == NULL) { + if (key == NULL || key->dsa == NULL || (key->type != KEY_DSA && + key->type != KEY_DSA_CERT && key->type != KEY_DSA_CERT_V00)) { error("ssh_dss_sign: no DSA key"); return -1; } @@ -118,9 +117,8 @@ ssh_dss_verify(const Key *key, const u_char *signature, u_int signaturelen, int rlen, ret; Buffer b; - if (key == NULL || - (key->type != KEY_DSA && key->type != KEY_DSA_CERT) || - key->dsa == NULL) { + if (key == NULL || key->dsa == NULL || (key->type != KEY_DSA && + key->type != KEY_DSA_CERT && key->type != KEY_DSA_CERT_V00)) { error("ssh_dss_verify: no DSA key"); return -1; } diff --git a/ssh-keygen.1 b/ssh-keygen.1 index 3e03a9bd0..aacd4d3dc 100644 --- a/ssh-keygen.1 +++ b/ssh-keygen.1 @@ -1,4 +1,4 @@ -.\" $OpenBSD: ssh-keygen.1,v 1.92 2010/03/13 23:38:13 jmc Exp $ +.\" $OpenBSD: ssh-keygen.1,v 1.93 2010/04/16 01:47:26 djm Exp $ .\" .\" -*- nroff -*- .\" @@ -37,7 +37,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: March 13 2010 $ +.Dd $Mdocdate: April 16 2010 $ .Dt SSH-KEYGEN 1 .Os .Sh NAME @@ -110,8 +110,9 @@ .Fl I Ar certificate_identity .Op Fl h .Op Fl n Ar principals -.Op Fl O Ar constraint +.Op Fl O Ar option .Op Fl V Ar validity_interval +.Op Fl z Ar serial_number .Ar .Nm ssh-keygen .Fl L @@ -299,13 +300,13 @@ Multiple principals may be specified, separated by commas. Please see the .Sx CERTIFICATES section for details. -.It Fl O Ar constraint -Specify a certificate constraint when signing a key. +.It Fl O Ar option +Specify a certificate option when signing a key. This option may be specified multiple times. Please see the .Sx CERTIFICATES section for details. -The constraints that are valid for user certificates are: +The options that are valid for user certificates are: .Bl -tag -width Ds .It Ic clear Clear all enabled permissions. @@ -355,7 +356,7 @@ is a comma-separated list of one or more address/netmask pairs in CIDR format. .El .Pp -At present, no constraints are valid for host keys. +At present, no options are valid for host keys. .It Fl P Ar passphrase Provides the (old) passphrase. .It Fl p @@ -441,6 +442,10 @@ Specify desired generator when testing candidate moduli for DH-GEX. .It Fl y This option will read a private OpenSSH format file and print an OpenSSH public key to stdout. +.It Fl z Ar serial_number +Specifies a serial number to be embedded in the certificate to distinguish +this certificate from others from the same CA. +The default serial number is zero. .El .Sh MODULI GENERATION .Nm @@ -501,7 +506,7 @@ that both ends of a connection share common moduli. supports signing of keys to produce certificates that may be used for user or host authentication. Certificates consist of a public key, some identity information, zero or -more principal (user or host) names and an optional set of constraints that +more principal (user or host) names and an optional set of options that are signed by a Certification Authority (CA) key. Clients or servers may then trust only the CA key and verify its signature on a certificate rather than trusting many user/host keys. @@ -541,11 +546,11 @@ To generate a certificate for a specified set of principals: .Dl "$ ssh-keygen -s ca_key -I key_id -h -n host.domain user_key.pub" .Pp Additional limitations on the validity and use of user certificates may -be specified through certificate constraints. -A constrained certificate may disable features of the SSH session, may be +be specified through certificate options.. +A certificate option may disable features of the SSH session, may be valid only when presented from particular source addresses or may force the use of a specific command. -For a list of valid certificate constraints, see the documentation for the +For a list of valid certificate options, see the documentation for the .Fl O option above. .Pp diff --git a/ssh-keygen.c b/ssh-keygen.c index 37e516ff2..8938dc051 100644 --- a/ssh-keygen.c +++ b/ssh-keygen.c @@ -1,4 +1,4 @@ -/* $OpenBSD: ssh-keygen.c,v 1.185 2010/03/15 19:40:02 stevesk Exp $ */ +/* $OpenBSD: ssh-keygen.c,v 1.186 2010/04/16 01:47:26 djm Exp $ */ /* * Author: Tatu Ylonen * Copyright (c) 1994 Tatu Ylonen , Espoo, Finland @@ -105,6 +105,9 @@ char *identity_comment = NULL; /* Path to CA key when certifying keys. */ char *ca_key_path = NULL; +/* Certificate serial number */ +long long cert_serial = 0; + /* Key type when certifying */ u_int cert_key_type = SSH2_CERT_TYPE_USER; @@ -118,18 +121,18 @@ char *cert_principals = NULL; u_int64_t cert_valid_from = 0; u_int64_t cert_valid_to = ~0ULL; -/* Certificate constraints */ -#define CONSTRAINT_X_FWD (1) -#define CONSTRAINT_AGENT_FWD (1<<1) -#define CONSTRAINT_PORT_FWD (1<<2) -#define CONSTRAINT_PTY (1<<3) -#define CONSTRAINT_USER_RC (1<<4) -#define CONSTRAINT_DEFAULT (CONSTRAINT_X_FWD|CONSTRAINT_AGENT_FWD| \ - CONSTRAINT_PORT_FWD|CONSTRAINT_PTY| \ - CONSTRAINT_USER_RC) -u_int32_t constraint_flags = CONSTRAINT_DEFAULT; -char *constraint_command = NULL; -char *constraint_src_addr = NULL; +/* Certificate options */ +#define CRITOPT_X_FWD (1) +#define CRITOPT_AGENT_FWD (1<<1) +#define CRITOPT_PORT_FWD (1<<2) +#define CRITOPT_PTY (1<<3) +#define CRITOPT_USER_RC (1<<4) +#define CRITOPT_DEFAULT (CRITOPT_X_FWD|CRITOPT_AGENT_FWD| \ + CRITOPT_PORT_FWD|CRITOPT_PTY| \ + CRITOPT_USER_RC) +u_int32_t critical_flags = CRITOPT_DEFAULT; +char *critical_command = NULL; +char *critical_src_addr = NULL; /* Dump public key file in format used by real and the original SSH 2 */ int convert_to_ssh2 = 0; @@ -161,9 +164,13 @@ ask_filename(struct passwd *pw, const char *prompt) case KEY_RSA1: name = _PATH_SSH_CLIENT_IDENTITY; break; + case KEY_DSA_CERT: + case KEY_DSA_CERT_V00: case KEY_DSA: name = _PATH_SSH_CLIENT_ID_DSA; break; + case KEY_RSA_CERT: + case KEY_RSA_CERT_V00: case KEY_RSA: name = _PATH_SSH_CLIENT_ID_RSA; break; @@ -1104,7 +1111,7 @@ fmt_validity(u_int64_t valid_from, u_int64_t valid_to) } static void -add_flag_constraint(Buffer *c, const char *name) +add_flag_option(Buffer *c, const char *name) { debug3("%s: %s", __func__, name); buffer_put_cstring(c, name); @@ -1112,7 +1119,7 @@ add_flag_constraint(Buffer *c, const char *name) } static void -add_string_constraint(Buffer *c, const char *name, const char *value) +add_string_option(Buffer *c, const char *name, const char *value) { Buffer b; @@ -1127,24 +1134,23 @@ add_string_constraint(Buffer *c, const char *name, const char *value) } static void -prepare_constraint_buf(Buffer *c) +prepare_options_buf(Buffer *c) { - buffer_clear(c); - if ((constraint_flags & CONSTRAINT_X_FWD) != 0) - add_flag_constraint(c, "permit-X11-forwarding"); - if ((constraint_flags & CONSTRAINT_AGENT_FWD) != 0) - add_flag_constraint(c, "permit-agent-forwarding"); - if ((constraint_flags & CONSTRAINT_PORT_FWD) != 0) - add_flag_constraint(c, "permit-port-forwarding"); - if ((constraint_flags & CONSTRAINT_PTY) != 0) - add_flag_constraint(c, "permit-pty"); - if ((constraint_flags & CONSTRAINT_USER_RC) != 0) - add_flag_constraint(c, "permit-user-rc"); - if (constraint_command != NULL) - add_string_constraint(c, "force-command", constraint_command); - if (constraint_src_addr != NULL) - add_string_constraint(c, "source-address", constraint_src_addr); + if ((critical_flags & CRITOPT_X_FWD) != 0) + add_flag_option(c, "permit-X11-forwarding"); + if ((critical_flags & CRITOPT_AGENT_FWD) != 0) + add_flag_option(c, "permit-agent-forwarding"); + if ((critical_flags & CRITOPT_PORT_FWD) != 0) + add_flag_option(c, "permit-port-forwarding"); + if ((critical_flags & CRITOPT_PTY) != 0) + add_flag_option(c, "permit-pty"); + if ((critical_flags & CRITOPT_USER_RC) != 0) + add_flag_option(c, "permit-user-rc"); + if (critical_command != NULL) + add_string_option(c, "force-command", critical_command); + if (critical_src_addr != NULL) + add_string_option(c, "source-address", critical_src_addr); } static void @@ -1155,12 +1161,32 @@ do_ca_sign(struct passwd *pw, int argc, char **argv) Key *ca, *public; char *otmp, *tmp, *cp, *out, *comment, **plist = NULL; FILE *f; + int v00 = 0; /* legacy keys */ tmp = tilde_expand_filename(ca_key_path, pw->pw_uid); if ((ca = load_identity(tmp)) == NULL) fatal("Couldn't load CA key \"%s\"", tmp); xfree(tmp); + if (key_type_name != NULL) { + switch (key_type_from_name(key_type_name)) { + case KEY_RSA_CERT_V00: + case KEY_DSA_CERT_V00: + v00 = 1; + break; + case KEY_UNSPEC: + if (strcasecmp(key_type_name, "v00") == 0) { + v00 = 1; + break; + } else if (strcasecmp(key_type_name, "v01") == 0) + break; + /* FALLTHROUGH */ + default: + fprintf(stderr, "unknown key type %s\n", key_type_name); + exit(1); + } + } + for (i = 0; i < argc; i++) { /* Split list of principals */ n = 0; @@ -1183,15 +1209,16 @@ do_ca_sign(struct passwd *pw, int argc, char **argv) __func__, tmp, key_type(public)); /* Prepare certificate to sign */ - if (key_to_certified(public) != 0) + if (key_to_certified(public, v00) != 0) fatal("Could not upgrade key %s to certificate", tmp); public->cert->type = cert_key_type; + public->cert->serial = (u_int64_t)cert_serial; public->cert->key_id = xstrdup(cert_key_id); public->cert->nprincipals = n; public->cert->principals = plist; public->cert->valid_after = cert_valid_from; public->cert->valid_before = cert_valid_to; - prepare_constraint_buf(&public->cert->constraints); + prepare_options_buf(&public->cert->critical); public->cert->signature_key = key_from_private(ca); if (key_certify(public, ca) != 0) @@ -1212,13 +1239,14 @@ do_ca_sign(struct passwd *pw, int argc, char **argv) fprintf(f, " %s\n", comment); fclose(f); - if (!quiet) - logit("Signed %s key %s: id \"%s\"%s%s valid %s", - cert_key_type == SSH2_CERT_TYPE_USER?"user":"host", - out, cert_key_id, + if (!quiet) { + logit("Signed %s key %s: id \"%s\" serial %llu%s%s " + "valid %s", key_cert_type(public), + out, public->cert->key_id, public->cert->serial, cert_principals != NULL ? " for " : "", cert_principals != NULL ? cert_principals : "", fmt_validity(cert_valid_from, cert_valid_to)); + } key_free(public); xfree(out); @@ -1321,50 +1349,50 @@ parse_cert_times(char *timespec) } static void -add_cert_constraint(char *opt) +add_cert_option(char *opt) { char *val; if (strcmp(opt, "clear") == 0) - constraint_flags = 0; + critical_flags = 0; else if (strcasecmp(opt, "no-x11-forwarding") == 0) - constraint_flags &= ~CONSTRAINT_X_FWD; + critical_flags &= ~CRITOPT_X_FWD; else if (strcasecmp(opt, "permit-x11-forwarding") == 0) - constraint_flags |= CONSTRAINT_X_FWD; + critical_flags |= CRITOPT_X_FWD; else if (strcasecmp(opt, "no-agent-forwarding") == 0) - constraint_flags &= ~CONSTRAINT_AGENT_FWD; + critical_flags &= ~CRITOPT_AGENT_FWD; else if (strcasecmp(opt, "permit-agent-forwarding") == 0) - constraint_flags |= CONSTRAINT_AGENT_FWD; + critical_flags |= CRITOPT_AGENT_FWD; else if (strcasecmp(opt, "no-port-forwarding") == 0) - constraint_flags &= ~CONSTRAINT_PORT_FWD; + critical_flags &= ~CRITOPT_PORT_FWD; else if (strcasecmp(opt, "permit-port-forwarding") == 0) - constraint_flags |= CONSTRAINT_PORT_FWD; + critical_flags |= CRITOPT_PORT_FWD; else if (strcasecmp(opt, "no-pty") == 0) - constraint_flags &= ~CONSTRAINT_PTY; + critical_flags &= ~CRITOPT_PTY; else if (strcasecmp(opt, "permit-pty") == 0) - constraint_flags |= CONSTRAINT_PTY; + critical_flags |= CRITOPT_PTY; else if (strcasecmp(opt, "no-user-rc") == 0) - constraint_flags &= ~CONSTRAINT_USER_RC; + critical_flags &= ~CRITOPT_USER_RC; else if (strcasecmp(opt, "permit-user-rc") == 0) - constraint_flags |= CONSTRAINT_USER_RC; + critical_flags |= CRITOPT_USER_RC; else if (strncasecmp(opt, "force-command=", 14) == 0) { val = opt + 14; if (*val == '\0') - fatal("Empty force-command constraint"); - if (constraint_command != NULL) + fatal("Empty force-command option"); + if (critical_command != NULL) fatal("force-command already specified"); - constraint_command = xstrdup(val); + critical_command = xstrdup(val); } else if (strncasecmp(opt, "source-address=", 15) == 0) { val = opt + 15; if (*val == '\0') - fatal("Empty source-address constraint"); - if (constraint_src_addr != NULL) + fatal("Empty source-address option"); + if (critical_src_addr != NULL) fatal("source-address already specified"); if (addr_match_cidr_list(NULL, val) != 0) fatal("Invalid source-address list"); - constraint_src_addr = xstrdup(val); + critical_src_addr = xstrdup(val); } else - fatal("Unsupported certificate constraint \"%s\"", opt); + fatal("Unsupported certificate option \"%s\"", opt); } static void @@ -1373,9 +1401,9 @@ do_show_cert(struct passwd *pw) Key *key; struct stat st; char *key_fp, *ca_fp; - Buffer constraints, constraint; + Buffer options, option; u_char *name, *data; - u_int i, dlen; + u_int i, dlen, v00; if (!have_identity) ask_filename(pw, "Enter file in which the key is"); @@ -1387,17 +1415,21 @@ do_show_cert(struct passwd *pw) fatal("%s is not a public key", identity_file); if (!key_is_cert(key)) fatal("%s is not a certificate", identity_file); - + v00 = key->type == KEY_RSA_CERT_V00 || key->type == KEY_DSA_CERT_V00; + key_fp = key_fingerprint(key, SSH_FP_MD5, SSH_FP_HEX); ca_fp = key_fingerprint(key->cert->signature_key, SSH_FP_MD5, SSH_FP_HEX); printf("%s:\n", identity_file); - printf(" %s %s certificate %s\n", key_type(key), - key_cert_type(key), key_fp); - printf(" Signed by %s CA %s\n", + printf(" Type: %s %s certificate\n", key_ssh_name(key), + key_cert_type(key)); + printf(" Public key: %s %s\n", key_type(key), key_fp); + printf(" Signing CA: %s %s\n", key_type(key->cert->signature_key), ca_fp); - printf(" Key ID \"%s\"\n", key->cert->key_id); + printf(" Key ID: \"%s\"\n", key->cert->key_id); + if (!v00) + printf(" Serial: %llu\n", key->cert->serial); printf(" Valid: %s\n", fmt_validity(key->cert->valid_after, key->cert->valid_before)); printf(" Principals: "); @@ -1409,20 +1441,20 @@ do_show_cert(struct passwd *pw) key->cert->principals[i]); printf("\n"); } - printf(" Constraints: "); - if (buffer_len(&key->cert->constraints) == 0) + printf(" Critical Options: "); + if (buffer_len(&key->cert->critical) == 0) printf("(none)\n"); else { printf("\n"); - buffer_init(&constraints); - buffer_append(&constraints, - buffer_ptr(&key->cert->constraints), - buffer_len(&key->cert->constraints)); - buffer_init(&constraint); - while (buffer_len(&constraints) != 0) { - name = buffer_get_string(&constraints, NULL); - data = buffer_get_string_ptr(&constraints, &dlen); - buffer_append(&constraint, data, dlen); + buffer_init(&options); + buffer_append(&options, + buffer_ptr(&key->cert->critical), + buffer_len(&key->cert->critical)); + buffer_init(&option); + while (buffer_len(&options) != 0) { + name = buffer_get_string(&options, NULL); + data = buffer_get_string_ptr(&options, &dlen); + buffer_append(&option, data, dlen); printf(" %s", name); if (strcmp(name, "permit-X11-forwarding") == 0 || strcmp(name, "permit-agent-forwarding") == 0 || @@ -1432,22 +1464,43 @@ do_show_cert(struct passwd *pw) printf("\n"); else if (strcmp(name, "force-command") == 0 || strcmp(name, "source-address") == 0) { - data = buffer_get_string(&constraint, NULL); + data = buffer_get_string(&option, NULL); printf(" %s\n", data); xfree(data); } else { - printf(" UNKNOWN CONSTRAINT (len %u)\n", - buffer_len(&constraint)); - buffer_clear(&constraint); + printf(" UNKNOWN OPTION (len %u)\n", + buffer_len(&option)); + buffer_clear(&option); } xfree(name); - if (buffer_len(&constraint) != 0) - fatal("Constraint corrupt: extra data at end"); + if (buffer_len(&option) != 0) + fatal("Option corrupt: extra data at end"); + } + buffer_free(&option); + buffer_free(&options); + } + if (!v00) { + printf(" Extensions: "); + if (buffer_len(&key->cert->extensions) == 0) + printf("(none)\n"); + else { + printf("\n"); + buffer_init(&options); + buffer_append(&options, + buffer_ptr(&key->cert->extensions), + buffer_len(&key->cert->extensions)); + buffer_init(&option); + while (buffer_len(&options) != 0) { + name = buffer_get_string(&options, NULL); + (void)buffer_get_string_ptr(&options, &dlen); + printf(" %s UNKNOWN OPTION " + "(len %u)\n", name, dlen); + xfree(name); + } + buffer_free(&option); + buffer_free(&options); } - buffer_free(&constraint); - buffer_free(&constraints); } - exit(0); } @@ -1478,7 +1531,7 @@ usage(void) fprintf(stderr, " -M memory Amount of memory (MB) to use for generating DH-GEX moduli.\n"); fprintf(stderr, " -n name,... User/host principal names to include in certificate\n"); fprintf(stderr, " -N phrase Provide new passphrase.\n"); - fprintf(stderr, " -O cnstr Specify a certificate constraint.\n"); + fprintf(stderr, " -O cnstr Specify a certificate option.\n"); fprintf(stderr, " -P phrase Provide old passphrase.\n"); fprintf(stderr, " -p Change passphrase of private key file.\n"); fprintf(stderr, " -q Quiet.\n"); @@ -1541,7 +1594,7 @@ main(int argc, char **argv) } while ((opt = getopt(argc, argv, "degiqpclBHLhvxXyF:b:f:t:D:I:P:N:n:" - "O:C:r:g:R:T:G:M:S:s:a:V:W:")) != -1) { + "O:C:r:g:R:T:G:M:S:s:a:V:W:z:")) != -1) { switch (opt) { case 'b': bits = (u_int32_t)strtonum(optarg, 768, 32768, &errstr); @@ -1597,7 +1650,7 @@ main(int argc, char **argv) identity_new_passphrase = optarg; break; case 'O': - add_cert_constraint(optarg); + add_cert_option(optarg); break; case 'C': identity_comment = optarg; @@ -1612,7 +1665,7 @@ main(int argc, char **argv) break; case 'h': cert_key_type = SSH2_CERT_TYPE_HOST; - constraint_flags = 0; + critical_flags = 0; break; case 'i': case 'X': @@ -1661,9 +1714,8 @@ main(int argc, char **argv) break; case 'M': memory = (u_int32_t)strtonum(optarg, 1, UINT_MAX, &errstr); - if (errstr) { + if (errstr) fatal("Memory limit is %s: %s", errstr, optarg); - } break; case 'G': do_gen_candidates = 1; @@ -1685,6 +1737,11 @@ main(int argc, char **argv) case 'V': parse_cert_times(optarg); break; + case 'z': + cert_serial = strtonum(optarg, 0, LLONG_MAX, &errstr); + if (errstr) + fatal("Invalid serial number: %s", errstr); + break; case '?': default: usage(); diff --git a/ssh-rsa.c b/ssh-rsa.c index 842857fee..bb9cc8e20 100644 --- a/ssh-rsa.c +++ b/ssh-rsa.c @@ -1,4 +1,4 @@ -/* $OpenBSD: ssh-rsa.c,v 1.40 2010/02/26 20:29:54 djm Exp $ */ +/* $OpenBSD: ssh-rsa.c,v 1.41 2010/04/16 01:47:26 djm Exp $ */ /* * Copyright (c) 2000, 2003 Markus Friedl * @@ -46,9 +46,8 @@ ssh_rsa_sign(const Key *key, u_char **sigp, u_int *lenp, int ok, nid; Buffer b; - if (key == NULL || - (key->type != KEY_RSA && key->type != KEY_RSA_CERT) || - key->rsa == NULL) { + if (key == NULL || key->rsa == NULL || (key->type != KEY_RSA && + key->type != KEY_RSA_CERT && key->type != KEY_RSA_CERT_V00)) { error("ssh_rsa_sign: no RSA key"); return -1; } @@ -115,9 +114,8 @@ ssh_rsa_verify(const Key *key, const u_char *signature, u_int signaturelen, u_int len, dlen, modlen; int rlen, ret, nid; - if (key == NULL || - (key->type != KEY_RSA && key->type != KEY_RSA_CERT) || - key->rsa == NULL) { + if (key == NULL || key->rsa == NULL || (key->type != KEY_RSA && + key->type != KEY_RSA_CERT && key->type != KEY_RSA_CERT_V00)) { error("ssh_rsa_verify: no RSA key"); return -1; } diff --git a/sshconnect.c b/sshconnect.c index ca83bc792..3c8b8c7c2 100644 --- a/sshconnect.c +++ b/sshconnect.c @@ -1,4 +1,4 @@ -/* $OpenBSD: sshconnect.c,v 1.222 2010/04/14 22:27:42 djm Exp $ */ +/* $OpenBSD: sshconnect.c,v 1.223 2010/04/16 01:47:26 djm Exp $ */ /* * Author: Tatu Ylonen * Copyright (c) 1995 Tatu Ylonen , Espoo, Finland @@ -586,9 +586,9 @@ check_host_cert(const char *host, const Key *host_key) error("%s", reason); return 0; } - if (buffer_len(&host_key->cert->constraints) != 0) { - error("Certificate for %s contains unsupported constraint(s)", - host); + if (buffer_len(&host_key->cert->critical) != 0) { + error("Certificate for %s contains unsupported " + "critical options(s)", host); return 0; } return 1; diff --git a/sshconnect2.c b/sshconnect2.c index 25a3323f0..e146a4b26 100644 --- a/sshconnect2.c +++ b/sshconnect2.c @@ -1,4 +1,4 @@ -/* $OpenBSD: sshconnect2.c,v 1.181 2010/04/10 02:10:56 djm Exp $ */ +/* $OpenBSD: sshconnect2.c,v 1.182 2010/04/16 01:47:26 djm Exp $ */ /* * Copyright (c) 2000 Markus Friedl. All rights reserved. * Copyright (c) 2008 Damien Miller. All rights reserved. @@ -1140,8 +1140,11 @@ sign_and_send_pubkey(Authctxt *authctxt, Identity *id) u_int skip = 0; int ret = -1; int have_sig = 1; + char *fp; - debug3("sign_and_send_pubkey"); + fp = key_fingerprint(id->key, SSH_FP_MD5, SSH_FP_HEX); + debug3("sign_and_send_pubkey: %s %s", key_type(id->key), fp); + xfree(fp); if (key_to_blob(id->key, &blob, &bloblen) == 0) { /* we cannot handle this key */ diff --git a/sshd.c b/sshd.c index bc0d2753f..a7d3ee5c4 100644 --- a/sshd.c +++ b/sshd.c @@ -1,4 +1,4 @@ -/* $OpenBSD: sshd.c,v 1.374 2010/03/07 11:57:13 dtucker Exp $ */ +/* $OpenBSD: sshd.c,v 1.375 2010/04/16 01:47:26 djm Exp $ */ /* * Author: Tatu Ylonen * Copyright (c) 1995 Tatu Ylonen , Espoo, Finland @@ -744,6 +744,8 @@ list_hostkey_types(void) if (key == NULL) continue; switch (key->type) { + case KEY_RSA_CERT_V00: + case KEY_DSA_CERT_V00: case KEY_RSA_CERT: case KEY_DSA_CERT: if (buffer_len(&b) > 0) @@ -767,10 +769,17 @@ get_hostkey_by_type(int type, int need_private) Key *key; for (i = 0; i < options.num_host_key_files; i++) { - if (type == KEY_RSA_CERT || type == KEY_DSA_CERT) + switch (type) { + case KEY_RSA_CERT_V00: + case KEY_DSA_CERT_V00: + case KEY_RSA_CERT: + case KEY_DSA_CERT: key = sensitive_data.host_certificates[i]; - else + break; + default: key = sensitive_data.host_keys[i]; + break; + } if (key != NULL && key->type == type) return need_private ? sensitive_data.host_keys[i] : key; -- cgit v1.2.3 From c617aa9ff541d00df413846835ad31e556e71b31 Mon Sep 17 00:00:00 2001 From: Damien Miller Date: Sun, 18 Apr 2010 08:08:20 +1000 Subject: - djm@cvs.openbsd.org 2010/04/16 21:14:27 [sshconnect.c] oops, %r => remote username, not %u --- ChangeLog | 3 +++ sshconnect.c | 4 ++-- 2 files changed, 5 insertions(+), 2 deletions(-) (limited to 'sshconnect.c') diff --git a/ChangeLog b/ChangeLog index f629ff037..04eefa62b 100644 --- a/ChangeLog +++ b/ChangeLog @@ -6,6 +6,9 @@ - jmc@cvs.openbsd.org 2010/04/16 06:47:04 [ssh-keygen.1 ssh-keygen.c] tweak previous; ok djm + - djm@cvs.openbsd.org 2010/04/16 21:14:27 + [sshconnect.c] + oops, %r => remote username, not %u 20100416 - (djm) Release openssh-5.5p1 diff --git a/sshconnect.c b/sshconnect.c index 3c8b8c7c2..f55beffe4 100644 --- a/sshconnect.c +++ b/sshconnect.c @@ -1,4 +1,4 @@ -/* $OpenBSD: sshconnect.c,v 1.223 2010/04/16 01:47:26 djm Exp $ */ +/* $OpenBSD: sshconnect.c,v 1.224 2010/04/16 21:14:27 djm Exp $ */ /* * Author: Tatu Ylonen * Copyright (c) 1995 Tatu Ylonen , Espoo, Finland @@ -102,7 +102,7 @@ ssh_proxy_connect(const char *host, u_short port, const char *proxy_command) */ xasprintf(&tmp, "exec %s", proxy_command); command_string = percent_expand(tmp, "h", host, "p", strport, - "u", options.user, (char *)NULL); + "r", options.user, (char *)NULL); xfree(tmp); /* Create pipes for communicating with the proxy. */ -- cgit v1.2.3