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