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