1*0Sstevel@tonic-gate /* 2*0Sstevel@tonic-gate * Author: Tatu Ylonen <ylo@cs.hut.fi> 3*0Sstevel@tonic-gate * Copyright (c) 1995 Tatu Ylonen <ylo@cs.hut.fi>, Espoo, Finland 4*0Sstevel@tonic-gate * All rights reserved 5*0Sstevel@tonic-gate * This program is the ssh daemon. It listens for connections from clients, 6*0Sstevel@tonic-gate * and performs authentication, executes use commands or shell, and forwards 7*0Sstevel@tonic-gate * information to/from the application to the user client over an encrypted 8*0Sstevel@tonic-gate * connection. This can also handle forwarding of X11, TCP/IP, and 9*0Sstevel@tonic-gate * authentication agent connections. 10*0Sstevel@tonic-gate * 11*0Sstevel@tonic-gate * As far as I am concerned, the code I have written for this software 12*0Sstevel@tonic-gate * can be used freely for any purpose. Any derived versions of this 13*0Sstevel@tonic-gate * software must be clearly marked as such, and if the derived work is 14*0Sstevel@tonic-gate * incompatible with the protocol description in the RFC file, it must be 15*0Sstevel@tonic-gate * called by a name other than "ssh" or "Secure Shell". 16*0Sstevel@tonic-gate * 17*0Sstevel@tonic-gate * SSH2 implementation: 18*0Sstevel@tonic-gate * Privilege Separation: 19*0Sstevel@tonic-gate * 20*0Sstevel@tonic-gate * Copyright (c) 2000, 2001, 2002 Markus Friedl. All rights reserved. 21*0Sstevel@tonic-gate * Copyright (c) 2002 Niels Provos. All rights reserved. 22*0Sstevel@tonic-gate * 23*0Sstevel@tonic-gate * Redistribution and use in source and binary forms, with or without 24*0Sstevel@tonic-gate * modification, are permitted provided that the following conditions 25*0Sstevel@tonic-gate * are met: 26*0Sstevel@tonic-gate * 1. Redistributions of source code must retain the above copyright 27*0Sstevel@tonic-gate * notice, this list of conditions and the following disclaimer. 28*0Sstevel@tonic-gate * 2. Redistributions in binary form must reproduce the above copyright 29*0Sstevel@tonic-gate * notice, this list of conditions and the following disclaimer in the 30*0Sstevel@tonic-gate * documentation and/or other materials provided with the distribution. 31*0Sstevel@tonic-gate * 32*0Sstevel@tonic-gate * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR 33*0Sstevel@tonic-gate * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES 34*0Sstevel@tonic-gate * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. 35*0Sstevel@tonic-gate * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, 36*0Sstevel@tonic-gate * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT 37*0Sstevel@tonic-gate * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, 38*0Sstevel@tonic-gate * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY 39*0Sstevel@tonic-gate * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT 40*0Sstevel@tonic-gate * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF 41*0Sstevel@tonic-gate * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 42*0Sstevel@tonic-gate */ 43*0Sstevel@tonic-gate /* 44*0Sstevel@tonic-gate * Copyright 2005 Sun Microsystems, Inc. All rights reserved. 45*0Sstevel@tonic-gate * Use is subject to license terms. 46*0Sstevel@tonic-gate */ 47*0Sstevel@tonic-gate 48*0Sstevel@tonic-gate #include "includes.h" 49*0Sstevel@tonic-gate RCSID("$OpenBSD: sshd.c,v 1.260 2002/09/27 10:42:09 mickey Exp $"); 50*0Sstevel@tonic-gate 51*0Sstevel@tonic-gate #pragma ident "%Z%%M% %I% %E% SMI" 52*0Sstevel@tonic-gate 53*0Sstevel@tonic-gate #include <openssl/dh.h> 54*0Sstevel@tonic-gate #include <openssl/bn.h> 55*0Sstevel@tonic-gate #include <openssl/md5.h> 56*0Sstevel@tonic-gate 57*0Sstevel@tonic-gate #include <openssl/rand.h> 58*0Sstevel@tonic-gate #ifdef HAVE_SECUREWARE 59*0Sstevel@tonic-gate #include <sys/security.h> 60*0Sstevel@tonic-gate #include <prot.h> 61*0Sstevel@tonic-gate #endif 62*0Sstevel@tonic-gate 63*0Sstevel@tonic-gate #include "ssh.h" 64*0Sstevel@tonic-gate #include "ssh1.h" 65*0Sstevel@tonic-gate #include "ssh2.h" 66*0Sstevel@tonic-gate #include "xmalloc.h" 67*0Sstevel@tonic-gate #include "rsa.h" 68*0Sstevel@tonic-gate #include "sshpty.h" 69*0Sstevel@tonic-gate #include "packet.h" 70*0Sstevel@tonic-gate #include "mpaux.h" 71*0Sstevel@tonic-gate #include "log.h" 72*0Sstevel@tonic-gate #include "servconf.h" 73*0Sstevel@tonic-gate #include "uidswap.h" 74*0Sstevel@tonic-gate #include "compat.h" 75*0Sstevel@tonic-gate #include "buffer.h" 76*0Sstevel@tonic-gate #include "cipher.h" 77*0Sstevel@tonic-gate #include "kex.h" 78*0Sstevel@tonic-gate #include "key.h" 79*0Sstevel@tonic-gate #include "dh.h" 80*0Sstevel@tonic-gate #include "myproposal.h" 81*0Sstevel@tonic-gate #include "authfile.h" 82*0Sstevel@tonic-gate #include "pathnames.h" 83*0Sstevel@tonic-gate #include "atomicio.h" 84*0Sstevel@tonic-gate #include "canohost.h" 85*0Sstevel@tonic-gate #include "auth.h" 86*0Sstevel@tonic-gate #include "misc.h" 87*0Sstevel@tonic-gate #include "dispatch.h" 88*0Sstevel@tonic-gate #include "channels.h" 89*0Sstevel@tonic-gate #include "session.h" 90*0Sstevel@tonic-gate #include "monitor_mm.h" 91*0Sstevel@tonic-gate #include "monitor.h" 92*0Sstevel@tonic-gate #include "monitor_wrap.h" 93*0Sstevel@tonic-gate #include "monitor_fdpass.h" 94*0Sstevel@tonic-gate #include "g11n.h" 95*0Sstevel@tonic-gate #include "sshlogin.h" 96*0Sstevel@tonic-gate #include "xlist.h" 97*0Sstevel@tonic-gate 98*0Sstevel@tonic-gate #ifdef HAVE_BSM 99*0Sstevel@tonic-gate #include "bsmaudit.h" 100*0Sstevel@tonic-gate adt_session_data_t *ah = NULL; 101*0Sstevel@tonic-gate #endif /* HAVE_BSM */ 102*0Sstevel@tonic-gate 103*0Sstevel@tonic-gate #ifdef ALTPRIVSEP 104*0Sstevel@tonic-gate #include "altprivsep.h" 105*0Sstevel@tonic-gate #endif /* ALTPRIVSEP */ 106*0Sstevel@tonic-gate 107*0Sstevel@tonic-gate #ifdef HAVE_SOLARIS_CONTRACTS 108*0Sstevel@tonic-gate #include <sys/ctfs.h> 109*0Sstevel@tonic-gate #include <sys/contract.h> 110*0Sstevel@tonic-gate #include <sys/contract/process.h> 111*0Sstevel@tonic-gate #include <libcontract.h> 112*0Sstevel@tonic-gate #endif /* HAVE_SOLARIS_CONTRACTS */ 113*0Sstevel@tonic-gate 114*0Sstevel@tonic-gate #ifdef GSSAPI 115*0Sstevel@tonic-gate #include "ssh-gss.h" 116*0Sstevel@tonic-gate extern Gssctxt *xxx_gssctxt; 117*0Sstevel@tonic-gate #endif /* GSSAPI */ 118*0Sstevel@tonic-gate 119*0Sstevel@tonic-gate #ifdef LIBWRAP 120*0Sstevel@tonic-gate #include <tcpd.h> 121*0Sstevel@tonic-gate #include <syslog.h> 122*0Sstevel@tonic-gate #ifndef lint 123*0Sstevel@tonic-gate int allow_severity = LOG_INFO; 124*0Sstevel@tonic-gate int deny_severity = LOG_WARNING; 125*0Sstevel@tonic-gate #endif /* lint */ 126*0Sstevel@tonic-gate #endif /* LIBWRAP */ 127*0Sstevel@tonic-gate 128*0Sstevel@tonic-gate #ifndef O_NOCTTY 129*0Sstevel@tonic-gate #define O_NOCTTY 0 130*0Sstevel@tonic-gate #endif 131*0Sstevel@tonic-gate 132*0Sstevel@tonic-gate #ifdef HAVE___PROGNAME 133*0Sstevel@tonic-gate extern char *__progname; 134*0Sstevel@tonic-gate #else 135*0Sstevel@tonic-gate char *__progname; 136*0Sstevel@tonic-gate #endif 137*0Sstevel@tonic-gate 138*0Sstevel@tonic-gate /* Server configuration options. */ 139*0Sstevel@tonic-gate ServerOptions options; 140*0Sstevel@tonic-gate 141*0Sstevel@tonic-gate /* Name of the server configuration file. */ 142*0Sstevel@tonic-gate static char *config_file_name = _PATH_SERVER_CONFIG_FILE; 143*0Sstevel@tonic-gate 144*0Sstevel@tonic-gate /* 145*0Sstevel@tonic-gate * Flag indicating whether IPv4 or IPv6. This can be set on the command line. 146*0Sstevel@tonic-gate * Default value is AF_UNSPEC means both IPv4 and IPv6. 147*0Sstevel@tonic-gate */ 148*0Sstevel@tonic-gate #ifdef IPV4_DEFAULT 149*0Sstevel@tonic-gate int IPv4or6 = AF_INET; 150*0Sstevel@tonic-gate #else 151*0Sstevel@tonic-gate int IPv4or6 = AF_UNSPEC; 152*0Sstevel@tonic-gate #endif 153*0Sstevel@tonic-gate 154*0Sstevel@tonic-gate /* 155*0Sstevel@tonic-gate * Debug mode flag. This can be set on the command line. If debug 156*0Sstevel@tonic-gate * mode is enabled, extra debugging output will be sent to the system 157*0Sstevel@tonic-gate * log, the daemon will not go to background, and will exit after processing 158*0Sstevel@tonic-gate * the first connection. 159*0Sstevel@tonic-gate */ 160*0Sstevel@tonic-gate int debug_flag = 0; 161*0Sstevel@tonic-gate 162*0Sstevel@tonic-gate /* Flag indicating that the daemon should only test the configuration and keys. */ 163*0Sstevel@tonic-gate static int test_flag = 0; 164*0Sstevel@tonic-gate 165*0Sstevel@tonic-gate /* Flag indicating that the daemon is being started from inetd. */ 166*0Sstevel@tonic-gate static int inetd_flag = 0; 167*0Sstevel@tonic-gate 168*0Sstevel@tonic-gate /* Flag indicating that sshd should not detach and become a daemon. */ 169*0Sstevel@tonic-gate static int no_daemon_flag = 0; 170*0Sstevel@tonic-gate 171*0Sstevel@tonic-gate /* debug goes to stderr unless inetd_flag is set */ 172*0Sstevel@tonic-gate int log_stderr = 0; 173*0Sstevel@tonic-gate 174*0Sstevel@tonic-gate /* Saved arguments to main(). */ 175*0Sstevel@tonic-gate static char **saved_argv; 176*0Sstevel@tonic-gate static int saved_argc; 177*0Sstevel@tonic-gate 178*0Sstevel@tonic-gate /* 179*0Sstevel@tonic-gate * The sockets that the server is listening; this is used in the SIGHUP 180*0Sstevel@tonic-gate * signal handler. 181*0Sstevel@tonic-gate */ 182*0Sstevel@tonic-gate #define MAX_LISTEN_SOCKS 16 183*0Sstevel@tonic-gate static int listen_socks[MAX_LISTEN_SOCKS]; 184*0Sstevel@tonic-gate static int num_listen_socks = 0; 185*0Sstevel@tonic-gate 186*0Sstevel@tonic-gate /* 187*0Sstevel@tonic-gate * the client's version string, passed by sshd2 in compat mode. if != NULL, 188*0Sstevel@tonic-gate * sshd will skip the version-number exchange 189*0Sstevel@tonic-gate */ 190*0Sstevel@tonic-gate static char *client_version_string = NULL; 191*0Sstevel@tonic-gate static char *server_version_string = NULL; 192*0Sstevel@tonic-gate 193*0Sstevel@tonic-gate /* for rekeying XXX fixme */ 194*0Sstevel@tonic-gate Kex *xxx_kex; 195*0Sstevel@tonic-gate 196*0Sstevel@tonic-gate /* 197*0Sstevel@tonic-gate * Any really sensitive data in the application is contained in this 198*0Sstevel@tonic-gate * structure. The idea is that this structure could be locked into memory so 199*0Sstevel@tonic-gate * that the pages do not get written into swap. However, there are some 200*0Sstevel@tonic-gate * problems. The private key contains BIGNUMs, and we do not (in principle) 201*0Sstevel@tonic-gate * have access to the internals of them, and locking just the structure is 202*0Sstevel@tonic-gate * not very useful. Currently, memory locking is not implemented. 203*0Sstevel@tonic-gate */ 204*0Sstevel@tonic-gate static struct { 205*0Sstevel@tonic-gate Key *server_key; /* ephemeral server key */ 206*0Sstevel@tonic-gate Key *ssh1_host_key; /* ssh1 host key */ 207*0Sstevel@tonic-gate Key **host_keys; /* all private host keys */ 208*0Sstevel@tonic-gate int have_ssh1_key; 209*0Sstevel@tonic-gate int have_ssh2_key; 210*0Sstevel@tonic-gate u_char ssh1_cookie[SSH_SESSION_KEY_LENGTH]; 211*0Sstevel@tonic-gate } sensitive_data; 212*0Sstevel@tonic-gate 213*0Sstevel@tonic-gate /* 214*0Sstevel@tonic-gate * Flag indicating whether the RSA server key needs to be regenerated. 215*0Sstevel@tonic-gate * Is set in the SIGALRM handler and cleared when the key is regenerated. 216*0Sstevel@tonic-gate */ 217*0Sstevel@tonic-gate static volatile sig_atomic_t key_do_regen = 0; 218*0Sstevel@tonic-gate 219*0Sstevel@tonic-gate /* This is set to true when a signal is received. */ 220*0Sstevel@tonic-gate static volatile sig_atomic_t received_sighup = 0; 221*0Sstevel@tonic-gate static volatile sig_atomic_t received_sigterm = 0; 222*0Sstevel@tonic-gate 223*0Sstevel@tonic-gate /* session identifier, used by RSA-auth */ 224*0Sstevel@tonic-gate u_char session_id[16]; 225*0Sstevel@tonic-gate 226*0Sstevel@tonic-gate /* same for ssh2 */ 227*0Sstevel@tonic-gate u_char *session_id2 = NULL; 228*0Sstevel@tonic-gate int session_id2_len = 0; 229*0Sstevel@tonic-gate 230*0Sstevel@tonic-gate /* record remote hostname or ip */ 231*0Sstevel@tonic-gate u_int utmp_len = MAXHOSTNAMELEN; 232*0Sstevel@tonic-gate 233*0Sstevel@tonic-gate /* options.max_startup sized array of fd ints */ 234*0Sstevel@tonic-gate static int *startup_pipes = NULL; 235*0Sstevel@tonic-gate static int startup_pipe = -1; /* in child */ 236*0Sstevel@tonic-gate 237*0Sstevel@tonic-gate /* variables used for privilege separation */ 238*0Sstevel@tonic-gate extern struct monitor *pmonitor; 239*0Sstevel@tonic-gate extern int use_privsep; 240*0Sstevel@tonic-gate 241*0Sstevel@tonic-gate #ifdef GSSAPI 242*0Sstevel@tonic-gate static gss_OID_set mechs = GSS_C_NULL_OID_SET; 243*0Sstevel@tonic-gate #endif /* GSSAPI */ 244*0Sstevel@tonic-gate 245*0Sstevel@tonic-gate /* Prototypes for various functions defined later in this file. */ 246*0Sstevel@tonic-gate void destroy_sensitive_data(void); 247*0Sstevel@tonic-gate static void demote_sensitive_data(void); 248*0Sstevel@tonic-gate 249*0Sstevel@tonic-gate static void do_ssh1_kex(void); 250*0Sstevel@tonic-gate static void do_ssh2_kex(void); 251*0Sstevel@tonic-gate 252*0Sstevel@tonic-gate /* 253*0Sstevel@tonic-gate * Close all listening sockets 254*0Sstevel@tonic-gate */ 255*0Sstevel@tonic-gate static void 256*0Sstevel@tonic-gate close_listen_socks(void) 257*0Sstevel@tonic-gate { 258*0Sstevel@tonic-gate int i; 259*0Sstevel@tonic-gate 260*0Sstevel@tonic-gate for (i = 0; i < num_listen_socks; i++) 261*0Sstevel@tonic-gate (void) close(listen_socks[i]); 262*0Sstevel@tonic-gate num_listen_socks = -1; 263*0Sstevel@tonic-gate } 264*0Sstevel@tonic-gate 265*0Sstevel@tonic-gate static void 266*0Sstevel@tonic-gate close_startup_pipes(void) 267*0Sstevel@tonic-gate { 268*0Sstevel@tonic-gate int i; 269*0Sstevel@tonic-gate 270*0Sstevel@tonic-gate if (startup_pipes) 271*0Sstevel@tonic-gate for (i = 0; i < options.max_startups; i++) 272*0Sstevel@tonic-gate if (startup_pipes[i] != -1) 273*0Sstevel@tonic-gate (void) close(startup_pipes[i]); 274*0Sstevel@tonic-gate } 275*0Sstevel@tonic-gate 276*0Sstevel@tonic-gate /* 277*0Sstevel@tonic-gate * Signal handler for SIGHUP. Sshd execs itself when it receives SIGHUP; 278*0Sstevel@tonic-gate * the effect is to reread the configuration file (and to regenerate 279*0Sstevel@tonic-gate * the server key). 280*0Sstevel@tonic-gate */ 281*0Sstevel@tonic-gate static void 282*0Sstevel@tonic-gate sighup_handler(int sig) 283*0Sstevel@tonic-gate { 284*0Sstevel@tonic-gate int save_errno = errno; 285*0Sstevel@tonic-gate 286*0Sstevel@tonic-gate received_sighup = 1; 287*0Sstevel@tonic-gate (void) signal(SIGHUP, sighup_handler); 288*0Sstevel@tonic-gate errno = save_errno; 289*0Sstevel@tonic-gate } 290*0Sstevel@tonic-gate 291*0Sstevel@tonic-gate /* 292*0Sstevel@tonic-gate * Called from the main program after receiving SIGHUP. 293*0Sstevel@tonic-gate * Restarts the server. 294*0Sstevel@tonic-gate */ 295*0Sstevel@tonic-gate static void 296*0Sstevel@tonic-gate sighup_restart(void) 297*0Sstevel@tonic-gate { 298*0Sstevel@tonic-gate log("Received SIGHUP; restarting."); 299*0Sstevel@tonic-gate close_listen_socks(); 300*0Sstevel@tonic-gate close_startup_pipes(); 301*0Sstevel@tonic-gate (void) execv(saved_argv[0], saved_argv); 302*0Sstevel@tonic-gate log("RESTART FAILED: av[0]='%.100s', error: %.100s.", saved_argv[0], 303*0Sstevel@tonic-gate strerror(errno)); 304*0Sstevel@tonic-gate exit(1); 305*0Sstevel@tonic-gate } 306*0Sstevel@tonic-gate 307*0Sstevel@tonic-gate /* 308*0Sstevel@tonic-gate * Generic signal handler for terminating signals in the master daemon. 309*0Sstevel@tonic-gate */ 310*0Sstevel@tonic-gate static void 311*0Sstevel@tonic-gate sigterm_handler(int sig) 312*0Sstevel@tonic-gate { 313*0Sstevel@tonic-gate received_sigterm = sig; 314*0Sstevel@tonic-gate } 315*0Sstevel@tonic-gate 316*0Sstevel@tonic-gate /* 317*0Sstevel@tonic-gate * SIGCHLD handler. This is called whenever a child dies. This will then 318*0Sstevel@tonic-gate * reap any zombies left by exited children. 319*0Sstevel@tonic-gate */ 320*0Sstevel@tonic-gate static void 321*0Sstevel@tonic-gate main_sigchld_handler(int sig) 322*0Sstevel@tonic-gate { 323*0Sstevel@tonic-gate int save_errno = errno; 324*0Sstevel@tonic-gate pid_t pid; 325*0Sstevel@tonic-gate int status; 326*0Sstevel@tonic-gate 327*0Sstevel@tonic-gate while ((pid = waitpid(-1, &status, WNOHANG)) > 0 || 328*0Sstevel@tonic-gate (pid < 0 && errno == EINTR)) 329*0Sstevel@tonic-gate ; 330*0Sstevel@tonic-gate 331*0Sstevel@tonic-gate (void) signal(SIGCHLD, main_sigchld_handler); 332*0Sstevel@tonic-gate errno = save_errno; 333*0Sstevel@tonic-gate } 334*0Sstevel@tonic-gate 335*0Sstevel@tonic-gate /* 336*0Sstevel@tonic-gate * Signal handler for the alarm after the login grace period has expired. 337*0Sstevel@tonic-gate */ 338*0Sstevel@tonic-gate static void 339*0Sstevel@tonic-gate grace_alarm_handler(int sig) 340*0Sstevel@tonic-gate { 341*0Sstevel@tonic-gate /* XXX no idea how fix this signal handler */ 342*0Sstevel@tonic-gate 343*0Sstevel@tonic-gate /* Log error and exit. */ 344*0Sstevel@tonic-gate fatal("Timeout before authentication for %s", get_remote_ipaddr()); 345*0Sstevel@tonic-gate } 346*0Sstevel@tonic-gate 347*0Sstevel@tonic-gate #ifdef HAVE_SOLARIS_CONTRACTS 348*0Sstevel@tonic-gate static int contracts_fd = -1; 349*0Sstevel@tonic-gate void 350*0Sstevel@tonic-gate contracts_pre_fork() 351*0Sstevel@tonic-gate { 352*0Sstevel@tonic-gate const char *during = "opening process contract template"; 353*0Sstevel@tonic-gate 354*0Sstevel@tonic-gate /* 355*0Sstevel@tonic-gate * Failure should not be treated as fatal on the theory that 356*0Sstevel@tonic-gate * it's better to start with children in the same contract as 357*0Sstevel@tonic-gate * the master listener than not at all. 358*0Sstevel@tonic-gate */ 359*0Sstevel@tonic-gate 360*0Sstevel@tonic-gate if (contracts_fd == -1) { 361*0Sstevel@tonic-gate if ((contracts_fd = open64(CTFS_ROOT "/process/template", 362*0Sstevel@tonic-gate O_RDWR)) == -1) 363*0Sstevel@tonic-gate goto cleanup; 364*0Sstevel@tonic-gate 365*0Sstevel@tonic-gate during = "setting sundry contract terms"; 366*0Sstevel@tonic-gate if ((errno = ct_pr_tmpl_set_param(contracts_fd, CT_PR_PGRPONLY))) 367*0Sstevel@tonic-gate goto cleanup; 368*0Sstevel@tonic-gate 369*0Sstevel@tonic-gate if ((errno = ct_tmpl_set_informative(contracts_fd, CT_PR_EV_HWERR))) 370*0Sstevel@tonic-gate goto cleanup; 371*0Sstevel@tonic-gate 372*0Sstevel@tonic-gate if ((errno = ct_pr_tmpl_set_fatal(contracts_fd, CT_PR_EV_HWERR))) 373*0Sstevel@tonic-gate goto cleanup; 374*0Sstevel@tonic-gate 375*0Sstevel@tonic-gate if ((errno = ct_tmpl_set_critical(contracts_fd, 0))) 376*0Sstevel@tonic-gate goto cleanup; 377*0Sstevel@tonic-gate } 378*0Sstevel@tonic-gate 379*0Sstevel@tonic-gate during = "setting active template"; 380*0Sstevel@tonic-gate if ((errno = ct_tmpl_activate(contracts_fd))) 381*0Sstevel@tonic-gate goto cleanup; 382*0Sstevel@tonic-gate 383*0Sstevel@tonic-gate debug3("Set active contract"); 384*0Sstevel@tonic-gate return; 385*0Sstevel@tonic-gate 386*0Sstevel@tonic-gate cleanup: 387*0Sstevel@tonic-gate if (contracts_fd != -1) 388*0Sstevel@tonic-gate (void) close(contracts_fd); 389*0Sstevel@tonic-gate 390*0Sstevel@tonic-gate contracts_fd = -1; 391*0Sstevel@tonic-gate 392*0Sstevel@tonic-gate if (errno) 393*0Sstevel@tonic-gate debug2("Error while trying to set up active contract" 394*0Sstevel@tonic-gate " template: %s while %s", strerror(errno), during); 395*0Sstevel@tonic-gate } 396*0Sstevel@tonic-gate 397*0Sstevel@tonic-gate void 398*0Sstevel@tonic-gate contracts_post_fork_child() 399*0Sstevel@tonic-gate { 400*0Sstevel@tonic-gate /* Clear active template so fork() creates no new contracts. */ 401*0Sstevel@tonic-gate 402*0Sstevel@tonic-gate if (contracts_fd == -1) 403*0Sstevel@tonic-gate return; 404*0Sstevel@tonic-gate 405*0Sstevel@tonic-gate if ((errno = (ct_tmpl_clear(contracts_fd)))) 406*0Sstevel@tonic-gate debug2("Error while trying to clear active contract template" 407*0Sstevel@tonic-gate " (child): %s", strerror(errno)); 408*0Sstevel@tonic-gate else 409*0Sstevel@tonic-gate debug3("Cleared active contract template (child)"); 410*0Sstevel@tonic-gate 411*0Sstevel@tonic-gate (void) close(contracts_fd); 412*0Sstevel@tonic-gate 413*0Sstevel@tonic-gate contracts_fd = -1; 414*0Sstevel@tonic-gate } 415*0Sstevel@tonic-gate 416*0Sstevel@tonic-gate void 417*0Sstevel@tonic-gate contracts_post_fork_parent(int fork_succeeded) 418*0Sstevel@tonic-gate { 419*0Sstevel@tonic-gate char path[PATH_MAX]; 420*0Sstevel@tonic-gate int cfd, n; 421*0Sstevel@tonic-gate ct_stathdl_t st; 422*0Sstevel@tonic-gate ctid_t latest; 423*0Sstevel@tonic-gate 424*0Sstevel@tonic-gate /* Clear active template, abandon latest contract. */ 425*0Sstevel@tonic-gate if (contracts_fd == -1) 426*0Sstevel@tonic-gate return; 427*0Sstevel@tonic-gate 428*0Sstevel@tonic-gate if ((errno = ct_tmpl_clear(contracts_fd))) 429*0Sstevel@tonic-gate debug2("Error while clearing active contract template: %s", 430*0Sstevel@tonic-gate strerror(errno)); 431*0Sstevel@tonic-gate else 432*0Sstevel@tonic-gate debug3("Cleared active contract template (parent)"); 433*0Sstevel@tonic-gate 434*0Sstevel@tonic-gate if (!fork_succeeded) 435*0Sstevel@tonic-gate return; 436*0Sstevel@tonic-gate 437*0Sstevel@tonic-gate if ((cfd = open64(CTFS_ROOT "/process/latest", O_RDONLY)) == -1) { 438*0Sstevel@tonic-gate debug2("Error while getting latest contract: %s", 439*0Sstevel@tonic-gate strerror(errno)); 440*0Sstevel@tonic-gate return; 441*0Sstevel@tonic-gate } 442*0Sstevel@tonic-gate 443*0Sstevel@tonic-gate if ((errno = ct_status_read(cfd, CTD_COMMON, &st)) != 0) { 444*0Sstevel@tonic-gate debug2("Error while getting latest contract ID: %s", 445*0Sstevel@tonic-gate strerror(errno)); 446*0Sstevel@tonic-gate (void) close(cfd); 447*0Sstevel@tonic-gate return; 448*0Sstevel@tonic-gate } 449*0Sstevel@tonic-gate 450*0Sstevel@tonic-gate latest = ct_status_get_id(st); 451*0Sstevel@tonic-gate ct_status_free(st); 452*0Sstevel@tonic-gate (void) close(cfd); 453*0Sstevel@tonic-gate 454*0Sstevel@tonic-gate n = snprintf(path, PATH_MAX, CTFS_ROOT "/all/%ld/ctl", latest); 455*0Sstevel@tonic-gate 456*0Sstevel@tonic-gate if (n >= PATH_MAX) { 457*0Sstevel@tonic-gate debug2("Error while opening the latest contract ctl file: %s", 458*0Sstevel@tonic-gate strerror(ENAMETOOLONG)); 459*0Sstevel@tonic-gate return; 460*0Sstevel@tonic-gate } 461*0Sstevel@tonic-gate 462*0Sstevel@tonic-gate if ((cfd = open64(path, O_WRONLY)) == -1) { 463*0Sstevel@tonic-gate debug2("Error while opening the latest contract ctl file: %s", 464*0Sstevel@tonic-gate strerror(errno)); 465*0Sstevel@tonic-gate return; 466*0Sstevel@tonic-gate } 467*0Sstevel@tonic-gate 468*0Sstevel@tonic-gate if ((errno = ct_ctl_abandon(cfd))) 469*0Sstevel@tonic-gate debug2("Error while abandoning latest contract: %s", 470*0Sstevel@tonic-gate strerror(errno)); 471*0Sstevel@tonic-gate else 472*0Sstevel@tonic-gate debug3("Abandoned latest contract"); 473*0Sstevel@tonic-gate 474*0Sstevel@tonic-gate (void) close(cfd); 475*0Sstevel@tonic-gate } 476*0Sstevel@tonic-gate #endif /* HAVE_SOLARIS_CONTRACTS */ 477*0Sstevel@tonic-gate 478*0Sstevel@tonic-gate /* 479*0Sstevel@tonic-gate * Signal handler for the key regeneration alarm. Note that this 480*0Sstevel@tonic-gate * alarm only occurs in the daemon waiting for connections, and it does not 481*0Sstevel@tonic-gate * do anything with the private key or random state before forking. 482*0Sstevel@tonic-gate * Thus there should be no concurrency control/asynchronous execution 483*0Sstevel@tonic-gate * problems. 484*0Sstevel@tonic-gate */ 485*0Sstevel@tonic-gate static void 486*0Sstevel@tonic-gate generate_ephemeral_server_key(void) 487*0Sstevel@tonic-gate { 488*0Sstevel@tonic-gate u_int32_t rnd = 0; 489*0Sstevel@tonic-gate int i; 490*0Sstevel@tonic-gate 491*0Sstevel@tonic-gate verbose("Generating %s%d bit RSA key.", 492*0Sstevel@tonic-gate sensitive_data.server_key ? "new " : "", options.server_key_bits); 493*0Sstevel@tonic-gate if (sensitive_data.server_key != NULL) 494*0Sstevel@tonic-gate key_free(sensitive_data.server_key); 495*0Sstevel@tonic-gate sensitive_data.server_key = key_generate(KEY_RSA1, 496*0Sstevel@tonic-gate options.server_key_bits); 497*0Sstevel@tonic-gate verbose("RSA key generation complete."); 498*0Sstevel@tonic-gate 499*0Sstevel@tonic-gate for (i = 0; i < SSH_SESSION_KEY_LENGTH; i++) { 500*0Sstevel@tonic-gate if (i % 4 == 0) 501*0Sstevel@tonic-gate rnd = arc4random(); 502*0Sstevel@tonic-gate sensitive_data.ssh1_cookie[i] = rnd & 0xff; 503*0Sstevel@tonic-gate rnd >>= 8; 504*0Sstevel@tonic-gate } 505*0Sstevel@tonic-gate arc4random_stir(); 506*0Sstevel@tonic-gate } 507*0Sstevel@tonic-gate 508*0Sstevel@tonic-gate static void 509*0Sstevel@tonic-gate key_regeneration_alarm(int sig) 510*0Sstevel@tonic-gate { 511*0Sstevel@tonic-gate int save_errno = errno; 512*0Sstevel@tonic-gate 513*0Sstevel@tonic-gate (void) signal(SIGALRM, SIG_DFL); 514*0Sstevel@tonic-gate errno = save_errno; 515*0Sstevel@tonic-gate key_do_regen = 1; 516*0Sstevel@tonic-gate } 517*0Sstevel@tonic-gate 518*0Sstevel@tonic-gate static void 519*0Sstevel@tonic-gate sshd_exchange_identification(int sock_in, int sock_out) 520*0Sstevel@tonic-gate { 521*0Sstevel@tonic-gate int i, mismatch; 522*0Sstevel@tonic-gate int remote_major, remote_minor; 523*0Sstevel@tonic-gate int major, minor; 524*0Sstevel@tonic-gate char *s; 525*0Sstevel@tonic-gate char buf[256]; /* Must not be larger than remote_version. */ 526*0Sstevel@tonic-gate char remote_version[256]; /* Must be at least as big as buf. */ 527*0Sstevel@tonic-gate 528*0Sstevel@tonic-gate if ((options.protocol & SSH_PROTO_1) && 529*0Sstevel@tonic-gate (options.protocol & SSH_PROTO_2)) { 530*0Sstevel@tonic-gate major = PROTOCOL_MAJOR_1; 531*0Sstevel@tonic-gate minor = 99; 532*0Sstevel@tonic-gate } else if (options.protocol & SSH_PROTO_2) { 533*0Sstevel@tonic-gate major = PROTOCOL_MAJOR_2; 534*0Sstevel@tonic-gate minor = PROTOCOL_MINOR_2; 535*0Sstevel@tonic-gate } else { 536*0Sstevel@tonic-gate major = PROTOCOL_MAJOR_1; 537*0Sstevel@tonic-gate minor = PROTOCOL_MINOR_1; 538*0Sstevel@tonic-gate } 539*0Sstevel@tonic-gate (void) snprintf(buf, sizeof buf, "SSH-%d.%d-%.100s\n", major, minor, SSH_VERSION); 540*0Sstevel@tonic-gate server_version_string = xstrdup(buf); 541*0Sstevel@tonic-gate 542*0Sstevel@tonic-gate if (client_version_string == NULL) { 543*0Sstevel@tonic-gate /* Send our protocol version identification. */ 544*0Sstevel@tonic-gate if (atomicio(write, sock_out, server_version_string, 545*0Sstevel@tonic-gate strlen(server_version_string)) 546*0Sstevel@tonic-gate != strlen(server_version_string)) { 547*0Sstevel@tonic-gate log("Could not write ident string to %s", get_remote_ipaddr()); 548*0Sstevel@tonic-gate fatal_cleanup(); 549*0Sstevel@tonic-gate } 550*0Sstevel@tonic-gate 551*0Sstevel@tonic-gate /* Read other sides version identification. */ 552*0Sstevel@tonic-gate (void) memset(buf, 0, sizeof(buf)); 553*0Sstevel@tonic-gate for (i = 0; i < sizeof(buf) - 1; i++) { 554*0Sstevel@tonic-gate if (atomicio(read, sock_in, &buf[i], 1) != 1) { 555*0Sstevel@tonic-gate log("Did not receive identification string from %s", 556*0Sstevel@tonic-gate get_remote_ipaddr()); 557*0Sstevel@tonic-gate fatal_cleanup(); 558*0Sstevel@tonic-gate } 559*0Sstevel@tonic-gate if (buf[i] == '\r') { 560*0Sstevel@tonic-gate buf[i] = 0; 561*0Sstevel@tonic-gate /* Kludge for F-Secure Macintosh < 1.0.2 */ 562*0Sstevel@tonic-gate if (i == 12 && 563*0Sstevel@tonic-gate strncmp(buf, "SSH-1.5-W1.0", 12) == 0) 564*0Sstevel@tonic-gate break; 565*0Sstevel@tonic-gate continue; 566*0Sstevel@tonic-gate } 567*0Sstevel@tonic-gate if (buf[i] == '\n') { 568*0Sstevel@tonic-gate buf[i] = 0; 569*0Sstevel@tonic-gate break; 570*0Sstevel@tonic-gate } 571*0Sstevel@tonic-gate } 572*0Sstevel@tonic-gate buf[sizeof(buf) - 1] = 0; 573*0Sstevel@tonic-gate client_version_string = xstrdup(buf); 574*0Sstevel@tonic-gate } 575*0Sstevel@tonic-gate 576*0Sstevel@tonic-gate /* 577*0Sstevel@tonic-gate * Check that the versions match. In future this might accept 578*0Sstevel@tonic-gate * several versions and set appropriate flags to handle them. 579*0Sstevel@tonic-gate */ 580*0Sstevel@tonic-gate if (sscanf(client_version_string, "SSH-%d.%d-%[^\n]\n", 581*0Sstevel@tonic-gate &remote_major, &remote_minor, remote_version) != 3) { 582*0Sstevel@tonic-gate s = "Protocol mismatch.\n"; 583*0Sstevel@tonic-gate (void) atomicio(write, sock_out, s, strlen(s)); 584*0Sstevel@tonic-gate (void) close(sock_in); 585*0Sstevel@tonic-gate (void) close(sock_out); 586*0Sstevel@tonic-gate log("Bad protocol version identification '%.100s' from %s", 587*0Sstevel@tonic-gate client_version_string, get_remote_ipaddr()); 588*0Sstevel@tonic-gate fatal_cleanup(); 589*0Sstevel@tonic-gate } 590*0Sstevel@tonic-gate debug("Client protocol version %d.%d; client software version %.100s", 591*0Sstevel@tonic-gate remote_major, remote_minor, remote_version); 592*0Sstevel@tonic-gate 593*0Sstevel@tonic-gate compat_datafellows(remote_version); 594*0Sstevel@tonic-gate 595*0Sstevel@tonic-gate if (datafellows & SSH_BUG_PROBE) { 596*0Sstevel@tonic-gate log("probed from %s with %s. Don't panic.", 597*0Sstevel@tonic-gate get_remote_ipaddr(), client_version_string); 598*0Sstevel@tonic-gate fatal_cleanup(); 599*0Sstevel@tonic-gate } 600*0Sstevel@tonic-gate 601*0Sstevel@tonic-gate if (datafellows & SSH_BUG_SCANNER) { 602*0Sstevel@tonic-gate log("scanned from %s with %s. Don't panic.", 603*0Sstevel@tonic-gate get_remote_ipaddr(), client_version_string); 604*0Sstevel@tonic-gate fatal_cleanup(); 605*0Sstevel@tonic-gate } 606*0Sstevel@tonic-gate 607*0Sstevel@tonic-gate mismatch = 0; 608*0Sstevel@tonic-gate switch (remote_major) { 609*0Sstevel@tonic-gate case 1: 610*0Sstevel@tonic-gate if (remote_minor == 99) { 611*0Sstevel@tonic-gate if (options.protocol & SSH_PROTO_2) 612*0Sstevel@tonic-gate enable_compat20(); 613*0Sstevel@tonic-gate else 614*0Sstevel@tonic-gate mismatch = 1; 615*0Sstevel@tonic-gate break; 616*0Sstevel@tonic-gate } 617*0Sstevel@tonic-gate if (!(options.protocol & SSH_PROTO_1)) { 618*0Sstevel@tonic-gate mismatch = 1; 619*0Sstevel@tonic-gate break; 620*0Sstevel@tonic-gate } 621*0Sstevel@tonic-gate if (remote_minor < 3) { 622*0Sstevel@tonic-gate packet_disconnect("Your ssh version is too old and " 623*0Sstevel@tonic-gate "is no longer supported. Please install a newer version."); 624*0Sstevel@tonic-gate } else if (remote_minor == 3) { 625*0Sstevel@tonic-gate /* note that this disables agent-forwarding */ 626*0Sstevel@tonic-gate enable_compat13(); 627*0Sstevel@tonic-gate } 628*0Sstevel@tonic-gate break; 629*0Sstevel@tonic-gate case 2: 630*0Sstevel@tonic-gate if (options.protocol & SSH_PROTO_2) { 631*0Sstevel@tonic-gate enable_compat20(); 632*0Sstevel@tonic-gate break; 633*0Sstevel@tonic-gate } 634*0Sstevel@tonic-gate /* FALLTHROUGH */ 635*0Sstevel@tonic-gate default: 636*0Sstevel@tonic-gate mismatch = 1; 637*0Sstevel@tonic-gate break; 638*0Sstevel@tonic-gate } 639*0Sstevel@tonic-gate chop(server_version_string); 640*0Sstevel@tonic-gate debug("Local version string %.200s", server_version_string); 641*0Sstevel@tonic-gate 642*0Sstevel@tonic-gate if (mismatch) { 643*0Sstevel@tonic-gate s = "Protocol major versions differ.\n"; 644*0Sstevel@tonic-gate (void) atomicio(write, sock_out, s, strlen(s)); 645*0Sstevel@tonic-gate (void) close(sock_in); 646*0Sstevel@tonic-gate (void) close(sock_out); 647*0Sstevel@tonic-gate log("Protocol major versions differ for %s: %.200s vs. %.200s", 648*0Sstevel@tonic-gate get_remote_ipaddr(), 649*0Sstevel@tonic-gate server_version_string, client_version_string); 650*0Sstevel@tonic-gate fatal_cleanup(); 651*0Sstevel@tonic-gate } 652*0Sstevel@tonic-gate } 653*0Sstevel@tonic-gate 654*0Sstevel@tonic-gate /* Destroy the host and server keys. They will no longer be needed. */ 655*0Sstevel@tonic-gate void 656*0Sstevel@tonic-gate destroy_sensitive_data(void) 657*0Sstevel@tonic-gate { 658*0Sstevel@tonic-gate int i; 659*0Sstevel@tonic-gate 660*0Sstevel@tonic-gate if (sensitive_data.server_key) { 661*0Sstevel@tonic-gate key_free(sensitive_data.server_key); 662*0Sstevel@tonic-gate sensitive_data.server_key = NULL; 663*0Sstevel@tonic-gate } 664*0Sstevel@tonic-gate for (i = 0; i < options.num_host_key_files; i++) { 665*0Sstevel@tonic-gate if (sensitive_data.host_keys[i]) { 666*0Sstevel@tonic-gate key_free(sensitive_data.host_keys[i]); 667*0Sstevel@tonic-gate sensitive_data.host_keys[i] = NULL; 668*0Sstevel@tonic-gate } 669*0Sstevel@tonic-gate } 670*0Sstevel@tonic-gate sensitive_data.ssh1_host_key = NULL; 671*0Sstevel@tonic-gate (void) memset(sensitive_data.ssh1_cookie, 0, SSH_SESSION_KEY_LENGTH); 672*0Sstevel@tonic-gate } 673*0Sstevel@tonic-gate 674*0Sstevel@tonic-gate /* Demote private to public keys for network child */ 675*0Sstevel@tonic-gate static void 676*0Sstevel@tonic-gate demote_sensitive_data(void) 677*0Sstevel@tonic-gate { 678*0Sstevel@tonic-gate Key *tmp; 679*0Sstevel@tonic-gate int i; 680*0Sstevel@tonic-gate 681*0Sstevel@tonic-gate if (sensitive_data.server_key) { 682*0Sstevel@tonic-gate tmp = key_demote(sensitive_data.server_key); 683*0Sstevel@tonic-gate key_free(sensitive_data.server_key); 684*0Sstevel@tonic-gate sensitive_data.server_key = tmp; 685*0Sstevel@tonic-gate } 686*0Sstevel@tonic-gate 687*0Sstevel@tonic-gate for (i = 0; i < options.num_host_key_files; i++) { 688*0Sstevel@tonic-gate if (sensitive_data.host_keys[i]) { 689*0Sstevel@tonic-gate tmp = key_demote(sensitive_data.host_keys[i]); 690*0Sstevel@tonic-gate key_free(sensitive_data.host_keys[i]); 691*0Sstevel@tonic-gate sensitive_data.host_keys[i] = tmp; 692*0Sstevel@tonic-gate if (tmp->type == KEY_RSA1) 693*0Sstevel@tonic-gate sensitive_data.ssh1_host_key = tmp; 694*0Sstevel@tonic-gate } 695*0Sstevel@tonic-gate } 696*0Sstevel@tonic-gate 697*0Sstevel@tonic-gate /* We do not clear ssh1_host key and cookie. XXX - Okay Niels? */ 698*0Sstevel@tonic-gate } 699*0Sstevel@tonic-gate 700*0Sstevel@tonic-gate static void 701*0Sstevel@tonic-gate privsep_preauth_child(void) 702*0Sstevel@tonic-gate { 703*0Sstevel@tonic-gate u_int32_t rnd[256]; 704*0Sstevel@tonic-gate gid_t gidset[1]; 705*0Sstevel@tonic-gate struct passwd *pw; 706*0Sstevel@tonic-gate int i; 707*0Sstevel@tonic-gate 708*0Sstevel@tonic-gate /* Enable challenge-response authentication for privilege separation */ 709*0Sstevel@tonic-gate privsep_challenge_enable(); 710*0Sstevel@tonic-gate 711*0Sstevel@tonic-gate for (i = 0; i < 256; i++) 712*0Sstevel@tonic-gate rnd[i] = arc4random(); 713*0Sstevel@tonic-gate RAND_seed(rnd, sizeof(rnd)); 714*0Sstevel@tonic-gate 715*0Sstevel@tonic-gate /* Demote the private keys to public keys. */ 716*0Sstevel@tonic-gate demote_sensitive_data(); 717*0Sstevel@tonic-gate 718*0Sstevel@tonic-gate if ((pw = getpwnam(SSH_PRIVSEP_USER)) == NULL) 719*0Sstevel@tonic-gate fatal("Privilege separation user %s does not exist", 720*0Sstevel@tonic-gate SSH_PRIVSEP_USER); 721*0Sstevel@tonic-gate (void) memset(pw->pw_passwd, 0, strlen(pw->pw_passwd)); 722*0Sstevel@tonic-gate endpwent(); 723*0Sstevel@tonic-gate 724*0Sstevel@tonic-gate /* Change our root directory */ 725*0Sstevel@tonic-gate if (chroot(_PATH_PRIVSEP_CHROOT_DIR) == -1) 726*0Sstevel@tonic-gate fatal("chroot(\"%s\"): %s", _PATH_PRIVSEP_CHROOT_DIR, 727*0Sstevel@tonic-gate strerror(errno)); 728*0Sstevel@tonic-gate if (chdir("/") == -1) 729*0Sstevel@tonic-gate fatal("chdir(\"/\"): %s", strerror(errno)); 730*0Sstevel@tonic-gate 731*0Sstevel@tonic-gate /* Drop our privileges */ 732*0Sstevel@tonic-gate debug3("privsep user:group %u:%u", (u_int)pw->pw_uid, 733*0Sstevel@tonic-gate (u_int)pw->pw_gid); 734*0Sstevel@tonic-gate #if 0 735*0Sstevel@tonic-gate /* XXX not ready, to heavy after chroot */ 736*0Sstevel@tonic-gate do_setusercontext(pw); 737*0Sstevel@tonic-gate #else 738*0Sstevel@tonic-gate gidset[0] = pw->pw_gid; 739*0Sstevel@tonic-gate if (setgid(pw->pw_gid) < 0) 740*0Sstevel@tonic-gate fatal("setgid failed for %ld", pw->pw_gid); 741*0Sstevel@tonic-gate if (setgroups(1, gidset) < 0) 742*0Sstevel@tonic-gate fatal("setgroups: %.100s", strerror(errno)); 743*0Sstevel@tonic-gate permanently_set_uid(pw); 744*0Sstevel@tonic-gate #endif 745*0Sstevel@tonic-gate } 746*0Sstevel@tonic-gate 747*0Sstevel@tonic-gate static Authctxt * 748*0Sstevel@tonic-gate privsep_preauth(void) 749*0Sstevel@tonic-gate { 750*0Sstevel@tonic-gate Authctxt *authctxt = NULL; 751*0Sstevel@tonic-gate int status; 752*0Sstevel@tonic-gate pid_t pid; 753*0Sstevel@tonic-gate 754*0Sstevel@tonic-gate /* Set up unprivileged child process to deal with network data */ 755*0Sstevel@tonic-gate pmonitor = monitor_init(); 756*0Sstevel@tonic-gate /* Store a pointer to the kex for later rekeying */ 757*0Sstevel@tonic-gate pmonitor->m_pkex = &xxx_kex; 758*0Sstevel@tonic-gate 759*0Sstevel@tonic-gate pid = fork(); 760*0Sstevel@tonic-gate if (pid == -1) { 761*0Sstevel@tonic-gate fatal("fork of unprivileged child failed"); 762*0Sstevel@tonic-gate } else if (pid != 0) { 763*0Sstevel@tonic-gate fatal_remove_cleanup((void (*) (void *)) packet_close, NULL); 764*0Sstevel@tonic-gate 765*0Sstevel@tonic-gate debug2("Network child is on pid %ld", (long)pid); 766*0Sstevel@tonic-gate 767*0Sstevel@tonic-gate (void) close(pmonitor->m_recvfd); 768*0Sstevel@tonic-gate authctxt = monitor_child_preauth(pmonitor); 769*0Sstevel@tonic-gate (void) close(pmonitor->m_sendfd); 770*0Sstevel@tonic-gate 771*0Sstevel@tonic-gate /* Sync memory */ 772*0Sstevel@tonic-gate monitor_sync(pmonitor); 773*0Sstevel@tonic-gate 774*0Sstevel@tonic-gate /* Wait for the child's exit status */ 775*0Sstevel@tonic-gate while (waitpid(pid, &status, 0) < 0) 776*0Sstevel@tonic-gate if (errno != EINTR) 777*0Sstevel@tonic-gate break; 778*0Sstevel@tonic-gate 779*0Sstevel@tonic-gate /* Reinstall, since the child has finished */ 780*0Sstevel@tonic-gate fatal_add_cleanup((void (*) (void *)) packet_close, NULL); 781*0Sstevel@tonic-gate 782*0Sstevel@tonic-gate return (authctxt); 783*0Sstevel@tonic-gate } else { 784*0Sstevel@tonic-gate /* child */ 785*0Sstevel@tonic-gate 786*0Sstevel@tonic-gate (void) close(pmonitor->m_sendfd); 787*0Sstevel@tonic-gate 788*0Sstevel@tonic-gate /* Demote the child */ 789*0Sstevel@tonic-gate if (getuid() == 0 || geteuid() == 0) 790*0Sstevel@tonic-gate privsep_preauth_child(); 791*0Sstevel@tonic-gate setproctitle("%s", "[net]"); 792*0Sstevel@tonic-gate } 793*0Sstevel@tonic-gate return (NULL); 794*0Sstevel@tonic-gate } 795*0Sstevel@tonic-gate 796*0Sstevel@tonic-gate static void 797*0Sstevel@tonic-gate privsep_postauth(Authctxt *authctxt) 798*0Sstevel@tonic-gate { 799*0Sstevel@tonic-gate extern Authctxt *x_authctxt; 800*0Sstevel@tonic-gate 801*0Sstevel@tonic-gate /* XXX - Remote port forwarding */ 802*0Sstevel@tonic-gate x_authctxt = authctxt; 803*0Sstevel@tonic-gate 804*0Sstevel@tonic-gate #ifdef DISABLE_FD_PASSING 805*0Sstevel@tonic-gate if (1) { 806*0Sstevel@tonic-gate #else 807*0Sstevel@tonic-gate if (authctxt->pw->pw_uid == 0 || options.use_login) { 808*0Sstevel@tonic-gate #endif 809*0Sstevel@tonic-gate /* File descriptor passing is broken or root login */ 810*0Sstevel@tonic-gate monitor_apply_keystate(pmonitor); 811*0Sstevel@tonic-gate use_privsep = 0; 812*0Sstevel@tonic-gate return; 813*0Sstevel@tonic-gate } 814*0Sstevel@tonic-gate 815*0Sstevel@tonic-gate if (startup_pipe != -1) { 816*0Sstevel@tonic-gate (void) close(startup_pipe); 817*0Sstevel@tonic-gate startup_pipe = -1; 818*0Sstevel@tonic-gate } 819*0Sstevel@tonic-gate 820*0Sstevel@tonic-gate /* New socket pair */ 821*0Sstevel@tonic-gate monitor_reinit(pmonitor); 822*0Sstevel@tonic-gate 823*0Sstevel@tonic-gate pmonitor->m_pid = fork(); 824*0Sstevel@tonic-gate if (pmonitor->m_pid == -1) 825*0Sstevel@tonic-gate fatal("fork of unprivileged child failed"); 826*0Sstevel@tonic-gate else if (pmonitor->m_pid != 0) { 827*0Sstevel@tonic-gate fatal_remove_cleanup((void (*) (void *)) packet_close, NULL); 828*0Sstevel@tonic-gate 829*0Sstevel@tonic-gate debug2("User child is on pid %ld", (long)pmonitor->m_pid); 830*0Sstevel@tonic-gate (void) close(pmonitor->m_recvfd); 831*0Sstevel@tonic-gate monitor_child_postauth(pmonitor); 832*0Sstevel@tonic-gate 833*0Sstevel@tonic-gate /* NEVERREACHED */ 834*0Sstevel@tonic-gate exit(0); 835*0Sstevel@tonic-gate } 836*0Sstevel@tonic-gate 837*0Sstevel@tonic-gate (void) close(pmonitor->m_sendfd); 838*0Sstevel@tonic-gate 839*0Sstevel@tonic-gate /* Demote the private keys to public keys. */ 840*0Sstevel@tonic-gate demote_sensitive_data(); 841*0Sstevel@tonic-gate 842*0Sstevel@tonic-gate /* Drop privileges */ 843*0Sstevel@tonic-gate do_setusercontext(authctxt->pw); 844*0Sstevel@tonic-gate 845*0Sstevel@tonic-gate /* It is safe now to apply the key state */ 846*0Sstevel@tonic-gate monitor_apply_keystate(pmonitor); 847*0Sstevel@tonic-gate } 848*0Sstevel@tonic-gate 849*0Sstevel@tonic-gate static char * 850*0Sstevel@tonic-gate list_hostkey_types(void) 851*0Sstevel@tonic-gate { 852*0Sstevel@tonic-gate Buffer b; 853*0Sstevel@tonic-gate char *p; 854*0Sstevel@tonic-gate int i; 855*0Sstevel@tonic-gate 856*0Sstevel@tonic-gate buffer_init(&b); 857*0Sstevel@tonic-gate for (i = 0; i < options.num_host_key_files; i++) { 858*0Sstevel@tonic-gate Key *key = sensitive_data.host_keys[i]; 859*0Sstevel@tonic-gate if (key == NULL) 860*0Sstevel@tonic-gate continue; 861*0Sstevel@tonic-gate switch (key->type) { 862*0Sstevel@tonic-gate case KEY_RSA: 863*0Sstevel@tonic-gate case KEY_DSA: 864*0Sstevel@tonic-gate if (buffer_len(&b) > 0) 865*0Sstevel@tonic-gate buffer_append(&b, ",", 1); 866*0Sstevel@tonic-gate p = key_ssh_name(key); 867*0Sstevel@tonic-gate buffer_append(&b, p, strlen(p)); 868*0Sstevel@tonic-gate break; 869*0Sstevel@tonic-gate } 870*0Sstevel@tonic-gate } 871*0Sstevel@tonic-gate buffer_append(&b, "\0", 1); 872*0Sstevel@tonic-gate p = xstrdup(buffer_ptr(&b)); 873*0Sstevel@tonic-gate buffer_free(&b); 874*0Sstevel@tonic-gate debug("list_hostkey_types: %s", p); 875*0Sstevel@tonic-gate return p; 876*0Sstevel@tonic-gate } 877*0Sstevel@tonic-gate 878*0Sstevel@tonic-gate #ifdef lint 879*0Sstevel@tonic-gate static 880*0Sstevel@tonic-gate #endif /* lint */ 881*0Sstevel@tonic-gate Key * 882*0Sstevel@tonic-gate get_hostkey_by_type(int type) 883*0Sstevel@tonic-gate { 884*0Sstevel@tonic-gate int i; 885*0Sstevel@tonic-gate 886*0Sstevel@tonic-gate for (i = 0; i < options.num_host_key_files; i++) { 887*0Sstevel@tonic-gate Key *key = sensitive_data.host_keys[i]; 888*0Sstevel@tonic-gate if (key != NULL && key->type == type) 889*0Sstevel@tonic-gate return key; 890*0Sstevel@tonic-gate } 891*0Sstevel@tonic-gate return NULL; 892*0Sstevel@tonic-gate } 893*0Sstevel@tonic-gate 894*0Sstevel@tonic-gate #ifdef lint 895*0Sstevel@tonic-gate static 896*0Sstevel@tonic-gate #endif /* lint */ 897*0Sstevel@tonic-gate Key * 898*0Sstevel@tonic-gate get_hostkey_by_index(int ind) 899*0Sstevel@tonic-gate { 900*0Sstevel@tonic-gate if (ind < 0 || ind >= options.num_host_key_files) 901*0Sstevel@tonic-gate return (NULL); 902*0Sstevel@tonic-gate return (sensitive_data.host_keys[ind]); 903*0Sstevel@tonic-gate } 904*0Sstevel@tonic-gate 905*0Sstevel@tonic-gate #ifdef lint 906*0Sstevel@tonic-gate static 907*0Sstevel@tonic-gate #endif /* lint */ 908*0Sstevel@tonic-gate int 909*0Sstevel@tonic-gate get_hostkey_index(Key *key) 910*0Sstevel@tonic-gate { 911*0Sstevel@tonic-gate int i; 912*0Sstevel@tonic-gate 913*0Sstevel@tonic-gate for (i = 0; i < options.num_host_key_files; i++) { 914*0Sstevel@tonic-gate if (key == sensitive_data.host_keys[i]) 915*0Sstevel@tonic-gate return (i); 916*0Sstevel@tonic-gate } 917*0Sstevel@tonic-gate return (-1); 918*0Sstevel@tonic-gate } 919*0Sstevel@tonic-gate 920*0Sstevel@tonic-gate /* 921*0Sstevel@tonic-gate * returns 1 if connection should be dropped, 0 otherwise. 922*0Sstevel@tonic-gate * dropping starts at connection #max_startups_begin with a probability 923*0Sstevel@tonic-gate * of (max_startups_rate/100). the probability increases linearly until 924*0Sstevel@tonic-gate * all connections are dropped for startups > max_startups 925*0Sstevel@tonic-gate */ 926*0Sstevel@tonic-gate static int 927*0Sstevel@tonic-gate drop_connection(int startups) 928*0Sstevel@tonic-gate { 929*0Sstevel@tonic-gate double p, r; 930*0Sstevel@tonic-gate 931*0Sstevel@tonic-gate if (startups < options.max_startups_begin) 932*0Sstevel@tonic-gate return 0; 933*0Sstevel@tonic-gate if (startups >= options.max_startups) 934*0Sstevel@tonic-gate return 1; 935*0Sstevel@tonic-gate if (options.max_startups_rate == 100) 936*0Sstevel@tonic-gate return 1; 937*0Sstevel@tonic-gate 938*0Sstevel@tonic-gate p = 100 - options.max_startups_rate; 939*0Sstevel@tonic-gate p *= startups - options.max_startups_begin; 940*0Sstevel@tonic-gate p /= (double) (options.max_startups - options.max_startups_begin); 941*0Sstevel@tonic-gate p += options.max_startups_rate; 942*0Sstevel@tonic-gate p /= 100.0; 943*0Sstevel@tonic-gate r = arc4random() / (double) UINT_MAX; 944*0Sstevel@tonic-gate 945*0Sstevel@tonic-gate debug("drop_connection: p %g, r %g", p, r); 946*0Sstevel@tonic-gate return (r < p) ? 1 : 0; 947*0Sstevel@tonic-gate } 948*0Sstevel@tonic-gate 949*0Sstevel@tonic-gate static void 950*0Sstevel@tonic-gate usage(void) 951*0Sstevel@tonic-gate { 952*0Sstevel@tonic-gate (void) fprintf(stderr, gettext("sshd version %s\n"), SSH_VERSION); 953*0Sstevel@tonic-gate (void) fprintf(stderr, 954*0Sstevel@tonic-gate gettext("Usage: %s [options]\n" 955*0Sstevel@tonic-gate "Options:\n" 956*0Sstevel@tonic-gate " -f file Configuration file (default %s)\n" 957*0Sstevel@tonic-gate " -d Debugging mode (multiple -d means more " 958*0Sstevel@tonic-gate "debugging)\n" 959*0Sstevel@tonic-gate " -i Started from inetd\n" 960*0Sstevel@tonic-gate " -D Do not fork into daemon mode\n" 961*0Sstevel@tonic-gate " -t Only test configuration file and keys\n" 962*0Sstevel@tonic-gate " -q Quiet (no logging)\n" 963*0Sstevel@tonic-gate " -p port Listen on the specified port (default: 22)\n" 964*0Sstevel@tonic-gate " -k seconds Regenerate server key every this many seconds " 965*0Sstevel@tonic-gate "(default: 3600)\n" 966*0Sstevel@tonic-gate " -g seconds Grace period for authentication (default: 600)\n" 967*0Sstevel@tonic-gate " -b bits Size of server RSA key (default: 768 bits)\n" 968*0Sstevel@tonic-gate " -h file File from which to read host key (default: %s)\n" 969*0Sstevel@tonic-gate " -4 Use IPv4 only\n" 970*0Sstevel@tonic-gate " -6 Use IPv6 only\n" 971*0Sstevel@tonic-gate " -o option Process the option as if it was read from " 972*0Sstevel@tonic-gate "a configuration file.\n"), 973*0Sstevel@tonic-gate __progname, _PATH_SERVER_CONFIG_FILE, _PATH_HOST_KEY_FILE); 974*0Sstevel@tonic-gate exit(1); 975*0Sstevel@tonic-gate } 976*0Sstevel@tonic-gate 977*0Sstevel@tonic-gate /* 978*0Sstevel@tonic-gate * Main program for the daemon. 979*0Sstevel@tonic-gate */ 980*0Sstevel@tonic-gate int 981*0Sstevel@tonic-gate main(int ac, char **av) 982*0Sstevel@tonic-gate { 983*0Sstevel@tonic-gate extern char *optarg; 984*0Sstevel@tonic-gate extern int optind; 985*0Sstevel@tonic-gate int opt, sock_in = 0, sock_out = 0, newsock, j, i, fdsetsz, on = 1; 986*0Sstevel@tonic-gate pid_t pid; 987*0Sstevel@tonic-gate socklen_t fromlen; 988*0Sstevel@tonic-gate fd_set *fdset; 989*0Sstevel@tonic-gate struct sockaddr_storage from; 990*0Sstevel@tonic-gate const char *remote_ip; 991*0Sstevel@tonic-gate int remote_port; 992*0Sstevel@tonic-gate FILE *f; 993*0Sstevel@tonic-gate struct addrinfo *ai; 994*0Sstevel@tonic-gate char ntop[NI_MAXHOST], strport[NI_MAXSERV]; 995*0Sstevel@tonic-gate int listen_sock, maxfd; 996*0Sstevel@tonic-gate int startup_p[2]; 997*0Sstevel@tonic-gate int startups = 0; 998*0Sstevel@tonic-gate Authctxt *authctxt; 999*0Sstevel@tonic-gate Key *key; 1000*0Sstevel@tonic-gate int ret, key_used = 0; 1001*0Sstevel@tonic-gate #ifdef HAVE_BSM 1002*0Sstevel@tonic-gate au_id_t auid = AU_NOAUDITID; 1003*0Sstevel@tonic-gate #endif /* HAVE_BSM */ 1004*0Sstevel@tonic-gate #ifdef ALTPRIVSEP 1005*0Sstevel@tonic-gate pid_t aps_child; 1006*0Sstevel@tonic-gate #endif /* ALTPRIVSEP */ 1007*0Sstevel@tonic-gate 1008*0Sstevel@tonic-gate __progname = get_progname(av[0]); 1009*0Sstevel@tonic-gate 1010*0Sstevel@tonic-gate (void) g11n_setlocale(LC_ALL, ""); 1011*0Sstevel@tonic-gate 1012*0Sstevel@tonic-gate #ifdef HAVE_SECUREWARE 1013*0Sstevel@tonic-gate (void)set_auth_parameters(ac, av); 1014*0Sstevel@tonic-gate #endif 1015*0Sstevel@tonic-gate 1016*0Sstevel@tonic-gate init_rng(); 1017*0Sstevel@tonic-gate 1018*0Sstevel@tonic-gate /* Save argv. */ 1019*0Sstevel@tonic-gate saved_argc = ac; 1020*0Sstevel@tonic-gate saved_argv = av; 1021*0Sstevel@tonic-gate 1022*0Sstevel@tonic-gate /* Initialize configuration options to their default values. */ 1023*0Sstevel@tonic-gate initialize_server_options(&options); 1024*0Sstevel@tonic-gate 1025*0Sstevel@tonic-gate /* Parse command-line arguments. */ 1026*0Sstevel@tonic-gate while ((opt = getopt(ac, av, "f:p:b:k:h:g:V:u:o:dDeiqtQ46")) != -1) { 1027*0Sstevel@tonic-gate switch (opt) { 1028*0Sstevel@tonic-gate case '4': 1029*0Sstevel@tonic-gate IPv4or6 = AF_INET; 1030*0Sstevel@tonic-gate break; 1031*0Sstevel@tonic-gate case '6': 1032*0Sstevel@tonic-gate IPv4or6 = AF_INET6; 1033*0Sstevel@tonic-gate break; 1034*0Sstevel@tonic-gate case 'f': 1035*0Sstevel@tonic-gate config_file_name = optarg; 1036*0Sstevel@tonic-gate break; 1037*0Sstevel@tonic-gate case 'd': 1038*0Sstevel@tonic-gate if (0 == debug_flag) { 1039*0Sstevel@tonic-gate debug_flag = 1; 1040*0Sstevel@tonic-gate options.log_level = SYSLOG_LEVEL_DEBUG1; 1041*0Sstevel@tonic-gate } else if (options.log_level < SYSLOG_LEVEL_DEBUG3) { 1042*0Sstevel@tonic-gate options.log_level++; 1043*0Sstevel@tonic-gate } else { 1044*0Sstevel@tonic-gate (void) fprintf(stderr, 1045*0Sstevel@tonic-gate gettext("Debug level too high.\n")); 1046*0Sstevel@tonic-gate exit(1); 1047*0Sstevel@tonic-gate } 1048*0Sstevel@tonic-gate break; 1049*0Sstevel@tonic-gate case 'D': 1050*0Sstevel@tonic-gate no_daemon_flag = 1; 1051*0Sstevel@tonic-gate break; 1052*0Sstevel@tonic-gate case 'e': 1053*0Sstevel@tonic-gate log_stderr = 1; 1054*0Sstevel@tonic-gate break; 1055*0Sstevel@tonic-gate case 'i': 1056*0Sstevel@tonic-gate inetd_flag = 1; 1057*0Sstevel@tonic-gate break; 1058*0Sstevel@tonic-gate case 'Q': 1059*0Sstevel@tonic-gate /* ignored */ 1060*0Sstevel@tonic-gate break; 1061*0Sstevel@tonic-gate case 'q': 1062*0Sstevel@tonic-gate options.log_level = SYSLOG_LEVEL_QUIET; 1063*0Sstevel@tonic-gate break; 1064*0Sstevel@tonic-gate case 'b': 1065*0Sstevel@tonic-gate options.server_key_bits = atoi(optarg); 1066*0Sstevel@tonic-gate break; 1067*0Sstevel@tonic-gate case 'p': 1068*0Sstevel@tonic-gate options.ports_from_cmdline = 1; 1069*0Sstevel@tonic-gate if (options.num_ports >= MAX_PORTS) { 1070*0Sstevel@tonic-gate (void) fprintf(stderr, gettext("too many ports.\n")); 1071*0Sstevel@tonic-gate exit(1); 1072*0Sstevel@tonic-gate } 1073*0Sstevel@tonic-gate options.ports[options.num_ports++] = a2port(optarg); 1074*0Sstevel@tonic-gate if (options.ports[options.num_ports-1] == 0) { 1075*0Sstevel@tonic-gate (void) fprintf(stderr, gettext("Bad port number.\n")); 1076*0Sstevel@tonic-gate exit(1); 1077*0Sstevel@tonic-gate } 1078*0Sstevel@tonic-gate break; 1079*0Sstevel@tonic-gate case 'g': 1080*0Sstevel@tonic-gate if ((options.login_grace_time = convtime(optarg)) == -1) { 1081*0Sstevel@tonic-gate (void) fprintf(stderr, 1082*0Sstevel@tonic-gate gettext("Invalid login grace time.\n")); 1083*0Sstevel@tonic-gate exit(1); 1084*0Sstevel@tonic-gate } 1085*0Sstevel@tonic-gate break; 1086*0Sstevel@tonic-gate case 'k': 1087*0Sstevel@tonic-gate if ((options.key_regeneration_time = convtime(optarg)) == -1) { 1088*0Sstevel@tonic-gate (void) fprintf(stderr, 1089*0Sstevel@tonic-gate gettext("Invalid key regeneration " 1090*0Sstevel@tonic-gate "interval.\n")); 1091*0Sstevel@tonic-gate exit(1); 1092*0Sstevel@tonic-gate } 1093*0Sstevel@tonic-gate break; 1094*0Sstevel@tonic-gate case 'h': 1095*0Sstevel@tonic-gate if (options.num_host_key_files >= MAX_HOSTKEYS) { 1096*0Sstevel@tonic-gate (void) fprintf(stderr, 1097*0Sstevel@tonic-gate gettext("too many host keys.\n")); 1098*0Sstevel@tonic-gate exit(1); 1099*0Sstevel@tonic-gate } 1100*0Sstevel@tonic-gate options.host_key_files[options.num_host_key_files++] = optarg; 1101*0Sstevel@tonic-gate break; 1102*0Sstevel@tonic-gate case 'V': 1103*0Sstevel@tonic-gate client_version_string = optarg; 1104*0Sstevel@tonic-gate /* only makes sense with inetd_flag, i.e. no listen() */ 1105*0Sstevel@tonic-gate inetd_flag = 1; 1106*0Sstevel@tonic-gate break; 1107*0Sstevel@tonic-gate case 't': 1108*0Sstevel@tonic-gate test_flag = 1; 1109*0Sstevel@tonic-gate break; 1110*0Sstevel@tonic-gate case 'o': 1111*0Sstevel@tonic-gate if (process_server_config_line(&options, optarg, 1112*0Sstevel@tonic-gate "command-line", 0) != 0) 1113*0Sstevel@tonic-gate exit(1); 1114*0Sstevel@tonic-gate break; 1115*0Sstevel@tonic-gate case '?': 1116*0Sstevel@tonic-gate default: 1117*0Sstevel@tonic-gate usage(); 1118*0Sstevel@tonic-gate break; 1119*0Sstevel@tonic-gate } 1120*0Sstevel@tonic-gate } 1121*0Sstevel@tonic-gate SSLeay_add_all_algorithms(); 1122*0Sstevel@tonic-gate channel_set_af(IPv4or6); 1123*0Sstevel@tonic-gate 1124*0Sstevel@tonic-gate /* 1125*0Sstevel@tonic-gate * Force logging to stderr until we have loaded the private host 1126*0Sstevel@tonic-gate * key (unless started from inetd) 1127*0Sstevel@tonic-gate */ 1128*0Sstevel@tonic-gate log_init(__progname, 1129*0Sstevel@tonic-gate options.log_level == SYSLOG_LEVEL_NOT_SET ? 1130*0Sstevel@tonic-gate SYSLOG_LEVEL_INFO : options.log_level, 1131*0Sstevel@tonic-gate options.log_facility == SYSLOG_FACILITY_NOT_SET ? 1132*0Sstevel@tonic-gate SYSLOG_FACILITY_AUTH : options.log_facility, 1133*0Sstevel@tonic-gate !inetd_flag); 1134*0Sstevel@tonic-gate 1135*0Sstevel@tonic-gate #ifdef _UNICOS 1136*0Sstevel@tonic-gate /* Cray can define user privs drop all prives now! 1137*0Sstevel@tonic-gate * Not needed on PRIV_SU systems! 1138*0Sstevel@tonic-gate */ 1139*0Sstevel@tonic-gate drop_cray_privs(); 1140*0Sstevel@tonic-gate #endif 1141*0Sstevel@tonic-gate 1142*0Sstevel@tonic-gate seed_rng(); 1143*0Sstevel@tonic-gate 1144*0Sstevel@tonic-gate /* Read server configuration options from the configuration file. */ 1145*0Sstevel@tonic-gate read_server_config(&options, config_file_name); 1146*0Sstevel@tonic-gate 1147*0Sstevel@tonic-gate /* Fill in default values for those options not explicitly set. */ 1148*0Sstevel@tonic-gate fill_default_server_options(&options); 1149*0Sstevel@tonic-gate 1150*0Sstevel@tonic-gate utmp_len = options.lookup_client_hostnames ? utmp_len : 0; 1151*0Sstevel@tonic-gate 1152*0Sstevel@tonic-gate /* Check that there are no remaining arguments. */ 1153*0Sstevel@tonic-gate if (optind < ac) { 1154*0Sstevel@tonic-gate (void) fprintf(stderr, gettext("Extra argument %s.\n"), av[optind]); 1155*0Sstevel@tonic-gate exit(1); 1156*0Sstevel@tonic-gate } 1157*0Sstevel@tonic-gate 1158*0Sstevel@tonic-gate debug("sshd version %.100s", SSH_VERSION); 1159*0Sstevel@tonic-gate 1160*0Sstevel@tonic-gate /* load private host keys */ 1161*0Sstevel@tonic-gate if (options.num_host_key_files > 0) 1162*0Sstevel@tonic-gate sensitive_data.host_keys = 1163*0Sstevel@tonic-gate xmalloc(options.num_host_key_files * sizeof(Key *)); 1164*0Sstevel@tonic-gate for (i = 0; i < options.num_host_key_files; i++) 1165*0Sstevel@tonic-gate sensitive_data.host_keys[i] = NULL; 1166*0Sstevel@tonic-gate sensitive_data.server_key = NULL; 1167*0Sstevel@tonic-gate sensitive_data.ssh1_host_key = NULL; 1168*0Sstevel@tonic-gate sensitive_data.have_ssh1_key = 0; 1169*0Sstevel@tonic-gate sensitive_data.have_ssh2_key = 0; 1170*0Sstevel@tonic-gate 1171*0Sstevel@tonic-gate for (i = 0; i < options.num_host_key_files; i++) { 1172*0Sstevel@tonic-gate key = key_load_private(options.host_key_files[i], "", NULL); 1173*0Sstevel@tonic-gate sensitive_data.host_keys[i] = key; 1174*0Sstevel@tonic-gate if (key == NULL) { 1175*0Sstevel@tonic-gate error("Could not load host key: %s", 1176*0Sstevel@tonic-gate options.host_key_files[i]); 1177*0Sstevel@tonic-gate sensitive_data.host_keys[i] = NULL; 1178*0Sstevel@tonic-gate continue; 1179*0Sstevel@tonic-gate } 1180*0Sstevel@tonic-gate switch (key->type) { 1181*0Sstevel@tonic-gate case KEY_RSA1: 1182*0Sstevel@tonic-gate sensitive_data.ssh1_host_key = key; 1183*0Sstevel@tonic-gate sensitive_data.have_ssh1_key = 1; 1184*0Sstevel@tonic-gate break; 1185*0Sstevel@tonic-gate case KEY_RSA: 1186*0Sstevel@tonic-gate case KEY_DSA: 1187*0Sstevel@tonic-gate sensitive_data.have_ssh2_key = 1; 1188*0Sstevel@tonic-gate break; 1189*0Sstevel@tonic-gate } 1190*0Sstevel@tonic-gate debug("private host key: #%d type %d %s", i, key->type, 1191*0Sstevel@tonic-gate key_type(key)); 1192*0Sstevel@tonic-gate } 1193*0Sstevel@tonic-gate if ((options.protocol & SSH_PROTO_1) && !sensitive_data.have_ssh1_key) { 1194*0Sstevel@tonic-gate log("Disabling protocol version 1. Could not load host key"); 1195*0Sstevel@tonic-gate options.protocol &= ~SSH_PROTO_1; 1196*0Sstevel@tonic-gate } 1197*0Sstevel@tonic-gate if ((options.protocol & SSH_PROTO_2) && 1198*0Sstevel@tonic-gate !sensitive_data.have_ssh2_key) { 1199*0Sstevel@tonic-gate #ifdef GSSAPI 1200*0Sstevel@tonic-gate if (options.gss_keyex) 1201*0Sstevel@tonic-gate ssh_gssapi_server_mechs(&mechs); 1202*0Sstevel@tonic-gate 1203*0Sstevel@tonic-gate if (mechs == GSS_C_NULL_OID_SET) { 1204*0Sstevel@tonic-gate log("Disabling protocol version 2. Could not load host" 1205*0Sstevel@tonic-gate "key or GSS-API mechanisms"); 1206*0Sstevel@tonic-gate options.protocol &= ~SSH_PROTO_2; 1207*0Sstevel@tonic-gate } 1208*0Sstevel@tonic-gate #else 1209*0Sstevel@tonic-gate log("Disabling protocol version 2. Could not load host key"); 1210*0Sstevel@tonic-gate options.protocol &= ~SSH_PROTO_2; 1211*0Sstevel@tonic-gate #endif /* GSSAPI */ 1212*0Sstevel@tonic-gate } 1213*0Sstevel@tonic-gate if (!(options.protocol & (SSH_PROTO_1|SSH_PROTO_2))) { 1214*0Sstevel@tonic-gate log("sshd: no hostkeys available -- exiting."); 1215*0Sstevel@tonic-gate exit(1); 1216*0Sstevel@tonic-gate } 1217*0Sstevel@tonic-gate 1218*0Sstevel@tonic-gate /* Check certain values for sanity. */ 1219*0Sstevel@tonic-gate if (options.protocol & SSH_PROTO_1) { 1220*0Sstevel@tonic-gate if (options.server_key_bits < 512 || 1221*0Sstevel@tonic-gate options.server_key_bits > 32768) { 1222*0Sstevel@tonic-gate (void) fprintf(stderr, gettext("Bad server key size.\n")); 1223*0Sstevel@tonic-gate exit(1); 1224*0Sstevel@tonic-gate } 1225*0Sstevel@tonic-gate /* 1226*0Sstevel@tonic-gate * Check that server and host key lengths differ sufficiently. This 1227*0Sstevel@tonic-gate * is necessary to make double encryption work with rsaref. Oh, I 1228*0Sstevel@tonic-gate * hate software patents. I dont know if this can go? Niels 1229*0Sstevel@tonic-gate */ 1230*0Sstevel@tonic-gate if (options.server_key_bits > 1231*0Sstevel@tonic-gate BN_num_bits(sensitive_data.ssh1_host_key->rsa->n) - 1232*0Sstevel@tonic-gate SSH_KEY_BITS_RESERVED && options.server_key_bits < 1233*0Sstevel@tonic-gate BN_num_bits(sensitive_data.ssh1_host_key->rsa->n) + 1234*0Sstevel@tonic-gate SSH_KEY_BITS_RESERVED) { 1235*0Sstevel@tonic-gate options.server_key_bits = 1236*0Sstevel@tonic-gate BN_num_bits(sensitive_data.ssh1_host_key->rsa->n) + 1237*0Sstevel@tonic-gate SSH_KEY_BITS_RESERVED; 1238*0Sstevel@tonic-gate debug("Forcing server key to %d bits to make it differ from host key.", 1239*0Sstevel@tonic-gate options.server_key_bits); 1240*0Sstevel@tonic-gate } 1241*0Sstevel@tonic-gate } 1242*0Sstevel@tonic-gate 1243*0Sstevel@tonic-gate if (use_privsep) { 1244*0Sstevel@tonic-gate struct stat st; 1245*0Sstevel@tonic-gate 1246*0Sstevel@tonic-gate if (getpwnam(SSH_PRIVSEP_USER) == NULL) 1247*0Sstevel@tonic-gate fatal("Privilege separation user %s does not exist", 1248*0Sstevel@tonic-gate SSH_PRIVSEP_USER); 1249*0Sstevel@tonic-gate if ((stat(_PATH_PRIVSEP_CHROOT_DIR, &st) == -1) || 1250*0Sstevel@tonic-gate (S_ISDIR(st.st_mode) == 0)) 1251*0Sstevel@tonic-gate fatal("Missing privilege separation directory: %s", 1252*0Sstevel@tonic-gate _PATH_PRIVSEP_CHROOT_DIR); 1253*0Sstevel@tonic-gate 1254*0Sstevel@tonic-gate #ifdef HAVE_CYGWIN 1255*0Sstevel@tonic-gate if (check_ntsec(_PATH_PRIVSEP_CHROOT_DIR) && 1256*0Sstevel@tonic-gate (st.st_uid != getuid () || 1257*0Sstevel@tonic-gate (st.st_mode & (S_IWGRP|S_IWOTH)) != 0)) 1258*0Sstevel@tonic-gate #else 1259*0Sstevel@tonic-gate if (st.st_uid != 0 || (st.st_mode & (S_IWGRP|S_IWOTH)) != 0) 1260*0Sstevel@tonic-gate #endif 1261*0Sstevel@tonic-gate fatal("Bad owner or mode for %s", 1262*0Sstevel@tonic-gate _PATH_PRIVSEP_CHROOT_DIR); 1263*0Sstevel@tonic-gate } 1264*0Sstevel@tonic-gate 1265*0Sstevel@tonic-gate /* Configuration looks good, so exit if in test mode. */ 1266*0Sstevel@tonic-gate if (test_flag) 1267*0Sstevel@tonic-gate exit(0); 1268*0Sstevel@tonic-gate 1269*0Sstevel@tonic-gate /* 1270*0Sstevel@tonic-gate * Clear out any supplemental groups we may have inherited. This 1271*0Sstevel@tonic-gate * prevents inadvertent creation of files with bad modes (in the 1272*0Sstevel@tonic-gate * portable version at least, it's certainly possible for PAM 1273*0Sstevel@tonic-gate * to create a file, and we can't control the code in every 1274*0Sstevel@tonic-gate * module which might be used). 1275*0Sstevel@tonic-gate */ 1276*0Sstevel@tonic-gate if (setgroups(0, NULL) < 0) 1277*0Sstevel@tonic-gate debug("setgroups() failed: %.200s", strerror(errno)); 1278*0Sstevel@tonic-gate 1279*0Sstevel@tonic-gate /* Initialize the log (it is reinitialized below in case we forked). */ 1280*0Sstevel@tonic-gate if (debug_flag && !inetd_flag) 1281*0Sstevel@tonic-gate log_stderr = 1; 1282*0Sstevel@tonic-gate log_init(__progname, options.log_level, options.log_facility, log_stderr); 1283*0Sstevel@tonic-gate 1284*0Sstevel@tonic-gate #ifdef HAVE_BSM 1285*0Sstevel@tonic-gate (void) setauid(&auid); 1286*0Sstevel@tonic-gate #endif /* HAVE_BSM */ 1287*0Sstevel@tonic-gate 1288*0Sstevel@tonic-gate /* 1289*0Sstevel@tonic-gate * If not in debugging mode, and not started from inetd, disconnect 1290*0Sstevel@tonic-gate * from the controlling terminal, and fork. The original process 1291*0Sstevel@tonic-gate * exits. 1292*0Sstevel@tonic-gate */ 1293*0Sstevel@tonic-gate if (!(debug_flag || inetd_flag || no_daemon_flag)) { 1294*0Sstevel@tonic-gate #ifdef TIOCNOTTY 1295*0Sstevel@tonic-gate int fd; 1296*0Sstevel@tonic-gate #endif /* TIOCNOTTY */ 1297*0Sstevel@tonic-gate if (daemon(0, 0) < 0) 1298*0Sstevel@tonic-gate fatal("daemon() failed: %.200s", strerror(errno)); 1299*0Sstevel@tonic-gate 1300*0Sstevel@tonic-gate /* Disconnect from the controlling tty. */ 1301*0Sstevel@tonic-gate #ifdef TIOCNOTTY 1302*0Sstevel@tonic-gate fd = open(_PATH_TTY, O_RDWR | O_NOCTTY); 1303*0Sstevel@tonic-gate if (fd >= 0) { 1304*0Sstevel@tonic-gate (void) ioctl(fd, TIOCNOTTY, NULL); 1305*0Sstevel@tonic-gate (void) close(fd); 1306*0Sstevel@tonic-gate } 1307*0Sstevel@tonic-gate #endif /* TIOCNOTTY */ 1308*0Sstevel@tonic-gate } 1309*0Sstevel@tonic-gate /* Reinitialize the log (because of the fork above). */ 1310*0Sstevel@tonic-gate log_init(__progname, options.log_level, options.log_facility, log_stderr); 1311*0Sstevel@tonic-gate 1312*0Sstevel@tonic-gate /* Initialize the random number generator. */ 1313*0Sstevel@tonic-gate arc4random_stir(); 1314*0Sstevel@tonic-gate 1315*0Sstevel@tonic-gate /* Chdir to the root directory so that the current disk can be 1316*0Sstevel@tonic-gate unmounted if desired. */ 1317*0Sstevel@tonic-gate (void) chdir("/"); 1318*0Sstevel@tonic-gate 1319*0Sstevel@tonic-gate /* ignore SIGPIPE */ 1320*0Sstevel@tonic-gate (void) signal(SIGPIPE, SIG_IGN); 1321*0Sstevel@tonic-gate 1322*0Sstevel@tonic-gate /* Start listening for a socket, unless started from inetd. */ 1323*0Sstevel@tonic-gate if (inetd_flag) { 1324*0Sstevel@tonic-gate int s1; 1325*0Sstevel@tonic-gate s1 = dup(0); /* Make sure descriptors 0, 1, and 2 are in use. */ 1326*0Sstevel@tonic-gate (void) dup(s1); 1327*0Sstevel@tonic-gate sock_in = dup(0); 1328*0Sstevel@tonic-gate sock_out = dup(1); 1329*0Sstevel@tonic-gate startup_pipe = -1; 1330*0Sstevel@tonic-gate /* 1331*0Sstevel@tonic-gate * We intentionally do not close the descriptors 0, 1, and 2 1332*0Sstevel@tonic-gate * as our code for setting the descriptors won\'t work if 1333*0Sstevel@tonic-gate * ttyfd happens to be one of those. 1334*0Sstevel@tonic-gate */ 1335*0Sstevel@tonic-gate debug("inetd sockets after dupping: %d, %d", sock_in, sock_out); 1336*0Sstevel@tonic-gate if (options.protocol & SSH_PROTO_1) 1337*0Sstevel@tonic-gate generate_ephemeral_server_key(); 1338*0Sstevel@tonic-gate } else { 1339*0Sstevel@tonic-gate for (ai = options.listen_addrs; ai; ai = ai->ai_next) { 1340*0Sstevel@tonic-gate if (ai->ai_family != AF_INET && ai->ai_family != AF_INET6) 1341*0Sstevel@tonic-gate continue; 1342*0Sstevel@tonic-gate if (num_listen_socks >= MAX_LISTEN_SOCKS) 1343*0Sstevel@tonic-gate fatal("Too many listen sockets. " 1344*0Sstevel@tonic-gate "Enlarge MAX_LISTEN_SOCKS"); 1345*0Sstevel@tonic-gate if (getnameinfo(ai->ai_addr, ai->ai_addrlen, 1346*0Sstevel@tonic-gate ntop, sizeof(ntop), strport, sizeof(strport), 1347*0Sstevel@tonic-gate NI_NUMERICHOST|NI_NUMERICSERV) != 0) { 1348*0Sstevel@tonic-gate error("getnameinfo failed"); 1349*0Sstevel@tonic-gate continue; 1350*0Sstevel@tonic-gate } 1351*0Sstevel@tonic-gate /* Create socket for listening. */ 1352*0Sstevel@tonic-gate listen_sock = socket(ai->ai_family, SOCK_STREAM, 0); 1353*0Sstevel@tonic-gate if (listen_sock < 0) { 1354*0Sstevel@tonic-gate /* kernel may not support ipv6 */ 1355*0Sstevel@tonic-gate verbose("socket: %.100s", strerror(errno)); 1356*0Sstevel@tonic-gate continue; 1357*0Sstevel@tonic-gate } 1358*0Sstevel@tonic-gate if (fcntl(listen_sock, F_SETFL, O_NONBLOCK) < 0) { 1359*0Sstevel@tonic-gate error("listen_sock O_NONBLOCK: %s", strerror(errno)); 1360*0Sstevel@tonic-gate (void) close(listen_sock); 1361*0Sstevel@tonic-gate continue; 1362*0Sstevel@tonic-gate } 1363*0Sstevel@tonic-gate /* 1364*0Sstevel@tonic-gate * Set socket options. 1365*0Sstevel@tonic-gate * Allow local port reuse in TIME_WAIT. 1366*0Sstevel@tonic-gate */ 1367*0Sstevel@tonic-gate if (setsockopt(listen_sock, SOL_SOCKET, SO_REUSEADDR, 1368*0Sstevel@tonic-gate &on, sizeof(on)) == -1) 1369*0Sstevel@tonic-gate error("setsockopt SO_REUSEADDR: %s", strerror(errno)); 1370*0Sstevel@tonic-gate 1371*0Sstevel@tonic-gate debug("Bind to port %s on %s.", strport, ntop); 1372*0Sstevel@tonic-gate 1373*0Sstevel@tonic-gate /* Bind the socket to the desired port. */ 1374*0Sstevel@tonic-gate if (bind(listen_sock, ai->ai_addr, ai->ai_addrlen) < 0) { 1375*0Sstevel@tonic-gate if (!ai->ai_next) 1376*0Sstevel@tonic-gate error("Bind to port %s on %s failed: %.200s.", 1377*0Sstevel@tonic-gate strport, ntop, strerror(errno)); 1378*0Sstevel@tonic-gate (void) close(listen_sock); 1379*0Sstevel@tonic-gate continue; 1380*0Sstevel@tonic-gate } 1381*0Sstevel@tonic-gate listen_socks[num_listen_socks] = listen_sock; 1382*0Sstevel@tonic-gate num_listen_socks++; 1383*0Sstevel@tonic-gate 1384*0Sstevel@tonic-gate /* Start listening on the port. */ 1385*0Sstevel@tonic-gate log("Server listening on %s port %s.", ntop, strport); 1386*0Sstevel@tonic-gate if (listen(listen_sock, 5) < 0) 1387*0Sstevel@tonic-gate fatal("listen: %.100s", strerror(errno)); 1388*0Sstevel@tonic-gate 1389*0Sstevel@tonic-gate } 1390*0Sstevel@tonic-gate freeaddrinfo(options.listen_addrs); 1391*0Sstevel@tonic-gate 1392*0Sstevel@tonic-gate if (!num_listen_socks) 1393*0Sstevel@tonic-gate fatal("Cannot bind any address."); 1394*0Sstevel@tonic-gate 1395*0Sstevel@tonic-gate if (options.protocol & SSH_PROTO_1) 1396*0Sstevel@tonic-gate generate_ephemeral_server_key(); 1397*0Sstevel@tonic-gate 1398*0Sstevel@tonic-gate /* 1399*0Sstevel@tonic-gate * Arrange to restart on SIGHUP. The handler needs 1400*0Sstevel@tonic-gate * listen_sock. 1401*0Sstevel@tonic-gate */ 1402*0Sstevel@tonic-gate (void) signal(SIGHUP, sighup_handler); 1403*0Sstevel@tonic-gate 1404*0Sstevel@tonic-gate (void) signal(SIGTERM, sigterm_handler); 1405*0Sstevel@tonic-gate (void) signal(SIGQUIT, sigterm_handler); 1406*0Sstevel@tonic-gate 1407*0Sstevel@tonic-gate /* Arrange SIGCHLD to be caught. */ 1408*0Sstevel@tonic-gate (void) signal(SIGCHLD, main_sigchld_handler); 1409*0Sstevel@tonic-gate 1410*0Sstevel@tonic-gate /* Write out the pid file after the sigterm handler is setup */ 1411*0Sstevel@tonic-gate if (!debug_flag) { 1412*0Sstevel@tonic-gate /* 1413*0Sstevel@tonic-gate * Record our pid in /var/run/sshd.pid to make it 1414*0Sstevel@tonic-gate * easier to kill the correct sshd. We don't want to 1415*0Sstevel@tonic-gate * do this before the bind above because the bind will 1416*0Sstevel@tonic-gate * fail if there already is a daemon, and this will 1417*0Sstevel@tonic-gate * overwrite any old pid in the file. 1418*0Sstevel@tonic-gate */ 1419*0Sstevel@tonic-gate f = fopen(options.pid_file, "wb"); 1420*0Sstevel@tonic-gate if (f) { 1421*0Sstevel@tonic-gate (void) fprintf(f, "%ld\n", (long) getpid()); 1422*0Sstevel@tonic-gate (void) fclose(f); 1423*0Sstevel@tonic-gate } 1424*0Sstevel@tonic-gate } 1425*0Sstevel@tonic-gate 1426*0Sstevel@tonic-gate /* setup fd set for listen */ 1427*0Sstevel@tonic-gate fdset = NULL; 1428*0Sstevel@tonic-gate maxfd = 0; 1429*0Sstevel@tonic-gate for (i = 0; i < num_listen_socks; i++) 1430*0Sstevel@tonic-gate if (listen_socks[i] > maxfd) 1431*0Sstevel@tonic-gate maxfd = listen_socks[i]; 1432*0Sstevel@tonic-gate /* pipes connected to unauthenticated childs */ 1433*0Sstevel@tonic-gate startup_pipes = xmalloc(options.max_startups * sizeof(int)); 1434*0Sstevel@tonic-gate for (i = 0; i < options.max_startups; i++) 1435*0Sstevel@tonic-gate startup_pipes[i] = -1; 1436*0Sstevel@tonic-gate 1437*0Sstevel@tonic-gate /* 1438*0Sstevel@tonic-gate * Stay listening for connections until the system crashes or 1439*0Sstevel@tonic-gate * the daemon is killed with a signal. 1440*0Sstevel@tonic-gate */ 1441*0Sstevel@tonic-gate for (;;) { 1442*0Sstevel@tonic-gate if (received_sighup) 1443*0Sstevel@tonic-gate sighup_restart(); 1444*0Sstevel@tonic-gate if (fdset != NULL) 1445*0Sstevel@tonic-gate xfree(fdset); 1446*0Sstevel@tonic-gate fdsetsz = howmany(maxfd+1, NFDBITS) * sizeof(fd_mask); 1447*0Sstevel@tonic-gate fdset = (fd_set *)xmalloc(fdsetsz); 1448*0Sstevel@tonic-gate (void) memset(fdset, 0, fdsetsz); 1449*0Sstevel@tonic-gate 1450*0Sstevel@tonic-gate for (i = 0; i < num_listen_socks; i++) 1451*0Sstevel@tonic-gate FD_SET(listen_socks[i], fdset); 1452*0Sstevel@tonic-gate for (i = 0; i < options.max_startups; i++) 1453*0Sstevel@tonic-gate if (startup_pipes[i] != -1) 1454*0Sstevel@tonic-gate FD_SET(startup_pipes[i], fdset); 1455*0Sstevel@tonic-gate 1456*0Sstevel@tonic-gate /* Wait in select until there is a connection. */ 1457*0Sstevel@tonic-gate ret = select(maxfd+1, fdset, NULL, NULL, NULL); 1458*0Sstevel@tonic-gate if (ret < 0 && errno != EINTR) 1459*0Sstevel@tonic-gate error("select: %.100s", strerror(errno)); 1460*0Sstevel@tonic-gate if (received_sigterm) { 1461*0Sstevel@tonic-gate log("Received signal %d; terminating.", 1462*0Sstevel@tonic-gate (int) received_sigterm); 1463*0Sstevel@tonic-gate close_listen_socks(); 1464*0Sstevel@tonic-gate (void) unlink(options.pid_file); 1465*0Sstevel@tonic-gate exit(255); 1466*0Sstevel@tonic-gate } 1467*0Sstevel@tonic-gate if (key_used && key_do_regen) { 1468*0Sstevel@tonic-gate generate_ephemeral_server_key(); 1469*0Sstevel@tonic-gate key_used = 0; 1470*0Sstevel@tonic-gate key_do_regen = 0; 1471*0Sstevel@tonic-gate } 1472*0Sstevel@tonic-gate if (ret < 0) 1473*0Sstevel@tonic-gate continue; 1474*0Sstevel@tonic-gate 1475*0Sstevel@tonic-gate for (i = 0; i < options.max_startups; i++) 1476*0Sstevel@tonic-gate if (startup_pipes[i] != -1 && 1477*0Sstevel@tonic-gate FD_ISSET(startup_pipes[i], fdset)) { 1478*0Sstevel@tonic-gate /* 1479*0Sstevel@tonic-gate * the read end of the pipe is ready 1480*0Sstevel@tonic-gate * if the child has closed the pipe 1481*0Sstevel@tonic-gate * after successful authentication 1482*0Sstevel@tonic-gate * or if the child has died 1483*0Sstevel@tonic-gate */ 1484*0Sstevel@tonic-gate (void) close(startup_pipes[i]); 1485*0Sstevel@tonic-gate startup_pipes[i] = -1; 1486*0Sstevel@tonic-gate startups--; 1487*0Sstevel@tonic-gate } 1488*0Sstevel@tonic-gate for (i = 0; i < num_listen_socks; i++) { 1489*0Sstevel@tonic-gate if (!FD_ISSET(listen_socks[i], fdset)) 1490*0Sstevel@tonic-gate continue; 1491*0Sstevel@tonic-gate fromlen = sizeof(from); 1492*0Sstevel@tonic-gate newsock = accept(listen_socks[i], (struct sockaddr *)&from, 1493*0Sstevel@tonic-gate &fromlen); 1494*0Sstevel@tonic-gate if (newsock < 0) { 1495*0Sstevel@tonic-gate if (errno != EINTR && errno != EWOULDBLOCK) 1496*0Sstevel@tonic-gate error("accept: %.100s", strerror(errno)); 1497*0Sstevel@tonic-gate continue; 1498*0Sstevel@tonic-gate } 1499*0Sstevel@tonic-gate if (fcntl(newsock, F_SETFL, 0) < 0) { 1500*0Sstevel@tonic-gate error("newsock del O_NONBLOCK: %s", strerror(errno)); 1501*0Sstevel@tonic-gate (void) close(newsock); 1502*0Sstevel@tonic-gate continue; 1503*0Sstevel@tonic-gate } 1504*0Sstevel@tonic-gate if (drop_connection(startups) == 1) { 1505*0Sstevel@tonic-gate debug("drop connection #%d", startups); 1506*0Sstevel@tonic-gate (void) close(newsock); 1507*0Sstevel@tonic-gate continue; 1508*0Sstevel@tonic-gate } 1509*0Sstevel@tonic-gate if (pipe(startup_p) == -1) { 1510*0Sstevel@tonic-gate (void) close(newsock); 1511*0Sstevel@tonic-gate continue; 1512*0Sstevel@tonic-gate } 1513*0Sstevel@tonic-gate 1514*0Sstevel@tonic-gate for (j = 0; j < options.max_startups; j++) 1515*0Sstevel@tonic-gate if (startup_pipes[j] == -1) { 1516*0Sstevel@tonic-gate startup_pipes[j] = startup_p[0]; 1517*0Sstevel@tonic-gate if (maxfd < startup_p[0]) 1518*0Sstevel@tonic-gate maxfd = startup_p[0]; 1519*0Sstevel@tonic-gate startups++; 1520*0Sstevel@tonic-gate break; 1521*0Sstevel@tonic-gate } 1522*0Sstevel@tonic-gate 1523*0Sstevel@tonic-gate /* 1524*0Sstevel@tonic-gate * Got connection. Fork a child to handle it, unless 1525*0Sstevel@tonic-gate * we are in debugging mode. 1526*0Sstevel@tonic-gate */ 1527*0Sstevel@tonic-gate if (debug_flag) { 1528*0Sstevel@tonic-gate /* 1529*0Sstevel@tonic-gate * In debugging mode. Close the listening 1530*0Sstevel@tonic-gate * socket, and start processing the 1531*0Sstevel@tonic-gate * connection without forking. 1532*0Sstevel@tonic-gate */ 1533*0Sstevel@tonic-gate debug("Server will not fork when running in debugging mode."); 1534*0Sstevel@tonic-gate close_listen_socks(); 1535*0Sstevel@tonic-gate sock_in = newsock; 1536*0Sstevel@tonic-gate sock_out = newsock; 1537*0Sstevel@tonic-gate startup_pipe = -1; 1538*0Sstevel@tonic-gate pid = getpid(); 1539*0Sstevel@tonic-gate break; 1540*0Sstevel@tonic-gate } else { 1541*0Sstevel@tonic-gate /* 1542*0Sstevel@tonic-gate * Normal production daemon. Fork, and have 1543*0Sstevel@tonic-gate * the child process the connection. The 1544*0Sstevel@tonic-gate * parent continues listening. 1545*0Sstevel@tonic-gate */ 1546*0Sstevel@tonic-gate #ifdef HAVE_SOLARIS_CONTRACTS 1547*0Sstevel@tonic-gate /* 1548*0Sstevel@tonic-gate * Setup Solaris contract template so 1549*0Sstevel@tonic-gate * the child process is in a different 1550*0Sstevel@tonic-gate * process contract than the parent; 1551*0Sstevel@tonic-gate * prevents established connections from 1552*0Sstevel@tonic-gate * being killed when the sshd master 1553*0Sstevel@tonic-gate * listener service is stopped. 1554*0Sstevel@tonic-gate */ 1555*0Sstevel@tonic-gate contracts_pre_fork(); 1556*0Sstevel@tonic-gate #endif /* HAVE_SOLARIS_CONTRACTS */ 1557*0Sstevel@tonic-gate if ((pid = fork()) == 0) { 1558*0Sstevel@tonic-gate /* 1559*0Sstevel@tonic-gate * Child. Close the listening and max_startup 1560*0Sstevel@tonic-gate * sockets. Start using the accepted socket. 1561*0Sstevel@tonic-gate * Reinitialize logging (since our pid has 1562*0Sstevel@tonic-gate * changed). We break out of the loop to handle 1563*0Sstevel@tonic-gate * the connection. 1564*0Sstevel@tonic-gate */ 1565*0Sstevel@tonic-gate #ifdef HAVE_SOLARIS_CONTRACTS 1566*0Sstevel@tonic-gate contracts_post_fork_child(); 1567*0Sstevel@tonic-gate #endif /* HAVE_SOLARIS_CONTRACTS */ 1568*0Sstevel@tonic-gate startup_pipe = startup_p[1]; 1569*0Sstevel@tonic-gate close_startup_pipes(); 1570*0Sstevel@tonic-gate close_listen_socks(); 1571*0Sstevel@tonic-gate sock_in = newsock; 1572*0Sstevel@tonic-gate sock_out = newsock; 1573*0Sstevel@tonic-gate log_init(__progname, options.log_level, options.log_facility, log_stderr); 1574*0Sstevel@tonic-gate break; 1575*0Sstevel@tonic-gate } 1576*0Sstevel@tonic-gate 1577*0Sstevel@tonic-gate #ifdef HAVE_SOLARIS_CONTRACTS 1578*0Sstevel@tonic-gate contracts_post_fork_parent((pid > 0)); 1579*0Sstevel@tonic-gate #endif /* HAVE_SOLARIS_CONTRACTS */ 1580*0Sstevel@tonic-gate } 1581*0Sstevel@tonic-gate 1582*0Sstevel@tonic-gate /* Parent. Stay in the loop. */ 1583*0Sstevel@tonic-gate if (pid < 0) 1584*0Sstevel@tonic-gate error("fork: %.100s", strerror(errno)); 1585*0Sstevel@tonic-gate else 1586*0Sstevel@tonic-gate debug("Forked child %ld.", (long)pid); 1587*0Sstevel@tonic-gate 1588*0Sstevel@tonic-gate (void) close(startup_p[1]); 1589*0Sstevel@tonic-gate 1590*0Sstevel@tonic-gate /* Mark that the key has been used (it was "given" to the child). */ 1591*0Sstevel@tonic-gate if ((options.protocol & SSH_PROTO_1) && 1592*0Sstevel@tonic-gate key_used == 0) { 1593*0Sstevel@tonic-gate /* Schedule server key regeneration alarm. */ 1594*0Sstevel@tonic-gate (void) signal(SIGALRM, key_regeneration_alarm); 1595*0Sstevel@tonic-gate (void) alarm(options.key_regeneration_time); 1596*0Sstevel@tonic-gate key_used = 1; 1597*0Sstevel@tonic-gate } 1598*0Sstevel@tonic-gate 1599*0Sstevel@tonic-gate arc4random_stir(); 1600*0Sstevel@tonic-gate 1601*0Sstevel@tonic-gate /* Close the new socket (the child is now taking care of it). */ 1602*0Sstevel@tonic-gate (void) close(newsock); 1603*0Sstevel@tonic-gate } 1604*0Sstevel@tonic-gate /* child process check (or debug mode) */ 1605*0Sstevel@tonic-gate if (num_listen_socks < 0) 1606*0Sstevel@tonic-gate break; 1607*0Sstevel@tonic-gate } 1608*0Sstevel@tonic-gate } 1609*0Sstevel@tonic-gate 1610*0Sstevel@tonic-gate /* This is the child processing a new connection. */ 1611*0Sstevel@tonic-gate #ifdef HAVE_BSM 1612*0Sstevel@tonic-gate audit_sshd_settid(newsock); 1613*0Sstevel@tonic-gate #endif 1614*0Sstevel@tonic-gate /* 1615*0Sstevel@tonic-gate * Create a new session and process group since the 4.4BSD 1616*0Sstevel@tonic-gate * setlogin() affects the entire process group. We don't 1617*0Sstevel@tonic-gate * want the child to be able to affect the parent. 1618*0Sstevel@tonic-gate */ 1619*0Sstevel@tonic-gate #if 0 1620*0Sstevel@tonic-gate /* XXX: this breaks Solaris */ 1621*0Sstevel@tonic-gate if (!debug_flag && !inetd_flag && setsid() < 0) 1622*0Sstevel@tonic-gate error("setsid: %.100s", strerror(errno)); 1623*0Sstevel@tonic-gate #endif 1624*0Sstevel@tonic-gate 1625*0Sstevel@tonic-gate /* 1626*0Sstevel@tonic-gate * Disable the key regeneration alarm. We will not regenerate the 1627*0Sstevel@tonic-gate * key since we are no longer in a position to give it to anyone. We 1628*0Sstevel@tonic-gate * will not restart on SIGHUP since it no longer makes sense. 1629*0Sstevel@tonic-gate */ 1630*0Sstevel@tonic-gate (void) alarm(0); 1631*0Sstevel@tonic-gate (void) signal(SIGALRM, SIG_DFL); 1632*0Sstevel@tonic-gate (void) signal(SIGHUP, SIG_DFL); 1633*0Sstevel@tonic-gate (void) signal(SIGTERM, SIG_DFL); 1634*0Sstevel@tonic-gate (void) signal(SIGQUIT, SIG_DFL); 1635*0Sstevel@tonic-gate (void) signal(SIGCHLD, SIG_DFL); 1636*0Sstevel@tonic-gate (void) signal(SIGINT, SIG_DFL); 1637*0Sstevel@tonic-gate 1638*0Sstevel@tonic-gate /* Set keepalives if requested. */ 1639*0Sstevel@tonic-gate if (options.keepalives && 1640*0Sstevel@tonic-gate setsockopt(sock_in, SOL_SOCKET, SO_KEEPALIVE, &on, 1641*0Sstevel@tonic-gate sizeof(on)) < 0) 1642*0Sstevel@tonic-gate debug2("setsockopt SO_KEEPALIVE: %.100s", strerror(errno)); 1643*0Sstevel@tonic-gate 1644*0Sstevel@tonic-gate /* 1645*0Sstevel@tonic-gate * Register our connection. This turns encryption off because we do 1646*0Sstevel@tonic-gate * not have a key. 1647*0Sstevel@tonic-gate */ 1648*0Sstevel@tonic-gate packet_set_connection(sock_in, sock_out); 1649*0Sstevel@tonic-gate 1650*0Sstevel@tonic-gate remote_port = get_remote_port(); 1651*0Sstevel@tonic-gate remote_ip = get_remote_ipaddr(); 1652*0Sstevel@tonic-gate 1653*0Sstevel@tonic-gate #ifdef LIBWRAP 1654*0Sstevel@tonic-gate /* Check whether logins are denied from this host. */ 1655*0Sstevel@tonic-gate { 1656*0Sstevel@tonic-gate struct request_info req; 1657*0Sstevel@tonic-gate 1658*0Sstevel@tonic-gate (void) request_init(&req, RQ_DAEMON, __progname, RQ_FILE, sock_in, 0); 1659*0Sstevel@tonic-gate fromhost(&req); 1660*0Sstevel@tonic-gate 1661*0Sstevel@tonic-gate if (!hosts_access(&req)) { 1662*0Sstevel@tonic-gate debug("Connection refused by tcp wrapper"); 1663*0Sstevel@tonic-gate refuse(&req); 1664*0Sstevel@tonic-gate /* NOTREACHED */ 1665*0Sstevel@tonic-gate fatal("libwrap refuse returns"); 1666*0Sstevel@tonic-gate } 1667*0Sstevel@tonic-gate } 1668*0Sstevel@tonic-gate #endif /* LIBWRAP */ 1669*0Sstevel@tonic-gate 1670*0Sstevel@tonic-gate /* Log the connection. */ 1671*0Sstevel@tonic-gate verbose("Connection from %.500s port %d", remote_ip, remote_port); 1672*0Sstevel@tonic-gate 1673*0Sstevel@tonic-gate /* 1674*0Sstevel@tonic-gate * We don\'t want to listen forever unless the other side 1675*0Sstevel@tonic-gate * successfully authenticates itself. So we set up an alarm which is 1676*0Sstevel@tonic-gate * cleared after successful authentication. A limit of zero 1677*0Sstevel@tonic-gate * indicates no limit. Note that we don\'t set the alarm in debugging 1678*0Sstevel@tonic-gate * mode; it is just annoying to have the server exit just when you 1679*0Sstevel@tonic-gate * are about to discover the bug. 1680*0Sstevel@tonic-gate */ 1681*0Sstevel@tonic-gate (void) signal(SIGALRM, grace_alarm_handler); 1682*0Sstevel@tonic-gate if (!debug_flag) 1683*0Sstevel@tonic-gate (void) alarm(options.login_grace_time); 1684*0Sstevel@tonic-gate 1685*0Sstevel@tonic-gate sshd_exchange_identification(sock_in, sock_out); 1686*0Sstevel@tonic-gate /* 1687*0Sstevel@tonic-gate * Check that the connection comes from a privileged port. 1688*0Sstevel@tonic-gate * Rhosts-Authentication only makes sense from privileged 1689*0Sstevel@tonic-gate * programs. Of course, if the intruder has root access on his local 1690*0Sstevel@tonic-gate * machine, he can connect from any port. So do not use these 1691*0Sstevel@tonic-gate * authentication methods from machines that you do not trust. 1692*0Sstevel@tonic-gate */ 1693*0Sstevel@tonic-gate if (options.rhosts_authentication && 1694*0Sstevel@tonic-gate (remote_port >= IPPORT_RESERVED || 1695*0Sstevel@tonic-gate remote_port < IPPORT_RESERVED / 2)) { 1696*0Sstevel@tonic-gate debug("Rhosts Authentication disabled, " 1697*0Sstevel@tonic-gate "originating port %d not trusted.", remote_port); 1698*0Sstevel@tonic-gate options.rhosts_authentication = 0; 1699*0Sstevel@tonic-gate } 1700*0Sstevel@tonic-gate #if defined(KRB4) && !defined(KRB5) 1701*0Sstevel@tonic-gate if (!packet_connection_is_ipv4() && 1702*0Sstevel@tonic-gate options.kerberos_authentication) { 1703*0Sstevel@tonic-gate debug("Kerberos Authentication disabled, only available for IPv4."); 1704*0Sstevel@tonic-gate options.kerberos_authentication = 0; 1705*0Sstevel@tonic-gate } 1706*0Sstevel@tonic-gate #endif /* KRB4 && !KRB5 */ 1707*0Sstevel@tonic-gate #ifdef AFS 1708*0Sstevel@tonic-gate /* If machine has AFS, set process authentication group. */ 1709*0Sstevel@tonic-gate if (k_hasafs()) { 1710*0Sstevel@tonic-gate k_setpag(); 1711*0Sstevel@tonic-gate k_unlog(); 1712*0Sstevel@tonic-gate } 1713*0Sstevel@tonic-gate #endif /* AFS */ 1714*0Sstevel@tonic-gate 1715*0Sstevel@tonic-gate packet_set_nonblocking(); 1716*0Sstevel@tonic-gate 1717*0Sstevel@tonic-gate if (use_privsep) 1718*0Sstevel@tonic-gate if ((authctxt = privsep_preauth()) != NULL) 1719*0Sstevel@tonic-gate goto authenticated; 1720*0Sstevel@tonic-gate 1721*0Sstevel@tonic-gate /* perform the key exchange */ 1722*0Sstevel@tonic-gate /* authenticate user and start session */ 1723*0Sstevel@tonic-gate if (compat20) { 1724*0Sstevel@tonic-gate do_ssh2_kex(); 1725*0Sstevel@tonic-gate authctxt = do_authentication2(); 1726*0Sstevel@tonic-gate } else { 1727*0Sstevel@tonic-gate do_ssh1_kex(); 1728*0Sstevel@tonic-gate authctxt = do_authentication(); 1729*0Sstevel@tonic-gate } 1730*0Sstevel@tonic-gate 1731*0Sstevel@tonic-gate /* 1732*0Sstevel@tonic-gate * If we use privilege separation, the unprivileged child transfers 1733*0Sstevel@tonic-gate * the current keystate and exits 1734*0Sstevel@tonic-gate */ 1735*0Sstevel@tonic-gate if (use_privsep) { 1736*0Sstevel@tonic-gate mm_send_keystate(pmonitor); 1737*0Sstevel@tonic-gate exit(0); 1738*0Sstevel@tonic-gate } 1739*0Sstevel@tonic-gate 1740*0Sstevel@tonic-gate authenticated: 1741*0Sstevel@tonic-gate /* Authentication complete */ 1742*0Sstevel@tonic-gate (void) alarm(0); 1743*0Sstevel@tonic-gate 1744*0Sstevel@tonic-gate if (startup_pipe != -1) { 1745*0Sstevel@tonic-gate (void) close(startup_pipe); 1746*0Sstevel@tonic-gate startup_pipe = -1; 1747*0Sstevel@tonic-gate } 1748*0Sstevel@tonic-gate 1749*0Sstevel@tonic-gate /* 1750*0Sstevel@tonic-gate * In privilege separation, we fork another child and prepare 1751*0Sstevel@tonic-gate * file descriptor passing. 1752*0Sstevel@tonic-gate */ 1753*0Sstevel@tonic-gate if (use_privsep) { 1754*0Sstevel@tonic-gate privsep_postauth(authctxt); 1755*0Sstevel@tonic-gate /* the monitor process [priv] will not return */ 1756*0Sstevel@tonic-gate if (!compat20) 1757*0Sstevel@tonic-gate destroy_sensitive_data(); 1758*0Sstevel@tonic-gate } 1759*0Sstevel@tonic-gate 1760*0Sstevel@tonic-gate #ifdef ALTPRIVSEP 1761*0Sstevel@tonic-gate if ((aps_child = altprivsep_start_monitor(authctxt)) == -1) 1762*0Sstevel@tonic-gate fatal("Monitor could not be started."); 1763*0Sstevel@tonic-gate 1764*0Sstevel@tonic-gate if (aps_child > 0) { 1765*0Sstevel@tonic-gate 1766*0Sstevel@tonic-gate /* ALTPRIVSEP Monitor */ 1767*0Sstevel@tonic-gate 1768*0Sstevel@tonic-gate /* 1769*0Sstevel@tonic-gate * The ALTPRIVSEP monitor here does: 1770*0Sstevel@tonic-gate * 1771*0Sstevel@tonic-gate * - record keeping and auditing 1772*0Sstevel@tonic-gate * - PAM cleanup 1773*0Sstevel@tonic-gate */ 1774*0Sstevel@tonic-gate 1775*0Sstevel@tonic-gate /* 1776*0Sstevel@tonic-gate * If the monitor fatal()s it will audit/record a logout, so 1777*0Sstevel@tonic-gate * we'd better do something to really mean it: shutdown the 1778*0Sstevel@tonic-gate * socket but leave the child alone -- it's been disconnected 1779*0Sstevel@tonic-gate * and we hope it exits, but killing any pid from a privleged 1780*0Sstevel@tonic-gate * monitor could be dangerous. 1781*0Sstevel@tonic-gate * 1782*0Sstevel@tonic-gate * NOTE: Order matters -- these fatal cleanups must come before 1783*0Sstevel@tonic-gate * the audit logout fatal cleanup as these functions are called 1784*0Sstevel@tonic-gate * in in LIFO. 1785*0Sstevel@tonic-gate * 1786*0Sstevel@tonic-gate * NOTE: The monitor will packet_close(), which will close 1787*0Sstevel@tonic-gate * "newsock," so we dup() it. 1788*0Sstevel@tonic-gate */ 1789*0Sstevel@tonic-gate newsock = dup(newsock); 1790*0Sstevel@tonic-gate fatal_add_cleanup((void (*)(void *))altprivsep_shutdown_sock, 1791*0Sstevel@tonic-gate (void *)&newsock); 1792*0Sstevel@tonic-gate 1793*0Sstevel@tonic-gate if (compat20) { 1794*0Sstevel@tonic-gate debug3("Recording SSHv2 session login in wtmpx"); 1795*0Sstevel@tonic-gate record_login(getpid(), NULL, "sshd", authctxt->user); 1796*0Sstevel@tonic-gate } 1797*0Sstevel@tonic-gate 1798*0Sstevel@tonic-gate #ifdef HAVE_BSM 1799*0Sstevel@tonic-gate fatal_remove_cleanup( 1800*0Sstevel@tonic-gate (void (*)(void *))audit_failed_login_cleanup, 1801*0Sstevel@tonic-gate (void *)authctxt); 1802*0Sstevel@tonic-gate 1803*0Sstevel@tonic-gate audit_sshd_login(&ah, authctxt->pw->pw_uid, 1804*0Sstevel@tonic-gate authctxt->pw->pw_gid); 1805*0Sstevel@tonic-gate 1806*0Sstevel@tonic-gate fatal_add_cleanup((void (*)(void *))audit_sshd_logout, 1807*0Sstevel@tonic-gate (void *)&ah); 1808*0Sstevel@tonic-gate #endif /* HAVE_BSM */ 1809*0Sstevel@tonic-gate 1810*0Sstevel@tonic-gate #ifdef GSSAPI 1811*0Sstevel@tonic-gate fatal_add_cleanup((void (*)(void *))ssh_gssapi_cleanup_creds, 1812*0Sstevel@tonic-gate (void *)&xxx_gssctxt); 1813*0Sstevel@tonic-gate #endif /* GSSAPI */ 1814*0Sstevel@tonic-gate 1815*0Sstevel@tonic-gate altprivsep_do_monitor(authctxt, aps_child); 1816*0Sstevel@tonic-gate 1817*0Sstevel@tonic-gate /* If we got here the connection is dead. */ 1818*0Sstevel@tonic-gate fatal_remove_cleanup((void (*)(void *))altprivsep_shutdown_sock, 1819*0Sstevel@tonic-gate (void *)&newsock); 1820*0Sstevel@tonic-gate 1821*0Sstevel@tonic-gate if (compat20) { 1822*0Sstevel@tonic-gate debug3("Recording SSHv2 session logout in wtmpx"); 1823*0Sstevel@tonic-gate record_logout(getpid(), NULL, "sshd", authctxt->user); 1824*0Sstevel@tonic-gate } 1825*0Sstevel@tonic-gate 1826*0Sstevel@tonic-gate /* 1827*0Sstevel@tonic-gate * Make sure the socket is closed. The monitor can't call 1828*0Sstevel@tonic-gate * packet_close here as it's done a packet_set_connection() 1829*0Sstevel@tonic-gate * with the pipe to the child instead of the socket. 1830*0Sstevel@tonic-gate */ 1831*0Sstevel@tonic-gate (void) shutdown(newsock, SHUT_RDWR); 1832*0Sstevel@tonic-gate 1833*0Sstevel@tonic-gate #ifdef GSSAPI 1834*0Sstevel@tonic-gate fatal_remove_cleanup((void (*)(void *))ssh_gssapi_cleanup_creds, 1835*0Sstevel@tonic-gate &xxx_gssctxt); 1836*0Sstevel@tonic-gate ssh_gssapi_cleanup_creds(xxx_gssctxt); 1837*0Sstevel@tonic-gate ssh_gssapi_server_mechs(NULL); /* release cached mechs list */ 1838*0Sstevel@tonic-gate #endif /* GSSAPI */ 1839*0Sstevel@tonic-gate 1840*0Sstevel@tonic-gate #ifdef HAVE_BSM 1841*0Sstevel@tonic-gate fatal_remove_cleanup((void (*)(void *))audit_sshd_logout, (void *)&ah); 1842*0Sstevel@tonic-gate audit_sshd_logout(&ah); 1843*0Sstevel@tonic-gate #endif /* HAVE_BSM */ 1844*0Sstevel@tonic-gate 1845*0Sstevel@tonic-gate #ifdef USE_PAM 1846*0Sstevel@tonic-gate finish_pam(authctxt); 1847*0Sstevel@tonic-gate #endif /* USE_PAM */ 1848*0Sstevel@tonic-gate 1849*0Sstevel@tonic-gate return (ret); 1850*0Sstevel@tonic-gate 1851*0Sstevel@tonic-gate /* NOTREACHED */ 1852*0Sstevel@tonic-gate 1853*0Sstevel@tonic-gate } else { 1854*0Sstevel@tonic-gate 1855*0Sstevel@tonic-gate /* ALTPRIVSEP Child */ 1856*0Sstevel@tonic-gate 1857*0Sstevel@tonic-gate /* 1858*0Sstevel@tonic-gate * Drop privileges, access to privileged resources. 1859*0Sstevel@tonic-gate * 1860*0Sstevel@tonic-gate * Destroy private host keys, if any. 1861*0Sstevel@tonic-gate * 1862*0Sstevel@tonic-gate * No need to release any GSS credentials -- sshd only acquires 1863*0Sstevel@tonic-gate * creds to determine what mechs it can negotiate then releases 1864*0Sstevel@tonic-gate * them right away and uses GSS_C_NO_CREDENTIAL to accept 1865*0Sstevel@tonic-gate * contexts. 1866*0Sstevel@tonic-gate */ 1867*0Sstevel@tonic-gate debug2("Unprivileged server process dropping privileges"); 1868*0Sstevel@tonic-gate permanently_set_uid(authctxt->pw); 1869*0Sstevel@tonic-gate destroy_sensitive_data(); 1870*0Sstevel@tonic-gate ssh_gssapi_server_mechs(NULL); /* release cached mechs list */ 1871*0Sstevel@tonic-gate 1872*0Sstevel@tonic-gate /* Logged-in session. */ 1873*0Sstevel@tonic-gate do_authenticated(authctxt); 1874*0Sstevel@tonic-gate 1875*0Sstevel@tonic-gate /* The connection has been terminated. */ 1876*0Sstevel@tonic-gate verbose("Closing connection to %.100s", remote_ip); 1877*0Sstevel@tonic-gate 1878*0Sstevel@tonic-gate packet_close(); 1879*0Sstevel@tonic-gate 1880*0Sstevel@tonic-gate return (0); 1881*0Sstevel@tonic-gate 1882*0Sstevel@tonic-gate /* NOTREACHED */ 1883*0Sstevel@tonic-gate } 1884*0Sstevel@tonic-gate 1885*0Sstevel@tonic-gate #else /* ALTPRIVSEP */ 1886*0Sstevel@tonic-gate 1887*0Sstevel@tonic-gate if (compat20) { 1888*0Sstevel@tonic-gate debug3("Recording SSHv2 session login in wtmpx"); 1889*0Sstevel@tonic-gate record_login(getpid(), NULL, "sshd", authctxt->user); 1890*0Sstevel@tonic-gate } 1891*0Sstevel@tonic-gate 1892*0Sstevel@tonic-gate #ifdef HAVE_BSM 1893*0Sstevel@tonic-gate fatal_remove_cleanup( 1894*0Sstevel@tonic-gate (void (*)(void *))audit_failed_login_cleanup, 1895*0Sstevel@tonic-gate (void *)authctxt); 1896*0Sstevel@tonic-gate 1897*0Sstevel@tonic-gate audit_sshd_login(&ah, authctxt->pw->pw_uid, 1898*0Sstevel@tonic-gate authctxt->pw->pw_gid); 1899*0Sstevel@tonic-gate 1900*0Sstevel@tonic-gate fatal_add_cleanup((void (*)(void *))audit_sshd_logout, 1901*0Sstevel@tonic-gate (void *)&ah); 1902*0Sstevel@tonic-gate #endif /* HAVE_BSM */ 1903*0Sstevel@tonic-gate 1904*0Sstevel@tonic-gate #ifdef GSSAPI 1905*0Sstevel@tonic-gate fatal_add_cleanup((void (*)(void *))ssh_gssapi_cleanup_creds, 1906*0Sstevel@tonic-gate (void *)&xxx_gssctxt); 1907*0Sstevel@tonic-gate #endif /* GSSAPI */ 1908*0Sstevel@tonic-gate 1909*0Sstevel@tonic-gate /* Perform session preparation. */ 1910*0Sstevel@tonic-gate do_authenticated(authctxt); 1911*0Sstevel@tonic-gate 1912*0Sstevel@tonic-gate /* XXX - Add PRIVSEP() macro */ 1913*0Sstevel@tonic-gate if (compat20) { 1914*0Sstevel@tonic-gate debug3("Recording SSHv2 session logout in wtmpx"); 1915*0Sstevel@tonic-gate record_logout(getpid(), NULL, "sshd", authctxt->user); 1916*0Sstevel@tonic-gate } 1917*0Sstevel@tonic-gate 1918*0Sstevel@tonic-gate #ifdef GSSAPI 1919*0Sstevel@tonic-gate fatal_remove_cleanup((void (*)(void *))ssh_gssapi_cleanup_creds, 1920*0Sstevel@tonic-gate &xxx_gssctxt); 1921*0Sstevel@tonic-gate ssh_gssapi_cleanup_creds(xxx_gssctxt); 1922*0Sstevel@tonic-gate ssh_gssapi_server_mechs(NULL); /* release cached server mechs */ 1923*0Sstevel@tonic-gate #endif /* GSSAPI */ 1924*0Sstevel@tonic-gate 1925*0Sstevel@tonic-gate #ifdef HAVE_BSM 1926*0Sstevel@tonic-gate fatal_remove_cleanup((void (*)(void *))audit_sshd_logout, (void *)&ah); 1927*0Sstevel@tonic-gate audit_sshd_logout(&ah); 1928*0Sstevel@tonic-gate #endif /* HAVE_BSM */ 1929*0Sstevel@tonic-gate 1930*0Sstevel@tonic-gate #ifdef USE_PAM 1931*0Sstevel@tonic-gate finish_pam(authctxt); 1932*0Sstevel@tonic-gate #endif /* USE_PAM */ 1933*0Sstevel@tonic-gate 1934*0Sstevel@tonic-gate /* The connection has been terminated. */ 1935*0Sstevel@tonic-gate verbose("Closing connection to %.100s", remote_ip); 1936*0Sstevel@tonic-gate 1937*0Sstevel@tonic-gate packet_close(); 1938*0Sstevel@tonic-gate 1939*0Sstevel@tonic-gate if (use_privsep) 1940*0Sstevel@tonic-gate mm_terminate(); 1941*0Sstevel@tonic-gate 1942*0Sstevel@tonic-gate return (0); 1943*0Sstevel@tonic-gate #endif /* ALTPRIVSEP */ 1944*0Sstevel@tonic-gate } 1945*0Sstevel@tonic-gate 1946*0Sstevel@tonic-gate /* 1947*0Sstevel@tonic-gate * Decrypt session_key_int using our private server key and private host key 1948*0Sstevel@tonic-gate * (key with larger modulus first). 1949*0Sstevel@tonic-gate */ 1950*0Sstevel@tonic-gate int 1951*0Sstevel@tonic-gate ssh1_session_key(BIGNUM *session_key_int) 1952*0Sstevel@tonic-gate { 1953*0Sstevel@tonic-gate int rsafail = 0; 1954*0Sstevel@tonic-gate 1955*0Sstevel@tonic-gate if (BN_cmp(sensitive_data.server_key->rsa->n, sensitive_data.ssh1_host_key->rsa->n) > 0) { 1956*0Sstevel@tonic-gate /* Server key has bigger modulus. */ 1957*0Sstevel@tonic-gate if (BN_num_bits(sensitive_data.server_key->rsa->n) < 1958*0Sstevel@tonic-gate BN_num_bits(sensitive_data.ssh1_host_key->rsa->n) + SSH_KEY_BITS_RESERVED) { 1959*0Sstevel@tonic-gate fatal("do_connection: %s: server_key %d < host_key %d + SSH_KEY_BITS_RESERVED %d", 1960*0Sstevel@tonic-gate get_remote_ipaddr(), 1961*0Sstevel@tonic-gate BN_num_bits(sensitive_data.server_key->rsa->n), 1962*0Sstevel@tonic-gate BN_num_bits(sensitive_data.ssh1_host_key->rsa->n), 1963*0Sstevel@tonic-gate SSH_KEY_BITS_RESERVED); 1964*0Sstevel@tonic-gate } 1965*0Sstevel@tonic-gate if (rsa_private_decrypt(session_key_int, session_key_int, 1966*0Sstevel@tonic-gate sensitive_data.server_key->rsa) <= 0) 1967*0Sstevel@tonic-gate rsafail++; 1968*0Sstevel@tonic-gate if (rsa_private_decrypt(session_key_int, session_key_int, 1969*0Sstevel@tonic-gate sensitive_data.ssh1_host_key->rsa) <= 0) 1970*0Sstevel@tonic-gate rsafail++; 1971*0Sstevel@tonic-gate } else { 1972*0Sstevel@tonic-gate /* Host key has bigger modulus (or they are equal). */ 1973*0Sstevel@tonic-gate if (BN_num_bits(sensitive_data.ssh1_host_key->rsa->n) < 1974*0Sstevel@tonic-gate BN_num_bits(sensitive_data.server_key->rsa->n) + SSH_KEY_BITS_RESERVED) { 1975*0Sstevel@tonic-gate fatal("do_connection: %s: host_key %d < server_key %d + SSH_KEY_BITS_RESERVED %d", 1976*0Sstevel@tonic-gate get_remote_ipaddr(), 1977*0Sstevel@tonic-gate BN_num_bits(sensitive_data.ssh1_host_key->rsa->n), 1978*0Sstevel@tonic-gate BN_num_bits(sensitive_data.server_key->rsa->n), 1979*0Sstevel@tonic-gate SSH_KEY_BITS_RESERVED); 1980*0Sstevel@tonic-gate } 1981*0Sstevel@tonic-gate if (rsa_private_decrypt(session_key_int, session_key_int, 1982*0Sstevel@tonic-gate sensitive_data.ssh1_host_key->rsa) < 0) 1983*0Sstevel@tonic-gate rsafail++; 1984*0Sstevel@tonic-gate if (rsa_private_decrypt(session_key_int, session_key_int, 1985*0Sstevel@tonic-gate sensitive_data.server_key->rsa) < 0) 1986*0Sstevel@tonic-gate rsafail++; 1987*0Sstevel@tonic-gate } 1988*0Sstevel@tonic-gate return (rsafail); 1989*0Sstevel@tonic-gate } 1990*0Sstevel@tonic-gate /* 1991*0Sstevel@tonic-gate * SSH1 key exchange 1992*0Sstevel@tonic-gate */ 1993*0Sstevel@tonic-gate static void 1994*0Sstevel@tonic-gate do_ssh1_kex(void) 1995*0Sstevel@tonic-gate { 1996*0Sstevel@tonic-gate int i, len; 1997*0Sstevel@tonic-gate int rsafail = 0; 1998*0Sstevel@tonic-gate BIGNUM *session_key_int; 1999*0Sstevel@tonic-gate u_char session_key[SSH_SESSION_KEY_LENGTH]; 2000*0Sstevel@tonic-gate u_char cookie[8]; 2001*0Sstevel@tonic-gate u_int cipher_type, auth_mask, protocol_flags; 2002*0Sstevel@tonic-gate u_int32_t rnd = 0; 2003*0Sstevel@tonic-gate 2004*0Sstevel@tonic-gate /* 2005*0Sstevel@tonic-gate * Generate check bytes that the client must send back in the user 2006*0Sstevel@tonic-gate * packet in order for it to be accepted; this is used to defy ip 2007*0Sstevel@tonic-gate * spoofing attacks. Note that this only works against somebody 2008*0Sstevel@tonic-gate * doing IP spoofing from a remote machine; any machine on the local 2009*0Sstevel@tonic-gate * network can still see outgoing packets and catch the random 2010*0Sstevel@tonic-gate * cookie. This only affects rhosts authentication, and this is one 2011*0Sstevel@tonic-gate * of the reasons why it is inherently insecure. 2012*0Sstevel@tonic-gate */ 2013*0Sstevel@tonic-gate for (i = 0; i < 8; i++) { 2014*0Sstevel@tonic-gate if (i % 4 == 0) 2015*0Sstevel@tonic-gate rnd = arc4random(); 2016*0Sstevel@tonic-gate cookie[i] = rnd & 0xff; 2017*0Sstevel@tonic-gate rnd >>= 8; 2018*0Sstevel@tonic-gate } 2019*0Sstevel@tonic-gate 2020*0Sstevel@tonic-gate /* 2021*0Sstevel@tonic-gate * Send our public key. We include in the packet 64 bits of random 2022*0Sstevel@tonic-gate * data that must be matched in the reply in order to prevent IP 2023*0Sstevel@tonic-gate * spoofing. 2024*0Sstevel@tonic-gate */ 2025*0Sstevel@tonic-gate packet_start(SSH_SMSG_PUBLIC_KEY); 2026*0Sstevel@tonic-gate for (i = 0; i < 8; i++) 2027*0Sstevel@tonic-gate packet_put_char(cookie[i]); 2028*0Sstevel@tonic-gate 2029*0Sstevel@tonic-gate /* Store our public server RSA key. */ 2030*0Sstevel@tonic-gate packet_put_int(BN_num_bits(sensitive_data.server_key->rsa->n)); 2031*0Sstevel@tonic-gate packet_put_bignum(sensitive_data.server_key->rsa->e); 2032*0Sstevel@tonic-gate packet_put_bignum(sensitive_data.server_key->rsa->n); 2033*0Sstevel@tonic-gate 2034*0Sstevel@tonic-gate /* Store our public host RSA key. */ 2035*0Sstevel@tonic-gate packet_put_int(BN_num_bits(sensitive_data.ssh1_host_key->rsa->n)); 2036*0Sstevel@tonic-gate packet_put_bignum(sensitive_data.ssh1_host_key->rsa->e); 2037*0Sstevel@tonic-gate packet_put_bignum(sensitive_data.ssh1_host_key->rsa->n); 2038*0Sstevel@tonic-gate 2039*0Sstevel@tonic-gate /* Put protocol flags. */ 2040*0Sstevel@tonic-gate packet_put_int(SSH_PROTOFLAG_HOST_IN_FWD_OPEN); 2041*0Sstevel@tonic-gate 2042*0Sstevel@tonic-gate /* Declare which ciphers we support. */ 2043*0Sstevel@tonic-gate packet_put_int(cipher_mask_ssh1(0)); 2044*0Sstevel@tonic-gate 2045*0Sstevel@tonic-gate /* Declare supported authentication types. */ 2046*0Sstevel@tonic-gate auth_mask = 0; 2047*0Sstevel@tonic-gate if (options.rhosts_authentication) 2048*0Sstevel@tonic-gate auth_mask |= 1 << SSH_AUTH_RHOSTS; 2049*0Sstevel@tonic-gate if (options.rhosts_rsa_authentication) 2050*0Sstevel@tonic-gate auth_mask |= 1 << SSH_AUTH_RHOSTS_RSA; 2051*0Sstevel@tonic-gate if (options.rsa_authentication) 2052*0Sstevel@tonic-gate auth_mask |= 1 << SSH_AUTH_RSA; 2053*0Sstevel@tonic-gate #if defined(KRB4) || defined(KRB5) 2054*0Sstevel@tonic-gate if (options.kerberos_authentication) 2055*0Sstevel@tonic-gate auth_mask |= 1 << SSH_AUTH_KERBEROS; 2056*0Sstevel@tonic-gate #endif 2057*0Sstevel@tonic-gate #if defined(AFS) || defined(KRB5) 2058*0Sstevel@tonic-gate if (options.kerberos_tgt_passing) 2059*0Sstevel@tonic-gate auth_mask |= 1 << SSH_PASS_KERBEROS_TGT; 2060*0Sstevel@tonic-gate #endif 2061*0Sstevel@tonic-gate #ifdef AFS 2062*0Sstevel@tonic-gate if (options.afs_token_passing) 2063*0Sstevel@tonic-gate auth_mask |= 1 << SSH_PASS_AFS_TOKEN; 2064*0Sstevel@tonic-gate #endif 2065*0Sstevel@tonic-gate if (options.challenge_response_authentication == 1) 2066*0Sstevel@tonic-gate auth_mask |= 1 << SSH_AUTH_TIS; 2067*0Sstevel@tonic-gate if (options.password_authentication) 2068*0Sstevel@tonic-gate auth_mask |= 1 << SSH_AUTH_PASSWORD; 2069*0Sstevel@tonic-gate packet_put_int(auth_mask); 2070*0Sstevel@tonic-gate 2071*0Sstevel@tonic-gate /* Send the packet and wait for it to be sent. */ 2072*0Sstevel@tonic-gate packet_send(); 2073*0Sstevel@tonic-gate packet_write_wait(); 2074*0Sstevel@tonic-gate 2075*0Sstevel@tonic-gate debug("Sent %d bit server key and %d bit host key.", 2076*0Sstevel@tonic-gate BN_num_bits(sensitive_data.server_key->rsa->n), 2077*0Sstevel@tonic-gate BN_num_bits(sensitive_data.ssh1_host_key->rsa->n)); 2078*0Sstevel@tonic-gate 2079*0Sstevel@tonic-gate /* Read clients reply (cipher type and session key). */ 2080*0Sstevel@tonic-gate packet_read_expect(SSH_CMSG_SESSION_KEY); 2081*0Sstevel@tonic-gate 2082*0Sstevel@tonic-gate /* Get cipher type and check whether we accept this. */ 2083*0Sstevel@tonic-gate cipher_type = packet_get_char(); 2084*0Sstevel@tonic-gate 2085*0Sstevel@tonic-gate if (!(cipher_mask_ssh1(0) & (1 << cipher_type))) { 2086*0Sstevel@tonic-gate packet_disconnect("Warning: client selects unsupported cipher."); 2087*0Sstevel@tonic-gate } 2088*0Sstevel@tonic-gate 2089*0Sstevel@tonic-gate /* Get check bytes from the packet. These must match those we 2090*0Sstevel@tonic-gate sent earlier with the public key packet. */ 2091*0Sstevel@tonic-gate for (i = 0; i < 8; i++) { 2092*0Sstevel@tonic-gate if (cookie[i] != packet_get_char()) { 2093*0Sstevel@tonic-gate packet_disconnect("IP Spoofing check bytes do not match."); 2094*0Sstevel@tonic-gate } 2095*0Sstevel@tonic-gate } 2096*0Sstevel@tonic-gate 2097*0Sstevel@tonic-gate debug("Encryption type: %.200s", cipher_name(cipher_type)); 2098*0Sstevel@tonic-gate 2099*0Sstevel@tonic-gate /* Get the encrypted integer. */ 2100*0Sstevel@tonic-gate if ((session_key_int = BN_new()) == NULL) 2101*0Sstevel@tonic-gate fatal("do_ssh1_kex: BN_new failed"); 2102*0Sstevel@tonic-gate packet_get_bignum(session_key_int); 2103*0Sstevel@tonic-gate 2104*0Sstevel@tonic-gate protocol_flags = packet_get_int(); 2105*0Sstevel@tonic-gate packet_set_protocol_flags(protocol_flags); 2106*0Sstevel@tonic-gate packet_check_eom(); 2107*0Sstevel@tonic-gate 2108*0Sstevel@tonic-gate /* Decrypt session_key_int using host/server keys */ 2109*0Sstevel@tonic-gate rsafail = PRIVSEP(ssh1_session_key(session_key_int)); 2110*0Sstevel@tonic-gate 2111*0Sstevel@tonic-gate /* 2112*0Sstevel@tonic-gate * Extract session key from the decrypted integer. The key is in the 2113*0Sstevel@tonic-gate * least significant 256 bits of the integer; the first byte of the 2114*0Sstevel@tonic-gate * key is in the highest bits. 2115*0Sstevel@tonic-gate */ 2116*0Sstevel@tonic-gate if (!rsafail) { 2117*0Sstevel@tonic-gate (void) BN_mask_bits(session_key_int, sizeof(session_key) * 8); 2118*0Sstevel@tonic-gate len = BN_num_bytes(session_key_int); 2119*0Sstevel@tonic-gate if (len < 0 || len > sizeof(session_key)) { 2120*0Sstevel@tonic-gate error("do_connection: bad session key len from %s: " 2121*0Sstevel@tonic-gate "session_key_int %d > sizeof(session_key) %lu", 2122*0Sstevel@tonic-gate get_remote_ipaddr(), len, (u_long)sizeof(session_key)); 2123*0Sstevel@tonic-gate rsafail++; 2124*0Sstevel@tonic-gate } else { 2125*0Sstevel@tonic-gate (void) memset(session_key, 0, sizeof(session_key)); 2126*0Sstevel@tonic-gate (void) BN_bn2bin(session_key_int, 2127*0Sstevel@tonic-gate session_key + sizeof(session_key) - len); 2128*0Sstevel@tonic-gate 2129*0Sstevel@tonic-gate compute_session_id(session_id, cookie, 2130*0Sstevel@tonic-gate sensitive_data.ssh1_host_key->rsa->n, 2131*0Sstevel@tonic-gate sensitive_data.server_key->rsa->n); 2132*0Sstevel@tonic-gate /* 2133*0Sstevel@tonic-gate * Xor the first 16 bytes of the session key with the 2134*0Sstevel@tonic-gate * session id. 2135*0Sstevel@tonic-gate */ 2136*0Sstevel@tonic-gate for (i = 0; i < 16; i++) 2137*0Sstevel@tonic-gate session_key[i] ^= session_id[i]; 2138*0Sstevel@tonic-gate } 2139*0Sstevel@tonic-gate } 2140*0Sstevel@tonic-gate if (rsafail) { 2141*0Sstevel@tonic-gate int bytes = BN_num_bytes(session_key_int); 2142*0Sstevel@tonic-gate u_char *buf = xmalloc(bytes); 2143*0Sstevel@tonic-gate MD5_CTX md; 2144*0Sstevel@tonic-gate 2145*0Sstevel@tonic-gate log("do_connection: generating a fake encryption key"); 2146*0Sstevel@tonic-gate (void) BN_bn2bin(session_key_int, buf); 2147*0Sstevel@tonic-gate MD5_Init(&md); 2148*0Sstevel@tonic-gate MD5_Update(&md, buf, bytes); 2149*0Sstevel@tonic-gate MD5_Update(&md, sensitive_data.ssh1_cookie, SSH_SESSION_KEY_LENGTH); 2150*0Sstevel@tonic-gate MD5_Final(session_key, &md); 2151*0Sstevel@tonic-gate MD5_Init(&md); 2152*0Sstevel@tonic-gate MD5_Update(&md, session_key, 16); 2153*0Sstevel@tonic-gate MD5_Update(&md, buf, bytes); 2154*0Sstevel@tonic-gate MD5_Update(&md, sensitive_data.ssh1_cookie, SSH_SESSION_KEY_LENGTH); 2155*0Sstevel@tonic-gate MD5_Final(session_key + 16, &md); 2156*0Sstevel@tonic-gate (void) memset(buf, 0, bytes); 2157*0Sstevel@tonic-gate xfree(buf); 2158*0Sstevel@tonic-gate for (i = 0; i < 16; i++) 2159*0Sstevel@tonic-gate session_id[i] = session_key[i] ^ session_key[i + 16]; 2160*0Sstevel@tonic-gate } 2161*0Sstevel@tonic-gate /* Destroy the private and public keys. No longer. */ 2162*0Sstevel@tonic-gate destroy_sensitive_data(); 2163*0Sstevel@tonic-gate 2164*0Sstevel@tonic-gate if (use_privsep) 2165*0Sstevel@tonic-gate mm_ssh1_session_id(session_id); 2166*0Sstevel@tonic-gate 2167*0Sstevel@tonic-gate /* Destroy the decrypted integer. It is no longer needed. */ 2168*0Sstevel@tonic-gate BN_clear_free(session_key_int); 2169*0Sstevel@tonic-gate 2170*0Sstevel@tonic-gate /* Set the session key. From this on all communications will be encrypted. */ 2171*0Sstevel@tonic-gate packet_set_encryption_key(session_key, SSH_SESSION_KEY_LENGTH, cipher_type); 2172*0Sstevel@tonic-gate 2173*0Sstevel@tonic-gate /* Destroy our copy of the session key. It is no longer needed. */ 2174*0Sstevel@tonic-gate (void) memset(session_key, 0, sizeof(session_key)); 2175*0Sstevel@tonic-gate 2176*0Sstevel@tonic-gate debug("Received session key; encryption turned on."); 2177*0Sstevel@tonic-gate 2178*0Sstevel@tonic-gate /* Send an acknowledgment packet. Note that this packet is sent encrypted. */ 2179*0Sstevel@tonic-gate packet_start(SSH_SMSG_SUCCESS); 2180*0Sstevel@tonic-gate packet_send(); 2181*0Sstevel@tonic-gate packet_write_wait(); 2182*0Sstevel@tonic-gate } 2183*0Sstevel@tonic-gate 2184*0Sstevel@tonic-gate /* 2185*0Sstevel@tonic-gate * SSH2 key exchange: diffie-hellman-group1-sha1 2186*0Sstevel@tonic-gate */ 2187*0Sstevel@tonic-gate static void 2188*0Sstevel@tonic-gate do_ssh2_kex(void) 2189*0Sstevel@tonic-gate { 2190*0Sstevel@tonic-gate Kex *kex; 2191*0Sstevel@tonic-gate Kex_hook_func kex_hook = NULL; 2192*0Sstevel@tonic-gate char **locales; 2193*0Sstevel@tonic-gate 2194*0Sstevel@tonic-gate if (options.ciphers != NULL) { 2195*0Sstevel@tonic-gate myproposal[PROPOSAL_ENC_ALGS_CTOS] = 2196*0Sstevel@tonic-gate myproposal[PROPOSAL_ENC_ALGS_STOC] = options.ciphers; 2197*0Sstevel@tonic-gate } 2198*0Sstevel@tonic-gate myproposal[PROPOSAL_ENC_ALGS_CTOS] = 2199*0Sstevel@tonic-gate compat_cipher_proposal(myproposal[PROPOSAL_ENC_ALGS_CTOS]); 2200*0Sstevel@tonic-gate myproposal[PROPOSAL_ENC_ALGS_STOC] = 2201*0Sstevel@tonic-gate compat_cipher_proposal(myproposal[PROPOSAL_ENC_ALGS_STOC]); 2202*0Sstevel@tonic-gate 2203*0Sstevel@tonic-gate if (options.macs != NULL) { 2204*0Sstevel@tonic-gate myproposal[PROPOSAL_MAC_ALGS_CTOS] = 2205*0Sstevel@tonic-gate myproposal[PROPOSAL_MAC_ALGS_STOC] = options.macs; 2206*0Sstevel@tonic-gate } 2207*0Sstevel@tonic-gate if (!options.compression) { 2208*0Sstevel@tonic-gate myproposal[PROPOSAL_COMP_ALGS_CTOS] = 2209*0Sstevel@tonic-gate myproposal[PROPOSAL_COMP_ALGS_STOC] = "none"; 2210*0Sstevel@tonic-gate } 2211*0Sstevel@tonic-gate 2212*0Sstevel@tonic-gate /* 2213*0Sstevel@tonic-gate * Prepare kex algs / hostkey algs (excluding GSS, which is 2214*0Sstevel@tonic-gate * handled in the kex hook. 2215*0Sstevel@tonic-gate * 2216*0Sstevel@tonic-gate * XXX This should probably move to the kex hook as well, where 2217*0Sstevel@tonic-gate * all non-constant kex offer material belongs. 2218*0Sstevel@tonic-gate */ 2219*0Sstevel@tonic-gate myproposal[PROPOSAL_SERVER_HOST_KEY_ALGS] = list_hostkey_types(); 2220*0Sstevel@tonic-gate 2221*0Sstevel@tonic-gate /* If we have no host key algs we can't offer KEXDH/KEX_DH_GEX */ 2222*0Sstevel@tonic-gate if (myproposal[PROPOSAL_SERVER_HOST_KEY_ALGS] == NULL || 2223*0Sstevel@tonic-gate *myproposal[PROPOSAL_SERVER_HOST_KEY_ALGS] == '\0') 2224*0Sstevel@tonic-gate myproposal[PROPOSAL_KEX_ALGS] = ""; 2225*0Sstevel@tonic-gate 2226*0Sstevel@tonic-gate if ((locales = g11n_getlocales()) != NULL) { 2227*0Sstevel@tonic-gate /* Solaris 9 SSH expects a list of locales */ 2228*0Sstevel@tonic-gate if (datafellows & SSH_BUG_LOCALES_NOT_LANGTAGS) 2229*0Sstevel@tonic-gate myproposal[PROPOSAL_LANG_STOC] = xjoin(locales, ','); 2230*0Sstevel@tonic-gate else 2231*0Sstevel@tonic-gate myproposal[PROPOSAL_LANG_STOC] = 2232*0Sstevel@tonic-gate g11n_locales2langs(locales); 2233*0Sstevel@tonic-gate } 2234*0Sstevel@tonic-gate 2235*0Sstevel@tonic-gate if ((myproposal[PROPOSAL_LANG_STOC] != NULL) || 2236*0Sstevel@tonic-gate (strcmp(myproposal[PROPOSAL_LANG_STOC], "")) != 0) 2237*0Sstevel@tonic-gate myproposal[PROPOSAL_LANG_CTOS] = 2238*0Sstevel@tonic-gate xstrdup(myproposal[PROPOSAL_LANG_STOC]); 2239*0Sstevel@tonic-gate 2240*0Sstevel@tonic-gate #ifdef GSSAPI 2241*0Sstevel@tonic-gate if (options.gss_keyex) 2242*0Sstevel@tonic-gate kex_hook = ssh_gssapi_server_kex_hook; 2243*0Sstevel@tonic-gate #endif /* GSSAPI */ 2244*0Sstevel@tonic-gate 2245*0Sstevel@tonic-gate /* start key exchange */ 2246*0Sstevel@tonic-gate kex = kex_setup(NULL, myproposal, kex_hook); 2247*0Sstevel@tonic-gate kex->kex[KEX_DH_GRP1_SHA1] = kexdh_server; 2248*0Sstevel@tonic-gate kex->kex[KEX_DH_GEX_SHA1] = kexgex_server; 2249*0Sstevel@tonic-gate #ifdef GSSAPI 2250*0Sstevel@tonic-gate kex->kex[KEX_GSS_GRP1_SHA1] = kexgss_server; 2251*0Sstevel@tonic-gate #endif /* GSSAPI */ 2252*0Sstevel@tonic-gate kex->server = 1; 2253*0Sstevel@tonic-gate kex->client_version_string=client_version_string; 2254*0Sstevel@tonic-gate kex->server_version_string=server_version_string; 2255*0Sstevel@tonic-gate kex->load_host_key=&get_hostkey_by_type; 2256*0Sstevel@tonic-gate kex->host_key_index=&get_hostkey_index; 2257*0Sstevel@tonic-gate 2258*0Sstevel@tonic-gate xxx_kex = kex; 2259*0Sstevel@tonic-gate 2260*0Sstevel@tonic-gate dispatch_run(DISPATCH_BLOCK, &kex->done, kex); 2261*0Sstevel@tonic-gate 2262*0Sstevel@tonic-gate if (kex->name) { 2263*0Sstevel@tonic-gate xfree(kex->name); 2264*0Sstevel@tonic-gate kex->name = NULL; 2265*0Sstevel@tonic-gate } 2266*0Sstevel@tonic-gate session_id2 = kex->session_id; 2267*0Sstevel@tonic-gate session_id2_len = kex->session_id_len; 2268*0Sstevel@tonic-gate 2269*0Sstevel@tonic-gate #ifdef DEBUG_KEXDH 2270*0Sstevel@tonic-gate /* send 1st encrypted/maced/compressed message */ 2271*0Sstevel@tonic-gate packet_start(SSH2_MSG_IGNORE); 2272*0Sstevel@tonic-gate packet_put_cstring("markus"); 2273*0Sstevel@tonic-gate packet_send(); 2274*0Sstevel@tonic-gate packet_write_wait(); 2275*0Sstevel@tonic-gate #endif 2276*0Sstevel@tonic-gate debug("KEX done"); 2277*0Sstevel@tonic-gate } 2278