summaryrefslogtreecommitdiff
path: root/sshconnect2.c
diff options
context:
space:
mode:
Diffstat (limited to 'sshconnect2.c')
-rw-r--r--sshconnect2.c625
1 files changed, 461 insertions, 164 deletions
diff --git a/sshconnect2.c b/sshconnect2.c
index 642b34b9e..933c223ec 100644
--- a/sshconnect2.c
+++ b/sshconnect2.c
@@ -23,7 +23,9 @@
23 */ 23 */
24 24
25#include "includes.h" 25#include "includes.h"
26RCSID("$OpenBSD: sshconnect2.c,v 1.114 2003/04/01 10:22:21 markus Exp $"); 26RCSID("$OpenBSD: sshconnect2.c,v 1.124 2003/08/25 10:33:33 djm Exp $");
27
28#include "openbsd-compat/sys-queue.h"
27 29
28#include "ssh.h" 30#include "ssh.h"
29#include "ssh2.h" 31#include "ssh2.h"
@@ -48,6 +50,10 @@ RCSID("$OpenBSD: sshconnect2.c,v 1.114 2003/04/01 10:22:21 markus Exp $");
48#include "msg.h" 50#include "msg.h"
49#include "pathnames.h" 51#include "pathnames.h"
50 52
53#ifdef GSSAPI
54#include "ssh-gss.h"
55#endif
56
51/* import */ 57/* import */
52extern char *client_version_string; 58extern char *client_version_string;
53extern char *server_version_string; 59extern char *server_version_string;
@@ -58,7 +64,7 @@ extern Options options;
58 */ 64 */
59 65
60u_char *session_id2 = NULL; 66u_char *session_id2 = NULL;
61int session_id2_len = 0; 67u_int session_id2_len = 0;
62 68
63char *xxx_host; 69char *xxx_host;
64struct sockaddr *xxx_hostaddr; 70struct sockaddr *xxx_hostaddr;
@@ -82,7 +88,7 @@ ssh_kex2(char *host, struct sockaddr *hostaddr)
82 xxx_hostaddr = hostaddr; 88 xxx_hostaddr = hostaddr;
83 89
84 if (options.ciphers == (char *)-1) { 90 if (options.ciphers == (char *)-1) {
85 log("No valid ciphers for protocol version 2 given, using defaults."); 91 logit("No valid ciphers for protocol version 2 given, using defaults.");
86 options.ciphers = NULL; 92 options.ciphers = NULL;
87 } 93 }
88 if (options.ciphers != NULL) { 94 if (options.ciphers != NULL) {
@@ -108,6 +114,9 @@ ssh_kex2(char *host, struct sockaddr *hostaddr)
108 myproposal[PROPOSAL_SERVER_HOST_KEY_ALGS] = 114 myproposal[PROPOSAL_SERVER_HOST_KEY_ALGS] =
109 options.hostkeyalgorithms; 115 options.hostkeyalgorithms;
110 116
117 if (options.rekey_limit)
118 packet_set_rekey_limit(options.rekey_limit);
119
111 /* start key exchange */ 120 /* start key exchange */
112 kex = kex_setup(myproposal); 121 kex = kex_setup(myproposal);
113 kex->kex[KEX_DH_GRP1_SHA1] = kexdh_client; 122 kex->kex[KEX_DH_GRP1_SHA1] = kexdh_client;
@@ -138,10 +147,18 @@ ssh_kex2(char *host, struct sockaddr *hostaddr)
138 147
139typedef struct Authctxt Authctxt; 148typedef struct Authctxt Authctxt;
140typedef struct Authmethod Authmethod; 149typedef struct Authmethod Authmethod;
141 150typedef struct identity Identity;
142typedef int sign_cb_fn( 151typedef struct idlist Idlist;
143 Authctxt *authctxt, Key *key, 152
144 u_char **sigp, u_int *lenp, u_char *data, u_int datalen); 153struct identity {
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);
145 162
146struct Authctxt { 163struct Authctxt {
147 const char *server_user; 164 const char *server_user;
@@ -152,14 +169,14 @@ struct Authctxt {
152 int success; 169 int success;
153 char *authlist; 170 char *authlist;
154 /* pubkey */ 171 /* pubkey */
155 Key *last_key; 172 Idlist keys;
156 sign_cb_fn *last_key_sign;
157 int last_key_hint;
158 AuthenticationConnection *agent; 173 AuthenticationConnection *agent;
159 /* hostbased */ 174 /* hostbased */
160 Sensitive *sensitive; 175 Sensitive *sensitive;
161 /* kbd-interactive */ 176 /* kbd-interactive */
162 int info_req_seen; 177 int info_req_seen;
178 /* generic */
179 void *methoddata;
163}; 180};
164struct Authmethod { 181struct Authmethod {
165 char *name; /* string to compare against server's list */ 182 char *name; /* string to compare against server's list */
@@ -181,17 +198,35 @@ int userauth_pubkey(Authctxt *);
181int userauth_passwd(Authctxt *); 198int userauth_passwd(Authctxt *);
182int userauth_kbdint(Authctxt *); 199int userauth_kbdint(Authctxt *);
183int userauth_hostbased(Authctxt *); 200int 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
184 211
185void userauth(Authctxt *, char *); 212void userauth(Authctxt *, char *);
186 213
187static int sign_and_send_pubkey(Authctxt *, Key *, sign_cb_fn *); 214static int sign_and_send_pubkey(Authctxt *, Identity *);
188static void clear_auth_state(Authctxt *); 215static void pubkey_prepare(Authctxt *);
216static void pubkey_cleanup(Authctxt *);
217static Key *load_identity_file(char *);
189 218
190static Authmethod *authmethod_get(char *authlist); 219static Authmethod *authmethod_get(char *authlist);
191static Authmethod *authmethod_lookup(const char *name); 220static Authmethod *authmethod_lookup(const char *name);
192static char *authmethods_get(void); 221static char *authmethods_get(void);
193 222
194Authmethod authmethods[] = { 223Authmethod authmethods[] = {
224#ifdef GSSAPI
225 {"gssapi",
226 userauth_gssapi,
227 &options.gss_authentication,
228 NULL},
229#endif
195 {"hostbased", 230 {"hostbased",
196 userauth_hostbased, 231 userauth_hostbased,
197 &options.hostbased_authentication, 232 &options.hostbased_authentication,
@@ -248,7 +283,7 @@ ssh_userauth2(const char *local_user, const char *server_user, char *host,
248 283
249 /* setup authentication context */ 284 /* setup authentication context */
250 memset(&authctxt, 0, sizeof(authctxt)); 285 memset(&authctxt, 0, sizeof(authctxt));
251 authctxt.agent = ssh_get_authentication_connection(); 286 pubkey_prepare(&authctxt);
252 authctxt.server_user = server_user; 287 authctxt.server_user = server_user;
253 authctxt.local_user = local_user; 288 authctxt.local_user = local_user;
254 authctxt.host = host; 289 authctxt.host = host;
@@ -256,6 +291,7 @@ ssh_userauth2(const char *local_user, const char *server_user, char *host,
256 authctxt.success = 0; 291 authctxt.success = 0;
257 authctxt.method = authmethod_lookup("none"); 292 authctxt.method = authmethod_lookup("none");
258 authctxt.authlist = NULL; 293 authctxt.authlist = NULL;
294 authctxt.methoddata = NULL;
259 authctxt.sensitive = sensitive; 295 authctxt.sensitive = sensitive;
260 authctxt.info_req_seen = 0; 296 authctxt.info_req_seen = 0;
261 if (authctxt.method == NULL) 297 if (authctxt.method == NULL)
@@ -270,14 +306,19 @@ ssh_userauth2(const char *local_user, const char *server_user, char *host,
270 dispatch_set(SSH2_MSG_USERAUTH_BANNER, &input_userauth_banner); 306 dispatch_set(SSH2_MSG_USERAUTH_BANNER, &input_userauth_banner);
271 dispatch_run(DISPATCH_BLOCK, &authctxt.success, &authctxt); /* loop until success */ 307 dispatch_run(DISPATCH_BLOCK, &authctxt.success, &authctxt); /* loop until success */
272 308
273 if (authctxt.agent != NULL) 309 pubkey_cleanup(&authctxt);
274 ssh_close_authentication_connection(authctxt.agent); 310 dispatch_range(SSH2_MSG_USERAUTH_MIN, SSH2_MSG_USERAUTH_MAX, NULL);
275 311
276 debug("Authentication succeeded (%s).", authctxt.method->name); 312 debug("Authentication succeeded (%s).", authctxt.method->name);
277} 313}
314
278void 315void
279userauth(Authctxt *authctxt, char *authlist) 316userauth(Authctxt *authctxt, char *authlist)
280{ 317{
318 if (authctxt->methoddata) {
319 xfree(authctxt->methoddata);
320 authctxt->methoddata = NULL;
321 }
281 if (authlist == NULL) { 322 if (authlist == NULL) {
282 authlist = authctxt->authlist; 323 authlist = authctxt->authlist;
283 } else { 324 } else {
@@ -290,6 +331,12 @@ userauth(Authctxt *authctxt, char *authlist)
290 if (method == NULL) 331 if (method == NULL)
291 fatal("Permission denied (%s).", authlist); 332 fatal("Permission denied (%s).", authlist);
292 authctxt->method = method; 333 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 */
293 if (method->userauth(authctxt) != 0) { 340 if (method->userauth(authctxt) != 0) {
294 debug2("we sent a %s packet, wait for reply", method->name); 341 debug2("we sent a %s packet, wait for reply", method->name);
295 break; 342 break;
@@ -314,7 +361,7 @@ input_userauth_banner(int type, u_int32_t seq, void *ctxt)
314 debug3("input_userauth_banner"); 361 debug3("input_userauth_banner");
315 msg = packet_get_string(NULL); 362 msg = packet_get_string(NULL);
316 lang = packet_get_string(NULL); 363 lang = packet_get_string(NULL);
317 fprintf(stderr, "%s", msg); 364 logit("%s", msg);
318 xfree(msg); 365 xfree(msg);
319 xfree(lang); 366 xfree(lang);
320} 367}
@@ -327,7 +374,8 @@ input_userauth_success(int type, u_int32_t seq, void *ctxt)
327 fatal("input_userauth_success: no authentication context"); 374 fatal("input_userauth_success: no authentication context");
328 if (authctxt->authlist) 375 if (authctxt->authlist)
329 xfree(authctxt->authlist); 376 xfree(authctxt->authlist);
330 clear_auth_state(authctxt); 377 if (authctxt->methoddata)
378 xfree(authctxt->methoddata);
331 authctxt->success = 1; /* break out */ 379 authctxt->success = 1; /* break out */
332} 380}
333 381
@@ -346,10 +394,9 @@ input_userauth_failure(int type, u_int32_t seq, void *ctxt)
346 packet_check_eom(); 394 packet_check_eom();
347 395
348 if (partial != 0) 396 if (partial != 0)
349 log("Authenticated with partial success."); 397 logit("Authenticated with partial success.");
350 debug("Authentications that can continue: %s", authlist); 398 debug("Authentications that can continue: %s", authlist);
351 399
352 clear_auth_state(authctxt);
353 userauth(authctxt, authlist); 400 userauth(authctxt, authlist);
354} 401}
355void 402void
@@ -357,6 +404,7 @@ input_userauth_pk_ok(int type, u_int32_t seq, void *ctxt)
357{ 404{
358 Authctxt *authctxt = ctxt; 405 Authctxt *authctxt = ctxt;
359 Key *key = NULL; 406 Key *key = NULL;
407 Identity *id = NULL;
360 Buffer b; 408 Buffer b;
361 int pktype, sent = 0; 409 int pktype, sent = 0;
362 u_int alen, blen; 410 u_int alen, blen;
@@ -379,55 +427,267 @@ input_userauth_pk_ok(int type, u_int32_t seq, void *ctxt)
379 } 427 }
380 packet_check_eom(); 428 packet_check_eom();
381 429
382 debug("Server accepts key: pkalg %s blen %u lastkey %p hint %d", 430 debug("Server accepts key: pkalg %s blen %u", pkalg, blen);
383 pkalg, blen, authctxt->last_key, authctxt->last_key_hint);
384 431
385 do { 432 if ((pktype = key_type_from_name(pkalg)) == KEY_UNSPEC) {
386 if (authctxt->last_key == NULL || 433 debug("unknown pkalg %s", pkalg);
387 authctxt->last_key_sign == NULL) { 434 goto done;
388 debug("no last key or no sign cb"); 435 }
389 break; 436 if ((key = key_from_blob(pkblob, blen)) == NULL) {
390 } 437 debug("no key from blob. pkalg %s", pkalg);
391 if ((pktype = key_type_from_name(pkalg)) == KEY_UNSPEC) { 438 goto done;
392 debug("unknown pkalg %s", pkalg); 439 }
393 break; 440 if (key->type != pktype) {
394 } 441 error("input_userauth_pk_ok: type mismatch "
395 if ((key = key_from_blob(pkblob, blen)) == NULL) { 442 "for decoded key (received %d, expected %d)",
396 debug("no key from blob. pkalg %s", pkalg); 443 key->type, pktype);
397 break; 444 goto done;
398 } 445 }
399 if (key->type != pktype) { 446 fp = key_fingerprint(key, SSH_FP_MD5, SSH_FP_HEX);
400 error("input_userauth_pk_ok: type mismatch " 447 debug2("input_userauth_pk_ok: fp %s", fp);
401 "for decoded key (received %d, expected %d)", 448 xfree(fp);
402 key->type, pktype); 449
403 break; 450 TAILQ_FOREACH(id, &authctxt->keys, next) {
404 } 451 if (key_equal(key, id->key)) {
405 fp = key_fingerprint(key, SSH_FP_MD5, SSH_FP_HEX); 452 sent = sign_and_send_pubkey(authctxt, id);
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; 453 break;
411 } 454 }
412 sent = sign_and_send_pubkey(authctxt, key, 455 }
413 authctxt->last_key_sign); 456done:
414 } while (0);
415
416 if (key != NULL) 457 if (key != NULL)
417 key_free(key); 458 key_free(key);
418 xfree(pkalg); 459 xfree(pkalg);
419 xfree(pkblob); 460 xfree(pkblob);
420 461
421 /* unregister */
422 clear_auth_state(authctxt);
423 dispatch_set(SSH2_MSG_USERAUTH_PK_OK, NULL);
424
425 /* try another method if we did not send a packet */ 462 /* try another method if we did not send a packet */
426 if (sent == 0) 463 if (sent == 0)
427 userauth(authctxt, NULL); 464 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);
428 508
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);
429} 590}
430 591
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
431int 691int
432userauth_none(Authctxt *authctxt) 692userauth_none(Authctxt *authctxt)
433{ 693{
@@ -491,7 +751,7 @@ input_userauth_passwd_changereq(int type, u_int32_t seqnr, void *ctxt)
491 info = packet_get_string(NULL); 751 info = packet_get_string(NULL);
492 lang = packet_get_string(NULL); 752 lang = packet_get_string(NULL);
493 if (strlen(info) > 0) 753 if (strlen(info) > 0)
494 log("%s", info); 754 logit("%s", info);
495 xfree(info); 755 xfree(info);
496 xfree(lang); 756 xfree(lang);
497 packet_start(SSH2_MSG_USERAUTH_REQUEST); 757 packet_start(SSH2_MSG_USERAUTH_REQUEST);
@@ -523,7 +783,7 @@ input_userauth_passwd_changereq(int type, u_int32_t seqnr, void *ctxt)
523 if (strcmp(password, retype) != 0) { 783 if (strcmp(password, retype) != 0) {
524 memset(password, 0, strlen(password)); 784 memset(password, 0, strlen(password));
525 xfree(password); 785 xfree(password);
526 log("Mismatch; try again, EOF to quit."); 786 logit("Mismatch; try again, EOF to quit.");
527 password = NULL; 787 password = NULL;
528 } 788 }
529 memset(retype, 0, strlen(retype)); 789 memset(retype, 0, strlen(retype));
@@ -539,34 +799,44 @@ input_userauth_passwd_changereq(int type, u_int32_t seqnr, void *ctxt)
539 &input_userauth_passwd_changereq); 799 &input_userauth_passwd_changereq);
540} 800}
541 801
542static void 802static int
543clear_auth_state(Authctxt *authctxt) 803identity_sign(Identity *id, u_char **sigp, u_int *lenp,
804 u_char *data, u_int datalen)
544{ 805{
545 /* XXX clear authentication state */ 806 Key *prv;
546 dispatch_set(SSH2_MSG_USERAUTH_PASSWD_CHANGEREQ, NULL); 807 int ret;
547 808
548 if (authctxt->last_key != NULL && authctxt->last_key_hint == -1) { 809 /* the agent supports this key */
549 debug3("clear_auth_state: key_free %p", authctxt->last_key); 810 if (id->ac)
550 key_free(authctxt->last_key); 811 return (ssh_agent_sign(id->ac, id->key, sigp, lenp,
551 } 812 data, datalen));
552 authctxt->last_key = NULL; 813 /*
553 authctxt->last_key_hint = -2; 814 * we have already loaded the private key or
554 authctxt->last_key_sign = NULL; 815 * the private key is stored in external hardware
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);
555} 825}
556 826
557static int 827static int
558sign_and_send_pubkey(Authctxt *authctxt, Key *k, sign_cb_fn *sign_callback) 828sign_and_send_pubkey(Authctxt *authctxt, Identity *id)
559{ 829{
560 Buffer b; 830 Buffer b;
561 u_char *blob, *signature; 831 u_char *blob, *signature;
562 u_int bloblen, slen; 832 u_int bloblen, slen;
563 int skip = 0; 833 u_int skip = 0;
564 int ret = -1; 834 int ret = -1;
565 int have_sig = 1; 835 int have_sig = 1;
566 836
567 debug3("sign_and_send_pubkey"); 837 debug3("sign_and_send_pubkey");
568 838
569 if (key_to_blob(k, &blob, &bloblen) == 0) { 839 if (key_to_blob(id->key, &blob, &bloblen) == 0) {
570 /* we cannot handle this key */ 840 /* we cannot handle this key */
571 debug3("sign_and_send_pubkey: cannot handle key"); 841 debug3("sign_and_send_pubkey: cannot handle key");
572 return 0; 842 return 0;
@@ -591,12 +861,12 @@ sign_and_send_pubkey(Authctxt *authctxt, Key *k, sign_cb_fn *sign_callback)
591 } else { 861 } else {
592 buffer_put_cstring(&b, authctxt->method->name); 862 buffer_put_cstring(&b, authctxt->method->name);
593 buffer_put_char(&b, have_sig); 863 buffer_put_char(&b, have_sig);
594 buffer_put_cstring(&b, key_ssh_name(k)); 864 buffer_put_cstring(&b, key_ssh_name(id->key));
595 } 865 }
596 buffer_put_string(&b, blob, bloblen); 866 buffer_put_string(&b, blob, bloblen);
597 867
598 /* generate signature */ 868 /* generate signature */
599 ret = (*sign_callback)(authctxt, k, &signature, &slen, 869 ret = identity_sign(id, &signature, &slen,
600 buffer_ptr(&b), buffer_len(&b)); 870 buffer_ptr(&b), buffer_len(&b));
601 if (ret == -1) { 871 if (ret == -1) {
602 xfree(blob); 872 xfree(blob);
@@ -616,7 +886,7 @@ sign_and_send_pubkey(Authctxt *authctxt, Key *k, sign_cb_fn *sign_callback)
616 buffer_put_cstring(&b, authctxt->method->name); 886 buffer_put_cstring(&b, authctxt->method->name);
617 buffer_put_char(&b, have_sig); 887 buffer_put_char(&b, have_sig);
618 if (!(datafellows & SSH_BUG_PKAUTH)) 888 if (!(datafellows & SSH_BUG_PKAUTH))
619 buffer_put_cstring(&b, key_ssh_name(k)); 889 buffer_put_cstring(&b, key_ssh_name(id->key));
620 buffer_put_string(&b, blob, bloblen); 890 buffer_put_string(&b, blob, bloblen);
621 } 891 }
622 xfree(blob); 892 xfree(blob);
@@ -640,23 +910,19 @@ sign_and_send_pubkey(Authctxt *authctxt, Key *k, sign_cb_fn *sign_callback)
640} 910}
641 911
642static int 912static int
643send_pubkey_test(Authctxt *authctxt, Key *k, sign_cb_fn *sign_callback, 913send_pubkey_test(Authctxt *authctxt, Identity *id)
644 int hint)
645{ 914{
646 u_char *blob; 915 u_char *blob;
647 u_int bloblen, have_sig = 0; 916 u_int bloblen, have_sig = 0;
648 917
649 debug3("send_pubkey_test"); 918 debug3("send_pubkey_test");
650 919
651 if (key_to_blob(k, &blob, &bloblen) == 0) { 920 if (key_to_blob(id->key, &blob, &bloblen) == 0) {
652 /* we cannot handle this key */ 921 /* we cannot handle this key */
653 debug3("send_pubkey_test: cannot handle key"); 922 debug3("send_pubkey_test: cannot handle key");
654 return 0; 923 return 0;
655 } 924 }
656 /* register callback for USERAUTH_PK_OK message */ 925 /* 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;
660 dispatch_set(SSH2_MSG_USERAUTH_PK_OK, &input_userauth_pk_ok); 926 dispatch_set(SSH2_MSG_USERAUTH_PK_OK, &input_userauth_pk_ok);
661 927
662 packet_start(SSH2_MSG_USERAUTH_REQUEST); 928 packet_start(SSH2_MSG_USERAUTH_REQUEST);
@@ -665,7 +931,7 @@ send_pubkey_test(Authctxt *authctxt, Key *k, sign_cb_fn *sign_callback,
665 packet_put_cstring(authctxt->method->name); 931 packet_put_cstring(authctxt->method->name);
666 packet_put_char(have_sig); 932 packet_put_char(have_sig);
667 if (!(datafellows & SSH_BUG_PKAUTH)) 933 if (!(datafellows & SSH_BUG_PKAUTH))
668 packet_put_cstring(key_ssh_name(k)); 934 packet_put_cstring(key_ssh_name(id->key));
669 packet_put_string(blob, bloblen); 935 packet_put_string(blob, bloblen);
670 xfree(blob); 936 xfree(blob);
671 packet_send(); 937 packet_send();
@@ -710,103 +976,134 @@ load_identity_file(char *filename)
710 return private; 976 return private;
711} 977}
712 978
713static int 979/*
714identity_sign_cb(Authctxt *authctxt, Key *key, u_char **sigp, u_int *lenp, 980 * try keys in the following order:
715 u_char *data, u_int datalen) 981 * 1. agent keys that are found in the config file
716{ 982 * 2. other agent keys
717 Key *private; 983 * 3. keys that are only listed in the config file
718 int idx, ret; 984 */
719 985static void
720 idx = authctxt->last_key_hint; 986pubkey_prepare(Authctxt *authctxt)
721 if (idx < 0)
722 return -1;
723
724 /* private key is stored in external hardware */
725 if (options.identity_keys[idx]->flags & KEY_FLAG_EXT)
726 return key_sign(options.identity_keys[idx], sigp, lenp, data, datalen);
727
728 private = load_identity_file(options.identity_files[idx]);
729 if (private == NULL)
730 return -1;
731 ret = key_sign(private, sigp, lenp, data, datalen);
732 key_free(private);
733 return ret;
734}
735
736static int
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)
746{ 987{
747 return key_sign(key, sigp, lenp, data, datalen); 988 Identity *id;
989 Idlist agent, files, *preferred;
990 Key *key;
991 AuthenticationConnection *ac;
992 char *comment;
993 int i, found;
994
995 TAILQ_INIT(&agent); /* keys from the agent */
996 TAILQ_INIT(&files); /* keys from the config file */
997 preferred = &authctxt->keys;
998 TAILQ_INIT(preferred); /* preferred order of keys */
999
1000 /* list of keys stored in the filesystem */
1001 for (i = 0; i < options.num_identity_files; i++) {
1002 key = options.identity_keys[i];
1003 if (key && key->type == KEY_RSA1)
1004 continue;
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 }
748} 1054}
749 1055
750static int 1056static void
751userauth_pubkey_agent(Authctxt *authctxt) 1057pubkey_cleanup(Authctxt *authctxt)
752{ 1058{
753 static int called = 0; 1059 Identity *id;
754 int ret = 0; 1060
755 char *comment; 1061 if (authctxt->agent != NULL)
756 Key *k; 1062 ssh_close_authentication_connection(authctxt->agent);
757 1063 for (id = TAILQ_FIRST(&authctxt->keys); id;
758 if (called == 0) { 1064 id = TAILQ_FIRST(&authctxt->keys)) {
759 if (ssh_get_num_identities(authctxt->agent, 2) == 0) 1065 TAILQ_REMOVE(&authctxt->keys, id, next);
760 debug2("userauth_pubkey_agent: no keys at all"); 1066 if (id->key)
761 called = 1; 1067 key_free(id->key);
762 } 1068 if (id->filename)
763 k = ssh_get_next_identity(authctxt->agent, &comment, 2); 1069 xfree(id->filename);
764 if (k == NULL) { 1070 xfree(id);
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);
772 } 1071 }
773 if (ret == 0)
774 debug2("userauth_pubkey_agent: no message sent");
775 return ret;
776} 1072}
777 1073
778int 1074int
779userauth_pubkey(Authctxt *authctxt) 1075userauth_pubkey(Authctxt *authctxt)
780{ 1076{
781 static int idx = 0; 1077 Identity *id;
782 int sent = 0; 1078 int sent = 0;
783 Key *key;
784 char *filename;
785 1079
786 if (authctxt->agent != NULL) { 1080 while ((id = TAILQ_FIRST(&authctxt->keys))) {
787 do { 1081 if (id->tried++)
788 sent = userauth_pubkey_agent(authctxt); 1082 return (0);
789 } while (!sent && authctxt->agent->howmany > 0); 1083 TAILQ_REMOVE(&authctxt->keys, id, next);
790 } 1084 TAILQ_INSERT_TAIL(&authctxt->keys, id, next);
791 while (!sent && idx < options.num_identity_files) { 1085 /*
792 key = options.identity_keys[idx]; 1086 * send a test message if we have the public key. for
793 filename = options.identity_files[idx]; 1087 * encrypted keys we cannot do this and have to load the
794 if (key == NULL) { 1088 * private key instead
795 debug("Trying private key: %s", filename); 1089 */
796 key = load_identity_file(filename); 1090 if (id->key && id->key->type != KEY_RSA1) {
797 if (key != NULL) { 1091 debug("Offering public key: %s", id->filename);
798 sent = sign_and_send_pubkey(authctxt, key, 1092 sent = send_pubkey_test(authctxt, id);
799 key_sign_cb); 1093 } else if (id->key == NULL) {
800 key_free(key); 1094 debug("Trying private key: %s", id->filename);
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;
801 } 1101 }
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);
806 } 1102 }
807 idx++; 1103 if (sent)
1104 return (sent);
808 } 1105 }
809 return sent; 1106 return (0);
810} 1107}
811 1108
812/* 1109/*
@@ -862,9 +1159,9 @@ input_userauth_info_req(int type, u_int32_t seq, void *ctxt)
862 inst = packet_get_string(NULL); 1159 inst = packet_get_string(NULL);
863 lang = packet_get_string(NULL); 1160 lang = packet_get_string(NULL);
864 if (strlen(name) > 0) 1161 if (strlen(name) > 0)
865 log("%s", name); 1162 logit("%s", name);
866 if (strlen(inst) > 0) 1163 if (strlen(inst) > 0)
867 log("%s", inst); 1164 logit("%s", inst);
868 xfree(name); 1165 xfree(name);
869 xfree(inst); 1166 xfree(inst);
870 xfree(lang); 1167 xfree(lang);