diff options
-rw-r--r-- | ChangeLog | 32 | ||||
-rw-r--r-- | Makefile.in | 2 | ||||
-rw-r--r-- | auth-options.c | 208 | ||||
-rw-r--r-- | auth-options.h | 13 | ||||
-rw-r--r-- | auth-rsa.c | 199 | ||||
-rw-r--r-- | auth2.c | 61 | ||||
-rw-r--r-- | channels.c | 3 | ||||
-rw-r--r-- | compat.c | 3 | ||||
-rw-r--r-- | readconf.c | 4 | ||||
-rw-r--r-- | scp.c | 5 | ||||
-rw-r--r-- | servconf.c | 31 | ||||
-rw-r--r-- | servconf.h | 7 | ||||
-rw-r--r-- | serverloop.c | 7 | ||||
-rw-r--r-- | session.c | 86 | ||||
-rw-r--r-- | sshconnect.c | 35 | ||||
-rw-r--r-- | sshd.8 | 7 | ||||
-rw-r--r-- | sshd_config | 2 |
17 files changed, 431 insertions, 274 deletions
@@ -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 | ||
12 | 20000613 | 44 | 20000613 |
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 | ||
41 | SSHOBJS= ssh.o sshconnect.o sshconnect1.o sshconnect2.o log-client.o readconf.o clientloop.o | 41 | SSHOBJS= ssh.o sshconnect.o sshconnect1.o sshconnect2.o log-client.o readconf.o clientloop.o |
42 | 42 | ||
43 | SSHDOBJS= 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 | 43 | SSHDOBJS= 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 | ||
45 | TROFFMAN = scp.1 ssh-add.1 ssh-agent.1 ssh-keygen.1 ssh.1 sshd.8 | 45 | TROFFMAN = scp.1 ssh-add.1 ssh-agent.1 ssh-keygen.1 ssh.1 sshd.8 |
46 | CATMAN = scp.0 ssh-add.0 ssh-agent.0 ssh-keygen.0 ssh.0 sshd.0 | 46 | CATMAN = 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" | ||
2 | RCSID("$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 */ | ||
10 | int no_port_forwarding_flag = 0; | ||
11 | int no_agent_forwarding_flag = 0; | ||
12 | int no_x11_forwarding_flag = 0; | ||
13 | int no_pty_flag = 0; | ||
14 | |||
15 | /* "command=" option. */ | ||
16 | char *forced_command = NULL; | ||
17 | |||
18 | /* "environment=" options. */ | ||
19 | struct envstring *custom_environment = NULL; | ||
20 | |||
21 | /* return 1 if access is granted, 0 if not. side effect: sets key option flags */ | ||
22 | int | ||
23 | auth_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 | } | ||
184 | next_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 | |||
201 | bad_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. */ | ||
4 | extern int no_port_forwarding_flag; | ||
5 | extern int no_agent_forwarding_flag; | ||
6 | extern int no_x11_forwarding_flag; | ||
7 | extern int no_pty_flag; | ||
8 | extern char *forced_command; | ||
9 | extern struct envstring *custom_environment; | ||
10 | |||
11 | /* return 1 if access is granted, 0 if not. side effect: sets key option flags */ | ||
12 | int 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" |
19 | RCSID("$Id: auth-rsa.c,v 1.20 2000/06/07 09:55:44 djm Exp $"); | 19 | RCSID("$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. */ | ||
34 | extern int no_port_forwarding_flag; | ||
35 | extern int no_agent_forwarding_flag; | ||
36 | extern int no_x11_forwarding_flag; | ||
37 | extern int no_pty_flag; | ||
38 | extern char *forced_command; | ||
39 | extern 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 | } |
@@ -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" |
30 | RCSID("$OpenBSD: auth2.c,v 1.8 2000/05/08 17:42:24 markus Exp $"); | 30 | RCSID("$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 */ |
59 | extern ServerOptions options; | 60 | extern ServerOptions options; |
@@ -69,7 +70,7 @@ void protocol_error(int type, int plen); | |||
69 | /* auth */ | 70 | /* auth */ |
70 | int ssh2_auth_none(struct passwd *pw); | 71 | int ssh2_auth_none(struct passwd *pw); |
71 | int ssh2_auth_password(struct passwd *pw); | 72 | int ssh2_auth_password(struct passwd *pw); |
72 | int ssh2_auth_pubkey(struct passwd *pw, unsigned char *raw, unsigned int rlen); | 73 | int ssh2_auth_pubkey(struct passwd *pw, char *service); |
73 | 74 | ||
74 | /* helper */ | 75 | /* helper */ |
75 | struct passwd* auth_set_user(char *u, char *s); | 76 | struct 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 | } |
279 | int | 277 | int |
280 | ssh2_auth_pubkey(struct passwd *pw, unsigned char *raw, unsigned int rlen) | 278 | ssh2_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" |
20 | RCSID("$Id: channels.c,v 1.32 2000/06/07 09:55:44 djm Exp $"); | 20 | RCSID("$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) |
@@ -28,7 +28,7 @@ | |||
28 | */ | 28 | */ |
29 | 29 | ||
30 | #include "includes.h" | 30 | #include "includes.h" |
31 | RCSID("$Id: compat.c,v 1.11 2000/05/30 03:44:53 damien Exp $"); | 31 | RCSID("$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" |
17 | RCSID("$Id: readconf.c,v 1.16 2000/06/07 09:55:44 djm Exp $"); | 17 | RCSID("$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 | /* |
@@ -45,7 +45,7 @@ | |||
45 | */ | 45 | */ |
46 | 46 | ||
47 | #include "includes.h" | 47 | #include "includes.h" |
48 | RCSID("$Id: scp.c,v 1.23 2000/05/17 12:53:35 damien Exp $"); | 48 | RCSID("$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 | ||
1014 | char * | 1013 | char * |
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" |
15 | RCSID("$Id: servconf.c,v 1.18 2000/06/07 09:55:44 djm Exp $"); | 15 | RCSID("$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 | ||
80 | void | 81 | void |
@@ -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. */ |
166 | typedef enum { | 167 | typedef 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 | ||
28 | typedef struct { | 29 | typedef 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 | ||
27 | static Buffer stdin_buffer; /* Buffer for stdin data. */ | 28 | static Buffer stdin_buffer; /* Buffer for stdin data. */ |
28 | static Buffer stdout_buffer; /* Buffer for stdout data. */ | 29 | static 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); |
@@ -8,7 +8,7 @@ | |||
8 | */ | 8 | */ |
9 | 9 | ||
10 | #include "includes.h" | 10 | #include "includes.h" |
11 | RCSID("$OpenBSD: session.c,v 1.17 2000/06/05 19:53:40 markus Exp $"); | 11 | RCSID("$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]; | |||
88 | char *aixloginmsg; | 89 | char *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. */ | ||
92 | int no_port_forwarding_flag = 0; | ||
93 | int no_agent_forwarding_flag = 0; | ||
94 | int no_x11_forwarding_flag = 0; | ||
95 | int no_pty_flag = 0; | ||
96 | |||
97 | /* RSA authentication "command=" option. */ | ||
98 | char *forced_command = NULL; | ||
99 | |||
100 | /* RSA authentication "environment=" options. */ | ||
101 | struct 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) | |||
1318 | int | 1321 | int |
1319 | session_x11_req(Session *s) | 1322 | session_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 | ||
1374 | int | ||
1375 | session_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 | |||
1388 | int | ||
1389 | session_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 | |||
1367 | void | 1409 | void |
1368 | session_input_channel_req(int id, void *arg) | 1410 | session_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" |
11 | RCSID("$OpenBSD: sshconnect.c,v 1.74 2000/05/17 16:57:02 markus Exp $"); | 11 | RCSID("$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 | /* |
@@ -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 | |||
543 | directory or files world-writable. | 543 | directory or files world-writable. |
544 | The default is | 544 | The default is |
545 | .Dq yes . | 545 | .Dq yes . |
546 | .It Cm Subsystem | ||
547 | Configures an external subsystem (e.g. file transfer daemon). | ||
548 | Arguments should be a subsystem name and a command to execute upon subsystem request. | ||
549 | By default no subsystems are defined. | ||
550 | Note that this option applies to protocol version 2 only. | ||
546 | .It Cm SyslogFacility | 551 | .It Cm SyslogFacility |
547 | Gives the facility code that is used when logging messages from | 552 | Gives 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 | ||
50 | CheckMail no | 50 | CheckMail no |
51 | UseLogin no | 51 | UseLogin no |
52 | |||
53 | #Subsystem sftp /usr/local/sbin/sftpd | ||