]> andersk Git - openssh.git/commitdiff
- (djm) OpenBSD CVS changes:
authordjm <djm>
Fri, 18 Aug 2000 03:59:06 +0000 (03:59 +0000)
committerdjm <djm>
Fri, 18 Aug 2000 03:59:06 +0000 (03:59 +0000)
   - markus@cvs.openbsd.org  2000/07/22 03:14:37
     [servconf.c servconf.h sshd.8 sshd.c sshd_config]
     random early drop; ok theo, niels
   - deraadt@cvs.openbsd.org 2000/07/26 11:46:51
     [ssh.1]
     typo
   - deraadt@cvs.openbsd.org 2000/08/01 11:46:11
     [sshd.8]
     many fixes from pepper@mail.reppep.com
   - provos@cvs.openbsd.org  2000/08/01 13:01:42
     [Makefile.in util.c aux.c]
     rename aux.c to util.c to help with cygwin port
   - deraadt@cvs.openbsd.org 2000/08/02 00:23:31
     [authfd.c]
     correct sun_len; Alexander@Leidinger.net
   - provos@cvs.openbsd.org  2000/08/02 10:27:17
     [readconf.c sshd.8]
     disable kerberos authentication by default
   - provos@cvs.openbsd.org  2000/08/02 11:27:05
     [sshd.8 readconf.c auth-krb4.c]
     disallow kerberos authentication if we can't verify the TGT; from
     dugsong@
     kerberos authentication is on by default only if you have a srvtab.
   - markus@cvs.openbsd.org  2000/08/04 14:30:07
     [auth.c]
     unused
   - markus@cvs.openbsd.org  2000/08/04 14:30:35
     [sshd_config]
     MaxStartups
   - markus@cvs.openbsd.org  2000/08/15 13:20:46
     [authfd.c]
     cleanup; ok niels@
   - markus@cvs.openbsd.org  2000/08/17 14:05:10
     [session.c]
     cleanup login(1)-like jobs, no duplicate utmp entries
   - markus@cvs.openbsd.org  2000/08/17 14:06:34
     [session.c sshd.8 sshd.c]
      sshd -u len, similar to telnetd

16 files changed:
ChangeLog
Makefile.in
acconfig.h
auth-krb4.c
auth.c
authfd.c
bsd-mktemp.c
configure.in
readconf.c
servconf.c
servconf.h
session.c
ssh.1
sshd.8
sshd.c
sshd_config

index 0e122cf3a599f1ad1547cbb630ef10469ccc0be4..2f5cee9a2ba3de0bad5e325c97478b54530bfc08 100644 (file)
--- a/ChangeLog
+++ b/ChangeLog
@@ -1,3 +1,44 @@
+20000818
+ - (djm) OpenBSD CVS changes:
+   - markus@cvs.openbsd.org  2000/07/22 03:14:37
+     [servconf.c servconf.h sshd.8 sshd.c sshd_config]
+     random early drop; ok theo, niels
+   - deraadt@cvs.openbsd.org 2000/07/26 11:46:51
+     [ssh.1]
+     typo
+   - deraadt@cvs.openbsd.org 2000/08/01 11:46:11
+     [sshd.8]
+     many fixes from pepper@mail.reppep.com
+   - provos@cvs.openbsd.org  2000/08/01 13:01:42
+     [Makefile.in util.c aux.c]
+     rename aux.c to util.c to help with cygwin port
+   - deraadt@cvs.openbsd.org 2000/08/02 00:23:31
+     [authfd.c]
+     correct sun_len; Alexander@Leidinger.net
+   - provos@cvs.openbsd.org  2000/08/02 10:27:17
+     [readconf.c sshd.8]
+     disable kerberos authentication by default
+   - provos@cvs.openbsd.org  2000/08/02 11:27:05
+     [sshd.8 readconf.c auth-krb4.c]
+     disallow kerberos authentication if we can't verify the TGT; from
+     dugsong@
+     kerberos authentication is on by default only if you have a srvtab.
+   - markus@cvs.openbsd.org  2000/08/04 14:30:07
+     [auth.c]
+     unused
+   - markus@cvs.openbsd.org  2000/08/04 14:30:35
+     [sshd_config]
+     MaxStartups
+   - markus@cvs.openbsd.org  2000/08/15 13:20:46
+     [authfd.c]
+     cleanup; ok niels@
+   - markus@cvs.openbsd.org  2000/08/17 14:05:10
+     [session.c]
+     cleanup login(1)-like jobs, no duplicate utmp entries
+   - markus@cvs.openbsd.org  2000/08/17 14:06:34
+     [session.c sshd.8 sshd.c]
+      sshd -u len, similar to telnetd
+
 20000816
  - (djm) Replacement for inet_ntoa for Irix (which breaks on gcc)
  - (djm) Fix strerror replacement for old SunOS. Based on patch from 
index 0aaaa68859356aa21bc6cb20a01be7d2d6ad56a4..ff34c49323d40287d9b10d45966b63e7893993f5 100644 (file)
@@ -34,7 +34,7 @@ INSTALL_SSH_PRNG_CMDS=@INSTALL_SSH_PRNG_CMDS@
 
 TARGETS=ssh sshd ssh-add ssh-keygen ssh-agent scp $(EXTRA_TARGETS)
 
-LIBSSH_OBJS=atomicio.o authfd.o authfile.o aux.o bufaux.o buffer.o canohost.o channels.o cipher.o compat.o compress.o crc32.o deattack.o dispatch.o dsa.o fingerprint.o hmac.o hostfile.o key.o kex.o log.o match.o mpaux.o nchan.o packet.o radix.o entropy.o readpass.o rsa.o tildexpand.o ttymodes.o uidswap.o uuencode.o xmalloc.o 
+LIBSSH_OBJS=atomicio.o authfd.o authfile.o bufaux.o buffer.o canohost.o channels.o cipher.o compat.o compress.o crc32.o deattack.o dispatch.o dsa.o fingerprint.o hmac.o hostfile.o key.o kex.o log.o match.o mpaux.o nchan.o packet.o radix.o entropy.o readpass.o rsa.o tildexpand.o ttymodes.o uidswap.o util.o uuencode.o xmalloc.o 
 
 LIBOPENBSD_COMPAT_OBJS=bsd-arc4random.o bsd-base64.o bsd-bindresvport.o bsd-daemon.o bsd-inet_aton.o bsd-inet_ntoa.o bsd-misc.o bsd-mktemp.o bsd-rresvport.o bsd-setenv.o bsd-sigaction.o bsd-snprintf.o bsd-strlcat.o bsd-strlcpy.o bsd-strsep.o fake-getaddrinfo.o fake-getnameinfo.o next-posix.o
 
