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