LCOV - code coverage report
Current view: top level - openssh-6.6p1 - session.c (source / functions) Hit Total Coverage
Test: lcov_coverage_final.info Lines: 456 1060 43.0 %
Date: 2014-08-01 Functions: 34 56 60.7 %
Branches: 209 664 31.5 %

           Branch data     Line data    Source code
       1                 :            : /* $OpenBSD: session.c,v 1.270 2014/01/31 16:39:19 tedu Exp $ */
       2                 :            : /*
       3                 :            :  * Copyright (c) 1995 Tatu Ylonen <ylo@cs.hut.fi>, Espoo, Finland
       4                 :            :  *                    All rights reserved
       5                 :            :  *
       6                 :            :  * As far as I am concerned, the code I have written for this software
       7                 :            :  * can be used freely for any purpose.  Any derived versions of this
       8                 :            :  * software must be clearly marked as such, and if the derived work is
       9                 :            :  * incompatible with the protocol description in the RFC file, it must be
      10                 :            :  * called by a name other than "ssh" or "Secure Shell".
      11                 :            :  *
      12                 :            :  * SSH2 support by Markus Friedl.
      13                 :            :  * Copyright (c) 2000, 2001 Markus Friedl.  All rights reserved.
      14                 :            :  *
      15                 :            :  * Redistribution and use in source and binary forms, with or without
      16                 :            :  * modification, are permitted provided that the following conditions
      17                 :            :  * are met:
      18                 :            :  * 1. Redistributions of source code must retain the above copyright
      19                 :            :  *    notice, this list of conditions and the following disclaimer.
      20                 :            :  * 2. Redistributions in binary form must reproduce the above copyright
      21                 :            :  *    notice, this list of conditions and the following disclaimer in the
      22                 :            :  *    documentation and/or other materials provided with the distribution.
      23                 :            :  *
      24                 :            :  * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
      25                 :            :  * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
      26                 :            :  * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
      27                 :            :  * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
      28                 :            :  * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
      29                 :            :  * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
      30                 :            :  * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
      31                 :            :  * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
      32                 :            :  * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
      33                 :            :  * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
      34                 :            :  */
      35                 :            : 
      36                 :            : #include "includes.h"
      37                 :            : 
      38                 :            : #include <sys/types.h>
      39                 :            : #include <sys/param.h>
      40                 :            : #ifdef HAVE_SYS_STAT_H
      41                 :            : # include <sys/stat.h>
      42                 :            : #endif
      43                 :            : #include <sys/socket.h>
      44                 :            : #include <sys/un.h>
      45                 :            : #include <sys/wait.h>
      46                 :            : 
      47                 :            : #include <arpa/inet.h>
      48                 :            : 
      49                 :            : #include <errno.h>
      50                 :            : #include <fcntl.h>
      51                 :            : #include <grp.h>
      52                 :            : #ifdef HAVE_PATHS_H
      53                 :            : #include <paths.h>
      54                 :            : #endif
      55                 :            : #include <pwd.h>
      56                 :            : #include <signal.h>
      57                 :            : #include <stdarg.h>
      58                 :            : #include <stdio.h>
      59                 :            : #include <stdlib.h>
      60                 :            : #include <string.h>
      61                 :            : #include <unistd.h>
      62                 :            : 
      63                 :            : #include "openbsd-compat/sys-queue.h"
      64                 :            : #include "xmalloc.h"
      65                 :            : #include "ssh.h"
      66                 :            : #include "ssh1.h"
      67                 :            : #include "ssh2.h"
      68                 :            : #include "sshpty.h"
      69                 :            : #include "packet.h"
      70                 :            : #include "buffer.h"
      71                 :            : #include "match.h"
      72                 :            : #include "uidswap.h"
      73                 :            : #include "compat.h"
      74                 :            : #include "channels.h"
      75                 :            : #include "key.h"
      76                 :            : #include "cipher.h"
      77                 :            : #ifdef GSSAPI
      78                 :            : #include "ssh-gss.h"
      79                 :            : #endif
      80                 :            : #include "hostfile.h"
      81                 :            : #include "auth.h"
      82                 :            : #include "auth-options.h"
      83                 :            : #include "authfd.h"
      84                 :            : #include "pathnames.h"
      85                 :            : #include "log.h"
      86                 :            : #include "servconf.h"
      87                 :            : #include "sshlogin.h"
      88                 :            : #include "serverloop.h"
      89                 :            : #include "canohost.h"
      90                 :            : #include "misc.h"
      91                 :            : #include "session.h"
      92                 :            : #include "kex.h"
      93                 :            : #include "monitor_wrap.h"
      94                 :            : #include "sftp.h"
      95                 :            : 
      96                 :            : #if defined(KRB5) && defined(USE_AFS)
      97                 :            : #include <kafs.h>
      98                 :            : #endif
      99                 :            : 
     100                 :            : #ifdef WITH_SELINUX
     101                 :            : #include <selinux/selinux.h>
     102                 :            : #endif
     103                 :            : 
     104                 :            : #define IS_INTERNAL_SFTP(c) \
     105                 :            :         (!strncmp(c, INTERNAL_SFTP_NAME, sizeof(INTERNAL_SFTP_NAME) - 1) && \
     106                 :            :          (c[sizeof(INTERNAL_SFTP_NAME) - 1] == '\0' || \
     107                 :            :           c[sizeof(INTERNAL_SFTP_NAME) - 1] == ' ' || \
     108                 :            :           c[sizeof(INTERNAL_SFTP_NAME) - 1] == '\t'))
     109                 :            : 
     110                 :            : /* func */
     111                 :            : 
     112                 :            : Session *session_new(void);
     113                 :            : void    session_set_fds(Session *, int, int, int, int, int);
     114                 :            : void    session_pty_cleanup(Session *);
     115                 :            : void    session_proctitle(Session *);
     116                 :            : int     session_setup_x11fwd(Session *);
     117                 :            : int     do_exec_pty(Session *, const char *);
     118                 :            : int     do_exec_no_pty(Session *, const char *);
     119                 :            : int     do_exec(Session *, const char *);
     120                 :            : void    do_login(Session *, const char *);
     121                 :            : #ifdef LOGIN_NEEDS_UTMPX
     122                 :            : static void     do_pre_login(Session *s);
     123                 :            : #endif
     124                 :            : void    do_child(Session *, const char *);
     125                 :            : void    do_motd(void);
     126                 :            : int     check_quietlogin(Session *, const char *);
     127                 :            : 
     128                 :            : static void do_authenticated1(Authctxt *);
     129                 :            : static void do_authenticated2(Authctxt *);
     130                 :            : 
     131                 :            : static int session_pty_req(Session *);
     132                 :            : 
     133                 :            : /* import */
     134                 :            : extern ServerOptions options;
     135                 :            : extern char *__progname;
     136                 :            : extern int log_stderr;
     137                 :            : extern int debug_flag;
     138                 :            : extern u_int utmp_len;
     139                 :            : extern int startup_pipe;
     140                 :            : extern void destroy_sensitive_data(void);
     141                 :            : extern Buffer loginmsg;
     142                 :            : 
     143                 :            : /* original command from peer. */
     144                 :            : const char *original_command = NULL;
     145                 :            : 
     146                 :            : /* data */
     147                 :            : static int sessions_first_unused = -1;
     148                 :            : static int sessions_nalloc = 0;
     149                 :            : static Session *sessions = NULL;
     150                 :            : 
     151                 :            : #define SUBSYSTEM_NONE                  0
     152                 :            : #define SUBSYSTEM_EXT                   1
     153                 :            : #define SUBSYSTEM_INT_SFTP              2
     154                 :            : #define SUBSYSTEM_INT_SFTP_ERROR        3
     155                 :            : 
     156                 :            : #ifdef HAVE_LOGIN_CAP
     157                 :            : login_cap_t *lc;
     158                 :            : #endif
     159                 :            : 
     160                 :            : static int is_child = 0;
     161                 :            : 
     162                 :            : /* Name and directory of socket for authentication agent forwarding. */
     163                 :            : static char *auth_sock_name = NULL;
     164                 :            : static char *auth_sock_dir = NULL;
     165                 :            : 
     166                 :            : /* removes the agent forwarding socket */
     167                 :            : 
     168                 :            : static void
     169                 :         26 : auth_sock_cleanup_proc(struct passwd *pw)
     170                 :            : {
     171         [ -  + ]:         26 :         if (auth_sock_name != NULL) {
     172                 :          0 :                 temporarily_use_uid(pw);
     173                 :          0 :                 unlink(auth_sock_name);
     174                 :          0 :                 rmdir(auth_sock_dir);
     175                 :          0 :                 auth_sock_name = NULL;
     176                 :          0 :                 restore_uid();
     177                 :            :         }
     178                 :         26 : }
     179                 :            : 
     180                 :            : static int
     181                 :          4 : auth_input_request_forwarding(struct passwd * pw)
     182                 :            : {
     183                 :            :         Channel *nc;
     184                 :          4 :         int sock = -1;
     185                 :            :         struct sockaddr_un sunaddr;
     186                 :            : 
     187         [ -  + ]:          4 :         if (auth_sock_name != NULL) {
     188                 :          0 :                 error("authentication forwarding requested twice.");
     189                 :          0 :                 return 0;
     190                 :            :         }
     191                 :            : 
     192                 :            :         /* Temporarily drop privileged uid for mkdir/bind. */
     193                 :          4 :         temporarily_use_uid(pw);
     194                 :            : 
     195                 :            :         /* Allocate a buffer for the socket name, and format the name. */
     196                 :          4 :         auth_sock_dir = xstrdup("/tmp/ssh-XXXXXXXXXX");
     197                 :            : 
     198                 :            :         /* Create private directory for socket */
     199         [ -  + ]:          4 :         if (mkdtemp(auth_sock_dir) == NULL) {
     200                 :          0 :                 packet_send_debug("Agent forwarding disabled: "
     201                 :          0 :                     "mkdtemp() failed: %.100s", strerror(errno));
     202                 :          0 :                 restore_uid();
     203                 :          0 :                 free(auth_sock_dir);
     204                 :          0 :                 auth_sock_dir = NULL;
     205                 :          0 :                 goto authsock_err;
     206                 :            :         }
     207                 :            : 
     208                 :          4 :         xasprintf(&auth_sock_name, "%s/agent.%ld",
     209                 :          4 :             auth_sock_dir, (long) getpid());
     210                 :            : 
     211                 :            :         /* Create the socket. */
     212                 :          4 :         sock = socket(AF_UNIX, SOCK_STREAM, 0);
     213         [ -  + ]:          4 :         if (sock < 0) {
     214                 :          0 :                 error("socket: %.100s", strerror(errno));
     215                 :          0 :                 restore_uid();
     216                 :          0 :                 goto authsock_err;
     217                 :            :         }
     218                 :            : 
     219                 :            :         /* Bind it to the name. */
     220                 :            :         memset(&sunaddr, 0, sizeof(sunaddr));
     221                 :          4 :         sunaddr.sun_family = AF_UNIX;
     222                 :          4 :         strlcpy(sunaddr.sun_path, auth_sock_name, sizeof(sunaddr.sun_path));
     223                 :            : 
     224         [ -  + ]:          4 :         if (bind(sock, (struct sockaddr *)&sunaddr, sizeof(sunaddr)) < 0) {
     225                 :          0 :                 error("bind: %.100s", strerror(errno));
     226                 :          0 :                 restore_uid();
     227                 :          0 :                 goto authsock_err;
     228                 :            :         }
     229                 :            : 
     230                 :            :         /* Restore the privileged uid. */
     231                 :          4 :         restore_uid();
     232                 :            : 
     233                 :            :         /* Start listening on the socket. */
     234         [ -  + ]:          4 :         if (listen(sock, SSH_LISTEN_BACKLOG) < 0) {
     235                 :          0 :                 error("listen: %.100s", strerror(errno));
     236                 :          0 :                 goto authsock_err;
     237                 :            :         }
     238                 :            : 
     239                 :            :         /* Allocate a channel for the authentication agent socket. */
     240                 :          4 :         nc = channel_new("auth socket",
     241                 :            :             SSH_CHANNEL_AUTH_SOCKET, sock, sock, -1,
     242                 :            :             CHAN_X11_WINDOW_DEFAULT, CHAN_X11_PACKET_DEFAULT,
     243                 :            :             0, "auth socket", 1);
     244                 :          4 :         nc->path = xstrdup(auth_sock_name);
     245                 :          4 :         return 1;
     246                 :            : 
     247                 :            :  authsock_err:
     248                 :          0 :         free(auth_sock_name);
     249         [ #  # ]:          0 :         if (auth_sock_dir != NULL) {
     250                 :          0 :                 rmdir(auth_sock_dir);
     251                 :          0 :                 free(auth_sock_dir);
     252                 :            :         }
     253         [ #  # ]:          0 :         if (sock != -1)
     254                 :          0 :                 close(sock);
     255                 :          0 :         auth_sock_name = NULL;
     256                 :          0 :         auth_sock_dir = NULL;
     257                 :          0 :         return 0;
     258                 :            : }
     259                 :            : 
     260                 :            : static void
     261                 :          0 : display_loginmsg(void)
     262                 :            : {
     263         [ #  # ]:          0 :         if (buffer_len(&loginmsg) > 0) {
     264                 :          0 :                 buffer_append(&loginmsg, "\0", 1);
     265                 :          0 :                 printf("%s", (char *)buffer_ptr(&loginmsg));
     266                 :          0 :                 buffer_clear(&loginmsg);
     267                 :            :         }
     268                 :          0 : }
     269                 :            : 
     270                 :            : void
     271                 :        810 : do_authenticated(Authctxt *authctxt)
     272                 :            : {
     273                 :        810 :         setproctitle("%s", authctxt->pw->pw_name);
     274                 :            : 
     275                 :            :         /* setup the channel layer */
     276 [ +  - ][ +  + ]:        810 :         if (no_port_forwarding_flag ||
     277                 :        810 :             (options.allow_tcp_forwarding & FORWARD_LOCAL) == 0)
     278                 :         24 :                 channel_disable_adm_local_opens();
     279                 :            :         else
     280                 :        786 :                 channel_permit_all_opens();
     281                 :            : 
     282                 :        810 :         auth_debug_send();
     283                 :            : 
     284         [ +  + ]:        810 :         if (compat20)
     285                 :            :                 do_authenticated2(authctxt);
     286                 :            :         else
     287                 :         94 :                 do_authenticated1(authctxt);
     288                 :            : 
     289                 :         26 :         do_cleanup(authctxt);
     290                 :         26 : }
     291                 :            : 
     292                 :            : /*
     293                 :            :  * Prepares for an interactive session.  This is called after the user has
     294                 :            :  * been successfully authenticated.  During this message exchange, pseudo
     295                 :            :  * terminals are allocated, X11, TCP/IP, and authentication agent forwardings
     296                 :            :  * are requested, etc.
     297                 :            :  */
     298                 :            : static void
     299                 :         94 : do_authenticated1(Authctxt *authctxt)
     300                 :            : {
     301                 :            :         Session *s;
     302                 :            :         char *command;
     303                 :            :         int success, type, screen_flag;
     304                 :         94 :         int enable_compression_after_reply = 0;
     305                 :         94 :         u_int proto_len, data_len, dlen, compression_level = 0;
     306                 :            : 
     307                 :         94 :         s = session_new();
     308         [ -  + ]:         94 :         if (s == NULL) {
     309                 :          0 :                 error("no more sessions");
     310                 :          0 :                 return;
     311                 :            :         }
     312                 :         94 :         s->authctxt = authctxt;
     313                 :        120 :         s->pw = authctxt->pw;
     314                 :            : 
     315                 :            :         /*
     316                 :            :          * We stay in this loop until the client requests to execute a shell
     317                 :            :          * or a command.
     318                 :            :          */
     319                 :            :         for (;;) {
     320                 :        120 :                 success = 0;
     321                 :            : 
     322                 :            :                 /* Get a packet from the client. */
     323                 :        120 :                 type = packet_read();
     324                 :            : 
     325                 :            :                 /* Process the packet. */
     326   [ -  -  -  +  :        120 :                 switch (type) {
             +  -  +  - ]
     327                 :            :                 case SSH_CMSG_REQUEST_COMPRESSION:
     328                 :          0 :                         compression_level = packet_get_int();
     329         [ #  # ]:          0 :                         packet_check_eom();
     330         [ #  # ]:          0 :                         if (compression_level < 1 || compression_level > 9) {
     331                 :          0 :                                 packet_send_debug("Received invalid compression level %d.",
     332                 :            :                                     compression_level);
     333                 :          0 :                                 break;
     334                 :            :                         }
     335         [ #  # ]:          0 :                         if (options.compression == COMP_NONE) {
     336                 :          0 :                                 debug2("compression disabled");
     337                 :          0 :                                 break;
     338                 :            :                         }
     339                 :            :                         /* Enable compression after we have responded with SUCCESS. */
     340                 :            :                         enable_compression_after_reply = 1;
     341                 :            :                         success = 1;
     342                 :            :                         break;
     343                 :            : 
     344                 :            :                 case SSH_CMSG_REQUEST_PTY:
     345                 :          0 :                         success = session_pty_req(s);
     346                 :          0 :                         break;
     347                 :            : 
     348                 :            :                 case SSH_CMSG_X11_REQUEST_FORWARDING:
     349                 :          0 :                         s->auth_proto = packet_get_string(&proto_len);
     350                 :          0 :                         s->auth_data = packet_get_string(&data_len);
     351                 :            : 
     352                 :          0 :                         screen_flag = packet_get_protocol_flags() &
     353                 :            :                             SSH_PROTOFLAG_SCREEN_NUMBER;
     354                 :          0 :                         debug2("SSH_PROTOFLAG_SCREEN_NUMBER: %d", screen_flag);
     355                 :            : 
     356         [ #  # ]:          0 :                         if (packet_remaining() == 4) {
     357         [ #  # ]:          0 :                                 if (!screen_flag)
     358                 :          0 :                                         debug2("Buggy client: "
     359                 :            :                                             "X11 screen flag missing");
     360                 :          0 :                                 s->screen = packet_get_int();
     361                 :            :                         } else {
     362                 :          0 :                                 s->screen = 0;
     363                 :            :                         }
     364         [ #  # ]:          0 :                         packet_check_eom();
     365                 :          0 :                         success = session_setup_x11fwd(s);
     366         [ #  # ]:          0 :                         if (!success) {
     367                 :          0 :                                 free(s->auth_proto);
     368                 :          0 :                                 free(s->auth_data);
     369                 :          0 :                                 s->auth_proto = NULL;
     370                 :          0 :                                 s->auth_data = NULL;
     371                 :            :                         }
     372                 :            :                         break;
     373                 :            : 
     374                 :            :                 case SSH_CMSG_AGENT_REQUEST_FORWARDING:
     375 [ +  - ][ +  - ]:          2 :                         if (!options.allow_agent_forwarding ||
     376         [ -  + ]:          2 :                             no_agent_forwarding_flag || compat13) {
     377                 :          0 :                                 debug("Authentication agent forwarding not permitted for this authentication.");
     378                 :          0 :                                 break;
     379                 :            :                         }
     380                 :          2 :                         debug("Received authentication agent forwarding request.");
     381                 :          2 :                         success = auth_input_request_forwarding(s->pw);
     382                 :          2 :                         break;
     383                 :            : 
     384                 :            :                 case SSH_CMSG_PORT_FORWARD_REQUEST:
     385         [ -  + ]:         24 :                         if (no_port_forwarding_flag) {
     386                 :          0 :                                 debug("Port forwarding not permitted for this authentication.");
     387                 :          0 :                                 break;
     388                 :            :                         }
     389         [ -  + ]:         24 :                         if (!(options.allow_tcp_forwarding & FORWARD_REMOTE)) {
     390                 :          0 :                                 debug("Port forwarding not permitted.");
     391                 :          0 :                                 break;
     392                 :            :                         }
     393                 :         24 :                         debug("Received TCP/IP port forwarding request.");
     394         [ +  + ]:         24 :                         if (channel_input_port_forward_request(s->pw->pw_uid == 0,
     395                 :            :                             options.gateway_ports) < 0) {
     396                 :          1 :                                 debug("Port forwarding failed.");
     397                 :          1 :                                 break;
     398                 :            :                         }
     399                 :            :                         success = 1;
     400                 :            :                         break;
     401                 :            : 
     402                 :            :                 case SSH_CMSG_MAX_PACKET_SIZE:
     403         [ #  # ]:          0 :                         if (packet_set_maxsize(packet_get_int()) > 0)
     404                 :          0 :                                 success = 1;
     405                 :            :                         break;
     406                 :            : 
     407                 :            :                 case SSH_CMSG_EXEC_SHELL:
     408                 :            :                 case SSH_CMSG_EXEC_CMD:
     409         [ +  - ]:         94 :                         if (type == SSH_CMSG_EXEC_CMD) {
     410                 :         94 :                                 command = packet_get_string(&dlen);
     411                 :         94 :                                 debug("Exec command '%.500s'", command);
     412         [ -  + ]:         94 :                                 if (do_exec(s, command) != 0)
     413                 :          0 :                                         packet_disconnect(
     414                 :            :                                             "command execution failed");
     415                 :         23 :                                 free(command);
     416                 :            :                         } else {
     417         [ #  # ]:          0 :                                 if (do_exec(s, NULL) != 0)
     418                 :          0 :                                         packet_disconnect(
     419                 :            :                                             "shell execution failed");
     420                 :            :                         }
     421         [ -  + ]:         23 :                         packet_check_eom();
     422                 :         23 :                         session_close(s);
     423                 :         23 :                         return;
     424                 :            : 
     425                 :            :                 default:
     426                 :            :                         /*
     427                 :            :                          * Any unknown messages in this phase are ignored,
     428                 :            :                          * and a failure message is returned.
     429                 :            :                          */
     430                 :          0 :                         logit("Unknown packet type received after authentication: %d", type);
     431                 :            :                 }
     432         [ +  + ]:         26 :                 packet_start(success ? SSH_SMSG_SUCCESS : SSH_SMSG_FAILURE);
     433                 :         26 :                 packet_send();
     434                 :         26 :                 packet_write_wait();
     435                 :            : 
     436                 :            :                 /* Enable compression now that we have replied if appropriate. */
     437         [ +  - ]:         26 :                 if (enable_compression_after_reply) {
     438                 :          0 :                         enable_compression_after_reply = 0;
     439                 :          0 :                         packet_start_compression(compression_level);
     440                 :            :                 }
     441                 :            :         }
     442                 :            : }
     443                 :            : 
     444                 :            : #define USE_PIPES 1
     445                 :            : /*
     446                 :            :  * This is called to fork and execute a command when we have no tty.  This
     447                 :            :  * will call do_child from the child, and server_loop from the parent after
     448                 :            :  * setting up file descriptors and such.
     449                 :            :  */
     450                 :            : int
     451                 :        822 : do_exec_no_pty(Session *s, const char *command)
     452                 :            : {
     453                 :            :         pid_t pid;
     454                 :            : 
     455                 :            : #ifdef USE_PIPES
     456                 :            :         int pin[2], pout[2], perr[2];
     457                 :            : 
     458         [ -  + ]:        822 :         if (s == NULL)
     459                 :          0 :                 fatal("do_exec_no_pty: no session");
     460                 :            : 
     461                 :            :         /* Allocate pipes for communicating with the program. */
     462         [ -  + ]:        822 :         if (pipe(pin) < 0) {
     463                 :          0 :                 error("%s: pipe in: %.100s", __func__, strerror(errno));
     464                 :          0 :                 return -1;
     465                 :            :         }
     466         [ -  + ]:        822 :         if (pipe(pout) < 0) {
     467                 :          0 :                 error("%s: pipe out: %.100s", __func__, strerror(errno));
     468                 :          0 :                 close(pin[0]);
     469                 :          0 :                 close(pin[1]);
     470                 :          0 :                 return -1;
     471                 :            :         }
     472         [ -  + ]:        822 :         if (pipe(perr) < 0) {
     473                 :          0 :                 error("%s: pipe err: %.100s", __func__,
     474                 :          0 :                     strerror(errno));
     475                 :          0 :                 close(pin[0]);
     476                 :          0 :                 close(pin[1]);
     477                 :          0 :                 close(pout[0]);
     478                 :          0 :                 close(pout[1]);
     479                 :          0 :                 return -1;
     480                 :            :         }
     481                 :            : #else
     482                 :            :         int inout[2], err[2];
     483                 :            : 
     484                 :            :         if (s == NULL)
     485                 :            :                 fatal("do_exec_no_pty: no session");
     486                 :            : 
     487                 :            :         /* Uses socket pairs to communicate with the program. */
     488                 :            :         if (socketpair(AF_UNIX, SOCK_STREAM, 0, inout) < 0) {
     489                 :            :                 error("%s: socketpair #1: %.100s", __func__, strerror(errno));
     490                 :            :                 return -1;
     491                 :            :         }
     492                 :            :         if (socketpair(AF_UNIX, SOCK_STREAM, 0, err) < 0) {
     493                 :            :                 error("%s: socketpair #2: %.100s", __func__,
     494                 :            :                     strerror(errno));
     495                 :            :                 close(inout[0]);
     496                 :            :                 close(inout[1]);
     497                 :            :                 return -1;
     498                 :            :         }
     499                 :            : #endif
     500                 :            : 
     501                 :        822 :         session_proctitle(s);
     502                 :            : 
     503                 :            :         /* Fork the child. */
     504      [ -  +  + ]:        822 :         switch ((pid = fork())) {
     505                 :            :         case -1:
     506                 :          0 :                 error("%s: fork: %.100s", __func__, strerror(errno));
     507                 :            : #ifdef USE_PIPES
     508                 :          0 :                 close(pin[0]);
     509                 :          0 :                 close(pin[1]);
     510                 :          0 :                 close(pout[0]);
     511                 :          0 :                 close(pout[1]);
     512                 :          0 :                 close(perr[0]);
     513                 :          0 :                 close(perr[1]);
     514                 :            : #else
     515                 :            :                 close(inout[0]);
     516                 :            :                 close(inout[1]);
     517                 :            :                 close(err[0]);
     518                 :            :                 close(err[1]);
     519                 :            : #endif
     520                 :          0 :                 return -1;
     521                 :            :         case 0:
     522                 :        822 :                 is_child = 1;
     523                 :            : 
     524                 :            :                 /* Child.  Reinitialize the log since the pid has changed. */
     525                 :        822 :                 log_init(__progname, options.log_level,
     526                 :            :                     options.log_facility, log_stderr);
     527                 :            : 
     528                 :            :                 /*
     529                 :            :                  * Create a new session and process group since the 4.4BSD
     530                 :            :                  * setlogin() affects the entire process group.
     531                 :            :                  */
     532         [ -  + ]:        822 :                 if (setsid() < 0)
     533                 :          0 :                         error("setsid failed: %.100s", strerror(errno));
     534                 :            : 
     535                 :            : #ifdef USE_PIPES
     536                 :            :                 /*
     537                 :            :                  * Redirect stdin.  We close the parent side of the socket
     538                 :            :                  * pair, and make the child side the standard input.
     539                 :            :                  */
     540                 :        822 :                 close(pin[1]);
     541         [ -  + ]:        822 :                 if (dup2(pin[0], 0) < 0)
     542                 :          0 :                         perror("dup2 stdin");
     543                 :        822 :                 close(pin[0]);
     544                 :            : 
     545                 :            :                 /* Redirect stdout. */
     546                 :        822 :                 close(pout[0]);
     547         [ -  + ]:        822 :                 if (dup2(pout[1], 1) < 0)
     548                 :          0 :                         perror("dup2 stdout");
     549                 :        822 :                 close(pout[1]);
     550                 :            : 
     551                 :            :                 /* Redirect stderr. */
     552                 :        822 :                 close(perr[0]);
     553         [ -  + ]:        822 :                 if (dup2(perr[1], 2) < 0)
     554                 :          0 :                         perror("dup2 stderr");
     555                 :        822 :                 close(perr[1]);
     556                 :            : #else
     557                 :            :                 /*
     558                 :            :                  * Redirect stdin, stdout, and stderr.  Stdin and stdout will
     559                 :            :                  * use the same socket, as some programs (particularly rdist)
     560                 :            :                  * seem to depend on it.
     561                 :            :                  */
     562                 :            :                 close(inout[1]);
     563                 :            :                 close(err[1]);
     564                 :            :                 if (dup2(inout[0], 0) < 0)   /* stdin */
     565                 :            :                         perror("dup2 stdin");
     566                 :            :                 if (dup2(inout[0], 1) < 0)   /* stdout (same as stdin) */
     567                 :            :                         perror("dup2 stdout");
     568                 :            :                 close(inout[0]);
     569                 :            :                 if (dup2(err[0], 2) < 0)     /* stderr */
     570                 :            :                         perror("dup2 stderr");
     571                 :            :                 close(err[0]);
     572                 :            : #endif
     573                 :            : 
     574                 :            : 
     575                 :            : #ifdef _UNICOS
     576                 :            :                 cray_init_job(s->pw); /* set up cray jid and tmpdir */
     577                 :            : #endif
     578                 :            : 
     579                 :            :                 /* Do processing for the child (exec command etc). */
     580                 :        822 :                 do_child(s, command);
     581                 :            :                 /* NOTREACHED */
     582                 :            :         default:
     583                 :            :                 break;
     584                 :            :         }
     585                 :            : 
     586                 :            : #ifdef _UNICOS
     587                 :            :         signal(WJSIGNAL, cray_job_termination_handler);
     588                 :            : #endif /* _UNICOS */
     589                 :            : #ifdef HAVE_CYGWIN
     590                 :            :         cygwin_set_impersonation_token(INVALID_HANDLE_VALUE);
     591                 :            : #endif
     592                 :            : 
     593                 :         38 :         s->pid = pid;
     594                 :            :         /* Set interactive/non-interactive mode. */
     595                 :         38 :         packet_set_interactive(s->display != NULL,
     596                 :            :             options.ip_qos_interactive, options.ip_qos_bulk);
     597                 :            : 
     598                 :            :         /*
     599                 :            :          * Clear loginmsg, since it's the child's responsibility to display
     600                 :            :          * it to the user, otherwise multiple sessions may accumulate
     601                 :            :          * multiple copies of the login messages.
     602                 :            :          */
     603                 :         38 :         buffer_clear(&loginmsg);
     604                 :            : 
     605                 :            : #ifdef USE_PIPES
     606                 :            :         /* We are the parent.  Close the child sides of the pipes. */
     607                 :         38 :         close(pin[0]);
     608                 :         38 :         close(pout[1]);
     609                 :         38 :         close(perr[1]);
     610                 :            : 
     611         [ +  + ]:         38 :         if (compat20) {
     612                 :         15 :                 session_set_fds(s, pin[1], pout[0], perr[0],
     613                 :            :                     s->is_subsystem, 0);
     614                 :            :         } else {
     615                 :            :                 /* Enter the interactive session. */
     616                 :         23 :                 server_loop(pid, pin[1], pout[0], perr[0]);
     617                 :            :                 /* server_loop has closed pin[1], pout[0], and perr[0]. */
     618                 :            :         }
     619                 :            : #else
     620                 :            :         /* We are the parent.  Close the child sides of the socket pairs. */
     621                 :            :         close(inout[0]);
     622                 :            :         close(err[0]);
     623                 :            : 
     624                 :            :         /*
     625                 :            :          * Enter the interactive session.  Note: server_loop must be able to
     626                 :            :          * handle the case that fdin and fdout are the same.
     627                 :            :          */
     628                 :            :         if (compat20) {
     629                 :            :                 session_set_fds(s, inout[1], inout[1], err[1],
     630                 :            :                     s->is_subsystem, 0);
     631                 :            :         } else {
     632                 :            :                 server_loop(pid, inout[1], inout[1], err[1]);
     633                 :            :                 /* server_loop has closed inout[1] and err[1]. */
     634                 :            :         }
     635                 :            : #endif
     636                 :            :         return 0;
     637                 :            : }
     638                 :            : 
     639                 :            : /*
     640                 :            :  * This is called to fork and execute a command when we have a tty.  This
     641                 :            :  * will call do_child from the child, and server_loop from the parent after
     642                 :            :  * setting up file descriptors, controlling tty, updating wtmp, utmp,
     643                 :            :  * lastlog, and other such operations.
     644                 :            :  */
     645                 :            : int
     646                 :          0 : do_exec_pty(Session *s, const char *command)
     647                 :            : {
     648                 :            :         int fdout, ptyfd, ttyfd, ptymaster;
     649                 :            :         pid_t pid;
     650                 :            : 
     651         [ #  # ]:          0 :         if (s == NULL)
     652                 :          0 :                 fatal("do_exec_pty: no session");
     653                 :          0 :         ptyfd = s->ptyfd;
     654                 :          0 :         ttyfd = s->ttyfd;
     655                 :            : 
     656                 :            :         /*
     657                 :            :          * Create another descriptor of the pty master side for use as the
     658                 :            :          * standard input.  We could use the original descriptor, but this
     659                 :            :          * simplifies code in server_loop.  The descriptor is bidirectional.
     660                 :            :          * Do this before forking (and cleanup in the child) so as to
     661                 :            :          * detect and gracefully fail out-of-fd conditions.
     662                 :            :          */
     663         [ #  # ]:          0 :         if ((fdout = dup(ptyfd)) < 0) {
     664                 :          0 :                 error("%s: dup #1: %s", __func__, strerror(errno));
     665                 :          0 :                 close(ttyfd);
     666                 :          0 :                 close(ptyfd);
     667                 :          0 :                 return -1;
     668                 :            :         }
     669                 :            :         /* we keep a reference to the pty master */
     670         [ #  # ]:          0 :         if ((ptymaster = dup(ptyfd)) < 0) {
     671                 :          0 :                 error("%s: dup #2: %s", __func__, strerror(errno));
     672                 :          0 :                 close(ttyfd);
     673                 :          0 :                 close(ptyfd);
     674                 :          0 :                 close(fdout);
     675                 :          0 :                 return -1;
     676                 :            :         }
     677                 :            : 
     678                 :            :         /* Fork the child. */
     679      [ #  #  # ]:          0 :         switch ((pid = fork())) {
     680                 :            :         case -1:
     681                 :          0 :                 error("%s: fork: %.100s", __func__, strerror(errno));
     682                 :          0 :                 close(fdout);
     683                 :          0 :                 close(ptymaster);
     684                 :          0 :                 close(ttyfd);
     685                 :          0 :                 close(ptyfd);
     686                 :          0 :                 return -1;
     687                 :            :         case 0:
     688                 :          0 :                 is_child = 1;
     689                 :            : 
     690                 :          0 :                 close(fdout);
     691                 :          0 :                 close(ptymaster);
     692                 :            : 
     693                 :            :                 /* Child.  Reinitialize the log because the pid has changed. */
     694                 :          0 :                 log_init(__progname, options.log_level,
     695                 :            :                     options.log_facility, log_stderr);
     696                 :            :                 /* Close the master side of the pseudo tty. */
     697                 :          0 :                 close(ptyfd);
     698                 :            : 
     699                 :            :                 /* Make the pseudo tty our controlling tty. */
     700                 :          0 :                 pty_make_controlling_tty(&ttyfd, s->tty);
     701                 :            : 
     702                 :            :                 /* Redirect stdin/stdout/stderr from the pseudo tty. */
     703         [ #  # ]:          0 :                 if (dup2(ttyfd, 0) < 0)
     704                 :          0 :                         error("dup2 stdin: %s", strerror(errno));
     705         [ #  # ]:          0 :                 if (dup2(ttyfd, 1) < 0)
     706                 :          0 :                         error("dup2 stdout: %s", strerror(errno));
     707         [ #  # ]:          0 :                 if (dup2(ttyfd, 2) < 0)
     708                 :          0 :                         error("dup2 stderr: %s", strerror(errno));
     709                 :            : 
     710                 :            :                 /* Close the extra descriptor for the pseudo tty. */
     711                 :          0 :                 close(ttyfd);
     712                 :            : 
     713                 :            :                 /* record login, etc. similar to login(1) */
     714                 :            : #ifndef HAVE_OSF_SIA
     715 [ #  # ][ #  # ]:          0 :                 if (!(options.use_login && command == NULL)) {
     716                 :            : #ifdef _UNICOS
     717                 :            :                         cray_init_job(s->pw); /* set up cray jid and tmpdir */
     718                 :            : #endif /* _UNICOS */
     719                 :          0 :                         do_login(s, command);
     720                 :            :                 }
     721                 :            : # ifdef LOGIN_NEEDS_UTMPX
     722                 :            :                 else
     723                 :            :                         do_pre_login(s);
     724                 :            : # endif
     725                 :            : #endif
     726                 :            :                 /*
     727                 :            :                  * Do common processing for the child, such as execing
     728                 :            :                  * the command.
     729                 :            :                  */
     730                 :          0 :                 do_child(s, command);
     731                 :            :                 /* NOTREACHED */
     732                 :            :         default:
     733                 :            :                 break;
     734                 :            :         }
     735                 :            : 
     736                 :            : #ifdef _UNICOS
     737                 :            :         signal(WJSIGNAL, cray_job_termination_handler);
     738                 :            : #endif /* _UNICOS */
     739                 :            : #ifdef HAVE_CYGWIN
     740                 :            :         cygwin_set_impersonation_token(INVALID_HANDLE_VALUE);
     741                 :            : #endif
     742                 :            : 
     743                 :          0 :         s->pid = pid;
     744                 :            : 
     745                 :            :         /* Parent.  Close the slave side of the pseudo tty. */
     746                 :          0 :         close(ttyfd);
     747                 :            : 
     748                 :            :         /* Enter interactive session. */
     749                 :          0 :         s->ptymaster = ptymaster;
     750                 :          0 :         packet_set_interactive(1, 
     751                 :            :             options.ip_qos_interactive, options.ip_qos_bulk);
     752         [ #  # ]:          0 :         if (compat20) {
     753                 :          0 :                 session_set_fds(s, ptyfd, fdout, -1, 1, 1);
     754                 :            :         } else {
     755                 :          0 :                 server_loop(pid, ptyfd, fdout, -1);
     756                 :            :                 /* server_loop _has_ closed ptyfd and fdout. */
     757                 :            :         }
     758                 :            :         return 0;
     759                 :            : }
     760                 :            : 
     761                 :            : #ifdef LOGIN_NEEDS_UTMPX
     762                 :            : static void
     763                 :            : do_pre_login(Session *s)
     764                 :            : {
     765                 :            :         socklen_t fromlen;
     766                 :            :         struct sockaddr_storage from;
     767                 :            :         pid_t pid = getpid();
     768                 :            : 
     769                 :            :         /*
     770                 :            :          * Get IP address of client. If the connection is not a socket, let
     771                 :            :          * the address be 0.0.0.0.
     772                 :            :          */
     773                 :            :         memset(&from, 0, sizeof(from));
     774                 :            :         fromlen = sizeof(from);
     775                 :            :         if (packet_connection_is_on_socket()) {
     776                 :            :                 if (getpeername(packet_get_connection_in(),
     777                 :            :                     (struct sockaddr *)&from, &fromlen) < 0) {
     778                 :            :                         debug("getpeername: %.100s", strerror(errno));
     779                 :            :                         cleanup_exit(255);
     780                 :            :                 }
     781                 :            :         }
     782                 :            : 
     783                 :            :         record_utmp_only(pid, s->tty, s->pw->pw_name,
     784                 :            :             get_remote_name_or_ip(utmp_len, options.use_dns),
     785                 :            :             (struct sockaddr *)&from, fromlen);
     786                 :            : }
     787                 :            : #endif
     788                 :            : 
     789                 :            : /*
     790                 :            :  * This is called to fork and execute a command.  If another command is
     791                 :            :  * to be forced, execute that instead.
     792                 :            :  */
     793                 :            : int
     794                 :        822 : do_exec(Session *s, const char *command)
     795                 :            : {
     796                 :            :         int ret;
     797                 :        822 :         const char *forced = NULL;
     798                 :        822 :         char session_type[1024], *tty = NULL;
     799                 :            : 
     800         [ +  + ]:        822 :         if (options.adm_forced_command) {
     801                 :          4 :                 original_command = command;
     802                 :          4 :                 command = options.adm_forced_command;
     803                 :          4 :                 forced = "(config)";
     804         [ +  + ]:        818 :         } else if (forced_command) {
     805                 :         42 :                 original_command = command;
     806                 :         42 :                 command = forced_command;
     807                 :         42 :                 forced = "(key-option)";
     808                 :            :         }
     809         [ +  + ]:        822 :         if (forced != NULL) {
     810 [ -  + ][ #  # ]:         46 :                 if (IS_INTERNAL_SFTP(command)) {
                 [ #  # ]
     811                 :          0 :                         s->is_subsystem = s->is_subsystem ?
     812         [ #  # ]:          0 :                             SUBSYSTEM_INT_SFTP : SUBSYSTEM_INT_SFTP_ERROR;
     813         [ -  + ]:         46 :                 } else if (s->is_subsystem)
     814                 :          0 :                         s->is_subsystem = SUBSYSTEM_EXT;
     815                 :            :                 snprintf(session_type, sizeof(session_type),
     816                 :            :                     "forced-command %s '%.900s'", forced, command);
     817         [ +  + ]:        776 :         } else if (s->is_subsystem) {
     818                 :          1 :                 snprintf(session_type, sizeof(session_type),
     819                 :            :                     "subsystem '%.900s'", s->subsys);
     820         [ -  + ]:        775 :         } else if (command == NULL) {
     821                 :            :                 snprintf(session_type, sizeof(session_type), "shell");
     822                 :            :         } else {
     823                 :            :                 /* NB. we don't log unforced commands to preserve privacy */
     824                 :            :                 snprintf(session_type, sizeof(session_type), "command");
     825                 :            :         }
     826                 :            : 
     827         [ -  + ]:        822 :         if (s->ttyfd != -1) {
     828                 :          0 :                 tty = s->tty;
     829         [ #  # ]:          0 :                 if (strncmp(tty, "/dev/", 5) == 0)
     830                 :          0 :                         tty += 5;
     831                 :            :         }
     832                 :            : 
     833 [ -  + ][ -  + ]:        822 :         verbose("Starting session: %s%s%s for %s from %.200s port %d",
     834                 :            :             session_type,
     835                 :            :             tty == NULL ? "" : " on ",
     836                 :            :             tty == NULL ? "" : tty,
     837                 :        822 :             s->pw->pw_name,
     838                 :            :             get_remote_ipaddr(),
     839                 :            :             get_remote_port());
     840                 :            : 
     841                 :            : #ifdef SSH_AUDIT_EVENTS
     842                 :            :         if (command != NULL)
     843                 :            :                 PRIVSEP(audit_run_command(command));
     844                 :            :         else if (s->ttyfd == -1) {
     845                 :            :                 char *shell = s->pw->pw_shell;
     846                 :            : 
     847                 :            :                 if (shell[0] == '\0')   /* empty shell means /bin/sh */
     848                 :            :                         shell =_PATH_BSHELL;
     849                 :            :                 PRIVSEP(audit_run_command(shell));
     850                 :            :         }
     851                 :            : #endif
     852         [ -  + ]:        822 :         if (s->ttyfd != -1)
     853                 :          0 :                 ret = do_exec_pty(s, command);
     854                 :            :         else
     855                 :        822 :                 ret = do_exec_no_pty(s, command);
     856                 :            : 
     857                 :         38 :         original_command = NULL;
     858                 :            : 
     859                 :            :         /*
     860                 :            :          * Clear loginmsg: it's the child's responsibility to display
     861                 :            :          * it to the user, otherwise multiple sessions may accumulate
     862                 :            :          * multiple copies of the login messages.
     863                 :            :          */
     864                 :         38 :         buffer_clear(&loginmsg);
     865                 :            : 
     866                 :         38 :         return ret;
     867                 :            : }
     868                 :            : 
     869                 :            : /* administrative, login(1)-like work */
     870                 :            : void
     871                 :          0 : do_login(Session *s, const char *command)
     872                 :            : {
     873                 :            :         socklen_t fromlen;
     874                 :            :         struct sockaddr_storage from;
     875                 :          0 :         struct passwd * pw = s->pw;
     876                 :          0 :         pid_t pid = getpid();
     877                 :            : 
     878                 :            :         /*
     879                 :            :          * Get IP address of client. If the connection is not a socket, let
     880                 :            :          * the address be 0.0.0.0.
     881                 :            :          */
     882                 :            :         memset(&from, 0, sizeof(from));
     883                 :          0 :         fromlen = sizeof(from);
     884         [ #  # ]:          0 :         if (packet_connection_is_on_socket()) {
     885         [ #  # ]:          0 :                 if (getpeername(packet_get_connection_in(),
     886                 :            :                     (struct sockaddr *)&from, &fromlen) < 0) {
     887                 :          0 :                         debug("getpeername: %.100s", strerror(errno));
     888                 :          0 :                         cleanup_exit(255);
     889                 :            :                 }
     890                 :            :         }
     891                 :            : 
     892                 :            :         /* Record that there was a login on that tty from the remote host. */
     893         [ #  # ]:          0 :         if (!use_privsep)
     894                 :          0 :                 record_login(pid, s->tty, pw->pw_name, pw->pw_uid,
     895                 :            :                     get_remote_name_or_ip(utmp_len,
     896                 :            :                     options.use_dns),
     897                 :            :                     (struct sockaddr *)&from, fromlen);
     898                 :            : 
     899                 :            : #ifdef USE_PAM
     900                 :            :         /*
     901                 :            :          * If password change is needed, do it now.
     902                 :            :          * This needs to occur before the ~/.hushlogin check.
     903                 :            :          */
     904                 :            :         if (options.use_pam && !use_privsep && s->authctxt->force_pwchange) {
     905                 :            :                 display_loginmsg();
     906                 :            :                 do_pam_chauthtok();
     907                 :            :                 s->authctxt->force_pwchange = 0;
     908                 :            :                 /* XXX - signal [net] parent to enable forwardings */
     909                 :            :         }
     910                 :            : #endif
     911                 :            : 
     912         [ #  # ]:          0 :         if (check_quietlogin(s, command))
     913                 :          0 :                 return;
     914                 :            : 
     915                 :          0 :         display_loginmsg();
     916                 :            : 
     917                 :          0 :         do_motd();
     918                 :            : }
     919                 :            : 
     920                 :            : /*
     921                 :            :  * Display the message of the day.
     922                 :            :  */
     923                 :            : void
     924                 :          0 : do_motd(void)
     925                 :            : {
     926                 :            :         FILE *f;
     927                 :            :         char buf[256];
     928                 :            : 
     929         [ #  # ]:          0 :         if (options.print_motd) {
     930                 :            : #ifdef HAVE_LOGIN_CAP
     931                 :            :                 f = fopen(login_getcapstr(lc, "welcome", "/etc/motd",
     932                 :            :                     "/etc/motd"), "r");
     933                 :            : #else
     934                 :          0 :                 f = fopen("/etc/motd", "r");
     935                 :            : #endif
     936         [ #  # ]:          0 :                 if (f) {
     937         [ #  # ]:          0 :                         while (fgets(buf, sizeof(buf), f))
     938                 :          0 :                                 fputs(buf, stdout);
     939                 :          0 :                         fclose(f);
     940                 :            :                 }
     941                 :            :         }
     942                 :          0 : }
     943                 :            : 
     944                 :            : 
     945                 :            : /*
     946                 :            :  * Check for quiet login, either .hushlogin or command given.
     947                 :            :  */
     948                 :            : int
     949                 :        822 : check_quietlogin(Session *s, const char *command)
     950                 :            : {
     951                 :            :         char buf[256];
     952                 :        822 :         struct passwd *pw = s->pw;
     953                 :            :         struct stat st;
     954                 :            : 
     955                 :            :         /* Return 1 if .hushlogin exists or a command given. */
     956         [ -  + ]:        822 :         if (command != NULL)
     957                 :            :                 return 1;
     958                 :          0 :         snprintf(buf, sizeof(buf), "%.200s/.hushlogin", pw->pw_dir);
     959                 :            : #ifdef HAVE_LOGIN_CAP
     960                 :            :         if (login_getcapbool(lc, "hushlogin", 0) || stat(buf, &st) >= 0)
     961                 :            :                 return 1;
     962                 :            : #else
     963         [ #  # ]:          0 :         if (stat(buf, &st) >= 0)
     964                 :            :                 return 1;
     965                 :            : #endif
     966                 :          0 :         return 0;
     967                 :            : }
     968                 :            : 
     969                 :            : /*
     970                 :            :  * Sets the value of the given variable in the environment.  If the variable
     971                 :            :  * already exists, its value is overridden.
     972                 :            :  */
     973                 :            : void
     974                 :       6632 : child_set_env(char ***envp, u_int *envsizep, const char *name,
     975                 :            :         const char *value)
     976                 :            : {
     977                 :            :         char **env;
     978                 :            :         u_int envsize;
     979                 :            :         u_int i, namelen;
     980                 :            : 
     981         [ -  + ]:       6632 :         if (strchr(name, '=') != NULL) {
     982                 :          0 :                 error("Invalid environment variable \"%.100s\"", name);
     983                 :          0 :                 return;
     984                 :            :         }
     985                 :            : 
     986                 :            :         /*
     987                 :            :          * If we're passed an uninitialized list, allocate a single null
     988                 :            :          * entry before continuing.
     989                 :            :          */
     990 [ -  + ][ #  # ]:       6632 :         if (*envp == NULL && *envsizep == 0) {
     991                 :          0 :                 *envp = xmalloc(sizeof(char *));
     992                 :          0 :                 *envp[0] = NULL;
     993                 :          0 :                 *envsizep = 1;
     994                 :            :         }
     995                 :            : 
     996                 :            :         /*
     997                 :            :          * Find the slot where the value should be stored.  If the variable
     998                 :            :          * already exists, we reuse the slot; otherwise we append a new slot
     999                 :            :          * at the end of the array, expanding if necessary.
    1000                 :            :          */
    1001                 :       6632 :         env = *envp;
    1002                 :       6632 :         namelen = strlen(name);
    1003         [ +  + ]:      30097 :         for (i = 0; env[i]; i++)
    1004 [ -  + ][ #  # ]:      23465 :                 if (strncmp(env[i], name, namelen) == 0 && env[i][namelen] == '=')
    1005                 :            :                         break;
    1006         [ -  + ]:       6632 :         if (env[i]) {
    1007                 :            :                 /* Reuse the slot. */
    1008                 :          0 :                 free(env[i]);
    1009                 :            :         } else {
    1010                 :            :                 /* New variable.  Expand if necessary. */
    1011                 :       6632 :                 envsize = *envsizep;
    1012         [ -  + ]:       6632 :                 if (i >= envsize - 1) {
    1013         [ #  # ]:          0 :                         if (envsize >= 1000)
    1014                 :          0 :                                 fatal("child_set_env: too many env vars");
    1015                 :          0 :                         envsize += 50;
    1016                 :          0 :                         env = (*envp) = xrealloc(env, envsize, sizeof(char *));
    1017                 :          0 :                         *envsizep = envsize;
    1018                 :            :                 }
    1019                 :            :                 /* Need to set the NULL pointer at end of array beyond the new slot. */
    1020                 :       6632 :                 env[i + 1] = NULL;
    1021                 :            :         }
    1022                 :            : 
    1023                 :            :         /* Allocate space and format the variable in the appropriate slot. */
    1024                 :       6632 :         env[i] = xmalloc(strlen(name) + 1 + strlen(value) + 1);
    1025                 :       6632 :         snprintf(env[i], strlen(name) + 1 + strlen(value) + 1, "%s=%s", name, value);
    1026                 :            : }
    1027                 :            : 
    1028                 :            : /*
    1029                 :            :  * Reads environment variables from the given file and adds/overrides them
    1030                 :            :  * into the environment.  If the file does not exist, this does nothing.
    1031                 :            :  * Otherwise, it must consist of empty lines, comments (line starts with '#')
    1032                 :            :  * and assignments of the form name=value.  No other forms are allowed.
    1033                 :            :  */
    1034                 :            : static void
    1035                 :          6 : read_environment_file(char ***env, u_int *envsize,
    1036                 :            :         const char *filename)
    1037                 :            : {
    1038                 :            :         FILE *f;
    1039                 :            :         char buf[4096];
    1040                 :            :         char *cp, *value;
    1041                 :          6 :         u_int lineno = 0;
    1042                 :            : 
    1043                 :          6 :         f = fopen(filename, "r");
    1044         [ -  + ]:          6 :         if (!f)
    1045                 :          6 :                 return;
    1046                 :            : 
    1047         [ #  # ]:          0 :         while (fgets(buf, sizeof(buf), f)) {
    1048         [ #  # ]:          0 :                 if (++lineno > 1000)
    1049                 :          0 :                         fatal("Too many lines in environment file %s", filename);
    1050         [ #  # ]:          0 :                 for (cp = buf; *cp == ' ' || *cp == '\t'; cp++)
    1051                 :            :                         ;
    1052 [ #  # ][ #  # ]:          0 :                 if (!*cp || *cp == '#' || *cp == '\n')
    1053                 :          0 :                         continue;
    1054                 :            : 
    1055                 :          0 :                 cp[strcspn(cp, "\n")] = '\0';
    1056                 :            : 
    1057                 :          0 :                 value = strchr(cp, '=');
    1058         [ #  # ]:          0 :                 if (value == NULL) {
    1059                 :          0 :                         fprintf(stderr, "Bad line %u in %.100s\n", lineno,
    1060                 :            :                             filename);
    1061                 :          0 :                         continue;
    1062                 :            :                 }
    1063                 :            :                 /*
    1064                 :            :                  * Replace the equals sign by nul, and advance value to
    1065                 :            :                  * the value string.
    1066                 :            :                  */
    1067                 :          0 :                 *value = '\0';
    1068                 :          0 :                 value++;
    1069                 :          0 :                 child_set_env(env, envsize, cp, value);
    1070                 :            :         }
    1071                 :          0 :         fclose(f);
    1072                 :            : }
    1073                 :            : 
    1074                 :            : #ifdef HAVE_ETC_DEFAULT_LOGIN
    1075                 :            : /*
    1076                 :            :  * Return named variable from specified environment, or NULL if not present.
    1077                 :            :  */
    1078                 :            : static char *
    1079                 :            : child_get_env(char **env, const char *name)
    1080                 :            : {
    1081                 :            :         int i;
    1082                 :            :         size_t len;
    1083                 :            : 
    1084                 :            :         len = strlen(name);
    1085                 :            :         for (i=0; env[i] != NULL; i++)
    1086                 :            :                 if (strncmp(name, env[i], len) == 0 && env[i][len] == '=')
    1087                 :            :                         return(env[i] + len + 1);
    1088                 :            :         return NULL;
    1089                 :            : }
    1090                 :            : 
    1091                 :            : /*
    1092                 :            :  * Read /etc/default/login.
    1093                 :            :  * We pick up the PATH (or SUPATH for root) and UMASK.
    1094                 :            :  */
    1095                 :            : static void
    1096                 :            : read_etc_default_login(char ***env, u_int *envsize, uid_t uid)
    1097                 :            : {
    1098                 :            :         char **tmpenv = NULL, *var;
    1099                 :            :         u_int i, tmpenvsize = 0;
    1100                 :            :         u_long mask;
    1101                 :            : 
    1102                 :            :         /*
    1103                 :            :          * We don't want to copy the whole file to the child's environment,
    1104                 :            :          * so we use a temporary environment and copy the variables we're
    1105                 :            :          * interested in.
    1106                 :            :          */
    1107                 :            :         read_environment_file(&tmpenv, &tmpenvsize, "/etc/default/login");
    1108                 :            : 
    1109                 :            :         if (tmpenv == NULL)
    1110                 :            :                 return;
    1111                 :            : 
    1112                 :            :         if (uid == 0)
    1113                 :            :                 var = child_get_env(tmpenv, "SUPATH");
    1114                 :            :         else
    1115                 :            :                 var = child_get_env(tmpenv, "PATH");
    1116                 :            :         if (var != NULL)
    1117                 :            :                 child_set_env(env, envsize, "PATH", var);
    1118                 :            : 
    1119                 :            :         if ((var = child_get_env(tmpenv, "UMASK")) != NULL)
    1120                 :            :                 if (sscanf(var, "%5lo", &mask) == 1)
    1121                 :            :                         umask((mode_t)mask);
    1122                 :            : 
    1123                 :            :         for (i = 0; tmpenv[i] != NULL; i++)
    1124                 :            :                 free(tmpenv[i]);
    1125                 :            :         free(tmpenv);
    1126                 :            : }
    1127                 :            : #endif /* HAVE_ETC_DEFAULT_LOGIN */
    1128                 :            : 
    1129                 :            : void
    1130                 :          0 : copy_environment(char **source, char ***env, u_int *envsize)
    1131                 :            : {
    1132                 :            :         char *var_name, *var_val;
    1133                 :            :         int i;
    1134                 :            : 
    1135         [ #  # ]:          0 :         if (source == NULL)
    1136                 :          0 :                 return;
    1137                 :            : 
    1138         [ #  # ]:          0 :         for(i = 0; source[i] != NULL; i++) {
    1139                 :          0 :                 var_name = xstrdup(source[i]);
    1140         [ #  # ]:          0 :                 if ((var_val = strstr(var_name, "=")) == NULL) {
    1141                 :          0 :                         free(var_name);
    1142                 :          0 :                         continue;
    1143                 :            :                 }
    1144                 :          0 :                 *var_val++ = '\0';
    1145                 :            : 
    1146                 :          0 :                 debug3("Copy environment: %s=%s", var_name, var_val);
    1147                 :          0 :                 child_set_env(env, envsize, var_name, var_val);
    1148                 :            : 
    1149                 :          0 :                 free(var_name);
    1150                 :            :         }
    1151                 :            : }
    1152                 :            : 
    1153                 :            : static char **
    1154                 :        822 : do_setup_env(Session *s, const char *shell)
    1155                 :            : {
    1156                 :            :         char buf[256];
    1157                 :            :         u_int i, envsize;
    1158                 :            :         char **env, *laddr;
    1159                 :        822 :         struct passwd *pw = s->pw;
    1160                 :            : #if !defined (HAVE_LOGIN_CAP) && !defined (HAVE_CYGWIN)
    1161                 :        822 :         char *path = NULL;
    1162                 :            : #endif
    1163                 :            : 
    1164                 :            :         /* Initialize the environment. */
    1165                 :        822 :         envsize = 100;
    1166                 :        822 :         env = xcalloc(envsize, sizeof(char *));
    1167                 :        822 :         env[0] = NULL;
    1168                 :            : 
    1169                 :            : #ifdef HAVE_CYGWIN
    1170                 :            :         /*
    1171                 :            :          * The Windows environment contains some setting which are
    1172                 :            :          * important for a running system. They must not be dropped.
    1173                 :            :          */
    1174                 :            :         {
    1175                 :            :                 char **p;
    1176                 :            : 
    1177                 :            :                 p = fetch_windows_environment();
    1178                 :            :                 copy_environment(p, &env, &envsize);
    1179                 :            :                 free_windows_environment(p);
    1180                 :            :         }
    1181                 :            : #endif
    1182                 :            : 
    1183                 :            : #ifdef GSSAPI
    1184                 :            :         /* Allow any GSSAPI methods that we've used to alter
    1185                 :            :          * the childs environment as they see fit
    1186                 :            :          */
    1187                 :            :         ssh_gssapi_do_child(&env, &envsize);
    1188                 :            : #endif
    1189                 :            : 
    1190         [ +  - ]:        822 :         if (!options.use_login) {
    1191                 :            :                 /* Set basic environment. */
    1192         [ +  + ]:        826 :                 for (i = 0; i < s->num_env; i++)
    1193                 :          4 :                         child_set_env(&env, &envsize, s->env[i].name,
    1194                 :          4 :                             s->env[i].val);
    1195                 :            : 
    1196                 :        822 :                 child_set_env(&env, &envsize, "USER", pw->pw_name);
    1197                 :        822 :                 child_set_env(&env, &envsize, "LOGNAME", pw->pw_name);
    1198                 :            : #ifdef _AIX
    1199                 :            :                 child_set_env(&env, &envsize, "LOGIN", pw->pw_name);
    1200                 :            : #endif
    1201                 :        822 :                 child_set_env(&env, &envsize, "HOME", pw->pw_dir);
    1202                 :            : #ifdef HAVE_LOGIN_CAP
    1203                 :            :                 if (setusercontext(lc, pw, pw->pw_uid, LOGIN_SETPATH) < 0)
    1204                 :            :                         child_set_env(&env, &envsize, "PATH", _PATH_STDPATH);
    1205                 :            :                 else
    1206                 :            :                         child_set_env(&env, &envsize, "PATH", getenv("PATH"));
    1207                 :            : #else /* HAVE_LOGIN_CAP */
    1208                 :            : # ifndef HAVE_CYGWIN
    1209                 :            :                 /*
    1210                 :            :                  * There's no standard path on Windows. The path contains
    1211                 :            :                  * important components pointing to the system directories,
    1212                 :            :                  * needed for loading shared libraries. So the path better
    1213                 :            :                  * remains intact here.
    1214                 :            :                  */
    1215                 :            : #  ifdef HAVE_ETC_DEFAULT_LOGIN
    1216                 :            :                 read_etc_default_login(&env, &envsize, pw->pw_uid);
    1217                 :            :                 path = child_get_env(env, "PATH");
    1218                 :            : #  endif /* HAVE_ETC_DEFAULT_LOGIN */
    1219                 :            :                 if (path == NULL || *path == '\0') {
    1220                 :        822 :                         child_set_env(&env, &envsize, "PATH",
    1221                 :            :                             s->pw->pw_uid == 0 ?
    1222                 :            :                                 SUPERUSER_PATH : _PATH_STDPATH);
    1223                 :            :                 }
    1224                 :            : # endif /* HAVE_CYGWIN */
    1225                 :            : #endif /* HAVE_LOGIN_CAP */
    1226                 :            : 
    1227                 :        822 :                 snprintf(buf, sizeof buf, "%.200s/%.50s",
    1228                 :            :                          _PATH_MAILDIR, pw->pw_name);
    1229                 :        822 :                 child_set_env(&env, &envsize, "MAIL", buf);
    1230                 :            : 
    1231                 :            :                 /* Normal systems set SHELL by default. */
    1232                 :        822 :                 child_set_env(&env, &envsize, "SHELL", shell);
    1233                 :            :         }
    1234         [ -  + ]:        822 :         if (getenv("TZ"))
    1235                 :          0 :                 child_set_env(&env, &envsize, "TZ", getenv("TZ"));
    1236                 :            : 
    1237                 :            :         /* Set custom environment options from RSA authentication. */
    1238         [ +  - ]:        822 :         if (!options.use_login) {
    1239         [ +  + ]:        824 :                 while (custom_environment) {
    1240                 :          2 :                         struct envstring *ce = custom_environment;
    1241                 :          2 :                         char *str = ce->s;
    1242                 :            : 
    1243         [ +  + ]:          8 :                         for (i = 0; str[i] != '=' && str[i]; i++)
    1244                 :            :                                 ;
    1245         [ +  - ]:          2 :                         if (str[i] == '=') {
    1246                 :          2 :                                 str[i] = 0;
    1247                 :          2 :                                 child_set_env(&env, &envsize, str, str + i + 1);
    1248                 :            :                         }
    1249                 :          2 :                         custom_environment = ce->next;
    1250                 :          2 :                         free(ce->s);
    1251                 :          2 :                         free(ce);
    1252                 :            :                 }
    1253                 :            :         }
    1254                 :            : 
    1255                 :            :         /* SSH_CLIENT deprecated */
    1256                 :        822 :         snprintf(buf, sizeof buf, "%.50s %d %d",
    1257                 :            :             get_remote_ipaddr(), get_remote_port(), get_local_port());
    1258                 :        822 :         child_set_env(&env, &envsize, "SSH_CLIENT", buf);
    1259                 :            : 
    1260                 :        822 :         laddr = get_local_ipaddr(packet_get_connection_in());
    1261                 :        822 :         snprintf(buf, sizeof buf, "%.50s %d %.50s %d",
    1262                 :            :             get_remote_ipaddr(), get_remote_port(), laddr, get_local_port());
    1263                 :        822 :         free(laddr);
    1264                 :        822 :         child_set_env(&env, &envsize, "SSH_CONNECTION", buf);
    1265                 :            : 
    1266         [ -  + ]:        822 :         if (s->ttyfd != -1)
    1267                 :          0 :                 child_set_env(&env, &envsize, "SSH_TTY", s->tty);
    1268         [ -  + ]:        822 :         if (s->term)
    1269                 :          0 :                 child_set_env(&env, &envsize, "TERM", s->term);
    1270         [ -  + ]:        822 :         if (s->display)
    1271                 :          0 :                 child_set_env(&env, &envsize, "DISPLAY", s->display);
    1272         [ +  + ]:        822 :         if (original_command)
    1273                 :         46 :                 child_set_env(&env, &envsize, "SSH_ORIGINAL_COMMAND",
    1274                 :            :                     original_command);
    1275                 :            : 
    1276                 :            : #ifdef _UNICOS
    1277                 :            :         if (cray_tmpdir[0] != '\0')
    1278                 :            :                 child_set_env(&env, &envsize, "TMPDIR", cray_tmpdir);
    1279                 :            : #endif /* _UNICOS */
    1280                 :            : 
    1281                 :            :         /*
    1282                 :            :          * Since we clear KRB5CCNAME at startup, if it's set now then it
    1283                 :            :          * must have been set by a native authentication method (eg AIX or
    1284                 :            :          * SIA), so copy it to the child.
    1285                 :            :          */
    1286                 :            :         {
    1287                 :            :                 char *cp;
    1288                 :            : 
    1289         [ -  + ]:        822 :                 if ((cp = getenv("KRB5CCNAME")) != NULL)
    1290                 :          0 :                         child_set_env(&env, &envsize, "KRB5CCNAME", cp);
    1291                 :            :         }
    1292                 :            : 
    1293                 :            : #ifdef _AIX
    1294                 :            :         {
    1295                 :            :                 char *cp;
    1296                 :            : 
    1297                 :            :                 if ((cp = getenv("AUTHSTATE")) != NULL)
    1298                 :            :                         child_set_env(&env, &envsize, "AUTHSTATE", cp);
    1299                 :            :                 read_environment_file(&env, &envsize, "/etc/environment");
    1300                 :            :         }
    1301                 :            : #endif
    1302                 :            : #ifdef KRB5
    1303                 :            :         if (s->authctxt->krb5_ccname)
    1304                 :            :                 child_set_env(&env, &envsize, "KRB5CCNAME",
    1305                 :            :                     s->authctxt->krb5_ccname);
    1306                 :            : #endif
    1307                 :            : #ifdef USE_PAM
    1308                 :            :         /*
    1309                 :            :          * Pull in any environment variables that may have
    1310                 :            :          * been set by PAM.
    1311                 :            :          */
    1312                 :            :         if (options.use_pam) {
    1313                 :            :                 char **p;
    1314                 :            : 
    1315                 :            :                 p = fetch_pam_child_environment();
    1316                 :            :                 copy_environment(p, &env, &envsize);
    1317                 :            :                 free_pam_environment(p);
    1318                 :            : 
    1319                 :            :                 p = fetch_pam_environment();
    1320                 :            :                 copy_environment(p, &env, &envsize);
    1321                 :            :                 free_pam_environment(p);
    1322                 :            :         }
    1323                 :            : #endif /* USE_PAM */
    1324                 :            : 
    1325         [ +  + ]:        822 :         if (auth_sock_name != NULL)
    1326                 :          4 :                 child_set_env(&env, &envsize, SSH_AUTHSOCKET_ENV_NAME,
    1327                 :            :                     auth_sock_name);
    1328                 :            : 
    1329                 :            :         /* read $HOME/.ssh/environment. */
    1330 [ +  + ][ +  - ]:        822 :         if (options.permit_user_env && !options.use_login) {
    1331         [ +  - ]:          6 :                 snprintf(buf, sizeof buf, "%.200s/.ssh/environment",
    1332         [ +  - ]:          6 :                     strcmp(pw->pw_dir, "/") ? pw->pw_dir : "");
    1333                 :          6 :                 read_environment_file(&env, &envsize, buf);
    1334                 :            :         }
    1335         [ -  + ]:        822 :         if (debug_flag) {
    1336                 :            :                 /* dump the environment */
    1337                 :          0 :                 fprintf(stderr, "Environment:\n");
    1338         [ #  # ]:          0 :                 for (i = 0; env[i]; i++)
    1339                 :          0 :                         fprintf(stderr, "  %.200s\n", env[i]);
    1340                 :            :         }
    1341                 :        822 :         return env;
    1342                 :            : }
    1343                 :            : 
    1344                 :            : /*
    1345                 :            :  * Run $HOME/.ssh/rc, /etc/ssh/sshrc, or xauth (whichever is found
    1346                 :            :  * first in this order).
    1347                 :            :  */
    1348                 :            : static void
    1349                 :        822 : do_rc_files(Session *s, const char *shell)
    1350                 :            : {
    1351                 :        822 :         FILE *f = NULL;
    1352                 :            :         char cmd[1024];
    1353                 :            :         int do_xauth;
    1354                 :            :         struct stat st;
    1355                 :            : 
    1356                 :        822 :         do_xauth =
    1357 [ -  + ][ #  # ]:        822 :             s->display != NULL && s->auth_proto != NULL && s->auth_data != NULL;
                 [ #  # ]
    1358                 :            : 
    1359                 :            :         /* ignore _PATH_SSH_USER_RC for subsystems and admin forced commands */
    1360 [ +  + ][ +  + ]:        822 :         if (!s->is_subsystem && options.adm_forced_command == NULL &&
                 [ +  - ]
    1361         [ -  + ]:        817 :             !no_user_rc && stat(_PATH_SSH_USER_RC, &st) >= 0) {
    1362                 :            :                 snprintf(cmd, sizeof cmd, "%s -c '%s %s'",
    1363                 :            :                     shell, _PATH_BSHELL, _PATH_SSH_USER_RC);
    1364         [ #  # ]:          0 :                 if (debug_flag)
    1365                 :          0 :                         fprintf(stderr, "Running %s\n", cmd);
    1366                 :          0 :                 f = popen(cmd, "w");
    1367         [ #  # ]:          0 :                 if (f) {
    1368         [ #  # ]:          0 :                         if (do_xauth)
    1369                 :          0 :                                 fprintf(f, "%s %s\n", s->auth_proto,
    1370                 :            :                                     s->auth_data);
    1371                 :          0 :                         pclose(f);
    1372                 :            :                 } else
    1373                 :          0 :                         fprintf(stderr, "Could not run %s\n",
    1374                 :            :                             _PATH_SSH_USER_RC);
    1375         [ -  + ]:        822 :         } else if (stat(_PATH_SSH_SYSTEM_RC, &st) >= 0) {
    1376         [ #  # ]:          0 :                 if (debug_flag)
    1377                 :          0 :                         fprintf(stderr, "Running %s %s\n", _PATH_BSHELL,
    1378                 :            :                             _PATH_SSH_SYSTEM_RC);
    1379                 :          0 :                 f = popen(_PATH_BSHELL " " _PATH_SSH_SYSTEM_RC, "w");
    1380         [ #  # ]:          0 :                 if (f) {
    1381         [ #  # ]:          0 :                         if (do_xauth)
    1382                 :          0 :                                 fprintf(f, "%s %s\n", s->auth_proto,
    1383                 :            :                                     s->auth_data);
    1384                 :          0 :                         pclose(f);
    1385                 :            :                 } else
    1386                 :          0 :                         fprintf(stderr, "Could not run %s\n",
    1387                 :            :                             _PATH_SSH_SYSTEM_RC);
    1388 [ -  + ][ #  # ]:        822 :         } else if (do_xauth && options.xauth_location != NULL) {
    1389                 :            :                 /* Add authority data to .Xauthority if appropriate. */
    1390         [ #  # ]:          0 :                 if (debug_flag) {
    1391                 :          0 :                         fprintf(stderr,
    1392                 :            :                             "Running %.500s remove %.100s\n",
    1393                 :            :                             options.xauth_location, s->auth_display);
    1394                 :          0 :                         fprintf(stderr,
    1395                 :            :                             "%.500s add %.100s %.100s %.100s\n",
    1396                 :            :                             options.xauth_location, s->auth_display,
    1397                 :            :                             s->auth_proto, s->auth_data);
    1398                 :            :                 }
    1399                 :          0 :                 snprintf(cmd, sizeof cmd, "%s -q -",
    1400                 :            :                     options.xauth_location);
    1401                 :          0 :                 f = popen(cmd, "w");
    1402         [ #  # ]:          0 :                 if (f) {
    1403                 :          0 :                         fprintf(f, "remove %s\n",
    1404                 :            :                             s->auth_display);
    1405                 :          0 :                         fprintf(f, "add %s %s %s\n",
    1406                 :            :                             s->auth_display, s->auth_proto,
    1407                 :            :                             s->auth_data);
    1408                 :          0 :                         pclose(f);
    1409                 :            :                 } else {
    1410                 :          0 :                         fprintf(stderr, "Could not run %s\n",
    1411                 :            :                             cmd);
    1412                 :            :                 }
    1413                 :            :         }
    1414                 :        822 : }
    1415                 :            : 
    1416                 :            : static void
    1417                 :       1644 : do_nologin(struct passwd *pw)
    1418                 :            : {
    1419                 :        822 :         FILE *f = NULL;
    1420                 :        822 :         char buf[1024], *nl, *def_nl = _PATH_NOLOGIN;
    1421                 :            :         struct stat sb;
    1422                 :            : 
    1423                 :            : #ifdef HAVE_LOGIN_CAP
    1424                 :            :         if (login_getcapbool(lc, "ignorenologin", 0) || pw->pw_uid == 0)
    1425                 :            :                 return;
    1426                 :            :         nl = login_getcapstr(lc, "nologin", def_nl, def_nl);
    1427                 :            : #else
    1428         [ +  - ]:        822 :         if (pw->pw_uid == 0)
    1429                 :            :                 return;
    1430                 :        822 :         nl = def_nl;
    1431                 :            : #endif
    1432         [ -  + ]:        822 :         if (stat(nl, &sb) == -1) {
    1433                 :            :                 if (nl != def_nl)
    1434                 :            :                         free(nl);
    1435                 :            :                 return;
    1436                 :            :         }
    1437                 :            : 
    1438                 :            :         /* /etc/nologin exists.  Print its contents if we can and exit. */
    1439                 :          0 :         logit("User %.100s not allowed because %s exists", pw->pw_name, nl);
    1440         [ #  # ]:          0 :         if ((f = fopen(nl, "r")) != NULL) {
    1441         [ #  # ]:          0 :                 while (fgets(buf, sizeof(buf), f))
    1442                 :          0 :                         fputs(buf, stderr);
    1443                 :          0 :                 fclose(f);
    1444                 :            :         }
    1445                 :          0 :         exit(254);
    1446                 :            : }
    1447                 :            : 
    1448                 :            : /*
    1449                 :            :  * Chroot into a directory after checking it for safety: all path components
    1450                 :            :  * must be root-owned directories with strict permissions.
    1451                 :            :  */
    1452                 :            : static void
    1453                 :          0 : safely_chroot(const char *path, uid_t uid)
    1454                 :            : {
    1455                 :            :         const char *cp;
    1456                 :            :         char component[MAXPATHLEN];
    1457                 :            :         struct stat st;
    1458                 :            : 
    1459         [ #  # ]:          0 :         if (*path != '/')
    1460                 :          0 :                 fatal("chroot path does not begin at root");
    1461         [ #  # ]:          0 :         if (strlen(path) >= sizeof(component))
    1462                 :          0 :                 fatal("chroot path too long");
    1463                 :            : 
    1464                 :            :         /*
    1465                 :            :          * Descend the path, checking that each component is a
    1466                 :            :          * root-owned directory with strict permissions.
    1467                 :            :          */
    1468         [ #  # ]:          0 :         for (cp = path; cp != NULL;) {
    1469         [ #  # ]:          0 :                 if ((cp = strchr(cp, '/')) == NULL)
    1470                 :          0 :                         strlcpy(component, path, sizeof(component));
    1471                 :            :                 else {
    1472                 :          0 :                         cp++;
    1473                 :          0 :                         memcpy(component, path, cp - path);
    1474                 :          0 :                         component[cp - path] = '\0';
    1475                 :            :                 }
    1476                 :            :         
    1477                 :          0 :                 debug3("%s: checking '%s'", __func__, component);
    1478                 :            : 
    1479         [ #  # ]:          0 :                 if (stat(component, &st) != 0)
    1480                 :          0 :                         fatal("%s: stat(\"%s\"): %s", __func__,
    1481                 :          0 :                             component, strerror(errno));
    1482         [ #  # ]:          0 :                 if (st.st_uid != 0 || (st.st_mode & 022) != 0)
    1483         [ #  # ]:          0 :                         fatal("bad ownership or modes for chroot "
    1484                 :            :                             "directory %s\"%s\"", 
    1485                 :            :                             cp == NULL ? "" : "component ", component);
    1486         [ #  # ]:          0 :                 if (!S_ISDIR(st.st_mode))
    1487         [ #  # ]:          0 :                         fatal("chroot path %s\"%s\" is not a directory",
    1488                 :            :                             cp == NULL ? "" : "component ", component);
    1489                 :            : 
    1490                 :            :         }
    1491                 :            : 
    1492         [ #  # ]:          0 :         if (chdir(path) == -1)
    1493                 :          0 :                 fatal("Unable to chdir to chroot path \"%s\": "
    1494                 :          0 :                     "%s", path, strerror(errno));
    1495         [ #  # ]:          0 :         if (chroot(path) == -1)
    1496                 :          0 :                 fatal("chroot(\"%s\"): %s", path, strerror(errno));
    1497         [ #  # ]:          0 :         if (chdir("/") == -1)
    1498                 :          0 :                 fatal("%s: chdir(/) after chroot: %s",
    1499                 :          0 :                     __func__, strerror(errno));
    1500                 :          0 :         verbose("Changed root directory to \"%s\"", path);
    1501                 :          0 : }
    1502                 :            : 
    1503                 :            : /* Set login name, uid, gid, and groups. */
    1504                 :            : void
    1505                 :       1557 : do_setusercontext(struct passwd *pw)
    1506                 :            : {
    1507                 :            :         char *chroot_path, *tmp;
    1508                 :            : 
    1509                 :       1557 :         platform_setusercontext(pw);
    1510                 :            : 
    1511         [ -  + ]:       1557 :         if (platform_privileged_uidswap()) {
    1512                 :            : #ifdef HAVE_LOGIN_CAP
    1513                 :            :                 if (setusercontext(lc, pw, pw->pw_uid,
    1514                 :            :                     (LOGIN_SETALL & ~(LOGIN_SETPATH|LOGIN_SETUSER))) < 0) {
    1515                 :            :                         perror("unable to set user context");
    1516                 :            :                         exit(1);
    1517                 :            :                 }
    1518                 :            : #else
    1519         [ #  # ]:          0 :                 if (setlogin(pw->pw_name) < 0)
    1520                 :          0 :                         error("setlogin failed: %s", strerror(errno));
    1521         [ #  # ]:          0 :                 if (setgid(pw->pw_gid) < 0) {
    1522                 :          0 :                         perror("setgid");
    1523                 :          0 :                         exit(1);
    1524                 :            :                 }
    1525                 :            :                 /* Initialize the group list. */
    1526         [ #  # ]:          0 :                 if (initgroups(pw->pw_name, pw->pw_gid) < 0) {
    1527                 :          0 :                         perror("initgroups");
    1528                 :          0 :                         exit(1);
    1529                 :            :                 }
    1530                 :          0 :                 endgrent();
    1531                 :            : #endif
    1532                 :            : 
    1533                 :          0 :                 platform_setusercontext_post_groups(pw);
    1534                 :            : 
    1535 [ #  # ][ #  # ]:          0 :                 if (options.chroot_directory != NULL &&
    1536                 :          0 :                     strcasecmp(options.chroot_directory, "none") != 0) {
    1537                 :          0 :                         tmp = tilde_expand_filename(options.chroot_directory,
    1538                 :            :                             pw->pw_uid);
    1539                 :          0 :                         chroot_path = percent_expand(tmp, "h", pw->pw_dir,
    1540                 :            :                             "u", pw->pw_name, (char *)NULL);
    1541                 :          0 :                         safely_chroot(chroot_path, pw->pw_uid);
    1542                 :          0 :                         free(tmp);
    1543                 :          0 :                         free(chroot_path);
    1544                 :            :                         /* Make sure we don't attempt to chroot again */
    1545                 :          0 :                         free(options.chroot_directory);
    1546                 :          0 :                         options.chroot_directory = NULL;
    1547                 :            :                 }
    1548                 :            : 
    1549                 :            : #ifdef HAVE_LOGIN_CAP
    1550                 :            :                 if (setusercontext(lc, pw, pw->pw_uid, LOGIN_SETUSER) < 0) {
    1551                 :            :                         perror("unable to set user context (setuser)");
    1552                 :            :                         exit(1);
    1553                 :            :                 }
    1554                 :            :                 /* 
    1555                 :            :                  * FreeBSD's setusercontext() will not apply the user's
    1556                 :            :                  * own umask setting unless running with the user's UID.
    1557                 :            :                  */
    1558                 :            :                 (void) setusercontext(lc, pw, pw->pw_uid, LOGIN_SETUMASK);
    1559                 :            : #else
    1560                 :            : # ifdef USE_LIBIAF
    1561                 :            :         if (set_id(pw->pw_name) != 0) {
    1562                 :            :                 fatal("set_id(%s) Failed", pw->pw_name);
    1563                 :            :         }
    1564                 :            : # endif /* USE_LIBIAF */
    1565                 :            :                 /* Permanently switch to the desired uid. */
    1566                 :          0 :                 permanently_set_uid(pw);
    1567                 :            : #endif
    1568 [ -  + ][ #  # ]:       1557 :         } else if (options.chroot_directory != NULL &&
    1569                 :          0 :             strcasecmp(options.chroot_directory, "none") != 0) {
    1570                 :          0 :                 fatal("server lacks privileges to chroot to ChrootDirectory");
    1571                 :            :         }
    1572                 :            : 
    1573 [ +  - ][ -  + ]:       1557 :         if (getuid() != pw->pw_uid || geteuid() != pw->pw_uid)
    1574                 :          0 :                 fatal("Failed to set uids to %u.", (u_int) pw->pw_uid);
    1575                 :       1557 : }
    1576                 :            : 
    1577                 :            : static void
    1578                 :          0 : do_pwchange(Session *s)
    1579                 :            : {
    1580                 :          0 :         fflush(NULL);
    1581                 :          0 :         fprintf(stderr, "WARNING: Your password has expired.\n");
    1582         [ #  # ]:          0 :         if (s->ttyfd != -1) {
    1583                 :          0 :                 fprintf(stderr,
    1584                 :            :                     "You must change your password now and login again!\n");
    1585                 :            : #ifdef WITH_SELINUX
    1586                 :            :                 setexeccon(NULL);
    1587                 :            : #endif
    1588                 :            : #ifdef PASSWD_NEEDS_USERNAME
    1589                 :            :                 execl(_PATH_PASSWD_PROG, "passwd", s->pw->pw_name,
    1590                 :            :                     (char *)NULL);
    1591                 :            : #else
    1592                 :          0 :                 execl(_PATH_PASSWD_PROG, "passwd", (char *)NULL);
    1593                 :            : #endif
    1594                 :          0 :                 perror("passwd");
    1595                 :            :         } else {
    1596                 :          0 :                 fprintf(stderr,
    1597                 :            :                     "Password change required but no TTY available.\n");
    1598                 :            :         }
    1599                 :          0 :         exit(1);
    1600                 :            : }
    1601                 :            : 
    1602                 :            : static void
    1603                 :          0 : launch_login(struct passwd *pw, const char *hostname)
    1604                 :            : {
    1605                 :            :         /* Launch login(1). */
    1606                 :            : 
    1607                 :          0 :         execl(LOGIN_PROGRAM, "login", "-h", hostname,
    1608                 :            : #ifdef xxxLOGIN_NEEDS_TERM
    1609                 :            :                     (s->term ? s->term : "unknown"),
    1610                 :            : #endif /* LOGIN_NEEDS_TERM */
    1611                 :            : #ifdef LOGIN_NO_ENDOPT
    1612                 :            :             "-p", "-f", pw->pw_name, (char *)NULL);
    1613                 :            : #else
    1614                 :            :             "-p", "-f", "--", pw->pw_name, (char *)NULL);
    1615                 :            : #endif
    1616                 :            : 
    1617                 :            :         /* Login couldn't be executed, die. */
    1618                 :            : 
    1619                 :          0 :         perror("login");
    1620                 :          0 :         exit(1);
    1621                 :            : }
    1622                 :            : 
    1623                 :            : static void
    1624                 :        822 : child_close_fds(void)
    1625                 :            : {
    1626                 :            :         extern AuthenticationConnection *auth_conn;
    1627                 :            : 
    1628         [ -  + ]:        822 :         if (auth_conn) {
    1629                 :          0 :                 ssh_close_authentication_connection(auth_conn);
    1630                 :          0 :                 auth_conn = NULL;
    1631                 :            :         }
    1632                 :            : 
    1633         [ +  + ]:        822 :         if (packet_get_connection_in() == packet_get_connection_out())
    1634                 :        102 :                 close(packet_get_connection_in());
    1635                 :            :         else {
    1636                 :        720 :                 close(packet_get_connection_in());
    1637                 :        720 :                 close(packet_get_connection_out());
    1638                 :            :         }
    1639                 :            :         /*
    1640                 :            :          * Close all descriptors related to channels.  They will still remain
    1641                 :            :          * open in the parent.
    1642                 :            :          */
    1643                 :            :         /* XXX better use close-on-exec? -markus */
    1644                 :        822 :         channel_close_all();
    1645                 :            : 
    1646                 :            :         /*
    1647                 :            :          * Close any extra file descriptors.  Note that there may still be
    1648                 :            :          * descriptors left by system functions.  They will be closed later.
    1649                 :            :          */
    1650                 :        822 :         endpwent();
    1651                 :            : 
    1652                 :            :         /*
    1653                 :            :          * Close any extra open file descriptors so that we don't have them
    1654                 :            :          * hanging around in clients.  Note that we want to do this after
    1655                 :            :          * initgroups, because at least on Solaris 2.3 it leaves file
    1656                 :            :          * descriptors open.
    1657                 :            :          */
    1658                 :        822 :         closefrom(STDERR_FILENO + 1);
    1659                 :        822 : }
    1660                 :            : 
    1661                 :            : /*
    1662                 :            :  * Performs common processing for the child, such as setting up the
    1663                 :            :  * environment, closing extra file descriptors, setting the user and group
    1664                 :            :  * ids, and executing the command or shell.
    1665                 :            :  */
    1666                 :            : #define ARGV_MAX 10
    1667                 :            : void
    1668                 :        822 : do_child(Session *s, const char *command)
    1669                 :            : {
    1670                 :            :         extern char **environ;
    1671                 :            :         char **env;
    1672                 :            :         char *argv[ARGV_MAX];
    1673                 :        822 :         const char *shell, *shell0, *hostname = NULL;
    1674                 :       1644 :         struct passwd *pw = s->pw;
    1675                 :        822 :         int r = 0;
    1676                 :            : 
    1677                 :            :         /* remove hostkey from the child's memory */
    1678                 :        822 :         destroy_sensitive_data();
    1679                 :            : 
    1680                 :            :         /* Force a password change */
    1681         [ -  + ]:        822 :         if (s->authctxt->force_pwchange) {
    1682                 :          0 :                 do_setusercontext(pw);
    1683                 :          0 :                 child_close_fds();
    1684                 :          0 :                 do_pwchange(s);
    1685                 :            :                 exit(1);
    1686                 :            :         }
    1687                 :            : 
    1688                 :            :         /* login(1) is only called if we execute the login shell */
    1689 [ -  + ][ #  # ]:        822 :         if (options.use_login && command != NULL)
    1690                 :          0 :                 options.use_login = 0;
    1691                 :            : 
    1692                 :            : #ifdef _UNICOS
    1693                 :            :         cray_setup(pw->pw_uid, pw->pw_name, command);
    1694                 :            : #endif /* _UNICOS */
    1695                 :            : 
    1696                 :            :         /*
    1697                 :            :          * Login(1) does this as well, and it needs uid 0 for the "-h"
    1698                 :            :          * switch, so we let login(1) to this for us.
    1699                 :            :          */
    1700         [ +  - ]:        822 :         if (!options.use_login) {
    1701                 :            : #ifdef HAVE_OSF_SIA
    1702                 :            :                 session_setup_sia(pw, s->ttyfd == -1 ? NULL : s->tty);
    1703                 :            :                 if (!check_quietlogin(s, command))
    1704                 :            :                         do_motd();
    1705                 :            : #else /* HAVE_OSF_SIA */
    1706                 :            :                 /* When PAM is enabled we rely on it to do the nologin check */
    1707         [ +  - ]:        822 :                 if (!options.use_pam)
    1708                 :        822 :                         do_nologin(pw);
    1709                 :        822 :                 do_setusercontext(pw);
    1710                 :            :                 /*
    1711                 :            :                  * PAM session modules in do_setusercontext may have
    1712                 :            :                  * generated messages, so if this in an interactive
    1713                 :            :                  * login then display them too.
    1714                 :            :                  */
    1715         [ -  + ]:        822 :                 if (!check_quietlogin(s, command))
    1716                 :          0 :                         display_loginmsg();
    1717                 :            : #endif /* HAVE_OSF_SIA */
    1718                 :            :         }
    1719                 :            : 
    1720                 :            : #ifdef USE_PAM
    1721                 :            :         if (options.use_pam && !options.use_login && !is_pam_session_open()) {
    1722                 :            :                 debug3("PAM session not opened, exiting");
    1723                 :            :                 display_loginmsg();
    1724                 :            :                 exit(254);
    1725                 :            :         }
    1726                 :            : #endif
    1727                 :            : 
    1728                 :            :         /*
    1729                 :            :          * Get the shell from the password data.  An empty shell field is
    1730                 :            :          * legal, and means /bin/sh.
    1731                 :            :          */
    1732         [ +  - ]:        822 :         shell = (pw->pw_shell[0] == '\0') ? _PATH_BSHELL : pw->pw_shell;
    1733                 :            : 
    1734                 :            :         /*
    1735                 :            :          * Make sure $SHELL points to the shell from the password file,
    1736                 :            :          * even if shell is overridden from login.conf
    1737                 :            :          */
    1738                 :        822 :         env = do_setup_env(s, shell);
    1739                 :            : 
    1740                 :            : #ifdef HAVE_LOGIN_CAP
    1741                 :            :         shell = login_getcapstr(lc, "shell", (char *)shell, (char *)shell);
    1742                 :            : #endif
    1743                 :            : 
    1744                 :            :         /* we have to stash the hostname before we close our socket. */
    1745         [ -  + ]:        822 :         if (options.use_login)
    1746                 :          0 :                 hostname = get_remote_name_or_ip(utmp_len,
    1747                 :            :                     options.use_dns);
    1748                 :            :         /*
    1749                 :            :          * Close the connection descriptors; note that this is the child, and
    1750                 :            :          * the server will still have the socket open, and it is important
    1751                 :            :          * that we do not shutdown it.  Note that the descriptors cannot be
    1752                 :            :          * closed before building the environment, as we call
    1753                 :            :          * get_remote_ipaddr there.
    1754                 :            :          */
    1755                 :        822 :         child_close_fds();
    1756                 :            : 
    1757                 :            :         /*
    1758                 :            :          * Must take new environment into use so that .ssh/rc,
    1759                 :            :          * /etc/ssh/sshrc and xauth are run in the proper environment.
    1760                 :            :          */
    1761                 :        822 :         environ = env;
    1762                 :            : 
    1763                 :            : #if defined(KRB5) && defined(USE_AFS)
    1764                 :            :         /*
    1765                 :            :          * At this point, we check to see if AFS is active and if we have
    1766                 :            :          * a valid Kerberos 5 TGT. If so, it seems like a good idea to see
    1767                 :            :          * if we can (and need to) extend the ticket into an AFS token. If
    1768                 :            :          * we don't do this, we run into potential problems if the user's
    1769                 :            :          * home directory is in AFS and it's not world-readable.
    1770                 :            :          */
    1771                 :            : 
    1772                 :            :         if (options.kerberos_get_afs_token && k_hasafs() &&
    1773                 :            :             (s->authctxt->krb5_ctx != NULL)) {
    1774                 :            :                 char cell[64];
    1775                 :            : 
    1776                 :            :                 debug("Getting AFS token");
    1777                 :            : 
    1778                 :            :                 k_setpag();
    1779                 :            : 
    1780                 :            :                 if (k_afs_cell_of_file(pw->pw_dir, cell, sizeof(cell)) == 0)
    1781                 :            :                         krb5_afslog(s->authctxt->krb5_ctx,
    1782                 :            :                             s->authctxt->krb5_fwd_ccache, cell, NULL);
    1783                 :            : 
    1784                 :            :                 krb5_afslog_home(s->authctxt->krb5_ctx,
    1785                 :            :                     s->authctxt->krb5_fwd_ccache, NULL, NULL, pw->pw_dir);
    1786                 :            :         }
    1787                 :            : #endif
    1788                 :            : 
    1789                 :            :         /* Change current directory to the user's home directory. */
    1790         [ -  + ]:        822 :         if (chdir(pw->pw_dir) < 0) {
    1791                 :            :                 /* Suppress missing homedir warning for chroot case */
    1792                 :            : #ifdef HAVE_LOGIN_CAP
    1793                 :            :                 r = login_getcapbool(lc, "requirehome", 0);
    1794                 :            : #endif
    1795 [ #  # ][ #  # ]:          0 :                 if (r || options.chroot_directory == NULL ||
    1796                 :          0 :                     strcasecmp(options.chroot_directory, "none") == 0)
    1797                 :          0 :                         fprintf(stderr, "Could not chdir to home "
    1798                 :            :                             "directory %s: %s\n", pw->pw_dir,
    1799                 :          0 :                             strerror(errno));
    1800                 :            :                 if (r)
    1801                 :            :                         exit(1);
    1802                 :            :         }
    1803                 :            : 
    1804                 :        822 :         closefrom(STDERR_FILENO + 1);
    1805                 :            : 
    1806         [ +  - ]:        822 :         if (!options.use_login)
    1807                 :        822 :                 do_rc_files(s, shell);
    1808                 :            : 
    1809                 :            :         /* restore SIGPIPE for child */
    1810                 :        822 :         signal(SIGPIPE, SIG_DFL);
    1811                 :            : 
    1812         [ -  + ]:        822 :         if (s->is_subsystem == SUBSYSTEM_INT_SFTP_ERROR) {
    1813                 :            :                 printf("This service allows sftp connections only.\n");
    1814                 :          0 :                 fflush(NULL);
    1815                 :          0 :                 exit(1);
    1816         [ -  + ]:        822 :         } else if (s->is_subsystem == SUBSYSTEM_INT_SFTP) {
    1817                 :            :                 extern int optind, optreset;
    1818                 :            :                 int i;
    1819                 :            :                 char *p, *args;
    1820                 :            : 
    1821                 :          0 :                 setproctitle("%s@%s", s->pw->pw_name, INTERNAL_SFTP_NAME);
    1822         [ #  # ]:          0 :                 args = xstrdup(command ? command : "sftp-server");
    1823         [ #  # ]:          0 :                 for (i = 0, (p = strtok(args, " ")); p; (p = strtok(NULL, " ")))
    1824         [ #  # ]:          0 :                         if (i < ARGV_MAX - 1)
    1825                 :          0 :                                 argv[i++] = p;
    1826                 :          0 :                 argv[i] = NULL;
    1827                 :          0 :                 optind = optreset = 1;
    1828                 :          0 :                 __progname = argv[0];
    1829                 :            : #ifdef WITH_SELINUX
    1830                 :            :                 ssh_selinux_change_context("sftpd_t");
    1831                 :            : #endif
    1832                 :          0 :                 exit(sftp_server_main(i, argv, s->pw));
    1833                 :            :         }
    1834                 :            : 
    1835                 :        822 :         fflush(NULL);
    1836                 :            : 
    1837         [ -  + ]:        822 :         if (options.use_login) {
    1838                 :          0 :                 launch_login(pw, hostname);
    1839                 :            :                 /* NEVERREACHED */
    1840                 :            :         }
    1841                 :            : 
    1842                 :            :         /* Get the last component of the shell name. */
    1843         [ +  - ]:        822 :         if ((shell0 = strrchr(shell, '/')) != NULL)
    1844                 :        822 :                 shell0++;
    1845                 :            :         else
    1846                 :            :                 shell0 = shell;
    1847                 :            : 
    1848                 :            :         /*
    1849                 :            :          * If we have no command, execute the shell.  In this case, the shell
    1850                 :            :          * name to be passed in argv[0] is preceded by '-' to indicate that
    1851                 :            :          * this is a login shell.
    1852                 :            :          */
    1853         [ -  + ]:        822 :         if (!command) {
    1854                 :            :                 char argv0[256];
    1855                 :            : 
    1856                 :            :                 /* Start the shell.  Set initial character to '-'. */
    1857                 :          0 :                 argv0[0] = '-';
    1858                 :            : 
    1859         [ #  # ]:          0 :                 if (strlcpy(argv0 + 1, shell0, sizeof(argv0) - 1)
    1860                 :            :                     >= sizeof(argv0) - 1) {
    1861                 :          0 :                         errno = EINVAL;
    1862                 :          0 :                         perror(shell);
    1863                 :          0 :                         exit(1);
    1864                 :            :                 }
    1865                 :            : 
    1866                 :            :                 /* Execute the shell. */
    1867                 :          0 :                 argv[0] = argv0;
    1868                 :          0 :                 argv[1] = NULL;
    1869                 :          0 :                 execve(shell, argv, env);
    1870                 :            : 
    1871                 :            :                 /* Executing the shell failed. */
    1872                 :          0 :                 perror(shell);
    1873                 :          0 :                 exit(1);
    1874                 :            :         }
    1875                 :            :         /*
    1876                 :            :          * Execute the command using the user's shell.  This uses the -c
    1877                 :            :          * option to execute the command.
    1878                 :            :          */
    1879                 :        822 :         argv[0] = (char *) shell0;
    1880                 :        822 :         argv[1] = "-c";
    1881                 :        822 :         argv[2] = (char *) command;
    1882                 :        822 :         argv[3] = NULL;
    1883                 :        822 :         execve(shell, argv, env);
    1884                 :        822 :         perror(shell);
    1885                 :          0 :         exit(1);
    1886                 :            : }
    1887                 :            : 
    1888                 :            : void
    1889                 :        848 : session_unused(int id)
    1890                 :            : {
    1891                 :        848 :         debug3("%s: session id %d unused", __func__, id);
    1892 [ +  - ][ -  + ]:        848 :         if (id >= options.max_sessions ||
    1893                 :        848 :             id >= sessions_nalloc) {
    1894                 :          0 :                 fatal("%s: insane session id %d (max %d nalloc %d)",
    1895                 :            :                     __func__, id, options.max_sessions, sessions_nalloc);
    1896                 :            :         }
    1897                 :        848 :         memset(&sessions[id], 0, sizeof(*sessions));
    1898                 :        848 :         sessions[id].self = id;
    1899                 :        848 :         sessions[id].used = 0;
    1900                 :        848 :         sessions[id].chanid = -1;
    1901                 :        848 :         sessions[id].ptyfd = -1;
    1902                 :        848 :         sessions[id].ttyfd = -1;
    1903                 :        848 :         sessions[id].ptymaster = -1;
    1904                 :        848 :         sessions[id].x11_chanids = NULL;
    1905                 :        848 :         sessions[id].next_unused = sessions_first_unused;
    1906                 :        848 :         sessions_first_unused = id;
    1907                 :        848 : }
    1908                 :            : 
    1909                 :            : Session *
    1910                 :        823 : session_new(void)
    1911                 :            : {
    1912                 :            :         Session *s, *tmp;
    1913                 :            : 
    1914         [ +  + ]:        823 :         if (sessions_first_unused == -1) {
    1915         [ +  - ]:        809 :                 if (sessions_nalloc >= options.max_sessions)
    1916                 :            :                         return NULL;
    1917                 :        809 :                 debug2("%s: allocate (allocated %d max %d)",
    1918                 :            :                     __func__, sessions_nalloc, options.max_sessions);
    1919                 :        809 :                 tmp = xrealloc(sessions, sessions_nalloc + 1,
    1920                 :            :                     sizeof(*sessions));
    1921         [ -  + ]:        809 :                 if (tmp == NULL) {
    1922                 :          0 :                         error("%s: cannot allocate %d sessions",
    1923                 :            :                             __func__, sessions_nalloc + 1);
    1924                 :          0 :                         return NULL;
    1925                 :            :                 }
    1926                 :        809 :                 sessions = tmp;
    1927                 :        809 :                 session_unused(sessions_nalloc++);
    1928                 :            :         }
    1929                 :            : 
    1930 [ +  - ][ -  + ]:        823 :         if (sessions_first_unused >= sessions_nalloc ||
    1931                 :            :             sessions_first_unused < 0) {
    1932                 :          0 :                 fatal("%s: insane first_unused %d max %d nalloc %d",
    1933                 :            :                     __func__, sessions_first_unused, options.max_sessions,
    1934                 :            :                     sessions_nalloc);
    1935                 :            :         }
    1936                 :            : 
    1937                 :        823 :         s = &sessions[sessions_first_unused];
    1938         [ -  + ]:        823 :         if (s->used) {
    1939                 :          0 :                 fatal("%s: session %d already used",
    1940                 :            :                     __func__, sessions_first_unused);
    1941                 :            :         }
    1942                 :        823 :         sessions_first_unused = s->next_unused;
    1943                 :        823 :         s->used = 1;
    1944                 :        823 :         s->next_unused = -1;
    1945                 :        823 :         debug("session_new: session %d", s->self);
    1946                 :            : 
    1947                 :        823 :         return s;
    1948                 :            : }
    1949                 :            : 
    1950                 :            : static void
    1951                 :          0 : session_dump(void)
    1952                 :            : {
    1953                 :            :         int i;
    1954         [ #  # ]:          0 :         for (i = 0; i < sessions_nalloc; i++) {
    1955                 :          0 :                 Session *s = &sessions[i];
    1956                 :            : 
    1957                 :          0 :                 debug("dump: used %d next_unused %d session %d %p "
    1958                 :            :                     "channel %d pid %ld",
    1959                 :            :                     s->used,
    1960                 :            :                     s->next_unused,
    1961                 :            :                     s->self,
    1962                 :            :                     s,
    1963                 :            :                     s->chanid,
    1964                 :          0 :                     (long)s->pid);
    1965                 :            :         }
    1966                 :          0 : }
    1967                 :            : 
    1968                 :            : int
    1969                 :        729 : session_open(Authctxt *authctxt, int chanid)
    1970                 :            : {
    1971                 :        729 :         Session *s = session_new();
    1972                 :        729 :         debug("session_open: channel %d", chanid);
    1973         [ -  + ]:        729 :         if (s == NULL) {
    1974                 :          0 :                 error("no more sessions");
    1975                 :          0 :                 return 0;
    1976                 :            :         }
    1977                 :        729 :         s->authctxt = authctxt;
    1978                 :        729 :         s->pw = authctxt->pw;
    1979 [ +  - ][ -  + ]:        729 :         if (s->pw == NULL || !authctxt->valid)
    1980                 :          0 :                 fatal("no user for session %d", s->self);
    1981                 :        729 :         debug("session_open: session %d: link with channel %d", s->self, chanid);
    1982                 :        729 :         s->chanid = chanid;
    1983                 :        729 :         return 1;
    1984                 :            : }
    1985                 :            : 
    1986                 :            : Session *
    1987                 :          0 : session_by_tty(char *tty)
    1988                 :            : {
    1989                 :            :         int i;
    1990         [ #  # ]:          0 :         for (i = 0; i < sessions_nalloc; i++) {
    1991                 :          0 :                 Session *s = &sessions[i];
    1992 [ #  # ][ #  # ]:          0 :                 if (s->used && s->ttyfd != -1 && strcmp(s->tty, tty) == 0) {
                 [ #  # ]
    1993                 :          0 :                         debug("session_by_tty: session %d tty %s", i, tty);
    1994                 :          0 :                         return s;
    1995                 :            :                 }
    1996                 :            :         }
    1997                 :          0 :         debug("session_by_tty: unknown tty %.100s", tty);
    1998                 :          0 :         session_dump();
    1999                 :          0 :         return NULL;
    2000                 :            : }
    2001                 :            : 
    2002                 :            : static Session *
    2003                 :        808 : session_by_channel(int id)
    2004                 :            : {
    2005                 :            :         int i;
    2006         [ +  - ]:        808 :         for (i = 0; i < sessions_nalloc; i++) {
    2007                 :        808 :                 Session *s = &sessions[i];
    2008 [ +  - ][ +  - ]:        808 :                 if (s->used && s->chanid == id) {
    2009                 :        808 :                         debug("session_by_channel: session %d channel %d",
    2010                 :            :                             i, id);
    2011                 :        808 :                         return s;
    2012                 :            :                 }
    2013                 :            :         }
    2014                 :          0 :         debug("session_by_channel: unknown channel %d", id);
    2015                 :          0 :         session_dump();
    2016                 :          0 :         return NULL;
    2017                 :            : }
    2018                 :            : 
    2019                 :            : static Session *
    2020                 :          0 : session_by_x11_channel(int id)
    2021                 :            : {
    2022                 :            :         int i, j;
    2023                 :            : 
    2024         [ #  # ]:          0 :         for (i = 0; i < sessions_nalloc; i++) {
    2025                 :          0 :                 Session *s = &sessions[i];
    2026                 :            : 
    2027 [ #  # ][ #  # ]:          0 :                 if (s->x11_chanids == NULL || !s->used)
    2028                 :          0 :                         continue;
    2029         [ #  # ]:          0 :                 for (j = 0; s->x11_chanids[j] != -1; j++) {
    2030         [ #  # ]:          0 :                         if (s->x11_chanids[j] == id) {
    2031                 :          0 :                                 debug("session_by_x11_channel: session %d "
    2032                 :            :                                     "channel %d", s->self, id);
    2033                 :          0 :                                 return s;
    2034                 :            :                         }
    2035                 :            :                 }
    2036                 :            :         }
    2037                 :          0 :         debug("session_by_x11_channel: unknown channel %d", id);
    2038                 :          0 :         session_dump();
    2039                 :          0 :         return NULL;
    2040                 :            : }
    2041                 :            : 
    2042                 :            : static Session *
    2043                 :         15 : session_by_pid(pid_t pid)
    2044                 :            : {
    2045                 :            :         int i;
    2046                 :         15 :         debug("session_by_pid: pid %ld", (long)pid);
    2047         [ +  - ]:         15 :         for (i = 0; i < sessions_nalloc; i++) {
    2048                 :         15 :                 Session *s = &sessions[i];
    2049 [ +  - ][ -  + ]:         15 :                 if (s->used && s->pid == pid)
    2050                 :            :                         return s;
    2051                 :            :         }
    2052                 :          0 :         error("session_by_pid: unknown pid %ld", (long)pid);
    2053                 :          0 :         session_dump();
    2054                 :          0 :         return NULL;
    2055                 :            : }
    2056                 :            : 
    2057                 :            : static int
    2058                 :          0 : session_window_change_req(Session *s)
    2059                 :            : {
    2060                 :          0 :         s->col = packet_get_int();
    2061                 :          0 :         s->row = packet_get_int();
    2062                 :          0 :         s->xpixel = packet_get_int();
    2063                 :          0 :         s->ypixel = packet_get_int();
    2064         [ #  # ]:          0 :         packet_check_eom();
    2065                 :          0 :         pty_change_window_size(s->ptyfd, s->row, s->col, s->xpixel, s->ypixel);
    2066                 :          0 :         return 1;
    2067                 :            : }
    2068                 :            : 
    2069                 :            : static int
    2070                 :          0 : session_pty_req(Session *s)
    2071                 :            : {
    2072                 :            :         u_int len;
    2073                 :            :         int n_bytes;
    2074                 :            : 
    2075 [ #  # ][ #  # ]:          0 :         if (no_pty_flag || !options.permit_tty) {
    2076                 :          0 :                 debug("Allocating a pty not permitted for this authentication.");
    2077                 :          0 :                 return 0;
    2078                 :            :         }
    2079         [ #  # ]:          0 :         if (s->ttyfd != -1) {
    2080                 :          0 :                 packet_disconnect("Protocol error: you already have a pty.");
    2081                 :            :                 return 0;
    2082                 :            :         }
    2083                 :            : 
    2084                 :          0 :         s->term = packet_get_string(&len);
    2085                 :            : 
    2086         [ #  # ]:          0 :         if (compat20) {
    2087                 :          0 :                 s->col = packet_get_int();
    2088                 :          0 :                 s->row = packet_get_int();
    2089                 :            :         } else {
    2090                 :          0 :                 s->row = packet_get_int();
    2091                 :          0 :                 s->col = packet_get_int();
    2092                 :            :         }
    2093                 :          0 :         s->xpixel = packet_get_int();
    2094                 :          0 :         s->ypixel = packet_get_int();
    2095                 :            : 
    2096         [ #  # ]:          0 :         if (strcmp(s->term, "") == 0) {
    2097                 :          0 :                 free(s->term);
    2098                 :          0 :                 s->term = NULL;
    2099                 :            :         }
    2100                 :            : 
    2101                 :            :         /* Allocate a pty and open it. */
    2102                 :          0 :         debug("Allocating pty.");
    2103 [ #  # ][ #  # ]:          0 :         if (!PRIVSEP(pty_allocate(&s->ptyfd, &s->ttyfd, s->tty,
    2104                 :            :             sizeof(s->tty)))) {
    2105                 :          0 :                 free(s->term);
    2106                 :          0 :                 s->term = NULL;
    2107                 :          0 :                 s->ptyfd = -1;
    2108                 :          0 :                 s->ttyfd = -1;
    2109                 :          0 :                 error("session_pty_req: session %d alloc failed", s->self);
    2110                 :          0 :                 return 0;
    2111                 :            :         }
    2112                 :          0 :         debug("session_pty_req: session %d alloc %s", s->self, s->tty);
    2113                 :            : 
    2114                 :            :         /* for SSH1 the tty modes length is not given */
    2115         [ #  # ]:          0 :         if (!compat20)
    2116                 :          0 :                 n_bytes = packet_remaining();
    2117                 :          0 :         tty_parse_modes(s->ttyfd, &n_bytes);
    2118                 :            : 
    2119         [ #  # ]:          0 :         if (!use_privsep)
    2120                 :          0 :                 pty_setowner(s->pw, s->tty);
    2121                 :            : 
    2122                 :            :         /* Set window size from the packet. */
    2123                 :          0 :         pty_change_window_size(s->ptyfd, s->row, s->col, s->xpixel, s->ypixel);
    2124                 :            : 
    2125         [ #  # ]:          0 :         packet_check_eom();
    2126                 :          0 :         session_proctitle(s);
    2127                 :          0 :         return 1;
    2128                 :            : }
    2129                 :            : 
    2130                 :            : static int
    2131                 :          1 : session_subsystem_req(Session *s)
    2132                 :            : {
    2133                 :            :         struct stat st;
    2134                 :            :         u_int len;
    2135                 :          1 :         int success = 0;
    2136                 :            :         char *prog, *cmd;
    2137                 :            :         u_int i;
    2138                 :            : 
    2139                 :          1 :         s->subsys = packet_get_string(&len);
    2140         [ -  + ]:          1 :         packet_check_eom();
    2141                 :          1 :         debug2("subsystem request for %.100s by user %s", s->subsys,
    2142                 :          1 :             s->pw->pw_name);
    2143                 :            : 
    2144         [ +  - ]:          1 :         for (i = 0; i < options.num_subsystems; i++) {
    2145         [ +  - ]:          1 :                 if (strcmp(s->subsys, options.subsystem_name[i]) == 0) {
    2146                 :          1 :                         prog = options.subsystem_command[i];
    2147                 :          1 :                         cmd = options.subsystem_args[i];
    2148         [ -  + ]:          1 :                         if (strcmp(INTERNAL_SFTP_NAME, prog) == 0) {
    2149                 :          0 :                                 s->is_subsystem = SUBSYSTEM_INT_SFTP;
    2150                 :          0 :                                 debug("subsystem: %s", prog);
    2151                 :            :                         } else {
    2152         [ -  + ]:          1 :                                 if (stat(prog, &st) < 0)
    2153                 :          0 :                                         debug("subsystem: cannot stat %s: %s",
    2154                 :          0 :                                             prog, strerror(errno));
    2155                 :          1 :                                 s->is_subsystem = SUBSYSTEM_EXT;
    2156                 :          1 :                                 debug("subsystem: exec() %s", cmd);
    2157                 :            :                         }
    2158                 :          1 :                         success = do_exec(s, cmd) == 0;
    2159                 :          1 :                         break;
    2160                 :            :                 }
    2161                 :            :         }
    2162                 :            : 
    2163         [ -  + ]:          1 :         if (!success)
    2164                 :          0 :                 logit("subsystem request for %.100s by user %s failed, "
    2165                 :          0 :                     "subsystem not found", s->subsys, s->pw->pw_name);
    2166                 :            : 
    2167                 :          1 :         return success;
    2168                 :            : }
    2169                 :            : 
    2170                 :            : static int
    2171                 :          0 : session_x11_req(Session *s)
    2172                 :            : {
    2173                 :            :         int success;
    2174                 :            : 
    2175 [ #  # ][ #  # ]:          0 :         if (s->auth_proto != NULL || s->auth_data != NULL) {
    2176                 :          0 :                 error("session_x11_req: session %d: "
    2177                 :            :                     "x11 forwarding already active", s->self);
    2178                 :          0 :                 return 0;
    2179                 :            :         }
    2180                 :          0 :         s->single_connection = packet_get_char();
    2181                 :          0 :         s->auth_proto = packet_get_string(NULL);
    2182                 :          0 :         s->auth_data = packet_get_string(NULL);
    2183                 :          0 :         s->screen = packet_get_int();
    2184         [ #  # ]:          0 :         packet_check_eom();
    2185                 :            : 
    2186                 :          0 :         success = session_setup_x11fwd(s);
    2187         [ #  # ]:          0 :         if (!success) {
    2188                 :          0 :                 free(s->auth_proto);
    2189                 :          0 :                 free(s->auth_data);
    2190                 :          0 :                 s->auth_proto = NULL;
    2191                 :          0 :                 s->auth_data = NULL;
    2192                 :            :         }
    2193                 :          0 :         return success;
    2194                 :            : }
    2195                 :            : 
    2196                 :            : static int
    2197                 :          0 : session_shell_req(Session *s)
    2198                 :            : {
    2199         [ #  # ]:          0 :         packet_check_eom();
    2200                 :          0 :         return do_exec(s, NULL) == 0;
    2201                 :            : }
    2202                 :            : 
    2203                 :            : static int
    2204                 :        727 : session_exec_req(Session *s)
    2205                 :            : {
    2206                 :            :         u_int len, success;
    2207                 :            : 
    2208                 :        727 :         char *command = packet_get_string(&len);
    2209         [ -  + ]:        727 :         packet_check_eom();
    2210                 :        727 :         success = do_exec(s, command) == 0;
    2211                 :         14 :         free(command);
    2212                 :         14 :         return success;
    2213                 :            : }
    2214                 :            : 
    2215                 :            : static int
    2216                 :          0 : session_break_req(Session *s)
    2217                 :            : {
    2218                 :            : 
    2219                 :          0 :         packet_get_int();       /* ignored */
    2220         [ #  # ]:          0 :         packet_check_eom();
    2221                 :            : 
    2222 [ #  # ][ #  # ]:          0 :         if (s->ptymaster == -1 || tcsendbreak(s->ptymaster, 0) < 0)
    2223                 :            :                 return 0;
    2224                 :            :         return 1;
    2225                 :            : }
    2226                 :            : 
    2227                 :            : static int
    2228                 :        120 : session_env_req(Session *s)
    2229                 :            : {
    2230                 :            :         char *name, *val;
    2231                 :            :         u_int name_len, val_len, i;
    2232                 :            : 
    2233                 :         60 :         name = packet_get_cstring(&name_len);
    2234                 :         60 :         val = packet_get_cstring(&val_len);
    2235         [ -  + ]:         60 :         packet_check_eom();
    2236                 :            : 
    2237                 :            :         /* Don't set too many environment variables */
    2238         [ +  - ]:         60 :         if (s->num_env > 128) {
    2239                 :          0 :                 debug2("Ignoring env request %s: too many env vars", name);
    2240                 :            :                 goto fail;
    2241                 :            :         }
    2242                 :            : 
    2243         [ +  + ]:        174 :         for (i = 0; i < options.num_accept_env; i++) {
    2244         [ +  + ]:        118 :                 if (match_pattern(name, options.accept_env[i])) {
    2245                 :          4 :                         debug2("Setting env %d: %s=%s", s->num_env, name, val);
    2246                 :          4 :                         s->env = xrealloc(s->env, s->num_env + 1,
    2247                 :            :                             sizeof(*s->env));
    2248                 :          4 :                         s->env[s->num_env].name = name;
    2249                 :          4 :                         s->env[s->num_env].val = val;
    2250                 :          4 :                         s->num_env++;
    2251                 :            :                         return (1);
    2252                 :            :                 }
    2253                 :            :         }
    2254                 :         56 :         debug2("Ignoring env request %s: disallowed name", name);
    2255                 :            : 
    2256                 :            :  fail:
    2257                 :         56 :         free(name);
    2258                 :         56 :         free(val);
    2259                 :            :         return (0);
    2260                 :            : }
    2261                 :            : 
    2262                 :            : static int
    2263                 :          4 : session_auth_agent_req(Session *s)
    2264                 :            : {
    2265                 :            :         static int called = 0;
    2266         [ -  + ]:          2 :         packet_check_eom();
    2267 [ +  - ][ -  + ]:          2 :         if (no_agent_forwarding_flag || !options.allow_agent_forwarding) {
    2268                 :          0 :                 debug("session_auth_agent_req: no_agent_forwarding_flag");
    2269                 :            :                 return 0;
    2270                 :            :         }
    2271         [ +  - ]:          2 :         if (called) {
    2272                 :            :                 return 0;
    2273                 :            :         } else {
    2274                 :          2 :                 called = 1;
    2275                 :          2 :                 return auth_input_request_forwarding(s->pw);
    2276                 :            :         }
    2277                 :            : }
    2278                 :            : 
    2279                 :            : int
    2280                 :        790 : session_input_channel_req(Channel *c, const char *rtype)
    2281                 :            : {
    2282                 :        790 :         int success = 0;
    2283                 :            :         Session *s;
    2284                 :            : 
    2285         [ -  + ]:        790 :         if ((s = session_by_channel(c->self)) == NULL) {
    2286                 :          0 :                 logit("session_input_channel_req: no session %d req %.100s",
    2287                 :            :                     c->self, rtype);
    2288                 :          0 :                 return 0;
    2289                 :            :         }
    2290                 :        790 :         debug("session_input_channel_req: session %d req %s", s->self, rtype);
    2291                 :            : 
    2292                 :            :         /*
    2293                 :            :          * a session is in LARVAL state until a shell, a command
    2294                 :            :          * or a subsystem is executed
    2295                 :            :          */
    2296         [ +  - ]:        790 :         if (c->type == SSH_CHANNEL_LARVAL) {
    2297         [ -  + ]:        790 :                 if (strcmp(rtype, "shell") == 0) {
    2298                 :          0 :                         success = session_shell_req(s);
    2299         [ +  + ]:        790 :                 } else if (strcmp(rtype, "exec") == 0) {
    2300                 :        727 :                         success = session_exec_req(s);
    2301         [ -  + ]:         63 :                 } else if (strcmp(rtype, "pty-req") == 0) {
    2302                 :          0 :                         success = session_pty_req(s);
    2303         [ -  + ]:         63 :                 } else if (strcmp(rtype, "x11-req") == 0) {
    2304                 :          0 :                         success = session_x11_req(s);
    2305         [ +  + ]:         63 :                 } else if (strcmp(rtype, "auth-agent-req@openssh.com") == 0) {
    2306                 :          2 :                         success = session_auth_agent_req(s);
    2307         [ +  + ]:         61 :                 } else if (strcmp(rtype, "subsystem") == 0) {
    2308                 :          1 :                         success = session_subsystem_req(s);
    2309 [ +  - ][ +  - ]:         60 :                 } else if (strcmp(rtype, "env") == 0) {
         [ +  - ][ +  - ]
    2310                 :         60 :                         success = session_env_req(s);
    2311                 :            :                 }
    2312                 :            :         }
    2313         [ -  + ]:         77 :         if (strcmp(rtype, "window-change") == 0) {
    2314                 :          0 :                 success = session_window_change_req(s);
    2315         [ -  + ]:         77 :         } else if (strcmp(rtype, "break") == 0) {
    2316                 :          0 :                 success = session_break_req(s);
    2317                 :            :         }
    2318                 :            : 
    2319                 :         77 :         return success;
    2320                 :            : }
    2321                 :            : 
    2322                 :            : void
    2323                 :         15 : session_set_fds(Session *s, int fdin, int fdout, int fderr, int ignore_fderr,
    2324                 :            :     int is_tty)
    2325                 :            : {
    2326         [ -  + ]:         15 :         if (!compat20)
    2327                 :          0 :                 fatal("session_set_fds: called for proto != 2.0");
    2328                 :            :         /*
    2329                 :            :          * now that have a child and a pipe to the child,
    2330                 :            :          * we can activate our channel and register the fd's
    2331                 :            :          */
    2332         [ -  + ]:         15 :         if (s->chanid == -1)
    2333                 :          0 :                 fatal("no channel for session %d", s->self);
    2334                 :         15 :         channel_set_fds(s->chanid,
    2335                 :            :             fdout, fdin, fderr,
    2336                 :            :             ignore_fderr ? CHAN_EXTENDED_IGNORE : CHAN_EXTENDED_READ,
    2337                 :            :             1, is_tty, CHAN_SES_WINDOW_DEFAULT);
    2338                 :         15 : }
    2339                 :            : 
    2340                 :            : /*
    2341                 :            :  * Function to perform pty cleanup. Also called if we get aborted abnormally
    2342                 :            :  * (e.g., due to a dropped connection).
    2343                 :            :  */
    2344                 :            : void
    2345                 :          0 : session_pty_cleanup2(Session *s)
    2346                 :            : {
    2347         [ #  # ]:          0 :         if (s == NULL) {
    2348                 :          0 :                 error("session_pty_cleanup: no session");
    2349                 :          0 :                 return;
    2350                 :            :         }
    2351         [ #  # ]:          0 :         if (s->ttyfd == -1)
    2352                 :            :                 return;
    2353                 :            : 
    2354                 :          0 :         debug("session_pty_cleanup: session %d release %s", s->self, s->tty);
    2355                 :            : 
    2356                 :            :         /* Record that the user has logged out. */
    2357         [ #  # ]:          0 :         if (s->pid != 0)
    2358                 :          0 :                 record_logout(s->pid, s->tty, s->pw->pw_name);
    2359                 :            : 
    2360                 :            :         /* Release the pseudo-tty. */
    2361         [ #  # ]:          0 :         if (getuid() == 0)
    2362                 :          0 :                 pty_release(s->tty);
    2363                 :            : 
    2364                 :            :         /*
    2365                 :            :          * Close the server side of the socket pairs.  We must do this after
    2366                 :            :          * the pty cleanup, so that another process doesn't get this pty
    2367                 :            :          * while we're still cleaning up.
    2368                 :            :          */
    2369 [ #  # ][ #  # ]:          0 :         if (s->ptymaster != -1 && close(s->ptymaster) < 0)
    2370                 :          0 :                 error("close(s->ptymaster/%d): %s",
    2371                 :          0 :                     s->ptymaster, strerror(errno));
    2372                 :            : 
    2373                 :            :         /* unlink pty from session */
    2374                 :          0 :         s->ttyfd = -1;
    2375                 :            : }
    2376                 :            : 
    2377                 :            : void
    2378                 :          0 : session_pty_cleanup(Session *s)
    2379                 :            : {
    2380         [ #  # ]:          0 :         PRIVSEP(session_pty_cleanup2(s));
    2381                 :          0 : }
    2382                 :            : 
    2383                 :            : static char *
    2384                 :          0 : sig2name(int sig)
    2385                 :            : {
    2386                 :            : #define SSH_SIG(x) if (sig == SIG ## x) return #x
    2387         [ #  # ]:          0 :         SSH_SIG(ABRT);
    2388         [ #  # ]:          0 :         SSH_SIG(ALRM);
    2389         [ #  # ]:          0 :         SSH_SIG(FPE);
    2390         [ #  # ]:          0 :         SSH_SIG(HUP);
    2391         [ #  # ]:          0 :         SSH_SIG(ILL);
    2392         [ #  # ]:          0 :         SSH_SIG(INT);
    2393         [ #  # ]:          0 :         SSH_SIG(KILL);
    2394         [ #  # ]:          0 :         SSH_SIG(PIPE);
    2395         [ #  # ]:          0 :         SSH_SIG(QUIT);
    2396         [ #  # ]:          0 :         SSH_SIG(SEGV);
    2397         [ #  # ]:          0 :         SSH_SIG(TERM);
    2398         [ #  # ]:          0 :         SSH_SIG(USR1);
    2399         [ #  # ]:          0 :         SSH_SIG(USR2);
    2400                 :            : #undef  SSH_SIG
    2401                 :          0 :         return "SIG@openssh.com";
    2402                 :            : }
    2403                 :            : 
    2404                 :            : static void
    2405                 :          0 : session_close_x11(int id)
    2406                 :            : {
    2407                 :            :         Channel *c;
    2408                 :            : 
    2409         [ #  # ]:          0 :         if ((c = channel_by_id(id)) == NULL) {
    2410                 :          0 :                 debug("session_close_x11: x11 channel %d missing", id);
    2411                 :            :         } else {
    2412                 :            :                 /* Detach X11 listener */
    2413                 :          0 :                 debug("session_close_x11: detach x11 channel %d", id);
    2414                 :          0 :                 channel_cancel_cleanup(id);
    2415         [ #  # ]:          0 :                 if (c->ostate != CHAN_OUTPUT_CLOSED)
    2416                 :          0 :                         chan_mark_dead(c);
    2417                 :            :         }
    2418                 :          0 : }
    2419                 :            : 
    2420                 :            : static void
    2421                 :          0 : session_close_single_x11(int id, void *arg)
    2422                 :            : {
    2423                 :            :         Session *s;
    2424                 :            :         u_int i;
    2425                 :            : 
    2426                 :          0 :         debug3("session_close_single_x11: channel %d", id);
    2427                 :          0 :         channel_cancel_cleanup(id);
    2428         [ #  # ]:          0 :         if ((s = session_by_x11_channel(id)) == NULL)
    2429                 :          0 :                 fatal("session_close_single_x11: no x11 channel %d", id);
    2430         [ #  # ]:          0 :         for (i = 0; s->x11_chanids[i] != -1; i++) {
    2431                 :          0 :                 debug("session_close_single_x11: session %d: "
    2432                 :            :                     "closing channel %d", s->self, s->x11_chanids[i]);
    2433                 :            :                 /*
    2434                 :            :                  * The channel "id" is already closing, but make sure we
    2435                 :            :                  * close all of its siblings.
    2436                 :            :                  */
    2437         [ #  # ]:          0 :                 if (s->x11_chanids[i] != id)
    2438                 :          0 :                         session_close_x11(s->x11_chanids[i]);
    2439                 :            :         }
    2440                 :          0 :         free(s->x11_chanids);
    2441                 :          0 :         s->x11_chanids = NULL;
    2442                 :          0 :         free(s->display);
    2443                 :          0 :         s->display = NULL;
    2444                 :          0 :         free(s->auth_proto);
    2445                 :          0 :         s->auth_proto = NULL;
    2446                 :          0 :         free(s->auth_data);
    2447                 :          0 :         s->auth_data = NULL;
    2448                 :          0 :         free(s->auth_display);
    2449                 :          0 :         s->auth_display = NULL;
    2450                 :          0 : }
    2451                 :            : 
    2452                 :            : static void
    2453                 :         15 : session_exit_message(Session *s, int status)
    2454                 :            : {
    2455                 :            :         Channel *c;
    2456                 :            : 
    2457         [ -  + ]:         15 :         if ((c = channel_lookup(s->chanid)) == NULL)
    2458                 :          0 :                 fatal("session_exit_message: session %d: no channel %d",
    2459                 :            :                     s->self, s->chanid);
    2460                 :         15 :         debug("session_exit_message: session %d channel %d pid %ld",
    2461                 :         15 :             s->self, s->chanid, (long)s->pid);
    2462                 :            : 
    2463         [ +  - ]:         15 :         if (WIFEXITED(status)) {
    2464                 :         15 :                 channel_request_start(s->chanid, "exit-status", 0);
    2465                 :         15 :                 packet_put_int(WEXITSTATUS(status));
    2466                 :         15 :                 packet_send();
    2467         [ #  # ]:          0 :         } else if (WIFSIGNALED(status)) {
    2468                 :          0 :                 channel_request_start(s->chanid, "exit-signal", 0);
    2469                 :          0 :                 packet_put_cstring(sig2name(WTERMSIG(status)));
    2470                 :            : #ifdef WCOREDUMP
    2471                 :          0 :                 packet_put_char(WCOREDUMP(status)? 1 : 0);
    2472                 :            : #else /* WCOREDUMP */
    2473                 :            :                 packet_put_char(0);
    2474                 :            : #endif /* WCOREDUMP */
    2475                 :          0 :                 packet_put_cstring("");
    2476                 :          0 :                 packet_put_cstring("");
    2477                 :          0 :                 packet_send();
    2478                 :            :         } else {
    2479                 :            :                 /* Some weird exit cause.  Just exit. */
    2480                 :          0 :                 packet_disconnect("wait returned status %04x.", status);
    2481                 :            :         }
    2482                 :            : 
    2483                 :            :         /* disconnect channel */
    2484                 :         15 :         debug("session_exit_message: release channel %d", s->chanid);
    2485                 :            : 
    2486                 :            :         /*
    2487                 :            :          * Adjust cleanup callback attachment to send close messages when
    2488                 :            :          * the channel gets EOF. The session will be then be closed
    2489                 :            :          * by session_close_by_channel when the childs close their fds.
    2490                 :            :          */
    2491                 :         15 :         channel_register_cleanup(c->self, session_close_by_channel, 1);
    2492                 :            : 
    2493                 :            :         /*
    2494                 :            :          * emulate a write failure with 'chan_write_failed', nobody will be
    2495                 :            :          * interested in data we write.
    2496                 :            :          * Note that we must not call 'chan_read_failed', since there could
    2497                 :            :          * be some more data waiting in the pipe.
    2498                 :            :          */
    2499         [ +  + ]:         15 :         if (c->ostate != CHAN_OUTPUT_CLOSED)
    2500                 :          9 :                 chan_write_failed(c);
    2501                 :         15 : }
    2502                 :            : 
    2503                 :            : void
    2504                 :         39 : session_close(Session *s)
    2505                 :            : {
    2506                 :            :         u_int i;
    2507                 :            : 
    2508                 :         39 :         debug("session_close: session %d pid %ld", s->self, (long)s->pid);
    2509         [ -  + ]:         39 :         if (s->ttyfd != -1)
    2510                 :          0 :                 session_pty_cleanup(s);
    2511                 :         39 :         free(s->term);
    2512                 :         39 :         free(s->display);
    2513                 :         39 :         free(s->x11_chanids);
    2514                 :         39 :         free(s->auth_display);
    2515                 :         39 :         free(s->auth_data);
    2516                 :         39 :         free(s->auth_proto);
    2517                 :         39 :         free(s->subsys);
    2518         [ +  + ]:         39 :         if (s->env != NULL) {
    2519         [ +  + ]:          2 :                 for (i = 0; i < s->num_env; i++) {
    2520                 :          1 :                         free(s->env[i].name);
    2521                 :          1 :                         free(s->env[i].val);
    2522                 :            :                 }
    2523                 :          1 :                 free(s->env);
    2524                 :            :         }
    2525                 :         39 :         session_proctitle(s);
    2526                 :         39 :         session_unused(s->self);
    2527                 :         39 : }
    2528                 :            : 
    2529                 :            : void
    2530                 :         15 : session_close_by_pid(pid_t pid, int status)
    2531                 :            : {
    2532                 :         15 :         Session *s = session_by_pid(pid);
    2533         [ -  + ]:         15 :         if (s == NULL) {
    2534                 :          0 :                 debug("session_close_by_pid: no session for pid %ld",
    2535                 :            :                     (long)pid);
    2536                 :          0 :                 return;
    2537                 :            :         }
    2538         [ +  - ]:         15 :         if (s->chanid != -1)
    2539                 :         15 :                 session_exit_message(s, status);
    2540         [ -  + ]:         15 :         if (s->ttyfd != -1)
    2541                 :          0 :                 session_pty_cleanup(s);
    2542                 :         15 :         s->pid = 0;
    2543                 :            : }
    2544                 :            : 
    2545                 :            : /*
    2546                 :            :  * this is called when a channel dies before
    2547                 :            :  * the session 'child' itself dies
    2548                 :            :  */
    2549                 :            : void
    2550                 :         18 : session_close_by_channel(int id, void *arg)
    2551                 :            : {
    2552                 :         18 :         Session *s = session_by_channel(id);
    2553                 :            :         u_int i;
    2554                 :            : 
    2555         [ -  + ]:         18 :         if (s == NULL) {
    2556                 :          0 :                 debug("session_close_by_channel: no session for id %d", id);
    2557                 :          0 :                 return;
    2558                 :            :         }
    2559                 :         18 :         debug("session_close_by_channel: channel %d child %ld",
    2560                 :         18 :             id, (long)s->pid);
    2561         [ +  + ]:         18 :         if (s->pid != 0) {
    2562                 :          4 :                 debug("session_close_by_channel: channel %d: has child", id);
    2563                 :            :                 /*
    2564                 :            :                  * delay detach of session, but release pty, since
    2565                 :            :                  * the fd's to the child are already closed
    2566                 :            :                  */
    2567         [ -  + ]:          4 :                 if (s->ttyfd != -1)
    2568                 :          0 :                         session_pty_cleanup(s);
    2569                 :            :                 return;
    2570                 :            :         }
    2571                 :            :         /* detach by removing callback */
    2572                 :         14 :         channel_cancel_cleanup(s->chanid);
    2573                 :            : 
    2574                 :            :         /* Close any X11 listeners associated with this session */
    2575         [ -  + ]:         14 :         if (s->x11_chanids != NULL) {
    2576         [ #  # ]:          0 :                 for (i = 0; s->x11_chanids[i] != -1; i++) {
    2577                 :          0 :                         session_close_x11(s->x11_chanids[i]);
    2578                 :          0 :                         s->x11_chanids[i] = -1;
    2579                 :            :                 }
    2580                 :            :         }
    2581                 :            : 
    2582                 :         14 :         s->chanid = -1;
    2583                 :         14 :         session_close(s);
    2584                 :            : }
    2585                 :            : 
    2586                 :            : void
    2587                 :         29 : session_destroy_all(void (*closefunc)(Session *))
    2588                 :            : {
    2589                 :            :         int i;
    2590         [ +  + ]:         32 :         for (i = 0; i < sessions_nalloc; i++) {
    2591                 :          3 :                 Session *s = &sessions[i];
    2592         [ +  + ]:          3 :                 if (s->used) {
    2593         [ -  + ]:          2 :                         if (closefunc != NULL)
    2594                 :          0 :                                 closefunc(s);
    2595                 :            :                         else
    2596                 :          2 :                                 session_close(s);
    2597                 :            :                 }
    2598                 :            :         }
    2599                 :         29 : }
    2600                 :            : 
    2601                 :            : static char *
    2602                 :        861 : session_tty_list(void)
    2603                 :            : {
    2604                 :            :         static char buf[1024];
    2605                 :            :         int i;
    2606                 :            :         char *cp;
    2607                 :            : 
    2608                 :        861 :         buf[0] = '\0';
    2609         [ +  + ]:       1722 :         for (i = 0; i < sessions_nalloc; i++) {
    2610                 :        861 :                 Session *s = &sessions[i];
    2611 [ +  - ][ -  + ]:        861 :                 if (s->used && s->ttyfd != -1) {
    2612                 :            : 
    2613         [ #  # ]:          0 :                         if (strncmp(s->tty, "/dev/", 5) != 0) {
    2614                 :          0 :                                 cp = strrchr(s->tty, '/');
    2615         [ #  # ]:          0 :                                 cp = (cp == NULL) ? s->tty : cp + 1;
    2616                 :            :                         } else
    2617                 :          0 :                                 cp = s->tty + 5;
    2618                 :            : 
    2619         [ #  # ]:          0 :                         if (buf[0] != '\0')
    2620                 :          0 :                                 strlcat(buf, ",", sizeof buf);
    2621                 :          0 :                         strlcat(buf, cp, sizeof buf);
    2622                 :            :                 }
    2623                 :            :         }
    2624         [ +  - ]:        861 :         if (buf[0] == '\0')
    2625                 :        861 :                 strlcpy(buf, "notty", sizeof buf);
    2626                 :        861 :         return buf;
    2627                 :            : }
    2628                 :            : 
    2629                 :            : void
    2630                 :        861 : session_proctitle(Session *s)
    2631                 :            : {
    2632         [ -  + ]:        861 :         if (s->pw == NULL)
    2633                 :          0 :                 error("no user for session %d", s->self);
    2634                 :            :         else
    2635                 :        861 :                 setproctitle("%s@%s", s->pw->pw_name, session_tty_list());
    2636                 :        861 : }
    2637                 :            : 
    2638                 :            : int
    2639                 :          0 : session_setup_x11fwd(Session *s)
    2640                 :            : {
    2641                 :            :         struct stat st;
    2642                 :            :         char display[512], auth_display[512];
    2643                 :            :         char hostname[MAXHOSTNAMELEN];
    2644                 :            :         u_int i;
    2645                 :            : 
    2646         [ #  # ]:          0 :         if (no_x11_forwarding_flag) {
    2647                 :          0 :                 packet_send_debug("X11 forwarding disabled in user configuration file.");
    2648                 :          0 :                 return 0;
    2649                 :            :         }
    2650         [ #  # ]:          0 :         if (!options.x11_forwarding) {
    2651                 :          0 :                 debug("X11 forwarding disabled in server configuration file.");
    2652                 :          0 :                 return 0;
    2653                 :            :         }
    2654   [ #  #  #  # ]:          0 :         if (!options.xauth_location ||
    2655                 :          0 :             (stat(options.xauth_location, &st) == -1)) {
    2656                 :          0 :                 packet_send_debug("No xauth program; cannot forward with spoofing.");
    2657                 :          0 :                 return 0;
    2658                 :            :         }
    2659         [ #  # ]:          0 :         if (options.use_login) {
    2660                 :          0 :                 packet_send_debug("X11 forwarding disabled; "
    2661                 :            :                     "not compatible with UseLogin=yes.");
    2662                 :          0 :                 return 0;
    2663                 :            :         }
    2664         [ #  # ]:          0 :         if (s->display != NULL) {
    2665                 :          0 :                 debug("X11 display already set.");
    2666                 :          0 :                 return 0;
    2667                 :            :         }
    2668         [ #  # ]:          0 :         if (x11_create_display_inet(options.x11_display_offset,
    2669                 :            :             options.x11_use_localhost, s->single_connection,
    2670                 :            :             &s->display_number, &s->x11_chanids) == -1) {
    2671                 :          0 :                 debug("x11_create_display_inet failed.");
    2672                 :          0 :                 return 0;
    2673                 :            :         }
    2674         [ #  # ]:          0 :         for (i = 0; s->x11_chanids[i] != -1; i++) {
    2675                 :          0 :                 channel_register_cleanup(s->x11_chanids[i],
    2676                 :            :                     session_close_single_x11, 0);
    2677                 :            :         }
    2678                 :            : 
    2679                 :            :         /* Set up a suitable value for the DISPLAY variable. */
    2680         [ #  # ]:          0 :         if (gethostname(hostname, sizeof(hostname)) < 0)
    2681                 :          0 :                 fatal("gethostname: %.100s", strerror(errno));
    2682                 :            :         /*
    2683                 :            :          * auth_display must be used as the displayname when the
    2684                 :            :          * authorization entry is added with xauth(1).  This will be
    2685                 :            :          * different than the DISPLAY string for localhost displays.
    2686                 :            :          */
    2687         [ #  # ]:          0 :         if (options.x11_use_localhost) {
    2688                 :          0 :                 snprintf(display, sizeof display, "localhost:%u.%u",
    2689                 :            :                     s->display_number, s->screen);
    2690                 :          0 :                 snprintf(auth_display, sizeof auth_display, "unix:%u.%u",
    2691                 :            :                     s->display_number, s->screen);
    2692                 :          0 :                 s->display = xstrdup(display);
    2693                 :          0 :                 s->auth_display = xstrdup(auth_display);
    2694                 :            :         } else {
    2695                 :            : #ifdef IPADDR_IN_DISPLAY
    2696                 :            :                 struct hostent *he;
    2697                 :            :                 struct in_addr my_addr;
    2698                 :            : 
    2699                 :            :                 he = gethostbyname(hostname);
    2700                 :            :                 if (he == NULL) {
    2701                 :            :                         error("Can't get IP address for X11 DISPLAY.");
    2702                 :            :                         packet_send_debug("Can't get IP address for X11 DISPLAY.");
    2703                 :            :                         return 0;
    2704                 :            :                 }
    2705                 :            :                 memcpy(&my_addr, he->h_addr_list[0], sizeof(struct in_addr));
    2706                 :            :                 snprintf(display, sizeof display, "%.50s:%u.%u", inet_ntoa(my_addr),
    2707                 :            :                     s->display_number, s->screen);
    2708                 :            : #else
    2709                 :          0 :                 snprintf(display, sizeof display, "%.400s:%u.%u", hostname,
    2710                 :            :                     s->display_number, s->screen);
    2711                 :            : #endif
    2712                 :          0 :                 s->display = xstrdup(display);
    2713                 :          0 :                 s->auth_display = xstrdup(display);
    2714                 :            :         }
    2715                 :            : 
    2716                 :            :         return 1;
    2717                 :            : }
    2718                 :            : 
    2719                 :            : static void
    2720                 :            : do_authenticated2(Authctxt *authctxt)
    2721                 :            : {
    2722                 :        716 :         server_loop2(authctxt);
    2723                 :            : }
    2724                 :            : 
    2725                 :            : void
    2726                 :         26 : do_cleanup(Authctxt *authctxt)
    2727                 :            : {
    2728                 :            :         static int called = 0;
    2729                 :            : 
    2730                 :         26 :         debug("do_cleanup");
    2731                 :            : 
    2732                 :            :         /* no cleanup if we're in the child for login shell */
    2733         [ +  - ]:         26 :         if (is_child)
    2734                 :            :                 return;
    2735                 :            : 
    2736                 :            :         /* avoid double cleanup */
    2737         [ +  - ]:         26 :         if (called)
    2738                 :            :                 return;
    2739                 :         26 :         called = 1;
    2740                 :            : 
    2741         [ +  - ]:         26 :         if (authctxt == NULL)
    2742                 :            :                 return;
    2743                 :            : 
    2744                 :            : #ifdef USE_PAM
    2745                 :            :         if (options.use_pam) {
    2746                 :            :                 sshpam_cleanup();
    2747                 :            :                 sshpam_thread_cleanup();
    2748                 :            :         }
    2749                 :            : #endif
    2750                 :            : 
    2751         [ +  - ]:         26 :         if (!authctxt->authenticated)
    2752                 :            :                 return;
    2753                 :            : 
    2754                 :            : #ifdef KRB5
    2755                 :            :         if (options.kerberos_ticket_cleanup &&
    2756                 :            :             authctxt->krb5_ctx)
    2757                 :            :                 krb5_cleanup_proc(authctxt);
    2758                 :            : #endif
    2759                 :            : 
    2760                 :            : #ifdef GSSAPI
    2761                 :            :         if (compat20 && options.gss_cleanup_creds)
    2762                 :            :                 ssh_gssapi_cleanup_creds();
    2763                 :            : #endif
    2764                 :            : 
    2765                 :            :         /* remove agent socket */
    2766                 :         26 :         auth_sock_cleanup_proc(authctxt->pw);
    2767                 :            : 
    2768                 :            :         /*
    2769                 :            :          * Cleanup ptys/utmp only if privsep is disabled,
    2770                 :            :          * or if running in monitor.
    2771                 :            :          */
    2772 [ +  + ][ -  + ]:         26 :         if (!use_privsep || mm_is_monitor())
    2773                 :          1 :                 session_destroy_all(session_pty_cleanup2);
    2774                 :            : }

Generated by: LCOV version 1.9