diff options
-rw-r--r-- | ChangeLog | 21 | ||||
-rw-r--r-- | PROTOCOL.certkeys | 73 | ||||
-rw-r--r-- | auth-options.c | 21 | ||||
-rw-r--r-- | auth-options.h | 4 | ||||
-rw-r--r-- | auth-rsa.c | 4 | ||||
-rw-r--r-- | auth2-pubkey.c | 9 | ||||
-rw-r--r-- | authfd.c | 6 | ||||
-rw-r--r-- | key.c | 177 | ||||
-rw-r--r-- | key.h | 11 | ||||
-rw-r--r-- | myproposal.h | 11 | ||||
-rw-r--r-- | ssh-add.c | 4 | ||||
-rw-r--r-- | ssh-agent.c | 5 | ||||
-rw-r--r-- | ssh-dss.c | 12 | ||||
-rw-r--r-- | ssh-keygen.1 | 27 | ||||
-rw-r--r-- | ssh-keygen.c | 235 | ||||
-rw-r--r-- | ssh-rsa.c | 12 | ||||
-rw-r--r-- | sshconnect.c | 8 | ||||
-rw-r--r-- | sshconnect2.c | 7 | ||||
-rw-r--r-- | sshd.c | 15 |
19 files changed, 449 insertions, 213 deletions
@@ -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 | ||
45 | 20100410 | 66 | 20100410 |
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 | |||
16 | system already in SSH to allow certificate-based authentication. | 16 | system already in SSH to allow certificate-based authentication. |
17 | The certificates used are not traditional X.509 certificates, with | 17 | The certificates used are not traditional X.509 certificates, with |
18 | numerous options and complex encoding rules, but something rather | 18 | numerous options and complex encoding rules, but something rather |
19 | more minimal: a key, some identity information and usage constraints | 19 | more minimal: a key, some identity information and usage options |
20 | that have been signed with some other trusted key. | 20 | that have been signed with some other trusted key. |
21 | 21 | ||
22 | A sshd server may be configured to allow authentication via certified | 22 | 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 | |||
27 | to specify CA keys in ~/.ssh/known_hosts. | 27 | to specify CA keys in ~/.ssh/known_hosts. |
28 | 28 | ||
29 | Certified keys are represented using two new key types: | 29 | Certified keys are represented using two new key types: |
30 | ssh-rsa-cert-v00@openssh.com and ssh-dss-cert-v00@openssh.com that | 30 | ssh-rsa-cert-v01@openssh.com and ssh-dss-cert-v01@openssh.com that |
31 | include certification information along with the public key that is used | 31 | include certification information along with the public key that is used |
32 | to sign challenges. ssh-keygen performs the CA signing operation. | 32 | to sign challenges. ssh-keygen performs the CA signing operation. |
33 | 33 | ||
@@ -47,7 +47,7 @@ in RFC4252 section 7. | |||
47 | New public key formats | 47 | New public key formats |
48 | ---------------------- | 48 | ---------------------- |
49 | 49 | ||
50 | The ssh-rsa-cert-v00@openssh.com and ssh-dss-cert-v00@openssh.com key | 50 | The ssh-rsa-cert-v01@openssh.com and ssh-dss-cert-v01@openssh.com key |
51 | types take a similar high-level format (note: data types and | 51 | types take a similar high-level format (note: data types and |
52 | encoding are as per RFC4251 section 5). The serialised wire encoding of | 52 | encoding are as per RFC4251 section 5). The serialised wire encoding of |
53 | these certificates is also used for storing them on disk. | 53 | these 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 | ||
58 | RSA certificate | 58 | RSA 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 | ||
74 | DSA certificate | 76 | DSA 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 | ||
96 | The 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 | ||
98 | inducing collisions in the signature hash infeasible. | ||
99 | |||
92 | e and n are the RSA exponent and public modulus respectively. | 100 | e and n are the RSA exponent and public modulus respectively. |
93 | 101 | ||
94 | p, q, g, y are the DSA parameters as described in FIPS-186-2. | 102 | p, q, g, y are the DSA parameters as described in FIPS-186-2. |
95 | 103 | ||
104 | serial is an optional certificate serial number set by the CA to | ||
105 | provide an abbreviated way to refer to certificates from that CA. | ||
106 | If a CA does not with to number its certificates it must set this | ||
107 | field to zero. | ||
108 | |||
96 | type specifies whether this certificate is for identification of a user | 109 | type specifies whether this certificate is for identification of a user |
97 | or a host using a SSH_CERT_TYPE_... value. | 110 | or 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 | |||
112 | 00:00:00. A certificate is considered valid if: | 125 | 00:00:00. A certificate is considered valid if: |
113 | valid after <= current time < valid before | 126 | valid after <= current time < valid before |
114 | 127 | ||
115 | constraints is a set of zero or more key constraints encoded as below. | 128 | criticial options is a set of zero or more key options encoded as |
129 | below. All such options are "critical" in the sense that an implementation | ||
130 | must refuse to authorise a key that has an unrecognised option. | ||
116 | 131 | ||
117 | The nonce field is a CA-provided random bitstring of arbitrary length | 132 | extensions 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 | 133 | are not critical, and an implementation that encounters one that it does |
119 | inducing collisions in the signature hash infeasible. | 134 | not recognise may safely ignore it. No extensions are defined at present. |
120 | 135 | ||
121 | The reserved field is current unused and is ignored in this version of | 136 | The reserved field is currently unused and is ignored in this version of |
122 | the protocol. | 137 | the protocol. |
123 | 138 | ||
124 | signature key contains the CA key used to sign the certificate. | 139 | 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 | |||
132 | encoded according to the rules defined for the CA's public key algorithm | 147 | encoded 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 | ||
135 | Constraints | 150 | Critical options |
136 | ----------- | 151 | ---------------- |
137 | 152 | ||
138 | The constraints section of the certificate specifies zero or more | 153 | The critical options section of the certificate specifies zero or more |
139 | constraints on the certificates validity. The format of this field | 154 | options on the certificates validity. The format of this field |
140 | is a sequence of zero or more tuples: | 155 | is a sequence of zero or more tuples: |
141 | 156 | ||
142 | string name | 157 | string name |
143 | string data | 158 | string data |
144 | 159 | ||
145 | The name field identifies the constraint and the data field encodes | 160 | The name field identifies the option and the data field encodes |
146 | constraint-specific information (see below). All constraints are | 161 | option-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 |
148 | then the validating party should refuse to accept the certificate. | 163 | then the validating party should refuse to accept the certificate. |
149 | 164 | ||
150 | The supported constraints and the contents and structure of their | 165 | The supported options and the contents and structure of their |
151 | data fields are: | 166 | data fields are: |
152 | 167 | ||
153 | Name Format Description | 168 | Name Format Description |
@@ -159,35 +174,35 @@ force-command string Specifies a command that is executed | |||
159 | 174 | ||
160 | permit-X11-forwarding empty Flag indicating that X11 forwarding | 175 | permit-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 | ||
164 | permit-agent-forwarding empty Flag indicating that agent forwarding | 179 | permit-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 | ||
169 | permit-port-forwarding empty Flag indicating that port-forwarding | 184 | permit-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 | ||
174 | permit-pty empty Flag indicating that PTY allocation | 189 | permit-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 | ||
179 | permit-user-rc empty Flag indicating that execution of | 194 | permit-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 | ||
184 | source-address string Comma-separated list of source addresses | 199 | source-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 | */ |
383 | int | 383 | int |
384 | auth_cert_constraints(Buffer *c_orig, struct passwd *pw) | 384 | auth_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 | ||
35 | int auth_parse_options(struct passwd *, char *, char *, u_long); | 35 | int auth_parse_options(struct passwd *, char *, char *, u_long); |
36 | void auth_clear_options(void); | 36 | void auth_clear_options(void); |
37 | int auth_cert_constraints(Buffer *, struct passwd *); | 37 | int 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", |
@@ -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; |
@@ -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) | |||
1012 | static int | 1049 | static int |
1013 | cert_parse(Buffer *b, Key *key, const u_char *blob, u_int blen) | 1050 | cert_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) | |||
1344 | int | 1414 | int |
1345 | key_is_cert(const Key *k) | 1415 | key_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 | |||
1353 | key_type_plain(int type) | 1432 | key_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 */ |
1366 | int | 1447 | int |
1367 | key_to_certified(Key *k) | 1448 | key_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 | |||
1386 | key_drop_cert(Key *k) | 1467 | key_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 | |||
1643 | int | ||
1644 | key_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 | } | ||
@@ -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 | }; |
42 | enum fp_type { | 44 | enum fp_type { |
@@ -56,11 +58,13 @@ enum fp_rep { | |||
56 | struct KeyCert { | 58 | struct 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 *); | |||
92 | int key_type_from_name(char *); | 96 | int key_type_from_name(char *); |
93 | int key_is_cert(const Key *); | 97 | int key_is_cert(const Key *); |
94 | int key_type_plain(int); | 98 | int key_type_plain(int); |
95 | int key_to_certified(Key *); | 99 | int key_to_certified(Key *, int); |
96 | int key_drop_cert(Key *); | 100 | int key_drop_cert(Key *); |
97 | int key_certify(Key *, Key *); | 101 | int key_certify(Key *, Key *); |
98 | void key_cert_copy(const Key *, struct Key *); | 102 | void key_cert_copy(const Key *, struct Key *); |
99 | int key_cert_check_authority(const Key *, int, int, const char *, | 103 | int key_cert_check_authority(const Key *, int, int, const char *, |
100 | const char **); | 104 | const char **); |
105 | int key_cert_is_legacy(Key *); | ||
101 | 106 | ||
102 | Key *key_from_blob(const u_char *, u_int); | 107 | Key *key_from_blob(const u_char *, u_int); |
103 | int key_to_blob(const Key *, u_char **, u_int *); | 108 | 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 @@ | |||
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," \ |
@@ -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) { |
@@ -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. | |||
299 | Please see the | 300 | Please see the |
300 | .Sx CERTIFICATES | 301 | .Sx CERTIFICATES |
301 | section for details. | 302 | section for details. |
302 | .It Fl O Ar constraint | 303 | .It Fl O Ar option |
303 | Specify a certificate constraint when signing a key. | 304 | Specify a certificate option when signing a key. |
304 | This option may be specified multiple times. | 305 | This option may be specified multiple times. |
305 | Please see the | 306 | Please see the |
306 | .Sx CERTIFICATES | 307 | .Sx CERTIFICATES |
307 | section for details. | 308 | section for details. |
308 | The constraints that are valid for user certificates are: | 309 | The 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 |
311 | Clear all enabled permissions. | 312 | Clear all enabled permissions. |
@@ -355,7 +356,7 @@ is a comma-separated list of one or more address/netmask pairs in CIDR | |||
355 | format. | 356 | format. |
356 | .El | 357 | .El |
357 | .Pp | 358 | .Pp |
358 | At present, no constraints are valid for host keys. | 359 | At present, no options are valid for host keys. |
359 | .It Fl P Ar passphrase | 360 | .It Fl P Ar passphrase |
360 | Provides the (old) passphrase. | 361 | Provides 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 |
442 | This option will read a private | 443 | This option will read a private |
443 | OpenSSH format file and print an OpenSSH public key to stdout. | 444 | OpenSSH format file and print an OpenSSH public key to stdout. |
445 | .It Fl z Ar serial_number | ||
446 | Specifies a serial number to be embedded in the certificate to distinguish | ||
447 | this certificate from others from the same CA. | ||
448 | The 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. | |||
501 | supports signing of keys to produce certificates that may be used for | 506 | supports signing of keys to produce certificates that may be used for |
502 | user or host authentication. | 507 | user or host authentication. |
503 | Certificates consist of a public key, some identity information, zero or | 508 | Certificates consist of a public key, some identity information, zero or |
504 | more principal (user or host) names and an optional set of constraints that | 509 | more principal (user or host) names and an optional set of options that |
505 | are signed by a Certification Authority (CA) key. | 510 | are signed by a Certification Authority (CA) key. |
506 | Clients or servers may then trust only the CA key and verify its signature | 511 | Clients or servers may then trust only the CA key and verify its signature |
507 | on a certificate rather than trusting many user/host keys. | 512 | on 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 |
543 | Additional limitations on the validity and use of user certificates may | 548 | Additional limitations on the validity and use of user certificates may |
544 | be specified through certificate constraints. | 549 | be specified through certificate options.. |
545 | A constrained certificate may disable features of the SSH session, may be | 550 | A certificate option may disable features of the SSH session, may be |
546 | valid only when presented from particular source addresses or may | 551 | valid only when presented from particular source addresses or may |
547 | force the use of a specific command. | 552 | force the use of a specific command. |
548 | For a list of valid certificate constraints, see the documentation for the | 553 | For a list of valid certificate options, see the documentation for the |
549 | .Fl O | 554 | .Fl O |
550 | option above. | 555 | option 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. */ |
106 | char *ca_key_path = NULL; | 106 | char *ca_key_path = NULL; |
107 | 107 | ||
108 | /* Certificate serial number */ | ||
109 | long long cert_serial = 0; | ||
110 | |||
108 | /* Key type when certifying */ | 111 | /* Key type when certifying */ |
109 | u_int cert_key_type = SSH2_CERT_TYPE_USER; | 112 | u_int cert_key_type = SSH2_CERT_TYPE_USER; |
110 | 113 | ||
@@ -118,18 +121,18 @@ char *cert_principals = NULL; | |||
118 | u_int64_t cert_valid_from = 0; | 121 | u_int64_t cert_valid_from = 0; |
119 | u_int64_t cert_valid_to = ~0ULL; | 122 | u_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) |
130 | u_int32_t constraint_flags = CONSTRAINT_DEFAULT; | 133 | u_int32_t critical_flags = CRITOPT_DEFAULT; |
131 | char *constraint_command = NULL; | 134 | char *critical_command = NULL; |
132 | char *constraint_src_addr = NULL; | 135 | char *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 */ |
135 | int convert_to_ssh2 = 0; | 138 | int 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 | ||
1106 | static void | 1113 | static void |
1107 | add_flag_constraint(Buffer *c, const char *name) | 1114 | add_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 | ||
1114 | static void | 1121 | static void |
1115 | add_string_constraint(Buffer *c, const char *name, const char *value) | 1122 | add_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 | ||
1129 | static void | 1136 | static void |
1130 | prepare_constraint_buf(Buffer *c) | 1137 | prepare_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 | ||
1150 | static void | 1156 | static 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 | ||
1323 | static void | 1351 | static void |
1324 | add_cert_constraint(char *opt) | 1352 | add_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 | ||
1370 | static void | 1398 | static 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(); |
@@ -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 */ |
@@ -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; |