source: trunk/third/openssh/session.c @ 20858

Revision 20858, 55.0 KB checked in by zacheiss, 20 years ago (diff)
Failure to convert our forward credentials to v4 tickets should not result in the forwarded tickets being destroyed.
Line 
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, 2001 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"
36RCSID("$OpenBSD: session.c,v 1.150 2002/09/16 19:55:33 stevesk 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#include "monitor_wrap.h"
60
61#ifdef GSSAPI
62#include "ssh-gss.h"
63#endif
64
65#ifdef HAVE_CYGWIN
66#include <windows.h>
67#include <sys/cygwin.h>
68#define is_winnt       (GetVersion() < 0x80000000)
69#endif
70
71#include <al.h>
72extern int setpag(), ktc_ForgetAllTokens();
73void try_afscall(int (*func)(void));
74void krb_cleanup(void);
75static void pwfree(struct passwd *);
76int *session_warnings = NULL;
77extern int is_local_acct;
78
79#ifdef KRB5
80#include <krb5.h>
81#ifndef HEIMDAL
82#define krb5_get_err_text(context,code) error_message(code)
83#endif /* !HEIMDAL */
84#endif
85
86/* func */
87
88Session *session_new(void);
89void    session_set_fds(Session *, int, int, int);
90void    session_pty_cleanup(void *);
91void    session_proctitle(Session *);
92int     session_setup_x11fwd(Session *);
93void    do_exec_pty(Session *, const char *);
94void    do_exec_no_pty(Session *, const char *);
95void    do_exec(Session *, const char *);
96void    do_login(Session *, const char *);
97#ifdef LOGIN_NEEDS_UTMPX
98static void     do_pre_login(Session *s);
99#endif
100void    do_child(Session *, const char *);
101void    do_motd(void);
102int     check_quietlogin(Session *, const char *);
103
104static void do_authenticated1(Authctxt *);
105static void do_authenticated2(Authctxt *);
106
107static int session_pty_req(Session *);
108
109/* import */
110extern ServerOptions options;
111extern char *__progname;
112extern int log_stderr;
113extern int debug_flag;
114extern u_int utmp_len;
115extern int startup_pipe;
116extern void destroy_sensitive_data(void);
117
118/* original command from peer. */
119const char *original_command = NULL;
120
121/* data */
122#define MAX_SESSIONS 10
123Session sessions[MAX_SESSIONS];
124
125#ifdef WITH_AIXAUTHENTICATE
126char *aixloginmsg;
127#endif /* WITH_AIXAUTHENTICATE */
128
129#ifdef HAVE_LOGIN_CAP
130login_cap_t *lc;
131#endif
132
133/* Name and directory of socket for authentication agent forwarding. */
134static char *auth_sock_name = NULL;
135static char *auth_sock_dir = NULL;
136
137/* removes the agent forwarding socket */
138
139static void
140auth_sock_cleanup_proc(void *_pw)
141{
142        struct passwd *pw = _pw;
143
144        if (auth_sock_name != NULL) {
145                temporarily_use_uid(pw);
146                unlink(auth_sock_name);
147                rmdir(auth_sock_dir);
148                auth_sock_name = NULL;
149                restore_uid();
150        }
151}
152
153static int
154auth_input_request_forwarding(struct passwd * pw)
155{
156        Channel *nc;
157        int sock;
158        struct sockaddr_un sunaddr;
159
160        if (auth_sock_name != NULL) {
161                error("authentication forwarding requested twice.");
162                return 0;
163        }
164
165        /* Temporarily drop privileged uid for mkdir/bind. */
166        temporarily_use_uid(pw);
167
168        /* Allocate a buffer for the socket name, and format the name. */
169        auth_sock_name = xmalloc(MAXPATHLEN);
170        auth_sock_dir = xmalloc(MAXPATHLEN);
171        strlcpy(auth_sock_dir, "/tmp/ssh-XXXXXXXX", MAXPATHLEN);
172
173        /* Create private directory for socket */
174        if (mkdtemp(auth_sock_dir) == NULL) {
175                packet_send_debug("Agent forwarding disabled: "
176                    "mkdtemp() failed: %.100s", strerror(errno));
177                restore_uid();
178                xfree(auth_sock_name);
179                xfree(auth_sock_dir);
180                auth_sock_name = NULL;
181                auth_sock_dir = NULL;
182                return 0;
183        }
184        snprintf(auth_sock_name, MAXPATHLEN, "%s/agent.%ld",
185                 auth_sock_dir, (long) getpid());
186
187        /* delete agent socket on fatal() */
188        fatal_add_cleanup(auth_sock_cleanup_proc, pw);
189
190        /* Create the socket. */
191        sock = socket(AF_UNIX, SOCK_STREAM, 0);
192        if (sock < 0)
193                packet_disconnect("socket: %.100s", strerror(errno));
194
195        /* Bind it to the name. */
196        memset(&sunaddr, 0, sizeof(sunaddr));
197        sunaddr.sun_family = AF_UNIX;
198        strlcpy(sunaddr.sun_path, auth_sock_name, sizeof(sunaddr.sun_path));
199
200        if (bind(sock, (struct sockaddr *) & sunaddr, sizeof(sunaddr)) < 0)
201                packet_disconnect("bind: %.100s", strerror(errno));
202
203        /* Restore the privileged uid. */
204        restore_uid();
205
206        /* Start listening on the socket. */
207        if (listen(sock, 5) < 0)
208                packet_disconnect("listen: %.100s", strerror(errno));
209
210        /* Allocate a channel for the authentication agent socket. */
211        nc = channel_new("auth socket",
212            SSH_CHANNEL_AUTH_SOCKET, sock, sock, -1,
213            CHAN_X11_WINDOW_DEFAULT, CHAN_X11_PACKET_DEFAULT,
214            0, xstrdup("auth socket"), 1);
215        strlcpy(nc->path, auth_sock_name, sizeof(nc->path));
216        return 1;
217}
218
219
220void
221do_authenticated(Authctxt *authctxt)
222{
223        /*
224         * Cancel the alarm we set to limit the time taken for
225         * authentication.
226         */
227        alarm(0);
228        if (startup_pipe != -1) {
229                close(startup_pipe);
230                startup_pipe = -1;
231        }
232
233        if (authctxt->pw->pw_uid == 0)
234          syslog(LOG_NOTICE, "ROOT LOGIN as '%s' from %s",
235                 authctxt->pw->pw_name,
236                 get_canonical_hostname(options.verify_reverse_mapping));
237       
238        /* setup the channel layer */
239        if (!no_port_forwarding_flag && options.allow_tcp_forwarding)
240                channel_permit_all_opens();
241
242        if (compat20)
243                do_authenticated2(authctxt);
244        else
245                do_authenticated1(authctxt);
246
247        /* remove agent socket */
248        if (auth_sock_name != NULL)
249                auth_sock_cleanup_proc(authctxt->pw);
250#ifdef KRB4
251        if (options.kerberos_ticket_cleanup)
252                krb4_cleanup_proc(authctxt);
253#endif
254#ifdef KRB5
255        if (options.kerberos_ticket_cleanup)
256                krb5_cleanup_proc(authctxt);
257#endif
258}
259
260/*
261 * Prepares for an interactive session.  This is called after the user has
262 * been successfully authenticated.  During this message exchange, pseudo
263 * terminals are allocated, X11, TCP/IP, and authentication agent forwardings
264 * are requested, etc.
265 */
266static void
267do_authenticated1(Authctxt *authctxt)
268{
269        Session *s;
270        char *command;
271        int success, type, screen_flag;
272        int enable_compression_after_reply = 0;
273        u_int proto_len, data_len, dlen, compression_level = 0;
274
275        s = session_new();
276        s->authctxt = authctxt;
277        s->pw = authctxt->pw;
278
279        /*
280         * We stay in this loop until the client requests to execute a shell
281         * or a command.
282         */
283        for (;;) {
284                success = 0;
285
286                /* Get a packet from the client. */
287                type = packet_read();
288
289                /* Process the packet. */
290                switch (type) {
291                case SSH_CMSG_REQUEST_COMPRESSION:
292                        compression_level = packet_get_int();
293                        packet_check_eom();
294                        if (compression_level < 1 || compression_level > 9) {
295                                packet_send_debug("Received illegal compression level %d.",
296                                    compression_level);
297                                break;
298                        }
299                        if (!options.compression) {
300                                debug2("compression disabled");
301                                break;
302                        }
303                        /* Enable compression after we have responded with SUCCESS. */
304                        enable_compression_after_reply = 1;
305                        success = 1;
306                        break;
307
308                case SSH_CMSG_REQUEST_PTY:
309                        success = session_pty_req(s);
310                        break;
311
312                case SSH_CMSG_X11_REQUEST_FORWARDING:
313                        s->auth_proto = packet_get_string(&proto_len);
314                        s->auth_data = packet_get_string(&data_len);
315
316                        screen_flag = packet_get_protocol_flags() &
317                            SSH_PROTOFLAG_SCREEN_NUMBER;
318                        debug2("SSH_PROTOFLAG_SCREEN_NUMBER: %d", screen_flag);
319
320                        if (packet_remaining() == 4) {
321                                if (!screen_flag)
322                                        debug2("Buggy client: "
323                                            "X11 screen flag missing");
324                                s->screen = packet_get_int();
325                        } else {
326                                s->screen = 0;
327                        }
328                        packet_check_eom();
329                        success = session_setup_x11fwd(s);
330                        if (!success) {
331                                xfree(s->auth_proto);
332                                xfree(s->auth_data);
333                                s->auth_proto = NULL;
334                                s->auth_data = NULL;
335                        }
336                        break;
337
338                case SSH_CMSG_AGENT_REQUEST_FORWARDING:
339                        if (no_agent_forwarding_flag || compat13) {
340                                debug("Authentication agent forwarding not permitted for this authentication.");
341                                break;
342                        }
343                        debug("Received authentication agent forwarding request.");
344                        success = auth_input_request_forwarding(s->pw);
345                        break;
346
347                case SSH_CMSG_PORT_FORWARD_REQUEST:
348                        if (no_port_forwarding_flag) {
349                                debug("Port forwarding not permitted for this authentication.");
350                                break;
351                        }
352                        if (!options.allow_tcp_forwarding) {
353                                debug("Port forwarding not permitted.");
354                                break;
355                        }
356                        debug("Received TCP/IP port forwarding request.");
357                        channel_input_port_forward_request(s->pw->pw_uid == 0, options.gateway_ports);
358                        success = 1;
359                        break;
360
361                case SSH_CMSG_MAX_PACKET_SIZE:
362                        if (packet_set_maxsize(packet_get_int()) > 0)
363                                success = 1;
364                        break;
365
366#if defined(AFS) || defined(KRB5)
367                case SSH_CMSG_HAVE_KERBEROS_TGT:
368                        success =
369                          do_auth1_kerberos_tgt_pass(s->authctxt, type);
370                        break;
371#endif /* AFS || KRB5 */
372
373#ifdef AFS
374                case SSH_CMSG_HAVE_AFS_TOKEN:
375                        if (!options.afs_token_passing || !k_hasafs()) {
376                                verbose("AFS token passing disabled.");
377                        } else {
378                                /* Accept AFS token. */
379                                char *token = packet_get_string(&dlen);
380                                packet_check_eom();
381
382                                if (auth_afs_token(s->authctxt, token))
383                                        success = 1;
384                                else
385                                        verbose("AFS token refused for %.100s",
386                                            s->authctxt->user);
387                                xfree(token);
388                        }
389                        break;
390#endif /* AFS */
391
392                case SSH_CMSG_EXEC_SHELL:
393                case SSH_CMSG_EXEC_CMD:
394                        if (type == SSH_CMSG_EXEC_CMD) {
395                                command = packet_get_string(&dlen);
396                                debug("Exec command '%.500s'", command);
397                                do_exec(s, command);
398                                xfree(command);
399                        } else {
400                                do_exec(s, NULL);
401                        }
402                        packet_check_eom();
403                        session_close(s);
404                        return;
405
406                default:
407                        /*
408                         * Any unknown messages in this phase are ignored,
409                         * and a failure message is returned.
410                         */
411                        log("Unknown packet type received after authentication: %d", type);
412                }
413                packet_start(success ? SSH_SMSG_SUCCESS : SSH_SMSG_FAILURE);
414                packet_send();
415                packet_write_wait();
416
417                /* Enable compression now that we have replied if appropriate. */
418                if (enable_compression_after_reply) {
419                        enable_compression_after_reply = 0;
420                        packet_start_compression(compression_level);
421                }
422        }
423}
424
425/*
426 * This is called from both do_authenticated1(), for the normal case,
427 * and also from do_authloop(), for compatibility with ssh.com.
428 */
429
430int do_auth1_kerberos_tgt_pass(Authctxt *authctxt, int type)
431{
432        int success;
433        u_int dlen;
434
435#if defined(AFS) || defined(KRB5)
436        if (!options.kerberos_tgt_passing) {
437                verbose("Kerberos TGT passing disabled.");
438        } else {
439                char *kdata = packet_get_string(&dlen);
440                packet_check_eom();
441               
442                /* XXX - 0x41, see creds_to_radix version */
443                if (kdata[0] != 0x41) {
444#ifdef KRB5
445                        krb5_data tgt;
446                        tgt.data = kdata;
447                        tgt.length = dlen;
448                       
449                        if (auth_krb5_tgt(authctxt, &tgt))
450                                success = 1;
451                        else
452                                verbose("Kerberos v5 TGT refused for %.100s",
453                                    authctxt->user);
454#endif /* KRB5 */
455                } else {
456#ifdef AFS
457                        if (auth_krb4_tgt(authctxt, kdata))
458                                success = 1;
459                        else
460                                verbose("Kerberos v4 TGT refused for %.100s",
461                                    authctxt->user);
462#endif /* AFS */
463                }
464                xfree(kdata);
465        }
466#endif /* AFS || KRB5 */
467        return success;
468}
469
470/*
471 * This is called to fork and execute a command when we have no tty.  This
472 * will call do_child from the child, and server_loop from the parent after
473 * setting up file descriptors and such.
474 */
475void
476do_exec_no_pty(Session *s, const char *command)
477{
478        pid_t pid;
479
480#ifdef USE_PIPES
481        int pin[2], pout[2], perr[2];
482        /* Allocate pipes for communicating with the program. */
483        if (pipe(pin) < 0 || pipe(pout) < 0 || pipe(perr) < 0)
484                packet_disconnect("Could not create pipes: %.100s",
485                                  strerror(errno));
486#else /* USE_PIPES */
487        int inout[2], err[2];
488        /* Uses socket pairs to communicate with the program. */
489        if (socketpair(AF_UNIX, SOCK_STREAM, 0, inout) < 0 ||
490            socketpair(AF_UNIX, SOCK_STREAM, 0, err) < 0)
491                packet_disconnect("Could not create socket pairs: %.100s",
492                                  strerror(errno));
493#endif /* USE_PIPES */
494        if (s == NULL)
495                fatal("do_exec_no_pty: no session");
496
497        session_proctitle(s);
498
499#if defined(USE_PAM)
500        do_pam_session(s->pw->pw_name, NULL);
501        do_pam_setcred(1);
502        if (is_pam_password_change_required())
503                packet_disconnect("Password change required but no "
504                    "TTY available");
505#endif /* USE_PAM */
506
507        /* Fork the child. */
508        if ((pid = fork()) == 0) {
509                fatal_remove_all_cleanups();
510
511                /* Child.  Reinitialize the log since the pid has changed. */
512                log_init(__progname, options.log_level, options.log_facility, log_stderr);
513
514                /*
515                 * Create a new session and process group since the 4.4BSD
516                 * setlogin() affects the entire process group.
517                 */
518                if (setsid() < 0)
519                        error("setsid failed: %.100s", strerror(errno));
520
521#ifdef USE_PIPES
522                /*
523                 * Redirect stdin.  We close the parent side of the socket
524                 * pair, and make the child side the standard input.
525                 */
526                close(pin[1]);
527                if (dup2(pin[0], 0) < 0)
528                        perror("dup2 stdin");
529                close(pin[0]);
530
531                /* Redirect stdout. */
532                close(pout[0]);
533                if (dup2(pout[1], 1) < 0)
534                        perror("dup2 stdout");
535                close(pout[1]);
536
537                /* Redirect stderr. */
538                close(perr[0]);
539                if (dup2(perr[1], 2) < 0)
540                        perror("dup2 stderr");
541                close(perr[1]);
542#else /* USE_PIPES */
543                /*
544                 * Redirect stdin, stdout, and stderr.  Stdin and stdout will
545                 * use the same socket, as some programs (particularly rdist)
546                 * seem to depend on it.
547                 */
548                close(inout[1]);
549                close(err[1]);
550                if (dup2(inout[0], 0) < 0)      /* stdin */
551                        perror("dup2 stdin");
552                if (dup2(inout[0], 1) < 0)      /* stdout.  Note: same socket as stdin. */
553                        perror("dup2 stdout");
554                if (dup2(err[0], 2) < 0)        /* stderr */
555                        perror("dup2 stderr");
556#endif /* USE_PIPES */
557
558#ifdef _UNICOS
559                cray_init_job(s->pw); /* set up cray jid and tmpdir */
560#endif
561
562                /* Do processing for the child (exec command etc). */
563                do_child(s, command);
564                /* NOTREACHED */
565        }
566#ifdef _UNICOS
567        signal(WJSIGNAL, cray_job_termination_handler);
568#endif /* _UNICOS */
569#ifdef HAVE_CYGWIN
570        if (is_winnt)
571                cygwin_set_impersonation_token(INVALID_HANDLE_VALUE);
572#endif
573        if (pid < 0)
574                packet_disconnect("fork failed: %.100s", strerror(errno));
575        s->pid = pid;
576        /* Set interactive/non-interactive mode. */
577        packet_set_interactive(s->display != NULL);
578#ifdef USE_PIPES
579        /* We are the parent.  Close the child sides of the pipes. */
580        close(pin[0]);
581        close(pout[1]);
582        close(perr[1]);
583
584        if (compat20) {
585                session_set_fds(s, pin[1], pout[0], s->is_subsystem ? -1 : perr[0]);
586        } else {
587                /* Enter the interactive session. */
588                server_loop(pid, pin[1], pout[0], perr[0]);
589                /* server_loop has closed pin[1], pout[0], and perr[0]. */
590        }
591#else /* USE_PIPES */
592        /* We are the parent.  Close the child sides of the socket pairs. */
593        close(inout[0]);
594        close(err[0]);
595
596        /*
597         * Enter the interactive session.  Note: server_loop must be able to
598         * handle the case that fdin and fdout are the same.
599         */
600        if (compat20) {
601                session_set_fds(s, inout[1], inout[1], s->is_subsystem ? -1 : err[1]);
602        } else {
603                server_loop(pid, inout[1], inout[1], err[1]);
604                /* server_loop has closed inout[1] and err[1]. */
605        }
606#endif /* USE_PIPES */
607}
608
609/*
610 * This is called to fork and execute a command when we have a tty.  This
611 * will call do_child from the child, and server_loop from the parent after
612 * setting up file descriptors, controlling tty, updating wtmp, utmp,
613 * lastlog, and other such operations.
614 */
615void
616do_exec_pty(Session *s, const char *command)
617{
618        int fdout, ptyfd, ttyfd, ptymaster;
619        pid_t pid;
620
621        if (s == NULL)
622                fatal("do_exec_pty: no session");
623        ptyfd = s->ptyfd;
624        ttyfd = s->ttyfd;
625
626#if defined(USE_PAM)
627        do_pam_session(s->pw->pw_name, s->tty);
628        do_pam_setcred(1);
629#endif
630
631        /* Fork the child. */
632        if ((pid = fork()) == 0) {
633                fatal_remove_all_cleanups();
634
635                /* Child.  Reinitialize the log because the pid has changed. */
636                log_init(__progname, options.log_level, options.log_facility, log_stderr);
637                /* Close the master side of the pseudo tty. */
638                close(ptyfd);
639
640                /* Make the pseudo tty our controlling tty. */
641                pty_make_controlling_tty(&ttyfd, s->tty);
642
643                /* Redirect stdin/stdout/stderr from the pseudo tty. */
644                if (dup2(ttyfd, 0) < 0)
645                        error("dup2 stdin: %s", strerror(errno));
646                if (dup2(ttyfd, 1) < 0)
647                        error("dup2 stdout: %s", strerror(errno));
648                if (dup2(ttyfd, 2) < 0)
649                        error("dup2 stderr: %s", strerror(errno));
650
651                /* Close the extra descriptor for the pseudo tty. */
652                close(ttyfd);
653
654                /* record login, etc. similar to login(1) */
655#ifndef HAVE_OSF_SIA
656                if (!(options.use_login && command == NULL)) {
657#ifdef _UNICOS
658                        cray_init_job(s->pw); /* set up cray jid and tmpdir */
659#endif /* _UNICOS */
660                        do_login(s, command);
661                }
662# ifdef LOGIN_NEEDS_UTMPX
663                else
664                        do_pre_login(s);
665# endif
666#endif
667
668                /* Do common processing for the child, such as execing the command. */
669                do_child(s, command);
670                /* NOTREACHED */
671        }
672#ifdef _UNICOS
673        signal(WJSIGNAL, cray_job_termination_handler);
674#endif /* _UNICOS */
675#ifdef HAVE_CYGWIN
676        if (is_winnt)
677                cygwin_set_impersonation_token(INVALID_HANDLE_VALUE);
678#endif
679        if (pid < 0)
680                packet_disconnect("fork failed: %.100s", strerror(errno));
681        s->pid = pid;
682
683        /* Parent.  Close the slave side of the pseudo tty. */
684        close(ttyfd);
685
686        /*
687         * Create another descriptor of the pty master side for use as the
688         * standard input.  We could use the original descriptor, but this
689         * simplifies code in server_loop.  The descriptor is bidirectional.
690         */
691        fdout = dup(ptyfd);
692        if (fdout < 0)
693                packet_disconnect("dup #1 failed: %.100s", strerror(errno));
694
695        /* we keep a reference to the pty master */
696        ptymaster = dup(ptyfd);
697        if (ptymaster < 0)
698                packet_disconnect("dup #2 failed: %.100s", strerror(errno));
699        s->ptymaster = ptymaster;
700
701        /* Enter interactive session. */
702        packet_set_interactive(1);
703        if (compat20) {
704                session_set_fds(s, ptyfd, fdout, -1);
705        } else {
706                server_loop(pid, ptyfd, fdout, -1);
707                /* server_loop _has_ closed ptyfd and fdout. */
708        }
709}
710
711#ifdef LOGIN_NEEDS_UTMPX
712static void
713do_pre_login(Session *s)
714{
715        socklen_t fromlen;
716        struct sockaddr_storage from;
717        pid_t pid = getpid();
718
719        /*
720         * Get IP address of client. If the connection is not a socket, let
721         * the address be 0.0.0.0.
722         */
723        memset(&from, 0, sizeof(from));
724        fromlen = sizeof(from);
725        if (packet_connection_is_on_socket()) {
726                if (getpeername(packet_get_connection_in(),
727                    (struct sockaddr *) & from, &fromlen) < 0) {
728                        debug("getpeername: %.100s", strerror(errno));
729                        fatal_cleanup();
730                }
731        }
732
733        record_utmp_only(pid, s->tty, s->pw->pw_name,
734            get_remote_name_or_ip(utmp_len, options.verify_reverse_mapping),
735            (struct sockaddr *)&from);
736}
737#endif
738
739/*
740 * This is called to fork and execute a command.  If another command is
741 * to be forced, execute that instead.
742 */
743void
744do_exec(Session *s, const char *command)
745{
746  int status;
747  char *filetext, *errmem;
748  const char *err;
749  int havecred = 0;
750
751#if defined(GSSAPI)
752        temporarily_use_uid(s->pw);
753        ssh_gssapi_storecreds(s->authctxt);
754        restore_uid();
755#endif
756
757#if KRB5
758  if (s->authctxt->krb5_ticket_file)
759    {
760      havecred = 1;
761      if (options.kerberos524 && s->authctxt->krb5_user)
762        {
763          status = do_krb524_conversion(s->authctxt);
764          if (status)
765            debug("krb524 failed: %s",
766                  krb5_get_err_text(s->authctxt->krb5_ctx, status));
767        }
768    }
769 
770#endif
771        try_afscall(setpag);
772        atexit(krb_cleanup);
773
774        if (!is_local_acct)
775          {
776            struct passwd *pw;
777
778            status = al_acct_create(s->authctxt->user, getpid(), havecred, 1,
779                                    &session_warnings);
780            if (status != AL_SUCCESS && status != AL_WARNINGS)
781              packet_disconnect("%s\n", al_strerror(status, &errmem));
782            /*
783             * Look up the passwd entry again, as al_acct_create()
784             * may have modified it.
785             */
786            pw = getpwnam(s->authctxt->user);
787            if (pw == NULL)
788              packet_disconnect("Cannot get password entry\n");
789            pwfree(s->authctxt->pw);
790            s->authctxt->pw = pwcopy(pw);
791            s->pw = s->authctxt->pw;
792          }
793
794        if (forced_command) {
795                original_command = command;
796                command = forced_command;
797                debug("Forced command '%.900s'", command);
798        }
799
800        if (s->ttyfd != -1)
801                do_exec_pty(s, command);
802        else
803                do_exec_no_pty(s, command);
804
805        original_command = NULL;
806}
807
808
809/* administrative, login(1)-like work */
810void
811do_login(Session *s, const char *command)
812{
813        char *time_string;
814        socklen_t fromlen;
815        struct sockaddr_storage from;
816        struct passwd * pw = s->pw;
817        pid_t pid = getpid();
818
819        /*
820         * Get IP address of client. If the connection is not a socket, let
821         * the address be 0.0.0.0.
822         */
823        memset(&from, 0, sizeof(from));
824        if (packet_connection_is_on_socket()) {
825                fromlen = sizeof(from);
826                if (getpeername(packet_get_connection_in(),
827                    (struct sockaddr *) & from, &fromlen) < 0) {
828                        debug("getpeername: %.100s", strerror(errno));
829                        fatal_cleanup();
830                }
831        }
832
833        /* Record that there was a login on that tty from the remote host. */
834        if (!use_privsep)
835                record_login(pid, s->tty, pw->pw_name, pw->pw_uid,
836                    get_remote_name_or_ip(utmp_len,
837                    options.verify_reverse_mapping),
838                    (struct sockaddr *)&from, fromlen);
839
840#ifdef USE_PAM
841        /*
842         * If password change is needed, do it now.
843         * This needs to occur before the ~/.hushlogin check.
844         */
845        if (is_pam_password_change_required()) {
846                print_pam_messages();
847                do_pam_chauthtok();
848        }
849#endif
850
851        if (check_quietlogin(s, command))
852                return;
853
854#ifdef USE_PAM
855        if (!is_pam_password_change_required())
856                print_pam_messages();
857#endif /* USE_PAM */
858#ifdef WITH_AIXAUTHENTICATE
859        if (aixloginmsg && *aixloginmsg)
860                printf("%s\n", aixloginmsg);
861#endif /* WITH_AIXAUTHENTICATE */
862
863#ifndef NO_SSH_LASTLOG
864        if (options.print_lastlog && s->last_login_time != 0) {
865                time_string = ctime(&s->last_login_time);
866                if (strchr(time_string, '\n'))
867                        *strchr(time_string, '\n') = 0;
868                if (strcmp(s->hostname, "") == 0)
869                        printf("Last login: %s\r\n", time_string);
870                else
871                        printf("Last login: %s from %s\r\n", time_string,
872                            s->hostname);
873        }
874#endif /* NO_SSH_LASTLOG */
875
876        do_motd();
877}
878
879/*
880 * Display the message of the day.
881 */
882void
883do_motd(void)
884{
885        FILE *f;
886        char buf[256];
887
888        if (options.print_motd) {
889#ifdef HAVE_LOGIN_CAP
890                f = fopen(login_getcapstr(lc, "welcome", "/etc/motd",
891                    "/etc/motd"), "r");
892#else
893                f = fopen("/etc/motd", "r");
894#endif
895                if (f) {
896                        while (fgets(buf, sizeof(buf), f))
897                                fputs(buf, stdout);
898                        fclose(f);
899                }
900        }
901}
902
903
904/*
905 * Check for quiet login, either .hushlogin or command given.
906 */
907int
908check_quietlogin(Session *s, const char *command)
909{
910        char buf[256];
911        struct passwd *pw = s->pw;
912        struct stat st;
913
914        /* Return 1 if .hushlogin exists or a command given. */
915        if (command != NULL)
916                return 1;
917        snprintf(buf, sizeof(buf), "%.200s/.hushlogin", pw->pw_dir);
918#ifdef HAVE_LOGIN_CAP
919        if (login_getcapbool(lc, "hushlogin", 0) || stat(buf, &st) >= 0)
920                return 1;
921#else
922        if (stat(buf, &st) >= 0)
923                return 1;
924#endif
925        return 0;
926}
927
928/*
929 * Sets the value of the given variable in the environment.  If the variable
930 * already exists, its value is overriden.
931 */
932void
933child_set_env(char ***envp, u_int *envsizep, const char *name,
934        const char *value)
935{
936        u_int i, namelen;
937        char **env;
938
939        /*
940         * Find the slot where the value should be stored.  If the variable
941         * already exists, we reuse the slot; otherwise we append a new slot
942         * at the end of the array, expanding if necessary.
943         */
944        env = *envp;
945        namelen = strlen(name);
946        for (i = 0; env[i]; i++)
947                if (strncmp(env[i], name, namelen) == 0 && env[i][namelen] == '=')
948                        break;
949        if (env[i]) {
950                /* Reuse the slot. */
951                xfree(env[i]);
952        } else {
953                /* New variable.  Expand if necessary. */
954                if (i >= (*envsizep) - 1) {
955                        if (*envsizep >= 1000)
956                                fatal("child_set_env: too many env vars,"
957                                    " skipping: %.100s", name);
958                        (*envsizep) += 50;
959                        env = (*envp) = xrealloc(env, (*envsizep) * sizeof(char *));
960                }
961                /* Need to set the NULL pointer at end of array beyond the new slot. */
962                env[i + 1] = NULL;
963        }
964
965        /* Allocate space and format the variable in the appropriate slot. */
966        env[i] = xmalloc(strlen(name) + 1 + strlen(value) + 1);
967        snprintf(env[i], strlen(name) + 1 + strlen(value) + 1, "%s=%s", name, value);
968}
969
970/*
971 * Reads environment variables from the given file and adds/overrides them
972 * into the environment.  If the file does not exist, this does nothing.
973 * Otherwise, it must consist of empty lines, comments (line starts with '#')
974 * and assignments of the form name=value.  No other forms are allowed.
975 */
976static void
977read_environment_file(char ***env, u_int *envsize,
978        const char *filename)
979{
980        FILE *f;
981        char buf[4096];
982        char *cp, *value;
983        u_int lineno = 0;
984
985        f = fopen(filename, "r");
986        if (!f)
987                return;
988
989        while (fgets(buf, sizeof(buf), f)) {
990                if (++lineno > 1000)
991                        fatal("Too many lines in environment file %s", filename);
992                for (cp = buf; *cp == ' ' || *cp == '\t'; cp++)
993                        ;
994                if (!*cp || *cp == '#' || *cp == '\n')
995                        continue;
996                if (strchr(cp, '\n'))
997                        *strchr(cp, '\n') = '\0';
998                value = strchr(cp, '=');
999                if (value == NULL) {
1000                        fprintf(stderr, "Bad line %u in %.100s\n", lineno,
1001                            filename);
1002                        continue;
1003                }
1004                /*
1005                 * Replace the equals sign by nul, and advance value to
1006                 * the value string.
1007                 */
1008                *value = '\0';
1009                value++;
1010                child_set_env(env, envsize, cp, value);
1011        }
1012        fclose(f);
1013}
1014
1015void copy_environment(char **source, char ***env, u_int *envsize)
1016{
1017        char *var_name, *var_val;
1018        int i;
1019
1020        if (source == NULL)
1021                return;
1022
1023        for(i = 0; source[i] != NULL; i++) {
1024                var_name = xstrdup(source[i]);
1025                if ((var_val = strstr(var_name, "=")) == NULL) {
1026                        xfree(var_name);
1027                        continue;
1028                }
1029                *var_val++ = '\0';
1030
1031                debug3("Copy environment: %s=%s", var_name, var_val);
1032                child_set_env(env, envsize, var_name, var_val);
1033               
1034                xfree(var_name);
1035        }
1036}
1037
1038static char **
1039do_setup_env(Session *s, const char *shell)
1040{
1041        char buf[256];
1042        u_int i, envsize;
1043        char **env, *cp;
1044        struct passwd *pw = s->pw;
1045
1046        /* Initialize the environment. */
1047        envsize = 100;
1048        env = xmalloc(envsize * sizeof(char *));
1049        env[0] = NULL;
1050       
1051        /* Print any leftover libAL warnings */
1052        if (session_warnings)
1053          {
1054            int i;
1055            char *errmem;
1056           
1057            for (i = 0; session_warnings[i]; i++)
1058              {
1059                fprintf(stderr, "Warning: %s\n",
1060                        al_strerror(session_warnings[i], &errmem));
1061                al_free_errmem(errmem);
1062              }
1063            free(session_warnings);
1064          }
1065
1066#ifdef HAVE_CYGWIN
1067        /*
1068         * The Windows environment contains some setting which are
1069         * important for a running system. They must not be dropped.
1070         */
1071        copy_environment(environ, &env, &envsize);
1072#endif
1073
1074#ifdef GSSAPI
1075        /* Allow any GSSAPI methods that we've used to alter
1076         * the childs environment as they see fit
1077         */
1078        ssh_gssapi_do_child(&env,&envsize);
1079#endif
1080
1081        if (!options.use_login) {
1082                /* Set basic environment. */
1083                child_set_env(&env, &envsize, "USER", pw->pw_name);
1084                child_set_env(&env, &envsize, "LOGNAME", pw->pw_name);
1085                child_set_env(&env, &envsize, "HOME", pw->pw_dir);
1086#ifdef HAVE_LOGIN_CAP
1087                if (setusercontext(lc, pw, pw->pw_uid, LOGIN_SETPATH) < 0)
1088                        child_set_env(&env, &envsize, "PATH", _PATH_STDPATH);
1089                else
1090                        child_set_env(&env, &envsize, "PATH", getenv("PATH"));
1091#else /* HAVE_LOGIN_CAP */
1092# ifndef HAVE_CYGWIN
1093                /*
1094                 * There's no standard path on Windows. The path contains
1095                 * important components pointing to the system directories,
1096                 * needed for loading shared libraries. So the path better
1097                 * remains intact here.
1098                 */
1099#  ifdef SUPERUSER_PATH
1100                child_set_env(&env, &envsize, "PATH",
1101                    s->pw->pw_uid == 0 ? SUPERUSER_PATH : _PATH_STDPATH);
1102#  else
1103                child_set_env(&env, &envsize, "PATH", _PATH_STDPATH);
1104#  endif /* SUPERUSER_PATH */
1105# endif /* HAVE_CYGWIN */
1106#endif /* HAVE_LOGIN_CAP */
1107
1108                snprintf(buf, sizeof buf, "%.200s/%.50s",
1109                         _PATH_MAILDIR, pw->pw_name);
1110                child_set_env(&env, &envsize, "MAIL", buf);
1111
1112                /* Normal systems set SHELL by default. */
1113                child_set_env(&env, &envsize, "SHELL", shell);
1114        }
1115        if (getenv("TZ"))
1116                child_set_env(&env, &envsize, "TZ", getenv("TZ"));
1117
1118        /* Set custom environment options from RSA authentication. */
1119        if (!options.use_login) {
1120                while (custom_environment) {
1121                        struct envstring *ce = custom_environment;
1122                        char *str = ce->s;
1123
1124                        for (i = 0; str[i] != '=' && str[i]; i++)
1125                                ;
1126                        if (str[i] == '=') {
1127                                str[i] = 0;
1128                                child_set_env(&env, &envsize, str, str + i + 1);
1129                        }
1130                        custom_environment = ce->next;
1131                        xfree(ce->s);
1132                        xfree(ce);
1133                }
1134        }
1135
1136        /* SSH_CLIENT deprecated */
1137        snprintf(buf, sizeof buf, "%.50s %d %d",
1138            get_remote_ipaddr(), get_remote_port(), get_local_port());
1139        child_set_env(&env, &envsize, "SSH_CLIENT", buf);
1140
1141        snprintf(buf, sizeof buf, "%.50s %d %.50s %d",
1142            get_remote_ipaddr(), get_remote_port(),
1143            get_local_ipaddr(packet_get_connection_in()), get_local_port());
1144        child_set_env(&env, &envsize, "SSH_CONNECTION", buf);
1145
1146        if (s->ttyfd != -1)
1147                child_set_env(&env, &envsize, "SSH_TTY", s->tty);
1148        if (s->term)
1149                child_set_env(&env, &envsize, "TERM", s->term);
1150        if (s->display)
1151                child_set_env(&env, &envsize, "DISPLAY", s->display);
1152        if (original_command)
1153                child_set_env(&env, &envsize, "SSH_ORIGINAL_COMMAND",
1154                    original_command);
1155
1156#ifdef _UNICOS
1157        if (cray_tmpdir[0] != '\0')
1158                child_set_env(&env, &envsize, "TMPDIR", cray_tmpdir);
1159#endif /* _UNICOS */
1160
1161#ifdef _AIX
1162        {
1163                if ((cp = getenv("AUTHSTATE")) != NULL)
1164                        child_set_env(&env, &envsize, "AUTHSTATE", cp);
1165                if ((cp = getenv("KRB5CCNAME")) != NULL)
1166                        child_set_env(&env, &envsize, "KRB5CCNAME", cp);
1167                read_environment_file(&env, &envsize, "/etc/environment");
1168        }
1169#endif
1170#ifdef KRB4
1171        if (s->authctxt->krb4_ticket_file)
1172                child_set_env(&env, &envsize, "KRBTKFILE",
1173                    s->authctxt->krb4_ticket_file);
1174#endif
1175#ifdef KRB5
1176        if (s->authctxt->krb5_ticket_file)
1177                child_set_env(&env, &envsize, "KRB5CCNAME",
1178                    s->authctxt->krb5_ticket_file);
1179        /*
1180         * XXX something bad might happen if you did Krb4 at the same time...
1181         */
1182        if ((cp = getenv("KRBTKFILE")) != NULL)
1183                child_set_env(&env, &envsize, "KRBTKFILE", cp);
1184#endif
1185#ifdef USE_PAM
1186        /*
1187         * Pull in any environment variables that may have
1188         * been set by PAM.
1189         */
1190        {
1191                char **p;
1192
1193                p = fetch_pam_environment();
1194                copy_environment(p, &env, &envsize);
1195                free_pam_environment(p);
1196        }
1197#endif /* USE_PAM */
1198
1199        if (auth_sock_name != NULL)
1200                child_set_env(&env, &envsize, SSH_AUTHSOCKET_ENV_NAME,
1201                    auth_sock_name);
1202
1203        { /* more hacks */
1204                sprintf(buf, "/tmp/xauth-%s-%d", s->authctxt->user,
1205                        (int)getpid());
1206                if (mkdir(buf, S_IRWXU) == -1)
1207                {
1208                        /* XXX */
1209                        fprintf(stderr, "Could not create xauth directory %s: %s\n"
1210                                "Disabling X forwarding.\n", buf, strerror(errno));
1211                }
1212                else
1213                {
1214                        strcat(buf, "/Xauthority");
1215                        child_set_env(&env, &envsize, "XAUTHORITY", buf);
1216                }
1217        }     
1218
1219
1220        /* read $HOME/.ssh/environment. */
1221        if (options.permit_user_env && !options.use_login) {
1222                snprintf(buf, sizeof buf, "%.200s/.ssh/environment",
1223                    strcmp(pw->pw_dir, "/") ? pw->pw_dir : "");
1224                read_environment_file(&env, &envsize, buf);
1225        }
1226        if (debug_flag) {
1227                /* dump the environment */
1228                fprintf(stderr, "Environment:\n");
1229                for (i = 0; env[i]; i++)
1230                        fprintf(stderr, "  %.300s\n", env[i]);
1231        }
1232        return env;
1233}
1234
1235/*
1236 * Run $HOME/.ssh/rc, /etc/ssh/sshrc, or xauth (whichever is found
1237 * first in this order).
1238 */
1239static void
1240do_rc_files(Session *s, const char *shell)
1241{
1242        FILE *f = NULL;
1243        char cmd[1024];
1244        int do_xauth;
1245        struct stat st;
1246
1247        do_xauth =
1248            s->display != NULL && s->auth_proto != NULL && s->auth_data != NULL;
1249
1250        /* ignore _PATH_SSH_USER_RC for subsystems */
1251        if (!s->is_subsystem && (stat(_PATH_SSH_USER_RC, &st) >= 0)) {
1252                snprintf(cmd, sizeof cmd, "%s -c '%s %s'",
1253                    shell, _PATH_BSHELL, _PATH_SSH_USER_RC);
1254                if (debug_flag)
1255                        fprintf(stderr, "Running %s\n", cmd);
1256                f = popen(cmd, "w");
1257                if (f) {
1258                        if (do_xauth)
1259                                fprintf(f, "%s %s\n", s->auth_proto,
1260                                    s->auth_data);
1261                        pclose(f);
1262                } else
1263                        fprintf(stderr, "Could not run %s\n",
1264                            _PATH_SSH_USER_RC);
1265        } else if (stat(_PATH_SSH_SYSTEM_RC, &st) >= 0) {
1266                if (debug_flag)
1267                        fprintf(stderr, "Running %s %s\n", _PATH_BSHELL,
1268                            _PATH_SSH_SYSTEM_RC);
1269                f = popen(_PATH_BSHELL " " _PATH_SSH_SYSTEM_RC, "w");
1270                if (f) {
1271                        if (do_xauth)
1272                                fprintf(f, "%s %s\n", s->auth_proto,
1273                                    s->auth_data);
1274                        pclose(f);
1275                } else
1276                        fprintf(stderr, "Could not run %s\n",
1277                            _PATH_SSH_SYSTEM_RC);
1278        } else if (do_xauth && options.xauth_location != NULL) {
1279                /* Add authority data to .Xauthority if appropriate. */
1280                if (debug_flag) {
1281                        fprintf(stderr,
1282                            "Running %.500s add "
1283                            "%.100s %.100s %.100s\n",
1284                            options.xauth_location, s->auth_display,
1285                            s->auth_proto, s->auth_data);
1286                }
1287                snprintf(cmd, sizeof cmd, "%s -q -",
1288                    options.xauth_location);
1289                f = popen(cmd, "w");
1290                if (f) {
1291                        fprintf(f, "add %s %s %s\n",
1292                            s->auth_display, s->auth_proto,
1293                            s->auth_data);
1294                        pclose(f);
1295                } else {
1296                        fprintf(stderr, "Could not run %s\n",
1297                            cmd);
1298                }
1299        }
1300}
1301
1302static void
1303do_nologin(struct passwd *pw)
1304{
1305        FILE *f = NULL;
1306        char buf[1024];
1307
1308#ifdef HAVE_LOGIN_CAP
1309        if (!login_getcapbool(lc, "ignorenologin", 0) && pw->pw_uid)
1310                f = fopen(login_getcapstr(lc, "nologin", _PATH_NOLOGIN,
1311                    _PATH_NOLOGIN), "r");
1312#else
1313        if (pw->pw_uid)
1314                f = fopen(_PATH_NOLOGIN, "r");
1315#endif
1316        if (f) {
1317                /* /etc/nologin exists.  Print its contents and exit. */
1318                log("User %.100s not allowed because %s exists",
1319                    pw->pw_name, _PATH_NOLOGIN);
1320                while (fgets(buf, sizeof(buf), f))
1321                        fputs(buf, stderr);
1322                fclose(f);
1323                exit(254);
1324        }
1325}
1326
1327/* Set login name, uid, gid, and groups. */
1328void
1329do_setusercontext(struct passwd *pw)
1330{
1331#ifdef HAVE_CYGWIN
1332        if (is_winnt) {
1333#else /* HAVE_CYGWIN */
1334        if (getuid() == 0 || geteuid() == 0) {
1335#endif /* HAVE_CYGWIN */
1336#ifdef HAVE_SETPCRED
1337                setpcred(pw->pw_name);
1338#endif /* HAVE_SETPCRED */
1339#ifdef HAVE_LOGIN_CAP
1340# ifdef __bsdi__
1341                setpgid(0, 0);
1342# endif
1343                if (setusercontext(lc, pw, pw->pw_uid,
1344                    (LOGIN_SETALL & ~LOGIN_SETPATH)) < 0) {
1345                        perror("unable to set user context");
1346                        exit(1);
1347                }
1348#else
1349# if defined(HAVE_GETLUID) && defined(HAVE_SETLUID)
1350                /* Sets login uid for accounting */
1351                if (getluid() == -1 && setluid(pw->pw_uid) == -1)
1352                        error("setluid: %s", strerror(errno));
1353# endif /* defined(HAVE_GETLUID) && defined(HAVE_SETLUID) */
1354
1355                if (setlogin(pw->pw_name) < 0)
1356                        error("setlogin failed: %s", strerror(errno));
1357                if (setgid(pw->pw_gid) < 0) {
1358                        perror("setgid");
1359                        exit(1);
1360                }
1361                /* Initialize the group list. */
1362                if (initgroups(pw->pw_name, pw->pw_gid) < 0) {
1363                        perror("initgroups");
1364                        exit(1);
1365                }
1366                endgrent();
1367# ifdef USE_PAM
1368                /*
1369                 * PAM credentials may take the form of supplementary groups.
1370                 * These will have been wiped by the above initgroups() call.
1371                 * Reestablish them here.
1372                 */
1373                do_pam_setcred(0);
1374# endif /* USE_PAM */
1375# if defined(WITH_IRIX_PROJECT) || defined(WITH_IRIX_JOBS) || defined(WITH_IRIX_ARRAY)
1376                irix_setusercontext(pw);
1377#  endif /* defined(WITH_IRIX_PROJECT) || defined(WITH_IRIX_JOBS) || defined(WITH_IRIX_ARRAY) */
1378# ifdef _AIX
1379                aix_usrinfo(pw);
1380# endif /* _AIX */
1381                /* Permanently switch to the desired uid. */
1382                permanently_set_uid(pw);
1383#endif
1384        }
1385        if (getuid() != pw->pw_uid || geteuid() != pw->pw_uid)
1386                fatal("Failed to set uids to %u.", (u_int) pw->pw_uid);
1387}
1388
1389static void
1390launch_login(struct passwd *pw, const char *hostname)
1391{
1392        /* Launch login(1). */
1393
1394        execl(LOGIN_PROGRAM, "login", "-h", hostname,
1395#ifdef xxxLOGIN_NEEDS_TERM
1396                    (s->term ? s->term : "unknown"),
1397#endif /* LOGIN_NEEDS_TERM */
1398#ifdef LOGIN_NO_ENDOPT
1399            "-p", "-f", pw->pw_name, (char *)NULL);
1400#else
1401            "-p", "-f", "--", pw->pw_name, (char *)NULL);
1402#endif
1403
1404        /* Login couldn't be executed, die. */
1405
1406        perror("login");
1407        exit(1);
1408}
1409
1410/*
1411 * Performs common processing for the child, such as setting up the
1412 * environment, closing extra file descriptors, setting the user and group
1413 * ids, and executing the command or shell.
1414 */
1415void
1416do_child(Session *s, const char *command)
1417{
1418        extern char **environ;
1419        char **env;
1420        char *argv[10];
1421        const char *shell, *shell0, *hostname = NULL;
1422        struct passwd *pw = s->pw;
1423        u_int i;
1424
1425        /* remove hostkey from the child's memory */
1426        destroy_sensitive_data();
1427
1428        /* login(1) is only called if we execute the login shell */
1429        if (options.use_login && command != NULL)
1430                options.use_login = 0;
1431
1432#ifdef _UNICOS
1433        cray_setup(pw->pw_uid, pw->pw_name, command);
1434#endif /* _UNICOS */
1435
1436        /*
1437         * Login(1) does this as well, and it needs uid 0 for the "-h"
1438         * switch, so we let login(1) to this for us.
1439         */
1440        if (!options.use_login) {
1441#ifdef HAVE_OSF_SIA
1442                session_setup_sia(pw->pw_name, s->ttyfd == -1 ? NULL : s->tty);
1443                if (!check_quietlogin(s, command))
1444                        do_motd();
1445#else /* HAVE_OSF_SIA */
1446                do_nologin(pw);
1447                do_setusercontext(pw);
1448#endif /* HAVE_OSF_SIA */
1449        }
1450
1451        /*
1452         * Get the shell from the password data.  An empty shell field is
1453         * legal, and means /bin/sh.
1454         */
1455        shell = (pw->pw_shell[0] == '\0') ? _PATH_BSHELL : pw->pw_shell;
1456#ifdef HAVE_LOGIN_CAP
1457        shell = login_getcapstr(lc, "shell", (char *)shell, (char *)shell);
1458#endif
1459
1460        env = do_setup_env(s, shell);
1461
1462        /* we have to stash the hostname before we close our socket. */
1463        if (options.use_login)
1464                hostname = get_remote_name_or_ip(utmp_len,
1465                    options.verify_reverse_mapping);
1466        /*
1467         * Close the connection descriptors; note that this is the child, and
1468         * the server will still have the socket open, and it is important
1469         * that we do not shutdown it.  Note that the descriptors cannot be
1470         * closed before building the environment, as we call
1471         * get_remote_ipaddr there.
1472         */
1473        if (packet_get_connection_in() == packet_get_connection_out())
1474                close(packet_get_connection_in());
1475        else {
1476                close(packet_get_connection_in());
1477                close(packet_get_connection_out());
1478        }
1479        /*
1480         * Close all descriptors related to channels.  They will still remain
1481         * open in the parent.
1482         */
1483        /* XXX better use close-on-exec? -markus */
1484        channel_close_all();
1485
1486        /*
1487         * Close any extra file descriptors.  Note that there may still be
1488         * descriptors left by system functions.  They will be closed later.
1489         */
1490        endpwent();
1491
1492        /*
1493         * Close any extra open file descriptors so that we don\'t have them
1494         * hanging around in clients.  Note that we want to do this after
1495         * initgroups, because at least on Solaris 2.3 it leaves file
1496         * descriptors open.
1497         */
1498        for (i = 3; i < 64; i++)
1499                close(i);
1500
1501        /*
1502         * Must take new environment into use so that .ssh/rc,
1503         * /etc/ssh/sshrc and xauth are run in the proper environment.
1504         */
1505        environ = env;
1506
1507#ifdef AFS
1508        /* Try to get AFS tokens for the local cell. */
1509        if (k_hasafs()) {
1510                char cell[64];
1511
1512                if (k_afs_cell_of_file(pw->pw_dir, cell, sizeof(cell)) == 0)
1513                        krb_afslog(cell, 0);
1514
1515                krb_afslog(0, 0);
1516        }
1517#endif /* AFS */
1518
1519        /* Change current directory to the user\'s home directory. */
1520        if (chdir(pw->pw_dir) < 0) {
1521                fprintf(stderr, "Could not chdir to home directory %s: %s\n",
1522                    pw->pw_dir, strerror(errno));
1523#ifdef HAVE_LOGIN_CAP
1524                if (login_getcapbool(lc, "requirehome", 0))
1525                        exit(1);
1526#endif
1527        }
1528
1529        if (!options.use_login)
1530                do_rc_files(s, shell);
1531
1532        /* restore SIGPIPE for child */
1533        signal(SIGPIPE,  SIG_DFL);
1534
1535        if (options.use_login) {
1536                launch_login(pw, hostname);
1537                /* NEVERREACHED */
1538        }
1539
1540        /* Get the last component of the shell name. */
1541        if ((shell0 = strrchr(shell, '/')) != NULL)
1542                shell0++;
1543        else
1544                shell0 = shell;
1545
1546        /*
1547         * If we have no command, execute the shell.  In this case, the shell
1548         * name to be passed in argv[0] is preceded by '-' to indicate that
1549         * this is a login shell.
1550         */
1551        if (!command) {
1552                char argv0[256];
1553
1554                /* Start the shell.  Set initial character to '-'. */
1555                argv0[0] = '-';
1556
1557                if (strlcpy(argv0 + 1, shell0, sizeof(argv0) - 1)
1558                    >= sizeof(argv0) - 1) {
1559                        errno = EINVAL;
1560                        perror(shell);
1561                        exit(1);
1562                }
1563
1564                /* Execute the shell. */
1565                argv[0] = argv0;
1566                argv[1] = NULL;
1567                execve(shell, argv, env);
1568
1569                /* Executing the shell failed. */
1570                perror(shell);
1571                exit(1);
1572        }
1573        /*
1574         * Execute the command using the user's shell.  This uses the -c
1575         * option to execute the command.
1576         */
1577        argv[0] = (char *) shell0;
1578        argv[1] = "-c";
1579        argv[2] = (char *) command;
1580        argv[3] = NULL;
1581        execve(shell, argv, env);
1582        perror(shell);
1583        exit(1);
1584}
1585
1586Session *
1587session_new(void)
1588{
1589        int i;
1590        static int did_init = 0;
1591        if (!did_init) {
1592                debug("session_new: init");
1593                for (i = 0; i < MAX_SESSIONS; i++) {
1594                        sessions[i].used = 0;
1595                }
1596                did_init = 1;
1597        }
1598        for (i = 0; i < MAX_SESSIONS; i++) {
1599                Session *s = &sessions[i];
1600                if (! s->used) {
1601                        memset(s, 0, sizeof(*s));
1602                        s->chanid = -1;
1603                        s->ptyfd = -1;
1604                        s->ttyfd = -1;
1605                        s->used = 1;
1606                        s->self = i;
1607                        debug("session_new: session %d", i);
1608                        return s;
1609                }
1610        }
1611        return NULL;
1612}
1613
1614static void
1615session_dump(void)
1616{
1617        int i;
1618        for (i = 0; i < MAX_SESSIONS; i++) {
1619                Session *s = &sessions[i];
1620                debug("dump: used %d session %d %p channel %d pid %ld",
1621                    s->used,
1622                    s->self,
1623                    s,
1624                    s->chanid,
1625                    (long)s->pid);
1626        }
1627}
1628
1629int
1630session_open(Authctxt *authctxt, int chanid)
1631{
1632        Session *s = session_new();
1633        debug("session_open: channel %d", chanid);
1634        if (s == NULL) {
1635                error("no more sessions");
1636                return 0;
1637        }
1638        s->authctxt = authctxt;
1639        s->pw = authctxt->pw;
1640        if (s->pw == NULL)
1641                fatal("no user for session %d", s->self);
1642        debug("session_open: session %d: link with channel %d", s->self, chanid);
1643        s->chanid = chanid;
1644        return 1;
1645}
1646
1647Session *
1648session_by_tty(char *tty)
1649{
1650        int i;
1651        for (i = 0; i < MAX_SESSIONS; i++) {
1652                Session *s = &sessions[i];
1653                if (s->used && s->ttyfd != -1 && strcmp(s->tty, tty) == 0) {
1654                        debug("session_by_tty: session %d tty %s", i, tty);
1655                        return s;
1656                }
1657        }
1658        debug("session_by_tty: unknown tty %.100s", tty);
1659        session_dump();
1660        return NULL;
1661}
1662
1663static Session *
1664session_by_channel(int id)
1665{
1666        int i;
1667        for (i = 0; i < MAX_SESSIONS; i++) {
1668                Session *s = &sessions[i];
1669                if (s->used && s->chanid == id) {
1670                        debug("session_by_channel: session %d channel %d", i, id);
1671                        return s;
1672                }
1673        }
1674        debug("session_by_channel: unknown channel %d", id);
1675        session_dump();
1676        return NULL;
1677}
1678
1679static Session *
1680session_by_pid(pid_t pid)
1681{
1682        int i;
1683        debug("session_by_pid: pid %ld", (long)pid);
1684        for (i = 0; i < MAX_SESSIONS; i++) {
1685                Session *s = &sessions[i];
1686                if (s->used && s->pid == pid)
1687                        return s;
1688        }
1689        error("session_by_pid: unknown pid %ld", (long)pid);
1690        session_dump();
1691        return NULL;
1692}
1693
1694static int
1695session_window_change_req(Session *s)
1696{
1697        s->col = packet_get_int();
1698        s->row = packet_get_int();
1699        s->xpixel = packet_get_int();
1700        s->ypixel = packet_get_int();
1701        packet_check_eom();
1702        pty_change_window_size(s->ptyfd, s->row, s->col, s->xpixel, s->ypixel);
1703        return 1;
1704}
1705
1706static int
1707session_pty_req(Session *s)
1708{
1709        u_int len;
1710        int n_bytes;
1711
1712        if (no_pty_flag) {
1713                debug("Allocating a pty not permitted for this authentication.");
1714                return 0;
1715        }
1716        if (s->ttyfd != -1) {
1717                packet_disconnect("Protocol error: you already have a pty.");
1718                return 0;
1719        }
1720        /* Get the time and hostname when the user last logged in. */
1721        if (options.print_lastlog) {
1722                s->hostname[0] = '\0';
1723                s->last_login_time = get_last_login_time(s->pw->pw_uid,
1724                    s->pw->pw_name, s->hostname, sizeof(s->hostname));
1725        }
1726
1727        s->term = packet_get_string(&len);
1728
1729        if (compat20) {
1730                s->col = packet_get_int();
1731                s->row = packet_get_int();
1732        } else {
1733                s->row = packet_get_int();
1734                s->col = packet_get_int();
1735        }
1736        s->xpixel = packet_get_int();
1737        s->ypixel = packet_get_int();
1738
1739        if (strcmp(s->term, "") == 0) {
1740                xfree(s->term);
1741                s->term = NULL;
1742        }
1743
1744        /* Allocate a pty and open it. */
1745        debug("Allocating pty.");
1746        if (!PRIVSEP(pty_allocate(&s->ptyfd, &s->ttyfd, s->tty, sizeof(s->tty)))) {
1747                if (s->term)
1748                        xfree(s->term);
1749                s->term = NULL;
1750                s->ptyfd = -1;
1751                s->ttyfd = -1;
1752                error("session_pty_req: session %d alloc failed", s->self);
1753                return 0;
1754        }
1755        debug("session_pty_req: session %d alloc %s", s->self, s->tty);
1756
1757        /* for SSH1 the tty modes length is not given */
1758        if (!compat20)
1759                n_bytes = packet_remaining();
1760        tty_parse_modes(s->ttyfd, &n_bytes);
1761
1762        /*
1763         * Add a cleanup function to clear the utmp entry and record logout
1764         * time in case we call fatal() (e.g., the connection gets closed).
1765         */
1766        fatal_add_cleanup(session_pty_cleanup, (void *)s);
1767        if (!use_privsep)
1768                pty_setowner(s->pw, s->tty);
1769
1770        /* Set window size from the packet. */
1771        pty_change_window_size(s->ptyfd, s->row, s->col, s->xpixel, s->ypixel);
1772
1773        packet_check_eom();
1774        session_proctitle(s);
1775        return 1;
1776}
1777
1778static int
1779session_subsystem_req(Session *s)
1780{
1781        struct stat st;
1782        u_int len;
1783        int success = 0;
1784        char *cmd, *subsys = packet_get_string(&len);
1785        int i;
1786
1787        packet_check_eom();
1788        log("subsystem request for %.100s", subsys);
1789
1790        for (i = 0; i < options.num_subsystems; i++) {
1791                if (strcmp(subsys, options.subsystem_name[i]) == 0) {
1792                        cmd = options.subsystem_command[i];
1793                        if (stat(cmd, &st) < 0) {
1794                                error("subsystem: cannot stat %s: %s", cmd,
1795                                    strerror(errno));
1796                                break;
1797                        }
1798                        debug("subsystem: exec() %s", cmd);
1799                        s->is_subsystem = 1;
1800                        do_exec(s, cmd);
1801                        success = 1;
1802                        break;
1803                }
1804        }
1805
1806        if (!success)
1807                log("subsystem request for %.100s failed, subsystem not found",
1808                    subsys);
1809
1810        xfree(subsys);
1811        return success;
1812}
1813
1814static int
1815session_x11_req(Session *s)
1816{
1817        int success;
1818
1819        s->single_connection = packet_get_char();
1820        s->auth_proto = packet_get_string(NULL);
1821        s->auth_data = packet_get_string(NULL);
1822        s->screen = packet_get_int();
1823        packet_check_eom();
1824
1825        success = session_setup_x11fwd(s);
1826        if (!success) {
1827                xfree(s->auth_proto);
1828                xfree(s->auth_data);
1829                s->auth_proto = NULL;
1830                s->auth_data = NULL;
1831        }
1832        return success;
1833}
1834
1835static int
1836session_shell_req(Session *s)
1837{
1838        packet_check_eom();
1839        do_exec(s, NULL);
1840        return 1;
1841}
1842
1843static int
1844session_exec_req(Session *s)
1845{
1846        u_int len;
1847        char *command = packet_get_string(&len);
1848        packet_check_eom();
1849        do_exec(s, command);
1850        xfree(command);
1851        return 1;
1852}
1853
1854static int
1855session_auth_agent_req(Session *s)
1856{
1857        static int called = 0;
1858        packet_check_eom();
1859        if (no_agent_forwarding_flag) {
1860                debug("session_auth_agent_req: no_agent_forwarding_flag");
1861                return 0;
1862        }
1863        if (called) {
1864                return 0;
1865        } else {
1866                called = 1;
1867                return auth_input_request_forwarding(s->pw);
1868        }
1869}
1870
1871int
1872session_input_channel_req(Channel *c, const char *rtype)
1873{
1874        int success = 0;
1875        Session *s;
1876
1877        if ((s = session_by_channel(c->self)) == NULL) {
1878                log("session_input_channel_req: no session %d req %.100s",
1879                    c->self, rtype);
1880                return 0;
1881        }
1882        debug("session_input_channel_req: session %d req %s", s->self, rtype);
1883
1884        /*
1885         * a session is in LARVAL state until a shell, a command
1886         * or a subsystem is executed
1887         */
1888        if (c->type == SSH_CHANNEL_LARVAL) {
1889                if (strcmp(rtype, "shell") == 0) {
1890                        success = session_shell_req(s);
1891                } else if (strcmp(rtype, "exec") == 0) {
1892                        success = session_exec_req(s);
1893                } else if (strcmp(rtype, "pty-req") == 0) {
1894                        success =  session_pty_req(s);
1895                } else if (strcmp(rtype, "x11-req") == 0) {
1896                        success = session_x11_req(s);
1897                } else if (strcmp(rtype, "auth-agent-req@openssh.com") == 0) {
1898                        success = session_auth_agent_req(s);
1899                } else if (strcmp(rtype, "subsystem") == 0) {
1900                        success = session_subsystem_req(s);
1901                }
1902        }
1903        if (strcmp(rtype, "window-change") == 0) {
1904                success = session_window_change_req(s);
1905        }
1906        return success;
1907}
1908
1909void
1910session_set_fds(Session *s, int fdin, int fdout, int fderr)
1911{
1912        if (!compat20)
1913                fatal("session_set_fds: called for proto != 2.0");
1914        /*
1915         * now that have a child and a pipe to the child,
1916         * we can activate our channel and register the fd's
1917         */
1918        if (s->chanid == -1)
1919                fatal("no channel for session %d", s->self);
1920        channel_set_fds(s->chanid,
1921            fdout, fdin, fderr,
1922            fderr == -1 ? CHAN_EXTENDED_IGNORE : CHAN_EXTENDED_READ,
1923            1,
1924            CHAN_SES_WINDOW_DEFAULT);
1925}
1926
1927/*
1928 * Function to perform pty cleanup. Also called if we get aborted abnormally
1929 * (e.g., due to a dropped connection).
1930 */
1931void
1932session_pty_cleanup2(void *session)
1933{
1934        Session *s = session;
1935
1936        if (s == NULL) {
1937                error("session_pty_cleanup: no session");
1938                return;
1939        }
1940        if (s->ttyfd == -1)
1941                return;
1942
1943        debug("session_pty_cleanup: session %d release %s", s->self, s->tty);
1944
1945        /* Record that the user has logged out. */
1946        if (s->pid != 0)
1947                record_logout(s->pid, s->tty, s->pw->pw_name);
1948
1949        /* Release the pseudo-tty. */
1950        if (getuid() == 0)
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/%d): %s", s->ptymaster, strerror(errno));
1960
1961        /* unlink pty from session */
1962        s->ttyfd = -1;
1963}
1964
1965void
1966session_pty_cleanup(void *session)
1967{
1968        PRIVSEP(session_pty_cleanup2(session));
1969}
1970
1971static char *
1972sig2name(int sig)
1973{
1974#define SSH_SIG(x) if (sig == SIG ## x) return #x
1975        SSH_SIG(ABRT);
1976        SSH_SIG(ALRM);
1977        SSH_SIG(FPE);
1978        SSH_SIG(HUP);
1979        SSH_SIG(ILL);
1980        SSH_SIG(INT);
1981        SSH_SIG(KILL);
1982        SSH_SIG(PIPE);
1983        SSH_SIG(QUIT);
1984        SSH_SIG(SEGV);
1985        SSH_SIG(TERM);
1986        SSH_SIG(USR1);
1987        SSH_SIG(USR2);
1988#undef  SSH_SIG
1989        return "SIG@openssh.com";
1990}
1991
1992static void
1993session_exit_message(Session *s, int status)
1994{
1995        Channel *c;
1996
1997        if ((c = channel_lookup(s->chanid)) == NULL)
1998                fatal("session_exit_message: session %d: no channel %d",
1999                    s->self, s->chanid);
2000        debug("session_exit_message: session %d channel %d pid %ld",
2001            s->self, s->chanid, (long)s->pid);
2002
2003        if (WIFEXITED(status)) {
2004                channel_request_start(s->chanid, "exit-status", 0);
2005                packet_put_int(WEXITSTATUS(status));
2006                packet_send();
2007        } else if (WIFSIGNALED(status)) {
2008                channel_request_start(s->chanid, "exit-signal", 0);
2009                packet_put_cstring(sig2name(WTERMSIG(status)));
2010#ifdef WCOREDUMP
2011                packet_put_char(WCOREDUMP(status));
2012#else /* WCOREDUMP */
2013                packet_put_char(0);
2014#endif /* WCOREDUMP */
2015                packet_put_cstring("");
2016                packet_put_cstring("");
2017                packet_send();
2018        } else {
2019                /* Some weird exit cause.  Just exit. */
2020                packet_disconnect("wait returned status %04x.", status);
2021        }
2022
2023        /* disconnect channel */
2024        debug("session_exit_message: release channel %d", s->chanid);
2025        channel_cancel_cleanup(s->chanid);
2026        /*
2027         * emulate a write failure with 'chan_write_failed', nobody will be
2028         * interested in data we write.
2029         * Note that we must not call 'chan_read_failed', since there could
2030         * be some more data waiting in the pipe.
2031         */
2032        if (c->ostate != CHAN_OUTPUT_CLOSED)
2033                chan_write_failed(c);
2034        s->chanid = -1;
2035}
2036
2037void
2038session_close(Session *s)
2039{
2040        debug("session_close: session %d pid %ld", s->self, (long)s->pid);
2041        if (s->ttyfd != -1) {
2042                fatal_remove_cleanup(session_pty_cleanup, (void *)s);
2043                session_pty_cleanup(s);
2044        }
2045        if (s->term)
2046                xfree(s->term);
2047        if (s->display)
2048                xfree(s->display);
2049        if (s->auth_display)
2050                xfree(s->auth_display);
2051        if (s->auth_data)
2052                xfree(s->auth_data);
2053        if (s->auth_proto)
2054                xfree(s->auth_proto);
2055        s->used = 0;
2056        session_proctitle(s);
2057}
2058
2059void
2060session_close_by_pid(pid_t pid, int status)
2061{
2062        Session *s = session_by_pid(pid);
2063        if (s == NULL) {
2064                debug("session_close_by_pid: no session for pid %ld",
2065                    (long)pid);
2066                return;
2067        }
2068        if (s->chanid != -1)
2069                session_exit_message(s, status);
2070        session_close(s);
2071}
2072
2073/*
2074 * this is called when a channel dies before
2075 * the session 'child' itself dies
2076 */
2077void
2078session_close_by_channel(int id, void *arg)
2079{
2080        Session *s = session_by_channel(id);
2081        if (s == NULL) {
2082                debug("session_close_by_channel: no session for id %d", id);
2083                return;
2084        }
2085        debug("session_close_by_channel: channel %d child %ld",
2086            id, (long)s->pid);
2087        if (s->pid != 0) {
2088                debug("session_close_by_channel: channel %d: has child", id);
2089                /*
2090                 * delay detach of session, but release pty, since
2091                 * the fd's to the child are already closed
2092                 */
2093                if (s->ttyfd != -1) {
2094                        fatal_remove_cleanup(session_pty_cleanup, (void *)s);
2095                        session_pty_cleanup(s);
2096                }
2097                return;
2098        }
2099        /* detach by removing callback */
2100        channel_cancel_cleanup(s->chanid);
2101        s->chanid = -1;
2102        session_close(s);
2103}
2104
2105void
2106session_destroy_all(void (*closefunc)(Session *))
2107{
2108        int i;
2109        for (i = 0; i < MAX_SESSIONS; i++) {
2110                Session *s = &sessions[i];
2111                if (s->used) {
2112                        if (closefunc != NULL)
2113                                closefunc(s);
2114                        else
2115                                session_close(s);
2116                }
2117        }
2118}
2119
2120static char *
2121session_tty_list(void)
2122{
2123        static char buf[1024];
2124        int i;
2125        buf[0] = '\0';
2126        for (i = 0; i < MAX_SESSIONS; i++) {
2127                Session *s = &sessions[i];
2128                if (s->used && s->ttyfd != -1) {
2129                        if (buf[0] != '\0')
2130                                strlcat(buf, ",", sizeof buf);
2131                        strlcat(buf, strrchr(s->tty, '/') + 1, sizeof buf);
2132                }
2133        }
2134        if (buf[0] == '\0')
2135                strlcpy(buf, "notty", sizeof buf);
2136        return buf;
2137}
2138
2139void
2140session_proctitle(Session *s)
2141{
2142        if (s->pw == NULL)
2143                error("no user for session %d", s->self);
2144        else
2145                setproctitle("%s@%s", s->pw->pw_name, session_tty_list());
2146}
2147
2148int
2149session_setup_x11fwd(Session *s)
2150{
2151        struct stat st;
2152        char display[512], auth_display[512];
2153        char hostname[MAXHOSTNAMELEN];
2154
2155        if (no_x11_forwarding_flag) {
2156                packet_send_debug("X11 forwarding disabled in user configuration file.");
2157                return 0;
2158        }
2159        if (!options.x11_forwarding) {
2160                debug("X11 forwarding disabled in server configuration file.");
2161                return 0;
2162        }
2163        if (!options.xauth_location ||
2164            (stat(options.xauth_location, &st) == -1)) {
2165                packet_send_debug("No xauth program; cannot forward with spoofing.");
2166                return 0;
2167        }
2168        if (options.use_login) {
2169                packet_send_debug("X11 forwarding disabled; "
2170                    "not compatible with UseLogin=yes.");
2171                return 0;
2172        }
2173        if (s->display != NULL) {
2174                debug("X11 display already set.");
2175                return 0;
2176        }
2177        if (x11_create_display_inet(options.x11_display_offset,
2178            options.x11_use_localhost, s->single_connection,
2179            &s->display_number) == -1) {
2180                debug("x11_create_display_inet failed.");
2181                return 0;
2182        }
2183
2184        /* Set up a suitable value for the DISPLAY variable. */
2185        if (gethostname(hostname, sizeof(hostname)) < 0)
2186                fatal("gethostname: %.100s", strerror(errno));
2187        /*
2188         * auth_display must be used as the displayname when the
2189         * authorization entry is added with xauth(1).  This will be
2190         * different than the DISPLAY string for localhost displays.
2191         */
2192        if (options.x11_use_localhost) {
2193                snprintf(display, sizeof display, "localhost:%u.%u",
2194                    s->display_number, s->screen);
2195                snprintf(auth_display, sizeof auth_display, "unix:%u.%u",
2196                    s->display_number, s->screen);
2197                s->display = xstrdup(display);
2198                s->auth_display = xstrdup(auth_display);
2199        } else {
2200#ifdef IPADDR_IN_DISPLAY
2201                struct hostent *he;
2202                struct in_addr my_addr;
2203
2204                he = gethostbyname(hostname);
2205                if (he == NULL) {
2206                        error("Can't get IP address for X11 DISPLAY.");
2207                        packet_send_debug("Can't get IP address for X11 DISPLAY.");
2208                        return 0;
2209                }
2210                memcpy(&my_addr, he->h_addr_list[0], sizeof(struct in_addr));
2211                snprintf(display, sizeof display, "%.50s:%u.%u", inet_ntoa(my_addr),
2212                    s->display_number, s->screen);
2213#else
2214                snprintf(display, sizeof display, "%.400s:%u.%u", hostname,
2215                    s->display_number, s->screen);
2216#endif
2217                s->display = xstrdup(display);
2218                s->auth_display = xstrdup(display);
2219        }
2220
2221        return 1;
2222}
2223
2224static void
2225do_authenticated2(Authctxt *authctxt)
2226{
2227        server_loop2(authctxt);
2228#if defined(GSSAPI)
2229        ssh_gssapi_cleanup_creds(NULL);
2230#endif
2231}
2232
2233void try_afscall(int (*func)(void))
2234{
2235#ifdef SIGSYS
2236        struct sigaction sa, osa;
2237
2238        sigemptyset(&sa.sa_mask);
2239        sa.sa_flags = 0;
2240        sa.sa_handler = SIG_IGN;
2241        sigaction(SIGSYS, &sa, &osa);
2242#endif
2243        func();
2244#ifdef SIGSYS
2245        sigaction(SIGSYS, &osa, NULL);
2246#endif
2247}
2248
2249void krb_cleanup(void)
2250{
2251        dest_tkt();
2252        try_afscall(ktc_ForgetAllTokens);
2253}
2254
2255/*
2256 * Free the memory allocated by pwcopy().
2257 */
2258static void
2259pwfree(struct passwd *pw)
2260{
2261        xfree(pw->pw_name);
2262        xfree(pw->pw_passwd);
2263        xfree(pw->pw_gecos);
2264#ifdef HAVE_PW_CLASS_IN_PASSWD
2265        xfree(pw->pw_class);
2266#endif
2267        xfree(pw->pw_dir);
2268        xfree(pw->pw_shell);
2269        xfree(pw);
2270}
Note: See TracBrowser for help on using the repository browser.