sshconnect.c revision 57464
1169689Skan/* 2169689Skan * Author: Tatu Ylonen <ylo@cs.hut.fi> 3169689Skan * Copyright (c) 1995 Tatu Ylonen <ylo@cs.hut.fi>, Espoo, Finland 4169689Skan * All rights reserved 5169689Skan * Created: Sat Mar 18 22:15:47 1995 ylo 6169689Skan * Code to connect to a remote host, and to perform the client side of the 7169689Skan * login (authentication) dialog. 8169689Skan * 9169689Skan * $FreeBSD: head/crypto/openssh/sshconnect.c 57464 2000-02-25 01:53:12Z green $ 10169689Skan */ 11169689Skan 12169689Skan#include "includes.h" 13169689SkanRCSID("$OpenBSD: sshconnect.c,v 1.56 2000/02/18 08:50:33 markus Exp $"); 14169689Skan 15169689Skan#include <openssl/bn.h> 16169689Skan#include "xmalloc.h" 17169689Skan#include "rsa.h" 18169689Skan#include "ssh.h" 19169689Skan#include "packet.h" 20169689Skan#include "authfd.h" 21169689Skan#include "cipher.h" 22169689Skan#include "mpaux.h" 23169689Skan#include "uidswap.h" 24169689Skan#include "compat.h" 25169689Skan#include "readconf.h" 26169689Skan#include "fingerprint.h" 27169689Skan 28220150Smm#include <openssl/md5.h> 29169689Skan 30169689Skan/* Session id for the current session. */ 31169689Skanunsigned char session_id[16]; 32169689Skan 33169689Skan/* authentications supported by server */ 34169689Skanunsigned int supported_authentications; 35169689Skan 36169689Skanextern Options options; 37169689Skanextern char *__progname; 38169689Skan 39169689Skan/* 40169689Skan * Connect to the given ssh server using a proxy command. 41169689Skan */ 42169689Skanint 43169689Skanssh_proxy_connect(const char *host, u_short port, uid_t original_real_uid, 44169689Skan const char *proxy_command) 45169689Skan{ 46169689Skan Buffer command; 47169689Skan const char *cp; 48169689Skan char *command_string; 49169689Skan int pin[2], pout[2]; 50169689Skan int pid; 51169689Skan char strport[NI_MAXSERV]; 52169689Skan 53169689Skan /* Convert the port number into a string. */ 54169689Skan snprintf(strport, sizeof strport, "%hu", port); 55169689Skan 56169689Skan /* Build the final command string in the buffer by making the 57169689Skan appropriate substitutions to the given proxy command. */ 58169689Skan buffer_init(&command); 59169689Skan for (cp = proxy_command; *cp; cp++) { 60169689Skan if (cp[0] == '%' && cp[1] == '%') { 61169689Skan buffer_append(&command, "%", 1); 62169689Skan cp++; 63169689Skan continue; 64169689Skan } 65169689Skan if (cp[0] == '%' && cp[1] == 'h') { 66169689Skan buffer_append(&command, host, strlen(host)); 67169689Skan cp++; 68169689Skan continue; 69169689Skan } 70169689Skan if (cp[0] == '%' && cp[1] == 'p') { 71169689Skan buffer_append(&command, strport, strlen(strport)); 72169689Skan cp++; 73169689Skan continue; 74169689Skan } 75169689Skan buffer_append(&command, cp, 1); 76169689Skan } 77169689Skan buffer_append(&command, "\0", 1); 78169689Skan 79169689Skan /* Get the final command string. */ 80169689Skan command_string = buffer_ptr(&command); 81169689Skan 82169689Skan /* Create pipes for communicating with the proxy. */ 83169689Skan if (pipe(pin) < 0 || pipe(pout) < 0) 84169689Skan fatal("Could not create pipes to communicate with the proxy: %.100s", 85169689Skan strerror(errno)); 86169689Skan 87169689Skan debug("Executing proxy command: %.500s", command_string); 88169689Skan 89169689Skan /* Fork and execute the proxy command. */ 90169689Skan if ((pid = fork()) == 0) { 91169689Skan char *argv[10]; 92169689Skan 93169689Skan /* Child. Permanently give up superuser privileges. */ 94169689Skan permanently_set_uid(original_real_uid); 95169689Skan 96169689Skan /* Redirect stdin and stdout. */ 97169689Skan close(pin[1]); 98169689Skan if (pin[0] != 0) { 99169689Skan if (dup2(pin[0], 0) < 0) 100169689Skan perror("dup2 stdin"); 101169689Skan close(pin[0]); 102169689Skan } 103169689Skan close(pout[0]); 104169689Skan if (dup2(pout[1], 1) < 0) 105169689Skan perror("dup2 stdout"); 106169689Skan /* Cannot be 1 because pin allocated two descriptors. */ 107169689Skan close(pout[1]); 108169689Skan 109169689Skan /* Stderr is left as it is so that error messages get 110169689Skan printed on the user's terminal. */ 111169689Skan argv[0] = "/bin/sh"; 112169689Skan argv[1] = "-c"; 113169689Skan argv[2] = command_string; 114169689Skan argv[3] = NULL; 115169689Skan 116169689Skan /* Execute the proxy command. Note that we gave up any 117169689Skan extra privileges above. */ 118169689Skan execv("/bin/sh", argv); 119169689Skan perror("/bin/sh"); 120169689Skan exit(1); 121169689Skan } 122169689Skan /* Parent. */ 123169689Skan if (pid < 0) 124169689Skan fatal("fork failed: %.100s", strerror(errno)); 125169689Skan 126169689Skan /* Close child side of the descriptors. */ 127169689Skan close(pin[0]); 128169689Skan close(pout[1]); 129169689Skan 130169689Skan /* Free the command name. */ 131169689Skan buffer_free(&command); 132169689Skan 133169689Skan /* Set the connection file descriptors. */ 134169689Skan packet_set_connection(pout[0], pin[1]); 135169689Skan 136169689Skan return 1; 137169689Skan} 138169689Skan 139169689Skan/* 140169689Skan * Creates a (possibly privileged) socket for use as the ssh connection. 141169689Skan */ 142169689Skanint 143169689Skanssh_create_socket(uid_t original_real_uid, int privileged, int family) 144169689Skan{ 145169689Skan int sock; 146169689Skan 147169689Skan /* 148169689Skan * If we are running as root and want to connect to a privileged 149169689Skan * port, bind our own socket to a privileged port. 150169689Skan */ 151169689Skan if (privileged) { 152169689Skan int p = IPPORT_RESERVED - 1; 153169689Skan sock = rresvport_af(&p, family); 154169689Skan if (sock < 0) 155169689Skan error("rresvport: af=%d %.100s", family, strerror(errno)); 156169689Skan else 157169689Skan debug("Allocated local port %d.", p); 158169689Skan } else { 159169689Skan /* 160169689Skan * Just create an ordinary socket on arbitrary port. We use 161169689Skan * the user's uid to create the socket. 162169689Skan */ 163169689Skan temporarily_use_uid(original_real_uid); 164169689Skan sock = socket(family, SOCK_STREAM, 0); 165169689Skan if (sock < 0) 166169689Skan error("socket: %.100s", strerror(errno)); 167169689Skan restore_uid(); 168169689Skan } 169169689Skan return sock; 170169689Skan} 171169689Skan 172169689Skan/* 173169689Skan * Opens a TCP/IP connection to the remote server on the given host. 174169689Skan * The address of the remote host will be returned in hostaddr. 175169689Skan * If port is 0, the default port will be used. If anonymous is zero, 176169689Skan * a privileged port will be allocated to make the connection. 177169689Skan * This requires super-user privileges if anonymous is false. 178169689Skan * Connection_attempts specifies the maximum number of tries (one per 179169689Skan * second). If proxy_command is non-NULL, it specifies the command (with %h 180169689Skan * and %p substituted for host and port, respectively) to use to contact 181169689Skan * the daemon. 182169689Skan */ 183169689Skanint 184169689Skanssh_connect(const char *host, struct sockaddr_storage * hostaddr, 185169689Skan u_short port, int connection_attempts, 186169689Skan int anonymous, uid_t original_real_uid, 187169689Skan const char *proxy_command) 188169689Skan{ 189169689Skan int sock = -1, attempt; 190169689Skan struct servent *sp; 191169689Skan struct addrinfo hints, *ai, *aitop; 192169689Skan char ntop[NI_MAXHOST], strport[NI_MAXSERV]; 193169689Skan int gaierr; 194169689Skan struct linger linger; 195169689Skan 196169689Skan debug("ssh_connect: getuid %d geteuid %d anon %d", 197169689Skan (int) getuid(), (int) geteuid(), anonymous); 198169689Skan 199169689Skan /* Get default port if port has not been set. */ 200169689Skan if (port == 0) { 201169689Skan sp = getservbyname(SSH_SERVICE_NAME, "tcp"); 202169689Skan if (sp) 203169689Skan port = ntohs(sp->s_port); 204169689Skan else 205169689Skan port = SSH_DEFAULT_PORT; 206169689Skan } 207169689Skan /* If a proxy command is given, connect using it. */ 208169689Skan if (proxy_command != NULL) 209169689Skan return ssh_proxy_connect(host, port, original_real_uid, proxy_command); 210169689Skan 211169689Skan /* No proxy command. */ 212169689Skan 213169689Skan memset(&hints, 0, sizeof(hints)); 214169689Skan hints.ai_family = IPv4or6; 215169689Skan hints.ai_socktype = SOCK_STREAM; 216169689Skan snprintf(strport, sizeof strport, "%d", port); 217169689Skan if ((gaierr = getaddrinfo(host, strport, &hints, &aitop)) != 0) 218169689Skan fatal("%s: %.100s: %s", __progname, host, 219169689Skan gai_strerror(gaierr)); 220169689Skan 221169689Skan /* 222169689Skan * Try to connect several times. On some machines, the first time 223169689Skan * will sometimes fail. In general socket code appears to behave 224169689Skan * quite magically on many machines. 225169689Skan */ 226169689Skan for (attempt = 0; attempt < connection_attempts; attempt++) { 227169689Skan if (attempt > 0) 228169689Skan debug("Trying again..."); 229169689Skan 230169689Skan /* Loop through addresses for this host, and try each one in 231169689Skan sequence until the connection succeeds. */ 232169689Skan for (ai = aitop; ai; ai = ai->ai_next) { 233169689Skan if (ai->ai_family != AF_INET && ai->ai_family != AF_INET6) 234169689Skan continue; 235169689Skan if (getnameinfo(ai->ai_addr, ai->ai_addrlen, 236169689Skan ntop, sizeof(ntop), strport, sizeof(strport), 237169689Skan NI_NUMERICHOST|NI_NUMERICSERV) != 0) { 238169689Skan error("ssh_connect: getnameinfo failed"); 239169689Skan continue; 240169689Skan } 241169689Skan debug("Connecting to %.200s [%.100s] port %s.", 242169689Skan host, ntop, strport); 243169689Skan 244169689Skan /* Create a socket for connecting. */ 245169689Skan sock = ssh_create_socket(original_real_uid, 246169689Skan !anonymous && geteuid() == 0 && port < IPPORT_RESERVED, 247169689Skan ai->ai_family); 248169689Skan if (sock < 0) 249169689Skan continue; 250169689Skan 251169689Skan /* Connect to the host. We use the user's uid in the 252169689Skan * hope that it will help with tcp_wrappers showing 253169689Skan * the remote uid as root. 254169689Skan */ 255169689Skan temporarily_use_uid(original_real_uid); 256169689Skan if (connect(sock, ai->ai_addr, ai->ai_addrlen) >= 0) { 257169689Skan /* Successful connection. */ 258169689Skan memcpy(hostaddr, ai->ai_addr, sizeof(*hostaddr)); 259169689Skan restore_uid(); 260169689Skan break; 261169689Skan } else { 262169689Skan debug("connect: %.100s", strerror(errno)); 263169689Skan restore_uid(); 264169689Skan /* 265169689Skan * Close the failed socket; there appear to 266169689Skan * be some problems when reusing a socket for 267169689Skan * which connect() has already returned an 268169689Skan * error. 269169689Skan */ 270169689Skan shutdown(sock, SHUT_RDWR); 271169689Skan close(sock); 272169689Skan } 273169689Skan } 274169689Skan if (ai) 275169689Skan break; /* Successful connection. */ 276169689Skan 277169689Skan /* Sleep a moment before retrying. */ 278169689Skan sleep(1); 279169689Skan } 280169689Skan 281169689Skan freeaddrinfo(aitop); 282169689Skan 283169689Skan /* Return failure if we didn't get a successful connection. */ 284169689Skan if (attempt >= connection_attempts) 285169689Skan return 0; 286169689Skan 287169689Skan debug("Connection established."); 288169689Skan 289169689Skan /* 290169689Skan * Set socket options. We would like the socket to disappear as soon 291169689Skan * as it has been closed for whatever reason. 292169689Skan */ 293169689Skan /* setsockopt(sock, SOL_SOCKET, SO_REUSEADDR, (void *)&on, sizeof(on)); */ 294169689Skan linger.l_onoff = 1; 295169689Skan linger.l_linger = 5; 296169689Skan setsockopt(sock, SOL_SOCKET, SO_LINGER, (void *) &linger, sizeof(linger)); 297169689Skan 298169689Skan /* Set the connection. */ 299169689Skan packet_set_connection(sock, sock); 300169689Skan 301169689Skan return 1; 302169689Skan} 303169689Skan 304169689Skan/* 305169689Skan * Checks if the user has an authentication agent, and if so, tries to 306169689Skan * authenticate using the agent. 307169689Skan */ 308169689Skanint 309169689Skantry_agent_authentication() 310169689Skan{ 311169689Skan int status, type; 312169689Skan char *comment; 313169689Skan AuthenticationConnection *auth; 314169689Skan unsigned char response[16]; 315169689Skan unsigned int i; 316169689Skan BIGNUM *e, *n, *challenge; 317169689Skan 318169689Skan /* Get connection to the agent. */ 319169689Skan auth = ssh_get_authentication_connection(); 320169689Skan if (!auth) 321169689Skan return 0; 322169689Skan 323169689Skan e = BN_new(); 324169689Skan n = BN_new(); 325169689Skan challenge = BN_new(); 326169689Skan 327169689Skan /* Loop through identities served by the agent. */ 328169689Skan for (status = ssh_get_first_identity(auth, e, n, &comment); 329169689Skan status; 330169689Skan status = ssh_get_next_identity(auth, e, n, &comment)) { 331169689Skan int plen, clen; 332169689Skan 333169689Skan /* Try this identity. */ 334169689Skan debug("Trying RSA authentication via agent with '%.100s'", comment); 335169689Skan xfree(comment); 336169689Skan 337169689Skan /* Tell the server that we are willing to authenticate using this key. */ 338169689Skan packet_start(SSH_CMSG_AUTH_RSA); 339169689Skan packet_put_bignum(n); 340169689Skan packet_send(); 341169689Skan packet_write_wait(); 342169689Skan 343169689Skan /* Wait for server's response. */ 344169689Skan type = packet_read(&plen); 345169689Skan 346169689Skan /* The server sends failure if it doesn\'t like our key or 347169689Skan does not support RSA authentication. */ 348169689Skan if (type == SSH_SMSG_FAILURE) { 349169689Skan debug("Server refused our key."); 350169689Skan continue; 351169689Skan } 352169689Skan /* Otherwise it should have sent a challenge. */ 353169689Skan if (type != SSH_SMSG_AUTH_RSA_CHALLENGE) 354169689Skan packet_disconnect("Protocol error during RSA authentication: %d", 355169689Skan type); 356169689Skan 357169689Skan packet_get_bignum(challenge, &clen); 358169689Skan 359169689Skan packet_integrity_check(plen, clen, type); 360169689Skan 361169689Skan debug("Received RSA challenge from server."); 362169689Skan 363169689Skan /* Ask the agent to decrypt the challenge. */ 364169689Skan if (!ssh_decrypt_challenge(auth, e, n, challenge, 365169689Skan session_id, 1, response)) { 366169689Skan /* The agent failed to authenticate this identifier although it 367169689Skan advertised it supports this. Just return a wrong value. */ 368169689Skan log("Authentication agent failed to decrypt challenge."); 369169689Skan memset(response, 0, sizeof(response)); 370169689Skan } 371169689Skan debug("Sending response to RSA challenge."); 372169689Skan 373169689Skan /* Send the decrypted challenge back to the server. */ 374169689Skan packet_start(SSH_CMSG_AUTH_RSA_RESPONSE); 375169689Skan for (i = 0; i < 16; i++) 376169689Skan packet_put_char(response[i]); 377169689Skan packet_send(); 378169689Skan packet_write_wait(); 379169689Skan 380169689Skan /* Wait for response from the server. */ 381169689Skan type = packet_read(&plen); 382169689Skan 383169689Skan /* The server returns success if it accepted the authentication. */ 384169689Skan if (type == SSH_SMSG_SUCCESS) { 385169689Skan debug("RSA authentication accepted by server."); 386169689Skan BN_clear_free(e); 387169689Skan BN_clear_free(n); 388169689Skan BN_clear_free(challenge); 389169689Skan return 1; 390169689Skan } 391169689Skan /* Otherwise it should return failure. */ 392169689Skan if (type != SSH_SMSG_FAILURE) 393169689Skan packet_disconnect("Protocol error waiting RSA auth response: %d", 394169689Skan type); 395169689Skan } 396169689Skan 397169689Skan BN_clear_free(e); 398169689Skan BN_clear_free(n); 399169689Skan BN_clear_free(challenge); 400169689Skan 401169689Skan debug("RSA authentication using agent refused."); 402169689Skan return 0; 403169689Skan} 404169689Skan 405169689Skan/* 406169689Skan * Computes the proper response to a RSA challenge, and sends the response to 407169689Skan * the server. 408169689Skan */ 409169689Skanvoid 410169689Skanrespond_to_rsa_challenge(BIGNUM * challenge, RSA * prv) 411169689Skan{ 412169689Skan unsigned char buf[32], response[16]; 413169689Skan MD5_CTX md; 414169689Skan int i, len; 415169689Skan 416169689Skan /* Decrypt the challenge using the private key. */ 417169689Skan rsa_private_decrypt(challenge, challenge, prv); 418169689Skan 419169689Skan /* Compute the response. */ 420169689Skan /* The response is MD5 of decrypted challenge plus session id. */ 421169689Skan len = BN_num_bytes(challenge); 422169689Skan if (len <= 0 || len > sizeof(buf)) 423169689Skan packet_disconnect("respond_to_rsa_challenge: bad challenge length %d", 424169689Skan len); 425169689Skan 426169689Skan memset(buf, 0, sizeof(buf)); 427169689Skan BN_bn2bin(challenge, buf + sizeof(buf) - len); 428169689Skan MD5_Init(&md); 429169689Skan MD5_Update(&md, buf, 32); 430169689Skan MD5_Update(&md, session_id, 16); 431169689Skan MD5_Final(response, &md); 432169689Skan 433169689Skan debug("Sending response to host key RSA challenge."); 434169689Skan 435169689Skan /* Send the response back to the server. */ 436169689Skan packet_start(SSH_CMSG_AUTH_RSA_RESPONSE); 437169689Skan for (i = 0; i < 16; i++) 438169689Skan packet_put_char(response[i]); 439169689Skan packet_send(); 440169689Skan packet_write_wait(); 441169689Skan 442169689Skan memset(buf, 0, sizeof(buf)); 443169689Skan memset(response, 0, sizeof(response)); 444169689Skan memset(&md, 0, sizeof(md)); 445169689Skan} 446169689Skan 447169689Skan/* 448169689Skan * Checks if the user has authentication file, and if so, tries to authenticate 449169689Skan * the user using it. 450169689Skan */ 451169689Skanint 452169689Skantry_rsa_authentication(const char *authfile) 453169689Skan{ 454169689Skan BIGNUM *challenge; 455169689Skan RSA *private_key; 456169689Skan RSA *public_key; 457169689Skan char *passphrase, *comment; 458169689Skan int type, i; 459169689Skan int plen, clen; 460169689Skan 461169689Skan /* Try to load identification for the authentication key. */ 462169689Skan public_key = RSA_new(); 463169689Skan if (!load_public_key(authfile, public_key, &comment)) { 464169689Skan RSA_free(public_key); 465169689Skan /* Could not load it. Fail. */ 466169689Skan return 0; 467169689Skan } 468169689Skan debug("Trying RSA authentication with key '%.100s'", comment); 469169689Skan 470169689Skan /* Tell the server that we are willing to authenticate using this key. */ 471169689Skan packet_start(SSH_CMSG_AUTH_RSA); 472169689Skan packet_put_bignum(public_key->n); 473169689Skan packet_send(); 474169689Skan packet_write_wait(); 475169689Skan 476169689Skan /* We no longer need the public key. */ 477169689Skan RSA_free(public_key); 478169689Skan 479169689Skan /* Wait for server's response. */ 480169689Skan type = packet_read(&plen); 481169689Skan 482169689Skan /* 483169689Skan * The server responds with failure if it doesn\'t like our key or 484169689Skan * doesn\'t support RSA authentication. 485169689Skan */ 486169689Skan if (type == SSH_SMSG_FAILURE) { 487169689Skan debug("Server refused our key."); 488169689Skan xfree(comment); 489169689Skan return 0; 490169689Skan } 491169689Skan /* Otherwise, the server should respond with a challenge. */ 492169689Skan if (type != SSH_SMSG_AUTH_RSA_CHALLENGE) 493169689Skan packet_disconnect("Protocol error during RSA authentication: %d", type); 494169689Skan 495169689Skan /* Get the challenge from the packet. */ 496169689Skan challenge = BN_new(); 497169689Skan packet_get_bignum(challenge, &clen); 498169689Skan 499169689Skan packet_integrity_check(plen, clen, type); 500169689Skan 501169689Skan debug("Received RSA challenge from server."); 502169689Skan 503169689Skan private_key = RSA_new(); 504169689Skan /* 505169689Skan * Load the private key. Try first with empty passphrase; if it 506169689Skan * fails, ask for a passphrase. 507169689Skan */ 508169689Skan if (!load_private_key(authfile, "", private_key, NULL)) { 509169689Skan char buf[300]; 510169689Skan snprintf(buf, sizeof buf, "Enter passphrase for RSA key '%.100s': ", 511169689Skan comment); 512169689Skan if (!options.batch_mode) 513169689Skan passphrase = read_passphrase(buf, 0); 514169689Skan else { 515169689Skan debug("Will not query passphrase for %.100s in batch mode.", 516169689Skan comment); 517169689Skan passphrase = xstrdup(""); 518169689Skan } 519169689Skan 520169689Skan /* Load the authentication file using the pasphrase. */ 521169689Skan if (!load_private_key(authfile, passphrase, private_key, NULL)) { 522169689Skan memset(passphrase, 0, strlen(passphrase)); 523169689Skan xfree(passphrase); 524169689Skan error("Bad passphrase."); 525169689Skan 526169689Skan /* Send a dummy response packet to avoid protocol error. */ 527169689Skan packet_start(SSH_CMSG_AUTH_RSA_RESPONSE); 528169689Skan for (i = 0; i < 16; i++) 529169689Skan packet_put_char(0); 530169689Skan packet_send(); 531169689Skan packet_write_wait(); 532169689Skan 533169689Skan /* Expect the server to reject it... */ 534169689Skan packet_read_expect(&plen, SSH_SMSG_FAILURE); 535169689Skan xfree(comment); 536169689Skan return 0; 537169689Skan } 538169689Skan /* Destroy the passphrase. */ 539169689Skan memset(passphrase, 0, strlen(passphrase)); 540169689Skan xfree(passphrase); 541169689Skan } 542169689Skan /* We no longer need the comment. */ 543169689Skan xfree(comment); 544169689Skan 545169689Skan /* Compute and send a response to the challenge. */ 546169689Skan respond_to_rsa_challenge(challenge, private_key); 547169689Skan 548169689Skan /* Destroy the private key. */ 549169689Skan RSA_free(private_key); 550169689Skan 551169689Skan /* We no longer need the challenge. */ 552169689Skan BN_clear_free(challenge); 553169689Skan 554169689Skan /* Wait for response from the server. */ 555169689Skan type = packet_read(&plen); 556169689Skan if (type == SSH_SMSG_SUCCESS) { 557169689Skan debug("RSA authentication accepted by server."); 558169689Skan return 1; 559169689Skan } 560169689Skan if (type != SSH_SMSG_FAILURE) 561169689Skan packet_disconnect("Protocol error waiting RSA auth response: %d", type); 562169689Skan debug("RSA authentication refused."); 563169689Skan return 0; 564169689Skan} 565169689Skan 566169689Skan/* 567169689Skan * Tries to authenticate the user using combined rhosts or /etc/hosts.equiv 568169689Skan * authentication and RSA host authentication. 569169689Skan */ 570169689Skanint 571169689Skantry_rhosts_rsa_authentication(const char *local_user, RSA * host_key) 572169689Skan{ 573169689Skan int type; 574169689Skan BIGNUM *challenge; 575169689Skan int plen, clen; 576169689Skan 577169689Skan debug("Trying rhosts or /etc/hosts.equiv with RSA host authentication."); 578169689Skan 579169689Skan /* Tell the server that we are willing to authenticate using this key. */ 580169689Skan packet_start(SSH_CMSG_AUTH_RHOSTS_RSA); 581169689Skan packet_put_string(local_user, strlen(local_user)); 582169689Skan packet_put_int(BN_num_bits(host_key->n)); 583169689Skan packet_put_bignum(host_key->e); 584169689Skan packet_put_bignum(host_key->n); 585169689Skan packet_send(); 586169689Skan packet_write_wait(); 587169689Skan 588169689Skan /* Wait for server's response. */ 589169689Skan type = packet_read(&plen); 590169689Skan 591169689Skan /* The server responds with failure if it doesn't admit our 592169689Skan .rhosts authentication or doesn't know our host key. */ 593169689Skan if (type == SSH_SMSG_FAILURE) { 594169689Skan debug("Server refused our rhosts authentication or host key."); 595169689Skan return 0; 596169689Skan } 597169689Skan /* Otherwise, the server should respond with a challenge. */ 598169689Skan if (type != SSH_SMSG_AUTH_RSA_CHALLENGE) 599169689Skan packet_disconnect("Protocol error during RSA authentication: %d", type); 600169689Skan 601169689Skan /* Get the challenge from the packet. */ 602169689Skan challenge = BN_new(); 603169689Skan packet_get_bignum(challenge, &clen); 604169689Skan 605169689Skan packet_integrity_check(plen, clen, type); 606169689Skan 607169689Skan debug("Received RSA challenge for host key from server."); 608169689Skan 609169689Skan /* Compute a response to the challenge. */ 610169689Skan respond_to_rsa_challenge(challenge, host_key); 611169689Skan 612169689Skan /* We no longer need the challenge. */ 613169689Skan BN_clear_free(challenge); 614169689Skan 615169689Skan /* Wait for response from the server. */ 616169689Skan type = packet_read(&plen); 617169689Skan if (type == SSH_SMSG_SUCCESS) { 618169689Skan debug("Rhosts or /etc/hosts.equiv with RSA host authentication accepted by server."); 619169689Skan return 1; 620169689Skan } 621169689Skan if (type != SSH_SMSG_FAILURE) 622169689Skan packet_disconnect("Protocol error waiting RSA auth response: %d", type); 623169689Skan debug("Rhosts or /etc/hosts.equiv with RSA host authentication refused."); 624169689Skan return 0; 625169689Skan} 626169689Skan 627169689Skan#ifdef KRB4 628169689Skanint 629169689Skantry_kerberos_authentication() 630169689Skan{ 631169689Skan KTEXT_ST auth; /* Kerberos data */ 632169689Skan char *reply; 633169689Skan char inst[INST_SZ]; 634169689Skan char *realm; 635169689Skan CREDENTIALS cred; 636169689Skan int r, type, plen; 637169689Skan Key_schedule schedule; 638169689Skan u_long checksum, cksum; 639169689Skan MSG_DAT msg_data; 640169689Skan struct sockaddr_in local, foreign; 641169689Skan struct stat st; 642169689Skan 643169689Skan /* Don't do anything if we don't have any tickets. */ 644169689Skan if (stat(tkt_string(), &st) < 0) 645169689Skan return 0; 646169689Skan 647169689Skan strncpy(inst, (char *) krb_get_phost(get_canonical_hostname()), INST_SZ); 648169689Skan 649169689Skan realm = (char *) krb_realmofhost(get_canonical_hostname()); 650169689Skan if (!realm) { 651169689Skan debug("Kerberos V4: no realm for %s", get_canonical_hostname()); 652169689Skan return 0; 653169689Skan } 654169689Skan /* This can really be anything. */ 655169689Skan checksum = (u_long) getpid(); 656169689Skan 657169689Skan r = krb_mk_req(&auth, KRB4_SERVICE_NAME, inst, realm, checksum); 658169689Skan if (r != KSUCCESS) { 659169689Skan debug("Kerberos V4 krb_mk_req failed: %s", krb_err_txt[r]); 660169689Skan return 0; 661169689Skan } 662169689Skan /* Get session key to decrypt the server's reply with. */ 663169689Skan r = krb_get_cred(KRB4_SERVICE_NAME, inst, realm, &cred); 664169689Skan if (r != KSUCCESS) { 665169689Skan debug("get_cred failed: %s", krb_err_txt[r]); 666169689Skan return 0; 667169689Skan } 668169689Skan des_key_sched((des_cblock *) cred.session, schedule); 669169689Skan 670169689Skan /* Send authentication info to server. */ 671169689Skan packet_start(SSH_CMSG_AUTH_KERBEROS); 672169689Skan packet_put_string((char *) auth.dat, auth.length); 673169689Skan packet_send(); 674169689Skan packet_write_wait(); 675169689Skan 676169689Skan /* Zero the buffer. */ 677169689Skan (void) memset(auth.dat, 0, MAX_KTXT_LEN); 678169689Skan 679169689Skan r = sizeof(local); 680169689Skan memset(&local, 0, sizeof(local)); 681169689Skan if (getsockname(packet_get_connection_in(), 682169689Skan (struct sockaddr *) & local, &r) < 0) 683169689Skan debug("getsockname failed: %s", strerror(errno)); 684169689Skan 685169689Skan r = sizeof(foreign); 686169689Skan memset(&foreign, 0, sizeof(foreign)); 687169689Skan if (getpeername(packet_get_connection_in(), 688169689Skan (struct sockaddr *) & foreign, &r) < 0) { 689169689Skan debug("getpeername failed: %s", strerror(errno)); 690169689Skan fatal_cleanup(); 691169689Skan } 692169689Skan /* Get server reply. */ 693169689Skan type = packet_read(&plen); 694169689Skan switch (type) { 695169689Skan case SSH_SMSG_FAILURE: 696169689Skan /* Should really be SSH_SMSG_AUTH_KERBEROS_FAILURE */ 697169689Skan debug("Kerberos V4 authentication failed."); 698169689Skan return 0; 699169689Skan break; 700169689Skan 701169689Skan case SSH_SMSG_AUTH_KERBEROS_RESPONSE: 702169689Skan /* SSH_SMSG_AUTH_KERBEROS_SUCCESS */ 703169689Skan debug("Kerberos V4 authentication accepted."); 704169689Skan 705169689Skan /* Get server's response. */ 706169689Skan reply = packet_get_string((unsigned int *) &auth.length); 707169689Skan memcpy(auth.dat, reply, auth.length); 708169689Skan xfree(reply); 709169689Skan 710169689Skan packet_integrity_check(plen, 4 + auth.length, type); 711169689Skan 712169689Skan /* 713169689Skan * If his response isn't properly encrypted with the session 714169689Skan * key, and the decrypted checksum fails to match, he's 715169689Skan * bogus. Bail out. 716169689Skan */ 717169689Skan r = krb_rd_priv(auth.dat, auth.length, schedule, &cred.session, 718169689Skan &foreign, &local, &msg_data); 719169689Skan if (r != KSUCCESS) { 720169689Skan debug("Kerberos V4 krb_rd_priv failed: %s", krb_err_txt[r]); 721169689Skan packet_disconnect("Kerberos V4 challenge failed!"); 722169689Skan } 723169689Skan /* Fetch the (incremented) checksum that we supplied in the request. */ 724169689Skan (void) memcpy((char *) &cksum, (char *) msg_data.app_data, sizeof(cksum)); 725169689Skan cksum = ntohl(cksum); 726169689Skan 727169689Skan /* If it matches, we're golden. */ 728169689Skan if (cksum == checksum + 1) { 729169689Skan debug("Kerberos V4 challenge successful."); 730169689Skan return 1; 731169689Skan } else 732169689Skan packet_disconnect("Kerberos V4 challenge failed!"); 733169689Skan break; 734169689Skan 735169689Skan default: 736169689Skan packet_disconnect("Protocol error on Kerberos V4 response: %d", type); 737169689Skan } 738169689Skan return 0; 739169689Skan} 740169689Skan 741169689Skan#endif /* KRB4 */ 742169689Skan 743169689Skan#ifdef AFS 744169689Skanint 745169689Skansend_kerberos_tgt() 746169689Skan{ 747169689Skan CREDENTIALS *creds; 748169689Skan char pname[ANAME_SZ], pinst[INST_SZ], prealm[REALM_SZ]; 749169689Skan int r, type, plen; 750169689Skan unsigned char buffer[8192]; 751169689Skan struct stat st; 752169689Skan 753169689Skan /* Don't do anything if we don't have any tickets. */ 754169689Skan if (stat(tkt_string(), &st) < 0) 755169689Skan return 0; 756169689Skan 757169689Skan creds = xmalloc(sizeof(*creds)); 758169689Skan 759169689Skan if ((r = krb_get_tf_fullname(TKT_FILE, pname, pinst, prealm)) != KSUCCESS) { 760169689Skan debug("Kerberos V4 tf_fullname failed: %s", krb_err_txt[r]); 761169689Skan return 0; 762169689Skan } 763169689Skan if ((r = krb_get_cred("krbtgt", prealm, prealm, creds)) != GC_OK) { 764169689Skan debug("Kerberos V4 get_cred failed: %s", krb_err_txt[r]); 765169689Skan return 0; 766169689Skan } 767169689Skan if (time(0) > krb_life_to_time(creds->issue_date, creds->lifetime)) { 768169689Skan debug("Kerberos V4 ticket expired: %s", TKT_FILE); 769169689Skan return 0; 770169689Skan } 771169689Skan creds_to_radix(creds, buffer); 772169689Skan xfree(creds); 773169689Skan 774169689Skan packet_start(SSH_CMSG_HAVE_KERBEROS_TGT); 775169689Skan packet_put_string((char *) buffer, strlen(buffer)); 776169689Skan packet_send(); 777169689Skan packet_write_wait(); 778169689Skan 779169689Skan type = packet_read(&plen); 780169689Skan 781169689Skan if (type == SSH_SMSG_FAILURE) 782169689Skan debug("Kerberos TGT for realm %s rejected.", prealm); 783169689Skan else if (type != SSH_SMSG_SUCCESS) 784169689Skan packet_disconnect("Protocol error on Kerberos TGT response: %d", type); 785169689Skan 786169689Skan return 1; 787169689Skan} 788169689Skan 789169689Skanvoid 790169689Skansend_afs_tokens(void) 791169689Skan{ 792169689Skan CREDENTIALS creds; 793169689Skan struct ViceIoctl parms; 794169689Skan struct ClearToken ct; 795169689Skan int i, type, len, plen; 796169689Skan char buf[2048], *p, *server_cell; 797169689Skan unsigned char buffer[8192]; 798169689Skan 799169689Skan /* Move over ktc_GetToken, here's something leaner. */ 800169689Skan for (i = 0; i < 100; i++) { /* just in case */ 801169689Skan parms.in = (char *) &i; 802169689Skan parms.in_size = sizeof(i); 803169689Skan parms.out = buf; 804169689Skan parms.out_size = sizeof(buf); 805169689Skan if (k_pioctl(0, VIOCGETTOK, &parms, 0) != 0) 806169689Skan break; 807169689Skan p = buf; 808169689Skan 809169689Skan /* Get secret token. */ 810169689Skan memcpy(&creds.ticket_st.length, p, sizeof(unsigned int)); 811169689Skan if (creds.ticket_st.length > MAX_KTXT_LEN) 812169689Skan break; 813169689Skan p += sizeof(unsigned int); 814169689Skan memcpy(creds.ticket_st.dat, p, creds.ticket_st.length); 815169689Skan p += creds.ticket_st.length; 816169689Skan 817169689Skan /* Get clear token. */ 818169689Skan memcpy(&len, p, sizeof(len)); 819169689Skan if (len != sizeof(struct ClearToken)) 820169689Skan break; 821169689Skan p += sizeof(len); 822169689Skan memcpy(&ct, p, len); 823169689Skan p += len; 824169689Skan p += sizeof(len); /* primary flag */ 825169689Skan server_cell = p; 826169689Skan 827169689Skan /* Flesh out our credentials. */ 828169689Skan strlcpy(creds.service, "afs", sizeof creds.service); 829169689Skan creds.instance[0] = '\0'; 830169689Skan strlcpy(creds.realm, server_cell, REALM_SZ); 831169689Skan memcpy(creds.session, ct.HandShakeKey, DES_KEY_SZ); 832169689Skan creds.issue_date = ct.BeginTimestamp; 833169689Skan creds.lifetime = krb_time_to_life(creds.issue_date, ct.EndTimestamp); 834169689Skan creds.kvno = ct.AuthHandle; 835169689Skan snprintf(creds.pname, sizeof(creds.pname), "AFS ID %d", ct.ViceId); 836169689Skan creds.pinst[0] = '\0'; 837169689Skan 838169689Skan /* Encode token, ship it off. */ 839169689Skan if (!creds_to_radix(&creds, buffer)) 840169689Skan break; 841169689Skan packet_start(SSH_CMSG_HAVE_AFS_TOKEN); 842169689Skan packet_put_string((char *) buffer, strlen(buffer)); 843169689Skan packet_send(); 844169689Skan packet_write_wait(); 845169689Skan 846169689Skan /* Roger, Roger. Clearance, Clarence. What's your vector, 847169689Skan Victor? */ 848169689Skan type = packet_read(&plen); 849169689Skan 850169689Skan if (type == SSH_SMSG_FAILURE) 851169689Skan debug("AFS token for cell %s rejected.", server_cell); 852169689Skan else if (type != SSH_SMSG_SUCCESS) 853169689Skan packet_disconnect("Protocol error on AFS token response: %d", type); 854169689Skan } 855169689Skan} 856169689Skan 857169689Skan#endif /* AFS */ 858169689Skan 859169689Skan/* 860169689Skan * Tries to authenticate with any string-based challenge/response system. 861169689Skan * Note that the client code is not tied to s/key or TIS. 862169689Skan */ 863169689Skanint 864169689Skantry_skey_authentication() 865169689Skan{ 866169689Skan int type, i, payload_len; 867169689Skan char *challenge, *response; 868169689Skan 869169689Skan debug("Doing skey authentication."); 870169689Skan 871169689Skan /* request a challenge */ 872169689Skan packet_start(SSH_CMSG_AUTH_TIS); 873169689Skan packet_send(); 874169689Skan packet_write_wait(); 875169689Skan 876169689Skan type = packet_read(&payload_len); 877169689Skan if (type != SSH_SMSG_FAILURE && 878169689Skan type != SSH_SMSG_AUTH_TIS_CHALLENGE) { 879169689Skan packet_disconnect("Protocol error: got %d in response " 880169689Skan "to skey-auth", type); 881169689Skan } 882169689Skan if (type != SSH_SMSG_AUTH_TIS_CHALLENGE) { 883169689Skan debug("No challenge for skey authentication."); 884169689Skan return 0; 885169689Skan } 886169689Skan challenge = packet_get_string(&payload_len); 887169689Skan if (options.cipher == SSH_CIPHER_NONE) 888169689Skan log("WARNING: Encryption is disabled! " 889169689Skan "Reponse will be transmitted in clear text."); 890169689Skan fprintf(stderr, "%s\n", challenge); 891169689Skan xfree(challenge); 892169689Skan fflush(stderr); 893169689Skan for (i = 0; i < options.number_of_password_prompts; i++) { 894169689Skan if (i != 0) 895169689Skan error("Permission denied, please try again."); 896169689Skan response = read_passphrase("Response: ", 0); 897169689Skan packet_start(SSH_CMSG_AUTH_TIS_RESPONSE); 898169689Skan packet_put_string(response, strlen(response)); 899169689Skan memset(response, 0, strlen(response)); 900169689Skan xfree(response); 901169689Skan packet_send(); 902169689Skan packet_write_wait(); 903169689Skan type = packet_read(&payload_len); 904169689Skan if (type == SSH_SMSG_SUCCESS) 905169689Skan return 1; 906169689Skan if (type != SSH_SMSG_FAILURE) 907169689Skan packet_disconnect("Protocol error: got %d in response " 908169689Skan "to skey-auth-reponse", type); 909169689Skan } 910169689Skan /* failure */ 911169689Skan return 0; 912169689Skan} 913169689Skan 914169689Skan/* 915220150Smm * Tries to authenticate with plain passwd authentication. 916220150Smm */ 917220150Smmint 918220150Smmtry_password_authentication(char *prompt) 919220150Smm{ 920220150Smm int type, i, payload_len; 921220150Smm char *password; 922220150Smm 923220150Smm debug("Doing password authentication."); 924220150Smm if (options.cipher == SSH_CIPHER_NONE) 925220150Smm log("WARNING: Encryption is disabled! Password will be transmitted in clear text."); 926220150Smm for (i = 0; i < options.number_of_password_prompts; i++) { 927220150Smm if (i != 0) 928220150Smm error("Permission denied, please try again."); 929220150Smm password = read_passphrase(prompt, 0); 930220150Smm packet_start(SSH_CMSG_AUTH_PASSWORD); 931220150Smm packet_put_string(password, strlen(password)); 932220150Smm memset(password, 0, strlen(password)); 933220150Smm xfree(password); 934220150Smm packet_send(); 935220150Smm packet_write_wait(); 936220150Smm 937220150Smm type = packet_read(&payload_len); 938220150Smm if (type == SSH_SMSG_SUCCESS) 939220150Smm return 1; 940220150Smm if (type != SSH_SMSG_FAILURE) 941220150Smm packet_disconnect("Protocol error: got %d in response to passwd auth", type); 942220150Smm } 943220150Smm /* failure */ 944220150Smm return 0; 945220150Smm} 946220150Smm 947220150Smm/* 948220150Smm * Waits for the server identification string, and sends our own 949220150Smm * identification string. 950220150Smm */ 951220150Smmvoid 952220150Smmssh_exchange_identification() 953220150Smm{ 954220150Smm char buf[256], remote_version[256]; /* must be same size! */ 955220150Smm int remote_major, remote_minor, i; 956220150Smm int connection_in = packet_get_connection_in(); 957220150Smm int connection_out = packet_get_connection_out(); 958220150Smm 959220150Smm /* Read other side\'s version identification. */ 960220150Smm for (i = 0; i < sizeof(buf) - 1; i++) { 961220150Smm int len = read(connection_in, &buf[i], 1); 962220150Smm if (len < 0) 963220150Smm fatal("ssh_exchange_identification: read: %.100s", strerror(errno)); 964220150Smm if (len != 1) 965220150Smm fatal("ssh_exchange_identification: Connection closed by remote host"); 966169689Skan if (buf[i] == '\r') { 967169689Skan buf[i] = '\n'; 968169689Skan buf[i + 1] = 0; 969169689Skan break; 970169689Skan } 971169689Skan if (buf[i] == '\n') { 972169689Skan buf[i + 1] = 0; 973169689Skan break; 974169689Skan } 975169689Skan } 976169689Skan buf[sizeof(buf) - 1] = 0; 977169689Skan 978169689Skan /* 979169689Skan * Check that the versions match. In future this might accept 980169689Skan * several versions and set appropriate flags to handle them. 981169689Skan */ 982169689Skan if (sscanf(buf, "SSH-%d.%d-%[^\n]\n", &remote_major, &remote_minor, 983169689Skan remote_version) != 3) 984169689Skan fatal("Bad remote protocol version identification: '%.100s'", buf); 985169689Skan debug("Remote protocol version %d.%d, remote software version %.100s", 986169689Skan remote_major, remote_minor, remote_version); 987169689Skan 988169689Skan /* Check if the remote protocol version is too old. */ 989169689Skan if (remote_major == 1 && remote_minor < 3) 990169689Skan fatal("Remote machine has too old SSH software version."); 991169689Skan 992169689Skan /* We speak 1.3, too. */ 993169689Skan if (remote_major == 1 && remote_minor == 3) { 994169689Skan enable_compat13(); 995169689Skan if (options.forward_agent) { 996169689Skan log("Agent forwarding disabled for protocol 1.3"); 997169689Skan options.forward_agent = 0; 998169689Skan } 999169689Skan } 1000169689Skan#if 0 1001169689Skan /* 1002169689Skan * Removed for now, to permit compatibility with latter versions. The 1003169689Skan * server will reject our version and disconnect if it doesn't 1004169689Skan * support it. 1005169689Skan */ 1006169689Skan if (remote_major != PROTOCOL_MAJOR) 1007169689Skan fatal("Protocol major versions differ: %d vs. %d", 1008169689Skan PROTOCOL_MAJOR, remote_major); 1009169689Skan#endif 1010169689Skan 1011169689Skan /* Send our own protocol version identification. */ 1012169689Skan snprintf(buf, sizeof buf, "SSH-%d.%d-%.100s\n", 1013169689Skan PROTOCOL_MAJOR, PROTOCOL_MINOR, SSH_VERSION); 1014169689Skan if (atomicio(write, connection_out, buf, strlen(buf)) != strlen(buf)) 1015169689Skan fatal("write: %.100s", strerror(errno)); 1016169689Skan} 1017169689Skan 1018169689Skanint ssh_cipher_default = SSH_CIPHER_3DES; 1019169689Skan 1020169689Skanint 1021169689Skanread_yes_or_no(const char *prompt, int defval) 1022169689Skan{ 1023169689Skan char buf[1024]; 1024169689Skan FILE *f; 1025169689Skan int retval = -1; 1026169689Skan 1027169689Skan if (isatty(0)) 1028169689Skan f = stdin; 1029169689Skan else 1030169689Skan f = fopen("/dev/tty", "rw"); 1031169689Skan 1032169689Skan if (f == NULL) 1033169689Skan return 0; 1034169689Skan 1035169689Skan fflush(stdout); 1036169689Skan 1037169689Skan while (1) { 1038169689Skan fprintf(stderr, "%s", prompt); 1039169689Skan if (fgets(buf, sizeof(buf), f) == NULL) { 1040169689Skan /* Print a newline (the prompt probably didn\'t have one). */ 1041169689Skan fprintf(stderr, "\n"); 1042169689Skan strlcpy(buf, "no", sizeof buf); 1043169689Skan } 1044169689Skan /* Remove newline from response. */ 1045169689Skan if (strchr(buf, '\n')) 1046169689Skan *strchr(buf, '\n') = 0; 1047169689Skan 1048169689Skan if (buf[0] == 0) 1049169689Skan retval = defval; 1050169689Skan if (strcmp(buf, "yes") == 0) 1051169689Skan retval = 1; 1052169689Skan if (strcmp(buf, "no") == 0) 1053169689Skan retval = 0; 1054169689Skan 1055169689Skan if (retval != -1) { 1056169689Skan if (f != stdin) 1057169689Skan fclose(f); 1058169689Skan return retval; 1059169689Skan } 1060169689Skan } 1061169689Skan} 1062169689Skan 1063169689Skan/* 1064169689Skan * check whether the supplied host key is valid, return only if ok. 1065169689Skan */ 1066169689Skan 1067169689Skanvoid 1068169689Skancheck_host_key(char *host, struct sockaddr *hostaddr, RSA *host_key) 1069169689Skan{ 1070169689Skan RSA *file_key; 1071169689Skan char *ip = NULL; 1072169689Skan char hostline[1000], *hostp; 1073169689Skan HostStatus host_status; 1074169689Skan HostStatus ip_status; 1075169689Skan int local = 0, host_ip_differ = 0; 1076169689Skan char ntop[NI_MAXHOST]; 1077169689Skan 1078169689Skan /* 1079169689Skan * Force accepting of the host key for loopback/localhost. The 1080169689Skan * problem is that if the home directory is NFS-mounted to multiple 1081169689Skan * machines, localhost will refer to a different machine in each of 1082169689Skan * them, and the user will get bogus HOST_CHANGED warnings. This 1083169689Skan * essentially disables host authentication for localhost; however, 1084169689Skan * this is probably not a real problem. 1085169689Skan */ 1086169689Skan switch (hostaddr->sa_family) { 1087169689Skan case AF_INET: 1088169689Skan local = (ntohl(((struct sockaddr_in *)hostaddr)->sin_addr.s_addr) >> 24) == IN_LOOPBACKNET; 1089169689Skan break; 1090169689Skan#ifdef INET6 1091169689Skan case AF_INET6: 1092169689Skan local = IN6_IS_ADDR_LOOPBACK(&(((struct sockaddr_in6 *)hostaddr)->sin6_addr)); 1093169689Skan break; 1094169689Skan#endif 1095169689Skan default: 1096169689Skan local = 0; 1097169689Skan break; 1098169689Skan } 1099169689Skan if (local) { 1100169689Skan debug("Forcing accepting of host key for loopback/localhost."); 1101169689Skan return; 1102169689Skan } 1103169689Skan 1104169689Skan /* 1105169689Skan * Turn off check_host_ip for proxy connects, since 1106169689Skan * we don't have the remote ip-address 1107169689Skan */ 1108169689Skan if (options.proxy_command != NULL && options.check_host_ip) 1109169689Skan options.check_host_ip = 0; 1110169689Skan 1111220150Smm if (options.check_host_ip) { 1112220150Smm if (getnameinfo(hostaddr, hostaddr->sa_len, ntop, sizeof(ntop), 1113220150Smm NULL, 0, NI_NUMERICHOST) != 0) 1114220150Smm fatal("check_host_key: getnameinfo failed"); 1115220150Smm ip = xstrdup(ntop); 1116169689Skan } 1117169689Skan 1118169689Skan /* 1119169689Skan * Store the host key from the known host file in here so that we can 1120169689Skan * compare it with the key for the IP address. 1121169689Skan */ 1122169689Skan file_key = RSA_new(); 1123169689Skan file_key->n = BN_new(); 1124169689Skan file_key->e = BN_new(); 1125169689Skan 1126169689Skan /* 1127169689Skan * Check if the host key is present in the user\'s list of known 1128169689Skan * hosts or in the systemwide list. 1129169689Skan */ 1130169689Skan host_status = check_host_in_hostfile(options.user_hostfile, host, 1131169689Skan host_key->e, host_key->n, 1132169689Skan file_key->e, file_key->n); 1133169689Skan if (host_status == HOST_NEW) 1134169689Skan host_status = check_host_in_hostfile(options.system_hostfile, host, 1135169689Skan host_key->e, host_key->n, 1136169689Skan file_key->e, file_key->n); 1137169689Skan /* 1138169689Skan * Also perform check for the ip address, skip the check if we are 1139169689Skan * localhost or the hostname was an ip address to begin with 1140169689Skan */ 1141169689Skan if (options.check_host_ip && !local && strcmp(host, ip)) { 1142169689Skan RSA *ip_key = RSA_new(); 1143169689Skan ip_key->n = BN_new(); 1144169689Skan ip_key->e = BN_new(); 1145169689Skan ip_status = check_host_in_hostfile(options.user_hostfile, ip, 1146169689Skan host_key->e, host_key->n, 1147169689Skan ip_key->e, ip_key->n); 1148169689Skan 1149169689Skan if (ip_status == HOST_NEW) 1150169689Skan ip_status = check_host_in_hostfile(options.system_hostfile, ip, 1151169689Skan host_key->e, host_key->n, 1152169689Skan ip_key->e, ip_key->n); 1153169689Skan if (host_status == HOST_CHANGED && 1154169689Skan (ip_status != HOST_CHANGED || 1155169689Skan (BN_cmp(ip_key->e, file_key->e) || BN_cmp(ip_key->n, file_key->n)))) 1156169689Skan host_ip_differ = 1; 1157169689Skan 1158169689Skan RSA_free(ip_key); 1159169689Skan } else 1160169689Skan ip_status = host_status; 1161169689Skan 1162169689Skan RSA_free(file_key); 1163169689Skan 1164169689Skan switch (host_status) { 1165169689Skan case HOST_OK: 1166169689Skan /* The host is known and the key matches. */ 1167169689Skan debug("Host '%.200s' is known and matches the host key.", host); 1168169689Skan if (options.check_host_ip) { 1169169689Skan if (ip_status == HOST_NEW) { 1170169689Skan if (!add_host_to_hostfile(options.user_hostfile, ip, 1171169689Skan host_key->e, host_key->n)) 1172169689Skan log("Failed to add the host key for IP address '%.30s' to the list of known hosts (%.30s).", 1173169689Skan ip, options.user_hostfile); 1174169689Skan else 1175169689Skan log("Warning: Permanently added host key for IP address '%.30s' to the list of known hosts.", 1176169689Skan ip); 1177169689Skan } else if (ip_status != HOST_OK) 1178169689Skan log("Warning: the host key for '%.200s' differs from the key for the IP address '%.30s'", 1179169689Skan host, ip); 1180169689Skan } 1181169689Skan break; 1182169689Skan case HOST_NEW: 1183169689Skan /* The host is new. */ 1184169689Skan if (options.strict_host_key_checking == 1) { 1185169689Skan /* User has requested strict host key checking. We will not add the host key 1186169689Skan automatically. The only alternative left is to abort. */ 1187169689Skan fatal("No host key is known for %.200s and you have requested strict checking.", host); 1188169689Skan } else if (options.strict_host_key_checking == 2) { 1189169689Skan /* The default */ 1190169689Skan char prompt[1024]; 1191169689Skan char *fp = fingerprint(host_key->e, host_key->n); 1192169689Skan snprintf(prompt, sizeof(prompt), 1193169689Skan "The authenticity of host '%.200s' can't be established.\n" 1194169689Skan "Key fingerprint is %d %s.\n" 1195169689Skan "Are you sure you want to continue connecting (yes/no)? ", 1196169689Skan host, BN_num_bits(host_key->n), fp); 1197169689Skan if (!read_yes_or_no(prompt, -1)) 1198169689Skan fatal("Aborted by user!\n"); 1199169689Skan } 1200169689Skan if (options.check_host_ip && ip_status == HOST_NEW && strcmp(host, ip)) { 1201169689Skan snprintf(hostline, sizeof(hostline), "%s,%s", host, ip); 1202169689Skan hostp = hostline; 1203169689Skan } else 1204169689Skan hostp = host; 1205169689Skan 1206169689Skan /* If not in strict mode, add the key automatically to the local known_hosts file. */ 1207169689Skan if (!add_host_to_hostfile(options.user_hostfile, hostp, 1208169689Skan host_key->e, host_key->n)) 1209169689Skan log("Failed to add the host to the list of known hosts (%.500s).", 1210169689Skan options.user_hostfile); 1211169689Skan else 1212169689Skan log("Warning: Permanently added '%.200s' to the list of known hosts.", 1213169689Skan hostp); 1214169689Skan break; 1215169689Skan case HOST_CHANGED: 1216169689Skan if (options.check_host_ip && host_ip_differ) { 1217169689Skan char *msg; 1218169689Skan if (ip_status == HOST_NEW) 1219169689Skan msg = "is unknown"; 1220169689Skan else if (ip_status == HOST_OK) 1221169689Skan msg = "is unchanged"; 1222169689Skan else 1223169689Skan msg = "has a different value"; 1224169689Skan error("@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@"); 1225169689Skan error("@ WARNING: POSSIBLE DNS SPOOFING DETECTED! @"); 1226169689Skan error("@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@"); 1227169689Skan error("The host key for %s has changed,", host); 1228169689Skan error("and the key for the according IP address %s", ip); 1229169689Skan error("%s. This could either mean that", msg); 1230169689Skan error("DNS SPOOFING is happening or the IP address for the host"); 1231169689Skan error("and its host key have changed at the same time"); 1232169689Skan } 1233169689Skan /* The host key has changed. */ 1234169689Skan error("@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@"); 1235169689Skan error("@ WARNING: REMOTE HOST IDENTIFICATION HAS CHANGED! @"); 1236169689Skan error("@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@"); 1237169689Skan error("IT IS POSSIBLE THAT SOMEONE IS DOING SOMETHING NASTY!"); 1238169689Skan error("Someone could be eavesdropping on you right now (man-in-the-middle attack)!"); 1239169689Skan error("It is also possible that the host key has just been changed."); 1240169689Skan error("Please contact your system administrator."); 1241169689Skan error("Add correct host key in %.100s to get rid of this message.", 1242169689Skan options.user_hostfile); 1243169689Skan 1244169689Skan /* 1245169689Skan * If strict host key checking is in use, the user will have 1246169689Skan * to edit the key manually and we can only abort. 1247169689Skan */ 1248169689Skan if (options.strict_host_key_checking) 1249169689Skan fatal("Host key for %.200s has changed and you have requested strict checking.", host); 1250169689Skan 1251169689Skan /* 1252169689Skan * If strict host key checking has not been requested, allow 1253169689Skan * the connection but without password authentication or 1254169689Skan * agent forwarding. 1255169689Skan */ 1256169689Skan if (options.password_authentication) { 1257169689Skan error("Password authentication is disabled to avoid trojan horses."); 1258169689Skan options.password_authentication = 0; 1259169689Skan } 1260169689Skan if (options.forward_agent) { 1261169689Skan error("Agent forwarding is disabled to avoid trojan horses."); 1262169689Skan options.forward_agent = 0; 1263169689Skan } 1264169689Skan /* 1265169689Skan * XXX Should permit the user to change to use the new id. 1266169689Skan * This could be done by converting the host key to an 1267169689Skan * identifying sentence, tell that the host identifies itself 1268169689Skan * by that sentence, and ask the user if he/she whishes to 1269169689Skan * accept the authentication. 1270169689Skan */ 1271169689Skan break; 1272169689Skan } 1273169689Skan if (options.check_host_ip) 1274169689Skan xfree(ip); 1275169689Skan} 1276169689Skan 1277169689Skan/* 1278169689Skan * SSH1 key exchange 1279169689Skan */ 1280169689Skanvoid 1281169689Skanssh_kex(char *host, struct sockaddr *hostaddr) 1282169689Skan{ 1283169689Skan int i; 1284169689Skan BIGNUM *key; 1285169689Skan RSA *host_key; 1286169689Skan RSA *public_key; 1287169689Skan int bits, rbits; 1288169689Skan unsigned char session_key[SSH_SESSION_KEY_LENGTH]; 1289169689Skan unsigned char cookie[8]; 1290169689Skan unsigned int supported_ciphers; 1291169689Skan unsigned int server_flags, client_flags; 1292169689Skan int payload_len, clen, sum_len = 0; 1293169689Skan u_int32_t rand = 0; 1294169689Skan 1295169689Skan debug("Waiting for server public key."); 1296169689Skan 1297169689Skan /* Wait for a public key packet from the server. */ 1298169689Skan packet_read_expect(&payload_len, SSH_SMSG_PUBLIC_KEY); 1299169689Skan 1300169689Skan /* Get cookie from the packet. */ 1301169689Skan for (i = 0; i < 8; i++) 1302169689Skan cookie[i] = packet_get_char(); 1303169689Skan 1304169689Skan /* Get the public key. */ 1305169689Skan public_key = RSA_new(); 1306169689Skan bits = packet_get_int();/* bits */ 1307169689Skan public_key->e = BN_new(); 1308169689Skan packet_get_bignum(public_key->e, &clen); 1309169689Skan sum_len += clen; 1310169689Skan public_key->n = BN_new(); 1311169689Skan packet_get_bignum(public_key->n, &clen); 1312169689Skan sum_len += clen; 1313169689Skan 1314169689Skan rbits = BN_num_bits(public_key->n); 1315169689Skan if (bits != rbits) { 1316169689Skan log("Warning: Server lies about size of server public key: " 1317169689Skan "actual size is %d bits vs. announced %d.", rbits, bits); 1318169689Skan log("Warning: This may be due to an old implementation of ssh."); 1319169689Skan } 1320169689Skan /* Get the host key. */ 1321169689Skan host_key = RSA_new(); 1322169689Skan bits = packet_get_int();/* bits */ 1323169689Skan host_key->e = BN_new(); 1324169689Skan packet_get_bignum(host_key->e, &clen); 1325169689Skan sum_len += clen; 1326169689Skan host_key->n = BN_new(); 1327169689Skan packet_get_bignum(host_key->n, &clen); 1328169689Skan sum_len += clen; 1329169689Skan 1330169689Skan rbits = BN_num_bits(host_key->n); 1331169689Skan if (bits != rbits) { 1332169689Skan log("Warning: Server lies about size of server host key: " 1333169689Skan "actual size is %d bits vs. announced %d.", rbits, bits); 1334169689Skan log("Warning: This may be due to an old implementation of ssh."); 1335169689Skan } 1336169689Skan 1337169689Skan /* Get protocol flags. */ 1338169689Skan server_flags = packet_get_int(); 1339169689Skan packet_set_protocol_flags(server_flags); 1340169689Skan 1341169689Skan supported_ciphers = packet_get_int(); 1342169689Skan supported_authentications = packet_get_int(); 1343169689Skan 1344169689Skan debug("Received server public key (%d bits) and host key (%d bits).", 1345169689Skan BN_num_bits(public_key->n), BN_num_bits(host_key->n)); 1346169689Skan 1347169689Skan packet_integrity_check(payload_len, 1348169689Skan 8 + 4 + sum_len + 0 + 4 + 0 + 0 + 4 + 4 + 4, 1349169689Skan SSH_SMSG_PUBLIC_KEY); 1350169689Skan 1351169689Skan check_host_key(host, hostaddr, host_key); 1352169689Skan 1353169689Skan client_flags = SSH_PROTOFLAG_SCREEN_NUMBER | SSH_PROTOFLAG_HOST_IN_FWD_OPEN; 1354169689Skan 1355169689Skan compute_session_id(session_id, cookie, host_key->n, public_key->n); 1356169689Skan 1357169689Skan /* Generate a session key. */ 1358169689Skan arc4random_stir(); 1359169689Skan 1360169689Skan /* 1361169689Skan * Generate an encryption key for the session. The key is a 256 bit 1362169689Skan * random number, interpreted as a 32-byte key, with the least 1363169689Skan * significant 8 bits being the first byte of the key. 1364169689Skan */ 1365169689Skan for (i = 0; i < 32; i++) { 1366169689Skan if (i % 4 == 0) 1367169689Skan rand = arc4random(); 1368169689Skan session_key[i] = rand & 0xff; 1369169689Skan rand >>= 8; 1370169689Skan } 1371169689Skan 1372169689Skan /* 1373169689Skan * According to the protocol spec, the first byte of the session key 1374169689Skan * is the highest byte of the integer. The session key is xored with 1375169689Skan * the first 16 bytes of the session id. 1376169689Skan */ 1377169689Skan key = BN_new(); 1378169689Skan BN_set_word(key, 0); 1379169689Skan for (i = 0; i < SSH_SESSION_KEY_LENGTH; i++) { 1380169689Skan BN_lshift(key, key, 8); 1381169689Skan if (i < 16) 1382169689Skan BN_add_word(key, session_key[i] ^ session_id[i]); 1383169689Skan else 1384169689Skan BN_add_word(key, session_key[i]); 1385169689Skan } 1386169689Skan 1387169689Skan /* 1388169689Skan * Encrypt the integer using the public key and host key of the 1389169689Skan * server (key with smaller modulus first). 1390169689Skan */ 1391169689Skan if (BN_cmp(public_key->n, host_key->n) < 0) { 1392169689Skan /* Public key has smaller modulus. */ 1393169689Skan if (BN_num_bits(host_key->n) < 1394169689Skan BN_num_bits(public_key->n) + SSH_KEY_BITS_RESERVED) { 1395169689Skan fatal("respond_to_rsa_challenge: host_key %d < public_key %d + " 1396169689Skan "SSH_KEY_BITS_RESERVED %d", 1397169689Skan BN_num_bits(host_key->n), 1398169689Skan BN_num_bits(public_key->n), 1399169689Skan SSH_KEY_BITS_RESERVED); 1400169689Skan } 1401169689Skan rsa_public_encrypt(key, key, public_key); 1402169689Skan rsa_public_encrypt(key, key, host_key); 1403169689Skan } else { 1404169689Skan /* Host key has smaller modulus (or they are equal). */ 1405169689Skan if (BN_num_bits(public_key->n) < 1406169689Skan BN_num_bits(host_key->n) + SSH_KEY_BITS_RESERVED) { 1407169689Skan fatal("respond_to_rsa_challenge: public_key %d < host_key %d + " 1408169689Skan "SSH_KEY_BITS_RESERVED %d", 1409169689Skan BN_num_bits(public_key->n), 1410169689Skan BN_num_bits(host_key->n), 1411169689Skan SSH_KEY_BITS_RESERVED); 1412169689Skan } 1413169689Skan rsa_public_encrypt(key, key, host_key); 1414169689Skan rsa_public_encrypt(key, key, public_key); 1415169689Skan } 1416169689Skan 1417169689Skan /* Destroy the public keys since we no longer need them. */ 1418169689Skan RSA_free(public_key); 1419169689Skan RSA_free(host_key); 1420169689Skan 1421169689Skan if (options.cipher == SSH_CIPHER_NOT_SET) { 1422169689Skan if (cipher_mask() & supported_ciphers & (1 << ssh_cipher_default)) 1423169689Skan options.cipher = ssh_cipher_default; 1424169689Skan else { 1425169689Skan debug("Cipher %s not supported, using %.100s instead.", 1426169689Skan cipher_name(ssh_cipher_default), 1427169689Skan cipher_name(SSH_FALLBACK_CIPHER)); 1428169689Skan options.cipher = SSH_FALLBACK_CIPHER; 1429169689Skan } 1430169689Skan } 1431169689Skan /* Check that the selected cipher is supported. */ 1432169689Skan if (!(supported_ciphers & (1 << options.cipher))) 1433169689Skan fatal("Selected cipher type %.100s not supported by server.", 1434169689Skan cipher_name(options.cipher)); 1435169689Skan 1436169689Skan debug("Encryption type: %.100s", cipher_name(options.cipher)); 1437169689Skan 1438169689Skan /* Send the encrypted session key to the server. */ 1439169689Skan packet_start(SSH_CMSG_SESSION_KEY); 1440169689Skan packet_put_char(options.cipher); 1441169689Skan 1442169689Skan /* Send the cookie back to the server. */ 1443169689Skan for (i = 0; i < 8; i++) 1444169689Skan packet_put_char(cookie[i]); 1445169689Skan 1446169689Skan /* Send and destroy the encrypted encryption key integer. */ 1447169689Skan packet_put_bignum(key); 1448169689Skan BN_clear_free(key); 1449169689Skan 1450169689Skan /* Send protocol flags. */ 1451169689Skan packet_put_int(client_flags); 1452169689Skan 1453169689Skan /* Send the packet now. */ 1454169689Skan packet_send(); 1455169689Skan packet_write_wait(); 1456169689Skan 1457169689Skan debug("Sent encrypted session key."); 1458169689Skan 1459169689Skan /* Set the encryption key. */ 1460169689Skan packet_set_encryption_key(session_key, SSH_SESSION_KEY_LENGTH, options.cipher); 1461169689Skan 1462169689Skan /* We will no longer need the session key here. Destroy any extra copies. */ 1463169689Skan memset(session_key, 0, sizeof(session_key)); 1464169689Skan 1465169689Skan /* 1466169689Skan * Expect a success message from the server. Note that this message 1467169689Skan * will be received in encrypted form. 1468169689Skan */ 1469169689Skan packet_read_expect(&payload_len, SSH_SMSG_SUCCESS); 1470169689Skan 1471169689Skan debug("Received encrypted confirmation."); 1472169689Skan} 1473169689Skan 1474169689Skan/* 1475169689Skan * Authenticate user 1476169689Skan */ 1477169689Skanvoid 1478169689Skanssh_userauth(int host_key_valid, RSA *own_host_key, 1479169689Skan uid_t original_real_uid, char *host) 1480169689Skan{ 1481169689Skan int i, type; 1482169689Skan int payload_len; 1483169689Skan struct passwd *pw; 1484169689Skan const char *server_user, *local_user; 1485169689Skan 1486169689Skan /* Get local user name. Use it as server user if no user name was given. */ 1487169689Skan pw = getpwuid(original_real_uid); 1488169689Skan if (!pw) 1489169689Skan fatal("User id %d not found from user database.", original_real_uid); 1490169689Skan local_user = xstrdup(pw->pw_name); 1491169689Skan server_user = options.user ? options.user : local_user; 1492169689Skan 1493169689Skan /* Send the name of the user to log in as on the server. */ 1494169689Skan packet_start(SSH_CMSG_USER); 1495169689Skan packet_put_string(server_user, strlen(server_user)); 1496169689Skan packet_send(); 1497169689Skan packet_write_wait(); 1498169689Skan 1499169689Skan /* 1500169689Skan * The server should respond with success if no authentication is 1501169689Skan * needed (the user has no password). Otherwise the server responds 1502169689Skan * with failure. 1503169689Skan */ 1504169689Skan type = packet_read(&payload_len); 1505169689Skan 1506169689Skan /* check whether the connection was accepted without authentication. */ 1507169689Skan if (type == SSH_SMSG_SUCCESS) 1508169689Skan return; 1509169689Skan if (type != SSH_SMSG_FAILURE) 1510169689Skan packet_disconnect("Protocol error: got %d in response to SSH_CMSG_USER", 1511169689Skan type); 1512169689Skan 1513169689Skan#ifdef AFS 1514169689Skan /* Try Kerberos tgt passing if the server supports it. */ 1515169689Skan if ((supported_authentications & (1 << SSH_PASS_KERBEROS_TGT)) && 1516169689Skan options.kerberos_tgt_passing) { 1517169689Skan if (options.cipher == SSH_CIPHER_NONE) 1518169689Skan log("WARNING: Encryption is disabled! Ticket will be transmitted in the clear!"); 1519169689Skan (void) send_kerberos_tgt(); 1520169689Skan } 1521169689Skan /* Try AFS token passing if the server supports it. */ 1522169689Skan if ((supported_authentications & (1 << SSH_PASS_AFS_TOKEN)) && 1523169689Skan options.afs_token_passing && k_hasafs()) { 1524169689Skan if (options.cipher == SSH_CIPHER_NONE) 1525169689Skan log("WARNING: Encryption is disabled! Token will be transmitted in the clear!"); 1526169689Skan send_afs_tokens(); 1527169689Skan } 1528169689Skan#endif /* AFS */ 1529169689Skan 1530169689Skan#ifdef KRB4 1531169689Skan if ((supported_authentications & (1 << SSH_AUTH_KERBEROS)) && 1532169689Skan options.kerberos_authentication) { 1533169689Skan debug("Trying Kerberos authentication."); 1534169689Skan if (try_kerberos_authentication()) { 1535169689Skan /* The server should respond with success or failure. */ 1536169689Skan type = packet_read(&payload_len); 1537169689Skan if (type == SSH_SMSG_SUCCESS) 1538169689Skan return; 1539169689Skan if (type != SSH_SMSG_FAILURE) 1540169689Skan packet_disconnect("Protocol error: got %d in response to Kerberos auth", type); 1541169689Skan } 1542169689Skan } 1543169689Skan#endif /* KRB4 */ 1544169689Skan 1545169689Skan /* 1546169689Skan * Use rhosts authentication if running in privileged socket and we 1547169689Skan * do not wish to remain anonymous. 1548169689Skan */ 1549169689Skan if ((supported_authentications & (1 << SSH_AUTH_RHOSTS)) && 1550169689Skan options.rhosts_authentication) { 1551169689Skan debug("Trying rhosts authentication."); 1552169689Skan packet_start(SSH_CMSG_AUTH_RHOSTS); 1553169689Skan packet_put_string(local_user, strlen(local_user)); 1554169689Skan packet_send(); 1555169689Skan packet_write_wait(); 1556169689Skan 1557169689Skan /* The server should respond with success or failure. */ 1558169689Skan type = packet_read(&payload_len); 1559169689Skan if (type == SSH_SMSG_SUCCESS) 1560169689Skan return; 1561169689Skan if (type != SSH_SMSG_FAILURE) 1562169689Skan packet_disconnect("Protocol error: got %d in response to rhosts auth", 1563169689Skan type); 1564169689Skan } 1565169689Skan /* 1566169689Skan * Try .rhosts or /etc/hosts.equiv authentication with RSA host 1567169689Skan * authentication. 1568169689Skan */ 1569169689Skan if ((supported_authentications & (1 << SSH_AUTH_RHOSTS_RSA)) && 1570169689Skan options.rhosts_rsa_authentication && host_key_valid) { 1571169689Skan if (try_rhosts_rsa_authentication(local_user, own_host_key)) 1572169689Skan return; 1573169689Skan } 1574169689Skan /* Try RSA authentication if the server supports it. */ 1575169689Skan if ((supported_authentications & (1 << SSH_AUTH_RSA)) && 1576169689Skan options.rsa_authentication) { 1577169689Skan /* 1578169689Skan * Try RSA authentication using the authentication agent. The 1579169689Skan * agent is tried first because no passphrase is needed for 1580169689Skan * it, whereas identity files may require passphrases. 1581169689Skan */ 1582169689Skan if (try_agent_authentication()) 1583169689Skan return; 1584169689Skan 1585169689Skan /* Try RSA authentication for each identity. */ 1586169689Skan for (i = 0; i < options.num_identity_files; i++) 1587169689Skan if (try_rsa_authentication(options.identity_files[i])) 1588169689Skan return; 1589169689Skan } 1590169689Skan /* Try skey authentication if the server supports it. */ 1591169689Skan if ((supported_authentications & (1 << SSH_AUTH_TIS)) && 1592169689Skan options.skey_authentication && !options.batch_mode) { 1593169689Skan if (try_skey_authentication()) 1594169689Skan return; 1595169689Skan } 1596169689Skan /* Try password authentication if the server supports it. */ 1597169689Skan if ((supported_authentications & (1 << SSH_AUTH_PASSWORD)) && 1598169689Skan options.password_authentication && !options.batch_mode) { 1599169689Skan char prompt[80]; 1600169689Skan 1601169689Skan snprintf(prompt, sizeof(prompt), "%.30s@%.40s's password: ", 1602169689Skan server_user, host); 1603169689Skan if (try_password_authentication(prompt)) 1604169689Skan return; 1605169689Skan } 1606169689Skan /* All authentication methods have failed. Exit with an error message. */ 1607169689Skan fatal("Permission denied."); 1608169689Skan /* NOTREACHED */ 1609169689Skan} 1610169689Skan 1611169689Skan/* 1612169689Skan * Starts a dialog with the server, and authenticates the current user on the 1613169689Skan * server. This does not need any extra privileges. The basic connection 1614169689Skan * to the server must already have been established before this is called. 1615169689Skan * If login fails, this function prints an error and never returns. 1616169689Skan * This function does not require super-user privileges. 1617169689Skan */ 1618169689Skanvoid 1619169689Skanssh_login(int host_key_valid, RSA *own_host_key, const char *orighost, 1620169689Skan struct sockaddr *hostaddr, uid_t original_real_uid) 1621169689Skan{ 1622169689Skan char *host, *cp; 1623169689Skan 1624169689Skan /* Convert the user-supplied hostname into all lowercase. */ 1625169689Skan host = xstrdup(orighost); 1626169689Skan for (cp = host; *cp; cp++) 1627169689Skan if (isupper(*cp)) 1628169689Skan *cp = tolower(*cp); 1629169689Skan 1630169689Skan /* Exchange protocol version identification strings with the server. */ 1631169689Skan ssh_exchange_identification(); 1632169689Skan 1633169689Skan /* Put the connection into non-blocking mode. */ 1634169689Skan packet_set_nonblocking(); 1635169689Skan 1636169689Skan supported_authentications = 0; 1637169689Skan /* key exchange */ 1638169689Skan ssh_kex(host, hostaddr); 1639169689Skan if (supported_authentications == 0) 1640169689Skan fatal("supported_authentications == 0."); 1641169689Skan /* authenticate user */ 1642169689Skan ssh_userauth(host_key_valid, own_host_key, original_real_uid, host); 1643169689Skan} 1644169689Skan