summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--ChangeLog32
-rw-r--r--Makefile.in4
-rw-r--r--auth.c606
-rw-r--r--auth.h6
-rw-r--r--bufaux.c53
-rw-r--r--bufaux.h5
-rw-r--r--channels.c1194
-rw-r--r--channels.h194
-rw-r--r--cipher.c123
-rw-r--r--cipher.h22
-rw-r--r--clientloop.c205
-rw-r--r--compress.c40
-rw-r--r--dispatch.c78
-rw-r--r--dispatch.h11
-rw-r--r--log-server.c12
-rw-r--r--mpaux.c8
-rw-r--r--nchan.c9
-rw-r--r--nchan.h4
-rw-r--r--packet.c3
-rw-r--r--pty.h4
-rw-r--r--readconf.c3
-rw-r--r--serverloop.c195
-rw-r--r--session.c1153
-rw-r--r--session.h7
-rw-r--r--ssh.c3
-rw-r--r--ssh.h171
-rw-r--r--ssh2.h106
-rw-r--r--sshd.810
-rw-r--r--sshd.c1855
29 files changed, 3410 insertions, 2706 deletions
diff --git a/ChangeLog b/ChangeLog
index 2462417dc..585686e2a 100644
--- a/ChangeLog
+++ b/ChangeLog
@@ -1,3 +1,35 @@
120000401
2 - Big OpenBSD CVS update (mainly beginnings of SSH2 infrastructure)
3 - [auth.c session.c sshd.c auth.h]
4 split sshd.c -> auth.c session.c sshd.c plus cleanup and goto-removal
5 - [bufaux.c bufaux.h]
6 support ssh2 bignums
7 - [channels.c channels.h clientloop.c sshd.c nchan.c nchan.h packet.c]
8 [readconf.c ssh.c ssh.h serverloop.c]
9 replace big switch() with function tables (prepare for ssh2)
10 - [ssh2.h]
11 ssh2 message type codes
12 - [sshd.8]
13 reorder Xr to avoid cutting
14 - [serverloop.c]
15 close(fdin) if fdin != fdout, shutdown otherwise, ok theo@
16 - [channels.c]
17 missing close
18 allow bigger packets
19 - [cipher.c cipher.h]
20 support ssh2 ciphers
21 - [compress.c]
22 cleanup, less code
23 - [dispatch.c dispatch.h]
24 function tables for different message types
25 - [log-server.c]
26 do not log() if debuggin to stderr
27 rename a cpp symbol, to avoid param.h collision
28 - [mpaux.c]
29 KNF
30 - [nchan.c]
31 sync w/ channels.c
32
120000326 3320000326
2 - Better tests for OpenSSL w/ RSAref 34 - Better tests for OpenSSL w/ RSAref
3 - Added replacement setenv() function from OpenBSD libc. Suggested by 35 - Added replacement setenv() function from OpenBSD libc. Suggested by
diff --git a/Makefile.in b/Makefile.in
index 6fee608df..43870d5f9 100644
--- a/Makefile.in
+++ b/Makefile.in
@@ -31,11 +31,11 @@ LDFLAGS=-L. @LDFLAGS@
31 31
32TARGETS=ssh sshd ssh-add ssh-keygen ssh-agent scp $(EXTRA_TARGETS) 32TARGETS=ssh sshd ssh-add ssh-keygen ssh-agent scp $(EXTRA_TARGETS)
33 33
34LIBOBJS= atomicio.o authfd.o authfile.o bsd-bindresvport.o bsd-daemon.o bsd-misc.o bsd-mktemp.o bsd-rresvport.o bsd-setenv.o bsd-snprintf.o bsd-strlcat.o bsd-strlcpy.o bufaux.o buffer.o canohost.o channels.o cipher.o compat.o compress.o crc32.o deattack.o fake-getaddrinfo.o fake-getnameinfo.o fingerprint.o hostfile.o key.o log.o match.o mpaux.o nchan.o packet.o radix.o random.o readpass.o rsa.o tildexpand.o ttymodes.o uidswap.o xmalloc.o 34LIBOBJS= atomicio.o authfd.o authfile.o bsd-bindresvport.o bsd-daemon.o bsd-misc.o bsd-mktemp.o bsd-rresvport.o bsd-setenv.o bsd-snprintf.o bsd-strlcat.o bsd-strlcpy.o bufaux.o buffer.o canohost.o channels.o cipher.o compat.o compress.o crc32.o deattack.o dispatch.o fake-getaddrinfo.o fake-getnameinfo.o fingerprint.o hostfile.o key.o log.o match.o mpaux.o nchan.o packet.o radix.o random.o readpass.o rsa.o tildexpand.o ttymodes.o uidswap.o xmalloc.o
35 35
36SSHOBJS= ssh.o sshconnect.o log-client.o readconf.o clientloop.o 36SSHOBJS= ssh.o sshconnect.o log-client.o readconf.o clientloop.o
37 37
38SSHDOBJS= sshd.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 servconf.o serverloop.o bsd-login.o md5crypt.o 38SSHDOBJS= sshd.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 servconf.o serverloop.o bsd-login.o md5crypt.o session.o auth.o
39 39
40TROFFMAN = scp.1 ssh-add.1 ssh-agent.1 ssh-keygen.1 ssh.1 sshd.8 40TROFFMAN = scp.1 ssh-add.1 ssh-agent.1 ssh-keygen.1 ssh.1 sshd.8
41CATMAN = scp.0 ssh-add.0 ssh-agent.0 ssh-keygen.0 ssh.0 sshd.0 41CATMAN = scp.0 ssh-add.0 ssh-agent.0 ssh-keygen.0 ssh.0 sshd.0
diff --git a/auth.c b/auth.c
new file mode 100644
index 000000000..11b538172
--- /dev/null
+++ b/auth.c
@@ -0,0 +1,606 @@
1/*
2 * Copyright (c) 1995 Tatu Ylonen <ylo@cs.hut.fi>, Espoo, Finland
3 * All rights reserved
4 */
5
6#include "includes.h"
7RCSID("$OpenBSD: auth.c,v 1.1 2000/03/28 21:15:45 markus Exp $");
8
9#include "xmalloc.h"
10#include "rsa.h"
11#include "ssh.h"
12#include "pty.h"
13#include "packet.h"
14#include "buffer.h"
15#include "cipher.h"
16#include "mpaux.h"
17#include "servconf.h"
18#include "channels.h"
19#include "match.h"
20
21#include "session.h"
22#include "dispatch.h"
23
24/* import */
25extern ServerOptions options;
26extern char *forced_command;
27
28/*
29 * Check if the user is allowed to log in via ssh. If user is listed in
30 * DenyUsers or user's primary group is listed in DenyGroups, false will
31 * be returned. If AllowUsers isn't empty and user isn't listed there, or
32 * if AllowGroups isn't empty and user isn't listed there, false will be
33 * returned.
34 * If the user's shell is not executable, false will be returned.
35 * Otherwise true is returned.
36 */
37static int
38allowed_user(struct passwd * pw)
39{
40 struct stat st;
41 struct group *grp;
42 int i;
43#ifdef WITH_AIXAUTHENTICATE
44 char *loginmsg;
45#endif /* WITH_AIXAUTHENTICATE */
46
47 /* Shouldn't be called if pw is NULL, but better safe than sorry... */
48 if (!pw)
49 return 0;
50
51 /* deny if shell does not exists or is not executable */
52 if (stat(pw->pw_shell, &st) != 0)
53 return 0;
54 if (!((st.st_mode & S_IFREG) && (st.st_mode & (S_IXOTH|S_IXUSR|S_IXGRP))))
55 return 0;
56
57 /* Return false if user is listed in DenyUsers */
58 if (options.num_deny_users > 0) {
59 if (!pw->pw_name)
60 return 0;
61 for (i = 0; i < options.num_deny_users; i++)
62 if (match_pattern(pw->pw_name, options.deny_users[i]))
63 return 0;
64 }
65 /* Return false if AllowUsers isn't empty and user isn't listed there */
66 if (options.num_allow_users > 0) {
67 if (!pw->pw_name)
68 return 0;
69 for (i = 0; i < options.num_allow_users; i++)
70 if (match_pattern(pw->pw_name, options.allow_users[i]))
71 break;
72 /* i < options.num_allow_users iff we break for loop */
73 if (i >= options.num_allow_users)
74 return 0;
75 }
76 /* Get the primary group name if we need it. Return false if it fails */
77 if (options.num_deny_groups > 0 || options.num_allow_groups > 0) {
78 grp = getgrgid(pw->pw_gid);
79 if (!grp)
80 return 0;
81
82 /* Return false if user's group is listed in DenyGroups */
83 if (options.num_deny_groups > 0) {
84 if (!grp->gr_name)
85 return 0;
86 for (i = 0; i < options.num_deny_groups; i++)
87 if (match_pattern(grp->gr_name, options.deny_groups[i]))
88 return 0;
89 }
90 /*
91 * Return false if AllowGroups isn't empty and user's group
92 * isn't listed there
93 */
94 if (options.num_allow_groups > 0) {
95 if (!grp->gr_name)
96 return 0;
97 for (i = 0; i < options.num_allow_groups; i++)
98 if (match_pattern(grp->gr_name, options.allow_groups[i]))
99 break;
100 /* i < options.num_allow_groups iff we break for
101 loop */
102 if (i >= options.num_allow_groups)
103 return 0;
104 }
105 }
106
107#ifdef WITH_AIXAUTHENTICATE
108 if (loginrestrictions(pw->pw_name,S_LOGIN,NULL,&loginmsg) != 0)
109 return 0;
110#endif /* WITH_AIXAUTHENTICATE */
111
112 /* We found no reason not to let this user try to log on... */
113 return 1;
114}
115
116/*
117 * convert ssh auth msg type into description
118 */
119char *
120get_authname(int type)
121{
122 static char buf[1024];
123 switch (type) {
124 case SSH_CMSG_AUTH_PASSWORD:
125 return "password";
126 case SSH_CMSG_AUTH_RSA:
127 return "rsa";
128 case SSH_CMSG_AUTH_RHOSTS_RSA:
129 return "rhosts-rsa";
130 case SSH_CMSG_AUTH_RHOSTS:
131 return "rhosts";
132#ifdef KRB4
133 case SSH_CMSG_AUTH_KERBEROS:
134 return "kerberos";
135#endif
136#ifdef SKEY
137 case SSH_CMSG_AUTH_TIS_RESPONSE:
138 return "s/key";
139#endif
140 }
141 snprintf(buf, sizeof buf, "bad-auth-msg-%d", type);
142 return buf;
143}
144
145#define AUTH_FAIL_MAX 6
146#define AUTH_FAIL_LOG (AUTH_FAIL_MAX/2)
147#define AUTH_FAIL_MSG "Too many authentication failures for %.100s"
148
149/*
150 * The user does not exist or access is denied,
151 * but fake indication that authentication is needed.
152 */
153void
154do_fake_authloop1(char *user)
155{
156 int attempt = 0;
157
158 log("Faking authloop for illegal user %.200s from %.200s port %d",
159 user,
160 get_remote_ipaddr(),
161 get_remote_port());
162
163#ifdef WITH_AIXAUTHENTICATE
164 if (strncmp(get_authname(type),"password",
165 strlen(get_authname(type))) == 0)
166 loginfailed(pw->pw_name,get_canonical_hostname(),"ssh");
167#endif /* WITH_AIXAUTHENTICATE */
168
169 /* Indicate that authentication is needed. */
170 packet_start(SSH_SMSG_FAILURE);
171 packet_send();
172 packet_write_wait();
173
174 /*
175 * Keep reading packets, and always respond with a failure. This is
176 * to avoid disclosing whether such a user really exists.
177 */
178 for (attempt = 1;; attempt++) {
179 /* Read a packet. This will not return if the client disconnects. */
180 int plen;
181#ifndef SKEY
182 (void)packet_read(&plen);
183#else /* SKEY */
184 int type = packet_read(&plen);
185 unsigned int dlen;
186 char *password, *skeyinfo;
187 /* Try to send a fake s/key challenge. */
188 if (options.skey_authentication == 1 &&
189 (skeyinfo = skey_fake_keyinfo(user)) != NULL) {
190 password = NULL;
191 if (type == SSH_CMSG_AUTH_TIS) {
192 packet_start(SSH_SMSG_AUTH_TIS_CHALLENGE);
193 packet_put_string(skeyinfo, strlen(skeyinfo));
194 packet_send();
195 packet_write_wait();
196 continue;
197 } else if (type == SSH_CMSG_AUTH_PASSWORD &&
198 options.password_authentication &&
199 (password = packet_get_string(&dlen)) != NULL &&
200 dlen == 5 &&
201 strncasecmp(password, "s/key", 5) == 0 ) {
202 packet_send_debug(skeyinfo);
203 }
204 if (password != NULL)
205 xfree(password);
206 }
207#endif
208 if (attempt > AUTH_FAIL_MAX)
209 packet_disconnect(AUTH_FAIL_MSG, user);
210
211 /*
212 * Send failure. This should be indistinguishable from a
213 * failed authentication.
214 */
215 packet_start(SSH_SMSG_FAILURE);
216 packet_send();
217 packet_write_wait();
218 }
219 /* NOTREACHED */
220 abort();
221}
222
223/*
224 * read packets and try to authenticate local user *pw.
225 * return if authentication is successfull
226 */
227void
228do_authloop(struct passwd * pw)
229{
230 int attempt = 0;
231 unsigned int bits;
232 RSA *client_host_key;
233 BIGNUM *n;
234 char *client_user = NULL, *password = NULL;
235 char user[1024];
236 unsigned int dlen;
237 int plen, nlen, elen;
238 unsigned int ulen;
239 int type = 0;
240 void (*authlog) (const char *fmt,...) = verbose;
241
242 /* Indicate that authentication is needed. */
243 packet_start(SSH_SMSG_FAILURE);
244 packet_send();
245 packet_write_wait();
246
247 for (attempt = 1;; attempt++) {
248 int authenticated = 0;
249 strlcpy(user, "", sizeof user);
250
251 /* Get a packet from the client. */
252 type = packet_read(&plen);
253
254 /* Process the packet. */
255 switch (type) {
256#ifdef AFS
257 case SSH_CMSG_HAVE_KERBEROS_TGT:
258 if (!options.kerberos_tgt_passing) {
259 /* packet_get_all(); */
260 verbose("Kerberos tgt passing disabled.");
261 break;
262 } else {
263 /* Accept Kerberos tgt. */
264 char *tgt = packet_get_string(&dlen);
265 packet_integrity_check(plen, 4 + dlen, type);
266 if (!auth_kerberos_tgt(pw, tgt))
267 verbose("Kerberos tgt REFUSED for %s", pw->pw_name);
268 xfree(tgt);
269 }
270 continue;
271
272 case SSH_CMSG_HAVE_AFS_TOKEN:
273 if (!options.afs_token_passing || !k_hasafs()) {
274 /* packet_get_all(); */
275 verbose("AFS token passing disabled.");
276 break;
277 } else {
278 /* Accept AFS token. */
279 char *token_string = packet_get_string(&dlen);
280 packet_integrity_check(plen, 4 + dlen, type);
281 if (!auth_afs_token(pw, token_string))
282 verbose("AFS token REFUSED for %s", pw->pw_name);
283 xfree(token_string);
284 }
285 continue;
286#endif /* AFS */
287#ifdef KRB4
288 case SSH_CMSG_AUTH_KERBEROS:
289 if (!options.kerberos_authentication) {
290 /* packet_get_all(); */
291 verbose("Kerberos authentication disabled.");
292 break;
293 } else {
294 /* Try Kerberos v4 authentication. */
295 KTEXT_ST auth;
296 char *tkt_user = NULL;
297 char *kdata = packet_get_string((unsigned int *) &auth.length);
298 packet_integrity_check(plen, 4 + auth.length, type);
299
300 if (auth.length < MAX_KTXT_LEN)
301 memcpy(auth.dat, kdata, auth.length);
302 xfree(kdata);
303
304 authenticated = auth_krb4(pw->pw_name, &auth, &tkt_user);
305
306 if (authenticated) {
307 snprintf(user, sizeof user, " tktuser %s", tkt_user);
308 xfree(tkt_user);
309 }
310 }
311 break;
312#endif /* KRB4 */
313
314 case SSH_CMSG_AUTH_RHOSTS:
315 if (!options.rhosts_authentication) {
316 verbose("Rhosts authentication disabled.");
317 break;
318 }
319 /*
320 * Get client user name. Note that we just have to
321 * trust the client; this is one reason why rhosts
322 * authentication is insecure. (Another is
323 * IP-spoofing on a local network.)
324 */
325 client_user = packet_get_string(&ulen);
326 packet_integrity_check(plen, 4 + ulen, type);
327
328 /* Try to authenticate using /etc/hosts.equiv and
329 .rhosts. */
330 authenticated = auth_rhosts(pw, client_user);
331
332 snprintf(user, sizeof user, " ruser %s", client_user);
333 break;
334
335 case SSH_CMSG_AUTH_RHOSTS_RSA:
336 if (!options.rhosts_rsa_authentication) {
337 verbose("Rhosts with RSA authentication disabled.");
338 break;
339 }
340 /*
341 * Get client user name. Note that we just have to
342 * trust the client; root on the client machine can
343 * claim to be any user.
344 */
345 client_user = packet_get_string(&ulen);
346
347 /* Get the client host key. */
348 client_host_key = RSA_new();
349 if (client_host_key == NULL)
350 fatal("RSA_new failed");
351 client_host_key->e = BN_new();
352 client_host_key->n = BN_new();
353 if (client_host_key->e == NULL || client_host_key->n == NULL)
354 fatal("BN_new failed");
355 bits = packet_get_int();
356 packet_get_bignum(client_host_key->e, &elen);
357 packet_get_bignum(client_host_key->n, &nlen);
358
359 if (bits != BN_num_bits(client_host_key->n))
360 error("Warning: keysize mismatch for client_host_key: "
361 "actual %d, announced %d", BN_num_bits(client_host_key->n), bits);
362 packet_integrity_check(plen, (4 + ulen) + 4 + elen + nlen, type);
363
364 authenticated = auth_rhosts_rsa(pw, client_user, client_host_key);
365 RSA_free(client_host_key);
366
367 snprintf(user, sizeof user, " ruser %s", client_user);
368 break;
369
370 case SSH_CMSG_AUTH_RSA:
371 if (!options.rsa_authentication) {
372 verbose("RSA authentication disabled.");
373 break;
374 }
375 /* RSA authentication requested. */
376 n = BN_new();
377 packet_get_bignum(n, &nlen);
378 packet_integrity_check(plen, nlen, type);
379 authenticated = auth_rsa(pw, n);
380 BN_clear_free(n);
381 break;
382
383 case SSH_CMSG_AUTH_PASSWORD:
384 if (!options.password_authentication) {
385 verbose("Password authentication disabled.");
386 break;
387 }
388 /*
389 * Read user password. It is in plain text, but was
390 * transmitted over the encrypted channel so it is
391 * not visible to an outside observer.
392 */
393 password = packet_get_string(&dlen);
394 packet_integrity_check(plen, 4 + dlen, type);
395
396#ifdef USE_PAM
397 /* Do PAM auth with password */
398 authenticated = auth_pam_password(pw, password);
399#else /* USE_PAM */
400 /* Try authentication with the password. */
401 authenticated = auth_password(pw, password);
402#endif /* USE_PAM */
403 memset(password, 0, strlen(password));
404 xfree(password);
405 break;
406
407#ifdef SKEY
408 case SSH_CMSG_AUTH_TIS:
409 debug("rcvd SSH_CMSG_AUTH_TIS");
410 if (options.skey_authentication == 1) {
411 char *skeyinfo = skey_keyinfo(pw->pw_name);
412 if (skeyinfo == NULL) {
413 debug("generating fake skeyinfo for %.100s.", pw->pw_name);
414 skeyinfo = skey_fake_keyinfo(pw->pw_name);
415 }
416 if (skeyinfo != NULL) {
417 /* we send our s/key- in tis-challenge messages */
418 debug("sending challenge '%s'", skeyinfo);
419 packet_start(SSH_SMSG_AUTH_TIS_CHALLENGE);
420 packet_put_string(skeyinfo, strlen(skeyinfo));
421 packet_send();
422 packet_write_wait();
423 continue;
424 }
425 }
426 break;
427 case SSH_CMSG_AUTH_TIS_RESPONSE:
428 debug("rcvd SSH_CMSG_AUTH_TIS_RESPONSE");
429 if (options.skey_authentication == 1) {
430 char *response = packet_get_string(&dlen);
431 debug("skey response == '%s'", response);
432 packet_integrity_check(plen, 4 + dlen, type);
433 authenticated = (skey_haskey(pw->pw_name) == 0 &&
434 skey_passcheck(pw->pw_name, response) != -1);
435 xfree(response);
436 }
437 break;
438#else
439 case SSH_CMSG_AUTH_TIS:
440 /* TIS Authentication is unsupported */
441 log("TIS authentication unsupported.");
442 break;
443#endif
444
445 default:
446 /*
447 * Any unknown messages will be ignored (and failure
448 * returned) during authentication.
449 */
450 log("Unknown message during authentication: type %d", type);
451 break;
452 }
453
454 /*
455 * Check if the user is logging in as root and root logins
456 * are disallowed.
457 * Note that root login is allowed for forced commands.
458 */
459 if (authenticated && pw->pw_uid == 0 && !options.permit_root_login) {
460 if (forced_command) {
461 log("Root login accepted for forced command.");
462 } else {
463 authenticated = 0;
464 log("ROOT LOGIN REFUSED FROM %.200s",
465 get_canonical_hostname());
466 }
467 }
468
469 /* Raise logging level */
470 if (authenticated ||
471 attempt == AUTH_FAIL_LOG ||
472 type == SSH_CMSG_AUTH_PASSWORD)
473 authlog = log;
474
475 authlog("%s %s for %.200s from %.200s port %d%s",
476 authenticated ? "Accepted" : "Failed",
477 get_authname(type),
478 pw->pw_uid == 0 ? "ROOT" : pw->pw_name,
479 get_remote_ipaddr(),
480 get_remote_port(),
481 user);
482
483#ifdef USE_PAM
484 if (authenticated) {
485 if (!do_pam_account(pw->pw_name, client_user)) {
486 if (client_user != NULL) {
487 xfree(client_user);
488 client_user = NULL;
489 }
490 do_fake_authloop1(pw->pw_name);
491 }
492 return;
493 }
494#else /* USE_PAM */
495 if (authenticated) {
496 return;
497 }
498#endif /* USE_PAM */
499
500 if (client_user != NULL) {
501 xfree(client_user);
502 client_user = NULL;
503 }
504
505 if (attempt > AUTH_FAIL_MAX)
506 packet_disconnect(AUTH_FAIL_MSG, pw->pw_name);
507
508 /* Send a message indicating that the authentication attempt failed. */
509 packet_start(SSH_SMSG_FAILURE);
510 packet_send();
511 packet_write_wait();
512 }
513}
514
515/*
516 * Performs authentication of an incoming connection. Session key has already
517 * been exchanged and encryption is enabled.
518 */
519void
520do_authentication()
521{
522 struct passwd *pw, pwcopy;
523 int plen;
524 unsigned int ulen;
525 char *user;
526#ifdef WITH_AIXAUTHENTICATE
527 char *loginmsg;
528#endif /* WITH_AIXAUTHENTICATE */
529
530 /* Get the name of the user that we wish to log in as. */
531 packet_read_expect(&plen, SSH_CMSG_USER);
532
533 /* Get the user name. */
534 user = packet_get_string(&ulen);
535 packet_integrity_check(plen, (4 + ulen), SSH_CMSG_USER);
536
537 setproctitle("%s", user);
538
539#ifdef AFS
540 /* If machine has AFS, set process authentication group. */
541 if (k_hasafs()) {
542 k_setpag();
543 k_unlog();
544 }
545#endif /* AFS */
546
547 /* Verify that the user is a valid user. */
548 pw = getpwnam(user);
549 if (!pw || !allowed_user(pw))
550 do_fake_authloop1(user);
551 xfree(user);
552
553 /* Take a copy of the returned structure. */
554 memset(&pwcopy, 0, sizeof(pwcopy));
555 pwcopy.pw_name = xstrdup(pw->pw_name);
556 pwcopy.pw_passwd = xstrdup(pw->pw_passwd);
557 pwcopy.pw_uid = pw->pw_uid;
558 pwcopy.pw_gid = pw->pw_gid;
559 pwcopy.pw_dir = xstrdup(pw->pw_dir);
560 pwcopy.pw_shell = xstrdup(pw->pw_shell);
561 pw = &pwcopy;
562
563#ifdef USE_PAM
564 start_pam(pw);
565#endif
566
567 /*
568 * If we are not running as root, the user must have the same uid as
569 * the server.
570 */
571 if (getuid() != 0 && pw->pw_uid != getuid())
572 packet_disconnect("Cannot change user when server not running as root.");
573
574 debug("Attempting authentication for %.100s.", pw->pw_name);
575
576 /* If the user has no password, accept authentication immediately. */
577 if (options.password_authentication &&
578#ifdef KRB4
579 (!options.kerberos_authentication || options.kerberos_or_local_passwd) &&
580#endif /* KRB4 */
581#ifdef USE_PAM
582 auth_pam_password(pw, "")) {
583#else /* USE_PAM */
584 auth_password(pw, "")) {
585#endif /* USE_PAM */
586 /* Authentication with empty password succeeded. */
587 log("Login for user %s from %.100s, accepted without authentication.",
588 pw->pw_name, get_remote_ipaddr());
589 } else {
590 /* Loop until the user has been authenticated or the
591 connection is closed, do_authloop() returns only if
592 authentication is successfull */
593 do_authloop(pw);
594 }
595
596 /* The user has been authenticated and accepted. */
597#ifdef WITH_AIXAUTHENTICATE
598 loginsuccess(user,get_canonical_hostname(),"ssh",&loginmsg);
599#endif /* WITH_AIXAUTHENTICATE */
600 packet_start(SSH_SMSG_SUCCESS);
601 packet_send();
602 packet_write_wait();
603
604 /* Perform session preparation. */
605 do_authenticated(pw);
606}
diff --git a/auth.h b/auth.h
new file mode 100644
index 000000000..805177723
--- /dev/null
+++ b/auth.h
@@ -0,0 +1,6 @@
1#ifndef AUTH_H
2#define AUTH_H
3
4void do_authentication(void);
5
6#endif
diff --git a/bufaux.c b/bufaux.c
index 0c1381e36..4ab45a2f8 100644
--- a/bufaux.c
+++ b/bufaux.c
@@ -12,10 +12,12 @@
12 * Auxiliary functions for storing and retrieving various data types to/from 12 * Auxiliary functions for storing and retrieving various data types to/from
13 * Buffers. 13 * Buffers.
14 * 14 *
15 * SSH2 packet format added by Markus Friedl
16 *
15 */ 17 */
16 18
17#include "includes.h" 19#include "includes.h"
18RCSID("$Id: bufaux.c,v 1.8 2000/03/17 12:40:15 damien Exp $"); 20RCSID("$Id: bufaux.c,v 1.9 2000/04/01 01:09:23 damien Exp $");
19 21
20#include "ssh.h" 22#include "ssh.h"
21 23
@@ -83,6 +85,50 @@ buffer_get_bignum(Buffer *buffer, BIGNUM *value)
83} 85}
84 86
85/* 87/*
88 * Stores an BIGNUM in the buffer in SSH2 format.
89 */
90void
91buffer_put_bignum2(Buffer *buffer, BIGNUM *value)
92{
93 int bytes = BN_num_bytes(value) + 1;
94 unsigned char *buf = xmalloc(bytes);
95 int oi;
96 int hasnohigh = 0;
97 buf[0] = '\0';
98 /* Get the value of in binary */
99 oi = BN_bn2bin(value, buf+1);
100 if (oi != bytes-1)
101 fatal("buffer_put_bignum: BN_bn2bin() failed: oi %d != bin_size %d",
102 oi, bytes);
103 hasnohigh = (buf[1] & 0x80) ? 0 : 1;
104 if (value->neg) {
105 /**XXX should be two's-complement */
106 int i, carry;
107 unsigned char *uc = buf;
108 log("negativ!");
109 for(i = bytes-1, carry = 1; i>=0; i--) {
110 uc[i] ^= 0xff;
111 if(carry)
112 carry = !++uc[i];
113 }
114 }
115 buffer_put_string(buffer, buf+hasnohigh, bytes-hasnohigh);
116 memset(buf, 0, bytes);
117 xfree(buf);
118}
119
120int
121buffer_get_bignum2(Buffer *buffer, BIGNUM *value)
122{
123 /**XXX should be two's-complement */
124 int len;
125 unsigned char *bin = (unsigned char *)buffer_get_string(buffer, (unsigned int *)&len);
126 BN_bin2bn(bin, len, value);
127 xfree(bin);
128 return len;
129}
130
131/*
86 * Returns an integer from the buffer (4 bytes, msb first). 132 * Returns an integer from the buffer (4 bytes, msb first).
87 */ 133 */
88unsigned int 134unsigned int
@@ -142,6 +188,11 @@ buffer_put_string(Buffer *buffer, const void *buf, unsigned int len)
142 buffer_put_int(buffer, len); 188 buffer_put_int(buffer, len);
143 buffer_append(buffer, buf, len); 189 buffer_append(buffer, buf, len);
144} 190}
191void
192buffer_put_cstring(Buffer *buffer, const char *s)
193{
194 buffer_put_string(buffer, s, strlen(s));
195}
145 196
146/* 197/*
147 * Returns a character from the buffer (0 - 255). 198 * Returns a character from the buffer (0 - 255).
diff --git a/bufaux.h b/bufaux.h
index 8884c17f4..b22e98bd4 100644
--- a/bufaux.h
+++ b/bufaux.h
@@ -11,7 +11,7 @@
11 * 11 *
12 */ 12 */
13 13
14/* RCSID("$Id: bufaux.h,v 1.3 1999/11/25 00:54:58 damien Exp $"); */ 14/* RCSID("$Id: bufaux.h,v 1.4 2000/04/01 01:09:23 damien Exp $"); */
15 15
16#ifndef BUFAUX_H 16#ifndef BUFAUX_H
17#define BUFAUX_H 17#define BUFAUX_H
@@ -23,9 +23,11 @@
23 * by (bits+7)/8 bytes of binary data, msb first. 23 * by (bits+7)/8 bytes of binary data, msb first.
24 */ 24 */
25void buffer_put_bignum(Buffer * buffer, BIGNUM * value); 25void buffer_put_bignum(Buffer * buffer, BIGNUM * value);
26void buffer_put_bignum2(Buffer * buffer, BIGNUM * value);
26 27
27/* Retrieves an BIGNUM from the buffer. */ 28/* Retrieves an BIGNUM from the buffer. */
28int buffer_get_bignum(Buffer * buffer, BIGNUM * value); 29int buffer_get_bignum(Buffer * buffer, BIGNUM * value);
30int buffer_get_bignum2(Buffer *buffer, BIGNUM * value);
29 31
30/* Returns an integer from the buffer (4 bytes, msb first). */ 32/* Returns an integer from the buffer (4 bytes, msb first). */
31unsigned int buffer_get_int(Buffer * buffer); 33unsigned int buffer_get_int(Buffer * buffer);
@@ -51,5 +53,6 @@ char *buffer_get_string(Buffer * buffer, unsigned int *length_ptr);
51 53
52/* Stores and arbitrary binary string in the buffer. */ 54/* Stores and arbitrary binary string in the buffer. */
53void buffer_put_string(Buffer * buffer, const void *buf, unsigned int len); 55void buffer_put_string(Buffer * buffer, const void *buf, unsigned int len);
56void buffer_put_cstring(Buffer *buffer, const char *s);
54 57
55#endif /* BUFAUX_H */ 58#endif /* BUFAUX_H */
diff --git a/channels.c b/channels.c
index e60ecc614..b87ff9f4f 100644
--- a/channels.c
+++ b/channels.c
@@ -16,7 +16,7 @@
16 */ 16 */
17 17
18#include "includes.h" 18#include "includes.h"
19RCSID("$Id: channels.c,v 1.19 2000/03/17 12:40:15 damien Exp $"); 19RCSID("$Id: channels.c,v 1.20 2000/04/01 01:09:23 damien Exp $");
20 20
21#include "ssh.h" 21#include "ssh.h"
22#include "packet.h" 22#include "packet.h"
@@ -37,6 +37,10 @@ RCSID("$Id: channels.c,v 1.19 2000/03/17 12:40:15 damien Exp $");
37/* Max len of agent socket */ 37/* Max len of agent socket */
38#define MAX_SOCKET_NAME 100 38#define MAX_SOCKET_NAME 100
39 39
40/* default buffer for tcp-fwd-channel */
41#define CHAN_WINDOW_DEFAULT (8*1024)
42#define CHAN_PACKET_DEFAULT (CHAN_WINDOW_DEFAULT/2)
43
40/* 44/*
41 * Pointer to an array containing all allocated channels. The array is 45 * Pointer to an array containing all allocated channels. The array is
42 * dynamically extended as needed. 46 * dynamically extended as needed.
@@ -81,8 +85,9 @@ unsigned int x11_fake_data_len;
81 * network (which might be behind a firewall). 85 * network (which might be behind a firewall).
82 */ 86 */
83typedef struct { 87typedef struct {
84 char *host; /* Host name. */ 88 char *host_to_connect; /* Connect to 'host'. */
85 u_short port; /* Port number. */ 89 u_short port_to_connect; /* Connect to 'port'. */
90 u_short listen_port; /* Remote side should listen port number. */
86} ForwardPermission; 91} ForwardPermission;
87 92
88/* List of all permitted host/port pairs to connect. */ 93/* List of all permitted host/port pairs to connect. */
@@ -119,20 +124,43 @@ channel_permit_all_opens()
119 all_opens_permitted = 1; 124 all_opens_permitted = 1;
120} 125}
121 126
127/* lookup channel by id */
128
129Channel *
130channel_lookup(int id)
131{
132 Channel *c;
133 if (id < 0 && id > channels_alloc) {
134 log("channel_lookup: %d: bad id", id);
135 return NULL;
136 }
137 c = &channels[id];
138 if (c->type == SSH_CHANNEL_FREE) {
139 log("channel_lookup: %d: bad id: channel free", id);
140 return NULL;
141 }
142 return c;
143}
144
122/* 145/*
123 * Allocate a new channel object and set its type and socket. This will cause 146 * Allocate a new channel object and set its type and socket. This will cause
124 * remote_name to be freed. 147 * remote_name to be freed.
125 */ 148 */
126 149
127int 150int
128channel_allocate(int type, int sock, char *remote_name) 151channel_new(char *ctype, int type, int rfd, int wfd, int efd,
152 int window, int maxpack, int extended_usage, char *remote_name)
129{ 153{
130 int i, found; 154 int i, found;
131 Channel *c; 155 Channel *c;
132 156
133 /* Update the maximum file descriptor value. */ 157 /* Update the maximum file descriptor value. */
134 if (sock > channel_max_fd_value) 158 if (rfd > channel_max_fd_value)
135 channel_max_fd_value = sock; 159 channel_max_fd_value = rfd;
160 if (wfd > channel_max_fd_value)
161 channel_max_fd_value = wfd;
162 if (efd > channel_max_fd_value)
163 channel_max_fd_value = efd;
136 /* XXX set close-on-exec -markus */ 164 /* XXX set close-on-exec -markus */
137 165
138 /* Do initial allocation if this is the first call. */ 166 /* Do initial allocation if this is the first call. */
@@ -167,388 +195,514 @@ channel_allocate(int type, int sock, char *remote_name)
167 c = &channels[found]; 195 c = &channels[found];
168 buffer_init(&c->input); 196 buffer_init(&c->input);
169 buffer_init(&c->output); 197 buffer_init(&c->output);
198 buffer_init(&c->extended);
170 chan_init_iostates(c); 199 chan_init_iostates(c);
171 c->self = found; 200 c->self = found;
172 c->type = type; 201 c->type = type;
173 c->sock = sock; 202 c->ctype = ctype;
203 c->local_window = window;
204 c->local_window_max = window;
205 c->local_consumed = 0;
206 c->local_maxpacket = maxpack;
207 c->remote_window = 0;
208 c->remote_maxpacket = 0;
209 c->rfd = rfd;
210 c->wfd = wfd;
211 c->sock = (rfd == wfd) ? rfd : -1;
212 c->efd = efd;
213 c->extended_usage = extended_usage;
174 c->remote_id = -1; 214 c->remote_id = -1;
175 c->remote_name = remote_name; 215 c->remote_name = remote_name;
216 c->remote_window = 0;
217 c->remote_maxpacket = 0;
218 c->cb_fn = NULL;
219 c->cb_arg = NULL;
220 c->cb_event = 0;
221 c->dettach_user = NULL;
176 debug("channel %d: new [%s]", found, remote_name); 222 debug("channel %d: new [%s]", found, remote_name);
177 return found; 223 return found;
178} 224}
225int
226channel_allocate(int type, int sock, char *remote_name)
227{
228 return channel_new("", type, sock, sock, -1, 0, 0, 0, remote_name);
229}
179 230
180/* Free the channel and close its socket. */ 231/* Free the channel and close its socket. */
181 232
182void 233void
183channel_free(int channel) 234channel_free(int id)
184{ 235{
185 if (channel < 0 || channel >= channels_alloc || 236 Channel *c = channel_lookup(id);
186 channels[channel].type == SSH_CHANNEL_FREE) 237 if (c == NULL)
187 packet_disconnect("channel free: bad local channel %d", channel); 238 packet_disconnect("channel free: bad local channel %d", id);
188 239 debug("channel_free: channel %d: status: %s", id, channel_open_message());
189 if (compat13) 240 if (c->sock != -1) {
190 shutdown(channels[channel].sock, SHUT_RDWR); 241 shutdown(c->sock, SHUT_RDWR);
191 close(channels[channel].sock); 242 close(c->sock);
192 buffer_free(&channels[channel].input); 243 }
193 buffer_free(&channels[channel].output); 244 buffer_free(&c->input);
194 channels[channel].type = SSH_CHANNEL_FREE; 245 buffer_free(&c->output);
195 if (channels[channel].remote_name) { 246 buffer_free(&c->extended);
196 xfree(channels[channel].remote_name); 247 c->type = SSH_CHANNEL_FREE;
197 channels[channel].remote_name = NULL; 248 if (c->remote_name) {
249 xfree(c->remote_name);
250 c->remote_name = NULL;
198 } 251 }
199} 252}
200 253
201/* 254/*
202 * This is called just before select() to add any bits relevant to channels 255 * 'channel_pre*' are called just before select() to add any bits relevant to
203 * in the select bitmasks. 256 * channels in the select bitmasks.
257 */
258/*
259 * 'channel_post*': perform any appropriate operations for channels which
260 * have events pending.
204 */ 261 */
262typedef void chan_fn(Channel *c, fd_set * readset, fd_set * writeset);
263chan_fn *channel_pre[SSH_CHANNEL_MAX_TYPE];
264chan_fn *channel_post[SSH_CHANNEL_MAX_TYPE];
205 265
206void 266void
207channel_prepare_select(fd_set * readset, fd_set * writeset) 267channel_pre_listener(Channel *c, fd_set * readset, fd_set * writeset)
208{ 268{
209 int i; 269 FD_SET(c->sock, readset);
210 Channel *ch; 270}
211 unsigned char *ucp;
212 unsigned int proto_len, data_len;
213 271
214 for (i = 0; i < channels_alloc; i++) { 272void
215 ch = &channels[i]; 273channel_pre_open_13(Channel *c, fd_set * readset, fd_set * writeset)
216redo: 274{
217 switch (ch->type) { 275 if (buffer_len(&c->input) < packet_get_maxsize())
218 case SSH_CHANNEL_X11_LISTENER: 276 FD_SET(c->sock, readset);
219 case SSH_CHANNEL_PORT_LISTENER: 277 if (buffer_len(&c->output) > 0)
220 case SSH_CHANNEL_AUTH_SOCKET: 278 FD_SET(c->sock, writeset);
221 FD_SET(ch->sock, readset); 279}
222 break;
223 280
224 case SSH_CHANNEL_OPEN: 281void
225 if (compat13) { 282channel_pre_open_15(Channel *c, fd_set * readset, fd_set * writeset)
226 if (buffer_len(&ch->input) < packet_get_maxsize()) 283{
227 FD_SET(ch->sock, readset); 284 /* test whether sockets are 'alive' for read/write */
228 if (buffer_len(&ch->output) > 0) 285 if (c->istate == CHAN_INPUT_OPEN)
229 FD_SET(ch->sock, writeset); 286 if (buffer_len(&c->input) < packet_get_maxsize())
230 break; 287 FD_SET(c->sock, readset);
231 } 288 if (c->ostate == CHAN_OUTPUT_OPEN ||
232 /* test whether sockets are 'alive' for read/write */ 289 c->ostate == CHAN_OUTPUT_WAIT_DRAIN) {
233 if (ch->istate == CHAN_INPUT_OPEN) 290 if (buffer_len(&c->output) > 0) {
234 if (buffer_len(&ch->input) < packet_get_maxsize()) 291 FD_SET(c->sock, writeset);
235 FD_SET(ch->sock, readset); 292 } else if (c->ostate == CHAN_OUTPUT_WAIT_DRAIN) {
236 if (ch->ostate == CHAN_OUTPUT_OPEN || 293 chan_obuf_empty(c);
237 ch->ostate == CHAN_OUTPUT_WAIT_DRAIN) { 294 }
238 if (buffer_len(&ch->output) > 0) { 295 }
239 FD_SET(ch->sock, writeset); 296}
240 } else if (ch->ostate == CHAN_OUTPUT_WAIT_DRAIN) {
241 chan_obuf_empty(ch);
242 }
243 }
244 break;
245 297
246 case SSH_CHANNEL_INPUT_DRAINING: 298void
247 if (!compat13) 299channel_pre_input_draining(Channel *c, fd_set * readset, fd_set * writeset)
248 fatal("cannot happen: IN_DRAIN"); 300{
249 if (buffer_len(&ch->input) == 0) { 301 if (buffer_len(&c->input) == 0) {
250 packet_start(SSH_MSG_CHANNEL_CLOSE); 302 packet_start(SSH_MSG_CHANNEL_CLOSE);
251 packet_put_int(ch->remote_id); 303 packet_put_int(c->remote_id);
252 packet_send(); 304 packet_send();
253 ch->type = SSH_CHANNEL_CLOSED; 305 c->type = SSH_CHANNEL_CLOSED;
254 debug("Closing channel %d after input drain.", ch->self); 306 debug("Closing channel %d after input drain.", c->self);
255 break; 307 }
256 } 308}
257 break;
258 309
259 case SSH_CHANNEL_OUTPUT_DRAINING: 310void
260 if (!compat13) 311channel_pre_output_draining(Channel *c, fd_set * readset, fd_set * writeset)
261 fatal("cannot happen: OUT_DRAIN"); 312{
262 if (buffer_len(&ch->output) == 0) { 313 if (buffer_len(&c->output) == 0)
263 channel_free(i); 314 channel_free(c->self);
264 break; 315 else
265 } 316 FD_SET(c->sock, writeset);
266 FD_SET(ch->sock, writeset); 317}
267 break;
268 318
269 case SSH_CHANNEL_X11_OPEN: 319/*
270 /* 320 * This is a special state for X11 authentication spoofing. An opened X11
271 * This is a special state for X11 authentication 321 * connection (when authentication spoofing is being done) remains in this
272 * spoofing. An opened X11 connection (when 322 * state until the first packet has been completely read. The authentication
273 * authentication spoofing is being done) remains in 323 * data in that packet is then substituted by the real data if it matches the
274 * this state until the first packet has been 324 * fake data, and the channel is put into normal mode.
275 * completely read. The authentication data in that 325 */
276 * packet is then substituted by the real data if it 326int
277 * matches the fake data, and the channel is put into 327x11_open_helper(Channel *c)
278 * normal mode. 328{
279 */ 329 unsigned char *ucp;
280 /* Check if the fixed size part of the packet is in buffer. */ 330 unsigned int proto_len, data_len;
281 if (buffer_len(&ch->output) < 12)
282 break;
283 331
284 /* Parse the lengths of variable-length fields. */ 332 /* Check if the fixed size part of the packet is in buffer. */
285 ucp = (unsigned char *) buffer_ptr(&ch->output); 333 if (buffer_len(&c->output) < 12)
286 if (ucp[0] == 0x42) { /* Byte order MSB first. */ 334 return 0;
287 proto_len = 256 * ucp[6] + ucp[7]; 335
288 data_len = 256 * ucp[8] + ucp[9]; 336 /* Parse the lengths of variable-length fields. */
289 } else if (ucp[0] == 0x6c) { /* Byte order LSB first. */ 337 ucp = (unsigned char *) buffer_ptr(&c->output);
290 proto_len = ucp[6] + 256 * ucp[7]; 338 if (ucp[0] == 0x42) { /* Byte order MSB first. */
291 data_len = ucp[8] + 256 * ucp[9]; 339 proto_len = 256 * ucp[6] + ucp[7];
292 } else { 340 data_len = 256 * ucp[8] + ucp[9];
293 debug("Initial X11 packet contains bad byte order byte: 0x%x", 341 } else if (ucp[0] == 0x6c) { /* Byte order LSB first. */
294 ucp[0]); 342 proto_len = ucp[6] + 256 * ucp[7];
295 ch->type = SSH_CHANNEL_OPEN; 343 data_len = ucp[8] + 256 * ucp[9];
296 goto reject; 344 } else {
297 } 345 debug("Initial X11 packet contains bad byte order byte: 0x%x",
346 ucp[0]);
347 return -1;
348 }
298 349
299 /* Check if the whole packet is in buffer. */ 350 /* Check if the whole packet is in buffer. */
300 if (buffer_len(&ch->output) < 351 if (buffer_len(&c->output) <
301 12 + ((proto_len + 3) & ~3) + ((data_len + 3) & ~3)) 352 12 + ((proto_len + 3) & ~3) + ((data_len + 3) & ~3))
302 break; 353 return 0;
303 354
304 /* Check if authentication protocol matches. */ 355 /* Check if authentication protocol matches. */
305 if (proto_len != strlen(x11_saved_proto) || 356 if (proto_len != strlen(x11_saved_proto) ||
306 memcmp(ucp + 12, x11_saved_proto, proto_len) != 0) { 357 memcmp(ucp + 12, x11_saved_proto, proto_len) != 0) {
307 debug("X11 connection uses different authentication protocol."); 358 debug("X11 connection uses different authentication protocol.");
308 ch->type = SSH_CHANNEL_OPEN; 359 return -1;
309 goto reject; 360 }
310 } 361 /* Check if authentication data matches our fake data. */
311 /* Check if authentication data matches our fake data. */ 362 if (data_len != x11_fake_data_len ||
312 if (data_len != x11_fake_data_len || 363 memcmp(ucp + 12 + ((proto_len + 3) & ~3),
313 memcmp(ucp + 12 + ((proto_len + 3) & ~3), 364 x11_fake_data, x11_fake_data_len) != 0) {
314 x11_fake_data, x11_fake_data_len) != 0) { 365 debug("X11 auth data does not match fake data.");
315 debug("X11 auth data does not match fake data."); 366 return -1;
316 ch->type = SSH_CHANNEL_OPEN; 367 }
317 goto reject; 368 /* Check fake data length */
318 } 369 if (x11_fake_data_len != x11_saved_data_len) {
319 /* Check fake data length */ 370 error("X11 fake_data_len %d != saved_data_len %d",
320 if (x11_fake_data_len != x11_saved_data_len) { 371 x11_fake_data_len, x11_saved_data_len);
321 error("X11 fake_data_len %d != saved_data_len %d", 372 return -1;
322 x11_fake_data_len, x11_saved_data_len); 373 }
323 ch->type = SSH_CHANNEL_OPEN; 374 /*
324 goto reject; 375 * Received authentication protocol and data match
325 } 376 * our fake data. Substitute the fake data with real
326 /* 377 * data.
327 * Received authentication protocol and data match 378 */
328 * our fake data. Substitute the fake data with real 379 memcpy(ucp + 12 + ((proto_len + 3) & ~3),
329 * data. 380 x11_saved_data, x11_saved_data_len);
330 */ 381 return 1;
331 memcpy(ucp + 12 + ((proto_len + 3) & ~3), 382}
332 x11_saved_data, x11_saved_data_len);
333 383
334 /* Start normal processing for the channel. */ 384void
335 ch->type = SSH_CHANNEL_OPEN; 385channel_pre_x11_open_13(Channel *c, fd_set * readset, fd_set * writeset)
336 goto redo; 386{
387 int ret = x11_open_helper(c);
388 if (ret == 1) {
389 /* Start normal processing for the channel. */
390 c->type = SSH_CHANNEL_OPEN;
391 } else if (ret == -1) {
392 /*
393 * We have received an X11 connection that has bad
394 * authentication information.
395 */
396 log("X11 connection rejected because of wrong authentication.\r\n");
397 buffer_clear(&c->input);
398 buffer_clear(&c->output);
399 close(c->sock);
400 c->sock = -1;
401 c->type = SSH_CHANNEL_CLOSED;
402 packet_start(SSH_MSG_CHANNEL_CLOSE);
403 packet_put_int(c->remote_id);
404 packet_send();
405 }
406}
337 407
338 reject: 408void
339 /* 409channel_pre_x11_open_15(Channel *c, fd_set * readset, fd_set * writeset)
340 * We have received an X11 connection that has bad 410{
341 * authentication information. 411 int ret = x11_open_helper(c);
342 */ 412 if (ret == 1) {
343 log("X11 connection rejected because of wrong authentication.\r\n"); 413 c->type = SSH_CHANNEL_OPEN;
344 buffer_clear(&ch->input); 414 } else if (ret == -1) {
345 buffer_clear(&ch->output); 415 debug("X11 rejected %d i%d/o%d", c->self, c->istate, c->ostate);
346 if (compat13) { 416 chan_read_failed(c);
347 close(ch->sock); 417 chan_write_failed(c);
348 ch->sock = -1; 418 debug("X11 closed %d i%d/o%d", c->self, c->istate, c->ostate);
349 ch->type = SSH_CHANNEL_CLOSED; 419 }
350 packet_start(SSH_MSG_CHANNEL_CLOSE); 420}
351 packet_put_int(ch->remote_id);
352 packet_send();
353 } else {
354 debug("X11 rejected %d i%d/o%d", ch->self, ch->istate, ch->ostate);
355 chan_read_failed(ch);
356 chan_write_failed(ch);
357 debug("X11 rejected %d i%d/o%d", ch->self, ch->istate, ch->ostate);
358 }
359 break;
360 421
361 case SSH_CHANNEL_FREE: 422/* This is our fake X11 server socket. */
362 default: 423void
363 continue; 424channel_post_x11_listener(Channel *c, fd_set * readset, fd_set * writeset)
425{
426 struct sockaddr addr;
427 int newsock, newch;
428 socklen_t addrlen;
429 char buf[16384], *remote_hostname;
430
431 if (FD_ISSET(c->sock, readset)) {
432 debug("X11 connection requested.");
433 addrlen = sizeof(addr);
434 newsock = accept(c->sock, &addr, &addrlen);
435 if (newsock < 0) {
436 error("accept: %.100s", strerror(errno));
437 return;
364 } 438 }
439 remote_hostname = get_remote_hostname(newsock);
440 snprintf(buf, sizeof buf, "X11 connection from %.200s port %d",
441 remote_hostname, get_peer_port(newsock));
442 xfree(remote_hostname);
443 newch = channel_allocate(SSH_CHANNEL_OPENING, newsock,
444 xstrdup(buf));
445 packet_start(SSH_SMSG_X11_OPEN);
446 packet_put_int(newch);
447 if (have_hostname_in_open)
448 packet_put_string(buf, strlen(buf));
449 packet_send();
365 } 450 }
366} 451}
367 452
368/* 453/*
369 * After select, perform any appropriate operations for channels which have 454 * This socket is listening for connections to a forwarded TCP/IP port.
370 * events pending.
371 */ 455 */
456void
457channel_post_port_listener(Channel *c, fd_set * readset, fd_set * writeset)
458{
459 struct sockaddr addr;
460 int newsock, newch;
461 socklen_t addrlen;
462 char buf[1024], *remote_hostname;
463 int remote_port;
464
465 if (FD_ISSET(c->sock, readset)) {
466 debug("Connection to port %d forwarding "
467 "to %.100s port %d requested.",
468 c->listening_port, c->path, c->host_port);
469 addrlen = sizeof(addr);
470 newsock = accept(c->sock, &addr, &addrlen);
471 if (newsock < 0) {
472 error("accept: %.100s", strerror(errno));
473 return;
474 }
475 remote_hostname = get_remote_hostname(newsock);
476 remote_port = get_peer_port(newsock);
477 snprintf(buf, sizeof buf,
478 "listen port %d for %.100s port %d, "
479 "connect from %.200s port %d",
480 c->listening_port, c->path, c->host_port,
481 remote_hostname, remote_port);
482 newch = channel_new("direct-tcpip",
483 SSH_CHANNEL_OPENING, newsock, newsock, -1,
484 c->local_window_max, c->local_maxpacket,
485 0, xstrdup(buf));
486
487 packet_start(SSH_MSG_PORT_OPEN);
488 packet_put_int(newch);
489 packet_put_string(c->path, strlen(c->path));
490 packet_put_int(c->host_port);
491 if (have_hostname_in_open) {
492 packet_put_string(buf, strlen(buf));
493 }
494 packet_send();
495 xfree(remote_hostname);
496 }
497}
372 498
373void 499/*
374channel_after_select(fd_set * readset, fd_set * writeset) 500 * This is the authentication agent socket listening for connections from
501 * clients.
502 */
503void
504channel_post_auth_listener(Channel *c, fd_set * readset, fd_set * writeset)
375{ 505{
376 struct sockaddr addr; 506 struct sockaddr addr;
377 int newsock, i, newch, len; 507 int newsock, newch;
378 socklen_t addrlen; 508 socklen_t addrlen;
379 Channel *ch;
380 char buf[16384], *remote_hostname;
381 509
382 /* Loop over all channels... */ 510 if (FD_ISSET(c->sock, readset)) {
383 for (i = 0; i < channels_alloc; i++) { 511 addrlen = sizeof(addr);
384 ch = &channels[i]; 512 newsock = accept(c->sock, &addr, &addrlen);
385 switch (ch->type) { 513 if (newsock < 0) {
386 case SSH_CHANNEL_X11_LISTENER: 514 error("accept from auth socket: %.100s", strerror(errno));
387 /* This is our fake X11 server socket. */ 515 return;
388 if (FD_ISSET(ch->sock, readset)) { 516 }
389 debug("X11 connection requested."); 517 newch = channel_allocate(SSH_CHANNEL_OPENING, newsock,
390 addrlen = sizeof(addr); 518 xstrdup("accepted auth socket"));
391 newsock = accept(ch->sock, &addr, &addrlen); 519 packet_start(SSH_SMSG_AGENT_OPEN);
392 if (newsock < 0) { 520 packet_put_int(newch);
393 error("accept: %.100s", strerror(errno)); 521 packet_send();
394 break; 522 }
395 } 523}
396 remote_hostname = get_remote_hostname(newsock);
397 snprintf(buf, sizeof buf, "X11 connection from %.200s port %d",
398 remote_hostname, get_peer_port(newsock));
399 xfree(remote_hostname);
400 newch = channel_allocate(SSH_CHANNEL_OPENING, newsock,
401 xstrdup(buf));
402 packet_start(SSH_SMSG_X11_OPEN);
403 packet_put_int(newch);
404 if (have_hostname_in_open)
405 packet_put_string(buf, strlen(buf));
406 packet_send();
407 }
408 break;
409 524
410 case SSH_CHANNEL_PORT_LISTENER: 525int
411 /* 526channel_handle_rfd(Channel *c, fd_set * readset, fd_set * writeset)
412 * This socket is listening for connections to a 527{
413 * forwarded TCP/IP port. 528 char buf[16*1024];
414 */ 529 int len;
415 if (FD_ISSET(ch->sock, readset)) { 530
416 debug("Connection to port %d forwarding to %.100s port %d requested.", 531 if (c->rfd != -1 &&
417 ch->listening_port, ch->path, ch->host_port); 532 FD_ISSET(c->rfd, readset)) {
418 addrlen = sizeof(addr); 533 len = read(c->rfd, buf, sizeof(buf));
419 newsock = accept(ch->sock, &addr, &addrlen); 534 if (len <= 0) {
420 if (newsock < 0) { 535 debug("channel %d: read<0 rfd %d len %d",
421 error("accept: %.100s", strerror(errno)); 536 c->self, c->rfd, len);
422 break; 537 if (compat13) {
423 } 538 buffer_consume(&c->output, buffer_len(&c->output));
424 remote_hostname = get_remote_hostname(newsock); 539 c->type = SSH_CHANNEL_INPUT_DRAINING;
425 snprintf(buf, sizeof buf, "listen port %d for %.100s port %d, connect from %.200s port %d", 540 debug("Channel %d status set to input draining.", c->self);
426 ch->listening_port, ch->path, ch->host_port, 541 } else {
427 remote_hostname, get_peer_port(newsock)); 542 chan_read_failed(c);
428 xfree(remote_hostname);
429 newch = channel_allocate(SSH_CHANNEL_OPENING, newsock,
430 xstrdup(buf));
431 packet_start(SSH_MSG_PORT_OPEN);
432 packet_put_int(newch);
433 packet_put_string(ch->path, strlen(ch->path));
434 packet_put_int(ch->host_port);
435 if (have_hostname_in_open)
436 packet_put_string(buf, strlen(buf));
437 packet_send();
438 } 543 }
439 break; 544 return -1;
440 545 }
441 case SSH_CHANNEL_AUTH_SOCKET: 546 buffer_append(&c->input, buf, len);
442 /* 547 }
443 * This is the authentication agent socket listening 548 return 1;
444 * for connections from clients. 549}
445 */ 550int
446 if (FD_ISSET(ch->sock, readset)) { 551channel_handle_wfd(Channel *c, fd_set * readset, fd_set * writeset)
447 addrlen = sizeof(addr); 552{
448 newsock = accept(ch->sock, &addr, &addrlen); 553 int len;
449 if (newsock < 0) { 554
450 error("accept from auth socket: %.100s", strerror(errno)); 555 /* Send buffered output data to the socket. */
451 break; 556 if (c->wfd != -1 &&
452 } 557 FD_ISSET(c->wfd, writeset) &&
453 newch = channel_allocate(SSH_CHANNEL_OPENING, newsock, 558 buffer_len(&c->output) > 0) {
454 xstrdup("accepted auth socket")); 559 len = write(c->wfd, buffer_ptr(&c->output),
455 packet_start(SSH_SMSG_AGENT_OPEN); 560 buffer_len(&c->output));
456 packet_put_int(newch); 561 if (len <= 0) {
457 packet_send(); 562 if (compat13) {
563 buffer_consume(&c->output, buffer_len(&c->output));
564 debug("Channel %d status set to input draining.", c->self);
565 c->type = SSH_CHANNEL_INPUT_DRAINING;
566 } else {
567 chan_write_failed(c);
458 } 568 }
459 break; 569 return -1;
570 }
571 buffer_consume(&c->output, len);
572 }
573 return 1;
574}
460 575
461 case SSH_CHANNEL_OPEN: 576void
462 /* 577channel_post_open_1(Channel *c, fd_set * readset, fd_set * writeset)
463 * This is an open two-way communication channel. It 578{
464 * is not of interest to us at this point what kind 579 channel_handle_rfd(c, readset, writeset);
465 * of data is being transmitted. 580 channel_handle_wfd(c, readset, writeset);
466 */ 581}
467 582
468 /* 583void
469 * Read available incoming data and append it to 584channel_post_output_drain_13(Channel *c, fd_set * readset, fd_set * writeset)
470 * buffer; shutdown socket, if read or write failes 585{
471 */ 586 int len;
472 if (FD_ISSET(ch->sock, readset)) { 587 /* Send buffered output data to the socket. */
473 len = read(ch->sock, buf, sizeof(buf)); 588 if (FD_ISSET(c->sock, writeset) && buffer_len(&c->output) > 0) {
474 if (len <= 0) { 589 len = write(c->sock, buffer_ptr(&c->output),
475 if (compat13) { 590 buffer_len(&c->output));
476 buffer_consume(&ch->output, buffer_len(&ch->output)); 591 if (len <= 0)
477 ch->type = SSH_CHANNEL_INPUT_DRAINING; 592 buffer_consume(&c->output, buffer_len(&c->output));
478 debug("Channel %d status set to input draining.", i); 593 else
479 } else { 594 buffer_consume(&c->output, len);
480 chan_read_failed(ch); 595 }
481 } 596}
482 break;
483 }
484 buffer_append(&ch->input, buf, len);
485 }
486 /* Send buffered output data to the socket. */
487 if (FD_ISSET(ch->sock, writeset) && buffer_len(&ch->output) > 0) {
488 len = write(ch->sock, buffer_ptr(&ch->output),
489 buffer_len(&ch->output));
490 if (len <= 0) {
491 if (compat13) {
492 buffer_consume(&ch->output, buffer_len(&ch->output));
493 debug("Channel %d status set to input draining.", i);
494 ch->type = SSH_CHANNEL_INPUT_DRAINING;
495 } else {
496 chan_write_failed(ch);
497 }
498 break;
499 }
500 buffer_consume(&ch->output, len);
501 }
502 break;
503 597
504 case SSH_CHANNEL_OUTPUT_DRAINING: 598void
505 if (!compat13) 599channel_handler_init_13(void)
506 fatal("cannot happen: OUT_DRAIN"); 600{
507 /* Send buffered output data to the socket. */ 601 channel_pre[SSH_CHANNEL_OPEN] = &channel_pre_open_13;
508 if (FD_ISSET(ch->sock, writeset) && buffer_len(&ch->output) > 0) { 602 channel_pre[SSH_CHANNEL_X11_OPEN] = &channel_pre_x11_open_13;
509 len = write(ch->sock, buffer_ptr(&ch->output), 603 channel_pre[SSH_CHANNEL_X11_LISTENER] = &channel_pre_listener;
510 buffer_len(&ch->output)); 604 channel_pre[SSH_CHANNEL_PORT_LISTENER] = &channel_pre_listener;
511 if (len <= 0) 605 channel_pre[SSH_CHANNEL_AUTH_SOCKET] = &channel_pre_listener;
512 buffer_consume(&ch->output, buffer_len(&ch->output)); 606 channel_pre[SSH_CHANNEL_INPUT_DRAINING] = &channel_pre_input_draining;
513 else 607 channel_pre[SSH_CHANNEL_OUTPUT_DRAINING] = &channel_pre_output_draining;
514 buffer_consume(&ch->output, len); 608
515 } 609 channel_post[SSH_CHANNEL_OPEN] = &channel_post_open_1;
516 break; 610 channel_post[SSH_CHANNEL_X11_LISTENER] = &channel_post_x11_listener;
611 channel_post[SSH_CHANNEL_PORT_LISTENER] = &channel_post_port_listener;
612 channel_post[SSH_CHANNEL_AUTH_SOCKET] = &channel_post_auth_listener;
613 channel_post[SSH_CHANNEL_OUTPUT_DRAINING] = &channel_post_output_drain_13;
614}
517 615
518 case SSH_CHANNEL_X11_OPEN: 616void
519 case SSH_CHANNEL_FREE: 617channel_handler_init_15(void)
520 default: 618{
619 channel_pre[SSH_CHANNEL_OPEN] = &channel_pre_open_15;
620 channel_pre[SSH_CHANNEL_X11_OPEN] = &channel_pre_x11_open_15;
621 channel_pre[SSH_CHANNEL_X11_LISTENER] = &channel_pre_listener;
622 channel_pre[SSH_CHANNEL_PORT_LISTENER] = &channel_pre_listener;
623 channel_pre[SSH_CHANNEL_AUTH_SOCKET] = &channel_pre_listener;
624
625 channel_post[SSH_CHANNEL_X11_LISTENER] = &channel_post_x11_listener;
626 channel_post[SSH_CHANNEL_PORT_LISTENER] = &channel_post_port_listener;
627 channel_post[SSH_CHANNEL_AUTH_SOCKET] = &channel_post_auth_listener;
628 channel_post[SSH_CHANNEL_OPEN] = &channel_post_open_1;
629}
630
631void
632channel_handler_init(void)
633{
634 int i;
635 for(i = 0; i < SSH_CHANNEL_MAX_TYPE; i++) {
636 channel_pre[i] = NULL;
637 channel_post[i] = NULL;
638 }
639 if (compat13)
640 channel_handler_init_13();
641 else
642 channel_handler_init_15();
643}
644
645void
646channel_handler(chan_fn *ftab[], fd_set * readset, fd_set * writeset)
647{
648 static int did_init = 0;
649 int i;
650 Channel *c;
651
652 if (!did_init) {
653 channel_handler_init();
654 did_init = 1;
655 }
656 for (i = 0; i < channels_alloc; i++) {
657 c = &channels[i];
658 if (c->type == SSH_CHANNEL_FREE)
521 continue; 659 continue;
522 } 660 if (ftab[c->type] == NULL)
661 continue;
662 (*ftab[c->type])(c, readset, writeset);
663 if (!compat13)
664 chan_delete_if_full_closed(c);
523 } 665 }
524} 666}
525 667
668void
669channel_prepare_select(fd_set * readset, fd_set * writeset)
670{
671 channel_handler(channel_pre, readset, writeset);
672}
673
674void
675channel_after_select(fd_set * readset, fd_set * writeset)
676{
677 channel_handler(channel_post, readset, writeset);
678}
679
526/* If there is data to send to the connection, send some of it now. */ 680/* If there is data to send to the connection, send some of it now. */
527 681
528void 682void
529channel_output_poll() 683channel_output_poll()
530{ 684{
531 int len, i; 685 int len, i;
532 Channel *ch; 686 Channel *c;
533 687
534 for (i = 0; i < channels_alloc; i++) { 688 for (i = 0; i < channels_alloc; i++) {
535 ch = &channels[i]; 689 c = &channels[i];
536 690
537 /* We are only interested in channels that can have buffered incoming data. */ 691 /* We are only interested in channels that can have buffered incoming data. */
538 if (compat13) { 692 if (compat13) {
539 if (ch->type != SSH_CHANNEL_OPEN && 693 if (c->type != SSH_CHANNEL_OPEN &&
540 ch->type != SSH_CHANNEL_INPUT_DRAINING) 694 c->type != SSH_CHANNEL_INPUT_DRAINING)
541 continue; 695 continue;
542 } else { 696 } else {
543 if (ch->type != SSH_CHANNEL_OPEN) 697 if (c->type != SSH_CHANNEL_OPEN)
544 continue; 698 continue;
545 if (ch->istate != CHAN_INPUT_OPEN && 699 if (c->istate != CHAN_INPUT_OPEN &&
546 ch->istate != CHAN_INPUT_WAIT_DRAIN) 700 c->istate != CHAN_INPUT_WAIT_DRAIN)
547 continue; 701 continue;
548 } 702 }
549 703
550 /* Get the amount of buffered data for this channel. */ 704 /* Get the amount of buffered data for this channel. */
551 len = buffer_len(&ch->input); 705 len = buffer_len(&c->input);
552 if (len > 0) { 706 if (len > 0) {
553 /* Send some data for the other side over the secure connection. */ 707 /* Send some data for the other side over the secure connection. */
554 if (packet_is_interactive()) { 708 if (packet_is_interactive()) {
@@ -556,22 +710,26 @@ channel_output_poll()
556 len = 512; 710 len = 512;
557 } else { 711 } else {
558 /* Keep the packets at reasonable size. */ 712 /* Keep the packets at reasonable size. */
559 if (len > packet_get_maxsize()/2) 713 if (len > packet_get_maxsize())
560 len = packet_get_maxsize()/2; 714 len = packet_get_maxsize()/2;
561 } 715 }
562 packet_start(SSH_MSG_CHANNEL_DATA); 716 if (len > 0) {
563 packet_put_int(ch->remote_id); 717 packet_start(SSH_MSG_CHANNEL_DATA);
564 packet_put_string(buffer_ptr(&ch->input), len); 718 packet_put_int(c->remote_id);
565 packet_send(); 719 packet_put_string(buffer_ptr(&c->input), len);
566 buffer_consume(&ch->input, len); 720 packet_send();
567 } else if (ch->istate == CHAN_INPUT_WAIT_DRAIN) { 721 buffer_consume(&c->input, len);
722 c->remote_window -= len;
723debug("channel %d: send data len %d", c->self, len);
724 }
725 } else if (c->istate == CHAN_INPUT_WAIT_DRAIN) {
568 if (compat13) 726 if (compat13)
569 fatal("cannot happen: istate == INPUT_WAIT_DRAIN for proto 1.3"); 727 fatal("cannot happen: istate == INPUT_WAIT_DRAIN for proto 1.3");
570 /* 728 /*
571 * input-buffer is empty and read-socket shutdown: 729 * input-buffer is empty and read-socket shutdown:
572 * tell peer, that we will not send more data: send IEOF 730 * tell peer, that we will not send more data: send IEOF
573 */ 731 */
574 chan_ibuf_empty(ch); 732 chan_ibuf_empty(c);
575 } 733 }
576 } 734 }
577} 735}
@@ -583,35 +741,33 @@ channel_output_poll()
583 */ 741 */
584 742
585void 743void
586channel_input_data(int payload_len) 744channel_input_data(int type, int plen)
587{ 745{
588 int id; 746 int id;
589 char *data; 747 char *data;
590 unsigned int data_len; 748 unsigned int data_len;
591 Channel *ch; 749 Channel *c;
592 750
593 /* Get the channel number and verify it. */ 751 /* Get the channel number and verify it. */
594 id = packet_get_int(); 752 id = packet_get_int();
595 if (id < 0 || id >= channels_alloc) 753 c = channel_lookup(id);
754 if (c == NULL)
596 packet_disconnect("Received data for nonexistent channel %d.", id); 755 packet_disconnect("Received data for nonexistent channel %d.", id);
597 ch = &channels[id];
598
599 if (ch->type == SSH_CHANNEL_FREE)
600 packet_disconnect("Received data for free channel %d.", ch->self);
601 756
602 /* Ignore any data for non-open channels (might happen on close) */ 757 /* Ignore any data for non-open channels (might happen on close) */
603 if (ch->type != SSH_CHANNEL_OPEN && 758 if (c->type != SSH_CHANNEL_OPEN &&
604 ch->type != SSH_CHANNEL_X11_OPEN) 759 c->type != SSH_CHANNEL_X11_OPEN)
605 return; 760 return;
606 761
607 /* same for protocol 1.5 if output end is no longer open */ 762 /* same for protocol 1.5 if output end is no longer open */
608 if (!compat13 && ch->ostate != CHAN_OUTPUT_OPEN) 763 if (!compat13 && c->ostate != CHAN_OUTPUT_OPEN)
609 return; 764 return;
610 765
611 /* Get the data. */ 766 /* Get the data. */
612 data = packet_get_string(&data_len); 767 data = packet_get_string(&data_len);
613 packet_integrity_check(payload_len, 4 + 4 + data_len, SSH_MSG_CHANNEL_DATA); 768
614 buffer_append(&ch->output, data, data_len); 769 packet_integrity_check(plen, 4 + 4 + data_len, SSH_MSG_CHANNEL_DATA);
770 buffer_append(&c->output, data, data_len);
615 xfree(data); 771 xfree(data);
616} 772}
617 773
@@ -624,45 +780,60 @@ int
624channel_not_very_much_buffered_data() 780channel_not_very_much_buffered_data()
625{ 781{
626 unsigned int i; 782 unsigned int i;
627 Channel *ch; 783 Channel *c;
628 784
629 for (i = 0; i < channels_alloc; i++) { 785 for (i = 0; i < channels_alloc; i++) {
630 ch = &channels[i]; 786 c = &channels[i];
631 if (ch->type == SSH_CHANNEL_OPEN) { 787 if (c->type == SSH_CHANNEL_OPEN) {
632 if (buffer_len(&ch->input) > packet_get_maxsize()) 788 if (buffer_len(&c->input) > packet_get_maxsize()) {
789 debug("channel %d: big input buffer %d",
790 c->self, buffer_len(&c->input));
633 return 0; 791 return 0;
634 if (buffer_len(&ch->output) > packet_get_maxsize()) 792 }
793 if (buffer_len(&c->output) > packet_get_maxsize()) {
794 debug("channel %d: big output buffer %d",
795 c->self, buffer_len(&c->output));
635 return 0; 796 return 0;
797 }
636 } 798 }
637 } 799 }
638 return 1; 800 return 1;
639} 801}
640 802
641/* This is called after receiving CHANNEL_CLOSE/IEOF. */ 803void
804channel_input_ieof(int type, int plen)
805{
806 int id;
807 Channel *c;
808
809 packet_integrity_check(plen, 4, type);
810
811 id = packet_get_int();
812 c = channel_lookup(id);
813 if (c == NULL)
814 packet_disconnect("Received ieof for nonexistent channel %d.", id);
815 chan_rcvd_ieof(c);
816}
642 817
643void 818void
644channel_input_close() 819channel_input_close(int type, int plen)
645{ 820{
646 int channel; 821 int id;
822 Channel *c;
647 823
648 /* Get the channel number and verify it. */ 824 packet_integrity_check(plen, 4, type);
649 channel = packet_get_int(); 825
650 if (channel < 0 || channel >= channels_alloc || 826 id = packet_get_int();
651 channels[channel].type == SSH_CHANNEL_FREE) 827 c = channel_lookup(id);
652 packet_disconnect("Received data for nonexistent channel %d.", channel); 828 if (c == NULL)
653 829 packet_disconnect("Received close for nonexistent channel %d.", id);
654 if (!compat13) {
655 /* proto version 1.5 overloads CLOSE with IEOF */
656 chan_rcvd_ieof(&channels[channel]);
657 return;
658 }
659 830
660 /* 831 /*
661 * Send a confirmation that we have closed the channel and no more 832 * Send a confirmation that we have closed the channel and no more
662 * data is coming for it. 833 * data is coming for it.
663 */ 834 */
664 packet_start(SSH_MSG_CHANNEL_CLOSE_CONFIRMATION); 835 packet_start(SSH_MSG_CHANNEL_CLOSE_CONFIRMATION);
665 packet_put_int(channels[channel].remote_id); 836 packet_put_int(c->remote_id);
666 packet_send(); 837 packet_send();
667 838
668 /* 839 /*
@@ -672,81 +843,80 @@ channel_input_close()
672 * no-one to receive the confirmation. The channel gets freed when 843 * no-one to receive the confirmation. The channel gets freed when
673 * the confirmation arrives. 844 * the confirmation arrives.
674 */ 845 */
675 if (channels[channel].type != SSH_CHANNEL_CLOSED) { 846 if (c->type != SSH_CHANNEL_CLOSED) {
676 /* 847 /*
677 * Not a closed channel - mark it as draining, which will 848 * Not a closed channel - mark it as draining, which will
678 * cause it to be freed later. 849 * cause it to be freed later.
679 */ 850 */
680 buffer_consume(&channels[channel].input, 851 buffer_consume(&c->input, buffer_len(&c->input));
681 buffer_len(&channels[channel].input)); 852 c->type = SSH_CHANNEL_OUTPUT_DRAINING;
682 channels[channel].type = SSH_CHANNEL_OUTPUT_DRAINING;
683 } 853 }
684} 854}
685 855
686/* This is called after receiving CHANNEL_CLOSE_CONFIRMATION/OCLOSE. */ 856/* proto version 1.5 overloads CLOSE_CONFIRMATION with OCLOSE */
687
688void 857void
689channel_input_close_confirmation() 858channel_input_oclose(int type, int plen)
690{ 859{
691 int channel; 860 int id = packet_get_int();
692 861 Channel *c = channel_lookup(id);
693 /* Get the channel number and verify it. */ 862 packet_integrity_check(plen, 4, type);
694 channel = packet_get_int(); 863 if (c == NULL)
695 if (channel < 0 || channel >= channels_alloc) 864 packet_disconnect("Received oclose for nonexistent channel %d.", id);
696 packet_disconnect("Received close confirmation for out-of-range channel %d.", 865 chan_rcvd_oclose(c);
697 channel);
698
699 if (!compat13) {
700 /* proto version 1.5 overloads CLOSE_CONFIRMATION with OCLOSE */
701 chan_rcvd_oclose(&channels[channel]);
702 return;
703 }
704 if (channels[channel].type != SSH_CHANNEL_CLOSED)
705 packet_disconnect("Received close confirmation for non-closed channel %d (type %d).",
706 channel, channels[channel].type);
707
708 /* Free the channel. */
709 channel_free(channel);
710} 866}
711 867
712/* This is called after receiving CHANNEL_OPEN_CONFIRMATION. */ 868void
869channel_input_close_confirmation(int type, int plen)
870{
871 int id = packet_get_int();
872 Channel *c = channel_lookup(id);
873
874 if (c == NULL)
875 packet_disconnect("Received close confirmation for "
876 "out-of-range channel %d.", id);
877 if (c->type != SSH_CHANNEL_CLOSED)
878 packet_disconnect("Received close confirmation for "
879 "non-closed channel %d (type %d).", id, c->type);
880 channel_free(c->self);
881}
713 882
714void 883void
715channel_input_open_confirmation() 884channel_input_open_confirmation(int type, int plen)
716{ 885{
717 int channel, remote_channel; 886 int id, remote_id;
887 Channel *c;
718 888
719 /* Get the channel number and verify it. */ 889 packet_integrity_check(plen, 4 + 4, type);
720 channel = packet_get_int();
721 if (channel < 0 || channel >= channels_alloc ||
722 channels[channel].type != SSH_CHANNEL_OPENING)
723 packet_disconnect("Received open confirmation for non-opening channel %d.",
724 channel);
725 890
726 /* Get remote side's id for this channel. */ 891 id = packet_get_int();
727 remote_channel = packet_get_int(); 892 c = channel_lookup(id);
728 893
894 if (c==NULL || c->type != SSH_CHANNEL_OPENING)
895 packet_disconnect("Received open confirmation for "
896 "non-opening channel %d.", id);
897 remote_id = packet_get_int();
729 /* Record the remote channel number and mark that the channel is now open. */ 898 /* Record the remote channel number and mark that the channel is now open. */
730 channels[channel].remote_id = remote_channel; 899 c->remote_id = remote_id;
731 channels[channel].type = SSH_CHANNEL_OPEN; 900 c->type = SSH_CHANNEL_OPEN;
732} 901}
733 902
734/* This is called after receiving CHANNEL_OPEN_FAILURE from the other side. */
735
736void 903void
737channel_input_open_failure() 904channel_input_open_failure(int type, int plen)
738{ 905{
739 int channel; 906 int id;
907 Channel *c;
740 908
741 /* Get the channel number and verify it. */ 909 packet_integrity_check(plen, 4, type);
742 channel = packet_get_int(); 910
743 if (channel < 0 || channel >= channels_alloc || 911 id = packet_get_int();
744 channels[channel].type != SSH_CHANNEL_OPENING) 912 c = channel_lookup(id);
745 packet_disconnect("Received open failure for non-opening channel %d.", 913
746 channel); 914 if (c==NULL || c->type != SSH_CHANNEL_OPENING)
915 packet_disconnect("Received open failure for "
916 "non-opening channel %d.", id);
747 917
748 /* Free the channel. This will also close the socket. */ 918 /* Free the channel. This will also close the socket. */
749 channel_free(channel); 919 channel_free(id);
750} 920}
751 921
752/* 922/*
@@ -859,15 +1029,16 @@ channel_open_message()
859 case SSH_CHANNEL_X11_OPEN: 1029 case SSH_CHANNEL_X11_OPEN:
860 case SSH_CHANNEL_INPUT_DRAINING: 1030 case SSH_CHANNEL_INPUT_DRAINING:
861 case SSH_CHANNEL_OUTPUT_DRAINING: 1031 case SSH_CHANNEL_OUTPUT_DRAINING:
862 snprintf(buf, sizeof buf, " #%d %.300s (t%d r%d i%d/%d o%d/%d)\r\n", 1032 snprintf(buf, sizeof buf, " #%d %.300s (t%d r%d i%d/%d o%d/%d fd %d/%d)\r\n",
863 c->self, c->remote_name, 1033 c->self, c->remote_name,
864 c->type, c->remote_id, 1034 c->type, c->remote_id,
865 c->istate, buffer_len(&c->input), 1035 c->istate, buffer_len(&c->input),
866 c->ostate, buffer_len(&c->output)); 1036 c->ostate, buffer_len(&c->output),
1037 c->rfd, c->wfd);
867 buffer_append(&buffer, buf, strlen(buf)); 1038 buffer_append(&buffer, buf, strlen(buf));
868 continue; 1039 continue;
869 default: 1040 default:
870 fatal("channel_still_open: bad channel type %d", c->type); 1041 fatal("channel_open_message: bad channel type %d", c->type);
871 /* NOTREACHED */ 1042 /* NOTREACHED */
872 } 1043 }
873 } 1044 }
@@ -950,8 +1121,11 @@ channel_request_local_forwarding(u_short port, const char *host,
950 continue; 1121 continue;
951 } 1122 }
952 /* Allocate a channel number for the socket. */ 1123 /* Allocate a channel number for the socket. */
953 ch = channel_allocate(SSH_CHANNEL_PORT_LISTENER, sock, 1124 ch = channel_new(
954 xstrdup("port listener")); 1125 "port listener", SSH_CHANNEL_PORT_LISTENER,
1126 sock, sock, -1,
1127 CHAN_WINDOW_DEFAULT, CHAN_PACKET_DEFAULT,
1128 0, xstrdup("port listener"));
955 strlcpy(channels[ch].path, host, sizeof(channels[ch].path)); 1129 strlcpy(channels[ch].path, host, sizeof(channels[ch].path));
956 channels[ch].host_port = host_port; 1130 channels[ch].host_port = host_port;
957 channels[ch].listening_port = port; 1131 channels[ch].listening_port = port;
@@ -968,26 +1142,26 @@ channel_request_local_forwarding(u_short port, const char *host,
968 */ 1142 */
969 1143
970void 1144void
971channel_request_remote_forwarding(u_short port, const char *host, 1145channel_request_remote_forwarding(u_short listen_port, const char *host_to_connect,
972 u_short remote_port) 1146 u_short port_to_connect)
973{ 1147{
974 int payload_len; 1148 int payload_len;
975 /* Record locally that connection to this host/port is permitted. */ 1149 /* Record locally that connection to this host/port is permitted. */
976 if (num_permitted_opens >= SSH_MAX_FORWARDS_PER_DIRECTION) 1150 if (num_permitted_opens >= SSH_MAX_FORWARDS_PER_DIRECTION)
977 fatal("channel_request_remote_forwarding: too many forwards"); 1151 fatal("channel_request_remote_forwarding: too many forwards");
978 1152
979 permitted_opens[num_permitted_opens].host = xstrdup(host); 1153 permitted_opens[num_permitted_opens].host_to_connect = xstrdup(host_to_connect);
980 permitted_opens[num_permitted_opens].port = remote_port; 1154 permitted_opens[num_permitted_opens].port_to_connect = port_to_connect;
1155 permitted_opens[num_permitted_opens].listen_port = listen_port;
981 num_permitted_opens++; 1156 num_permitted_opens++;
982 1157
983 /* Send the forward request to the remote side. */ 1158 /* Send the forward request to the remote side. */
984 packet_start(SSH_CMSG_PORT_FORWARD_REQUEST); 1159 packet_start(SSH_CMSG_PORT_FORWARD_REQUEST);
985 packet_put_int(port); 1160 packet_put_int(port_to_connect);
986 packet_put_string(host, strlen(host)); 1161 packet_put_string(host_to_connect, strlen(host_to_connect));
987 packet_put_int(remote_port); 1162 packet_put_int(listen_port);
988 packet_send(); 1163 packet_send();
989 packet_write_wait(); 1164 packet_write_wait();
990
991 /* 1165 /*
992 * Wait for response from the remote side. It will send a disconnect 1166 * Wait for response from the remote side. It will send a disconnect
993 * message on failure, and we will never see it here. 1167 * message on failure, and we will never see it here.
@@ -1029,63 +1203,14 @@ channel_input_port_forward_request(int is_root)
1029 xfree(hostname); 1203 xfree(hostname);
1030} 1204}
1031 1205
1032/* 1206/* XXX move to aux.c */
1033 * This is called after receiving PORT_OPEN message. This attempts to 1207int
1034 * connect to the given host:port, and sends back CHANNEL_OPEN_CONFIRMATION 1208channel_connect_to(const char *host, u_short host_port)
1035 * or CHANNEL_OPEN_FAILURE.
1036 */
1037
1038void
1039channel_input_port_open(int payload_len)
1040{ 1209{
1041 int remote_channel, sock = 0, newch, i;
1042 u_short host_port;
1043 char *host, *originator_string;
1044 unsigned int host_len, originator_len;
1045 struct addrinfo hints, *ai, *aitop; 1210 struct addrinfo hints, *ai, *aitop;
1046 char ntop[NI_MAXHOST], strport[NI_MAXSERV]; 1211 char ntop[NI_MAXHOST], strport[NI_MAXSERV];
1047 int gaierr; 1212 int gaierr;
1048 1213 int sock = -1;
1049 /* Get remote channel number. */
1050 remote_channel = packet_get_int();
1051
1052 /* Get host name to connect to. */
1053 host = packet_get_string(&host_len);
1054
1055 /* Get port to connect to. */
1056 host_port = packet_get_int();
1057
1058 /* Get remote originator name. */
1059 if (have_hostname_in_open) {
1060 originator_string = packet_get_string(&originator_len);
1061 originator_len += 4; /* size of packet_int */
1062 } else {
1063 originator_string = xstrdup("unknown (remote did not supply name)");
1064 originator_len = 0; /* no originator supplied */
1065 }
1066
1067 packet_integrity_check(payload_len,
1068 4 + 4 + host_len + 4 + originator_len,
1069 SSH_MSG_PORT_OPEN);
1070
1071 /* Check if opening that port is permitted. */
1072 if (!all_opens_permitted) {
1073 /* Go trough all permitted ports. */
1074 for (i = 0; i < num_permitted_opens; i++)
1075 if (permitted_opens[i].port == host_port &&
1076 strcmp(permitted_opens[i].host, host) == 0)
1077 break;
1078
1079 /* Check if we found the requested port among those permitted. */
1080 if (i >= num_permitted_opens) {
1081 /* The port is not permitted. */
1082 log("Received request to connect to %.100s:%d, but the request was denied.",
1083 host, host_port);
1084 packet_start(SSH_MSG_CHANNEL_OPEN_FAILURE);
1085 packet_put_int(remote_channel);
1086 packet_send();
1087 }
1088 }
1089 1214
1090 memset(&hints, 0, sizeof(hints)); 1215 memset(&hints, 0, sizeof(hints));
1091 hints.ai_family = IPv4or6; 1216 hints.ai_family = IPv4or6;
@@ -1093,15 +1218,14 @@ channel_input_port_open(int payload_len)
1093 snprintf(strport, sizeof strport, "%d", host_port); 1218 snprintf(strport, sizeof strport, "%d", host_port);
1094 if ((gaierr = getaddrinfo(host, strport, &hints, &aitop)) != 0) { 1219 if ((gaierr = getaddrinfo(host, strport, &hints, &aitop)) != 0) {
1095 error("%.100s: unknown host (%s)", host, gai_strerror(gaierr)); 1220 error("%.100s: unknown host (%s)", host, gai_strerror(gaierr));
1096 goto fail; 1221 return -1;
1097 } 1222 }
1098
1099 for (ai = aitop; ai; ai = ai->ai_next) { 1223 for (ai = aitop; ai; ai = ai->ai_next) {
1100 if (ai->ai_family != AF_INET && ai->ai_family != AF_INET6) 1224 if (ai->ai_family != AF_INET && ai->ai_family != AF_INET6)
1101 continue; 1225 continue;
1102 if (getnameinfo(ai->ai_addr, ai->ai_addrlen, ntop, sizeof(ntop), 1226 if (getnameinfo(ai->ai_addr, ai->ai_addrlen, ntop, sizeof(ntop),
1103 strport, sizeof(strport), NI_NUMERICHOST|NI_NUMERICSERV) != 0) { 1227 strport, sizeof(strport), NI_NUMERICHOST|NI_NUMERICSERV) != 0) {
1104 error("channel_input_port_open: getnameinfo failed"); 1228 error("channel_connect_to: getnameinfo failed");
1105 continue; 1229 continue;
1106 } 1230 }
1107 /* Create the socket. */ 1231 /* Create the socket. */
@@ -1121,37 +1245,82 @@ channel_input_port_open(int payload_len)
1121 1245
1122 } 1246 }
1123 freeaddrinfo(aitop); 1247 freeaddrinfo(aitop);
1124
1125 if (!ai) { 1248 if (!ai) {
1126 error("connect %.100s port %d: failed.", host, host_port); 1249 error("connect %.100s port %d: failed.", host, host_port);
1127 goto fail; 1250 return -1;
1128 } 1251 }
1252 /* success */
1253 return sock;
1254}
1129 1255
1130 /* Successful connection. */ 1256/*
1257 * This is called after receiving PORT_OPEN message. This attempts to
1258 * connect to the given host:port, and sends back CHANNEL_OPEN_CONFIRMATION
1259 * or CHANNEL_OPEN_FAILURE.
1260 */
1131 1261
1132 /* Allocate a channel for this connection. */ 1262void
1133 newch = channel_allocate(SSH_CHANNEL_OPEN, sock, originator_string); 1263channel_input_port_open(int type, int plen)
1134 channels[newch].remote_id = remote_channel; 1264{
1265 u_short host_port;
1266 char *host, *originator_string;
1267 int remote_channel, sock = -1, newch, i, denied;
1268 unsigned int host_len, originator_len;
1135 1269
1136 /* Send a confirmation to the remote host. */ 1270 /* Get remote channel number. */
1137 packet_start(SSH_MSG_CHANNEL_OPEN_CONFIRMATION); 1271 remote_channel = packet_get_int();
1138 packet_put_int(remote_channel);
1139 packet_put_int(newch);
1140 packet_send();
1141 1272
1142 /* Free the argument string. */ 1273 /* Get host name to connect to. */
1143 xfree(host); 1274 host = packet_get_string(&host_len);
1144 1275
1145 return; 1276 /* Get port to connect to. */
1277 host_port = packet_get_int();
1146 1278
1147fail: 1279 /* Get remote originator name. */
1148 /* Free the argument string. */ 1280 if (have_hostname_in_open) {
1149 xfree(host); 1281 originator_string = packet_get_string(&originator_len);
1282 originator_len += 4; /* size of packet_int */
1283 } else {
1284 originator_string = xstrdup("unknown (remote did not supply name)");
1285 originator_len = 0; /* no originator supplied */
1286 }
1150 1287
1151 /* Send refusal to the remote host. */ 1288 packet_integrity_check(plen,
1152 packet_start(SSH_MSG_CHANNEL_OPEN_FAILURE); 1289 4 + 4 + host_len + 4 + originator_len, SSH_MSG_PORT_OPEN);
1153 packet_put_int(remote_channel); 1290
1154 packet_send(); 1291 /* Check if opening that port is permitted. */
1292 denied = 0;
1293 if (!all_opens_permitted) {
1294 /* Go trough all permitted ports. */
1295 for (i = 0; i < num_permitted_opens; i++)
1296 if (permitted_opens[i].port_to_connect == host_port &&
1297 strcmp(permitted_opens[i].host_to_connect, host) == 0)
1298 break;
1299
1300 /* Check if we found the requested port among those permitted. */
1301 if (i >= num_permitted_opens) {
1302 /* The port is not permitted. */
1303 log("Received request to connect to %.100s:%d, but the request was denied.",
1304 host, host_port);
1305 denied = 1;
1306 }
1307 }
1308 sock = denied ? -1 : channel_connect_to(host, host_port);
1309 if (sock > 0) {
1310 /* Allocate a channel for this connection. */
1311 newch = channel_allocate(SSH_CHANNEL_OPEN, sock, originator_string);
1312 channels[newch].remote_id = remote_channel;
1313
1314 packet_start(SSH_MSG_CHANNEL_OPEN_CONFIRMATION);
1315 packet_put_int(remote_channel);
1316 packet_put_int(newch);
1317 packet_send();
1318 } else {
1319 packet_start(SSH_MSG_CHANNEL_OPEN_FAILURE);
1320 packet_put_int(remote_channel);
1321 packet_send();
1322 }
1323 xfree(host);
1155} 1324}
1156 1325
1157/* 1326/*
@@ -1336,7 +1505,7 @@ connect_local_xsocket(unsigned int dnr)
1336 */ 1505 */
1337 1506
1338void 1507void
1339x11_input_open(int payload_len) 1508x11_input_open(int type, int plen)
1340{ 1509{
1341 int remote_channel, display_number, sock = 0, newch; 1510 int remote_channel, display_number, sock = 0, newch;
1342 const char *display; 1511 const char *display;
@@ -1359,7 +1528,7 @@ x11_input_open(int payload_len)
1359 } 1528 }
1360 1529
1361 debug("Received X11 open request."); 1530 debug("Received X11 open request.");
1362 packet_integrity_check(payload_len, 4 + remote_len, SSH_SMSG_X11_OPEN); 1531 packet_integrity_check(plen, 4 + remote_len, SSH_SMSG_X11_OPEN);
1363 1532
1364 /* Try to open a socket for the local X server. */ 1533 /* Try to open a socket for the local X server. */
1365 display = getenv("DISPLAY"); 1534 display = getenv("DISPLAY");
@@ -1425,19 +1594,18 @@ x11_input_open(int payload_len)
1425 sock = socket(ai->ai_family, SOCK_STREAM, 0); 1594 sock = socket(ai->ai_family, SOCK_STREAM, 0);
1426 if (sock < 0) { 1595 if (sock < 0) {
1427 debug("socket: %.100s", strerror(errno)); 1596 debug("socket: %.100s", strerror(errno));
1428 continue; 1597 continue;
1429 } 1598 }
1430 /* Connect it to the display. */ 1599 /* Connect it to the display. */
1431 if (connect(sock, ai->ai_addr, ai->ai_addrlen) < 0) { 1600 if (connect(sock, ai->ai_addr, ai->ai_addrlen) < 0) {
1432 debug("connect %.100s port %d: %.100s", buf, 6000 + display_number, 1601 debug("connect %.100s port %d: %.100s", buf,
1433 strerror(errno)); 1602 6000 + display_number, strerror(errno));
1434 close(sock); 1603 close(sock);
1435 continue; 1604 continue;
1605 }
1606 /* Success */
1607 break;
1436 } 1608 }
1437 /* Success */
1438 break;
1439
1440 } /* (ai = aitop, ai; ai = ai->ai_next) */
1441 freeaddrinfo(aitop); 1609 freeaddrinfo(aitop);
1442 if (!ai) { 1610 if (!ai) {
1443 error("connect %.100s port %d: %.100s", buf, 6000 + display_number, 1611 error("connect %.100s port %d: %.100s", buf, 6000 + display_number,
@@ -1625,11 +1793,13 @@ auth_input_request_forwarding(struct passwd * pw)
1625/* This is called to process an SSH_SMSG_AGENT_OPEN message. */ 1793/* This is called to process an SSH_SMSG_AGENT_OPEN message. */
1626 1794
1627void 1795void
1628auth_input_open_request() 1796auth_input_open_request(int type, int plen)
1629{ 1797{
1630 int remch, sock, newch; 1798 int remch, sock, newch;
1631 char *dummyname; 1799 char *dummyname;
1632 1800
1801 packet_integrity_check(plen, 4, type);
1802
1633 /* Read the remote channel number from the message. */ 1803 /* Read the remote channel number from the message. */
1634 remch = packet_get_int(); 1804 remch = packet_get_int();
1635 1805
diff --git a/channels.h b/channels.h
index f8bca5c9a..73ff5a595 100644
--- a/channels.h
+++ b/channels.h
@@ -1,4 +1,4 @@
1/* RCSID("$Id: channels.h,v 1.4 1999/11/25 00:54:58 damien Exp $"); */ 1/* RCSID("$Id: channels.h,v 1.5 2000/04/01 01:09:23 damien Exp $"); */
2 2
3#ifndef CHANNELS_H 3#ifndef CHANNELS_H
4#define CHANNELS_H 4#define CHANNELS_H
@@ -10,17 +10,18 @@
10#define SSH_CHANNEL_OPENING 3 /* waiting for confirmation */ 10#define SSH_CHANNEL_OPENING 3 /* waiting for confirmation */
11#define SSH_CHANNEL_OPEN 4 /* normal open two-way channel */ 11#define SSH_CHANNEL_OPEN 4 /* normal open two-way channel */
12#define SSH_CHANNEL_CLOSED 5 /* waiting for close confirmation */ 12#define SSH_CHANNEL_CLOSED 5 /* waiting for close confirmation */
13/* SSH_CHANNEL_AUTH_FD 6 authentication fd */ 13#define SSH_CHANNEL_AUTH_SOCKET 6 /* authentication socket */
14#define SSH_CHANNEL_AUTH_SOCKET 7 /* authentication socket */ 14#define SSH_CHANNEL_X11_OPEN 7 /* reading first X11 packet */
15/* SSH_CHANNEL_AUTH_SOCKET_FD 8 connection to auth socket */ 15#define SSH_CHANNEL_INPUT_DRAINING 8 /* sending remaining data to conn */
16#define SSH_CHANNEL_X11_OPEN 9 /* reading first X11 packet */ 16#define SSH_CHANNEL_OUTPUT_DRAINING 9 /* sending remaining data to app */
17#define SSH_CHANNEL_INPUT_DRAINING 10 /* sending remaining data to conn */ 17#define SSH_CHANNEL_LARVAL 10 /* larval session */
18#define SSH_CHANNEL_OUTPUT_DRAINING 11 /* sending remaining data to app */ 18#define SSH_CHANNEL_MAX_TYPE 11
19 19
20/* 20/*
21 * Data structure for channel data. This is iniailized in channel_allocate 21 * Data structure for channel data. This is iniailized in channel_allocate
22 * and cleared in channel_free. 22 * and cleared in channel_free.
23 */ 23 */
24typedef void channel_callback_fn(int id, void *arg);
24 25
25typedef struct Channel { 26typedef struct Channel {
26 int type; /* channel type/state */ 27 int type; /* channel type/state */
@@ -29,15 +30,192 @@ typedef struct Channel {
29 /* peer can be reached over encrypted connection, via packet-sent */ 30 /* peer can be reached over encrypted connection, via packet-sent */
30 int istate; /* input from channel (state of receive half) */ 31 int istate; /* input from channel (state of receive half) */
31 int ostate; /* output to channel (state of transmit half) */ 32 int ostate; /* output to channel (state of transmit half) */
32 int sock; /* data socket, linked to this channel */ 33 int rfd; /* read fd */
34 int wfd; /* write fd */
35 int efd; /* extended fd */
36 int sock; /* sock fd */
33 Buffer input; /* data read from socket, to be sent over 37 Buffer input; /* data read from socket, to be sent over
34 * encrypted connection */ 38 * encrypted connection */
35 Buffer output; /* data received over encrypted connection for 39 Buffer output; /* data received over encrypted connection for
36 * send on socket */ 40 * send on socket */
41 Buffer extended;
37 char path[200]; /* path for unix domain sockets, or host name 42 char path[200]; /* path for unix domain sockets, or host name
38 * for forwards */ 43 * for forwards */
39 int listening_port; /* port being listened for forwards */ 44 int listening_port; /* port being listened for forwards */
40 int host_port; /* remote port to connect for forwards */ 45 int host_port; /* remote port to connect for forwards */
41 char *remote_name; /* remote hostname */ 46 char *remote_name; /* remote hostname */
47
48 int remote_window;
49 int remote_maxpacket;
50 int local_window;
51 int local_window_max;
52 int local_consumed;
53 int local_maxpacket;
54 int extended_usage;
55
56 char *ctype; /* type */
57
58 // callback
59 channel_callback_fn *cb_fn;
60 void *cb_arg;
61 int cb_event;
62 channel_callback_fn *dettach_user;
42} Channel; 63} Channel;
64
65#define CHAN_EXTENDED_IGNORE 0
66#define CHAN_EXTENDED_READ 1
67#define CHAN_EXTENDED_WRITE 2
68
69void channel_open(int id);
70Channel *channel_lookup(int id);
71
72int
73channel_new(char *ctype, int type, int rfd, int wfd, int efd,
74 int window, int maxpack, int extended_usage, char *remote_name);
75
76void channel_input_close(int type, int plen);
77void channel_input_close_confirmation(int type, int plen);
78void channel_input_data(int type, int plen);
79void channel_input_ieof(int type, int plen);
80void channel_input_oclose(int type, int plen);
81void channel_input_open_confirmation(int type, int plen);
82void channel_input_open_failure(int type, int plen);
83void channel_input_port_open(int type, int plen);
84void channel_input_open(int type, int plen);
85
86/* Sets specific protocol options. */
87void channel_set_options(int hostname_in_open);
88
89/*
90 * Allocate a new channel object and set its type and socket. Remote_name
91 * must have been allocated with xmalloc; this will free it when the channel
92 * is freed.
93 */
94int channel_allocate(int type, int sock, char *remote_name);
95
96/* Free the channel and close its socket. */
97void channel_free(int channel);
98
99/* Add any bits relevant to channels in select bitmasks. */
100void channel_prepare_select(fd_set * readset, fd_set * writeset);
101
102/*
103 * After select, perform any appropriate operations for channels which have
104 * events pending.
105 */
106void channel_after_select(fd_set * readset, fd_set * writeset);
107
108/* If there is data to send to the connection, send some of it now. */
109void channel_output_poll(void);
110
111/* Returns true if no channel has too much buffered data. */
112int channel_not_very_much_buffered_data(void);
113
114/* This closes any sockets that are listening for connections; this removes
115 any unix domain sockets. */
116void channel_stop_listening(void);
117
118/*
119 * Closes the sockets of all channels. This is used to close extra file
120 * descriptors after a fork.
121 */
122void channel_close_all(void);
123
124/* Returns the maximum file descriptor number used by the channels. */
125int channel_max_fd(void);
126
127/* Returns true if there is still an open channel over the connection. */
128int channel_still_open(void);
129
130/*
131 * Returns a string containing a list of all open channels. The list is
132 * suitable for displaying to the user. It uses crlf instead of newlines.
133 * The caller should free the string with xfree.
134 */
135char *channel_open_message(void);
136
137/*
138 * Initiate forwarding of connections to local port "port" through the secure
139 * channel to host:port from remote side. This never returns if there was an
140 * error.
141 */
142void
143channel_request_local_forwarding(u_short port, const char *host,
144 u_short remote_port, int gateway_ports);
145
146/*
147 * Initiate forwarding of connections to port "port" on remote host through
148 * the secure channel to host:port from local side. This never returns if
149 * there was an error. This registers that open requests for that port are
150 * permitted.
151 */
152void
153channel_request_remote_forwarding(u_short port, const char *host,
154 u_short remote_port);
155
156/*
157 * Permits opening to any host/port in SSH_MSG_PORT_OPEN. This is usually
158 * called by the server, because the user could connect to any port anyway,
159 * and the server has no way to know but to trust the client anyway.
160 */
161void channel_permit_all_opens(void);
162
163/*
164 * This is called after receiving CHANNEL_FORWARDING_REQUEST. This initates
165 * listening for the port, and sends back a success reply (or disconnect
166 * message if there was an error). This never returns if there was an error.
167 */
168void channel_input_port_forward_request(int is_root);
169
170/*
171 * Creates a port for X11 connections, and starts listening for it. Returns
172 * the display name, or NULL if an error was encountered.
173 */
174char *x11_create_display(int screen);
175
176/*
177 * Creates an internet domain socket for listening for X11 connections.
178 * Returns a suitable value for the DISPLAY variable, or NULL if an error
179 * occurs.
180 */
181char *x11_create_display_inet(int screen, int x11_display_offset);
182
183/*
184 * This is called when SSH_SMSG_X11_OPEN is received. The packet contains
185 * the remote channel number. We should do whatever we want, and respond
186 * with either SSH_MSG_OPEN_CONFIRMATION or SSH_MSG_OPEN_FAILURE.
187 */
188void x11_input_open(int type, int plen);
189
190/*
191 * Requests forwarding of X11 connections. This should be called on the
192 * client only.
193 */
194void x11_request_forwarding(void);
195
196/*
197 * Requests forwarding for X11 connections, with authentication spoofing.
198 * This should be called in the client only.
199 */
200void x11_request_forwarding_with_spoofing(const char *proto, const char *data);
201
202/* Sends a message to the server to request authentication fd forwarding. */
203void auth_request_forwarding(void);
204
205/*
206 * Returns the name of the forwarded authentication socket. Returns NULL if
207 * there is no forwarded authentication socket. The returned value points to
208 * a static buffer.
209 */
210char *auth_get_socket_name(void);
211
212/*
213 * This if called to process SSH_CMSG_AGENT_REQUEST_FORWARDING on the server.
214 * This starts forwarding authentication requests.
215 */
216void auth_input_request_forwarding(struct passwd * pw);
217
218/* This is called to process an SSH_SMSG_AGENT_OPEN message. */
219void auth_input_open_request(int type, int plen);
220
43#endif 221#endif
diff --git a/cipher.c b/cipher.c
index bf1518ded..f7b7b4726 100644
--- a/cipher.c
+++ b/cipher.c
@@ -12,7 +12,7 @@
12 */ 12 */
13 13
14#include "includes.h" 14#include "includes.h"
15RCSID("$Id: cipher.c,v 1.14 2000/03/26 03:04:52 damien Exp $"); 15RCSID("$Id: cipher.c,v 1.15 2000/04/01 01:09:23 damien Exp $");
16 16
17#include "ssh.h" 17#include "ssh.h"
18#include "cipher.h" 18#include "cipher.h"
@@ -122,7 +122,12 @@ static char *cipher_names[] =
122 "3des", 122 "3des",
123 "tss", 123 "tss",
124 "rc4", 124 "rc4",
125 "blowfish" 125 "blowfish",
126 "reserved",
127 "blowfish-cbc",
128 "3des-cbc",
129 "arcfour",
130 "cast128-cbc"
126}; 131};
127 132
128/* 133/*
@@ -137,6 +142,10 @@ cipher_mask()
137 unsigned int mask = 0; 142 unsigned int mask = 0;
138 mask |= 1 << SSH_CIPHER_3DES; /* Mandatory */ 143 mask |= 1 << SSH_CIPHER_3DES; /* Mandatory */
139 mask |= 1 << SSH_CIPHER_BLOWFISH; 144 mask |= 1 << SSH_CIPHER_BLOWFISH;
145 mask |= 1 << SSH_CIPHER_BLOWFISH_CBC;
146 mask |= 1 << SSH_CIPHER_3DES_CBC;
147 mask |= 1 << SSH_CIPHER_ARCFOUR;
148 mask |= 1 << SSH_CIPHER_CAST128_CBC;
140 return mask; 149 return mask;
141} 150}
142 151
@@ -233,16 +242,84 @@ cipher_set_key(CipherContext *context, int cipher,
233 break; 242 break;
234 243
235 case SSH_CIPHER_BLOWFISH: 244 case SSH_CIPHER_BLOWFISH:
245 if (keylen < 16)
246 error("Key length %d is insufficient for blowfish.", keylen);
236 BF_set_key(&context->u.bf.key, keylen, padded); 247 BF_set_key(&context->u.bf.key, keylen, padded);
237 memset(context->u.bf.iv, 0, 8); 248 memset(context->u.bf.iv, 0, 8);
238 break; 249 break;
239 250
251 case SSH_CIPHER_3DES_CBC:
252 case SSH_CIPHER_BLOWFISH_CBC:
253 case SSH_CIPHER_ARCFOUR:
254 case SSH_CIPHER_CAST128_CBC:
255 fatal("cipher_set_key: illegal cipher: %s", cipher_name(cipher));
256 break;
257
240 default: 258 default:
241 fatal("cipher_set_key: unknown cipher: %s", cipher_name(cipher)); 259 fatal("cipher_set_key: unknown cipher: %s", cipher_name(cipher));
242 } 260 }
243 memset(padded, 0, sizeof(padded)); 261 memset(padded, 0, sizeof(padded));
244} 262}
245 263
264
265void
266cipher_set_key_iv(CipherContext * context, int cipher,
267 const unsigned char *key, int keylen,
268 const unsigned char *iv, int ivlen)
269{
270 /* Set cipher type. */
271 context->type = cipher;
272
273 /* Initialize the initialization vector. */
274 switch (cipher) {
275 case SSH_CIPHER_NONE:
276 break;
277
278 case SSH_CIPHER_3DES:
279 case SSH_CIPHER_BLOWFISH:
280 fatal("cipher_set_key_iv: illegal cipher: %s", cipher_name(cipher));
281 break;
282
283 case SSH_CIPHER_3DES_CBC:
284 if (keylen < 24)
285 error("Key length %d is insufficient for 3des-cbc.", keylen);
286 des_set_key((void *) key, context->u.des3.key1);
287 des_set_key((void *) (key+8), context->u.des3.key2);
288 des_set_key((void *) (key+16), context->u.des3.key3);
289 if (ivlen < 8)
290 error("IV length %d is insufficient for 3des-cbc.", ivlen);
291 memcpy(context->u.des3.iv3, (char *)iv, 8);
292 break;
293
294 case SSH_CIPHER_BLOWFISH_CBC:
295 if (keylen < 16)
296 error("Key length %d is insufficient for blowfish.", keylen);
297 if (ivlen < 8)
298 error("IV length %d is insufficient for blowfish.", ivlen);
299 BF_set_key(&context->u.bf.key, keylen, (unsigned char *)key);
300 memcpy(context->u.bf.iv, (char *)iv, 8);
301 break;
302
303 case SSH_CIPHER_ARCFOUR:
304 if (keylen < 16)
305 error("Key length %d is insufficient for arcfour.", keylen);
306 RC4_set_key(&context->u.rc4, keylen, (unsigned char *)key);
307 break;
308
309 case SSH_CIPHER_CAST128_CBC:
310 if (keylen < 16)
311 error("Key length %d is insufficient for cast128.", keylen);
312 if (ivlen < 8)
313 error("IV length %d is insufficient for cast128.", ivlen);
314 CAST_set_key(&context->u.cast.key, keylen, (unsigned char *) key);
315 memcpy(context->u.cast.iv, (char *)iv, 8);
316 break;
317
318 default:
319 fatal("cipher_set_key: unknown cipher: %s", cipher_name(cipher));
320 }
321}
322
246/* Encrypts data using the cipher. */ 323/* Encrypts data using the cipher. */
247 324
248void 325void
@@ -272,6 +349,27 @@ cipher_encrypt(CipherContext *context, unsigned char *dest,
272 swap_bytes(dest, dest, len); 349 swap_bytes(dest, dest, len);
273 break; 350 break;
274 351
352 case SSH_CIPHER_BLOWFISH_CBC:
353 BF_cbc_encrypt((void *)src, dest, len,
354 &context->u.bf.key, context->u.bf.iv,
355 BF_ENCRYPT);
356 break;
357
358 case SSH_CIPHER_3DES_CBC:
359 des_ede3_cbc_encrypt(src, dest, len,
360 context->u.des3.key1, context->u.des3.key2,
361 context->u.des3.key3, &context->u.des3.iv3, DES_ENCRYPT);
362 break;
363
364 case SSH_CIPHER_ARCFOUR:
365 RC4(&context->u.rc4, len, (unsigned char *)src, dest);
366 break;
367
368 case SSH_CIPHER_CAST128_CBC:
369 CAST_cbc_encrypt(src, dest, len,
370 &context->u.cast.key, context->u.cast.iv, CAST_ENCRYPT);
371 break;
372
275 default: 373 default:
276 fatal("cipher_encrypt: unknown cipher: %s", cipher_name(context->type)); 374 fatal("cipher_encrypt: unknown cipher: %s", cipher_name(context->type));
277 } 375 }
@@ -306,6 +404,27 @@ cipher_decrypt(CipherContext *context, unsigned char *dest,
306 swap_bytes(dest, dest, len); 404 swap_bytes(dest, dest, len);
307 break; 405 break;
308 406
407 case SSH_CIPHER_BLOWFISH_CBC:
408 BF_cbc_encrypt((void *) src, dest, len,
409 &context->u.bf.key, context->u.bf.iv,
410 BF_DECRYPT);
411 break;
412
413 case SSH_CIPHER_3DES_CBC:
414 des_ede3_cbc_encrypt(src, dest, len,
415 context->u.des3.key1, context->u.des3.key2,
416 context->u.des3.key3, &context->u.des3.iv3, DES_DECRYPT);
417 break;
418
419 case SSH_CIPHER_ARCFOUR:
420 RC4(&context->u.rc4, len, (unsigned char *)src, dest);
421 break;
422
423 case SSH_CIPHER_CAST128_CBC:
424 CAST_cbc_encrypt(src, dest, len,
425 &context->u.cast.key, context->u.cast.iv, CAST_DECRYPT);
426 break;
427
309 default: 428 default:
310 fatal("cipher_decrypt: unknown cipher: %s", cipher_name(context->type)); 429 fatal("cipher_decrypt: unknown cipher: %s", cipher_name(context->type));
311 } 430 }
diff --git a/cipher.h b/cipher.h
index c323a6c50..6cfeb6399 100644
--- a/cipher.h
+++ b/cipher.h
@@ -11,7 +11,7 @@
11 * 11 *
12 */ 12 */
13 13
14/* RCSID("$Id: cipher.h,v 1.6 2000/03/26 03:04:52 damien Exp $"); */ 14/* RCSID("$Id: cipher.h,v 1.7 2000/04/01 01:09:23 damien Exp $"); */
15 15
16#ifndef CIPHER_H 16#ifndef CIPHER_H
17#define CIPHER_H 17#define CIPHER_H
@@ -21,10 +21,14 @@
21#ifdef HAVE_OPENSSL 21#ifdef HAVE_OPENSSL
22#include <openssl/des.h> 22#include <openssl/des.h>
23#include <openssl/blowfish.h> 23#include <openssl/blowfish.h>
24#include <openssl/rc4.h>
25#include <openssl/cast.h>
24#endif 26#endif
25#ifdef HAVE_SSL 27#ifdef HAVE_SSL
26#include <ssl/des.h> 28#include <ssl/des.h>
27#include <ssl/blowfish.h> 29#include <ssl/blowfish.h>
30#include <ssl/rc4.h>
31#include <ssl/cast.h>
28#endif 32#endif
29 33
30/* Cipher types. New types can be added, but old types should not be removed 34/* Cipher types. New types can be added, but old types should not be removed
@@ -37,6 +41,13 @@
37#define SSH_CIPHER_BROKEN_TSS 4 /* TRI's Simple Stream encryption CBC */ 41#define SSH_CIPHER_BROKEN_TSS 4 /* TRI's Simple Stream encryption CBC */
38#define SSH_CIPHER_BROKEN_RC4 5 /* Alleged RC4 */ 42#define SSH_CIPHER_BROKEN_RC4 5 /* Alleged RC4 */
39#define SSH_CIPHER_BLOWFISH 6 43#define SSH_CIPHER_BLOWFISH 6
44#define SSH_CIPHER_RESERVED 7
45
46/* these ciphers are used in SSH2: */
47#define SSH_CIPHER_BLOWFISH_CBC 8
48#define SSH_CIPHER_3DES_CBC 9
49#define SSH_CIPHER_ARCFOUR 10 /* Alleged RC4 */
50#define SSH_CIPHER_CAST128_CBC 11
40 51
41typedef struct { 52typedef struct {
42 unsigned int type; 53 unsigned int type;
@@ -52,6 +63,11 @@ typedef struct {
52 struct bf_key_st key; 63 struct bf_key_st key;
53 unsigned char iv[8]; 64 unsigned char iv[8];
54 } bf; 65 } bf;
66 struct {
67 CAST_KEY key;
68 unsigned char iv[8];
69 } cast;
70 RC4_KEY rc4;
55 } u; 71 } u;
56} CipherContext; 72} CipherContext;
57/* 73/*
@@ -77,6 +93,10 @@ int cipher_number(const char *name);
77void 93void
78cipher_set_key(CipherContext * context, int cipher, 94cipher_set_key(CipherContext * context, int cipher,
79 const unsigned char *key, int keylen, int for_encryption); 95 const unsigned char *key, int keylen, int for_encryption);
96void
97cipher_set_key_iv(CipherContext * context, int cipher,
98 const unsigned char *key, int keylen,
99 const unsigned char *iv, int ivlen);
80 100
81/* 101/*
82 * Sets key for the cipher by computing the MD5 checksum of the passphrase, 102 * Sets key for the cipher by computing the MD5 checksum of the passphrase,
diff --git a/clientloop.c b/clientloop.c
index bfa3019b6..1bc6d7e67 100644
--- a/clientloop.c
+++ b/clientloop.c
@@ -15,7 +15,7 @@
15 */ 15 */
16 16
17#include "includes.h" 17#include "includes.h"
18RCSID("$Id: clientloop.c,v 1.7 1999/12/07 04:38:32 damien Exp $"); 18RCSID("$Id: clientloop.c,v 1.8 2000/04/01 01:09:23 damien Exp $");
19 19
20#include "xmalloc.h" 20#include "xmalloc.h"
21#include "ssh.h" 21#include "ssh.h"
@@ -24,6 +24,11 @@ RCSID("$Id: clientloop.c,v 1.7 1999/12/07 04:38:32 damien Exp $");
24#include "authfd.h" 24#include "authfd.h"
25#include "readconf.h" 25#include "readconf.h"
26 26
27#include "compat.h"
28#include "channels.h"
29#include "dispatch.h"
30
31
27/* Flag indicating that stdin should be redirected from /dev/null. */ 32/* Flag indicating that stdin should be redirected from /dev/null. */
28extern int stdin_null_flag; 33extern int stdin_null_flag;
29 34
@@ -228,108 +233,6 @@ client_check_initial_eof_on_stdin()
228 } 233 }
229} 234}
230 235
231/*
232 * Get packets from the connection input buffer, and process them as long as
233 * there are packets available.
234 */
235
236void
237client_process_buffered_input_packets()
238{
239 int type;
240 char *data;
241 unsigned int data_len;
242 int payload_len;
243
244 /* Process any buffered packets from the server. */
245 while (!quit_pending &&
246 (type = packet_read_poll(&payload_len)) != SSH_MSG_NONE) {
247 switch (type) {
248
249 case SSH_SMSG_STDOUT_DATA:
250 data = packet_get_string(&data_len);
251 packet_integrity_check(payload_len, 4 + data_len, type);
252 buffer_append(&stdout_buffer, data, data_len);
253 stdout_bytes += data_len;
254 memset(data, 0, data_len);
255 xfree(data);
256 break;
257
258 case SSH_SMSG_STDERR_DATA:
259 data = packet_get_string(&data_len);
260 packet_integrity_check(payload_len, 4 + data_len, type);
261 buffer_append(&stderr_buffer, data, data_len);
262 stdout_bytes += data_len;
263 memset(data, 0, data_len);
264 xfree(data);
265 break;
266
267 case SSH_SMSG_EXITSTATUS:
268 packet_integrity_check(payload_len, 4, type);
269 exit_status = packet_get_int();
270 /* Acknowledge the exit. */
271 packet_start(SSH_CMSG_EXIT_CONFIRMATION);
272 packet_send();
273 /*
274 * Must wait for packet to be sent since we are
275 * exiting the loop.
276 */
277 packet_write_wait();
278 /* Flag that we want to exit. */
279 quit_pending = 1;
280 break;
281
282 case SSH_SMSG_X11_OPEN:
283 x11_input_open(payload_len);
284 break;
285
286 case SSH_MSG_PORT_OPEN:
287 channel_input_port_open(payload_len);
288 break;
289
290 case SSH_SMSG_AGENT_OPEN:
291 packet_integrity_check(payload_len, 4, type);
292 auth_input_open_request();
293 break;
294
295 case SSH_MSG_CHANNEL_OPEN_CONFIRMATION:
296 packet_integrity_check(payload_len, 4 + 4, type);
297 channel_input_open_confirmation();
298 break;
299
300 case SSH_MSG_CHANNEL_OPEN_FAILURE:
301 packet_integrity_check(payload_len, 4, type);
302 channel_input_open_failure();
303 break;
304
305 case SSH_MSG_CHANNEL_DATA:
306 channel_input_data(payload_len);
307 break;
308
309 case SSH_MSG_CHANNEL_CLOSE:
310 packet_integrity_check(payload_len, 4, type);
311 channel_input_close();
312 break;
313
314 case SSH_MSG_CHANNEL_CLOSE_CONFIRMATION:
315 packet_integrity_check(payload_len, 4, type);
316 channel_input_close_confirmation();
317 break;
318
319 default:
320 /*
321 * Any unknown packets received during the actual
322 * session cause the session to terminate. This is
323 * intended to make debugging easier since no
324 * confirmations are sent. Any compatible protocol
325 * extensions must be negotiated during the
326 * preparatory phase.
327 */
328 packet_disconnect("Protocol error during session: type %d",
329 type);
330 }
331 }
332}
333 236
334/* 237/*
335 * Make packets from buffered stdin data, and buffer them for sending to the 238 * Make packets from buffered stdin data, and buffer them for sending to the
@@ -776,12 +679,32 @@ client_process_output(fd_set * writeset)
776} 679}
777 680
778/* 681/*
682 * Get packets from the connection input buffer, and process them as long as
683 * there are packets available.
684 *
685 * Any unknown packets received during the actual
686 * session cause the session to terminate. This is
687 * intended to make debugging easier since no
688 * confirmations are sent. Any compatible protocol
689 * extensions must be negotiated during the
690 * preparatory phase.
691 */
692
693void
694client_process_buffered_input_packets()
695{
696 dispatch_run(DISPATCH_NONBLOCK, &quit_pending);
697}
698
699/*
779 * Implements the interactive session with the server. This is called after 700 * Implements the interactive session with the server. This is called after
780 * the user has been authenticated, and a command has been started on the 701 * the user has been authenticated, and a command has been started on the
781 * remote host. If escape_char != -1, it is the character used as an escape 702 * remote host. If escape_char != -1, it is the character used as an escape
782 * character for terminating or suspending the session. 703 * character for terminating or suspending the session.
783 */ 704 */
784 705
706void client_init_dispatch(void);
707
785int 708int
786client_loop(int have_pty, int escape_char_arg) 709client_loop(int have_pty, int escape_char_arg)
787{ 710{
@@ -816,6 +739,8 @@ client_loop(int have_pty, int escape_char_arg)
816 buffer_init(&stdout_buffer); 739 buffer_init(&stdout_buffer);
817 buffer_init(&stderr_buffer); 740 buffer_init(&stderr_buffer);
818 741
742 client_init_dispatch();
743
819 /* Set signal handlers to restore non-blocking mode. */ 744 /* Set signal handlers to restore non-blocking mode. */
820 signal(SIGINT, signal_handler); 745 signal(SIGINT, signal_handler);
821 signal(SIGQUIT, signal_handler); 746 signal(SIGQUIT, signal_handler);
@@ -950,3 +875,77 @@ client_loop(int have_pty, int escape_char_arg)
950 debug("Exit status %d", exit_status); 875 debug("Exit status %d", exit_status);
951 return exit_status; 876 return exit_status;
952} 877}
878
879/*********/
880
881void
882client_input_stdout_data(int type, int plen)
883{
884 unsigned int data_len;
885 char *data = packet_get_string(&data_len);
886 packet_integrity_check(plen, 4 + data_len, type);
887 buffer_append(&stdout_buffer, data, data_len);
888 stdout_bytes += data_len;
889 memset(data, 0, data_len);
890 xfree(data);
891}
892void
893client_input_stderr_data(int type, int plen)
894{
895 unsigned int data_len;
896 char *data = packet_get_string(&data_len);
897 packet_integrity_check(plen, 4 + data_len, type);
898 buffer_append(&stderr_buffer, data, data_len);
899 stdout_bytes += data_len;
900 memset(data, 0, data_len);
901 xfree(data);
902}
903void
904client_input_exit_status(int type, int plen)
905{
906 packet_integrity_check(plen, 4, type);
907 exit_status = packet_get_int();
908 /* Acknowledge the exit. */
909 packet_start(SSH_CMSG_EXIT_CONFIRMATION);
910 packet_send();
911 /*
912 * Must wait for packet to be sent since we are
913 * exiting the loop.
914 */
915 packet_write_wait();
916 /* Flag that we want to exit. */
917 quit_pending = 1;
918}
919
920void
921client_init_dispatch_13()
922{
923 dispatch_init(NULL);
924 dispatch_set(SSH_MSG_CHANNEL_CLOSE, &channel_input_close);
925 dispatch_set(SSH_MSG_CHANNEL_CLOSE_CONFIRMATION, &channel_input_close_confirmation);
926 dispatch_set(SSH_MSG_CHANNEL_DATA, &channel_input_data);
927 dispatch_set(SSH_MSG_CHANNEL_DATA, &channel_input_data);
928 dispatch_set(SSH_MSG_CHANNEL_OPEN_CONFIRMATION, &channel_input_open_confirmation);
929 dispatch_set(SSH_MSG_CHANNEL_OPEN_FAILURE, &channel_input_open_failure);
930 dispatch_set(SSH_MSG_PORT_OPEN, &channel_input_port_open);
931 dispatch_set(SSH_SMSG_AGENT_OPEN, &auth_input_open_request);
932 dispatch_set(SSH_SMSG_EXITSTATUS, &client_input_exit_status);
933 dispatch_set(SSH_SMSG_STDERR_DATA, &client_input_stderr_data);
934 dispatch_set(SSH_SMSG_STDOUT_DATA, &client_input_stdout_data);
935 dispatch_set(SSH_SMSG_X11_OPEN, &x11_input_open);
936}
937void
938client_init_dispatch_15()
939{
940 client_init_dispatch_13();
941 dispatch_set(SSH_MSG_CHANNEL_CLOSE, &channel_input_ieof);
942 dispatch_set(SSH_MSG_CHANNEL_CLOSE_CONFIRMATION, & channel_input_oclose);
943}
944void
945client_init_dispatch()
946{
947 if (compat13)
948 client_init_dispatch_13();
949 else
950 client_init_dispatch_15();
951}
diff --git a/compress.c b/compress.c
index cf15c6670..ee5cdccb5 100644
--- a/compress.c
+++ b/compress.c
@@ -14,7 +14,7 @@
14 */ 14 */
15 15
16#include "includes.h" 16#include "includes.h"
17RCSID("$Id: compress.c,v 1.4 2000/03/17 12:40:16 damien Exp $"); 17RCSID("$Id: compress.c,v 1.5 2000/04/01 01:09:24 damien Exp $");
18 18
19#include "ssh.h" 19#include "ssh.h"
20#include "buffer.h" 20#include "buffer.h"
@@ -90,23 +90,13 @@ buffer_compress(Buffer * input_buffer, Buffer * output_buffer)
90 case Z_OK: 90 case Z_OK:
91 /* Append compressed data to output_buffer. */ 91 /* Append compressed data to output_buffer. */
92 buffer_append(output_buffer, buf, 92 buffer_append(output_buffer, buf,
93 sizeof(buf) - outgoing_stream.avail_out); 93 sizeof(buf) - outgoing_stream.avail_out);
94 break; 94 break;
95 case Z_STREAM_END:
96 fatal("buffer_compress: deflate returned Z_STREAM_END");
97 /* NOTREACHED */
98 case Z_STREAM_ERROR:
99 fatal("buffer_compress: deflate returned Z_STREAM_ERROR");
100 /* NOTREACHED */
101 case Z_BUF_ERROR:
102 fatal("buffer_compress: deflate returned Z_BUF_ERROR");
103 /* NOTREACHED */
104 default: 95 default:
105 fatal("buffer_compress: deflate returned %d", status); 96 fatal("buffer_compress: deflate returned %d", status);
106 /* NOTREACHED */ 97 /* NOTREACHED */
107 } 98 }
108 } 99 } while (outgoing_stream.avail_out == 0);
109 while (outgoing_stream.avail_out == 0);
110} 100}
111 101
112/* 102/*
@@ -127,27 +117,17 @@ buffer_uncompress(Buffer * input_buffer, Buffer * output_buffer)
127 incoming_stream.next_in = (unsigned char *) buffer_ptr(input_buffer); 117 incoming_stream.next_in = (unsigned char *) buffer_ptr(input_buffer);
128 incoming_stream.avail_in = buffer_len(input_buffer); 118 incoming_stream.avail_in = buffer_len(input_buffer);
129 119
130 incoming_stream.next_out = (unsigned char *) buf;
131 incoming_stream.avail_out = sizeof(buf);
132
133 for (;;) { 120 for (;;) {
121 /* Set up fixed-size output buffer. */
122 incoming_stream.next_out = (unsigned char *) buf;
123 incoming_stream.avail_out = sizeof(buf);
124
134 status = inflate(&incoming_stream, Z_PARTIAL_FLUSH); 125 status = inflate(&incoming_stream, Z_PARTIAL_FLUSH);
135 switch (status) { 126 switch (status) {
136 case Z_OK: 127 case Z_OK:
137 buffer_append(output_buffer, buf, 128 buffer_append(output_buffer, buf,
138 sizeof(buf) - incoming_stream.avail_out); 129 sizeof(buf) - incoming_stream.avail_out);
139 incoming_stream.next_out = (unsigned char *) buf;
140 incoming_stream.avail_out = sizeof(buf);
141 break; 130 break;
142 case Z_STREAM_END:
143 fatal("buffer_uncompress: inflate returned Z_STREAM_END");
144 /* NOTREACHED */
145 case Z_DATA_ERROR:
146 fatal("buffer_uncompress: inflate returned Z_DATA_ERROR");
147 /* NOTREACHED */
148 case Z_STREAM_ERROR:
149 fatal("buffer_uncompress: inflate returned Z_STREAM_ERROR");
150 /* NOTREACHED */
151 case Z_BUF_ERROR: 131 case Z_BUF_ERROR:
152 /* 132 /*
153 * Comments in zlib.h say that we should keep calling 133 * Comments in zlib.h say that we should keep calling
@@ -155,11 +135,9 @@ buffer_uncompress(Buffer * input_buffer, Buffer * output_buffer)
155 * be the error that we get. 135 * be the error that we get.
156 */ 136 */
157 return; 137 return;
158 case Z_MEM_ERROR:
159 fatal("buffer_uncompress: inflate returned Z_MEM_ERROR");
160 /* NOTREACHED */
161 default: 138 default:
162 fatal("buffer_uncompress: inflate returned %d", status); 139 fatal("buffer_uncompress: inflate returned %d", status);
140 /* NOTREACHED */
163 } 141 }
164 } 142 }
165} 143}
diff --git a/dispatch.c b/dispatch.c
new file mode 100644
index 000000000..8594f986e
--- /dev/null
+++ b/dispatch.c
@@ -0,0 +1,78 @@
1/*
2 * Copyright (c) 2000 Markus Friedl. All rights reserved.
3 *
4 * Redistribution and use in source and binary forms, with or without
5 * modification, are permitted provided that the following conditions
6 * are met:
7 * 1. Redistributions of source code must retain the above copyright
8 * notice, this list of conditions and the following disclaimer.
9 * 2. Redistributions in binary form must reproduce the above copyright
10 * notice, this list of conditions and the following disclaimer in the
11 * documentation and/or other materials provided with the distribution.
12 * 3. All advertising materials mentioning features or use of this software
13 * must display the following acknowledgement:
14 * This product includes software developed by Markus Friedl.
15 * 4. The name of the author may not be used to endorse or promote products
16 * derived from this software without specific prior written permission.
17 *
18 * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
19 * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
20 * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
21 * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
22 * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
23 * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
24 * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
25 * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
26 * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
27 * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
28 */
29#include "includes.h"
30RCSID("$Id: dispatch.c,v 1.1 2000/04/01 01:09:24 damien Exp $");
31#include "ssh.h"
32#include "dispatch.h"
33#include "packet.h"
34
35#define DISPATCH_MIN 0
36#define DISPATCH_MAX 255
37
38dispatch_fn *dispatch[DISPATCH_MAX];
39
40void
41dispatch_protocol_error(int type, int plen)
42{
43 error("Hm, dispatch protocol error: type %d plen %d", type, plen);
44}
45void
46dispatch_init(dispatch_fn *dflt)
47{
48 int i;
49 for (i = 0; i < DISPATCH_MAX; i++)
50 dispatch[i] = dflt;
51}
52void
53dispatch_set(int type, dispatch_fn *fn)
54{
55 dispatch[type] = fn;
56}
57void
58dispatch_run(int mode, int *done)
59{
60 for (;;) {
61 int plen;
62 int type;
63
64 if (mode == DISPATCH_BLOCK) {
65 type = packet_read(&plen);
66 } else {
67 type = packet_read_poll(&plen);
68 if (type == SSH_MSG_NONE)
69 return;
70 }
71 if (type > 0 && type < DISPATCH_MAX && dispatch[type] != NULL)
72 (*dispatch[type])(type, plen);
73 else
74 packet_disconnect("protocol error: rcvd type %d", type);
75 if (done != NULL && *done)
76 return;
77 }
78}
diff --git a/dispatch.h b/dispatch.h
new file mode 100644
index 000000000..12084aafe
--- /dev/null
+++ b/dispatch.h
@@ -0,0 +1,11 @@
1enum {
2 DISPATCH_BLOCK,
3 DISPATCH_NONBLOCK
4};
5
6typedef void dispatch_fn(int type, int plen);
7
8void dispatch_init(dispatch_fn *dflt);
9void dispatch_set(int type, dispatch_fn *fn);
10void dispatch_run(int mode, int *done);
11void dispatch_protocol_error(int type, int plen);
diff --git a/log-server.c b/log-server.c
index 7f732ed3b..476e49f80 100644
--- a/log-server.c
+++ b/log-server.c
@@ -15,7 +15,7 @@
15 */ 15 */
16 16
17#include "includes.h" 17#include "includes.h"
18RCSID("$Id: log-server.c,v 1.7 2000/03/09 10:27:50 damien Exp $"); 18RCSID("$Id: log-server.c,v 1.8 2000/04/01 01:09:24 damien Exp $");
19 19
20#include <syslog.h> 20#include <syslog.h>
21#include "packet.h" 21#include "packet.h"
@@ -137,9 +137,11 @@ do_log(LogLevel level, const char *fmt, va_list args)
137 } else { 137 } else {
138 vsnprintf(msgbuf, sizeof(msgbuf), fmt, args); 138 vsnprintf(msgbuf, sizeof(msgbuf), fmt, args);
139 } 139 }
140 if (log_on_stderr) 140 if (log_on_stderr) {
141 fprintf(stderr, "%s\n", msgbuf); 141 fprintf(stderr, "%s\n", msgbuf);
142 openlog(__progname, LOG_PID, log_facility); 142 } else {
143 syslog(pri, "%.500s", msgbuf); 143 openlog(__progname, LOG_PID, log_facility);
144 closelog(); 144 syslog(pri, "%.500s", msgbuf);
145 closelog();
146 }
145} 147}
diff --git a/mpaux.c b/mpaux.c
index 24e9ce138..c105ce076 100644
--- a/mpaux.c
+++ b/mpaux.c
@@ -15,7 +15,7 @@
15*/ 15*/
16 16
17#include "includes.h" 17#include "includes.h"
18RCSID("$Id: mpaux.c,v 1.8 1999/12/13 23:47:16 damien Exp $"); 18RCSID("$Id: mpaux.c,v 1.9 2000/04/01 01:09:24 damien Exp $");
19 19
20#include "getput.h" 20#include "getput.h"
21#include "xmalloc.h" 21#include "xmalloc.h"
@@ -31,9 +31,9 @@ RCSID("$Id: mpaux.c,v 1.8 1999/12/13 23:47:16 damien Exp $");
31 31
32void 32void
33compute_session_id(unsigned char session_id[16], 33compute_session_id(unsigned char session_id[16],
34 unsigned char cookie[8], 34 unsigned char cookie[8],
35 BIGNUM* host_key_n, 35 BIGNUM* host_key_n,
36 BIGNUM* session_key_n) 36 BIGNUM* session_key_n)
37{ 37{
38 unsigned int host_key_bytes = BN_num_bytes(host_key_n); 38 unsigned int host_key_bytes = BN_num_bytes(host_key_n);
39 unsigned int session_key_bytes = BN_num_bytes(session_key_n); 39 unsigned int session_key_bytes = BN_num_bytes(session_key_n);
diff --git a/nchan.c b/nchan.c
index 0c8066f87..996623fb4 100644
--- a/nchan.c
+++ b/nchan.c
@@ -28,7 +28,7 @@
28 */ 28 */
29 29
30#include "includes.h" 30#include "includes.h"
31RCSID("$Id: nchan.c,v 1.5 2000/01/14 04:45:50 damien Exp $"); 31RCSID("$Id: nchan.c,v 1.6 2000/04/01 01:09:24 damien Exp $");
32 32
33#include "ssh.h" 33#include "ssh.h"
34 34
@@ -41,7 +41,6 @@ static void chan_send_ieof(Channel *c);
41static void chan_send_oclose(Channel *c); 41static void chan_send_oclose(Channel *c);
42static void chan_shutdown_write(Channel *c); 42static void chan_shutdown_write(Channel *c);
43static void chan_shutdown_read(Channel *c); 43static void chan_shutdown_read(Channel *c);
44static void chan_delete_if_full_closed(Channel *c);
45 44
46/* 45/*
47 * EVENTS update channel input/output states execute ACTIONS 46 * EVENTS update channel input/output states execute ACTIONS
@@ -73,7 +72,6 @@ chan_rcvd_oclose(Channel *c)
73 error("protocol error: chan_rcvd_oclose %d for istate %d", c->self, c->istate); 72 error("protocol error: chan_rcvd_oclose %d for istate %d", c->self, c->istate);
74 return; 73 return;
75 } 74 }
76 chan_delete_if_full_closed(c);
77} 75}
78void 76void
79chan_read_failed(Channel *c) 77chan_read_failed(Channel *c)
@@ -121,7 +119,6 @@ chan_rcvd_ieof(Channel *c)
121 case CHAN_OUTPUT_WAIT_IEOF: 119 case CHAN_OUTPUT_WAIT_IEOF:
122 debug("channel %d: OUTPUT_WAIT_IEOF -> OUTPUT_CLOSED [rvcd IEOF]", c->self); 120 debug("channel %d: OUTPUT_WAIT_IEOF -> OUTPUT_CLOSED [rvcd IEOF]", c->self);
123 c->ostate = CHAN_OUTPUT_CLOSED; 121 c->ostate = CHAN_OUTPUT_CLOSED;
124 chan_delete_if_full_closed(c);
125 break; 122 break;
126 default: 123 default:
127 error("protocol error: chan_rcvd_ieof %d for ostate %d", c->self, c->ostate); 124 error("protocol error: chan_rcvd_ieof %d for ostate %d", c->self, c->ostate);
@@ -141,7 +138,6 @@ chan_write_failed(Channel *c)
141 debug("channel %d: OUTPUT_WAIT_DRAIN -> OUTPUT_CLOSED [write failed]", c->self); 138 debug("channel %d: OUTPUT_WAIT_DRAIN -> OUTPUT_CLOSED [write failed]", c->self);
142 chan_send_oclose(c); 139 chan_send_oclose(c);
143 c->ostate = CHAN_OUTPUT_CLOSED; 140 c->ostate = CHAN_OUTPUT_CLOSED;
144 chan_delete_if_full_closed(c);
145 break; 141 break;
146 default: 142 default:
147 error("internal error: chan_write_failed %d for ostate %d", c->self, c->ostate); 143 error("internal error: chan_write_failed %d for ostate %d", c->self, c->ostate);
@@ -160,7 +156,6 @@ chan_obuf_empty(Channel *c)
160 debug("channel %d: OUTPUT_WAIT_DRAIN -> OUTPUT_CLOSED [obuf empty, send OCLOSE]", c->self); 156 debug("channel %d: OUTPUT_WAIT_DRAIN -> OUTPUT_CLOSED [obuf empty, send OCLOSE]", c->self);
161 chan_send_oclose(c); 157 chan_send_oclose(c);
162 c->ostate = CHAN_OUTPUT_CLOSED; 158 c->ostate = CHAN_OUTPUT_CLOSED;
163 chan_delete_if_full_closed(c);
164 break; 159 break;
165 default: 160 default:
166 error("internal error: chan_obuf_empty %d for ostate %d", c->self, c->ostate); 161 error("internal error: chan_obuf_empty %d for ostate %d", c->self, c->ostate);
@@ -222,7 +217,7 @@ chan_shutdown_read(Channel *c)
222 error("chan_shutdown_read failed for #%d/fd%d [i%d o%d]: %.100s", 217 error("chan_shutdown_read failed for #%d/fd%d [i%d o%d]: %.100s",
223 c->self, c->sock, c->istate, c->ostate, strerror(errno)); 218 c->self, c->sock, c->istate, c->ostate, strerror(errno));
224} 219}
225static void 220void
226chan_delete_if_full_closed(Channel *c) 221chan_delete_if_full_closed(Channel *c)
227{ 222{
228 if (c->istate == CHAN_INPUT_CLOSED && c->ostate == CHAN_OUTPUT_CLOSED) { 223 if (c->istate == CHAN_INPUT_CLOSED && c->ostate == CHAN_OUTPUT_CLOSED) {
diff --git a/nchan.h b/nchan.h
index 49f2d0609..0ceee1c71 100644
--- a/nchan.h
+++ b/nchan.h
@@ -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 29
30/* RCSID("$Id: nchan.h,v 1.3 1999/11/25 00:54:59 damien Exp $"); */ 30/* RCSID("$Id: nchan.h,v 1.4 2000/04/01 01:09:24 damien Exp $"); */
31 31
32#ifndef NCHAN_H 32#ifndef NCHAN_H
33#define NCHAN_H 33#define NCHAN_H
@@ -83,4 +83,6 @@ void chan_write_failed(Channel * c);
83void chan_obuf_empty(Channel * c); 83void chan_obuf_empty(Channel * c);
84 84
85void chan_init_iostates(Channel * c); 85void chan_init_iostates(Channel * c);
86
87void chan_delete_if_full_closed(Channel *c);
86#endif 88#endif
diff --git a/packet.c b/packet.c
index f65ae989d..ffce2c745 100644
--- a/packet.c
+++ b/packet.c
@@ -15,7 +15,7 @@
15 */ 15 */
16 16
17#include "includes.h" 17#include "includes.h"
18RCSID("$Id: packet.c,v 1.12 2000/03/09 10:27:50 damien Exp $"); 18RCSID("$Id: packet.c,v 1.13 2000/04/01 01:09:25 damien Exp $");
19 19
20#include "xmalloc.h" 20#include "xmalloc.h"
21#include "buffer.h" 21#include "buffer.h"
@@ -28,6 +28,7 @@ RCSID("$Id: packet.c,v 1.12 2000/03/09 10:27:50 damien Exp $");
28 28
29#include "compress.h" 29#include "compress.h"
30#include "deattack.h" 30#include "deattack.h"
31#include "channels.h"
31 32
32/* 33/*
33 * This variable contains the file descriptors used for communicating with 34 * This variable contains the file descriptors used for communicating with
diff --git a/pty.h b/pty.h
index b97b96df0..af6c279d7 100644
--- a/pty.h
+++ b/pty.h
@@ -13,7 +13,7 @@
13 * tty. 13 * tty.
14 */ 14 */
15 15
16/* RCSID("$Id: pty.h,v 1.6 2000/03/09 10:27:51 damien Exp $"); */ 16/* RCSID("$Id: pty.h,v 1.7 2000/04/01 01:09:25 damien Exp $"); */
17 17
18#ifndef PTY_H 18#ifndef PTY_H
19#define PTY_H 19#define PTY_H
@@ -45,6 +45,4 @@ pty_change_window_size(int ptyfd, int row, int col,
45 45
46void pty_setowner(struct passwd *pw, const char *ttyname); 46void pty_setowner(struct passwd *pw, const char *ttyname);
47 47
48void pty_setowner(struct passwd *pw, const char *ttyname);
49
50#endif /* PTY_H */ 48#endif /* PTY_H */
diff --git a/readconf.c b/readconf.c
index 99023d136..bb420ac05 100644
--- a/readconf.c
+++ b/readconf.c
@@ -14,11 +14,12 @@
14 */ 14 */
15 15
16#include "includes.h" 16#include "includes.h"
17RCSID("$Id: readconf.c,v 1.8 2000/03/09 10:27:51 damien Exp $"); 17RCSID("$Id: readconf.c,v 1.9 2000/04/01 01:09:25 damien Exp $");
18 18
19#include "ssh.h" 19#include "ssh.h"
20#include "cipher.h" 20#include "cipher.h"
21#include "readconf.h" 21#include "readconf.h"
22#include "match.h"
22#include "xmalloc.h" 23#include "xmalloc.h"
23 24
24/* Format of the configuration file: 25/* Format of the configuration file:
diff --git a/serverloop.c b/serverloop.c
index 2afca7637..8bf448ceb 100644
--- a/serverloop.c
+++ b/serverloop.c
@@ -13,6 +13,10 @@
13#include "buffer.h" 13#include "buffer.h"
14#include "servconf.h" 14#include "servconf.h"
15#include "pty.h" 15#include "pty.h"
16#include "channels.h"
17
18#include "compat.h"
19#include "dispatch.h"
16 20
17static Buffer stdin_buffer; /* Buffer for stdin data. */ 21static Buffer stdin_buffer; /* Buffer for stdin data. */
18static Buffer stdout_buffer; /* Buffer for stdout data. */ 22static Buffer stdout_buffer; /* Buffer for stdout data. */
@@ -47,6 +51,8 @@ static volatile int child_terminated; /* The child has terminated. */
47static volatile int child_has_selected; /* Child has had chance to drain. */ 51static volatile int child_has_selected; /* Child has had chance to drain. */
48static volatile int child_wait_status; /* Status from wait(). */ 52static volatile int child_wait_status; /* Status from wait(). */
49 53
54void server_init_dispatch(void);
55
50void 56void
51sigchld_handler(int sig) 57sigchld_handler(int sig)
52{ 58{
@@ -68,104 +74,6 @@ sigchld_handler(int sig)
68} 74}
69 75
70/* 76/*
71 * Process any buffered packets that have been received from the client.
72 */
73void
74process_buffered_input_packets()
75{
76 int type;
77 char *data;
78 unsigned int data_len;
79 int row, col, xpixel, ypixel;
80 int payload_len;
81
82 /* Process buffered packets from the client. */
83 while ((type = packet_read_poll(&payload_len)) != SSH_MSG_NONE) {
84 switch (type) {
85 case SSH_CMSG_STDIN_DATA:
86 /* Stdin data from the client. Append it to the buffer. */
87 /* Ignore any data if the client has closed stdin. */
88 if (fdin == -1)
89 break;
90 data = packet_get_string(&data_len);
91 packet_integrity_check(payload_len, (4 + data_len), type);
92 buffer_append(&stdin_buffer, data, data_len);
93 memset(data, 0, data_len);
94 xfree(data);
95 break;
96
97 case SSH_CMSG_EOF:
98 /*
99 * Eof from the client. The stdin descriptor to the
100 * program will be closed when all buffered data has
101 * drained.
102 */
103 debug("EOF received for stdin.");
104 packet_integrity_check(payload_len, 0, type);
105 stdin_eof = 1;
106 break;
107
108 case SSH_CMSG_WINDOW_SIZE:
109 debug("Window change received.");
110 packet_integrity_check(payload_len, 4 * 4, type);
111 row = packet_get_int();
112 col = packet_get_int();
113 xpixel = packet_get_int();
114 ypixel = packet_get_int();
115 if (fdin != -1)
116 pty_change_window_size(fdin, row, col, xpixel, ypixel);
117 break;
118
119 case SSH_MSG_PORT_OPEN:
120 debug("Received port open request.");
121 channel_input_port_open(payload_len);
122 break;
123
124 case SSH_MSG_CHANNEL_OPEN_CONFIRMATION:
125 debug("Received channel open confirmation.");
126 packet_integrity_check(payload_len, 4 + 4, type);
127 channel_input_open_confirmation();
128 break;
129
130 case SSH_MSG_CHANNEL_OPEN_FAILURE:
131 debug("Received channel open failure.");
132 packet_integrity_check(payload_len, 4, type);
133 channel_input_open_failure();
134 break;
135
136 case SSH_MSG_CHANNEL_DATA:
137 channel_input_data(payload_len);
138 break;
139
140 case SSH_MSG_CHANNEL_CLOSE:
141 debug("Received channel close.");
142 packet_integrity_check(payload_len, 4, type);
143 channel_input_close();
144 break;
145
146 case SSH_MSG_CHANNEL_CLOSE_CONFIRMATION:
147 debug("Received channel close confirmation.");
148 packet_integrity_check(payload_len, 4, type);
149 channel_input_close_confirmation();
150 break;
151
152 default:
153 /*
154 * In this phase, any unexpected messages cause a
155 * protocol error. This is to ease debugging; also,
156 * since no confirmations are sent messages,
157 * unprocessed unknown messages could cause strange
158 * problems. Any compatible protocol extensions must
159 * be negotiated before entering the interactive
160 * session.
161 */
162 packet_disconnect("Protocol error during session: type %d",
163 type);
164 }
165 }
166}
167
168/*
169 * Make packets from buffered stderr data, and buffer it for sending 77 * Make packets from buffered stderr data, and buffer it for sending
170 * to the client. 78 * to the client.
171 */ 79 */
@@ -378,7 +286,7 @@ process_output(fd_set * writeset)
378#ifdef USE_PIPES 286#ifdef USE_PIPES
379 close(fdin); 287 close(fdin);
380#else 288#else
381 if (fdout == -1) 289 if (fdin != fdout)
382 close(fdin); 290 close(fdin);
383 else 291 else
384 shutdown(fdin, SHUT_WR); /* We will no longer send. */ 292 shutdown(fdin, SHUT_WR); /* We will no longer send. */
@@ -425,6 +333,12 @@ drain_output()
425 packet_write_wait(); 333 packet_write_wait();
426} 334}
427 335
336void
337process_buffered_input_packets()
338{
339 dispatch_run(DISPATCH_NONBLOCK, NULL);
340}
341
428/* 342/*
429 * Performs the interactive session. This handles data transmission between 343 * Performs the interactive session. This handles data transmission between
430 * the client and the program. Note that the notion of stdin, stdout, and 344 * the client and the program. Note that the notion of stdin, stdout, and
@@ -490,6 +404,8 @@ server_loop(int pid, int fdin_arg, int fdout_arg, int fderr_arg)
490 if (fderr == -1) 404 if (fderr == -1)
491 fderr_eof = 1; 405 fderr_eof = 1;
492 406
407 server_init_dispatch();
408
493 /* Main loop of the server for the interactive session mode. */ 409 /* Main loop of the server for the interactive session mode. */
494 for (;;) { 410 for (;;) {
495 fd_set readset, writeset; 411 fd_set readset, writeset;
@@ -505,7 +421,7 @@ server_loop(int pid, int fdin_arg, int fdout_arg, int fderr_arg)
505#ifdef USE_PIPES 421#ifdef USE_PIPES
506 close(fdin); 422 close(fdin);
507#else 423#else
508 if (fdout == -1) 424 if (fdin != fdout)
509 close(fdin); 425 close(fdin);
510 else 426 else
511 shutdown(fdin, SHUT_WR); /* We will no longer send. */ 427 shutdown(fdin, SHUT_WR); /* We will no longer send. */
@@ -549,7 +465,7 @@ server_loop(int pid, int fdin_arg, int fdout_arg, int fderr_arg)
549 (buffer_len(&stdout_buffer) == 0) && 465 (buffer_len(&stdout_buffer) == 0) &&
550 (buffer_len(&stderr_buffer) == 0)) { 466 (buffer_len(&stderr_buffer) == 0)) {
551 if (!channel_still_open()) 467 if (!channel_still_open())
552 goto quit; 468 break;
553 if (!waiting_termination) { 469 if (!waiting_termination) {
554 const char *s = "Waiting for forwarded connections to terminate...\r\n"; 470 const char *s = "Waiting for forwarded connections to terminate...\r\n";
555 char *cp; 471 char *cp;
@@ -576,7 +492,6 @@ server_loop(int pid, int fdin_arg, int fdout_arg, int fderr_arg)
576 process_output(&writeset); 492 process_output(&writeset);
577 } 493 }
578 494
579quit:
580 /* Cleanup and termination code. */ 495 /* Cleanup and termination code. */
581 496
582 /* Wait until all output has been sent to the client. */ 497 /* Wait until all output has been sent to the client. */
@@ -662,3 +577,79 @@ quit:
662 packet_disconnect("wait returned status %04x.", wait_status); 577 packet_disconnect("wait returned status %04x.", wait_status);
663 /* NOTREACHED */ 578 /* NOTREACHED */
664} 579}
580
581void
582server_input_stdin_data(int type, int plen)
583{
584 char *data;
585 unsigned int data_len;
586
587 /* Stdin data from the client. Append it to the buffer. */
588 /* Ignore any data if the client has closed stdin. */
589 if (fdin == -1)
590 return;
591 data = packet_get_string(&data_len);
592 packet_integrity_check(plen, (4 + data_len), type);
593 buffer_append(&stdin_buffer, data, data_len);
594 memset(data, 0, data_len);
595 xfree(data);
596}
597
598void
599server_input_eof(int type, int plen)
600{
601 /*
602 * Eof from the client. The stdin descriptor to the
603 * program will be closed when all buffered data has
604 * drained.
605 */
606 debug("EOF received for stdin.");
607 packet_integrity_check(plen, 0, type);
608 stdin_eof = 1;
609}
610
611void
612server_input_window_size(int type, int plen)
613{
614 int row = packet_get_int();
615 int col = packet_get_int();
616 int xpixel = packet_get_int();
617 int ypixel = packet_get_int();
618
619 debug("Window change received.");
620 packet_integrity_check(plen, 4 * 4, type);
621 if (fdin != -1)
622 pty_change_window_size(fdin, row, col, xpixel, ypixel);
623}
624
625void
626server_init_dispatch_13()
627{
628 debug("server_init_dispatch_13");
629 dispatch_init(NULL);
630 dispatch_set(SSH_CMSG_EOF, &server_input_eof);
631 dispatch_set(SSH_CMSG_STDIN_DATA, &server_input_stdin_data);
632 dispatch_set(SSH_CMSG_WINDOW_SIZE, &server_input_window_size);
633 dispatch_set(SSH_MSG_CHANNEL_CLOSE, &channel_input_close);
634 dispatch_set(SSH_MSG_CHANNEL_CLOSE_CONFIRMATION, &channel_input_close_confirmation);
635 dispatch_set(SSH_MSG_CHANNEL_DATA, &channel_input_data);
636 dispatch_set(SSH_MSG_CHANNEL_OPEN_CONFIRMATION, &channel_input_open_confirmation);
637 dispatch_set(SSH_MSG_CHANNEL_OPEN_FAILURE, &channel_input_open_failure);
638 dispatch_set(SSH_MSG_PORT_OPEN, &channel_input_port_open);
639}
640void
641server_init_dispatch_15()
642{
643 server_init_dispatch_13();
644 debug("server_init_dispatch_15");
645 dispatch_set(SSH_MSG_CHANNEL_CLOSE, &channel_input_ieof);
646 dispatch_set(SSH_MSG_CHANNEL_CLOSE_CONFIRMATION, &channel_input_oclose);
647}
648void
649server_init_dispatch()
650{
651 if (compat13)
652 server_init_dispatch_13();
653 else
654 server_init_dispatch_15();
655}
diff --git a/session.c b/session.c
new file mode 100644
index 000000000..2128fe394
--- /dev/null
+++ b/session.c
@@ -0,0 +1,1153 @@
1/*
2 * Copyright (c) 1995 Tatu Ylonen <ylo@cs.hut.fi>, Espoo, Finland
3 * All rights reserved
4 */
5
6#include "includes.h"
7RCSID("$OpenBSD: session.c,v 1.1 2000/03/28 21:15:45 markus Exp $");
8
9#include "xmalloc.h"
10#include "ssh.h"
11#include "pty.h"
12#include "packet.h"
13#include "buffer.h"
14#include "cipher.h"
15#include "mpaux.h"
16#include "servconf.h"
17#include "uidswap.h"
18#include "compat.h"
19#include "channels.h"
20#include "nchan.h"
21
22/* types */
23
24#define TTYSZ 64
25typedef struct Session Session;
26struct Session {
27 int used;
28 int self;
29 struct passwd *pw;
30 pid_t pid;
31 /* tty */
32 char *term;
33 int ptyfd, ttyfd, ptymaster;
34 int row, col, xpixel, ypixel;
35 char tty[TTYSZ];
36 /* X11 */
37 char *display;
38 int screen;
39 char *auth_proto;
40 char *auth_data;
41 /* proto 2 */
42 int chanid;
43};
44
45/* func */
46
47Session *session_new(void);
48void session_set_fds(Session *s, int fdin, int fdout, int fderr);
49void session_pty_cleanup(Session *s);
50void do_exec_pty(Session *s, const char *command, struct passwd * pw);
51void do_exec_no_pty(Session *s, const char *command, struct passwd * pw);
52
53void
54do_child(const char *command, struct passwd * pw, const char *term,
55 const char *display, const char *auth_proto,
56 const char *auth_data, const char *ttyname);
57
58/* import */
59extern ServerOptions options;
60extern char *__progname;
61extern int log_stderr;
62extern int debug_flag;
63
64/* Local Xauthority file. */
65static char *xauthfile;
66
67/* data */
68#define MAX_SESSIONS 10
69Session sessions[MAX_SESSIONS];
70
71/* Flags set in auth-rsa from authorized_keys flags. These are set in auth-rsa.c. */
72int no_port_forwarding_flag = 0;
73int no_agent_forwarding_flag = 0;
74int no_x11_forwarding_flag = 0;
75int no_pty_flag = 0;
76
77/* RSA authentication "command=" option. */
78char *forced_command = NULL;
79
80/* RSA authentication "environment=" options. */
81struct envstring *custom_environment = NULL;
82
83/*
84 * Remove local Xauthority file.
85 */
86void
87xauthfile_cleanup_proc(void *ignore)
88{
89 debug("xauthfile_cleanup_proc called");
90
91 if (xauthfile != NULL) {
92 char *p;
93 unlink(xauthfile);
94 p = strrchr(xauthfile, '/');
95 if (p != NULL) {
96 *p = '\0';
97 rmdir(xauthfile);
98 }
99 xfree(xauthfile);
100 xauthfile = NULL;
101 }
102}
103
104/*
105 * Function to perform cleanup if we get aborted abnormally (e.g., due to a
106 * dropped connection).
107 */
108void
109pty_cleanup_proc(void *session)
110{
111 Session *s=session;
112 if (s == NULL)
113 fatal("pty_cleanup_proc: no session");
114 debug("pty_cleanup_proc: %s", s->tty);
115
116 if (s->pid != 0) {
117 /* Record that the user has logged out. */
118 record_logout(s->pid, s->tty);
119 }
120
121 /* Release the pseudo-tty. */
122 pty_release(s->tty);
123}
124
125/*
126 * Prepares for an interactive session. This is called after the user has
127 * been successfully authenticated. During this message exchange, pseudo
128 * terminals are allocated, X11, TCP/IP, and authentication agent forwardings
129 * are requested, etc.
130 */
131void
132do_authenticated(struct passwd * pw)
133{
134 Session *s;
135 int type;
136 int compression_level = 0, enable_compression_after_reply = 0;
137 int have_pty = 0;
138 char *command;
139 int n_bytes;
140 int plen;
141 unsigned int proto_len, data_len, dlen;
142
143 /*
144 * Cancel the alarm we set to limit the time taken for
145 * authentication.
146 */
147 alarm(0);
148
149 /*
150 * Inform the channel mechanism that we are the server side and that
151 * the client may request to connect to any port at all. (The user
152 * could do it anyway, and we wouldn\'t know what is permitted except
153 * by the client telling us, so we can equally well trust the client
154 * not to request anything bogus.)
155 */
156 if (!no_port_forwarding_flag)
157 channel_permit_all_opens();
158
159 s = session_new();
160
161 /*
162 * We stay in this loop until the client requests to execute a shell
163 * or a command.
164 */
165 for (;;) {
166 int success = 0;
167
168 /* Get a packet from the client. */
169 type = packet_read(&plen);
170
171 /* Process the packet. */
172 switch (type) {
173 case SSH_CMSG_REQUEST_COMPRESSION:
174 packet_integrity_check(plen, 4, type);
175 compression_level = packet_get_int();
176 if (compression_level < 1 || compression_level > 9) {
177 packet_send_debug("Received illegal compression level %d.",
178 compression_level);
179 break;
180 }
181 /* Enable compression after we have responded with SUCCESS. */
182 enable_compression_after_reply = 1;
183 success = 1;
184 break;
185
186 case SSH_CMSG_REQUEST_PTY:
187 if (no_pty_flag) {
188 debug("Allocating a pty not permitted for this authentication.");
189 break;
190 }
191 if (have_pty)
192 packet_disconnect("Protocol error: you already have a pty.");
193
194 debug("Allocating pty.");
195
196 /* Allocate a pty and open it. */
197 if (!pty_allocate(&s->ptyfd, &s->ttyfd, s->tty,
198 sizeof(s->tty))) {
199 error("Failed to allocate pty.");
200 break;
201 }
202 fatal_add_cleanup(pty_cleanup_proc, (void *)s);
203 pty_setowner(pw, s->tty);
204
205 /* Get TERM from the packet. Note that the value may be of arbitrary length. */
206 s->term = packet_get_string(&dlen);
207 packet_integrity_check(dlen, strlen(s->term), type);
208 /* packet_integrity_check(plen, 4 + dlen + 4*4 + n_bytes, type); */
209 /* Remaining bytes */
210 n_bytes = plen - (4 + dlen + 4 * 4);
211
212 if (strcmp(s->term, "") == 0) {
213 xfree(s->term);
214 s->term = NULL;
215 }
216 /* Get window size from the packet. */
217 s->row = packet_get_int();
218 s->col = packet_get_int();
219 s->xpixel = packet_get_int();
220 s->ypixel = packet_get_int();
221 pty_change_window_size(s->ptyfd, s->row, s->col, s->xpixel, s->ypixel);
222
223 /* Get tty modes from the packet. */
224 tty_parse_modes(s->ttyfd, &n_bytes);
225 packet_integrity_check(plen, 4 + dlen + 4 * 4 + n_bytes, type);
226
227 /* Indicate that we now have a pty. */
228 success = 1;
229 have_pty = 1;
230 break;
231
232 case SSH_CMSG_X11_REQUEST_FORWARDING:
233 if (!options.x11_forwarding) {
234 packet_send_debug("X11 forwarding disabled in server configuration file.");
235 break;
236 }
237#ifdef XAUTH_PATH
238 if (no_x11_forwarding_flag) {
239 packet_send_debug("X11 forwarding not permitted for this authentication.");
240 break;
241 }
242 debug("Received request for X11 forwarding with auth spoofing.");
243 if (s->display != NULL)
244 packet_disconnect("Protocol error: X11 display already set.");
245
246 s->auth_proto = packet_get_string(&proto_len);
247 s->auth_data = packet_get_string(&data_len);
248 packet_integrity_check(plen, 4 + proto_len + 4 + data_len + 4, type);
249
250 if (packet_get_protocol_flags() & SSH_PROTOFLAG_SCREEN_NUMBER)
251 s->screen = packet_get_int();
252 else
253 s->screen = 0;
254 s->display = x11_create_display_inet(s->screen, options.x11_display_offset);
255
256 if (s->display == NULL)
257 break;
258
259 /* Setup to always have a local .Xauthority. */
260 xauthfile = xmalloc(MAXPATHLEN);
261 strlcpy(xauthfile, "/tmp/ssh-XXXXXXXX", MAXPATHLEN);
262 temporarily_use_uid(pw->pw_uid);
263 if (mkdtemp(xauthfile) == NULL) {
264 restore_uid();
265 error("private X11 dir: mkdtemp %s failed: %s",
266 xauthfile, strerror(errno));
267 xfree(xauthfile);
268 xauthfile = NULL;
269 break;
270 }
271 strlcat(xauthfile, "/cookies", MAXPATHLEN);
272 open(xauthfile, O_RDWR|O_CREAT|O_EXCL, 0600);
273 restore_uid();
274 fatal_add_cleanup(xauthfile_cleanup_proc, NULL);
275 success = 1;
276 break;
277#else /* XAUTH_PATH */
278 packet_send_debug("No xauth program; cannot forward with spoofing.");
279 break;
280#endif /* XAUTH_PATH */
281
282 case SSH_CMSG_AGENT_REQUEST_FORWARDING:
283 if (no_agent_forwarding_flag || compat13) {
284 debug("Authentication agent forwarding not permitted for this authentication.");
285 break;
286 }
287 debug("Received authentication agent forwarding request.");
288 auth_input_request_forwarding(pw);
289 success = 1;
290 break;
291
292 case SSH_CMSG_PORT_FORWARD_REQUEST:
293 if (no_port_forwarding_flag) {
294 debug("Port forwarding not permitted for this authentication.");
295 break;
296 }
297 debug("Received TCP/IP port forwarding request.");
298 channel_input_port_forward_request(pw->pw_uid == 0);
299 success = 1;
300 break;
301
302 case SSH_CMSG_MAX_PACKET_SIZE:
303 if (packet_set_maxsize(packet_get_int()) > 0)
304 success = 1;
305 break;
306
307 case SSH_CMSG_EXEC_SHELL:
308 case SSH_CMSG_EXEC_CMD:
309 /* Set interactive/non-interactive mode. */
310 packet_set_interactive(have_pty || s->display != NULL,
311 options.keepalives);
312
313 if (type == SSH_CMSG_EXEC_CMD) {
314 command = packet_get_string(&dlen);
315 debug("Exec command '%.500s'", command);
316 packet_integrity_check(plen, 4 + dlen, type);
317 } else {
318 command = NULL;
319 packet_integrity_check(plen, 0, type);
320 }
321 if (forced_command != NULL) {
322 command = forced_command;
323 debug("Forced command '%.500s'", forced_command);
324 }
325 if (have_pty)
326 do_exec_pty(s, command, pw);
327 else
328 do_exec_no_pty(s, command, pw);
329
330 if (command != NULL)
331 xfree(command);
332 /* Cleanup user's local Xauthority file. */
333 if (xauthfile)
334 xauthfile_cleanup_proc(NULL);
335 return;
336
337 default:
338 /*
339 * Any unknown messages in this phase are ignored,
340 * and a failure message is returned.
341 */
342 log("Unknown packet type received after authentication: %d", type);
343 }
344 packet_start(success ? SSH_SMSG_SUCCESS : SSH_SMSG_FAILURE);
345 packet_send();
346 packet_write_wait();
347
348 /* Enable compression now that we have replied if appropriate. */
349 if (enable_compression_after_reply) {
350 enable_compression_after_reply = 0;
351 packet_start_compression(compression_level);
352 }
353 }
354}
355
356/*
357 * This is called to fork and execute a command when we have no tty. This
358 * will call do_child from the child, and server_loop from the parent after
359 * setting up file descriptors and such.
360 */
361void
362do_exec_no_pty(Session *s, const char *command, struct passwd * pw)
363{
364 int pid;
365
366#ifdef USE_PIPES
367 int pin[2], pout[2], perr[2];
368 /* Allocate pipes for communicating with the program. */
369 if (pipe(pin) < 0 || pipe(pout) < 0 || pipe(perr) < 0)
370 packet_disconnect("Could not create pipes: %.100s",
371 strerror(errno));
372#else /* USE_PIPES */
373 int inout[2], err[2];
374 /* Uses socket pairs to communicate with the program. */
375 if (socketpair(AF_UNIX, SOCK_STREAM, 0, inout) < 0 ||
376 socketpair(AF_UNIX, SOCK_STREAM, 0, err) < 0)
377 packet_disconnect("Could not create socket pairs: %.100s",
378 strerror(errno));
379#endif /* USE_PIPES */
380 if (s == NULL)
381 fatal("do_exec_no_pty: no session");
382
383 setproctitle("%s@notty", pw->pw_name);
384
385#ifdef USE_PAM
386 do_pam_setcred();
387#endif /* USE_PAM */
388
389 /* Fork the child. */
390 if ((pid = fork()) == 0) {
391 /* Child. Reinitialize the log since the pid has changed. */
392 log_init(__progname, options.log_level, options.log_facility, log_stderr);
393
394 /*
395 * Create a new session and process group since the 4.4BSD
396 * setlogin() affects the entire process group.
397 */
398 if (setsid() < 0)
399 error("setsid failed: %.100s", strerror(errno));
400
401#ifdef USE_PIPES
402 /*
403 * Redirect stdin. We close the parent side of the socket
404 * pair, and make the child side the standard input.
405 */
406 close(pin[1]);
407 if (dup2(pin[0], 0) < 0)
408 perror("dup2 stdin");
409 close(pin[0]);
410
411 /* Redirect stdout. */
412 close(pout[0]);
413 if (dup2(pout[1], 1) < 0)
414 perror("dup2 stdout");
415 close(pout[1]);
416
417 /* Redirect stderr. */
418 close(perr[0]);
419 if (dup2(perr[1], 2) < 0)
420 perror("dup2 stderr");
421 close(perr[1]);
422#else /* USE_PIPES */
423 /*
424 * Redirect stdin, stdout, and stderr. Stdin and stdout will
425 * use the same socket, as some programs (particularly rdist)
426 * seem to depend on it.
427 */
428 close(inout[1]);
429 close(err[1]);
430 if (dup2(inout[0], 0) < 0) /* stdin */
431 perror("dup2 stdin");
432 if (dup2(inout[0], 1) < 0) /* stdout. Note: same socket as stdin. */
433 perror("dup2 stdout");
434 if (dup2(err[0], 2) < 0) /* stderr */
435 perror("dup2 stderr");
436#endif /* USE_PIPES */
437
438 /* Do processing for the child (exec command etc). */
439 do_child(command, pw, NULL, s->display, s->auth_proto, s->auth_data, NULL);
440 /* NOTREACHED */
441 }
442 if (pid < 0)
443 packet_disconnect("fork failed: %.100s", strerror(errno));
444 s->pid = pid;
445#ifdef USE_PIPES
446 /* We are the parent. Close the child sides of the pipes. */
447 close(pin[0]);
448 close(pout[1]);
449 close(perr[1]);
450
451 /* Enter the interactive session. */
452 server_loop(pid, pin[1], pout[0], perr[0]);
453 /* server_loop has closed pin[1], pout[1], and perr[1]. */
454#else /* USE_PIPES */
455 /* We are the parent. Close the child sides of the socket pairs. */
456 close(inout[0]);
457 close(err[0]);
458
459 /*
460 * Enter the interactive session. Note: server_loop must be able to
461 * handle the case that fdin and fdout are the same.
462 */
463 server_loop(pid, inout[1], inout[1], err[1]);
464 /* server_loop has closed inout[1] and err[1]. */
465#endif /* USE_PIPES */
466}
467
468/*
469 * This is called to fork and execute a command when we have a tty. This
470 * will call do_child from the child, and server_loop from the parent after
471 * setting up file descriptors, controlling tty, updating wtmp, utmp,
472 * lastlog, and other such operations.
473 */
474void
475do_exec_pty(Session *s, const char *command, struct passwd * pw)
476{
477 FILE *f;
478 char buf[100], *time_string;
479 char line[256];
480 const char *hostname;
481 int fdout, ptyfd, ttyfd, ptymaster;
482 int quiet_login;
483 pid_t pid;
484 socklen_t fromlen;
485 struct sockaddr_storage from;
486 struct stat st;
487 time_t last_login_time;
488
489 if (s == NULL)
490 fatal("do_exec_pty: no session");
491 ptyfd = s->ptyfd;
492 ttyfd = s->ttyfd;
493
494 /* Get remote host name. */
495 hostname = get_canonical_hostname();
496
497 /*
498 * Get the time when the user last logged in. Buf will be set to
499 * contain the hostname the last login was from.
500 */
501 if (!options.use_login) {
502 last_login_time = get_last_login_time(pw->pw_uid, pw->pw_name,
503 buf, sizeof(buf));
504 }
505 setproctitle("%s@%s", pw->pw_name, strrchr(s->tty, '/') + 1);
506
507#ifdef USE_PAM
508 do_pam_session(pw->pw_name, s->tty);
509 do_pam_setcred();
510#endif /* USE_PAM */
511
512 /* Fork the child. */
513 if ((pid = fork()) == 0) {
514 pid = getpid();
515
516 /* Child. Reinitialize the log because the pid has
517 changed. */
518 log_init(__progname, options.log_level, options.log_facility, log_stderr);
519
520 /* Close the master side of the pseudo tty. */
521 close(ptyfd);
522
523 /* Make the pseudo tty our controlling tty. */
524 pty_make_controlling_tty(&ttyfd, s->tty);
525
526 /* Redirect stdin from the pseudo tty. */
527 if (dup2(ttyfd, fileno(stdin)) < 0)
528 error("dup2 stdin failed: %.100s", strerror(errno));
529
530 /* Redirect stdout to the pseudo tty. */
531 if (dup2(ttyfd, fileno(stdout)) < 0)
532 error("dup2 stdin failed: %.100s", strerror(errno));
533
534 /* Redirect stderr to the pseudo tty. */
535 if (dup2(ttyfd, fileno(stderr)) < 0)
536 error("dup2 stdin failed: %.100s", strerror(errno));
537
538 /* Close the extra descriptor for the pseudo tty. */
539 close(ttyfd);
540
541///XXXX ? move to do_child() ??
542 /*
543 * Get IP address of client. This is needed because we want
544 * to record where the user logged in from. If the
545 * connection is not a socket, let the ip address be 0.0.0.0.
546 */
547 memset(&from, 0, sizeof(from));
548 if (packet_connection_is_on_socket()) {
549 fromlen = sizeof(from);
550 if (getpeername(packet_get_connection_in(),
551 (struct sockaddr *) & from, &fromlen) < 0) {
552 debug("getpeername: %.100s", strerror(errno));
553 fatal_cleanup();
554 }
555 }
556 /* Record that there was a login on that terminal. */
557 record_login(pid, s->tty, pw->pw_name, pw->pw_uid, hostname,
558 (struct sockaddr *)&from);
559
560 /* Check if .hushlogin exists. */
561 snprintf(line, sizeof line, "%.200s/.hushlogin", pw->pw_dir);
562 quiet_login = stat(line, &st) >= 0;
563
564#ifdef USE_PAM
565 if (!quiet_login)
566 print_pam_messages();
567#endif /* USE_PAM */
568
569 /*
570 * If the user has logged in before, display the time of last
571 * login. However, don't display anything extra if a command
572 * has been specified (so that ssh can be used to execute
573 * commands on a remote machine without users knowing they
574 * are going to another machine). Login(1) will do this for
575 * us as well, so check if login(1) is used
576 */
577 if (command == NULL && last_login_time != 0 && !quiet_login &&
578 !options.use_login) {
579 /* Convert the date to a string. */
580 time_string = ctime(&last_login_time);
581 /* Remove the trailing newline. */
582 if (strchr(time_string, '\n'))
583 *strchr(time_string, '\n') = 0;
584 /* Display the last login time. Host if displayed
585 if known. */
586 if (strcmp(buf, "") == 0)
587 printf("Last login: %s\r\n", time_string);
588 else
589 printf("Last login: %s from %s\r\n", time_string, buf);
590 }
591 /*
592 * Print /etc/motd unless a command was specified or printing
593 * it was disabled in server options or login(1) will be
594 * used. Note that some machines appear to print it in
595 * /etc/profile or similar.
596 */
597 if (command == NULL && options.print_motd && !quiet_login &&
598 !options.use_login) {
599 /* Print /etc/motd if it exists. */
600 f = fopen("/etc/motd", "r");
601 if (f) {
602 while (fgets(line, sizeof(line), f))
603 fputs(line, stdout);
604 fclose(f);
605 }
606 }
607 /* Do common processing for the child, such as execing the command. */
608 do_child(command, pw, s->term, s->display, s->auth_proto, s->auth_data, s->tty);
609 /* NOTREACHED */
610 }
611 if (pid < 0)
612 packet_disconnect("fork failed: %.100s", strerror(errno));
613 s->pid = pid;
614
615 /* Parent. Close the slave side of the pseudo tty. */
616 close(ttyfd);
617
618 /*
619 * Create another descriptor of the pty master side for use as the
620 * standard input. We could use the original descriptor, but this
621 * simplifies code in server_loop. The descriptor is bidirectional.
622 */
623 fdout = dup(ptyfd);
624 if (fdout < 0)
625 packet_disconnect("dup #1 failed: %.100s", strerror(errno));
626
627 /* we keep a reference to the pty master */
628 ptymaster = dup(ptyfd);
629 if (ptymaster < 0)
630 packet_disconnect("dup #2 failed: %.100s", strerror(errno));
631 s->ptymaster = ptymaster;
632
633 /* Enter interactive session. */
634 server_loop(pid, ptyfd, fdout, -1);
635 /* server_loop _has_ closed ptyfd and fdout. */
636 session_pty_cleanup(s);
637}
638
639/*
640 * Sets the value of the given variable in the environment. If the variable
641 * already exists, its value is overriden.
642 */
643void
644child_set_env(char ***envp, unsigned int *envsizep, const char *name,
645 const char *value)
646{
647 unsigned int i, namelen;
648 char **env;
649
650 /*
651 * Find the slot where the value should be stored. If the variable
652 * already exists, we reuse the slot; otherwise we append a new slot
653 * at the end of the array, expanding if necessary.
654 */
655 env = *envp;
656 namelen = strlen(name);
657 for (i = 0; env[i]; i++)
658 if (strncmp(env[i], name, namelen) == 0 && env[i][namelen] == '=')
659 break;
660 if (env[i]) {
661 /* Reuse the slot. */
662 xfree(env[i]);
663 } else {
664 /* New variable. Expand if necessary. */
665 if (i >= (*envsizep) - 1) {
666 (*envsizep) += 50;
667 env = (*envp) = xrealloc(env, (*envsizep) * sizeof(char *));
668 }
669 /* Need to set the NULL pointer at end of array beyond the new slot. */
670 env[i + 1] = NULL;
671 }
672
673 /* Allocate space and format the variable in the appropriate slot. */
674 env[i] = xmalloc(strlen(name) + 1 + strlen(value) + 1);
675 snprintf(env[i], strlen(name) + 1 + strlen(value) + 1, "%s=%s", name, value);
676}
677
678/*
679 * Reads environment variables from the given file and adds/overrides them
680 * into the environment. If the file does not exist, this does nothing.
681 * Otherwise, it must consist of empty lines, comments (line starts with '#')
682 * and assignments of the form name=value. No other forms are allowed.
683 */
684void
685read_environment_file(char ***env, unsigned int *envsize,
686 const char *filename)
687{
688 FILE *f;
689 char buf[4096];
690 char *cp, *value;
691
692 f = fopen(filename, "r");
693 if (!f)
694 return;
695
696 while (fgets(buf, sizeof(buf), f)) {
697 for (cp = buf; *cp == ' ' || *cp == '\t'; cp++)
698 ;
699 if (!*cp || *cp == '#' || *cp == '\n')
700 continue;
701 if (strchr(cp, '\n'))
702 *strchr(cp, '\n') = '\0';
703 value = strchr(cp, '=');
704 if (value == NULL) {
705 fprintf(stderr, "Bad line in %.100s: %.200s\n", filename, buf);
706 continue;
707 }
708 /* Replace the equals sign by nul, and advance value to the value string. */
709 *value = '\0';
710 value++;
711 child_set_env(env, envsize, cp, value);
712 }
713 fclose(f);
714}
715
716#ifdef USE_PAM
717/*
718 * Sets any environment variables which have been specified by PAM
719 */
720void do_pam_environment(char ***env, int *envsize)
721{
722 char *equals, var_name[512], var_val[512];
723 char **pam_env;
724 int i;
725
726 if ((pam_env = fetch_pam_environment()) == NULL)
727 return;
728
729 for(i = 0; pam_env[i] != NULL; i++) {
730 if ((equals = strstr(pam_env[i], "=")) == NULL)
731 continue;
732
733 if (strlen(pam_env[i]) < (sizeof(var_name) - 1)) {
734 memset(var_name, '\0', sizeof(var_name));
735 memset(var_val, '\0', sizeof(var_val));
736
737 strncpy(var_name, pam_env[i], equals - pam_env[i]);
738 strcpy(var_val, equals + 1);
739
740 debug("PAM environment: %s=%s", var_name, var_val);
741
742 child_set_env(env, envsize, var_name, var_val);
743 }
744 }
745}
746#endif /* USE_PAM */
747
748/*
749 * Performs common processing for the child, such as setting up the
750 * environment, closing extra file descriptors, setting the user and group
751 * ids, and executing the command or shell.
752 */
753void
754do_child(const char *command, struct passwd * pw, const char *term,
755 const char *display, const char *auth_proto,
756 const char *auth_data, const char *ttyname)
757{
758 const char *shell, *cp = NULL;
759 char buf[256];
760 FILE *f;
761 unsigned int envsize, i;
762 char **env;
763 extern char **environ;
764 struct stat st;
765 char *argv[10];
766
767#ifndef USE_PAM /* pam_nologin handles this */
768 f = fopen("/etc/nologin", "r");
769 if (f) {
770 /* /etc/nologin exists. Print its contents and exit. */
771 while (fgets(buf, sizeof(buf), f))
772 fputs(buf, stderr);
773 fclose(f);
774 if (pw->pw_uid != 0)
775 exit(254);
776 }
777#endif /* USE_PAM */
778
779 /* Set login name in the kernel. */
780 if (setlogin(pw->pw_name) < 0)
781 error("setlogin failed: %s", strerror(errno));
782
783 /* Set uid, gid, and groups. */
784 /* Login(1) does this as well, and it needs uid 0 for the "-h"
785 switch, so we let login(1) to this for us. */
786 if (!options.use_login) {
787 if (getuid() == 0 || geteuid() == 0) {
788 if (setgid(pw->pw_gid) < 0) {
789 perror("setgid");
790 exit(1);
791 }
792 /* Initialize the group list. */
793 if (initgroups(pw->pw_name, pw->pw_gid) < 0) {
794 perror("initgroups");
795 exit(1);
796 }
797 endgrent();
798
799 /* Permanently switch to the desired uid. */
800 permanently_set_uid(pw->pw_uid);
801 }
802 if (getuid() != pw->pw_uid || geteuid() != pw->pw_uid)
803 fatal("Failed to set uids to %d.", (int) pw->pw_uid);
804 }
805 /*
806 * Get the shell from the password data. An empty shell field is
807 * legal, and means /bin/sh.
808 */
809 shell = (pw->pw_shell[0] == '\0') ? _PATH_BSHELL : pw->pw_shell;
810
811#ifdef AFS
812 /* Try to get AFS tokens for the local cell. */
813 if (k_hasafs()) {
814 char cell[64];
815
816 if (k_afs_cell_of_file(pw->pw_dir, cell, sizeof(cell)) == 0)
817 krb_afslog(cell, 0);
818
819 krb_afslog(0, 0);
820 }
821#endif /* AFS */
822
823 /* Initialize the environment. */
824 envsize = 100;
825 env = xmalloc(envsize * sizeof(char *));
826 env[0] = NULL;
827
828 if (!options.use_login) {
829 /* Set basic environment. */
830 child_set_env(&env, &envsize, "USER", pw->pw_name);
831 child_set_env(&env, &envsize, "LOGNAME", pw->pw_name);
832 child_set_env(&env, &envsize, "HOME", pw->pw_dir);
833 child_set_env(&env, &envsize, "PATH", _PATH_STDPATH);
834
835 snprintf(buf, sizeof buf, "%.200s/%.50s",
836 _PATH_MAILDIR, pw->pw_name);
837 child_set_env(&env, &envsize, "MAIL", buf);
838
839 /* Normal systems set SHELL by default. */
840 child_set_env(&env, &envsize, "SHELL", shell);
841 }
842 if (getenv("TZ"))
843 child_set_env(&env, &envsize, "TZ", getenv("TZ"));
844
845 /* Set custom environment options from RSA authentication. */
846 while (custom_environment) {
847 struct envstring *ce = custom_environment;
848 char *s = ce->s;
849 int i;
850 for (i = 0; s[i] != '=' && s[i]; i++);
851 if (s[i] == '=') {
852 s[i] = 0;
853 child_set_env(&env, &envsize, s, s + i + 1);
854 }
855 custom_environment = ce->next;
856 xfree(ce->s);
857 xfree(ce);
858 }
859
860 snprintf(buf, sizeof buf, "%.50s %d %d",
861 get_remote_ipaddr(), get_remote_port(), get_local_port());
862 child_set_env(&env, &envsize, "SSH_CLIENT", buf);
863
864 if (ttyname)
865 child_set_env(&env, &envsize, "SSH_TTY", ttyname);
866 if (term)
867 child_set_env(&env, &envsize, "TERM", term);
868 if (display)
869 child_set_env(&env, &envsize, "DISPLAY", display);
870
871#ifdef _AIX
872 {
873 char *authstate,*krb5cc;
874
875 if ((authstate = getenv("AUTHSTATE")) != NULL)
876 child_set_env(&env,&envsize,"AUTHSTATE",authstate);
877
878 if ((krb5cc = getenv("KRB5CCNAME")) != NULL)
879 child_set_env(&env,&envsize,"KRB5CCNAME",krb5cc);
880 }
881#endif
882
883#ifdef KRB4
884 {
885 extern char *ticket;
886
887 if (ticket)
888 child_set_env(&env, &envsize, "KRBTKFILE", ticket);
889 }
890#endif /* KRB4 */
891
892#ifdef USE_PAM
893 /* Pull in any environment variables that may have been set by PAM. */
894 do_pam_environment(&env, &envsize);
895#endif /* USE_PAM */
896
897 read_environment_file(&env,&envsize,"/etc/environment");
898
899 if (xauthfile)
900 child_set_env(&env, &envsize, "XAUTHORITY", xauthfile);
901 if (auth_get_socket_name() != NULL)
902 child_set_env(&env, &envsize, SSH_AUTHSOCKET_ENV_NAME,
903 auth_get_socket_name());
904
905 /* read $HOME/.ssh/environment. */
906 if (!options.use_login) {
907 snprintf(buf, sizeof buf, "%.200s/.ssh/environment", pw->pw_dir);
908 read_environment_file(&env, &envsize, buf);
909 }
910 if (debug_flag) {
911 /* dump the environment */
912 fprintf(stderr, "Environment:\n");
913 for (i = 0; env[i]; i++)
914 fprintf(stderr, " %.200s\n", env[i]);
915 }
916 /*
917 * Close the connection descriptors; note that this is the child, and
918 * the server will still have the socket open, and it is important
919 * that we do not shutdown it. Note that the descriptors cannot be
920 * closed before building the environment, as we call
921 * get_remote_ipaddr there.
922 */
923 if (packet_get_connection_in() == packet_get_connection_out())
924 close(packet_get_connection_in());
925 else {
926 close(packet_get_connection_in());
927 close(packet_get_connection_out());
928 }
929 /*
930 * Close all descriptors related to channels. They will still remain
931 * open in the parent.
932 */
933 /* XXX better use close-on-exec? -markus */
934 channel_close_all();
935
936 /*
937 * Close any extra file descriptors. Note that there may still be
938 * descriptors left by system functions. They will be closed later.
939 */
940 endpwent();
941
942 /*
943 * Close any extra open file descriptors so that we don\'t have them
944 * hanging around in clients. Note that we want to do this after
945 * initgroups, because at least on Solaris 2.3 it leaves file
946 * descriptors open.
947 */
948 for (i = 3; i < 64; i++)
949 close(i);
950
951 /* Change current directory to the user\'s home directory. */
952 if (chdir(pw->pw_dir) < 0)
953 fprintf(stderr, "Could not chdir to home directory %s: %s\n",
954 pw->pw_dir, strerror(errno));
955
956 /*
957 * Must take new environment into use so that .ssh/rc, /etc/sshrc and
958 * xauth are run in the proper environment.
959 */
960 environ = env;
961
962 /*
963 * Run $HOME/.ssh/rc, /etc/sshrc, or xauth (whichever is found first
964 * in this order).
965 */
966 if (!options.use_login) {
967 if (stat(SSH_USER_RC, &st) >= 0) {
968 if (debug_flag)
969 fprintf(stderr, "Running /bin/sh %s\n", SSH_USER_RC);
970
971 f = popen("/bin/sh " SSH_USER_RC, "w");
972 if (f) {
973 if (auth_proto != NULL && auth_data != NULL)
974 fprintf(f, "%s %s\n", auth_proto, auth_data);
975 pclose(f);
976 } else
977 fprintf(stderr, "Could not run %s\n", SSH_USER_RC);
978 } else if (stat(SSH_SYSTEM_RC, &st) >= 0) {
979 if (debug_flag)
980 fprintf(stderr, "Running /bin/sh %s\n", SSH_SYSTEM_RC);
981
982 f = popen("/bin/sh " SSH_SYSTEM_RC, "w");
983 if (f) {
984 if (auth_proto != NULL && auth_data != NULL)
985 fprintf(f, "%s %s\n", auth_proto, auth_data);
986 pclose(f);
987 } else
988 fprintf(stderr, "Could not run %s\n", SSH_SYSTEM_RC);
989 }
990#ifdef XAUTH_PATH
991 else {
992 /* Add authority data to .Xauthority if appropriate. */
993 if (auth_proto != NULL && auth_data != NULL) {
994 if (debug_flag)
995 fprintf(stderr, "Running %.100s add %.100s %.100s %.100s\n",
996 XAUTH_PATH, display, auth_proto, auth_data);
997
998 f = popen(XAUTH_PATH " -q -", "w");
999 if (f) {
1000 fprintf(f, "add %s %s %s\n", display, auth_proto, auth_data);
1001 pclose(f);
1002 } else
1003 fprintf(stderr, "Could not run %s -q -\n", XAUTH_PATH);
1004 }
1005 }
1006#endif /* XAUTH_PATH */
1007
1008 /* Get the last component of the shell name. */
1009 cp = strrchr(shell, '/');
1010 if (cp)
1011 cp++;
1012 else
1013 cp = shell;
1014 }
1015 /*
1016 * If we have no command, execute the shell. In this case, the shell
1017 * name to be passed in argv[0] is preceded by '-' to indicate that
1018 * this is a login shell.
1019 */
1020 if (!command) {
1021 if (!options.use_login) {
1022 char buf[256];
1023
1024 /*
1025 * Check for mail if we have a tty and it was enabled
1026 * in server options.
1027 */
1028 if (ttyname && options.check_mail) {
1029 char *mailbox;
1030 struct stat mailstat;
1031 mailbox = getenv("MAIL");
1032 if (mailbox != NULL) {
1033 if (stat(mailbox, &mailstat) != 0 || mailstat.st_size == 0)
1034 printf("No mail.\n");
1035 else if (mailstat.st_mtime < mailstat.st_atime)
1036 printf("You have mail.\n");
1037 else
1038 printf("You have new mail.\n");
1039 }
1040 }
1041 /* Start the shell. Set initial character to '-'. */
1042 buf[0] = '-';
1043 strncpy(buf + 1, cp, sizeof(buf) - 1);
1044 buf[sizeof(buf) - 1] = 0;
1045
1046 /* Execute the shell. */
1047 argv[0] = buf;
1048 argv[1] = NULL;
1049 execve(shell, argv, env);
1050
1051 /* Executing the shell failed. */
1052 perror(shell);
1053 exit(1);
1054
1055 } else {
1056 /* Launch login(1). */
1057
1058 execl("/usr/bin/login", "login", "-h", get_remote_ipaddr(),
1059 "-p", "-f", "--", pw->pw_name, NULL);
1060
1061 /* Login couldn't be executed, die. */
1062
1063 perror("login");
1064 exit(1);
1065 }
1066 }
1067 /*
1068 * Execute the command using the user's shell. This uses the -c
1069 * option to execute the command.
1070 */
1071 argv[0] = (char *) cp;
1072 argv[1] = "-c";
1073 argv[2] = (char *) command;
1074 argv[3] = NULL;
1075 execve(shell, argv, env);
1076 perror(shell);
1077 exit(1);
1078}
1079
1080Session *
1081session_new(void)
1082{
1083 int i;
1084 static int did_init = 0;
1085 if (!did_init) {
1086 debug("session_new: init");
1087 for(i = 0; i < MAX_SESSIONS; i++) {
1088 sessions[i].used = 0;
1089 sessions[i].self = i;
1090 }
1091 did_init = 1;
1092 }
1093 for(i = 0; i < MAX_SESSIONS; i++) {
1094 Session *s = &sessions[i];
1095 if (! s->used) {
1096 s->pid = 0;
1097 s->chanid = -1;
1098 s->ptyfd = -1;
1099 s->ttyfd = -1;
1100 s->term = NULL;
1101 s->pw = NULL;
1102 s->display = NULL;
1103 s->screen = 0;
1104 s->auth_data = NULL;
1105 s->auth_proto = NULL;
1106 s->used = 1;
1107 debug("session_new: session %d", i);
1108 return s;
1109 }
1110 }
1111 return NULL;
1112}
1113
1114void
1115session_dump(void)
1116{
1117 int i;
1118 for(i = 0; i < MAX_SESSIONS; i++) {
1119 Session *s = &sessions[i];
1120 debug("dump: used %d session %d %p channel %d pid %d",
1121 s->used,
1122 s->self,
1123 s,
1124 s->chanid,
1125 s->pid);
1126 }
1127}
1128
1129void
1130session_pty_cleanup(Session *s)
1131{
1132 if (s == NULL || s->ttyfd == -1)
1133 return;
1134
1135 debug("session_pty_cleanup: session %i release %s", s->self, s->tty);
1136
1137 /* Cancel the cleanup function. */
1138 fatal_remove_cleanup(pty_cleanup_proc, (void *)s);
1139
1140 /* Record that the user has logged out. */
1141 record_logout(s->pid, s->tty);
1142
1143 /* Release the pseudo-tty. */
1144 pty_release(s->tty);
1145
1146 /*
1147 * Close the server side of the socket pairs. We must do this after
1148 * the pty cleanup, so that another process doesn't get this pty
1149 * while we're still cleaning up.
1150 */
1151 if (close(s->ptymaster) < 0)
1152 error("close(s->ptymaster): %s", strerror(errno));
1153}
diff --git a/session.h b/session.h
new file mode 100644
index 000000000..2051b737d
--- /dev/null
+++ b/session.h
@@ -0,0 +1,7 @@
1#ifndef SESSION_H
2#define SESSION_H
3
4/* SSH1 */
5void do_authenticated(struct passwd * pw);
6
7#endif
diff --git a/ssh.c b/ssh.c
index faba54ec1..70f9d6a68 100644
--- a/ssh.c
+++ b/ssh.c
@@ -11,7 +11,7 @@
11 */ 11 */
12 12
13#include "includes.h" 13#include "includes.h"
14RCSID("$Id: ssh.c,v 1.22 2000/03/26 03:04:54 damien Exp $"); 14RCSID("$Id: ssh.c,v 1.23 2000/04/01 01:09:26 damien Exp $");
15 15
16#include "xmalloc.h" 16#include "xmalloc.h"
17#include "ssh.h" 17#include "ssh.h"
@@ -20,6 +20,7 @@ RCSID("$Id: ssh.c,v 1.22 2000/03/26 03:04:54 damien Exp $");
20#include "authfd.h" 20#include "authfd.h"
21#include "readconf.h" 21#include "readconf.h"
22#include "uidswap.h" 22#include "uidswap.h"
23#include "channels.h"
23 24
24#ifdef HAVE___PROGNAME 25#ifdef HAVE___PROGNAME
25extern char *__progname; 26extern char *__progname;
diff --git a/ssh.h b/ssh.h
index 8bd708150..cc8940b53 100644
--- a/ssh.h
+++ b/ssh.h
@@ -13,7 +13,7 @@
13 * 13 *
14 */ 14 */
15 15
16/* RCSID("$Id: ssh.h,v 1.28 2000/03/26 03:04:54 damien Exp $"); */ 16/* RCSID("$Id: ssh.h,v 1.29 2000/04/01 01:09:26 damien Exp $"); */
17 17
18#ifndef SSH_H 18#ifndef SSH_H
19#define SSH_H 19#define SSH_H
@@ -486,175 +486,6 @@ void fatal_add_cleanup(void (*proc) (void *context), void *context);
486/* Removes a cleanup function to be called at fatal(). */ 486/* Removes a cleanup function to be called at fatal(). */
487void fatal_remove_cleanup(void (*proc) (void *context), void *context); 487void fatal_remove_cleanup(void (*proc) (void *context), void *context);
488 488
489/*---------------- definitions for channels ------------------*/
490
491/* Sets specific protocol options. */
492void channel_set_options(int hostname_in_open);
493
494/*
495 * Allocate a new channel object and set its type and socket. Remote_name
496 * must have been allocated with xmalloc; this will free it when the channel
497 * is freed.
498 */
499int channel_allocate(int type, int sock, char *remote_name);
500
501/* Free the channel and close its socket. */
502void channel_free(int channel);
503
504/* Add any bits relevant to channels in select bitmasks. */
505void channel_prepare_select(fd_set * readset, fd_set * writeset);
506
507/*
508 * After select, perform any appropriate operations for channels which have
509 * events pending.
510 */
511void channel_after_select(fd_set * readset, fd_set * writeset);
512
513/* If there is data to send to the connection, send some of it now. */
514void channel_output_poll(void);
515
516/*
517 * This is called when a packet of type CHANNEL_DATA has just been received.
518 * The message type has already been consumed, but channel number and data is
519 * still there.
520 */
521void channel_input_data(int payload_len);
522
523/* Returns true if no channel has too much buffered data. */
524int channel_not_very_much_buffered_data(void);
525
526/* This is called after receiving CHANNEL_CLOSE. */
527void channel_input_close(void);
528
529/* This is called after receiving CHANNEL_CLOSE_CONFIRMATION. */
530void channel_input_close_confirmation(void);
531
532/* This is called after receiving CHANNEL_OPEN_CONFIRMATION. */
533void channel_input_open_confirmation(void);
534
535/* This is called after receiving CHANNEL_OPEN_FAILURE from the other side. */
536void channel_input_open_failure(void);
537
538/* This closes any sockets that are listening for connections; this removes
539 any unix domain sockets. */
540void channel_stop_listening(void);
541
542/*
543 * Closes the sockets of all channels. This is used to close extra file
544 * descriptors after a fork.
545 */
546void channel_close_all(void);
547
548/* Returns the maximum file descriptor number used by the channels. */
549int channel_max_fd(void);
550
551/* Returns true if there is still an open channel over the connection. */
552int channel_still_open(void);
553
554/*
555 * Returns a string containing a list of all open channels. The list is
556 * suitable for displaying to the user. It uses crlf instead of newlines.
557 * The caller should free the string with xfree.
558 */
559char *channel_open_message(void);
560
561/*
562 * Initiate forwarding of connections to local port "port" through the secure
563 * channel to host:port from remote side. This never returns if there was an
564 * error.
565 */
566void
567channel_request_local_forwarding(u_short port, const char *host,
568 u_short remote_port, int gateway_ports);
569
570/*
571 * Initiate forwarding of connections to port "port" on remote host through
572 * the secure channel to host:port from local side. This never returns if
573 * there was an error. This registers that open requests for that port are
574 * permitted.
575 */
576void
577channel_request_remote_forwarding(u_short port, const char *host,
578 u_short remote_port);
579
580/*
581 * Permits opening to any host/port in SSH_MSG_PORT_OPEN. This is usually
582 * called by the server, because the user could connect to any port anyway,
583 * and the server has no way to know but to trust the client anyway.
584 */
585void channel_permit_all_opens(void);
586
587/*
588 * This is called after receiving CHANNEL_FORWARDING_REQUEST. This initates
589 * listening for the port, and sends back a success reply (or disconnect
590 * message if there was an error). This never returns if there was an error.
591 */
592void channel_input_port_forward_request(int is_root);
593
594/*
595 * This is called after receiving PORT_OPEN message. This attempts to
596 * connect to the given host:port, and sends back CHANNEL_OPEN_CONFIRMATION
597 * or CHANNEL_OPEN_FAILURE.
598 */
599void channel_input_port_open(int payload_len);
600
601/*
602 * Creates a port for X11 connections, and starts listening for it. Returns
603 * the display name, or NULL if an error was encountered.
604 */
605char *x11_create_display(int screen);
606
607/*
608 * Creates an internet domain socket for listening for X11 connections.
609 * Returns a suitable value for the DISPLAY variable, or NULL if an error
610 * occurs.
611 */
612char *x11_create_display_inet(int screen, int x11_display_offset);
613
614/*
615 * This is called when SSH_SMSG_X11_OPEN is received. The packet contains
616 * the remote channel number. We should do whatever we want, and respond
617 * with either SSH_MSG_OPEN_CONFIRMATION or SSH_MSG_OPEN_FAILURE.
618 */
619void x11_input_open(int payload_len);
620
621/*
622 * Requests forwarding of X11 connections. This should be called on the
623 * client only.
624 */
625void x11_request_forwarding(void);
626
627/*
628 * Requests forwarding for X11 connections, with authentication spoofing.
629 * This should be called in the client only.
630 */
631void x11_request_forwarding_with_spoofing(const char *proto, const char *data);
632
633/* Sends a message to the server to request authentication fd forwarding. */
634void auth_request_forwarding(void);
635
636/*
637 * Returns the name of the forwarded authentication socket. Returns NULL if
638 * there is no forwarded authentication socket. The returned value points to
639 * a static buffer.
640 */
641char *auth_get_socket_name(void);
642
643/*
644 * This if called to process SSH_CMSG_AGENT_REQUEST_FORWARDING on the server.
645 * This starts forwarding authentication requests.
646 */
647void auth_input_request_forwarding(struct passwd * pw);
648
649/* This is called to process an SSH_SMSG_AGENT_OPEN message. */
650void auth_input_open_request(void);
651
652/*
653 * Returns true if the given string matches the pattern (which may contain ?
654 * and * as wildcards), and zero if it does not match.
655 */
656int match_pattern(const char *s, const char *pattern);
657
658/* 489/*
659 * Expands tildes in the file name. Returns data allocated by xmalloc. 490 * Expands tildes in the file name. Returns data allocated by xmalloc.
660 * Warning: this calls getpw*. 491 * Warning: this calls getpw*.
diff --git a/ssh2.h b/ssh2.h
new file mode 100644
index 000000000..cc659f847
--- /dev/null
+++ b/ssh2.h
@@ -0,0 +1,106 @@
1/*
2 * draft-ietf-secsh-architecture-04.txt
3 *
4 * Transport layer protocol:
5 *
6 * 1-19 Transport layer generic (e.g. disconnect, ignore, debug,
7 * etc)
8 * 20-29 Algorithm negotiation
9 * 30-49 Key exchange method specific (numbers can be reused for
10 * different authentication methods)
11 *
12 * User authentication protocol:
13 *
14 * 50-59 User authentication generic
15 * 60-79 User authentication method specific (numbers can be reused
16 * for different authentication methods)
17 *
18 * Connection protocol:
19 *
20 * 80-89 Connection protocol generic
21 * 90-127 Channel related messages
22 *
23 * Reserved for client protocols:
24 *
25 * 128-191 Reserved
26 *
27 * Local extensions:
28 *
29 * 192-255 Local extensions
30 */
31
32/* transport layer: generic */
33
34#define SSH2_MSG_DISCONNECT 1
35#define SSH2_MSG_IGNORE 2
36#define SSH2_MSG_UNIMPLEMENTED 3
37#define SSH2_MSG_DEBUG 4
38#define SSH2_MSG_SERVICE_REQUEST 5
39#define SSH2_MSG_SERVICE_ACCEPT 6
40
41/* transport layer: alg negotiation */
42
43#define SSH2_MSG_KEXINIT 20
44#define SSH2_MSG_NEWKEYS 21
45
46/* transport layer: kex specific messages, can be reused */
47
48#define SSH2_MSG_KEXDH_INIT 30
49#define SSH2_MSG_KEXDH_REPLY 31
50
51/* user authentication: generic */
52
53#define SSH2_MSG_USERAUTH_REQUEST 50
54#define SSH2_MSG_USERAUTH_FAILURE 51
55#define SSH2_MSG_USERAUTH_SUCCESS 52
56#define SSH2_MSG_USERAUTH_BANNER 53
57
58/* user authentication: method specific, can be reused */
59
60#define SSH2_MSG_USERAUTH_PK_OK 60
61#define SSH2_MSG_USERAUTH_PASSWD_CHANGEREQ 60
62#define SSH2_MSG_USERAUTH_INFO_REQUEST 60
63#define SSH2_MSG_USERAUTH_INFO_RESPONSE 61
64
65/* connection protocol: generic */
66
67#define SSH2_MSG_GLOBAL_REQUEST 80
68#define SSH2_MSG_REQUEST_SUCCESS 81
69#define SSH2_MSG_REQUEST_FAILURE 82
70
71/* channel related messages */
72
73#define SSH2_MSG_CHANNEL_OPEN 90
74#define SSH2_MSG_CHANNEL_OPEN_CONFIRMATION 91
75#define SSH2_MSG_CHANNEL_OPEN_FAILURE 92
76#define SSH2_MSG_CHANNEL_WINDOW_ADJUST 93
77#define SSH2_MSG_CHANNEL_DATA 94
78#define SSH2_MSG_CHANNEL_EXTENDED_DATA 95
79#define SSH2_MSG_CHANNEL_EOF 96
80#define SSH2_MSG_CHANNEL_CLOSE 97
81#define SSH2_MSG_CHANNEL_REQUEST 98
82#define SSH2_MSG_CHANNEL_SUCCESS 99
83#define SSH2_MSG_CHANNEL_FAILURE 100
84
85/* disconnect reason code */
86
87#define SSH2_DISCONNECT_HOST_NOT_ALLOWED_TO_CONNECT 1
88#define SSH2_DISCONNECT_PROTOCOL_ERROR 2
89#define SSH2_DISCONNECT_KEY_EXCHANGE_FAILED 3
90#define SSH2_DISCONNECT_HOST_AUTHENTICATION_FAILED 4
91#define SSH2_DISCONNECT_MAC_ERROR 5
92#define SSH2_DISCONNECT_COMPRESSION_ERROR 6
93#define SSH2_DISCONNECT_SERVICE_NOT_AVAILABLE 7
94#define SSH2_DISCONNECT_PROTOCOL_VERSION_NOT_SUPPORTED 8
95#define SSH2_DISCONNECT_HOST_KEY_NOT_VERIFIABLE 9
96#define SSH2_DISCONNECT_CONNECTION_LOST 10
97#define SSH2_DISCONNECT_BY_APPLICATION 11
98
99/* misc */
100
101#define SSH2_OPEN_ADMINISTRATIVELY_PROHIBITED 1
102#define SSH2_OPEN_CONNECT_FAILED 2
103#define SSH2_OPEN_UNKNOWN_CHANNEL_TYPE 3
104#define SSH2_OPEN_RESOURCE_SHORTAGE 4
105
106#define SSH2_EXTENDED_DATA_STDERR 1
diff --git a/sshd.8 b/sshd.8
index 3c24210bd..0de3cef4a 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.15 2000/03/26 03:04:55 damien Exp $ 12.\" $Id: sshd.8,v 1.16 2000/04/01 01:09:27 damien Exp $
13.\" 13.\"
14.Dd September 25, 1999 14.Dd September 25, 1999
15.Dt SSHD 8 15.Dt SSHD 8
@@ -69,7 +69,7 @@ random number as a session key which is used to encrypt all further
69communications in the session. 69communications in the session.
70The rest of the session is encrypted 70The rest of the session is encrypted
71using a conventional cipher, currently Blowfish and 3DES, with 3DES 71using a conventional cipher, currently Blowfish and 3DES, with 3DES
72being is used by default. 72being used by default.
73The client selects the encryption algorithm 73The client selects the encryption algorithm
74to use from those offered by the server. 74to use from those offered by the server.
75.Pp 75.Pp
@@ -877,11 +877,11 @@ The libraries described in
877.Xr ssl 8 877.Xr ssl 8
878are required for proper operation. 878are required for proper operation.
879.Sh SEE ALSO 879.Sh SEE ALSO
880.Xr rlogin 1 ,
881.Xr rsh 1 ,
882.Xr scp 1 , 880.Xr scp 1 ,
883.Xr ssh 1 , 881.Xr ssh 1 ,
884.Xr ssh-add 1 , 882.Xr ssh-add 1 ,
885.Xr ssh-agent 1 , 883.Xr ssh-agent 1 ,
886.Xr ssh-keygen 1 , 884.Xr ssh-keygen 1 ,
887.Xr ssl 8 885.Xr ssl 8 ,
886.Xr rlogin 1 ,
887.Xr rsh 1
diff --git a/sshd.c b/sshd.c
index bf951212c..6ec413d6f 100644
--- a/sshd.c
+++ b/sshd.c
@@ -11,19 +11,37 @@
11 */ 11 */
12 12
13#include "includes.h" 13#include "includes.h"
14RCSID("$OpenBSD: sshd.c,v 1.94 2000/03/23 22:15:34 markus Exp $"); 14RCSID("$OpenBSD: sshd.c,v 1.96 2000/03/28 21:15:45 markus Exp $");
15 15
16#include "xmalloc.h" 16#include "xmalloc.h"
17#include "rsa.h" 17#include "rsa.h"
18#include "ssh.h" 18#include "ssh.h"
19#include "pty.h" 19#include "pty.h"
20#include "packet.h" 20#include "packet.h"
21#include "buffer.h"
22#include "cipher.h" 21#include "cipher.h"
23#include "mpaux.h" 22#include "mpaux.h"
24#include "servconf.h" 23#include "servconf.h"
25#include "uidswap.h" 24#include "uidswap.h"
26#include "compat.h" 25#include "compat.h"
26#include "buffer.h"
27
28#ifdef HAVE_OPENSSL
29# include <openssl/dh.h>
30# include <openssl/bn.h>
31# include <openssl/hmac.h>
32# include <openssl/dsa.h>
33# include <openssl/rsa.h>
34#endif
35#ifdef HAVE_SSL
36# include <ssl/dh.h>
37# include <ssl/bn.h>
38# include <ssl/hmac.h>
39# include <ssl/dsa.h>
40# include <ssl/rsa.h>
41#endif
42#include "key.h"
43
44#include "auth.h"
27 45
28#ifdef LIBWRAP 46#ifdef LIBWRAP
29#include <tcpd.h> 47#include <tcpd.h>
@@ -36,9 +54,6 @@ int deny_severity = LOG_WARNING;
36#define O_NOCTTY 0 54#define O_NOCTTY 0
37#endif 55#endif
38 56
39/* Local Xauthority file. */
40static char *xauthfile = NULL;
41
42/* Server configuration options. */ 57/* Server configuration options. */
43ServerOptions options; 58ServerOptions options;
44 59
@@ -88,21 +103,7 @@ int num_listen_socks = 0;
88 * sshd will skip the version-number exchange 103 * sshd will skip the version-number exchange
89 */ 104 */
90char *client_version_string = NULL; 105char *client_version_string = NULL;
91 106char *server_version_string = NULL;
92/* Flags set in auth-rsa from authorized_keys flags. These are set in auth-rsa.c. */
93int no_port_forwarding_flag = 0;
94int no_agent_forwarding_flag = 0;
95int no_x11_forwarding_flag = 0;
96int no_pty_flag = 0;
97
98/* RSA authentication "command=" option. */
99char *forced_command = NULL;
100
101/* RSA authentication "environment=" options. */
102struct envstring *custom_environment = NULL;
103
104/* Session id for the current session. */
105unsigned char session_id[16];
106 107
107/* 108/*
108 * Any really sensitive data in the application is contained in this 109 * Any really sensitive data in the application is contained in this
@@ -130,43 +131,11 @@ int received_sighup = 0;
130 the private key. */ 131 the private key. */
131RSA *public_key; 132RSA *public_key;
132 133
133/* Prototypes for various functions defined later in this file. */ 134/* session identifier, used by RSA-auth */
134void do_ssh_kex(); 135unsigned char session_id[16];
135void do_authentication();
136void do_authloop(struct passwd * pw);
137void do_fake_authloop(char *user);
138void do_authenticated(struct passwd * pw);
139void do_exec_pty(const char *command, int ptyfd, int ttyfd,
140 const char *ttyname, struct passwd * pw, const char *term,
141 const char *display, const char *auth_proto,
142 const char *auth_data);
143void do_exec_no_pty(const char *command, struct passwd * pw,
144 const char *display, const char *auth_proto,
145 const char *auth_data);
146void do_child(const char *command, struct passwd * pw, const char *term,
147 const char *display, const char *auth_proto,
148 const char *auth_data, const char *ttyname);
149 136
150/* 137/* Prototypes for various functions defined later in this file. */
151 * Remove local Xauthority file. 138void do_ssh1_kex();
152 */
153void
154xauthfile_cleanup_proc(void *ignore)
155{
156 debug("xauthfile_cleanup_proc called");
157
158 if (xauthfile != NULL) {
159 char *p;
160 unlink(xauthfile);
161 p = strrchr(xauthfile, '/');
162 if (p != NULL) {
163 *p = '\0';
164 rmdir(xauthfile);
165 }
166 xfree(xauthfile);
167 xauthfile = NULL;
168 }
169}
170 139
171/* 140/*
172 * Close all listening sockets 141 * Close all listening sockets
@@ -250,35 +219,6 @@ grace_alarm_handler(int sig)
250} 219}
251 220
252/* 221/*
253 * convert ssh auth msg type into description
254 */
255char *
256get_authname(int type)
257{
258 static char buf[1024];
259 switch (type) {
260 case SSH_CMSG_AUTH_PASSWORD:
261 return "password";
262 case SSH_CMSG_AUTH_RSA:
263 return "rsa";
264 case SSH_CMSG_AUTH_RHOSTS_RSA:
265 return "rhosts-rsa";
266 case SSH_CMSG_AUTH_RHOSTS:
267 return "rhosts";
268#ifdef KRB4
269 case SSH_CMSG_AUTH_KERBEROS:
270 return "kerberos";
271#endif
272#ifdef SKEY
273 case SSH_CMSG_AUTH_TIS_RESPONSE:
274 return "s/key";
275#endif
276 }
277 snprintf(buf, sizeof buf, "bad-auth-msg-%d", type);
278 return buf;
279}
280
281/*
282 * Signal handler for the key regeneration alarm. Note that this 222 * Signal handler for the key regeneration alarm. Note that this
283 * alarm only occurs in the daemon waiting for connections, and it does not 223 * alarm only occurs in the daemon waiting for connections, and it does not
284 * do anything with the private key or random state before forking. 224 * do anything with the private key or random state before forking.
@@ -315,6 +255,88 @@ key_regeneration_alarm(int sig)
315 errno = save_errno; 255 errno = save_errno;
316} 256}
317 257
258void
259sshd_exchange_identification(int sock_in, int sock_out)
260{
261 int i;
262 int remote_major, remote_minor;
263 char *s;
264 char buf[256]; /* Must not be larger than remote_version. */
265 char remote_version[256]; /* Must be at least as big as buf. */
266
267 snprintf(buf, sizeof buf, "SSH-%d.%d-%.100s\n",
268 PROTOCOL_MAJOR, PROTOCOL_MINOR, SSH_VERSION);
269 server_version_string = xstrdup(buf);
270
271 if (client_version_string == NULL) {
272 /* Send our protocol version identification. */
273 if (atomicio(write, sock_out, server_version_string, strlen(server_version_string))
274 != strlen(server_version_string)) {
275 log("Could not write ident string to %s.", get_remote_ipaddr());
276 fatal_cleanup();
277 }
278
279 /* Read other side\'s version identification. */
280 for (i = 0; i < sizeof(buf) - 1; i++) {
281 if (read(sock_in, &buf[i], 1) != 1) {
282 log("Did not receive ident string from %s.", get_remote_ipaddr());
283 fatal_cleanup();
284 }
285 if (buf[i] == '\r') {
286 buf[i] = '\n';
287 buf[i + 1] = 0;
288 continue;
289 /*break; XXX eat \r */
290 }
291 if (buf[i] == '\n') {
292 /* buf[i] == '\n' */
293 buf[i + 1] = 0;
294 break;
295 }
296 }
297 buf[sizeof(buf) - 1] = 0;
298 client_version_string = xstrdup(buf);
299 }
300
301 /*
302 * Check that the versions match. In future this might accept
303 * several versions and set appropriate flags to handle them.
304 */
305 if (sscanf(client_version_string, "SSH-%d.%d-%[^\n]\n",
306 &remote_major, &remote_minor, remote_version) != 3) {
307 s = "Protocol mismatch.\n";
308 (void) atomicio(write, sock_out, s, strlen(s));
309 close(sock_in);
310 close(sock_out);
311 log("Bad protocol version identification '%.100s' from %s",
312 client_version_string, get_remote_ipaddr());
313 fatal_cleanup();
314 }
315 debug("Client protocol version %d.%d; client software version %.100s",
316 remote_major, remote_minor, remote_version);
317
318 switch(remote_major) {
319 case 1:
320 if (remote_minor < 3) {
321 packet_disconnect("Your ssh version is too old and"
322 "is no longer supported. Please install a newer version.");
323 } else if (remote_minor == 3) {
324 /* note that this disables agent-forwarding */
325 enable_compat13();
326 }
327 break;
328 default:
329 s = "Protocol major versions differ.\n";
330 (void) atomicio(write, sock_out, s, strlen(s));
331 close(sock_in);
332 close(sock_out);
333 log("Protocol major versions differ for %s: %d vs. %d",
334 get_remote_ipaddr(), PROTOCOL_MAJOR, remote_major);
335 fatal_cleanup();
336 break;
337 }
338}
339
318/* 340/*
319 * Main program for the daemon. 341 * Main program for the daemon.
320 */ 342 */
@@ -325,12 +347,9 @@ main(int ac, char **av)
325 extern int optind; 347 extern int optind;
326 int opt, sock_in = 0, sock_out = 0, newsock, i, fdsetsz, pid, on = 1; 348 int opt, sock_in = 0, sock_out = 0, newsock, i, fdsetsz, pid, on = 1;
327 socklen_t fromlen; 349 socklen_t fromlen;
328 int remote_major, remote_minor;
329 int silentrsa = 0; 350 int silentrsa = 0;
330 fd_set *fdset; 351 fd_set *fdset;
331 struct sockaddr_storage from; 352 struct sockaddr_storage from;
332 char buf[100]; /* Must not be larger than remote_version. */
333 char remote_version[100]; /* Must be at least as big as buf. */
334 const char *remote_ip; 353 const char *remote_ip;
335 int remote_port; 354 int remote_port;
336 char *comment; 355 char *comment;
@@ -794,73 +813,7 @@ main(int ac, char **av)
794 if (!debug_flag) 813 if (!debug_flag)
795 alarm(options.login_grace_time); 814 alarm(options.login_grace_time);
796 815
797 if (client_version_string != NULL) { 816 sshd_exchange_identification(sock_in, sock_out);
798 /* we are exec'ed by sshd2, so skip exchange of protocol version */
799 strlcpy(buf, client_version_string, sizeof(buf));
800 } else {
801 /* Send our protocol version identification. */
802 snprintf(buf, sizeof buf, "SSH-%d.%d-%.100s\n",
803 PROTOCOL_MAJOR, PROTOCOL_MINOR, SSH_VERSION);
804 if (atomicio(write, sock_out, buf, strlen(buf)) != strlen(buf)) {
805 log("Could not write ident string to %s.", remote_ip);
806 fatal_cleanup();
807 }
808
809 /* Read other side\'s version identification. */
810 for (i = 0; i < sizeof(buf) - 1; i++) {
811 if (read(sock_in, &buf[i], 1) != 1) {
812 log("Did not receive ident string from %s.", remote_ip);
813 fatal_cleanup();
814 }
815 if (buf[i] == '\r') {
816 buf[i] = '\n';
817 buf[i + 1] = 0;
818 break;
819 }
820 if (buf[i] == '\n') {
821 /* buf[i] == '\n' */
822 buf[i + 1] = 0;
823 break;
824 }
825 }
826 buf[sizeof(buf) - 1] = 0;
827 }
828
829 /*
830 * Check that the versions match. In future this might accept
831 * several versions and set appropriate flags to handle them.
832 */
833 if (sscanf(buf, "SSH-%d.%d-%[^\n]\n", &remote_major, &remote_minor,
834 remote_version) != 3) {
835 char *s = "Protocol mismatch.\n";
836
837 (void) atomicio(write, sock_out, s, strlen(s));
838 close(sock_in);
839 close(sock_out);
840 log("Bad protocol version identification '%.100s' from %s",
841 buf, remote_ip);
842 fatal_cleanup();
843 }
844 debug("Client protocol version %d.%d; client software version %.100s",
845 remote_major, remote_minor, remote_version);
846 if (remote_major != PROTOCOL_MAJOR) {
847 char *s = "Protocol major versions differ.\n";
848
849 (void) atomicio(write, sock_out, s, strlen(s));
850 close(sock_in);
851 close(sock_out);
852 log("Protocol major versions differ for %s: %d vs. %d",
853 remote_ip, PROTOCOL_MAJOR, remote_major);
854 fatal_cleanup();
855 }
856 /* Check that the client has sufficiently high software version. */
857 if (remote_major == 1 && remote_minor < 3)
858 packet_disconnect("Your ssh version is too old and is no longer supported. Please install a newer version.");
859
860 if (remote_major == 1 && remote_minor == 3) {
861 /* note that this disables agent-forwarding */
862 enable_compat13();
863 }
864 /* 817 /*
865 * Check that the connection comes from a privileged port. Rhosts- 818 * Check that the connection comes from a privileged port. Rhosts-
866 * and Rhosts-RSA-Authentication only make sense from priviledged 819 * and Rhosts-RSA-Authentication only make sense from priviledged
@@ -884,8 +837,7 @@ main(int ac, char **av)
884 packet_set_nonblocking(); 837 packet_set_nonblocking();
885 838
886 /* perform the key exchange */ 839 /* perform the key exchange */
887 do_ssh_kex(); 840 do_ssh1_kex();
888
889 /* authenticate user and start session */ 841 /* authenticate user and start session */
890 do_authentication(); 842 do_authentication();
891 843
@@ -895,10 +847,6 @@ main(int ac, char **av)
895 (void) dest_tkt(); 847 (void) dest_tkt();
896#endif /* KRB4 */ 848#endif /* KRB4 */
897 849
898 /* Cleanup user's local Xauthority file. */
899 if (xauthfile)
900 xauthfile_cleanup_proc(NULL);
901
902 /* The connection has been terminated. */ 850 /* The connection has been terminated. */
903 verbose("Closing connection to %.100s", remote_ip); 851 verbose("Closing connection to %.100s", remote_ip);
904 852
@@ -914,7 +862,7 @@ main(int ac, char **av)
914 * SSH1 key exchange 862 * SSH1 key exchange
915 */ 863 */
916void 864void
917do_ssh_kex() 865do_ssh1_kex()
918{ 866{
919 int i, len; 867 int i, len;
920 int plen, slen; 868 int plen, slen;
@@ -1101,1586 +1049,3 @@ do_ssh_kex()
1101 packet_send(); 1049 packet_send();
1102 packet_write_wait(); 1050 packet_write_wait();
1103} 1051}
1104
1105
1106/*
1107 * Check if the user is allowed to log in via ssh. If user is listed in
1108 * DenyUsers or user's primary group is listed in DenyGroups, false will
1109 * be returned. If AllowUsers isn't empty and user isn't listed there, or
1110 * if AllowGroups isn't empty and user isn't listed there, false will be
1111 * returned.
1112 * If the user's shell is not executable, false will be returned.
1113 * Otherwise true is returned.
1114 */
1115static int
1116allowed_user(struct passwd * pw)
1117{
1118 struct stat st;
1119 struct group *grp;
1120 int i;
1121#ifdef WITH_AIXAUTHENTICATE
1122 char *loginmsg;
1123#endif /* WITH_AIXAUTHENTICATE */
1124
1125 /* Shouldn't be called if pw is NULL, but better safe than sorry... */
1126 if (!pw)
1127 return 0;
1128
1129 /* deny if shell does not exists or is not executable */
1130 if (stat(pw->pw_shell, &st) != 0)
1131 return 0;
1132 if (!((st.st_mode & S_IFREG) && (st.st_mode & (S_IXOTH|S_IXUSR|S_IXGRP))))
1133 return 0;
1134
1135 /* Return false if user is listed in DenyUsers */
1136 if (options.num_deny_users > 0) {
1137 if (!pw->pw_name)
1138 return 0;
1139 for (i = 0; i < options.num_deny_users; i++)
1140 if (match_pattern(pw->pw_name, options.deny_users[i]))
1141 return 0;
1142 }
1143 /* Return false if AllowUsers isn't empty and user isn't listed there */
1144 if (options.num_allow_users > 0) {
1145 if (!pw->pw_name)
1146 return 0;
1147 for (i = 0; i < options.num_allow_users; i++)
1148 if (match_pattern(pw->pw_name, options.allow_users[i]))
1149 break;
1150 /* i < options.num_allow_users iff we break for loop */
1151 if (i >= options.num_allow_users)
1152 return 0;
1153 }
1154 /* Get the primary group name if we need it. Return false if it fails */
1155 if (options.num_deny_groups > 0 || options.num_allow_groups > 0) {
1156 grp = getgrgid(pw->pw_gid);
1157 if (!grp)
1158 return 0;
1159
1160 /* Return false if user's group is listed in DenyGroups */
1161 if (options.num_deny_groups > 0) {
1162 if (!grp->gr_name)
1163 return 0;
1164 for (i = 0; i < options.num_deny_groups; i++)
1165 if (match_pattern(grp->gr_name, options.deny_groups[i]))
1166 return 0;
1167 }
1168 /*
1169 * Return false if AllowGroups isn't empty and user's group
1170 * isn't listed there
1171 */
1172 if (options.num_allow_groups > 0) {
1173 if (!grp->gr_name)
1174 return 0;
1175 for (i = 0; i < options.num_allow_groups; i++)
1176 if (match_pattern(grp->gr_name, options.allow_groups[i]))
1177 break;
1178 /* i < options.num_allow_groups iff we break for
1179 loop */
1180 if (i >= options.num_allow_groups)
1181 return 0;
1182 }
1183 }
1184
1185#ifdef WITH_AIXAUTHENTICATE
1186 if (loginrestrictions(pw->pw_name,S_LOGIN,NULL,&loginmsg) != 0)
1187 return 0;
1188#endif /* WITH_AIXAUTHENTICATE */
1189
1190 /* We found no reason not to let this user try to log on... */
1191 return 1;
1192}
1193
1194/*
1195 * Performs authentication of an incoming connection. Session key has already
1196 * been exchanged and encryption is enabled.
1197 */
1198void
1199do_authentication()
1200{
1201 struct passwd *pw, pwcopy;
1202 int plen;
1203 unsigned int ulen;
1204 char *user;
1205
1206 /* Get the name of the user that we wish to log in as. */
1207 packet_read_expect(&plen, SSH_CMSG_USER);
1208
1209 /* Get the user name. */
1210 user = packet_get_string(&ulen);
1211 packet_integrity_check(plen, (4 + ulen), SSH_CMSG_USER);
1212
1213 setproctitle("%s", user);
1214
1215#ifdef WITH_AIXAUTHENTICATE
1216 char *loginmsg;
1217#endif /* WITH_AIXAUTHENTICATE */
1218
1219#ifdef AFS
1220 /* If machine has AFS, set process authentication group. */
1221 if (k_hasafs()) {
1222 k_setpag();
1223 k_unlog();
1224 }
1225#endif /* AFS */
1226
1227 /* Verify that the user is a valid user. */
1228 pw = getpwnam(user);
1229 if (!pw || !allowed_user(pw))
1230 do_fake_authloop(user);
1231 xfree(user);
1232
1233 /* Take a copy of the returned structure. */
1234 memset(&pwcopy, 0, sizeof(pwcopy));
1235 pwcopy.pw_name = xstrdup(pw->pw_name);
1236 pwcopy.pw_passwd = xstrdup(pw->pw_passwd);
1237 pwcopy.pw_uid = pw->pw_uid;
1238 pwcopy.pw_gid = pw->pw_gid;
1239 pwcopy.pw_dir = xstrdup(pw->pw_dir);
1240 pwcopy.pw_shell = xstrdup(pw->pw_shell);
1241 pw = &pwcopy;
1242
1243#ifdef USE_PAM
1244 start_pam(pw);
1245#endif
1246
1247 /*
1248 * If we are not running as root, the user must have the same uid as
1249 * the server.
1250 */
1251 if (getuid() != 0 && pw->pw_uid != getuid())
1252 packet_disconnect("Cannot change user when server not running as root.");
1253
1254 debug("Attempting authentication for %.100s.", pw->pw_name);
1255
1256 /* If the user has no password, accept authentication immediately. */
1257 if (options.password_authentication &&
1258#ifdef KRB4
1259 (!options.kerberos_authentication || options.kerberos_or_local_passwd) &&
1260#endif /* KRB4 */
1261#ifdef USE_PAM
1262 auth_pam_password(pw, "")) {
1263#else /* USE_PAM */
1264 auth_password(pw, "")) {
1265#endif /* USE_PAM */
1266 /* Authentication with empty password succeeded. */
1267 log("Login for user %s from %.100s, accepted without authentication.",
1268 pw->pw_name, get_remote_ipaddr());
1269 } else {
1270 /* Loop until the user has been authenticated or the
1271 connection is closed, do_authloop() returns only if
1272 authentication is successfull */
1273 do_authloop(pw);
1274 }
1275
1276 /* The user has been authenticated and accepted. */
1277#ifdef WITH_AIXAUTHENTICATE
1278 loginsuccess(user,get_canonical_hostname(),"ssh",&loginmsg);
1279#endif /* WITH_AIXAUTHENTICATE */
1280 packet_start(SSH_SMSG_SUCCESS);
1281 packet_send();
1282 packet_write_wait();
1283
1284 /* Perform session preparation. */
1285 do_authenticated(pw);
1286}
1287
1288#define AUTH_FAIL_MAX 6
1289#define AUTH_FAIL_LOG (AUTH_FAIL_MAX/2)
1290#define AUTH_FAIL_MSG "Too many authentication failures for %.100s"
1291
1292/*
1293 * read packets and try to authenticate local user *pw.
1294 * return if authentication is successfull
1295 */
1296void
1297do_authloop(struct passwd * pw)
1298{
1299 int attempt = 0;
1300 unsigned int bits;
1301 RSA *client_host_key;
1302 BIGNUM *n;
1303 char *client_user = NULL, *password = NULL;
1304 char user[1024];
1305 unsigned int dlen;
1306 int plen, nlen, elen;
1307 unsigned int ulen;
1308 int type = 0;
1309 void (*authlog) (const char *fmt,...) = verbose;
1310
1311 /* Indicate that authentication is needed. */
1312 packet_start(SSH_SMSG_FAILURE);
1313 packet_send();
1314 packet_write_wait();
1315
1316 for (attempt = 1;; attempt++) {
1317 int authenticated = 0;
1318 strlcpy(user, "", sizeof user);
1319
1320 /* Get a packet from the client. */
1321 type = packet_read(&plen);
1322
1323 /* Process the packet. */
1324 switch (type) {
1325#ifdef AFS
1326 case SSH_CMSG_HAVE_KERBEROS_TGT:
1327 if (!options.kerberos_tgt_passing) {
1328 /* packet_get_all(); */
1329 verbose("Kerberos tgt passing disabled.");
1330 break;
1331 } else {
1332 /* Accept Kerberos tgt. */
1333 char *tgt = packet_get_string(&dlen);
1334 packet_integrity_check(plen, 4 + dlen, type);
1335 if (!auth_kerberos_tgt(pw, tgt))
1336 verbose("Kerberos tgt REFUSED for %s", pw->pw_name);
1337 xfree(tgt);
1338 }
1339 continue;
1340
1341 case SSH_CMSG_HAVE_AFS_TOKEN:
1342 if (!options.afs_token_passing || !k_hasafs()) {
1343 /* packet_get_all(); */
1344 verbose("AFS token passing disabled.");
1345 break;
1346 } else {
1347 /* Accept AFS token. */
1348 char *token_string = packet_get_string(&dlen);
1349 packet_integrity_check(plen, 4 + dlen, type);
1350 if (!auth_afs_token(pw, token_string))
1351 verbose("AFS token REFUSED for %s", pw->pw_name);
1352 xfree(token_string);
1353 }
1354 continue;
1355#endif /* AFS */
1356#ifdef KRB4
1357 case SSH_CMSG_AUTH_KERBEROS:
1358 if (!options.kerberos_authentication) {
1359 /* packet_get_all(); */
1360 verbose("Kerberos authentication disabled.");
1361 break;
1362 } else {
1363 /* Try Kerberos v4 authentication. */
1364 KTEXT_ST auth;
1365 char *tkt_user = NULL;
1366 char *kdata = packet_get_string((unsigned int *) &auth.length);
1367 packet_integrity_check(plen, 4 + auth.length, type);
1368
1369 if (auth.length < MAX_KTXT_LEN)
1370 memcpy(auth.dat, kdata, auth.length);
1371 xfree(kdata);
1372
1373 authenticated = auth_krb4(pw->pw_name, &auth, &tkt_user);
1374
1375 if (authenticated) {
1376 snprintf(user, sizeof user, " tktuser %s", tkt_user);
1377 xfree(tkt_user);
1378 }
1379 }
1380 break;
1381#endif /* KRB4 */
1382
1383 case SSH_CMSG_AUTH_RHOSTS:
1384 if (!options.rhosts_authentication) {
1385 verbose("Rhosts authentication disabled.");
1386 break;
1387 }
1388 /*
1389 * Get client user name. Note that we just have to
1390 * trust the client; this is one reason why rhosts
1391 * authentication is insecure. (Another is
1392 * IP-spoofing on a local network.)
1393 */
1394 client_user = packet_get_string(&ulen);
1395 packet_integrity_check(plen, 4 + ulen, type);
1396
1397 /* Try to authenticate using /etc/hosts.equiv and
1398 .rhosts. */
1399 authenticated = auth_rhosts(pw, client_user);
1400
1401 snprintf(user, sizeof user, " ruser %s", client_user);
1402 break;
1403
1404 case SSH_CMSG_AUTH_RHOSTS_RSA:
1405 if (!options.rhosts_rsa_authentication) {
1406 verbose("Rhosts with RSA authentication disabled.");
1407 break;
1408 }
1409 /*
1410 * Get client user name. Note that we just have to
1411 * trust the client; root on the client machine can
1412 * claim to be any user.
1413 */
1414 client_user = packet_get_string(&ulen);
1415
1416 /* Get the client host key. */
1417 client_host_key = RSA_new();
1418 if (client_host_key == NULL)
1419 fatal("RSA_new failed");
1420 client_host_key->e = BN_new();
1421 client_host_key->n = BN_new();
1422 if (client_host_key->e == NULL || client_host_key->n == NULL)
1423 fatal("BN_new failed");
1424 bits = packet_get_int();
1425 packet_get_bignum(client_host_key->e, &elen);
1426 packet_get_bignum(client_host_key->n, &nlen);
1427
1428 if (bits != BN_num_bits(client_host_key->n))
1429 error("Warning: keysize mismatch for client_host_key: "
1430 "actual %d, announced %d", BN_num_bits(client_host_key->n), bits);
1431 packet_integrity_check(plen, (4 + ulen) + 4 + elen + nlen, type);
1432
1433 authenticated = auth_rhosts_rsa(pw, client_user, client_host_key);
1434 RSA_free(client_host_key);
1435
1436 snprintf(user, sizeof user, " ruser %s", client_user);
1437 break;
1438
1439 case SSH_CMSG_AUTH_RSA:
1440 if (!options.rsa_authentication) {
1441 verbose("RSA authentication disabled.");
1442 break;
1443 }
1444 /* RSA authentication requested. */
1445 n = BN_new();
1446 packet_get_bignum(n, &nlen);
1447 packet_integrity_check(plen, nlen, type);
1448 authenticated = auth_rsa(pw, n);
1449 BN_clear_free(n);
1450 break;
1451
1452 case SSH_CMSG_AUTH_PASSWORD:
1453 if (!options.password_authentication) {
1454 verbose("Password authentication disabled.");
1455 break;
1456 }
1457 /*
1458 * Read user password. It is in plain text, but was
1459 * transmitted over the encrypted channel so it is
1460 * not visible to an outside observer.
1461 */
1462 password = packet_get_string(&dlen);
1463 packet_integrity_check(plen, 4 + dlen, type);
1464
1465#ifdef USE_PAM
1466 /* Do PAM auth with password */
1467 authenticated = auth_pam_password(pw, password);
1468#else /* USE_PAM */
1469 /* Try authentication with the password. */
1470 authenticated = auth_password(pw, password);
1471#endif /* USE_PAM */
1472 memset(password, 0, strlen(password));
1473 xfree(password);
1474 break;
1475
1476#ifdef SKEY
1477 case SSH_CMSG_AUTH_TIS:
1478 debug("rcvd SSH_CMSG_AUTH_TIS");
1479 if (options.skey_authentication == 1) {
1480 char *skeyinfo = skey_keyinfo(pw->pw_name);
1481 if (skeyinfo == NULL) {
1482 debug("generating fake skeyinfo for %.100s.", pw->pw_name);
1483 skeyinfo = skey_fake_keyinfo(pw->pw_name);
1484 }
1485 if (skeyinfo != NULL) {
1486 /* we send our s/key- in tis-challenge messages */
1487 debug("sending challenge '%s'", skeyinfo);
1488 packet_start(SSH_SMSG_AUTH_TIS_CHALLENGE);
1489 packet_put_string(skeyinfo, strlen(skeyinfo));
1490 packet_send();
1491 packet_write_wait();
1492 continue;
1493 }
1494 }
1495 break;
1496 case SSH_CMSG_AUTH_TIS_RESPONSE:
1497 debug("rcvd SSH_CMSG_AUTH_TIS_RESPONSE");
1498 if (options.skey_authentication == 1) {
1499 char *response = packet_get_string(&dlen);
1500 debug("skey response == '%s'", response);
1501 packet_integrity_check(plen, 4 + dlen, type);
1502 authenticated = (skey_haskey(pw->pw_name) == 0 &&
1503 skey_passcheck(pw->pw_name, response) != -1);
1504 xfree(response);
1505 }
1506 break;
1507#else
1508 case SSH_CMSG_AUTH_TIS:
1509 /* TIS Authentication is unsupported */
1510 log("TIS authentication unsupported.");
1511 break;
1512#endif
1513
1514 default:
1515 /*
1516 * Any unknown messages will be ignored (and failure
1517 * returned) during authentication.
1518 */
1519 log("Unknown message during authentication: type %d", type);
1520 break;
1521 }
1522
1523 /*
1524 * Check if the user is logging in as root and root logins
1525 * are disallowed.
1526 * Note that root login is allowed for forced commands.
1527 */
1528 if (authenticated && pw->pw_uid == 0 && !options.permit_root_login) {
1529 if (forced_command) {
1530 log("Root login accepted for forced command.");
1531 } else {
1532 authenticated = 0;
1533 log("ROOT LOGIN REFUSED FROM %.200s",
1534 get_canonical_hostname());
1535 }
1536 }
1537
1538 /* Raise logging level */
1539 if (authenticated ||
1540 attempt == AUTH_FAIL_LOG ||
1541 type == SSH_CMSG_AUTH_PASSWORD)
1542 authlog = log;
1543
1544 authlog("%s %s for %.200s from %.200s port %d%s",
1545 authenticated ? "Accepted" : "Failed",
1546 get_authname(type),
1547 pw->pw_uid == 0 ? "ROOT" : pw->pw_name,
1548 get_remote_ipaddr(),
1549 get_remote_port(),
1550 user);
1551
1552#ifdef USE_PAM
1553 if (authenticated) {
1554 if (!do_pam_account(pw->pw_name, client_user)) {
1555 if (client_user != NULL) {
1556 xfree(client_user);
1557 client_user = NULL;
1558 }
1559 do_fake_authloop(pw->pw_name);
1560 }
1561 return;
1562 }
1563#else /* USE_PAM */
1564 if (authenticated) {
1565 return;
1566 }
1567#endif /* USE_PAM */
1568
1569 if (client_user != NULL) {
1570 xfree(client_user);
1571 client_user = NULL;
1572 }
1573
1574 if (attempt > AUTH_FAIL_MAX)
1575 packet_disconnect(AUTH_FAIL_MSG, pw->pw_name);
1576
1577 /* Send a message indicating that the authentication attempt failed. */
1578 packet_start(SSH_SMSG_FAILURE);
1579 packet_send();
1580 packet_write_wait();
1581 }
1582}
1583
1584/*
1585 * The user does not exist or access is denied,
1586 * but fake indication that authentication is needed.
1587 */
1588void
1589do_fake_authloop(char *user)
1590{
1591 int attempt = 0;
1592
1593 log("Faking authloop for illegal user %.200s from %.200s port %d",
1594 user,
1595 get_remote_ipaddr(),
1596 get_remote_port());
1597
1598 /* Indicate that authentication is needed. */
1599 packet_start(SSH_SMSG_FAILURE);
1600 packet_send();
1601 packet_write_wait();
1602
1603 /*
1604 * Keep reading packets, and always respond with a failure. This is
1605 * to avoid disclosing whether such a user really exists.
1606 */
1607 for (attempt = 1;; attempt++) {
1608 /* Read a packet. This will not return if the client disconnects. */
1609 int plen;
1610#ifndef SKEY
1611 (void)packet_read(&plen);
1612#else /* SKEY */
1613 int type = packet_read(&plen);
1614 unsigned int dlen;
1615 char *password, *skeyinfo;
1616 /* Try to send a fake s/key challenge. */
1617 if (options.skey_authentication == 1 &&
1618 (skeyinfo = skey_fake_keyinfo(user)) != NULL) {
1619 password = NULL;
1620 if (type == SSH_CMSG_AUTH_TIS) {
1621 packet_start(SSH_SMSG_AUTH_TIS_CHALLENGE);
1622 packet_put_string(skeyinfo, strlen(skeyinfo));
1623 packet_send();
1624 packet_write_wait();
1625 continue;
1626 } else if (type == SSH_CMSG_AUTH_PASSWORD &&
1627 options.password_authentication &&
1628 (password = packet_get_string(&dlen)) != NULL &&
1629 dlen == 5 &&
1630 strncasecmp(password, "s/key", 5) == 0 ) {
1631 packet_send_debug(skeyinfo);
1632 }
1633 if (password != NULL)
1634 xfree(password);
1635 }
1636#endif
1637 if (attempt > AUTH_FAIL_MAX)
1638 packet_disconnect(AUTH_FAIL_MSG, user);
1639
1640 /*
1641 * Send failure. This should be indistinguishable from a
1642 * failed authentication.
1643 */
1644 packet_start(SSH_SMSG_FAILURE);
1645 packet_send();
1646 packet_write_wait();
1647#ifdef WITH_AIXAUTHENTICATE
1648 if (strncmp(get_authname(type),"password",
1649 strlen(get_authname(type))) == 0)
1650 loginfailed(pw->pw_name,get_canonical_hostname(),"ssh");
1651#endif /* WITH_AIXAUTHENTICATE */
1652 }
1653 /* NOTREACHED */
1654 abort();
1655}
1656
1657struct pty_cleanup_context {
1658 const char *ttyname;
1659 int pid;
1660};
1661
1662/*
1663 * Function to perform cleanup if we get aborted abnormally (e.g., due to a
1664 * dropped connection).
1665 */
1666void
1667pty_cleanup_proc(void *context)
1668{
1669 struct pty_cleanup_context *cu = context;
1670
1671 debug("pty_cleanup_proc called");
1672
1673 /* Record that the user has logged out. */
1674 record_logout(cu->pid, cu->ttyname);
1675
1676 /* Release the pseudo-tty. */
1677 pty_release(cu->ttyname);
1678}
1679
1680/* simple cleanup: chown tty slave back to root */
1681static void
1682pty_release_proc(void *tty)
1683{
1684 char *ttyname = tty;
1685 pty_release(ttyname);
1686}
1687
1688/*
1689 * Prepares for an interactive session. This is called after the user has
1690 * been successfully authenticated. During this message exchange, pseudo
1691 * terminals are allocated, X11, TCP/IP, and authentication agent forwardings
1692 * are requested, etc.
1693 */
1694void
1695do_authenticated(struct passwd * pw)
1696{
1697 int type;
1698 int compression_level = 0, enable_compression_after_reply = 0;
1699 int have_pty = 0, ptyfd = -1, ttyfd = -1;
1700 int row, col, xpixel, ypixel, screen;
1701 char ttyname[64];
1702 char *command, *term = NULL, *display = NULL, *proto = NULL, *data = NULL;
1703 int plen;
1704 unsigned int dlen;
1705 int n_bytes;
1706
1707 /*
1708 * Cancel the alarm we set to limit the time taken for
1709 * authentication.
1710 */
1711 alarm(0);
1712
1713 /*
1714 * Inform the channel mechanism that we are the server side and that
1715 * the client may request to connect to any port at all. (The user
1716 * could do it anyway, and we wouldn\'t know what is permitted except
1717 * by the client telling us, so we can equally well trust the client
1718 * not to request anything bogus.)
1719 */
1720 if (!no_port_forwarding_flag)
1721 channel_permit_all_opens();
1722
1723 /*
1724 * We stay in this loop until the client requests to execute a shell
1725 * or a command.
1726 */
1727 while (1) {
1728
1729 /* Get a packet from the client. */
1730 type = packet_read(&plen);
1731
1732 /* Process the packet. */
1733 switch (type) {
1734 case SSH_CMSG_REQUEST_COMPRESSION:
1735 packet_integrity_check(plen, 4, type);
1736 compression_level = packet_get_int();
1737 if (compression_level < 1 || compression_level > 9) {
1738 packet_send_debug("Received illegal compression level %d.",
1739 compression_level);
1740 goto fail;
1741 }
1742 /* Enable compression after we have responded with SUCCESS. */
1743 enable_compression_after_reply = 1;
1744 break;
1745
1746 case SSH_CMSG_REQUEST_PTY:
1747 if (no_pty_flag) {
1748 debug("Allocating a pty not permitted for this authentication.");
1749 goto fail;
1750 }
1751 if (have_pty)
1752 packet_disconnect("Protocol error: you already have a pty.");
1753
1754 debug("Allocating pty.");
1755
1756 /* Allocate a pty and open it. */
1757 if (!pty_allocate(&ptyfd, &ttyfd, ttyname,
1758 sizeof(ttyname))) {
1759 error("Failed to allocate pty.");
1760 goto fail;
1761 }
1762 fatal_add_cleanup(pty_release_proc, (void *)ttyname);
1763 pty_setowner(pw, ttyname);
1764
1765 /* Get TERM from the packet. Note that the value may be of arbitrary length. */
1766 term = packet_get_string(&dlen);
1767 packet_integrity_check(dlen, strlen(term), type);
1768
1769 /* Remaining bytes */
1770 n_bytes = plen - (4 + dlen + 4 * 4);
1771
1772 if (strcmp(term, "") == 0) {
1773 xfree(term);
1774 term = NULL;
1775 }
1776
1777 /* Get window size from the packet. */
1778 row = packet_get_int();
1779 col = packet_get_int();
1780 xpixel = packet_get_int();
1781 ypixel = packet_get_int();
1782 pty_change_window_size(ptyfd, row, col, xpixel, ypixel);
1783
1784 /* Get tty modes from the packet. */
1785 tty_parse_modes(ttyfd, &n_bytes);
1786 packet_integrity_check(plen, 4 + dlen + 4 * 4 + n_bytes, type);
1787
1788 /* Indicate that we now have a pty. */
1789 have_pty = 1;
1790 break;
1791
1792 case SSH_CMSG_X11_REQUEST_FORWARDING:
1793 if (!options.x11_forwarding) {
1794 packet_send_debug("X11 forwarding disabled in server configuration file.");
1795 goto fail;
1796 }
1797#ifdef XAUTH_PATH
1798 if (no_x11_forwarding_flag) {
1799 packet_send_debug("X11 forwarding not permitted for this authentication.");
1800 goto fail;
1801 }
1802 debug("Received request for X11 forwarding with auth spoofing.");
1803 if (display)
1804 packet_disconnect("Protocol error: X11 display already set.");
1805 {
1806 unsigned int proto_len, data_len;
1807 proto = packet_get_string(&proto_len);
1808 data = packet_get_string(&data_len);
1809 packet_integrity_check(plen, 4 + proto_len + 4 + data_len + 4, type);
1810 }
1811 if (packet_get_protocol_flags() & SSH_PROTOFLAG_SCREEN_NUMBER)
1812 screen = packet_get_int();
1813 else
1814 screen = 0;
1815 display = x11_create_display_inet(screen, options.x11_display_offset);
1816 if (!display)
1817 goto fail;
1818
1819 /* Setup to always have a local .Xauthority. */
1820 xauthfile = xmalloc(MAXPATHLEN);
1821 strlcpy(xauthfile, "/tmp/ssh-XXXXXXXX", MAXPATHLEN);
1822 temporarily_use_uid(pw->pw_uid);
1823 if (mkdtemp(xauthfile) == NULL) {
1824 restore_uid();
1825 error("private X11 dir: mkdtemp %s failed: %s",
1826 xauthfile, strerror(errno));
1827 xfree(xauthfile);
1828 xauthfile = NULL;
1829 goto fail;
1830 }
1831 strlcat(xauthfile, "/cookies", MAXPATHLEN);
1832 open(xauthfile, O_RDWR|O_CREAT|O_EXCL, 0600);
1833 restore_uid();
1834 fatal_add_cleanup(xauthfile_cleanup_proc, NULL);
1835 break;
1836#else /* XAUTH_PATH */
1837 packet_send_debug("No xauth program; cannot forward with spoofing.");
1838 goto fail;
1839#endif /* XAUTH_PATH */
1840
1841 case SSH_CMSG_AGENT_REQUEST_FORWARDING:
1842 if (no_agent_forwarding_flag || compat13) {
1843 debug("Authentication agent forwarding not permitted for this authentication.");
1844 goto fail;
1845 }
1846 debug("Received authentication agent forwarding request.");
1847 auth_input_request_forwarding(pw);
1848 break;
1849
1850 case SSH_CMSG_PORT_FORWARD_REQUEST:
1851 if (no_port_forwarding_flag) {
1852 debug("Port forwarding not permitted for this authentication.");
1853 goto fail;
1854 }
1855 debug("Received TCP/IP port forwarding request.");
1856 channel_input_port_forward_request(pw->pw_uid == 0);
1857 break;
1858
1859 case SSH_CMSG_MAX_PACKET_SIZE:
1860 if (packet_set_maxsize(packet_get_int()) < 0)
1861 goto fail;
1862 break;
1863
1864 case SSH_CMSG_EXEC_SHELL:
1865 /* Set interactive/non-interactive mode. */
1866 packet_set_interactive(have_pty || display != NULL,
1867 options.keepalives);
1868
1869 if (forced_command != NULL)
1870 goto do_forced_command;
1871 debug("Forking shell.");
1872 packet_integrity_check(plen, 0, type);
1873 if (have_pty)
1874 do_exec_pty(NULL, ptyfd, ttyfd, ttyname, pw, term, display, proto, data);
1875 else
1876 do_exec_no_pty(NULL, pw, display, proto, data);
1877 return;
1878
1879 case SSH_CMSG_EXEC_CMD:
1880 /* Set interactive/non-interactive mode. */
1881 packet_set_interactive(have_pty || display != NULL,
1882 options.keepalives);
1883
1884 if (forced_command != NULL)
1885 goto do_forced_command;
1886 /* Get command from the packet. */
1887 {
1888 unsigned int dlen;
1889 command = packet_get_string(&dlen);
1890 debug("Executing command '%.500s'", command);
1891 packet_integrity_check(plen, 4 + dlen, type);
1892 }
1893 if (have_pty)
1894 do_exec_pty(command, ptyfd, ttyfd, ttyname, pw, term, display, proto, data);
1895 else
1896 do_exec_no_pty(command, pw, display, proto, data);
1897 xfree(command);
1898 return;
1899
1900 default:
1901 /*
1902 * Any unknown messages in this phase are ignored,
1903 * and a failure message is returned.
1904 */
1905 log("Unknown packet type received after authentication: %d", type);
1906 goto fail;
1907 }
1908
1909 /* The request was successfully processed. */
1910 packet_start(SSH_SMSG_SUCCESS);
1911 packet_send();
1912 packet_write_wait();
1913
1914 /* Enable compression now that we have replied if appropriate. */
1915 if (enable_compression_after_reply) {
1916 enable_compression_after_reply = 0;
1917 packet_start_compression(compression_level);
1918 }
1919 continue;
1920
1921fail:
1922 /* The request failed. */
1923 packet_start(SSH_SMSG_FAILURE);
1924 packet_send();
1925 packet_write_wait();
1926 continue;
1927
1928do_forced_command:
1929 /*
1930 * There is a forced command specified for this login.
1931 * Execute it.
1932 */
1933 debug("Executing forced command: %.900s", forced_command);
1934 if (have_pty)
1935 do_exec_pty(forced_command, ptyfd, ttyfd, ttyname, pw, term, display, proto, data);
1936 else
1937 do_exec_no_pty(forced_command, pw, display, proto, data);
1938 return;
1939 }
1940}
1941
1942/*
1943 * This is called to fork and execute a command when we have no tty. This
1944 * will call do_child from the child, and server_loop from the parent after
1945 * setting up file descriptors and such.
1946 */
1947void
1948do_exec_no_pty(const char *command, struct passwd * pw,
1949 const char *display, const char *auth_proto,
1950 const char *auth_data)
1951{
1952 int pid;
1953
1954#ifdef USE_PIPES
1955 int pin[2], pout[2], perr[2];
1956 /* Allocate pipes for communicating with the program. */
1957 if (pipe(pin) < 0 || pipe(pout) < 0 || pipe(perr) < 0)
1958 packet_disconnect("Could not create pipes: %.100s",
1959 strerror(errno));
1960#else /* USE_PIPES */
1961 int inout[2], err[2];
1962 /* Uses socket pairs to communicate with the program. */
1963 if (socketpair(AF_UNIX, SOCK_STREAM, 0, inout) < 0 ||
1964 socketpair(AF_UNIX, SOCK_STREAM, 0, err) < 0)
1965 packet_disconnect("Could not create socket pairs: %.100s",
1966 strerror(errno));
1967#endif /* USE_PIPES */
1968
1969 setproctitle("%s@notty", pw->pw_name);
1970
1971#ifdef USE_PAM
1972 do_pam_setcred();
1973#endif /* USE_PAM */
1974
1975 /* Fork the child. */
1976 if ((pid = fork()) == 0) {
1977 /* Child. Reinitialize the log since the pid has changed. */
1978 log_init(av0, options.log_level, options.log_facility, log_stderr);
1979
1980 /*
1981 * Create a new session and process group since the 4.4BSD
1982 * setlogin() affects the entire process group.
1983 */
1984 if (setsid() < 0)
1985 error("setsid failed: %.100s", strerror(errno));
1986
1987#ifdef USE_PIPES
1988 /*
1989 * Redirect stdin. We close the parent side of the socket
1990 * pair, and make the child side the standard input.
1991 */
1992 close(pin[1]);
1993 if (dup2(pin[0], 0) < 0)
1994 perror("dup2 stdin");
1995 close(pin[0]);
1996
1997 /* Redirect stdout. */
1998 close(pout[0]);
1999 if (dup2(pout[1], 1) < 0)
2000 perror("dup2 stdout");
2001 close(pout[1]);
2002
2003 /* Redirect stderr. */
2004 close(perr[0]);
2005 if (dup2(perr[1], 2) < 0)
2006 perror("dup2 stderr");
2007 close(perr[1]);
2008#else /* USE_PIPES */
2009 /*
2010 * Redirect stdin, stdout, and stderr. Stdin and stdout will
2011 * use the same socket, as some programs (particularly rdist)
2012 * seem to depend on it.
2013 */
2014 close(inout[1]);
2015 close(err[1]);
2016 if (dup2(inout[0], 0) < 0) /* stdin */
2017 perror("dup2 stdin");
2018 if (dup2(inout[0], 1) < 0) /* stdout. Note: same socket as stdin. */
2019 perror("dup2 stdout");
2020 if (dup2(err[0], 2) < 0) /* stderr */
2021 perror("dup2 stderr");
2022#endif /* USE_PIPES */
2023
2024 /* Do processing for the child (exec command etc). */
2025 do_child(command, pw, NULL, display, auth_proto, auth_data, NULL);
2026 /* NOTREACHED */
2027 }
2028 if (pid < 0)
2029 packet_disconnect("fork failed: %.100s", strerror(errno));
2030#ifdef USE_PIPES
2031 /* We are the parent. Close the child sides of the pipes. */
2032 close(pin[0]);
2033 close(pout[1]);
2034 close(perr[1]);
2035
2036 /* Enter the interactive session. */
2037 server_loop(pid, pin[1], pout[0], perr[0]);
2038 /* server_loop has closed pin[1], pout[1], and perr[1]. */
2039#else /* USE_PIPES */
2040 /* We are the parent. Close the child sides of the socket pairs. */
2041 close(inout[0]);
2042 close(err[0]);
2043
2044 /*
2045 * Enter the interactive session. Note: server_loop must be able to
2046 * handle the case that fdin and fdout are the same.
2047 */
2048 server_loop(pid, inout[1], inout[1], err[1]);
2049 /* server_loop has closed inout[1] and err[1]. */
2050#endif /* USE_PIPES */
2051}
2052
2053/*
2054 * This is called to fork and execute a command when we have a tty. This
2055 * will call do_child from the child, and server_loop from the parent after
2056 * setting up file descriptors, controlling tty, updating wtmp, utmp,
2057 * lastlog, and other such operations.
2058 */
2059void
2060do_exec_pty(const char *command, int ptyfd, int ttyfd,
2061 const char *ttyname, struct passwd * pw, const char *term,
2062 const char *display, const char *auth_proto,
2063 const char *auth_data)
2064{
2065 int pid, fdout;
2066 int ptymaster;
2067 const char *hostname;
2068 time_t last_login_time;
2069 char buf[100], *time_string;
2070 FILE *f;
2071 char line[256];
2072 struct stat st;
2073 int quiet_login;
2074 struct sockaddr_storage from;
2075 socklen_t fromlen;
2076 struct pty_cleanup_context cleanup_context;
2077
2078 /* Get remote host name. */
2079 hostname = get_canonical_hostname();
2080
2081 /*
2082 * Get the time when the user last logged in. Buf will be set to
2083 * contain the hostname the last login was from.
2084 */
2085 if (!options.use_login) {
2086 last_login_time = get_last_login_time(pw->pw_uid, pw->pw_name,
2087 buf, sizeof(buf));
2088 }
2089 setproctitle("%s@%s", pw->pw_name, strrchr(ttyname, '/') + 1);
2090
2091#ifdef USE_PAM
2092 do_pam_session(pw->pw_name, ttyname);
2093 do_pam_setcred();
2094#endif /* USE_PAM */
2095
2096 /* Fork the child. */
2097 if ((pid = fork()) == 0) {
2098 pid = getpid();
2099
2100 /* Child. Reinitialize the log because the pid has
2101 changed. */
2102 log_init(av0, options.log_level, options.log_facility, log_stderr);
2103
2104 /* Close the master side of the pseudo tty. */
2105 close(ptyfd);
2106
2107 /* Make the pseudo tty our controlling tty. */
2108 pty_make_controlling_tty(&ttyfd, ttyname);
2109
2110 /* Redirect stdin from the pseudo tty. */
2111 if (dup2(ttyfd, fileno(stdin)) < 0)
2112 error("dup2 stdin failed: %.100s", strerror(errno));
2113
2114 /* Redirect stdout to the pseudo tty. */
2115 if (dup2(ttyfd, fileno(stdout)) < 0)
2116 error("dup2 stdin failed: %.100s", strerror(errno));
2117
2118 /* Redirect stderr to the pseudo tty. */
2119 if (dup2(ttyfd, fileno(stderr)) < 0)
2120 error("dup2 stdin failed: %.100s", strerror(errno));
2121
2122 /* Close the extra descriptor for the pseudo tty. */
2123 close(ttyfd);
2124
2125 /*
2126 * Get IP address of client. This is needed because we want
2127 * to record where the user logged in from. If the
2128 * connection is not a socket, let the ip address be 0.0.0.0.
2129 */
2130 memset(&from, 0, sizeof(from));
2131 if (packet_get_connection_in() == packet_get_connection_out()) {
2132 fromlen = sizeof(from);
2133 if (getpeername(packet_get_connection_in(),
2134 (struct sockaddr *) & from, &fromlen) < 0) {
2135 debug("getpeername: %.100s", strerror(errno));
2136 fatal_cleanup();
2137 }
2138 }
2139 /* Record that there was a login on that terminal. */
2140 record_login(pid, ttyname, pw->pw_name, pw->pw_uid, hostname,
2141 (struct sockaddr *)&from);
2142
2143 /* Check if .hushlogin exists. */
2144 snprintf(line, sizeof line, "%.200s/.hushlogin", pw->pw_dir);
2145 quiet_login = stat(line, &st) >= 0;
2146
2147#ifdef USE_PAM
2148 if (!quiet_login)
2149 print_pam_messages();
2150#endif /* USE_PAM */
2151
2152 /*
2153 * If the user has logged in before, display the time of last
2154 * login. However, don't display anything extra if a command
2155 * has been specified (so that ssh can be used to execute
2156 * commands on a remote machine without users knowing they
2157 * are going to another machine). Login(1) will do this for
2158 * us as well, so check if login(1) is used
2159 */
2160 if (command == NULL && last_login_time != 0 && !quiet_login &&
2161 !options.use_login) {
2162 /* Convert the date to a string. */
2163 time_string = ctime(&last_login_time);
2164 /* Remove the trailing newline. */
2165 if (strchr(time_string, '\n'))
2166 *strchr(time_string, '\n') = 0;
2167 /* Display the last login time. Host if displayed
2168 if known. */
2169 if (strcmp(buf, "") == 0)
2170 printf("Last login: %s\r\n", time_string);
2171 else
2172 printf("Last login: %s from %s\r\n", time_string, buf);
2173 }
2174 /*
2175 * Print /etc/motd unless a command was specified or printing
2176 * it was disabled in server options or login(1) will be
2177 * used. Note that some machines appear to print it in
2178 * /etc/profile or similar.
2179 */
2180 if (command == NULL && options.print_motd && !quiet_login &&
2181 !options.use_login) {
2182 /* Print /etc/motd if it exists. */
2183 f = fopen("/etc/motd", "r");
2184 if (f) {
2185 while (fgets(line, sizeof(line), f))
2186 fputs(line, stdout);
2187 fclose(f);
2188 }
2189 }
2190 /* Do common processing for the child, such as execing the command. */
2191 do_child(command, pw, term, display, auth_proto, auth_data, ttyname);
2192 /* NOTREACHED */
2193 }
2194 if (pid < 0)
2195 packet_disconnect("fork failed: %.100s", strerror(errno));
2196 /* Parent. Close the slave side of the pseudo tty. */
2197 close(ttyfd);
2198
2199 /*
2200 * Add a cleanup function to clear the utmp entry and record logout
2201 * time in case we call fatal() (e.g., the connection gets closed).
2202 */
2203 cleanup_context.pid = pid;
2204 cleanup_context.ttyname = ttyname;
2205 fatal_add_cleanup(pty_cleanup_proc, (void *) &cleanup_context);
2206 fatal_remove_cleanup(pty_release_proc, (void *) ttyname);
2207
2208 /*
2209 * Create another descriptor of the pty master side for use as the
2210 * standard input. We could use the original descriptor, but this
2211 * simplifies code in server_loop. The descriptor is bidirectional.
2212 */
2213 fdout = dup(ptyfd);
2214 if (fdout < 0)
2215 packet_disconnect("dup #1 failed: %.100s", strerror(errno));
2216
2217 /* we keep a reference to the pty master */
2218 ptymaster = dup(ptyfd);
2219 if (ptymaster < 0)
2220 packet_disconnect("dup #2 failed: %.100s", strerror(errno));
2221
2222 /* Enter interactive session. */
2223 server_loop(pid, ptyfd, fdout, -1);
2224 /* server_loop _has_ closed ptyfd and fdout. */
2225
2226 /* Cancel the cleanup function. */
2227 fatal_remove_cleanup(pty_cleanup_proc, (void *) &cleanup_context);
2228
2229 /* Record that the user has logged out. */
2230 record_logout(pid, ttyname);
2231
2232 /* Release the pseudo-tty. */
2233 pty_release(ttyname);
2234
2235 /*
2236 * Close the server side of the socket pairs. We must do this after
2237 * the pty cleanup, so that another process doesn't get this pty
2238 * while we're still cleaning up.
2239 */
2240 if (close(ptymaster) < 0)
2241 error("close(ptymaster): %s", strerror(errno));
2242}
2243
2244/*
2245 * Sets the value of the given variable in the environment. If the variable
2246 * already exists, its value is overriden.
2247 */
2248void
2249child_set_env(char ***envp, unsigned int *envsizep, const char *name,
2250 const char *value)
2251{
2252 unsigned int i, namelen;
2253 char **env;
2254
2255 /*
2256 * Find the slot where the value should be stored. If the variable
2257 * already exists, we reuse the slot; otherwise we append a new slot
2258 * at the end of the array, expanding if necessary.
2259 */
2260 env = *envp;
2261 namelen = strlen(name);
2262 for (i = 0; env[i]; i++)
2263 if (strncmp(env[i], name, namelen) == 0 && env[i][namelen] == '=')
2264 break;
2265 if (env[i]) {
2266 /* Reuse the slot. */
2267 xfree(env[i]);
2268 } else {
2269 /* New variable. Expand if necessary. */
2270 if (i >= (*envsizep) - 1) {
2271 (*envsizep) += 50;
2272 env = (*envp) = xrealloc(env, (*envsizep) * sizeof(char *));
2273 }
2274 /* Need to set the NULL pointer at end of array beyond the new slot. */
2275 env[i + 1] = NULL;
2276 }
2277
2278 /* Allocate space and format the variable in the appropriate slot. */
2279 env[i] = xmalloc(strlen(name) + 1 + strlen(value) + 1);
2280 snprintf(env[i], strlen(name) + 1 + strlen(value) + 1, "%s=%s", name, value);
2281}
2282
2283/*
2284 * Reads environment variables from the given file and adds/overrides them
2285 * into the environment. If the file does not exist, this does nothing.
2286 * Otherwise, it must consist of empty lines, comments (line starts with '#')
2287 * and assignments of the form name=value. No other forms are allowed.
2288 */
2289void
2290read_environment_file(char ***env, unsigned int *envsize,
2291 const char *filename)
2292{
2293 FILE *f;
2294 char buf[4096];
2295 char *cp, *value;
2296
2297 f = fopen(filename, "r");
2298 if (!f)
2299 return;
2300
2301 while (fgets(buf, sizeof(buf), f)) {
2302 for (cp = buf; *cp == ' ' || *cp == '\t'; cp++)
2303 ;
2304 if (!*cp || *cp == '#' || *cp == '\n')
2305 continue;
2306 if (strchr(cp, '\n'))
2307 *strchr(cp, '\n') = '\0';
2308 value = strchr(cp, '=');
2309 if (value == NULL) {
2310 fprintf(stderr, "Bad line in %.100s: %.200s\n", filename, buf);
2311 continue;
2312 }
2313 /* Replace the equals sign by nul, and advance value to the value string. */
2314 *value = '\0';
2315 value++;
2316 child_set_env(env, envsize, cp, value);
2317 }
2318 fclose(f);
2319}
2320
2321#ifdef USE_PAM
2322/*
2323 * Sets any environment variables which have been specified by PAM
2324 */
2325void do_pam_environment(char ***env, int *envsize)
2326{
2327 char *equals, var_name[512], var_val[512];
2328 char **pam_env;
2329 int i;
2330
2331 if ((pam_env = fetch_pam_environment()) == NULL)
2332 return;
2333
2334 for(i = 0; pam_env[i] != NULL; i++) {
2335 if ((equals = strstr(pam_env[i], "=")) == NULL)
2336 continue;
2337
2338 if (strlen(pam_env[i]) < (sizeof(var_name) - 1))
2339 {
2340 memset(var_name, '\0', sizeof(var_name));
2341 memset(var_val, '\0', sizeof(var_val));
2342
2343 strncpy(var_name, pam_env[i], equals - pam_env[i]);
2344 strcpy(var_val, equals + 1);
2345
2346 debug("PAM environment: %s=%s", var_name, var_val);
2347
2348 child_set_env(env, envsize, var_name, var_val);
2349 }
2350 }
2351}
2352#endif /* USE_PAM */
2353
2354/*
2355 * Performs common processing for the child, such as setting up the
2356 * environment, closing extra file descriptors, setting the user and group
2357 * ids, and executing the command or shell.
2358 */
2359void
2360do_child(const char *command, struct passwd * pw, const char *term,
2361 const char *display, const char *auth_proto,
2362 const char *auth_data, const char *ttyname)
2363{
2364 const char *shell, *cp = NULL;
2365 char buf[256];
2366 FILE *f;
2367 unsigned int envsize, i;
2368 char **env;
2369 extern char **environ;
2370 struct stat st;
2371 char *argv[10];
2372
2373#ifndef USE_PAM /* pam_nologin handles this */
2374 /* Check /etc/nologin. */
2375 f = fopen("/etc/nologin", "r");
2376 if (f) {
2377 /* /etc/nologin exists. Print its contents and exit. */
2378 while (fgets(buf, sizeof(buf), f))
2379 fputs(buf, stderr);
2380 fclose(f);
2381 if (pw->pw_uid != 0)
2382 exit(254);
2383 }
2384#endif /* USE_PAM */
2385
2386 /* Set login name in the kernel. */
2387 if (setlogin(pw->pw_name) < 0)
2388 error("setlogin failed: %s", strerror(errno));
2389
2390 /* Set uid, gid, and groups. */
2391 /* Login(1) does this as well, and it needs uid 0 for the "-h"
2392 switch, so we let login(1) to this for us. */
2393 if (!options.use_login) {
2394 if (getuid() == 0 || geteuid() == 0) {
2395 if (setgid(pw->pw_gid) < 0) {
2396 perror("setgid");
2397 exit(1);
2398 }
2399 /* Initialize the group list. */
2400 if (initgroups(pw->pw_name, pw->pw_gid) < 0) {
2401 perror("initgroups");
2402 exit(1);
2403 }
2404 endgrent();
2405
2406 /* Permanently switch to the desired uid. */
2407 permanently_set_uid(pw->pw_uid);
2408 }
2409 if (getuid() != pw->pw_uid || geteuid() != pw->pw_uid)
2410 fatal("Failed to set uids to %d.", (int) pw->pw_uid);
2411 }
2412 /*
2413 * Get the shell from the password data. An empty shell field is
2414 * legal, and means /bin/sh.
2415 */
2416 shell = (pw->pw_shell[0] == '\0') ? _PATH_BSHELL : pw->pw_shell;
2417
2418#ifdef AFS
2419 /* Try to get AFS tokens for the local cell. */
2420 if (k_hasafs()) {
2421 char cell[64];
2422
2423 if (k_afs_cell_of_file(pw->pw_dir, cell, sizeof(cell)) == 0)
2424 krb_afslog(cell, 0);
2425
2426 krb_afslog(0, 0);
2427 }
2428#endif /* AFS */
2429
2430 /* Initialize the environment. */
2431 envsize = 100;
2432 env = xmalloc(envsize * sizeof(char *));
2433 env[0] = NULL;
2434
2435 if (!options.use_login) {
2436 /* Set basic environment. */
2437 child_set_env(&env, &envsize, "USER", pw->pw_name);
2438 child_set_env(&env, &envsize, "LOGNAME", pw->pw_name);
2439 child_set_env(&env, &envsize, "HOME", pw->pw_dir);
2440 child_set_env(&env, &envsize, "PATH", _PATH_STDPATH);
2441
2442 snprintf(buf, sizeof buf, "%.200s/%.50s",
2443 _PATH_MAILDIR, pw->pw_name);
2444 child_set_env(&env, &envsize, "MAIL", buf);
2445
2446 /* Normal systems set SHELL by default. */
2447 child_set_env(&env, &envsize, "SHELL", shell);
2448 }
2449 if (getenv("TZ"))
2450 child_set_env(&env, &envsize, "TZ", getenv("TZ"));
2451
2452 /* Set custom environment options from RSA authentication. */
2453 while (custom_environment) {
2454 struct envstring *ce = custom_environment;
2455 char *s = ce->s;
2456 int i;
2457 for (i = 0; s[i] != '=' && s[i]; i++);
2458 if (s[i] == '=') {
2459 s[i] = 0;
2460 child_set_env(&env, &envsize, s, s + i + 1);
2461 }
2462 custom_environment = ce->next;
2463 xfree(ce->s);
2464 xfree(ce);
2465 }
2466
2467 snprintf(buf, sizeof buf, "%.50s %d %d",
2468 get_remote_ipaddr(), get_remote_port(), get_local_port());
2469 child_set_env(&env, &envsize, "SSH_CLIENT", buf);
2470
2471 if (ttyname)
2472 child_set_env(&env, &envsize, "SSH_TTY", ttyname);
2473 if (term)
2474 child_set_env(&env, &envsize, "TERM", term);
2475 if (display)
2476 child_set_env(&env, &envsize, "DISPLAY", display);
2477
2478#ifdef _AIX
2479 {
2480 char *authstate,*krb5cc;
2481
2482 if ((authstate = getenv("AUTHSTATE")) != NULL)
2483 child_set_env(&env,&envsize,"AUTHSTATE",authstate);
2484
2485 if ((krb5cc = getenv("KRB5CCNAME")) != NULL)
2486 child_set_env(&env,&envsize,"KRB5CCNAME",krb5cc);
2487 }
2488#endif
2489
2490#ifdef KRB4
2491 {
2492 extern char *ticket;
2493
2494 if (ticket)
2495 child_set_env(&env, &envsize, "KRBTKFILE", ticket);
2496 }
2497#endif /* KRB4 */
2498
2499#ifdef USE_PAM
2500 /* Pull in any environment variables that may have been set by PAM. */
2501 do_pam_environment(&env, &envsize);
2502#endif /* USE_PAM */
2503
2504 if (xauthfile)
2505 child_set_env(&env, &envsize, "XAUTHORITY", xauthfile);
2506
2507 if (auth_get_socket_name() != NULL)
2508 child_set_env(&env, &envsize, SSH_AUTHSOCKET_ENV_NAME,
2509 auth_get_socket_name());
2510
2511 read_environment_file(&env,&envsize,"/etc/environment");
2512
2513 /* read $HOME/.ssh/environment. */
2514 if (!options.use_login) {
2515 snprintf(buf, sizeof buf, "%.200s/.ssh/environment", pw->pw_dir);
2516 read_environment_file(&env, &envsize, buf);
2517 }
2518 if (debug_flag) {
2519 /* dump the environment */
2520 fprintf(stderr, "Environment:\n");
2521 for (i = 0; env[i]; i++)
2522 fprintf(stderr, " %.200s\n", env[i]);
2523 }
2524 /*
2525 * Close the connection descriptors; note that this is the child, and
2526 * the server will still have the socket open, and it is important
2527 * that we do not shutdown it. Note that the descriptors cannot be
2528 * closed before building the environment, as we call
2529 * get_remote_ipaddr there.
2530 */
2531 if (packet_get_connection_in() == packet_get_connection_out())
2532 close(packet_get_connection_in());
2533 else {
2534 close(packet_get_connection_in());
2535 close(packet_get_connection_out());
2536 }
2537 /*
2538 * Close all descriptors related to channels. They will still remain
2539 * open in the parent.
2540 */
2541 /* XXX better use close-on-exec? -markus */
2542 channel_close_all();
2543
2544 /*
2545 * Close any extra file descriptors. Note that there may still be
2546 * descriptors left by system functions. They will be closed later.
2547 */
2548 endpwent();
2549
2550 /*
2551 * Close any extra open file descriptors so that we don\'t have them
2552 * hanging around in clients. Note that we want to do this after
2553 * initgroups, because at least on Solaris 2.3 it leaves file
2554 * descriptors open.
2555 */
2556 for (i = 3; i < 64; i++)
2557 close(i);
2558
2559 /* Change current directory to the user\'s home directory. */
2560 if (chdir(pw->pw_dir) < 0)
2561 fprintf(stderr, "Could not chdir to home directory %s: %s\n",
2562 pw->pw_dir, strerror(errno));
2563
2564 /*
2565 * Must take new environment into use so that .ssh/rc, /etc/sshrc and
2566 * xauth are run in the proper environment.
2567 */
2568 environ = env;
2569
2570 /*
2571 * Run $HOME/.ssh/rc, /etc/sshrc, or xauth (whichever is found first
2572 * in this order).
2573 */
2574 if (!options.use_login) {
2575 if (stat(SSH_USER_RC, &st) >= 0) {
2576 if (debug_flag)
2577 fprintf(stderr, "Running /bin/sh %s\n", SSH_USER_RC);
2578
2579 f = popen("/bin/sh " SSH_USER_RC, "w");
2580 if (f) {
2581 if (auth_proto != NULL && auth_data != NULL)
2582 fprintf(f, "%s %s\n", auth_proto, auth_data);
2583 pclose(f);
2584 } else
2585 fprintf(stderr, "Could not run %s\n", SSH_USER_RC);
2586 } else if (stat(SSH_SYSTEM_RC, &st) >= 0) {
2587 if (debug_flag)
2588 fprintf(stderr, "Running /bin/sh %s\n", SSH_SYSTEM_RC);
2589
2590 f = popen("/bin/sh " SSH_SYSTEM_RC, "w");
2591 if (f) {
2592 if (auth_proto != NULL && auth_data != NULL)
2593 fprintf(f, "%s %s\n", auth_proto, auth_data);
2594 pclose(f);
2595 } else
2596 fprintf(stderr, "Could not run %s\n", SSH_SYSTEM_RC);
2597 }
2598#ifdef XAUTH_PATH
2599 else {
2600 /* Add authority data to .Xauthority if appropriate. */
2601 if (auth_proto != NULL && auth_data != NULL) {
2602 if (debug_flag)
2603 fprintf(stderr, "Running %.100s add %.100s %.100s %.100s\n",
2604 XAUTH_PATH, display, auth_proto, auth_data);
2605
2606 f = popen(XAUTH_PATH " -q -", "w");
2607 if (f) {
2608 fprintf(f, "add %s %s %s\n", display, auth_proto, auth_data);
2609 pclose(f);
2610 } else
2611 fprintf(stderr, "Could not run %s -q -\n", XAUTH_PATH);
2612 }
2613 }
2614#endif /* XAUTH_PATH */
2615
2616 /* Get the last component of the shell name. */
2617 cp = strrchr(shell, '/');
2618 if (cp)
2619 cp++;
2620 else
2621 cp = shell;
2622 }
2623 /*
2624 * If we have no command, execute the shell. In this case, the shell
2625 * name to be passed in argv[0] is preceded by '-' to indicate that
2626 * this is a login shell.
2627 */
2628 if (!command) {
2629 if (!options.use_login) {
2630 char buf[256];
2631
2632 /*
2633 * Check for mail if we have a tty and it was enabled
2634 * in server options.
2635 */
2636 if (ttyname && options.check_mail) {
2637 char *mailbox;
2638 struct stat mailstat;
2639 mailbox = getenv("MAIL");
2640 if (mailbox != NULL) {
2641 if (stat(mailbox, &mailstat) != 0 || mailstat.st_size == 0)
2642 printf("No mail.\n");
2643 else if (mailstat.st_mtime < mailstat.st_atime)
2644 printf("You have mail.\n");
2645 else
2646 printf("You have new mail.\n");
2647 }
2648 }
2649 /* Start the shell. Set initial character to '-'. */
2650 buf[0] = '-';
2651 strncpy(buf + 1, cp, sizeof(buf) - 1);
2652 buf[sizeof(buf) - 1] = 0;
2653
2654 /* Execute the shell. */
2655 argv[0] = buf;
2656 argv[1] = NULL;
2657 execve(shell, argv, env);
2658
2659 /* Executing the shell failed. */
2660 perror(shell);
2661 exit(1);
2662
2663 } else {
2664 /* Launch login(1). */
2665
2666 execl(LOGIN_PROGRAM, "login", "-h", get_remote_ipaddr(),
2667 "-p", "-f", "--", pw->pw_name, NULL);
2668
2669 /* Login couldn't be executed, die. */
2670
2671 perror("login");
2672 exit(1);
2673 }
2674 }
2675 /*
2676 * Execute the command using the user's shell. This uses the -c
2677 * option to execute the command.
2678 */
2679 argv[0] = (char *) cp;
2680 argv[1] = "-c";
2681 argv[2] = (char *) command;
2682 argv[3] = NULL;
2683 execve(shell, argv, env);
2684 perror(shell);
2685 exit(1);
2686}