summaryrefslogtreecommitdiff
path: root/sshconnect2.c
diff options
context:
space:
mode:
Diffstat (limited to 'sshconnect2.c')
-rw-r--r--sshconnect2.c185
1 files changed, 102 insertions, 83 deletions
diff --git a/sshconnect2.c b/sshconnect2.c
index 933c223ec..3a218113c 100644
--- a/sshconnect2.c
+++ b/sshconnect2.c
@@ -23,7 +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.134 2004/01/19 21:25:15 markus Exp $");
27 27
28#include "openbsd-compat/sys-queue.h" 28#include "openbsd-compat/sys-queue.h"
29 29
@@ -222,7 +222,7 @@ static char *authmethods_get(void);
222 222
223Authmethod authmethods[] = { 223Authmethod authmethods[] = {
224#ifdef GSSAPI 224#ifdef GSSAPI
225 {"gssapi", 225 {"gssapi-with-mic",
226 userauth_gssapi, 226 userauth_gssapi,
227 &options.gss_authentication, 227 &options.gss_authentication,
228 NULL}, 228 NULL},
@@ -358,10 +358,12 @@ void
358input_userauth_banner(int type, u_int32_t seq, void *ctxt) 358input_userauth_banner(int type, u_int32_t seq, void *ctxt)
359{ 359{
360 char *msg, *lang; 360 char *msg, *lang;
361
361 debug3("input_userauth_banner"); 362 debug3("input_userauth_banner");
362 msg = packet_get_string(NULL); 363 msg = packet_get_string(NULL);
363 lang = packet_get_string(NULL); 364 lang = packet_get_string(NULL);
364 logit("%s", msg); 365 if (options.log_level > SYSLOG_LEVEL_QUIET)
366 fprintf(stderr, "%s", msg);
365 xfree(msg); 367 xfree(msg);
366 xfree(lang); 368 xfree(lang);
367} 369}
@@ -372,10 +374,14 @@ input_userauth_success(int type, u_int32_t seq, void *ctxt)
372 Authctxt *authctxt = ctxt; 374 Authctxt *authctxt = ctxt;
373 if (authctxt == NULL) 375 if (authctxt == NULL)
374 fatal("input_userauth_success: no authentication context"); 376 fatal("input_userauth_success: no authentication context");
375 if (authctxt->authlist) 377 if (authctxt->authlist) {
376 xfree(authctxt->authlist); 378 xfree(authctxt->authlist);
377 if (authctxt->methoddata) 379 authctxt->authlist = NULL;
380 }
381 if (authctxt->methoddata) {
378 xfree(authctxt->methoddata); 382 xfree(authctxt->methoddata);
383 authctxt->methoddata = NULL;
384 }
379 authctxt->success = 1; /* break out */ 385 authctxt->success = 1; /* break out */
380} 386}
381 387
@@ -447,7 +453,12 @@ input_userauth_pk_ok(int type, u_int32_t seq, void *ctxt)
447 debug2("input_userauth_pk_ok: fp %s", fp); 453 debug2("input_userauth_pk_ok: fp %s", fp);
448 xfree(fp); 454 xfree(fp);
449 455
450 TAILQ_FOREACH(id, &authctxt->keys, next) { 456 /*
457 * search keys in the reverse order, because last candidate has been
458 * moved to the end of the queue. this also avoids confusion by
459 * duplicate keys
460 */
461 TAILQ_FOREACH_REVERSE(id, &authctxt->keys, next, idlist) {
451 if (key_equal(key, id->key)) { 462 if (key_equal(key, id->key)) {
452 sent = sign_and_send_pubkey(authctxt, id); 463 sent = sign_and_send_pubkey(authctxt, id);
453 break; 464 break;
@@ -465,11 +476,11 @@ done:
465} 476}
466 477
467#ifdef GSSAPI 478#ifdef GSSAPI
468int 479int
469userauth_gssapi(Authctxt *authctxt) 480userauth_gssapi(Authctxt *authctxt)
470{ 481{
471 Gssctxt *gssctxt = NULL; 482 Gssctxt *gssctxt = NULL;
472 static gss_OID_set supported = NULL; 483 static gss_OID_set gss_supported = NULL;
473 static int mech = 0; 484 static int mech = 0;
474 OM_uint32 min; 485 OM_uint32 min;
475 int ok = 0; 486 int ok = 0;
@@ -477,18 +488,18 @@ userauth_gssapi(Authctxt *authctxt)
477 /* Try one GSSAPI method at a time, rather than sending them all at 488 /* Try one GSSAPI method at a time, rather than sending them all at
478 * once. */ 489 * once. */
479 490
480 if (supported == NULL) 491 if (gss_supported == NULL)
481 gss_indicate_mechs(&min, &supported); 492 gss_indicate_mechs(&min, &gss_supported);
482 493
483 /* Check to see if the mechanism is usable before we offer it */ 494 /* Check to see if the mechanism is usable before we offer it */
484 while (mech<supported->count && !ok) { 495 while (mech < gss_supported->count && !ok) {
485 if (gssctxt) 496 if (gssctxt)
486 ssh_gssapi_delete_ctx(&gssctxt); 497 ssh_gssapi_delete_ctx(&gssctxt);
487 ssh_gssapi_build_ctx(&gssctxt); 498 ssh_gssapi_build_ctx(&gssctxt);
488 ssh_gssapi_set_oid(gssctxt, &supported->elements[mech]); 499 ssh_gssapi_set_oid(gssctxt, &gss_supported->elements[mech]);
489 500
490 /* My DER encoding requires length<128 */ 501 /* My DER encoding requires length<128 */
491 if (supported->elements[mech].length < 128 && 502 if (gss_supported->elements[mech].length < 128 &&
492 !GSS_ERROR(ssh_gssapi_import_name(gssctxt, 503 !GSS_ERROR(ssh_gssapi_import_name(gssctxt,
493 authctxt->host))) { 504 authctxt->host))) {
494 ok = 1; /* Mechanism works */ 505 ok = 1; /* Mechanism works */
@@ -508,17 +519,11 @@ userauth_gssapi(Authctxt *authctxt)
508 519
509 packet_put_int(1); 520 packet_put_int(1);
510 521
511 /* Some servers encode the OID incorrectly (as we used to) */ 522 packet_put_int((gss_supported->elements[mech].length) + 2);
512 if (datafellows & SSH_BUG_GSSAPI_BER) { 523 packet_put_char(SSH_GSS_OIDTYPE);
513 packet_put_string(supported->elements[mech].elements, 524 packet_put_char(gss_supported->elements[mech].length);
514 supported->elements[mech].length); 525 packet_put_raw(gss_supported->elements[mech].elements,
515 } else { 526 gss_supported->elements[mech].length);
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 527
523 packet_send(); 528 packet_send();
524 529
@@ -532,15 +537,66 @@ userauth_gssapi(Authctxt *authctxt)
532 return 1; 537 return 1;
533} 538}
534 539
540static OM_uint32
541process_gssapi_token(void *ctxt, gss_buffer_t recv_tok)
542{
543 Authctxt *authctxt = ctxt;
544 Gssctxt *gssctxt = authctxt->methoddata;
545 gss_buffer_desc send_tok = GSS_C_EMPTY_BUFFER;
546 gss_buffer_desc gssbuf, mic;
547 OM_uint32 status, ms, flags;
548 Buffer b;
549
550 status = ssh_gssapi_init_ctx(gssctxt, options.gss_deleg_creds,
551 recv_tok, &send_tok, &flags);
552
553 if (send_tok.length > 0) {
554 if (GSS_ERROR(status))
555 packet_start(SSH2_MSG_USERAUTH_GSSAPI_ERRTOK);
556 else
557 packet_start(SSH2_MSG_USERAUTH_GSSAPI_TOKEN);
558
559 packet_put_string(send_tok.value, send_tok.length);
560 packet_send();
561 gss_release_buffer(&ms, &send_tok);
562 }
563
564 if (status == GSS_S_COMPLETE) {
565 /* send either complete or MIC, depending on mechanism */
566 if (!(flags & GSS_C_INTEG_FLAG)) {
567 packet_start(SSH2_MSG_USERAUTH_GSSAPI_EXCHANGE_COMPLETE);
568 packet_send();
569 } else {
570 ssh_gssapi_buildmic(&b, authctxt->server_user,
571 authctxt->service, "gssapi-with-mic");
572
573 gssbuf.value = buffer_ptr(&b);
574 gssbuf.length = buffer_len(&b);
575
576 status = ssh_gssapi_sign(gssctxt, &gssbuf, &mic);
577
578 if (!GSS_ERROR(status)) {
579 packet_start(SSH2_MSG_USERAUTH_GSSAPI_MIC);
580 packet_put_string(mic.value, mic.length);
581
582 packet_send();
583 }
584
585 buffer_free(&b);
586 gss_release_buffer(&ms, &mic);
587 }
588 }
589
590 return status;
591}
592
535void 593void
536input_gssapi_response(int type, u_int32_t plen, void *ctxt) 594input_gssapi_response(int type, u_int32_t plen, void *ctxt)
537{ 595{
538 Authctxt *authctxt = ctxt; 596 Authctxt *authctxt = ctxt;
539 Gssctxt *gssctxt; 597 Gssctxt *gssctxt;
540 OM_uint32 status, ms;
541 int oidlen; 598 int oidlen;
542 char *oidv; 599 char *oidv;
543 gss_buffer_desc send_tok = GSS_C_EMPTY_BUFFER;
544 600
545 if (authctxt == NULL) 601 if (authctxt == NULL)
546 fatal("input_gssapi_response: no authentication context"); 602 fatal("input_gssapi_response: no authentication context");
@@ -549,94 +605,55 @@ input_gssapi_response(int type, u_int32_t plen, void *ctxt)
549 /* Setup our OID */ 605 /* Setup our OID */
550 oidv = packet_get_string(&oidlen); 606 oidv = packet_get_string(&oidlen);
551 607
552 if (datafellows & SSH_BUG_GSSAPI_BER) { 608 if (oidlen <= 2 ||
553 if (!ssh_gssapi_check_oid(gssctxt, oidv, oidlen)) 609 oidv[0] != SSH_GSS_OIDTYPE ||
554 fatal("Server returned different OID than expected"); 610 oidv[1] != oidlen - 2) {
555 } else { 611 xfree(oidv);
556 if(oidv[0] != SSH_GSS_OIDTYPE || oidv[1] != oidlen-2) { 612 debug("Badly encoded mechanism OID received");
557 debug("Badly encoded mechanism OID received"); 613 userauth(authctxt, NULL);
558 userauth(authctxt, NULL); 614 return;
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 } 615 }
565 616
617 if (!ssh_gssapi_check_oid(gssctxt, oidv + 2, oidlen - 2))
618 fatal("Server returned different OID than expected");
619
566 packet_check_eom(); 620 packet_check_eom();
567 621
568 xfree(oidv); 622 xfree(oidv);
569 623
570 status = ssh_gssapi_init_ctx(gssctxt, options.gss_deleg_creds, 624 if (GSS_ERROR(process_gssapi_token(ctxt, GSS_C_NO_BUFFER))) {
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 */ 625 /* Start again with next method on list */
580 debug("Trying to start again"); 626 debug("Trying to start again");
581 userauth(authctxt, NULL); 627 userauth(authctxt, NULL);
582 return; 628 return;
583 } 629 }
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} 630}
591 631
592void 632void
593input_gssapi_token(int type, u_int32_t plen, void *ctxt) 633input_gssapi_token(int type, u_int32_t plen, void *ctxt)
594{ 634{
595 Authctxt *authctxt = ctxt; 635 Authctxt *authctxt = ctxt;
596 Gssctxt *gssctxt;
597 gss_buffer_desc send_tok = GSS_C_EMPTY_BUFFER;
598 gss_buffer_desc recv_tok; 636 gss_buffer_desc recv_tok;
599 OM_uint32 status, ms; 637 OM_uint32 status;
600 u_int slen; 638 u_int slen;
601 639
602 if (authctxt == NULL) 640 if (authctxt == NULL)
603 fatal("input_gssapi_response: no authentication context"); 641 fatal("input_gssapi_response: no authentication context");
604 gssctxt = authctxt->methoddata;
605 642
606 recv_tok.value = packet_get_string(&slen); 643 recv_tok.value = packet_get_string(&slen);
607 recv_tok.length = slen; /* safe typecast */ 644 recv_tok.length = slen; /* safe typecast */
608 645
609 packet_check_eom(); 646 packet_check_eom();
610 647
611 status=ssh_gssapi_init_ctx(gssctxt, options.gss_deleg_creds, 648 status = process_gssapi_token(ctxt, &recv_tok);
612 &recv_tok, &send_tok, NULL);
613 649
614 xfree(recv_tok.value); 650 xfree(recv_tok.value);
615 651
616 if (GSS_ERROR(status)) { 652 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 */ 653 /* Start again with the next method in the list */
624 userauth(authctxt, NULL); 654 userauth(authctxt, NULL);
625 return; 655 return;
626 } 656 }
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} 657}
641 658
642void 659void
@@ -1016,7 +1033,7 @@ pubkey_prepare(Authctxt *authctxt)
1016 key = ssh_get_next_identity(ac, &comment, 2)) { 1033 key = ssh_get_next_identity(ac, &comment, 2)) {
1017 found = 0; 1034 found = 0;
1018 TAILQ_FOREACH(id, &files, next) { 1035 TAILQ_FOREACH(id, &files, next) {
1019 /* agent keys from the config file are preferred */ 1036 /* agent keys from the config file are preferred */
1020 if (key_equal(key, id->key)) { 1037 if (key_equal(key, id->key)) {
1021 key_free(key); 1038 key_free(key);
1022 xfree(comment); 1039 xfree(comment);
@@ -1080,6 +1097,7 @@ userauth_pubkey(Authctxt *authctxt)
1080 while ((id = TAILQ_FIRST(&authctxt->keys))) { 1097 while ((id = TAILQ_FIRST(&authctxt->keys))) {
1081 if (id->tried++) 1098 if (id->tried++)
1082 return (0); 1099 return (0);
1100 /* move key to the end of the queue */
1083 TAILQ_REMOVE(&authctxt->keys, id, next); 1101 TAILQ_REMOVE(&authctxt->keys, id, next);
1084 TAILQ_INSERT_TAIL(&authctxt->keys, id, next); 1102 TAILQ_INSERT_TAIL(&authctxt->keys, id, next);
1085 /* 1103 /*
@@ -1244,11 +1262,12 @@ ssh_keysign(Key *key, u_char **sigp, u_int *lenp,
1244 buffer_init(&b); 1262 buffer_init(&b);
1245 buffer_put_int(&b, packet_get_connection_in()); /* send # of socket */ 1263 buffer_put_int(&b, packet_get_connection_in()); /* send # of socket */
1246 buffer_put_string(&b, data, datalen); 1264 buffer_put_string(&b, data, datalen);
1247 ssh_msg_send(to[1], version, &b); 1265 if (ssh_msg_send(to[1], version, &b) == -1)
1266 fatal("ssh_keysign: couldn't send request");
1248 1267
1249 if (ssh_msg_recv(from[0], &b) < 0) { 1268 if (ssh_msg_recv(from[0], &b) < 0) {
1250 error("ssh_keysign: no reply"); 1269 error("ssh_keysign: no reply");
1251 buffer_clear(&b); 1270 buffer_free(&b);
1252 return -1; 1271 return -1;
1253 } 1272 }
1254 close(from[0]); 1273 close(from[0]);
@@ -1260,11 +1279,11 @@ ssh_keysign(Key *key, u_char **sigp, u_int *lenp,
1260 1279
1261 if (buffer_get_char(&b) != version) { 1280 if (buffer_get_char(&b) != version) {
1262 error("ssh_keysign: bad version"); 1281 error("ssh_keysign: bad version");
1263 buffer_clear(&b); 1282 buffer_free(&b);
1264 return -1; 1283 return -1;
1265 } 1284 }
1266 *sigp = buffer_get_string(&b, lenp); 1285 *sigp = buffer_get_string(&b, lenp);
1267 buffer_clear(&b); 1286 buffer_free(&b);
1268 1287
1269 return 0; 1288 return 0;
1270} 1289}