⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 sshd.c

📁 C++编写
💻 C
📖 第 1 页 / 共 4 页
字号:
/* * Author: Tatu Ylonen <ylo@cs.hut.fi> * Copyright (c) 1995 Tatu Ylonen <ylo@cs.hut.fi>, Espoo, Finland *                    All rights reserved * This program is the ssh daemon.  It listens for connections from clients, * and performs authentication, executes use commands or shell, and forwards * information to/from the application to the user client over an encrypted * connection.  This can also handle forwarding of X11, TCP/IP, and * authentication agent connections. * * As far as I am concerned, the code I have written for this software * can be used freely for any purpose.  Any derived versions of this * software must be clearly marked as such, and if the derived work is * incompatible with the protocol description in the RFC file, it must be * called by a name other than "ssh" or "Secure Shell". * * SSH2 implementation: * Privilege Separation: * * Copyright (c) 2000, 2001, 2002 Markus Friedl.  All rights reserved. * Copyright (c) 2002 Niels Provos.  All rights reserved. * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions * are met: * 1. Redistributions of source code must retain the above copyright *    notice, this list of conditions and the following disclaimer. * 2. Redistributions in binary form must reproduce the above copyright *    notice, this list of conditions and the following disclaimer in the *    documentation and/or other materials provided with the distribution. * * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. */#include "includes.h"RCSID("$OpenBSD: sshd.c,v 1.263 2003/02/16 17:09:57 markus Exp $");#include <openssl/dh.h>#include <openssl/bn.h>#include <openssl/md5.h>#include <openssl/rand.h>#include "ssh.h"#include "ssh1.h"#include "ssh2.h"#include "xmalloc.h"#include "rsa.h"#include "sshpty.h"#include "packet.h"#include "mpaux.h"#include "log.h"#include "servconf.h"#include "uidswap.h"#include "compat.h"#include "buffer.h"#include "cipher.h"#include "kex.h"#include "key.h"#include "dh.h"#include "myproposal.h"#include "authfile.h"#include "pathnames.h"#include "atomicio.h"#include "canohost.h"#include "auth.h"#include "misc.h"#include "dispatch.h"#include "channels.h"#include "session.h"#include "monitor_mm.h"#include "monitor.h"#include "monitor_wrap.h"#include "monitor_fdpass.h"#ifdef LIBWRAP#include <tcpd.h>#include <syslog.h>int allow_severity = LOG_INFO;int deny_severity = LOG_WARNING;#endif /* LIBWRAP */#ifndef O_NOCTTY#define O_NOCTTY	0#endifextern char *__progname;/* Server configuration options. */ServerOptions options;/* Name of the server configuration file. */char *config_file_name = _PATH_SERVER_CONFIG_FILE;/* * Flag indicating whether IPv4 or IPv6.  This can be set on the command line. * Default value is AF_UNSPEC means both IPv4 and IPv6. */int IPv4or6 = AF_UNSPEC;/* * Debug mode flag.  This can be set on the command line.  If debug * mode is enabled, extra debugging output will be sent to the system * log, the daemon will not go to background, and will exit after processing * the first connection. */int debug_flag = 0;/* Flag indicating that the daemon should only test the configuration and keys. */int test_flag = 0;/* Flag indicating that the daemon is being started from inetd. */int inetd_flag = 0;/* Flag indicating that sshd should not detach and become a daemon. */int no_daemon_flag = 0;/* debug goes to stderr unless inetd_flag is set */int log_stderr = 0;/* Saved arguments to main(). */char **saved_argv;/* * The sockets that the server is listening; this is used in the SIGHUP * signal handler. */#define	MAX_LISTEN_SOCKS	16int listen_socks[MAX_LISTEN_SOCKS];int num_listen_socks = 0;/* * the client's version string, passed by sshd2 in compat mode. if != NULL, * sshd will skip the version-number exchange */char *client_version_string = NULL;char *server_version_string = NULL;/* for rekeying XXX fixme */Kex *xxx_kex;/* * Any really sensitive data in the application is contained in this * structure. The idea is that this structure could be locked into memory so * that the pages do not get written into swap.  However, there are some * problems. The private key contains BIGNUMs, and we do not (in principle) * have access to the internals of them, and locking just the structure is * not very useful.  Currently, memory locking is not implemented. */struct {	Key	*server_key;		/* ephemeral server key */	Key	*ssh1_host_key;		/* ssh1 host key */	Key	**host_keys;		/* all private host keys */	int	have_ssh1_key;	int	have_ssh2_key;	u_char	ssh1_cookie[SSH_SESSION_KEY_LENGTH];} sensitive_data;/* * Flag indicating whether the RSA server key needs to be regenerated. * Is set in the SIGALRM handler and cleared when the key is regenerated. */static volatile sig_atomic_t key_do_regen = 0;/* This is set to true when a signal is received. */static volatile sig_atomic_t received_sighup = 0;static volatile sig_atomic_t received_sigterm = 0;/* session identifier, used by RSA-auth */u_char session_id[16];/* same for ssh2 */u_char *session_id2 = NULL;int session_id2_len = 0;/* record remote hostname or ip */u_int utmp_len = MAXHOSTNAMELEN;/* options.max_startup sized array of fd ints */int *startup_pipes = NULL;int startup_pipe;		/* in child *//* variables used for privilege separation */int use_privsep;struct monitor *pmonitor;/* Prototypes for various functions defined later in this file. */void destroy_sensitive_data(void);void demote_sensitive_data(void);static void do_ssh1_kex(void);static void do_ssh2_kex(void);/* * Close all listening sockets */static voidclose_listen_socks(void){	int i;	for (i = 0; i < num_listen_socks; i++)		close(listen_socks[i]);	num_listen_socks = -1;}static voidclose_startup_pipes(void){	int i;	if (startup_pipes)		for (i = 0; i < options.max_startups; i++)			if (startup_pipes[i] != -1)				close(startup_pipes[i]);}/* * Signal handler for SIGHUP.  Sshd execs itself when it receives SIGHUP; * the effect is to reread the configuration file (and to regenerate * the server key). */static voidsighup_handler(int sig){	int save_errno = errno;	received_sighup = 1;	signal(SIGHUP, sighup_handler);	errno = save_errno;}/* * Called from the main program after receiving SIGHUP. * Restarts the server. */static voidsighup_restart(void){	log("Received SIGHUP; restarting.");	close_listen_socks();	close_startup_pipes();	execv(saved_argv[0], saved_argv);	log("RESTART FAILED: av[0]='%.100s', error: %.100s.", saved_argv[0],	    strerror(errno));	exit(1);}/* * Generic signal handler for terminating signals in the master daemon. */static voidsigterm_handler(int sig){	received_sigterm = sig;}/* * SIGCHLD handler.  This is called whenever a child dies.  This will then * reap any zombies left by exited children. */static voidmain_sigchld_handler(int sig){	int save_errno = errno;	pid_t pid;	int status;	while ((pid = waitpid(-1, &status, WNOHANG)) > 0 ||	    (pid < 0 && errno == EINTR))		;	signal(SIGCHLD, main_sigchld_handler);	errno = save_errno;}/* * Signal handler for the alarm after the login grace period has expired. */static voidgrace_alarm_handler(int sig){	/* XXX no idea how fix this signal handler */	/* Log error and exit. */	fatal("Timeout before authentication for %s", get_remote_ipaddr());}/* * Signal handler for the key regeneration alarm.  Note that this * alarm only occurs in the daemon waiting for connections, and it does not * do anything with the private key or random state before forking. * Thus there should be no concurrency control/asynchronous execution * problems. */static voidgenerate_ephemeral_server_key(void){	u_int32_t rnd = 0;	int i;	verbose("Generating %s%d bit RSA key.",	    sensitive_data.server_key ? "new " : "", options.server_key_bits);	if (sensitive_data.server_key != NULL)		key_free(sensitive_data.server_key);	sensitive_data.server_key = key_generate(KEY_RSA1,	    options.server_key_bits);	verbose("RSA key generation complete.");	for (i = 0; i < SSH_SESSION_KEY_LENGTH; i++) {		if (i % 4 == 0)			rnd = arc4random();		sensitive_data.ssh1_cookie[i] = rnd & 0xff;		rnd >>= 8;	}	arc4random_stir();}static voidkey_regeneration_alarm(int sig){	int save_errno = errno;	signal(SIGALRM, SIG_DFL);	errno = save_errno;	key_do_regen = 1;}static voidsshd_exchange_identification(int sock_in, int sock_out){	int i, mismatch;	int remote_major, remote_minor;	int major, minor;	char *s;	char buf[256];			/* Must not be larger than remote_version. */	char remote_version[256];	/* Must be at least as big as buf. */	if ((options.protocol & SSH_PROTO_1) &&	    (options.protocol & SSH_PROTO_2)) {		major = PROTOCOL_MAJOR_1;		minor = 99;	} else if (options.protocol & SSH_PROTO_2) {		major = PROTOCOL_MAJOR_2;		minor = PROTOCOL_MINOR_2;	} else {		major = PROTOCOL_MAJOR_1;		minor = PROTOCOL_MINOR_1;	}	snprintf(buf, sizeof buf, "SSH-%d.%d-%.100s\n", major, minor, SSH_VERSION);	server_version_string = xstrdup(buf);	if (client_version_string == NULL) {		/* Send our protocol version identification. */		if (atomicio(write, sock_out, server_version_string,		    strlen(server_version_string))		    != strlen(server_version_string)) {			log("Could not write ident string to %s", get_remote_ipaddr());			fatal_cleanup();		}		/* Read other sides version identification. */		memset(buf, 0, sizeof(buf));		for (i = 0; i < sizeof(buf) - 1; i++) {			if (atomicio(read, sock_in, &buf[i], 1) != 1) {				log("Did not receive identification string from %s",				    get_remote_ipaddr());				fatal_cleanup();			}			if (buf[i] == '\r') {				buf[i] = 0;				/* Kludge for F-Secure Macintosh < 1.0.2 */				if (i == 12 &&				    strncmp(buf, "SSH-1.5-W1.0", 12) == 0)					break;				continue;			}			if (buf[i] == '\n') {				buf[i] = 0;				break;			}		}		buf[sizeof(buf) - 1] = 0;		client_version_string = xstrdup(buf);	}	/*	 * Check that the versions match.  In future this might accept	 * several versions and set appropriate flags to handle them.	 */	if (sscanf(client_version_string, "SSH-%d.%d-%[^\n]\n",	    &remote_major, &remote_minor, remote_version) != 3) {		s = "Protocol mismatch.\n";		(void) atomicio(write, sock_out, s, strlen(s));		close(sock_in);		close(sock_out);		log("Bad protocol version identification '%.100s' from %s",		    client_version_string, get_remote_ipaddr());		fatal_cleanup();	}	debug("Client protocol version %d.%d; client software version %.100s",	    remote_major, remote_minor, remote_version);	compat_datafellows(remote_version);	if (datafellows & SSH_BUG_PROBE) {		log("probed from %s with %s.  Don't panic.",		    get_remote_ipaddr(), client_version_string);		fatal_cleanup();	}	if (datafellows & SSH_BUG_SCANNER) {		log("scanned from %s with %s.  Don't panic.",		    get_remote_ipaddr(), client_version_string);		fatal_cleanup();	}	mismatch = 0;	switch (remote_major) {	case 1:		if (remote_minor == 99) {			if (options.protocol & SSH_PROTO_2)				enable_compat20();			else				mismatch = 1;			break;		}		if (!(options.protocol & SSH_PROTO_1)) {			mismatch = 1;			break;		}		if (remote_minor < 3) {			packet_disconnect("Your ssh version is too old and "			    "is no longer supported.  Please install a newer version.");		} else if (remote_minor == 3) {			/* note that this disables agent-forwarding */

⌨️ 快捷键说明

复制代码 Ctrl + C
搜索代码 Ctrl + F
全屏模式 F11
切换主题 Ctrl + Shift + D
显示快捷键 ?
增大字号 Ctrl + =
减小字号 Ctrl + -