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