diff options
Diffstat (limited to 'authfd.c')
-rw-r--r-- | authfd.c | 174 |
1 files changed, 18 insertions, 156 deletions
@@ -1,4 +1,4 @@ | |||
1 | /* $OpenBSD: authfd.c,v 1.100 2015/12/04 16:41:28 markus Exp $ */ | 1 | /* $OpenBSD: authfd.c,v 1.105 2017/07/01 13:50:45 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 |
@@ -51,7 +51,6 @@ | |||
51 | 51 | ||
52 | #include "xmalloc.h" | 52 | #include "xmalloc.h" |
53 | #include "ssh.h" | 53 | #include "ssh.h" |
54 | #include "rsa.h" | ||
55 | #include "sshbuf.h" | 54 | #include "sshbuf.h" |
56 | #include "sshkey.h" | 55 | #include "sshkey.h" |
57 | #include "authfd.h" | 56 | #include "authfd.h" |
@@ -199,43 +198,6 @@ ssh_lock_agent(int sock, int lock, const char *password) | |||
199 | return r; | 198 | return r; |
200 | } | 199 | } |
201 | 200 | ||
202 | #ifdef WITH_SSH1 | ||
203 | static int | ||
204 | deserialise_identity1(struct sshbuf *ids, struct sshkey **keyp, char **commentp) | ||
205 | { | ||
206 | struct sshkey *key; | ||
207 | int r, keybits; | ||
208 | u_int32_t bits; | ||
209 | char *comment = NULL; | ||
210 | |||
211 | if ((key = sshkey_new(KEY_RSA1)) == NULL) | ||
212 | return SSH_ERR_ALLOC_FAIL; | ||
213 | if ((r = sshbuf_get_u32(ids, &bits)) != 0 || | ||
214 | (r = sshbuf_get_bignum1(ids, key->rsa->e)) != 0 || | ||
215 | (r = sshbuf_get_bignum1(ids, key->rsa->n)) != 0 || | ||
216 | (r = sshbuf_get_cstring(ids, &comment, NULL)) != 0) | ||
217 | goto out; | ||
218 | keybits = BN_num_bits(key->rsa->n); | ||
219 | /* XXX previously we just warned here. I think we should be strict */ | ||
220 | if (keybits < 0 || bits != (u_int)keybits) { | ||
221 | r = SSH_ERR_KEY_BITS_MISMATCH; | ||
222 | goto out; | ||
223 | } | ||
224 | if (keyp != NULL) { | ||
225 | *keyp = key; | ||
226 | key = NULL; | ||
227 | } | ||
228 | if (commentp != NULL) { | ||
229 | *commentp = comment; | ||
230 | comment = NULL; | ||
231 | } | ||
232 | r = 0; | ||
233 | out: | ||
234 | sshkey_free(key); | ||
235 | free(comment); | ||
236 | return r; | ||
237 | } | ||
238 | #endif | ||
239 | 201 | ||
240 | static int | 202 | static int |
241 | deserialise_identity2(struct sshbuf *ids, struct sshkey **keyp, char **commentp) | 203 | deserialise_identity2(struct sshbuf *ids, struct sshkey **keyp, char **commentp) |
@@ -264,35 +226,21 @@ deserialise_identity2(struct sshbuf *ids, struct sshkey **keyp, char **commentp) | |||
264 | * Fetch list of identities held by the agent. | 226 | * Fetch list of identities held by the agent. |
265 | */ | 227 | */ |
266 | int | 228 | int |
267 | ssh_fetch_identitylist(int sock, int version, struct ssh_identitylist **idlp) | 229 | ssh_fetch_identitylist(int sock, struct ssh_identitylist **idlp) |
268 | { | 230 | { |
269 | u_char type, code1 = 0, code2 = 0; | 231 | u_char type; |
270 | u_int32_t num, i; | 232 | u_int32_t num, i; |
271 | struct sshbuf *msg; | 233 | struct sshbuf *msg; |
272 | struct ssh_identitylist *idl = NULL; | 234 | struct ssh_identitylist *idl = NULL; |
273 | int r; | 235 | int r; |
274 | 236 | ||
275 | /* Determine request and expected response types */ | ||
276 | switch (version) { | ||
277 | case 1: | ||
278 | code1 = SSH_AGENTC_REQUEST_RSA_IDENTITIES; | ||
279 | code2 = SSH_AGENT_RSA_IDENTITIES_ANSWER; | ||
280 | break; | ||
281 | case 2: | ||
282 | code1 = SSH2_AGENTC_REQUEST_IDENTITIES; | ||
283 | code2 = SSH2_AGENT_IDENTITIES_ANSWER; | ||
284 | break; | ||
285 | default: | ||
286 | return SSH_ERR_INVALID_ARGUMENT; | ||
287 | } | ||
288 | |||
289 | /* | 237 | /* |
290 | * Send a message to the agent requesting for a list of the | 238 | * Send a message to the agent requesting for a list of the |
291 | * identities it can represent. | 239 | * identities it can represent. |
292 | */ | 240 | */ |
293 | if ((msg = sshbuf_new()) == NULL) | 241 | if ((msg = sshbuf_new()) == NULL) |
294 | return SSH_ERR_ALLOC_FAIL; | 242 | return SSH_ERR_ALLOC_FAIL; |
295 | if ((r = sshbuf_put_u8(msg, code1)) != 0) | 243 | if ((r = sshbuf_put_u8(msg, SSH2_AGENTC_REQUEST_IDENTITIES)) != 0) |
296 | goto out; | 244 | goto out; |
297 | 245 | ||
298 | if ((r = ssh_request_reply(sock, msg, msg)) != 0) | 246 | if ((r = ssh_request_reply(sock, msg, msg)) != 0) |
@@ -304,7 +252,7 @@ ssh_fetch_identitylist(int sock, int version, struct ssh_identitylist **idlp) | |||
304 | if (agent_failed(type)) { | 252 | if (agent_failed(type)) { |
305 | r = SSH_ERR_AGENT_FAILURE; | 253 | r = SSH_ERR_AGENT_FAILURE; |
306 | goto out; | 254 | goto out; |
307 | } else if (type != code2) { | 255 | } else if (type != SSH2_AGENT_IDENTITIES_ANSWER) { |
308 | r = SSH_ERR_INVALID_FORMAT; | 256 | r = SSH_ERR_INVALID_FORMAT; |
309 | goto out; | 257 | goto out; |
310 | } | 258 | } |
@@ -329,25 +277,14 @@ ssh_fetch_identitylist(int sock, int version, struct ssh_identitylist **idlp) | |||
329 | goto out; | 277 | goto out; |
330 | } | 278 | } |
331 | for (i = 0; i < num;) { | 279 | for (i = 0; i < num;) { |
332 | switch (version) { | 280 | if ((r = deserialise_identity2(msg, &(idl->keys[i]), |
333 | case 1: | 281 | &(idl->comments[i]))) != 0) { |
334 | #ifdef WITH_SSH1 | 282 | if (r == SSH_ERR_KEY_TYPE_UNKNOWN) { |
335 | if ((r = deserialise_identity1(msg, | 283 | /* Gracefully skip unknown key types */ |
336 | &(idl->keys[i]), &(idl->comments[i]))) != 0) | 284 | num--; |
285 | continue; | ||
286 | } else | ||
337 | goto out; | 287 | goto out; |
338 | #endif | ||
339 | break; | ||
340 | case 2: | ||
341 | if ((r = deserialise_identity2(msg, | ||
342 | &(idl->keys[i]), &(idl->comments[i]))) != 0) { | ||
343 | if (r == SSH_ERR_KEY_TYPE_UNKNOWN) { | ||
344 | /* Gracefully skip unknown key types */ | ||
345 | num--; | ||
346 | continue; | ||
347 | } else | ||
348 | goto out; | ||
349 | } | ||
350 | break; | ||
351 | } | 288 | } |
352 | i++; | 289 | i++; |
353 | } | 290 | } |
@@ -385,50 +322,10 @@ ssh_free_identitylist(struct ssh_identitylist *idl) | |||
385 | * otherwise. | 322 | * otherwise. |
386 | */ | 323 | */ |
387 | 324 | ||
388 | #ifdef WITH_SSH1 | ||
389 | int | ||
390 | ssh_decrypt_challenge(int sock, struct sshkey* key, BIGNUM *challenge, | ||
391 | u_char session_id[16], u_char response[16]) | ||
392 | { | ||
393 | struct sshbuf *msg; | ||
394 | int r; | ||
395 | u_char type; | ||
396 | |||
397 | if (key->type != KEY_RSA1) | ||
398 | return SSH_ERR_INVALID_ARGUMENT; | ||
399 | if ((msg = sshbuf_new()) == NULL) | ||
400 | return SSH_ERR_ALLOC_FAIL; | ||
401 | if ((r = sshbuf_put_u8(msg, SSH_AGENTC_RSA_CHALLENGE)) != 0 || | ||
402 | (r = sshbuf_put_u32(msg, BN_num_bits(key->rsa->n))) != 0 || | ||
403 | (r = sshbuf_put_bignum1(msg, key->rsa->e)) != 0 || | ||
404 | (r = sshbuf_put_bignum1(msg, key->rsa->n)) != 0 || | ||
405 | (r = sshbuf_put_bignum1(msg, challenge)) != 0 || | ||
406 | (r = sshbuf_put(msg, session_id, 16)) != 0 || | ||
407 | (r = sshbuf_put_u32(msg, 1)) != 0) /* Response type for proto 1.1 */ | ||
408 | goto out; | ||
409 | if ((r = ssh_request_reply(sock, msg, msg)) != 0) | ||
410 | goto out; | ||
411 | if ((r = sshbuf_get_u8(msg, &type)) != 0) | ||
412 | goto out; | ||
413 | if (agent_failed(type)) { | ||
414 | r = SSH_ERR_AGENT_FAILURE; | ||
415 | goto out; | ||
416 | } else if (type != SSH_AGENT_RSA_RESPONSE) { | ||
417 | r = SSH_ERR_INVALID_FORMAT; | ||
418 | goto out; | ||
419 | } | ||
420 | if ((r = sshbuf_get(msg, response, 16)) != 0) | ||
421 | goto out; | ||
422 | r = 0; | ||
423 | out: | ||
424 | sshbuf_free(msg); | ||
425 | return r; | ||
426 | } | ||
427 | #endif | ||
428 | 325 | ||
429 | /* encode signature algoritm in flag bits, so we can keep the msg format */ | 326 | /* encode signature algoritm in flag bits, so we can keep the msg format */ |
430 | static u_int | 327 | static u_int |
431 | agent_encode_alg(struct sshkey *key, const char *alg) | 328 | agent_encode_alg(const struct sshkey *key, const char *alg) |
432 | { | 329 | { |
433 | if (alg != NULL && key->type == KEY_RSA) { | 330 | if (alg != NULL && key->type == KEY_RSA) { |
434 | if (strcmp(alg, "rsa-sha2-256") == 0) | 331 | if (strcmp(alg, "rsa-sha2-256") == 0) |
@@ -441,7 +338,7 @@ agent_encode_alg(struct sshkey *key, const char *alg) | |||
441 | 338 | ||
442 | /* ask agent to sign data, returns err.h code on error, 0 on success */ | 339 | /* ask agent to sign data, returns err.h code on error, 0 on success */ |
443 | int | 340 | int |
444 | ssh_agent_sign(int sock, struct sshkey *key, | 341 | ssh_agent_sign(int sock, const struct sshkey *key, |
445 | u_char **sigp, size_t *lenp, | 342 | u_char **sigp, size_t *lenp, |
446 | const u_char *data, size_t datalen, const char *alg, u_int compat) | 343 | const u_char *data, size_t datalen, const char *alg, u_int compat) |
447 | { | 344 | { |
@@ -494,25 +391,6 @@ ssh_agent_sign(int sock, struct sshkey *key, | |||
494 | 391 | ||
495 | /* Encode key for a message to the agent. */ | 392 | /* Encode key for a message to the agent. */ |
496 | 393 | ||
497 | #ifdef WITH_SSH1 | ||
498 | static int | ||
499 | ssh_encode_identity_rsa1(struct sshbuf *b, RSA *key, const char *comment) | ||
500 | { | ||
501 | int r; | ||
502 | |||
503 | /* To keep within the protocol: p < q for ssh. in SSL p > q */ | ||
504 | if ((r = sshbuf_put_u32(b, BN_num_bits(key->n))) != 0 || | ||
505 | (r = sshbuf_put_bignum1(b, key->n)) != 0 || | ||
506 | (r = sshbuf_put_bignum1(b, key->e)) != 0 || | ||
507 | (r = sshbuf_put_bignum1(b, key->d)) != 0 || | ||
508 | (r = sshbuf_put_bignum1(b, key->iqmp)) != 0 || | ||
509 | (r = sshbuf_put_bignum1(b, key->q)) != 0 || | ||
510 | (r = sshbuf_put_bignum1(b, key->p)) != 0 || | ||
511 | (r = sshbuf_put_cstring(b, comment)) != 0) | ||
512 | return r; | ||
513 | return 0; | ||
514 | } | ||
515 | #endif | ||
516 | 394 | ||
517 | static int | 395 | static int |
518 | ssh_encode_identity_ssh2(struct sshbuf *b, struct sshkey *key, | 396 | ssh_encode_identity_ssh2(struct sshbuf *b, struct sshkey *key, |
@@ -561,16 +439,6 @@ ssh_add_identity_constrained(int sock, struct sshkey *key, const char *comment, | |||
561 | return SSH_ERR_ALLOC_FAIL; | 439 | return SSH_ERR_ALLOC_FAIL; |
562 | 440 | ||
563 | switch (key->type) { | 441 | switch (key->type) { |
564 | #ifdef WITH_SSH1 | ||
565 | case KEY_RSA1: | ||
566 | type = constrained ? | ||
567 | SSH_AGENTC_ADD_RSA_ID_CONSTRAINED : | ||
568 | SSH_AGENTC_ADD_RSA_IDENTITY; | ||
569 | if ((r = sshbuf_put_u8(msg, type)) != 0 || | ||
570 | (r = ssh_encode_identity_rsa1(msg, key->rsa, comment)) != 0) | ||
571 | goto out; | ||
572 | break; | ||
573 | #endif | ||
574 | #ifdef WITH_OPENSSL | 442 | #ifdef WITH_OPENSSL |
575 | case KEY_RSA: | 443 | case KEY_RSA: |
576 | case KEY_RSA_CERT: | 444 | case KEY_RSA_CERT: |
@@ -620,16 +488,6 @@ ssh_remove_identity(int sock, struct sshkey *key) | |||
620 | if ((msg = sshbuf_new()) == NULL) | 488 | if ((msg = sshbuf_new()) == NULL) |
621 | return SSH_ERR_ALLOC_FAIL; | 489 | return SSH_ERR_ALLOC_FAIL; |
622 | 490 | ||
623 | #ifdef WITH_SSH1 | ||
624 | if (key->type == KEY_RSA1) { | ||
625 | if ((r = sshbuf_put_u8(msg, | ||
626 | SSH_AGENTC_REMOVE_RSA_IDENTITY)) != 0 || | ||
627 | (r = sshbuf_put_u32(msg, BN_num_bits(key->rsa->n))) != 0 || | ||
628 | (r = sshbuf_put_bignum1(msg, key->rsa->e)) != 0 || | ||
629 | (r = sshbuf_put_bignum1(msg, key->rsa->n)) != 0) | ||
630 | goto out; | ||
631 | } else | ||
632 | #endif | ||
633 | if (key->type != KEY_UNSPEC) { | 491 | if (key->type != KEY_UNSPEC) { |
634 | if ((r = sshkey_to_blob(key, &blob, &blen)) != 0) | 492 | if ((r = sshkey_to_blob(key, &blob, &blen)) != 0) |
635 | goto out; | 493 | goto out; |
@@ -696,6 +554,10 @@ ssh_update_card(int sock, int add, const char *reader_id, const char *pin, | |||
696 | /* | 554 | /* |
697 | * Removes all identities from the agent. | 555 | * Removes all identities from the agent. |
698 | * This call is intended only for use by ssh-add(1) and like applications. | 556 | * This call is intended only for use by ssh-add(1) and like applications. |
557 | * | ||
558 | * This supports the SSH protocol 1 message to because, when clearing all | ||
559 | * keys from an agent, we generally want to clear both protocol v1 and v2 | ||
560 | * keys. | ||
699 | */ | 561 | */ |
700 | int | 562 | int |
701 | ssh_remove_all_identities(int sock, int version) | 563 | ssh_remove_all_identities(int sock, int version) |