summaryrefslogtreecommitdiff
path: root/sshconnect2.c
diff options
context:
space:
mode:
Diffstat (limited to 'sshconnect2.c')
-rw-r--r--sshconnect2.c625
1 files changed, 164 insertions, 461 deletions
diff --git a/sshconnect2.c b/sshconnect2.c
index 933c223ec..642b34b9e 100644
--- a/sshconnect2.c
+++ b/sshconnect2.c
@@ -23,9 +23,7 @@
23 */ 23 */
24 24
25#include "includes.h" 25#include "includes.h"
26RCSID("$OpenBSD: sshconnect2.c,v 1.124 2003/08/25 10:33:33 djm Exp $"); 26RCSID("$OpenBSD: sshconnect2.c,v 1.114 2003/04/01 10:22:21 markus Exp $");
27
28#include "openbsd-compat/sys-queue.h"
29 27
30#include "ssh.h" 28#include "ssh.h"
31#include "ssh2.h" 29#include "ssh2.h"
@@ -50,10 +48,6 @@ RCSID("$OpenBSD: sshconnect2.c,v 1.124 2003/08/25 10:33:33 djm Exp $");
50#include "msg.h" 48#include "msg.h"
51#include "pathnames.h" 49#include "pathnames.h"
52 50
53#ifdef GSSAPI
54#include "ssh-gss.h"
55#endif
56
57/* import */ 51/* import */
58extern char *client_version_string; 52extern char *client_version_string;
59extern char *server_version_string; 53extern char *server_version_string;
@@ -64,7 +58,7 @@ extern Options options;
64 */ 58 */
65 59
66u_char *session_id2 = NULL; 60u_char *session_id2 = NULL;
67u_int session_id2_len = 0; 61int session_id2_len = 0;
68 62
69char *xxx_host; 63char *xxx_host;
70struct sockaddr *xxx_hostaddr; 64struct sockaddr *xxx_hostaddr;
@@ -88,7 +82,7 @@ ssh_kex2(char *host, struct sockaddr *hostaddr)
88 xxx_hostaddr = hostaddr; 82 xxx_hostaddr = hostaddr;
89 83
90 if (options.ciphers == (char *)-1) { 84 if (options.ciphers == (char *)-1) {
91 logit("No valid ciphers for protocol version 2 given, using defaults."); 85 log("No valid ciphers for protocol version 2 given, using defaults.");
92 options.ciphers = NULL; 86 options.ciphers = NULL;
93 } 87 }
94 if (options.ciphers != NULL) { 88 if (options.ciphers != NULL) {
@@ -114,9 +108,6 @@ ssh_kex2(char *host, struct sockaddr *hostaddr)
114 myproposal[PROPOSAL_SERVER_HOST_KEY_ALGS] = 108 myproposal[PROPOSAL_SERVER_HOST_KEY_ALGS] =
115 options.hostkeyalgorithms; 109 options.hostkeyalgorithms;
116 110
117 if (options.rekey_limit)
118 packet_set_rekey_limit(options.rekey_limit);
119
120 /* start key exchange */ 111 /* start key exchange */
121 kex = kex_setup(myproposal); 112 kex = kex_setup(myproposal);
122 kex->kex[KEX_DH_GRP1_SHA1] = kexdh_client; 113 kex->kex[KEX_DH_GRP1_SHA1] = kexdh_client;
@@ -147,18 +138,10 @@ ssh_kex2(char *host, struct sockaddr *hostaddr)
147 138
148typedef struct Authctxt Authctxt; 139typedef struct Authctxt Authctxt;
149typedef struct Authmethod Authmethod; 140typedef struct Authmethod Authmethod;
150typedef struct identity Identity; 141
151typedef struct idlist Idlist; 142typedef int sign_cb_fn(
152 143 Authctxt *authctxt, Key *key,
153struct identity { 144 u_char **sigp, u_int *lenp, u_char *data, u_int datalen);
154 TAILQ_ENTRY(identity) next;
155 AuthenticationConnection *ac; /* set if agent supports key */
156 Key *key; /* public/private key */
157 char *filename; /* comment for agent-only keys */
158 int tried;
159 int isprivate; /* key points to the private key */
160};
161TAILQ_HEAD(idlist, identity);
162 145
163struct Authctxt { 146struct Authctxt {
164 const char *server_user; 147 const char *server_user;
@@ -169,14 +152,14 @@ struct Authctxt {
169 int success; 152 int success;
170 char *authlist; 153 char *authlist;
171 /* pubkey */ 154 /* pubkey */
172 Idlist keys; 155 Key *last_key;
156 sign_cb_fn *last_key_sign;
157 int last_key_hint;
173 AuthenticationConnection *agent; 158 AuthenticationConnection *agent;
174 /* hostbased */ 159 /* hostbased */
175 Sensitive *sensitive; 160 Sensitive *sensitive;
176 /* kbd-interactive */ 161 /* kbd-interactive */
177 int info_req_seen; 162 int info_req_seen;
178 /* generic */
179 void *methoddata;
180}; 163};
181struct Authmethod { 164struct Authmethod {
182 char *name; /* string to compare against server's list */ 165 char *name; /* string to compare against server's list */
@@ -198,35 +181,17 @@ int userauth_pubkey(Authctxt *);
198int userauth_passwd(Authctxt *); 181int userauth_passwd(Authctxt *);
199int userauth_kbdint(Authctxt *); 182int userauth_kbdint(Authctxt *);
200int userauth_hostbased(Authctxt *); 183int userauth_hostbased(Authctxt *);
201int userauth_kerberos(Authctxt *);
202
203#ifdef GSSAPI
204int userauth_gssapi(Authctxt *authctxt);
205void input_gssapi_response(int type, u_int32_t, void *);
206void input_gssapi_token(int type, u_int32_t, void *);
207void input_gssapi_hash(int type, u_int32_t, void *);
208void input_gssapi_error(int, u_int32_t, void *);
209void input_gssapi_errtok(int, u_int32_t, void *);
210#endif
211 184
212void userauth(Authctxt *, char *); 185void userauth(Authctxt *, char *);
213 186
214static int sign_and_send_pubkey(Authctxt *, Identity *); 187static int sign_and_send_pubkey(Authctxt *, Key *, sign_cb_fn *);
215static void pubkey_prepare(Authctxt *); 188static void clear_auth_state(Authctxt *);
216static void pubkey_cleanup(Authctxt *);
217static Key *load_identity_file(char *);
218 189
219static Authmethod *authmethod_get(char *authlist); 190static Authmethod *authmethod_get(char *authlist);
220static Authmethod *authmethod_lookup(const char *name); 191static Authmethod *authmethod_lookup(const char *name);
221static char *authmethods_get(void); 192static char *authmethods_get(void);
222 193
223Authmethod authmethods[] = { 194Authmethod authmethods[] = {
224#ifdef GSSAPI
225 {"gssapi",
226 userauth_gssapi,
227 &options.gss_authentication,
228 NULL},
229#endif
230 {"hostbased", 195 {"hostbased",
231 userauth_hostbased, 196 userauth_hostbased,
232 &options.hostbased_authentication, 197 &options.hostbased_authentication,
@@ -283,7 +248,7 @@ ssh_userauth2(const char *local_user, const char *server_user, char *host,
283 248
284 /* setup authentication context */ 249 /* setup authentication context */
285 memset(&authctxt, 0, sizeof(authctxt)); 250 memset(&authctxt, 0, sizeof(authctxt));
286 pubkey_prepare(&authctxt); 251 authctxt.agent = ssh_get_authentication_connection();
287 authctxt.server_user = server_user; 252 authctxt.server_user = server_user;
288 authctxt.local_user = local_user; 253 authctxt.local_user = local_user;
289 authctxt.host = host; 254 authctxt.host = host;
@@ -291,7 +256,6 @@ ssh_userauth2(const char *local_user, const char *server_user, char *host,
291 authctxt.success = 0; 256 authctxt.success = 0;
292 authctxt.method = authmethod_lookup("none"); 257 authctxt.method = authmethod_lookup("none");
293 authctxt.authlist = NULL; 258 authctxt.authlist = NULL;
294 authctxt.methoddata = NULL;
295 authctxt.sensitive = sensitive; 259 authctxt.sensitive = sensitive;
296 authctxt.info_req_seen = 0; 260 authctxt.info_req_seen = 0;
297 if (authctxt.method == NULL) 261 if (authctxt.method == NULL)
@@ -306,19 +270,14 @@ ssh_userauth2(const char *local_user, const char *server_user, char *host,
306 dispatch_set(SSH2_MSG_USERAUTH_BANNER, &input_userauth_banner); 270 dispatch_set(SSH2_MSG_USERAUTH_BANNER, &input_userauth_banner);
307 dispatch_run(DISPATCH_BLOCK, &authctxt.success, &authctxt); /* loop until success */ 271 dispatch_run(DISPATCH_BLOCK, &authctxt.success, &authctxt); /* loop until success */
308 272
309 pubkey_cleanup(&authctxt); 273 if (authctxt.agent != NULL)
310 dispatch_range(SSH2_MSG_USERAUTH_MIN, SSH2_MSG_USERAUTH_MAX, NULL); 274 ssh_close_authentication_connection(authctxt.agent);
311 275
312 debug("Authentication succeeded (%s).", authctxt.method->name); 276 debug("Authentication succeeded (%s).", authctxt.method->name);
313} 277}
314
315void 278void
316userauth(Authctxt *authctxt, char *authlist) 279userauth(Authctxt *authctxt, char *authlist)
317{ 280{
318 if (authctxt->methoddata) {
319 xfree(authctxt->methoddata);
320 authctxt->methoddata = NULL;
321 }
322 if (authlist == NULL) { 281 if (authlist == NULL) {
323 authlist = authctxt->authlist; 282 authlist = authctxt->authlist;
324 } else { 283 } else {
@@ -331,12 +290,6 @@ userauth(Authctxt *authctxt, char *authlist)
331 if (method == NULL) 290 if (method == NULL)
332 fatal("Permission denied (%s).", authlist); 291 fatal("Permission denied (%s).", authlist);
333 authctxt->method = method; 292 authctxt->method = method;
334
335 /* reset the per method handler */
336 dispatch_range(SSH2_MSG_USERAUTH_PER_METHOD_MIN,
337 SSH2_MSG_USERAUTH_PER_METHOD_MAX, NULL);
338
339 /* and try new method */
340 if (method->userauth(authctxt) != 0) { 293 if (method->userauth(authctxt) != 0) {
341 debug2("we sent a %s packet, wait for reply", method->name); 294 debug2("we sent a %s packet, wait for reply", method->name);
342 break; 295 break;
@@ -361,7 +314,7 @@ input_userauth_banner(int type, u_int32_t seq, void *ctxt)
361 debug3("input_userauth_banner"); 314 debug3("input_userauth_banner");
362 msg = packet_get_string(NULL); 315 msg = packet_get_string(NULL);
363 lang = packet_get_string(NULL); 316 lang = packet_get_string(NULL);
364 logit("%s", msg); 317 fprintf(stderr, "%s", msg);
365 xfree(msg); 318 xfree(msg);
366 xfree(lang); 319 xfree(lang);
367} 320}
@@ -374,8 +327,7 @@ input_userauth_success(int type, u_int32_t seq, void *ctxt)
374 fatal("input_userauth_success: no authentication context"); 327 fatal("input_userauth_success: no authentication context");
375 if (authctxt->authlist) 328 if (authctxt->authlist)
376 xfree(authctxt->authlist); 329 xfree(authctxt->authlist);
377 if (authctxt->methoddata) 330 clear_auth_state(authctxt);
378 xfree(authctxt->methoddata);
379 authctxt->success = 1; /* break out */ 331 authctxt->success = 1; /* break out */
380} 332}
381 333
@@ -394,9 +346,10 @@ input_userauth_failure(int type, u_int32_t seq, void *ctxt)
394 packet_check_eom(); 346 packet_check_eom();
395 347
396 if (partial != 0) 348 if (partial != 0)
397 logit("Authenticated with partial success."); 349 log("Authenticated with partial success.");
398 debug("Authentications that can continue: %s", authlist); 350 debug("Authentications that can continue: %s", authlist);
399 351
352 clear_auth_state(authctxt);
400 userauth(authctxt, authlist); 353 userauth(authctxt, authlist);
401} 354}
402void 355void
@@ -404,7 +357,6 @@ input_userauth_pk_ok(int type, u_int32_t seq, void *ctxt)
404{ 357{
405 Authctxt *authctxt = ctxt; 358 Authctxt *authctxt = ctxt;
406 Key *key = NULL; 359 Key *key = NULL;
407 Identity *id = NULL;
408 Buffer b; 360 Buffer b;
409 int pktype, sent = 0; 361 int pktype, sent = 0;
410 u_int alen, blen; 362 u_int alen, blen;
@@ -427,267 +379,55 @@ input_userauth_pk_ok(int type, u_int32_t seq, void *ctxt)
427 } 379 }
428 packet_check_eom(); 380 packet_check_eom();
429 381
430 debug("Server accepts key: pkalg %s blen %u", pkalg, blen); 382 debug("Server accepts key: pkalg %s blen %u lastkey %p hint %d",
431 383 pkalg, blen, authctxt->last_key, authctxt->last_key_hint);
432 if ((pktype = key_type_from_name(pkalg)) == KEY_UNSPEC) {
433 debug("unknown pkalg %s", pkalg);
434 goto done;
435 }
436 if ((key = key_from_blob(pkblob, blen)) == NULL) {
437 debug("no key from blob. pkalg %s", pkalg);
438 goto done;
439 }
440 if (key->type != pktype) {
441 error("input_userauth_pk_ok: type mismatch "
442 "for decoded key (received %d, expected %d)",
443 key->type, pktype);
444 goto done;
445 }
446 fp = key_fingerprint(key, SSH_FP_MD5, SSH_FP_HEX);
447 debug2("input_userauth_pk_ok: fp %s", fp);
448 xfree(fp);
449 384
450 TAILQ_FOREACH(id, &authctxt->keys, next) { 385 do {
451 if (key_equal(key, id->key)) { 386 if (authctxt->last_key == NULL ||
452 sent = sign_and_send_pubkey(authctxt, id); 387 authctxt->last_key_sign == NULL) {
388 debug("no last key or no sign cb");
453 break; 389 break;
454 } 390 }
455 } 391 if ((pktype = key_type_from_name(pkalg)) == KEY_UNSPEC) {
456done: 392 debug("unknown pkalg %s", pkalg);
393 break;
394 }
395 if ((key = key_from_blob(pkblob, blen)) == NULL) {
396 debug("no key from blob. pkalg %s", pkalg);
397 break;
398 }
399 if (key->type != pktype) {
400 error("input_userauth_pk_ok: type mismatch "
401 "for decoded key (received %d, expected %d)",
402 key->type, pktype);
403 break;
404 }
405 fp = key_fingerprint(key, SSH_FP_MD5, SSH_FP_HEX);
406 debug2("input_userauth_pk_ok: fp %s", fp);
407 xfree(fp);
408 if (!key_equal(key, authctxt->last_key)) {
409 debug("key != last_key");
410 break;
411 }
412 sent = sign_and_send_pubkey(authctxt, key,
413 authctxt->last_key_sign);
414 } while (0);
415
457 if (key != NULL) 416 if (key != NULL)
458 key_free(key); 417 key_free(key);
459 xfree(pkalg); 418 xfree(pkalg);
460 xfree(pkblob); 419 xfree(pkblob);
461 420
421 /* unregister */
422 clear_auth_state(authctxt);
423 dispatch_set(SSH2_MSG_USERAUTH_PK_OK, NULL);
424
462 /* try another method if we did not send a packet */ 425 /* try another method if we did not send a packet */
463 if (sent == 0) 426 if (sent == 0)
464 userauth(authctxt, NULL); 427 userauth(authctxt, NULL);
465}
466
467#ifdef GSSAPI
468int
469userauth_gssapi(Authctxt *authctxt)
470{
471 Gssctxt *gssctxt = NULL;
472 static gss_OID_set supported = NULL;
473 static int mech = 0;
474 OM_uint32 min;
475 int ok = 0;
476
477 /* Try one GSSAPI method at a time, rather than sending them all at
478 * once. */
479
480 if (supported == NULL)
481 gss_indicate_mechs(&min, &supported);
482
483 /* Check to see if the mechanism is usable before we offer it */
484 while (mech<supported->count && !ok) {
485 if (gssctxt)
486 ssh_gssapi_delete_ctx(&gssctxt);
487 ssh_gssapi_build_ctx(&gssctxt);
488 ssh_gssapi_set_oid(gssctxt, &supported->elements[mech]);
489
490 /* My DER encoding requires length<128 */
491 if (supported->elements[mech].length < 128 &&
492 !GSS_ERROR(ssh_gssapi_import_name(gssctxt,
493 authctxt->host))) {
494 ok = 1; /* Mechanism works */
495 } else {
496 mech++;
497 }
498 }
499
500 if (!ok) return 0;
501
502 authctxt->methoddata=(void *)gssctxt;
503
504 packet_start(SSH2_MSG_USERAUTH_REQUEST);
505 packet_put_cstring(authctxt->server_user);
506 packet_put_cstring(authctxt->service);
507 packet_put_cstring(authctxt->method->name);
508 428
509 packet_put_int(1);
510
511 /* Some servers encode the OID incorrectly (as we used to) */
512 if (datafellows & SSH_BUG_GSSAPI_BER) {
513 packet_put_string(supported->elements[mech].elements,
514 supported->elements[mech].length);
515 } else {
516 packet_put_int((supported->elements[mech].length)+2);
517 packet_put_char(SSH_GSS_OIDTYPE);
518 packet_put_char(supported->elements[mech].length);
519 packet_put_raw(supported->elements[mech].elements,
520 supported->elements[mech].length);
521 }
522
523 packet_send();
524
525 dispatch_set(SSH2_MSG_USERAUTH_GSSAPI_RESPONSE, &input_gssapi_response);
526 dispatch_set(SSH2_MSG_USERAUTH_GSSAPI_TOKEN, &input_gssapi_token);
527 dispatch_set(SSH2_MSG_USERAUTH_GSSAPI_ERROR, &input_gssapi_error);
528 dispatch_set(SSH2_MSG_USERAUTH_GSSAPI_ERRTOK, &input_gssapi_errtok);
529
530 mech++; /* Move along to next candidate */
531
532 return 1;
533}
534
535void
536input_gssapi_response(int type, u_int32_t plen, void *ctxt)
537{
538 Authctxt *authctxt = ctxt;
539 Gssctxt *gssctxt;
540 OM_uint32 status, ms;
541 int oidlen;
542 char *oidv;
543 gss_buffer_desc send_tok = GSS_C_EMPTY_BUFFER;
544
545 if (authctxt == NULL)
546 fatal("input_gssapi_response: no authentication context");
547 gssctxt = authctxt->methoddata;
548
549 /* Setup our OID */
550 oidv = packet_get_string(&oidlen);
551
552 if (datafellows & SSH_BUG_GSSAPI_BER) {
553 if (!ssh_gssapi_check_oid(gssctxt, oidv, oidlen))
554 fatal("Server returned different OID than expected");
555 } else {
556 if(oidv[0] != SSH_GSS_OIDTYPE || oidv[1] != oidlen-2) {
557 debug("Badly encoded mechanism OID received");
558 userauth(authctxt, NULL);
559 xfree(oidv);
560 return;
561 }
562 if (!ssh_gssapi_check_oid(gssctxt, oidv+2, oidlen-2))
563 fatal("Server returned different OID than expected");
564 }
565
566 packet_check_eom();
567
568 xfree(oidv);
569
570 status = ssh_gssapi_init_ctx(gssctxt, options.gss_deleg_creds,
571 GSS_C_NO_BUFFER, &send_tok, NULL);
572 if (GSS_ERROR(status)) {
573 if (send_tok.length > 0) {
574 packet_start(SSH2_MSG_USERAUTH_GSSAPI_ERRTOK);
575 packet_put_string(send_tok.value, send_tok.length);
576 packet_send();
577 gss_release_buffer(&ms, &send_tok);
578 }
579 /* Start again with next method on list */
580 debug("Trying to start again");
581 userauth(authctxt, NULL);
582 return;
583 }
584
585 /* We must have data to send */
586 packet_start(SSH2_MSG_USERAUTH_GSSAPI_TOKEN);
587 packet_put_string(send_tok.value, send_tok.length);
588 packet_send();
589 gss_release_buffer(&ms, &send_tok);
590} 429}
591 430
592void
593input_gssapi_token(int type, u_int32_t plen, void *ctxt)
594{
595 Authctxt *authctxt = ctxt;
596 Gssctxt *gssctxt;
597 gss_buffer_desc send_tok = GSS_C_EMPTY_BUFFER;
598 gss_buffer_desc recv_tok;
599 OM_uint32 status, ms;
600 u_int slen;
601
602 if (authctxt == NULL)
603 fatal("input_gssapi_response: no authentication context");
604 gssctxt = authctxt->methoddata;
605
606 recv_tok.value = packet_get_string(&slen);
607 recv_tok.length = slen; /* safe typecast */
608
609 packet_check_eom();
610
611 status=ssh_gssapi_init_ctx(gssctxt, options.gss_deleg_creds,
612 &recv_tok, &send_tok, NULL);
613
614 xfree(recv_tok.value);
615
616 if (GSS_ERROR(status)) {
617 if (send_tok.length > 0) {
618 packet_start(SSH2_MSG_USERAUTH_GSSAPI_ERRTOK);
619 packet_put_string(send_tok.value, send_tok.length);
620 packet_send();
621 gss_release_buffer(&ms, &send_tok);
622 }
623 /* Start again with the next method in the list */
624 userauth(authctxt, NULL);
625 return;
626 }
627
628 if (send_tok.length > 0) {
629 packet_start(SSH2_MSG_USERAUTH_GSSAPI_TOKEN);
630 packet_put_string(send_tok.value, send_tok.length);
631 packet_send();
632 gss_release_buffer(&ms, &send_tok);
633 }
634
635 if (status == GSS_S_COMPLETE) {
636 /* If that succeeded, send a exchange complete message */
637 packet_start(SSH2_MSG_USERAUTH_GSSAPI_EXCHANGE_COMPLETE);
638 packet_send();
639 }
640}
641
642void
643input_gssapi_errtok(int type, u_int32_t plen, void *ctxt)
644{
645 Authctxt *authctxt = ctxt;
646 Gssctxt *gssctxt;
647 gss_buffer_desc send_tok = GSS_C_EMPTY_BUFFER;
648 gss_buffer_desc recv_tok;
649 OM_uint32 status, ms;
650 u_int len;
651
652 if (authctxt == NULL)
653 fatal("input_gssapi_response: no authentication context");
654 gssctxt = authctxt->methoddata;
655
656 recv_tok.value = packet_get_string(&len);
657 recv_tok.length = len;
658
659 packet_check_eom();
660
661 /* Stick it into GSSAPI and see what it says */
662 status = ssh_gssapi_init_ctx(gssctxt, options.gss_deleg_creds,
663 &recv_tok, &send_tok, NULL);
664
665 xfree(recv_tok.value);
666 gss_release_buffer(&ms, &send_tok);
667
668 /* Server will be returning a failed packet after this one */
669}
670
671void
672input_gssapi_error(int type, u_int32_t plen, void *ctxt)
673{
674 OM_uint32 maj, min;
675 char *msg;
676 char *lang;
677
678 maj=packet_get_int();
679 min=packet_get_int();
680 msg=packet_get_string(NULL);
681 lang=packet_get_string(NULL);
682
683 packet_check_eom();
684
685 debug("Server GSSAPI Error:\n%s\n", msg);
686 xfree(msg);
687 xfree(lang);
688}
689#endif /* GSSAPI */
690
691int 431int
692userauth_none(Authctxt *authctxt) 432userauth_none(Authctxt *authctxt)
693{ 433{
@@ -751,7 +491,7 @@ input_userauth_passwd_changereq(int type, u_int32_t seqnr, void *ctxt)
751 info = packet_get_string(NULL); 491 info = packet_get_string(NULL);
752 lang = packet_get_string(NULL); 492 lang = packet_get_string(NULL);
753 if (strlen(info) > 0) 493 if (strlen(info) > 0)
754 logit("%s", info); 494 log("%s", info);
755 xfree(info); 495 xfree(info);
756 xfree(lang); 496 xfree(lang);
757 packet_start(SSH2_MSG_USERAUTH_REQUEST); 497 packet_start(SSH2_MSG_USERAUTH_REQUEST);
@@ -783,7 +523,7 @@ input_userauth_passwd_changereq(int type, u_int32_t seqnr, void *ctxt)
783 if (strcmp(password, retype) != 0) { 523 if (strcmp(password, retype) != 0) {
784 memset(password, 0, strlen(password)); 524 memset(password, 0, strlen(password));
785 xfree(password); 525 xfree(password);
786 logit("Mismatch; try again, EOF to quit."); 526 log("Mismatch; try again, EOF to quit.");
787 password = NULL; 527 password = NULL;
788 } 528 }
789 memset(retype, 0, strlen(retype)); 529 memset(retype, 0, strlen(retype));
@@ -799,44 +539,34 @@ input_userauth_passwd_changereq(int type, u_int32_t seqnr, void *ctxt)
799 &input_userauth_passwd_changereq); 539 &input_userauth_passwd_changereq);
800} 540}
801 541
802static int 542static void
803identity_sign(Identity *id, u_char **sigp, u_int *lenp, 543clear_auth_state(Authctxt *authctxt)
804 u_char *data, u_int datalen)
805{ 544{
806 Key *prv; 545 /* XXX clear authentication state */
807 int ret; 546 dispatch_set(SSH2_MSG_USERAUTH_PASSWD_CHANGEREQ, NULL);
808 547
809 /* the agent supports this key */ 548 if (authctxt->last_key != NULL && authctxt->last_key_hint == -1) {
810 if (id->ac) 549 debug3("clear_auth_state: key_free %p", authctxt->last_key);
811 return (ssh_agent_sign(id->ac, id->key, sigp, lenp, 550 key_free(authctxt->last_key);
812 data, datalen)); 551 }
813 /* 552 authctxt->last_key = NULL;
814 * we have already loaded the private key or 553 authctxt->last_key_hint = -2;
815 * the private key is stored in external hardware 554 authctxt->last_key_sign = NULL;
816 */
817 if (id->isprivate || (id->key->flags & KEY_FLAG_EXT))
818 return (key_sign(id->key, sigp, lenp, data, datalen));
819 /* load the private key from the file */
820 if ((prv = load_identity_file(id->filename)) == NULL)
821 return (-1);
822 ret = key_sign(prv, sigp, lenp, data, datalen);
823 key_free(prv);
824 return (ret);
825} 555}
826 556
827static int 557static int
828sign_and_send_pubkey(Authctxt *authctxt, Identity *id) 558sign_and_send_pubkey(Authctxt *authctxt, Key *k, sign_cb_fn *sign_callback)
829{ 559{
830 Buffer b; 560 Buffer b;
831 u_char *blob, *signature; 561 u_char *blob, *signature;
832 u_int bloblen, slen; 562 u_int bloblen, slen;
833 u_int skip = 0; 563 int skip = 0;
834 int ret = -1; 564 int ret = -1;
835 int have_sig = 1; 565 int have_sig = 1;
836 566
837 debug3("sign_and_send_pubkey"); 567 debug3("sign_and_send_pubkey");
838 568
839 if (key_to_blob(id->key, &blob, &bloblen) == 0) { 569 if (key_to_blob(k, &blob, &bloblen) == 0) {
840 /* we cannot handle this key */ 570 /* we cannot handle this key */
841 debug3("sign_and_send_pubkey: cannot handle key"); 571 debug3("sign_and_send_pubkey: cannot handle key");
842 return 0; 572 return 0;
@@ -861,12 +591,12 @@ sign_and_send_pubkey(Authctxt *authctxt, Identity *id)
861 } else { 591 } else {
862 buffer_put_cstring(&b, authctxt->method->name); 592 buffer_put_cstring(&b, authctxt->method->name);
863 buffer_put_char(&b, have_sig); 593 buffer_put_char(&b, have_sig);
864 buffer_put_cstring(&b, key_ssh_name(id->key)); 594 buffer_put_cstring(&b, key_ssh_name(k));
865 } 595 }
866 buffer_put_string(&b, blob, bloblen); 596 buffer_put_string(&b, blob, bloblen);
867 597
868 /* generate signature */ 598 /* generate signature */
869 ret = identity_sign(id, &signature, &slen, 599 ret = (*sign_callback)(authctxt, k, &signature, &slen,
870 buffer_ptr(&b), buffer_len(&b)); 600 buffer_ptr(&b), buffer_len(&b));
871 if (ret == -1) { 601 if (ret == -1) {
872 xfree(blob); 602 xfree(blob);
@@ -886,7 +616,7 @@ sign_and_send_pubkey(Authctxt *authctxt, Identity *id)
886 buffer_put_cstring(&b, authctxt->method->name); 616 buffer_put_cstring(&b, authctxt->method->name);
887 buffer_put_char(&b, have_sig); 617 buffer_put_char(&b, have_sig);
888 if (!(datafellows & SSH_BUG_PKAUTH)) 618 if (!(datafellows & SSH_BUG_PKAUTH))
889 buffer_put_cstring(&b, key_ssh_name(id->key)); 619 buffer_put_cstring(&b, key_ssh_name(k));
890 buffer_put_string(&b, blob, bloblen); 620 buffer_put_string(&b, blob, bloblen);
891 } 621 }
892 xfree(blob); 622 xfree(blob);
@@ -910,19 +640,23 @@ sign_and_send_pubkey(Authctxt *authctxt, Identity *id)
910} 640}
911 641
912static int 642static int
913send_pubkey_test(Authctxt *authctxt, Identity *id) 643send_pubkey_test(Authctxt *authctxt, Key *k, sign_cb_fn *sign_callback,
644 int hint)
914{ 645{
915 u_char *blob; 646 u_char *blob;
916 u_int bloblen, have_sig = 0; 647 u_int bloblen, have_sig = 0;
917 648
918 debug3("send_pubkey_test"); 649 debug3("send_pubkey_test");
919 650
920 if (key_to_blob(id->key, &blob, &bloblen) == 0) { 651 if (key_to_blob(k, &blob, &bloblen) == 0) {
921 /* we cannot handle this key */ 652 /* we cannot handle this key */
922 debug3("send_pubkey_test: cannot handle key"); 653 debug3("send_pubkey_test: cannot handle key");
923 return 0; 654 return 0;
924 } 655 }
925 /* register callback for USERAUTH_PK_OK message */ 656 /* register callback for USERAUTH_PK_OK message */
657 authctxt->last_key_sign = sign_callback;
658 authctxt->last_key_hint = hint;
659 authctxt->last_key = k;
926 dispatch_set(SSH2_MSG_USERAUTH_PK_OK, &input_userauth_pk_ok); 660 dispatch_set(SSH2_MSG_USERAUTH_PK_OK, &input_userauth_pk_ok);
927 661
928 packet_start(SSH2_MSG_USERAUTH_REQUEST); 662 packet_start(SSH2_MSG_USERAUTH_REQUEST);
@@ -931,7 +665,7 @@ send_pubkey_test(Authctxt *authctxt, Identity *id)
931 packet_put_cstring(authctxt->method->name); 665 packet_put_cstring(authctxt->method->name);
932 packet_put_char(have_sig); 666 packet_put_char(have_sig);
933 if (!(datafellows & SSH_BUG_PKAUTH)) 667 if (!(datafellows & SSH_BUG_PKAUTH))
934 packet_put_cstring(key_ssh_name(id->key)); 668 packet_put_cstring(key_ssh_name(k));
935 packet_put_string(blob, bloblen); 669 packet_put_string(blob, bloblen);
936 xfree(blob); 670 xfree(blob);
937 packet_send(); 671 packet_send();
@@ -976,134 +710,103 @@ load_identity_file(char *filename)
976 return private; 710 return private;
977} 711}
978 712
979/* 713static int
980 * try keys in the following order: 714identity_sign_cb(Authctxt *authctxt, Key *key, u_char **sigp, u_int *lenp,
981 * 1. agent keys that are found in the config file 715 u_char *data, u_int datalen)
982 * 2. other agent keys
983 * 3. keys that are only listed in the config file
984 */
985static void
986pubkey_prepare(Authctxt *authctxt)
987{ 716{
988 Identity *id; 717 Key *private;
989 Idlist agent, files, *preferred; 718 int idx, ret;
990 Key *key; 719
991 AuthenticationConnection *ac; 720 idx = authctxt->last_key_hint;
992 char *comment; 721 if (idx < 0)
993 int i, found; 722 return -1;
994 723
995 TAILQ_INIT(&agent); /* keys from the agent */ 724 /* private key is stored in external hardware */
996 TAILQ_INIT(&files); /* keys from the config file */ 725 if (options.identity_keys[idx]->flags & KEY_FLAG_EXT)
997 preferred = &authctxt->keys; 726 return key_sign(options.identity_keys[idx], sigp, lenp, data, datalen);
998 TAILQ_INIT(preferred); /* preferred order of keys */ 727
999 728 private = load_identity_file(options.identity_files[idx]);
1000 /* list of keys stored in the filesystem */ 729 if (private == NULL)
1001 for (i = 0; i < options.num_identity_files; i++) { 730 return -1;
1002 key = options.identity_keys[i]; 731 ret = key_sign(private, sigp, lenp, data, datalen);
1003 if (key && key->type == KEY_RSA1) 732 key_free(private);
1004 continue; 733 return ret;
1005 options.identity_keys[i] = NULL;
1006 id = xmalloc(sizeof(*id));
1007 memset(id, 0, sizeof(*id));
1008 id->key = key;
1009 id->filename = xstrdup(options.identity_files[i]);
1010 TAILQ_INSERT_TAIL(&files, id, next);
1011 }
1012 /* list of keys supported by the agent */
1013 if ((ac = ssh_get_authentication_connection())) {
1014 for (key = ssh_get_first_identity(ac, &comment, 2);
1015 key != NULL;
1016 key = ssh_get_next_identity(ac, &comment, 2)) {
1017 found = 0;
1018 TAILQ_FOREACH(id, &files, next) {
1019 /* agent keys from the config file are preferred */
1020 if (key_equal(key, id->key)) {
1021 key_free(key);
1022 xfree(comment);
1023 TAILQ_REMOVE(&files, id, next);
1024 TAILQ_INSERT_TAIL(preferred, id, next);
1025 id->ac = ac;
1026 found = 1;
1027 break;
1028 }
1029 }
1030 if (!found) {
1031 id = xmalloc(sizeof(*id));
1032 memset(id, 0, sizeof(*id));
1033 id->key = key;
1034 id->filename = comment;
1035 id->ac = ac;
1036 TAILQ_INSERT_TAIL(&agent, id, next);
1037 }
1038 }
1039 /* append remaining agent keys */
1040 for (id = TAILQ_FIRST(&agent); id; id = TAILQ_FIRST(&agent)) {
1041 TAILQ_REMOVE(&agent, id, next);
1042 TAILQ_INSERT_TAIL(preferred, id, next);
1043 }
1044 authctxt->agent = ac;
1045 }
1046 /* append remaining keys from the config file */
1047 for (id = TAILQ_FIRST(&files); id; id = TAILQ_FIRST(&files)) {
1048 TAILQ_REMOVE(&files, id, next);
1049 TAILQ_INSERT_TAIL(preferred, id, next);
1050 }
1051 TAILQ_FOREACH(id, preferred, next) {
1052 debug2("key: %s (%p)", id->filename, id->key);
1053 }
1054} 734}
1055 735
1056static void 736static int
1057pubkey_cleanup(Authctxt *authctxt) 737agent_sign_cb(Authctxt *authctxt, Key *key, u_char **sigp, u_int *lenp,
738 u_char *data, u_int datalen)
739{
740 return ssh_agent_sign(authctxt->agent, key, sigp, lenp, data, datalen);
741}
742
743static int
744key_sign_cb(Authctxt *authctxt, Key *key, u_char **sigp, u_int *lenp,
745 u_char *data, u_int datalen)
1058{ 746{
1059 Identity *id; 747 return key_sign(key, sigp, lenp, data, datalen);
1060 748}
1061 if (authctxt->agent != NULL) 749
1062 ssh_close_authentication_connection(authctxt->agent); 750static int
1063 for (id = TAILQ_FIRST(&authctxt->keys); id; 751userauth_pubkey_agent(Authctxt *authctxt)
1064 id = TAILQ_FIRST(&authctxt->keys)) { 752{
1065 TAILQ_REMOVE(&authctxt->keys, id, next); 753 static int called = 0;
1066 if (id->key) 754 int ret = 0;
1067 key_free(id->key); 755 char *comment;
1068 if (id->filename) 756 Key *k;
1069 xfree(id->filename); 757
1070 xfree(id); 758 if (called == 0) {
759 if (ssh_get_num_identities(authctxt->agent, 2) == 0)
760 debug2("userauth_pubkey_agent: no keys at all");
761 called = 1;
762 }
763 k = ssh_get_next_identity(authctxt->agent, &comment, 2);
764 if (k == NULL) {
765 debug2("userauth_pubkey_agent: no more keys");
766 } else {
767 debug("Offering agent key: %s", comment);
768 xfree(comment);
769 ret = send_pubkey_test(authctxt, k, agent_sign_cb, -1);
770 if (ret == 0)
771 key_free(k);
1071 } 772 }
773 if (ret == 0)
774 debug2("userauth_pubkey_agent: no message sent");
775 return ret;
1072} 776}
1073 777
1074int 778int
1075userauth_pubkey(Authctxt *authctxt) 779userauth_pubkey(Authctxt *authctxt)
1076{ 780{
1077 Identity *id; 781 static int idx = 0;
1078 int sent = 0; 782 int sent = 0;
783 Key *key;
784 char *filename;
1079 785
1080 while ((id = TAILQ_FIRST(&authctxt->keys))) { 786 if (authctxt->agent != NULL) {
1081 if (id->tried++) 787 do {
1082 return (0); 788 sent = userauth_pubkey_agent(authctxt);
1083 TAILQ_REMOVE(&authctxt->keys, id, next); 789 } while (!sent && authctxt->agent->howmany > 0);
1084 TAILQ_INSERT_TAIL(&authctxt->keys, id, next); 790 }
1085 /* 791 while (!sent && idx < options.num_identity_files) {
1086 * send a test message if we have the public key. for 792 key = options.identity_keys[idx];
1087 * encrypted keys we cannot do this and have to load the 793 filename = options.identity_files[idx];
1088 * private key instead 794 if (key == NULL) {
1089 */ 795 debug("Trying private key: %s", filename);
1090 if (id->key && id->key->type != KEY_RSA1) { 796 key = load_identity_file(filename);
1091 debug("Offering public key: %s", id->filename); 797 if (key != NULL) {
1092 sent = send_pubkey_test(authctxt, id); 798 sent = sign_and_send_pubkey(authctxt, key,
1093 } else if (id->key == NULL) { 799 key_sign_cb);
1094 debug("Trying private key: %s", id->filename); 800 key_free(key);
1095 id->key = load_identity_file(id->filename);
1096 if (id->key != NULL) {
1097 id->isprivate = 1;
1098 sent = sign_and_send_pubkey(authctxt, id);
1099 key_free(id->key);
1100 id->key = NULL;
1101 } 801 }
802 } else if (key->type != KEY_RSA1) {
803 debug("Offering public key: %s", filename);
804 sent = send_pubkey_test(authctxt, key,
805 identity_sign_cb, idx);
1102 } 806 }
1103 if (sent) 807 idx++;
1104 return (sent);
1105 } 808 }
1106 return (0); 809 return sent;
1107} 810}
1108 811
1109/* 812/*
@@ -1159,9 +862,9 @@ input_userauth_info_req(int type, u_int32_t seq, void *ctxt)
1159 inst = packet_get_string(NULL); 862 inst = packet_get_string(NULL);
1160 lang = packet_get_string(NULL); 863 lang = packet_get_string(NULL);
1161 if (strlen(name) > 0) 864 if (strlen(name) > 0)
1162 logit("%s", name); 865 log("%s", name);
1163 if (strlen(inst) > 0) 866 if (strlen(inst) > 0)
1164 logit("%s", inst); 867 log("%s", inst);
1165 xfree(name); 868 xfree(name);
1166 xfree(inst); 869 xfree(inst);
1167 xfree(lang); 870 xfree(lang);