--- rxvt-unicode/src/ptytty.C 2006/01/23 12:37:59 1.60 +++ rxvt-unicode/src/ptytty.C 2006/10/03 11:21:33 1.63 @@ -34,7 +34,6 @@ #include #include -#include #include #include @@ -71,120 +70,140 @@ * fd_tty _may_ also be set to an open fd to the slave device */ #if defined(UNIX98_PTY) -static int -get_pty (int *fd_tty, char **ttydev) -{ - int pfd; + + static int + get_pty (int *fd_tty, char **ttydev) + { + int pfd; # if defined(HAVE_GETPT) - pfd = getpt(); + pfd = getpt(); # elif defined(HAVE_POSIX_OPENPT) - pfd = posix_openpt (O_RDWR); + pfd = posix_openpt (O_RDWR); # else - pfd = open (CLONE_DEVICE, O_RDWR | O_NOCTTY, 0); + pfd = open (CLONE_DEVICE, O_RDWR | O_NOCTTY, 0); # endif - if (pfd >= 0) - { - if (grantpt (pfd) == 0 /* change slave permissions */ - && unlockpt (pfd) == 0) - { /* slave now unlocked */ - *ttydev = strdup (ptsname (pfd)); /* get slave's name */ - return pfd; - } - close (pfd); - } + if (pfd >= 0) + { + if (grantpt (pfd) == 0 /* change slave permissions */ + && unlockpt (pfd) == 0) + { /* slave now unlocked */ + *ttydev = strdup (ptsname (pfd)); /* get slave's name */ + return pfd; + } + + close (pfd); + } + + return -1; + } - return -1; -} #elif defined(HAVE_OPENPTY) -static int -get_pty (int *fd_tty, char **ttydev) -{ - int pfd; - int res; - char tty_name[32]; - - res = openpty (&pfd, fd_tty, tty_name, NULL, NULL); - if (res != -1) - { - *ttydev = strdup (tty_name); - return pfd; - } - return -1; -} + static int + get_pty (int *fd_tty, char **ttydev) + { + int pfd; + int res; + char tty_name[32]; + + res = openpty (&pfd, fd_tty, tty_name, NULL, NULL); + + if (res != -1) + { + *ttydev = strdup (tty_name); + return pfd; + } + + return -1; + } + #elif defined(HAVE__GETPTY) -static int -get_pty (int *fd_tty, char **ttydev) -{ - int pfd; - *ttydev = _getpty (&pfd, O_RDWR | O_NONBLOCK | O_NOCTTY, 0622, 0); - if (*ttydev != NULL) - return pfd; + static int + get_pty (int *fd_tty, char **ttydev) + { + int pfd; - return -1; -} -#elif defined(HAVE_DEV_PTC) -static int -get_pty (int *fd_tty, char **ttydev) -{ - int pfd; + *ttydev = _getpty (&pfd, O_RDWR | O_NONBLOCK | O_NOCTTY, 0622, 0); - if ((pfd = open ("/dev/ptc", O_RDWR | O_NOCTTY, 0)) >= 0) - { - *ttydev = strdup (ttyname (pfd)); + if (*ttydev != NULL) return pfd; - } - return -1; -} + return -1; + } + +#elif defined(HAVE_DEV_PTC) + + static int + get_pty (int *fd_tty, char **ttydev) + { + int pfd; + + if ((pfd = open ("/dev/ptc", O_RDWR | O_NOCTTY, 0)) >= 0) + { + *ttydev = strdup (ttyname (pfd)); + return pfd; + } + + return -1; + } + #elif defined(HAVE_DEV_CLONE) -static int -get_pty (int *fd_tty, char **ttydev) -{ - int pfd; - if ((pfd = open ("/dev/ptym/clone", O_RDWR | O_NOCTTY, 0)) >= 0) - { - *ttydev = strdup (ptsname (pfd)); - return pfd; - } + static int + get_pty (int *fd_tty, char **ttydev) + { + int pfd; + + if ((pfd = open ("/dev/ptym/clone", O_RDWR | O_NOCTTY, 0)) >= 0) + { + *ttydev = strdup (ptsname (pfd)); + return pfd; + } + + return -1; + } - return -1; -} #else -/* Based on the code in openssh/openbsd-compat/bsd-openpty.c */ -static int -get_pty (int *fd_tty, char **ttydev) -{ - int pfd; - int i; - char pty_name[32]; - char tty_name[32]; - const char *majors = "pqrstuvwxyzabcde"; - const char *minors = "0123456789abcdef"; - for (i = 0; i < 256; i++) - { - snprintf(pty_name, 32, "/dev/pty%c%c", majors[i / 16], minors[i % 16]); - snprintf(tty_name, 32, "/dev/tty%c%c", majors[i / 16], minors[i % 16]); - if ((pfd = open (pty_name, O_RDWR | O_NOCTTY, 0)) == -1) - { - snprintf(pty_name, 32, "/dev/ptyp%d", i); - snprintf(tty_name, 32, "/dev/ttyp%d", i); - if ((pfd = open (pty_name, O_RDWR | O_NOCTTY, 0)) == -1) - continue; - } - if (access (tty_name, R_OK | W_OK) == 0) - { - *ttydev = strdup (tty_name); - return pfd; - } - close (pfd); - } -} + /* Based on the code in openssh/openbsd-compat/bsd-openpty.c */ + static int + get_pty (int *fd_tty, char **ttydev) + { + int pfd; + int i; + char pty_name[32]; + char tty_name[32]; + const char *majors = "pqrstuvwxyzabcde"; + const char *minors = "0123456789abcdef"; + + for (i = 0; i < 256; i++) + { + snprintf(pty_name, 32, "/dev/pty%c%c", majors[i / 16], minors[i % 16]); + snprintf(tty_name, 32, "/dev/tty%c%c", majors[i / 16], minors[i % 16]); + + if ((pfd = open (pty_name, O_RDWR | O_NOCTTY, 0)) == -1) + { + snprintf(pty_name, 32, "/dev/ptyp%d", i); + snprintf(tty_name, 32, "/dev/ttyp%d", i); + if ((pfd = open (pty_name, O_RDWR | O_NOCTTY, 0)) == -1) + continue; + } + + if (access (tty_name, R_OK | W_OK) == 0) + { + *ttydev = strdup (tty_name); + return pfd; + } + + close (pfd); + } + + return -1; + } + #endif /*----------------------------------------------------------------------*/ @@ -330,8 +349,11 @@ void ptytty_unix::put () { - chmod (name, RESTORE_TTY_MODE); - chown (name, 0, ttyconf.gid); + if (name) + { + chmod (name, RESTORE_TTY_MODE); + chown (name, 0, ttyconf.gid); + } close_tty (); @@ -374,343 +396,3 @@ return true; } -///////////////////////////////////////////////////////////////////////////// -// helper/proxy support - -#if PTYTTY_HELPER - -static int sock_fd = -1, lock_fd = -1; -static int helper_pid, owner_pid; - -struct command -{ - enum { get, login, destroy } type; - - ptytty *id; - - bool login_shell; - int cmd_pid; - char hostname[512]; // arbitrary, but should be plenty -}; - -struct ptytty_proxy : ptytty -{ - ptytty *id; - - ptytty_proxy () - : id(0) - { - } - - ~ptytty_proxy (); - - bool get (); - void login (int cmd_pid, bool login_shell, const char *hostname); -}; - -#if PTYTTY_REENTRANT -# define NEED_TOKEN do { char ch; read (lock_fd, &ch, 1); } while (0) -# define GIVE_TOKEN do { char ch; write (lock_fd, &ch, 1); } while (0) -#else -# define NEED_TOKEN (void)0 -# define GIVE_TOKEN (void)0 -#endif - -bool -ptytty_proxy::get () -{ - NEED_TOKEN; - - command cmd; - - cmd.type = command::get; - - write (sock_fd, &cmd, sizeof (cmd)); - - if (read (sock_fd, &id, sizeof (id)) != sizeof (id)) - ptytty_fatal ("protocol error while creating pty using helper process, aborting.\n"); - - if (!id) - { - GIVE_TOKEN; - return false; - } - - if ((pty = recv_fd (sock_fd)) < 0 - || (tty = recv_fd (sock_fd)) < 0) - ptytty_fatal ("protocol error while reading pty/tty fds from helper process, aborting.\n"); - - GIVE_TOKEN; - return true; -} - -void -ptytty_proxy::login (int cmd_pid, bool login_shell, const char *hostname) -{ - NEED_TOKEN; - - command cmd; - - cmd.type = command::login; - cmd.id = id; - cmd.cmd_pid = cmd_pid; - cmd.login_shell = login_shell; - strncpy (cmd.hostname, hostname, sizeof (cmd.hostname)); - - write (sock_fd, &cmd, sizeof (cmd)); - - GIVE_TOKEN; -} - -ptytty_proxy::~ptytty_proxy () -{ - if (id) - { - NEED_TOKEN; - - command cmd; - - cmd.type = command::destroy; - cmd.id = id; - - write (sock_fd, &cmd, sizeof (cmd)); - - GIVE_TOKEN; - } -} - -static -void serve () -{ - command cmd; - vector ptys; - - for (;;) - { - GIVE_TOKEN; - - if (read (sock_fd, &cmd, sizeof (command)) != sizeof (command)) - break; - - if (cmd.type == command::get) - { - // -> id ptyfd ttyfd - cmd.id = new ptytty_unix; - - if (cmd.id->get ()) - { - write (sock_fd, &cmd.id, sizeof (cmd.id)); - ptys.push_back (cmd.id); - - ptytty::send_fd (sock_fd, cmd.id->pty); - ptytty::send_fd (sock_fd, cmd.id->tty); - } - else - { - delete cmd.id; - cmd.id = 0; - write (sock_fd, &cmd.id, sizeof (cmd.id)); - } - } - else if (cmd.type == command::login) - { -#if UTMP_SUPPORT - if (find (ptys.begin (), ptys.end (), cmd.id) != ptys.end ()) - { - cmd.hostname[sizeof (cmd.hostname) - 1] = 0; - cmd.id->login (cmd.cmd_pid, cmd.login_shell, cmd.hostname); - } -#endif - } - else if (cmd.type == command::destroy) - { - vector::iterator pty = find (ptys.begin (), ptys.end (), cmd.id); - - if (pty != ptys.end ()) - { - delete *pty; - ptys.erase (pty); - } - } - else - break; - - NEED_TOKEN; - } - - // destroy all ptys - for (vector::iterator i = ptys.end (); i-- > ptys.begin (); ) - delete *i; -} - -void -ptytty::use_helper () -{ -#ifndef PTYTTY_NO_PID_CHECK - int pid = getpid (); -#endif - - if (sock_fd >= 0 -#ifndef PTYTTY_NO_PID_CHECK - && pid == owner_pid -#endif - ) - return; - -#ifndef PTYTTY_NO_PID_CHECK - owner_pid = pid; -#endif - - int sv[2]; - - if (socketpair (AF_UNIX, SOCK_STREAM, 0, sv)) - ptytty_fatal ("could not create socket to communicate with pty/sessiondb helper, aborting.\n"); - -#ifdef PTYTTY_REENTRANT - int lv[2]; - - if (socketpair (AF_UNIX, SOCK_STREAM, 0, lv)) - ptytty_fatal ("could not create socket to communicate with pty/sessiondb helper, aborting.\n"); -#endif - - helper_pid = fork (); - - if (helper_pid < 0) - ptytty_fatal ("could not create pty/sessiondb helper process, aborting.\n"); - - if (helper_pid) - { - // client, process - sock_fd = sv[0]; - close (sv[1]); - fcntl (sock_fd, F_SETFD, FD_CLOEXEC); -#ifdef PTYTTY_REENTRANT - lock_fd = lv[0]; - close (lv[1]); - fcntl (lock_fd, F_SETFD, FD_CLOEXEC); -#endif - } - else - { - // server, pty-helper - sock_fd = sv[1]; -#ifdef PTYTTY_REENTRANT - lock_fd = lv[1]; -#endif - - chdir ("/"); - - signal (SIGHUP, SIG_IGN); - signal (SIGTERM, SIG_IGN); - signal (SIGINT, SIG_IGN); - signal (SIGPIPE, SIG_IGN); - - for (int fd = 0; fd < 1023; fd++) - if (fd != sock_fd && fd != lock_fd) - close (fd); - - serve (); - _exit (EXIT_SUCCESS); - } -} - -#endif - -ptytty * -ptytty::create () -{ -#if PTYTTY_HELPER - if (helper_pid -# ifndef PTYTTY_NO_PID_CHECK - && getpid () == owner_pid -# endif - ) - // use helper process - return new ptytty_proxy; - else -#endif - return new ptytty_unix; -} - -void -ptytty::init () -{ - uid_t uid = getuid (); - gid_t gid = getgid (); - - // before doing anything else, check for setuid/setgid operation, - // start the helper process and drop privileges - if (uid != geteuid () - || gid != getegid ()) - { -#if PTYTTY_HELPER - use_helper (); -#else - ptytty_warn ("running setuid/setgid without pty helper compiled in, continuing unprivileged.\n"); -#endif - - drop_privileges (); - } -} - -void -ptytty::drop_privileges () -{ - uid_t uid = getuid (); - gid_t gid = getgid (); - - // drop privileges -#if HAVE_SETRESUID - setresgid (gid, gid, gid); - setresuid (uid, uid, uid); -#elif HAVE_SETREUID - setregid (gid, gid); - setreuid (uid, uid); -#elif HAVE_SETUID - setgid (gid); - setuid (uid); -#endif - - if (uid != geteuid () - || gid != getegid ()) - ptytty_fatal ("unable to drop privileges, aborting.\n"); -} - -///////////////////////////////////////////////////////////////////////////// -// C API - -#ifndef PTYTTY_NO_C_API - -typedef void *PTYTTY; - -#define DEFINE_METHOD(retval, name, args1, args2) \ -extern "C" retval ptytty_ ## name args1 \ -{ return ((struct ptytty *)ptytty)->name args2; } - -DEFINE_METHOD(int,pty,(PTYTTY ptytty),) -DEFINE_METHOD(int,tty,(PTYTTY ptytty),) -DEFINE_METHOD(int,get,(PTYTTY ptytty),()) -DEFINE_METHOD(void,login,(PTYTTY ptytty, int cmd_pid, bool login_shell, const char *hostname),(cmd_pid,login_shell,hostname)) - -DEFINE_METHOD(void,close_tty,(PTYTTY ptytty),()) -DEFINE_METHOD(int,make_controlling_tty,(PTYTTY ptytty),()) -DEFINE_METHOD(void,set_utf8_mode,(PTYTTY ptytty, int on),(on)) - -#define DEFINE_STATIC(retval, name, args) \ -extern "C" retval ptytty_ ## name args \ -{ return ptytty::name args; } - -DEFINE_STATIC(void,drop_privileges,()) -DEFINE_STATIC(void,use_helper,()) -DEFINE_STATIC(void,init,()) - -DEFINE_STATIC(PTYTTY ,create,()) - -void ptytty_delete (PTYTTY ptytty) -{ - delete (struct ptytty *)ptytty; -} - -// send_fd, recv_fd not exposed - -#endif