home *** CD-ROM | disk | FTP | other *** search
/ Columbia Kermit / kermit.zip / k95source / ck_ssh.c < prev    next >
C/C++ Source or Header  |  2020-01-01  |  54KB  |  1,746 lines

  1. char *cksshv = "SSH support, 8.0.001, 13 Sep 2000";
  2. /*
  3.   C K _ S S H . C --  OpenSSL Interface for C-Kermit
  4.  
  5.   Copyright (C) 1985, 2001,
  6.     Trustees of Columbia University in the City of New York.
  7.     All rights reserved.  See the C-Kermit COPYING.TXT file or the
  8.     copyright text in the ckcmai.c module for disclaimer and permissions.
  9.  
  10.   Copyright (c) 1995 Tatu Ylonen <ylo@cs.hut.fi>, Espoo, Finland
  11.     All rights reserved
  12.  
  13.   Includes work by Niels Provos <provos@citi.umich.edu> to work with OpenSSL.
  14.  
  15. */
  16.  
  17. #include "ckcdeb.h"
  18. #ifdef SSH
  19. #undef SSH
  20. #endif /* SSH */
  21.  
  22. #ifdef CK_SSL
  23. #ifdef SSH
  24.  
  25. #include <openssl/ssl.h>
  26. #include <openssl/x509v3.h>
  27. #include <openssl/rand.h>
  28. #include <openssl/x509_vfy.h>
  29. #include <openssl/err.h>
  30. #include <openssl/bn.h>
  31. #include <openssl/evp.h>
  32. #include <openssl/dsa.h>
  33. #include <openssl/rsa.h>
  34.  
  35. #ifdef OS2
  36. #include "ckossl.h"
  37. #endif /* OS2 */
  38.  
  39. static char *client_version_string = NULL;
  40. static char *server_version_string = NULL;
  41.  
  42.  
  43. /* Flag indicating whether IPv4 or IPv6.
  44.    This should be a SET TCP ... command.  Need to look at supporting
  45.    IPv6 in ckcnet.c.   AF_UNSPEC means both IPv4 and IPv6. */
  46. static int IPv4or6 = AF_INET;
  47.  
  48. /* Flag indicating whether debug mode is on.
  49.    SET SSH DEBUG {ON, OFF }
  50. */
  51. static int debug_flag = 0;
  52.  
  53. /* Flag indicating whether a tty should be allocated */
  54. /* In other words, was Kermit started from a tty?    */
  55. static int tty_flag = 0;
  56.  
  57. /* don't exec a shell */
  58. static int no_shell_flag = 0;
  59. static int no_tty_flag = 0;
  60.  
  61. /*
  62.  * Flag indicating that nothing should be read from stdin.
  63.  * Not sure we should support this in Kermit
  64.  */
  65. static int stdin_null_flag = 0;
  66.  
  67. /*
  68.  * Flag indicating that ssh should fork after authentication.  This is useful
  69.  * so that the pasphrase can be entered manually, and then ssh goes to the
  70.  * background.  We will not support this in Kermit.
  71.  */
  72. static int fork_after_authentication_flag = 0;
  73.  
  74. /*
  75.  * General data structure for command line options and options configurable
  76.  * in configuration files.
  77.  */
  78.  
  79. #define SSH_MAX_IDENTITY_FILES            100
  80. #define SSH_MAX_FORWARDS_PER_DIRECTION    100
  81.  
  82. /* Data structure for representing a forwarding request. */
  83. typedef struct {
  84.         u_short   port;         /* Port to forward. */
  85.         char     *host;         /* Host to connect. */
  86.         u_short   host_port;    /* Port to connect on host. */
  87. }       Forward;
  88.  
  89. /* Data structure for representing option data. */
  90. typedef enum {
  91.         SYSLOG_LEVEL_QUIET,
  92.         SYSLOG_LEVEL_FATAL,
  93.         SYSLOG_LEVEL_ERROR,
  94.         SYSLOG_LEVEL_INFO,
  95.         SYSLOG_LEVEL_VERBOSE,
  96.         SYSLOG_LEVEL_DEBUG
  97. }       LogLevel;
  98.  
  99. typedef struct {
  100.         int     forward_agent;  /* Forward authentication agent. */
  101.         int     forward_x11;    /* Forward X11 display. */
  102.         char   *xauth_location; /* Location for xauth program */
  103.         int     gateway_ports;  /* Allow remote connects to forwarded ports. */
  104.         int     use_privileged_port;    /* Don't use privileged port if false. *
  105.         int     rhosts_authentication;  /* Try rhosts authentication. */
  106.         int     rhosts_rsa_authentication;      /* Try rhosts with RSA
  107.                                                  * authentication. */
  108.         int     rsa_authentication;     /* Try RSA authentication. */
  109.         int     dsa_authentication;     /* Try DSA authentication. */
  110.         int     skey_authentication;    /* Try S/Key or TIS authentication. */
  111. #ifdef KRB4
  112.         int     kerberos_authentication;        /* Try Kerberos
  113.                                                  * authentication. */
  114. #endif
  115. #ifdef AFS
  116.         int     kerberos_tgt_passing;   /* Try Kerberos tgt passing. */
  117.         int     afs_token_passing;      /* Try AFS token passing. */
  118. #endif
  119.         int     password_authentication;        /* Try password
  120.                                                  * authentication. */
  121.         int     fallback_to_rsh;/* Use rsh if cannot connect with ssh. */
  122.         int     use_rsh;        /* Always use rsh (don\'t try ssh). */
  123.         int     batch_mode;     /* Batch mode: do not ask for passwords. */
  124.         int     check_host_ip;  /* Also keep track of keys for IP address */
  125.         int     strict_host_key_checking;       /* Strict host key checking. */
  126.         int     compression;    /* Compress packets in both directions. */
  127.         int     compression_level;      /* Compression level 1 (fast) to 9
  128.                                          * (best). */
  129.         int     keepalives;     /* Set SO_KEEPALIVE. */
  130.         LogLevel log_level;     /* Level for logging. */
  131.  
  132.         int     port;           /* Port to connect. */
  133.         int     connection_attempts;    /* Max attempts (seconds) before
  134.                                          * giving up */
  135.         int     number_of_password_prompts;     /* Max number of password
  136.                                                  * prompts. */
  137.         int     cipher;         /* Cipher to use. */
  138.         char   *ciphers;        /* SSH2 ciphers in order of preference. */
  139.         int     protocol;       /* Protocol in order of preference. */
  140.         char   *hostname;       /* Real host to connect. */
  141.         char   *proxy_command;  /* Proxy command for connecting the host. */
  142.         char   *user;           /* User to log in as. */
  143.         int     escape_char;    /* Escape character; -2 = none */
  144.  
  145.         char   *system_hostfile;/* Path for /etc/ssh_known_hosts. */
  146.         char   *user_hostfile;  /* Path for $HOME/.ssh/known_hosts. */
  147.         char   *system_hostfile2;        char   *user_hostfile2;
  148.  
  149.         int     num_identity_files;     /* Number of files for RSA identities. *
  150.         int     num_identity_files2;    /* DSA identities. */
  151.         char   *identity_files[SSH_MAX_IDENTITY_FILES];
  152.         char   *identity_files2[SSH_MAX_IDENTITY_FILES];
  153.     
  154.         /* Local TCP/IP forward requests. */
  155.         int     num_local_forwards;
  156.         Forward local_forwards[SSH_MAX_FORWARDS_PER_DIRECTION];
  157.     
  158.         /* Remote TCP/IP forward requests. */
  159.         int     num_remote_forwards;
  160.         Forward remote_forwards[SSH_MAX_FORWARDS_PER_DIRECTION];
  161. } Options;
  162.  
  163. static Options options;
  164.  
  165. /*
  166.  * Name of the host we are connecting to.  This is the name given on the
  167.  * command line, or the HostName specified for the user-supplied name in a
  168.  * configuration file.
  169.  */
  170. static char *host;
  171.  
  172. /* socket address the host resolves to */
  173. static struct sockaddr_storage hostaddr;
  174.  
  175. /*
  176.  * Flag to indicate that we have received a window change signal which has
  177.  * not yet been processed.  This will cause a message indicating the new
  178.  * window size to be sent to the server a little later.  This is volatile
  179.  * because this is updated in a signal handler.
  180.  */
  181. static volatile int received_window_change_signal = 0;
  182.  
  183. /* Value of argv[0] (set in the main program). */
  184. static char *av0;
  185.  
  186. /* Flag indicating whether we have a valid host private key loaded. */
  187. static int host_private_key_loaded = 0;
  188.  
  189. /* Host private key. */
  190. static RSA *host_private_key = NULL;
  191.  
  192. /* Original real UID. */
  193. static uid_t original_real_uid;
  194.  
  195. /* command to be executed */
  196. static Buffer command;
  197.  
  198. /* SSH command line usage.  Use this to design the Kermit "ssh" personality. */
  199.  
  200. /*
  201.     fprintf(stderr, "Usage: %s [options] host [command]\n", av0);
  202.     fprintf(stderr, "Options:\n");
  203.     fprintf(stderr, "  -l user     Log in using this user name.\n");
  204.     fprintf(stderr, "  -n          Redirect input from /dev/null.\n");
  205.     fprintf(stderr, "  -A          Enable authentication agent forwarding.\n");
  206.     fprintf(stderr, "  -a          Disable authentication agent forwarding.\n");
  207. #ifdef AFS
  208.     fprintf(stderr, "  -k          Disable Kerberos ticket and AFS token forwarding.\n");
  209. #endif                /* AFS */
  210.         fprintf(stderr, "  -X          Enable X11 connection forwarding.\n");
  211.     fprintf(stderr, "  -x          Disable X11 connection forwarding.\n");
  212.     fprintf(stderr, "  -i file     Identity for RSA authentication (default: ~/.ssh/identity).\n");
  213.     fprintf(stderr, "  -t          Tty; allocate a tty even if command is given.\n");
  214.     fprintf(stderr, "  -T          Do not allocate a tty.\n");
  215.     fprintf(stderr, "  -v          Verbose; display verbose debugging messages.\n");
  216.     fprintf(stderr, "  -V          Display version number only.\n");
  217.     fprintf(stderr, "  -P          Don't allocate a privileged port.\n");
  218.     fprintf(stderr, "  -q          Quiet; don't display any warning messages.\n");
  219.     fprintf(stderr, "  -f          Fork into background after authentication.\n");
  220.     fprintf(stderr, "  -e char     Set escape character; ``none'' = disable (default: ~).\n");
  221.  
  222.     fprintf(stderr, "  -c cipher   Select encryption algorithm: "
  223.             "``3des'', "
  224.             "``blowfish''\n");
  225.     fprintf(stderr, "  -p port     Connect to this port.  Server must be on the same port.\n");
  226.     fprintf(stderr, "  -L listen-port:host:port   Forward local port to remote address\n");
  227.     fprintf(stderr, "  -R listen-port:host:port   Forward remote port to local address\n");
  228.     fprintf(stderr, "              These cause %s to listen for connections on a port, and\n", av0);
  229.     fprintf(stderr, "              forward them to the other side by connecting to host:port.\n");
  230.     fprintf(stderr, "  -C          Enable compression.\n");
  231.     fprintf(stderr, "  -N          Do not execute a shell or command.\n");
  232.     fprintf(stderr, "  -g          Allow remote hosts to connect to forwarded ports.\n");
  233.     fprintf(stderr, "  -4          Use IPv4 only.\n");
  234.     fprintf(stderr, "  -6          Use IPv6 only.\n");
  235.     fprintf(stderr, "  -2          Force protocol version 2.\n");
  236.     fprintf(stderr, "  -o 'option' Process the option as if it was read from a configuration file.\n");
  237. */
  238.  
  239. /* Function prototypes */
  240. _PROTOTYP(static int ssh_session,(void));
  241. _PROTOTYP(static int ssh_session2,(void));
  242. _PROTOTYP(VOID client_set_session_ident,(int id));
  243.  
  244. /*
  245.  * Connects to the given host using rsh (or prints an error message and exits
  246.  * if rsh is not available).  This function never returns.
  247.  */
  248. static void
  249. rsh_connect(char *host, char *user, Buffer * command)
  250. {
  251.     char *args[10];
  252.     int i;
  253.  
  254.     log("Using rsh.  WARNING: Connection will not be encrypted.");
  255.     /* Build argument list for rsh. */
  256.     i = 0;
  257.     args[i++] = _PATH_RSH;
  258.     /* host may have to come after user on some systems */
  259.     args[i++] = host;
  260.     if (user) {
  261.         args[i++] = "-l";
  262.         args[i++] = user;
  263.     }
  264.     if (buffer_len(command) > 0) {
  265.         buffer_append(command, "\0", 1);
  266.         args[i++] = buffer_ptr(command);
  267.     }
  268.     args[i++] = NULL;
  269.     if (debug_flag) {
  270.         for (i = 0; args[i]; i++) {
  271.             if (i != 0)
  272.                 fprintf(stderr, " ");
  273.             fprintf(stderr, "%s", args[i]);
  274.         }
  275.         fprintf(stderr, "\n");
  276.     }
  277.     execv(_PATH_RSH, args);
  278.     perror(_PATH_RSH);
  279.     exit(1);
  280. }
  281.  
  282. /*
  283.  * Main program for the ssh client.
  284.  */
  285. static int
  286. main(int ac, char **av)
  287. {
  288.     int i, opt, optind, exit_status, ok;
  289.     u_short fwd_port, fwd_host_port;
  290.     char *optarg, *cp, buf[256];
  291.     struct stat st;
  292.     struct passwd *pw, pwcopy;
  293.     int dummy;
  294.     uid_t original_effective_uid;
  295.  
  296.     init_rng();
  297.  
  298.     /*
  299.      * Save the original real uid.  It will be needed later (uid-swapping
  300.      * may clobber the real uid).
  301.      */
  302.     original_real_uid = getuid();
  303.     original_effective_uid = geteuid();
  304.  
  305.     /* If we are installed setuid root be careful to not drop core. */
  306.     if (original_real_uid != original_effective_uid) {
  307.         struct rlimit rlim;
  308.         rlim.rlim_cur = rlim.rlim_max = 0;
  309.         if (setrlimit(RLIMIT_CORE, &rlim) < 0)
  310.             fatal("setrlimit failed: %.100s", strerror(errno));
  311.     }
  312.     /*
  313.      * Use uid-swapping to give up root privileges for the duration of
  314.      * option processing.  We will re-instantiate the rights when we are
  315.      * ready to create the privileged port, and will permanently drop
  316.      * them when the port has been created (actually, when the connection
  317.      * has been made, as we may need to create the port several times).
  318.      */
  319.     temporarily_use_uid(original_real_uid);
  320.  
  321.     /*
  322.      * Set our umask to something reasonable, as some files are created
  323.      * with the default umask.  This will make them world-readable but
  324.      * writable only by the owner, which is ok for all files for which we
  325.      * don't set the modes explicitly.
  326.      */
  327.     umask(022);
  328.  
  329.     /* Save our own name. */
  330.     av0 = av[0];
  331.  
  332.     /* Initialize option structure to indicate that no values have been set. */
  333.     initialize_options(&options);
  334.  
  335.     /* Parse command-line arguments. */
  336.     host = NULL;
  337.  
  338.     /* If program name is not one of the standard names, use it as host name. */
  339.     if (strchr(av0, '/'))
  340.         cp = strrchr(av0, '/') + 1;
  341.     else
  342.         cp = av0;
  343.     if (strcmp(cp, "rsh") && strcmp(cp, "ssh") && strcmp(cp, "rlogin") &&
  344.         strcmp(cp, "slogin") && strcmp(cp, "remsh"))
  345.         host = cp;
  346.  
  347.     for (optind = 1; optind < ac; optind++) {
  348.         if (av[optind][0] != '-') {
  349.             if (host)
  350.                 break;
  351.             if ((cp = strchr(av[optind], '@'))) {
  352.                 if(cp == av[optind])
  353.                     usage();
  354.                 options.user = av[optind];
  355.                 *cp = '\0';
  356.                 host = ++cp;
  357.             } else
  358.                 host = av[optind];
  359.             continue;
  360.         }
  361.         opt = av[optind][1];
  362.         if (!opt)
  363.             usage();
  364.         if (strchr("eilcpLRo", opt)) {    /* options with arguments */
  365.             optarg = av[optind] + 2;
  366.             if (strcmp(optarg, "") == 0) {
  367.                 if (optind >= ac - 1)
  368.                     usage();
  369.                 optarg = av[++optind];
  370.             }
  371.         } else {
  372.             if (av[optind][2])
  373.                 usage();
  374.             optarg = NULL;
  375.         }
  376.         switch (opt) {
  377.         case '2':
  378.             options.protocol = SSH_PROTO_2;
  379.             break;
  380.         case '4':
  381.             IPv4or6 = AF_INET;
  382.             break;
  383.         case '6':
  384.             IPv4or6 = AF_INET6;
  385.             break;
  386.         case 'n':
  387.             stdin_null_flag = 1;
  388.             break;
  389.         case 'f':
  390.             fork_after_authentication_flag = 1;
  391.             stdin_null_flag = 1;
  392.             break;
  393.         case 'x':
  394.             options.forward_x11 = 0;
  395.             break;
  396.         case 'X':
  397.             options.forward_x11 = 1;
  398.             break;
  399.         case 'g':
  400.             options.gateway_ports = 1;
  401.             break;
  402.         case 'P':
  403.             options.use_privileged_port = 0;
  404.             break;
  405.         case 'a':
  406.             options.forward_agent = 0;
  407.             break;
  408.         case 'A':
  409.             options.forward_agent = 1;
  410.             break;
  411. #ifdef AFS
  412.         case 'k':
  413.             options.kerberos_tgt_passing = 0;
  414.             options.afs_token_passing = 0;
  415.             break;
  416. #endif
  417.         case 'i':
  418.             if (stat(optarg, &st) < 0) {
  419.                 fprintf(stderr, "Warning: Identity file %s does not exist.\n",
  420.                     optarg);
  421.                 break;
  422.             }
  423.             if (options.num_identity_files >= SSH_MAX_IDENTITY_FILES)
  424.                 fatal("Too many identity files specified (max %d)",
  425.                       SSH_MAX_IDENTITY_FILES);
  426.             options.identity_files[options.num_identity_files++] =
  427.                 xstrdup(optarg);
  428.             break;
  429.         case 't':
  430.             tty_flag = 1;
  431.             break;
  432.         case 'v':
  433.         case 'V':
  434.             fprintf(stderr, "SSH Version %s, protocol versions %d.%d/%d.%d.\n",
  435.                 SSH_VERSION,
  436.                 PROTOCOL_MAJOR_1, PROTOCOL_MINOR_1,
  437.                 PROTOCOL_MAJOR_2, PROTOCOL_MINOR_2);
  438.             fprintf(stderr, "Compiled with SSL (0x%8.8lx).\n", SSLeay());
  439.             if (opt == 'V')
  440.                 exit(0);
  441.             debug_flag = 1;
  442.             options.log_level = SYSLOG_LEVEL_DEBUG;
  443.             break;
  444.         case 'q':
  445.             options.log_level = SYSLOG_LEVEL_QUIET;
  446.             break;
  447.         case 'e':
  448.             if (optarg[0] == '^' && optarg[2] == 0 &&
  449.                 (unsigned char) optarg[1] >= 64 && (unsigned char) optarg[1] < 128)
  450.                 options.escape_char = (unsigned char) optarg[1] & 31;
  451.             else if (strlen(optarg) == 1)
  452.                 options.escape_char = (unsigned char) optarg[0];
  453.             else if (strcmp(optarg, "none") == 0)
  454.                 options.escape_char = -2;
  455.             else {
  456.                 fprintf(stderr, "Bad escape character '%s'.\n", optarg);
  457.                 exit(1);
  458.             }
  459.             break;
  460.         case 'c':
  461.             if (ciphers_valid(optarg)) {
  462.                 /* SSH2 only */
  463.                 options.ciphers = xstrdup(optarg);
  464.                 options.cipher = SSH_CIPHER_ILLEGAL;
  465.             } else {
  466.                 /* SSH1 only */
  467.                 options.cipher = cipher_number(optarg);
  468.                 if (options.cipher == -1) {
  469.                     fprintf(stderr, "Unknown cipher type '%s'\n", optarg);
  470.                     exit(1);
  471.                 }
  472.             }
  473.             break;
  474.         case 'p':
  475.             options.port = atoi(optarg);
  476.             break;
  477.         case 'l':
  478.             options.user = optarg;
  479.             break;
  480.         case 'R':
  481.             if (sscanf(optarg, "%hu/%255[^/]/%hu", &fwd_port, buf,
  482.                 &fwd_host_port) != 3 &&
  483.                 sscanf(optarg, "%hu:%255[^:]:%hu", &fwd_port, buf,
  484.                 &fwd_host_port) != 3) {
  485.                 fprintf(stderr, "Bad forwarding specification '%s'.\n", optarg);
  486.                 usage();
  487.                 /* NOTREACHED */
  488.             }
  489.             add_remote_forward(&options, fwd_port, buf, fwd_host_port);
  490.             break;
  491.         case 'L':
  492.             if (sscanf(optarg, "%hu/%255[^/]/%hu", &fwd_port, buf,
  493.                 &fwd_host_port) != 3 &&
  494.                 sscanf(optarg, "%hu:%255[^:]:%hu", &fwd_port, buf,
  495.                 &fwd_host_port) != 3) {
  496.                 fprintf(stderr, "Bad forwarding specification '%s'.\n", optarg);
  497.                 usage();
  498.                 /* NOTREACHED */
  499.             }
  500.             add_local_forward(&options, fwd_port, buf, fwd_host_port);
  501.             break;
  502.         case 'C':
  503.             options.compression = 1;
  504.             break;
  505.         case 'N':
  506.             no_shell_flag = 1;
  507.             no_tty_flag = 1;
  508.             break;
  509.         case 'T':
  510.             no_tty_flag = 1;
  511.             break;
  512.         case 'o':
  513.             dummy = 1;
  514.             if (process_config_line(&options, host ? host : "", optarg,
  515.                      "command-line", 0, &dummy) != 0)
  516.                 exit(1);
  517.             break;
  518.         default:
  519.             usage();
  520.         }
  521.     }
  522.  
  523.     /* Check that we got a host name. */
  524.     if (!host)
  525.         usage();
  526.  
  527.     /* Initialize the command to execute on remote host. */
  528.     buffer_init(&command);
  529.  
  530.     SSLeay_add_all_algorithms();
  531.  
  532.     /*
  533.      * Save the command to execute on the remote host in a buffer. There
  534.      * is no limit on the length of the command, except by the maximum
  535.      * packet size.  Also sets the tty flag if there is no command.
  536.      */
  537.     if (optind == ac) {
  538.         /* No command specified - execute shell on a tty. */
  539.         tty_flag = 1;
  540.     } else {
  541.         /* A command has been specified.  Store it into the
  542.            buffer. */
  543.         for (i = optind; i < ac; i++) {
  544.             if (i > optind)
  545.                 buffer_append(&command, " ", 1);
  546.             buffer_append(&command, av[i], strlen(av[i]));
  547.         }
  548.     }
  549.  
  550.     /* Cannot fork to background if no command. */
  551.     if (fork_after_authentication_flag && buffer_len(&command) == 0 && !no_shell_flag)
  552.         fatal("Cannot fork into background without a command to execute.");
  553.  
  554.     /* Allocate a tty by default if no command specified. */
  555.     if (buffer_len(&command) == 0)
  556.         tty_flag = 1;
  557.  
  558.     /* Do not allocate a tty if stdin is not a tty. */
  559.     if (!isatty(fileno(stdin))) {
  560.         if (tty_flag)
  561.             fprintf(stderr, "Pseudo-terminal will not be allocated because stdin is not a terminal.\n");
  562.         tty_flag = 0;
  563.     }
  564.     /* force */
  565.     if (no_tty_flag)
  566.         tty_flag = 0;
  567.  
  568.     /* Get user data. */
  569.     pw = getpwuid(original_real_uid);
  570.     if (!pw) {
  571.         fprintf(stderr, "You don't exist, go away!\n");
  572.         exit(1);
  573.     }
  574.     /* Take a copy of the returned structure. */
  575.     memset(&pwcopy, 0, sizeof(pwcopy));
  576.     pwcopy.pw_name = xstrdup(pw->pw_name);
  577.     pwcopy.pw_passwd = xstrdup(pw->pw_passwd);
  578.     pwcopy.pw_uid = pw->pw_uid;
  579.     pwcopy.pw_gid = pw->pw_gid;
  580. #ifdef HAVE_PW_CLASS_IN_PASSWD
  581.     pwcopy.pw_class = xstrdup(pw->pw_class);
  582. #endif
  583.     pwcopy.pw_dir = xstrdup(pw->pw_dir);
  584.     pwcopy.pw_shell = xstrdup(pw->pw_shell);
  585.     pw = &pwcopy;
  586.  
  587.     /* Initialize "log" output.  Since we are the client all output
  588.        actually goes to the terminal. */
  589.     log_init(av[0], options.log_level, SYSLOG_FACILITY_USER, 0);
  590.  
  591.     /* Read per-user configuration file. */
  592.     snprintf(buf, sizeof buf, "%.100s/%.100s", pw->pw_dir, SSH_USER_CONFFILE);
  593.     read_config_file(buf, host, &options);
  594.  
  595.     /* Read systemwide configuration file. */
  596.     read_config_file(HOST_CONFIG_FILE, host, &options);
  597.  
  598.     /* Fill configuration defaults. */
  599.     fill_default_options(&options);
  600.  
  601.     /* reinit */
  602.     log_init(av[0], options.log_level, SYSLOG_FACILITY_USER, 0);
  603.  
  604.     /* check if RSA support exists */
  605.     if ((options.protocol & SSH_PROTO_1) &&
  606.         rsa_alive() == 0) {
  607.         log("%s: no RSA support in libssl and libcrypto.  See ssl(8).",
  608.             __progname);
  609.         log("Disabling protocol version 1");
  610.         options.protocol &= ~ (SSH_PROTO_1|SSH_PROTO_1_PREFERRED);
  611.     }
  612.     if (! options.protocol & (SSH_PROTO_1|SSH_PROTO_2)) {
  613.         fprintf(stderr, "%s: No protocol version available.\n",
  614.             __progname);
  615.          exit(1);
  616.     }
  617.  
  618.     if (options.user == NULL)
  619.         options.user = xstrdup(pw->pw_name);
  620.  
  621.     if (options.hostname != NULL)
  622.         host = options.hostname;
  623.  
  624.     /* Find canonic host name. */
  625.     if (strchr(host, '.') == 0) {
  626.         struct addrinfo hints;
  627.         struct addrinfo *ai = NULL;
  628.         int errgai;
  629.         memset(&hints, 0, sizeof(hints));
  630.         hints.ai_family = IPv4or6;
  631.         hints.ai_flags = AI_CANONNAME;
  632.         hints.ai_socktype = SOCK_STREAM;
  633.         errgai = getaddrinfo(host, NULL, &hints, &ai);
  634.         if (errgai == 0) {
  635.             if (ai->ai_canonname != NULL)
  636.                 host = xstrdup(ai->ai_canonname);
  637.             freeaddrinfo(ai);
  638.         }
  639.     }
  640.     /* Disable rhosts authentication if not running as root. */
  641.     if (original_effective_uid != 0 || !options.use_privileged_port) {
  642.         options.rhosts_authentication = 0;
  643.         options.rhosts_rsa_authentication = 0;
  644.     }
  645.     /*
  646.      * If using rsh has been selected, exec it now (without trying
  647.      * anything else).  Note that we must release privileges first.
  648.      */
  649.     if (options.use_rsh) {
  650.         /*
  651.          * Restore our superuser privileges.  This must be done
  652.          * before permanently setting the uid.
  653.          */
  654.         restore_uid();
  655.  
  656.         /* Switch to the original uid permanently. */
  657.         permanently_set_uid(original_real_uid);
  658.  
  659.         /* Execute rsh. */
  660.         rsh_connect(host, options.user, &command);
  661.         fatal("rsh_connect returned");
  662.     }
  663.     /* Restore our superuser privileges. */
  664.     restore_uid();
  665.  
  666.     /*
  667.      * Open a connection to the remote host.  This needs root privileges
  668.      * if rhosts_{rsa_}authentication is enabled.
  669.      */
  670.  
  671.     ok = ssh_connect(host, &hostaddr, options.port,
  672.              options.connection_attempts,
  673.              !options.rhosts_authentication &&
  674.              !options.rhosts_rsa_authentication,
  675.              original_real_uid,
  676.              options.proxy_command);
  677.  
  678.     /*
  679.      * If we successfully made the connection, load the host private key
  680.      * in case we will need it later for combined rsa-rhosts
  681.      * authentication. This must be done before releasing extra
  682.      * privileges, because the file is only readable by root.
  683.      */
  684.     if (ok && (options.protocol & SSH_PROTO_1)) {
  685.         Key k;
  686.         host_private_key = RSA_new();
  687.         k.type = KEY_RSA;
  688.         k.rsa = host_private_key;
  689.         if (load_private_key(HOST_KEY_FILE, "", &k, NULL))
  690.             host_private_key_loaded = 1;
  691.     }
  692.     /*
  693.      * Get rid of any extra privileges that we may have.  We will no
  694.      * longer need them.  Also, extra privileges could make it very hard
  695.      * to read identity files and other non-world-readable files from the
  696.      * user's home directory if it happens to be on a NFS volume where
  697.      * root is mapped to nobody.
  698.      */
  699.  
  700.     /*
  701.      * Note that some legacy systems need to postpone the following call
  702.      * to permanently_set_uid() until the private hostkey is destroyed
  703.      * with RSA_free().  Otherwise the calling user could ptrace() the
  704.      * process, read the private hostkey and impersonate the host.
  705.      * OpenBSD does not allow ptracing of setuid processes.
  706.      */
  707.     permanently_set_uid(original_real_uid);
  708.  
  709.     /*
  710.      * Now that we are back to our own permissions, create ~/.ssh
  711.      * directory if it doesn\'t already exist.
  712.      */
  713.     snprintf(buf, sizeof buf, "%.100s/%.100s", pw->pw_dir, SSH_USER_DIR);
  714.     if (stat(buf, &st) < 0)
  715.         if (mkdir(buf, 0700) < 0)
  716.             error("Could not create directory '%.200s'.", buf);
  717.  
  718.     /* Check if the connection failed, and try "rsh" if appropriate. */
  719.     if (!ok) {
  720.         if (options.port != 0)
  721.             log("Secure connection to %.100s on port %hu refused%.100s.",
  722.                 host, options.port,
  723.                 options.fallback_to_rsh ? "; reverting to insecure method" : "");
  724.         else
  725.             log("Secure connection to %.100s refused%.100s.", host,
  726.                 options.fallback_to_rsh ? "; reverting to insecure method" : "");
  727.  
  728.         if (options.fallback_to_rsh) {
  729.             rsh_connect(host, options.user, &command);
  730.             fatal("rsh_connect returned");
  731.         }
  732.         exit(1);
  733.     }
  734.     /* Expand ~ in options.identity_files. */
  735.     /* XXX mem-leaks */
  736.     for (i = 0; i < options.num_identity_files; i++)
  737.         options.identity_files[i] =
  738.             tilde_expand_filename(options.identity_files[i], original_real_uid);
  739.     for (i = 0; i < options.num_identity_files2; i++)
  740.         options.identity_files2[i] =
  741.             tilde_expand_filename(options.identity_files2[i], original_real_uid);
  742.     /* Expand ~ in known host file names. */
  743.     options.system_hostfile = tilde_expand_filename(options.system_hostfile,
  744.         original_real_uid);
  745.     options.user_hostfile = tilde_expand_filename(options.user_hostfile,
  746.         original_real_uid);
  747.     options.system_hostfile2 = tilde_expand_filename(options.system_hostfile2,
  748.         original_real_uid);
  749.     options.user_hostfile2 = tilde_expand_filename(options.user_hostfile2,
  750.         original_real_uid);
  751.  
  752.     /* Log into the remote system.  This never returns if the login fails. */
  753.     ssh_login(host_private_key_loaded, host_private_key,
  754.           host, (struct sockaddr *)&hostaddr, original_real_uid);
  755.  
  756.     /* We no longer need the host private key.  Clear it now. */
  757.     if (host_private_key_loaded)
  758.         RSA_free(host_private_key);    /* Destroys contents safely */
  759.  
  760.     exit_status = compat20 ? ssh_session2() : ssh_session();
  761.     packet_close();
  762.     return exit_status;
  763. }
  764.  
  765. static void
  766. x11_get_proto(char *proto, int proto_len, char *data, int data_len)
  767. {
  768.     char line[512];
  769.     FILE *f;
  770.     int got_data = 0, i;
  771.  
  772.     if (options.xauth_location) {
  773.         /* Try to get Xauthority information for the display. */
  774.         snprintf(line, sizeof line, "%.100s list %.200s 2>/dev/null",
  775.             options.xauth_location, getenv("DISPLAY"));
  776.         f = popen(line, "r");
  777.         if (f && fgets(line, sizeof(line), f) &&
  778.             sscanf(line, "%*s %s %s", proto, data) == 2)
  779.             got_data = 1;
  780.         if (f)
  781.             pclose(f);
  782.     }
  783.     /*
  784.      * If we didn't get authentication data, just make up some
  785.      * data.  The forwarding code will check the validity of the
  786.      * response anyway, and substitute this data.  The X11
  787.      * server, however, will ignore this fake data and use
  788.      * whatever authentication mechanisms it was using otherwise
  789.      * for the local connection.
  790.      */
  791.     if (!got_data) {
  792.         u_int32_t rand = 0;
  793.  
  794.         strlcpy(proto, "MIT-MAGIC-COOKIE-1", proto_len);
  795.         for (i = 0; i < 16; i++) {
  796.             if (i % 4 == 0)
  797.                 rand = arc4random();
  798.             snprintf(data + 2 * i, data_len - 2 * i, "%02x", rand & 0xff);
  799.             rand >>= 8;
  800.         }
  801.     }
  802. }
  803.  
  804. static int
  805. ssh_session(void)
  806. {
  807.     int type;
  808.     int i;
  809.     int plen;
  810.     int interactive = 0;
  811.     int have_tty = 0;
  812.     struct winsize ws;
  813.     int authfd;
  814.     char *cp;
  815.  
  816.     /* Enable compression if requested. */
  817.     if (options.compression) {
  818.         debug("Requesting compression at level %d.", options.compression_level);
  819.  
  820.         if (options.compression_level < 1 || options.compression_level > 9)
  821.             fatal("Compression level must be from 1 (fast) to 9 (slow, best).");
  822.  
  823.         /* Send the request. */
  824.         packet_start(SSH_CMSG_REQUEST_COMPRESSION);
  825.         packet_put_int(options.compression_level);
  826.         packet_send();
  827.         packet_write_wait();
  828.         type = packet_read(&plen);
  829.         if (type == SSH_SMSG_SUCCESS)
  830.             packet_start_compression(options.compression_level);
  831.         else if (type == SSH_SMSG_FAILURE)
  832.             log("Warning: Remote host refused compression.");
  833.         else
  834.             packet_disconnect("Protocol error waiting for compression response.");
  835.     }
  836.     /* Allocate a pseudo tty if appropriate. */
  837.     if (tty_flag) {
  838.         debug("Requesting pty.");
  839.  
  840.         /* Start the packet. */
  841.         packet_start(SSH_CMSG_REQUEST_PTY);
  842.  
  843.         /* Store TERM in the packet.  There is no limit on the
  844.            length of the string. */
  845.         cp = getenv("TERM");
  846.         if (!cp)
  847.             cp = "";
  848.         packet_put_string(cp, strlen(cp));
  849.  
  850.         /* Store window size in the packet. */
  851.         if (ioctl(fileno(stdin), TIOCGWINSZ, &ws) < 0)
  852.             memset(&ws, 0, sizeof(ws));
  853.         packet_put_int(ws.ws_row);
  854.         packet_put_int(ws.ws_col);
  855.         packet_put_int(ws.ws_xpixel);
  856.         packet_put_int(ws.ws_ypixel);
  857.  
  858.         /* Store tty modes in the packet. */
  859.         tty_make_modes(fileno(stdin));
  860.  
  861.         /* Send the packet, and wait for it to leave. */
  862.         packet_send();
  863.         packet_write_wait();
  864.  
  865.         /* Read response from the server. */
  866.         type = packet_read(&plen);
  867.         if (type == SSH_SMSG_SUCCESS) {
  868.             interactive = 1;
  869.             have_tty = 1;
  870.         } else if (type == SSH_SMSG_FAILURE)
  871.             log("Warning: Remote host failed or refused to allocate a pseudo tty.");
  872.         else
  873.             packet_disconnect("Protocol error waiting for pty request response.");
  874.     }
  875.     /* Request X11 forwarding if enabled and DISPLAY is set. */
  876.     if (options.forward_x11 && getenv("DISPLAY") != NULL) {
  877.         char proto[512], data[512];
  878.         /* Get reasonable local authentication information. */
  879.         x11_get_proto(proto, sizeof proto, data, sizeof data);
  880.         /* Request forwarding with authentication spoofing. */
  881.         debug("Requesting X11 forwarding with authentication spoofing.");
  882.         x11_request_forwarding_with_spoofing(0, proto, data);
  883.  
  884.         /* Read response from the server. */
  885.         type = packet_read(&plen);
  886.         if (type == SSH_SMSG_SUCCESS) {
  887.             interactive = 1;
  888.         } else if (type == SSH_SMSG_FAILURE) {
  889.             log("Warning: Remote host denied X11 forwarding.");
  890.         } else {
  891.             packet_disconnect("Protocol error waiting for X11 forwarding");
  892.         }
  893.     }
  894.     /* Tell the packet module whether this is an interactive session. */
  895.     packet_set_interactive(interactive, options.keepalives);
  896.  
  897.     /* Clear agent forwarding if we don\'t have an agent. */
  898.     authfd = ssh_get_authentication_socket();
  899.     if (authfd < 0)
  900.         options.forward_agent = 0;
  901.     else
  902.         ssh_close_authentication_socket(authfd);
  903.  
  904.     /* Request authentication agent forwarding if appropriate. */
  905.     if (options.forward_agent) {
  906.         debug("Requesting authentication agent forwarding.");
  907.         auth_request_forwarding();
  908.  
  909.         /* Read response from the server. */
  910.         type = packet_read(&plen);
  911.         packet_integrity_check(plen, 0, type);
  912.         if (type != SSH_SMSG_SUCCESS)
  913.             log("Warning: Remote host denied authentication agent forwarding.");
  914.     }
  915.     /* Initiate local TCP/IP port forwardings. */
  916.     for (i = 0; i < options.num_local_forwards; i++) {
  917.         debug("Connections to local port %d forwarded to remote address %.200s:%d",
  918.               options.local_forwards[i].port,
  919.               options.local_forwards[i].host,
  920.               options.local_forwards[i].host_port);
  921.         channel_request_local_forwarding(options.local_forwards[i].port,
  922.                          options.local_forwards[i].host,
  923.                          options.local_forwards[i].host_port,
  924.                          options.gateway_ports);
  925.     }
  926.  
  927.     /* Initiate remote TCP/IP port forwardings. */
  928.     for (i = 0; i < options.num_remote_forwards; i++) {
  929.         debug("Connections to remote port %d forwarded to local address %.200s:%d",
  930.               options.remote_forwards[i].port,
  931.               options.remote_forwards[i].host,
  932.               options.remote_forwards[i].host_port);
  933.         channel_request_remote_forwarding(options.remote_forwards[i].port,
  934.                           options.remote_forwards[i].host,
  935.                           options.remote_forwards[i].host_port);
  936.     }
  937.  
  938.     /* If requested, let ssh continue in the background. */
  939.     if (fork_after_authentication_flag)
  940.         if (daemon(1, 1) < 0)
  941.             fatal("daemon() failed: %.200s", strerror(errno));
  942.  
  943.     /*
  944.      * If a command was specified on the command line, execute the
  945.      * command now. Otherwise request the server to start a shell.
  946.      */
  947.     if (buffer_len(&command) > 0) {
  948.         int len = buffer_len(&command);
  949.         if (len > 900)
  950.             len = 900;
  951.         debug("Sending command: %.*s", len, buffer_ptr(&command));
  952.         packet_start(SSH_CMSG_EXEC_CMD);
  953.         packet_put_string(buffer_ptr(&command), buffer_len(&command));
  954.         packet_send();
  955.         packet_write_wait();
  956.     } else {
  957.         debug("Requesting shell.");
  958.         packet_start(SSH_CMSG_EXEC_SHELL);
  959.         packet_send();
  960.         packet_write_wait();
  961.     }
  962.  
  963.     /* Enter the interactive session. */
  964.     return client_loop(have_tty, tty_flag ? options.escape_char : -1, 0);
  965. }
  966.  
  967. static void
  968. init_local_fwd(void)
  969. {
  970.     int i;
  971.     /* Initiate local TCP/IP port forwardings. */
  972.     for (i = 0; i < options.num_local_forwards; i++) {
  973.         debug("Connections to local port %d forwarded to remote address %.200s:%d",
  974.               options.local_forwards[i].port,
  975.               options.local_forwards[i].host,
  976.               options.local_forwards[i].host_port);
  977.         channel_request_local_forwarding(options.local_forwards[i].port,
  978.                          options.local_forwards[i].host,
  979.                          options.local_forwards[i].host_port,
  980.                          options.gateway_ports);
  981.     }
  982. }
  983.  
  984. static void
  985. client_init(int id, void *arg)
  986. {
  987.     int len;
  988.     debug("client_init id %d arg %d", id, (int)arg);
  989.  
  990.     if (no_shell_flag)
  991.         goto done;
  992.  
  993.     if (tty_flag) {
  994.         struct winsize ws;
  995.         char *cp;
  996.         cp = getenv("TERM");
  997.         if (!cp)
  998.             cp = "";
  999.         /* Store window size in the packet. */
  1000.         if (ioctl(fileno(stdin), TIOCGWINSZ, &ws) < 0)
  1001.             memset(&ws, 0, sizeof(ws));
  1002.  
  1003.         channel_request_start(id, "pty-req", 0);
  1004.         packet_put_cstring(cp);
  1005.         packet_put_int(ws.ws_col);
  1006.         packet_put_int(ws.ws_row);
  1007.         packet_put_int(ws.ws_xpixel);
  1008.         packet_put_int(ws.ws_ypixel);
  1009.         packet_put_cstring("");        /* XXX: encode terminal modes */
  1010.         packet_send();
  1011.         /* XXX wait for reply */
  1012.     }
  1013.     if (options.forward_x11 &&
  1014.         getenv("DISPLAY") != NULL) {
  1015.         char proto[512], data[512];
  1016.         /* Get reasonable local authentication information. */
  1017.         x11_get_proto(proto, sizeof proto, data, sizeof data);
  1018.         /* Request forwarding with authentication spoofing. */
  1019.         debug("Requesting X11 forwarding with authentication spoofing.");
  1020.         x11_request_forwarding_with_spoofing(id, proto, data);
  1021.         /* XXX wait for reply */
  1022.     }
  1023.  
  1024.     len = buffer_len(&command);
  1025.     if (len > 0) {
  1026.         if (len > 900)
  1027.             len = 900;
  1028.         debug("Sending command: %.*s", len, buffer_ptr(&command));
  1029.         channel_request_start(id, "exec", 0);
  1030.         packet_put_string(buffer_ptr(&command), len);
  1031.         packet_send();
  1032.     } else {
  1033.         channel_request(id, "shell", 0);
  1034.     }
  1035.     /* channel_callback(id, SSH2_MSG_OPEN_CONFIGMATION, client_init, 0); */
  1036. done:
  1037.     /* register different callback, etc. XXX */
  1038.     client_set_session_ident(id);
  1039. }
  1040.  
  1041. static int
  1042. ssh_session2(void)
  1043. {
  1044.     int window, packetmax, id;
  1045.     int in, out, err;
  1046.  
  1047.     if (stdin_null_flag) {
  1048.         in = open("/dev/null", O_RDONLY);
  1049.     } else {
  1050.         in = dup(STDIN_FILENO);
  1051.     }
  1052.     out = dup(STDOUT_FILENO);
  1053.     err = dup(STDERR_FILENO);
  1054.  
  1055.     if (in < 0 || out < 0 || err < 0)
  1056.         fatal("dup() in/out/err failed");
  1057.  
  1058.     /* should be pre-session */
  1059.     init_local_fwd();
  1060.     
  1061.     /* If requested, let ssh continue in the background. */
  1062.     if (fork_after_authentication_flag)
  1063.         if (daemon(1, 1) < 0)
  1064.             fatal("daemon() failed: %.200s", strerror(errno));
  1065.  
  1066.     window = 32*1024;
  1067.     if (tty_flag) {
  1068.         packetmax = window/8;
  1069.     } else {
  1070.         window *= 2;
  1071.         packetmax = window/2;
  1072.     }
  1073.  
  1074. /*XXX MAXPACK */
  1075.     id = channel_new(
  1076.         "session", SSH_CHANNEL_OPENING, in, out, err,
  1077.         window, packetmax, CHAN_EXTENDED_WRITE, xstrdup("client-session"));
  1078.  
  1079.     channel_open(id);
  1080.     channel_register_callback(id, SSH2_MSG_CHANNEL_OPEN_CONFIRMATION, client_init, (void *)0);
  1081.  
  1082.     return client_loop(tty_flag, tty_flag ? options.escape_char : -1, id);
  1083. }
  1084.  
  1085. /*
  1086.  * Connect to the given ssh server using a proxy command.
  1087.  */
  1088. static int
  1089. ssh_proxy_connect(const char *host, u_short port, uid_t original_real_uid,
  1090.           const char *proxy_command)
  1091. {
  1092.     Buffer command;
  1093.     const char *cp;
  1094.     char *command_string;
  1095.     int pin[2], pout[2];
  1096.     pid_t pid;
  1097.     char strport[NI_MAXSERV];
  1098.  
  1099.     /* Convert the port number into a string. */
  1100.     snprintf(strport, sizeof strport, "%hu", port);
  1101.  
  1102.     /* Build the final command string in the buffer by making the
  1103.     appropriate substitutions to the given proxy command. */
  1104.     buffer_init(&command);
  1105.     for (cp = proxy_command; *cp; cp++) {
  1106.         if (cp[0] == '%' && cp[1] == '%') {
  1107.             buffer_append(&command, "%", 1);
  1108.             cp++;
  1109.             continue;
  1110.         }
  1111.         if (cp[0] == '%' && cp[1] == 'h') {
  1112.             buffer_append(&command, host, strlen(host));
  1113.             cp++;
  1114.             continue;
  1115.         }
  1116.         if (cp[0] == '%' && cp[1] == 'p') {
  1117.             buffer_append(&command, strport, strlen(strport));
  1118.             cp++;
  1119.             continue;
  1120.         }
  1121.         buffer_append(&command, cp, 1);
  1122.     }
  1123.     buffer_append(&command, "\0", 1);
  1124.  
  1125.     /* Get the final command string. */
  1126.     command_string = buffer_ptr(&command);
  1127.  
  1128.     /* Create pipes for communicating with the proxy. */
  1129.     if (pipe(pin) < 0 || pipe(pout) < 0)
  1130.         fatal("Could not create pipes to communicate with the proxy: %.100s",
  1131.                strerror(errno));
  1132.  
  1133.     debug("Executing proxy command: %.500s", command_string);
  1134.  
  1135.     /* Fork and execute the proxy command. */
  1136.     if ((pid = fork()) == 0) {
  1137.         char *argv[10];
  1138.  
  1139.         /* Child.  Permanently give up superuser privileges. */
  1140.         permanently_set_uid(original_real_uid);
  1141.  
  1142.         /* Redirect stdin and stdout. */
  1143.         close(pin[1]);
  1144.         if (pin[0] != 0) {
  1145.             if (dup2(pin[0], 0) < 0)
  1146.                 perror("dup2 stdin");
  1147.             close(pin[0]);
  1148.         }
  1149.         close(pout[0]);
  1150.         if (dup2(pout[1], 1) < 0)
  1151.             perror("dup2 stdout");
  1152.         /* Cannot be 1 because pin allocated two descriptors. */
  1153.         close(pout[1]);
  1154.  
  1155.         /* Stderr is left as it is so that error messages get
  1156.            printed on the user's terminal. */
  1157.         argv[0] = _PATH_BSHELL;
  1158.         argv[1] = "-c";
  1159.         argv[2] = command_string;
  1160.         argv[3] = NULL;
  1161.  
  1162.         /* Execute the proxy command.  Note that we gave up any
  1163.            extra privileges above. */
  1164.         execv(_PATH_BSHELL, argv);
  1165.         perror(_PATH_BSHELL);
  1166.         exit(1);
  1167.     }
  1168.     /* Parent. */
  1169.     if (pid < 0)
  1170.         fatal("fork failed: %.100s", strerror(errno));
  1171.  
  1172.     /* Close child side of the descriptors. */
  1173.     close(pin[0]);
  1174.     close(pout[1]);
  1175.  
  1176.     /* Free the command name. */
  1177.     buffer_free(&command);
  1178.  
  1179.     /* Set the connection file descriptors. */
  1180.     packet_set_connection(pout[0], pin[1]);
  1181.  
  1182.     return 1;
  1183. }
  1184.  
  1185. /*
  1186.  * Creates a (possibly privileged) socket for use as the ssh connection.
  1187.  */
  1188. static int
  1189. ssh_create_socket(uid_t original_real_uid, int privileged, int family)
  1190. {
  1191.     int sock;
  1192.  
  1193.     /*
  1194.      * If we are running as root and want to connect to a privileged
  1195.      * port, bind our own socket to a privileged port.
  1196.      */
  1197.     if (privileged) {
  1198.         int p = IPPORT_RESERVED - 1;
  1199.         sock = rresvport_af(&p, family);
  1200.         if (sock < 0)
  1201.             error("rresvport: af=%d %.100s", family, strerror(errno));
  1202.         else
  1203.             debug("Allocated local port %d.", p);
  1204.     } else {
  1205.         /*
  1206.          * Just create an ordinary socket on arbitrary port.  We use
  1207.          * the user's uid to create the socket.
  1208.          */
  1209.         temporarily_use_uid(original_real_uid);
  1210.         sock = socket(family, SOCK_STREAM, 0);
  1211.         if (sock < 0)
  1212.             error("socket: %.100s", strerror(errno));
  1213.         restore_uid();
  1214.     }
  1215.     return sock;
  1216. }
  1217.  
  1218. /*
  1219.  * Opens a TCP/IP connection to the remote server on the given host.
  1220.  * The address of the remote host will be returned in hostaddr.
  1221.  * If port is 0, the default port will be used.  If anonymous is zero,
  1222.  * a privileged port will be allocated to make the connection.
  1223.  * This requires super-user privileges if anonymous is false.
  1224.  * Connection_attempts specifies the maximum number of tries (one per
  1225.  * second).  If proxy_command is non-NULL, it specifies the command (with %h
  1226.  * and %p substituted for host and port, respectively) to use to contact
  1227.  * the daemon.
  1228.  */
  1229. static int
  1230. ssh_connect(const char *host, struct sockaddr_storage * hostaddr,
  1231.         u_short port, int connection_attempts,
  1232.         int anonymous, uid_t original_real_uid,
  1233.         const char *proxy_command)
  1234. {
  1235.     int sock = -1, attempt;
  1236.     struct servent *sp;
  1237.     struct addrinfo hints, *ai, *aitop;
  1238.     char ntop[NI_MAXHOST], strport[NI_MAXSERV];
  1239.     int gaierr;
  1240.     struct linger linger;
  1241.  
  1242.     debug("ssh_connect: getuid %u geteuid %u anon %d",
  1243.           (u_int) getuid(), (u_int) geteuid(), anonymous);
  1244.  
  1245.     /* Get default port if port has not been set. */
  1246.     if (port == 0) {
  1247.         sp = getservbyname(SSH_SERVICE_NAME, "tcp");
  1248.         if (sp)
  1249.             port = ntohs(sp->s_port);
  1250.         else
  1251.             port = SSH_DEFAULT_PORT;
  1252.     }
  1253.     /* If a proxy command is given, connect using it. */
  1254.     if (proxy_command != NULL)
  1255.         return ssh_proxy_connect(host, port, original_real_uid, proxy_command);
  1256.  
  1257.     /* No proxy command. */
  1258.  
  1259.     memset(&hints, 0, sizeof(hints));
  1260.     hints.ai_family = IPv4or6;
  1261.     hints.ai_socktype = SOCK_STREAM;
  1262.     snprintf(strport, sizeof strport, "%d", port);
  1263.     if ((gaierr = getaddrinfo(host, strport, &hints, &aitop)) != 0)
  1264.         fatal("%s: %.100s: %s", __progname, host,
  1265.             gai_strerror(gaierr));
  1266.  
  1267.     /*
  1268.      * Try to connect several times.  On some machines, the first time
  1269.      * will sometimes fail.  In general socket code appears to behave
  1270.      * quite magically on many machines.
  1271.      */
  1272.     for (attempt = 0; attempt < connection_attempts; attempt++) {
  1273.         if (attempt > 0)
  1274.             debug("Trying again...");
  1275.  
  1276.         /* Loop through addresses for this host, and try each one in
  1277.            sequence until the connection succeeds. */
  1278.         for (ai = aitop; ai; ai = ai->ai_next) {
  1279.             if (ai->ai_family != AF_INET && ai->ai_family != AF_INET6)
  1280.                 continue;
  1281.             if (getnameinfo(ai->ai_addr, ai->ai_addrlen,
  1282.                 ntop, sizeof(ntop), strport, sizeof(strport),
  1283.                 NI_NUMERICHOST|NI_NUMERICSERV) != 0) {
  1284.                 error("ssh_connect: getnameinfo failed");
  1285.                 continue;
  1286.             }
  1287.             debug("Connecting to %.200s [%.100s] port %s.",
  1288.                 host, ntop, strport);
  1289.  
  1290.             /* Create a socket for connecting. */
  1291.             sock = ssh_create_socket(original_real_uid,
  1292.                 !anonymous && geteuid() == 0 && port < IPPORT_RESERVED,
  1293.                 ai->ai_family);
  1294.             if (sock < 0)
  1295.                 continue;
  1296.  
  1297.             /* Connect to the host.  We use the user's uid in the
  1298.              * hope that it will help with tcp_wrappers showing
  1299.              * the remote uid as root.
  1300.              */
  1301.             temporarily_use_uid(original_real_uid);
  1302.             if (connect(sock, ai->ai_addr, ai->ai_addrlen) >= 0) {
  1303.                 /* Successful connection. */
  1304.                 memcpy(hostaddr, ai->ai_addr, ai->ai_addrlen);
  1305.                 restore_uid();
  1306.                 break;
  1307.             } else {
  1308.                 debug("connect: %.100s", strerror(errno));
  1309.                 restore_uid();
  1310.                 /*
  1311.                  * Close the failed socket; there appear to
  1312.                  * be some problems when reusing a socket for
  1313.                  * which connect() has already returned an
  1314.                  * error.
  1315.                  */
  1316.                 shutdown(sock, SHUT_RDWR);
  1317.                 close(sock);
  1318.             }
  1319.         }
  1320.         if (ai)
  1321.             break;    /* Successful connection. */
  1322.  
  1323.         /* Sleep a moment before retrying. */
  1324.         sleep(1);
  1325.     }
  1326.  
  1327.     freeaddrinfo(aitop);
  1328.  
  1329.     /* Return failure if we didn't get a successful connection. */
  1330.     if (attempt >= connection_attempts)
  1331.         return 0;
  1332.  
  1333.     debug("Connection established.");
  1334.  
  1335.     /*
  1336.      * Set socket options.  We would like the socket to disappear as soon
  1337.      * as it has been closed for whatever reason.
  1338.      */
  1339.     /* setsockopt(sock, SOL_SOCKET, SO_REUSEADDR, (void *)&on, sizeof(on)); */
  1340.     linger.l_onoff = 1;
  1341.     linger.l_linger = 5;
  1342.     setsockopt(sock, SOL_SOCKET, SO_LINGER, (void *) &linger, sizeof(linger));
  1343.  
  1344.     /* Set the connection. */
  1345.     packet_set_connection(sock, sock);
  1346.  
  1347.     return 1;
  1348. }
  1349.  
  1350. /*
  1351.  * Waits for the server identification string, and sends our own
  1352.  * identification string.
  1353.  */
  1354. static void
  1355. ssh_exchange_identification()
  1356. {
  1357.     char buf[256], remote_version[256];    /* must be same size! */
  1358.     int remote_major, remote_minor, i, mismatch;
  1359.     int connection_in = packet_get_connection_in();
  1360.     int connection_out = packet_get_connection_out();
  1361.  
  1362.     /* Read other side\'s version identification. */
  1363.     for (;;) {
  1364.         for (i = 0; i < sizeof(buf) - 1; i++) {
  1365.             int len = atomicio(read, connection_in, &buf[i], 1);
  1366.             if (len < 0)
  1367.                 fatal("ssh_exchange_identification: read: %.100s", strerror(errno));
  1368.             if (len != 1)
  1369.                 fatal("ssh_exchange_identification: Connection closed by remote host");
  1370.             if (buf[i] == '\r') {
  1371.                 buf[i] = '\n';
  1372.                 buf[i + 1] = 0;
  1373.                 continue;        /**XXX wait for \n */
  1374.             }
  1375.             if (buf[i] == '\n') {
  1376.                 buf[i + 1] = 0;
  1377.                 break;
  1378.             }
  1379.         }
  1380.         buf[sizeof(buf) - 1] = 0;
  1381.         if (strncmp(buf, "SSH-", 4) == 0)
  1382.             break;
  1383.         debug("ssh_exchange_identification: %s", buf);
  1384.     }
  1385.     server_version_string = xstrdup(buf);
  1386.  
  1387.     /*
  1388.      * Check that the versions match.  In future this might accept
  1389.      * several versions and set appropriate flags to handle them.
  1390.      */
  1391.     if (sscanf(server_version_string, "SSH-%d.%d-%[^\n]\n",
  1392.         &remote_major, &remote_minor, remote_version) != 3)
  1393.         fatal("Bad remote protocol version identification: '%.100s'", buf);
  1394.     debug("Remote protocol version %d.%d, remote software version %.100s",
  1395.           remote_major, remote_minor, remote_version);
  1396.  
  1397.     compat_datafellows(remote_version);
  1398.     mismatch = 0;
  1399.  
  1400.     switch(remote_major) {
  1401.     case 1:
  1402.         if (remote_minor == 99 &&
  1403.             (options.protocol & SSH_PROTO_2) &&
  1404.             !(options.protocol & SSH_PROTO_1_PREFERRED)) {
  1405.             enable_compat20();
  1406.             break;
  1407.         }
  1408.         if (!(options.protocol & SSH_PROTO_1)) {
  1409.             mismatch = 1;
  1410.             break;
  1411.         }
  1412.         if (remote_minor < 3) {
  1413.             fatal("Remote machine has too old SSH software version.");
  1414.         } else if (remote_minor == 3) {
  1415.             /* We speak 1.3, too. */
  1416.             enable_compat13();
  1417.             if (options.forward_agent) {
  1418.                 log("Agent forwarding disabled for protocol 1.3");
  1419.                 options.forward_agent = 0;
  1420.             }
  1421.         }
  1422.         break;
  1423.     case 2:
  1424.         if (options.protocol & SSH_PROTO_2) {
  1425.             enable_compat20();
  1426.             break;
  1427.         }
  1428.         /* FALLTHROUGH */
  1429.     default:
  1430.         mismatch = 1;
  1431.         break;
  1432.     }
  1433.     if (mismatch)
  1434.         fatal("Protocol major versions differ: %d vs. %d",
  1435.             (options.protocol & SSH_PROTO_2) ? PROTOCOL_MAJOR_2 : PROTOCOL_MAJOR_1,
  1436.             remote_major);
  1437.     if (compat20)
  1438.         packet_set_ssh2_format();
  1439.     /* Send our own protocol version identification. */
  1440.     snprintf(buf, sizeof buf, "SSH-%d.%d-%.100s\n",
  1441.         compat20 ? PROTOCOL_MAJOR_2 : PROTOCOL_MAJOR_1,
  1442.         compat20 ? PROTOCOL_MINOR_2 : PROTOCOL_MINOR_1,
  1443.         SSH_VERSION);
  1444.     if (atomicio(write, connection_out, buf, strlen(buf)) != strlen(buf))
  1445.         fatal("write: %.100s", strerror(errno));
  1446.     client_version_string = xstrdup(buf);
  1447.     chop(client_version_string);
  1448.     chop(server_version_string);
  1449.     debug("Local version string %.100s", client_version_string);
  1450. }
  1451.  
  1452. static int
  1453. read_yes_or_no(const char *prompt, int defval)
  1454. {
  1455.     char buf[1024];
  1456.     FILE *f;
  1457.     int retval = -1;
  1458.  
  1459.     if (isatty(0))
  1460.         f = stdin;
  1461.     else
  1462.         f = fopen("/dev/tty", "rw");
  1463.  
  1464.     if (f == NULL)
  1465.         return 0;
  1466.  
  1467.     fflush(stdout);
  1468.  
  1469.     while (1) {
  1470.         fprintf(stderr, "%s", prompt);
  1471.         if (fgets(buf, sizeof(buf), f) == NULL) {
  1472.             /* Print a newline (the prompt probably didn\'t have one). */
  1473.             fprintf(stderr, "\n");
  1474.             strlcpy(buf, "no", sizeof buf);
  1475.         }
  1476.         /* Remove newline from response. */
  1477.         if (strchr(buf, '\n'))
  1478.             *strchr(buf, '\n') = 0;
  1479.  
  1480.         if (buf[0] == 0)
  1481.             retval = defval;
  1482.         if (strcmp(buf, "yes") == 0)
  1483.             retval = 1;
  1484.         if (strcmp(buf, "no") == 0)
  1485.             retval = 0;
  1486.  
  1487.         if (retval != -1) {
  1488.             if (f != stdin)
  1489.                 fclose(f);
  1490.             return retval;
  1491.         }
  1492.     }
  1493. }
  1494.  
  1495. /*
  1496.  * check whether the supplied host key is valid, return only if ok.
  1497.  */
  1498.  
  1499. static void
  1500. check_host_key(char *host, struct sockaddr *hostaddr, Key *host_key,
  1501.     const char *user_hostfile, const char *system_hostfile)
  1502. {
  1503.     Key *file_key;
  1504.     char *type = key_type(host_key);
  1505.     char *ip = NULL;
  1506.     char hostline[1000], *hostp;
  1507.     HostStatus host_status;
  1508.     HostStatus ip_status;
  1509.     int local = 0, host_ip_differ = 0;
  1510.     int salen;
  1511.     char ntop[NI_MAXHOST];
  1512.  
  1513.     /*
  1514.      * Force accepting of the host key for loopback/localhost. The
  1515.      * problem is that if the home directory is NFS-mounted to multiple
  1516.      * machines, localhost will refer to a different machine in each of
  1517.      * them, and the user will get bogus HOST_CHANGED warnings.  This
  1518.      * essentially disables host authentication for localhost; however,
  1519.      * this is probably not a real problem.
  1520.      */
  1521.     /**  hostaddr == 0! */
  1522.     switch (hostaddr->sa_family) {
  1523.     case AF_INET:
  1524.         local = (ntohl(((struct sockaddr_in *)hostaddr)->sin_addr.s_addr) >> 24) == IN_LOOPBACKNET;
  1525.         salen = sizeof(struct sockaddr_in);
  1526.         break;
  1527.     case AF_INET6:
  1528.         local = IN6_IS_ADDR_LOOPBACK(&(((struct sockaddr_in6 *)hostaddr)->sin6_addr));
  1529.         salen = sizeof(struct sockaddr_in6);
  1530.         break;
  1531.     default:
  1532.         local = 0;
  1533.         salen = sizeof(struct sockaddr_storage);
  1534.         break;
  1535.     }
  1536.     if (local) {
  1537.         debug("Forcing accepting of host key for loopback/localhost.");
  1538.         return;
  1539.     }
  1540.  
  1541.     /*
  1542.      * Turn off check_host_ip for proxy connects, since
  1543.      * we don't have the remote ip-address
  1544.      */
  1545.     if (options.proxy_command != NULL && options.check_host_ip)
  1546.         options.check_host_ip = 0;
  1547.  
  1548.     if (options.check_host_ip) {
  1549.         if (getnameinfo(hostaddr, salen, ntop, sizeof(ntop),
  1550.             NULL, 0, NI_NUMERICHOST) != 0)
  1551.             fatal("check_host_key: getnameinfo failed");
  1552.         ip = xstrdup(ntop);
  1553.     }
  1554.  
  1555.     /*
  1556.      * Store the host key from the known host file in here so that we can
  1557.      * compare it with the key for the IP address.
  1558.      */
  1559.     file_key = key_new(host_key->type);
  1560.  
  1561.     /*
  1562.      * Check if the host key is present in the user\'s list of known
  1563.      * hosts or in the systemwide list.
  1564.      */
  1565.     host_status = check_host_in_hostfile(user_hostfile, host, host_key, file_key);
  1566.     if (host_status == HOST_NEW)
  1567.         host_status = check_host_in_hostfile(system_hostfile, host, host_key, file_key);
  1568.     /*
  1569.      * Also perform check for the ip address, skip the check if we are
  1570.      * localhost or the hostname was an ip address to begin with
  1571.      */
  1572.     if (options.check_host_ip && !local && strcmp(host, ip)) {
  1573.         Key *ip_key = key_new(host_key->type);
  1574.         ip_status = check_host_in_hostfile(user_hostfile, ip, host_key, ip_key);
  1575.  
  1576.         if (ip_status == HOST_NEW)
  1577.             ip_status = check_host_in_hostfile(system_hostfile, ip, host_key, ip_key);
  1578.         if (host_status == HOST_CHANGED &&
  1579.             (ip_status != HOST_CHANGED || !key_equal(ip_key, file_key)))
  1580.             host_ip_differ = 1;
  1581.  
  1582.         key_free(ip_key);
  1583.     } else
  1584.         ip_status = host_status;
  1585.  
  1586.     key_free(file_key);
  1587.  
  1588.     switch (host_status) {
  1589.     case HOST_OK:
  1590.         /* The host is known and the key matches. */
  1591.         debug("Host '%.200s' is known and matches the %s host key.",
  1592.             host, type);
  1593.         if (options.check_host_ip) {
  1594.             if (ip_status == HOST_NEW) {
  1595.                 if (!add_host_to_hostfile(user_hostfile, ip, host_key))
  1596.                     log("Failed to add the %s host key for IP address '%.30s' to the list of known hosts (%.30s).",
  1597.                         type, ip, user_hostfile);
  1598.                 else
  1599.                     log("Warning: Permanently added the %s host key for IP address '%.30s' to the list of known hosts.",
  1600.                         type, ip);
  1601.             } else if (ip_status != HOST_OK)
  1602.                 log("Warning: the %s host key for '%.200s' differs from the key for the IP address '%.30s'",
  1603.                     type, host, ip);
  1604.         }
  1605.         break;
  1606.     case HOST_NEW:
  1607.         /* The host is new. */
  1608.         if (options.strict_host_key_checking == 1) {
  1609.             /* User has requested strict host key checking.  We will not add the host key
  1610.                automatically.  The only alternative left is to abort. */
  1611.             fatal("No %s host key is known for %.200s and you have requested strict checking.", type, host);
  1612.         } else if (options.strict_host_key_checking == 2) {
  1613.             /* The default */
  1614.             char prompt[1024];
  1615.             char *fp = key_fingerprint(host_key);
  1616.             snprintf(prompt, sizeof(prompt),
  1617.                 "The authenticity of host '%.200s' can't be established.\n"
  1618.                 "%s key fingerprint is %s.\n"
  1619.                 "Are you sure you want to continue connecting (yes/no)? ",
  1620.                 host, type, fp);
  1621.             if (!read_yes_or_no(prompt, -1))
  1622.                 fatal("Aborted by user!\n");
  1623.         }
  1624.         if (options.check_host_ip && ip_status == HOST_NEW && strcmp(host, ip)) {
  1625.             snprintf(hostline, sizeof(hostline), "%s,%s", host, ip);
  1626.             hostp = hostline;
  1627.         } else
  1628.             hostp = host;
  1629.  
  1630.         /* If not in strict mode, add the key automatically to the local known_hosts file. */
  1631.         if (!add_host_to_hostfile(user_hostfile, hostp, host_key))
  1632.             log("Failed to add the host to the list of known hosts (%.500s).",
  1633.                 user_hostfile);
  1634.         else
  1635.             log("Warning: Permanently added '%.200s' (%s) to the list of known hosts.",
  1636.                 hostp, type);
  1637.         break;
  1638.     case HOST_CHANGED:
  1639.         if (options.check_host_ip && host_ip_differ) {
  1640.             char *msg;
  1641.             if (ip_status == HOST_NEW)
  1642.                 msg = "is unknown";
  1643.             else if (ip_status == HOST_OK)
  1644.                 msg = "is unchanged";
  1645.             else
  1646.                 msg = "has a different value";
  1647.             error("@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@");
  1648.             error("@       WARNING: POSSIBLE DNS SPOOFING DETECTED!          @");
  1649.             error("@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@");
  1650.             error("The %s host key for %s has changed,", type, host);
  1651.             error("and the key for the according IP address %s", ip);
  1652.             error("%s. This could either mean that", msg);
  1653.             error("DNS SPOOFING is happening or the IP address for the host");
  1654.             error("and its host key have changed at the same time");
  1655.         }
  1656.         /* The host key has changed. */
  1657.         error("@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@");
  1658.         error("@    WARNING: REMOTE HOST IDENTIFICATION HAS CHANGED!     @");
  1659.         error("@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@");
  1660.         error("IT IS POSSIBLE THAT SOMEONE IS DOING SOMETHING NASTY!");
  1661.         error("Someone could be eavesdropping on you right now (man-in-the-middle attack)!");
  1662.         error("It is also possible that the %s host key has just been changed.", type);
  1663.         error("Please contact your system administrator.");
  1664.         error("Add correct host key in %.100s to get rid of this message.",
  1665.               user_hostfile);
  1666.  
  1667.         /*
  1668.          * If strict host key checking is in use, the user will have
  1669.          * to edit the key manually and we can only abort.
  1670.          */
  1671.         if (options.strict_host_key_checking)
  1672.             fatal("%s host key for %.200s has changed and you have requested strict checking.", type, host);
  1673.  
  1674.         /*
  1675.          * If strict host key checking has not been requested, allow
  1676.          * the connection but without password authentication or
  1677.          * agent forwarding.
  1678.          */
  1679.         if (options.password_authentication) {
  1680.             error("Password authentication is disabled to avoid trojan horses.");
  1681.             options.password_authentication = 0;
  1682.         }
  1683.         if (options.forward_agent) {
  1684.             error("Agent forwarding is disabled to avoid trojan horses.");
  1685.             options.forward_agent = 0;
  1686.         }
  1687.         /*
  1688.          * XXX Should permit the user to change to use the new id.
  1689.          * This could be done by converting the host key to an
  1690.          * identifying sentence, tell that the host identifies itself
  1691.          * by that sentence, and ask the user if he/she whishes to
  1692.          * accept the authentication.
  1693.          */
  1694.         break;
  1695.     }
  1696.     if (options.check_host_ip)
  1697.         xfree(ip);
  1698. }
  1699.  
  1700. /*
  1701.  * Starts a dialog with the server, and authenticates the current user on the
  1702.  * server.  This does not need any extra privileges.  The basic connection
  1703.  * to the server must already have been established before this is called.
  1704.  * If login fails, this function prints an error and never returns.
  1705.  * This function does not require super-user privileges.
  1706.  */
  1707. static void
  1708. ssh_login(int host_key_valid, RSA *own_host_key, const char *orighost,
  1709.     struct sockaddr *hostaddr, uid_t original_real_uid)
  1710. {
  1711.     struct passwd *pw;
  1712.     char *host, *cp;
  1713.     char *server_user, *local_user;
  1714.  
  1715.     /* Get local user name.  Use it as server user if no user name was given. */
  1716.     pw = getpwuid(original_real_uid);
  1717.     if (!pw)
  1718.         fatal("User id %u not found from user database.", original_real_uid);
  1719.     local_user = xstrdup(pw->pw_name);
  1720.     server_user = options.user ? options.user : local_user;
  1721.  
  1722.     /* Convert the user-supplied hostname into all lowercase. */
  1723.     host = xstrdup(orighost);
  1724.     for (cp = host; *cp; cp++)
  1725.         if (isupper(*cp))
  1726.             *cp = tolower(*cp);
  1727.  
  1728.     /* Exchange protocol version identification strings with the server. */
  1729.     ssh_exchange_identification();
  1730.  
  1731.     /* Put the connection into non-blocking mode. */
  1732.     packet_set_nonblocking();
  1733.  
  1734.     /* key exchange */
  1735.     /* authenticate user */
  1736.     if (compat20) {
  1737.         ssh_kex2(host, hostaddr);
  1738.         ssh_userauth2(server_user, host);
  1739.     } else {
  1740.         ssh_kex(host, hostaddr);
  1741.         ssh_userauth(local_user, server_user, host, host_key_valid, own_host_key);
  1742.     }
  1743. }
  1744. #endif /* SSH */
  1745. #endif /* CK_SSL */
  1746.