summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--ChangeLog41
-rw-r--r--Makefile.in2
-rw-r--r--acconfig.h3
-rw-r--r--auth-krb4.c8
-rw-r--r--auth.c4
-rw-r--r--authfd.c325
-rw-r--r--bsd-mktemp.c1
-rw-r--r--configure.in16
-rw-r--r--readconf.c2
-rw-r--r--servconf.c24
-rw-r--r--servconf.h4
-rw-r--r--session.c194
-rw-r--r--ssh.14
-rw-r--r--sshd.865
-rw-r--r--sshd.c43
-rw-r--r--sshd_config1
16 files changed, 400 insertions, 337 deletions
diff --git a/ChangeLog b/ChangeLog
index 0e122cf3a..2f5cee9a2 100644
--- a/ChangeLog
+++ b/ChangeLog
@@ -1,3 +1,44 @@
120000818
2 - (djm) OpenBSD CVS changes:
3 - markus@cvs.openbsd.org 2000/07/22 03:14:37
4 [servconf.c servconf.h sshd.8 sshd.c sshd_config]
5 random early drop; ok theo, niels
6 - deraadt@cvs.openbsd.org 2000/07/26 11:46:51
7 [ssh.1]
8 typo
9 - deraadt@cvs.openbsd.org 2000/08/01 11:46:11
10 [sshd.8]
11 many fixes from pepper@mail.reppep.com
12 - provos@cvs.openbsd.org 2000/08/01 13:01:42
13 [Makefile.in util.c aux.c]
14 rename aux.c to util.c to help with cygwin port
15 - deraadt@cvs.openbsd.org 2000/08/02 00:23:31
16 [authfd.c]
17 correct sun_len; Alexander@Leidinger.net
18 - provos@cvs.openbsd.org 2000/08/02 10:27:17
19 [readconf.c sshd.8]
20 disable kerberos authentication by default
21 - provos@cvs.openbsd.org 2000/08/02 11:27:05
22 [sshd.8 readconf.c auth-krb4.c]
23 disallow kerberos authentication if we can't verify the TGT; from
24 dugsong@
25 kerberos authentication is on by default only if you have a srvtab.
26 - markus@cvs.openbsd.org 2000/08/04 14:30:07
27 [auth.c]
28 unused
29 - markus@cvs.openbsd.org 2000/08/04 14:30:35
30 [sshd_config]
31 MaxStartups
32 - markus@cvs.openbsd.org 2000/08/15 13:20:46
33 [authfd.c]
34 cleanup; ok niels@
35 - markus@cvs.openbsd.org 2000/08/17 14:05:10
36 [session.c]
37 cleanup login(1)-like jobs, no duplicate utmp entries
38 - markus@cvs.openbsd.org 2000/08/17 14:06:34
39 [session.c sshd.8 sshd.c]
40 sshd -u len, similar to telnetd
41
120000816 4220000816
2 - (djm) Replacement for inet_ntoa for Irix (which breaks on gcc) 43 - (djm) Replacement for inet_ntoa for Irix (which breaks on gcc)
3 - (djm) Fix strerror replacement for old SunOS. Based on patch from 44 - (djm) Fix strerror replacement for old SunOS. Based on patch from
diff --git a/Makefile.in b/Makefile.in
index 0aaaa6885..ff34c4932 100644
--- a/Makefile.in
+++ b/Makefile.in
@@ -34,7 +34,7 @@ INSTALL_SSH_PRNG_CMDS=@INSTALL_SSH_PRNG_CMDS@
34 34
35TARGETS=ssh sshd ssh-add ssh-keygen ssh-agent scp $(EXTRA_TARGETS) 35TARGETS=ssh sshd ssh-add ssh-keygen ssh-agent scp $(EXTRA_TARGETS)
36 36
37LIBSSH_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 37LIBSSH_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
38 38
39LIBOPENBSD_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 39LIBOPENBSD_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
40 40
diff --git a/acconfig.h b/acconfig.h
index 6c25c8fc9..86607710f 100644
--- a/acconfig.h
+++ b/acconfig.h
@@ -6,6 +6,9 @@
6 6
7@TOP@ 7@TOP@
8 8
9/* Define if your system's struct sockaddr_un has a sun_len member */
10#undef HAVE_SUN_LEN_IN_SOCKADDR_UN
11
9/* Define if you system's inet_ntoa is busted (e.g. Irix gcc issue) */ 12/* Define if you system's inet_ntoa is busted (e.g. Irix gcc issue) */
10#undef BROKEN_INET_NTOA 13#undef BROKEN_INET_NTOA
11 14
diff --git a/auth-krb4.c b/auth-krb4.c
index e32089b74..ae2b2a3d8 100644
--- a/auth-krb4.c
+++ b/auth-krb4.c
@@ -9,7 +9,7 @@
9#include "ssh.h" 9#include "ssh.h"
10#include "servconf.h" 10#include "servconf.h"
11 11
12RCSID("$OpenBSD: auth-krb4.c,v 1.15 2000/06/22 23:54:59 djm Exp $"); 12RCSID("$OpenBSD: auth-krb4.c,v 1.16 2000/08/02 17:27:04 provos Exp $");
13 13
14#ifdef KRB4 14#ifdef KRB4
15char *ticket = NULL; 15char *ticket = NULL;
@@ -82,11 +82,12 @@ auth_krb4_password(struct passwd * pw, const char *password)
82 if (r == RD_AP_UNDEC) { 82 if (r == RD_AP_UNDEC) {
83 /* 83 /*
84 * Probably didn't have a srvtab on 84 * Probably didn't have a srvtab on
85 * localhost. Allow login. 85 * localhost. Disallow login.
86 */ 86 */
87 log("Kerberos V4 TGT for %s unverifiable, " 87 log("Kerberos V4 TGT for %s unverifiable, "
88 "no srvtab installed? krb_rd_req: %s", 88 "no srvtab installed? krb_rd_req: %s",
89 pw->pw_name, krb_err_txt[r]); 89 pw->pw_name, krb_err_txt[r]);
90 goto kerberos_auth_failure;
90 } else if (r != KSUCCESS) { 91 } else if (r != KSUCCESS) {
91 log("Kerberos V4 %s ticket unverifiable: %s", 92 log("Kerberos V4 %s ticket unverifiable: %s",
92 KRB4_SERVICE_NAME, krb_err_txt[r]); 93 KRB4_SERVICE_NAME, krb_err_txt[r]);
@@ -94,12 +95,13 @@ auth_krb4_password(struct passwd * pw, const char *password)
94 } 95 }
95 } else if (r == KDC_PR_UNKNOWN) { 96 } else if (r == KDC_PR_UNKNOWN) {
96 /* 97 /*
97 * Allow login if no rcmd service exists, but 98 * Disallow login if no rcmd service exists, and
98 * log the error. 99 * log the error.
99 */ 100 */
100 log("Kerberos V4 TGT for %s unverifiable: %s; %s.%s " 101 log("Kerberos V4 TGT for %s unverifiable: %s; %s.%s "
101 "not registered, or srvtab is wrong?", pw->pw_name, 102 "not registered, or srvtab is wrong?", pw->pw_name,
102 krb_err_txt[r], KRB4_SERVICE_NAME, phost); 103 krb_err_txt[r], KRB4_SERVICE_NAME, phost);
104 goto kerberos_auth_failure;
103 } else { 105 } else {
104 /* 106 /*
105 * TGT is bad, forget it. Possibly spoofed! 107 * TGT is bad, forget it. Possibly spoofed!
diff --git a/auth.c b/auth.c
index 5aeeec6de..dc3e82116 100644
--- a/auth.c
+++ b/auth.c
@@ -5,7 +5,7 @@
5 */ 5 */
6 6
7#include "includes.h" 7#include "includes.h"
8RCSID("$OpenBSD: auth.c,v 1.7 2000/05/17 21:37:24 deraadt Exp $"); 8RCSID("$OpenBSD: auth.c,v 1.8 2000/08/04 20:30:07 markus Exp $");
9 9
10#include "xmalloc.h" 10#include "xmalloc.h"
11#include "rsa.h" 11#include "rsa.h"
@@ -30,8 +30,6 @@ RCSID("$OpenBSD: auth.c,v 1.7 2000/05/17 21:37:24 deraadt Exp $");
30#include "ssh2.h" 30#include "ssh2.h"
31#include "auth.h" 31#include "auth.h"
32#include "session.h" 32#include "session.h"
33#include "dispatch.h"
34
35 33
36/* import */ 34/* import */
37extern ServerOptions options; 35extern ServerOptions options;
diff --git a/authfd.c b/authfd.c
index 227c99286..a34e111ac 100644
--- a/authfd.c
+++ b/authfd.c
@@ -14,7 +14,7 @@
14 */ 14 */
15 15
16#include "includes.h" 16#include "includes.h"
17RCSID("$OpenBSD: authfd.c,v 1.22 2000/07/16 08:27:20 markus Exp $"); 17RCSID("$OpenBSD: authfd.c,v 1.24 2000/08/15 19:20:46 markus Exp $");
18 18
19#include "ssh.h" 19#include "ssh.h"
20#include "rsa.h" 20#include "rsa.h"
@@ -31,7 +31,7 @@ RCSID("$OpenBSD: authfd.c,v 1.22 2000/07/16 08:27:20 markus Exp $");
31#include "kex.h" 31#include "kex.h"
32 32
33/* helper */ 33/* helper */
34int ssh_agent_get_reply(AuthenticationConnection *auth); 34int decode_reply(int type);
35 35
36/* Returns the number of the authentication fd, or -1 if there is none. */ 36/* Returns the number of the authentication fd, or -1 if there is none. */
37 37
@@ -39,7 +39,7 @@ int
39ssh_get_authentication_socket() 39ssh_get_authentication_socket()
40{ 40{
41 const char *authsocket; 41 const char *authsocket;
42 int sock; 42 int sock, len;
43 struct sockaddr_un sunaddr; 43 struct sockaddr_un sunaddr;
44 44
45 authsocket = getenv(SSH_AUTHSOCKET_ENV_NAME); 45 authsocket = getenv(SSH_AUTHSOCKET_ENV_NAME);
@@ -48,6 +48,11 @@ ssh_get_authentication_socket()
48 48
49 sunaddr.sun_family = AF_UNIX; 49 sunaddr.sun_family = AF_UNIX;
50 strlcpy(sunaddr.sun_path, authsocket, sizeof(sunaddr.sun_path)); 50 strlcpy(sunaddr.sun_path, authsocket, sizeof(sunaddr.sun_path));
51#ifdef HAVE_SUN_LEN_IN_SOCKADDR_UN
52 sunaddr.sun_len = len = SUN_LEN(&sunaddr)+1;
53#else /* HAVE_SUN_LEN_IN_SOCKADDR_UN */
54 len = SUN_LEN(&sunaddr)+1;
55#endif /* HAVE_SUN_LEN_IN_SOCKADDR_UN */
51 56
52 sock = socket(AF_UNIX, SOCK_STREAM, 0); 57 sock = socket(AF_UNIX, SOCK_STREAM, 0);
53 if (sock < 0) 58 if (sock < 0)
@@ -58,13 +63,67 @@ ssh_get_authentication_socket()
58 close(sock); 63 close(sock);
59 return -1; 64 return -1;
60 } 65 }
61 if (connect(sock, (struct sockaddr *) & sunaddr, sizeof(sunaddr)) < 0) { 66 if (connect(sock, (struct sockaddr *) & sunaddr, len) < 0) {
62 close(sock); 67 close(sock);
63 return -1; 68 return -1;
64 } 69 }
65 return sock; 70 return sock;
66} 71}
67 72
73int
74ssh_request_reply(AuthenticationConnection *auth,
75 Buffer *request, Buffer *reply)
76{
77 int l, len;
78 char buf[1024];
79
80 /* Get the length of the message, and format it in the buffer. */
81 len = buffer_len(request);
82 PUT_32BIT(buf, len);
83
84 /* Send the length and then the packet to the agent. */
85 if (atomicio(write, auth->fd, buf, 4) != 4 ||
86 atomicio(write, auth->fd, buffer_ptr(request),
87 buffer_len(request)) != buffer_len(request)) {
88 error("Error writing to authentication socket.");
89 return 0;
90 }
91 /*
92 * Wait for response from the agent. First read the length of the
93 * response packet.
94 */
95 len = 4;
96 while (len > 0) {
97 l = read(auth->fd, buf + 4 - len, len);
98 if (l <= 0) {
99 error("Error reading response length from authentication socket.");
100 return 0;
101 }
102 len -= l;
103 }
104
105 /* Extract the length, and check it for sanity. */
106 len = GET_32BIT(buf);
107 if (len > 256 * 1024)
108 fatal("Authentication response too long: %d", len);
109
110 /* Read the rest of the response in to the buffer. */
111 buffer_clear(reply);
112 while (len > 0) {
113 l = len;
114 if (l > sizeof(buf))
115 l = sizeof(buf);
116 l = read(auth->fd, buf, l);
117 if (l <= 0) {
118 error("Error reading response from authentication socket.");
119 return 0;
120 }
121 buffer_append(reply, (char *) buf, l);
122 len -= l;
123 }
124 return 1;
125}
126
68/* 127/*
69 * Closes the agent socket if it should be closed (depends on how it was 128 * Closes the agent socket if it should be closed (depends on how it was
70 * obtained). The argument must have been returned by 129 * obtained). The argument must have been returned by
@@ -133,62 +192,35 @@ ssh_close_authentication_connection(AuthenticationConnection *ac)
133 192
134int 193int
135ssh_get_first_identity(AuthenticationConnection *auth, 194ssh_get_first_identity(AuthenticationConnection *auth,
136 BIGNUM *e, BIGNUM *n, char **comment) 195 BIGNUM *e, BIGNUM *n, char **comment)
137{ 196{
138 unsigned char msg[8192]; 197 Buffer request;
139 int len, l; 198 int type;
140 199
141 /* 200 /*
142 * Send a message to the agent requesting for a list of the 201 * Send a message to the agent requesting for a list of the
143 * identities it can represent. 202 * identities it can represent.
144 */ 203 */
145 PUT_32BIT(msg, 1); 204 buffer_init(&request);
146 msg[4] = SSH_AGENTC_REQUEST_RSA_IDENTITIES; 205 buffer_put_char(&request, SSH_AGENTC_REQUEST_RSA_IDENTITIES);
147 if (atomicio(write, auth->fd, msg, 5) != 5) {
148 error("write auth->fd: %.100s", strerror(errno));
149 return 0;
150 }
151 /* Read the length of the response. XXX implement timeouts here. */
152 len = 4;
153 while (len > 0) {
154 l = read(auth->fd, msg + 4 - len, len);
155 if (l <= 0) {
156 error("read auth->fd: %.100s", strerror(errno));
157 return 0;
158 }
159 len -= l;
160 }
161
162 /*
163 * Extract the length, and check it for sanity. (We cannot trust
164 * authentication agents).
165 */
166 len = GET_32BIT(msg);
167 if (len < 1 || len > 256 * 1024)
168 fatal("Authentication reply message too long: %d\n", len);
169 206
170 /* Read the packet itself. */
171 buffer_clear(&auth->identities); 207 buffer_clear(&auth->identities);
172 while (len > 0) { 208 if (ssh_request_reply(auth, &request, &auth->identities) == 0) {
173 l = len; 209 buffer_free(&request);
174 if (l > sizeof(msg)) 210 return 0;
175 l = sizeof(msg);
176 l = read(auth->fd, msg, l);
177 if (l <= 0)
178 fatal("Incomplete authentication reply.");
179 buffer_append(&auth->identities, (char *) msg, l);
180 len -= l;
181 } 211 }
212 buffer_free(&request);
182 213
183 /* Get message type, and verify that we got a proper answer. */ 214 /* Get message type, and verify that we got a proper answer. */
184 buffer_get(&auth->identities, (char *) msg, 1); 215 type = buffer_get_char(&auth->identities);
185 if (msg[0] != SSH_AGENT_RSA_IDENTITIES_ANSWER) 216 if (type != SSH_AGENT_RSA_IDENTITIES_ANSWER)
186 fatal("Bad authentication reply message type: %d", msg[0]); 217 fatal("Bad authentication reply message type: %d", type);
187 218
188 /* Get the number of entries in the response and check it for sanity. */ 219 /* Get the number of entries in the response and check it for sanity. */
189 auth->howmany = buffer_get_int(&auth->identities); 220 auth->howmany = buffer_get_int(&auth->identities);
190 if (auth->howmany > 1024) 221 if (auth->howmany > 1024)
191 fatal("Too many identities in authentication reply: %d\n", auth->howmany); 222 fatal("Too many identities in authentication reply: %d\n",
223 auth->howmany);
192 224
193 /* Return the first entry (if any). */ 225 /* Return the first entry (if any). */
194 return ssh_get_next_identity(auth, e, n, comment); 226 return ssh_get_next_identity(auth, e, n, comment);
@@ -203,7 +235,7 @@ ssh_get_first_identity(AuthenticationConnection *auth,
203 235
204int 236int
205ssh_get_next_identity(AuthenticationConnection *auth, 237ssh_get_next_identity(AuthenticationConnection *auth,
206 BIGNUM *e, BIGNUM *n, char **comment) 238 BIGNUM *e, BIGNUM *n, char **comment)
207{ 239{
208 unsigned int bits; 240 unsigned int bits;
209 241
@@ -240,23 +272,22 @@ ssh_get_next_identity(AuthenticationConnection *auth,
240 272
241int 273int
242ssh_decrypt_challenge(AuthenticationConnection *auth, 274ssh_decrypt_challenge(AuthenticationConnection *auth,
243 BIGNUM* e, BIGNUM *n, BIGNUM *challenge, 275 BIGNUM* e, BIGNUM *n, BIGNUM *challenge,
244 unsigned char session_id[16], 276 unsigned char session_id[16],
245 unsigned int response_type, 277 unsigned int response_type,
246 unsigned char response[16]) 278 unsigned char response[16])
247{ 279{
248 Buffer buffer; 280 Buffer buffer;
249 unsigned char buf[8192]; 281 int success = 0;
250 int len, l, i; 282 int i;
283 int type;
251 284
252 /* Response type 0 is no longer supported. */
253 if (response_type == 0) 285 if (response_type == 0)
254 fatal("Compatibility with ssh protocol version 1.0 no longer supported."); 286 fatal("Compatibility with ssh protocol version "
287 "1.0 no longer supported.");
255 288
256 /* Format a message to the agent. */
257 buf[0] = SSH_AGENTC_RSA_CHALLENGE;
258 buffer_init(&buffer); 289 buffer_init(&buffer);
259 buffer_append(&buffer, (char *) buf, 1); 290 buffer_put_char(&buffer, SSH_AGENTC_RSA_CHALLENGE);
260 buffer_put_int(&buffer, BN_num_bits(n)); 291 buffer_put_int(&buffer, BN_num_bits(n));
261 buffer_put_bignum(&buffer, e); 292 buffer_put_bignum(&buffer, e);
262 buffer_put_bignum(&buffer, n); 293 buffer_put_bignum(&buffer, n);
@@ -264,77 +295,27 @@ ssh_decrypt_challenge(AuthenticationConnection *auth,
264 buffer_append(&buffer, (char *) session_id, 16); 295 buffer_append(&buffer, (char *) session_id, 16);
265 buffer_put_int(&buffer, response_type); 296 buffer_put_int(&buffer, response_type);
266 297
267 /* Get the length of the message, and format it in the buffer. */ 298 if (ssh_request_reply(auth, &buffer, &buffer) == 0) {
268 len = buffer_len(&buffer);
269 PUT_32BIT(buf, len);
270
271 /* Send the length and then the packet to the agent. */
272 if (atomicio(write, auth->fd, buf, 4) != 4 ||
273 atomicio(write, auth->fd, buffer_ptr(&buffer),
274 buffer_len(&buffer)) != buffer_len(&buffer)) {
275 error("Error writing to authentication socket.");
276error_cleanup:
277 buffer_free(&buffer); 299 buffer_free(&buffer);
278 return 0; 300 return 0;
279 } 301 }
280 /* 302 type = buffer_get_char(&buffer);
281 * Wait for response from the agent. First read the length of the
282 * response packet.
283 */
284 len = 4;
285 while (len > 0) {
286 l = read(auth->fd, buf + 4 - len, len);
287 if (l <= 0) {
288 error("Error reading response length from authentication socket.");
289 goto error_cleanup;
290 }
291 len -= l;
292 }
293
294 /* Extract the length, and check it for sanity. */
295 len = GET_32BIT(buf);
296 if (len > 256 * 1024)
297 fatal("Authentication response too long: %d", len);
298
299 /* Read the rest of the response in tothe buffer. */
300 buffer_clear(&buffer);
301 while (len > 0) {
302 l = len;
303 if (l > sizeof(buf))
304 l = sizeof(buf);
305 l = read(auth->fd, buf, l);
306 if (l <= 0) {
307 error("Error reading response from authentication socket.");
308 goto error_cleanup;
309 }
310 buffer_append(&buffer, (char *) buf, l);
311 len -= l;
312 }
313
314 /* Get the type of the packet. */
315 buffer_get(&buffer, (char *) buf, 1);
316 303
317 /* Check for agent failure message. */ 304 if (type == SSH_AGENT_FAILURE) {
318 if (buf[0] == SSH_AGENT_FAILURE) {
319 log("Agent admitted failure to authenticate using the key."); 305 log("Agent admitted failure to authenticate using the key.");
320 goto error_cleanup; 306 } else if (type != SSH_AGENT_RSA_RESPONSE) {
307 fatal("Bad authentication response: %d", type);
308 } else {
309 success = 1;
310 /*
311 * Get the response from the packet. This will abort with a
312 * fatal error if the packet is corrupt.
313 */
314 for (i = 0; i < 16; i++)
315 response[i] = buffer_get_char(&buffer);
321 } 316 }
322 /* Now it must be an authentication response packet. */
323 if (buf[0] != SSH_AGENT_RSA_RESPONSE)
324 fatal("Bad authentication response: %d", buf[0]);
325
326 /*
327 * Get the response from the packet. This will abort with a fatal
328 * error if the packet is corrupt.
329 */
330 for (i = 0; i < 16; i++)
331 response[i] = buffer_get_char(&buffer);
332
333 /* The buffer containing the packet is no longer needed. */
334 buffer_free(&buffer); 317 buffer_free(&buffer);
335 318 return success;
336 /* Correct answer. */
337 return 1;
338} 319}
339 320
340/* Encode key for a message to the agent. */ 321/* Encode key for a message to the agent. */
@@ -378,8 +359,7 @@ int
378ssh_add_identity(AuthenticationConnection *auth, Key *key, const char *comment) 359ssh_add_identity(AuthenticationConnection *auth, Key *key, const char *comment)
379{ 360{
380 Buffer buffer; 361 Buffer buffer;
381 unsigned char buf[8192]; 362 int type;
382 int len;
383 363
384 buffer_init(&buffer); 364 buffer_init(&buffer);
385 365
@@ -395,21 +375,13 @@ ssh_add_identity(AuthenticationConnection *auth, Key *key, const char *comment)
395 return 0; 375 return 0;
396 break; 376 break;
397 } 377 }
398 378 if (ssh_request_reply(auth, &buffer, &buffer) == 0) {
399 /* Get the length of the message, and format it in the buffer. */
400 len = buffer_len(&buffer);
401 PUT_32BIT(buf, len);
402
403 /* Send the length and then the packet to the agent. */
404 if (atomicio(write, auth->fd, buf, 4) != 4 ||
405 atomicio(write, auth->fd, buffer_ptr(&buffer),
406 buffer_len(&buffer)) != buffer_len(&buffer)) {
407 error("Error writing to authentication socket.");
408 buffer_free(&buffer); 379 buffer_free(&buffer);
409 return 0; 380 return 0;
410 } 381 }
382 type = buffer_get_char(&buffer);
411 buffer_free(&buffer); 383 buffer_free(&buffer);
412 return ssh_agent_get_reply(auth); 384 return decode_reply(type);
413} 385}
414 386
415/* 387/*
@@ -421,30 +393,21 @@ int
421ssh_remove_identity(AuthenticationConnection *auth, RSA *key) 393ssh_remove_identity(AuthenticationConnection *auth, RSA *key)
422{ 394{
423 Buffer buffer; 395 Buffer buffer;
424 unsigned char buf[5]; 396 int type;
425 int len;
426 397
427 /* Format a message to the agent. */
428 buffer_init(&buffer); 398 buffer_init(&buffer);
429 buffer_put_char(&buffer, SSH_AGENTC_REMOVE_RSA_IDENTITY); 399 buffer_put_char(&buffer, SSH_AGENTC_REMOVE_RSA_IDENTITY);
430 buffer_put_int(&buffer, BN_num_bits(key->n)); 400 buffer_put_int(&buffer, BN_num_bits(key->n));
431 buffer_put_bignum(&buffer, key->e); 401 buffer_put_bignum(&buffer, key->e);
432 buffer_put_bignum(&buffer, key->n); 402 buffer_put_bignum(&buffer, key->n);
433 403
434 /* Get the length of the message, and format it in the buffer. */ 404 if (ssh_request_reply(auth, &buffer, &buffer) == 0) {
435 len = buffer_len(&buffer);
436 PUT_32BIT(buf, len);
437
438 /* Send the length and then the packet to the agent. */
439 if (atomicio(write, auth->fd, buf, 4) != 4 ||
440 atomicio(write, auth->fd, buffer_ptr(&buffer),
441 buffer_len(&buffer)) != buffer_len(&buffer)) {
442 error("Error writing to authentication socket.");
443 buffer_free(&buffer); 405 buffer_free(&buffer);
444 return 0; 406 return 0;
445 } 407 }
408 type = buffer_get_char(&buffer);
446 buffer_free(&buffer); 409 buffer_free(&buffer);
447 return ssh_agent_get_reply(auth); 410 return decode_reply(type);
448} 411}
449 412
450/* 413/*
@@ -455,73 +418,27 @@ ssh_remove_identity(AuthenticationConnection *auth, RSA *key)
455int 418int
456ssh_remove_all_identities(AuthenticationConnection *auth) 419ssh_remove_all_identities(AuthenticationConnection *auth)
457{ 420{
458 unsigned char buf[5]; 421 Buffer buffer;
422 int type;
459 423
460 /* Get the length of the message, and format it in the buffer. */ 424 buffer_init(&buffer);
461 PUT_32BIT(buf, 1); 425 buffer_put_char(&buffer, SSH_AGENTC_REMOVE_ALL_RSA_IDENTITIES);
462 buf[4] = SSH_AGENTC_REMOVE_ALL_RSA_IDENTITIES;
463 426
464 /* Send the length and then the packet to the agent. */ 427 if (ssh_request_reply(auth, &buffer, &buffer) == 0) {
465 if (atomicio(write, auth->fd, buf, 5) != 5) { 428 buffer_free(&buffer);
466 error("Error writing to authentication socket.");
467 return 0; 429 return 0;
468 } 430 }
469 return ssh_agent_get_reply(auth); 431 type = buffer_get_char(&buffer);
432 buffer_free(&buffer);
433 return decode_reply(type);
470} 434}
471 435
472/*
473 * Read for reply from agent. returns 1 for success, 0 on error
474 */
475
476int 436int
477ssh_agent_get_reply(AuthenticationConnection *auth) 437decode_reply(int type)
478{ 438{
479 Buffer buffer;
480 unsigned char buf[8192];
481 int len, l, type;
482
483 /*
484 * Wait for response from the agent. First read the length of the
485 * response packet.
486 */
487 len = 4;
488 while (len > 0) {
489 l = read(auth->fd, buf + 4 - len, len);
490 if (l <= 0) {
491 error("Error reading response length from authentication socket.");
492 buffer_free(&buffer);
493 return 0;
494 }
495 len -= l;
496 }
497
498 /* Extract the length, and check it for sanity. */
499 len = GET_32BIT(buf);
500 if (len > 256 * 1024)
501 fatal("Response from agent too long: %d", len);
502
503 /* Read the rest of the response in to the buffer. */
504 buffer_init(&buffer);
505 while (len > 0) {
506 l = len;
507 if (l > sizeof(buf))
508 l = sizeof(buf);
509 l = read(auth->fd, buf, l);
510 if (l <= 0) {
511 error("Error reading response from authentication socket.");
512 buffer_free(&buffer);
513 return 0;
514 }
515 buffer_append(&buffer, (char *) buf, l);
516 len -= l;
517 }
518
519 /* Get the type of the packet. */
520 type = buffer_get_char(&buffer);
521 buffer_free(&buffer);
522 switch (type) { 439 switch (type) {
523 case SSH_AGENT_FAILURE: 440 case SSH_AGENT_FAILURE:
524log("SSH_AGENT_FAILURE"); 441 log("SSH_AGENT_FAILURE");
525 return 0; 442 return 0;
526 case SSH_AGENT_SUCCESS: 443 case SSH_AGENT_SUCCESS:
527 return 1; 444 return 1;
diff --git a/bsd-mktemp.c b/bsd-mktemp.c
index 7c02ea1a2..23831fa91 100644
--- a/bsd-mktemp.c
+++ b/bsd-mktemp.c
@@ -52,6 +52,7 @@ static char rcsid[] = "$OpenBSD: mktemp.c,v 1.13 1998/06/30 23:03:13 deraadt Exp
52#include <unistd.h> 52#include <unistd.h>
53 53
54#include "bsd-misc.h" 54#include "bsd-misc.h"
55#include "bsd-arc4random.h"
55 56
56static int _gettemp(char *, int *, int, int); 57static int _gettemp(char *, int *, int, int);
57 58
diff --git a/configure.in b/configure.in
index 974d0df6b..e9467011b 100644
--- a/configure.in
+++ b/configure.in
@@ -686,6 +686,22 @@ OSSH_CHECK_HEADER_FOR_FIELD(ut_time, utmp.h, HAVE_TIME_IN_UTMP)
686OSSH_CHECK_HEADER_FOR_FIELD(ut_time, utmpx.h, HAVE_TIME_IN_UTMPX) 686OSSH_CHECK_HEADER_FOR_FIELD(ut_time, utmpx.h, HAVE_TIME_IN_UTMPX)
687OSSH_CHECK_HEADER_FOR_FIELD(ut_tv, utmpx.h, HAVE_TV_IN_UTMPX) 687OSSH_CHECK_HEADER_FOR_FIELD(ut_tv, utmpx.h, HAVE_TV_IN_UTMPX)
688 688
689AC_CACHE_CHECK([for sun_len field in struct sockaddr_un],
690 ac_cv_have_sun_len_in_struct_sockaddr_un, [
691 AC_TRY_COMPILE(
692 [
693#include <sys/types.h>
694#include <sys/socket.h>
695 ],
696 [ struct sockaddr_un s; s.sun_len = 1; ],
697 [ ac_cv_have_sun_len_in_struct_sockaddr_un="yes" ],
698 [ ac_cv_have_sun_len_in_struct_sockaddr_un="no" ],
699 )
700])
701if test "x$ac_cv_have_sun_len_in_struct_sockaddr_un" = "xyes" ; then
702 AC_DEFINE(HAVE_SUN_LEN_IN_SOCKADDR_UN)
703fi
704
689AC_CACHE_CHECK([for ss_family field in struct sockaddr_storage], 705AC_CACHE_CHECK([for ss_family field in struct sockaddr_storage],
690 ac_cv_have_ss_family_in_struct_ss, [ 706 ac_cv_have_ss_family_in_struct_ss, [
691 AC_TRY_COMPILE( 707 AC_TRY_COMPILE(
diff --git a/readconf.c b/readconf.c
index 06cfaa1a3..f31b1c4e6 100644
--- a/readconf.c
+++ b/readconf.c
@@ -14,7 +14,7 @@
14 */ 14 */
15 15
16#include "includes.h" 16#include "includes.h"
17RCSID("$OpenBSD: readconf.c,v 1.43 2000/07/14 22:59:46 markus Exp $"); 17RCSID("$OpenBSD: readconf.c,v 1.45 2000/08/02 17:27:04 provos Exp $");
18 18
19#include "ssh.h" 19#include "ssh.h"
20#include "cipher.h" 20#include "cipher.h"
diff --git a/servconf.c b/servconf.c
index 477204cfd..6affb51e9 100644
--- a/servconf.c
+++ b/servconf.c
@@ -12,7 +12,7 @@
12 */ 12 */
13 13
14#include "includes.h" 14#include "includes.h"
15RCSID("$OpenBSD: servconf.c,v 1.49 2000/07/14 22:59:46 markus Exp $"); 15RCSID("$OpenBSD: servconf.c,v 1.50 2000/07/22 09:14:36 markus Exp $");
16 16
17#include "ssh.h" 17#include "ssh.h"
18#include "servconf.h" 18#include "servconf.h"
@@ -76,6 +76,8 @@ initialize_server_options(ServerOptions *options)
76 options->protocol = SSH_PROTO_UNKNOWN; 76 options->protocol = SSH_PROTO_UNKNOWN;
77 options->gateway_ports = -1; 77 options->gateway_ports = -1;
78 options->num_subsystems = 0; 78 options->num_subsystems = 0;
79 options->max_startups_begin = -1;
80 options->max_startups_rate = -1;
79 options->max_startups = -1; 81 options->max_startups = -1;
80} 82}
81 83
@@ -162,6 +164,10 @@ fill_default_server_options(ServerOptions *options)
162 options->gateway_ports = 0; 164 options->gateway_ports = 0;
163 if (options->max_startups == -1) 165 if (options->max_startups == -1)
164 options->max_startups = 10; 166 options->max_startups = 10;
167 if (options->max_startups_rate == -1)
168 options->max_startups_rate = 100; /* 100% */
169 if (options->max_startups_begin == -1)
170 options->max_startups_begin = options->max_startups;
165} 171}
166 172
167/* Keyword tokens. */ 173/* Keyword tokens. */
@@ -644,6 +650,22 @@ parse_flag:
644 break; 650 break;
645 651
646 case sMaxStartups: 652 case sMaxStartups:
653 arg = strdelim(&cp);
654 if (!arg || *arg == '\0')
655 fatal("%s line %d: Missing MaxStartups spec.",
656 filename, linenum);
657 if (sscanf(arg, "%d:%d:%d",
658 &options->max_startups_begin,
659 &options->max_startups_rate,
660 &options->max_startups) == 3) {
661 if (options->max_startups_begin >
662 options->max_startups ||
663 options->max_startups_rate > 100 ||
664 options->max_startups_rate < 1)
665 fatal("%s line %d: Illegal MaxStartups spec.",
666 filename, linenum);
667 break;
668 }
647 intptr = &options->max_startups; 669 intptr = &options->max_startups;
648 goto parse_int; 670 goto parse_int;
649 671
diff --git a/servconf.h b/servconf.h
index 95593722d..3b65c6a6f 100644
--- a/servconf.h
+++ b/servconf.h
@@ -13,7 +13,7 @@
13 * 13 *
14 */ 14 */
15 15
16/* RCSID("$OpenBSD: servconf.h,v 1.26 2000/06/26 21:59:18 markus Exp $"); */ 16/* RCSID("$OpenBSD: servconf.h,v 1.27 2000/07/22 09:14:36 markus Exp $"); */
17 17
18#ifndef SERVCONF_H 18#ifndef SERVCONF_H
19#define SERVCONF_H 19#define SERVCONF_H
@@ -100,6 +100,8 @@ typedef struct {
100 char *subsystem_name[MAX_SUBSYSTEMS]; 100 char *subsystem_name[MAX_SUBSYSTEMS];
101 char *subsystem_command[MAX_SUBSYSTEMS]; 101 char *subsystem_command[MAX_SUBSYSTEMS];
102 102
103 int max_startups_begin;
104 int max_startups_rate;
103 int max_startups; 105 int max_startups;
104 106
105} ServerOptions; 107} ServerOptions;
diff --git a/session.c b/session.c
index e68718a7e..d65b06984 100644
--- a/session.c
+++ b/session.c
@@ -8,7 +8,7 @@
8 */ 8 */
9 9
10#include "includes.h" 10#include "includes.h"
11RCSID("$OpenBSD: session.c,v 1.23 2000/07/11 08:11:33 deraadt Exp $"); 11RCSID("$OpenBSD: session.c,v 1.25 2000/08/17 20:06:34 markus Exp $");
12 12
13#include "xmalloc.h" 13#include "xmalloc.h"
14#include "ssh.h" 14#include "ssh.h"
@@ -85,6 +85,7 @@ void session_pty_cleanup(Session *s);
85void session_proctitle(Session *s); 85void session_proctitle(Session *s);
86void do_exec_pty(Session *s, const char *command, struct passwd * pw); 86void do_exec_pty(Session *s, const char *command, struct passwd * pw);
87void do_exec_no_pty(Session *s, const char *command, struct passwd * pw); 87void do_exec_no_pty(Session *s, const char *command, struct passwd * pw);
88void do_login(Session *s);
88 89
89void 90void
90do_child(const char *command, struct passwd * pw, const char *term, 91do_child(const char *command, struct passwd * pw, const char *term,
@@ -101,6 +102,7 @@ static const char *__progname = "sshd";
101 102
102extern int log_stderr; 103extern int log_stderr;
103extern int debug_flag; 104extern int debug_flag;
105extern unsigned int utmp_len;
104 106
105extern int startup_pipe; 107extern int startup_pipe;
106 108
@@ -523,35 +525,14 @@ do_exec_no_pty(Session *s, const char *command, struct passwd * pw)
523void 525void
524do_exec_pty(Session *s, const char *command, struct passwd * pw) 526do_exec_pty(Session *s, const char *command, struct passwd * pw)
525{ 527{
526 FILE *f;
527 char buf[100], *time_string;
528 char line[256];
529 const char *hostname;
530 int fdout, ptyfd, ttyfd, ptymaster; 528 int fdout, ptyfd, ttyfd, ptymaster;
531 int quiet_login;
532 pid_t pid; 529 pid_t pid;
533 socklen_t fromlen;
534 struct sockaddr_storage from;
535 struct stat st;
536 time_t last_login_time;
537 530
538 if (s == NULL) 531 if (s == NULL)
539 fatal("do_exec_pty: no session"); 532 fatal("do_exec_pty: no session");
540 ptyfd = s->ptyfd; 533 ptyfd = s->ptyfd;
541 ttyfd = s->ttyfd; 534 ttyfd = s->ttyfd;
542 535
543 /* Get remote host name. */
544 hostname = get_canonical_hostname();
545
546 /*
547 * Get the time when the user last logged in. Buf will be set to
548 * contain the hostname the last login was from.
549 */
550 if (!options.use_login) {
551 last_login_time = get_last_login_time(pw->pw_uid, pw->pw_name,
552 buf, sizeof(buf));
553 }
554
555#ifdef USE_PAM 536#ifdef USE_PAM
556 do_pam_session(pw->pw_name, s->tty); 537 do_pam_session(pw->pw_name, s->tty);
557 do_pam_setcred(); 538 do_pam_setcred();
@@ -559,10 +540,7 @@ do_exec_pty(Session *s, const char *command, struct passwd * pw)
559 540
560 /* Fork the child. */ 541 /* Fork the child. */
561 if ((pid = fork()) == 0) { 542 if ((pid = fork()) == 0) {
562 pid = getpid(); 543 /* Child. Reinitialize the log because the pid has changed. */
563
564 /* Child. Reinitialize the log because the pid has
565 changed. */
566 log_init(__progname, options.log_level, options.log_facility, log_stderr); 544 log_init(__progname, options.log_level, options.log_facility, log_stderr);
567 545
568 /* Close the master side of the pseudo tty. */ 546 /* Close the master side of the pseudo tty. */
@@ -586,82 +564,10 @@ do_exec_pty(Session *s, const char *command, struct passwd * pw)
586 /* Close the extra descriptor for the pseudo tty. */ 564 /* Close the extra descriptor for the pseudo tty. */
587 close(ttyfd); 565 close(ttyfd);
588 566
589/* XXXX ? move to do_child() ??*/ 567 /* record login, etc. similar to login(1) */
590 /* 568 if (command == NULL && !options.use_login)
591 * Get IP address of client. This is needed because we want 569 do_login(s);
592 * to record where the user logged in from. If the
593 * connection is not a socket, let the ip address be 0.0.0.0.
594 */
595 memset(&from, 0, sizeof(from));
596 if (packet_connection_is_on_socket()) {
597 fromlen = sizeof(from);
598 if (getpeername(packet_get_connection_in(),
599 (struct sockaddr *) & from, &fromlen) < 0) {
600 debug("getpeername: %.100s", strerror(errno));
601 fatal_cleanup();
602 }
603 }
604 /* Record that there was a login on that terminal. */
605 if (!options.use_login || command != NULL)
606 record_login(pid, s->tty, pw->pw_name, pw->pw_uid,
607 hostname, (struct sockaddr *)&from);
608
609 /* Check if .hushlogin exists. */
610 snprintf(line, sizeof line, "%.200s/.hushlogin", pw->pw_dir);
611 quiet_login = stat(line, &st) >= 0;
612 570
613#ifdef USE_PAM
614 if (!quiet_login)
615 print_pam_messages();
616#endif /* USE_PAM */
617
618 /*
619 * If the user has logged in before, display the time of last
620 * login. However, don't display anything extra if a command
621 * has been specified (so that ssh can be used to execute
622 * commands on a remote machine without users knowing they
623 * are going to another machine). Login(1) will do this for
624 * us as well, so check if login(1) is used
625 */
626 if (command == NULL && last_login_time != 0 && !quiet_login &&
627 !options.use_login) {
628 /* Convert the date to a string. */
629 time_string = ctime(&last_login_time);
630 /* Remove the trailing newline. */
631 if (strchr(time_string, '\n'))
632 *strchr(time_string, '\n') = 0;
633 /* Display the last login time. Host if displayed
634 if known. */
635 if (strcmp(buf, "") == 0)
636 printf("Last login: %s\r\n", time_string);
637 else
638 printf("Last login: %s from %s\r\n", time_string, buf);
639 }
640 /*
641 * Print /etc/motd unless a command was specified or printing
642 * it was disabled in server options or login(1) will be
643 * used. Note that some machines appear to print it in
644 * /etc/profile or similar.
645 */
646 if (command == NULL && options.print_motd && !quiet_login &&
647 !options.use_login) {
648 /* Print /etc/motd if it exists. */
649 f = fopen("/etc/motd", "r");
650 if (f) {
651 while (fgets(line, sizeof(line), f))
652 fputs(line, stdout);
653 fclose(f);
654 }
655 }
656#if defined(WITH_AIXAUTHENTICATE)
657 /*
658 * AIX handles the lastlog info differently. Display it here.
659 */
660 if (command == NULL && aixloginmsg && *aixloginmsg &&
661 !quiet_login && !options.use_login) {
662 printf("%s\n", aixloginmsg);
663 }
664#endif
665 /* Do common processing for the child, such as execing the command. */ 571 /* Do common processing for the child, such as execing the command. */
666 do_child(command, pw, s->term, s->display, s->auth_proto, 572 do_child(command, pw, s->term, s->display, s->auth_proto,
667 s->auth_data, s->tty); 573 s->auth_data, s->tty);
@@ -699,6 +605,87 @@ do_exec_pty(Session *s, const char *command, struct passwd * pw)
699 } 605 }
700} 606}
701 607
608const char *
609get_remote_name_or_ip(void)
610{
611 static const char *remote = "";
612 if (utmp_len > 0)
613 remote = get_canonical_hostname();
614 if (utmp_len == 0 || strlen(remote) > utmp_len)
615 remote = get_remote_ipaddr();
616 return remote;
617}
618
619/* administrative, login(1)-like work */
620void
621do_login(Session *s)
622{
623 FILE *f;
624 char *time_string;
625 char buf[256];
626 socklen_t fromlen;
627 struct sockaddr_storage from;
628 struct stat st;
629 time_t last_login_time;
630 struct passwd * pw = s->pw;
631 pid_t pid = getpid();
632
633 /*
634 * Get IP address of client. If the connection is not a socket, let
635 * the address be 0.0.0.0.
636 */
637 memset(&from, 0, sizeof(from));
638 if (packet_connection_is_on_socket()) {
639 fromlen = sizeof(from);
640 if (getpeername(packet_get_connection_in(),
641 (struct sockaddr *) & from, &fromlen) < 0) {
642 debug("getpeername: %.100s", strerror(errno));
643 fatal_cleanup();
644 }
645 }
646
647 /* Record that there was a login on that tty from the remote host. */
648 record_login(pid, s->tty, pw->pw_name, pw->pw_uid,
649 get_remote_name_or_ip(), (struct sockaddr *)&from);
650
651 /* Done if .hushlogin exists. */
652 snprintf(buf, sizeof(buf), "%.200s/.hushlogin", pw->pw_dir);
653 if (stat(buf, &st) >= 0)
654 return;
655
656#ifdef USE_PAM
657 print_pam_messages();
658#endif /* USE_PAM */
659#ifdef WITH_AIXAUTHENTICATE
660 if (aixloginmsg && *aixloginmsg)
661 printf("%s\n", aixloginmsg);
662#endif /* WITH_AIXAUTHENTICATE */
663
664 /*
665 * Get the time when the user last logged in. 'buf' will be set
666 * to contain the hostname the last login was from.
667 */
668 last_login_time = get_last_login_time(pw->pw_uid, pw->pw_name,
669 buf, sizeof(buf));
670 if (last_login_time != 0) {
671 time_string = ctime(&last_login_time);
672 if (strchr(time_string, '\n'))
673 *strchr(time_string, '\n') = 0;
674 if (strcmp(buf, "") == 0)
675 printf("Last login: %s\r\n", time_string);
676 else
677 printf("Last login: %s from %s\r\n", time_string, buf);
678 }
679 if (options.print_motd) {
680 f = fopen("/etc/motd", "r");
681 if (f) {
682 while (fgets(buf, sizeof(buf), f))
683 fputs(buf, stdout);
684 fclose(f);
685 }
686 }
687}
688
702/* 689/*
703 * Sets the value of the given variable in the environment. If the variable 690 * Sets the value of the given variable in the environment. If the variable
704 * already exists, its value is overriden. 691 * already exists, its value is overriden.
@@ -1265,8 +1252,9 @@ do_child(const char *command, struct passwd * pw, const char *term,
1265 } else { 1252 } else {
1266 /* Launch login(1). */ 1253 /* Launch login(1). */
1267 1254
1268 execl(LOGIN_PROGRAM, "login", "-h", get_remote_ipaddr(), 1255 execl(LOGIN_PROGRAM, "login",
1269 "-p", "-f", "--", pw->pw_name, NULL); 1256 "-h", get_remote_name_or_ip(),
1257 "-p", "-f", "--", pw->pw_name, NULL);
1270 1258
1271 /* Login couldn't be executed, die. */ 1259 /* Login couldn't be executed, die. */
1272 1260
diff --git a/ssh.1 b/ssh.1
index cd56e7bef..39368e0ce 100644
--- a/ssh.1
+++ b/ssh.1
@@ -9,7 +9,7 @@
9.\" 9.\"
10.\" Created: Sat Apr 22 21:55:14 1995 ylo 10.\" Created: Sat Apr 22 21:55:14 1995 ylo
11.\" 11.\"
12.\" $Id: ssh.1,v 1.28 2000/06/07 09:55:44 djm Exp $ 12.\" $Id: ssh.1,v 1.29 2000/08/18 03:59:06 djm Exp $
13.\" 13.\"
14.Dd September 25, 1999 14.Dd September 25, 1999
15.Dt SSH 1 15.Dt SSH 1
@@ -994,7 +994,7 @@ If the current session has no tty,
994this variable is not set. 994this variable is not set.
995.It Ev TZ 995.It Ev TZ
996The timezone variable is set to indicate the present timezone if it 996The timezone variable is set to indicate the present timezone if it
997was set when the daemon was started (e.i., the daemon passes the value 997was set when the daemon was started (i.e., the daemon passes the value
998on to new connections). 998on to new connections).
999.It Ev USER 999.It Ev USER
1000Set to the name of the user logging in. 1000Set to the name of the user logging in.
diff --git a/sshd.8 b/sshd.8
index b6aefe491..c8b99df38 100644
--- a/sshd.8
+++ b/sshd.8
@@ -9,7 +9,7 @@
9.\" 9.\"
10.\" Created: Sat Apr 22 21:55:14 1995 ylo 10.\" Created: Sat Apr 22 21:55:14 1995 ylo
11.\" 11.\"
12.\" $Id: sshd.8,v 1.25 2000/07/11 07:31:39 djm Exp $ 12.\" $Id: sshd.8,v 1.26 2000/08/18 03:59:06 djm Exp $
13.\" 13.\"
14.Dd September 25, 1999 14.Dd September 25, 1999
15.Dt SSHD 8 15.Dt SSHD 8
@@ -26,6 +26,7 @@
26.Op Fl h Ar host_key_file 26.Op Fl h Ar host_key_file
27.Op Fl k Ar key_gen_time 27.Op Fl k Ar key_gen_time
28.Op Fl p Ar port 28.Op Fl p Ar port
29.Op Fl u Ar len
29.Op Fl V Ar client_protocol_id 30.Op Fl V Ar client_protocol_id
30.Sh DESCRIPTION 31.Sh DESCRIPTION
31.Nm 32.Nm
@@ -104,7 +105,7 @@ into the machine).
104.Pp 105.Pp
105.Ss SSH protocol version 2 106.Ss SSH protocol version 2
106.Pp 107.Pp
107Version 2 works similar: 108Version 2 works similarly:
108Each host has a host-specific DSA key used to identify the host. 109Each host has a host-specific DSA key used to identify the host.
109However, when the daemon starts, it does not generate a server key. 110However, when the daemon starts, it does not generate a server key.
110Forward security is provided through a Diffie-Hellman key agreement. 111Forward security is provided through a Diffie-Hellman key agreement.
@@ -211,6 +212,22 @@ Quiet mode.
211Nothing is sent to the system log. 212Nothing is sent to the system log.
212Normally the beginning, 213Normally the beginning,
213authentication, and termination of each connection is logged. 214authentication, and termination of each connection is logged.
215.It Fl u Ar len
216This option is used to specify the size of the field
217in the
218.Li utmp
219structure that holds the remote host name.
220If the resolved host name is longer than
221.Ar len ,
222the dotted decimal value will be used instead.
223This allows hosts with very long host names that
224overflow this field to still be uniquely identified.
225Specifying
226.Fl u0
227indicates that only dotted decimal addresses
228should be put into the
229.Pa utmp
230file.
214.It Fl Q 231.It Fl Q
215Do not print an error message if RSA support is missing. 232Do not print an error message if RSA support is missing.
216.It Fl V Ar client_protocol_id 233.It Fl V Ar client_protocol_id
@@ -257,7 +274,7 @@ and
257.Ql ? 274.Ql ?
258can be used as 275can be used as
259wildcards in the patterns. 276wildcards in the patterns.
260Only group names are valid, a numerical group ID isn't recognized. 277Only group names are valid; a numerical group ID isn't recognized.
261By default login is allowed regardless of the primary group. 278By default login is allowed regardless of the primary group.
262.Pp 279.Pp
263.It Cm AllowUsers 280.It Cm AllowUsers
@@ -270,7 +287,7 @@ and
270.Ql ? 287.Ql ?
271can be used as 288can be used as
272wildcards in the patterns. 289wildcards in the patterns.
273Only user names are valid, a numerical user ID isn't recognized. 290Only user names are valid; a numerical user ID isn't recognized.
274By default login is allowed regardless of the user name. 291By default login is allowed regardless of the user name.
275.Pp 292.Pp
276.It Cm Ciphers 293.It Cm Ciphers
@@ -294,7 +311,7 @@ and
294.Ql ? 311.Ql ?
295can be used as 312can be used as
296wildcards in the patterns. 313wildcards in the patterns.
297Only group names are valid, a numerical group ID isn't recognized. 314Only group names are valid; a numerical group ID isn't recognized.
298By default login is allowed regardless of the primary group. 315By default login is allowed regardless of the primary group.
299.Pp 316.Pp
300.It Cm DenyUsers 317.It Cm DenyUsers
@@ -305,7 +322,7 @@ Login is disallowed for user names that match one of the patterns.
305and 322and
306.Ql ? 323.Ql ?
307can be used as wildcards in the patterns. 324can be used as wildcards in the patterns.
308Only user names are valid, a numerical user ID isn't recognized. 325Only user names are valid; a numerical user ID isn't recognized.
309By default login is allowed regardless of the user name. 326By default login is allowed regardless of the user name.
310.It Cm DSAAuthentication 327.It Cm DSAAuthentication
311Specifies whether DSA authentication is allowed. 328Specifies whether DSA authentication is allowed.
@@ -321,7 +338,7 @@ or
321.Dq no . 338.Dq no .
322The default is 339The default is
323.Dq no . 340.Dq no .
324.It Cm HostDsaKey 341.It Cm HostDSAKey
325Specifies the file containing the private DSA host key (default 342Specifies the file containing the private DSA host key (default
326.Pa /etc/ssh_host_dsa_key ) 343.Pa /etc/ssh_host_dsa_key )
327used by SSH protocol 2.0. 344used by SSH protocol 2.0.
@@ -383,7 +400,8 @@ Specifies whether Kerberos authentication is allowed.
383This can be in the form of a Kerberos ticket, or if 400This can be in the form of a Kerberos ticket, or if
384.Cm PasswordAuthentication 401.Cm PasswordAuthentication
385is yes, the password provided by the user will be validated through 402is yes, the password provided by the user will be validated through
386the Kerberos KDC. 403the Kerberos KDC. To use this option, the server needs a
404Kerberos servtab which allows the verification of the KDC's identity.
387Default is 405Default is
388.Dq yes . 406.Dq yes .
389.It Cm KerberosOrLocalPasswd 407.It Cm KerberosOrLocalPasswd
@@ -443,11 +461,28 @@ Additional connections will be dropped until authentication succeeds or the
443.Cm LoginGraceTime 461.Cm LoginGraceTime
444expires for a connection. 462expires for a connection.
445The default is 10. 463The default is 10.
464.Pp
465Alternatively, random early drop can be enabled by specifying
466the three colon separated values
467.Dq start:rate:full
468(e.g. "10:30:60").
469.Nm
470will refuse connection attempts with a probabillity of
471.Dq rate/100
472(30%)
473if there are currently
474.Dq start
475(10)
476unauthenticated connections.
477The probabillity increases linearly and all connection attempts
478are refused if the number of unauthenticated connections reaches
479.Dq full
480(60).
446.It Cm PasswordAuthentication 481.It Cm PasswordAuthentication
447Specifies whether password authentication is allowed. 482Specifies whether password authentication is allowed.
448The default is 483The default is
449.Dq yes . 484.Dq yes .
450Note that this option applies to both protocol version 1 and 2. 485Note that this option applies to both protocol versions 1 and 2.
451.It Cm PermitEmptyPasswords 486.It Cm PermitEmptyPasswords
452When password authentication is allowed, it specifies whether the 487When password authentication is allowed, it specifies whether the
453server allows login to accounts with empty password strings. 488server allows login to accounts with empty password strings.
@@ -568,7 +603,7 @@ Specifies whether
568is used for interactive login sessions. 603is used for interactive login sessions.
569Note that 604Note that
570.Xr login 1 605.Xr login 1
571is not never for remote command execution. 606is never used for remote command execution.
572The default is 607The default is
573.Dq no . 608.Dq no .
574.It Cm X11DisplayOffset 609.It Cm X11DisplayOffset
@@ -666,7 +701,7 @@ You don't want to type them in; instead, copy the
666.Pa identity.pub 701.Pa identity.pub
667file and edit it. 702file and edit it.
668.Pp 703.Pp
669The options (if present) consists of comma-separated option 704The options (if present) consist of comma-separated option
670specifications. 705specifications.
671No spaces are permitted, except within double quotes. 706No spaces are permitted, except within double quotes.
672The following option specifications are supported: 707The following option specifications are supported:
@@ -740,7 +775,7 @@ and
740files contain host public keys for all known hosts. 775files contain host public keys for all known hosts.
741The global file should 776The global file should
742be prepared by the administrator (optional), and the per-user file is 777be prepared by the administrator (optional), and the per-user file is
743maintained automatically: whenever the user connects an unknown host 778maintained automatically: whenever the user connects from an unknown host
744its key is added to the per-user file. 779its key is added to the per-user file.
745.Pp 780.Pp
746Each line in these files contains the following fields: hostnames, 781Each line in these files contains the following fields: hostnames,
@@ -815,7 +850,7 @@ Contains the process ID of the
815listening for connections (if there are several daemons running 850listening for connections (if there are several daemons running
816concurrently for different ports, this contains the pid of the one 851concurrently for different ports, this contains the pid of the one
817started last). 852started last).
818The contents of this file are not sensitive; it can be world-readable. 853The content of this file is not sensitive; it can be world-readable.
819.It Pa $HOME/.ssh/authorized_keys 854.It Pa $HOME/.ssh/authorized_keys
820Lists the RSA keys that can be used to log into the user's account. 855Lists the RSA keys that can be used to log into the user's account.
821This file must be readable by root (which may on some machines imply 856This 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
843authentication to check the public key of the host. 878authentication to check the public key of the host.
844The key must be listed in one of these files to be accepted. 879The key must be listed in one of these files to be accepted.
845The client uses the same files 880The client uses the same files
846to verify that the remote host is the one we intended to connect. 881to verify that the remote host is the one it intended to connect.
847These files should be writable only by root/the owner. 882These files should be writable only by root/the owner.
848.Pa /etc/ssh_known_hosts 883.Pa /etc/ssh_known_hosts
849should be world-readable, and 884should be world-readable, and
@@ -882,7 +917,7 @@ this file is exactly the same as for
882.Pa .rhosts . 917.Pa .rhosts .
883However, this file is 918However, this file is
884not used by rlogin and rshd, so using this permits access using SSH only. 919not used by rlogin and rshd, so using this permits access using SSH only.
885.Pa /etc/hosts.equiv 920.It Pa /etc/hosts.equiv
886This file is used during 921This file is used during
887.Pa .rhosts 922.Pa .rhosts
888authentication. 923authentication.
diff --git a/sshd.c b/sshd.c
index b6db074c8..ae02f2c40 100644
--- a/sshd.c
+++ b/sshd.c
@@ -14,7 +14,7 @@
14 */ 14 */
15 15
16#include "includes.h" 16#include "includes.h"
17RCSID("$OpenBSD: sshd.c,v 1.123 2000/07/18 01:25:01 djm Exp $"); 17RCSID("$OpenBSD: sshd.c,v 1.125 2000/08/17 20:06:34 markus Exp $");
18 18
19#include "xmalloc.h" 19#include "xmalloc.h"
20#include "rsa.h" 20#include "rsa.h"
@@ -139,6 +139,9 @@ unsigned char session_id[16];
139unsigned char *session_id2 = NULL; 139unsigned char *session_id2 = NULL;
140int session_id2_len = 0; 140int session_id2_len = 0;
141 141
142/* record remote hostname or ip */
143unsigned int utmp_len = MAXHOSTNAMELEN;
144
142/* Prototypes for various functions defined later in this file. */ 145/* Prototypes for various functions defined later in this file. */
143void do_ssh1_kex(); 146void do_ssh1_kex();
144void do_ssh2_kex(); 147void do_ssh2_kex();
@@ -400,6 +403,35 @@ destroy_sensitive_data(void)
400 key_free(sensitive_data.dsa_host_key); 403 key_free(sensitive_data.dsa_host_key);
401} 404}
402 405
406/*
407 * returns 1 if connection should be dropped, 0 otherwise.
408 * dropping starts at connection #max_startups_begin with a probability
409 * of (max_startups_rate/100). the probability increases linearly until
410 * all connections are dropped for startups > max_startups
411 */
412int
413drop_connection(int startups)
414{
415 double p, r;
416
417 if (startups < options.max_startups_begin)
418 return 0;
419 if (startups >= options.max_startups)
420 return 1;
421 if (options.max_startups_rate == 100)
422 return 1;
423
424 p = 100 - options.max_startups_rate;
425 p *= startups - options.max_startups_begin;
426 p /= (double) (options.max_startups - options.max_startups_begin);
427 p += options.max_startups_rate;
428 p /= 100.0;
429 r = arc4random() / (double) UINT_MAX;
430
431 debug("drop_connection: p %g, r %g", p, r);
432 return (r < p) ? 1 : 0;
433}
434
403int *startup_pipes = NULL; /* options.max_startup sized array of fd ints */ 435int *startup_pipes = NULL; /* options.max_startup sized array of fd ints */
404int startup_pipe; /* in child */ 436int startup_pipe; /* in child */
405 437
@@ -441,7 +473,7 @@ main(int ac, char **av)
441 initialize_server_options(&options); 473 initialize_server_options(&options);
442 474
443 /* Parse command-line arguments. */ 475 /* Parse command-line arguments. */
444 while ((opt = getopt(ac, av, "f:p:b:k:h:g:V:diqQ46")) != EOF) { 476 while ((opt = getopt(ac, av, "f:p:b:k:h:g:V:u:diqQ46")) != EOF) {
445 switch (opt) { 477 switch (opt) {
446 case '4': 478 case '4':
447 IPv4or6 = AF_INET; 479 IPv4or6 = AF_INET;
@@ -488,6 +520,9 @@ main(int ac, char **av)
488 /* only makes sense with inetd_flag, i.e. no listen() */ 520 /* only makes sense with inetd_flag, i.e. no listen() */
489 inetd_flag = 1; 521 inetd_flag = 1;
490 break; 522 break;
523 case 'u':
524 utmp_len = atoi(optarg);
525 break;
491 case '?': 526 case '?':
492 default: 527 default:
493 fprintf(stderr, "sshd version %s\n", SSH_VERSION); 528 fprintf(stderr, "sshd version %s\n", SSH_VERSION);
@@ -503,6 +538,7 @@ main(int ac, char **av)
503 fprintf(stderr, " -b bits Size of server RSA key (default: 768 bits)\n"); 538 fprintf(stderr, " -b bits Size of server RSA key (default: 768 bits)\n");
504 fprintf(stderr, " -h file File from which to read host key (default: %s)\n", 539 fprintf(stderr, " -h file File from which to read host key (default: %s)\n",
505 HOST_KEY_FILE); 540 HOST_KEY_FILE);
541 fprintf(stderr, " -u len Maximum hostname length for utmp recording\n");
506 fprintf(stderr, " -4 Use IPv4 only\n"); 542 fprintf(stderr, " -4 Use IPv4 only\n");
507 fprintf(stderr, " -6 Use IPv6 only\n"); 543 fprintf(stderr, " -6 Use IPv6 only\n");
508 exit(1); 544 exit(1);
@@ -823,7 +859,8 @@ main(int ac, char **av)
823 error("newsock del O_NONBLOCK: %s", strerror(errno)); 859 error("newsock del O_NONBLOCK: %s", strerror(errno));
824 continue; 860 continue;
825 } 861 }
826 if (startups >= options.max_startups) { 862 if (drop_connection(startups) == 1) {
863 debug("drop connection #%d", startups);
827 close(newsock); 864 close(newsock);
828 continue; 865 continue;
829 } 866 }
diff --git a/sshd_config b/sshd_config
index d3bab840a..a97b780e8 100644
--- a/sshd_config
+++ b/sshd_config
@@ -51,3 +51,4 @@ CheckMail no
51UseLogin no 51UseLogin no
52 52
53#Subsystem sftp /usr/local/sbin/sftpd 53#Subsystem sftp /usr/local/sbin/sftpd
54#MaxStartups 10:30:60