index 6c25c8fc994bc93c40fa23f6516a072234011fe1..86607710f59d35acdee5b6bf39a3ce2aa382d09d 100644 (file)
@@ -6,6 +6,9 @@
 
 @TOP@
 
+/* Define if your system's struct sockaddr_un has a sun_len member */
+#undef HAVE_SUN_LEN_IN_SOCKADDR_UN
+
 /* Define if you system's inet_ntoa is busted (e.g. Irix gcc issue) */
 #undef BROKEN_INET_NTOA
 
index e32089b74379a7edfebdd31b87c6a9dcd8e75d04..ae2b2a3d89211e24d03073f09b3fcefafef121be 100644 (file)
@@ -9,7 +9,7 @@
 #include "ssh.h"
 #include "servconf.h"
 
-RCSID("$OpenBSD: auth-krb4.c,v 1.15 2000/06/22 23:54:59 djm Exp $");
+RCSID("$OpenBSD: auth-krb4.c,v 1.16 2000/08/02 17:27:04 provos Exp $");
 
 #ifdef KRB4
 char *ticket = NULL;
@@ -82,11 +82,12 @@ auth_krb4_password(struct passwd * pw, const char *password)
                        if (r == RD_AP_UNDEC) {
                                /*
                                 * Probably didn't have a srvtab on
-                                * localhost. Allow login.
+                                * localhost. Disallow login.
                                 */
                                log("Kerberos V4 TGT for %s unverifiable, "
                                    "no srvtab installed? krb_rd_req: %s",
                                    pw->pw_name, krb_err_txt[r]);
+                               goto kerberos_auth_failure;
                        } else if (r != KSUCCESS) {
                                log("Kerberos V4 %s ticket unverifiable: %s",
                                    KRB4_SERVICE_NAME, krb_err_txt[r]);
@@ -94,12 +95,13 @@ auth_krb4_password(struct passwd * pw, const char *password)
                        }
                } else if (r == KDC_PR_UNKNOWN) {
                        /*
-                        * Allow login if no rcmd service exists, but
+                        * Disallow login if no rcmd service exists, and
                         * log the error.
                         */
                        log("Kerberos V4 TGT for %s unverifiable: %s; %s.%s "
                            "not registered, or srvtab is wrong?", pw->pw_name,
                        krb_err_txt[r], KRB4_SERVICE_NAME, phost);
+                       goto kerberos_auth_failure;
                } else {
                        /*
                         * TGT is bad, forget it. Possibly spoofed!
diff --git a/auth.c b/auth.c
index 5aeeec6dee62d93134cb96ffd327aa42937787cc..dc3e82116464c1569f5fa066e7b0cd702bd97a60 100644 (file)
--- a/auth.c
+++ b/auth.c
@@ -5,7 +5,7 @@
  */
 
 #include "includes.h"
-RCSID("$OpenBSD: auth.c,v 1.7 2000/05/17 21:37:24 deraadt Exp $");
+RCSID("$OpenBSD: auth.c,v 1.8 2000/08/04 20:30:07 markus Exp $");
 
 #include "xmalloc.h"
 #include "rsa.h"
@@ -30,8 +30,6 @@ RCSID("$OpenBSD: auth.c,v 1.7 2000/05/17 21:37:24 deraadt Exp $");
 #include "ssh2.h"
 #include "auth.h"
 #include "session.h"
-#include "dispatch.h"
-
 
 /* import */
 extern ServerOptions options;
index 227c99286eb7ab5d8613d90917a8579516aa2ff5..a34e111ac140bf9bc5226b90767fca65b5f481f2 100644 (file)
--- a/authfd.c
+++ b/authfd.c
@@ -14,7 +14,7 @@
  */
 
 #include "includes.h"
-RCSID("$OpenBSD: authfd.c,v 1.22 2000/07/16 08:27:20 markus Exp $");
+RCSID("$OpenBSD: authfd.c,v 1.24 2000/08/15 19:20:46 markus Exp $");
 
 #include "ssh.h"
 #include "rsa.h"
@@ -31,7 +31,7 @@ RCSID("$OpenBSD: authfd.c,v 1.22 2000/07/16 08:27:20 markus Exp $");
 #include "kex.h"
 
 /* helper */
-int ssh_agent_get_reply(AuthenticationConnection *auth);
+int    decode_reply(int type);
 
 /* Returns the number of the authentication fd, or -1 if there is none. */
 
@@ -39,7 +39,7 @@ int
 ssh_get_authentication_socket()
 {
        const char *authsocket;
-       int sock;
+       int sock, len;
        struct sockaddr_un sunaddr;
 
        authsocket = getenv(SSH_AUTHSOCKET_ENV_NAME);
@@ -48,6 +48,11 @@ ssh_get_authentication_socket()
 
        sunaddr.sun_family = AF_UNIX;
        strlcpy(sunaddr.sun_path, authsocket, sizeof(sunaddr.sun_path));
+#ifdef HAVE_SUN_LEN_IN_SOCKADDR_UN
+       sunaddr.sun_len = len = SUN_LEN(&sunaddr)+1;
+#else /* HAVE_SUN_LEN_IN_SOCKADDR_UN */
+       len = SUN_LEN(&sunaddr)+1;
+#endif /* HAVE_SUN_LEN_IN_SOCKADDR_UN */
 
        sock = socket(AF_UNIX, SOCK_STREAM, 0);
        if (sock < 0)
@@ -58,13 +63,67 @@ ssh_get_authentication_socket()
                close(sock);
                return -1;
        }
-       if (connect(sock, (struct sockaddr *) & sunaddr, sizeof(sunaddr)) < 0) {
+       if (connect(sock, (struct sockaddr *) & sunaddr, len) < 0) {
                close(sock);
                return -1;
        }
        return sock;
 }
 
+int
+ssh_request_reply(AuthenticationConnection *auth,
+    Buffer *request, Buffer *reply)
+{
+       int l, len;
+       char buf[1024];
+
+       /* Get the length of the message, and format it in the buffer. */
+       len = buffer_len(request);
+       PUT_32BIT(buf, len);
+
+       /* Send the length and then the packet to the agent. */
+       if (atomicio(write, auth->fd, buf, 4) != 4 ||
+           atomicio(write, auth->fd, buffer_ptr(request),
+           buffer_len(request)) != buffer_len(request)) {
+               error("Error writing to authentication socket.");
+               return 0;
+       }
+       /*
+        * Wait for response from the agent.  First read the length of the
+        * response packet.
+        */
+       len = 4;
+       while (len > 0) {
+               l = read(auth->fd, buf + 4 - len, len);
+               if (l <= 0) {
+                       error("Error reading response length from authentication socket.");
+                       return 0;
+               }
+               len -= l;
+       }
+
+       /* Extract the length, and check it for sanity. */
+       len = GET_32BIT(buf);
+       if (len > 256 * 1024)
+               fatal("Authentication response too long: %d", len);
+
+       /* Read the rest of the response in to the buffer. */
+       buffer_clear(reply);
+       while (len > 0) {
+               l = len;
+               if (l > sizeof(buf))
+                       l = sizeof(buf);
+               l = read(auth->fd, buf, l);
+               if (l <= 0) {
+                       error("Error reading response from authentication socket.");
+                       return 0;
+               }
+               buffer_append(reply, (char *) buf, l);
+               len -= l;
+       }
+       return 1;
+}
+
 /*
  * Closes the agent socket if it should be closed (depends on how it was
  * obtained).  The argument must have been returned by
@@ -133,62 +192,35 @@ ssh_close_authentication_connection(AuthenticationConnection *ac)
 
 int
 ssh_get_first_identity(AuthenticationConnection *auth,
-                      BIGNUM *e, BIGNUM *n, char **comment)
+    BIGNUM *e, BIGNUM *n, char **comment)
 {
-       unsigned char msg[8192];
-       int len, l;
+       Buffer request;
+       int type;
 
        /*
         * Send a message to the agent requesting for a list of the
         * identities it can represent.
         */
-       PUT_32BIT(msg, 1);
-       msg[4] = SSH_AGENTC_REQUEST_RSA_IDENTITIES;
-       if (atomicio(write, auth->fd, msg, 5) != 5) {
-               error("write auth->fd: %.100s", strerror(errno));
-               return 0;
-       }
-       /* Read the length of the response.  XXX implement timeouts here. */
-       len = 4;
-       while (len > 0) {
-               l = read(auth->fd, msg + 4 - len, len);
-               if (l <= 0) {
-                       error("read auth->fd: %.100s", strerror(errno));
-                       return 0;
-               }
-               len -= l;
-       }
-
-       /*
-        * Extract the length, and check it for sanity.  (We cannot trust
-        * authentication agents).
-        */
-       len = GET_32BIT(msg);
-       if (len < 1 || len > 256 * 1024)
-               fatal("Authentication reply message too long: %d\n", len);
+       buffer_init(&request);
+       buffer_put_char(&request, SSH_AGENTC_REQUEST_RSA_IDENTITIES);
 
-       /* Read the packet itself. */
        buffer_clear(&auth->identities);
-       while (len > 0) {
-               l = len;
-               if (l > sizeof(msg))
-                       l = sizeof(msg);
-               l = read(auth->fd, msg, l);
-               if (l <= 0)
-                       fatal("Incomplete authentication reply.");
-               buffer_append(&auth->identities, (char *) msg, l);
-               len -= l;
+       if (ssh_request_reply(auth, &request, &auth->identities) == 0) {
+               buffer_free(&request);
+               return 0;
        }
+       buffer_free(&request);
 
        /* Get message type, and verify that we got a proper answer. */
-       buffer_get(&auth->identities, (char *) msg, 1);
-       if (msg[0] != SSH_AGENT_RSA_IDENTITIES_ANSWER)
-               fatal("Bad authentication reply message type: %d", msg[0]);
+       type = buffer_get_char(&auth->identities);
+       if (type != SSH_AGENT_RSA_IDENTITIES_ANSWER)
+               fatal("Bad authentication reply message type: %d", type);
 
        /* Get the number of entries in the response and check it for sanity. */
        auth->howmany = buffer_get_int(&auth->identities);
        if (auth->howmany > 1024)
-               fatal("Too many identities in authentication reply: %d\n", auth->howmany);
+               fatal("Too many identities in authentication reply: %d\n",
+                   auth->howmany);
 
        /* Return the first entry (if any). */
        return ssh_get_next_identity(auth, e, n, comment);
@@ -203,7 +235,7 @@ ssh_get_first_identity(AuthenticationConnection *auth,
 
 int
 ssh_get_next_identity(AuthenticationConnection *auth,
-                     BIGNUM *e, BIGNUM *n, char **comment)
+    BIGNUM *e, BIGNUM *n, char **comment)
 {
        unsigned int bits;
 
@@ -240,23 +272,22 @@ ssh_get_next_identity(AuthenticationConnection *auth,
 
 int
 ssh_decrypt_challenge(AuthenticationConnection *auth,
-                     BIGNUM* e, BIGNUM *n, BIGNUM *challenge,
-                     unsigned char session_id[16],
-                     unsigned int response_type,
-                     unsigned char response[16])
+    BIGNUM* e, BIGNUM *n, BIGNUM *challenge,
+    unsigned char session_id[16],
+    unsigned int response_type,
+    unsigned char response[16])
 {
        Buffer buffer;
-       unsigned char buf[8192];
-       int len, l, i;
+       int success = 0;
+       int i;
+       int type;
 
-       /* Response type 0 is no longer supported. */
        if (response_type == 0)
-               fatal("Compatibility with ssh protocol version 1.0 no longer supported.");
+               fatal("Compatibility with ssh protocol version "
+                   "1.0 no longer supported.");
 
-       /* Format a message to the agent. */
-       buf[0] = SSH_AGENTC_RSA_CHALLENGE;
        buffer_init(&buffer);
-       buffer_append(&buffer, (char *) buf, 1);
+       buffer_put_char(&buffer, SSH_AGENTC_RSA_CHALLENGE);
        buffer_put_int(&buffer, BN_num_bits(n));
        buffer_put_bignum(&buffer, e);
        buffer_put_bignum(&buffer, n);
@@ -264,77 +295,27 @@ ssh_decrypt_challenge(AuthenticationConnection *auth,
        buffer_append(&buffer, (char *) session_id, 16);
        buffer_put_int(&buffer, response_type);
 
-       /* Get the length of the message, and format it in the buffer. */
-       len = buffer_len(&buffer);
-       PUT_32BIT(buf, len);
-
-       /* Send the length and then the packet to the agent. */
-       if (atomicio(write, auth->fd, buf, 4) != 4 ||
-           atomicio(write, auth->fd, buffer_ptr(&buffer),
-           buffer_len(&buffer)) != buffer_len(&buffer)) {
-               error("Error writing to authentication socket.");
-error_cleanup:
+       if (ssh_request_reply(auth, &buffer, &buffer) == 0) {
                buffer_free(&buffer);
                return 0;
        }
-       /*
-        * Wait for response from the agent.  First read the length of the
-        * response packet.
-        */
-       len = 4;
-       while (len > 0) {
-               l = read(auth->fd, buf + 4 - len, len);
-               if (l <= 0) {
-                       error("Error reading response length from authentication socket.");
-                       goto error_cleanup;
-               }
-               len -= l;
-       }
-
-       /* Extract the length, and check it for sanity. */
-       len = GET_32BIT(buf);
-       if (len > 256 * 1024)
-               fatal("Authentication response too long: %d", len);
-
-       /* Read the rest of the response in tothe buffer. */
-       buffer_clear(&buffer);
-       while (len > 0) {
-               l = len;
-               if (l > sizeof(buf))
-                       l = sizeof(buf);
-               l = read(auth->fd, buf, l);
-               if (l <= 0) {
-                       error("Error reading response from authentication socket.");
-                       goto error_cleanup;
-               }
-               buffer_append(&buffer, (char *) buf, l);
-               len -= l;
-       }
-
-       /* Get the type of the packet. */
-       buffer_get(&buffer, (char *) buf, 1);
+       type = buffer_get_char(&buffer);
 
-       /* Check for agent failure message. */
-       if (buf[0] == SSH_AGENT_FAILURE) {
+       if (type == SSH_AGENT_FAILURE) {
                log("Agent admitted failure to authenticate using the key.");
-               goto error_cleanup;
+       } else if (type != SSH_AGENT_RSA_RESPONSE) {
+               fatal("Bad authentication response: %d", type);
+       } else {
+               success = 1;
+               /*
+                * Get the response from the packet.  This will abort with a
+                * fatal error if the packet is corrupt.
+                */
+               for (i = 0; i < 16; i++)
+                       response[i] = buffer_get_char(&buffer);
        }
-       /* Now it must be an authentication response packet. */
-       if (buf[0] != SSH_AGENT_RSA_RESPONSE)
-               fatal("Bad authentication response: %d", buf[0]);
-
-       /*
-        * Get the response from the packet.  This will abort with a fatal
-        * error if the packet is corrupt.
-        */
-       for (i = 0; i < 16; i++)
-               response[i] = buffer_get_char(&buffer);
-
-       /* The buffer containing the packet is no longer needed. */
        buffer_free(&buffer);
-
-       /* Correct answer. */
-       return 1;
+       return success;
 }
 
 /* Encode key for a message to the agent. */
@@ -378,8 +359,7 @@ int
 ssh_add_identity(AuthenticationConnection *auth, Key *key, const char *comment)
 {
        Buffer buffer;
-       unsigned char buf[8192];
-       int len;
+       int type;
 
        buffer_init(&buffer);
 
@@ -395,21 +375,13 @@ ssh_add_identity(AuthenticationConnection *auth, Key *key, const char *comment)
                return 0;
                break;
        }
-
-       /* Get the length of the message, and format it in the buffer. */
-       len = buffer_len(&buffer);
-       PUT_32BIT(buf, len);
-
-       /* Send the length and then the packet to the agent. */
-       if (atomicio(write, auth->fd, buf, 4) != 4 ||
-           atomicio(write, auth->fd, buffer_ptr(&buffer),
-           buffer_len(&buffer)) != buffer_len(&buffer)) {
-               error("Error writing to authentication socket.");
+       if (ssh_request_reply(auth, &buffer, &buffer) == 0) {
                buffer_free(&buffer);
                return 0;
        }
+       type = buffer_get_char(&buffer);
        buffer_free(&buffer);
-       return ssh_agent_get_reply(auth);
+       return decode_reply(type);
 }
 
 /*
@@ -421,30 +393,21 @@ int
 ssh_remove_identity(AuthenticationConnection *auth, RSA *key)
 {
        Buffer buffer;
-       unsigned char buf[5];
-       int len;
+       int type;
 
-       /* Format a message to the agent. */
        buffer_init(&buffer);
        buffer_put_char(&buffer, SSH_AGENTC_REMOVE_RSA_IDENTITY);
        buffer_put_int(&buffer, BN_num_bits(key->n));
        buffer_put_bignum(&buffer, key->e);
        buffer_put_bignum(&buffer, key->n);
 
-       /* Get the length of the message, and format it in the buffer. */
-       len = buffer_len(&buffer);
-       PUT_32BIT(buf, len);
-
-       /* Send the length and then the packet to the agent. */
-       if (atomicio(write, auth->fd, buf, 4) != 4 ||
-           atomicio(write, auth->fd, buffer_ptr(&buffer),
-           buffer_len(&buffer)) != buffer_len(&buffer)) {
-               error("Error writing to authentication socket.");
+       if (ssh_request_reply(auth, &buffer, &buffer) == 0) {
                buffer_free(&buffer);
                return 0;
        }
+       type = buffer_get_char(&buffer);
        buffer_free(&buffer);
-       return ssh_agent_get_reply(auth);
+       return decode_reply(type);
 }
 
 /*
@@ -455,73 +418,27 @@ ssh_remove_identity(AuthenticationConnection *auth, RSA *key)
 int
 ssh_remove_all_identities(AuthenticationConnection *auth)
 {
-       unsigned char buf[5];
+       Buffer buffer;
+       int type;
 
-       /* Get the length of the message, and format it in the buffer. */
-       PUT_32BIT(buf, 1);
-       buf[4] = SSH_AGENTC_REMOVE_ALL_RSA_IDENTITIES;
+       buffer_init(&buffer);
+       buffer_put_char(&buffer, SSH_AGENTC_REMOVE_ALL_RSA_IDENTITIES);
 
-       /* Send the length and then the packet to the agent. */
-       if (atomicio(write, auth->fd, buf, 5) != 5) {
-               error("Error writing to authentication socket.");
+       if (ssh_request_reply(auth, &buffer, &buffer) == 0) {
+               buffer_free(&buffer);
                return 0;
        }
-       return ssh_agent_get_reply(auth);
+       type = buffer_get_char(&buffer);
+       buffer_free(&buffer);
+       return decode_reply(type);
 }
 
-/*
- * Read for reply from agent. returns 1 for success, 0 on error
- */
-
 int 
-ssh_agent_get_reply(AuthenticationConnection *auth)
+decode_reply(int type)
 {
-       Buffer buffer;
-       unsigned char buf[8192];
-       int len, l, type;
-
-       /*
-        * Wait for response from the agent.  First read the length of the
-        * response packet.
-        */
-       len = 4;
-       while (len > 0) {
-               l = read(auth->fd, buf + 4 - len, len);
-               if (l <= 0) {
-                       error("Error reading response length from authentication socket.");
-                       buffer_free(&buffer);
-                       return 0;
-               }
-               len -= l;
-       }
-
-       /* Extract the length, and check it for sanity. */
-       len = GET_32BIT(buf);
-       if (len > 256 * 1024)
-               fatal("Response from agent too long: %d", len);
-
-       /* Read the rest of the response in to the buffer. */
-       buffer_init(&buffer);
-       while (len > 0) {
-               l = len;
-               if (l > sizeof(buf))
-                       l = sizeof(buf);
-               l = read(auth->fd, buf, l);
-               if (l <= 0) {
-                       error("Error reading response from authentication socket.");
-                       buffer_free(&buffer);
-                       return 0;
-               }
-               buffer_append(&buffer, (char *) buf, l);
-               len -= l;
-       }
-
-       /* Get the type of the packet. */
-       type = buffer_get_char(&buffer);
-       buffer_free(&buffer);
        switch (type) {
        case SSH_AGENT_FAILURE:
-log("SSH_AGENT_FAILURE");
+               log("SSH_AGENT_FAILURE");
                return 0;
        case SSH_AGENT_SUCCESS:
                return 1;
index 7c02ea1a29084c970babe11459db90338b7a990b..23831fa91463d82d52294c33234ae1878685f8b4 100644 (file)
@@ -52,6 +52,7 @@ static char rcsid[] = "$OpenBSD: mktemp.c,v 1.13 1998/06/30 23:03:13 deraadt Exp
 #include <unistd.h>
 
 #include "bsd-misc.h"
+#include "bsd-arc4random.h"
 
 static int _gettemp(char *, int *, int, int);
 
index 974d0df6b6011fe445936619037319828dc93de7..e9467011bdc5172e5fd4099fcb5b5f5e80246452 100644 (file)
@@ -686,6 +686,22 @@ OSSH_CHECK_HEADER_FOR_FIELD(ut_time, utmp.h, HAVE_TIME_IN_UTMP)
 OSSH_CHECK_HEADER_FOR_FIELD(ut_time, utmpx.h, HAVE_TIME_IN_UTMPX)
 OSSH_CHECK_HEADER_FOR_FIELD(ut_tv, utmpx.h, HAVE_TV_IN_UTMPX)
 
+AC_CACHE_CHECK([for sun_len field in struct sockaddr_un],
+               ac_cv_have_sun_len_in_struct_sockaddr_un, [
+       AC_TRY_COMPILE(
+               [
+#include <sys/types.h>
+#include <sys/socket.h>
+               ],
+               [ struct sockaddr_un s; s.sun_len = 1; ],
+               [ ac_cv_have_sun_len_in_struct_sockaddr_un="yes" ],
+               [ ac_cv_have_sun_len_in_struct_sockaddr_un="no" ],
+       )
+])
+if test "x$ac_cv_have_sun_len_in_struct_sockaddr_un" = "xyes" ; then
+       AC_DEFINE(HAVE_SUN_LEN_IN_SOCKADDR_UN)
+fi
+
 AC_CACHE_CHECK([for ss_family field in struct sockaddr_storage],
                ac_cv_have_ss_family_in_struct_ss, [
        AC_TRY_COMPILE(
index 06cfaa1a3697da6f04ddc613eee643585701b8a4..f31b1c4e65380f50819cbac4021c606bd0d0f6a7 100644 (file)
@@ -14,7 +14,7 @@
  */
 
 #include "includes.h"
-RCSID("$OpenBSD: readconf.c,v 1.43 2000/07/14 22:59:46 markus Exp $");
+RCSID("$OpenBSD: readconf.c,v 1.45 2000/08/02 17:27:04 provos Exp $");
 
 #include "ssh.h"
 #include "cipher.h"
index 477204cfd69b870fe232166889cc3ec66c649ce7..6affb51e98c442eb30c5216627d979f2a6086a60 100644 (file)
@@ -12,7 +12,7 @@
  */
 
 #include "includes.h"
-RCSID("$OpenBSD: servconf.c,v 1.49 2000/07/14 22:59:46 markus Exp $");
+RCSID("$OpenBSD: servconf.c,v 1.50 2000/07/22 09:14:36 markus Exp $");
 
 #include "ssh.h"
 #include "servconf.h"
@@ -76,6 +76,8 @@ initialize_server_options(ServerOptions *options)
        options->protocol = SSH_PROTO_UNKNOWN;
        options->gateway_ports = -1;
        options->num_subsystems = 0;
+       options->max_startups_begin = -1;
+       options->max_startups_rate = -1;
        options->max_startups = -1;
 }
 
@@ -162,6 +164,10 @@ fill_default_server_options(ServerOptions *options)
                options->gateway_ports = 0;
        if (options->max_startups == -1)
                options->max_startups = 10;
+       if (options->max_startups_rate == -1)
+               options->max_startups_rate = 100;               /* 100% */
+       if (options->max_startups_begin == -1)
+               options->max_startups_begin = options->max_startups;
 }
 
 /* Keyword tokens. */
@@ -644,6 +650,22 @@ parse_flag:
                        break;
 
                case sMaxStartups:
+                       arg = strdelim(&cp);
+                       if (!arg || *arg == '\0')
+                               fatal("%s line %d: Missing MaxStartups spec.",
+                                     filename, linenum);
+                       if (sscanf(arg, "%d:%d:%d",
+                           &options->max_startups_begin,
+                           &options->max_startups_rate,
+                           &options->max_startups) == 3) {
+                               if (options->max_startups_begin >
+                                   options->max_startups ||
+                                   options->max_startups_rate > 100 ||
+                                   options->max_startups_rate < 1)
+                               fatal("%s line %d: Illegal MaxStartups spec.",
+                                     filename, linenum);
+                               break;
+                       }
                        intptr = &options->max_startups;
                        goto parse_int;
 
index 95593722dd9f80ee9e21299c4e844fb79f0f71e9..3b65c6a6f26b13724c7ced0d02508d60e9fc3168 100644 (file)
@@ -13,7 +13,7 @@
  *
  */
 
-/* RCSID("$OpenBSD: servconf.h,v 1.26 2000/06/26 21:59:18 markus Exp $"); */
+/* RCSID("$OpenBSD: servconf.h,v 1.27 2000/07/22 09:14:36 markus Exp $"); */
 
 #ifndef SERVCONF_H
 #define SERVCONF_H
@@ -100,6 +100,8 @@ typedef struct {
        char   *subsystem_name[MAX_SUBSYSTEMS];
        char   *subsystem_command[MAX_SUBSYSTEMS];
 
+       int     max_startups_begin;
+       int     max_startups_rate;
        int     max_startups;
 
 }       ServerOptions;
index e68718a7eb910e368aedee4d842fd0588ced6650..d65b06984a1e01ff5f8f834e9b2851c7b793eab5 100644 (file)
--- a/session.c
+++ b/session.c
@@ -8,7 +8,7 @@
  */
 
 #include "includes.h"
-RCSID("$OpenBSD: session.c,v 1.23 2000/07/11 08:11:33 deraadt Exp $");
+RCSID("$OpenBSD: session.c,v 1.25 2000/08/17 20:06:34 markus Exp $");
 
 #include "xmalloc.h"
 #include "ssh.h"
@@ -85,6 +85,7 @@ void  session_pty_cleanup(Session *s);
 void   session_proctitle(Session *s);
 void   do_exec_pty(Session *s, const char *command, struct passwd * pw);
 void   do_exec_no_pty(Session *s, const char *command, struct passwd * pw);
+void   do_login(Session *s);
 
 void
 do_child(const char *command, struct passwd * pw, const char *term,
@@ -101,6 +102,7 @@ static const char *__progname = "sshd";
 
 extern int log_stderr;
 extern int debug_flag;
+extern unsigned int utmp_len;
 
 extern int startup_pipe;
 
@@ -523,35 +525,14 @@ do_exec_no_pty(Session *s, const char *command, struct passwd * pw)
 void
 do_exec_pty(Session *s, const char *command, struct passwd * pw)
 {
-       FILE *f;
-       char buf[100], *time_string;
-       char line[256];
-       const char *hostname;
        int fdout, ptyfd, ttyfd, ptymaster;
-       int quiet_login;
        pid_t pid;
-       socklen_t fromlen;
-       struct sockaddr_storage from;
-       struct stat st;
-       time_t last_login_time;
 
        if (s == NULL)
                fatal("do_exec_pty: no session");
        ptyfd = s->ptyfd;
        ttyfd = s->ttyfd;
 
-       /* Get remote host name. */
-       hostname = get_canonical_hostname();
-
-       /*
-        * Get the time when the user last logged in.  Buf will be set to
-        * contain the hostname the last login was from.
-        */
-       if (!options.use_login) {
-               last_login_time = get_last_login_time(pw->pw_uid, pw->pw_name,
-                                                     buf, sizeof(buf));
-       }
-
 #ifdef USE_PAM
                        do_pam_session(pw->pw_name, s->tty);
                        do_pam_setcred();
@@ -559,10 +540,7 @@ do_exec_pty(Session *s, const char *command, struct passwd * pw)
 
        /* Fork the child. */
        if ((pid = fork()) == 0) {
-               pid = getpid();
-
-               /* Child.  Reinitialize the log because the pid has
-                  changed. */
+               /* Child.  Reinitialize the log because the pid has changed. */
                log_init(__progname, options.log_level, options.log_facility, log_stderr);
 
                /* Close the master side of the pseudo tty. */
@@ -586,82 +564,10 @@ do_exec_pty(Session *s, const char *command, struct passwd * pw)
                /* Close the extra descriptor for the pseudo tty. */
                close(ttyfd);
 
-/* XXXX ? move to do_child() ??*/
-               /*
-                * Get IP address of client.  This is needed because we want
-                * to record where the user logged in from.  If the
-                * connection is not a socket, let the ip address be 0.0.0.0.
-                */
-               memset(&from, 0, sizeof(from));
-               if (packet_connection_is_on_socket()) {
-                       fromlen = sizeof(from);
-                       if (getpeername(packet_get_connection_in(),
-                            (struct sockaddr *) & from, &fromlen) < 0) {
-                               debug("getpeername: %.100s", strerror(errno));
-                               fatal_cleanup();
-                       }
-               }
-               /* Record that there was a login on that terminal. */
-               if (!options.use_login || command != NULL)
-                       record_login(pid, s->tty, pw->pw_name, pw->pw_uid, 
-                           hostname, (struct sockaddr *)&from);
-
-               /* Check if .hushlogin exists. */
-               snprintf(line, sizeof line, "%.200s/.hushlogin", pw->pw_dir);
-               quiet_login = stat(line, &st) >= 0;
+               /* record login, etc. similar to login(1) */
+               if (command == NULL && !options.use_login)
+                       do_login(s);
 
-#ifdef USE_PAM
-               if (!quiet_login)
-                       print_pam_messages();
-#endif /* USE_PAM */
-
-               /*
-                * If the user has logged in before, display the time of last
-                * login. However, don't display anything extra if a command
-                * has been specified (so that ssh can be used to execute
-                * commands on a remote machine without users knowing they
-                * are going to another machine). Login(1) will do this for
-                * us as well, so check if login(1) is used
-                */
-               if (command == NULL && last_login_time != 0 && !quiet_login &&
-                   !options.use_login) {
-                       /* Convert the date to a string. */
-                       time_string = ctime(&last_login_time);
-                       /* Remove the trailing newline. */
-                       if (strchr(time_string, '\n'))
-                               *strchr(time_string, '\n') = 0;
-                       /* Display the last login time.  Host if displayed
-                          if known. */
-                       if (strcmp(buf, "") == 0)
-                               printf("Last login: %s\r\n", time_string);
-                       else
-                               printf("Last login: %s from %s\r\n", time_string, buf);
-               }
-               /*
-                * Print /etc/motd unless a command was specified or printing
-                * it was disabled in server options or login(1) will be
-                * used.  Note that some machines appear to print it in
-                * /etc/profile or similar.
-                */
-               if (command == NULL && options.print_motd && !quiet_login &&
-                   !options.use_login) {
-                       /* Print /etc/motd if it exists. */
-                       f = fopen("/etc/motd", "r");
-                       if (f) {
-                               while (fgets(line, sizeof(line), f))
-                                       fputs(line, stdout);
-                               fclose(f);
-                       }
-               }
-#if defined(WITH_AIXAUTHENTICATE)
-               /*
-                * AIX handles the lastlog info differently.  Display it here.
-                */
-               if (command == NULL && aixloginmsg && *aixloginmsg &&
-                   !quiet_login && !options.use_login) {
-                       printf("%s\n", aixloginmsg);
-               }
-#endif
                /* Do common processing for the child, such as execing the command. */
                do_child(command, pw, s->term, s->display, s->auth_proto,
                    s->auth_data, s->tty);
@@ -699,6 +605,87 @@ do_exec_pty(Session *s, const char *command, struct passwd * pw)
        }
 }
 
+const char *
+get_remote_name_or_ip(void)
+{
+       static const char *remote = "";
+       if (utmp_len > 0)
+               remote = get_canonical_hostname();
+       if (utmp_len == 0 || strlen(remote) > utmp_len)
+               remote = get_remote_ipaddr();
+       return remote;
+}
+
+/* administrative, login(1)-like work */
+void
+do_login(Session *s)
+{
+       FILE *f;
+       char *time_string;
+       char buf[256];
+       socklen_t fromlen;
+       struct sockaddr_storage from;
+       struct stat st;
+       time_t last_login_time;
+       struct passwd * pw = s->pw;
+       pid_t pid = getpid();
+
+       /*
+        * Get IP address of client. If the connection is not a socket, let
+        * the address be 0.0.0.0.
+        */
+       memset(&from, 0, sizeof(from));
+       if (packet_connection_is_on_socket()) {
+               fromlen = sizeof(from);
+               if (getpeername(packet_get_connection_in(),
+                    (struct sockaddr *) & from, &fromlen) < 0) {
+                       debug("getpeername: %.100s", strerror(errno));
+                       fatal_cleanup();
+               }
+       }
+
+       /* Record that there was a login on that tty from the remote host. */
+       record_login(pid, s->tty, pw->pw_name, pw->pw_uid,
+           get_remote_name_or_ip(), (struct sockaddr *)&from);
+
+       /* Done if .hushlogin exists. */
+       snprintf(buf, sizeof(buf), "%.200s/.hushlogin", pw->pw_dir);
+       if (stat(buf, &st) >= 0)
+               return;
+
+#ifdef USE_PAM
+       print_pam_messages();
+#endif /* USE_PAM */
+#ifdef WITH_AIXAUTHENTICATE
+       if (aixloginmsg && *aixloginmsg)
+               printf("%s\n", aixloginmsg);
+#endif /* WITH_AIXAUTHENTICATE */
+
+       /*
+        * Get the time when the user last logged in.  'buf' will be set
+        * to contain the hostname the last login was from. 
+        */
+       last_login_time = get_last_login_time(pw->pw_uid, pw->pw_name,
+           buf, sizeof(buf));
+       if (last_login_time != 0) {
+               time_string = ctime(&last_login_time);
+               if (strchr(time_string, '\n'))
+                       *strchr(time_string, '\n') = 0;
+               if (strcmp(buf, "") == 0)
+                       printf("Last login: %s\r\n", time_string);
+               else
+                       printf("Last login: %s from %s\r\n", time_string, buf);
+       }
+       if (options.print_motd) {
+               f = fopen("/etc/motd", "r");
+               if (f) {
+                       while (fgets(buf, sizeof(buf), f))
+                               fputs(buf, stdout);
+                       fclose(f);
+               }
+       }
+}
+
 /*
  * Sets the value of the given variable in the environment.  If the variable
  * already exists, its value is overriden.
@@ -1265,8 +1252,9 @@ do_child(const char *command, struct passwd * pw, const char *term,
                } else {
                        /* Launch login(1). */
 
-                       execl(LOGIN_PROGRAM, "login", "-h", get_remote_ipaddr(),
-                             "-p", "-f", "--", pw->pw_name, NULL);
+                       execl(LOGIN_PROGRAM, "login",
+                            "-h", get_remote_name_or_ip(),
+                            "-p", "-f", "--", pw->pw_name, NULL);
 
                        /* Login couldn't be executed, die. */
 
diff --git a/ssh.1 b/ssh.1
index 313acdc0d2d64ce3b2eb216581d039924efbe202..58bbb7016db4d3ca566bdd428a18606157217e3b 100644 (file)
--- a/ssh.1
+++ b/ssh.1
@@ -994,7 +994,7 @@ If the current session has no tty,
 this variable is not set.
 .It Ev TZ
 The timezone variable is set to indicate the present timezone if it
-was set when the daemon was started (e.i., the daemon passes the value
+was set when the daemon was started (i.e., the daemon passes the value
 on to new connections).
 .It Ev USER
 Set to the name of the user logging in.
diff --git a/sshd.8 b/sshd.8
index 346c55a5f996b6ed78b01ab06debc56d73f2ddec..b5c2aeff13638c12aeb1fdda81dd30b53ad5d01f 100644 (file)
--- a/sshd.8
+++ b/sshd.8
@@ -26,6 +26,7 @@
 .Op Fl h Ar host_key_file
 .Op Fl k Ar key_gen_time
 .Op Fl p Ar port
+.Op Fl u Ar len
 .Op Fl V Ar client_protocol_id
 .Sh DESCRIPTION
 .Nm
@@ -104,7 +105,7 @@ into the machine).
 .Pp
 .Ss SSH protocol version 2
 .Pp
-Version 2 works similar:
+Version 2 works similarly:
 Each host has a host-specific DSA key used to identify the host.
 However, when the daemon starts, it does not generate a server key.
 Forward security is provided through a Diffie-Hellman key agreement.
@@ -211,6 +212,22 @@ Quiet mode.
 Nothing is sent to the system log.
 Normally the beginning,
 authentication, and termination of each connection is logged.
+.It Fl u Ar len
+This option is used to specify the size of the field
+in the
+.Li utmp
+structure that holds the remote host name.
+If the resolved host name is longer than
+.Ar len ,
+the dotted decimal value will be used instead.
+This allows hosts with very long host names that
+overflow this field to still be uniquely identified.
+Specifying
+.Fl u0
+indicates that only dotted decimal addresses
+should be put into the
+.Pa utmp
+file.
 .It Fl Q
 Do not print an error message if RSA support is missing.
 .It Fl V Ar client_protocol_id
@@ -257,7 +274,7 @@ and
 .Ql ?
 can be used as
 wildcards in the patterns.
-Only group names are valid, a numerical group ID isn't recognized.
+Only group names are valid; a numerical group ID isn't recognized.
 By default login is allowed regardless of the primary group.
 .Pp
 .It Cm AllowUsers
@@ -270,7 +287,7 @@ and
 .Ql ?
 can be used as
 wildcards in the patterns.
-Only user names are valid, a numerical user ID isn't recognized.
+Only user names are valid; a numerical user ID isn't recognized.
 By default login is allowed regardless of the user name.
 .Pp
 .It Cm Ciphers
@@ -294,7 +311,7 @@ and
 .Ql ?
 can be used as
 wildcards in the patterns.
-Only group names are valid, a numerical group ID isn't recognized.
+Only group names are valid; a numerical group ID isn't recognized.
 By default login is allowed regardless of the primary group.
 .Pp
 .It Cm DenyUsers
@@ -305,7 +322,7 @@ Login is disallowed for user names that match one of the patterns.
 and
 .Ql ?
 can be used as wildcards in the patterns.
-Only user names are valid, a numerical user ID isn't recognized.
+Only user names are valid; a numerical user ID isn't recognized.
 By default login is allowed regardless of the user name.
 .It Cm DSAAuthentication
 Specifies whether DSA authentication is allowed.
@@ -321,7 +338,7 @@ or
 .Dq no .
 The default is
 .Dq no .
-.It Cm HostDsaKey
+.It Cm HostDSAKey
 Specifies the file containing the private DSA host key (default
 .Pa /etc/ssh_host_dsa_key )
 used by SSH protocol 2.0.
@@ -383,7 +400,8 @@ Specifies whether Kerberos authentication is allowed.
 This can be in the form of a Kerberos ticket, or if
 .Cm PasswordAuthentication
 is yes, the password provided by the user will be validated through
-the Kerberos KDC.
+the Kerberos KDC.  To use this option, the server needs a 
+Kerberos servtab which allows the verification of the KDC's identity.
 Default is
 .Dq yes .
 .It Cm KerberosOrLocalPasswd
@@ -443,11 +461,28 @@ Additional connections will be dropped until authentication succeeds or the
 .Cm LoginGraceTime
 expires for a connection.
 The default is 10.
+.Pp
+Alternatively, random early drop can be enabled by specifying
+the three colon separated values
+.Dq start:rate:full
+(e.g. "10:30:60").
+.Nm
+will refuse connection attempts with a probabillity of
+.Dq rate/100
+(30%)
+if there are currently
+.Dq start
+(10)
+unauthenticated connections.
+The probabillity increases linearly and all connection attempts
+are refused if the number of unauthenticated connections reaches
+.Dq full
+(60).
 .It Cm PasswordAuthentication
 Specifies whether password authentication is allowed.
 The default is
 .Dq yes .
-Note that this option applies to both protocol version 1 and 2.
+Note that this option applies to both protocol versions 1 and 2.
 .It Cm PermitEmptyPasswords
 When password authentication is allowed, it specifies whether the
 server allows login to accounts with empty password strings.
@@ -568,7 +603,7 @@ Specifies whether
 is used for interactive login sessions.
 Note that
 .Xr login 1
-is not never for remote command execution.
+is never used for remote command execution.
 The default is
 .Dq no .
 .It Cm X11DisplayOffset
@@ -666,7 +701,7 @@ You don't want to type them in; instead, copy the
 .Pa identity.pub
 file and edit it.
 .Pp
-The options (if present) consists of comma-separated option
+The options (if present) consist of comma-separated option
 specifications.
 No spaces are permitted, except within double quotes.
 The following option specifications are supported:
@@ -740,7 +775,7 @@ and
 files contain host public keys for all known hosts.
 The global file should
 be prepared by the administrator (optional), and the per-user file is
-maintained automatically: whenever the user connects an unknown host
+maintained automatically: whenever the user connects from an unknown host
 its key is added to the per-user file.
 .Pp
 Each line in these files contains the following fields: hostnames,
@@ -815,7 +850,7 @@ Contains the process ID of the
 listening for connections (if there are several daemons running
 concurrently for different ports, this contains the pid of the one
 started last).
-The contents of this file are not sensitive; it can be world-readable.
+The content of this file is not sensitive; it can be world-readable.
 .It Pa $HOME/.ssh/authorized_keys
 Lists the RSA keys that can be used to log into the user's account.
 This file must be readable by root (which may on some machines imply
@@ -843,7 +878,7 @@ These files are consulted when using rhosts with RSA host
 authentication to check the public key of the host.
 The key must be listed in one of these files to be accepted.
 The client uses the same files
-to verify that the remote host is the one we intended to connect.
+to verify that the remote host is the one it intended to connect.
 These files should be writable only by root/the owner.
 .Pa /etc/ssh_known_hosts
 should be world-readable, and
@@ -882,7 +917,7 @@ this file is exactly the same as for
 .Pa .rhosts .
 However, this file is
 not used by rlogin and rshd, so using this permits access using SSH only.
-.Pa /etc/hosts.equiv
+.It Pa /etc/hosts.equiv
 This file is used during
 .Pa .rhosts
 authentication.
diff --git a/sshd.c b/sshd.c
index b6db074c8c61a30d96eafb8391e9bdc1d8515249..ae02f2c401629cc72fe2123dc985176fe80ff880 100644 (file)
--- a/sshd.c
+++ b/sshd.c
@@ -14,7 +14,7 @@
  */
 
 #include "includes.h"
-RCSID("$OpenBSD: sshd.c,v 1.123 2000/07/18 01:25:01 djm Exp $");
+RCSID("$OpenBSD: sshd.c,v 1.125 2000/08/17 20:06:34 markus Exp $");
 
 #include "xmalloc.h"
 #include "rsa.h"
@@ -139,6 +139,9 @@ unsigned char session_id[16];
 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();
@@ -400,6 +403,35 @@ destroy_sensitive_data(void)
                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 */
 
@@ -441,7 +473,7 @@ main(int ac, char **av)
        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;
@@ -488,6 +520,9 @@ main(int ac, char **av)
                        /* 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);
@@ -503,6 +538,7 @@ main(int ac, char **av)
                        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);
@@ -823,7 +859,8 @@ main(int ac, char **av)
                                        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;
                                }
index d3bab840aacd889c1cb24052462f28efae238a82..a97b780e809f8c45b2443bda1c63546756265e12 100644 (file)
@@ -51,3 +51,4 @@ CheckMail no
 UseLogin no
 
 #Subsystem     sftp    /usr/local/sbin/sftpd
+#MaxStartups 10:30:60
This page took 0.147746 seconds and 5 git commands to generate.