Annotation of src/usr.bin/ssh/session.c, Revision 1.33
1.1 markus 1: /*
2: * Copyright (c) 1995 Tatu Ylonen <ylo@cs.hut.fi>, Espoo, Finland
3: * All rights reserved
4: */
1.2 markus 5: /*
6: * SSH2 support by Markus Friedl.
7: * Copyright (c) 2000 Markus Friedl. All rights reserved.
8: */
1.1 markus 9:
10: #include "includes.h"
1.33 ! markus 11: RCSID("$OpenBSD: session.c,v 1.33 2000/09/04 18:51:04 markus Exp $");
1.1 markus 12:
13: #include "xmalloc.h"
14: #include "ssh.h"
15: #include "pty.h"
16: #include "packet.h"
17: #include "buffer.h"
18: #include "cipher.h"
19: #include "mpaux.h"
20: #include "servconf.h"
21: #include "uidswap.h"
22: #include "compat.h"
23: #include "channels.h"
24: #include "nchan.h"
25:
1.2 markus 26: #include "bufaux.h"
27: #include "ssh2.h"
28: #include "auth.h"
1.19 markus 29: #include "auth-options.h"
1.2 markus 30:
1.28 millert 31: #ifdef HAVE_LOGIN_CAP
32: #include <login_cap.h>
33: #endif
34:
1.1 markus 35: /* types */
36:
37: #define TTYSZ 64
38: typedef struct Session Session;
39: struct Session {
40: int used;
41: int self;
1.7 markus 42: int extended;
1.1 markus 43: struct passwd *pw;
44: pid_t pid;
45: /* tty */
46: char *term;
47: int ptyfd, ttyfd, ptymaster;
48: int row, col, xpixel, ypixel;
49: char tty[TTYSZ];
50: /* X11 */
51: char *display;
52: int screen;
53: char *auth_proto;
54: char *auth_data;
1.7 markus 55: int single_connection;
1.1 markus 56: /* proto 2 */
57: int chanid;
58: };
59:
60: /* func */
61:
62: Session *session_new(void);
63: void session_set_fds(Session *s, int fdin, int fdout, int fderr);
64: void session_pty_cleanup(Session *s);
1.9 markus 65: void session_proctitle(Session *s);
1.1 markus 66: void do_exec_pty(Session *s, const char *command, struct passwd * pw);
67: void do_exec_no_pty(Session *s, const char *command, struct passwd * pw);
1.24 markus 68: void do_login(Session *s);
1.1 markus 69:
70: void
71: do_child(const char *command, struct passwd * pw, const char *term,
72: const char *display, const char *auth_proto,
73: const char *auth_data, const char *ttyname);
74:
75: /* import */
76: extern ServerOptions options;
77: extern char *__progname;
78: extern int log_stderr;
79: extern int debug_flag;
1.25 markus 80: extern unsigned int utmp_len;
1.1 markus 81:
1.21 markus 82: extern int startup_pipe;
83:
1.1 markus 84: /* Local Xauthority file. */
85: static char *xauthfile;
86:
87: /* data */
88: #define MAX_SESSIONS 10
89: Session sessions[MAX_SESSIONS];
90:
1.28 millert 91: #ifdef HAVE_LOGIN_CAP
92: static login_cap_t *lc;
93: #endif
94:
1.1 markus 95: /*
96: * Remove local Xauthority file.
97: */
98: void
99: xauthfile_cleanup_proc(void *ignore)
100: {
101: debug("xauthfile_cleanup_proc called");
102:
103: if (xauthfile != NULL) {
104: char *p;
105: unlink(xauthfile);
106: p = strrchr(xauthfile, '/');
107: if (p != NULL) {
108: *p = '\0';
109: rmdir(xauthfile);
110: }
111: xfree(xauthfile);
112: xauthfile = NULL;
113: }
114: }
115:
116: /*
117: * Function to perform cleanup if we get aborted abnormally (e.g., due to a
118: * dropped connection).
119: */
1.4 markus 120: void
1.1 markus 121: pty_cleanup_proc(void *session)
122: {
123: Session *s=session;
124: if (s == NULL)
125: fatal("pty_cleanup_proc: no session");
126: debug("pty_cleanup_proc: %s", s->tty);
127:
128: if (s->pid != 0) {
129: /* Record that the user has logged out. */
130: record_logout(s->pid, s->tty);
131: }
132:
133: /* Release the pseudo-tty. */
134: pty_release(s->tty);
135: }
136:
137: /*
138: * Prepares for an interactive session. This is called after the user has
139: * been successfully authenticated. During this message exchange, pseudo
140: * terminals are allocated, X11, TCP/IP, and authentication agent forwardings
141: * are requested, etc.
142: */
1.4 markus 143: void
1.1 markus 144: do_authenticated(struct passwd * pw)
145: {
146: Session *s;
1.33 ! markus 147: int type, fd;
1.1 markus 148: int compression_level = 0, enable_compression_after_reply = 0;
149: int have_pty = 0;
150: char *command;
151: int n_bytes;
152: int plen;
153: unsigned int proto_len, data_len, dlen;
154:
155: /*
156: * Cancel the alarm we set to limit the time taken for
157: * authentication.
158: */
159: alarm(0);
1.23 deraadt 160: if (startup_pipe != -1) {
161: close(startup_pipe);
162: startup_pipe = -1;
163: }
1.1 markus 164:
165: /*
166: * Inform the channel mechanism that we are the server side and that
167: * the client may request to connect to any port at all. (The user
168: * could do it anyway, and we wouldn\'t know what is permitted except
169: * by the client telling us, so we can equally well trust the client
170: * not to request anything bogus.)
171: */
172: if (!no_port_forwarding_flag)
173: channel_permit_all_opens();
174:
175: s = session_new();
1.7 markus 176: s->pw = pw;
1.1 markus 177:
1.28 millert 178: #ifdef HAVE_LOGIN_CAP
179: if ((lc = login_getclass(pw->pw_class)) == NULL) {
180: error("unable to get login class");
181: return;
182: }
183: #endif
184:
1.1 markus 185: /*
186: * We stay in this loop until the client requests to execute a shell
187: * or a command.
188: */
189: for (;;) {
190: int success = 0;
191:
192: /* Get a packet from the client. */
193: type = packet_read(&plen);
194:
195: /* Process the packet. */
196: switch (type) {
197: case SSH_CMSG_REQUEST_COMPRESSION:
198: packet_integrity_check(plen, 4, type);
199: compression_level = packet_get_int();
200: if (compression_level < 1 || compression_level > 9) {
201: packet_send_debug("Received illegal compression level %d.",
202: compression_level);
203: break;
204: }
205: /* Enable compression after we have responded with SUCCESS. */
206: enable_compression_after_reply = 1;
207: success = 1;
208: break;
209:
210: case SSH_CMSG_REQUEST_PTY:
211: if (no_pty_flag) {
212: debug("Allocating a pty not permitted for this authentication.");
213: break;
214: }
215: if (have_pty)
216: packet_disconnect("Protocol error: you already have a pty.");
217:
218: debug("Allocating pty.");
219:
220: /* Allocate a pty and open it. */
221: if (!pty_allocate(&s->ptyfd, &s->ttyfd, s->tty,
222: sizeof(s->tty))) {
223: error("Failed to allocate pty.");
224: break;
225: }
226: fatal_add_cleanup(pty_cleanup_proc, (void *)s);
227: pty_setowner(pw, s->tty);
228:
229: /* Get TERM from the packet. Note that the value may be of arbitrary length. */
230: s->term = packet_get_string(&dlen);
231: packet_integrity_check(dlen, strlen(s->term), type);
232: /* packet_integrity_check(plen, 4 + dlen + 4*4 + n_bytes, type); */
233: /* Remaining bytes */
234: n_bytes = plen - (4 + dlen + 4 * 4);
235:
236: if (strcmp(s->term, "") == 0) {
237: xfree(s->term);
238: s->term = NULL;
239: }
240: /* Get window size from the packet. */
241: s->row = packet_get_int();
242: s->col = packet_get_int();
243: s->xpixel = packet_get_int();
244: s->ypixel = packet_get_int();
245: pty_change_window_size(s->ptyfd, s->row, s->col, s->xpixel, s->ypixel);
246:
247: /* Get tty modes from the packet. */
248: tty_parse_modes(s->ttyfd, &n_bytes);
249: packet_integrity_check(plen, 4 + dlen + 4 * 4 + n_bytes, type);
1.10 markus 250:
251: session_proctitle(s);
1.1 markus 252:
253: /* Indicate that we now have a pty. */
254: success = 1;
255: have_pty = 1;
256: break;
257:
258: case SSH_CMSG_X11_REQUEST_FORWARDING:
259: if (!options.x11_forwarding) {
260: packet_send_debug("X11 forwarding disabled in server configuration file.");
261: break;
262: }
1.16 markus 263: if (!options.xauth_location) {
264: packet_send_debug("No xauth program; cannot forward with spoofing.");
265: break;
266: }
1.1 markus 267: if (no_x11_forwarding_flag) {
268: packet_send_debug("X11 forwarding not permitted for this authentication.");
269: break;
270: }
271: debug("Received request for X11 forwarding with auth spoofing.");
272: if (s->display != NULL)
273: packet_disconnect("Protocol error: X11 display already set.");
274:
275: s->auth_proto = packet_get_string(&proto_len);
276: s->auth_data = packet_get_string(&data_len);
277: packet_integrity_check(plen, 4 + proto_len + 4 + data_len + 4, type);
278:
279: if (packet_get_protocol_flags() & SSH_PROTOFLAG_SCREEN_NUMBER)
280: s->screen = packet_get_int();
281: else
282: s->screen = 0;
283: s->display = x11_create_display_inet(s->screen, options.x11_display_offset);
284:
285: if (s->display == NULL)
286: break;
287:
288: /* Setup to always have a local .Xauthority. */
289: xauthfile = xmalloc(MAXPATHLEN);
290: strlcpy(xauthfile, "/tmp/ssh-XXXXXXXX", MAXPATHLEN);
291: temporarily_use_uid(pw->pw_uid);
292: if (mkdtemp(xauthfile) == NULL) {
293: restore_uid();
294: error("private X11 dir: mkdtemp %s failed: %s",
295: xauthfile, strerror(errno));
296: xfree(xauthfile);
297: xauthfile = NULL;
1.7 markus 298: /* XXXX remove listening channels */
1.1 markus 299: break;
300: }
301: strlcat(xauthfile, "/cookies", MAXPATHLEN);
1.33 ! markus 302: fd = open(xauthfile, O_RDWR|O_CREAT|O_EXCL, 0600);
! 303: if (fd >= 0)
! 304: close(fd);
1.1 markus 305: restore_uid();
306: fatal_add_cleanup(xauthfile_cleanup_proc, NULL);
307: success = 1;
308: break;
309:
310: case SSH_CMSG_AGENT_REQUEST_FORWARDING:
311: if (no_agent_forwarding_flag || compat13) {
312: debug("Authentication agent forwarding not permitted for this authentication.");
313: break;
314: }
315: debug("Received authentication agent forwarding request.");
1.15 markus 316: success = auth_input_request_forwarding(pw);
1.1 markus 317: break;
318:
319: case SSH_CMSG_PORT_FORWARD_REQUEST:
320: if (no_port_forwarding_flag) {
321: debug("Port forwarding not permitted for this authentication.");
322: break;
323: }
324: debug("Received TCP/IP port forwarding request.");
1.12 markus 325: channel_input_port_forward_request(pw->pw_uid == 0, options.gateway_ports);
1.1 markus 326: success = 1;
327: break;
328:
329: case SSH_CMSG_MAX_PACKET_SIZE:
330: if (packet_set_maxsize(packet_get_int()) > 0)
331: success = 1;
332: break;
333:
334: case SSH_CMSG_EXEC_SHELL:
335: case SSH_CMSG_EXEC_CMD:
336: /* Set interactive/non-interactive mode. */
337: packet_set_interactive(have_pty || s->display != NULL,
338: options.keepalives);
339:
340: if (type == SSH_CMSG_EXEC_CMD) {
341: command = packet_get_string(&dlen);
342: debug("Exec command '%.500s'", command);
343: packet_integrity_check(plen, 4 + dlen, type);
344: } else {
345: command = NULL;
346: packet_integrity_check(plen, 0, type);
347: }
348: if (forced_command != NULL) {
349: command = forced_command;
350: debug("Forced command '%.500s'", forced_command);
351: }
352: if (have_pty)
353: do_exec_pty(s, command, pw);
354: else
355: do_exec_no_pty(s, command, pw);
356:
357: if (command != NULL)
358: xfree(command);
359: /* Cleanup user's local Xauthority file. */
360: if (xauthfile)
361: xauthfile_cleanup_proc(NULL);
362: return;
363:
364: default:
365: /*
366: * Any unknown messages in this phase are ignored,
367: * and a failure message is returned.
368: */
369: log("Unknown packet type received after authentication: %d", type);
370: }
371: packet_start(success ? SSH_SMSG_SUCCESS : SSH_SMSG_FAILURE);
372: packet_send();
373: packet_write_wait();
374:
375: /* Enable compression now that we have replied if appropriate. */
376: if (enable_compression_after_reply) {
377: enable_compression_after_reply = 0;
378: packet_start_compression(compression_level);
379: }
380: }
381: }
382:
383: /*
384: * This is called to fork and execute a command when we have no tty. This
385: * will call do_child from the child, and server_loop from the parent after
386: * setting up file descriptors and such.
387: */
1.4 markus 388: void
1.1 markus 389: do_exec_no_pty(Session *s, const char *command, struct passwd * pw)
390: {
391: int pid;
392:
393: #ifdef USE_PIPES
394: int pin[2], pout[2], perr[2];
395: /* Allocate pipes for communicating with the program. */
396: if (pipe(pin) < 0 || pipe(pout) < 0 || pipe(perr) < 0)
397: packet_disconnect("Could not create pipes: %.100s",
398: strerror(errno));
399: #else /* USE_PIPES */
400: int inout[2], err[2];
401: /* Uses socket pairs to communicate with the program. */
402: if (socketpair(AF_UNIX, SOCK_STREAM, 0, inout) < 0 ||
403: socketpair(AF_UNIX, SOCK_STREAM, 0, err) < 0)
404: packet_disconnect("Could not create socket pairs: %.100s",
405: strerror(errno));
406: #endif /* USE_PIPES */
407: if (s == NULL)
408: fatal("do_exec_no_pty: no session");
409:
1.9 markus 410: session_proctitle(s);
1.1 markus 411:
412: /* Fork the child. */
413: if ((pid = fork()) == 0) {
414: /* Child. Reinitialize the log since the pid has changed. */
415: log_init(__progname, options.log_level, options.log_facility, log_stderr);
416:
417: /*
418: * Create a new session and process group since the 4.4BSD
419: * setlogin() affects the entire process group.
420: */
421: if (setsid() < 0)
422: error("setsid failed: %.100s", strerror(errno));
423:
424: #ifdef USE_PIPES
425: /*
426: * Redirect stdin. We close the parent side of the socket
427: * pair, and make the child side the standard input.
428: */
429: close(pin[1]);
430: if (dup2(pin[0], 0) < 0)
431: perror("dup2 stdin");
432: close(pin[0]);
433:
434: /* Redirect stdout. */
435: close(pout[0]);
436: if (dup2(pout[1], 1) < 0)
437: perror("dup2 stdout");
438: close(pout[1]);
439:
440: /* Redirect stderr. */
441: close(perr[0]);
442: if (dup2(perr[1], 2) < 0)
443: perror("dup2 stderr");
444: close(perr[1]);
445: #else /* USE_PIPES */
446: /*
447: * Redirect stdin, stdout, and stderr. Stdin and stdout will
448: * use the same socket, as some programs (particularly rdist)
449: * seem to depend on it.
450: */
451: close(inout[1]);
452: close(err[1]);
453: if (dup2(inout[0], 0) < 0) /* stdin */
454: perror("dup2 stdin");
455: if (dup2(inout[0], 1) < 0) /* stdout. Note: same socket as stdin. */
456: perror("dup2 stdout");
457: if (dup2(err[0], 2) < 0) /* stderr */
458: perror("dup2 stderr");
459: #endif /* USE_PIPES */
460:
461: /* Do processing for the child (exec command etc). */
462: do_child(command, pw, NULL, s->display, s->auth_proto, s->auth_data, NULL);
463: /* NOTREACHED */
464: }
465: if (pid < 0)
466: packet_disconnect("fork failed: %.100s", strerror(errno));
467: s->pid = pid;
468: #ifdef USE_PIPES
469: /* We are the parent. Close the child sides of the pipes. */
470: close(pin[0]);
471: close(pout[1]);
472: close(perr[1]);
473:
1.2 markus 474: if (compat20) {
1.7 markus 475: session_set_fds(s, pin[1], pout[0], s->extended ? perr[0] : -1);
1.2 markus 476: } else {
477: /* Enter the interactive session. */
478: server_loop(pid, pin[1], pout[0], perr[0]);
479: /* server_loop has closed pin[1], pout[1], and perr[1]. */
480: }
1.1 markus 481: #else /* USE_PIPES */
482: /* We are the parent. Close the child sides of the socket pairs. */
483: close(inout[0]);
484: close(err[0]);
485:
486: /*
487: * Enter the interactive session. Note: server_loop must be able to
488: * handle the case that fdin and fdout are the same.
489: */
1.2 markus 490: if (compat20) {
1.7 markus 491: session_set_fds(s, inout[1], inout[1], s->extended ? err[1] : -1);
1.2 markus 492: } else {
493: server_loop(pid, inout[1], inout[1], err[1]);
494: /* server_loop has closed inout[1] and err[1]. */
495: }
1.1 markus 496: #endif /* USE_PIPES */
497: }
498:
499: /*
500: * This is called to fork and execute a command when we have a tty. This
501: * will call do_child from the child, and server_loop from the parent after
502: * setting up file descriptors, controlling tty, updating wtmp, utmp,
503: * lastlog, and other such operations.
504: */
1.4 markus 505: void
1.1 markus 506: do_exec_pty(Session *s, const char *command, struct passwd * pw)
507: {
508: int fdout, ptyfd, ttyfd, ptymaster;
509: pid_t pid;
510:
511: if (s == NULL)
512: fatal("do_exec_pty: no session");
513: ptyfd = s->ptyfd;
514: ttyfd = s->ttyfd;
515:
516: /* Fork the child. */
517: if ((pid = fork()) == 0) {
1.24 markus 518: /* Child. Reinitialize the log because the pid has changed. */
1.1 markus 519: log_init(__progname, options.log_level, options.log_facility, log_stderr);
520:
521: /* Close the master side of the pseudo tty. */
522: close(ptyfd);
523:
524: /* Make the pseudo tty our controlling tty. */
525: pty_make_controlling_tty(&ttyfd, s->tty);
526:
527: /* Redirect stdin from the pseudo tty. */
528: if (dup2(ttyfd, fileno(stdin)) < 0)
529: error("dup2 stdin failed: %.100s", strerror(errno));
530:
531: /* Redirect stdout to the pseudo tty. */
532: if (dup2(ttyfd, fileno(stdout)) < 0)
533: error("dup2 stdin failed: %.100s", strerror(errno));
534:
535: /* Redirect stderr to the pseudo tty. */
536: if (dup2(ttyfd, fileno(stderr)) < 0)
537: error("dup2 stdin failed: %.100s", strerror(errno));
538:
539: /* Close the extra descriptor for the pseudo tty. */
540: close(ttyfd);
541:
1.24 markus 542: /* record login, etc. similar to login(1) */
543: if (command == NULL && !options.use_login)
544: do_login(s);
1.1 markus 545:
546: /* Do common processing for the child, such as execing the command. */
1.14 deraadt 547: do_child(command, pw, s->term, s->display, s->auth_proto,
548: s->auth_data, s->tty);
1.1 markus 549: /* NOTREACHED */
550: }
551: if (pid < 0)
552: packet_disconnect("fork failed: %.100s", strerror(errno));
553: s->pid = pid;
554:
555: /* Parent. Close the slave side of the pseudo tty. */
556: close(ttyfd);
557:
558: /*
559: * Create another descriptor of the pty master side for use as the
560: * standard input. We could use the original descriptor, but this
561: * simplifies code in server_loop. The descriptor is bidirectional.
562: */
563: fdout = dup(ptyfd);
564: if (fdout < 0)
565: packet_disconnect("dup #1 failed: %.100s", strerror(errno));
566:
567: /* we keep a reference to the pty master */
568: ptymaster = dup(ptyfd);
569: if (ptymaster < 0)
570: packet_disconnect("dup #2 failed: %.100s", strerror(errno));
571: s->ptymaster = ptymaster;
572:
573: /* Enter interactive session. */
1.2 markus 574: if (compat20) {
575: session_set_fds(s, ptyfd, fdout, -1);
576: } else {
577: server_loop(pid, ptyfd, fdout, -1);
578: /* server_loop _has_ closed ptyfd and fdout. */
579: session_pty_cleanup(s);
1.24 markus 580: }
581: }
582:
1.25 markus 583: const char *
584: get_remote_name_or_ip(void)
585: {
586: static const char *remote = "";
587: if (utmp_len > 0)
588: remote = get_canonical_hostname();
589: if (utmp_len == 0 || strlen(remote) > utmp_len)
590: remote = get_remote_ipaddr();
591: return remote;
592: }
593:
1.24 markus 594: /* administrative, login(1)-like work */
595: void
596: do_login(Session *s)
597: {
598: FILE *f;
599: char *time_string;
600: char buf[256];
601: socklen_t fromlen;
602: struct sockaddr_storage from;
603: struct stat st;
604: time_t last_login_time;
605: struct passwd * pw = s->pw;
606: pid_t pid = getpid();
607:
608: /*
609: * Get IP address of client. If the connection is not a socket, let
610: * the address be 0.0.0.0.
611: */
612: memset(&from, 0, sizeof(from));
613: if (packet_connection_is_on_socket()) {
614: fromlen = sizeof(from);
615: if (getpeername(packet_get_connection_in(),
616: (struct sockaddr *) & from, &fromlen) < 0) {
617: debug("getpeername: %.100s", strerror(errno));
618: fatal_cleanup();
619: }
620: }
1.25 markus 621:
1.24 markus 622: /* Record that there was a login on that tty from the remote host. */
623: record_login(pid, s->tty, pw->pw_name, pw->pw_uid,
1.25 markus 624: get_remote_name_or_ip(), (struct sockaddr *)&from);
1.24 markus 625:
626: /* Done if .hushlogin exists. */
627: snprintf(buf, sizeof(buf), "%.200s/.hushlogin", pw->pw_dir);
1.28 millert 628: #ifdef HAVE_LOGIN_CAP
629: if (login_getcapbool(lc, "hushlogin", 0) || stat(buf, &st) >= 0)
630: #else
1.24 markus 631: if (stat(buf, &st) >= 0)
1.28 millert 632: #endif
1.24 markus 633: return;
634: /*
635: * Get the time when the user last logged in. 'buf' will be set
636: * to contain the hostname the last login was from.
637: */
638: last_login_time = get_last_login_time(pw->pw_uid, pw->pw_name,
639: buf, sizeof(buf));
640: if (last_login_time != 0) {
641: time_string = ctime(&last_login_time);
642: if (strchr(time_string, '\n'))
643: *strchr(time_string, '\n') = 0;
644: if (strcmp(buf, "") == 0)
645: printf("Last login: %s\r\n", time_string);
646: else
647: printf("Last login: %s from %s\r\n", time_string, buf);
648: }
649: if (options.print_motd) {
1.28 millert 650: #ifdef HAVE_LOGIN_CAP
651: f = fopen(login_getcapstr(lc, "welcome", "/etc/motd",
652: "/etc/motd"), "r");
653: #else
1.24 markus 654: f = fopen("/etc/motd", "r");
1.28 millert 655: #endif
1.24 markus 656: if (f) {
657: while (fgets(buf, sizeof(buf), f))
658: fputs(buf, stdout);
659: fclose(f);
660: }
1.2 markus 661: }
1.1 markus 662: }
663:
664: /*
665: * Sets the value of the given variable in the environment. If the variable
666: * already exists, its value is overriden.
667: */
1.4 markus 668: void
1.1 markus 669: child_set_env(char ***envp, unsigned int *envsizep, const char *name,
670: const char *value)
671: {
672: unsigned int i, namelen;
673: char **env;
674:
675: /*
676: * Find the slot where the value should be stored. If the variable
677: * already exists, we reuse the slot; otherwise we append a new slot
678: * at the end of the array, expanding if necessary.
679: */
680: env = *envp;
681: namelen = strlen(name);
682: for (i = 0; env[i]; i++)
683: if (strncmp(env[i], name, namelen) == 0 && env[i][namelen] == '=')
684: break;
685: if (env[i]) {
686: /* Reuse the slot. */
687: xfree(env[i]);
688: } else {
689: /* New variable. Expand if necessary. */
690: if (i >= (*envsizep) - 1) {
691: (*envsizep) += 50;
692: env = (*envp) = xrealloc(env, (*envsizep) * sizeof(char *));
693: }
694: /* Need to set the NULL pointer at end of array beyond the new slot. */
695: env[i + 1] = NULL;
696: }
697:
698: /* Allocate space and format the variable in the appropriate slot. */
699: env[i] = xmalloc(strlen(name) + 1 + strlen(value) + 1);
700: snprintf(env[i], strlen(name) + 1 + strlen(value) + 1, "%s=%s", name, value);
701: }
702:
703: /*
704: * Reads environment variables from the given file and adds/overrides them
705: * into the environment. If the file does not exist, this does nothing.
706: * Otherwise, it must consist of empty lines, comments (line starts with '#')
707: * and assignments of the form name=value. No other forms are allowed.
708: */
1.4 markus 709: void
1.1 markus 710: read_environment_file(char ***env, unsigned int *envsize,
711: const char *filename)
712: {
713: FILE *f;
714: char buf[4096];
715: char *cp, *value;
716:
717: f = fopen(filename, "r");
718: if (!f)
719: return;
720:
721: while (fgets(buf, sizeof(buf), f)) {
722: for (cp = buf; *cp == ' ' || *cp == '\t'; cp++)
723: ;
724: if (!*cp || *cp == '#' || *cp == '\n')
725: continue;
726: if (strchr(cp, '\n'))
727: *strchr(cp, '\n') = '\0';
728: value = strchr(cp, '=');
729: if (value == NULL) {
730: fprintf(stderr, "Bad line in %.100s: %.200s\n", filename, buf);
731: continue;
732: }
1.14 deraadt 733: /*
734: * Replace the equals sign by nul, and advance value to
735: * the value string.
736: */
1.1 markus 737: *value = '\0';
738: value++;
739: child_set_env(env, envsize, cp, value);
740: }
741: fclose(f);
742: }
743:
744: /*
745: * Performs common processing for the child, such as setting up the
746: * environment, closing extra file descriptors, setting the user and group
747: * ids, and executing the command or shell.
748: */
1.4 markus 749: void
1.1 markus 750: do_child(const char *command, struct passwd * pw, const char *term,
751: const char *display, const char *auth_proto,
752: const char *auth_data, const char *ttyname)
753: {
1.32 markus 754: const char *shell, *hostname = NULL, *cp = NULL;
1.1 markus 755: char buf[256];
1.16 markus 756: char cmd[1024];
1.27 millert 757: FILE *f = NULL;
1.1 markus 758: unsigned int envsize, i;
759: char **env;
760: extern char **environ;
761: struct stat st;
762: char *argv[10];
1.17 markus 763:
764: /* login(1) is only called if we execute the login shell */
765: if (options.use_login && command != NULL)
766: options.use_login = 0;
1.1 markus 767:
1.27 millert 768: if (!options.use_login) {
1.28 millert 769: #ifdef HAVE_LOGIN_CAP
770: if (!login_getcapbool(lc, "ignorenologin", 0) && pw->pw_uid)
771: f = fopen(login_getcapstr(lc, "nologin", _PATH_NOLOGIN,
772: _PATH_NOLOGIN), "r");
773: #else
1.27 millert 774: if (pw->pw_uid)
775: f = fopen(_PATH_NOLOGIN, "r");
1.28 millert 776: #endif
1.27 millert 777: if (f) {
778: /* /etc/nologin exists. Print its contents and exit. */
779: while (fgets(buf, sizeof(buf), f))
780: fputs(buf, stderr);
781: fclose(f);
1.1 markus 782: exit(254);
1.27 millert 783: }
1.1 markus 784: }
1.28 millert 785: /* Set login name, uid, gid, and groups. */
1.1 markus 786: /* Login(1) does this as well, and it needs uid 0 for the "-h"
787: switch, so we let login(1) to this for us. */
788: if (!options.use_login) {
789: if (getuid() == 0 || geteuid() == 0) {
1.28 millert 790: #ifdef HAVE_LOGIN_CAP
791: if (setusercontext(lc, pw, pw->pw_uid,
792: (LOGIN_SETALL & ~LOGIN_SETPATH)) < 0) {
793: perror("unable to set user context");
794: exit(1);
795:
796: }
797: #else
798: if (setlogin(pw->pw_name) < 0)
799: error("setlogin failed: %s", strerror(errno));
1.1 markus 800: if (setgid(pw->pw_gid) < 0) {
801: perror("setgid");
802: exit(1);
803: }
804: /* Initialize the group list. */
805: if (initgroups(pw->pw_name, pw->pw_gid) < 0) {
806: perror("initgroups");
807: exit(1);
808: }
809: endgrent();
810:
811: /* Permanently switch to the desired uid. */
812: permanently_set_uid(pw->pw_uid);
1.28 millert 813: #endif
1.1 markus 814: }
815: if (getuid() != pw->pw_uid || geteuid() != pw->pw_uid)
1.31 deraadt 816: fatal("Failed to set uids to %u.", (u_int) pw->pw_uid);
1.1 markus 817: }
818: /*
819: * Get the shell from the password data. An empty shell field is
820: * legal, and means /bin/sh.
821: */
822: shell = (pw->pw_shell[0] == '\0') ? _PATH_BSHELL : pw->pw_shell;
1.28 millert 823: #ifdef HAVE_LOGIN_CAP
824: shell = login_getcapstr(lc, "shell", (char *)shell, (char *)shell);
825: #endif
1.1 markus 826:
827: #ifdef AFS
828: /* Try to get AFS tokens for the local cell. */
829: if (k_hasafs()) {
830: char cell[64];
831:
832: if (k_afs_cell_of_file(pw->pw_dir, cell, sizeof(cell)) == 0)
833: krb_afslog(cell, 0);
834:
835: krb_afslog(0, 0);
836: }
837: #endif /* AFS */
838:
839: /* Initialize the environment. */
840: envsize = 100;
841: env = xmalloc(envsize * sizeof(char *));
842: env[0] = NULL;
843:
844: if (!options.use_login) {
845: /* Set basic environment. */
846: child_set_env(&env, &envsize, "USER", pw->pw_name);
847: child_set_env(&env, &envsize, "LOGNAME", pw->pw_name);
848: child_set_env(&env, &envsize, "HOME", pw->pw_dir);
1.28 millert 849: #ifdef HAVE_LOGIN_CAP
1.29 millert 850: (void) setusercontext(lc, pw, pw->pw_uid, LOGIN_SETPATH);
851: child_set_env(&env, &envsize, "PATH", getenv("PATH"));
1.28 millert 852: #else
1.29 millert 853: child_set_env(&env, &envsize, "PATH", _PATH_STDPATH);
1.28 millert 854: #endif
1.1 markus 855:
856: snprintf(buf, sizeof buf, "%.200s/%.50s",
857: _PATH_MAILDIR, pw->pw_name);
858: child_set_env(&env, &envsize, "MAIL", buf);
859:
860: /* Normal systems set SHELL by default. */
861: child_set_env(&env, &envsize, "SHELL", shell);
862: }
863: if (getenv("TZ"))
864: child_set_env(&env, &envsize, "TZ", getenv("TZ"));
865:
866: /* Set custom environment options from RSA authentication. */
867: while (custom_environment) {
868: struct envstring *ce = custom_environment;
869: char *s = ce->s;
870: int i;
871: for (i = 0; s[i] != '=' && s[i]; i++);
872: if (s[i] == '=') {
873: s[i] = 0;
874: child_set_env(&env, &envsize, s, s + i + 1);
875: }
876: custom_environment = ce->next;
877: xfree(ce->s);
878: xfree(ce);
879: }
880:
881: snprintf(buf, sizeof buf, "%.50s %d %d",
882: get_remote_ipaddr(), get_remote_port(), get_local_port());
883: child_set_env(&env, &envsize, "SSH_CLIENT", buf);
884:
885: if (ttyname)
886: child_set_env(&env, &envsize, "SSH_TTY", ttyname);
887: if (term)
888: child_set_env(&env, &envsize, "TERM", term);
889: if (display)
890: child_set_env(&env, &envsize, "DISPLAY", display);
891:
892: #ifdef KRB4
893: {
894: extern char *ticket;
895:
896: if (ticket)
897: child_set_env(&env, &envsize, "KRBTKFILE", ticket);
898: }
899: #endif /* KRB4 */
900:
901: if (xauthfile)
902: child_set_env(&env, &envsize, "XAUTHORITY", xauthfile);
903: if (auth_get_socket_name() != NULL)
904: child_set_env(&env, &envsize, SSH_AUTHSOCKET_ENV_NAME,
905: auth_get_socket_name());
906:
907: /* read $HOME/.ssh/environment. */
908: if (!options.use_login) {
1.14 deraadt 909: snprintf(buf, sizeof buf, "%.200s/.ssh/environment",
910: pw->pw_dir);
1.1 markus 911: read_environment_file(&env, &envsize, buf);
912: }
913: if (debug_flag) {
914: /* dump the environment */
915: fprintf(stderr, "Environment:\n");
916: for (i = 0; env[i]; i++)
917: fprintf(stderr, " %.200s\n", env[i]);
918: }
1.26 millert 919: /* we have to stash the hostname before we close our socket. */
920: if (options.use_login)
921: hostname = get_remote_name_or_ip();
1.1 markus 922: /*
923: * Close the connection descriptors; note that this is the child, and
924: * the server will still have the socket open, and it is important
925: * that we do not shutdown it. Note that the descriptors cannot be
926: * closed before building the environment, as we call
927: * get_remote_ipaddr there.
928: */
929: if (packet_get_connection_in() == packet_get_connection_out())
930: close(packet_get_connection_in());
931: else {
932: close(packet_get_connection_in());
933: close(packet_get_connection_out());
934: }
935: /*
936: * Close all descriptors related to channels. They will still remain
937: * open in the parent.
938: */
939: /* XXX better use close-on-exec? -markus */
940: channel_close_all();
941:
942: /*
943: * Close any extra file descriptors. Note that there may still be
944: * descriptors left by system functions. They will be closed later.
945: */
946: endpwent();
947:
948: /*
949: * Close any extra open file descriptors so that we don\'t have them
950: * hanging around in clients. Note that we want to do this after
951: * initgroups, because at least on Solaris 2.3 it leaves file
952: * descriptors open.
953: */
954: for (i = 3; i < 64; i++)
955: close(i);
956:
957: /* Change current directory to the user\'s home directory. */
1.28 millert 958: if (chdir(pw->pw_dir) < 0) {
1.1 markus 959: fprintf(stderr, "Could not chdir to home directory %s: %s\n",
960: pw->pw_dir, strerror(errno));
1.28 millert 961: #ifdef HAVE_LOGIN_CAP
962: if (login_getcapbool(lc, "requirehome", 0))
963: exit(1);
964: #endif
965: }
1.1 markus 966:
967: /*
968: * Must take new environment into use so that .ssh/rc, /etc/sshrc and
969: * xauth are run in the proper environment.
970: */
971: environ = env;
972:
973: /*
974: * Run $HOME/.ssh/rc, /etc/sshrc, or xauth (whichever is found first
975: * in this order).
976: */
977: if (!options.use_login) {
978: if (stat(SSH_USER_RC, &st) >= 0) {
979: if (debug_flag)
980: fprintf(stderr, "Running /bin/sh %s\n", SSH_USER_RC);
981:
982: f = popen("/bin/sh " SSH_USER_RC, "w");
983: if (f) {
984: if (auth_proto != NULL && auth_data != NULL)
985: fprintf(f, "%s %s\n", auth_proto, auth_data);
986: pclose(f);
987: } else
988: fprintf(stderr, "Could not run %s\n", SSH_USER_RC);
989: } else if (stat(SSH_SYSTEM_RC, &st) >= 0) {
990: if (debug_flag)
991: fprintf(stderr, "Running /bin/sh %s\n", SSH_SYSTEM_RC);
992:
993: f = popen("/bin/sh " SSH_SYSTEM_RC, "w");
994: if (f) {
995: if (auth_proto != NULL && auth_data != NULL)
996: fprintf(f, "%s %s\n", auth_proto, auth_data);
997: pclose(f);
998: } else
999: fprintf(stderr, "Could not run %s\n", SSH_SYSTEM_RC);
1.16 markus 1000: } else if (options.xauth_location != NULL) {
1.1 markus 1001: /* Add authority data to .Xauthority if appropriate. */
1002: if (auth_proto != NULL && auth_data != NULL) {
1.13 markus 1003: char *screen = strchr(display, ':');
1004: if (debug_flag) {
1.14 deraadt 1005: fprintf(stderr,
1006: "Running %.100s add %.100s %.100s %.100s\n",
1.16 markus 1007: options.xauth_location, display,
1008: auth_proto, auth_data);
1.13 markus 1009: if (screen != NULL)
1.14 deraadt 1010: fprintf(stderr,
1011: "Adding %.*s/unix%s %s %s\n",
1.30 deraadt 1012: (int)(screen-display), display,
1.14 deraadt 1013: screen, auth_proto, auth_data);
1.13 markus 1014: }
1.16 markus 1015: snprintf(cmd, sizeof cmd, "%s -q -",
1016: options.xauth_location);
1017: f = popen(cmd, "w");
1.1 markus 1018: if (f) {
1.14 deraadt 1019: fprintf(f, "add %s %s %s\n", display,
1020: auth_proto, auth_data);
1.13 markus 1021: if (screen != NULL)
1022: fprintf(f, "add %.*s/unix%s %s %s\n",
1.30 deraadt 1023: (int)(screen-display), display,
1.14 deraadt 1024: screen, auth_proto, auth_data);
1.1 markus 1025: pclose(f);
1.16 markus 1026: } else {
1027: fprintf(stderr, "Could not run %s\n",
1028: cmd);
1029: }
1.1 markus 1030: }
1031: }
1032: /* Get the last component of the shell name. */
1033: cp = strrchr(shell, '/');
1034: if (cp)
1035: cp++;
1036: else
1037: cp = shell;
1038: }
1039: /*
1040: * If we have no command, execute the shell. In this case, the shell
1041: * name to be passed in argv[0] is preceded by '-' to indicate that
1042: * this is a login shell.
1043: */
1044: if (!command) {
1045: if (!options.use_login) {
1046: char buf[256];
1047:
1048: /*
1049: * Check for mail if we have a tty and it was enabled
1050: * in server options.
1051: */
1052: if (ttyname && options.check_mail) {
1053: char *mailbox;
1054: struct stat mailstat;
1055: mailbox = getenv("MAIL");
1056: if (mailbox != NULL) {
1.14 deraadt 1057: if (stat(mailbox, &mailstat) != 0 ||
1058: mailstat.st_size == 0)
1.1 markus 1059: printf("No mail.\n");
1060: else if (mailstat.st_mtime < mailstat.st_atime)
1061: printf("You have mail.\n");
1062: else
1063: printf("You have new mail.\n");
1064: }
1065: }
1066: /* Start the shell. Set initial character to '-'. */
1067: buf[0] = '-';
1068: strncpy(buf + 1, cp, sizeof(buf) - 1);
1069: buf[sizeof(buf) - 1] = 0;
1070:
1071: /* Execute the shell. */
1072: argv[0] = buf;
1073: argv[1] = NULL;
1074: execve(shell, argv, env);
1075:
1076: /* Executing the shell failed. */
1077: perror(shell);
1078: exit(1);
1079:
1080: } else {
1081: /* Launch login(1). */
1082:
1.26 millert 1083: execl("/usr/bin/login", "login", "-h", hostname,
1.25 markus 1084: "-p", "-f", "--", pw->pw_name, NULL);
1.1 markus 1085:
1086: /* Login couldn't be executed, die. */
1087:
1088: perror("login");
1089: exit(1);
1090: }
1091: }
1092: /*
1093: * Execute the command using the user's shell. This uses the -c
1094: * option to execute the command.
1095: */
1096: argv[0] = (char *) cp;
1097: argv[1] = "-c";
1098: argv[2] = (char *) command;
1099: argv[3] = NULL;
1100: execve(shell, argv, env);
1101: perror(shell);
1102: exit(1);
1103: }
1104:
1105: Session *
1106: session_new(void)
1107: {
1108: int i;
1109: static int did_init = 0;
1110: if (!did_init) {
1111: debug("session_new: init");
1112: for(i = 0; i < MAX_SESSIONS; i++) {
1113: sessions[i].used = 0;
1114: sessions[i].self = i;
1115: }
1116: did_init = 1;
1117: }
1118: for(i = 0; i < MAX_SESSIONS; i++) {
1119: Session *s = &sessions[i];
1120: if (! s->used) {
1121: s->pid = 0;
1.7 markus 1122: s->extended = 0;
1.1 markus 1123: s->chanid = -1;
1124: s->ptyfd = -1;
1125: s->ttyfd = -1;
1126: s->term = NULL;
1127: s->pw = NULL;
1128: s->display = NULL;
1129: s->screen = 0;
1130: s->auth_data = NULL;
1131: s->auth_proto = NULL;
1132: s->used = 1;
1.7 markus 1133: s->pw = NULL;
1.1 markus 1134: debug("session_new: session %d", i);
1135: return s;
1136: }
1137: }
1138: return NULL;
1139: }
1140:
1141: void
1142: session_dump(void)
1143: {
1144: int i;
1145: for(i = 0; i < MAX_SESSIONS; i++) {
1146: Session *s = &sessions[i];
1147: debug("dump: used %d session %d %p channel %d pid %d",
1148: s->used,
1149: s->self,
1150: s,
1151: s->chanid,
1152: s->pid);
1153: }
1154: }
1155:
1.2 markus 1156: int
1157: session_open(int chanid)
1158: {
1159: Session *s = session_new();
1160: debug("session_open: channel %d", chanid);
1161: if (s == NULL) {
1162: error("no more sessions");
1163: return 0;
1164: }
1.7 markus 1165: s->pw = auth_get_user();
1166: if (s->pw == NULL)
1167: fatal("no user for session %i", s->self);
1.2 markus 1168: debug("session_open: session %d: link with channel %d", s->self, chanid);
1169: s->chanid = chanid;
1170: return 1;
1171: }
1172:
1173: Session *
1174: session_by_channel(int id)
1175: {
1176: int i;
1177: for(i = 0; i < MAX_SESSIONS; i++) {
1178: Session *s = &sessions[i];
1179: if (s->used && s->chanid == id) {
1180: debug("session_by_channel: session %d channel %d", i, id);
1181: return s;
1182: }
1183: }
1184: debug("session_by_channel: unknown channel %d", id);
1185: session_dump();
1186: return NULL;
1187: }
1188:
1189: Session *
1190: session_by_pid(pid_t pid)
1191: {
1192: int i;
1193: debug("session_by_pid: pid %d", pid);
1194: for(i = 0; i < MAX_SESSIONS; i++) {
1195: Session *s = &sessions[i];
1196: if (s->used && s->pid == pid)
1197: return s;
1198: }
1199: error("session_by_pid: unknown pid %d", pid);
1200: session_dump();
1201: return NULL;
1202: }
1203:
1204: int
1205: session_window_change_req(Session *s)
1206: {
1207: s->col = packet_get_int();
1208: s->row = packet_get_int();
1209: s->xpixel = packet_get_int();
1210: s->ypixel = packet_get_int();
1.3 markus 1211: packet_done();
1.2 markus 1212: pty_change_window_size(s->ptyfd, s->row, s->col, s->xpixel, s->ypixel);
1213: return 1;
1214: }
1215:
1216: int
1217: session_pty_req(Session *s)
1218: {
1219: unsigned int len;
1.3 markus 1220: char *term_modes; /* encoded terminal modes */
1.2 markus 1221:
1.19 markus 1222: if (no_pty_flag)
1223: return 0;
1.2 markus 1224: if (s->ttyfd != -1)
1.3 markus 1225: return 0;
1.2 markus 1226: s->term = packet_get_string(&len);
1227: s->col = packet_get_int();
1228: s->row = packet_get_int();
1229: s->xpixel = packet_get_int();
1230: s->ypixel = packet_get_int();
1.3 markus 1231: term_modes = packet_get_string(&len);
1232: packet_done();
1.2 markus 1233:
1234: if (strcmp(s->term, "") == 0) {
1235: xfree(s->term);
1236: s->term = NULL;
1237: }
1238: /* Allocate a pty and open it. */
1239: if (!pty_allocate(&s->ptyfd, &s->ttyfd, s->tty, sizeof(s->tty))) {
1240: xfree(s->term);
1241: s->term = NULL;
1242: s->ptyfd = -1;
1243: s->ttyfd = -1;
1244: error("session_pty_req: session %d alloc failed", s->self);
1.3 markus 1245: xfree(term_modes);
1246: return 0;
1.2 markus 1247: }
1248: debug("session_pty_req: session %d alloc %s", s->self, s->tty);
1249: /*
1250: * Add a cleanup function to clear the utmp entry and record logout
1251: * time in case we call fatal() (e.g., the connection gets closed).
1252: */
1253: fatal_add_cleanup(pty_cleanup_proc, (void *)s);
1254: pty_setowner(s->pw, s->tty);
1255: /* Get window size from the packet. */
1256: pty_change_window_size(s->ptyfd, s->row, s->col, s->xpixel, s->ypixel);
1257:
1.9 markus 1258: session_proctitle(s);
1259:
1.3 markus 1260: /* XXX parse and set terminal modes */
1261: xfree(term_modes);
1.2 markus 1262: return 1;
1263: }
1264:
1.7 markus 1265: int
1266: session_subsystem_req(Session *s)
1267: {
1268: unsigned int len;
1269: int success = 0;
1270: char *subsys = packet_get_string(&len);
1.18 jakob 1271: int i;
1.7 markus 1272:
1273: packet_done();
1274: log("subsystem request for %s", subsys);
1.18 jakob 1275:
1276: for (i = 0; i < options.num_subsystems; i++) {
1277: if(strcmp(subsys, options.subsystem_name[i]) == 0) {
1278: debug("subsystem: exec() %s", options.subsystem_command[i]);
1279: do_exec_no_pty(s, options.subsystem_command[i], s->pw);
1280: success = 1;
1281: }
1282: }
1283:
1284: if (!success)
1285: log("subsystem request for %s failed, subsystem not found", subsys);
1.7 markus 1286:
1287: xfree(subsys);
1288: return success;
1289: }
1290:
1291: int
1292: session_x11_req(Session *s)
1293: {
1.33 ! markus 1294: int fd;
1.22 deraadt 1295: if (no_x11_forwarding_flag) {
1.19 markus 1296: debug("X11 forwarding disabled in user configuration file.");
1297: return 0;
1298: }
1.7 markus 1299: if (!options.x11_forwarding) {
1300: debug("X11 forwarding disabled in server configuration file.");
1301: return 0;
1302: }
1303: if (xauthfile != NULL) {
1304: debug("X11 fwd already started.");
1305: return 0;
1306: }
1307:
1308: debug("Received request for X11 forwarding with auth spoofing.");
1309: if (s->display != NULL)
1310: packet_disconnect("Protocol error: X11 display already set.");
1311:
1312: s->single_connection = packet_get_char();
1313: s->auth_proto = packet_get_string(NULL);
1314: s->auth_data = packet_get_string(NULL);
1315: s->screen = packet_get_int();
1316: packet_done();
1317:
1318: s->display = x11_create_display_inet(s->screen, options.x11_display_offset);
1319: if (s->display == NULL) {
1320: xfree(s->auth_proto);
1321: xfree(s->auth_data);
1322: return 0;
1323: }
1324: xauthfile = xmalloc(MAXPATHLEN);
1325: strlcpy(xauthfile, "/tmp/ssh-XXXXXXXX", MAXPATHLEN);
1326: temporarily_use_uid(s->pw->pw_uid);
1327: if (mkdtemp(xauthfile) == NULL) {
1328: restore_uid();
1329: error("private X11 dir: mkdtemp %s failed: %s",
1330: xauthfile, strerror(errno));
1331: xfree(xauthfile);
1332: xauthfile = NULL;
1333: xfree(s->auth_proto);
1334: xfree(s->auth_data);
1335: /* XXXX remove listening channels */
1336: return 0;
1337: }
1338: strlcat(xauthfile, "/cookies", MAXPATHLEN);
1.33 ! markus 1339: fd = open(xauthfile, O_RDWR|O_CREAT|O_EXCL, 0600);
! 1340: if (fd >= 0)
! 1341: close(fd);
1.7 markus 1342: restore_uid();
1343: fatal_add_cleanup(xauthfile_cleanup_proc, s);
1344: return 1;
1345: }
1346:
1.19 markus 1347: int
1348: session_shell_req(Session *s)
1349: {
1350: /* if forced_command == NULL, the shell is execed */
1351: char *shell = forced_command;
1352: packet_done();
1353: s->extended = 1;
1354: if (s->ttyfd == -1)
1355: do_exec_no_pty(s, shell, s->pw);
1356: else
1357: do_exec_pty(s, shell, s->pw);
1358: return 1;
1359: }
1360:
1361: int
1362: session_exec_req(Session *s)
1363: {
1.20 markus 1364: unsigned int len;
1.19 markus 1365: char *command = packet_get_string(&len);
1366: packet_done();
1367: if (forced_command) {
1368: xfree(command);
1369: command = forced_command;
1370: debug("Forced command '%.500s'", forced_command);
1371: }
1372: s->extended = 1;
1373: if (s->ttyfd == -1)
1374: do_exec_no_pty(s, command, s->pw);
1375: else
1376: do_exec_pty(s, command, s->pw);
1377: if (forced_command == NULL)
1378: xfree(command);
1379: return 1;
1380: }
1381:
1.2 markus 1382: void
1383: session_input_channel_req(int id, void *arg)
1384: {
1385: unsigned int len;
1386: int reply;
1387: int success = 0;
1388: char *rtype;
1389: Session *s;
1390: Channel *c;
1391:
1392: rtype = packet_get_string(&len);
1393: reply = packet_get_char();
1394:
1395: s = session_by_channel(id);
1396: if (s == NULL)
1397: fatal("session_input_channel_req: channel %d: no session", id);
1398: c = channel_lookup(id);
1399: if (c == NULL)
1400: fatal("session_input_channel_req: channel %d: bad channel", id);
1401:
1402: debug("session_input_channel_req: session %d channel %d request %s reply %d",
1403: s->self, id, rtype, reply);
1404:
1405: /*
1406: * a session is in LARVAL state until a shell
1407: * or programm is executed
1408: */
1409: if (c->type == SSH_CHANNEL_LARVAL) {
1410: if (strcmp(rtype, "shell") == 0) {
1.19 markus 1411: success = session_shell_req(s);
1.2 markus 1412: } else if (strcmp(rtype, "exec") == 0) {
1.19 markus 1413: success = session_exec_req(s);
1.2 markus 1414: } else if (strcmp(rtype, "pty-req") == 0) {
1.3 markus 1415: success = session_pty_req(s);
1.7 markus 1416: } else if (strcmp(rtype, "x11-req") == 0) {
1417: success = session_x11_req(s);
1418: } else if (strcmp(rtype, "subsystem") == 0) {
1419: success = session_subsystem_req(s);
1.2 markus 1420: }
1421: }
1422: if (strcmp(rtype, "window-change") == 0) {
1423: success = session_window_change_req(s);
1424: }
1425:
1426: if (reply) {
1427: packet_start(success ?
1428: SSH2_MSG_CHANNEL_SUCCESS : SSH2_MSG_CHANNEL_FAILURE);
1429: packet_put_int(c->remote_id);
1430: packet_send();
1431: }
1432: xfree(rtype);
1433: }
1434:
1435: void
1436: session_set_fds(Session *s, int fdin, int fdout, int fderr)
1437: {
1438: if (!compat20)
1439: fatal("session_set_fds: called for proto != 2.0");
1440: /*
1441: * now that have a child and a pipe to the child,
1442: * we can activate our channel and register the fd's
1443: */
1444: if (s->chanid == -1)
1445: fatal("no channel for session %d", s->self);
1446: channel_set_fds(s->chanid,
1447: fdout, fdin, fderr,
1448: fderr == -1 ? CHAN_EXTENDED_IGNORE : CHAN_EXTENDED_READ);
1449: }
1450:
1.1 markus 1451: void
1452: session_pty_cleanup(Session *s)
1453: {
1454: if (s == NULL || s->ttyfd == -1)
1455: return;
1456:
1457: debug("session_pty_cleanup: session %i release %s", s->self, s->tty);
1458:
1459: /* Cancel the cleanup function. */
1460: fatal_remove_cleanup(pty_cleanup_proc, (void *)s);
1461:
1462: /* Record that the user has logged out. */
1463: record_logout(s->pid, s->tty);
1464:
1465: /* Release the pseudo-tty. */
1466: pty_release(s->tty);
1467:
1468: /*
1469: * Close the server side of the socket pairs. We must do this after
1470: * the pty cleanup, so that another process doesn't get this pty
1471: * while we're still cleaning up.
1472: */
1473: if (close(s->ptymaster) < 0)
1474: error("close(s->ptymaster): %s", strerror(errno));
1.2 markus 1475: }
1476:
1477: void
1478: session_exit_message(Session *s, int status)
1479: {
1480: Channel *c;
1481: if (s == NULL)
1482: fatal("session_close: no session");
1483: c = channel_lookup(s->chanid);
1484: if (c == NULL)
1485: fatal("session_close: session %d: no channel %d",
1486: s->self, s->chanid);
1487: debug("session_exit_message: session %d channel %d pid %d",
1488: s->self, s->chanid, s->pid);
1489:
1490: if (WIFEXITED(status)) {
1491: channel_request_start(s->chanid,
1492: "exit-status", 0);
1493: packet_put_int(WEXITSTATUS(status));
1494: packet_send();
1495: } else if (WIFSIGNALED(status)) {
1496: channel_request_start(s->chanid,
1497: "exit-signal", 0);
1498: packet_put_int(WTERMSIG(status));
1499: packet_put_char(WCOREDUMP(status));
1500: packet_put_cstring("");
1501: packet_put_cstring("");
1502: packet_send();
1503: } else {
1504: /* Some weird exit cause. Just exit. */
1505: packet_disconnect("wait returned status %04x.", status);
1506: }
1507:
1508: /* disconnect channel */
1509: debug("session_exit_message: release channel %d", s->chanid);
1510: channel_cancel_cleanup(s->chanid);
1.5 markus 1511: /*
1512: * emulate a write failure with 'chan_write_failed', nobody will be
1513: * interested in data we write.
1514: * Note that we must not call 'chan_read_failed', since there could
1515: * be some more data waiting in the pipe.
1516: */
1.8 markus 1517: if (c->ostate != CHAN_OUTPUT_CLOSED)
1518: chan_write_failed(c);
1.2 markus 1519: s->chanid = -1;
1520: }
1521:
1522: void
1523: session_free(Session *s)
1524: {
1525: debug("session_free: session %d pid %d", s->self, s->pid);
1526: if (s->term)
1527: xfree(s->term);
1528: if (s->display)
1529: xfree(s->display);
1530: if (s->auth_data)
1531: xfree(s->auth_data);
1532: if (s->auth_proto)
1533: xfree(s->auth_proto);
1534: s->used = 0;
1535: }
1536:
1537: void
1538: session_close(Session *s)
1539: {
1540: session_pty_cleanup(s);
1541: session_free(s);
1.9 markus 1542: session_proctitle(s);
1.2 markus 1543: }
1544:
1545: void
1546: session_close_by_pid(pid_t pid, int status)
1547: {
1548: Session *s = session_by_pid(pid);
1549: if (s == NULL) {
1550: debug("session_close_by_pid: no session for pid %d", s->pid);
1551: return;
1552: }
1553: if (s->chanid != -1)
1554: session_exit_message(s, status);
1555: session_close(s);
1556: }
1557:
1558: /*
1559: * this is called when a channel dies before
1560: * the session 'child' itself dies
1561: */
1562: void
1563: session_close_by_channel(int id, void *arg)
1564: {
1565: Session *s = session_by_channel(id);
1566: if (s == NULL) {
1567: debug("session_close_by_channel: no session for channel %d", id);
1568: return;
1569: }
1570: /* disconnect channel */
1571: channel_cancel_cleanup(s->chanid);
1572: s->chanid = -1;
1573:
1574: debug("session_close_by_channel: channel %d kill %d", id, s->pid);
1575: if (s->pid == 0) {
1576: /* close session immediately */
1577: session_close(s);
1578: } else {
1579: /* notify child, delay session cleanup */
1580: if (kill(s->pid, (s->ttyfd == -1) ? SIGTERM : SIGHUP) < 0)
1581: error("session_close_by_channel: kill %d: %s",
1582: s->pid, strerror(errno));
1583: }
1.9 markus 1584: }
1585:
1586: char *
1587: session_tty_list(void)
1588: {
1589: static char buf[1024];
1590: int i;
1591: buf[0] = '\0';
1592: for(i = 0; i < MAX_SESSIONS; i++) {
1593: Session *s = &sessions[i];
1594: if (s->used && s->ttyfd != -1) {
1595: if (buf[0] != '\0')
1596: strlcat(buf, ",", sizeof buf);
1597: strlcat(buf, strrchr(s->tty, '/') + 1, sizeof buf);
1598: }
1599: }
1600: if (buf[0] == '\0')
1601: strlcpy(buf, "notty", sizeof buf);
1602: return buf;
1603: }
1604:
1605: void
1606: session_proctitle(Session *s)
1607: {
1608: if (s->pw == NULL)
1609: error("no user for session %d", s->self);
1610: else
1611: setproctitle("%s@%s", s->pw->pw_name, session_tty_list());
1.2 markus 1612: }
1613:
1614: void
1615: do_authenticated2(void)
1616: {
1.28 millert 1617: struct passwd *pw;
1618:
1.2 markus 1619: /*
1620: * Cancel the alarm we set to limit the time taken for
1621: * authentication.
1622: */
1623: alarm(0);
1.23 deraadt 1624: if (startup_pipe != -1) {
1625: close(startup_pipe);
1626: startup_pipe = -1;
1627: }
1.28 millert 1628: #ifdef HAVE_LOGIN_CAP
1629: pw = auth_get_user();
1630: if ((lc = login_getclass(pw->pw_class)) == NULL) {
1631: error("unable to get login class");
1632: return;
1633: }
1634: #endif
1.2 markus 1635: server_loop2();
1.7 markus 1636: if (xauthfile)
1637: xauthfile_cleanup_proc(NULL);
1.1 markus 1638: }