1 /* 2 * Copyright (c) 2000 Markus Friedl. All rights reserved. 3 * 4 * Redistribution and use in source and binary forms, with or without 5 * modification, are permitted provided that the following conditions 6 * are met: 7 * 1. Redistributions of source code must retain the above copyright 8 * notice, this list of conditions and the following disclaimer. 9 * 2. Redistributions in binary form must reproduce the above copyright 10 * notice, this list of conditions and the following disclaimer in the 11 * documentation and/or other materials provided with the distribution. 12 * 13 * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR 14 * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES 15 * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. 16 * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, 17 * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT 18 * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, 19 * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY 20 * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT 21 * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF 22 * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 23 */ 24 /* 25 * Copyright 2007 Sun Microsystems, Inc. All rights reserved. 26 * Use is subject to license terms. 27 */ 28 29 #include "includes.h" 30 RCSID("$OpenBSD: sshconnect2.c,v 1.107 2002/07/01 19:48:46 markus Exp $"); 31 32 #pragma ident "%Z%%M% %I% %E% SMI" 33 34 #include "ssh.h" 35 #include "ssh2.h" 36 #include "xmalloc.h" 37 #include "buffer.h" 38 #include "packet.h" 39 #include "compat.h" 40 #include "bufaux.h" 41 #include "cipher.h" 42 #include "kex.h" 43 #include "myproposal.h" 44 #include "sshconnect.h" 45 #include "authfile.h" 46 #include "dh.h" 47 #include "authfd.h" 48 #include "log.h" 49 #include "readconf.h" 50 #include "readpass.h" 51 #include "match.h" 52 #include "dispatch.h" 53 #include "canohost.h" 54 #include "msg.h" 55 #include "pathnames.h" 56 #include "g11n.h" 57 58 #ifdef GSSAPI 59 #include "ssh-gss.h" 60 extern Gssctxt *xxx_gssctxt; 61 #endif /* GSSAPI */ 62 63 /* import */ 64 extern char *client_version_string; 65 extern char *server_version_string; 66 extern Options options; 67 extern Buffer command; 68 69 /* 70 * SSH2 key exchange 71 */ 72 73 u_char *session_id2 = NULL; 74 int session_id2_len = 0; 75 76 char *xxx_host; 77 struct sockaddr *xxx_hostaddr; 78 79 Kex *xxx_kex = NULL; 80 81 static int 82 verify_host_key_callback(Key *hostkey) 83 { 84 if (verify_host_key(xxx_host, xxx_hostaddr, hostkey) == -1) 85 fatal("Host key verification failed."); 86 return 0; 87 } 88 89 static int 90 accept_host_key_callback(Key *hostkey) 91 { 92 if (accept_host_key(xxx_host, xxx_hostaddr, hostkey) == -1) 93 log("GSS-API authenticated host key addition to " 94 "known_hosts file failed"); 95 return 0; 96 } 97 98 void 99 ssh_kex2(char *host, struct sockaddr *hostaddr) 100 { 101 Kex *kex; 102 Kex_hook_func kex_hook = NULL; 103 104 xxx_host = host; 105 xxx_hostaddr = hostaddr; 106 107 #ifdef GSSAPI 108 /* Add the GSSAPI mechanisms currently supported on this client to 109 * the key exchange algorithm proposal */ 110 if (options.gss_keyex) 111 kex_hook = ssh_gssapi_client_kex_hook; 112 #endif /* GSSAPI */ 113 if (options.ciphers == (char *)-1) { 114 log("No valid ciphers for protocol version 2 given, using defaults."); 115 options.ciphers = NULL; 116 } 117 if (options.ciphers != NULL) { 118 myproposal[PROPOSAL_ENC_ALGS_CTOS] = 119 myproposal[PROPOSAL_ENC_ALGS_STOC] = options.ciphers; 120 } 121 myproposal[PROPOSAL_ENC_ALGS_CTOS] = 122 compat_cipher_proposal(myproposal[PROPOSAL_ENC_ALGS_CTOS]); 123 myproposal[PROPOSAL_ENC_ALGS_STOC] = 124 compat_cipher_proposal(myproposal[PROPOSAL_ENC_ALGS_STOC]); 125 if (options.compression) { 126 myproposal[PROPOSAL_COMP_ALGS_CTOS] = 127 myproposal[PROPOSAL_COMP_ALGS_STOC] = "zlib,none"; 128 } else { 129 myproposal[PROPOSAL_COMP_ALGS_CTOS] = 130 myproposal[PROPOSAL_COMP_ALGS_STOC] = "none,zlib"; 131 } 132 if (options.macs != NULL) { 133 myproposal[PROPOSAL_MAC_ALGS_CTOS] = 134 myproposal[PROPOSAL_MAC_ALGS_STOC] = options.macs; 135 } 136 if (options.hostkeyalgorithms != NULL) 137 myproposal[PROPOSAL_SERVER_HOST_KEY_ALGS] = 138 options.hostkeyalgorithms; 139 140 if (options.rekey_limit) 141 packet_set_rekey_limit((u_int32_t)options.rekey_limit); 142 143 if (datafellows & SSH_BUG_LOCALES_NOT_LANGTAGS) { 144 char *locale = setlocale(LC_ALL, ""); 145 146 /* Solaris 9 SSHD expects a locale, not a langtag list */ 147 myproposal[PROPOSAL_LANG_CTOS] = ""; 148 if (locale != NULL && *locale != '\0' && 149 strcmp(locale, "C") != 0) 150 myproposal[PROPOSAL_LANG_CTOS] = locale; 151 } else { 152 myproposal[PROPOSAL_LANG_CTOS] = g11n_getlangs(); 153 } 154 155 /* Same languages proposal for both directions */ 156 if (myproposal[PROPOSAL_LANG_CTOS] == NULL) { 157 myproposal[PROPOSAL_LANG_CTOS] = ""; 158 myproposal[PROPOSAL_LANG_STOC] = ""; 159 } else { 160 myproposal[PROPOSAL_LANG_STOC] = 161 myproposal[PROPOSAL_LANG_CTOS]; 162 } 163 164 /* start key exchange */ 165 kex = kex_setup(host, myproposal, kex_hook); 166 kex->kex[KEX_DH_GRP1_SHA1] = kexdh_client; 167 kex->kex[KEX_DH_GEX_SHA1] = kexgex_client; 168 #ifdef GSSAPI 169 kex->kex[KEX_GSS_GRP1_SHA1] = kexgss_client; 170 kex->options.gss_deleg_creds = options.gss_deleg_creds; 171 #endif /* GSSAPI */ 172 kex->client_version_string=client_version_string; 173 kex->server_version_string=server_version_string; 174 kex->verify_host_key=&verify_host_key_callback; 175 kex->accept_host_key=&accept_host_key_callback; 176 177 xxx_kex = kex; 178 179 dispatch_run(DISPATCH_BLOCK, &kex->done, kex); 180 181 session_id2 = kex->session_id; 182 session_id2_len = kex->session_id_len; 183 184 #ifdef DEBUG_KEXDH 185 /* send 1st encrypted/maced/compressed message */ 186 packet_start(SSH2_MSG_IGNORE); 187 packet_put_cstring("markus"); 188 packet_send(); 189 packet_write_wait(); 190 #endif 191 debug("done: ssh_kex2."); 192 } 193 194 /* 195 * Authenticate user 196 */ 197 198 typedef struct Authctxt Authctxt; 199 typedef struct Authmethod Authmethod; 200 201 typedef int sign_cb_fn( 202 Authctxt *authctxt, Key *key, 203 u_char **sigp, u_int *lenp, u_char *data, u_int datalen); 204 205 struct Authctxt { 206 const char *server_user; 207 const char *local_user; 208 const char *host; 209 const char *service; 210 Authmethod *method; 211 int success; 212 char *authlist; 213 /* pubkey */ 214 Key *last_key; 215 sign_cb_fn *last_key_sign; 216 int last_key_hint; 217 AuthenticationConnection *agent; 218 /* hostbased */ 219 Sensitive *sensitive; 220 /* kbd-interactive */ 221 int info_req_seen; 222 /* generic */ 223 void *methoddata; 224 }; 225 struct Authmethod { 226 char *name; /* string to compare against server's list */ 227 int (*userauth)(Authctxt *authctxt); 228 void (*cleanup)(Authctxt *authctxt); 229 int *enabled; /* flag in option struct that enables method */ 230 int *batch_flag; /* flag in option struct that disables method */ 231 }; 232 233 void input_userauth_success(int, u_int32_t, void *); 234 void input_userauth_failure(int, u_int32_t, void *); 235 void input_userauth_banner(int, u_int32_t, void *); 236 void input_userauth_error(int, u_int32_t, void *); 237 void input_userauth_info_req(int, u_int32_t, void *); 238 void input_userauth_pk_ok(int, u_int32_t, void *); 239 void input_userauth_passwd_changereq(int, u_int32_t, void *); 240 241 int userauth_none(Authctxt *); 242 int userauth_pubkey(Authctxt *); 243 int userauth_passwd(Authctxt *); 244 int userauth_kbdint(Authctxt *); 245 int userauth_hostbased(Authctxt *); 246 247 #ifdef GSSAPI 248 static int userauth_gssapi_keyex(Authctxt *authctxt); 249 static int userauth_gssapi(Authctxt *authctxt); 250 static void userauth_gssapi_cleanup(Authctxt *authctxt); 251 static void input_gssapi_response(int type, u_int32_t, void *); 252 static void input_gssapi_token(int type, u_int32_t, void *); 253 static void input_gssapi_hash(int type, u_int32_t, void *); 254 static void input_gssapi_error(int, u_int32_t, void *); 255 static void input_gssapi_errtok(int, u_int32_t, void *); 256 #endif /* GSSAPI */ 257 258 void userauth(Authctxt *, char *); 259 260 static int sign_and_send_pubkey(Authctxt *, Key *, sign_cb_fn *); 261 static void clear_auth_state(Authctxt *); 262 263 static Authmethod *authmethod_get(char *authlist); 264 static Authmethod *authmethod_lookup(const char *name); 265 static char *authmethods_get(void); 266 267 Authmethod authmethods[] = { 268 #ifdef GSSAPI 269 {"gssapi-keyex", 270 userauth_gssapi_keyex, 271 userauth_gssapi_cleanup, 272 &options.gss_keyex, 273 NULL}, 274 {"gssapi-with-mic", 275 userauth_gssapi, 276 userauth_gssapi_cleanup, 277 &options.gss_authentication, 278 NULL}, 279 #endif /* GSSAPI */ 280 {"hostbased", 281 userauth_hostbased, 282 NULL, 283 &options.hostbased_authentication, 284 NULL}, 285 {"publickey", 286 userauth_pubkey, 287 NULL, 288 &options.pubkey_authentication, 289 NULL}, 290 {"keyboard-interactive", 291 userauth_kbdint, 292 NULL, 293 &options.kbd_interactive_authentication, 294 &options.batch_mode}, 295 {"password", 296 userauth_passwd, 297 NULL, 298 &options.password_authentication, 299 &options.batch_mode}, 300 {"none", 301 userauth_none, 302 NULL, 303 NULL, 304 NULL}, 305 {NULL, NULL, NULL, NULL, NULL} 306 }; 307 308 void 309 ssh_userauth2(const char *local_user, const char *server_user, char *host, 310 Sensitive *sensitive) 311 { 312 Authctxt authctxt; 313 int type; 314 315 if (options.challenge_response_authentication) 316 options.kbd_interactive_authentication = 1; 317 318 packet_start(SSH2_MSG_SERVICE_REQUEST); 319 packet_put_cstring("ssh-userauth"); 320 packet_send(); 321 debug("send SSH2_MSG_SERVICE_REQUEST"); 322 packet_write_wait(); 323 type = packet_read(); 324 if (type != SSH2_MSG_SERVICE_ACCEPT) 325 fatal("Server denied authentication request: %d", type); 326 if (packet_remaining() > 0) { 327 char *reply = packet_get_string(NULL); 328 debug2("service_accept: %s", reply); 329 xfree(reply); 330 } else { 331 debug2("buggy server: service_accept w/o service"); 332 } 333 packet_check_eom(); 334 debug("got SSH2_MSG_SERVICE_ACCEPT"); 335 336 if (options.preferred_authentications == NULL) 337 options.preferred_authentications = authmethods_get(); 338 339 /* setup authentication context */ 340 memset(&authctxt, 0, sizeof(authctxt)); 341 authctxt.agent = ssh_get_authentication_connection(); 342 authctxt.server_user = server_user; 343 authctxt.local_user = local_user; 344 authctxt.host = host; 345 authctxt.service = "ssh-connection"; /* service name */ 346 authctxt.success = 0; 347 authctxt.method = authmethod_lookup("none"); 348 authctxt.authlist = NULL; 349 authctxt.methoddata = NULL; 350 authctxt.sensitive = sensitive; 351 authctxt.info_req_seen = 0; 352 if (authctxt.method == NULL) 353 fatal("ssh_userauth2: internal error: cannot send userauth none request"); 354 355 /* initial userauth request */ 356 userauth_none(&authctxt); 357 358 dispatch_init(&input_userauth_error); 359 dispatch_set(SSH2_MSG_USERAUTH_SUCCESS, &input_userauth_success); 360 dispatch_set(SSH2_MSG_USERAUTH_FAILURE, &input_userauth_failure); 361 dispatch_set(SSH2_MSG_USERAUTH_BANNER, &input_userauth_banner); 362 dispatch_run(DISPATCH_BLOCK, &authctxt.success, &authctxt); /* loop until success */ 363 364 if (authctxt.agent != NULL) 365 ssh_close_authentication_connection(authctxt.agent); 366 367 debug("Authentication succeeded (%s)", authctxt.method->name); 368 } 369 void 370 userauth(Authctxt *authctxt, char *authlist) 371 { 372 if (authctxt->method != NULL && 373 authctxt->method->cleanup != NULL) 374 authctxt->method->cleanup(authctxt); 375 376 if (authlist == NULL) { 377 authlist = authctxt->authlist; 378 } else { 379 if (authctxt->authlist) 380 xfree(authctxt->authlist); 381 authctxt->authlist = authlist; 382 } 383 for (;;) { 384 Authmethod *method = authmethod_get(authlist); 385 if (method == NULL) 386 fatal("Permission denied (%s).", authlist); 387 authctxt->method = method; 388 if (method->userauth(authctxt) != 0) { 389 debug2("we sent a %s packet, wait for reply", method->name); 390 break; 391 } else { 392 debug2("we did not send a packet, disable method"); 393 method->enabled = NULL; 394 } 395 } 396 } 397 398 void 399 input_userauth_error(int type, u_int32_t seq, void *ctxt) 400 { 401 fatal("input_userauth_error: bad message during authentication: " 402 "type %d", type); 403 } 404 405 void 406 input_userauth_banner(int type, u_int32_t seq, void *ctxt) 407 { 408 char *msg, *lang; 409 410 debug3("input_userauth_banner"); 411 msg = packet_get_string(NULL); 412 lang = packet_get_string(NULL); 413 /* 414 * Banner is a warning message according to RFC 4252. So, never print 415 * a banner in error log level or lower. If the log level is higher, 416 * use DisableBanner option to decide whether to display it or not. 417 */ 418 if (options.log_level > SYSLOG_LEVEL_ERROR) 419 if (options.disable_banner == 0 || 420 (options.disable_banner == SSH_NO_BANNER_IN_EXEC_MODE && 421 buffer_len(&command) == 0)) 422 fprintf(stderr, "%s", msg); 423 xfree(msg); 424 xfree(lang); 425 } 426 427 void 428 input_userauth_success(int type, u_int32_t seq, void *ctxt) 429 { 430 Authctxt *authctxt = ctxt; 431 if (authctxt == NULL) 432 fatal("input_userauth_success: no authentication context"); 433 if (authctxt->authlist) 434 xfree(authctxt->authlist); 435 if (authctxt->method != NULL && 436 authctxt->method->cleanup != NULL) 437 authctxt->method->cleanup(authctxt); 438 clear_auth_state(authctxt); 439 authctxt->success = 1; /* break out */ 440 } 441 442 void 443 input_userauth_failure(int type, u_int32_t seq, void *ctxt) 444 { 445 Authctxt *authctxt = ctxt; 446 char *authlist = NULL; 447 int partial; 448 449 if (authctxt == NULL) 450 fatal("input_userauth_failure: no authentication context"); 451 452 authlist = packet_get_string(NULL); 453 partial = packet_get_char(); 454 packet_check_eom(); 455 456 if (partial != 0) 457 log("Authenticated with partial success."); 458 debug("Authentications that can continue: %s", authlist); 459 460 clear_auth_state(authctxt); 461 userauth(authctxt, authlist); 462 } 463 void 464 input_userauth_pk_ok(int type, u_int32_t seq, void *ctxt) 465 { 466 Authctxt *authctxt = ctxt; 467 Key *key = NULL; 468 Buffer b; 469 int pktype, sent = 0; 470 u_int alen, blen; 471 char *pkalg, *fp; 472 u_char *pkblob; 473 474 if (authctxt == NULL) 475 fatal("input_userauth_pk_ok: no authentication context"); 476 if (datafellows & SSH_BUG_PKOK) { 477 /* this is similar to SSH_BUG_PKAUTH */ 478 debug2("input_userauth_pk_ok: SSH_BUG_PKOK"); 479 pkblob = packet_get_string(&blen); 480 buffer_init(&b); 481 buffer_append(&b, pkblob, blen); 482 pkalg = buffer_get_string(&b, &alen); 483 buffer_free(&b); 484 } else { 485 pkalg = packet_get_string(&alen); 486 pkblob = packet_get_string(&blen); 487 } 488 packet_check_eom(); 489 490 debug("Server accepts key: pkalg %s blen %u lastkey %p hint %d", 491 pkalg, blen, authctxt->last_key, authctxt->last_key_hint); 492 493 do { 494 if (authctxt->last_key == NULL || 495 authctxt->last_key_sign == NULL) { 496 debug("no last key or no sign cb"); 497 break; 498 } 499 if ((pktype = key_type_from_name(pkalg)) == KEY_UNSPEC) { 500 debug("unknown pkalg %s", pkalg); 501 break; 502 } 503 if ((key = key_from_blob(pkblob, blen)) == NULL) { 504 debug("no key from blob. pkalg %s", pkalg); 505 break; 506 } 507 if (key->type != pktype) { 508 error("input_userauth_pk_ok: type mismatch " 509 "for decoded key (received %d, expected %d)", 510 key->type, pktype); 511 break; 512 } 513 fp = key_fingerprint(key, SSH_FP_MD5, SSH_FP_HEX); 514 debug2("input_userauth_pk_ok: fp %s", fp); 515 xfree(fp); 516 if (!key_equal(key, authctxt->last_key)) { 517 debug("key != last_key"); 518 break; 519 } 520 sent = sign_and_send_pubkey(authctxt, key, 521 authctxt->last_key_sign); 522 } while (0); 523 524 if (key != NULL) 525 key_free(key); 526 xfree(pkalg); 527 xfree(pkblob); 528 529 /* unregister */ 530 clear_auth_state(authctxt); 531 dispatch_set(SSH2_MSG_USERAUTH_PK_OK, NULL); 532 533 /* try another method if we did not send a packet */ 534 if (sent == 0) 535 userauth(authctxt, NULL); 536 537 } 538 539 #ifdef GSSAPI 540 int 541 userauth_gssapi(Authctxt *authctxt) 542 { 543 Gssctxt *gssctxt = NULL; 544 static int initialized = 0; 545 static int mech_idx = 0; 546 static gss_OID_set supported = GSS_C_NULL_OID_SET; 547 gss_OID mech = GSS_C_NULL_OID; 548 549 /* Things work better if we send one mechanism at a time, rather 550 * than them all at once. This means that if we fail at some point 551 * in the middle of a negotiation, we can come back and try something 552 * different. */ 553 554 if (datafellows & SSH_OLD_GSSAPI) return 0; 555 556 /* Before we offer a mechanism, check that we can support it. Don't 557 * bother trying to get credentials - as the standard fallback will 558 * deal with that kind of failure. 559 */ 560 561 if (!initialized) { 562 initialized = 1; 563 ssh_gssapi_client_mechs(authctxt->host, &supported); 564 if (supported == GSS_C_NULL_OID_SET || supported->count == 0) 565 return (0); 566 } else if (supported != GSS_C_NULL_OID_SET) { 567 /* Try next mech, if any */ 568 mech_idx++; 569 570 if (mech_idx >= supported->count) 571 return (0); 572 } else { 573 return (0); 574 } 575 576 mech = &supported->elements[mech_idx]; 577 578 ssh_gssapi_build_ctx(&gssctxt, 1, mech); 579 authctxt->methoddata=(void *)gssctxt; 580 581 packet_start(SSH2_MSG_USERAUTH_REQUEST); 582 packet_put_cstring(authctxt->server_user); 583 packet_put_cstring(authctxt->service); 584 packet_put_cstring(authctxt->method->name); 585 586 packet_put_int(1); 587 588 /* The newest gsskeyex draft stipulates that OIDs should 589 * be DER encoded, so we need to add the object type and 590 * length information back on */ 591 if (datafellows & SSH_BUG_GSSAPI_BER) { 592 packet_put_string(mech->elements, mech->length); 593 } else { 594 packet_put_int((mech->length)+2); 595 packet_put_char(0x06); 596 packet_put_char(mech->length); 597 packet_put_raw(mech->elements, mech->length); 598 } 599 600 packet_send(); 601 packet_write_wait(); 602 603 dispatch_set(SSH2_MSG_USERAUTH_GSSAPI_RESPONSE,&input_gssapi_response); 604 605 return 1; 606 } 607 608 void 609 input_gssapi_response(int type, u_int32_t plen, void *ctxt) 610 { 611 Authctxt *authctxt = ctxt; 612 Gssctxt *gssctxt; 613 OM_uint32 status,ms; 614 u_int oidlen; 615 char *oidv; 616 gss_buffer_desc send_tok; 617 618 if (authctxt == NULL) 619 fatal("input_gssapi_response: no authentication context"); 620 gssctxt = authctxt->methoddata; 621 622 /* Setup our OID */ 623 oidv=packet_get_string(&oidlen); 624 625 if (datafellows & SSH_BUG_GSSAPI_BER) { 626 if (!ssh_gssapi_check_mech_oid(gssctxt,oidv,oidlen)) { 627 gss_OID oid; 628 629 oid = ssh_gssapi_make_oid(oidlen, oidv); 630 debug("Server returned different OID (%s) than expected (%s)", 631 ssh_gssapi_oid_to_str(oid), 632 ssh_gssapi_oid_to_str(gssctxt->desired_mech)); 633 ssh_gssapi_release_oid(&oid); 634 clear_auth_state(authctxt); 635 userauth(authctxt,NULL); 636 return; 637 } 638 } else { 639 if(oidv[0]!=0x06 || oidv[1]!=oidlen-2) { 640 debug("Badly encoded mechanism OID received"); 641 clear_auth_state(authctxt); 642 userauth(authctxt,NULL); 643 return; 644 } 645 if (!ssh_gssapi_check_mech_oid(gssctxt,oidv+2,oidlen-2)) { 646 gss_OID oid; 647 648 oid = ssh_gssapi_make_oid(oidlen-2, oidv+2); 649 debug("Server returned different OID (%s) than expected (%s)", 650 ssh_gssapi_oid_to_str(oid), 651 ssh_gssapi_oid_to_str(gssctxt->desired_mech)); 652 clear_auth_state(authctxt); 653 userauth(authctxt,NULL); 654 return; 655 } 656 } 657 658 packet_check_eom(); 659 660 dispatch_set(SSH2_MSG_USERAUTH_GSSAPI_TOKEN,&input_gssapi_token); 661 dispatch_set(SSH2_MSG_USERAUTH_GSSAPI_ERROR,&input_gssapi_error); 662 dispatch_set(SSH2_MSG_USERAUTH_GSSAPI_ERRTOK,&input_gssapi_errtok); 663 664 status = ssh_gssapi_init_ctx(gssctxt, authctxt->host, 665 options.gss_deleg_creds, 666 GSS_C_NO_BUFFER, &send_tok); 667 if (GSS_ERROR(status)) { 668 if (send_tok.length>0) { 669 packet_start(SSH2_MSG_USERAUTH_GSSAPI_ERRTOK); 670 packet_put_string(send_tok.value,send_tok.length); 671 packet_send(); 672 packet_write_wait(); 673 } 674 /* Start again with next method on list */ 675 debug("Trying to start again"); 676 clear_auth_state(authctxt); 677 userauth(authctxt,NULL); 678 return; 679 } 680 681 /* We must have data to send */ 682 packet_start(SSH2_MSG_USERAUTH_GSSAPI_TOKEN); 683 packet_put_string(send_tok.value,send_tok.length); 684 packet_send(); 685 packet_write_wait(); 686 gss_release_buffer(&ms, &send_tok); 687 } 688 689 void 690 input_gssapi_token(int type, u_int32_t plen, void *ctxt) 691 { 692 Authctxt *authctxt = ctxt; 693 Gssctxt *gssctxt; 694 gss_buffer_desc send_tok, recv_tok, g_mic_data; 695 Buffer mic_data; 696 OM_uint32 status; 697 u_int slen; 698 699 if (authctxt == NULL || authctxt->method == NULL) 700 fatal("input_gssapi_response: no authentication context"); 701 gssctxt = authctxt->methoddata; 702 703 recv_tok.value=packet_get_string(&slen); 704 recv_tok.length=slen; /* safe typecast */ 705 706 status=ssh_gssapi_init_ctx(gssctxt, authctxt->host, 707 options.gss_deleg_creds, 708 &recv_tok, &send_tok); 709 710 packet_check_eom(); 711 712 if (GSS_ERROR(status)) { 713 if (send_tok.length>0) { 714 packet_start(SSH2_MSG_USERAUTH_GSSAPI_ERRTOK); 715 packet_put_string(send_tok.value,send_tok.length); 716 packet_send(); 717 packet_write_wait(); 718 } 719 /* Start again with the next method in the list */ 720 clear_auth_state(authctxt); 721 userauth(authctxt,NULL); 722 return; 723 } 724 725 if (send_tok.length>0) { 726 packet_start(SSH2_MSG_USERAUTH_GSSAPI_TOKEN); 727 packet_put_string(send_tok.value,send_tok.length); 728 packet_send(); 729 packet_write_wait(); 730 } 731 732 if (status != GSS_S_COMPLETE) 733 return; 734 735 /* Make data buffer to MIC */ 736 buffer_init(&mic_data); 737 buffer_put_string(&mic_data, session_id2, session_id2_len); 738 buffer_put_char(&mic_data, SSH2_MSG_USERAUTH_REQUEST); 739 buffer_put_cstring(&mic_data, authctxt->server_user); 740 buffer_put_cstring(&mic_data, authctxt->service); 741 buffer_put_cstring(&mic_data, authctxt->method->name); 742 743 /* Make MIC */ 744 g_mic_data.value = buffer_ptr(&mic_data); 745 g_mic_data.length = buffer_len(&mic_data); 746 747 status = ssh_gssapi_get_mic(gssctxt, &g_mic_data, &send_tok); 748 buffer_clear(&mic_data); 749 750 if (GSS_ERROR(status) || send_tok.length == 0) { 751 /* 752 * Oops, now what? There's no error token... 753 * Next userauth 754 */ 755 debug("GSS_GetMIC() failed! - " 756 "Abandoning GSSAPI userauth"); 757 clear_auth_state(authctxt); 758 userauth(authctxt,NULL); 759 return; 760 } 761 packet_start(SSH2_MSG_USERAUTH_GSSAPI_MIC); 762 packet_put_string(send_tok.value,send_tok.length); 763 packet_send(); 764 packet_write_wait(); 765 } 766 767 void 768 input_gssapi_errtok(int type, u_int32_t plen, void *ctxt) 769 { 770 OM_uint32 min_status; 771 Authctxt *authctxt = ctxt; 772 Gssctxt *gssctxt; 773 gss_buffer_desc send_tok, recv_tok; 774 775 if (authctxt == NULL) 776 fatal("input_gssapi_response: no authentication context"); 777 gssctxt = authctxt->methoddata; 778 779 recv_tok.value=packet_get_string(&recv_tok.length); 780 781 /* Stick it into GSSAPI and see what it says */ 782 (void) ssh_gssapi_init_ctx(gssctxt, authctxt->host, 783 options.gss_deleg_creds, 784 &recv_tok, &send_tok); 785 786 xfree(recv_tok.value); 787 (void) gss_release_buffer(&min_status, &send_tok); 788 789 debug("Server sent a GSS-API error token during GSS userauth -- %s", 790 ssh_gssapi_last_error(gssctxt, NULL, NULL)); 791 792 packet_check_eom(); 793 794 /* We can't send a packet to the server */ 795 796 /* The draft says that we should wait for the server to fail 797 * before starting the next authentication. So, we clear the 798 * state, but don't do anything else 799 */ 800 clear_auth_state(authctxt); 801 return; 802 } 803 804 void 805 input_gssapi_error(int type, u_int32_t plen, void *ctxt) 806 { 807 OM_uint32 maj,min; 808 char *msg; 809 char *lang; 810 811 maj = packet_get_int(); 812 min = packet_get_int(); 813 msg = packet_get_string(NULL); 814 lang = packet_get_string(NULL); 815 816 packet_check_eom(); 817 818 fprintf(stderr, "Server GSSAPI Error:\n%s (%d, %d)\n", msg, maj, min); 819 xfree(msg); 820 xfree(lang); 821 } 822 823 int 824 userauth_gssapi_keyex(Authctxt *authctxt) 825 { 826 Gssctxt *gssctxt; 827 gss_buffer_desc send_tok; 828 OM_uint32 status; 829 static int attempt = 0; 830 831 if (authctxt == NULL || authctxt->method == NULL) 832 fatal("input_gssapi_response: no authentication context"); 833 834 if (xxx_gssctxt == NULL || xxx_gssctxt->context == GSS_C_NO_CONTEXT) 835 return 0; 836 837 if (strcmp(authctxt->method->name, "gssapi-keyex") == 0) 838 authctxt->methoddata = gssctxt = xxx_gssctxt; 839 840 if (attempt++ >= 1) 841 return 0; 842 843 if (strcmp(authctxt->method->name, "gssapi-keyex") == 0) { 844 gss_buffer_desc g_mic_data; 845 Buffer mic_data; 846 847 debug2("Authenticating with GSS-API context from key exchange (w/ MIC)"); 848 849 /* Make data buffer to MIC */ 850 buffer_init(&mic_data); 851 buffer_put_string(&mic_data, session_id2, session_id2_len); 852 buffer_put_char(&mic_data, SSH2_MSG_USERAUTH_REQUEST); 853 buffer_put_cstring(&mic_data, authctxt->server_user); 854 buffer_put_cstring(&mic_data, authctxt->service); 855 buffer_put_cstring(&mic_data, authctxt->method->name); 856 857 /* Make MIC */ 858 g_mic_data.value = buffer_ptr(&mic_data); 859 g_mic_data.length = buffer_len(&mic_data); 860 status = ssh_gssapi_get_mic(gssctxt, &g_mic_data, &send_tok); 861 buffer_clear(&mic_data); 862 863 if (GSS_ERROR(status) || send_tok.length == 0) { 864 /* 865 * Oops, now what? There's no error token... 866 * Next userauth 867 */ 868 debug("GSS_GetMIC() failed! - " 869 "Abandoning GSSAPI userauth"); 870 clear_auth_state(authctxt); 871 userauth(authctxt,NULL); 872 return 0; 873 } 874 packet_start(SSH2_MSG_USERAUTH_REQUEST); 875 packet_put_cstring(authctxt->server_user); 876 packet_put_cstring(authctxt->service); 877 packet_put_cstring(authctxt->method->name); 878 packet_put_string(send_tok.value,send_tok.length); /* MIC */ 879 packet_send(); 880 packet_write_wait(); 881 (void) gss_release_buffer(&status, &send_tok); 882 } else if (strcmp(authctxt->method->name, "external-keyx") == 0) { 883 debug2("Authentication with deprecated \"external-keyx\"" 884 " method not supported"); 885 return 0; 886 } 887 return 1; 888 } 889 890 static 891 void 892 userauth_gssapi_cleanup(Authctxt *authctxt) 893 { 894 dispatch_set(SSH2_MSG_USERAUTH_GSSAPI_RESPONSE,NULL); 895 dispatch_set(SSH2_MSG_USERAUTH_GSSAPI_TOKEN,NULL); 896 dispatch_set(SSH2_MSG_USERAUTH_GSSAPI_ERROR,NULL); 897 dispatch_set(SSH2_MSG_USERAUTH_GSSAPI_ERRTOK,NULL); 898 899 if (authctxt == NULL || 900 authctxt->method == NULL || 901 authctxt->methoddata == NULL) 902 return; 903 904 if (strncmp(authctxt->method->name, "gssapi", strlen("gssapi")) == 0) { 905 ssh_gssapi_delete_ctx((Gssctxt **)&authctxt->methoddata); 906 } 907 } 908 #endif /* GSSAPI */ 909 910 int 911 userauth_none(Authctxt *authctxt) 912 { 913 /* initial userauth request */ 914 packet_start(SSH2_MSG_USERAUTH_REQUEST); 915 packet_put_cstring(authctxt->server_user); 916 packet_put_cstring(authctxt->service); 917 packet_put_cstring(authctxt->method->name); 918 packet_send(); 919 return 1; 920 921 } 922 923 int 924 userauth_passwd(Authctxt *authctxt) 925 { 926 static int attempt = 0; 927 char prompt[150]; 928 char *password; 929 930 if (attempt++ >= options.number_of_password_prompts) 931 return 0; 932 933 if (attempt != 1) 934 error("Permission denied, please try again."); 935 936 snprintf(prompt, sizeof(prompt), gettext("%.30s@%.128s's password: "), 937 authctxt->server_user, authctxt->host); 938 password = read_passphrase(prompt, 0); 939 packet_start(SSH2_MSG_USERAUTH_REQUEST); 940 packet_put_cstring(authctxt->server_user); 941 packet_put_cstring(authctxt->service); 942 packet_put_cstring(authctxt->method->name); 943 packet_put_char(0); 944 packet_put_cstring(password); 945 memset(password, 0, strlen(password)); 946 xfree(password); 947 packet_add_padding(64); 948 packet_send(); 949 950 dispatch_set(SSH2_MSG_USERAUTH_PASSWD_CHANGEREQ, 951 &input_userauth_passwd_changereq); 952 953 return 1; 954 } 955 /* 956 * parse PASSWD_CHANGEREQ, prompt user and send SSH2_MSG_USERAUTH_REQUEST 957 */ 958 void 959 input_userauth_passwd_changereq(int type, u_int32_t seqnr, void *ctxt) 960 { 961 Authctxt *authctxt = ctxt; 962 char *info, *lang, *password = NULL, *retype = NULL; 963 char prompt[150]; 964 965 debug2("input_userauth_passwd_changereq"); 966 967 if (authctxt == NULL) 968 fatal("input_userauth_passwd_changereq: " 969 "no authentication context"); 970 971 info = packet_get_string(NULL); 972 lang = packet_get_string(NULL); 973 if (strlen(info) > 0) 974 log("%s", info); 975 xfree(info); 976 xfree(lang); 977 packet_start(SSH2_MSG_USERAUTH_REQUEST); 978 packet_put_cstring(authctxt->server_user); 979 packet_put_cstring(authctxt->service); 980 packet_put_cstring(authctxt->method->name); 981 packet_put_char(1); /* additional info */ 982 snprintf(prompt, sizeof(prompt), 983 gettext("Enter %.30s@%.128s's old password: "), 984 authctxt->server_user, authctxt->host); 985 password = read_passphrase(prompt, 0); 986 packet_put_cstring(password); 987 memset(password, 0, strlen(password)); 988 xfree(password); 989 password = NULL; 990 while (password == NULL) { 991