LCOV - code coverage report
Current view: top level - openssh-6.6p1 - sshpty.c (source / functions) Hit Total Coverage
Test: lcov_coverage_final.info Lines: 0 74 0.0 %
Date: 2014-08-01 Functions: 0 5 0.0 %
Branches: 0 44 0.0 %

           Branch data     Line data    Source code
       1                 :            : /* $OpenBSD: sshpty.c,v 1.28 2007/09/11 23:49:09 stevesk Exp $ */
       2                 :            : /*
       3                 :            :  * Author: Tatu Ylonen <ylo@cs.hut.fi>
       4                 :            :  * Copyright (c) 1995 Tatu Ylonen <ylo@cs.hut.fi>, Espoo, Finland
       5                 :            :  *                    All rights reserved
       6                 :            :  * Allocating a pseudo-terminal, and making it the controlling tty.
       7                 :            :  *
       8                 :            :  * As far as I am concerned, the code I have written for this software
       9                 :            :  * can be used freely for any purpose.  Any derived versions of this
      10                 :            :  * software must be clearly marked as such, and if the derived work is
      11                 :            :  * incompatible with the protocol description in the RFC file, it must be
      12                 :            :  * called by a name other than "ssh" or "Secure Shell".
      13                 :            :  */
      14                 :            : 
      15                 :            : #include "includes.h"
      16                 :            : 
      17                 :            : #include <sys/types.h>
      18                 :            : #include <sys/ioctl.h>
      19                 :            : #include <sys/stat.h>
      20                 :            : #include <signal.h>
      21                 :            : 
      22                 :            : #include <errno.h>
      23                 :            : #include <fcntl.h>
      24                 :            : #include <grp.h>
      25                 :            : #ifdef HAVE_PATHS_H
      26                 :            : # include <paths.h>
      27                 :            : #endif
      28                 :            : #include <pwd.h>
      29                 :            : #include <stdarg.h>
      30                 :            : #include <string.h>
      31                 :            : #include <termios.h>
      32                 :            : #ifdef HAVE_UTIL_H
      33                 :            : # include <util.h>
      34                 :            : #endif
      35                 :            : #include <unistd.h>
      36                 :            : 
      37                 :            : #include "sshpty.h"
      38                 :            : #include "log.h"
      39                 :            : #include "misc.h"
      40                 :            : 
      41                 :            : #ifdef HAVE_PTY_H
      42                 :            : # include <pty.h>
      43                 :            : #endif
      44                 :            : 
      45                 :            : #ifndef O_NOCTTY
      46                 :            : #define O_NOCTTY 0
      47                 :            : #endif
      48                 :            : 
      49                 :            : #ifdef __APPLE__
      50                 :            : # include <AvailabilityMacros.h>
      51                 :            : # if (MAC_OS_X_VERSION_MAX_ALLOWED >= MAC_OS_X_VERSION_10_5)
      52                 :            : #  define __APPLE_PRIVPTY__
      53                 :            : # endif
      54                 :            : #endif
      55                 :            : 
      56                 :            : /*
      57                 :            :  * Allocates and opens a pty.  Returns 0 if no pty could be allocated, or
      58                 :            :  * nonzero if a pty was successfully allocated.  On success, open file
      59                 :            :  * descriptors for the pty and tty sides and the name of the tty side are
      60                 :            :  * returned (the buffer must be able to hold at least 64 characters).
      61                 :            :  */
      62                 :            : 
      63                 :            : int
      64                 :          0 : pty_allocate(int *ptyfd, int *ttyfd, char *namebuf, size_t namebuflen)
      65                 :            : {
      66                 :            :         /* openpty(3) exists in OSF/1 and some other os'es */
      67                 :            :         char *name;
      68                 :            :         int i;
      69                 :            : 
      70                 :          0 :         i = openpty(ptyfd, ttyfd, NULL, NULL, NULL);
      71         [ #  # ]:          0 :         if (i < 0) {
      72                 :          0 :                 error("openpty: %.100s", strerror(errno));
      73                 :          0 :                 return 0;
      74                 :            :         }
      75                 :          0 :         name = ttyname(*ttyfd);
      76         [ #  # ]:          0 :         if (!name)
      77                 :          0 :                 fatal("openpty returns device for which ttyname fails.");
      78                 :            : 
      79                 :          0 :         strlcpy(namebuf, name, namebuflen);     /* possible truncation */
      80                 :          0 :         return 1;
      81                 :            : }
      82                 :            : 
      83                 :            : /* Releases the tty.  Its ownership is returned to root, and permissions to 0666. */
      84                 :            : 
      85                 :            : void
      86                 :          0 : pty_release(const char *tty)
      87                 :            : {
      88                 :            : #ifndef __APPLE_PRIVPTY__
      89         [ #  # ]:          0 :         if (chown(tty, (uid_t) 0, (gid_t) 0) < 0)
      90                 :          0 :                 error("chown %.100s 0 0 failed: %.100s", tty, strerror(errno));
      91         [ #  # ]:          0 :         if (chmod(tty, (mode_t) 0666) < 0)
      92                 :          0 :                 error("chmod %.100s 0666 failed: %.100s", tty, strerror(errno));
      93                 :            : #endif /* __APPLE_PRIVPTY__ */
      94                 :          0 : }
      95                 :            : 
      96                 :            : /* Makes the tty the process's controlling tty and sets it to sane modes. */
      97                 :            : 
      98                 :            : void
      99                 :          0 : pty_make_controlling_tty(int *ttyfd, const char *tty)
     100                 :            : {
     101                 :            :         int fd;
     102                 :            : #ifdef USE_VHANGUP
     103                 :            :         void *old;
     104                 :            : #endif /* USE_VHANGUP */
     105                 :            : 
     106                 :            : #ifdef _UNICOS
     107                 :            :         if (setsid() < 0)
     108                 :            :                 error("setsid: %.100s", strerror(errno));
     109                 :            : 
     110                 :            :         fd = open(tty, O_RDWR|O_NOCTTY);
     111                 :            :         if (fd != -1) {
     112                 :            :                 signal(SIGHUP, SIG_IGN);
     113                 :            :                 ioctl(fd, TCVHUP, (char *)NULL);
     114                 :            :                 signal(SIGHUP, SIG_DFL);
     115                 :            :                 setpgid(0, 0);
     116                 :            :                 close(fd);
     117                 :            :         } else {
     118                 :            :                 error("Failed to disconnect from controlling tty.");
     119                 :            :         }
     120                 :            : 
     121                 :            :         debug("Setting controlling tty using TCSETCTTY.");
     122                 :            :         ioctl(*ttyfd, TCSETCTTY, NULL);
     123                 :            :         fd = open("/dev/tty", O_RDWR);
     124                 :            :         if (fd < 0)
     125                 :            :                 error("%.100s: %.100s", tty, strerror(errno));
     126                 :            :         close(*ttyfd);
     127                 :            :         *ttyfd = fd;
     128                 :            : #else /* _UNICOS */
     129                 :            : 
     130                 :            :         /* First disconnect from the old controlling tty. */
     131                 :            : #ifdef TIOCNOTTY
     132                 :          0 :         fd = open(_PATH_TTY, O_RDWR | O_NOCTTY);
     133         [ #  # ]:          0 :         if (fd >= 0) {
     134                 :          0 :                 (void) ioctl(fd, TIOCNOTTY, NULL);
     135                 :          0 :                 close(fd);
     136                 :            :         }
     137                 :            : #endif /* TIOCNOTTY */
     138         [ #  # ]:          0 :         if (setsid() < 0)
     139                 :          0 :                 error("setsid: %.100s", strerror(errno));
     140                 :            : 
     141                 :            :         /*
     142                 :            :          * Verify that we are successfully disconnected from the controlling
     143                 :            :          * tty.
     144                 :            :          */
     145                 :          0 :         fd = open(_PATH_TTY, O_RDWR | O_NOCTTY);
     146         [ #  # ]:          0 :         if (fd >= 0) {
     147                 :          0 :                 error("Failed to disconnect from controlling tty.");
     148                 :          0 :                 close(fd);
     149                 :            :         }
     150                 :            :         /* Make it our controlling tty. */
     151                 :            : #ifdef TIOCSCTTY
     152                 :          0 :         debug("Setting controlling tty using TIOCSCTTY.");
     153         [ #  # ]:          0 :         if (ioctl(*ttyfd, TIOCSCTTY, NULL) < 0)
     154                 :          0 :                 error("ioctl(TIOCSCTTY): %.100s", strerror(errno));
     155                 :            : #endif /* TIOCSCTTY */
     156                 :            : #ifdef NEED_SETPGRP
     157                 :            :         if (setpgrp(0,0) < 0)
     158                 :            :                 error("SETPGRP %s",strerror(errno));
     159                 :            : #endif /* NEED_SETPGRP */
     160                 :            : #ifdef USE_VHANGUP
     161                 :          0 :         old = signal(SIGHUP, SIG_IGN);
     162                 :          0 :         vhangup();
     163                 :          0 :         signal(SIGHUP, old);
     164                 :            : #endif /* USE_VHANGUP */
     165                 :          0 :         fd = open(tty, O_RDWR);
     166         [ #  # ]:          0 :         if (fd < 0) {
     167                 :          0 :                 error("%.100s: %.100s", tty, strerror(errno));
     168                 :            :         } else {
     169                 :            : #ifdef USE_VHANGUP
     170                 :          0 :                 close(*ttyfd);
     171                 :          0 :                 *ttyfd = fd;
     172                 :            : #else /* USE_VHANGUP */
     173                 :            :                 close(fd);
     174                 :            : #endif /* USE_VHANGUP */
     175                 :            :         }
     176                 :            :         /* Verify that we now have a controlling tty. */
     177                 :          0 :         fd = open(_PATH_TTY, O_WRONLY);
     178         [ #  # ]:          0 :         if (fd < 0)
     179                 :          0 :                 error("open /dev/tty failed - could not set controlling tty: %.100s",
     180                 :          0 :                     strerror(errno));
     181                 :            :         else
     182                 :          0 :                 close(fd);
     183                 :            : #endif /* _UNICOS */
     184                 :          0 : }
     185                 :            : 
     186                 :            : /* Changes the window size associated with the pty. */
     187                 :            : 
     188                 :            : void
     189                 :          0 : pty_change_window_size(int ptyfd, u_int row, u_int col,
     190                 :            :         u_int xpixel, u_int ypixel)
     191                 :            : {
     192                 :            :         struct winsize w;
     193                 :            : 
     194                 :            :         /* may truncate u_int -> u_short */
     195                 :          0 :         w.ws_row = row;
     196                 :          0 :         w.ws_col = col;
     197                 :          0 :         w.ws_xpixel = xpixel;
     198                 :          0 :         w.ws_ypixel = ypixel;
     199                 :          0 :         (void) ioctl(ptyfd, TIOCSWINSZ, &w);
     200                 :          0 : }
     201                 :            : 
     202                 :            : void
     203                 :          0 : pty_setowner(struct passwd *pw, const char *tty)
     204                 :            : {
     205                 :            :         struct group *grp;
     206                 :            :         gid_t gid;
     207                 :            :         mode_t mode;
     208                 :            :         struct stat st;
     209                 :            : 
     210                 :            :         /* Determine the group to make the owner of the tty. */
     211                 :          0 :         grp = getgrnam("tty");
     212         [ #  # ]:          0 :         if (grp) {
     213                 :          0 :                 gid = grp->gr_gid;
     214                 :          0 :                 mode = S_IRUSR | S_IWUSR | S_IWGRP;
     215                 :            :         } else {
     216                 :          0 :                 gid = pw->pw_gid;
     217                 :          0 :                 mode = S_IRUSR | S_IWUSR | S_IWGRP | S_IWOTH;
     218                 :            :         }
     219                 :            : 
     220                 :            :         /*
     221                 :            :          * Change owner and mode of the tty as required.
     222                 :            :          * Warn but continue if filesystem is read-only and the uids match/
     223                 :            :          * tty is owned by root.
     224                 :            :          */
     225         [ #  # ]:          0 :         if (stat(tty, &st))
     226                 :          0 :                 fatal("stat(%.100s) failed: %.100s", tty,
     227                 :          0 :                     strerror(errno));
     228                 :            : 
     229                 :            : #ifdef WITH_SELINUX
     230                 :            :         ssh_selinux_setup_pty(pw->pw_name, tty);
     231                 :            : #endif
     232                 :            : 
     233 [ #  # ][ #  # ]:          0 :         if (st.st_uid != pw->pw_uid || st.st_gid != gid) {
     234         [ #  # ]:          0 :                 if (chown(tty, pw->pw_uid, gid) < 0) {
     235 [ #  # ][ #  # ]:          0 :                         if (errno == EROFS &&
     236         [ #  # ]:          0 :                             (st.st_uid == pw->pw_uid || st.st_uid == 0))
     237                 :          0 :                                 debug("chown(%.100s, %u, %u) failed: %.100s",
     238                 :            :                                     tty, (u_int)pw->pw_uid, (u_int)gid,
     239                 :            :                                     strerror(errno));
     240                 :            :                         else
     241                 :          0 :                                 fatal("chown(%.100s, %u, %u) failed: %.100s",
     242                 :            :                                     tty, (u_int)pw->pw_uid, (u_int)gid,
     243                 :            :                                     strerror(errno));
     244                 :            :                 }
     245                 :            :         }
     246                 :            : 
     247         [ #  # ]:          0 :         if ((st.st_mode & (S_IRWXU|S_IRWXG|S_IRWXO)) != mode) {
     248         [ #  # ]:          0 :                 if (chmod(tty, mode) < 0) {
     249 [ #  # ][ #  # ]:          0 :                         if (errno == EROFS &&
     250                 :          0 :                             (st.st_mode & (S_IRGRP | S_IROTH)) == 0)
     251                 :          0 :                                 debug("chmod(%.100s, 0%o) failed: %.100s",
     252                 :            :                                     tty, (u_int)mode, strerror(errno));
     253                 :            :                         else
     254                 :          0 :                                 fatal("chmod(%.100s, 0%o) failed: %.100s",
     255                 :            :                                     tty, (u_int)mode, strerror(errno));
     256                 :            :                 }
     257                 :            :         }
     258                 :          0 : }

Generated by: LCOV version 1.9