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