summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--ChangeLog32
-rw-r--r--Makefile.in2
-rw-r--r--auth-options.c208
-rw-r--r--auth-options.h13
-rw-r--r--auth-rsa.c199
-rw-r--r--auth2.c61
-rw-r--r--channels.c3
-rw-r--r--compat.c3
-rw-r--r--readconf.c4
-rw-r--r--scp.c5
-rw-r--r--servconf.c31
-rw-r--r--servconf.h7
-rw-r--r--serverloop.c7
-rw-r--r--session.c86
-rw-r--r--sshconnect.c35
-rw-r--r--sshd.87
-rw-r--r--sshd_config2
17 files changed, 431 insertions, 274 deletions
diff --git a/ChangeLog b/ChangeLog
index 9ca8e55ff..b367ddc40 100644
--- a/ChangeLog
+++ b/ChangeLog
@@ -8,6 +8,38 @@
8 Martin Petrak <petrak@spsknm.schools.sk> 8 Martin Petrak <petrak@spsknm.schools.sk>
9 - (djm) Include sys/types.h when including netinet/in.h in configure tests. 9 - (djm) Include sys/types.h when including netinet/in.h in configure tests.
10 Patch from Jun-ichiro itojun Hagino <itojun@iijlab.net> 10 Patch from Jun-ichiro itojun Hagino <itojun@iijlab.net>
11 - OpenBSD CVS updates:
12 - deraadt@cvs.openbsd.org 2000/06/17 09:58:46
13 [channels.c]
14 everyone says "nix it" (remove protocol 2 debugging message)
15 - markus@cvs.openbsd.org 2000/06/17 13:24:34
16 [sshconnect.c]
17 allow extended server banners
18 - markus@cvs.openbsd.org 2000/06/17 14:30:10
19 [sshconnect.c]
20 missing atomicio, typo
21 - jakob@cvs.openbsd.org 2000/06/17 16:52:34
22 [servconf.c servconf.h session.c sshd.8 sshd_config]
23 add support for ssh v2 subsystems. ok markus@.
24 - deraadt@cvs.openbsd.org 2000/06/17 18:57:48
25 [readconf.c servconf.c]
26 include = in WHITESPACE; markus ok
27 - markus@cvs.openbsd.org 2000/06/17 19:09:10
28 [auth2.c]
29 implement bug compatibility with ssh-2.0.13 pubkey, server side
30 - markus@cvs.openbsd.org 2000/06/17 21:00:28
31 [compat.c]
32 initial support for ssh.com's 2.2.0
33 - markus@cvs.openbsd.org 2000/06/17 21:16:09
34 [scp.c]
35 typo
36 - markus@cvs.openbsd.org 2000/06/17 22:05:02
37 [auth-rsa.c auth2.c serverloop.c session.c auth-options.c auth-options.h]
38 split auth-rsa option parsing into auth-options
39 add options support to authorized_keys2
40 - markus@cvs.openbsd.org 2000/06/17 22:42:54
41 [session.c]
42 typo
11 43
1220000613 4420000613
13 - (djm) Fixes from Andrew McGill <andrewm@datrix.co.za>: 45 - (djm) Fixes from Andrew McGill <andrewm@datrix.co.za>:
diff --git a/Makefile.in b/Makefile.in
index 0a2a2cfc7..4037bfe8a 100644
--- a/Makefile.in
+++ b/Makefile.in
@@ -40,7 +40,7 @@ LIBOPENBSD_COMPAT_OBJS=bsd-base64.o bsd-bindresvport.o bsd-daemon.o bsd-misc.o b
40 40
41SSHOBJS= ssh.o sshconnect.o sshconnect1.o sshconnect2.o log-client.o readconf.o clientloop.o 41SSHOBJS= ssh.o sshconnect.o sshconnect1.o sshconnect2.o log-client.o readconf.o clientloop.o
42 42
43SSHDOBJS= sshd.o auth.o auth1.o auth2.o auth-rhosts.o auth-krb4.o auth-pam.o auth-passwd.o auth-rsa.o auth-rh-rsa.o pty.o log-server.o login.o loginrec.o servconf.o serverloop.o md5crypt.o session.o 43SSHDOBJS= sshd.o auth.o auth1.o auth2.o auth-rhosts.o auth-options.o auth-krb4.o auth-pam.o auth-passwd.o auth-rsa.o auth-rh-rsa.o pty.o log-server.o login.o loginrec.o servconf.o serverloop.o md5crypt.o session.o
44 44
45TROFFMAN = scp.1 ssh-add.1 ssh-agent.1 ssh-keygen.1 ssh.1 sshd.8 45TROFFMAN = scp.1 ssh-add.1 ssh-agent.1 ssh-keygen.1 ssh.1 sshd.8
46CATMAN = scp.0 ssh-add.0 ssh-agent.0 ssh-keygen.0 ssh.0 sshd.0 46CATMAN = scp.0 ssh-add.0 ssh-agent.0 ssh-keygen.0 ssh.0 sshd.0
diff --git a/auth-options.c b/auth-options.c
new file mode 100644
index 000000000..7ebbb7661
--- /dev/null
+++ b/auth-options.c
@@ -0,0 +1,208 @@
1#include "includes.h"
2RCSID("$Id: auth-options.c,v 1.1 2000/06/18 04:50:44 djm Exp $");
3
4#include "ssh.h"
5#include "packet.h"
6#include "xmalloc.h"
7#include "match.h"
8
9/* Flags set authorized_keys flags */
10int no_port_forwarding_flag = 0;
11int no_agent_forwarding_flag = 0;
12int no_x11_forwarding_flag = 0;
13int no_pty_flag = 0;
14
15/* "command=" option. */
16char *forced_command = NULL;
17
18/* "environment=" options. */
19struct envstring *custom_environment = NULL;
20
21/* return 1 if access is granted, 0 if not. side effect: sets key option flags */
22int
23auth_parse_options(struct passwd *pw, char *options, unsigned long linenum)
24{
25 const char *cp;
26 if (!options)
27 return 1;
28 while (*options && *options != ' ' && *options != '\t') {
29 cp = "no-port-forwarding";
30 if (strncmp(options, cp, strlen(cp)) == 0) {
31 packet_send_debug("Port forwarding disabled.");
32 no_port_forwarding_flag = 1;
33 options += strlen(cp);
34 goto next_option;
35 }
36 cp = "no-agent-forwarding";
37 if (strncmp(options, cp, strlen(cp)) == 0) {
38 packet_send_debug("Agent forwarding disabled.");
39 no_agent_forwarding_flag = 1;
40 options += strlen(cp);
41 goto next_option;
42 }
43 cp = "no-X11-forwarding";
44 if (strncmp(options, cp, strlen(cp)) == 0) {
45 packet_send_debug("X11 forwarding disabled.");
46 no_x11_forwarding_flag = 1;
47 options += strlen(cp);
48 goto next_option;
49 }
50 cp = "no-pty";
51 if (strncmp(options, cp, strlen(cp)) == 0) {
52 packet_send_debug("Pty allocation disabled.");
53 no_pty_flag = 1;
54 options += strlen(cp);
55 goto next_option;
56 }
57 cp = "command=\"";
58 if (strncmp(options, cp, strlen(cp)) == 0) {
59 int i;
60 options += strlen(cp);
61 forced_command = xmalloc(strlen(options) + 1);
62 i = 0;
63 while (*options) {
64 if (*options == '"')
65 break;
66 if (*options == '\\' && options[1] == '"') {
67 options += 2;
68 forced_command[i++] = '"';
69 continue;
70 }
71 forced_command[i++] = *options++;
72 }
73 if (!*options) {
74 debug("%.100s, line %lu: missing end quote",
75 SSH_USER_PERMITTED_KEYS, linenum);
76 packet_send_debug("%.100s, line %lu: missing end quote",
77 SSH_USER_PERMITTED_KEYS, linenum);
78 continue;
79 }
80 forced_command[i] = 0;
81 packet_send_debug("Forced command: %.900s", forced_command);
82 options++;
83 goto next_option;
84 }
85 cp = "environment=\"";
86 if (strncmp(options, cp, strlen(cp)) == 0) {
87 int i;
88 char *s;
89 struct envstring *new_envstring;
90 options += strlen(cp);
91 s = xmalloc(strlen(options) + 1);
92 i = 0;
93 while (*options) {
94 if (*options == '"')
95 break;
96 if (*options == '\\' && options[1] == '"') {
97 options += 2;
98 s[i++] = '"';
99 continue;
100 }
101 s[i++] = *options++;
102 }
103 if (!*options) {
104 debug("%.100s, line %lu: missing end quote",
105 SSH_USER_PERMITTED_KEYS, linenum);
106 packet_send_debug("%.100s, line %lu: missing end quote",
107 SSH_USER_PERMITTED_KEYS, linenum);
108 continue;
109 }
110 s[i] = 0;
111 packet_send_debug("Adding to environment: %.900s", s);
112 debug("Adding to environment: %.900s", s);
113 options++;
114 new_envstring = xmalloc(sizeof(struct envstring));
115 new_envstring->s = s;
116 new_envstring->next = custom_environment;
117 custom_environment = new_envstring;
118 goto next_option;
119 }
120 cp = "from=\"";
121 if (strncmp(options, cp, strlen(cp)) == 0) {
122 int mname, mip;
123 char *patterns = xmalloc(strlen(options) + 1);
124 int i;
125 options += strlen(cp);
126 i = 0;
127 while (*options) {
128 if (*options == '"')
129 break;
130 if (*options == '\\' && options[1] == '"') {
131 options += 2;
132 patterns[i++] = '"';
133 continue;
134 }
135 patterns[i++] = *options++;
136 }
137 if (!*options) {
138 debug("%.100s, line %lu: missing end quote",
139 SSH_USER_PERMITTED_KEYS, linenum);
140 packet_send_debug("%.100s, line %lu: missing end quote",
141 SSH_USER_PERMITTED_KEYS, linenum);
142 continue;
143 }
144 patterns[i] = 0;
145 options++;
146 /*
147 * Deny access if we get a negative
148 * match for the hostname or the ip
149 * or if we get not match at all
150 */
151 mname = match_hostname(get_canonical_hostname(),
152 patterns, strlen(patterns));
153 mip = match_hostname(get_remote_ipaddr(),
154 patterns, strlen(patterns));
155 xfree(patterns);
156 if (mname == -1 || mip == -1 ||
157 (mname != 1 && mip != 1)) {
158 log("Authentication tried for %.100s with correct key but not from a permitted host (host=%.200s, ip=%.200s).",
159 pw->pw_name, get_canonical_hostname(),
160 get_remote_ipaddr());
161 packet_send_debug("Your host '%.200s' is not permitted to use this key for login.",
162 get_canonical_hostname());
163 /* key invalid for this host, reset flags */
164 no_agent_forwarding_flag = 0;
165 no_port_forwarding_flag = 0;
166 no_pty_flag = 0;
167 no_x11_forwarding_flag = 0;
168 while (custom_environment) {
169 struct envstring *ce = custom_environment;
170 custom_environment = ce->next;
171 xfree(ce->s);
172 xfree(ce);
173 }
174 if (forced_command) {
175 xfree(forced_command);
176 forced_command = NULL;
177 }
178 /* deny access */
179 return 0;
180 }
181 /* Host name matches. */
182 goto next_option;
183 }
184next_option:
185 /*
186 * Skip the comma, and move to the next option
187 * (or break out if there are no more).
188 */
189 if (!*options)
190 fatal("Bugs in auth-options.c option processing.");
191 if (*options == ' ' || *options == '\t')
192 break; /* End of options. */
193 if (*options != ',')
194 goto bad_option;
195 options++;
196 /* Process the next option. */
197 }
198 /* grant access */
199 return 1;
200
201bad_option:
202 log("Bad options in %.100s file, line %lu: %.50s",
203 SSH_USER_PERMITTED_KEYS, linenum, options);
204 packet_send_debug("Bad options in %.100s file, line %lu: %.50s",
205 SSH_USER_PERMITTED_KEYS, linenum, options);
206 /* deny access */
207 return 0;
208}
diff --git a/auth-options.h b/auth-options.h
new file mode 100644
index 000000000..1ecdb9df4
--- /dev/null
+++ b/auth-options.h
@@ -0,0 +1,13 @@
1#ifndef AUTH_OPTIONS_H
2#define AUTH_OPTIONS_H
3/* Flags that may be set in authorized_keys options. */
4extern int no_port_forwarding_flag;
5extern int no_agent_forwarding_flag;
6extern int no_x11_forwarding_flag;
7extern int no_pty_flag;
8extern char *forced_command;
9extern struct envstring *custom_environment;
10
11/* return 1 if access is granted, 0 if not. side effect: sets key option flags */
12int auth_parse_options(struct passwd *pw, char *options, unsigned long linenum);
13#endif
diff --git a/auth-rsa.c b/auth-rsa.c
index f01c5c920..546e1d845 100644
--- a/auth-rsa.c
+++ b/auth-rsa.c
@@ -16,7 +16,7 @@
16 */ 16 */
17 17
18#include "includes.h" 18#include "includes.h"
19RCSID("$Id: auth-rsa.c,v 1.20 2000/06/07 09:55:44 djm Exp $"); 19RCSID("$Id: auth-rsa.c,v 1.21 2000/06/18 04:50:44 djm Exp $");
20 20
21#include "rsa.h" 21#include "rsa.h"
22#include "packet.h" 22#include "packet.h"
@@ -26,18 +26,11 @@ RCSID("$Id: auth-rsa.c,v 1.20 2000/06/07 09:55:44 djm Exp $");
26#include "uidswap.h" 26#include "uidswap.h"
27#include "match.h" 27#include "match.h"
28#include "servconf.h" 28#include "servconf.h"
29#include "auth-options.h"
29 30
30#include <openssl/rsa.h> 31#include <openssl/rsa.h>
31#include <openssl/md5.h> 32#include <openssl/md5.h>
32 33
33/* Flags that may be set in authorized_keys options. */
34extern int no_port_forwarding_flag;
35extern int no_agent_forwarding_flag;
36extern int no_x11_forwarding_flag;
37extern int no_pty_flag;
38extern char *forced_command;
39extern struct envstring *custom_environment;
40
41/* 34/*
42 * Session identifier that is used to bind key exchange and authentication 35 * Session identifier that is used to bind key exchange and authentication
43 * responses to a particular session. 36 * responses to a particular session.
@@ -133,7 +126,6 @@ auth_rsa(struct passwd *pw, BIGNUM *client_n)
133 unsigned long linenum = 0; 126 unsigned long linenum = 0;
134 struct stat st; 127 struct stat st;
135 RSA *pk; 128 RSA *pk;
136 int mname, mip;
137 129
138 /* Temporarily use the user's uid. */ 130 /* Temporarily use the user's uid. */
139 temporarily_use_uid(pw->pw_uid); 131 temporarily_use_uid(pw->pw_uid);
@@ -269,195 +261,10 @@ auth_rsa(struct passwd *pw, BIGNUM *client_n)
269 * authenticated. Note that we have not yet processed the 261 * authenticated. Note that we have not yet processed the
270 * options; this will be reset if the options cause the 262 * options; this will be reset if the options cause the
271 * authentication to be rejected. 263 * authentication to be rejected.
272 */
273 authenticated = 1;
274
275 /* RSA part of authentication was accepted. Now process the options. */
276 if (options) {
277 while (*options && *options != ' ' && *options != '\t') {
278 cp = "no-port-forwarding";
279 if (strncmp(options, cp, strlen(cp)) == 0) {
280 packet_send_debug("Port forwarding disabled.");
281 no_port_forwarding_flag = 1;
282 options += strlen(cp);
283 goto next_option;
284 }
285 cp = "no-agent-forwarding";
286 if (strncmp(options, cp, strlen(cp)) == 0) {
287 packet_send_debug("Agent forwarding disabled.");
288 no_agent_forwarding_flag = 1;
289 options += strlen(cp);
290 goto next_option;
291 }
292 cp = "no-X11-forwarding";
293 if (strncmp(options, cp, strlen(cp)) == 0) {
294 packet_send_debug("X11 forwarding disabled.");
295 no_x11_forwarding_flag = 1;
296 options += strlen(cp);
297 goto next_option;
298 }
299 cp = "no-pty";
300 if (strncmp(options, cp, strlen(cp)) == 0) {
301 packet_send_debug("Pty allocation disabled.");
302 no_pty_flag = 1;
303 options += strlen(cp);
304 goto next_option;
305 }
306 cp = "command=\"";
307 if (strncmp(options, cp, strlen(cp)) == 0) {
308 int i;
309 options += strlen(cp);
310 forced_command = xmalloc(strlen(options) + 1);
311 i = 0;
312 while (*options) {
313 if (*options == '"')
314 break;
315 if (*options == '\\' && options[1] == '"') {
316 options += 2;
317 forced_command[i++] = '"';
318 continue;
319 }
320 forced_command[i++] = *options++;
321 }
322 if (!*options) {
323 debug("%.100s, line %lu: missing end quote",
324 SSH_USER_PERMITTED_KEYS, linenum);
325 packet_send_debug("%.100s, line %lu: missing end quote",
326 SSH_USER_PERMITTED_KEYS, linenum);
327 continue;
328 }
329 forced_command[i] = 0;
330 packet_send_debug("Forced command: %.900s", forced_command);
331 options++;
332 goto next_option;
333 }
334 cp = "environment=\"";
335 if (strncmp(options, cp, strlen(cp)) == 0) {
336 int i;
337 char *s;
338 struct envstring *new_envstring;
339 options += strlen(cp);
340 s = xmalloc(strlen(options) + 1);
341 i = 0;
342 while (*options) {
343 if (*options == '"')
344 break;
345 if (*options == '\\' && options[1] == '"') {
346 options += 2;
347 s[i++] = '"';
348 continue;
349 }
350 s[i++] = *options++;
351 }
352 if (!*options) {
353 debug("%.100s, line %lu: missing end quote",
354 SSH_USER_PERMITTED_KEYS, linenum);
355 packet_send_debug("%.100s, line %lu: missing end quote",
356 SSH_USER_PERMITTED_KEYS, linenum);
357 continue;
358 }
359 s[i] = 0;
360 packet_send_debug("Adding to environment: %.900s", s);
361 debug("Adding to environment: %.900s", s);
362 options++;
363 new_envstring = xmalloc(sizeof(struct envstring));
364 new_envstring->s = s;
365 new_envstring->next = custom_environment;
366 custom_environment = new_envstring;
367 goto next_option;
368 }
369 cp = "from=\"";
370 if (strncmp(options, cp, strlen(cp)) == 0) {
371 char *patterns = xmalloc(strlen(options) + 1);
372 int i;
373 options += strlen(cp);
374 i = 0;
375 while (*options) {
376 if (*options == '"')
377 break;
378 if (*options == '\\' && options[1] == '"') {
379 options += 2;
380 patterns[i++] = '"';
381 continue;
382 }
383 patterns[i++] = *options++;
384 }
385 if (!*options) {
386 debug("%.100s, line %lu: missing end quote",
387 SSH_USER_PERMITTED_KEYS, linenum);
388 packet_send_debug("%.100s, line %lu: missing end quote",
389 SSH_USER_PERMITTED_KEYS, linenum);
390 continue;
391 }
392 patterns[i] = 0;
393 options++;
394 /*
395 * Deny access if we get a negative
396 * match for the hostname or the ip
397 * or if we get not match at all
398 */
399 mname = match_hostname(get_canonical_hostname(),
400 patterns, strlen(patterns));
401 mip = match_hostname(get_remote_ipaddr(),
402 patterns, strlen(patterns));
403 if (mname == -1 || mip == -1 ||
404 (mname != 1 && mip != 1)) {
405 log("RSA authentication tried for %.100s with correct key but not from a permitted host (host=%.200s, ip=%.200s).",
406 pw->pw_name, get_canonical_hostname(),
407 get_remote_ipaddr());
408 packet_send_debug("Your host '%.200s' is not permitted to use this key for login.",
409 get_canonical_hostname());
410 xfree(patterns);
411 /* key invalid for this host, reset flags */
412 authenticated = 0;
413 no_agent_forwarding_flag = 0;
414 no_port_forwarding_flag = 0;
415 no_pty_flag = 0;
416 no_x11_forwarding_flag = 0;
417 while (custom_environment) {
418 struct envstring *ce = custom_environment;
419 custom_environment = ce->next;
420 xfree(ce->s);
421 xfree(ce);
422 }
423 if (forced_command) {
424 xfree(forced_command);
425 forced_command = NULL;
426 }
427 break;
428 }
429 xfree(patterns);
430 /* Host name matches. */
431 goto next_option;
432 }
433 bad_option:
434 log("Bad options in %.100s file, line %lu: %.50s",
435 SSH_USER_PERMITTED_KEYS, linenum, options);
436 packet_send_debug("Bad options in %.100s file, line %lu: %.50s",
437 SSH_USER_PERMITTED_KEYS, linenum, options);
438 authenticated = 0;
439 break;
440
441 next_option:
442 /*
443 * Skip the comma, and move to the next option
444 * (or break out if there are no more).
445 */
446 if (!*options)
447 fatal("Bugs in auth-rsa.c option processing.");
448 if (*options == ' ' || *options == '\t')
449 break; /* End of options. */
450 if (*options != ',')
451 goto bad_option;
452 options++;
453 /* Process the next option. */
454 continue;
455 }
456 }
457 /*
458 * Break out of the loop if authentication was successful; 264 * Break out of the loop if authentication was successful;
459 * otherwise continue searching. 265 * otherwise continue searching.
460 */ 266 */
267 authenticated = auth_parse_options(pw, options, linenum);
461 if (authenticated) 268 if (authenticated)
462 break; 269 break;
463 } 270 }
diff --git a/auth2.c b/auth2.c
index 46c8c1f81..c7dcf1953 100644
--- a/auth2.c
+++ b/auth2.c
@@ -27,7 +27,7 @@
27 * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 27 * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
28 */ 28 */
29#include "includes.h" 29#include "includes.h"
30RCSID("$OpenBSD: auth2.c,v 1.8 2000/05/08 17:42:24 markus Exp $"); 30RCSID("$OpenBSD: auth2.c,v 1.10 2000/06/18 04:05:02 markus Exp $");
31 31
32#include <openssl/dsa.h> 32#include <openssl/dsa.h>
33#include <openssl/rsa.h> 33#include <openssl/rsa.h>
@@ -54,6 +54,7 @@ RCSID("$OpenBSD: auth2.c,v 1.8 2000/05/08 17:42:24 markus Exp $");
54 54
55#include "dsa.h" 55#include "dsa.h"
56#include "uidswap.h" 56#include "uidswap.h"
57#include "auth-options.h"
57 58
58/* import */ 59/* import */
59extern ServerOptions options; 60extern ServerOptions options;
@@ -69,7 +70,7 @@ void protocol_error(int type, int plen);
69/* auth */ 70/* auth */
70int ssh2_auth_none(struct passwd *pw); 71int ssh2_auth_none(struct passwd *pw);
71int ssh2_auth_password(struct passwd *pw); 72int ssh2_auth_password(struct passwd *pw);
72int ssh2_auth_pubkey(struct passwd *pw, unsigned char *raw, unsigned int rlen); 73int ssh2_auth_pubkey(struct passwd *pw, char *service);
73 74
74/* helper */ 75/* helper */
75struct passwd* auth_set_user(char *u, char *s); 76struct passwd* auth_set_user(char *u, char *s);
@@ -150,17 +151,14 @@ input_userauth_request(int type, int plen)
150{ 151{
151 static void (*authlog) (const char *fmt,...) = verbose; 152 static void (*authlog) (const char *fmt,...) = verbose;
152 static int attempt = 0; 153 static int attempt = 0;
153 unsigned int len, rlen; 154 unsigned int len;
154 int authenticated = 0; 155 int authenticated = 0;
155 char *raw, *user, *service, *method, *authmsg = NULL; 156 char *user, *service, *method, *authmsg = NULL;
156 struct passwd *pw; 157 struct passwd *pw;
157#ifdef WITH_AIXAUTHENTICATE 158#ifdef WITH_AIXAUTHENTICATE
158 extern char *aixloginmsg; 159 extern char *aixloginmsg;
159#endif /* WITH_AIXAUTHENTICATE */ 160#endif /* WITH_AIXAUTHENTICATE */
160 161
161 raw = packet_get_raw(&rlen);
162 if (plen != rlen)
163 fatal("plen != rlen");
164 user = packet_get_string(&len); 162 user = packet_get_string(&len);
165 service = packet_get_string(&len); 163 service = packet_get_string(&len);
166 method = packet_get_string(&len); 164 method = packet_get_string(&len);
@@ -180,7 +178,7 @@ input_userauth_request(int type, int plen)
180 } else if (strcmp(method, "password") == 0) { 178 } else if (strcmp(method, "password") == 0) {
181 authenticated = ssh2_auth_password(pw); 179 authenticated = ssh2_auth_password(pw);
182 } else if (strcmp(method, "publickey") == 0) { 180 } else if (strcmp(method, "publickey") == 0) {
183 authenticated = ssh2_auth_pubkey(pw, raw, rlen); 181 authenticated = ssh2_auth_pubkey(pw, service);
184 } 182 }
185 } 183 }
186 if (authenticated && pw && pw->pw_uid == 0 && !options.permit_root_login) { 184 if (authenticated && pw && pw->pw_uid == 0 && !options.permit_root_login) {
@@ -277,7 +275,7 @@ ssh2_auth_password(struct passwd *pw)
277 return authenticated; 275 return authenticated;
278} 276}
279int 277int
280ssh2_auth_pubkey(struct passwd *pw, unsigned char *raw, unsigned int rlen) 278ssh2_auth_pubkey(struct passwd *pw, char *service)
281{ 279{
282 Buffer b; 280 Buffer b;
283 Key *key; 281 Key *key;
@@ -290,10 +288,6 @@ ssh2_auth_pubkey(struct passwd *pw, unsigned char *raw, unsigned int rlen)
290 debug("pubkey auth disabled"); 288 debug("pubkey auth disabled");
291 return 0; 289 return 0;
292 } 290 }
293 if (datafellows & SSH_BUG_PUBKEYAUTH) {
294 log("bug compatibility with ssh-2.0.13 pubkey not implemented");
295 return 0;
296 }
297 have_sig = packet_get_char(); 291 have_sig = packet_get_char();
298 pkalg = packet_get_string(&alen); 292 pkalg = packet_get_string(&alen);
299 if (strcmp(pkalg, KEX_DSS) != 0) { 293 if (strcmp(pkalg, KEX_DSS) != 0) {
@@ -309,10 +303,18 @@ ssh2_auth_pubkey(struct passwd *pw, unsigned char *raw, unsigned int rlen)
309 packet_done(); 303 packet_done();
310 buffer_init(&b); 304 buffer_init(&b);
311 buffer_append(&b, session_id2, session_id2_len); 305 buffer_append(&b, session_id2, session_id2_len);
306
307 /* reconstruct packet */
312 buffer_put_char(&b, SSH2_MSG_USERAUTH_REQUEST); 308 buffer_put_char(&b, SSH2_MSG_USERAUTH_REQUEST);
313 if (slen + 4 > rlen) 309 buffer_put_cstring(&b, pw->pw_name);
314 fatal("bad rlen/slen"); 310 buffer_put_cstring(&b,
315 buffer_append(&b, raw, rlen - slen - 4); 311 datafellows & SSH_BUG_PUBKEYAUTH ?
312 "ssh-userauth" :
313 service);
314 buffer_put_cstring(&b, "publickey");
315 buffer_put_char(&b, have_sig);
316 buffer_put_cstring(&b, KEX_DSS);
317 buffer_put_string(&b, pkblob, blen);
316#ifdef DEBUG_DSS 318#ifdef DEBUG_DSS
317 buffer_dump(&b); 319 buffer_dump(&b);
318#endif 320#endif
@@ -471,17 +473,36 @@ user_dsa_key_allowed(struct passwd *pw, Key *key)
471 found = key_new(KEY_DSA); 473 found = key_new(KEY_DSA);
472 474
473 while (fgets(line, sizeof(line), f)) { 475 while (fgets(line, sizeof(line), f)) {
474 char *cp; 476 char *cp, *options = NULL;
475 linenum++; 477 linenum++;
476 /* Skip leading whitespace, empty and comment lines. */ 478 /* Skip leading whitespace, empty and comment lines. */
477 for (cp = line; *cp == ' ' || *cp == '\t'; cp++) 479 for (cp = line; *cp == ' ' || *cp == '\t'; cp++)
478 ; 480 ;
479 if (!*cp || *cp == '\n' || *cp == '#') 481 if (!*cp || *cp == '\n' || *cp == '#')
480 continue; 482 continue;
483
481 bits = key_read(found, &cp); 484 bits = key_read(found, &cp);
482 if (bits == 0) 485 if (bits == 0) {
483 continue; 486 /* no key? check if there are options for this key */
484 if (key_equal(found, key)) { 487 int quoted = 0;
488 options = cp;
489 for (; *cp && (quoted || (*cp != ' ' && *cp != '\t')); cp++) {
490 if (*cp == '\\' && cp[1] == '"')
491 cp++; /* Skip both */
492 else if (*cp == '"')
493 quoted = !quoted;
494 }
495 /* Skip remaining whitespace. */
496 for (; *cp == ' ' || *cp == '\t'; cp++)
497 ;
498 bits = key_read(found, &cp);
499 if (bits == 0) {
500 /* still no key? advance to next line*/
501 continue;
502 }
503 }
504 if (key_equal(found, key) &&
505 auth_parse_options(pw, options, linenum) == 1) {
485 found_key = 1; 506 found_key = 1;
486 debug("matching key found: file %s, line %ld", 507 debug("matching key found: file %s, line %ld",
487 file, linenum); 508 file, linenum);
diff --git a/channels.c b/channels.c
index bfa025ad7..9da9db474 100644
--- a/channels.c
+++ b/channels.c
@@ -17,7 +17,7 @@
17 */ 17 */
18 18
19#include "includes.h" 19#include "includes.h"
20RCSID("$Id: channels.c,v 1.32 2000/06/07 09:55:44 djm Exp $"); 20RCSID("$Id: channels.c,v 1.33 2000/06/18 04:50:44 djm Exp $");
21 21
22#include "ssh.h" 22#include "ssh.h"
23#include "packet.h" 23#include "packet.h"
@@ -932,7 +932,6 @@ channel_output_poll()
932 packet_send(); 932 packet_send();
933 buffer_consume(&c->input, len); 933 buffer_consume(&c->input, len);
934 c->remote_window -= len; 934 c->remote_window -= len;
935 debug("channel %d: send data len %d", c->self, len);
936 } 935 }
937 } else if (c->istate == CHAN_INPUT_WAIT_DRAIN) { 936 } else if (c->istate == CHAN_INPUT_WAIT_DRAIN) {
938 if (compat13) 937 if (compat13)
diff --git a/compat.c b/compat.c
index 967e0b6b8..8e77fd799 100644
--- a/compat.c
+++ b/compat.c
@@ -28,7 +28,7 @@
28 */ 28 */
29 29
30#include "includes.h" 30#include "includes.h"
31RCSID("$Id: compat.c,v 1.11 2000/05/30 03:44:53 damien Exp $"); 31RCSID("$Id: compat.c,v 1.12 2000/06/18 04:50:44 djm Exp $");
32 32
33#include "ssh.h" 33#include "ssh.h"
34#include "packet.h" 34#include "packet.h"
@@ -61,6 +61,7 @@ compat_datafellows(const char *version)
61 char *version; 61 char *version;
62 int bugs; 62 int bugs;
63 } check[] = { 63 } check[] = {
64 {"2.2.0", SSH_BUG_HMAC},
64 {"2.1.0", SSH_BUG_SIGBLOB|SSH_BUG_HMAC}, 65 {"2.1.0", SSH_BUG_SIGBLOB|SSH_BUG_HMAC},
65 {"2.0.1", SSH_BUG_SIGBLOB|SSH_BUG_HMAC|SSH_BUG_PUBKEYAUTH|SSH_BUG_X11FWD}, 66 {"2.0.1", SSH_BUG_SIGBLOB|SSH_BUG_HMAC|SSH_BUG_PUBKEYAUTH|SSH_BUG_X11FWD},
66 {NULL, 0} 67 {NULL, 0}
diff --git a/readconf.c b/readconf.c
index 2751db345..c6d6f67db 100644
--- a/readconf.c
+++ b/readconf.c
@@ -14,7 +14,7 @@
14 */ 14 */
15 15
16#include "includes.h" 16#include "includes.h"
17RCSID("$Id: readconf.c,v 1.16 2000/06/07 09:55:44 djm Exp $"); 17RCSID("$Id: readconf.c,v 1.17 2000/06/18 04:50:44 djm Exp $");
18 18
19#include "ssh.h" 19#include "ssh.h"
20#include "cipher.h" 20#include "cipher.h"
@@ -165,7 +165,7 @@ static struct {
165}; 165};
166 166
167/* Characters considered whitespace in strtok calls. */ 167/* Characters considered whitespace in strtok calls. */
168#define WHITESPACE " \t\r\n" 168#define WHITESPACE " \t\r\n="
169 169
170 170
171/* 171/*
diff --git a/scp.c b/scp.c
index 19f0fd944..773a4f59f 100644
--- a/scp.c
+++ b/scp.c
@@ -45,7 +45,7 @@
45 */ 45 */
46 46
47#include "includes.h" 47#include "includes.h"
48RCSID("$Id: scp.c,v 1.23 2000/05/17 12:53:35 damien Exp $"); 48RCSID("$Id: scp.c,v 1.24 2000/06/18 04:50:44 djm Exp $");
49 49
50#include "ssh.h" 50#include "ssh.h"
51#include "xmalloc.h" 51#include "xmalloc.h"
@@ -155,7 +155,6 @@ do_cmd(char *host, char *remuser, char *cmd, int *fdin, int *fdout)
155 args[i++] = "-4"; 155 args[i++] = "-4";
156 if (IPv6) 156 if (IPv6)
157 args[i++] = "-6"; 157 args[i++] = "-6";
158 args[i++] = "-oFallBackToRsh no";
159 if (verbose_mode) 158 if (verbose_mode)
160 args[i++] = "-v"; 159 args[i++] = "-v";
161 if (compress_flag) 160 if (compress_flag)
@@ -1008,7 +1007,7 @@ run_err(const char *fmt,...)
1008 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF 1007 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
1009 * SUCH DAMAGE. 1008 * SUCH DAMAGE.
1010 * 1009 *
1011 * $Id: scp.c,v 1.23 2000/05/17 12:53:35 damien Exp $ 1010 * $Id: scp.c,v 1.24 2000/06/18 04:50:44 djm Exp $
1012 */ 1011 */
1013 1012
1014char * 1013char *
diff --git a/servconf.c b/servconf.c
index 6583829e7..0e323231d 100644
--- a/servconf.c
+++ b/servconf.c
@@ -12,7 +12,7 @@
12 */ 12 */
13 13
14#include "includes.h" 14#include "includes.h"
15RCSID("$Id: servconf.c,v 1.18 2000/06/07 09:55:44 djm Exp $"); 15RCSID("$Id: servconf.c,v 1.19 2000/06/18 04:50:44 djm Exp $");
16 16
17#include "ssh.h" 17#include "ssh.h"
18#include "servconf.h" 18#include "servconf.h"
@@ -75,6 +75,7 @@ initialize_server_options(ServerOptions *options)
75 options->ciphers = NULL; 75 options->ciphers = NULL;
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} 79}
79 80
80void 81void
@@ -160,7 +161,7 @@ fill_default_server_options(ServerOptions *options)
160 options->gateway_ports = 0; 161 options->gateway_ports = 0;
161} 162}
162 163
163#define WHITESPACE " \t\r\n" 164#define WHITESPACE " \t\r\n="
164 165
165/* Keyword tokens. */ 166/* Keyword tokens. */
166typedef enum { 167typedef enum {
@@ -182,7 +183,7 @@ typedef enum {
182 sStrictModes, sEmptyPasswd, sRandomSeedFile, sKeepAlives, sCheckMail, 183 sStrictModes, sEmptyPasswd, sRandomSeedFile, sKeepAlives, sCheckMail,
183 sUseLogin, sAllowUsers, sDenyUsers, sAllowGroups, sDenyGroups, 184 sUseLogin, sAllowUsers, sDenyUsers, sAllowGroups, sDenyGroups,
184 sIgnoreUserKnownHosts, sHostDSAKeyFile, sCiphers, sProtocol, sPidFile, 185 sIgnoreUserKnownHosts, sHostDSAKeyFile, sCiphers, sProtocol, sPidFile,
185 sGatewayPorts, sDSAAuthentication, sXAuthLocation 186 sGatewayPorts, sDSAAuthentication, sXAuthLocation, sSubsystem
186} ServerOpCodes; 187} ServerOpCodes;
187 188
188/* Textual representation of the tokens. */ 189/* Textual representation of the tokens. */
@@ -237,6 +238,7 @@ static struct {
237 { "ciphers", sCiphers }, 238 { "ciphers", sCiphers },
238 { "protocol", sProtocol }, 239 { "protocol", sProtocol },
239 { "gatewayports", sGatewayPorts }, 240 { "gatewayports", sGatewayPorts },
241 { "subsystem", sSubsystem },
240 { NULL, 0 } 242 { NULL, 0 }
241}; 243};
242 244
@@ -302,6 +304,7 @@ read_server_config(ServerOptions *options, const char *filename)
302 int linenum, *intptr, value; 304 int linenum, *intptr, value;
303 int bad_options = 0; 305 int bad_options = 0;
304 ServerOpCodes opcode; 306 ServerOpCodes opcode;
307 int i;
305 308
306 f = fopen(filename, "r"); 309 f = fopen(filename, "r");
307 if (!f) { 310 if (!f) {
@@ -613,6 +616,28 @@ parse_flag:
613 *intptr = value; 616 *intptr = value;
614 break; 617 break;
615 618
619 case sSubsystem:
620 if(options->num_subsystems >= MAX_SUBSYSTEMS) {
621 fatal("%s line %d: too many subsystems defined.",
622 filename, linenum);
623 }
624 cp = strtok(NULL, WHITESPACE);
625 if (!cp)
626 fatal("%s line %d: Missing subsystem name.",
627 filename, linenum);
628 for (i = 0; i < options->num_subsystems; i++)
629 if(strcmp(cp, options->subsystem_name[i]) == 0)
630 fatal("%s line %d: Subsystem '%s' already defined.",
631 filename, linenum, cp);
632 options->subsystem_name[options->num_subsystems] = xstrdup(cp);
633 cp = strtok(NULL, WHITESPACE);
634 if (!cp)
635 fatal("%s line %d: Missing subsystem command.",
636 filename, linenum);
637 options->subsystem_command[options->num_subsystems] = xstrdup(cp);
638 options->num_subsystems++;
639 break;
640
616 default: 641 default:
617 fprintf(stderr, "%s line %d: Missing handler for opcode %s (%d)\n", 642 fprintf(stderr, "%s line %d: Missing handler for opcode %s (%d)\n",
618 filename, linenum, cp, opcode); 643 filename, linenum, cp, opcode);
diff --git a/servconf.h b/servconf.h
index 5c6212f2d..6c647c2ed 100644
--- a/servconf.h
+++ b/servconf.h
@@ -13,7 +13,7 @@
13 * 13 *
14 */ 14 */
15 15
16/* RCSID("$Id: servconf.h,v 1.12 2000/06/07 09:55:44 djm Exp $"); */ 16/* RCSID("$Id: servconf.h,v 1.13 2000/06/18 04:50:44 djm Exp $"); */
17 17
18#ifndef SERVCONF_H 18#ifndef SERVCONF_H
19#define SERVCONF_H 19#define SERVCONF_H
@@ -24,6 +24,7 @@
24#define MAX_DENY_USERS 256 /* Max # users on deny list. */ 24#define MAX_DENY_USERS 256 /* Max # users on deny list. */
25#define MAX_ALLOW_GROUPS 256 /* Max # groups on allow list. */ 25#define MAX_ALLOW_GROUPS 256 /* Max # groups on allow list. */
26#define MAX_DENY_GROUPS 256 /* Max # groups on deny list. */ 26#define MAX_DENY_GROUPS 256 /* Max # groups on deny list. */
27#define MAX_SUBSYSTEMS 256 /* Max # subsystems. */
27 28
28typedef struct { 29typedef struct {
29 unsigned int num_ports; 30 unsigned int num_ports;
@@ -94,6 +95,10 @@ typedef struct {
94 char *allow_groups[MAX_ALLOW_GROUPS]; 95 char *allow_groups[MAX_ALLOW_GROUPS];
95 unsigned int num_deny_groups; 96 unsigned int num_deny_groups;
96 char *deny_groups[MAX_DENY_GROUPS]; 97 char *deny_groups[MAX_DENY_GROUPS];
98
99 unsigned int num_subsystems;
100 char *subsystem_name[MAX_SUBSYSTEMS];
101 char *subsystem_command[MAX_SUBSYSTEMS];
97} ServerOptions; 102} ServerOptions;
98/* 103/*
99 * Initializes the server options to special values that indicate that they 104 * Initializes the server options to special values that indicate that they
diff --git a/serverloop.c b/serverloop.c
index b08fcfd92..311a285c3 100644
--- a/serverloop.c
+++ b/serverloop.c
@@ -23,6 +23,7 @@
23#include "ssh2.h" 23#include "ssh2.h"
24#include "session.h" 24#include "session.h"
25#include "dispatch.h" 25#include "dispatch.h"
26#include "auth-options.h"
26 27
27static Buffer stdin_buffer; /* Buffer for stdin data. */ 28static Buffer stdin_buffer; /* Buffer for stdin data. */
28static Buffer stdout_buffer; /* Buffer for stdout data. */ 29static Buffer stdout_buffer; /* Buffer for stdout data. */
@@ -719,7 +720,13 @@ input_direct_tcpip(void)
719 720
720 debug("open direct-tcpip: from %s port %d to %s port %d", 721 debug("open direct-tcpip: from %s port %d to %s port %d",
721 originator, originator_port, target, target_port); 722 originator, originator_port, target, target_port);
723
722 /* XXX check permission */ 724 /* XXX check permission */
725 if (! no_port_forwarding_flag) {
726 xfree(target);
727 xfree(originator);
728 return -1;
729 }
723 sock = channel_connect_to(target, target_port); 730 sock = channel_connect_to(target, target_port);
724 xfree(target); 731 xfree(target);
725 xfree(originator); 732 xfree(originator);
diff --git a/session.c b/session.c
index 6c1c32767..64e240b73 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.17 2000/06/05 19:53:40 markus Exp $"); 11RCSID("$OpenBSD: session.c,v 1.20 2000/06/18 04:42:54 markus Exp $");
12 12
13#include "xmalloc.h" 13#include "xmalloc.h"
14#include "ssh.h" 14#include "ssh.h"
@@ -26,6 +26,7 @@ RCSID("$OpenBSD: session.c,v 1.17 2000/06/05 19:53:40 markus Exp $");
26#include "bufaux.h" 26#include "bufaux.h"
27#include "ssh2.h" 27#include "ssh2.h"
28#include "auth.h" 28#include "auth.h"
29#include "auth-options.h"
29 30
30/* types */ 31/* types */
31 32
@@ -88,18 +89,6 @@ Session sessions[MAX_SESSIONS];
88char *aixloginmsg; 89char *aixloginmsg;
89#endif /* WITH_AIXAUTHENTICATE */ 90#endif /* WITH_AIXAUTHENTICATE */
90 91
91/* Flags set in auth-rsa from authorized_keys flags. These are set in auth-rsa.c. */
92int no_port_forwarding_flag = 0;
93int no_agent_forwarding_flag = 0;
94int no_x11_forwarding_flag = 0;
95int no_pty_flag = 0;
96
97/* RSA authentication "command=" option. */
98char *forced_command = NULL;
99
100/* RSA authentication "environment=" options. */
101struct envstring *custom_environment = NULL;
102
103/* 92/*
104 * Remove local Xauthority file. 93 * Remove local Xauthority file.
105 */ 94 */
@@ -1260,6 +1249,8 @@ session_pty_req(Session *s)
1260 unsigned int len; 1249 unsigned int len;
1261 char *term_modes; /* encoded terminal modes */ 1250 char *term_modes; /* encoded terminal modes */
1262 1251
1252 if (no_pty_flag)
1253 return 0;
1263 if (s->ttyfd != -1) 1254 if (s->ttyfd != -1)
1264 return 0; 1255 return 0;
1265 s->term = packet_get_string(&len); 1256 s->term = packet_get_string(&len);
@@ -1307,10 +1298,22 @@ session_subsystem_req(Session *s)
1307 unsigned int len; 1298 unsigned int len;
1308 int success = 0; 1299 int success = 0;
1309 char *subsys = packet_get_string(&len); 1300 char *subsys = packet_get_string(&len);
1301 int i;
1310 1302
1311 packet_done(); 1303 packet_done();
1312 log("subsystem request for %s", subsys); 1304 log("subsystem request for %s", subsys);
1313 1305
1306 for (i = 0; i < options.num_subsystems; i++) {
1307 if(strcmp(subsys, options.subsystem_name[i]) == 0) {
1308 debug("subsystem: exec() %s", options.subsystem_command[i]);
1309 do_exec_no_pty(s, options.subsystem_command[i], s->pw);
1310 success = 1;
1311 }
1312 }
1313
1314 if (!success)
1315 log("subsystem request for %s failed, subsystem not found", subsys);
1316
1314 xfree(subsys); 1317 xfree(subsys);
1315 return success; 1318 return success;
1316} 1319}
@@ -1318,6 +1321,10 @@ session_subsystem_req(Session *s)
1318int 1321int
1319session_x11_req(Session *s) 1322session_x11_req(Session *s)
1320{ 1323{
1324 if (!no_port_forwarding_flag) {
1325 debug("X11 forwarding disabled in user configuration file.");
1326 return 0;
1327 }
1321 if (!options.x11_forwarding) { 1328 if (!options.x11_forwarding) {
1322 debug("X11 forwarding disabled in server configuration file."); 1329 debug("X11 forwarding disabled in server configuration file.");
1323 return 0; 1330 return 0;
@@ -1364,6 +1371,41 @@ session_x11_req(Session *s)
1364 return 1; 1371 return 1;
1365} 1372}
1366 1373
1374int
1375session_shell_req(Session *s)
1376{
1377 /* if forced_command == NULL, the shell is execed */
1378 char *shell = forced_command;
1379 packet_done();
1380 s->extended = 1;
1381 if (s->ttyfd == -1)
1382 do_exec_no_pty(s, shell, s->pw);
1383 else
1384 do_exec_pty(s, shell, s->pw);
1385 return 1;
1386}
1387
1388int
1389session_exec_req(Session *s)
1390{
1391 unsigned int len;
1392 char *command = packet_get_string(&len);
1393 packet_done();
1394 if (forced_command) {
1395 xfree(command);
1396 command = forced_command;
1397 debug("Forced command '%.500s'", forced_command);
1398 }
1399 s->extended = 1;
1400 if (s->ttyfd == -1)
1401 do_exec_no_pty(s, command, s->pw);
1402 else
1403 do_exec_pty(s, command, s->pw);
1404 if (forced_command == NULL)
1405 xfree(command);
1406 return 1;
1407}
1408
1367void 1409void
1368session_input_channel_req(int id, void *arg) 1410session_input_channel_req(int id, void *arg)
1369{ 1411{
@@ -1393,23 +1435,9 @@ session_input_channel_req(int id, void *arg)
1393 */ 1435 */
1394 if (c->type == SSH_CHANNEL_LARVAL) { 1436 if (c->type == SSH_CHANNEL_LARVAL) {
1395 if (strcmp(rtype, "shell") == 0) { 1437 if (strcmp(rtype, "shell") == 0) {
1396 packet_done(); 1438 success = session_shell_req(s);
1397 s->extended = 1;
1398 if (s->ttyfd == -1)
1399 do_exec_no_pty(s, NULL, s->pw);
1400 else
1401 do_exec_pty(s, NULL, s->pw);
1402 success = 1;
1403 } else if (strcmp(rtype, "exec") == 0) { 1439 } else if (strcmp(rtype, "exec") == 0) {
1404 char *command = packet_get_string(&len); 1440 success = session_exec_req(s);
1405 packet_done();
1406 s->extended = 1;
1407 if (s->ttyfd == -1)
1408 do_exec_no_pty(s, command, s->pw);
1409 else
1410 do_exec_pty(s, command, s->pw);
1411 xfree(command);
1412 success = 1;
1413 } else if (strcmp(rtype, "pty-req") == 0) { 1441 } else if (strcmp(rtype, "pty-req") == 0) {
1414 success = session_pty_req(s); 1442 success = session_pty_req(s);
1415 } else if (strcmp(rtype, "x11-req") == 0) { 1443 } else if (strcmp(rtype, "x11-req") == 0) {
diff --git a/sshconnect.c b/sshconnect.c
index bf00159b3..835ca7b3a 100644
--- a/sshconnect.c
+++ b/sshconnect.c
@@ -8,7 +8,7 @@
8 */ 8 */
9 9
10#include "includes.h" 10#include "includes.h"
11RCSID("$OpenBSD: sshconnect.c,v 1.74 2000/05/17 16:57:02 markus Exp $"); 11RCSID("$OpenBSD: sshconnect.c,v 1.76 2000/06/17 20:30:10 markus Exp $");
12 12
13#include <openssl/bn.h> 13#include <openssl/bn.h>
14#include <openssl/dsa.h> 14#include <openssl/dsa.h>
@@ -314,23 +314,28 @@ ssh_exchange_identification()
314 int connection_out = packet_get_connection_out(); 314 int connection_out = packet_get_connection_out();
315 315
316 /* Read other side\'s version identification. */ 316 /* Read other side\'s version identification. */
317 for (i = 0; i < sizeof(buf) - 1; i++) { 317 for (;;) {
318 int len = read(connection_in, &buf[i], 1); 318 for (i = 0; i < sizeof(buf) - 1; i++) {
319 if (len < 0) 319 int len = atomicio(read, connection_in, &buf[i], 1);
320 fatal("ssh_exchange_identification: read: %.100s", strerror(errno)); 320 if (len < 0)
321 if (len != 1) 321 fatal("ssh_exchange_identification: read: %.100s", strerror(errno));
322 fatal("ssh_exchange_identification: Connection closed by remote host"); 322 if (len != 1)
323 if (buf[i] == '\r') { 323 fatal("ssh_exchange_identification: Connection closed by remote host");
324 buf[i] = '\n'; 324 if (buf[i] == '\r') {
325 buf[i + 1] = 0; 325 buf[i] = '\n';
326 continue; /**XXX wait for \n */ 326 buf[i + 1] = 0;
327 continue; /**XXX wait for \n */
328 }
329 if (buf[i] == '\n') {
330 buf[i + 1] = 0;
331 break;
332 }
327 } 333 }
328 if (buf[i] == '\n') { 334 buf[sizeof(buf) - 1] = 0;
329 buf[i + 1] = 0; 335 if (strncmp(buf, "SSH-", 4) == 0)
330 break; 336 break;
331 } 337 debug("ssh_exchange_identification: %s", buf);
332 } 338 }
333 buf[sizeof(buf) - 1] = 0;
334 server_version_string = xstrdup(buf); 339 server_version_string = xstrdup(buf);
335 340
336 /* 341 /*
diff --git a/sshd.8 b/sshd.8
index deb72e447..b71378c1e 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.23 2000/06/07 09:55:44 djm Exp $ 12.\" $Id: sshd.8,v 1.24 2000/06/18 04:50:45 djm Exp $
13.\" 13.\"
14.Dd September 25, 1999 14.Dd September 25, 1999
15.Dt SSHD 8 15.Dt SSHD 8
@@ -543,6 +543,11 @@ This is normally desirable because novices sometimes accidentally leave their
543directory or files world-writable. 543directory or files world-writable.
544The default is 544The default is
545.Dq yes . 545.Dq yes .
546.It Cm Subsystem
547Configures an external subsystem (e.g. file transfer daemon).
548Arguments should be a subsystem name and a command to execute upon subsystem request.
549By default no subsystems are defined.
550Note that this option applies to protocol version 2 only.
546.It Cm SyslogFacility 551.It Cm SyslogFacility
547Gives the facility code that is used when logging messages from 552Gives the facility code that is used when logging messages from
548.Nm sshd . 553.Nm sshd .
diff --git a/sshd_config b/sshd_config
index 52436ac36..d3bab840a 100644
--- a/sshd_config
+++ b/sshd_config
@@ -49,3 +49,5 @@ PermitEmptyPasswords no
49 49
50CheckMail no 50CheckMail no
51UseLogin no 51UseLogin no
52
53#Subsystem sftp /usr/local/sbin/sftpd