* Author: Tatu Ylonen <ylo@cs.hut.fi>
* Copyright (c) 1995 Tatu Ylonen <ylo@cs.hut.fi>, Espoo, Finland
* All rights reserved
- * Created: Fri Mar 17 17:09:28 1995 ylo
- * This program is the ssh daemon. It listens for connections from clients, and
- * performs authentication, executes use commands or shell, and forwards
+ * 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.
+ * connection. This can also handle forwarding of X11, TCP/IP, and
+ * authentication agent connections.
*
- * SSH2 implementation,
- * Copyright (c) 2000 Markus Friedl. All rights reserved.
+ * 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:
+ *
+ * Copyright (c) 2000 Markus Friedl. 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.121 2000/07/05 21:35:56 provos Exp $");
+RCSID("$OpenBSD: sshd.c,v 1.128 2000/09/17 15:38:59 markus Exp $");
#include "xmalloc.h"
#include "rsa.h"
unsigned char *session_id2 = NULL;
int session_id2_len = 0;
+/* record remote hostname or ip */
+unsigned int utmp_len = MAXHOSTNAMELEN;
+
/* Prototypes for various functions defined later in this file. */
void do_ssh1_kex();
void do_ssh2_kex();
key_free(sensitive_data.dsa_host_key);
}
+/*
+ * returns 1 if connection should be dropped, 0 otherwise.
+ * dropping starts at connection #max_startups_begin with a probability
+ * of (max_startups_rate/100). the probability increases linearly until
+ * all connections are dropped for startups > max_startups
+ */
+int
+drop_connection(int startups)
+{
+ double p, r;
+
+ if (startups < options.max_startups_begin)
+ return 0;
+ if (startups >= options.max_startups)
+ return 1;
+ if (options.max_startups_rate == 100)
+ return 1;
+
+ p = 100 - options.max_startups_rate;
+ p *= startups - options.max_startups_begin;
+ p /= (double) (options.max_startups - options.max_startups_begin);
+ p += options.max_startups_rate;
+ p /= 100.0;
+ r = arc4random() / (double) UINT_MAX;
+
+ debug("drop_connection: p %g, r %g", p, r);
+ return (r < p) ? 1 : 0;
+}
+
int *startup_pipes = NULL; /* options.max_startup sized array of fd ints */
int startup_pipe; /* in child */
initialize_server_options(&options);
/* Parse command-line arguments. */
- while ((opt = getopt(ac, av, "f:p:b:k:h:g:V:diqQ46")) != EOF) {
+ while ((opt = getopt(ac, av, "f:p:b:k:h:g:V:u:diqQ46")) != EOF) {
switch (opt) {
case '4':
IPv4or6 = AF_INET;
config_file_name = optarg;
break;
case 'd':
- debug_flag = 1;
- options.log_level = SYSLOG_LEVEL_DEBUG;
+ if (0 == debug_flag) {
+ debug_flag = 1;
+ options.log_level = SYSLOG_LEVEL_DEBUG1;
+ } else if (options.log_level < SYSLOG_LEVEL_DEBUG3) {
+ options.log_level++;
+ } else {
+ fprintf(stderr, "Too high debugging level.\n");
+ exit(1);
+ }
break;
case 'i':
inetd_flag = 1;
break;
case 'p':
options.ports_from_cmdline = 1;
- if (options.num_ports >= MAX_PORTS)
- fatal("too many ports.\n");
+ if (options.num_ports >= MAX_PORTS) {
+ fprintf(stderr, "too many ports.\n");
+ exit(1);
+ }
options.ports[options.num_ports++] = atoi(optarg);
break;
case 'g':
/* only makes sense with inetd_flag, i.e. no listen() */
inetd_flag = 1;
break;
+ case 'u':
+ utmp_len = atoi(optarg);
+ break;
case '?':
default:
fprintf(stderr, "sshd version %s\n", SSH_VERSION);
fprintf(stderr, "Usage: %s [options]\n", av0);
fprintf(stderr, "Options:\n");
fprintf(stderr, " -f file Configuration file (default %s)\n", SERVER_CONFIG_FILE);
- fprintf(stderr, " -d Debugging mode\n");
+ fprintf(stderr, " -d Debugging mode (multiple -d means more debugging)\n");
fprintf(stderr, " -i Started from inetd\n");
fprintf(stderr, " -q Quiet (no logging)\n");
fprintf(stderr, " -p port Listen on the specified port (default: 22)\n");
fprintf(stderr, " -b bits Size of server RSA key (default: 768 bits)\n");
fprintf(stderr, " -h file File from which to read host key (default: %s)\n",
HOST_KEY_FILE);
+ fprintf(stderr, " -u len Maximum hostname length for utmp recording\n");
fprintf(stderr, " -4 Use IPv4 only\n");
fprintf(stderr, " -6 Use IPv6 only\n");
exit(1);
}
}
+#ifdef HAVE_SCO_PROTECTED_PW
+ (void) set_auth_parameters(ac, av);
+#endif
+
/* Initialize the log (it is reinitialized below in case we forked). */
if (debug_flag && !inetd_flag)
log_stderr = 1;
s2 = dup(s1);
sock_in = dup(0);
sock_out = dup(1);
+ startup_pipe = -1;
/*
* We intentionally do not close the descriptors 0, 1, and 2
* as our code for setting the descriptors won\'t work if
* fail if there already is a daemon, and this will
* overwrite any old pid in the file.
*/
- f = fopen(options.pid_file, "w");
+ f = fopen(options.pid_file, "wb");
if (f) {
fprintf(f, "%u\n", (unsigned int) getpid());
fclose(f);
error("newsock del O_NONBLOCK: %s", strerror(errno));
continue;
}
- if (startups >= options.max_startups) {
+ if (drop_connection(startups) == 1) {
+ debug("drop connection #%d", startups);
close(newsock);
continue;
}
close_listen_socks();
sock_in = newsock;
sock_out = newsock;
- pid = getpid();
startup_pipe = -1;
+ pid = getpid();
break;
} else {
/*
signal(SIGTERM, SIG_DFL);
signal(SIGQUIT, SIG_DFL);
signal(SIGCHLD, SIG_DFL);
+ signal(SIGINT, SIG_DFL);
/*
* Set socket options for the connection. We want the socket to
if (len < 0 || len > sizeof(session_key))
fatal("do_connection: bad len from %s: session_key_int %d > sizeof(session_key) %d",
get_remote_ipaddr(),
- len, sizeof(session_key));
+ len, (int) sizeof(session_key));
memset(session_key, 0, sizeof(session_key));
BN_bn2bin(session_key_int, session_key + sizeof(session_key) - len);
#ifdef DEBUG_KEXDH
fprintf(stderr, "\ndh_client_pub= ");
- bignum_print(dh_client_pub);
+ BN_print_fp(stderr, dh_client_pub);
fprintf(stderr, "\n");
debug("bits %d", BN_num_bits(dh_client_pub));
#endif
#ifdef DEBUG_KEXDH
fprintf(stderr, "\np= ");
- bignum_print(dh->p);
+ BN_print_fp(stderr, dh->p);
fprintf(stderr, "\ng= ");
- bignum_print(dh->g);
+ bn_print(dh->g);
fprintf(stderr, "\npub= ");
- bignum_print(dh->pub_key);
+ BN_print_fp(stderr, dh->pub_key);
fprintf(stderr, "\n");
+ DHparams_print_fp(stderr, dh);
#endif
if (!dh_pub_is_valid(dh, dh_client_pub))
packet_disconnect("bad client public DH value");