]> andersk Git - openssh.git/blob - session.c
0625bf81f10d2ca25d27aa629fc44a913845825f
[openssh.git] / session.c
1 /*
2  * Copyright (c) 1995 Tatu Ylonen <ylo@cs.hut.fi>, Espoo, Finland
3  *                    All rights reserved
4  *
5  * As far as I am concerned, the code I have written for this software
6  * can be used freely for any purpose.  Any derived versions of this
7  * software must be clearly marked as such, and if the derived work is
8  * incompatible with the protocol description in the RFC file, it must be
9  * called by a name other than "ssh" or "Secure Shell".
10  *
11  * SSH2 support by Markus Friedl.
12  * Copyright (c) 2000 Markus Friedl.  All rights reserved.
13  *
14  * Redistribution and use in source and binary forms, with or without
15  * modification, are permitted provided that the following conditions
16  * are met:
17  * 1. Redistributions of source code must retain the above copyright
18  *    notice, this list of conditions and the following disclaimer.
19  * 2. Redistributions in binary form must reproduce the above copyright
20  *    notice, this list of conditions and the following disclaimer in the
21  *    documentation and/or other materials provided with the distribution.
22  *
23  * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
24  * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
25  * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
26  * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
27  * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
28  * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
29  * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
30  * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
31  * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
32  * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
33  */
34
35 #include "includes.h"
36 RCSID("$OpenBSD: session.c,v 1.78 2001/05/31 10:30:16 markus Exp $");
37
38 #include "ssh.h"
39 #include "ssh1.h"
40 #include "ssh2.h"
41 #include "xmalloc.h"
42 #include "sshpty.h"
43 #include "packet.h"
44 #include "buffer.h"
45 #include "mpaux.h"
46 #include "uidswap.h"
47 #include "compat.h"
48 #include "channels.h"
49 #include "bufaux.h"
50 #include "auth.h"
51 #include "auth-options.h"
52 #include "pathnames.h"
53 #include "log.h"
54 #include "servconf.h"
55 #include "sshlogin.h"
56 #include "serverloop.h"
57 #include "canohost.h"
58 #include "session.h"
59
60 #ifdef WITH_IRIX_PROJECT
61 #include <proj.h>
62 #endif /* WITH_IRIX_PROJECT */
63 #ifdef WITH_IRIX_JOBS
64 #include <sys/resource.h>
65 #endif
66 #ifdef WITH_IRIX_AUDIT
67 #include <sat.h>
68 #endif /* WITH_IRIX_AUDIT */
69
70 #if defined(HAVE_USERSEC_H)
71 #include <usersec.h>
72 #endif
73
74 #ifdef HAVE_CYGWIN
75 #include <windows.h>
76 #include <sys/cygwin.h>
77 #define is_winnt       (GetVersion() < 0x80000000)
78 #endif
79
80 /* AIX limits */
81 #if defined(HAVE_GETUSERATTR) && !defined(S_UFSIZE_HARD) && defined(S_UFSIZE)
82 # define S_UFSIZE_HARD  S_UFSIZE "_hard"
83 # define S_UCPU_HARD  S_UCPU "_hard"
84 # define S_UDATA_HARD  S_UDATA "_hard"
85 # define S_USTACK_HARD  S_USTACK "_hard"
86 # define S_URSS_HARD  S_URSS "_hard"
87 # define S_UCORE_HARD  S_UCORE "_hard"
88 # define S_UNOFILE_HARD S_UNOFILE "_hard"
89 #endif
90
91 #ifdef _AIX
92 # include <uinfo.h>
93 #endif
94
95 /* types */
96
97 #define TTYSZ 64
98 typedef struct Session Session;
99 struct Session {
100         int     used;
101         int     self;
102         struct  passwd *pw;
103         pid_t   pid;
104         /* tty */
105         char    *term;
106         int     ptyfd, ttyfd, ptymaster;
107         int     row, col, xpixel, ypixel;
108         char    tty[TTYSZ];
109         /* X11 */
110         char    *display;
111         int     screen;
112         char    *auth_proto;
113         char    *auth_data;
114         int     single_connection;
115         /* proto 2 */
116         int     chanid;
117         int     is_subsystem;
118 };
119
120 /* func */
121
122 Session *session_new(void);
123 void    session_set_fds(Session *s, int fdin, int fdout, int fderr);
124 void    session_pty_cleanup(Session *s);
125 void    session_proctitle(Session *s);
126 void    do_exec_pty(Session *s, const char *command);
127 void    do_exec_no_pty(Session *s, const char *command);
128 void    do_login(Session *s, const char *command);
129 #ifdef LOGIN_NEEDS_UTMPX
130 void    do_pre_login(Session *s);
131 #endif
132 void    do_child(Session *s, const char *command);
133 void    do_motd(void);
134 int     check_quietlogin(Session *s, const char *command);
135
136 void    do_authenticated1(Authctxt *authctxt);
137 void    do_authenticated2(Authctxt *authctxt);
138
139 /* import */
140 extern ServerOptions options;
141 extern char *__progname;
142 extern int log_stderr;
143 extern int debug_flag;
144 extern u_int utmp_len;
145 extern int startup_pipe;
146 extern void destroy_sensitive_data(void);
147
148 /* Local Xauthority file. */
149 static char *xauthfile;
150
151 /* original command from peer. */
152 char *original_command = NULL;
153
154 /* data */
155 #define MAX_SESSIONS 10
156 Session sessions[MAX_SESSIONS];
157
158 #ifdef WITH_AIXAUTHENTICATE
159 /* AIX's lastlogin message, set in auth1.c */
160 char *aixloginmsg;
161 #endif /* WITH_AIXAUTHENTICATE */
162
163 #ifdef HAVE_LOGIN_CAP
164 static login_cap_t *lc;
165 #endif
166
167 void
168 do_authenticated(Authctxt *authctxt)
169 {
170         /*
171          * Cancel the alarm we set to limit the time taken for
172          * authentication.
173          */
174         alarm(0);
175         if (startup_pipe != -1) {
176                 close(startup_pipe);
177                 startup_pipe = -1;
178         }
179 #if defined(HAVE_LOGIN_CAP) && defined(HAVE_PW_CLASS_IN_PASSWD)
180         if ((lc = login_getclass(authctxt->pw->pw_class)) == NULL) {
181                 error("unable to get login class");
182                 return;
183         }
184 #ifdef BSD_AUTH
185         if (auth_approval(NULL, lc, authctxt->pw->pw_name, "ssh") <= 0) {
186                 packet_disconnect("Approval failure for %s",
187                     authctxt->pw->pw_name);
188         }
189 #endif
190 #endif
191         /* setup the channel layer */
192         if (!no_port_forwarding_flag && options.allow_tcp_forwarding)
193                 channel_permit_all_opens();
194
195         if (compat20)
196                 do_authenticated2(authctxt);
197         else
198                 do_authenticated1(authctxt);
199 }
200
201 /*
202  * Remove local Xauthority file.
203  */
204 void
205 xauthfile_cleanup_proc(void *ignore)
206 {
207         debug("xauthfile_cleanup_proc called");
208
209         if (xauthfile != NULL) {
210                 char *p;
211                 unlink(xauthfile);
212                 p = strrchr(xauthfile, '/');
213                 if (p != NULL) {
214                         *p = '\0';
215                         rmdir(xauthfile);
216                 }
217                 xfree(xauthfile);
218                 xauthfile = NULL;
219         }
220 }
221
222 /*
223  * Function to perform cleanup if we get aborted abnormally (e.g., due to a
224  * dropped connection).
225  */
226 void
227 pty_cleanup_proc(void *session)
228 {
229         Session *s=session;
230         if (s == NULL)
231                 fatal("pty_cleanup_proc: no session");
232         debug("pty_cleanup_proc: %s", s->tty);
233
234         if (s->pid != 0) {
235                 /* Record that the user has logged out. */
236                 record_logout(s->pid, s->tty);
237         }
238
239         /* Release the pseudo-tty. */
240         pty_release(s->tty);
241 }
242
243 /*
244  * Prepares for an interactive session.  This is called after the user has
245  * been successfully authenticated.  During this message exchange, pseudo
246  * terminals are allocated, X11, TCP/IP, and authentication agent forwardings
247  * are requested, etc.
248  */
249 void
250 do_authenticated1(Authctxt *authctxt)
251 {
252         Session *s;
253         char *command;
254         int success, type, fd, n_bytes, plen, screen_flag, have_pty = 0;
255         int compression_level = 0, enable_compression_after_reply = 0;
256         u_int proto_len, data_len, dlen;
257         struct stat st;
258
259         s = session_new();
260         s->pw = authctxt->pw;
261
262         /*
263          * We stay in this loop until the client requests to execute a shell
264          * or a command.
265          */
266         for (;;) {
267                 success = 0;
268
269                 /* Get a packet from the client. */
270                 type = packet_read(&plen);
271
272                 /* Process the packet. */
273                 switch (type) {
274                 case SSH_CMSG_REQUEST_COMPRESSION:
275                         packet_integrity_check(plen, 4, type);
276                         compression_level = packet_get_int();
277                         if (compression_level < 1 || compression_level > 9) {
278                                 packet_send_debug("Received illegal compression level %d.",
279                                      compression_level);
280                                 break;
281                         }
282                         /* Enable compression after we have responded with SUCCESS. */
283                         enable_compression_after_reply = 1;
284                         success = 1;
285                         break;
286
287                 case SSH_CMSG_REQUEST_PTY:
288                         if (no_pty_flag) {
289                                 debug("Allocating a pty not permitted for this authentication.");
290                                 break;
291                         }
292                         if (have_pty)
293                                 packet_disconnect("Protocol error: you already have a pty.");
294
295                         debug("Allocating pty.");
296
297                         /* Allocate a pty and open it. */
298                         if (!pty_allocate(&s->ptyfd, &s->ttyfd, s->tty,
299                             sizeof(s->tty))) {
300                                 error("Failed to allocate pty.");
301                                 break;
302                         }
303                         fatal_add_cleanup(pty_cleanup_proc, (void *)s);
304                         pty_setowner(s->pw, s->tty);
305
306                         /* Get TERM from the packet.  Note that the value may be of arbitrary length. */
307                         s->term = packet_get_string(&dlen);
308                         packet_integrity_check(dlen, strlen(s->term), type);
309                         /* packet_integrity_check(plen, 4 + dlen + 4*4 + n_bytes, type); */
310                         /* Remaining bytes */
311                         n_bytes = plen - (4 + dlen + 4 * 4);
312
313                         if (strcmp(s->term, "") == 0) {
314                                 xfree(s->term);
315                                 s->term = NULL;
316                         }
317                         /* Get window size from the packet. */
318                         s->row = packet_get_int();
319                         s->col = packet_get_int();
320                         s->xpixel = packet_get_int();
321                         s->ypixel = packet_get_int();
322                         pty_change_window_size(s->ptyfd, s->row, s->col, s->xpixel, s->ypixel);
323
324                         /* Get tty modes from the packet. */
325                         tty_parse_modes(s->ttyfd, &n_bytes);
326                         packet_integrity_check(plen, 4 + dlen + 4 * 4 + n_bytes, type);
327
328                         session_proctitle(s);
329
330                         /* Indicate that we now have a pty. */
331                         success = 1;
332                         have_pty = 1;
333                         break;
334
335                 case SSH_CMSG_X11_REQUEST_FORWARDING:
336                         if (!options.x11_forwarding) {
337                                 packet_send_debug("X11 forwarding disabled in server configuration file.");
338                                 break;
339                         }
340                         if (!options.xauth_location ||
341                             (stat(options.xauth_location, &st) == -1)) {
342                                 packet_send_debug("No xauth program; cannot forward with spoofing.");
343                                 break;
344                         }
345                         if (no_x11_forwarding_flag) {
346                                 packet_send_debug("X11 forwarding not permitted for this authentication.");
347                                 break;
348                         }
349                         debug("Received request for X11 forwarding with auth spoofing.");
350                         if (s->display != NULL)
351                                 packet_disconnect("Protocol error: X11 display already set.");
352
353                         s->auth_proto = packet_get_string(&proto_len);
354                         s->auth_data = packet_get_string(&data_len);
355
356                         screen_flag = packet_get_protocol_flags() &
357                             SSH_PROTOFLAG_SCREEN_NUMBER;
358                         debug2("SSH_PROTOFLAG_SCREEN_NUMBER: %d", screen_flag);
359
360                         if (packet_remaining() == 4) {
361                                 if (!screen_flag)
362                                         debug2("Buggy client: "
363                                             "X11 screen flag missing");
364                                 packet_integrity_check(plen,
365                                     4 + proto_len + 4 + data_len + 4, type);
366                                 s->screen = packet_get_int();
367                         } else {
368                                 packet_integrity_check(plen,
369                                     4 + proto_len + 4 + data_len, type);
370                                 s->screen = 0;
371                         }
372                         s->display = x11_create_display_inet(s->screen, options.x11_display_offset);
373
374                         if (s->display == NULL)
375                                 break;
376
377                         /* Setup to always have a local .Xauthority. */
378                         xauthfile = xmalloc(MAXPATHLEN);
379                         strlcpy(xauthfile, "/tmp/ssh-XXXXXXXX", MAXPATHLEN);
380                         temporarily_use_uid(s->pw);
381                         if (mkdtemp(xauthfile) == NULL) {
382                                 restore_uid();
383                                 error("private X11 dir: mkdtemp %s failed: %s",
384                                     xauthfile, strerror(errno));
385                                 xfree(xauthfile);
386                                 xauthfile = NULL;
387                                 /* XXXX remove listening channels */
388                                 break;
389                         }
390                         strlcat(xauthfile, "/cookies", MAXPATHLEN);
391                         fd = open(xauthfile, O_RDWR|O_CREAT|O_EXCL, 0600);
392                         if (fd >= 0)
393                                 close(fd);
394                         restore_uid();
395                         fatal_add_cleanup(xauthfile_cleanup_proc, NULL);
396                         success = 1;
397                         break;
398
399                 case SSH_CMSG_AGENT_REQUEST_FORWARDING:
400                         if (no_agent_forwarding_flag || compat13) {
401                                 debug("Authentication agent forwarding not permitted for this authentication.");
402                                 break;
403                         }
404                         debug("Received authentication agent forwarding request.");
405                         success = auth_input_request_forwarding(s->pw);
406                         break;
407
408                 case SSH_CMSG_PORT_FORWARD_REQUEST:
409                         if (no_port_forwarding_flag) {
410                                 debug("Port forwarding not permitted for this authentication.");
411                                 break;
412                         }
413                         if (!options.allow_tcp_forwarding) {
414                                 debug("Port forwarding not permitted.");
415                                 break;
416                         }
417                         debug("Received TCP/IP port forwarding request.");
418                         channel_input_port_forward_request(s->pw->pw_uid == 0, options.gateway_ports);
419                         success = 1;
420                         break;
421
422                 case SSH_CMSG_MAX_PACKET_SIZE:
423                         if (packet_set_maxsize(packet_get_int()) > 0)
424                                 success = 1;
425                         break;
426
427                 case SSH_CMSG_EXEC_SHELL:
428                 case SSH_CMSG_EXEC_CMD:
429                         if (type == SSH_CMSG_EXEC_CMD) {
430                                 command = packet_get_string(&dlen);
431                                 debug("Exec command '%.500s'", command);
432                                 packet_integrity_check(plen, 4 + dlen, type);
433                         } else {
434                                 command = NULL;
435                                 packet_integrity_check(plen, 0, type);
436                         }
437                         if (forced_command != NULL) {
438                                 original_command = command;
439                                 command = forced_command;
440                                 debug("Forced command '%.500s'", forced_command);
441                         }
442                         if (have_pty)
443                                 do_exec_pty(s, command);
444                         else
445                                 do_exec_no_pty(s, command);
446
447                         if (command != NULL)
448                                 xfree(command);
449                         /* Cleanup user's local Xauthority file. */
450                         if (xauthfile)
451                                 xauthfile_cleanup_proc(NULL);
452                         return;
453
454                 default:
455                         /*
456                          * Any unknown messages in this phase are ignored,
457                          * and a failure message is returned.
458                          */
459                         log("Unknown packet type received after authentication: %d", type);
460                 }
461                 packet_start(success ? SSH_SMSG_SUCCESS : SSH_SMSG_FAILURE);
462                 packet_send();
463                 packet_write_wait();
464
465                 /* Enable compression now that we have replied if appropriate. */
466                 if (enable_compression_after_reply) {
467                         enable_compression_after_reply = 0;
468                         packet_start_compression(compression_level);
469                 }
470         }
471 }
472
473 /*
474  * This is called to fork and execute a command when we have no tty.  This
475  * will call do_child from the child, and server_loop from the parent after
476  * setting up file descriptors and such.
477  */
478 void
479 do_exec_no_pty(Session *s, const char *command)
480 {
481         int pid;
482
483 #ifdef USE_PIPES
484         int pin[2], pout[2], perr[2];
485         /* Allocate pipes for communicating with the program. */
486         if (pipe(pin) < 0 || pipe(pout) < 0 || pipe(perr) < 0)
487                 packet_disconnect("Could not create pipes: %.100s",
488                                   strerror(errno));
489 #else /* USE_PIPES */
490         int inout[2], err[2];
491         /* Uses socket pairs to communicate with the program. */
492         if (socketpair(AF_UNIX, SOCK_STREAM, 0, inout) < 0 ||
493             socketpair(AF_UNIX, SOCK_STREAM, 0, err) < 0)
494                 packet_disconnect("Could not create socket pairs: %.100s",
495                                   strerror(errno));
496 #endif /* USE_PIPES */
497         if (s == NULL)
498                 fatal("do_exec_no_pty: no session");
499
500         session_proctitle(s);
501
502 #if defined(USE_PAM)
503         do_pam_setcred(1);
504 #endif /* USE_PAM */
505
506         /* Fork the child. */
507         if ((pid = fork()) == 0) {
508                 /* Child.  Reinitialize the log since the pid has changed. */
509                 log_init(__progname, options.log_level, options.log_facility, log_stderr);
510
511                 /*
512                  * Create a new session and process group since the 4.4BSD
513                  * setlogin() affects the entire process group.
514                  */
515                 if (setsid() < 0)
516                         error("setsid failed: %.100s", strerror(errno));
517
518 #ifdef USE_PIPES
519                 /*
520                  * Redirect stdin.  We close the parent side of the socket
521                  * pair, and make the child side the standard input.
522                  */
523                 close(pin[1]);
524                 if (dup2(pin[0], 0) < 0)
525                         perror("dup2 stdin");
526                 close(pin[0]);
527
528                 /* Redirect stdout. */
529                 close(pout[0]);
530                 if (dup2(pout[1], 1) < 0)
531                         perror("dup2 stdout");
532                 close(pout[1]);
533
534                 /* Redirect stderr. */
535                 close(perr[0]);
536                 if (dup2(perr[1], 2) < 0)
537                         perror("dup2 stderr");
538                 close(perr[1]);
539 #else /* USE_PIPES */
540                 /*
541                  * Redirect stdin, stdout, and stderr.  Stdin and stdout will
542                  * use the same socket, as some programs (particularly rdist)
543                  * seem to depend on it.
544                  */
545                 close(inout[1]);
546                 close(err[1]);
547                 if (dup2(inout[0], 0) < 0)      /* stdin */
548                         perror("dup2 stdin");
549                 if (dup2(inout[0], 1) < 0)      /* stdout.  Note: same socket as stdin. */
550                         perror("dup2 stdout");
551                 if (dup2(err[0], 2) < 0)        /* stderr */
552                         perror("dup2 stderr");
553 #endif /* USE_PIPES */
554
555                 /* Do processing for the child (exec command etc). */
556                 do_child(s, command);
557                 /* NOTREACHED */
558         }
559 #ifdef HAVE_CYGWIN
560         if (is_winnt)
561                 cygwin_set_impersonation_token(INVALID_HANDLE_VALUE);
562 #endif
563         if (pid < 0)
564                 packet_disconnect("fork failed: %.100s", strerror(errno));
565         s->pid = pid;
566         /* Set interactive/non-interactive mode. */
567         packet_set_interactive(s->display != NULL);
568 #ifdef USE_PIPES
569         /* We are the parent.  Close the child sides of the pipes. */
570         close(pin[0]);
571         close(pout[1]);
572         close(perr[1]);
573
574         if (compat20) {
575                 session_set_fds(s, pin[1], pout[0], s->is_subsystem ? -1 : perr[0]);
576         } else {
577                 /* Enter the interactive session. */
578                 server_loop(pid, pin[1], pout[0], perr[0]);
579                 /* server_loop has closed pin[1], pout[0], and perr[0]. */
580         }
581 #else /* USE_PIPES */
582         /* We are the parent.  Close the child sides of the socket pairs. */
583         close(inout[0]);
584         close(err[0]);
585
586         /*
587          * Enter the interactive session.  Note: server_loop must be able to
588          * handle the case that fdin and fdout are the same.
589          */
590         if (compat20) {
591                 session_set_fds(s, inout[1], inout[1], s->is_subsystem ? -1 : err[1]);
592         } else {
593                 server_loop(pid, inout[1], inout[1], err[1]);
594                 /* server_loop has closed inout[1] and err[1]. */
595         }
596 #endif /* USE_PIPES */
597 }
598
599 /*
600  * This is called to fork and execute a command when we have a tty.  This
601  * will call do_child from the child, and server_loop from the parent after
602  * setting up file descriptors, controlling tty, updating wtmp, utmp,
603  * lastlog, and other such operations.
604  */
605 void
606 do_exec_pty(Session *s, const char *command)
607 {
608         int fdout, ptyfd, ttyfd, ptymaster;
609         pid_t pid;
610
611         if (s == NULL)
612                 fatal("do_exec_pty: no session");
613         ptyfd = s->ptyfd;
614         ttyfd = s->ttyfd;
615
616 #if defined(USE_PAM)
617         do_pam_session(s->pw->pw_name, s->tty);
618         do_pam_setcred(1);
619 #endif
620
621         /* Fork the child. */
622         if ((pid = fork()) == 0) {
623                 /* Child.  Reinitialize the log because the pid has changed. */
624                 log_init(__progname, options.log_level, options.log_facility, log_stderr);
625
626                 /* Close the master side of the pseudo tty. */
627                 close(ptyfd);
628
629                 /* Make the pseudo tty our controlling tty. */
630                 pty_make_controlling_tty(&ttyfd, s->tty);
631
632                 /* Redirect stdin from the pseudo tty. */
633                 if (dup2(ttyfd, fileno(stdin)) < 0)
634                         error("dup2 stdin failed: %.100s", strerror(errno));
635
636                 /* Redirect stdout to the pseudo tty. */
637                 if (dup2(ttyfd, fileno(stdout)) < 0)
638                         error("dup2 stdin failed: %.100s", strerror(errno));
639
640                 /* Redirect stderr to the pseudo tty. */
641                 if (dup2(ttyfd, fileno(stderr)) < 0)
642                         error("dup2 stdin failed: %.100s", strerror(errno));
643
644                 /* Close the extra descriptor for the pseudo tty. */
645                 close(ttyfd);
646
647                 /* record login, etc. similar to login(1) */
648 #ifndef HAVE_OSF_SIA
649                 if (!(options.use_login && command == NULL))
650                         do_login(s, command);
651 # ifdef LOGIN_NEEDS_UTMPX
652                 else
653                         do_pre_login(s);
654 # endif
655 #endif
656
657                 /* Do common processing for the child, such as execing the command. */
658                 do_child(s, command);
659                 /* NOTREACHED */
660         }
661 #ifdef HAVE_CYGWIN
662         if (is_winnt)
663                 cygwin_set_impersonation_token(INVALID_HANDLE_VALUE);
664 #endif
665         if (pid < 0)
666                 packet_disconnect("fork failed: %.100s", strerror(errno));
667         s->pid = pid;
668
669         /* Parent.  Close the slave side of the pseudo tty. */
670         close(ttyfd);
671
672         /*
673          * Create another descriptor of the pty master side for use as the
674          * standard input.  We could use the original descriptor, but this
675          * simplifies code in server_loop.  The descriptor is bidirectional.
676          */
677         fdout = dup(ptyfd);
678         if (fdout < 0)
679                 packet_disconnect("dup #1 failed: %.100s", strerror(errno));
680
681         /* we keep a reference to the pty master */
682         ptymaster = dup(ptyfd);
683         if (ptymaster < 0)
684                 packet_disconnect("dup #2 failed: %.100s", strerror(errno));
685         s->ptymaster = ptymaster;
686
687         /* Enter interactive session. */
688         packet_set_interactive(1);
689         if (compat20) {
690                 session_set_fds(s, ptyfd, fdout, -1);
691         } else {
692                 server_loop(pid, ptyfd, fdout, -1);
693                 /* server_loop _has_ closed ptyfd and fdout. */
694                 session_pty_cleanup(s);
695         }
696 }
697
698 #ifdef LOGIN_NEEDS_UTMPX
699 void
700 do_pre_login(Session *s)
701 {
702         socklen_t fromlen;
703         struct sockaddr_storage from;
704         pid_t pid = getpid();
705
706         /*
707          * Get IP address of client. If the connection is not a socket, let
708          * the address be 0.0.0.0.
709          */
710         memset(&from, 0, sizeof(from));
711         if (packet_connection_is_on_socket()) {
712                 fromlen = sizeof(from);
713                 if (getpeername(packet_get_connection_in(),
714                      (struct sockaddr *) & from, &fromlen) < 0) {
715                         debug("getpeername: %.100s", strerror(errno));
716                         fatal_cleanup();
717                 }
718         }
719
720         record_utmp_only(pid, s->tty, s->pw->pw_name,
721             get_remote_name_or_ip(utmp_len, options.reverse_mapping_check),
722             (struct sockaddr *)&from);
723 }
724 #endif
725
726 /* administrative, login(1)-like work */
727 void
728 do_login(Session *s, const char *command)
729 {
730         char *time_string;
731         char hostname[MAXHOSTNAMELEN];
732         socklen_t fromlen;
733         struct sockaddr_storage from;
734         time_t last_login_time;
735         struct passwd * pw = s->pw;
736         pid_t pid = getpid();
737
738         /*
739          * Get IP address of client. If the connection is not a socket, let
740          * the address be 0.0.0.0.
741          */
742         memset(&from, 0, sizeof(from));
743         if (packet_connection_is_on_socket()) {
744                 fromlen = sizeof(from);
745                 if (getpeername(packet_get_connection_in(),
746                      (struct sockaddr *) & from, &fromlen) < 0) {
747                         debug("getpeername: %.100s", strerror(errno));
748                         fatal_cleanup();
749                 }
750         }
751
752         /* Get the time and hostname when the user last logged in. */
753         if (options.print_lastlog) {
754                 hostname[0] = '\0';
755                 last_login_time = get_last_login_time(pw->pw_uid, pw->pw_name,
756                     hostname, sizeof(hostname));
757         }
758
759         /* Record that there was a login on that tty from the remote host. */
760         record_login(pid, s->tty, pw->pw_name, pw->pw_uid,
761             get_remote_name_or_ip(utmp_len, options.reverse_mapping_check),
762             (struct sockaddr *)&from);
763
764 #ifdef USE_PAM
765         /*
766          * If password change is needed, do it now.
767          * This needs to occur before the ~/.hushlogin check.
768          */
769         if (is_pam_password_change_required()) {
770                 print_pam_messages();
771                 do_pam_chauthtok();
772         }
773 #endif
774
775         if (check_quietlogin(s, command))
776                 return;
777
778 #ifdef USE_PAM
779         if (!is_pam_password_change_required())
780                 print_pam_messages();
781 #endif /* USE_PAM */
782 #ifdef WITH_AIXAUTHENTICATE
783         if (aixloginmsg && *aixloginmsg)
784                 printf("%s\n", aixloginmsg);
785 #endif /* WITH_AIXAUTHENTICATE */
786
787         if (options.print_lastlog && last_login_time != 0) {
788                 time_string = ctime(&last_login_time);
789                 if (strchr(time_string, '\n'))
790                         *strchr(time_string, '\n') = 0;
791                 if (strcmp(hostname, "") == 0)
792                         printf("Last login: %s\r\n", time_string);
793                 else
794                         printf("Last login: %s from %s\r\n", time_string, hostname);
795         }
796
797         do_motd();
798 }
799
800 /*
801  * Display the message of the day.
802  */
803 void
804 do_motd(void)
805 {
806         FILE *f;
807         char buf[256];
808
809         if (options.print_motd) {
810 #ifdef HAVE_LOGIN_CAP
811                 f = fopen(login_getcapstr(lc, "welcome", "/etc/motd",
812                     "/etc/motd"), "r");
813 #else
814                 f = fopen("/etc/motd", "r");
815 #endif
816                 if (f) {
817                         while (fgets(buf, sizeof(buf), f))
818                                 fputs(buf, stdout);
819                         fclose(f);
820                 }
821         }
822 }
823
824
825 /*
826  * Check for quiet login, either .hushlogin or command given.
827  */
828 int
829 check_quietlogin(Session *s, const char *command)
830 {
831         char buf[256];
832         struct passwd * pw = s->pw;
833         struct stat st;
834
835         /* Return 1 if .hushlogin exists or a command given. */
836         if (command != NULL)
837                 return 1;
838         snprintf(buf, sizeof(buf), "%.200s/.hushlogin", pw->pw_dir);
839 #ifdef HAVE_LOGIN_CAP
840         if (login_getcapbool(lc, "hushlogin", 0) || stat(buf, &st) >= 0)
841                 return 1;
842 #else
843         if (stat(buf, &st) >= 0)
844                 return 1;
845 #endif
846         return 0;
847 }
848
849 /*
850  * Sets the value of the given variable in the environment.  If the variable
851  * already exists, its value is overriden.
852  */
853 void
854 child_set_env(char ***envp, u_int *envsizep, const char *name,
855               const char *value)
856 {
857         u_int i, namelen;
858         char **env;
859
860         /*
861          * Find the slot where the value should be stored.  If the variable
862          * already exists, we reuse the slot; otherwise we append a new slot
863          * at the end of the array, expanding if necessary.
864          */
865         env = *envp;
866         namelen = strlen(name);
867         for (i = 0; env[i]; i++)
868                 if (strncmp(env[i], name, namelen) == 0 && env[i][namelen] == '=')
869                         break;
870         if (env[i]) {
871                 /* Reuse the slot. */
872                 xfree(env[i]);
873         } else {
874                 /* New variable.  Expand if necessary. */
875                 if (i >= (*envsizep) - 1) {
876                         (*envsizep) += 50;
877                         env = (*envp) = xrealloc(env, (*envsizep) * sizeof(char *));
878                 }
879                 /* Need to set the NULL pointer at end of array beyond the new slot. */
880                 env[i + 1] = NULL;
881         }
882
883         /* Allocate space and format the variable in the appropriate slot. */
884         env[i] = xmalloc(strlen(name) + 1 + strlen(value) + 1);
885         snprintf(env[i], strlen(name) + 1 + strlen(value) + 1, "%s=%s", name, value);
886 }
887
888 /*
889  * Reads environment variables from the given file and adds/overrides them
890  * into the environment.  If the file does not exist, this does nothing.
891  * Otherwise, it must consist of empty lines, comments (line starts with '#')
892  * and assignments of the form name=value.  No other forms are allowed.
893  */
894 void
895 read_environment_file(char ***env, u_int *envsize,
896                       const char *filename)
897 {
898         FILE *f;
899         char buf[4096];
900         char *cp, *value;
901
902         f = fopen(filename, "r");
903         if (!f)
904                 return;
905
906         while (fgets(buf, sizeof(buf), f)) {
907                 for (cp = buf; *cp == ' ' || *cp == '\t'; cp++)
908                         ;
909                 if (!*cp || *cp == '#' || *cp == '\n')
910                         continue;
911                 if (strchr(cp, '\n'))
912                         *strchr(cp, '\n') = '\0';
913                 value = strchr(cp, '=');
914                 if (value == NULL) {
915                         fprintf(stderr, "Bad line in %.100s: %.200s\n", filename, buf);
916                         continue;
917                 }
918                 /*
919                  * Replace the equals sign by nul, and advance value to
920                  * the value string.
921                  */
922                 *value = '\0';
923                 value++;
924                 child_set_env(env, envsize, cp, value);
925         }
926         fclose(f);
927 }
928
929 #ifdef USE_PAM
930 /*
931  * Sets any environment variables which have been specified by PAM
932  */
933 void do_pam_environment(char ***env, int *envsize)
934 {
935         char *equals, var_name[512], var_val[512];
936         char **pam_env;
937         int i;
938
939         if ((pam_env = fetch_pam_environment()) == NULL)
940                 return;
941
942         for(i = 0; pam_env[i] != NULL; i++) {
943                 if ((equals = strstr(pam_env[i], "=")) == NULL)
944                         continue;
945
946                 if (strlen(pam_env[i]) < (sizeof(var_name) - 1)) {
947                         memset(var_name, '\0', sizeof(var_name));
948                         memset(var_val, '\0', sizeof(var_val));
949
950                         strncpy(var_name, pam_env[i], equals - pam_env[i]);
951                         strcpy(var_val, equals + 1);
952
953                         debug3("PAM environment: %s=%s", var_name, var_val);
954
955                         child_set_env(env, envsize, var_name, var_val);
956                 }
957         }
958 }
959 #endif /* USE_PAM */
960
961 #ifdef HAVE_CYGWIN
962 void copy_environment(char ***env, int *envsize)
963 {
964         char *equals, var_name[512], var_val[512];
965         int i;
966
967         for(i = 0; environ[i] != NULL; i++) {
968                 if ((equals = strstr(environ[i], "=")) == NULL)
969                         continue;
970
971                 if (strlen(environ[i]) < (sizeof(var_name) - 1)) {
972                         memset(var_name, '\0', sizeof(var_name));
973                         memset(var_val, '\0', sizeof(var_val));
974
975                         strncpy(var_name, environ[i], equals - environ[i]);
976                         strcpy(var_val, equals + 1);
977
978                         debug3("Copy environment: %s=%s", var_name, var_val);
979
980                         child_set_env(env, envsize, var_name, var_val);
981                 }
982         }
983 }
984 #endif
985
986 #if defined(HAVE_GETUSERATTR)
987 /*
988  * AIX-specific login initialisation
989  */
990 void set_limit(char *user, char *soft, char *hard, int resource, int mult)
991 {
992         struct rlimit rlim;
993         int slim, hlim;
994
995         getrlimit(resource, &rlim);
996
997         slim = 0;
998         if (getuserattr(user, soft, &slim, SEC_INT) != -1) {
999                 if (slim < 0) {
1000                         rlim.rlim_cur = RLIM_INFINITY;
1001                 } else if (slim != 0) {
1002                         /* See the wackiness below */
1003                         if (rlim.rlim_cur == slim * mult)
1004                                 slim = 0;
1005                         else
1006                                 rlim.rlim_cur = slim * mult;
1007                 }
1008         }
1009
1010         hlim = 0;
1011         if (getuserattr(user, hard, &hlim, SEC_INT) != -1) {
1012                 if (hlim < 0) {
1013                         rlim.rlim_max = RLIM_INFINITY;
1014                 } else if (hlim != 0) {
1015                         rlim.rlim_max = hlim * mult;
1016                 }
1017         }
1018
1019         /*
1020          * XXX For cpu and fsize the soft limit is set to the hard limit
1021          * if the hard limit is left at its default value and the soft limit
1022          * is changed from its default value, either by requesting it
1023          * (slim == 0) or by setting it to the current default.  At least
1024          * that's how rlogind does it.  If you're confused you're not alone.
1025          * Bug or feature? AIX 4.3.1.2
1026          */
1027         if ((!strcmp(soft, "fsize") || !strcmp(soft, "cpu"))
1028             && hlim == 0 && slim != 0)
1029                 rlim.rlim_max = rlim.rlim_cur;
1030         /* A specified hard limit limits the soft limit */
1031         else if (hlim > 0 && rlim.rlim_cur > rlim.rlim_max)
1032                 rlim.rlim_cur = rlim.rlim_max;
1033         /* A soft limit can increase a hard limit */
1034         else if (rlim.rlim_cur > rlim.rlim_max)
1035                 rlim.rlim_max = rlim.rlim_cur;
1036
1037         if (setrlimit(resource, &rlim) != 0)
1038                 error("setrlimit(%.10s) failed: %.100s", soft, strerror(errno));
1039 }
1040
1041 void set_limits_from_userattr(char *user)
1042 {
1043         int mask;
1044         char buf[16];
1045
1046         set_limit(user, S_UFSIZE, S_UFSIZE_HARD, RLIMIT_FSIZE, 512);
1047         set_limit(user, S_UCPU, S_UCPU_HARD, RLIMIT_CPU, 1);
1048         set_limit(user, S_UDATA, S_UDATA_HARD, RLIMIT_DATA, 512);
1049         set_limit(user, S_USTACK, S_USTACK_HARD, RLIMIT_STACK, 512);
1050         set_limit(user, S_URSS, S_URSS_HARD, RLIMIT_RSS, 512);
1051         set_limit(user, S_UCORE, S_UCORE_HARD, RLIMIT_CORE, 512);
1052 #if defined(S_UNOFILE)
1053         set_limit(user, S_UNOFILE, S_UNOFILE_HARD, RLIMIT_NOFILE, 1);
1054 #endif
1055
1056         if (getuserattr(user, S_UMASK, &mask, SEC_INT) != -1) {
1057                 /* Convert decimal to octal */
1058                 (void) snprintf(buf, sizeof(buf), "%d", mask);
1059                 if (sscanf(buf, "%o", &mask) == 1)
1060                         umask(mask);
1061         }
1062 }
1063 #endif /* defined(HAVE_GETUSERATTR) */
1064
1065 /*
1066  * Performs common processing for the child, such as setting up the
1067  * environment, closing extra file descriptors, setting the user and group
1068  * ids, and executing the command or shell.
1069  */
1070 void
1071 do_child(Session *s, const char *command)
1072 {
1073         const char *shell, *hostname = NULL, *cp = NULL;
1074         struct passwd * pw = s->pw;
1075         char buf[256];
1076         char cmd[1024];
1077         FILE *f = NULL;
1078         u_int envsize, i;
1079         char **env;
1080         extern char **environ;
1081         struct stat st;
1082         char *argv[10];
1083         int do_xauth = s->auth_proto != NULL && s->auth_data != NULL;
1084 #ifdef WITH_IRIX_PROJECT
1085         prid_t projid;
1086 #endif /* WITH_IRIX_PROJECT */
1087 #ifdef WITH_IRIX_JOBS
1088         jid_t jid = 0;
1089 #else
1090 #ifdef WITH_IRIX_ARRAY
1091         int jid = 0;
1092 #endif /* WITH_IRIX_ARRAY */
1093 #endif /* WITH_IRIX_JOBS */
1094
1095         /* remove hostkey from the child's memory */
1096         destroy_sensitive_data();
1097
1098         /* login(1) is only called if we execute the login shell */
1099         if (options.use_login && command != NULL)
1100                 options.use_login = 0;
1101
1102 #if !defined(USE_PAM) && !defined(HAVE_OSF_SIA)
1103         if (!options.use_login) {
1104 # ifdef HAVE_LOGIN_CAP
1105                 if (!login_getcapbool(lc, "ignorenologin", 0) && pw->pw_uid)
1106                         f = fopen(login_getcapstr(lc, "nologin", _PATH_NOLOGIN,
1107                             _PATH_NOLOGIN), "r");
1108 # else /* HAVE_LOGIN_CAP */
1109                 if (pw->pw_uid)
1110                         f = fopen(_PATH_NOLOGIN, "r");
1111 # endif /* HAVE_LOGIN_CAP */
1112                 if (f) {
1113                         /* /etc/nologin exists.  Print its contents and exit. */
1114                         while (fgets(buf, sizeof(buf), f))
1115                                 fputs(buf, stderr);
1116                         fclose(f);
1117                         exit(254);
1118                 }
1119         }
1120 #endif /* USE_PAM || HAVE_OSF_SIA */
1121
1122         /* Set login name, uid, gid, and groups. */
1123         /* Login(1) does this as well, and it needs uid 0 for the "-h"
1124            switch, so we let login(1) to this for us. */
1125         if (!options.use_login) {
1126 #ifdef HAVE_OSF_SIA
1127                 session_setup_sia(pw->pw_name, s->ttyfd == -1 ? NULL : s->tty);
1128                 if (!check_quietlogin(s, command))
1129                         do_motd();
1130 #else /* HAVE_OSF_SIA */
1131 #ifdef HAVE_CYGWIN
1132                 if (is_winnt) {
1133 #else
1134                 if (getuid() == 0 || geteuid() == 0) {
1135 #endif
1136 # ifdef HAVE_GETUSERATTR
1137                         set_limits_from_userattr(pw->pw_name);
1138 # endif /* HAVE_GETUSERATTR */
1139 # ifdef HAVE_LOGIN_CAP
1140                         if (setusercontext(lc, pw, pw->pw_uid,
1141                             (LOGIN_SETALL & ~LOGIN_SETPATH)) < 0) {
1142                                 perror("unable to set user context");
1143                                 exit(1);
1144                         }
1145 # else /* HAVE_LOGIN_CAP */
1146 #if defined(HAVE_GETLUID) && defined(HAVE_SETLUID)
1147                         /* Sets login uid for accounting */
1148                         if (getluid() == -1 && setluid(pw->pw_uid) == -1)
1149                                 error("setluid: %s", strerror(errno));
1150 #endif /* defined(HAVE_GETLUID) && defined(HAVE_SETLUID) */
1151
1152                         if (setlogin(pw->pw_name) < 0)
1153                                 error("setlogin failed: %s", strerror(errno));
1154                         if (setgid(pw->pw_gid) < 0) {
1155                                 perror("setgid");
1156                                 exit(1);
1157                         }
1158                         /* Initialize the group list. */
1159                         if (initgroups(pw->pw_name, pw->pw_gid) < 0) {
1160                                 perror("initgroups");
1161                                 exit(1);
1162                         }
1163                         endgrent();
1164 #  ifdef USE_PAM
1165                         /*
1166                          * PAM credentials may take the form of 
1167                          * supplementary groups. These will have been 
1168                          * wiped by the above initgroups() call.
1169                          * Reestablish them here.
1170                          */
1171                         do_pam_setcred(0);
1172 #  endif /* USE_PAM */
1173 #  ifdef WITH_IRIX_JOBS
1174                         jid = jlimit_startjob(pw->pw_name, pw->pw_uid, "interactive");
1175                         if (jid == -1) {
1176                                 fatal("Failed to create job container: %.100s",
1177                                       strerror(errno));
1178                         }
1179 #  endif /* WITH_IRIX_JOBS */
1180 #  ifdef WITH_IRIX_ARRAY
1181                         /* initialize array session */
1182                         if (jid == 0) {
1183                                 if (newarraysess() != 0)
1184                                         fatal("Failed to set up new array session: %.100s",
1185                                               strerror(errno));
1186                         }
1187 #  endif /* WITH_IRIX_ARRAY */
1188 #  ifdef WITH_IRIX_PROJECT
1189                         /* initialize irix project info */
1190                         if ((projid = getdfltprojuser(pw->pw_name)) == -1) {
1191                           debug("Failed to get project id, using projid 0");
1192                           projid = 0;
1193                         }
1194                         if (setprid(projid))
1195                           fatal("Failed to initialize project %d for %s: %.100s",
1196                                 (int)projid, pw->pw_name, strerror(errno));
1197 #  endif /* WITH_IRIX_PROJECT */
1198 #ifdef WITH_IRIX_AUDIT
1199                         if (sysconf(_SC_AUDIT)) {
1200                                 debug("Setting sat id to %d", (int) pw->pw_uid);
1201                                 if (satsetid(pw->pw_uid))
1202                                         debug("error setting satid: %.100s", strerror(errno));
1203                         }
1204 #endif /* WITH_IRIX_AUDIT */
1205
1206 #ifdef _AIX
1207                         /*
1208                          * AIX has a "usrinfo" area where logname and
1209                          * other stuff is stored - a few applications
1210                          * actually use this and die if it's not set
1211                          */
1212                         if (s->ttyfd == -1)
1213                                 s->tty[0] = '\0';
1214                         cp = xmalloc(22 + strlen(s->tty) + 
1215                             2 * strlen(pw->pw_name));
1216                         i = sprintf(cp, "LOGNAME=%s%cNAME=%s%cTTY=%s%c%c",
1217                             pw->pw_name, 0, pw->pw_name, 0, s->tty, 0, 0);
1218                         if (usrinfo(SETUINFO, cp, i) == -1)
1219                                 fatal("Couldn't set usrinfo: %s", 
1220                                     strerror(errno));
1221                         debug3("AIX/UsrInfo: set len %d", i);
1222                         xfree(cp);
1223 #endif
1224
1225                         /* Permanently switch to the desired uid. */
1226                         permanently_set_uid(pw);
1227 # endif /* HAVE_LOGIN_CAP */
1228                 }
1229 #endif /* HAVE_OSF_SIA */
1230
1231 #ifdef HAVE_CYGWIN
1232                 if (is_winnt)
1233 #endif
1234                 if (getuid() != pw->pw_uid || geteuid() != pw->pw_uid)
1235                         fatal("Failed to set uids to %u.", (u_int) pw->pw_uid);
1236         }
1237         /*
1238          * Get the shell from the password data.  An empty shell field is
1239          * legal, and means /bin/sh.
1240          */
1241         shell = (pw->pw_shell[0] == '\0') ? _PATH_BSHELL : pw->pw_shell;
1242 #ifdef HAVE_LOGIN_CAP
1243         shell = login_getcapstr(lc, "shell", (char *)shell, (char *)shell);
1244 #endif
1245
1246 #ifdef AFS
1247         /* Try to get AFS tokens for the local cell. */
1248         if (k_hasafs()) {
1249                 char cell[64];
1250
1251                 if (k_afs_cell_of_file(pw->pw_dir, cell, sizeof(cell)) == 0)
1252                         krb_afslog(cell, 0);
1253
1254                 krb_afslog(0, 0);
1255         }
1256 #endif /* AFS */
1257
1258         /* Initialize the environment. */
1259         envsize = 100;
1260         env = xmalloc(envsize * sizeof(char *));
1261         env[0] = NULL;
1262
1263 #ifdef HAVE_CYGWIN
1264         /*
1265          * The Windows environment contains some setting which are
1266          * important for a running system. They must not be dropped.
1267          */
1268         copy_environment(&env, &envsize);
1269 #endif
1270
1271         if (!options.use_login) {
1272                 /* Set basic environment. */
1273                 child_set_env(&env, &envsize, "USER", pw->pw_name);
1274                 child_set_env(&env, &envsize, "LOGNAME", pw->pw_name);
1275                 child_set_env(&env, &envsize, "HOME", pw->pw_dir);
1276 #ifdef HAVE_LOGIN_CAP
1277                 (void) setusercontext(lc, pw, pw->pw_uid, LOGIN_SETPATH);
1278                 child_set_env(&env, &envsize, "PATH", getenv("PATH"));
1279 #else /* HAVE_LOGIN_CAP */
1280 # ifndef HAVE_CYGWIN
1281                 /*
1282                  * There's no standard path on Windows. The path contains
1283                  * important components pointing to the system directories,
1284                  * needed for loading shared libraries. So the path better
1285                  * remains intact here.
1286                  */
1287                 child_set_env(&env, &envsize, "PATH", _PATH_STDPATH);
1288 # endif /* HAVE_CYGWIN */
1289 #endif /* HAVE_LOGIN_CAP */
1290
1291                 snprintf(buf, sizeof buf, "%.200s/%.50s",
1292                          _PATH_MAILDIR, pw->pw_name);
1293                 child_set_env(&env, &envsize, "MAIL", buf);
1294
1295                 /* Normal systems set SHELL by default. */
1296                 child_set_env(&env, &envsize, "SHELL", shell);
1297         }
1298         if (getenv("TZ"))
1299                 child_set_env(&env, &envsize, "TZ", getenv("TZ"));
1300
1301         /* Set custom environment options from RSA authentication. */
1302         while (custom_environment) {
1303                 struct envstring *ce = custom_environment;
1304                 char *s = ce->s;
1305                 int i;
1306                 for (i = 0; s[i] != '=' && s[i]; i++);
1307                 if (s[i] == '=') {
1308                         s[i] = 0;
1309                         child_set_env(&env, &envsize, s, s + i + 1);
1310                 }
1311                 custom_environment = ce->next;
1312                 xfree(ce->s);
1313                 xfree(ce);
1314         }
1315
1316         snprintf(buf, sizeof buf, "%.50s %d %d",
1317                  get_remote_ipaddr(), get_remote_port(), get_local_port());
1318         child_set_env(&env, &envsize, "SSH_CLIENT", buf);
1319
1320         if (s->ttyfd != -1)
1321                 child_set_env(&env, &envsize, "SSH_TTY", s->tty);
1322         if (s->term)
1323                 child_set_env(&env, &envsize, "TERM", s->term);
1324         if (s->display)
1325                 child_set_env(&env, &envsize, "DISPLAY", s->display);
1326         if (original_command)
1327                 child_set_env(&env, &envsize, "SSH_ORIGINAL_COMMAND",
1328                     original_command);
1329
1330 #ifdef _AIX
1331         if ((cp = getenv("AUTHSTATE")) != NULL)
1332                 child_set_env(&env, &envsize, "AUTHSTATE", cp);
1333         if ((cp = getenv("KRB5CCNAME")) != NULL)
1334                 child_set_env(&env, &envsize, "KRB5CCNAME", cp);
1335         read_environment_file(&env, &envsize, "/etc/environment");
1336 #endif
1337
1338 #ifdef KRB4
1339         {
1340                 extern char *ticket;
1341
1342                 if (ticket)
1343                         child_set_env(&env, &envsize, "KRBTKFILE", ticket);
1344         }
1345 #endif /* KRB4 */
1346
1347 #ifdef USE_PAM
1348         /* Pull in any environment variables that may have been set by PAM. */
1349         do_pam_environment(&env, &envsize);
1350 #endif /* USE_PAM */
1351
1352         if (xauthfile)
1353                 child_set_env(&env, &envsize, "XAUTHORITY", xauthfile);
1354         if (auth_get_socket_name() != NULL)
1355                 child_set_env(&env, &envsize, SSH_AUTHSOCKET_ENV_NAME,
1356                               auth_get_socket_name());
1357
1358         /* read $HOME/.ssh/environment. */
1359         if (!options.use_login) {
1360                 snprintf(buf, sizeof buf, "%.200s/.ssh/environment",
1361                     pw->pw_dir);
1362                 read_environment_file(&env, &envsize, buf);
1363         }
1364         if (debug_flag) {
1365                 /* dump the environment */
1366                 fprintf(stderr, "Environment:\n");
1367                 for (i = 0; env[i]; i++)
1368                         fprintf(stderr, "  %.200s\n", env[i]);
1369         }
1370         /* we have to stash the hostname before we close our socket. */
1371         if (options.use_login)
1372                 hostname = get_remote_name_or_ip(utmp_len,
1373                     options.reverse_mapping_check);
1374         /*
1375          * Close the connection descriptors; note that this is the child, and
1376          * the server will still have the socket open, and it is important
1377          * that we do not shutdown it.  Note that the descriptors cannot be
1378          * closed before building the environment, as we call
1379          * get_remote_ipaddr there.
1380          */
1381         if (packet_get_connection_in() == packet_get_connection_out())
1382                 close(packet_get_connection_in());
1383         else {
1384                 close(packet_get_connection_in());
1385                 close(packet_get_connection_out());
1386         }
1387         /*
1388          * Close all descriptors related to channels.  They will still remain
1389          * open in the parent.
1390          */
1391         /* XXX better use close-on-exec? -markus */
1392         channel_close_all();
1393
1394         /*
1395          * Close any extra file descriptors.  Note that there may still be
1396          * descriptors left by system functions.  They will be closed later.
1397          */
1398         endpwent();
1399
1400         /*
1401          * Close any extra open file descriptors so that we don\'t have them
1402          * hanging around in clients.  Note that we want to do this after
1403          * initgroups, because at least on Solaris 2.3 it leaves file
1404          * descriptors open.
1405          */
1406         for (i = 3; i < 64; i++)
1407                 close(i);
1408
1409         /* Change current directory to the user\'s home directory. */
1410         if (chdir(pw->pw_dir) < 0) {
1411                 fprintf(stderr, "Could not chdir to home directory %s: %s\n",
1412                         pw->pw_dir, strerror(errno));
1413 #ifdef HAVE_LOGIN_CAP
1414                 if (login_getcapbool(lc, "requirehome", 0))
1415                         exit(1);
1416 #endif
1417         }
1418
1419         /*
1420          * Must take new environment into use so that .ssh/rc, /etc/sshrc and
1421          * xauth are run in the proper environment.
1422          */
1423         environ = env;
1424
1425         /*
1426          * Run $HOME/.ssh/rc, /etc/sshrc, or xauth (whichever is found first
1427          * in this order).
1428          */
1429         if (!options.use_login) {
1430                 /* ignore _PATH_SSH_USER_RC for subsystems */
1431                 if (!s->is_subsystem && (stat(_PATH_SSH_USER_RC, &st) >= 0)) {
1432                         snprintf(cmd, sizeof cmd, "%s -c '%s %s'",
1433                             shell, _PATH_BSHELL, _PATH_SSH_USER_RC);
1434                         if (debug_flag)
1435                                 fprintf(stderr, "Running %s\n", cmd);
1436                         f = popen(cmd, "w");
1437                         if (f) {
1438                                 if (do_xauth)
1439                                         fprintf(f, "%s %s\n", s->auth_proto,
1440                                             s->auth_data);
1441                                 pclose(f);
1442                         } else
1443                                 fprintf(stderr, "Could not run %s\n",
1444                                     _PATH_SSH_USER_RC);
1445                 } else if (stat(_PATH_SSH_SYSTEM_RC, &st) >= 0) {
1446                         if (debug_flag)
1447                                 fprintf(stderr, "Running %s %s\n", _PATH_BSHELL,
1448                                     _PATH_SSH_SYSTEM_RC);
1449                         f = popen(_PATH_BSHELL " " _PATH_SSH_SYSTEM_RC, "w");
1450                         if (f) {
1451                                 if (do_xauth)
1452                                         fprintf(f, "%s %s\n", s->auth_proto,
1453                                             s->auth_data);
1454                                 pclose(f);
1455                         } else
1456                                 fprintf(stderr, "Could not run %s\n",
1457                                     _PATH_SSH_SYSTEM_RC);
1458                 } else if (do_xauth && options.xauth_location != NULL) {
1459                         /* Add authority data to .Xauthority if appropriate. */
1460                         char *screen = strchr(s->display, ':');
1461
1462                         if (debug_flag) {
1463                                 fprintf(stderr,
1464                                     "Running %.100s add "
1465                                     "%.100s %.100s %.100s\n",
1466                                     options.xauth_location, s->display,
1467                                     s->auth_proto, s->auth_data);
1468                                 if (screen != NULL)
1469                                         fprintf(stderr,
1470                                             "Adding %.*s/unix%s %s %s\n",
1471                                             (int)(screen - s->display),
1472                                             s->display, screen,
1473                                             s->auth_proto, s->auth_data);
1474                         }
1475                         snprintf(cmd, sizeof cmd, "%s -q -",
1476                             options.xauth_location);
1477                         f = popen(cmd, "w");
1478                         if (f) {
1479                                 fprintf(f, "add %s %s %s\n", s->display,
1480                                     s->auth_proto, s->auth_data);
1481                                 if (screen != NULL)
1482                                         fprintf(f, "add %.*s/unix%s %s %s\n",
1483                                             (int)(screen - s->display),
1484                                             s->display, screen,
1485                                             s->auth_proto,
1486                                             s->auth_data);
1487                                 pclose(f);
1488                         } else {
1489                                 fprintf(stderr, "Could not run %s\n",
1490                                     cmd);
1491                         }
1492                 }
1493                 /* Get the last component of the shell name. */
1494                 cp = strrchr(shell, '/');
1495                 if (cp)
1496                         cp++;
1497                 else
1498                         cp = shell;
1499         }
1500
1501         /* restore SIGPIPE for child */
1502         signal(SIGPIPE,  SIG_DFL);
1503
1504         /*
1505          * If we have no command, execute the shell.  In this case, the shell
1506          * name to be passed in argv[0] is preceded by '-' to indicate that
1507          * this is a login shell.
1508          */
1509         if (!command) {
1510                 if (!options.use_login) {
1511                         char buf[256];
1512
1513                         /*
1514                          * Check for mail if we have a tty and it was enabled
1515                          * in server options.
1516                          */
1517                         if (s->ttyfd != -1 && options.check_mail) {
1518                                 char *mailbox;
1519                                 struct stat mailstat;
1520
1521                                 mailbox = getenv("MAIL");
1522                                 if (mailbox != NULL) {
1523                                         if (stat(mailbox, &mailstat) != 0 ||
1524                                             mailstat.st_size == 0)
1525                                                 printf("No mail.\n");
1526                                         else if (mailstat.st_mtime < mailstat.st_atime)
1527                                                 printf("You have mail.\n");
1528                                         else
1529                                                 printf("You have new mail.\n");
1530                                 }
1531                         }
1532                         /* Start the shell.  Set initial character to '-'. */
1533                         buf[0] = '-';
1534                         strncpy(buf + 1, cp, sizeof(buf) - 1);
1535                         buf[sizeof(buf) - 1] = 0;
1536
1537                         /* Execute the shell. */
1538                         argv[0] = buf;
1539                         argv[1] = NULL;
1540                         execve(shell, argv, env);
1541
1542                         /* Executing the shell failed. */
1543                         perror(shell);
1544                         exit(1);
1545
1546                 } else {
1547                         /* Launch login(1). */
1548
1549                         execl(LOGIN_PROGRAM, "login", "-h", hostname,
1550 #ifdef LOGIN_NEEDS_TERM
1551                              s->term? s->term : "unknown",
1552 #endif
1553                              "-p", "-f", "--", pw->pw_name, NULL);
1554
1555                         /* Login couldn't be executed, die. */
1556
1557                         perror("login");
1558                         exit(1);
1559                 }
1560         }
1561         /*
1562          * Execute the command using the user's shell.  This uses the -c
1563          * option to execute the command.
1564          */
1565         argv[0] = (char *) cp;
1566         argv[1] = "-c";
1567         argv[2] = (char *) command;
1568         argv[3] = NULL;
1569         execve(shell, argv, env);
1570         perror(shell);
1571         exit(1);
1572 }
1573
1574 Session *
1575 session_new(void)
1576 {
1577         int i;
1578         static int did_init = 0;
1579         if (!did_init) {
1580                 debug("session_new: init");
1581                 for(i = 0; i < MAX_SESSIONS; i++) {
1582                         sessions[i].used = 0;
1583                         sessions[i].self = i;
1584                 }
1585                 did_init = 1;
1586         }
1587         for(i = 0; i < MAX_SESSIONS; i++) {
1588                 Session *s = &sessions[i];
1589                 if (! s->used) {
1590                         memset(s, 0, sizeof(*s));
1591                         s->chanid = -1;
1592                         s->ptyfd = -1;
1593                         s->ttyfd = -1;
1594                         s->used = 1;
1595                         debug("session_new: session %d", i);
1596                         return s;
1597                 }
1598         }
1599         return NULL;
1600 }
1601
1602 void
1603 session_dump(void)
1604 {
1605         int i;
1606         for(i = 0; i < MAX_SESSIONS; i++) {
1607                 Session *s = &sessions[i];
1608                 debug("dump: used %d session %d %p channel %d pid %d",
1609                     s->used,
1610                     s->self,
1611                     s,
1612                     s->chanid,
1613                     s->pid);
1614         }
1615 }
1616
1617 int
1618 session_open(int chanid)
1619 {
1620         Session *s = session_new();
1621         debug("session_open: channel %d", chanid);
1622         if (s == NULL) {
1623                 error("no more sessions");
1624                 return 0;
1625         }
1626         s->pw = auth_get_user();
1627         if (s->pw == NULL)
1628                 fatal("no user for session %d", s->self);
1629         debug("session_open: session %d: link with channel %d", s->self, chanid);
1630         s->chanid = chanid;
1631         return 1;
1632 }
1633
1634 Session *
1635 session_by_channel(int id)
1636 {
1637         int i;
1638         for(i = 0; i < MAX_SESSIONS; i++) {
1639                 Session *s = &sessions[i];
1640                 if (s->used && s->chanid == id) {
1641                         debug("session_by_channel: session %d channel %d", i, id);
1642                         return s;
1643                 }
1644         }
1645         debug("session_by_channel: unknown channel %d", id);
1646         session_dump();
1647         return NULL;
1648 }
1649
1650 Session *
1651 session_by_pid(pid_t pid)
1652 {
1653         int i;
1654         debug("session_by_pid: pid %d", pid);
1655         for(i = 0; i < MAX_SESSIONS; i++) {
1656                 Session *s = &sessions[i];
1657                 if (s->used && s->pid == pid)
1658                         return s;
1659         }
1660         error("session_by_pid: unknown pid %d", pid);
1661         session_dump();
1662         return NULL;
1663 }
1664
1665 int
1666 session_window_change_req(Session *s)
1667 {
1668         s->col = packet_get_int();
1669         s->row = packet_get_int();
1670         s->xpixel = packet_get_int();
1671         s->ypixel = packet_get_int();
1672         packet_done();
1673         pty_change_window_size(s->ptyfd, s->row, s->col, s->xpixel, s->ypixel);
1674         return 1;
1675 }
1676
1677 int
1678 session_pty_req(Session *s)
1679 {
1680         u_int len;
1681         int n_bytes;
1682
1683         if (no_pty_flag)
1684                 return 0;
1685         if (s->ttyfd != -1)
1686                 return 0;
1687         s->term = packet_get_string(&len);
1688         s->col = packet_get_int();
1689         s->row = packet_get_int();
1690         s->xpixel = packet_get_int();
1691         s->ypixel = packet_get_int();
1692
1693         if (strcmp(s->term, "") == 0) {
1694                 xfree(s->term);
1695                 s->term = NULL;
1696         }
1697         /* Allocate a pty and open it. */
1698         if (!pty_allocate(&s->ptyfd, &s->ttyfd, s->tty, sizeof(s->tty))) {
1699                 xfree(s->term);
1700                 s->term = NULL;
1701                 s->ptyfd = -1;
1702                 s->ttyfd = -1;
1703                 error("session_pty_req: session %d alloc failed", s->self);
1704                 return 0;
1705         }
1706         debug("session_pty_req: session %d alloc %s", s->self, s->tty);
1707         /*
1708          * Add a cleanup function to clear the utmp entry and record logout
1709          * time in case we call fatal() (e.g., the connection gets closed).
1710          */
1711         fatal_add_cleanup(pty_cleanup_proc, (void *)s);
1712         pty_setowner(s->pw, s->tty);
1713         /* Get window size from the packet. */
1714         pty_change_window_size(s->ptyfd, s->row, s->col, s->xpixel, s->ypixel);
1715
1716         /* Get tty modes from the packet. */
1717         tty_parse_modes(s->ttyfd, &n_bytes);
1718         packet_done();
1719
1720         session_proctitle(s);
1721
1722         return 1;
1723 }
1724
1725 int
1726 session_subsystem_req(Session *s)
1727 {
1728         u_int len;
1729         int success = 0;
1730         char *subsys = packet_get_string(&len);
1731         int i;
1732
1733         packet_done();
1734         log("subsystem request for %s", subsys);
1735
1736         for (i = 0; i < options.num_subsystems; i++) {
1737                 if(strcmp(subsys, options.subsystem_name[i]) == 0) {
1738                         debug("subsystem: exec() %s", options.subsystem_command[i]);
1739                         s->is_subsystem = 1;
1740                         do_exec_no_pty(s, options.subsystem_command[i]);
1741                         success = 1;
1742                 }
1743         }
1744
1745         if (!success)
1746                 log("subsystem request for %s failed, subsystem not found", subsys);
1747
1748         xfree(subsys);
1749         return success;
1750 }
1751
1752 int
1753 session_x11_req(Session *s)
1754 {
1755         int fd;
1756         struct stat st;
1757         if (no_x11_forwarding_flag) {
1758                 debug("X11 forwarding disabled in user configuration file.");
1759                 return 0;
1760         }
1761         if (!options.x11_forwarding) {
1762                 debug("X11 forwarding disabled in server configuration file.");
1763                 return 0;
1764         }
1765         if (!options.xauth_location ||
1766             (stat(options.xauth_location, &st) == -1)) {
1767                 packet_send_debug("No xauth program; cannot forward with spoofing.");
1768                 return 0;
1769         }
1770         if (xauthfile != NULL) {
1771                 debug("X11 fwd already started.");
1772                 return 0;
1773         }
1774
1775         debug("Received request for X11 forwarding with auth spoofing.");
1776         if (s->display != NULL)
1777                 packet_disconnect("Protocol error: X11 display already set.");
1778
1779         s->single_connection = packet_get_char();
1780         s->auth_proto = packet_get_string(NULL);
1781         s->auth_data = packet_get_string(NULL);
1782         s->screen = packet_get_int();
1783         packet_done();
1784
1785         s->display = x11_create_display_inet(s->screen, options.x11_display_offset);
1786         if (s->display == NULL) {
1787                 xfree(s->auth_proto);
1788                 xfree(s->auth_data);
1789                 return 0;
1790         }
1791         xauthfile = xmalloc(MAXPATHLEN);
1792         strlcpy(xauthfile, "/tmp/ssh-XXXXXXXX", MAXPATHLEN);
1793         temporarily_use_uid(s->pw);
1794         if (mkdtemp(xauthfile) == NULL) {
1795                 restore_uid();
1796                 error("private X11 dir: mkdtemp %s failed: %s",
1797                     xauthfile, strerror(errno));
1798                 xfree(xauthfile);
1799                 xauthfile = NULL;
1800                 xfree(s->auth_proto);
1801                 xfree(s->auth_data);
1802                 /* XXXX remove listening channels */
1803                 return 0;
1804         }
1805         strlcat(xauthfile, "/cookies", MAXPATHLEN);
1806         fd = open(xauthfile, O_RDWR|O_CREAT|O_EXCL, 0600);
1807         if (fd >= 0)
1808                 close(fd);
1809         restore_uid();
1810         fatal_add_cleanup(xauthfile_cleanup_proc, s);
1811         return 1;
1812 }
1813
1814 int
1815 session_shell_req(Session *s)
1816 {
1817         /* if forced_command == NULL, the shell is execed */
1818         char *shell = forced_command;
1819         packet_done();
1820         if (s->ttyfd == -1)
1821                 do_exec_no_pty(s, shell);
1822         else
1823                 do_exec_pty(s, shell);
1824         return 1;
1825 }
1826
1827 int
1828 session_exec_req(Session *s)
1829 {
1830         u_int len;
1831         char *command = packet_get_string(&len);
1832         packet_done();
1833         if (forced_command) {
1834                 original_command = command;
1835                 command = forced_command;
1836                 debug("Forced command '%.500s'", forced_command);
1837         }
1838         if (s->ttyfd == -1)
1839                 do_exec_no_pty(s, command);
1840         else
1841                 do_exec_pty(s, command);
1842         if (forced_command == NULL)
1843                 xfree(command);
1844         return 1;
1845 }
1846
1847 int
1848 session_auth_agent_req(Session *s)
1849 {
1850         static int called = 0;
1851         packet_done();
1852         if (no_agent_forwarding_flag) {
1853                 debug("session_auth_agent_req: no_agent_forwarding_flag");
1854                 return 0;
1855         }
1856         if (called) {
1857                 return 0;
1858         } else {
1859                 called = 1;
1860                 return auth_input_request_forwarding(s->pw);
1861         }
1862 }
1863
1864 void
1865 session_input_channel_req(int id, void *arg)
1866 {
1867         u_int len;
1868         int reply;
1869         int success = 0;
1870         char *rtype;
1871         Session *s;
1872         Channel *c;
1873
1874         rtype = packet_get_string(&len);
1875         reply = packet_get_char();
1876
1877         s = session_by_channel(id);
1878         if (s == NULL)
1879                 fatal("session_input_channel_req: channel %d: no session", id);
1880         c = channel_lookup(id);
1881         if (c == NULL)
1882                 fatal("session_input_channel_req: channel %d: bad channel", id);
1883
1884         debug("session_input_channel_req: session %d channel %d request %s reply %d",
1885             s->self, id, rtype, reply);
1886
1887         /*
1888          * a session is in LARVAL state until a shell, a command
1889          * or a subsystem is executed
1890          */
1891         if (c->type == SSH_CHANNEL_LARVAL) {
1892                 if (strcmp(rtype, "shell") == 0) {
1893                         success = session_shell_req(s);
1894                 } else if (strcmp(rtype, "exec") == 0) {
1895                         success = session_exec_req(s);
1896                 } else if (strcmp(rtype, "pty-req") == 0) {
1897                         success =  session_pty_req(s);
1898                 } else if (strcmp(rtype, "x11-req") == 0) {
1899                         success = session_x11_req(s);
1900                 } else if (strcmp(rtype, "auth-agent-req@openssh.com") == 0) {
1901                         success = session_auth_agent_req(s);
1902                 } else if (strcmp(rtype, "subsystem") == 0) {
1903                         success = session_subsystem_req(s);
1904                 }
1905         }
1906         if (strcmp(rtype, "window-change") == 0) {
1907                 success = session_window_change_req(s);
1908         }
1909
1910         if (reply) {
1911                 packet_start(success ?
1912                     SSH2_MSG_CHANNEL_SUCCESS : SSH2_MSG_CHANNEL_FAILURE);
1913                 packet_put_int(c->remote_id);
1914                 packet_send();
1915         }
1916         xfree(rtype);
1917 }
1918
1919 void
1920 session_set_fds(Session *s, int fdin, int fdout, int fderr)
1921 {
1922         if (!compat20)
1923                 fatal("session_set_fds: called for proto != 2.0");
1924         /*
1925          * now that have a child and a pipe to the child,
1926          * we can activate our channel and register the fd's
1927          */
1928         if (s->chanid == -1)
1929                 fatal("no channel for session %d", s->self);
1930         channel_set_fds(s->chanid,
1931             fdout, fdin, fderr,
1932             fderr == -1 ? CHAN_EXTENDED_IGNORE : CHAN_EXTENDED_READ,
1933             1);
1934 }
1935
1936 void
1937 session_pty_cleanup(Session *s)
1938 {
1939         if (s == NULL || s->ttyfd == -1)
1940                 return;
1941
1942         debug("session_pty_cleanup: session %d release %s", s->self, s->tty);
1943
1944         /* Cancel the cleanup function. */
1945         fatal_remove_cleanup(pty_cleanup_proc, (void *)s);
1946
1947         /* Record that the user has logged out. */
1948         record_logout(s->pid, s->tty);
1949
1950         /* Release the pseudo-tty. */
1951         pty_release(s->tty);
1952
1953         /*
1954          * Close the server side of the socket pairs.  We must do this after
1955          * the pty cleanup, so that another process doesn't get this pty
1956          * while we're still cleaning up.
1957          */
1958         if (close(s->ptymaster) < 0)
1959                 error("close(s->ptymaster): %s", strerror(errno));
1960 }
1961
1962 void
1963 session_exit_message(Session *s, int status)
1964 {
1965         Channel *c;
1966         if (s == NULL)
1967                 fatal("session_close: no session");
1968         c = channel_lookup(s->chanid);
1969         if (c == NULL)
1970                 fatal("session_close: session %d: no channel %d",
1971                     s->self, s->chanid);
1972         debug("session_exit_message: session %d channel %d pid %d",
1973             s->self, s->chanid, s->pid);
1974
1975         if (WIFEXITED(status)) {
1976                 channel_request_start(s->chanid,
1977                     "exit-status", 0);
1978                 packet_put_int(WEXITSTATUS(status));
1979                 packet_send();
1980         } else if (WIFSIGNALED(status)) {
1981                 channel_request_start(s->chanid,
1982                     "exit-signal", 0);
1983                 packet_put_int(WTERMSIG(status));
1984 #ifdef WCOREDUMP
1985                 packet_put_char(WCOREDUMP(status));
1986 #else /* WCOREDUMP */
1987                 packet_put_char(0);
1988 #endif /* WCOREDUMP */
1989                 packet_put_cstring("");
1990                 packet_put_cstring("");
1991                 packet_send();
1992         } else {
1993                 /* Some weird exit cause.  Just exit. */
1994                 packet_disconnect("wait returned status %04x.", status);
1995         }
1996
1997         /* disconnect channel */
1998         debug("session_exit_message: release channel %d", s->chanid);
1999         channel_cancel_cleanup(s->chanid);
2000         /*
2001          * emulate a write failure with 'chan_write_failed', nobody will be
2002          * interested in data we write.
2003          * Note that we must not call 'chan_read_failed', since there could
2004          * be some more data waiting in the pipe.
2005          */
2006         if (c->ostate != CHAN_OUTPUT_CLOSED)
2007                 chan_write_failed(c);
2008         s->chanid = -1;
2009 }
2010
2011 void
2012 session_free(Session *s)
2013 {
2014         debug("session_free: session %d pid %d", s->self, s->pid);
2015         if (s->term)
2016                 xfree(s->term);
2017         if (s->display)
2018                 xfree(s->display);
2019         if (s->auth_data)
2020                 xfree(s->auth_data);
2021         if (s->auth_proto)
2022                 xfree(s->auth_proto);
2023         s->used = 0;
2024 }
2025
2026 void
2027 session_close(Session *s)
2028 {
2029         session_pty_cleanup(s);
2030         session_free(s);
2031         session_proctitle(s);
2032 }
2033
2034 void
2035 session_close_by_pid(pid_t pid, int status)
2036 {
2037         Session *s = session_by_pid(pid);
2038         if (s == NULL) {
2039                 debug("session_close_by_pid: no session for pid %d", s->pid);
2040                 return;
2041         }
2042         if (s->chanid != -1)
2043                 session_exit_message(s, status);
2044         session_close(s);
2045 }
2046
2047 /*
2048  * this is called when a channel dies before
2049  * the session 'child' itself dies
2050  */
2051 void
2052 session_close_by_channel(int id, void *arg)
2053 {
2054         Session *s = session_by_channel(id);
2055         if (s == NULL) {
2056                 debug("session_close_by_channel: no session for channel %d", id);
2057                 return;
2058         }
2059         /* disconnect channel */
2060         channel_cancel_cleanup(s->chanid);
2061         s->chanid = -1;
2062
2063         debug("session_close_by_channel: channel %d kill %d", id, s->pid);
2064         if (s->pid == 0) {
2065                 /* close session immediately */
2066                 session_close(s);
2067         } else {
2068                 /* notify child, delay session cleanup */
2069                 if (kill(s->pid, (s->ttyfd == -1) ? SIGTERM : SIGHUP) < 0)
2070                         error("session_close_by_channel: kill %d: %s",
2071                             s->pid, strerror(errno));
2072         }
2073 }
2074
2075 char *
2076 session_tty_list(void)
2077 {
2078         static char buf[1024];
2079         int i;
2080         buf[0] = '\0';
2081         for(i = 0; i < MAX_SESSIONS; i++) {
2082                 Session *s = &sessions[i];
2083                 if (s->used && s->ttyfd != -1) {
2084                         if (buf[0] != '\0')
2085                                 strlcat(buf, ",", sizeof buf);
2086                         strlcat(buf, strrchr(s->tty, '/') + 1, sizeof buf);
2087                 }
2088         }
2089         if (buf[0] == '\0')
2090                 strlcpy(buf, "notty", sizeof buf);
2091         return buf;
2092 }
2093
2094 void
2095 session_proctitle(Session *s)
2096 {
2097         if (s->pw == NULL)
2098                 error("no user for session %d", s->self);
2099         else
2100                 setproctitle("%s@%s", s->pw->pw_name, session_tty_list());
2101 }
2102
2103 void
2104 do_authenticated2(Authctxt *authctxt)
2105 {
2106
2107         server_loop2();
2108         if (xauthfile)
2109                 xauthfile_cleanup_proc(NULL);
2110 }
This page took 0.541502 seconds and 3 git commands to generate.