diff options
-rw-r--r-- | ChangeLog | 41 | ||||
-rw-r--r-- | Makefile.in | 2 | ||||
-rw-r--r-- | acconfig.h | 3 | ||||
-rw-r--r-- | auth-krb4.c | 8 | ||||
-rw-r--r-- | auth.c | 4 | ||||
-rw-r--r-- | authfd.c | 325 | ||||
-rw-r--r-- | bsd-mktemp.c | 1 | ||||
-rw-r--r-- | configure.in | 16 | ||||
-rw-r--r-- | readconf.c | 2 | ||||
-rw-r--r-- | servconf.c | 24 | ||||
-rw-r--r-- | servconf.h | 4 | ||||
-rw-r--r-- | session.c | 194 | ||||
-rw-r--r-- | ssh.1 | 4 | ||||
-rw-r--r-- | sshd.8 | 65 | ||||
-rw-r--r-- | sshd.c | 43 | ||||
-rw-r--r-- | sshd_config | 1 |
16 files changed, 400 insertions, 337 deletions
@@ -1,3 +1,44 @@ | |||
1 | 20000818 | ||
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 | |||
1 | 20000816 | 42 | 20000816 |
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 | ||
35 | TARGETS=ssh sshd ssh-add ssh-keygen ssh-agent scp $(EXTRA_TARGETS) | 35 | TARGETS=ssh sshd ssh-add ssh-keygen ssh-agent scp $(EXTRA_TARGETS) |
36 | 36 | ||
37 | 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 | 37 | 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 |
38 | 38 | ||
39 | 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 | 39 | 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 |
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 | ||
12 | RCSID("$OpenBSD: auth-krb4.c,v 1.15 2000/06/22 23:54:59 djm Exp $"); | 12 | RCSID("$OpenBSD: auth-krb4.c,v 1.16 2000/08/02 17:27:04 provos Exp $"); |
13 | 13 | ||
14 | #ifdef KRB4 | 14 | #ifdef KRB4 |
15 | char *ticket = NULL; | 15 | char *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! |
@@ -5,7 +5,7 @@ | |||
5 | */ | 5 | */ |
6 | 6 | ||
7 | #include "includes.h" | 7 | #include "includes.h" |
8 | RCSID("$OpenBSD: auth.c,v 1.7 2000/05/17 21:37:24 deraadt Exp $"); | 8 | RCSID("$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 */ |
37 | extern ServerOptions options; | 35 | extern ServerOptions options; |
@@ -14,7 +14,7 @@ | |||
14 | */ | 14 | */ |
15 | 15 | ||
16 | #include "includes.h" | 16 | #include "includes.h" |
17 | RCSID("$OpenBSD: authfd.c,v 1.22 2000/07/16 08:27:20 markus Exp $"); | 17 | RCSID("$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 */ |
34 | int ssh_agent_get_reply(AuthenticationConnection *auth); | 34 | int 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 | |||
39 | ssh_get_authentication_socket() | 39 | ssh_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 | ||
73 | int | ||
74 | ssh_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 | ||
134 | int | 193 | int |
135 | ssh_get_first_identity(AuthenticationConnection *auth, | 194 | ssh_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 | ||
204 | int | 236 | int |
205 | ssh_get_next_identity(AuthenticationConnection *auth, | 237 | ssh_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 | ||
241 | int | 273 | int |
242 | ssh_decrypt_challenge(AuthenticationConnection *auth, | 274 | ssh_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."); | ||
276 | error_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 | |||
378 | ssh_add_identity(AuthenticationConnection *auth, Key *key, const char *comment) | 359 | ssh_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 | |||
421 | ssh_remove_identity(AuthenticationConnection *auth, RSA *key) | 393 | ssh_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) | |||
455 | int | 418 | int |
456 | ssh_remove_all_identities(AuthenticationConnection *auth) | 419 | ssh_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 | |||
476 | int | 436 | int |
477 | ssh_agent_get_reply(AuthenticationConnection *auth) | 437 | decode_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: |
524 | log("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 | ||
56 | static int _gettemp(char *, int *, int, int); | 57 | static 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) | |||
686 | OSSH_CHECK_HEADER_FOR_FIELD(ut_time, utmpx.h, HAVE_TIME_IN_UTMPX) | 686 | OSSH_CHECK_HEADER_FOR_FIELD(ut_time, utmpx.h, HAVE_TIME_IN_UTMPX) |
687 | OSSH_CHECK_HEADER_FOR_FIELD(ut_tv, utmpx.h, HAVE_TV_IN_UTMPX) | 687 | OSSH_CHECK_HEADER_FOR_FIELD(ut_tv, utmpx.h, HAVE_TV_IN_UTMPX) |
688 | 688 | ||
689 | AC_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 | ]) | ||
701 | if test "x$ac_cv_have_sun_len_in_struct_sockaddr_un" = "xyes" ; then | ||
702 | AC_DEFINE(HAVE_SUN_LEN_IN_SOCKADDR_UN) | ||
703 | fi | ||
704 | |||
689 | AC_CACHE_CHECK([for ss_family field in struct sockaddr_storage], | 705 | AC_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" |
17 | RCSID("$OpenBSD: readconf.c,v 1.43 2000/07/14 22:59:46 markus Exp $"); | 17 | RCSID("$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" |
15 | RCSID("$OpenBSD: servconf.c,v 1.49 2000/07/14 22:59:46 markus Exp $"); | 15 | RCSID("$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; |
@@ -8,7 +8,7 @@ | |||
8 | */ | 8 | */ |
9 | 9 | ||
10 | #include "includes.h" | 10 | #include "includes.h" |
11 | RCSID("$OpenBSD: session.c,v 1.23 2000/07/11 08:11:33 deraadt Exp $"); | 11 | RCSID("$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); | |||
85 | void session_proctitle(Session *s); | 85 | void session_proctitle(Session *s); |
86 | void do_exec_pty(Session *s, const char *command, struct passwd * pw); | 86 | void do_exec_pty(Session *s, const char *command, struct passwd * pw); |
87 | void do_exec_no_pty(Session *s, const char *command, struct passwd * pw); | 87 | void do_exec_no_pty(Session *s, const char *command, struct passwd * pw); |
88 | void do_login(Session *s); | ||
88 | 89 | ||
89 | void | 90 | void |
90 | do_child(const char *command, struct passwd * pw, const char *term, | 91 | do_child(const char *command, struct passwd * pw, const char *term, |
@@ -101,6 +102,7 @@ static const char *__progname = "sshd"; | |||
101 | 102 | ||
102 | extern int log_stderr; | 103 | extern int log_stderr; |
103 | extern int debug_flag; | 104 | extern int debug_flag; |
105 | extern unsigned int utmp_len; | ||
104 | 106 | ||
105 | extern int startup_pipe; | 107 | extern int startup_pipe; |
106 | 108 | ||
@@ -523,35 +525,14 @@ do_exec_no_pty(Session *s, const char *command, struct passwd * pw) | |||
523 | void | 525 | void |
524 | do_exec_pty(Session *s, const char *command, struct passwd * pw) | 526 | do_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 | ||
608 | const char * | ||
609 | get_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 */ | ||
620 | void | ||
621 | do_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 | ||
@@ -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, | |||
994 | this variable is not set. | 994 | this variable is not set. |
995 | .It Ev TZ | 995 | .It Ev TZ |
996 | The timezone variable is set to indicate the present timezone if it | 996 | The timezone variable is set to indicate the present timezone if it |
997 | was set when the daemon was started (e.i., the daemon passes the value | 997 | was set when the daemon was started (i.e., the daemon passes the value |
998 | on to new connections). | 998 | on to new connections). |
999 | .It Ev USER | 999 | .It Ev USER |
1000 | Set to the name of the user logging in. | 1000 | Set to the name of the user logging in. |
@@ -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 |
107 | Version 2 works similar: | 108 | Version 2 works similarly: |
108 | Each host has a host-specific DSA key used to identify the host. | 109 | Each host has a host-specific DSA key used to identify the host. |
109 | However, when the daemon starts, it does not generate a server key. | 110 | However, when the daemon starts, it does not generate a server key. |
110 | Forward security is provided through a Diffie-Hellman key agreement. | 111 | Forward security is provided through a Diffie-Hellman key agreement. |
@@ -211,6 +212,22 @@ Quiet mode. | |||
211 | Nothing is sent to the system log. | 212 | Nothing is sent to the system log. |
212 | Normally the beginning, | 213 | Normally the beginning, |
213 | authentication, and termination of each connection is logged. | 214 | authentication, and termination of each connection is logged. |
215 | .It Fl u Ar len | ||
216 | This option is used to specify the size of the field | ||
217 | in the | ||
218 | .Li utmp | ||
219 | structure that holds the remote host name. | ||
220 | If the resolved host name is longer than | ||
221 | .Ar len , | ||
222 | the dotted decimal value will be used instead. | ||
223 | This allows hosts with very long host names that | ||
224 | overflow this field to still be uniquely identified. | ||
225 | Specifying | ||
226 | .Fl u0 | ||
227 | indicates that only dotted decimal addresses | ||
228 | should be put into the | ||
229 | .Pa utmp | ||
230 | file. | ||
214 | .It Fl Q | 231 | .It Fl Q |
215 | Do not print an error message if RSA support is missing. | 232 | Do 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 ? |
258 | can be used as | 275 | can be used as |
259 | wildcards in the patterns. | 276 | wildcards in the patterns. |
260 | Only group names are valid, a numerical group ID isn't recognized. | 277 | Only group names are valid; a numerical group ID isn't recognized. |
261 | By default login is allowed regardless of the primary group. | 278 | By 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 ? |
271 | can be used as | 288 | can be used as |
272 | wildcards in the patterns. | 289 | wildcards in the patterns. |
273 | Only user names are valid, a numerical user ID isn't recognized. | 290 | Only user names are valid; a numerical user ID isn't recognized. |
274 | By default login is allowed regardless of the user name. | 291 | By 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 ? |
295 | can be used as | 312 | can be used as |
296 | wildcards in the patterns. | 313 | wildcards in the patterns. |
297 | Only group names are valid, a numerical group ID isn't recognized. | 314 | Only group names are valid; a numerical group ID isn't recognized. |
298 | By default login is allowed regardless of the primary group. | 315 | By 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. | |||
305 | and | 322 | and |
306 | .Ql ? | 323 | .Ql ? |
307 | can be used as wildcards in the patterns. | 324 | can be used as wildcards in the patterns. |
308 | Only user names are valid, a numerical user ID isn't recognized. | 325 | Only user names are valid; a numerical user ID isn't recognized. |
309 | By default login is allowed regardless of the user name. | 326 | By default login is allowed regardless of the user name. |
310 | .It Cm DSAAuthentication | 327 | .It Cm DSAAuthentication |
311 | Specifies whether DSA authentication is allowed. | 328 | Specifies whether DSA authentication is allowed. |
@@ -321,7 +338,7 @@ or | |||
321 | .Dq no . | 338 | .Dq no . |
322 | The default is | 339 | The default is |
323 | .Dq no . | 340 | .Dq no . |
324 | .It Cm HostDsaKey | 341 | .It Cm HostDSAKey |
325 | Specifies the file containing the private DSA host key (default | 342 | Specifies the file containing the private DSA host key (default |
326 | .Pa /etc/ssh_host_dsa_key ) | 343 | .Pa /etc/ssh_host_dsa_key ) |
327 | used by SSH protocol 2.0. | 344 | used by SSH protocol 2.0. |
@@ -383,7 +400,8 @@ Specifies whether Kerberos authentication is allowed. | |||
383 | This can be in the form of a Kerberos ticket, or if | 400 | This can be in the form of a Kerberos ticket, or if |
384 | .Cm PasswordAuthentication | 401 | .Cm PasswordAuthentication |
385 | is yes, the password provided by the user will be validated through | 402 | is yes, the password provided by the user will be validated through |
386 | the Kerberos KDC. | 403 | the Kerberos KDC. To use this option, the server needs a |
404 | Kerberos servtab which allows the verification of the KDC's identity. | ||
387 | Default is | 405 | Default 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 |
444 | expires for a connection. | 462 | expires for a connection. |
445 | The default is 10. | 463 | The default is 10. |
464 | .Pp | ||
465 | Alternatively, random early drop can be enabled by specifying | ||
466 | the three colon separated values | ||
467 | .Dq start:rate:full | ||
468 | (e.g. "10:30:60"). | ||
469 | .Nm | ||
470 | will refuse connection attempts with a probabillity of | ||
471 | .Dq rate/100 | ||
472 | (30%) | ||
473 | if there are currently | ||
474 | .Dq start | ||
475 | (10) | ||
476 | unauthenticated connections. | ||
477 | The probabillity increases linearly and all connection attempts | ||
478 | are refused if the number of unauthenticated connections reaches | ||
479 | .Dq full | ||
480 | (60). | ||
446 | .It Cm PasswordAuthentication | 481 | .It Cm PasswordAuthentication |
447 | Specifies whether password authentication is allowed. | 482 | Specifies whether password authentication is allowed. |
448 | The default is | 483 | The default is |
449 | .Dq yes . | 484 | .Dq yes . |
450 | Note that this option applies to both protocol version 1 and 2. | 485 | Note that this option applies to both protocol versions 1 and 2. |
451 | .It Cm PermitEmptyPasswords | 486 | .It Cm PermitEmptyPasswords |
452 | When password authentication is allowed, it specifies whether the | 487 | When password authentication is allowed, it specifies whether the |
453 | server allows login to accounts with empty password strings. | 488 | server allows login to accounts with empty password strings. |
@@ -568,7 +603,7 @@ Specifies whether | |||
568 | is used for interactive login sessions. | 603 | is used for interactive login sessions. |
569 | Note that | 604 | Note that |
570 | .Xr login 1 | 605 | .Xr login 1 |
571 | is not never for remote command execution. | 606 | is never used for remote command execution. |
572 | The default is | 607 | The 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 |
667 | file and edit it. | 702 | file and edit it. |
668 | .Pp | 703 | .Pp |
669 | The options (if present) consists of comma-separated option | 704 | The options (if present) consist of comma-separated option |
670 | specifications. | 705 | specifications. |
671 | No spaces are permitted, except within double quotes. | 706 | No spaces are permitted, except within double quotes. |
672 | The following option specifications are supported: | 707 | The following option specifications are supported: |
@@ -740,7 +775,7 @@ and | |||
740 | files contain host public keys for all known hosts. | 775 | files contain host public keys for all known hosts. |
741 | The global file should | 776 | The global file should |
742 | be prepared by the administrator (optional), and the per-user file is | 777 | be prepared by the administrator (optional), and the per-user file is |
743 | maintained automatically: whenever the user connects an unknown host | 778 | maintained automatically: whenever the user connects from an unknown host |
744 | its key is added to the per-user file. | 779 | its key is added to the per-user file. |
745 | .Pp | 780 | .Pp |
746 | Each line in these files contains the following fields: hostnames, | 781 | Each line in these files contains the following fields: hostnames, |
@@ -815,7 +850,7 @@ Contains the process ID of the | |||
815 | listening for connections (if there are several daemons running | 850 | listening for connections (if there are several daemons running |
816 | concurrently for different ports, this contains the pid of the one | 851 | concurrently for different ports, this contains the pid of the one |
817 | started last). | 852 | started last). |
818 | The contents of this file are not sensitive; it can be world-readable. | 853 | The 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 |
820 | Lists the RSA keys that can be used to log into the user's account. | 855 | Lists the RSA keys that can be used to log into the user's account. |
821 | This file must be readable by root (which may on some machines imply | 856 | 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 | |||
843 | authentication to check the public key of the host. | 878 | authentication to check the public key of the host. |
844 | The key must be listed in one of these files to be accepted. | 879 | The key must be listed in one of these files to be accepted. |
845 | The client uses the same files | 880 | The client uses the same files |
846 | to verify that the remote host is the one we intended to connect. | 881 | to verify that the remote host is the one it intended to connect. |
847 | These files should be writable only by root/the owner. | 882 | These files should be writable only by root/the owner. |
848 | .Pa /etc/ssh_known_hosts | 883 | .Pa /etc/ssh_known_hosts |
849 | should be world-readable, and | 884 | should be world-readable, and |
@@ -882,7 +917,7 @@ this file is exactly the same as for | |||
882 | .Pa .rhosts . | 917 | .Pa .rhosts . |
883 | However, this file is | 918 | However, this file is |
884 | not used by rlogin and rshd, so using this permits access using SSH only. | 919 | not used by rlogin and rshd, so using this permits access using SSH only. |
885 | .Pa /etc/hosts.equiv | 920 | .It Pa /etc/hosts.equiv |
886 | This file is used during | 921 | This file is used during |
887 | .Pa .rhosts | 922 | .Pa .rhosts |
888 | authentication. | 923 | authentication. |
@@ -14,7 +14,7 @@ | |||
14 | */ | 14 | */ |
15 | 15 | ||
16 | #include "includes.h" | 16 | #include "includes.h" |
17 | RCSID("$OpenBSD: sshd.c,v 1.123 2000/07/18 01:25:01 djm Exp $"); | 17 | RCSID("$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]; | |||
139 | unsigned char *session_id2 = NULL; | 139 | unsigned char *session_id2 = NULL; |
140 | int session_id2_len = 0; | 140 | int session_id2_len = 0; |
141 | 141 | ||
142 | /* record remote hostname or ip */ | ||
143 | unsigned 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. */ |
143 | void do_ssh1_kex(); | 146 | void do_ssh1_kex(); |
144 | void do_ssh2_kex(); | 147 | void 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 | */ | ||
412 | int | ||
413 | drop_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 | |||
403 | int *startup_pipes = NULL; /* options.max_startup sized array of fd ints */ | 435 | int *startup_pipes = NULL; /* options.max_startup sized array of fd ints */ |
404 | int startup_pipe; /* in child */ | 436 | int 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 | |||
51 | UseLogin no | 51 | UseLogin no |
52 | 52 | ||
53 | #Subsystem sftp /usr/local/sbin/sftpd | 53 | #Subsystem sftp /usr/local/sbin/sftpd |
54 | #MaxStartups 10:30:60 | ||