]> andersk Git - gssapi-openssh.git/blame - openssh/session.c
http://www.psc.edu/networking/projects/hpn-ssh/openssh-4.5p1-hpn12v14.diff.gz
[gssapi-openssh.git] / openssh / session.c
CommitLineData
ff7ec503 1/* $OpenBSD: session.c,v 1.220 2006/10/09 23:36:11 djm Exp $ */
3c0ef626 2/*
3 * Copyright (c) 1995 Tatu Ylonen <ylo@cs.hut.fi>, Espoo, Finland
4 * All rights reserved
5 *
6 * As far as I am concerned, the code I have written for this software
7 * can be used freely for any purpose. Any derived versions of this
8 * software must be clearly marked as such, and if the derived work is
9 * incompatible with the protocol description in the RFC file, it must be
10 * called by a name other than "ssh" or "Secure Shell".
11 *
12 * SSH2 support by Markus Friedl.
13 * Copyright (c) 2000, 2001 Markus Friedl. All rights reserved.
14 *
15 * Redistribution and use in source and binary forms, with or without
16 * modification, are permitted provided that the following conditions
17 * are met:
18 * 1. Redistributions of source code must retain the above copyright
19 * notice, this list of conditions and the following disclaimer.
20 * 2. Redistributions in binary form must reproduce the above copyright
21 * notice, this list of conditions and the following disclaimer in the
22 * documentation and/or other materials provided with the distribution.
23 *
24 * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
25 * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
26 * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
27 * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
28 * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
29 * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
30 * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
31 * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
32 * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
33 * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
34 */
35
36#include "includes.h"
3c0ef626 37
9108f8d9 38#include <sys/types.h>
39#include <sys/param.h>
40#ifdef HAVE_SYS_STAT_H
41# include <sys/stat.h>
42#endif
43#include <sys/socket.h>
44#include <sys/un.h>
45#include <sys/wait.h>
46
47#include <arpa/inet.h>
48
49#include <errno.h>
50#include <grp.h>
51#ifdef HAVE_PATHS_H
52#include <paths.h>
53#endif
54#include <pwd.h>
55#include <signal.h>
56#include <stdarg.h>
57#include <stdio.h>
58#include <stdlib.h>
59#include <string.h>
60#include <unistd.h>
61
62#include "xmalloc.h"
3c0ef626 63#include "ssh.h"
64#include "ssh1.h"
65#include "ssh2.h"
3c0ef626 66#include "sshpty.h"
67#include "packet.h"
68#include "buffer.h"
c9f39d2c 69#include "match.h"
3c0ef626 70#include "uidswap.h"
71#include "compat.h"
72#include "channels.h"
9108f8d9 73#include "key.h"
74#include "cipher.h"
75#ifdef GSSAPI
76#include "ssh-gss.h"
77#endif
78#include "hostfile.h"
3c0ef626 79#include "auth.h"
80#include "auth-options.h"
81#include "pathnames.h"
82#include "log.h"
83#include "servconf.h"
84#include "sshlogin.h"
85#include "serverloop.h"
86#include "canohost.h"
87#include "session.h"
665a873d 88#include "kex.h"
700318f3 89#include "monitor_wrap.h"
3c0ef626 90
cdd66111 91#if defined(KRB5) && defined(USE_AFS)
92#include <kafs.h>
93#endif
94
3c0ef626 95/* func */
96
97Session *session_new(void);
98void session_set_fds(Session *, int, int, int);
cdd66111 99void session_pty_cleanup(Session *);
3c0ef626 100void session_proctitle(Session *);
101int session_setup_x11fwd(Session *);
102void do_exec_pty(Session *, const char *);
103void do_exec_no_pty(Session *, const char *);
104void do_exec(Session *, const char *);
105void do_login(Session *, const char *);
106#ifdef LOGIN_NEEDS_UTMPX
107static void do_pre_login(Session *s);
108#endif
109void do_child(Session *, const char *);
110void do_motd(void);
111int check_quietlogin(Session *, const char *);
112
113static void do_authenticated1(Authctxt *);
114static void do_authenticated2(Authctxt *);
115
3c0ef626 116static int session_pty_req(Session *);
117
118/* import */
119extern ServerOptions options;
120extern char *__progname;
121extern int log_stderr;
122extern int debug_flag;
123extern u_int utmp_len;
124extern int startup_pipe;
125extern void destroy_sensitive_data(void);
0fff78ff 126extern Buffer loginmsg;
3c0ef626 127
128/* original command from peer. */
129const char *original_command = NULL;
130
131/* data */
132#define MAX_SESSIONS 10
133Session sessions[MAX_SESSIONS];
134
3c0ef626 135#ifdef HAVE_LOGIN_CAP
700318f3 136login_cap_t *lc;
3c0ef626 137#endif
138
cdd66111 139static int is_child = 0;
140
f5799ae1 141/* Name and directory of socket for authentication agent forwarding. */
142static char *auth_sock_name = NULL;
143static char *auth_sock_dir = NULL;
144
145/* removes the agent forwarding socket */
146
147static void
cdd66111 148auth_sock_cleanup_proc(struct passwd *pw)
f5799ae1 149{
f5799ae1 150 if (auth_sock_name != NULL) {
151 temporarily_use_uid(pw);
152 unlink(auth_sock_name);
153 rmdir(auth_sock_dir);
154 auth_sock_name = NULL;
155 restore_uid();
156 }
157}
158
159static int
160auth_input_request_forwarding(struct passwd * pw)
161{
162 Channel *nc;
163 int sock;
164 struct sockaddr_un sunaddr;
165
166 if (auth_sock_name != NULL) {
167 error("authentication forwarding requested twice.");
168 return 0;
169 }
170
171 /* Temporarily drop privileged uid for mkdir/bind. */
172 temporarily_use_uid(pw);
173
174 /* Allocate a buffer for the socket name, and format the name. */
175 auth_sock_name = xmalloc(MAXPATHLEN);
176 auth_sock_dir = xmalloc(MAXPATHLEN);
cdd66111 177 strlcpy(auth_sock_dir, "/tmp/ssh-XXXXXXXXXX", MAXPATHLEN);
f5799ae1 178
179 /* Create private directory for socket */
180 if (mkdtemp(auth_sock_dir) == NULL) {
181 packet_send_debug("Agent forwarding disabled: "
182 "mkdtemp() failed: %.100s", strerror(errno));
183 restore_uid();
184 xfree(auth_sock_name);
185 xfree(auth_sock_dir);
186 auth_sock_name = NULL;
187 auth_sock_dir = NULL;
188 return 0;
189 }
190 snprintf(auth_sock_name, MAXPATHLEN, "%s/agent.%ld",
191 auth_sock_dir, (long) getpid());
192
f5799ae1 193 /* Create the socket. */
194 sock = socket(AF_UNIX, SOCK_STREAM, 0);
195 if (sock < 0)
196 packet_disconnect("socket: %.100s", strerror(errno));
197
198 /* Bind it to the name. */
199 memset(&sunaddr, 0, sizeof(sunaddr));
200 sunaddr.sun_family = AF_UNIX;
201 strlcpy(sunaddr.sun_path, auth_sock_name, sizeof(sunaddr.sun_path));
202
9108f8d9 203 if (bind(sock, (struct sockaddr *)&sunaddr, sizeof(sunaddr)) < 0)
f5799ae1 204 packet_disconnect("bind: %.100s", strerror(errno));
205
206 /* Restore the privileged uid. */
207 restore_uid();
208
209 /* Start listening on the socket. */
cdd66111 210 if (listen(sock, SSH_LISTEN_BACKLOG) < 0)
f5799ae1 211 packet_disconnect("listen: %.100s", strerror(errno));
212
213 /* Allocate a channel for the authentication agent socket. */
d6f3ca1e 214 /* this shouldn't matter if its hpn or not - cjr */
f5799ae1 215 nc = channel_new("auth socket",
216 SSH_CHANNEL_AUTH_SOCKET, sock, sock, -1,
217 CHAN_X11_WINDOW_DEFAULT, CHAN_X11_PACKET_DEFAULT,
0fff78ff 218 0, "auth socket", 1);
f5799ae1 219 strlcpy(nc->path, auth_sock_name, sizeof(nc->path));
220 return 1;
221}
222
cdd66111 223static void
224display_loginmsg(void)
225{
665a873d 226 if (buffer_len(&loginmsg) > 0) {
227 buffer_append(&loginmsg, "\0", 1);
228 printf("%s", (char *)buffer_ptr(&loginmsg));
229 buffer_clear(&loginmsg);
230 }
cdd66111 231}
f5799ae1 232
3c0ef626 233void
234do_authenticated(Authctxt *authctxt)
235{
6a9b3198 236 setproctitle("%s", authctxt->pw->pw_name);
237
3c0ef626 238 /* setup the channel layer */
239 if (!no_port_forwarding_flag && options.allow_tcp_forwarding)
240 channel_permit_all_opens();
241
242 if (compat20)
243 do_authenticated2(authctxt);
244 else
245 do_authenticated1(authctxt);
246
cdd66111 247 do_cleanup(authctxt);
3c0ef626 248}
249
250/*
251 * Prepares for an interactive session. This is called after the user has
252 * been successfully authenticated. During this message exchange, pseudo
253 * terminals are allocated, X11, TCP/IP, and authentication agent forwardings
254 * are requested, etc.
255 */
256static void
257do_authenticated1(Authctxt *authctxt)
258{
259 Session *s;
260 char *command;
e9a17296 261 int success, type, screen_flag;
680cee3b 262 int enable_compression_after_reply = 0;
263 u_int proto_len, data_len, dlen, compression_level = 0;
3c0ef626 264
265 s = session_new();
996d5e62 266 if (s == NULL) {
267 error("no more sessions");
268 return;
269 }
3c0ef626 270 s->authctxt = authctxt;
271 s->pw = authctxt->pw;
272
273 /*
274 * We stay in this loop until the client requests to execute a shell
275 * or a command.
276 */
277 for (;;) {
278 success = 0;
279
280 /* Get a packet from the client. */
e9a17296 281 type = packet_read();
3c0ef626 282
283 /* Process the packet. */
284 switch (type) {
285 case SSH_CMSG_REQUEST_COMPRESSION:
3c0ef626 286 compression_level = packet_get_int();
e9a17296 287 packet_check_eom();
3c0ef626 288 if (compression_level < 1 || compression_level > 9) {
c9f39d2c 289 packet_send_debug("Received invalid compression level %d.",
e9a17296 290 compression_level);
3c0ef626 291 break;
292 }
665a873d 293 if (options.compression == COMP_NONE) {
f5799ae1 294 debug2("compression disabled");
295 break;
296 }
3c0ef626 297 /* Enable compression after we have responded with SUCCESS. */
298 enable_compression_after_reply = 1;
299 success = 1;
300 break;
301
302 case SSH_CMSG_REQUEST_PTY:
303 success = session_pty_req(s);
304 break;
305
306 case SSH_CMSG_X11_REQUEST_FORWARDING:
307 s->auth_proto = packet_get_string(&proto_len);
308 s->auth_data = packet_get_string(&data_len);
309
310 screen_flag = packet_get_protocol_flags() &
311 SSH_PROTOFLAG_SCREEN_NUMBER;
312 debug2("SSH_PROTOFLAG_SCREEN_NUMBER: %d", screen_flag);
313
314 if (packet_remaining() == 4) {
315 if (!screen_flag)
316 debug2("Buggy client: "
317 "X11 screen flag missing");
318 s->screen = packet_get_int();
319 } else {
320 s->screen = 0;
321 }
e9a17296 322 packet_check_eom();
3c0ef626 323 success = session_setup_x11fwd(s);
324 if (!success) {
325 xfree(s->auth_proto);
326 xfree(s->auth_data);
327 s->auth_proto = NULL;
328 s->auth_data = NULL;
329 }
330 break;
331
332 case SSH_CMSG_AGENT_REQUEST_FORWARDING:
333 if (no_agent_forwarding_flag || compat13) {
334 debug("Authentication agent forwarding not permitted for this authentication.");
335 break;
336 }
337 debug("Received authentication agent forwarding request.");
338 success = auth_input_request_forwarding(s->pw);
339 break;
340
341 case SSH_CMSG_PORT_FORWARD_REQUEST:
342 if (no_port_forwarding_flag) {
343 debug("Port forwarding not permitted for this authentication.");
344 break;
345 }
346 if (!options.allow_tcp_forwarding) {
347 debug("Port forwarding not permitted.");
348 break;
349 }
350 debug("Received TCP/IP port forwarding request.");
9108f8d9 351 if (channel_input_port_forward_request(s->pw->pw_uid == 0,
d6f3ca1e 352 options.gateway_ports, options.hpn_disabled,
353 options.hpn_buffer_size) < 0) {
9108f8d9 354 debug("Port forwarding failed.");
355 break;
356 }
3c0ef626 357 success = 1;
358 break;
359
360 case SSH_CMSG_MAX_PACKET_SIZE:
361 if (packet_set_maxsize(packet_get_int()) > 0)
362 success = 1;
363 break;
e9a17296 364
3c0ef626 365 case SSH_CMSG_EXEC_SHELL:
366 case SSH_CMSG_EXEC_CMD:
367 if (type == SSH_CMSG_EXEC_CMD) {
368 command = packet_get_string(&dlen);
369 debug("Exec command '%.500s'", command);
370 do_exec(s, command);
371 xfree(command);
372 } else {
373 do_exec(s, NULL);
374 }
e9a17296 375 packet_check_eom();
3c0ef626 376 session_close(s);
377 return;
378
379 default:
380 /*
381 * Any unknown messages in this phase are ignored,
382 * and a failure message is returned.
383 */
0fff78ff 384 logit("Unknown packet type received after authentication: %d", type);
3c0ef626 385 }
386 packet_start(success ? SSH_SMSG_SUCCESS : SSH_SMSG_FAILURE);
387 packet_send();
388 packet_write_wait();
389
390 /* Enable compression now that we have replied if appropriate. */
391 if (enable_compression_after_reply) {
392 enable_compression_after_reply = 0;
393 packet_start_compression(compression_level);
394 }
395 }
396}
397
398/*
399 * This is called to fork and execute a command when we have no tty. This
400 * will call do_child from the child, and server_loop from the parent after
401 * setting up file descriptors and such.
402 */
403void
404do_exec_no_pty(Session *s, const char *command)
405{
f5799ae1 406 pid_t pid;
3c0ef626 407
408#ifdef USE_PIPES
409 int pin[2], pout[2], perr[2];
410 /* Allocate pipes for communicating with the program. */
411 if (pipe(pin) < 0 || pipe(pout) < 0 || pipe(perr) < 0)
412 packet_disconnect("Could not create pipes: %.100s",
413 strerror(errno));
414#else /* USE_PIPES */
415 int inout[2], err[2];
416 /* Uses socket pairs to communicate with the program. */
417 if (socketpair(AF_UNIX, SOCK_STREAM, 0, inout) < 0 ||
418 socketpair(AF_UNIX, SOCK_STREAM, 0, err) < 0)
419 packet_disconnect("Could not create socket pairs: %.100s",
420 strerror(errno));
421#endif /* USE_PIPES */
422 if (s == NULL)
423 fatal("do_exec_no_pty: no session");
424
425 session_proctitle(s);
426
427#if defined(USE_PAM)
cdd66111 428 if (options.use_pam && !use_privsep)
0fff78ff 429 do_pam_setcred(1);
3c0ef626 430#endif /* USE_PAM */
431
432 /* Fork the child. */
433 if ((pid = fork()) == 0) {
cdd66111 434 is_child = 1;
41b2f314 435
3c0ef626 436 /* Child. Reinitialize the log since the pid has changed. */
437 log_init(__progname, options.log_level, options.log_facility, log_stderr);
438
439 /*
440 * Create a new session and process group since the 4.4BSD
441 * setlogin() affects the entire process group.
442 */
443 if (setsid() < 0)
444 error("setsid failed: %.100s", strerror(errno));
445
446#ifdef USE_PIPES
447 /*
448 * Redirect stdin. We close the parent side of the socket
449 * pair, and make the child side the standard input.
450 */
451 close(pin[1]);
452 if (dup2(pin[0], 0) < 0)
453 perror("dup2 stdin");
454 close(pin[0]);
455
456 /* Redirect stdout. */
457 close(pout[0]);
458 if (dup2(pout[1], 1) < 0)
459 perror("dup2 stdout");
460 close(pout[1]);
461
462 /* Redirect stderr. */
463 close(perr[0]);
464 if (dup2(perr[1], 2) < 0)
465 perror("dup2 stderr");
466 close(perr[1]);
467#else /* USE_PIPES */
468 /*
469 * Redirect stdin, stdout, and stderr. Stdin and stdout will
470 * use the same socket, as some programs (particularly rdist)
471 * seem to depend on it.
472 */
473 close(inout[1]);
474 close(err[1]);
475 if (dup2(inout[0], 0) < 0) /* stdin */
476 perror("dup2 stdin");
477 if (dup2(inout[0], 1) < 0) /* stdout. Note: same socket as stdin. */
478 perror("dup2 stdout");
479 if (dup2(err[0], 2) < 0) /* stderr */
480 perror("dup2 stderr");
481#endif /* USE_PIPES */
482
41b2f314 483#ifdef _UNICOS
484 cray_init_job(s->pw); /* set up cray jid and tmpdir */
485#endif
486
3c0ef626 487 /* Do processing for the child (exec command etc). */
488 do_child(s, command);
489 /* NOTREACHED */
490 }
41b2f314 491#ifdef _UNICOS
492 signal(WJSIGNAL, cray_job_termination_handler);
493#endif /* _UNICOS */
3c0ef626 494#ifdef HAVE_CYGWIN
495 if (is_winnt)
496 cygwin_set_impersonation_token(INVALID_HANDLE_VALUE);
497#endif
498 if (pid < 0)
499 packet_disconnect("fork failed: %.100s", strerror(errno));
500 s->pid = pid;
501 /* Set interactive/non-interactive mode. */
502 packet_set_interactive(s->display != NULL);
503#ifdef USE_PIPES
504 /* We are the parent. Close the child sides of the pipes. */
505 close(pin[0]);
506 close(pout[1]);
507 close(perr[1]);
508
509 if (compat20) {
c9f39d2c 510 if (s->is_subsystem) {
511 close(perr[0]);
512 perr[0] = -1;
513 }
514 session_set_fds(s, pin[1], pout[0], perr[0]);
3c0ef626 515 } else {
516 /* Enter the interactive session. */
517 server_loop(pid, pin[1], pout[0], perr[0]);
518 /* server_loop has closed pin[1], pout[0], and perr[0]. */
519 }
520#else /* USE_PIPES */
521 /* We are the parent. Close the child sides of the socket pairs. */
522 close(inout[0]);
523 close(err[0]);
524
99be0775 525 /*
526 * Clear loginmsg, since it's the child's responsibility to display
527 * it to the user, otherwise multiple sessions may accumulate
528 * multiple copies of the login messages.
529 */
530 buffer_clear(&loginmsg);
531
3c0ef626 532 /*
533 * Enter the interactive session. Note: server_loop must be able to
534 * handle the case that fdin and fdout are the same.
535 */
536 if (compat20) {
537 session_set_fds(s, inout[1], inout[1], s->is_subsystem ? -1 : err[1]);
538 } else {
539 server_loop(pid, inout[1], inout[1], err[1]);
540 /* server_loop has closed inout[1] and err[1]. */
541 }
542#endif /* USE_PIPES */
543}
544
545/*
546 * This is called to fork and execute a command when we have a tty. This
547 * will call do_child from the child, and server_loop from the parent after
548 * setting up file descriptors, controlling tty, updating wtmp, utmp,
549 * lastlog, and other such operations.
550 */
551void
552do_exec_pty(Session *s, const char *command)
553{
554 int fdout, ptyfd, ttyfd, ptymaster;
555 pid_t pid;
556
557 if (s == NULL)
558 fatal("do_exec_pty: no session");
559 ptyfd = s->ptyfd;
560 ttyfd = s->ttyfd;
561
562#if defined(USE_PAM)
0fff78ff 563 if (options.use_pam) {
564 do_pam_set_tty(s->tty);
cdd66111 565 if (!use_privsep)
566 do_pam_setcred(1);
0fff78ff 567 }
3c0ef626 568#endif
569
570 /* Fork the child. */
571 if ((pid = fork()) == 0) {
cdd66111 572 is_child = 1;
3c0ef626 573
574 /* Child. Reinitialize the log because the pid has changed. */
575 log_init(__progname, options.log_level, options.log_facility, log_stderr);
576 /* Close the master side of the pseudo tty. */
577 close(ptyfd);
578
579 /* Make the pseudo tty our controlling tty. */
580 pty_make_controlling_tty(&ttyfd, s->tty);
581
582 /* Redirect stdin/stdout/stderr from the pseudo tty. */
583 if (dup2(ttyfd, 0) < 0)
584 error("dup2 stdin: %s", strerror(errno));
585 if (dup2(ttyfd, 1) < 0)
586 error("dup2 stdout: %s", strerror(errno));
587 if (dup2(ttyfd, 2) < 0)
588 error("dup2 stderr: %s", strerror(errno));
589
590 /* Close the extra descriptor for the pseudo tty. */
591 close(ttyfd);
592
593 /* record login, etc. similar to login(1) */
594#ifndef HAVE_OSF_SIA
41b2f314 595 if (!(options.use_login && command == NULL)) {
596#ifdef _UNICOS
597 cray_init_job(s->pw); /* set up cray jid and tmpdir */
598#endif /* _UNICOS */
3c0ef626 599 do_login(s, command);
41b2f314 600 }
3c0ef626 601# ifdef LOGIN_NEEDS_UTMPX
602 else
603 do_pre_login(s);
604# endif
605#endif
606
607 /* Do common processing for the child, such as execing the command. */
608 do_child(s, command);
609 /* NOTREACHED */
610 }
41b2f314 611#ifdef _UNICOS
612 signal(WJSIGNAL, cray_job_termination_handler);
613#endif /* _UNICOS */
3c0ef626 614#ifdef HAVE_CYGWIN
615 if (is_winnt)
616 cygwin_set_impersonation_token(INVALID_HANDLE_VALUE);
617#endif
618 if (pid < 0)
619 packet_disconnect("fork failed: %.100s", strerror(errno));
620 s->pid = pid;
621
622 /* Parent. Close the slave side of the pseudo tty. */
623 close(ttyfd);
624
625 /*
626 * Create another descriptor of the pty master side for use as the
627 * standard input. We could use the original descriptor, but this
628 * simplifies code in server_loop. The descriptor is bidirectional.
629 */
630 fdout = dup(ptyfd);
631 if (fdout < 0)
632 packet_disconnect("dup #1 failed: %.100s", strerror(errno));
633
634 /* we keep a reference to the pty master */
635 ptymaster = dup(ptyfd);
636 if (ptymaster < 0)
637 packet_disconnect("dup #2 failed: %.100s", strerror(errno));
638 s->ptymaster = ptymaster;
639
640 /* Enter interactive session. */
641 packet_set_interactive(1);
642 if (compat20) {
643 session_set_fds(s, ptyfd, fdout, -1);
644 } else {
645 server_loop(pid, ptyfd, fdout, -1);
646 /* server_loop _has_ closed ptyfd and fdout. */
647 }
648}
649
650#ifdef LOGIN_NEEDS_UTMPX
651static void
652do_pre_login(Session *s)
653{
654 socklen_t fromlen;
655 struct sockaddr_storage from;
656 pid_t pid = getpid();
657
658 /*
659 * Get IP address of client. If the connection is not a socket, let
660 * the address be 0.0.0.0.
661 */
662 memset(&from, 0, sizeof(from));
41b2f314 663 fromlen = sizeof(from);
3c0ef626 664 if (packet_connection_is_on_socket()) {
3c0ef626 665 if (getpeername(packet_get_connection_in(),
9108f8d9 666 (struct sockaddr *)&from, &fromlen) < 0) {
3c0ef626 667 debug("getpeername: %.100s", strerror(errno));
cdd66111 668 cleanup_exit(255);
3c0ef626 669 }
670 }
671
672 record_utmp_only(pid, s->tty, s->pw->pw_name,
0fff78ff 673 get_remote_name_or_ip(utmp_len, options.use_dns),
6a9b3198 674 (struct sockaddr *)&from, fromlen);
3c0ef626 675}
676#endif
677
678/*
679 * This is called to fork and execute a command. If another command is
680 * to be forced, execute that instead.
681 */
682void
683do_exec(Session *s, const char *command)
684{
9108f8d9 685 if (options.adm_forced_command) {
686 original_command = command;
687 command = options.adm_forced_command;
688 debug("Forced command (config) '%.900s'", command);
689 } else if (forced_command) {
3c0ef626 690 original_command = command;
691 command = forced_command;
9108f8d9 692 debug("Forced command (key option) '%.900s'", command);
3c0ef626 693 }
694
996d5e62 695#ifdef SSH_AUDIT_EVENTS
696 if (command != NULL)
697 PRIVSEP(audit_run_command(command));
698 else if (s->ttyfd == -1) {
699 char *shell = s->pw->pw_shell;
700
701 if (shell[0] == '\0') /* empty shell means /bin/sh */
702 shell =_PATH_BSHELL;
703 PRIVSEP(audit_run_command(shell));
0fff78ff 704 }
705#endif
706
3c0ef626 707 if (s->ttyfd != -1)
708 do_exec_pty(s, command);
709 else
710 do_exec_no_pty(s, command);
711
712 original_command = NULL;
3c0ef626 713
c9f39d2c 714 /*
715 * Clear loginmsg: it's the child's responsibility to display
716 * it to the user, otherwise multiple sessions may accumulate
717 * multiple copies of the login messages.
718 */
719 buffer_clear(&loginmsg);
720}
e9a17296 721
3c0ef626 722/* administrative, login(1)-like work */
723void
724do_login(Session *s, const char *command)
725{
3c0ef626 726 socklen_t fromlen;
727 struct sockaddr_storage from;
3c0ef626 728 struct passwd * pw = s->pw;
729 pid_t pid = getpid();
730
731 /*
732 * Get IP address of client. If the connection is not a socket, let
733 * the address be 0.0.0.0.
734 */
735 memset(&from, 0, sizeof(from));
6a9b3198 736 fromlen = sizeof(from);
3c0ef626 737 if (packet_connection_is_on_socket()) {
3c0ef626 738 if (getpeername(packet_get_connection_in(),
e9a17296 739 (struct sockaddr *) & from, &fromlen) < 0) {
3c0ef626 740 debug("getpeername: %.100s", strerror(errno));
cdd66111 741 cleanup_exit(255);
3c0ef626 742 }
743 }
744
3c0ef626 745 /* Record that there was a login on that tty from the remote host. */
700318f3 746 if (!use_privsep)
747 record_login(pid, s->tty, pw->pw_name, pw->pw_uid,
748 get_remote_name_or_ip(utmp_len,
0fff78ff 749 options.use_dns),
41b2f314 750 (struct sockaddr *)&from, fromlen);
3c0ef626 751
752#ifdef USE_PAM
753 /*
754 * If password change is needed, do it now.
755 * This needs to occur before the ~/.hushlogin check.
756 */
cdd66111 757 if (options.use_pam && !use_privsep && s->authctxt->force_pwchange) {
758 display_loginmsg();
3c0ef626 759 do_pam_chauthtok();
cdd66111 760 s->authctxt->force_pwchange = 0;
0fff78ff 761 /* XXX - signal [net] parent to enable forwardings */
3c0ef626 762 }
763#endif
764
765 if (check_quietlogin(s, command))
766 return;
767
cdd66111 768 display_loginmsg();
3c0ef626 769
3c0ef626 770 do_motd();
771}
772
773/*
774 * Display the message of the day.
775 */
776void
777do_motd(void)
778{
779 FILE *f;
780 char buf[256];
781
782 if (options.print_motd) {
783#ifdef HAVE_LOGIN_CAP
784 f = fopen(login_getcapstr(lc, "welcome", "/etc/motd",
785 "/etc/motd"), "r");
786#else
787 f = fopen("/etc/motd", "r");
788#endif
789 if (f) {
790 while (fgets(buf, sizeof(buf), f))
791 fputs(buf, stdout);
792 fclose(f);
793 }
794 }
795}
796
797
798/*
799 * Check for quiet login, either .hushlogin or command given.
800 */
801int
802check_quietlogin(Session *s, const char *command)
803{
804 char buf[256];
805 struct passwd *pw = s->pw;
806 struct stat st;
807
808 /* Return 1 if .hushlogin exists or a command given. */
809 if (command != NULL)
810 return 1;
811 snprintf(buf, sizeof(buf), "%.200s/.hushlogin", pw->pw_dir);
812#ifdef HAVE_LOGIN_CAP
813 if (login_getcapbool(lc, "hushlogin", 0) || stat(buf, &st) >= 0)
814 return 1;
815#else
816 if (stat(buf, &st) >= 0)
817 return 1;
818#endif
819 return 0;
820}
821
822/*
823 * Sets the value of the given variable in the environment. If the variable
824 * already exists, its value is overriden.
825 */
0fff78ff 826void
3c0ef626 827child_set_env(char ***envp, u_int *envsizep, const char *name,
e9a17296 828 const char *value)
3c0ef626 829{
3c0ef626 830 char **env;
acc3d05e 831 u_int envsize;
832 u_int i, namelen;
3c0ef626 833
0fff78ff 834 /*
835 * If we're passed an uninitialized list, allocate a single null
836 * entry before continuing.
837 */
838 if (*envp == NULL && *envsizep == 0) {
839 *envp = xmalloc(sizeof(char *));
840 *envp[0] = NULL;
841 *envsizep = 1;
842 }
843
3c0ef626 844 /*
845 * Find the slot where the value should be stored. If the variable
846 * already exists, we reuse the slot; otherwise we append a new slot
847 * at the end of the array, expanding if necessary.
848 */
849 env = *envp;
850 namelen = strlen(name);
851 for (i = 0; env[i]; i++)
852 if (strncmp(env[i], name, namelen) == 0 && env[i][namelen] == '=')
853 break;
854 if (env[i]) {
855 /* Reuse the slot. */
856 xfree(env[i]);
857 } else {
858 /* New variable. Expand if necessary. */
acc3d05e 859 envsize = *envsizep;
860 if (i >= envsize - 1) {
861 if (envsize >= 1000)
862 fatal("child_set_env: too many env vars");
863 envsize += 50;
9108f8d9 864 env = (*envp) = xrealloc(env, envsize, sizeof(char *));
acc3d05e 865 *envsizep = envsize;
3c0ef626 866 }
867 /* Need to set the NULL pointer at end of array beyond the new slot. */
868 env[i + 1] = NULL;
869 }
870
871 /* Allocate space and format the variable in the appropriate slot. */
872 env[i] = xmalloc(strlen(name) + 1 + strlen(value) + 1);
873 snprintf(env[i], strlen(name) + 1 + strlen(value) + 1, "%s=%s", name, value);
874}
875
876/*
877 * Reads environment variables from the given file and adds/overrides them
878 * into the environment. If the file does not exist, this does nothing.
879 * Otherwise, it must consist of empty lines, comments (line starts with '#')
880 * and assignments of the form name=value. No other forms are allowed.
881 */
882static void
883read_environment_file(char ***env, u_int *envsize,
e9a17296 884 const char *filename)
3c0ef626 885{
886 FILE *f;
887 char buf[4096];
888 char *cp, *value;
680cee3b 889 u_int lineno = 0;
3c0ef626 890
891 f = fopen(filename, "r");
892 if (!f)
893 return;
894
895 while (fgets(buf, sizeof(buf), f)) {
680cee3b 896 if (++lineno > 1000)
897 fatal("Too many lines in environment file %s", filename);
3c0ef626 898 for (cp = buf; *cp == ' ' || *cp == '\t'; cp++)
899 ;
900 if (!*cp || *cp == '#' || *cp == '\n')
901 continue;
902 if (strchr(cp, '\n'))
903 *strchr(cp, '\n') = '\0';
904 value = strchr(cp, '=');
905 if (value == NULL) {
680cee3b 906 fprintf(stderr, "Bad line %u in %.100s\n", lineno,
907 filename);
3c0ef626 908 continue;
909 }
910 /*
911 * Replace the equals sign by nul, and advance value to
912 * the value string.
913 */
914 *value = '\0';
915 value++;
916 child_set_env(env, envsize, cp, value);
917 }
918 fclose(f);
919}
920
0fff78ff 921#ifdef HAVE_ETC_DEFAULT_LOGIN
922/*
923 * Return named variable from specified environment, or NULL if not present.
924 */
925static char *
926child_get_env(char **env, const char *name)
927{
928 int i;
929 size_t len;
930
931 len = strlen(name);
932 for (i=0; env[i] != NULL; i++)
933 if (strncmp(name, env[i], len) == 0 && env[i][len] == '=')
934 return(env[i] + len + 1);
935 return NULL;
936}
937
938/*
939 * Read /etc/default/login.
940 * We pick up the PATH (or SUPATH for root) and UMASK.
941 */
942static void
943read_etc_default_login(char ***env, u_int *envsize, uid_t uid)
944{
945 char **tmpenv = NULL, *var;
acc3d05e 946 u_int i, tmpenvsize = 0;
cdd66111 947 u_long mask;
0fff78ff 948
949 /*
950 * We don't want to copy the whole file to the child's environment,
951 * so we use a temporary environment and copy the variables we're
952 * interested in.
953 */
954 read_environment_file(&tmpenv, &tmpenvsize, "/etc/default/login");
955
acc3d05e 956 if (tmpenv == NULL)
957 return;
958
0fff78ff 959 if (uid == 0)
960 var = child_get_env(tmpenv, "SUPATH");
961 else
962 var = child_get_env(tmpenv, "PATH");
963 if (var != NULL)
964 child_set_env(env, envsize, "PATH", var);
cdd66111 965
0fff78ff 966 if ((var = child_get_env(tmpenv, "UMASK")) != NULL)
967 if (sscanf(var, "%5lo", &mask) == 1)
cdd66111 968 umask((mode_t)mask);
969
0fff78ff 970 for (i = 0; tmpenv[i] != NULL; i++)
971 xfree(tmpenv[i]);
972 xfree(tmpenv);
973}
974#endif /* HAVE_ETC_DEFAULT_LOGIN */
975
665a873d 976void
977copy_environment(char **source, char ***env, u_int *envsize)
3c0ef626 978{
e9a17296 979 char *var_name, *var_val;
3c0ef626 980 int i;
981
e9a17296 982 if (source == NULL)
3c0ef626 983 return;
984
e9a17296 985 for(i = 0; source[i] != NULL; i++) {
986 var_name = xstrdup(source[i]);
987 if ((var_val = strstr(var_name, "=")) == NULL) {
988 xfree(var_name);
3c0ef626 989 continue;
3c0ef626 990 }
e9a17296 991 *var_val++ = '\0';
3c0ef626 992
e9a17296 993 debug3("Copy environment: %s=%s", var_name, var_val);
994 child_set_env(env, envsize, var_name, var_val);
cdd66111 995
e9a17296 996 xfree(var_name);
3c0ef626 997 }
998}
3c0ef626 999
e9a17296 1000static char **
1001do_setup_env(Session *s, const char *shell)
3c0ef626 1002{
3c0ef626 1003 char buf[256];
e9a17296 1004 u_int i, envsize;
9108f8d9 1005 char **env, *laddr;
e9a17296 1006 struct passwd *pw = s->pw;
9108f8d9 1007#ifndef HAVE_LOGIN_CAP
1008 char *path = NULL;
1009#endif
3c0ef626 1010
1011 /* Initialize the environment. */
1012 envsize = 100;
9108f8d9 1013 env = xcalloc(envsize, sizeof(char *));
3c0ef626 1014 env[0] = NULL;
1015
1016#ifdef HAVE_CYGWIN
1017 /*
1018 * The Windows environment contains some setting which are
1019 * important for a running system. They must not be dropped.
1020 */
996d5e62 1021 {
1022 char **p;
1023
1024 p = fetch_windows_environment();
1025 copy_environment(p, &env, &envsize);
1026 free_windows_environment(p);
1027 }
3c0ef626 1028#endif
1029
0fff78ff 1030#ifdef GSSAPI
cdd66111 1031 /* Allow any GSSAPI methods that we've used to alter
0fff78ff 1032 * the childs environment as they see fit
1033 */
1034 ssh_gssapi_do_child(&env, &envsize);
1035#endif
1036
3c0ef626 1037 if (!options.use_login) {
1038 /* Set basic environment. */
c9f39d2c 1039 for (i = 0; i < s->num_env; i++)
1040 child_set_env(&env, &envsize, s->env[i].name,
1041 s->env[i].val);
1042
3c0ef626 1043 child_set_env(&env, &envsize, "USER", pw->pw_name);
1044 child_set_env(&env, &envsize, "LOGNAME", pw->pw_name);
6a9b3198 1045#ifdef _AIX
1046 child_set_env(&env, &envsize, "LOGIN", pw->pw_name);
1047#endif
3c0ef626 1048 child_set_env(&env, &envsize, "HOME", pw->pw_dir);
1049#ifdef HAVE_LOGIN_CAP
41b2f314 1050 if (setusercontext(lc, pw, pw->pw_uid, LOGIN_SETPATH) < 0)
1051 child_set_env(&env, &envsize, "PATH", _PATH_STDPATH);
1052 else
1053 child_set_env(&env, &envsize, "PATH", getenv("PATH"));
3c0ef626 1054#else /* HAVE_LOGIN_CAP */
1055# ifndef HAVE_CYGWIN
1056 /*
1057 * There's no standard path on Windows. The path contains
1058 * important components pointing to the system directories,
1059 * needed for loading shared libraries. So the path better
1060 * remains intact here.
1061 */
0fff78ff 1062# ifdef HAVE_ETC_DEFAULT_LOGIN
1063 read_etc_default_login(&env, &envsize, pw->pw_uid);
1064 path = child_get_env(env, "PATH");
1065# endif /* HAVE_ETC_DEFAULT_LOGIN */
1066 if (path == NULL || *path == '\0') {
cdd66111 1067 child_set_env(&env, &envsize, "PATH",
0fff78ff 1068 s->pw->pw_uid == 0 ?
1069 SUPERUSER_PATH : _PATH_STDPATH);
1070 }
3c0ef626 1071# endif /* HAVE_CYGWIN */
1072#endif /* HAVE_LOGIN_CAP */
1073
1074 snprintf(buf, sizeof buf, "%.200s/%.50s",
1075 _PATH_MAILDIR, pw->pw_name);
1076 child_set_env(&env, &envsize, "MAIL", buf);
1077
1078 /* Normal systems set SHELL by default. */
1079 child_set_env(&env, &envsize, "SHELL", shell);
1080 }
1081 if (getenv("TZ"))
1082 child_set_env(&env, &envsize, "TZ", getenv("TZ"));
1083
1084 /* Set custom environment options from RSA authentication. */
1085 if (!options.use_login) {
1086 while (custom_environment) {
1087 struct envstring *ce = custom_environment;
41b2f314 1088 char *str = ce->s;
e9a17296 1089
41b2f314 1090 for (i = 0; str[i] != '=' && str[i]; i++)
3c0ef626 1091 ;
41b2f314 1092 if (str[i] == '=') {
1093 str[i] = 0;
1094 child_set_env(&env, &envsize, str, str + i + 1);
3c0ef626 1095 }
1096 custom_environment = ce->next;
1097 xfree(ce->s);
1098 xfree(ce);
1099 }
1100 }
1101
41b2f314 1102 /* SSH_CLIENT deprecated */
3c0ef626 1103 snprintf(buf, sizeof buf, "%.50s %d %d",
e9a17296 1104 get_remote_ipaddr(), get_remote_port(), get_local_port());
3c0ef626 1105 child_set_env(&env, &envsize, "SSH_CLIENT", buf);
1106
6a9b3198 1107 laddr = get_local_ipaddr(packet_get_connection_in());
41b2f314 1108 snprintf(buf, sizeof buf, "%.50s %d %.50s %d",
6a9b3198 1109 get_remote_ipaddr(), get_remote_port(), laddr, get_local_port());
1110 xfree(laddr);
41b2f314 1111 child_set_env(&env, &envsize, "SSH_CONNECTION", buf);
1112
3c0ef626 1113 if (s->ttyfd != -1)
1114 child_set_env(&env, &envsize, "SSH_TTY", s->tty);
1115 if (s->term)
1116 child_set_env(&env, &envsize, "TERM", s->term);
1117 if (s->display)
1118 child_set_env(&env, &envsize, "DISPLAY", s->display);
1119 if (original_command)
1120 child_set_env(&env, &envsize, "SSH_ORIGINAL_COMMAND",
1121 original_command);
1122
41b2f314 1123#ifdef _UNICOS
1124 if (cray_tmpdir[0] != '\0')
1125 child_set_env(&env, &envsize, "TMPDIR", cray_tmpdir);
1126#endif /* _UNICOS */
1127
996d5e62 1128 /*
1129 * Since we clear KRB5CCNAME at startup, if it's set now then it
1130 * must have been set by a native authentication method (eg AIX or
1131 * SIA), so copy it to the child.
1132 */
1133 {
1134 char *cp;
1135
1136 if ((cp = getenv("KRB5CCNAME")) != NULL)
1137 child_set_env(&env, &envsize, "KRB5CCNAME", cp);
1138 }
1139
3c0ef626 1140#ifdef _AIX
e9a17296 1141 {
1142 char *cp;
1143
1144 if ((cp = getenv("AUTHSTATE")) != NULL)
1145 child_set_env(&env, &envsize, "AUTHSTATE", cp);
e9a17296 1146 read_environment_file(&env, &envsize, "/etc/environment");
1147 }
3c0ef626 1148#endif
3c0ef626 1149#ifdef KRB5
99be0775 1150 if (s->authctxt->krb5_ccname)
3c0ef626 1151 child_set_env(&env, &envsize, "KRB5CCNAME",
99be0775 1152 s->authctxt->krb5_ccname);
3c0ef626 1153#endif
1154#ifdef USE_PAM
41b2f314 1155 /*
1156 * Pull in any environment variables that may have
1157 * been set by PAM.
1158 */
0fff78ff 1159 if (options.use_pam) {
cdd66111 1160 char **p;
41b2f314 1161
cdd66111 1162 p = fetch_pam_child_environment();
1163 copy_environment(p, &env, &envsize);
1164 free_pam_environment(p);
1165
1166 p = fetch_pam_environment();
41b2f314 1167 copy_environment(p, &env, &envsize);
1168 free_pam_environment(p);
1169 }
3c0ef626 1170#endif /* USE_PAM */
1171
f5799ae1 1172 if (auth_sock_name != NULL)
3c0ef626 1173 child_set_env(&env, &envsize, SSH_AUTHSOCKET_ENV_NAME,
f5799ae1 1174 auth_sock_name);
3c0ef626 1175
1176 /* read $HOME/.ssh/environment. */
41b2f314 1177 if (options.permit_user_env && !options.use_login) {
3c0ef626 1178 snprintf(buf, sizeof buf, "%.200s/.ssh/environment",
41b2f314 1179 strcmp(pw->pw_dir, "/") ? pw->pw_dir : "");
3c0ef626 1180 read_environment_file(&env, &envsize, buf);
1181 }
1182 if (debug_flag) {
1183 /* dump the environment */
1184 fprintf(stderr, "Environment:\n");
1185 for (i = 0; env[i]; i++)
1186 fprintf(stderr, " %.200s\n", env[i]);
1187 }
e9a17296 1188 return env;
1189}
1190
1191/*
1192 * Run $HOME/.ssh/rc, /etc/ssh/sshrc, or xauth (whichever is found
1193 * first in this order).
1194 */
1195static void
1196do_rc_files(Session *s, const char *shell)
1197{
1198 FILE *f = NULL;
1199 char cmd[1024];
1200 int do_xauth;
1201 struct stat st;
1202
1203 do_xauth =
1204 s->display != NULL && s->auth_proto != NULL && s->auth_data != NULL;
1205
1206 /* ignore _PATH_SSH_USER_RC for subsystems */
1207 if (!s->is_subsystem && (stat(_PATH_SSH_USER_RC, &st) >= 0)) {
1208 snprintf(cmd, sizeof cmd, "%s -c '%s %s'",
1209 shell, _PATH_BSHELL, _PATH_SSH_USER_RC);
1210 if (debug_flag)
1211 fprintf(stderr, "Running %s\n", cmd);
1212 f = popen(cmd, "w");
1213 if (f) {
1214 if (do_xauth)
1215 fprintf(f, "%s %s\n", s->auth_proto,
1216 s->auth_data);
1217 pclose(f);
1218 } else
1219 fprintf(stderr, "Could not run %s\n",
1220 _PATH_SSH_USER_RC);
1221 } else if (stat(_PATH_SSH_SYSTEM_RC, &st) >= 0) {
1222 if (debug_flag)
1223 fprintf(stderr, "Running %s %s\n", _PATH_BSHELL,
1224 _PATH_SSH_SYSTEM_RC);
1225 f = popen(_PATH_BSHELL " " _PATH_SSH_SYSTEM_RC, "w");
1226 if (f) {
1227 if (do_xauth)
1228 fprintf(f, "%s %s\n", s->auth_proto,
1229 s->auth_data);
1230 pclose(f);
1231 } else
1232 fprintf(stderr, "Could not run %s\n",
1233 _PATH_SSH_SYSTEM_RC);
1234 } else if (do_xauth && options.xauth_location != NULL) {
1235 /* Add authority data to .Xauthority if appropriate. */
1236 if (debug_flag) {
1237 fprintf(stderr,
6a9b3198 1238 "Running %.500s remove %.100s\n",
cdd66111 1239 options.xauth_location, s->auth_display);
6a9b3198 1240 fprintf(stderr,
1241 "%.500s add %.100s %.100s %.100s\n",
e9a17296 1242 options.xauth_location, s->auth_display,
1243 s->auth_proto, s->auth_data);
1244 }
1245 snprintf(cmd, sizeof cmd, "%s -q -",
1246 options.xauth_location);
1247 f = popen(cmd, "w");
1248 if (f) {
6a9b3198 1249 fprintf(f, "remove %s\n",
1250 s->auth_display);
e9a17296 1251 fprintf(f, "add %s %s %s\n",
1252 s->auth_display, s->auth_proto,
1253 s->auth_data);
1254 pclose(f);
1255 } else {
1256 fprintf(stderr, "Could not run %s\n",
1257 cmd);
1258 }
1259 }
1260}
1261
1262static void
1263do_nologin(struct passwd *pw)
1264{
1265 FILE *f = NULL;
1266 char buf[1024];
1267
1268#ifdef HAVE_LOGIN_CAP
1269 if (!login_getcapbool(lc, "ignorenologin", 0) && pw->pw_uid)
1270 f = fopen(login_getcapstr(lc, "nologin", _PATH_NOLOGIN,
1271 _PATH_NOLOGIN), "r");
1272#else
1273 if (pw->pw_uid)
1274 f = fopen(_PATH_NOLOGIN, "r");
1275#endif
1276 if (f) {
1277 /* /etc/nologin exists. Print its contents and exit. */
0fff78ff 1278 logit("User %.100s not allowed because %s exists",
41b2f314 1279 pw->pw_name, _PATH_NOLOGIN);
e9a17296 1280 while (fgets(buf, sizeof(buf), f))
1281 fputs(buf, stderr);
1282 fclose(f);
6a9b3198 1283 fflush(NULL);
e9a17296 1284 exit(254);
1285 }
1286}
1287
1288/* Set login name, uid, gid, and groups. */
700318f3 1289void
e9a17296 1290do_setusercontext(struct passwd *pw)
1291{
6a9b3198 1292#ifndef HAVE_CYGWIN
1293 if (getuid() == 0 || geteuid() == 0)
e9a17296 1294#endif /* HAVE_CYGWIN */
6a9b3198 1295 {
1296
f5799ae1 1297#ifdef HAVE_SETPCRED
0fff78ff 1298 if (setpcred(pw->pw_name, (char **)NULL) == -1)
1299 fatal("Failed to set process credentials");
f5799ae1 1300#endif /* HAVE_SETPCRED */
e9a17296 1301#ifdef HAVE_LOGIN_CAP
41b2f314 1302# ifdef __bsdi__
680cee3b 1303 setpgid(0, 0);
41b2f314 1304# endif
996d5e62 1305#ifdef GSSAPI
1306 if (options.gss_authentication) {
1307 temporarily_use_uid(pw);
1308 ssh_gssapi_storecreds();
1309 restore_uid();
1310 }
1311#endif
cdd66111 1312# ifdef USE_PAM
1313 if (options.use_pam) {
1314 do_pam_session();
1315 do_pam_setcred(0);
1316 }
1317# endif /* USE_PAM */
e9a17296 1318 if (setusercontext(lc, pw, pw->pw_uid,
1319 (LOGIN_SETALL & ~LOGIN_SETPATH)) < 0) {
1320 perror("unable to set user context");
1321 exit(1);
1322 }
1323#else
1324# if defined(HAVE_GETLUID) && defined(HAVE_SETLUID)
1325 /* Sets login uid for accounting */
1326 if (getluid() == -1 && setluid(pw->pw_uid) == -1)
1327 error("setluid: %s", strerror(errno));
1328# endif /* defined(HAVE_GETLUID) && defined(HAVE_SETLUID) */
1329
1330 if (setlogin(pw->pw_name) < 0)
1331 error("setlogin failed: %s", strerror(errno));
1332 if (setgid(pw->pw_gid) < 0) {
1333 perror("setgid");
1334 exit(1);
1335 }
1336 /* Initialize the group list. */
1337 if (initgroups(pw->pw_name, pw->pw_gid) < 0) {
1338 perror("initgroups");
1339 exit(1);
1340 }
1341 endgrent();
996d5e62 1342#ifdef GSSAPI
1343 if (options.gss_authentication) {
1344 temporarily_use_uid(pw);
1345 ssh_gssapi_storecreds();
1346 restore_uid();
1347 }
1348#endif
e9a17296 1349# ifdef USE_PAM
1350 /*
cdd66111 1351 * PAM credentials may take the form of supplementary groups.
e9a17296 1352 * These will have been wiped by the above initgroups() call.
1353 * Reestablish them here.
1354 */
0fff78ff 1355 if (options.use_pam) {
1356 do_pam_session();
1357 do_pam_setcred(0);
1358 }
e9a17296 1359# endif /* USE_PAM */
1360# if defined(WITH_IRIX_PROJECT) || defined(WITH_IRIX_JOBS) || defined(WITH_IRIX_ARRAY)
1361 irix_setusercontext(pw);
1362# endif /* defined(WITH_IRIX_PROJECT) || defined(WITH_IRIX_JOBS) || defined(WITH_IRIX_ARRAY) */
680cee3b 1363# ifdef _AIX
41b2f314 1364 aix_usrinfo(pw);
680cee3b 1365# endif /* _AIX */
665a873d 1366#if defined(HAVE_LIBIAF) && !defined(BROKEN_LIBIAF)
1367 if (set_id(pw->pw_name) != 0) {
1368 exit(1);
1369 }
1370#endif /* HAVE_LIBIAF && !BROKEN_LIBIAF */
e9a17296 1371 /* Permanently switch to the desired uid. */
1372 permanently_set_uid(pw);
1373#endif
1374 }
6a9b3198 1375
1376#ifdef HAVE_CYGWIN
1377 if (is_winnt)
1378#endif
e9a17296 1379 if (getuid() != pw->pw_uid || geteuid() != pw->pw_uid)
1380 fatal("Failed to set uids to %u.", (u_int) pw->pw_uid);
9108f8d9 1381
1382#ifdef WITH_SELINUX
1383 ssh_selinux_setup_exec_context(pw->pw_name);
1384#endif
e9a17296 1385}
1386
cdd66111 1387static void
1388do_pwchange(Session *s)
1389{
c9f39d2c 1390 fflush(NULL);
cdd66111 1391 fprintf(stderr, "WARNING: Your password has expired.\n");
1392 if (s->ttyfd != -1) {
c9f39d2c 1393 fprintf(stderr,
cdd66111 1394 "You must change your password now and login again!\n");
996d5e62 1395#ifdef PASSWD_NEEDS_USERNAME
1396 execl(_PATH_PASSWD_PROG, "passwd", s->pw->pw_name,
1397 (char *)NULL);
1398#else
cdd66111 1399 execl(_PATH_PASSWD_PROG, "passwd", (char *)NULL);
996d5e62 1400#endif
cdd66111 1401 perror("passwd");
1402 } else {
1403 fprintf(stderr,
1404 "Password change required but no TTY available.\n");
1405 }
1406 exit(1);
1407}
1408
700318f3 1409static void
1410launch_login(struct passwd *pw, const char *hostname)
1411{
1412 /* Launch login(1). */
1413
f5799ae1 1414 execl(LOGIN_PROGRAM, "login", "-h", hostname,
700318f3 1415#ifdef xxxLOGIN_NEEDS_TERM
f5799ae1 1416 (s->term ? s->term : "unknown"),
700318f3 1417#endif /* LOGIN_NEEDS_TERM */
1418#ifdef LOGIN_NO_ENDOPT
1419 "-p", "-f", pw->pw_name, (char *)NULL);
1420#else
1421 "-p", "-f", "--", pw->pw_name, (char *)NULL);
1422#endif
1423
1424 /* Login couldn't be executed, die. */
1425
1426 perror("login");
1427 exit(1);
1428}
1429
cdd66111 1430static void
1431child_close_fds(void)
1432{
1433 int i;
1434
1435 if (packet_get_connection_in() == packet_get_connection_out())
1436 close(packet_get_connection_in());
1437 else {
1438 close(packet_get_connection_in());
1439 close(packet_get_connection_out());
1440 }
1441 /*
1442 * Close all descriptors related to channels. They will still remain
1443 * open in the parent.
1444 */
1445 /* XXX better use close-on-exec? -markus */
1446 channel_close_all();
1447
1448 /*
1449 * Close any extra file descriptors. Note that there may still be
1450 * descriptors left by system functions. They will be closed later.
1451 */
1452 endpwent();
1453
1454 /*
2c06c99b 1455 * Close any extra open file descriptors so that we don't have them
cdd66111 1456 * hanging around in clients. Note that we want to do this after
1457 * initgroups, because at least on Solaris 2.3 it leaves file
1458 * descriptors open.
1459 */
1460 for (i = 3; i < 64; i++)
1461 close(i);
1462}
1463
e9a17296 1464/*
1465 * Performs common processing for the child, such as setting up the
1466 * environment, closing extra file descriptors, setting the user and group
1467 * ids, and executing the command or shell.
1468 */
1469void
1470do_child(Session *s, const char *command)
1471{
1472 extern char **environ;
1473 char **env;
1474 char *argv[10];
1475 const char *shell, *shell0, *hostname = NULL;
1476 struct passwd *pw = s->pw;
e9a17296 1477
1478 /* remove hostkey from the child's memory */
1479 destroy_sensitive_data();
1480
cdd66111 1481 /* Force a password change */
1482 if (s->authctxt->force_pwchange) {
1483 do_setusercontext(pw);
1484 child_close_fds();
1485 do_pwchange(s);
1486 exit(1);
1487 }
1488
e9a17296 1489 /* login(1) is only called if we execute the login shell */
1490 if (options.use_login && command != NULL)
1491 options.use_login = 0;
1492
41b2f314 1493#ifdef _UNICOS
1494 cray_setup(pw->pw_uid, pw->pw_name, command);
1495#endif /* _UNICOS */
1496
e9a17296 1497 /*
1498 * Login(1) does this as well, and it needs uid 0 for the "-h"
1499 * switch, so we let login(1) to this for us.
1500 */
1501 if (!options.use_login) {
1502#ifdef HAVE_OSF_SIA
6a9b3198 1503 session_setup_sia(pw, s->ttyfd == -1 ? NULL : s->tty);
e9a17296 1504 if (!check_quietlogin(s, command))
1505 do_motd();
1506#else /* HAVE_OSF_SIA */
2c06c99b 1507 /* When PAM is enabled we rely on it to do the nologin check */
1508 if (!options.use_pam)
1509 do_nologin(pw);
e9a17296 1510 do_setusercontext(pw);
c9f39d2c 1511 /*
1512 * PAM session modules in do_setusercontext may have
1513 * generated messages, so if this in an interactive
1514 * login then display them too.
1515 */
996d5e62 1516 if (!check_quietlogin(s, command))
c9f39d2c 1517 display_loginmsg();
e9a17296 1518#endif /* HAVE_OSF_SIA */
1519 }
1520
996d5e62 1521#ifdef USE_PAM
dec6d9fe 1522 if (options.use_pam && !options.use_login && !is_pam_session_open()) {
1523 debug3("PAM session not opened, exiting");
996d5e62 1524 display_loginmsg();
1525 exit(254);
1526 }
1527#endif
1528
e9a17296 1529 /*
1530 * Get the shell from the password data. An empty shell field is
1531 * legal, and means /bin/sh.
1532 */
1533 shell = (pw->pw_shell[0] == '\0') ? _PATH_BSHELL : pw->pw_shell;
6a9b3198 1534
1535 /*
1536 * Make sure $SHELL points to the shell from the password file,
1537 * even if shell is overridden from login.conf
1538 */
1539 env = do_setup_env(s, shell);
1540
e9a17296 1541#ifdef HAVE_LOGIN_CAP
1542 shell = login_getcapstr(lc, "shell", (char *)shell, (char *)shell);
1543#endif
1544
3c0ef626 1545 /* we have to stash the hostname before we close our socket. */
1546 if (options.use_login)
1547 hostname = get_remote_name_or_ip(utmp_len,
0fff78ff 1548 options.use_dns);
3c0ef626 1549 /*
1550 * Close the connection descriptors; note that this is the child, and
1551 * the server will still have the socket open, and it is important
1552 * that we do not shutdown it. Note that the descriptors cannot be
1553 * closed before building the environment, as we call
1554 * get_remote_ipaddr there.
1555 */
cdd66111 1556 child_close_fds();
3c0ef626 1557
1558 /*
cdd66111 1559 * Must take new environment into use so that .ssh/rc,
1560 * /etc/ssh/sshrc and xauth are run in the proper environment.
3c0ef626 1561 */
cdd66111 1562 environ = env;
3c0ef626 1563
cdd66111 1564#if defined(KRB5) && defined(USE_AFS)
3c0ef626 1565 /*
cdd66111 1566 * At this point, we check to see if AFS is active and if we have
1567 * a valid Kerberos 5 TGT. If so, it seems like a good idea to see
1568 * if we can (and need to) extend the ticket into an AFS token. If
1569 * we don't do this, we run into potential problems if the user's
1570 * home directory is in AFS and it's not world-readable.
3c0ef626 1571 */
3c0ef626 1572
cdd66111 1573 if (options.kerberos_get_afs_token && k_hasafs() &&
665a873d 1574 (s->authctxt->krb5_ctx != NULL)) {
cdd66111 1575 char cell[64];
1576
1577 debug("Getting AFS token");
1578
1579 k_setpag();
1580
1581 if (k_afs_cell_of_file(pw->pw_dir, cell, sizeof(cell)) == 0)
1582 krb5_afslog(s->authctxt->krb5_ctx,
1583 s->authctxt->krb5_fwd_ccache, cell, NULL);
1584
1585 krb5_afslog_home(s->authctxt->krb5_ctx,
1586 s->authctxt->krb5_fwd_ccache, NULL, NULL, pw->pw_dir);
1587 }
1588#endif
3c0ef626 1589
2c06c99b 1590 /* Change current directory to the user's home directory. */
3c0ef626 1591 if (chdir(pw->pw_dir) < 0) {
1592 fprintf(stderr, "Could not chdir to home directory %s: %s\n",
1593 pw->pw_dir, strerror(errno));
1594#ifdef HAVE_LOGIN_CAP
1595 if (login_getcapbool(lc, "requirehome", 0))
1596 exit(1);
1597#endif
1598 }
1599
e9a17296 1600 if (!options.use_login)
1601 do_rc_files(s, shell);
3c0ef626 1602
1603 /* restore SIGPIPE for child */
9108f8d9 1604 signal(SIGPIPE, SIG_DFL);
3c0ef626 1605
e9a17296 1606 if (options.use_login) {
700318f3 1607 launch_login(pw, hostname);
1608 /* NEVERREACHED */
e9a17296 1609 }
1610
1611 /* Get the last component of the shell name. */
1612 if ((shell0 = strrchr(shell, '/')) != NULL)
1613 shell0++;
1614 else
1615 shell0 = shell;
1616
3c0ef626 1617 /*
1618 * If we have no command, execute the shell. In this case, the shell
1619 * name to be passed in argv[0] is preceded by '-' to indicate that
1620 * this is a login shell.
1621 */
1622 if (!command) {
e9a17296 1623 char argv0[256];
3c0ef626 1624
e9a17296 1625 /* Start the shell. Set initial character to '-'. */
1626 argv0[0] = '-';
3c0ef626 1627
e9a17296 1628 if (strlcpy(argv0 + 1, shell0, sizeof(argv0) - 1)
1629 >= sizeof(argv0) - 1) {
1630 errno = EINVAL;
3c0ef626 1631 perror(shell);
1632 exit(1);
e9a17296 1633 }
3c0ef626 1634
e9a17296 1635 /* Execute the shell. */
1636 argv[0] = argv0;
1637 argv[1] = NULL;
1638 execve(shell, argv, env);
3c0ef626 1639
e9a17296 1640 /* Executing the shell failed. */
1641 perror(shell);
1642 exit(1);
3c0ef626 1643 }
1644 /*
1645 * Execute the command using the user's shell. This uses the -c
1646 * option to execute the command.
1647 */
e9a17296 1648 argv[0] = (char *) shell0;
3c0ef626 1649 argv[1] = "-c";
1650 argv[2] = (char *) command;
1651 argv[3] = NULL;
1652 execve(shell, argv, env);
1653 perror(shell);
1654 exit(1);
1655}
1656
1657Session *
1658session_new(void)
1659{
1660 int i;
1661 static int did_init = 0;
1662 if (!did_init) {
1663 debug("session_new: init");
e9a17296 1664 for (i = 0; i < MAX_SESSIONS; i++) {
3c0ef626 1665 sessions[i].used = 0;
1666 }
1667 did_init = 1;
1668 }
e9a17296 1669 for (i = 0; i < MAX_SESSIONS; i++) {
3c0ef626 1670 Session *s = &sessions[i];
1671 if (! s->used) {
1672 memset(s, 0, sizeof(*s));
1673 s->chanid = -1;
1674 s->ptyfd = -1;
1675 s->ttyfd = -1;
1676 s->used = 1;
1677 s->self = i;
665a873d 1678 s->x11_chanids = NULL;
3c0ef626 1679 debug("session_new: session %d", i);
1680 return s;
1681 }
1682 }
1683 return NULL;
1684}
1685
1686static void
1687session_dump(void)
1688{
1689 int i;
e9a17296 1690 for (i = 0; i < MAX_SESSIONS; i++) {
3c0ef626 1691 Session *s = &sessions[i];
f5799ae1 1692 debug("dump: used %d session %d %p channel %d pid %ld",
3c0ef626 1693 s->used,
1694 s->self,
1695 s,
1696 s->chanid,
f5799ae1 1697 (long)s->pid);
3c0ef626 1698 }
1699}
1700
1701int
1702session_open(Authctxt *authctxt, int chanid)
1703{
1704 Session *s = session_new();
1705 debug("session_open: channel %d", chanid);
1706 if (s == NULL) {
1707 error("no more sessions");
1708 return 0;
1709 }
1710 s->authctxt = authctxt;
1711 s->pw = authctxt->pw;
cdd66111 1712 if (s->pw == NULL || !authctxt->valid)
3c0ef626 1713 fatal("no user for session %d", s->self);
1714 debug("session_open: session %d: link with channel %d", s->self, chanid);
1715 s->chanid = chanid;
1716 return 1;
1717}
1718
700318f3 1719Session *
1720session_by_tty(char *tty)
1721{
1722 int i;
1723 for (i = 0; i < MAX_SESSIONS; i++) {
1724 Session *s = &sessions[i];
1725 if (s->used && s->ttyfd != -1 && strcmp(s->tty, tty) == 0) {
1726 debug("session_by_tty: session %d tty %s", i, tty);
1727 return s;
1728 }
1729 }
1730 debug("session_by_tty: unknown tty %.100s", tty);
1731 session_dump();
1732 return NULL;
1733}
1734
3c0ef626 1735static Session *
1736session_by_channel(int id)
1737{
1738 int i;
e9a17296 1739 for (i = 0; i < MAX_SESSIONS; i++) {
3c0ef626 1740 Session *s = &sessions[i];
1741 if (s->used && s->chanid == id) {
1742 debug("session_by_channel: session %d channel %d", i, id);
1743 return s;
1744 }
1745 }
1746 debug("session_by_channel: unknown channel %d", id);
1747 session_dump();
1748 return NULL;
1749}
1750
665a873d 1751static Session *
1752session_by_x11_channel(int id)
1753{
1754 int i, j;
1755
1756 for (i = 0; i < MAX_SESSIONS; i++) {
1757 Session *s = &sessions[i];
1758
1759 if (s->x11_chanids == NULL || !s->used)
1760 continue;
1761 for (j = 0; s->x11_chanids[j] != -1; j++) {
1762 if (s->x11_chanids[j] == id) {
1763 debug("session_by_x11_channel: session %d "
1764 "channel %d", s->self, id);
1765 return s;
1766 }
1767 }
1768 }
1769 debug("session_by_x11_channel: unknown channel %d", id);
1770 session_dump();
1771 return NULL;
1772}
1773
3c0ef626 1774static Session *
1775session_by_pid(pid_t pid)
1776{
1777 int i;
f5799ae1 1778 debug("session_by_pid: pid %ld", (long)pid);
e9a17296 1779 for (i = 0; i < MAX_SESSIONS; i++) {
3c0ef626 1780 Session *s = &sessions[i];
1781 if (s->used && s->pid == pid)
1782 return s;
1783 }
f5799ae1 1784 error("session_by_pid: unknown pid %ld", (long)pid);
3c0ef626 1785 session_dump();
1786 return NULL;
1787}
1788
1789static int
1790session_window_change_req(Session *s)
1791{
1792 s->col = packet_get_int();
1793 s->row = packet_get_int();
1794 s->xpixel = packet_get_int();
1795 s->ypixel = packet_get_int();
e9a17296 1796 packet_check_eom();
3c0ef626 1797 pty_change_window_size(s->ptyfd, s->row, s->col, s->xpixel, s->ypixel);
1798 return 1;
1799}
1800
1801static int
1802session_pty_req(Session *s)
1803{
1804 u_int len;
1805 int n_bytes;
1806
1807 if (no_pty_flag) {
1808 debug("Allocating a pty not permitted for this authentication.");
1809 return 0;
1810 }
1811 if (s->ttyfd != -1) {
1812 packet_disconnect("Protocol error: you already have a pty.");
1813 return 0;
1814 }
1815
1816 s->term = packet_get_string(&len);
1817
1818 if (compat20) {
1819 s->col = packet_get_int();
1820 s->row = packet_get_int();
1821 } else {
1822 s->row = packet_get_int();
1823 s->col = packet_get_int();
1824 }
1825 s->xpixel = packet_get_int();
1826 s->ypixel = packet_get_int();
1827
1828 if (strcmp(s->term, "") == 0) {
1829 xfree(s->term);
1830 s->term = NULL;
1831 }
1832
1833 /* Allocate a pty and open it. */
1834 debug("Allocating pty.");
700318f3 1835 if (!PRIVSEP(pty_allocate(&s->ptyfd, &s->ttyfd, s->tty, sizeof(s->tty)))) {
3c0ef626 1836 if (s->term)
1837 xfree(s->term);
1838 s->term = NULL;
1839 s->ptyfd = -1;
1840 s->ttyfd = -1;
1841 error("session_pty_req: session %d alloc failed", s->self);
1842 return 0;
1843 }
1844 debug("session_pty_req: session %d alloc %s", s->self, s->tty);
1845
1846 /* for SSH1 the tty modes length is not given */
1847 if (!compat20)
1848 n_bytes = packet_remaining();
1849 tty_parse_modes(s->ttyfd, &n_bytes);
1850
700318f3 1851 if (!use_privsep)
1852 pty_setowner(s->pw, s->tty);
3c0ef626 1853
1854 /* Set window size from the packet. */
1855 pty_change_window_size(s->ptyfd, s->row, s->col, s->xpixel, s->ypixel);
1856
e9a17296 1857 packet_check_eom();
3c0ef626 1858 session_proctitle(s);
1859 return 1;
1860}
1861
1862static int
1863session_subsystem_req(Session *s)
1864{
1865 struct stat st;
1866 u_int len;
1867 int success = 0;
9108f8d9 1868 char *prog, *cmd, *subsys = packet_get_string(&len);
665a873d 1869 u_int i;
3c0ef626 1870
e9a17296 1871 packet_check_eom();
0fff78ff 1872 logit("subsystem request for %.100s", subsys);
3c0ef626 1873
1874 for (i = 0; i < options.num_subsystems; i++) {
1875 if (strcmp(subsys, options.subsystem_name[i]) == 0) {
9108f8d9 1876 prog = options.subsystem_command[i];
1877 cmd = options.subsystem_args[i];
1878 if (stat(prog, &st) < 0) {
1879 error("subsystem: cannot stat %s: %s", prog,
3c0ef626 1880 strerror(errno));
1881 break;
1882 }
1883 debug("subsystem: exec() %s", cmd);
1884 s->is_subsystem = 1;
1885 do_exec(s, cmd);
1886 success = 1;
e9a17296 1887 break;
3c0ef626 1888 }
1889 }
1890
1891 if (!success)
0fff78ff 1892 logit("subsystem request for %.100s failed, subsystem not found",
3c0ef626 1893 subsys);
1894
1895 xfree(subsys);
1896 return success;
1897}
1898
1899static int
1900session_x11_req(Session *s)
1901{
1902 int success;
1903
665a873d 1904 if (s->auth_proto != NULL || s->auth_data != NULL) {
1905 error("session_x11_req: session %d: "
2c06c99b 1906 "x11 forwarding already active", s->self);
665a873d 1907 return 0;
1908 }
3c0ef626 1909 s->single_connection = packet_get_char();
1910 s->auth_proto = packet_get_string(NULL);
1911 s->auth_data = packet_get_string(NULL);
1912 s->screen = packet_get_int();
e9a17296 1913 packet_check_eom();
3c0ef626 1914
1915 success = session_setup_x11fwd(s);
1916 if (!success) {
1917 xfree(s->auth_proto);
1918 xfree(s->auth_data);
1919 s->auth_proto = NULL;
1920 s->auth_data = NULL;
1921 }
1922 return success;
1923}
1924
1925static int
1926session_shell_req(Session *s)
1927{
e9a17296 1928 packet_check_eom();
3c0ef626 1929 do_exec(s, NULL);
1930 return 1;
1931}
1932
1933static int
1934session_exec_req(Session *s)
1935{
1936 u_int len;
1937 char *command = packet_get_string(&len);
e9a17296 1938 packet_check_eom();
3c0ef626 1939 do_exec(s, command);
1940 xfree(command);
1941 return 1;
1942}
1943
0fff78ff 1944static int
1945session_break_req(Session *s)
1946{
0fff78ff 1947
c9f39d2c 1948 packet_get_int(); /* ignored */
0fff78ff 1949 packet_check_eom();
1950
1951 if (s->ttyfd == -1 ||
1952 tcsendbreak(s->ttyfd, 0) < 0)
1953 return 0;
1954 return 1;
1955}
1956
c9f39d2c 1957static int
1958session_env_req(Session *s)
1959{
1960 char *name, *val;
1961 u_int name_len, val_len, i;
1962
1963 name = packet_get_string(&name_len);
1964 val = packet_get_string(&val_len);
1965 packet_check_eom();
1966
1967 /* Don't set too many environment variables */
1968 if (s->num_env > 128) {
1969 debug2("Ignoring env request %s: too many env vars", name);
1970 goto fail;
1971 }
1972
1973 for (i = 0; i < options.num_accept_env; i++) {
1974 if (match_pattern(name, options.accept_env[i])) {
1975 debug2("Setting env %d: %s=%s", s->num_env, name, val);
9108f8d9 1976 s->env = xrealloc(s->env, s->num_env + 1,
1977 sizeof(*s->env));
c9f39d2c 1978 s->env[s->num_env].name = name;
1979 s->env[s->num_env].val = val;
1980 s->num_env++;
1981 return (1);
1982 }
1983 }
1984 debug2("Ignoring env request %s: disallowed name", name);
1985
1986 fail:
1987 xfree(name);
1988 xfree(val);
1989 return (0);
1990}
1991
3c0ef626 1992static int
1993session_auth_agent_req(Session *s)
1994{
1995 static int called = 0;
e9a17296 1996 packet_check_eom();
3c0ef626 1997 if (no_agent_forwarding_flag) {
1998 debug("session_auth_agent_req: no_agent_forwarding_flag");
1999 return 0;
2000 }
2001 if (called) {
2002 return 0;
2003 } else {
2004 called = 1;
2005 return auth_input_request_forwarding(s->pw);
2006 }
2007}
2008
e9a17296 2009int
2010session_input_channel_req(Channel *c, const char *rtype)
3c0ef626 2011{
3c0ef626 2012 int success = 0;
3c0ef626 2013 Session *s;
3c0ef626 2014
e9a17296 2015 if ((s = session_by_channel(c->self)) == NULL) {
0fff78ff 2016 logit("session_input_channel_req: no session %d req %.100s",
e9a17296 2017 c->self, rtype);
2018 return 0;
2019 }
2020 debug("session_input_channel_req: session %d req %s", s->self, rtype);
3c0ef626 2021
2022 /*
2023 * a session is in LARVAL state until a shell, a command
2024 * or a subsystem is executed
2025 */
2026 if (c->type == SSH_CHANNEL_LARVAL) {
2027 if (strcmp(rtype, "shell") == 0) {
2028 success = session_shell_req(s);
2029 } else if (strcmp(rtype, "exec") == 0) {
2030 success = session_exec_req(s);
2031 } else if (strcmp(rtype, "pty-req") == 0) {
2032 success = session_pty_req(s);
2033 } else if (strcmp(rtype, "x11-req") == 0) {
2034 success = session_x11_req(s);
2035 } else if (strcmp(rtype, "auth-agent-req@openssh.com") == 0) {
2036 success = session_auth_agent_req(s);
2037 } else if (strcmp(rtype, "subsystem") == 0) {
2038 success = session_subsystem_req(s);
c9f39d2c 2039 } else if (strcmp(rtype, "env") == 0) {
2040 success = session_env_req(s);
3c0ef626 2041 }
2042 }
2043 if (strcmp(rtype, "window-change") == 0) {
2044 success = session_window_change_req(s);
c9f39d2c 2045 } else if (strcmp(rtype, "break") == 0) {
2046 success = session_break_req(s);
3c0ef626 2047 }
c9f39d2c 2048
e9a17296 2049 return success;
3c0ef626 2050}
2051
2052void
2053session_set_fds(Session *s, int fdin, int fdout, int fderr)
2054{
2055 if (!compat20)
2056 fatal("session_set_fds: called for proto != 2.0");
2057 /*
2058 * now that have a child and a pipe to the child,
2059 * we can activate our channel and register the fd's
2060 */
2061 if (s->chanid == -1)
2062 fatal("no channel for session %d", s->self);
d6f3ca1e 2063 if(options.hpn_disabled)
2064 channel_set_fds(s->chanid,
2065 fdout, fdin, fderr,
2066 fderr == -1 ? CHAN_EXTENDED_IGNORE : CHAN_EXTENDED_READ,
2067 1,
2068 CHAN_SES_WINDOW_DEFAULT);
2069 else
2070 channel_set_fds(s->chanid,
2071 fdout, fdin, fderr,
2072 fderr == -1 ? CHAN_EXTENDED_IGNORE : CHAN_EXTENDED_READ,
2073 1,
2074 options.hpn_buffer_size);
3c0ef626 2075}
2076
2077/*
2078 * Function to perform pty cleanup. Also called if we get aborted abnormally
2079 * (e.g., due to a dropped connection).
2080 */
700318f3 2081void
cdd66111 2082session_pty_cleanup2(Session *s)
3c0ef626 2083{
3c0ef626 2084 if (s == NULL) {
2085 error("session_pty_cleanup: no session");
2086 return;
2087 }
2088 if (s->ttyfd == -1)
2089 return;
2090
2091 debug("session_pty_cleanup: session %d release %s", s->self, s->tty);
2092
2093 /* Record that the user has logged out. */
2094 if (s->pid != 0)
e9a17296 2095 record_logout(s->pid, s->tty, s->pw->pw_name);
3c0ef626 2096
2097 /* Release the pseudo-tty. */
700318f3 2098 if (getuid() == 0)
2099 pty_release(s->tty);
3c0ef626 2100
2101 /*
2102 * Close the server side of the socket pairs. We must do this after
2103 * the pty cleanup, so that another process doesn't get this pty
2104 * while we're still cleaning up.
2105 */
2106 if (close(s->ptymaster) < 0)
700318f3 2107 error("close(s->ptymaster/%d): %s", s->ptymaster, strerror(errno));
3c0ef626 2108
2109 /* unlink pty from session */
2110 s->ttyfd = -1;
2111}
2112
700318f3 2113void
cdd66111 2114session_pty_cleanup(Session *s)
700318f3 2115{
cdd66111 2116 PRIVSEP(session_pty_cleanup2(s));
700318f3 2117}
2118
41b2f314 2119static char *
2120sig2name(int sig)
2121{
2122#define SSH_SIG(x) if (sig == SIG ## x) return #x
2123 SSH_SIG(ABRT);
2124 SSH_SIG(ALRM);
2125 SSH_SIG(FPE);
2126 SSH_SIG(HUP);
2127 SSH_SIG(ILL);
2128 SSH_SIG(INT);
2129 SSH_SIG(KILL);
2130 SSH_SIG(PIPE);
2131 SSH_SIG(QUIT);
2132 SSH_SIG(SEGV);
2133 SSH_SIG(TERM);
2134 SSH_SIG(USR1);
2135 SSH_SIG(USR2);
2136#undef SSH_SIG
2137 return "SIG@openssh.com";
2138}
2139
665a873d 2140static void
2141session_close_x11(int id)
2142{
2143 Channel *c;
2144
2c06c99b 2145 if ((c = channel_by_id(id)) == NULL) {
665a873d 2146 debug("session_close_x11: x11 channel %d missing", id);
2147 } else {
2148 /* Detach X11 listener */
2149 debug("session_close_x11: detach x11 channel %d", id);
2150 channel_cancel_cleanup(id);
2151 if (c->ostate != CHAN_OUTPUT_CLOSED)
2152 chan_mark_dead(c);
2153 }
2154}
2155
2156static void
2157session_close_single_x11(int id, void *arg)
2158{
2159 Session *s;
2160 u_int i;
2161
2162 debug3("session_close_single_x11: channel %d", id);
2163 channel_cancel_cleanup(id);
2164 if ((s = session_by_x11_channel(id)) == NULL)
2165 fatal("session_close_single_x11: no x11 channel %d", id);
2166 for (i = 0; s->x11_chanids[i] != -1; i++) {
2167 debug("session_close_single_x11: session %d: "
2168 "closing channel %d", s->self, s->x11_chanids[i]);
2169 /*
2170 * The channel "id" is already closing, but make sure we
2171 * close all of its siblings.
2172 */
2173 if (s->x11_chanids[i] != id)
2174 session_close_x11(s->x11_chanids[i]);
2175 }
2176 xfree(s->x11_chanids);
2177 s->x11_chanids = NULL;
2178 if (s->display) {
2179 xfree(s->display);
2180 s->display = NULL;
2181 }
2182 if (s->auth_proto) {
2183 xfree(s->auth_proto);
2184 s->auth_proto = NULL;
2185 }
2186 if (s->auth_data) {
2187 xfree(s->auth_data);
2188 s->auth_data = NULL;
2189 }
2190 if (s->auth_display) {
2191 xfree(s->auth_display);
2192 s->auth_display = NULL;
2193 }
2194}
2195
3c0ef626 2196static void
2197session_exit_message(Session *s, int status)
2198{
2199 Channel *c;
e9a17296 2200
2201 if ((c = channel_lookup(s->chanid)) == NULL)
3c0ef626 2202 fatal("session_exit_message: session %d: no channel %d",
2203 s->self, s->chanid);
f5799ae1 2204 debug("session_exit_message: session %d channel %d pid %ld",
2205 s->self, s->chanid, (long)s->pid);
3c0ef626 2206
2207 if (WIFEXITED(status)) {
e9a17296 2208 channel_request_start(s->chanid, "exit-status", 0);
3c0ef626 2209 packet_put_int(WEXITSTATUS(status));
2210 packet_send();
2211 } else if (WIFSIGNALED(status)) {
e9a17296 2212 channel_request_start(s->chanid, "exit-signal", 0);
41b2f314 2213 packet_put_cstring(sig2name(WTERMSIG(status)));
3c0ef626 2214#ifdef WCOREDUMP
2215 packet_put_char(WCOREDUMP(status));
2216#else /* WCOREDUMP */
2217 packet_put_char(0);
2218#endif /* WCOREDUMP */
2219 packet_put_cstring("");
2220 packet_put_cstring("");
2221 packet_send();
2222 } else {
2223 /* Some weird exit cause. Just exit. */
2224 packet_disconnect("wait returned status %04x.", status);
2225 }
2226
2227 /* disconnect channel */
2228 debug("session_exit_message: release channel %d", s->chanid);
2c06c99b 2229
2230 /*
2231 * Adjust cleanup callback attachment to send close messages when
9108f8d9 2232 * the channel gets EOF. The session will be then be closed
2c06c99b 2233 * by session_close_by_channel when the childs close their fds.
2234 */
2235 channel_register_cleanup(c->self, session_close_by_channel, 1);
2236
3c0ef626 2237 /*
2238 * emulate a write failure with 'chan_write_failed', nobody will be
2239 * interested in data we write.
2240 * Note that we must not call 'chan_read_failed', since there could
2241 * be some more data waiting in the pipe.
2242 */
2243 if (c->ostate != CHAN_OUTPUT_CLOSED)
2244 chan_write_failed(c);
3c0ef626 2245}
2246
700318f3 2247void
3c0ef626 2248session_close(Session *s)
2249{
665a873d 2250 u_int i;
c9f39d2c 2251
f5799ae1 2252 debug("session_close: session %d pid %ld", s->self, (long)s->pid);
cdd66111 2253 if (s->ttyfd != -1)
3c0ef626 2254 session_pty_cleanup(s);
3c0ef626 2255 if (s->term)
2256 xfree(s->term);
2257 if (s->display)
2258 xfree(s->display);
665a873d 2259 if (s->x11_chanids)
2260 xfree(s->x11_chanids);
e9a17296 2261 if (s->auth_display)
2262 xfree(s->auth_display);
3c0ef626 2263 if (s->auth_data)
2264 xfree(s->auth_data);
2265 if (s->auth_proto)
2266 xfree(s->auth_proto);
2267 s->used = 0;
9108f8d9 2268 if (s->env != NULL) {
2269 for (i = 0; i < s->num_env; i++) {
2270 xfree(s->env[i].name);
2271 xfree(s->env[i].val);
2272 }
c9f39d2c 2273 xfree(s->env);
9108f8d9 2274 }
3c0ef626 2275 session_proctitle(s);
2276}
2277
2278void
2279session_close_by_pid(pid_t pid, int status)
2280{
2281 Session *s = session_by_pid(pid);
2282 if (s == NULL) {
f5799ae1 2283 debug("session_close_by_pid: no session for pid %ld",
2284 (long)pid);
3c0ef626 2285 return;
2286 }
2287 if (s->chanid != -1)
2288 session_exit_message(s, status);
2c06c99b 2289 if (s->ttyfd != -1)
2290 session_pty_cleanup(s);
f2f068fa 2291 s->pid = 0;
3c0ef626 2292}
2293
2294/*
2295 * this is called when a channel dies before
2296 * the session 'child' itself dies
2297 */
2298void
2299session_close_by_channel(int id, void *arg)
2300{
2301 Session *s = session_by_channel(id);
2c06c99b 2302 u_int i;
665a873d 2303
3c0ef626 2304 if (s == NULL) {
2305 debug("session_close_by_channel: no session for id %d", id);
2306 return;
2307 }
f5799ae1 2308 debug("session_close_by_channel: channel %d child %ld",
2309 id, (long)s->pid);
3c0ef626 2310 if (s->pid != 0) {
2311 debug("session_close_by_channel: channel %d: has child", id);
2312 /*
2313 * delay detach of session, but release pty, since
2314 * the fd's to the child are already closed
2315 */
cdd66111 2316 if (s->ttyfd != -1)
3c0ef626 2317 session_pty_cleanup(s);
3c0ef626 2318 return;
2319 }
2320 /* detach by removing callback */
2321 channel_cancel_cleanup(s->chanid);
2c06c99b 2322
2323 /* Close any X11 listeners associated with this session */
2324 if (s->x11_chanids != NULL) {
2325 for (i = 0; s->x11_chanids[i] != -1; i++) {
2326 session_close_x11(s->x11_chanids[i]);
2327 s->x11_chanids[i] = -1;
2328 }
2329 }
2330
3c0ef626 2331 s->chanid = -1;
2332 session_close(s);
2333}
2334
2335void
700318f3 2336session_destroy_all(void (*closefunc)(Session *))
3c0ef626 2337{
2338 int i;
e9a17296 2339 for (i = 0; i < MAX_SESSIONS; i++) {
3c0ef626 2340 Session *s = &sessions[i];
700318f3 2341 if (s->used) {
2342 if (closefunc != NULL)
2343 closefunc(s);
2344 else
2345 session_close(s);
2346 }
3c0ef626 2347 }
2348}
2349
2350static char *
2351session_tty_list(void)
2352{
2353 static char buf[1024];
2354 int i;
6a9b3198 2355 char *cp;
2356
3c0ef626 2357 buf[0] = '\0';
e9a17296 2358 for (i = 0; i < MAX_SESSIONS; i++) {
3c0ef626 2359 Session *s = &sessions[i];
2360 if (s->used && s->ttyfd != -1) {
cdd66111 2361
6a9b3198 2362 if (strncmp(s->tty, "/dev/", 5) != 0) {
2363 cp = strrchr(s->tty, '/');
2364 cp = (cp == NULL) ? s->tty : cp + 1;
2365 } else
2366 cp = s->tty + 5;
cdd66111 2367
3c0ef626 2368 if (buf[0] != '\0')
2369 strlcat(buf, ",", sizeof buf);
6a9b3198 2370 strlcat(buf, cp, sizeof buf);
3c0ef626 2371 }
2372 }
2373 if (buf[0] == '\0')
2374 strlcpy(buf, "notty", sizeof buf);
2375 return buf;
2376}
2377
2378void
2379session_proctitle(Session *s)
2380{
2381 if (s->pw == NULL)
2382 error("no user for session %d", s->self);
2383 else
2384 setproctitle("%s@%s", s->pw->pw_name, session_tty_list());
2385}
2386
2387int
2388session_setup_x11fwd(Session *s)
2389{
2390 struct stat st;
e9a17296 2391 char display[512], auth_display[512];
2392 char hostname[MAXHOSTNAMELEN];
665a873d 2393 u_int i;
3c0ef626 2394
2395 if (no_x11_forwarding_flag) {
2396 packet_send_debug("X11 forwarding disabled in user configuration file.");
2397 return 0;
2398 }
2399 if (!options.x11_forwarding) {
2400 debug("X11 forwarding disabled in server configuration file.");
2401 return 0;
2402 }
2403 if (!options.xauth_location ||
2404 (stat(options.xauth_location, &st) == -1)) {
2405 packet_send_debug("No xauth program; cannot forward with spoofing.");
2406 return 0;
2407 }
2408 if (options.use_login) {
2409 packet_send_debug("X11 forwarding disabled; "
2410 "not compatible with UseLogin=yes.");
2411 return 0;
2412 }
2413 if (s->display != NULL) {
2414 debug("X11 display already set.");
2415 return 0;
2416 }
680cee3b 2417 if (x11_create_display_inet(options.x11_display_offset,
2418 options.x11_use_localhost, s->single_connection,
d6f3ca1e 2419 &s->display_number, &s->x11_chanids,
2420 options.hpn_disabled, options.hpn_buffer_size) == -1) {
3c0ef626 2421 debug("x11_create_display_inet failed.");
2422 return 0;
2423 }
665a873d 2424 for (i = 0; s->x11_chanids[i] != -1; i++) {
2425 channel_register_cleanup(s->x11_chanids[i],
2c06c99b 2426 session_close_single_x11, 0);
665a873d 2427 }
e9a17296 2428
2429 /* Set up a suitable value for the DISPLAY variable. */
2430 if (gethostname(hostname, sizeof(hostname)) < 0)
2431 fatal("gethostname: %.100s", strerror(errno));
2432 /*
2433 * auth_display must be used as the displayname when the
2434 * authorization entry is added with xauth(1). This will be
2435 * different than the DISPLAY string for localhost displays.
2436 */
2437 if (options.x11_use_localhost) {
680cee3b 2438 snprintf(display, sizeof display, "localhost:%u.%u",
e9a17296 2439 s->display_number, s->screen);
680cee3b 2440 snprintf(auth_display, sizeof auth_display, "unix:%u.%u",
e9a17296 2441 s->display_number, s->screen);
2442 s->display = xstrdup(display);
2443 s->auth_display = xstrdup(auth_display);
2444 } else {
2445#ifdef IPADDR_IN_DISPLAY
2446 struct hostent *he;
2447 struct in_addr my_addr;
2448
2449 he = gethostbyname(hostname);
2450 if (he == NULL) {
2451 error("Can't get IP address for X11 DISPLAY.");
2452 packet_send_debug("Can't get IP address for X11 DISPLAY.");
2453 return 0;
2454 }
2455 memcpy(&my_addr, he->h_addr_list[0], sizeof(struct in_addr));
680cee3b 2456 snprintf(display, sizeof display, "%.50s:%u.%u", inet_ntoa(my_addr),
e9a17296 2457 s->display_number, s->screen);
2458#else
680cee3b 2459 snprintf(display, sizeof display, "%.400s:%u.%u", hostname,
e9a17296 2460 s->display_number, s->screen);
2461#endif
2462 s->display = xstrdup(display);
2463 s->auth_display = xstrdup(display);
2464 }
2465
3c0ef626 2466 return 1;
2467}
2468
2469static void
2470do_authenticated2(Authctxt *authctxt)
2471{
2472 server_loop2(authctxt);
cdd66111 2473}
2474
2475void
2476do_cleanup(Authctxt *authctxt)
2477{
2478 static int called = 0;
2479
2480 debug("do_cleanup");
2481
2482 /* no cleanup if we're in the child for login shell */
2483 if (is_child)
2484 return;
2485
2486 /* avoid double cleanup */
2487 if (called)
2488 return;
2489 called = 1;
2490
9108f8d9 2491 if (authctxt == NULL || !authctxt->authenticated)
cdd66111 2492 return;
2493#ifdef KRB5
2494 if (options.kerberos_ticket_cleanup &&
2495 authctxt->krb5_ctx)
2496 krb5_cleanup_proc(authctxt);
0fff78ff 2497#endif
cdd66111 2498
2499#ifdef GSSAPI
2500 if (compat20 && options.gss_cleanup_creds)
2501 ssh_gssapi_cleanup_creds();
2502#endif
2503
2504#ifdef USE_PAM
2505 if (options.use_pam) {
2506 sshpam_cleanup();
2507 sshpam_thread_cleanup();
2508 }
2509#endif
2510
2511 /* remove agent socket */
2512 auth_sock_cleanup_proc(authctxt->pw);
2513
2514 /*
2515 * Cleanup ptys/utmp only if privsep is disabled,
2516 * or if running in monitor.
2517 */
2518 if (!use_privsep || mm_is_monitor())
2519 session_destroy_all(session_pty_cleanup2);
3c0ef626 2520}
This page took 0.452622 seconds and 5 git commands to generate.