summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorDamien Miller <djm@mindrot.org>2010-04-16 15:56:21 +1000
committerDamien Miller <djm@mindrot.org>2010-04-16 15:56:21 +1000
commit4e270b05dd9d850fb9e2e0ac43f33cb4090d3ebc (patch)
tree4fc84942b5966e9f38f18a1257ac43ddbed336be
parent031c9100dfe3ee65a29084ebbd61965a76b3ad26 (diff)
- 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@
-rw-r--r--ChangeLog21
-rw-r--r--PROTOCOL.certkeys73
-rw-r--r--auth-options.c21
-rw-r--r--auth-options.h4
-rw-r--r--auth-rsa.c4
-rw-r--r--auth2-pubkey.c9
-rw-r--r--authfd.c6
-rw-r--r--key.c177
-rw-r--r--key.h11
-rw-r--r--myproposal.h11
-rw-r--r--ssh-add.c4
-rw-r--r--ssh-agent.c5
-rw-r--r--ssh-dss.c12
-rw-r--r--ssh-keygen.127
-rw-r--r--ssh-keygen.c235
-rw-r--r--ssh-rsa.c12
-rw-r--r--sshconnect.c8
-rw-r--r--sshconnect2.c7
-rw-r--r--sshd.c15
19 files changed, 449 insertions, 213 deletions
diff --git a/ChangeLog b/ChangeLog
index fd4ce5db2..b058de0f8 100644
--- a/ChangeLog
+++ b/ChangeLog
@@ -41,6 +41,27 @@
41 retry lookup for private key if there's no matching key with CKA_SIGN 41 retry lookup for private key if there's no matching key with CKA_SIGN
42 attribute enabled; this fixes fixes MuscleCard support (bugzilla #1736) 42 attribute enabled; this fixes fixes MuscleCard support (bugzilla #1736)
43 ok djm@ 43 ok djm@
44 - djm@cvs.openbsd.org 2010/04/16 01:47:26
45 [PROTOCOL.certkeys auth-options.c auth-options.h auth-rsa.c]
46 [auth2-pubkey.c authfd.c key.c key.h myproposal.h ssh-add.c]
47 [ssh-agent.c ssh-dss.c ssh-keygen.1 ssh-keygen.c ssh-rsa.c]
48 [sshconnect.c sshconnect2.c sshd.c]
49 revised certificate format ssh-{dss,rsa}-cert-v01@openssh.com with the
50 following changes:
51
52 move the nonce field to the beginning of the certificate where it can
53 better protect against chosen-prefix attacks on the signature hash
54
55 Rename "constraints" field to "critical options"
56
57 Add a new non-critical "extensions" field
58
59 Add a serial number
60
61 The older format is still support for authentication and cert generation
62 (use "ssh-keygen -t v00 -s ca_key ..." to generate a v00 certificate)
63
64 ok markus@
44 65
4520100410 6620100410
46 - (dtucker) [configure.ac] Put the check for the existence of getaddrinfo 67 - (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
16system already in SSH to allow certificate-based authentication. 16system already in SSH to allow certificate-based authentication.
17The certificates used are not traditional X.509 certificates, with 17The certificates used are not traditional X.509 certificates, with
18numerous options and complex encoding rules, but something rather 18numerous options and complex encoding rules, but something rather
19more minimal: a key, some identity information and usage constraints 19more minimal: a key, some identity information and usage options
20that have been signed with some other trusted key. 20that have been signed with some other trusted key.
21 21
22A sshd server may be configured to allow authentication via certified 22A 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
27to specify CA keys in ~/.ssh/known_hosts. 27to specify CA keys in ~/.ssh/known_hosts.
28 28
29Certified keys are represented using two new key types: 29Certified keys are represented using two new key types:
30ssh-rsa-cert-v00@openssh.com and ssh-dss-cert-v00@openssh.com that 30ssh-rsa-cert-v01@openssh.com and ssh-dss-cert-v01@openssh.com that
31include certification information along with the public key that is used 31include certification information along with the public key that is used
32to sign challenges. ssh-keygen performs the CA signing operation. 32to sign challenges. ssh-keygen performs the CA signing operation.
33 33
@@ -47,7 +47,7 @@ in RFC4252 section 7.
47New public key formats 47New public key formats
48---------------------- 48----------------------
49 49
50The ssh-rsa-cert-v00@openssh.com and ssh-dss-cert-v00@openssh.com key 50The ssh-rsa-cert-v01@openssh.com and ssh-dss-cert-v01@openssh.com key
51types take a similar high-level format (note: data types and 51types take a similar high-level format (note: data types and
52encoding are as per RFC4251 section 5). The serialised wire encoding of 52encoding are as per RFC4251 section 5). The serialised wire encoding of
53these certificates is also used for storing them on disk. 53these certificates is also used for storing them on disk.
@@ -57,42 +57,55 @@ these certificates is also used for storing them on disk.
57 57
58RSA certificate 58RSA certificate
59 59
60 string "ssh-rsa-cert-v00@openssh.com" 60 string "ssh-rsa-cert-v01@openssh.com"
61 string nonce
61 mpint e 62 mpint e
62 mpint n 63 mpint n
64 uint64 serial
63 uint32 type 65 uint32 type
64 string key id 66 string key id
65 string valid principals 67 string valid principals
66 uint64 valid after 68 uint64 valid after
67 uint64 valid before 69 uint64 valid before
68 string constraints 70 string critical options
69 string nonce 71 string extensions
70 string reserved 72 string reserved
71 string signature key 73 string signature key
72 string signature 74 string signature
73 75
74DSA certificate 76DSA certificate
75 77
76 string "ssh-dss-cert-v00@openssh.com" 78 string "ssh-dss-cert-v01@openssh.com"
79 string nonce
77 mpint p 80 mpint p
78 mpint q 81 mpint q
79 mpint g 82 mpint g
80 mpint y 83 mpint y
84 uint64 serial
81 uint32 type 85 uint32 type
82 string key id 86 string key id
83 string valid principals 87 string valid principals
84 uint64 valid after 88 uint64 valid after
85 uint64 valid before 89 uint64 valid before
86 string constraints 90 string critical options
87 string nonce 91 string extensions
88 string reserved 92 string reserved
89 string signature key 93 string signature key
90 string signature 94 string signature
91 95
96The nonce field is a CA-provided random bitstring of arbitrary length
97(but typically 16 or 32 bytes) included to make attacks that depend on
98inducing collisions in the signature hash infeasible.
99
92e and n are the RSA exponent and public modulus respectively. 100e and n are the RSA exponent and public modulus respectively.
93 101
94p, q, g, y are the DSA parameters as described in FIPS-186-2. 102p, q, g, y are the DSA parameters as described in FIPS-186-2.
95 103
104serial is an optional certificate serial number set by the CA to
105provide an abbreviated way to refer to certificates from that CA.
106If a CA does not with to number its certificates it must set this
107field to zero.
108
96type specifies whether this certificate is for identification of a user 109type specifies whether this certificate is for identification of a user
97or a host using a SSH_CERT_TYPE_... value. 110or a host using a SSH_CERT_TYPE_... value.
98 111
@@ -112,13 +125,15 @@ certificate. Each represents a time in seconds since 1970-01-01
11200:00:00. A certificate is considered valid if: 12500:00:00. A certificate is considered valid if:
113 valid after <= current time < valid before 126 valid after <= current time < valid before
114 127
115constraints is a set of zero or more key constraints encoded as below. 128criticial options is a set of zero or more key options encoded as
129below. All such options are "critical" in the sense that an implementation
130must refuse to authorise a key that has an unrecognised option.
116 131
117The nonce field is a CA-provided random bitstring of arbitrary length 132extensions is a set of zero or more optional extensions. These extensions
118(but typically 16 or 32 bytes) included to make attacks that depend on 133are not critical, and an implementation that encounters one that it does
119inducing collisions in the signature hash infeasible. 134not recognise may safely ignore it. No extensions are defined at present.
120 135
121The reserved field is current unused and is ignored in this version of 136The reserved field is currently unused and is ignored in this version of
122the protocol. 137the protocol.
123 138
124signature key contains the CA key used to sign the certificate. 139signature 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
132encoded according to the rules defined for the CA's public key algorithm 147encoded according to the rules defined for the CA's public key algorithm
133(RFC4253 section 6.6 for ssh-rsa and ssh-dss). 148(RFC4253 section 6.6 for ssh-rsa and ssh-dss).
134 149
135Constraints 150Critical options
136----------- 151----------------
137 152
138The constraints section of the certificate specifies zero or more 153The critical options section of the certificate specifies zero or more
139constraints on the certificates validity. The format of this field 154options on the certificates validity. The format of this field
140is a sequence of zero or more tuples: 155is a sequence of zero or more tuples:
141 156
142 string name 157 string name
143 string data 158 string data
144 159
145The name field identifies the constraint and the data field encodes 160The name field identifies the option and the data field encodes
146constraint-specific information (see below). All constraints are 161option-specific information (see below). All options are
147"critical", if an implementation does not recognise a constraint 162"critical", if an implementation does not recognise a option
148then the validating party should refuse to accept the certificate. 163then the validating party should refuse to accept the certificate.
149 164
150The supported constraints and the contents and structure of their 165The supported options and the contents and structure of their
151data fields are: 166data fields are:
152 167
153Name Format Description 168Name Format Description
@@ -159,35 +174,35 @@ force-command string Specifies a command that is executed
159 174
160permit-X11-forwarding empty Flag indicating that X11 forwarding 175permit-X11-forwarding empty Flag indicating that X11 forwarding
161 should be permitted. X11 forwarding will 176 should be permitted. X11 forwarding will
162 be refused if this constraint is absent. 177 be refused if this option is absent.
163 178
164permit-agent-forwarding empty Flag indicating that agent forwarding 179permit-agent-forwarding empty Flag indicating that agent forwarding
165 should be allowed. Agent forwarding 180 should be allowed. Agent forwarding
166 must not be permitted unless this 181 must not be permitted unless this
167 constraint is present. 182 option is present.
168 183
169permit-port-forwarding empty Flag indicating that port-forwarding 184permit-port-forwarding empty Flag indicating that port-forwarding
170 should be allowed. If this constraint is 185 should be allowed. If this option is
171 not present then no port forwarding will 186 not present then no port forwarding will
172 be allowed. 187 be allowed.
173 188
174permit-pty empty Flag indicating that PTY allocation 189permit-pty empty Flag indicating that PTY allocation
175 should be permitted. In the absence of 190 should be permitted. In the absence of
176 this constraint PTY allocation will be 191 this option PTY allocation will be
177 disabled. 192 disabled.
178 193
179permit-user-rc empty Flag indicating that execution of 194permit-user-rc empty Flag indicating that execution of
180 ~/.ssh/rc should be permitted. Execution 195 ~/.ssh/rc should be permitted. Execution
181 of this script will not be permitted if 196 of this script will not be permitted if
182 this constraint is not present. 197 this option is not present.
183 198
184source-address string Comma-separated list of source addresses 199source-address string Comma-separated list of source addresses
185 from which this certificate is accepted 200 from which this certificate is accepted
186 for authentication. Addresses are 201 for authentication. Addresses are
187 specified in CIDR format (nn.nn.nn.nn/nn 202 specified in CIDR format (nn.nn.nn.nn/nn
188 or hhhh::hhhh/nn). 203 or hhhh::hhhh/nn).
189 If this constraint is not present then 204 If this option is not present then
190 certificates may be presented from any 205 certificates may be presented from any
191 source address. 206 source address.
192 207
193$OpenBSD: PROTOCOL.certkeys,v 1.3 2010/03/03 22:50:40 djm Exp $ 208$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 @@
1/* $OpenBSD: auth-options.c,v 1.49 2010/03/16 15:46:52 stevesk Exp $ */ 1/* $OpenBSD: auth-options.c,v 1.50 2010/04/16 01:47:26 djm Exp $ */
2/* 2/*
3 * Author: Tatu Ylonen <ylo@cs.hut.fi> 3 * Author: Tatu Ylonen <ylo@cs.hut.fi>
4 * Copyright (c) 1995 Tatu Ylonen <ylo@cs.hut.fi>, Espoo, Finland 4 * Copyright (c) 1995 Tatu Ylonen <ylo@cs.hut.fi>, Espoo, Finland
@@ -27,10 +27,10 @@
27#include "canohost.h" 27#include "canohost.h"
28#include "buffer.h" 28#include "buffer.h"
29#include "channels.h" 29#include "channels.h"
30#include "auth-options.h"
31#include "servconf.h" 30#include "servconf.h"
32#include "misc.h" 31#include "misc.h"
33#include "key.h" 32#include "key.h"
33#include "auth-options.h"
34#include "hostfile.h" 34#include "hostfile.h"
35#include "auth.h" 35#include "auth.h"
36#ifdef GSSAPI 36#ifdef GSSAPI
@@ -377,11 +377,11 @@ bad_option:
377} 377}
378 378
379/* 379/*
380 * Set options from certificate constraints. These supersede user key options 380 * Set options from critical certificate options. These supersede user key
381 * so this must be called after auth_parse_options(). 381 * options so this must be called after auth_parse_options().
382 */ 382 */
383int 383int
384auth_cert_constraints(Buffer *c_orig, struct passwd *pw) 384auth_cert_options(Key *k, struct passwd *pw)
385{ 385{
386 u_char *name = NULL, *data_blob = NULL; 386 u_char *name = NULL, *data_blob = NULL;
387 u_int nlen, dlen, clen; 387 u_int nlen, dlen, clen;
@@ -400,12 +400,13 @@ auth_cert_constraints(Buffer *c_orig, struct passwd *pw)
400 400
401 /* Make copy to avoid altering original */ 401 /* Make copy to avoid altering original */
402 buffer_init(&c); 402 buffer_init(&c);
403 buffer_append(&c, buffer_ptr(c_orig), buffer_len(c_orig)); 403 buffer_append(&c,
404 buffer_ptr(&k->cert->critical), buffer_len(&k->cert->critical));
404 405
405 while (buffer_len(&c) > 0) { 406 while (buffer_len(&c) > 0) {
406 if ((name = buffer_get_string_ret(&c, &nlen)) == NULL || 407 if ((name = buffer_get_string_ret(&c, &nlen)) == NULL ||
407 (data_blob = buffer_get_string_ret(&c, &dlen)) == NULL) { 408 (data_blob = buffer_get_string_ret(&c, &dlen)) == NULL) {
408 error("Certificate constraints corrupt"); 409 error("Certificate options corrupt");
409 goto out; 410 goto out;
410 } 411 }
411 buffer_append(&data, data_blob, dlen); 412 buffer_append(&data, data_blob, dlen);
@@ -439,7 +440,7 @@ auth_cert_constraints(Buffer *c_orig, struct passwd *pw)
439 } 440 }
440 if (cert_forced_command != NULL) { 441 if (cert_forced_command != NULL) {
441 error("Certificate has multiple " 442 error("Certificate has multiple "
442 "force-command constraints"); 443 "force-command options");
443 xfree(command); 444 xfree(command);
444 goto out; 445 goto out;
445 } 446 }
@@ -459,7 +460,7 @@ auth_cert_constraints(Buffer *c_orig, struct passwd *pw)
459 } 460 }
460 if (cert_source_address_done++) { 461 if (cert_source_address_done++) {
461 error("Certificate has multiple " 462 error("Certificate has multiple "
462 "source-address constraints"); 463 "source-address options");
463 xfree(allowed); 464 xfree(allowed);
464 goto out; 465 goto out;
465 } 466 }
@@ -502,7 +503,7 @@ auth_cert_constraints(Buffer *c_orig, struct passwd *pw)
502 name = data_blob = NULL; 503 name = data_blob = NULL;
503 } 504 }
504 505
505 /* successfully parsed all constraints */ 506 /* successfully parsed all options */
506 ret = 0; 507 ret = 0;
507 508
508 no_port_forwarding_flag |= cert_no_port_forwarding_flag; 509 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 @@
1/* $OpenBSD: auth-options.h,v 1.18 2010/02/26 20:29:54 djm Exp $ */ 1/* $OpenBSD: auth-options.h,v 1.19 2010/04/16 01:47:26 djm Exp $ */
2 2
3/* 3/*
4 * Author: Tatu Ylonen <ylo@cs.hut.fi> 4 * Author: Tatu Ylonen <ylo@cs.hut.fi>
@@ -34,6 +34,6 @@ extern int key_is_cert_authority;
34 34
35int auth_parse_options(struct passwd *, char *, char *, u_long); 35int auth_parse_options(struct passwd *, char *, char *, u_long);
36void auth_clear_options(void); 36void auth_clear_options(void);
37int auth_cert_constraints(Buffer *, struct passwd *); 37int auth_cert_options(Key *, struct passwd *);
38 38
39#endif 39#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 @@
1/* $OpenBSD: auth-rsa.c,v 1.74 2010/03/04 10:36:03 djm Exp $ */ 1/* $OpenBSD: auth-rsa.c,v 1.75 2010/04/16 01:47:26 djm Exp $ */
2/* 2/*
3 * Author: Tatu Ylonen <ylo@cs.hut.fi> 3 * Author: Tatu Ylonen <ylo@cs.hut.fi>
4 * Copyright (c) 1995 Tatu Ylonen <ylo@cs.hut.fi>, Espoo, Finland 4 * Copyright (c) 1995 Tatu Ylonen <ylo@cs.hut.fi>, Espoo, Finland
@@ -34,11 +34,11 @@
34#include "uidswap.h" 34#include "uidswap.h"
35#include "match.h" 35#include "match.h"
36#include "buffer.h" 36#include "buffer.h"
37#include "auth-options.h"
38#include "pathnames.h" 37#include "pathnames.h"
39#include "log.h" 38#include "log.h"
40#include "servconf.h" 39#include "servconf.h"
41#include "key.h" 40#include "key.h"
41#include "auth-options.h"
42#include "hostfile.h" 42#include "hostfile.h"
43#include "auth.h" 43#include "auth.h"
44#ifdef GSSAPI 44#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 @@
1/* $OpenBSD: auth2-pubkey.c,v 1.22 2010/03/10 23:27:17 djm Exp $ */ 1/* $OpenBSD: auth2-pubkey.c,v 1.23 2010/04/16 01:47:26 djm Exp $ */
2/* 2/*
3 * Copyright (c) 2000 Markus Friedl. All rights reserved. 3 * Copyright (c) 2000 Markus Friedl. All rights reserved.
4 * 4 *
@@ -235,7 +235,7 @@ user_key_allowed2(struct passwd *pw, Key *key, char *file)
235 } 235 }
236 if (auth_parse_options(pw, key_options, file, linenum) != 1) 236 if (auth_parse_options(pw, key_options, file, linenum) != 1)
237 continue; 237 continue;
238 if (key->type == KEY_RSA_CERT || key->type == KEY_DSA_CERT) { 238 if (key_is_cert(key)) {
239 if (!key_is_cert_authority) 239 if (!key_is_cert_authority)
240 continue; 240 continue;
241 if (!key_equal(found, key->cert->signature_key)) 241 if (!key_equal(found, key->cert->signature_key))
@@ -251,8 +251,7 @@ user_key_allowed2(struct passwd *pw, Key *key, char *file)
251 auth_debug_add("%s", reason); 251 auth_debug_add("%s", reason);
252 continue; 252 continue;
253 } 253 }
254 if (auth_cert_constraints(&key->cert->constraints, 254 if (auth_cert_options(key, pw) != 0) {
255 pw) != 0) {
256 xfree(fp); 255 xfree(fp);
257 continue; 256 continue;
258 } 257 }
@@ -307,7 +306,7 @@ user_cert_trusted_ca(struct passwd *pw, Key *key)
307 auth_debug_add("%s", reason); 306 auth_debug_add("%s", reason);
308 goto out; 307 goto out;
309 } 308 }
310 if (auth_cert_constraints(&key->cert->constraints, pw) != 0) 309 if (auth_cert_options(key, pw) != 0)
311 goto out; 310 goto out;
312 311
313 verbose("Accepted certificate ID \"%s\" signed by %s CA %s via %s", 312 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 @@
1/* $OpenBSD: authfd.c,v 1.82 2010/02/26 20:29:54 djm Exp $ */ 1/* $OpenBSD: authfd.c,v 1.83 2010/04/16 01:47:26 djm Exp $ */
2/* 2/*
3 * Author: Tatu Ylonen <ylo@cs.hut.fi> 3 * Author: Tatu Ylonen <ylo@cs.hut.fi>
4 * Copyright (c) 1995 Tatu Ylonen <ylo@cs.hut.fi>, Espoo, Finland 4 * Copyright (c) 1995 Tatu Ylonen <ylo@cs.hut.fi>, Espoo, Finland
@@ -483,6 +483,7 @@ ssh_encode_identity_ssh2(Buffer *b, Key *key, const char *comment)
483 buffer_put_bignum2(b, key->rsa->p); 483 buffer_put_bignum2(b, key->rsa->p);
484 buffer_put_bignum2(b, key->rsa->q); 484 buffer_put_bignum2(b, key->rsa->q);
485 break; 485 break;
486 case KEY_RSA_CERT_V00:
486 case KEY_RSA_CERT: 487 case KEY_RSA_CERT:
487 if (key->cert == NULL || buffer_len(&key->cert->certblob) == 0) 488 if (key->cert == NULL || buffer_len(&key->cert->certblob) == 0)
488 fatal("%s: no cert/certblob", __func__); 489 fatal("%s: no cert/certblob", __func__);
@@ -500,6 +501,7 @@ ssh_encode_identity_ssh2(Buffer *b, Key *key, const char *comment)
500 buffer_put_bignum2(b, key->dsa->pub_key); 501 buffer_put_bignum2(b, key->dsa->pub_key);
501 buffer_put_bignum2(b, key->dsa->priv_key); 502 buffer_put_bignum2(b, key->dsa->priv_key);
502 break; 503 break;
504 case KEY_DSA_CERT_V00:
503 case KEY_DSA_CERT: 505 case KEY_DSA_CERT:
504 if (key->cert == NULL || buffer_len(&key->cert->certblob) == 0) 506 if (key->cert == NULL || buffer_len(&key->cert->certblob) == 0)
505 fatal("%s: no cert/certblob", __func__); 507 fatal("%s: no cert/certblob", __func__);
@@ -535,8 +537,10 @@ ssh_add_identity_constrained(AuthenticationConnection *auth, Key *key,
535 break; 537 break;
536 case KEY_RSA: 538 case KEY_RSA:
537 case KEY_RSA_CERT: 539 case KEY_RSA_CERT:
540 case KEY_RSA_CERT_V00:
538 case KEY_DSA: 541 case KEY_DSA:
539 case KEY_DSA_CERT: 542 case KEY_DSA_CERT:
543 case KEY_DSA_CERT_V00:
540 type = constrained ? 544 type = constrained ?
541 SSH2_AGENTC_ADD_ID_CONSTRAINED : 545 SSH2_AGENTC_ADD_ID_CONSTRAINED :
542 SSH2_AGENTC_ADD_IDENTITY; 546 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 @@
1/* $OpenBSD: key.c,v 1.86 2010/03/15 19:40:02 stevesk Exp $ */ 1/* $OpenBSD: key.c,v 1.87 2010/04/16 01:47:26 djm Exp $ */
2/* 2/*
3 * read_bignum(): 3 * read_bignum():
4 * Copyright (c) 1995 Tatu Ylonen <ylo@cs.hut.fi>, Espoo, Finland 4 * Copyright (c) 1995 Tatu Ylonen <ylo@cs.hut.fi>, Espoo, Finland
@@ -61,7 +61,8 @@ cert_new(void)
61 61
62 cert = xcalloc(1, sizeof(*cert)); 62 cert = xcalloc(1, sizeof(*cert));
63 buffer_init(&cert->certblob); 63 buffer_init(&cert->certblob);
64 buffer_init(&cert->constraints); 64 buffer_init(&cert->critical);
65 buffer_init(&cert->extensions);
65 cert->key_id = NULL; 66 cert->key_id = NULL;
66 cert->principals = NULL; 67 cert->principals = NULL;
67 cert->signature_key = NULL; 68 cert->signature_key = NULL;
@@ -82,6 +83,7 @@ key_new(int type)
82 switch (k->type) { 83 switch (k->type) {
83 case KEY_RSA1: 84 case KEY_RSA1:
84 case KEY_RSA: 85 case KEY_RSA:
86 case KEY_RSA_CERT_V00:
85 case KEY_RSA_CERT: 87 case KEY_RSA_CERT:
86 if ((rsa = RSA_new()) == NULL) 88 if ((rsa = RSA_new()) == NULL)
87 fatal("key_new: RSA_new failed"); 89 fatal("key_new: RSA_new failed");
@@ -92,6 +94,7 @@ key_new(int type)
92 k->rsa = rsa; 94 k->rsa = rsa;
93 break; 95 break;
94 case KEY_DSA: 96 case KEY_DSA:
97 case KEY_DSA_CERT_V00:
95 case KEY_DSA_CERT: 98 case KEY_DSA_CERT:
96 if ((dsa = DSA_new()) == NULL) 99 if ((dsa = DSA_new()) == NULL)
97 fatal("key_new: DSA_new failed"); 100 fatal("key_new: DSA_new failed");
@@ -124,6 +127,7 @@ key_add_private(Key *k)
124 switch (k->type) { 127 switch (k->type) {
125 case KEY_RSA1: 128 case KEY_RSA1:
126 case KEY_RSA: 129 case KEY_RSA:
130 case KEY_RSA_CERT_V00:
127 case KEY_RSA_CERT: 131 case KEY_RSA_CERT:
128 if ((k->rsa->d = BN_new()) == NULL) 132 if ((k->rsa->d = BN_new()) == NULL)
129 fatal("key_new_private: BN_new failed"); 133 fatal("key_new_private: BN_new failed");
@@ -139,6 +143,7 @@ key_add_private(Key *k)
139 fatal("key_new_private: BN_new failed"); 143 fatal("key_new_private: BN_new failed");
140 break; 144 break;
141 case KEY_DSA: 145 case KEY_DSA:
146 case KEY_DSA_CERT_V00:
142 case KEY_DSA_CERT: 147 case KEY_DSA_CERT:
143 if ((k->dsa->priv_key = BN_new()) == NULL) 148 if ((k->dsa->priv_key = BN_new()) == NULL)
144 fatal("key_new_private: BN_new failed"); 149 fatal("key_new_private: BN_new failed");
@@ -165,7 +170,8 @@ cert_free(struct KeyCert *cert)
165 u_int i; 170 u_int i;
166 171
167 buffer_free(&cert->certblob); 172 buffer_free(&cert->certblob);
168 buffer_free(&cert->constraints); 173 buffer_free(&cert->critical);
174 buffer_free(&cert->extensions);
169 if (cert->key_id != NULL) 175 if (cert->key_id != NULL)
170 xfree(cert->key_id); 176 xfree(cert->key_id);
171 for (i = 0; i < cert->nprincipals; i++) 177 for (i = 0; i < cert->nprincipals; i++)
@@ -184,12 +190,14 @@ key_free(Key *k)
184 switch (k->type) { 190 switch (k->type) {
185 case KEY_RSA1: 191 case KEY_RSA1:
186 case KEY_RSA: 192 case KEY_RSA:
193 case KEY_RSA_CERT_V00:
187 case KEY_RSA_CERT: 194 case KEY_RSA_CERT:
188 if (k->rsa != NULL) 195 if (k->rsa != NULL)
189 RSA_free(k->rsa); 196 RSA_free(k->rsa);
190 k->rsa = NULL; 197 k->rsa = NULL;
191 break; 198 break;
192 case KEY_DSA: 199 case KEY_DSA:
200 case KEY_DSA_CERT_V00:
193 case KEY_DSA_CERT: 201 case KEY_DSA_CERT:
194 if (k->dsa != NULL) 202 if (k->dsa != NULL)
195 DSA_free(k->dsa); 203 DSA_free(k->dsa);
@@ -238,11 +246,13 @@ key_equal_public(const Key *a, const Key *b)
238 246
239 switch (a->type) { 247 switch (a->type) {
240 case KEY_RSA1: 248 case KEY_RSA1:
249 case KEY_RSA_CERT_V00:
241 case KEY_RSA_CERT: 250 case KEY_RSA_CERT:
242 case KEY_RSA: 251 case KEY_RSA:
243 return a->rsa != NULL && b->rsa != NULL && 252 return a->rsa != NULL && b->rsa != NULL &&
244 BN_cmp(a->rsa->e, b->rsa->e) == 0 && 253 BN_cmp(a->rsa->e, b->rsa->e) == 0 &&
245 BN_cmp(a->rsa->n, b->rsa->n) == 0; 254 BN_cmp(a->rsa->n, b->rsa->n) == 0;
255 case KEY_DSA_CERT_V00:
246 case KEY_DSA_CERT: 256 case KEY_DSA_CERT:
247 case KEY_DSA: 257 case KEY_DSA:
248 return a->dsa != NULL && b->dsa != NULL && 258 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)
304 case KEY_RSA: 314 case KEY_RSA:
305 key_to_blob(k, &blob, &len); 315 key_to_blob(k, &blob, &len);
306 break; 316 break;
317 case KEY_DSA_CERT_V00:
318 case KEY_RSA_CERT_V00:
307 case KEY_DSA_CERT: 319 case KEY_DSA_CERT:
308 case KEY_RSA_CERT: 320 case KEY_RSA_CERT:
309 /* We want a fingerprint of the _key_ not of the cert */ 321 /* We want a fingerprint of the _key_ not of the cert */
@@ -631,6 +643,8 @@ key_read(Key *ret, char **cpp)
631 case KEY_UNSPEC: 643 case KEY_UNSPEC:
632 case KEY_RSA: 644 case KEY_RSA:
633 case KEY_DSA: 645 case KEY_DSA:
646 case KEY_DSA_CERT_V00:
647 case KEY_RSA_CERT_V00:
634 case KEY_DSA_CERT: 648 case KEY_DSA_CERT:
635 case KEY_RSA_CERT: 649 case KEY_RSA_CERT:
636 space = strchr(cp, ' '); 650 space = strchr(cp, ' ');
@@ -757,11 +771,13 @@ key_write(const Key *key, FILE *f)
757 error("key_write: failed for RSA key"); 771 error("key_write: failed for RSA key");
758 return 0; 772 return 0;
759 case KEY_DSA: 773 case KEY_DSA:
774 case KEY_DSA_CERT_V00:
760 case KEY_DSA_CERT: 775 case KEY_DSA_CERT:
761 if (key->dsa == NULL) 776 if (key->dsa == NULL)
762 return 0; 777 return 0;
763 break; 778 break;
764 case KEY_RSA: 779 case KEY_RSA:
780 case KEY_RSA_CERT_V00:
765 case KEY_RSA_CERT: 781 case KEY_RSA_CERT:
766 if (key->rsa == NULL) 782 if (key->rsa == NULL)
767 return 0; 783 return 0;
@@ -793,6 +809,10 @@ key_type(const Key *k)
793 return "RSA"; 809 return "RSA";
794 case KEY_DSA: 810 case KEY_DSA:
795 return "DSA"; 811 return "DSA";
812 case KEY_RSA_CERT_V00:
813 return "RSA-CERT-V00";
814 case KEY_DSA_CERT_V00:
815 return "DSA-CERT-V00";
796 case KEY_RSA_CERT: 816 case KEY_RSA_CERT:
797 return "RSA-CERT"; 817 return "RSA-CERT";
798 case KEY_DSA_CERT: 818 case KEY_DSA_CERT:
@@ -822,10 +842,14 @@ key_ssh_name(const Key *k)
822 return "ssh-rsa"; 842 return "ssh-rsa";
823 case KEY_DSA: 843 case KEY_DSA:
824 return "ssh-dss"; 844 return "ssh-dss";
825 case KEY_RSA_CERT: 845 case KEY_RSA_CERT_V00:
826 return "ssh-rsa-cert-v00@openssh.com"; 846 return "ssh-rsa-cert-v00@openssh.com";
827 case KEY_DSA_CERT: 847 case KEY_DSA_CERT_V00:
828 return "ssh-dss-cert-v00@openssh.com"; 848 return "ssh-dss-cert-v00@openssh.com";
849 case KEY_RSA_CERT:
850 return "ssh-rsa-cert-v01@openssh.com";
851 case KEY_DSA_CERT:
852 return "ssh-dss-cert-v01@openssh.com";
829 } 853 }
830 return "ssh-unknown"; 854 return "ssh-unknown";
831} 855}
@@ -836,9 +860,11 @@ key_size(const Key *k)
836 switch (k->type) { 860 switch (k->type) {
837 case KEY_RSA1: 861 case KEY_RSA1:
838 case KEY_RSA: 862 case KEY_RSA:
863 case KEY_RSA_CERT_V00:
839 case KEY_RSA_CERT: 864 case KEY_RSA_CERT:
840 return BN_num_bits(k->rsa->n); 865 return BN_num_bits(k->rsa->n);
841 case KEY_DSA: 866 case KEY_DSA:
867 case KEY_DSA_CERT_V00:
842 case KEY_DSA_CERT: 868 case KEY_DSA_CERT:
843 return BN_num_bits(k->dsa->p); 869 return BN_num_bits(k->dsa->p);
844 } 870 }
@@ -882,6 +908,8 @@ key_generate(int type, u_int bits)
882 case KEY_RSA1: 908 case KEY_RSA1:
883 k->rsa = rsa_generate_private_key(bits); 909 k->rsa = rsa_generate_private_key(bits);
884 break; 910 break;
911 case KEY_RSA_CERT_V00:
912 case KEY_DSA_CERT_V00:
885 case KEY_RSA_CERT: 913 case KEY_RSA_CERT:
886 case KEY_DSA_CERT: 914 case KEY_DSA_CERT:
887 fatal("key_generate: cert keys cannot be generated directly"); 915 fatal("key_generate: cert keys cannot be generated directly");
@@ -912,9 +940,12 @@ key_cert_copy(const Key *from_key, struct Key *to_key)
912 buffer_append(&to->certblob, buffer_ptr(&from->certblob), 940 buffer_append(&to->certblob, buffer_ptr(&from->certblob),
913 buffer_len(&from->certblob)); 941 buffer_len(&from->certblob));
914 942
915 buffer_append(&to->constraints, buffer_ptr(&from->constraints), 943 buffer_append(&to->critical,
916 buffer_len(&from->constraints)); 944 buffer_ptr(&from->critical), buffer_len(&from->critical));
945 buffer_append(&to->extensions,
946 buffer_ptr(&from->extensions), buffer_len(&from->extensions));
917 947
948 to->serial = from->serial;
918 to->type = from->type; 949 to->type = from->type;
919 to->key_id = from->key_id == NULL ? NULL : xstrdup(from->key_id); 950 to->key_id = from->key_id == NULL ? NULL : xstrdup(from->key_id);
920 to->valid_after = from->valid_after; 951 to->valid_after = from->valid_after;
@@ -940,6 +971,7 @@ key_from_private(const Key *k)
940 Key *n = NULL; 971 Key *n = NULL;
941 switch (k->type) { 972 switch (k->type) {
942 case KEY_DSA: 973 case KEY_DSA:
974 case KEY_DSA_CERT_V00:
943 case KEY_DSA_CERT: 975 case KEY_DSA_CERT:
944 n = key_new(k->type); 976 n = key_new(k->type);
945 if ((BN_copy(n->dsa->p, k->dsa->p) == NULL) || 977 if ((BN_copy(n->dsa->p, k->dsa->p) == NULL) ||
@@ -950,6 +982,7 @@ key_from_private(const Key *k)
950 break; 982 break;
951 case KEY_RSA: 983 case KEY_RSA:
952 case KEY_RSA1: 984 case KEY_RSA1:
985 case KEY_RSA_CERT_V00:
953 case KEY_RSA_CERT: 986 case KEY_RSA_CERT:
954 n = key_new(k->type); 987 n = key_new(k->type);
955 if ((BN_copy(n->rsa->n, k->rsa->n) == NULL) || 988 if ((BN_copy(n->rsa->n, k->rsa->n) == NULL) ||
@@ -979,8 +1012,12 @@ key_type_from_name(char *name)
979 } else if (strcmp(name, "ssh-dss") == 0) { 1012 } else if (strcmp(name, "ssh-dss") == 0) {
980 return KEY_DSA; 1013 return KEY_DSA;
981 } else if (strcmp(name, "ssh-rsa-cert-v00@openssh.com") == 0) { 1014 } else if (strcmp(name, "ssh-rsa-cert-v00@openssh.com") == 0) {
982 return KEY_RSA_CERT; 1015 return KEY_RSA_CERT_V00;
983 } else if (strcmp(name, "ssh-dss-cert-v00@openssh.com") == 0) { 1016 } else if (strcmp(name, "ssh-dss-cert-v00@openssh.com") == 0) {
1017 return KEY_DSA_CERT_V00;
1018 } else if (strcmp(name, "ssh-rsa-cert-v01@openssh.com") == 0) {
1019 return KEY_RSA_CERT;
1020 } else if (strcmp(name, "ssh-dss-cert-v01@openssh.com") == 0) {
984 return KEY_DSA_CERT; 1021 return KEY_DSA_CERT;
985 } 1022 }
986 debug2("key_type_from_name: unknown key type '%s'", name); 1023 debug2("key_type_from_name: unknown key type '%s'", name);
@@ -1012,26 +1049,31 @@ key_names_valid2(const char *names)
1012static int 1049static int
1013cert_parse(Buffer *b, Key *key, const u_char *blob, u_int blen) 1050cert_parse(Buffer *b, Key *key, const u_char *blob, u_int blen)
1014{ 1051{
1015 u_char *principals, *constraints, *sig_key, *sig; 1052 u_char *principals, *critical, *exts, *sig_key, *sig;
1016 u_int signed_len, plen, clen, sklen, slen, kidlen; 1053 u_int signed_len, plen, clen, sklen, slen, kidlen, elen;
1017 Buffer tmp; 1054 Buffer tmp;
1018 char *principal; 1055 char *principal;
1019 int ret = -1; 1056 int ret = -1;
1057 int v00 = key->type == KEY_DSA_CERT_V00 ||
1058 key->type == KEY_RSA_CERT_V00;
1020 1059
1021 buffer_init(&tmp); 1060 buffer_init(&tmp);
1022 1061
1023 /* Copy the entire key blob for verification and later serialisation */ 1062 /* Copy the entire key blob for verification and later serialisation */
1024 buffer_append(&key->cert->certblob, blob, blen); 1063 buffer_append(&key->cert->certblob, blob, blen);
1025 1064
1026 principals = constraints = sig_key = sig = NULL; 1065 elen = 0; /* Not touched for v00 certs */
1027 if (buffer_get_int_ret(&key->cert->type, b) != 0 || 1066 principals = exts = critical = sig_key = sig = NULL;
1067 if ((!v00 && buffer_get_int64_ret(&key->cert->serial, b) != 0) ||
1068 buffer_get_int_ret(&key->cert->type, b) != 0 ||
1028 (key->cert->key_id = buffer_get_string_ret(b, &kidlen)) == NULL || 1069 (key->cert->key_id = buffer_get_string_ret(b, &kidlen)) == NULL ||
1029 (principals = buffer_get_string_ret(b, &plen)) == NULL || 1070 (principals = buffer_get_string_ret(b, &plen)) == NULL ||
1030 buffer_get_int64_ret(&key->cert->valid_after, b) != 0 || 1071 buffer_get_int64_ret(&key->cert->valid_after, b) != 0 ||
1031 buffer_get_int64_ret(&key->cert->valid_before, b) != 0 || 1072 buffer_get_int64_ret(&key->cert->valid_before, b) != 0 ||
1032 (constraints = buffer_get_string_ret(b, &clen)) == NULL || 1073 (critical = buffer_get_string_ret(b, &clen)) == NULL ||
1033 /* skip nonce */ buffer_get_string_ptr_ret(b, NULL) == NULL || 1074 (!v00 && (exts = buffer_get_string_ret(b, &elen)) == NULL) ||
1034 /* skip reserved */ buffer_get_string_ptr_ret(b, NULL) == NULL || 1075 (v00 && buffer_get_string_ptr_ret(b, NULL) == NULL) || /* nonce */
1076 buffer_get_string_ptr_ret(b, NULL) == NULL || /* reserved */
1035 (sig_key = buffer_get_string_ret(b, &sklen)) == NULL) { 1077 (sig_key = buffer_get_string_ret(b, &sklen)) == NULL) {
1036 error("%s: parse error", __func__); 1078 error("%s: parse error", __func__);
1037 goto out; 1079 goto out;
@@ -1078,13 +1120,25 @@ cert_parse(Buffer *b, Key *key, const u_char *blob, u_int blen)
1078 1120
1079 buffer_clear(&tmp); 1121 buffer_clear(&tmp);
1080 1122
1081 buffer_append(&key->cert->constraints, constraints, clen); 1123 buffer_append(&key->cert->critical, critical, clen);
1082 buffer_append(&tmp, constraints, clen); 1124 buffer_append(&tmp, critical, clen);
1083 /* validate structure */ 1125 /* validate structure */
1084 while (buffer_len(&tmp) != 0) { 1126 while (buffer_len(&tmp) != 0) {
1085 if (buffer_get_string_ptr_ret(&tmp, NULL) == NULL || 1127 if (buffer_get_string_ptr_ret(&tmp, NULL) == NULL ||
1086 buffer_get_string_ptr_ret(&tmp, NULL) == NULL) { 1128 buffer_get_string_ptr_ret(&tmp, NULL) == NULL) {
1087 error("%s: Constraints data invalid", __func__); 1129 error("%s: critical option data invalid", __func__);
1130 goto out;
1131 }
1132 }
1133 buffer_clear(&tmp);
1134
1135 buffer_append(&key->cert->extensions, exts, elen);
1136 buffer_append(&tmp, exts, elen);
1137 /* validate structure */
1138 while (buffer_len(&tmp) != 0) {
1139 if (buffer_get_string_ptr_ret(&tmp, NULL) == NULL ||
1140 buffer_get_string_ptr_ret(&tmp, NULL) == NULL) {
1141 error("%s: extension data invalid", __func__);
1088 goto out; 1142 goto out;
1089 } 1143 }
1090 } 1144 }
@@ -1121,8 +1175,10 @@ cert_parse(Buffer *b, Key *key, const u_char *blob, u_int blen)
1121 buffer_free(&tmp); 1175 buffer_free(&tmp);
1122 if (principals != NULL) 1176 if (principals != NULL)
1123 xfree(principals); 1177 xfree(principals);
1124 if (constraints != NULL) 1178 if (critical != NULL)
1125 xfree(constraints); 1179 xfree(critical);
1180 if (exts != NULL)
1181 xfree(exts);
1126 if (sig_key != NULL) 1182 if (sig_key != NULL)
1127 xfree(sig_key); 1183 xfree(sig_key);
1128 if (sig != NULL) 1184 if (sig != NULL)
@@ -1151,8 +1207,11 @@ key_from_blob(const u_char *blob, u_int blen)
1151 type = key_type_from_name(ktype); 1207 type = key_type_from_name(ktype);
1152 1208
1153 switch (type) { 1209 switch (type) {
1154 case KEY_RSA:
1155 case KEY_RSA_CERT: 1210 case KEY_RSA_CERT:
1211 (void)buffer_get_string_ptr_ret(&b, NULL); /* Skip nonce */
1212 /* FALLTHROUGH */
1213 case KEY_RSA:
1214 case KEY_RSA_CERT_V00:
1156 key = key_new(type); 1215 key = key_new(type);
1157 if (buffer_get_bignum2_ret(&b, key->rsa->e) == -1 || 1216 if (buffer_get_bignum2_ret(&b, key->rsa->e) == -1 ||
1158 buffer_get_bignum2_ret(&b, key->rsa->n) == -1) { 1217 buffer_get_bignum2_ret(&b, key->rsa->n) == -1) {
@@ -1166,8 +1225,11 @@ key_from_blob(const u_char *blob, u_int blen)
1166 RSA_print_fp(stderr, key->rsa, 8); 1225 RSA_print_fp(stderr, key->rsa, 8);
1167#endif 1226#endif
1168 break; 1227 break;
1169 case KEY_DSA:
1170 case KEY_DSA_CERT: 1228 case KEY_DSA_CERT:
1229 (void)buffer_get_string_ptr_ret(&b, NULL); /* Skip nonce */
1230 /* FALLTHROUGH */
1231 case KEY_DSA:
1232 case KEY_DSA_CERT_V00:
1171 key = key_new(type); 1233 key = key_new(type);
1172 if (buffer_get_bignum2_ret(&b, key->dsa->p) == -1 || 1234 if (buffer_get_bignum2_ret(&b, key->dsa->p) == -1 ||
1173 buffer_get_bignum2_ret(&b, key->dsa->q) == -1 || 1235 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)
1213 } 1275 }
1214 buffer_init(&b); 1276 buffer_init(&b);
1215 switch (key->type) { 1277 switch (key->type) {
1278 case KEY_DSA_CERT_V00:
1279 case KEY_RSA_CERT_V00:
1216 case KEY_DSA_CERT: 1280 case KEY_DSA_CERT:
1217 case KEY_RSA_CERT: 1281 case KEY_RSA_CERT:
1218 /* Use the existing blob */ 1282 /* Use the existing blob */
@@ -1255,9 +1319,11 @@ key_sign(
1255 const u_char *data, u_int datalen) 1319 const u_char *data, u_int datalen)
1256{ 1320{
1257 switch (key->type) { 1321 switch (key->type) {
1322 case KEY_DSA_CERT_V00:
1258 case KEY_DSA_CERT: 1323 case KEY_DSA_CERT:
1259 case KEY_DSA: 1324 case KEY_DSA:
1260 return ssh_dss_sign(key, sigp, lenp, data, datalen); 1325 return ssh_dss_sign(key, sigp, lenp, data, datalen);
1326 case KEY_RSA_CERT_V00:
1261 case KEY_RSA_CERT: 1327 case KEY_RSA_CERT:
1262 case KEY_RSA: 1328 case KEY_RSA:
1263 return ssh_rsa_sign(key, sigp, lenp, data, datalen); 1329 return ssh_rsa_sign(key, sigp, lenp, data, datalen);
@@ -1281,9 +1347,11 @@ key_verify(
1281 return -1; 1347 return -1;
1282 1348
1283 switch (key->type) { 1349 switch (key->type) {
1350 case KEY_DSA_CERT_V00:
1284 case KEY_DSA_CERT: 1351 case KEY_DSA_CERT:
1285 case KEY_DSA: 1352 case KEY_DSA:
1286 return ssh_dss_verify(key, signature, signaturelen, data, datalen); 1353 return ssh_dss_verify(key, signature, signaturelen, data, datalen);
1354 case KEY_RSA_CERT_V00:
1287 case KEY_RSA_CERT: 1355 case KEY_RSA_CERT:
1288 case KEY_RSA: 1356 case KEY_RSA:
1289 return ssh_rsa_verify(key, signature, signaturelen, data, datalen); 1357 return ssh_rsa_verify(key, signature, signaturelen, data, datalen);
@@ -1306,6 +1374,7 @@ key_demote(const Key *k)
1306 pk->rsa = NULL; 1374 pk->rsa = NULL;
1307 1375
1308 switch (k->type) { 1376 switch (k->type) {
1377 case KEY_RSA_CERT_V00:
1309 case KEY_RSA_CERT: 1378 case KEY_RSA_CERT:
1310 key_cert_copy(k, pk); 1379 key_cert_copy(k, pk);
1311 /* FALLTHROUGH */ 1380 /* FALLTHROUGH */
@@ -1318,6 +1387,7 @@ key_demote(const Key *k)
1318 if ((pk->rsa->n = BN_dup(k->rsa->n)) == NULL) 1387 if ((pk->rsa->n = BN_dup(k->rsa->n)) == NULL)
1319 fatal("key_demote: BN_dup failed"); 1388 fatal("key_demote: BN_dup failed");
1320 break; 1389 break;
1390 case KEY_DSA_CERT_V00:
1321 case KEY_DSA_CERT: 1391 case KEY_DSA_CERT:
1322 key_cert_copy(k, pk); 1392 key_cert_copy(k, pk);
1323 /* FALLTHROUGH */ 1393 /* FALLTHROUGH */
@@ -1344,8 +1414,17 @@ key_demote(const Key *k)
1344int 1414int
1345key_is_cert(const Key *k) 1415key_is_cert(const Key *k)
1346{ 1416{
1347 return k != NULL && 1417 if (k == NULL)
1348 (k->type == KEY_RSA_CERT || k->type == KEY_DSA_CERT); 1418 return 0;
1419 switch (k->type) {
1420 case KEY_RSA_CERT_V00:
1421 case KEY_DSA_CERT_V00:
1422 case KEY_RSA_CERT:
1423 case KEY_DSA_CERT:
1424 return 1;
1425 default:
1426 return 0;
1427 }
1349} 1428}
1350 1429
1351/* Return the cert-less equivalent to a certified key type */ 1430/* Return the cert-less equivalent to a certified key type */
@@ -1353,8 +1432,10 @@ int
1353key_type_plain(int type) 1432key_type_plain(int type)
1354{ 1433{
1355 switch (type) { 1434 switch (type) {
1435 case KEY_RSA_CERT_V00:
1356 case KEY_RSA_CERT: 1436 case KEY_RSA_CERT:
1357 return KEY_RSA; 1437 return KEY_RSA;
1438 case KEY_DSA_CERT_V00:
1358 case KEY_DSA_CERT: 1439 case KEY_DSA_CERT:
1359 return KEY_DSA; 1440 return KEY_DSA;
1360 default: 1441 default:
@@ -1364,16 +1445,16 @@ key_type_plain(int type)
1364 1445
1365/* Convert a KEY_RSA or KEY_DSA to their _CERT equivalent */ 1446/* Convert a KEY_RSA or KEY_DSA to their _CERT equivalent */
1366int 1447int
1367key_to_certified(Key *k) 1448key_to_certified(Key *k, int legacy)
1368{ 1449{
1369 switch (k->type) { 1450 switch (k->type) {
1370 case KEY_RSA: 1451 case KEY_RSA:
1371 k->cert = cert_new(); 1452 k->cert = cert_new();
1372 k->type = KEY_RSA_CERT; 1453 k->type = legacy ? KEY_RSA_CERT_V00 : KEY_RSA_CERT;
1373 return 0; 1454 return 0;
1374 case KEY_DSA: 1455 case KEY_DSA:
1375 k->cert = cert_new(); 1456 k->cert = cert_new();
1376 k->type = KEY_DSA_CERT; 1457 k->type = legacy ? KEY_DSA_CERT_V00 : KEY_DSA_CERT;
1377 return 0; 1458 return 0;
1378 default: 1459 default:
1379 error("%s: key has incorrect type %s", __func__, key_type(k)); 1460 error("%s: key has incorrect type %s", __func__, key_type(k));
@@ -1386,10 +1467,12 @@ int
1386key_drop_cert(Key *k) 1467key_drop_cert(Key *k)
1387{ 1468{
1388 switch (k->type) { 1469 switch (k->type) {
1470 case KEY_RSA_CERT_V00:
1389 case KEY_RSA_CERT: 1471 case KEY_RSA_CERT:
1390 cert_free(k->cert); 1472 cert_free(k->cert);
1391 k->type = KEY_RSA; 1473 k->type = KEY_RSA;
1392 return 0; 1474 return 0;
1475 case KEY_DSA_CERT_V00:
1393 case KEY_DSA_CERT: 1476 case KEY_DSA_CERT:
1394 cert_free(k->cert); 1477 cert_free(k->cert);
1395 k->type = KEY_DSA; 1478 k->type = KEY_DSA;
@@ -1430,13 +1513,21 @@ key_certify(Key *k, Key *ca)
1430 buffer_clear(&k->cert->certblob); 1513 buffer_clear(&k->cert->certblob);
1431 buffer_put_cstring(&k->cert->certblob, key_ssh_name(k)); 1514 buffer_put_cstring(&k->cert->certblob, key_ssh_name(k));
1432 1515
1516 /* -v01 certs put nonce first */
1517 if (k->type == KEY_DSA_CERT || k->type == KEY_RSA_CERT) {
1518 arc4random_buf(&nonce, sizeof(nonce));
1519 buffer_put_string(&k->cert->certblob, nonce, sizeof(nonce));
1520 }
1521
1433 switch (k->type) { 1522 switch (k->type) {
1523 case KEY_DSA_CERT_V00:
1434 case KEY_DSA_CERT: 1524 case KEY_DSA_CERT:
1435 buffer_put_bignum2(&k->cert->certblob, k->dsa->p); 1525 buffer_put_bignum2(&k->cert->certblob, k->dsa->p);
1436 buffer_put_bignum2(&k->cert->certblob, k->dsa->q); 1526 buffer_put_bignum2(&k->cert->certblob, k->dsa->q);
1437 buffer_put_bignum2(&k->cert->certblob, k->dsa->g); 1527 buffer_put_bignum2(&k->cert->certblob, k->dsa->g);
1438 buffer_put_bignum2(&k->cert->certblob, k->dsa->pub_key); 1528 buffer_put_bignum2(&k->cert->certblob, k->dsa->pub_key);
1439 break; 1529 break;
1530 case KEY_RSA_CERT_V00:
1440 case KEY_RSA_CERT: 1531 case KEY_RSA_CERT:
1441 buffer_put_bignum2(&k->cert->certblob, k->rsa->e); 1532 buffer_put_bignum2(&k->cert->certblob, k->rsa->e);
1442 buffer_put_bignum2(&k->cert->certblob, k->rsa->n); 1533 buffer_put_bignum2(&k->cert->certblob, k->rsa->n);
@@ -1448,6 +1539,10 @@ key_certify(Key *k, Key *ca)
1448 return -1; 1539 return -1;
1449 } 1540 }
1450 1541
1542 /* -v01 certs have a serial number next */
1543 if (k->type == KEY_DSA_CERT || k->type == KEY_RSA_CERT)
1544 buffer_put_int64(&k->cert->certblob, k->cert->serial);
1545
1451 buffer_put_int(&k->cert->certblob, k->cert->type); 1546 buffer_put_int(&k->cert->certblob, k->cert->type);
1452 buffer_put_cstring(&k->cert->certblob, k->cert->key_id); 1547 buffer_put_cstring(&k->cert->certblob, k->cert->key_id);
1453 1548
@@ -1461,11 +1556,19 @@ key_certify(Key *k, Key *ca)
1461 buffer_put_int64(&k->cert->certblob, k->cert->valid_after); 1556 buffer_put_int64(&k->cert->certblob, k->cert->valid_after);
1462 buffer_put_int64(&k->cert->certblob, k->cert->valid_before); 1557 buffer_put_int64(&k->cert->certblob, k->cert->valid_before);
1463 buffer_put_string(&k->cert->certblob, 1558 buffer_put_string(&k->cert->certblob,
1464 buffer_ptr(&k->cert->constraints), 1559 buffer_ptr(&k->cert->critical), buffer_len(&k->cert->critical));
1465 buffer_len(&k->cert->constraints)); 1560
1561 /* -v01 certs have non-critical options here */
1562 if (k->type == KEY_DSA_CERT || k->type == KEY_RSA_CERT) {
1563 buffer_put_string(&k->cert->certblob,
1564 buffer_ptr(&k->cert->extensions),
1565 buffer_len(&k->cert->extensions));
1566 }
1567
1568 /* -v00 certs put the nonce at the end */
1569 if (k->type == KEY_DSA_CERT_V00 || k->type == KEY_RSA_CERT_V00)
1570 buffer_put_string(&k->cert->certblob, nonce, sizeof(nonce));
1466 1571
1467 arc4random_buf(&nonce, sizeof(nonce));
1468 buffer_put_string(&k->cert->certblob, nonce, sizeof(nonce));
1469 buffer_put_string(&k->cert->certblob, NULL, 0); /* reserved */ 1572 buffer_put_string(&k->cert->certblob, NULL, 0); /* reserved */
1470 buffer_put_string(&k->cert->certblob, ca_blob, ca_len); 1573 buffer_put_string(&k->cert->certblob, ca_blob, ca_len);
1471 xfree(ca_blob); 1574 xfree(ca_blob);
@@ -1536,3 +1639,15 @@ key_cert_check_authority(const Key *k, int want_host, int require_principal,
1536 } 1639 }
1537 return 0; 1640 return 0;
1538} 1641}
1642
1643int
1644key_cert_is_legacy(Key *k)
1645{
1646 switch (k->type) {
1647 case KEY_DSA_CERT_V00:
1648 case KEY_RSA_CERT_V00:
1649 return 1;
1650 default:
1651 return 0;
1652 }
1653}
diff --git a/key.h b/key.h
index 4f17777c0..11d30eae6 100644
--- a/key.h
+++ b/key.h
@@ -1,4 +1,4 @@
1/* $OpenBSD: key.h,v 1.29 2010/03/15 19:40:02 stevesk Exp $ */ 1/* $OpenBSD: key.h,v 1.30 2010/04/16 01:47:26 djm Exp $ */
2 2
3/* 3/*
4 * Copyright (c) 2000, 2001 Markus Friedl. All rights reserved. 4 * Copyright (c) 2000, 2001 Markus Friedl. All rights reserved.
@@ -37,6 +37,8 @@ enum types {
37 KEY_DSA, 37 KEY_DSA,
38 KEY_RSA_CERT, 38 KEY_RSA_CERT,
39 KEY_DSA_CERT, 39 KEY_DSA_CERT,
40 KEY_RSA_CERT_V00,
41 KEY_DSA_CERT_V00,
40 KEY_UNSPEC 42 KEY_UNSPEC
41}; 43};
42enum fp_type { 44enum fp_type {
@@ -56,11 +58,13 @@ enum fp_rep {
56struct KeyCert { 58struct KeyCert {
57 Buffer certblob; /* Kept around for use on wire */ 59 Buffer certblob; /* Kept around for use on wire */
58 u_int type; /* SSH2_CERT_TYPE_USER or SSH2_CERT_TYPE_HOST */ 60 u_int type; /* SSH2_CERT_TYPE_USER or SSH2_CERT_TYPE_HOST */
61 u_int64_t serial;
59 char *key_id; 62 char *key_id;
60 u_int nprincipals; 63 u_int nprincipals;
61 char **principals; 64 char **principals;
62 u_int64_t valid_after, valid_before; 65 u_int64_t valid_after, valid_before;
63 Buffer constraints; 66 Buffer critical;
67 Buffer extensions;
64 Key *signature_key; 68 Key *signature_key;
65}; 69};
66 70
@@ -92,12 +96,13 @@ Key *key_from_private(const Key *);
92int key_type_from_name(char *); 96int key_type_from_name(char *);
93int key_is_cert(const Key *); 97int key_is_cert(const Key *);
94int key_type_plain(int); 98int key_type_plain(int);
95int key_to_certified(Key *); 99int key_to_certified(Key *, int);
96int key_drop_cert(Key *); 100int key_drop_cert(Key *);
97int key_certify(Key *, Key *); 101int key_certify(Key *, Key *);
98void key_cert_copy(const Key *, struct Key *); 102void key_cert_copy(const Key *, struct Key *);
99int key_cert_check_authority(const Key *, int, int, const char *, 103int key_cert_check_authority(const Key *, int, int, const char *,
100 const char **); 104 const char **);
105int key_cert_is_legacy(Key *);
101 106
102Key *key_from_blob(const u_char *, u_int); 107Key *key_from_blob(const u_char *, u_int);
103int key_to_blob(const Key *, u_char **, u_int *); 108int 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 @@
1/* $OpenBSD: myproposal.h,v 1.24 2010/02/26 20:29:54 djm Exp $ */ 1/* $OpenBSD: myproposal.h,v 1.25 2010/04/16 01:47:26 djm Exp $ */
2 2
3/* 3/*
4 * Copyright (c) 2000 Markus Friedl. All rights reserved. 4 * Copyright (c) 2000 Markus Friedl. All rights reserved.
@@ -40,9 +40,12 @@
40 "diffie-hellman-group1-sha1" 40 "diffie-hellman-group1-sha1"
41#endif 41#endif
42 42
43#define KEX_DEFAULT_PK_ALG "ssh-rsa-cert-v00@openssh.com," \ 43#define KEX_DEFAULT_PK_ALG \
44 "ssh-dss-cert-v00@openssh.com," \ 44 "ssh-rsa-cert-v01@openssh.com," \
45 "ssh-rsa,ssh-dss" 45 "ssh-dss-cert-v01@openssh.com," \
46 "ssh-rsa-cert-v00@openssh.com," \
47 "ssh-dss-cert-v00@openssh.com," \
48 "ssh-rsa,ssh-dss"
46 49
47#define KEX_DEFAULT_ENCRYPT \ 50#define KEX_DEFAULT_ENCRYPT \
48 "aes128-ctr,aes192-ctr,aes256-ctr," \ 51 "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 @@
1/* $OpenBSD: ssh-add.c,v 1.94 2010/03/01 11:07:06 otto Exp $ */ 1/* $OpenBSD: ssh-add.c,v 1.95 2010/04/16 01:47:26 djm Exp $ */
2/* 2/*
3 * Author: Tatu Ylonen <ylo@cs.hut.fi> 3 * Author: Tatu Ylonen <ylo@cs.hut.fi>
4 * Copyright (c) 1995 Tatu Ylonen <ylo@cs.hut.fi>, Espoo, Finland 4 * Copyright (c) 1995 Tatu Ylonen <ylo@cs.hut.fi>, Espoo, Finland
@@ -204,7 +204,7 @@ add_file(AuthenticationConnection *ac, const char *filename)
204 xasprintf(&certpath, "%s-cert.pub", filename); 204 xasprintf(&certpath, "%s-cert.pub", filename);
205 if ((cert = key_load_public(certpath, NULL)) != NULL) { 205 if ((cert = key_load_public(certpath, NULL)) != NULL) {
206 /* Graft with private bits */ 206 /* Graft with private bits */
207 if (key_to_certified(private) != 0) 207 if (key_to_certified(private, key_cert_is_legacy(cert)) != 0)
208 fatal("%s: key_to_certified failed", __func__); 208 fatal("%s: key_to_certified failed", __func__);
209 key_cert_copy(cert, private); 209 key_cert_copy(cert, private);
210 key_free(cert); 210 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 @@
1/* $OpenBSD: ssh-agent.c,v 1.165 2010/02/26 20:29:54 djm Exp $ */ 1/* $OpenBSD: ssh-agent.c,v 1.166 2010/04/16 01:47:26 djm Exp $ */
2/* 2/*
3 * Author: Tatu Ylonen <ylo@cs.hut.fi> 3 * Author: Tatu Ylonen <ylo@cs.hut.fi>
4 * Copyright (c) 1995 Tatu Ylonen <ylo@cs.hut.fi>, Espoo, Finland 4 * Copyright (c) 1995 Tatu Ylonen <ylo@cs.hut.fi>, Espoo, Finland
@@ -500,6 +500,7 @@ process_add_identity(SocketEntry *e, int version)
500 buffer_get_bignum2(&e->request, k->dsa->pub_key); 500 buffer_get_bignum2(&e->request, k->dsa->pub_key);
501 buffer_get_bignum2(&e->request, k->dsa->priv_key); 501 buffer_get_bignum2(&e->request, k->dsa->priv_key);
502 break; 502 break;
503 case KEY_DSA_CERT_V00:
503 case KEY_DSA_CERT: 504 case KEY_DSA_CERT:
504 cert = buffer_get_string(&e->request, &len); 505 cert = buffer_get_string(&e->request, &len);
505 if ((k = key_from_blob(cert, len)) == NULL) 506 if ((k = key_from_blob(cert, len)) == NULL)
@@ -520,6 +521,7 @@ process_add_identity(SocketEntry *e, int version)
520 /* Generate additional parameters */ 521 /* Generate additional parameters */
521 rsa_generate_additional_parameters(k->rsa); 522 rsa_generate_additional_parameters(k->rsa);
522 break; 523 break;
524 case KEY_RSA_CERT_V00:
523 case KEY_RSA_CERT: 525 case KEY_RSA_CERT:
524 cert = buffer_get_string(&e->request, &len); 526 cert = buffer_get_string(&e->request, &len);
525 if ((k = key_from_blob(cert, len)) == NULL) 527 if ((k = key_from_blob(cert, len)) == NULL)
@@ -540,6 +542,7 @@ process_add_identity(SocketEntry *e, int version)
540 /* enable blinding */ 542 /* enable blinding */
541 switch (k->type) { 543 switch (k->type) {
542 case KEY_RSA: 544 case KEY_RSA:
545 case KEY_RSA_CERT_V00:
543 case KEY_RSA_CERT: 546 case KEY_RSA_CERT:
544 case KEY_RSA1: 547 case KEY_RSA1:
545 if (RSA_blinding_on(k->rsa, NULL) != 1) { 548 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 @@
1/* $OpenBSD: ssh-dss.c,v 1.25 2010/02/26 20:29:54 djm Exp $ */ 1/* $OpenBSD: ssh-dss.c,v 1.26 2010/04/16 01:47:26 djm Exp $ */
2/* 2/*
3 * Copyright (c) 2000 Markus Friedl. All rights reserved. 3 * Copyright (c) 2000 Markus Friedl. All rights reserved.
4 * 4 *
@@ -53,9 +53,8 @@ ssh_dss_sign(const Key *key, u_char **sigp, u_int *lenp,
53 u_int rlen, slen, len, dlen; 53 u_int rlen, slen, len, dlen;
54 Buffer b; 54 Buffer b;
55 55
56 if (key == NULL || 56 if (key == NULL || key->dsa == NULL || (key->type != KEY_DSA &&
57 (key->type != KEY_DSA && key->type != KEY_DSA_CERT) || 57 key->type != KEY_DSA_CERT && key->type != KEY_DSA_CERT_V00)) {
58 key->dsa == NULL) {
59 error("ssh_dss_sign: no DSA key"); 58 error("ssh_dss_sign: no DSA key");
60 return -1; 59 return -1;
61 } 60 }
@@ -118,9 +117,8 @@ ssh_dss_verify(const Key *key, const u_char *signature, u_int signaturelen,
118 int rlen, ret; 117 int rlen, ret;
119 Buffer b; 118 Buffer b;
120 119
121 if (key == NULL || 120 if (key == NULL || key->dsa == NULL || (key->type != KEY_DSA &&
122 (key->type != KEY_DSA && key->type != KEY_DSA_CERT) || 121 key->type != KEY_DSA_CERT && key->type != KEY_DSA_CERT_V00)) {
123 key->dsa == NULL) {
124 error("ssh_dss_verify: no DSA key"); 122 error("ssh_dss_verify: no DSA key");
125 return -1; 123 return -1;
126 } 124 }
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 @@
1.\" $OpenBSD: ssh-keygen.1,v 1.92 2010/03/13 23:38:13 jmc Exp $ 1.\" $OpenBSD: ssh-keygen.1,v 1.93 2010/04/16 01:47:26 djm Exp $
2.\" 2.\"
3.\" -*- nroff -*- 3.\" -*- nroff -*-
4.\" 4.\"
@@ -37,7 +37,7 @@
37.\" (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF 37.\" (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
38.\" THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 38.\" THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
39.\" 39.\"
40.Dd $Mdocdate: March 13 2010 $ 40.Dd $Mdocdate: April 16 2010 $
41.Dt SSH-KEYGEN 1 41.Dt SSH-KEYGEN 1
42.Os 42.Os
43.Sh NAME 43.Sh NAME
@@ -110,8 +110,9 @@
110.Fl I Ar certificate_identity 110.Fl I Ar certificate_identity
111.Op Fl h 111.Op Fl h
112.Op Fl n Ar principals 112.Op Fl n Ar principals
113.Op Fl O Ar constraint 113.Op Fl O Ar option
114.Op Fl V Ar validity_interval 114.Op Fl V Ar validity_interval
115.Op Fl z Ar serial_number
115.Ar 116.Ar
116.Nm ssh-keygen 117.Nm ssh-keygen
117.Fl L 118.Fl L
@@ -299,13 +300,13 @@ Multiple principals may be specified, separated by commas.
299Please see the 300Please see the
300.Sx CERTIFICATES 301.Sx CERTIFICATES
301section for details. 302section for details.
302.It Fl O Ar constraint 303.It Fl O Ar option
303Specify a certificate constraint when signing a key. 304Specify a certificate option when signing a key.
304This option may be specified multiple times. 305This option may be specified multiple times.
305Please see the 306Please see the
306.Sx CERTIFICATES 307.Sx CERTIFICATES
307section for details. 308section for details.
308The constraints that are valid for user certificates are: 309The options that are valid for user certificates are:
309.Bl -tag -width Ds 310.Bl -tag -width Ds
310.It Ic clear 311.It Ic clear
311Clear all enabled permissions. 312Clear all enabled permissions.
@@ -355,7 +356,7 @@ is a comma-separated list of one or more address/netmask pairs in CIDR
355format. 356format.
356.El 357.El
357.Pp 358.Pp
358At present, no constraints are valid for host keys. 359At present, no options are valid for host keys.
359.It Fl P Ar passphrase 360.It Fl P Ar passphrase
360Provides the (old) passphrase. 361Provides the (old) passphrase.
361.It Fl p 362.It Fl p
@@ -441,6 +442,10 @@ Specify desired generator when testing candidate moduli for DH-GEX.
441.It Fl y 442.It Fl y
442This option will read a private 443This option will read a private
443OpenSSH format file and print an OpenSSH public key to stdout. 444OpenSSH format file and print an OpenSSH public key to stdout.
445.It Fl z Ar serial_number
446Specifies a serial number to be embedded in the certificate to distinguish
447this certificate from others from the same CA.
448The default serial number is zero.
444.El 449.El
445.Sh MODULI GENERATION 450.Sh MODULI GENERATION
446.Nm 451.Nm
@@ -501,7 +506,7 @@ that both ends of a connection share common moduli.
501supports signing of keys to produce certificates that may be used for 506supports signing of keys to produce certificates that may be used for
502user or host authentication. 507user or host authentication.
503Certificates consist of a public key, some identity information, zero or 508Certificates consist of a public key, some identity information, zero or
504more principal (user or host) names and an optional set of constraints that 509more principal (user or host) names and an optional set of options that
505are signed by a Certification Authority (CA) key. 510are signed by a Certification Authority (CA) key.
506Clients or servers may then trust only the CA key and verify its signature 511Clients or servers may then trust only the CA key and verify its signature
507on a certificate rather than trusting many user/host keys. 512on a certificate rather than trusting many user/host keys.
@@ -541,11 +546,11 @@ To generate a certificate for a specified set of principals:
541.Dl "$ ssh-keygen -s ca_key -I key_id -h -n host.domain user_key.pub" 546.Dl "$ ssh-keygen -s ca_key -I key_id -h -n host.domain user_key.pub"
542.Pp 547.Pp
543Additional limitations on the validity and use of user certificates may 548Additional limitations on the validity and use of user certificates may
544be specified through certificate constraints. 549be specified through certificate options..
545A constrained certificate may disable features of the SSH session, may be 550A certificate option may disable features of the SSH session, may be
546valid only when presented from particular source addresses or may 551valid only when presented from particular source addresses or may
547force the use of a specific command. 552force the use of a specific command.
548For a list of valid certificate constraints, see the documentation for the 553For a list of valid certificate options, see the documentation for the
549.Fl O 554.Fl O
550option above. 555option above.
551.Pp 556.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 @@
1/* $OpenBSD: ssh-keygen.c,v 1.185 2010/03/15 19:40:02 stevesk Exp $ */ 1/* $OpenBSD: ssh-keygen.c,v 1.186 2010/04/16 01:47:26 djm Exp $ */
2/* 2/*
3 * Author: Tatu Ylonen <ylo@cs.hut.fi> 3 * Author: Tatu Ylonen <ylo@cs.hut.fi>
4 * Copyright (c) 1994 Tatu Ylonen <ylo@cs.hut.fi>, Espoo, Finland 4 * Copyright (c) 1994 Tatu Ylonen <ylo@cs.hut.fi>, Espoo, Finland
@@ -105,6 +105,9 @@ char *identity_comment = NULL;
105/* Path to CA key when certifying keys. */ 105/* Path to CA key when certifying keys. */
106char *ca_key_path = NULL; 106char *ca_key_path = NULL;
107 107
108/* Certificate serial number */
109long long cert_serial = 0;
110
108/* Key type when certifying */ 111/* Key type when certifying */
109u_int cert_key_type = SSH2_CERT_TYPE_USER; 112u_int cert_key_type = SSH2_CERT_TYPE_USER;
110 113
@@ -118,18 +121,18 @@ char *cert_principals = NULL;
118u_int64_t cert_valid_from = 0; 121u_int64_t cert_valid_from = 0;
119u_int64_t cert_valid_to = ~0ULL; 122u_int64_t cert_valid_to = ~0ULL;
120 123
121/* Certificate constraints */ 124/* Certificate options */
122#define CONSTRAINT_X_FWD (1) 125#define CRITOPT_X_FWD (1)
123#define CONSTRAINT_AGENT_FWD (1<<1) 126#define CRITOPT_AGENT_FWD (1<<1)
124#define CONSTRAINT_PORT_FWD (1<<2) 127#define CRITOPT_PORT_FWD (1<<2)
125#define CONSTRAINT_PTY (1<<3) 128#define CRITOPT_PTY (1<<3)
126#define CONSTRAINT_USER_RC (1<<4) 129#define CRITOPT_USER_RC (1<<4)
127#define CONSTRAINT_DEFAULT (CONSTRAINT_X_FWD|CONSTRAINT_AGENT_FWD| \ 130#define CRITOPT_DEFAULT (CRITOPT_X_FWD|CRITOPT_AGENT_FWD| \
128 CONSTRAINT_PORT_FWD|CONSTRAINT_PTY| \ 131 CRITOPT_PORT_FWD|CRITOPT_PTY| \
129 CONSTRAINT_USER_RC) 132 CRITOPT_USER_RC)
130u_int32_t constraint_flags = CONSTRAINT_DEFAULT; 133u_int32_t critical_flags = CRITOPT_DEFAULT;
131char *constraint_command = NULL; 134char *critical_command = NULL;
132char *constraint_src_addr = NULL; 135char *critical_src_addr = NULL;
133 136
134/* Dump public key file in format used by real and the original SSH 2 */ 137/* Dump public key file in format used by real and the original SSH 2 */
135int convert_to_ssh2 = 0; 138int convert_to_ssh2 = 0;
@@ -161,9 +164,13 @@ ask_filename(struct passwd *pw, const char *prompt)
161 case KEY_RSA1: 164 case KEY_RSA1:
162 name = _PATH_SSH_CLIENT_IDENTITY; 165 name = _PATH_SSH_CLIENT_IDENTITY;
163 break; 166 break;
167 case KEY_DSA_CERT:
168 case KEY_DSA_CERT_V00:
164 case KEY_DSA: 169 case KEY_DSA:
165 name = _PATH_SSH_CLIENT_ID_DSA; 170 name = _PATH_SSH_CLIENT_ID_DSA;
166 break; 171 break;
172 case KEY_RSA_CERT:
173 case KEY_RSA_CERT_V00:
167 case KEY_RSA: 174 case KEY_RSA:
168 name = _PATH_SSH_CLIENT_ID_RSA; 175 name = _PATH_SSH_CLIENT_ID_RSA;
169 break; 176 break;
@@ -1104,7 +1111,7 @@ fmt_validity(u_int64_t valid_from, u_int64_t valid_to)
1104} 1111}
1105 1112
1106static void 1113static void
1107add_flag_constraint(Buffer *c, const char *name) 1114add_flag_option(Buffer *c, const char *name)
1108{ 1115{
1109 debug3("%s: %s", __func__, name); 1116 debug3("%s: %s", __func__, name);
1110 buffer_put_cstring(c, name); 1117 buffer_put_cstring(c, name);
@@ -1112,7 +1119,7 @@ add_flag_constraint(Buffer *c, const char *name)
1112} 1119}
1113 1120
1114static void 1121static void
1115add_string_constraint(Buffer *c, const char *name, const char *value) 1122add_string_option(Buffer *c, const char *name, const char *value)
1116{ 1123{
1117 Buffer b; 1124 Buffer b;
1118 1125
@@ -1127,24 +1134,23 @@ add_string_constraint(Buffer *c, const char *name, const char *value)
1127} 1134}
1128 1135
1129static void 1136static void
1130prepare_constraint_buf(Buffer *c) 1137prepare_options_buf(Buffer *c)
1131{ 1138{
1132
1133 buffer_clear(c); 1139 buffer_clear(c);
1134 if ((constraint_flags & CONSTRAINT_X_FWD) != 0) 1140 if ((critical_flags & CRITOPT_X_FWD) != 0)
1135 add_flag_constraint(c, "permit-X11-forwarding"); 1141 add_flag_option(c, "permit-X11-forwarding");
1136 if ((constraint_flags & CONSTRAINT_AGENT_FWD) != 0) 1142 if ((critical_flags & CRITOPT_AGENT_FWD) != 0)
1137 add_flag_constraint(c, "permit-agent-forwarding"); 1143 add_flag_option(c, "permit-agent-forwarding");
1138 if ((constraint_flags & CONSTRAINT_PORT_FWD) != 0) 1144 if ((critical_flags & CRITOPT_PORT_FWD) != 0)
1139 add_flag_constraint(c, "permit-port-forwarding"); 1145 add_flag_option(c, "permit-port-forwarding");
1140 if ((constraint_flags & CONSTRAINT_PTY) != 0) 1146 if ((critical_flags & CRITOPT_PTY) != 0)
1141 add_flag_constraint(c, "permit-pty"); 1147 add_flag_option(c, "permit-pty");
1142 if ((constraint_flags & CONSTRAINT_USER_RC) != 0) 1148 if ((critical_flags & CRITOPT_USER_RC) != 0)
1143 add_flag_constraint(c, "permit-user-rc"); 1149 add_flag_option(c, "permit-user-rc");
1144 if (constraint_command != NULL) 1150 if (critical_command != NULL)
1145 add_string_constraint(c, "force-command", constraint_command); 1151 add_string_option(c, "force-command", critical_command);
1146 if (constraint_src_addr != NULL) 1152 if (critical_src_addr != NULL)
1147 add_string_constraint(c, "source-address", constraint_src_addr); 1153 add_string_option(c, "source-address", critical_src_addr);
1148} 1154}
1149 1155
1150static void 1156static void
@@ -1155,12 +1161,32 @@ do_ca_sign(struct passwd *pw, int argc, char **argv)
1155 Key *ca, *public; 1161 Key *ca, *public;
1156 char *otmp, *tmp, *cp, *out, *comment, **plist = NULL; 1162 char *otmp, *tmp, *cp, *out, *comment, **plist = NULL;
1157 FILE *f; 1163 FILE *f;
1164 int v00 = 0; /* legacy keys */
1158 1165
1159 tmp = tilde_expand_filename(ca_key_path, pw->pw_uid); 1166 tmp = tilde_expand_filename(ca_key_path, pw->pw_uid);
1160 if ((ca = load_identity(tmp)) == NULL) 1167 if ((ca = load_identity(tmp)) == NULL)
1161 fatal("Couldn't load CA key \"%s\"", tmp); 1168 fatal("Couldn't load CA key \"%s\"", tmp);
1162 xfree(tmp); 1169 xfree(tmp);
1163 1170
1171 if (key_type_name != NULL) {
1172 switch (key_type_from_name(key_type_name)) {
1173 case KEY_RSA_CERT_V00:
1174 case KEY_DSA_CERT_V00:
1175 v00 = 1;
1176 break;
1177 case KEY_UNSPEC:
1178 if (strcasecmp(key_type_name, "v00") == 0) {
1179 v00 = 1;
1180 break;
1181 } else if (strcasecmp(key_type_name, "v01") == 0)
1182 break;
1183 /* FALLTHROUGH */
1184 default:
1185 fprintf(stderr, "unknown key type %s\n", key_type_name);
1186 exit(1);
1187 }
1188 }
1189
1164 for (i = 0; i < argc; i++) { 1190 for (i = 0; i < argc; i++) {
1165 /* Split list of principals */ 1191 /* Split list of principals */
1166 n = 0; 1192 n = 0;
@@ -1183,15 +1209,16 @@ do_ca_sign(struct passwd *pw, int argc, char **argv)
1183 __func__, tmp, key_type(public)); 1209 __func__, tmp, key_type(public));
1184 1210
1185 /* Prepare certificate to sign */ 1211 /* Prepare certificate to sign */
1186 if (key_to_certified(public) != 0) 1212 if (key_to_certified(public, v00) != 0)
1187 fatal("Could not upgrade key %s to certificate", tmp); 1213 fatal("Could not upgrade key %s to certificate", tmp);
1188 public->cert->type = cert_key_type; 1214 public->cert->type = cert_key_type;
1215 public->cert->serial = (u_int64_t)cert_serial;
1189 public->cert->key_id = xstrdup(cert_key_id); 1216 public->cert->key_id = xstrdup(cert_key_id);
1190 public->cert->nprincipals = n; 1217 public->cert->nprincipals = n;
1191 public->cert->principals = plist; 1218 public->cert->principals = plist;
1192 public->cert->valid_after = cert_valid_from; 1219 public->cert->valid_after = cert_valid_from;
1193 public->cert->valid_before = cert_valid_to; 1220 public->cert->valid_before = cert_valid_to;
1194 prepare_constraint_buf(&public->cert->constraints); 1221 prepare_options_buf(&public->cert->critical);
1195 public->cert->signature_key = key_from_private(ca); 1222 public->cert->signature_key = key_from_private(ca);
1196 1223
1197 if (key_certify(public, ca) != 0) 1224 if (key_certify(public, ca) != 0)
@@ -1212,13 +1239,14 @@ do_ca_sign(struct passwd *pw, int argc, char **argv)
1212 fprintf(f, " %s\n", comment); 1239 fprintf(f, " %s\n", comment);
1213 fclose(f); 1240 fclose(f);
1214 1241
1215 if (!quiet) 1242 if (!quiet) {
1216 logit("Signed %s key %s: id \"%s\"%s%s valid %s", 1243 logit("Signed %s key %s: id \"%s\" serial %llu%s%s "
1217 cert_key_type == SSH2_CERT_TYPE_USER?"user":"host", 1244 "valid %s", key_cert_type(public),
1218 out, cert_key_id, 1245 out, public->cert->key_id, public->cert->serial,
1219 cert_principals != NULL ? " for " : "", 1246 cert_principals != NULL ? " for " : "",
1220 cert_principals != NULL ? cert_principals : "", 1247 cert_principals != NULL ? cert_principals : "",
1221 fmt_validity(cert_valid_from, cert_valid_to)); 1248 fmt_validity(cert_valid_from, cert_valid_to));
1249 }
1222 1250
1223 key_free(public); 1251 key_free(public);
1224 xfree(out); 1252 xfree(out);
@@ -1321,50 +1349,50 @@ parse_cert_times(char *timespec)
1321} 1349}
1322 1350
1323static void 1351static void
1324add_cert_constraint(char *opt) 1352add_cert_option(char *opt)
1325{ 1353{
1326 char *val; 1354 char *val;
1327 1355
1328 if (strcmp(opt, "clear") == 0) 1356 if (strcmp(opt, "clear") == 0)
1329 constraint_flags = 0; 1357 critical_flags = 0;
1330 else if (strcasecmp(opt, "no-x11-forwarding") == 0) 1358 else if (strcasecmp(opt, "no-x11-forwarding") == 0)
1331 constraint_flags &= ~CONSTRAINT_X_FWD; 1359 critical_flags &= ~CRITOPT_X_FWD;
1332 else if (strcasecmp(opt, "permit-x11-forwarding") == 0) 1360 else if (strcasecmp(opt, "permit-x11-forwarding") == 0)
1333 constraint_flags |= CONSTRAINT_X_FWD; 1361 critical_flags |= CRITOPT_X_FWD;
1334 else if (strcasecmp(opt, "no-agent-forwarding") == 0) 1362 else if (strcasecmp(opt, "no-agent-forwarding") == 0)
1335 constraint_flags &= ~CONSTRAINT_AGENT_FWD; 1363 critical_flags &= ~CRITOPT_AGENT_FWD;
1336 else if (strcasecmp(opt, "permit-agent-forwarding") == 0) 1364 else if (strcasecmp(opt, "permit-agent-forwarding") == 0)
1337 constraint_flags |= CONSTRAINT_AGENT_FWD; 1365 critical_flags |= CRITOPT_AGENT_FWD;
1338 else if (strcasecmp(opt, "no-port-forwarding") == 0) 1366 else if (strcasecmp(opt, "no-port-forwarding") == 0)
1339 constraint_flags &= ~CONSTRAINT_PORT_FWD; 1367 critical_flags &= ~CRITOPT_PORT_FWD;
1340 else if (strcasecmp(opt, "permit-port-forwarding") == 0) 1368 else if (strcasecmp(opt, "permit-port-forwarding") == 0)
1341 constraint_flags |= CONSTRAINT_PORT_FWD; 1369 critical_flags |= CRITOPT_PORT_FWD;
1342 else if (strcasecmp(opt, "no-pty") == 0) 1370 else if (strcasecmp(opt, "no-pty") == 0)
1343 constraint_flags &= ~CONSTRAINT_PTY; 1371 critical_flags &= ~CRITOPT_PTY;
1344 else if (strcasecmp(opt, "permit-pty") == 0) 1372 else if (strcasecmp(opt, "permit-pty") == 0)
1345 constraint_flags |= CONSTRAINT_PTY; 1373 critical_flags |= CRITOPT_PTY;
1346 else if (strcasecmp(opt, "no-user-rc") == 0) 1374 else if (strcasecmp(opt, "no-user-rc") == 0)
1347 constraint_flags &= ~CONSTRAINT_USER_RC; 1375 critical_flags &= ~CRITOPT_USER_RC;
1348 else if (strcasecmp(opt, "permit-user-rc") == 0) 1376 else if (strcasecmp(opt, "permit-user-rc") == 0)
1349 constraint_flags |= CONSTRAINT_USER_RC; 1377 critical_flags |= CRITOPT_USER_RC;
1350 else if (strncasecmp(opt, "force-command=", 14) == 0) { 1378 else if (strncasecmp(opt, "force-command=", 14) == 0) {
1351 val = opt + 14; 1379 val = opt + 14;
1352 if (*val == '\0') 1380 if (*val == '\0')
1353 fatal("Empty force-command constraint"); 1381 fatal("Empty force-command option");
1354 if (constraint_command != NULL) 1382 if (critical_command != NULL)
1355 fatal("force-command already specified"); 1383 fatal("force-command already specified");
1356 constraint_command = xstrdup(val); 1384 critical_command = xstrdup(val);
1357 } else if (strncasecmp(opt, "source-address=", 15) == 0) { 1385 } else if (strncasecmp(opt, "source-address=", 15) == 0) {
1358 val = opt + 15; 1386 val = opt + 15;
1359 if (*val == '\0') 1387 if (*val == '\0')
1360 fatal("Empty source-address constraint"); 1388 fatal("Empty source-address option");
1361 if (constraint_src_addr != NULL) 1389 if (critical_src_addr != NULL)
1362 fatal("source-address already specified"); 1390 fatal("source-address already specified");
1363 if (addr_match_cidr_list(NULL, val) != 0) 1391 if (addr_match_cidr_list(NULL, val) != 0)
1364 fatal("Invalid source-address list"); 1392 fatal("Invalid source-address list");
1365 constraint_src_addr = xstrdup(val); 1393 critical_src_addr = xstrdup(val);
1366 } else 1394 } else
1367 fatal("Unsupported certificate constraint \"%s\"", opt); 1395 fatal("Unsupported certificate option \"%s\"", opt);
1368} 1396}
1369 1397
1370static void 1398static void
@@ -1373,9 +1401,9 @@ do_show_cert(struct passwd *pw)
1373 Key *key; 1401 Key *key;
1374 struct stat st; 1402 struct stat st;
1375 char *key_fp, *ca_fp; 1403 char *key_fp, *ca_fp;
1376 Buffer constraints, constraint; 1404 Buffer options, option;
1377 u_char *name, *data; 1405 u_char *name, *data;
1378 u_int i, dlen; 1406 u_int i, dlen, v00;
1379 1407
1380 if (!have_identity) 1408 if (!have_identity)
1381 ask_filename(pw, "Enter file in which the key is"); 1409 ask_filename(pw, "Enter file in which the key is");
@@ -1387,17 +1415,21 @@ do_show_cert(struct passwd *pw)
1387 fatal("%s is not a public key", identity_file); 1415 fatal("%s is not a public key", identity_file);
1388 if (!key_is_cert(key)) 1416 if (!key_is_cert(key))
1389 fatal("%s is not a certificate", identity_file); 1417 fatal("%s is not a certificate", identity_file);
1390 1418 v00 = key->type == KEY_RSA_CERT_V00 || key->type == KEY_DSA_CERT_V00;
1419
1391 key_fp = key_fingerprint(key, SSH_FP_MD5, SSH_FP_HEX); 1420 key_fp = key_fingerprint(key, SSH_FP_MD5, SSH_FP_HEX);
1392 ca_fp = key_fingerprint(key->cert->signature_key, 1421 ca_fp = key_fingerprint(key->cert->signature_key,
1393 SSH_FP_MD5, SSH_FP_HEX); 1422 SSH_FP_MD5, SSH_FP_HEX);
1394 1423
1395 printf("%s:\n", identity_file); 1424 printf("%s:\n", identity_file);
1396 printf(" %s %s certificate %s\n", key_type(key), 1425 printf(" Type: %s %s certificate\n", key_ssh_name(key),
1397 key_cert_type(key), key_fp); 1426 key_cert_type(key));
1398 printf(" Signed by %s CA %s\n", 1427 printf(" Public key: %s %s\n", key_type(key), key_fp);
1428 printf(" Signing CA: %s %s\n",
1399 key_type(key->cert->signature_key), ca_fp); 1429 key_type(key->cert->signature_key), ca_fp);
1400 printf(" Key ID \"%s\"\n", key->cert->key_id); 1430 printf(" Key ID: \"%s\"\n", key->cert->key_id);
1431 if (!v00)
1432 printf(" Serial: %llu\n", key->cert->serial);
1401 printf(" Valid: %s\n", 1433 printf(" Valid: %s\n",
1402 fmt_validity(key->cert->valid_after, key->cert->valid_before)); 1434 fmt_validity(key->cert->valid_after, key->cert->valid_before));
1403 printf(" Principals: "); 1435 printf(" Principals: ");
@@ -1409,20 +1441,20 @@ do_show_cert(struct passwd *pw)
1409 key->cert->principals[i]); 1441 key->cert->principals[i]);
1410 printf("\n"); 1442 printf("\n");
1411 } 1443 }
1412 printf(" Constraints: "); 1444 printf(" Critical Options: ");
1413 if (buffer_len(&key->cert->constraints) == 0) 1445 if (buffer_len(&key->cert->critical) == 0)
1414 printf("(none)\n"); 1446 printf("(none)\n");
1415 else { 1447 else {
1416 printf("\n"); 1448 printf("\n");
1417 buffer_init(&constraints); 1449 buffer_init(&options);
1418 buffer_append(&constraints, 1450 buffer_append(&options,
1419 buffer_ptr(&key->cert->constraints), 1451 buffer_ptr(&key->cert->critical),
1420 buffer_len(&key->cert->constraints)); 1452 buffer_len(&key->cert->critical));
1421 buffer_init(&constraint); 1453 buffer_init(&option);
1422 while (buffer_len(&constraints) != 0) { 1454 while (buffer_len(&options) != 0) {
1423 name = buffer_get_string(&constraints, NULL); 1455 name = buffer_get_string(&options, NULL);
1424 data = buffer_get_string_ptr(&constraints, &dlen); 1456 data = buffer_get_string_ptr(&options, &dlen);
1425 buffer_append(&constraint, data, dlen); 1457 buffer_append(&option, data, dlen);
1426 printf(" %s", name); 1458 printf(" %s", name);
1427 if (strcmp(name, "permit-X11-forwarding") == 0 || 1459 if (strcmp(name, "permit-X11-forwarding") == 0 ||
1428 strcmp(name, "permit-agent-forwarding") == 0 || 1460 strcmp(name, "permit-agent-forwarding") == 0 ||
@@ -1432,22 +1464,43 @@ do_show_cert(struct passwd *pw)
1432 printf("\n"); 1464 printf("\n");
1433 else if (strcmp(name, "force-command") == 0 || 1465 else if (strcmp(name, "force-command") == 0 ||
1434 strcmp(name, "source-address") == 0) { 1466 strcmp(name, "source-address") == 0) {
1435 data = buffer_get_string(&constraint, NULL); 1467 data = buffer_get_string(&option, NULL);
1436 printf(" %s\n", data); 1468 printf(" %s\n", data);
1437 xfree(data); 1469 xfree(data);
1438 } else { 1470 } else {
1439 printf(" UNKNOWN CONSTRAINT (len %u)\n", 1471 printf(" UNKNOWN OPTION (len %u)\n",
1440 buffer_len(&constraint)); 1472 buffer_len(&option));
1441 buffer_clear(&constraint); 1473 buffer_clear(&option);
1442 } 1474 }
1443 xfree(name); 1475 xfree(name);
1444 if (buffer_len(&constraint) != 0) 1476 if (buffer_len(&option) != 0)
1445 fatal("Constraint corrupt: extra data at end"); 1477 fatal("Option corrupt: extra data at end");
1478 }
1479 buffer_free(&option);
1480 buffer_free(&options);
1481 }
1482 if (!v00) {
1483 printf(" Extensions: ");
1484 if (buffer_len(&key->cert->extensions) == 0)
1485 printf("(none)\n");
1486 else {
1487 printf("\n");
1488 buffer_init(&options);
1489 buffer_append(&options,
1490 buffer_ptr(&key->cert->extensions),
1491 buffer_len(&key->cert->extensions));
1492 buffer_init(&option);
1493 while (buffer_len(&options) != 0) {
1494 name = buffer_get_string(&options, NULL);
1495 (void)buffer_get_string_ptr(&options, &dlen);
1496 printf(" %s UNKNOWN OPTION "
1497 "(len %u)\n", name, dlen);
1498 xfree(name);
1499 }
1500 buffer_free(&option);
1501 buffer_free(&options);
1446 } 1502 }
1447 buffer_free(&constraint);
1448 buffer_free(&constraints);
1449 } 1503 }
1450
1451 exit(0); 1504 exit(0);
1452} 1505}
1453 1506
@@ -1478,7 +1531,7 @@ usage(void)
1478 fprintf(stderr, " -M memory Amount of memory (MB) to use for generating DH-GEX moduli.\n"); 1531 fprintf(stderr, " -M memory Amount of memory (MB) to use for generating DH-GEX moduli.\n");
1479 fprintf(stderr, " -n name,... User/host principal names to include in certificate\n"); 1532 fprintf(stderr, " -n name,... User/host principal names to include in certificate\n");
1480 fprintf(stderr, " -N phrase Provide new passphrase.\n"); 1533 fprintf(stderr, " -N phrase Provide new passphrase.\n");
1481 fprintf(stderr, " -O cnstr Specify a certificate constraint.\n"); 1534 fprintf(stderr, " -O cnstr Specify a certificate option.\n");
1482 fprintf(stderr, " -P phrase Provide old passphrase.\n"); 1535 fprintf(stderr, " -P phrase Provide old passphrase.\n");
1483 fprintf(stderr, " -p Change passphrase of private key file.\n"); 1536 fprintf(stderr, " -p Change passphrase of private key file.\n");
1484 fprintf(stderr, " -q Quiet.\n"); 1537 fprintf(stderr, " -q Quiet.\n");
@@ -1541,7 +1594,7 @@ main(int argc, char **argv)
1541 } 1594 }
1542 1595
1543 while ((opt = getopt(argc, argv, "degiqpclBHLhvxXyF:b:f:t:D:I:P:N:n:" 1596 while ((opt = getopt(argc, argv, "degiqpclBHLhvxXyF:b:f:t:D:I:P:N:n:"
1544 "O:C:r:g:R:T:G:M:S:s:a:V:W:")) != -1) { 1597 "O:C:r:g:R:T:G:M:S:s:a:V:W:z:")) != -1) {
1545 switch (opt) { 1598 switch (opt) {
1546 case 'b': 1599 case 'b':
1547 bits = (u_int32_t)strtonum(optarg, 768, 32768, &errstr); 1600 bits = (u_int32_t)strtonum(optarg, 768, 32768, &errstr);
@@ -1597,7 +1650,7 @@ main(int argc, char **argv)
1597 identity_new_passphrase = optarg; 1650 identity_new_passphrase = optarg;
1598 break; 1651 break;
1599 case 'O': 1652 case 'O':
1600 add_cert_constraint(optarg); 1653 add_cert_option(optarg);
1601 break; 1654 break;
1602 case 'C': 1655 case 'C':
1603 identity_comment = optarg; 1656 identity_comment = optarg;
@@ -1612,7 +1665,7 @@ main(int argc, char **argv)
1612 break; 1665 break;
1613 case 'h': 1666 case 'h':
1614 cert_key_type = SSH2_CERT_TYPE_HOST; 1667 cert_key_type = SSH2_CERT_TYPE_HOST;
1615 constraint_flags = 0; 1668 critical_flags = 0;
1616 break; 1669 break;
1617 case 'i': 1670 case 'i':
1618 case 'X': 1671 case 'X':
@@ -1661,9 +1714,8 @@ main(int argc, char **argv)
1661 break; 1714 break;
1662 case 'M': 1715 case 'M':
1663 memory = (u_int32_t)strtonum(optarg, 1, UINT_MAX, &errstr); 1716 memory = (u_int32_t)strtonum(optarg, 1, UINT_MAX, &errstr);
1664 if (errstr) { 1717 if (errstr)
1665 fatal("Memory limit is %s: %s", errstr, optarg); 1718 fatal("Memory limit is %s: %s", errstr, optarg);
1666 }
1667 break; 1719 break;
1668 case 'G': 1720 case 'G':
1669 do_gen_candidates = 1; 1721 do_gen_candidates = 1;
@@ -1685,6 +1737,11 @@ main(int argc, char **argv)
1685 case 'V': 1737 case 'V':
1686 parse_cert_times(optarg); 1738 parse_cert_times(optarg);
1687 break; 1739 break;
1740 case 'z':
1741 cert_serial = strtonum(optarg, 0, LLONG_MAX, &errstr);
1742 if (errstr)
1743 fatal("Invalid serial number: %s", errstr);
1744 break;
1688 case '?': 1745 case '?':
1689 default: 1746 default:
1690 usage(); 1747 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 @@
1/* $OpenBSD: ssh-rsa.c,v 1.40 2010/02/26 20:29:54 djm Exp $ */ 1/* $OpenBSD: ssh-rsa.c,v 1.41 2010/04/16 01:47:26 djm Exp $ */
2/* 2/*
3 * Copyright (c) 2000, 2003 Markus Friedl <markus@openbsd.org> 3 * Copyright (c) 2000, 2003 Markus Friedl <markus@openbsd.org>
4 * 4 *
@@ -46,9 +46,8 @@ ssh_rsa_sign(const Key *key, u_char **sigp, u_int *lenp,
46 int ok, nid; 46 int ok, nid;
47 Buffer b; 47 Buffer b;
48 48
49 if (key == NULL || 49 if (key == NULL || key->rsa == NULL || (key->type != KEY_RSA &&
50 (key->type != KEY_RSA && key->type != KEY_RSA_CERT) || 50 key->type != KEY_RSA_CERT && key->type != KEY_RSA_CERT_V00)) {
51 key->rsa == NULL) {
52 error("ssh_rsa_sign: no RSA key"); 51 error("ssh_rsa_sign: no RSA key");
53 return -1; 52 return -1;
54 } 53 }
@@ -115,9 +114,8 @@ ssh_rsa_verify(const Key *key, const u_char *signature, u_int signaturelen,
115 u_int len, dlen, modlen; 114 u_int len, dlen, modlen;
116 int rlen, ret, nid; 115 int rlen, ret, nid;
117 116
118 if (key == NULL || 117 if (key == NULL || key->rsa == NULL || (key->type != KEY_RSA &&
119 (key->type != KEY_RSA && key->type != KEY_RSA_CERT) || 118 key->type != KEY_RSA_CERT && key->type != KEY_RSA_CERT_V00)) {
120 key->rsa == NULL) {
121 error("ssh_rsa_verify: no RSA key"); 119 error("ssh_rsa_verify: no RSA key");
122 return -1; 120 return -1;
123 } 121 }
diff --git a/sshconnect.c b/sshconnect.c
index ca83bc792..3c8b8c7c2 100644
--- a/sshconnect.c
+++ b/sshconnect.c
@@ -1,4 +1,4 @@
1/* $OpenBSD: sshconnect.c,v 1.222 2010/04/14 22:27:42 djm Exp $ */ 1/* $OpenBSD: sshconnect.c,v 1.223 2010/04/16 01:47:26 djm Exp $ */
2/* 2/*
3 * Author: Tatu Ylonen <ylo@cs.hut.fi> 3 * Author: Tatu Ylonen <ylo@cs.hut.fi>
4 * Copyright (c) 1995 Tatu Ylonen <ylo@cs.hut.fi>, Espoo, Finland 4 * Copyright (c) 1995 Tatu Ylonen <ylo@cs.hut.fi>, Espoo, Finland
@@ -586,9 +586,9 @@ check_host_cert(const char *host, const Key *host_key)
586 error("%s", reason); 586 error("%s", reason);
587 return 0; 587 return 0;
588 } 588 }
589 if (buffer_len(&host_key->cert->constraints) != 0) { 589 if (buffer_len(&host_key->cert->critical) != 0) {
590 error("Certificate for %s contains unsupported constraint(s)", 590 error("Certificate for %s contains unsupported "
591 host); 591 "critical options(s)", host);
592 return 0; 592 return 0;
593 } 593 }
594 return 1; 594 return 1;
diff --git a/sshconnect2.c b/sshconnect2.c
index 25a3323f0..e146a4b26 100644
--- a/sshconnect2.c
+++ b/sshconnect2.c
@@ -1,4 +1,4 @@
1/* $OpenBSD: sshconnect2.c,v 1.181 2010/04/10 02:10:56 djm Exp $ */ 1/* $OpenBSD: sshconnect2.c,v 1.182 2010/04/16 01:47:26 djm Exp $ */
2/* 2/*
3 * Copyright (c) 2000 Markus Friedl. All rights reserved. 3 * Copyright (c) 2000 Markus Friedl. All rights reserved.
4 * Copyright (c) 2008 Damien Miller. All rights reserved. 4 * Copyright (c) 2008 Damien Miller. All rights reserved.
@@ -1140,8 +1140,11 @@ sign_and_send_pubkey(Authctxt *authctxt, Identity *id)
1140 u_int skip = 0; 1140 u_int skip = 0;
1141 int ret = -1; 1141 int ret = -1;
1142 int have_sig = 1; 1142 int have_sig = 1;
1143 char *fp;
1143 1144
1144 debug3("sign_and_send_pubkey"); 1145 fp = key_fingerprint(id->key, SSH_FP_MD5, SSH_FP_HEX);
1146 debug3("sign_and_send_pubkey: %s %s", key_type(id->key), fp);
1147 xfree(fp);
1145 1148
1146 if (key_to_blob(id->key, &blob, &bloblen) == 0) { 1149 if (key_to_blob(id->key, &blob, &bloblen) == 0) {
1147 /* we cannot handle this key */ 1150 /* 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 @@
1/* $OpenBSD: sshd.c,v 1.374 2010/03/07 11:57:13 dtucker Exp $ */ 1/* $OpenBSD: sshd.c,v 1.375 2010/04/16 01:47:26 djm Exp $ */
2/* 2/*
3 * Author: Tatu Ylonen <ylo@cs.hut.fi> 3 * Author: Tatu Ylonen <ylo@cs.hut.fi>
4 * Copyright (c) 1995 Tatu Ylonen <ylo@cs.hut.fi>, Espoo, Finland 4 * Copyright (c) 1995 Tatu Ylonen <ylo@cs.hut.fi>, Espoo, Finland
@@ -744,6 +744,8 @@ list_hostkey_types(void)
744 if (key == NULL) 744 if (key == NULL)
745 continue; 745 continue;
746 switch (key->type) { 746 switch (key->type) {
747 case KEY_RSA_CERT_V00:
748 case KEY_DSA_CERT_V00:
747 case KEY_RSA_CERT: 749 case KEY_RSA_CERT:
748 case KEY_DSA_CERT: 750 case KEY_DSA_CERT:
749 if (buffer_len(&b) > 0) 751 if (buffer_len(&b) > 0)
@@ -767,10 +769,17 @@ get_hostkey_by_type(int type, int need_private)
767 Key *key; 769 Key *key;
768 770
769 for (i = 0; i < options.num_host_key_files; i++) { 771 for (i = 0; i < options.num_host_key_files; i++) {
770 if (type == KEY_RSA_CERT || type == KEY_DSA_CERT) 772 switch (type) {
773 case KEY_RSA_CERT_V00:
774 case KEY_DSA_CERT_V00:
775 case KEY_RSA_CERT:
776 case KEY_DSA_CERT:
771 key = sensitive_data.host_certificates[i]; 777 key = sensitive_data.host_certificates[i];
772 else 778 break;
779 default:
773 key = sensitive_data.host_keys[i]; 780 key = sensitive_data.host_keys[i];
781 break;
782 }
774 if (key != NULL && key->type == type) 783 if (key != NULL && key->type == type)
775 return need_private ? 784 return need_private ?
776 sensitive_data.host_keys[i] : key; 785 sensitive_data.host_keys[i] : key;