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