mirror of
https://bitbucket.org/smil3y/kdelibs.git
synced 2025-02-23 18:32:49 +00:00
kpty: assume grantpt() and unlockpt() are available
Signed-off-by: Ivailo Monev <xakepa10@gmail.com>
This commit is contained in:
parent
3764d9fa40
commit
87d3f0455d
6 changed files with 5 additions and 280 deletions
|
@ -119,8 +119,6 @@ if (UNIX)
|
||||||
set(HAVE_OPENPTY 0)
|
set(HAVE_OPENPTY 0)
|
||||||
|
|
||||||
check_function_exists(revoke HAVE_REVOKE)
|
check_function_exists(revoke HAVE_REVOKE)
|
||||||
check_function_exists(grantpt HAVE_GRANTPT)
|
|
||||||
check_function_exists(unlockpt HAVE_UNLOCKPT)
|
|
||||||
endif (openpty_in_libc OR openpty_in_libutil)
|
endif (openpty_in_libc OR openpty_in_libutil)
|
||||||
|
|
||||||
check_function_exists(ptsname_r HAVE_PTSNAME_R)
|
check_function_exists(ptsname_r HAVE_PTSNAME_R)
|
||||||
|
|
|
@ -2,11 +2,9 @@
|
||||||
#cmakedefine PTM_DEVICE "${PTM_DEVICE}"
|
#cmakedefine PTM_DEVICE "${PTM_DEVICE}"
|
||||||
|
|
||||||
#cmakedefine HAVE_LIBUTIL_H 1
|
#cmakedefine HAVE_LIBUTIL_H 1
|
||||||
#cmakedefine HAVE_GRANTPT 1
|
|
||||||
#cmakedefine HAVE_OPENPTY 1
|
#cmakedefine HAVE_OPENPTY 1
|
||||||
#cmakedefine HAVE_PTSNAME_R 1
|
#cmakedefine HAVE_PTSNAME_R 1
|
||||||
#cmakedefine HAVE_REVOKE 1
|
#cmakedefine HAVE_REVOKE 1
|
||||||
#cmakedefine HAVE_UNLOCKPT 1
|
|
||||||
|
|
||||||
#cmakedefine HAVE_PTY_H 1
|
#cmakedefine HAVE_PTY_H 1
|
||||||
#cmakedefine HAVE_TERMIO_H 1
|
#cmakedefine HAVE_TERMIO_H 1
|
||||||
|
|
|
@ -42,12 +42,6 @@ install(
|
||||||
|
|
||||||
########### next target ###############
|
########### next target ###############
|
||||||
|
|
||||||
if(NOT HAVE_OPENPTY)
|
|
||||||
add_executable(kgrantpty kgrantpty.c)
|
|
||||||
target_link_libraries(kgrantpty)
|
|
||||||
install(TARGETS kgrantpty DESTINATION ${KDE4_LIBEXEC_INSTALL_DIR})
|
|
||||||
endif()
|
|
||||||
|
|
||||||
if(ENABLE_TESTING)
|
if(ENABLE_TESTING)
|
||||||
add_subdirectory(tests)
|
add_subdirectory(tests)
|
||||||
endif()
|
endif()
|
||||||
|
|
180
kpty/kgrantpty.c
180
kpty/kgrantpty.c
|
@ -1,180 +0,0 @@
|
||||||
/* kgrantpty - helper program for KPty. */
|
|
||||||
|
|
||||||
/* This program is based on the glibc2.1 pt_chmod.
|
|
||||||
* It was pulled out from there since both Linux
|
|
||||||
* distributors and other OSes are not able to make
|
|
||||||
* use of the glibc for different reasons.
|
|
||||||
*
|
|
||||||
* THIS IS A ROOT SUID PROGRAM
|
|
||||||
*
|
|
||||||
* Things work as following:
|
|
||||||
*
|
|
||||||
* In konsole we open a master pty. This can be opened
|
|
||||||
* done by at most one process. Prior to opening the
|
|
||||||
* master pty, the slave pty cannot be opened. Then, in
|
|
||||||
* grantpty, we fork to this program. The trick is, that
|
|
||||||
* the parameter is passes as a file handle, which cannot
|
|
||||||
* be faked, so that we get a secure setuid root chmod/chown
|
|
||||||
* with this program.
|
|
||||||
*
|
|
||||||
* We have to chown/chmod the slave pty to prevent eavesdroping.
|
|
||||||
*
|
|
||||||
* Contributed by Zack Weinberg <zack@rabi.phys.columbia.edu>, 1998.
|
|
||||||
* Copyright (c) 1999 by Lars Doelle <lars.doelle@on-line.de>.
|
|
||||||
*
|
|
||||||
* This program is free software; you can redistribute it and/or modify
|
|
||||||
* it under the terms of the GNU General Public License as published by
|
|
||||||
* the Free Software Foundation; either version 2 of the License, or
|
|
||||||
* (at your option) any later version.
|
|
||||||
*
|
|
||||||
* This program is distributed in the hope that it will be useful,
|
|
||||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
|
||||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
|
||||||
* GNU General Public License for more details.
|
|
||||||
*
|
|
||||||
* You should have received a copy of the GNU General Public License
|
|
||||||
* along with this program; if not, write to the Free Software
|
|
||||||
* Foundation, Inc., 51 Franklin Street, Fifth Floor,
|
|
||||||
* Boston, MA 02110-1301, USA
|
|
||||||
*/
|
|
||||||
|
|
||||||
#include <config.h>
|
|
||||||
#include <config-pty.h>
|
|
||||||
|
|
||||||
#include <sys/types.h>
|
|
||||||
#include <errno.h>
|
|
||||||
#include <grp.h>
|
|
||||||
#include <stdio.h>
|
|
||||||
#include <stdlib.h>
|
|
||||||
#include <string.h>
|
|
||||||
#include <sys/stat.h>
|
|
||||||
#include <sys/ioctl.h>
|
|
||||||
#include <sys/param.h>
|
|
||||||
#include <unistd.h>
|
|
||||||
|
|
||||||
#ifdef HAVE_PTY_H
|
|
||||||
# include <pty.h>
|
|
||||||
#endif
|
|
||||||
|
|
||||||
|
|
||||||
#define TTY_GROUP "tty"
|
|
||||||
|
|
||||||
int main (int argc, char *argv[])
|
|
||||||
{
|
|
||||||
struct stat st;
|
|
||||||
gid_t gid;
|
|
||||||
uid_t uid;
|
|
||||||
mode_t mod;
|
|
||||||
char* tty = 0;
|
|
||||||
int fd;
|
|
||||||
#if defined(HAVE_PTSNAME_R)
|
|
||||||
char ttyb[32];
|
|
||||||
#endif
|
|
||||||
|
|
||||||
/* check preconditions **************************************************/
|
|
||||||
if (argc != 3 || (strcmp(argv[1],"--grant") && strcmp(argv[1],"--revoke")))
|
|
||||||
{
|
|
||||||
printf("usage: %s (--grant|--revoke) <file descriptor>\n"
|
|
||||||
"%s is a helper for the KDE core libraries.\n"
|
|
||||||
"It is not intended to be called from the command line.\n"
|
|
||||||
"It needs to be installed setuid root to function.\n",
|
|
||||||
argv[0], argv[0]);
|
|
||||||
return 1; /* FAIL */
|
|
||||||
}
|
|
||||||
|
|
||||||
if (geteuid () != 0)
|
|
||||||
{
|
|
||||||
fprintf(stderr, "%s not installed setuid root\n", argv[0]);
|
|
||||||
return 1; /* FAIL */
|
|
||||||
}
|
|
||||||
|
|
||||||
fd = atoi(argv[2]);
|
|
||||||
|
|
||||||
/* get slave pty name from master pty file handle *********/
|
|
||||||
#if defined(HAVE_PTSNAME_R)
|
|
||||||
memset(ttyb, '\0', sizeof(ttyb) * sizeof(char));
|
|
||||||
if (ptsname_r(fd, ttyb, sizeof(ttyb)) == 0) {
|
|
||||||
tty = ttyb;
|
|
||||||
if (!tty)
|
|
||||||
#else
|
|
||||||
tty = ptsname(fd);
|
|
||||||
if (!tty)
|
|
||||||
#endif
|
|
||||||
{
|
|
||||||
/* Check that fd is a valid master pseudo terminal. */
|
|
||||||
#if defined(HAVE_TTYNAME_R)
|
|
||||||
char pty[32];
|
|
||||||
memset(pty, '\0', sizeof(pty) * sizeof(char));
|
|
||||||
if (ttyname_r(fd, pty, sizeof(pty)) != 0)
|
|
||||||
#else
|
|
||||||
char *pty = ttyname(fd);
|
|
||||||
if (pty == NULL)
|
|
||||||
#endif
|
|
||||||
{
|
|
||||||
fprintf(stderr,"%s: cannot determine pty name.\n",argv[0]);
|
|
||||||
return 1; /* FAIL */
|
|
||||||
}
|
|
||||||
|
|
||||||
/* matches /dev/pty?? */
|
|
||||||
if (memcmp(pty,"/dev/pty",8))
|
|
||||||
{
|
|
||||||
fprintf(stderr,"%s: determined a strange pty name '%s'.\n",argv[0],pty);
|
|
||||||
#if !defined(HAVE_TTYNAME_R)
|
|
||||||
free(pty);
|
|
||||||
#endif
|
|
||||||
return 1; /* FAIL */
|
|
||||||
}
|
|
||||||
|
|
||||||
tty = malloc(strlen(pty) + 1);
|
|
||||||
strcpy(tty,"/dev/tty");
|
|
||||||
strcat(tty,pty+8);
|
|
||||||
#if !defined(HAVE_TTYNAME_R)
|
|
||||||
free(pty);
|
|
||||||
#endif
|
|
||||||
}
|
|
||||||
|
|
||||||
/* Check that the returned slave pseudo terminal is a character device. */
|
|
||||||
if (stat(tty, &st) < 0 || !S_ISCHR(st.st_mode))
|
|
||||||
{
|
|
||||||
fprintf(stderr,"%s: found '%s' not to be a character device.\n",argv[0],tty);
|
|
||||||
free(tty);
|
|
||||||
return 1; /* FAIL */
|
|
||||||
}
|
|
||||||
|
|
||||||
/* setup parameters for the operation ***********************************/
|
|
||||||
|
|
||||||
if (!strcmp(argv[1],"--grant"))
|
|
||||||
{
|
|
||||||
uid = getuid();
|
|
||||||
struct group* p = getgrnam(TTY_GROUP);
|
|
||||||
if (!p)
|
|
||||||
p = getgrnam("wheel");
|
|
||||||
gid = p ? p->gr_gid : getgid ();
|
|
||||||
mod = S_IRUSR | S_IWUSR | S_IWGRP;
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
uid = 0;
|
|
||||||
gid = st.st_gid == getgid () ? 0 : -1;
|
|
||||||
mod = S_IRUSR | S_IWUSR | S_IRGRP | S_IWGRP | S_IROTH | S_IWOTH;
|
|
||||||
}
|
|
||||||
|
|
||||||
/* Perform the actual chown/chmod ************************************/
|
|
||||||
|
|
||||||
if (chown(tty, uid, gid) < 0)
|
|
||||||
{
|
|
||||||
fprintf(stderr,"%s: cannot chown %s: %s\n",argv[0],tty,strerror(errno));
|
|
||||||
free(tty);
|
|
||||||
return 1; /* FAIL */
|
|
||||||
}
|
|
||||||
|
|
||||||
if (chmod(tty, mod) < 0)
|
|
||||||
{
|
|
||||||
fprintf(stderr,"%s: cannot chmod %s: %s\n",argv[0],tty,strerror(errno));
|
|
||||||
free(tty);
|
|
||||||
return 1; /* FAIL */
|
|
||||||
}
|
|
||||||
|
|
||||||
free(tty);
|
|
||||||
return 0; /* OK */
|
|
||||||
}
|
|
|
@ -80,13 +80,8 @@ extern "C" {
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
#include <kdebug.h>
|
#include <kdebug.h>
|
||||||
#include <kstandarddirs.h> // findExe
|
|
||||||
#include <kde_file.h>
|
#include <kde_file.h>
|
||||||
|
|
||||||
#include <QtCore/qprocess.h>
|
|
||||||
|
|
||||||
#define TTY_GROUP "tty"
|
|
||||||
|
|
||||||
#ifndef PATH_MAX
|
#ifndef PATH_MAX
|
||||||
# define PATH_MAX _POSIX_PATH_MAX
|
# define PATH_MAX _POSIX_PATH_MAX
|
||||||
#endif
|
#endif
|
||||||
|
@ -108,14 +103,6 @@ KPtyPrivate::~KPtyPrivate()
|
||||||
{
|
{
|
||||||
}
|
}
|
||||||
|
|
||||||
#ifndef HAVE_OPENPTY
|
|
||||||
bool KPtyPrivate::chownpty(bool grant)
|
|
||||||
{
|
|
||||||
return !QProcess::execute(KStandardDirs::findExe("kgrantpty"),
|
|
||||||
QStringList() << (grant?"--grant":"--revoke") << QString::number(masterFd));
|
|
||||||
}
|
|
||||||
#endif
|
|
||||||
|
|
||||||
/////////////////////////////
|
/////////////////////////////
|
||||||
// public member functions //
|
// public member functions //
|
||||||
/////////////////////////////
|
/////////////////////////////
|
||||||
|
@ -176,97 +163,29 @@ bool KPty::open()
|
||||||
#ifdef HAVE_PTSNAME_R
|
#ifdef HAVE_PTSNAME_R
|
||||||
char ptsn[32];
|
char ptsn[32];
|
||||||
::memset(ptsn, '\0', sizeof(ptsn) * sizeof(char));
|
::memset(ptsn, '\0', sizeof(ptsn) * sizeof(char));
|
||||||
if (ptsname_r(d->masterFd, ptsn, sizeof(ptsn)) == 0) {
|
if (::ptsname_r(d->masterFd, ptsn, sizeof(ptsn)) == 0) {
|
||||||
d->ttyName = ptsn;
|
d->ttyName = ptsn;
|
||||||
#else // HAVE_PTSNAME_R
|
#else // HAVE_PTSNAME_R
|
||||||
char *ptsn = ptsname(d->masterFd);
|
char *ptsn = ::ptsname(d->masterFd);
|
||||||
if (ptsn) {
|
if (ptsn) {
|
||||||
d->ttyName = ptsn;
|
d->ttyName = ptsn;
|
||||||
#endif // HAVE_PTSNAME_R
|
#endif // HAVE_PTSNAME_R
|
||||||
#ifdef HAVE_GRANTPT
|
if (::grantpt(d->masterFd) == 0)
|
||||||
if (!grantpt(d->masterFd))
|
|
||||||
goto grantedpt;
|
goto grantedpt;
|
||||||
#else // HAVE_GRANTPT
|
|
||||||
goto gotpty;
|
|
||||||
#endif // HAVE_GRANTPT
|
|
||||||
}
|
}
|
||||||
::close(d->masterFd);
|
::close(d->masterFd);
|
||||||
d->masterFd = -1;
|
d->masterFd = -1;
|
||||||
}
|
}
|
||||||
|
|
||||||
// Linux device names, FIXME: Trouble on other systems?
|
|
||||||
for (const char* s3 = "pqrstuvwxyzabcde"; *s3; s3++)
|
|
||||||
{
|
|
||||||
for (const char* s4 = "0123456789abcdef"; *s4; s4++)
|
|
||||||
{
|
|
||||||
ptyName = QString().sprintf("/dev/pty%c%c", *s3, *s4).toLatin1();
|
|
||||||
d->ttyName = QString().sprintf("/dev/tty%c%c", *s3, *s4).toLatin1();
|
|
||||||
|
|
||||||
d->masterFd = KDE_open(ptyName.data(), O_RDWR);
|
|
||||||
if (d->masterFd >= 0)
|
|
||||||
{
|
|
||||||
#ifdef Q_OS_SOLARIS
|
|
||||||
/* Need to check the process group of the pty.
|
|
||||||
* If it exists, then the slave pty is in use,
|
|
||||||
* and we need to get another one.
|
|
||||||
*/
|
|
||||||
int pgrp_rtn;
|
|
||||||
if (ioctl(d->masterFd, TIOCGPGRP, &pgrp_rtn) == 0 || errno != EIO) {
|
|
||||||
::close(d->masterFd);
|
|
||||||
d->masterFd = -1;
|
|
||||||
continue;
|
|
||||||
}
|
|
||||||
#endif /// Q_OS_SOLARIS
|
|
||||||
if (!access(d->ttyName.data(),R_OK|W_OK)) // checks availability based on permission bits
|
|
||||||
{
|
|
||||||
if (!geteuid())
|
|
||||||
{
|
|
||||||
struct group* p = getgrnam(TTY_GROUP);
|
|
||||||
if (!p)
|
|
||||||
p = getgrnam("wheel");
|
|
||||||
gid_t gid = p ? p->gr_gid : getgid ();
|
|
||||||
|
|
||||||
chown(d->ttyName.data(), getuid(), gid);
|
|
||||||
chmod(d->ttyName.data(), S_IRUSR|S_IWUSR|S_IWGRP);
|
|
||||||
}
|
|
||||||
goto gotpty;
|
|
||||||
}
|
|
||||||
::close(d->masterFd);
|
|
||||||
d->masterFd = -1;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
kWarning(175) << "Can't open a pseudo teletype";
|
kWarning(175) << "Can't open a pseudo teletype";
|
||||||
return false;
|
return false;
|
||||||
|
|
||||||
gotpty:
|
|
||||||
KDE_struct_stat st;
|
|
||||||
if (KDE_stat(d->ttyName.data(), &st))
|
|
||||||
return false; // this just cannot happen ... *cough* Yeah right, I just
|
|
||||||
// had it happen when pty #349 was allocated. I guess
|
|
||||||
// there was some sort of leak? I only had a few open.
|
|
||||||
if (((st.st_uid != getuid()) ||
|
|
||||||
(st.st_mode & (S_IRGRP|S_IXGRP|S_IROTH|S_IWOTH|S_IXOTH))) &&
|
|
||||||
!d->chownpty(true))
|
|
||||||
{
|
|
||||||
kWarning(175)
|
|
||||||
<< "chownpty failed for device " << ptyName << "::" << d->ttyName
|
|
||||||
<< "\nThis means the communication can be eavesdropped." << endl;
|
|
||||||
}
|
|
||||||
|
|
||||||
grantedpt:
|
grantedpt:
|
||||||
|
|
||||||
#ifdef HAVE_REVOKE
|
#ifdef HAVE_REVOKE
|
||||||
revoke(d->ttyName.data());
|
revoke(d->ttyName.data());
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
#ifdef HAVE_UNLOCKPT
|
|
||||||
unlockpt(d->masterFd);
|
unlockpt(d->masterFd);
|
||||||
#elif defined(TIOCSPTLCK)
|
|
||||||
int flag = 0;
|
|
||||||
ioctl(d->masterFd, TIOCSPTLCK, &flag);
|
|
||||||
#endif
|
|
||||||
|
|
||||||
d->slaveFd = KDE_open(d->ttyName.data(), O_RDWR | O_NOCTTY);
|
d->slaveFd = KDE_open(d->ttyName.data(), O_RDWR | O_NOCTTY);
|
||||||
if (d->slaveFd < 0)
|
if (d->slaveFd < 0)
|
||||||
|
@ -375,15 +294,14 @@ void KPty::close()
|
||||||
#ifndef HAVE_OPENPTY
|
#ifndef HAVE_OPENPTY
|
||||||
// don't bother resetting unix98 pty, it will go away after closing master anyway.
|
// don't bother resetting unix98 pty, it will go away after closing master anyway.
|
||||||
if (memcmp(d->ttyName.data(), "/dev/pts/", 9)) {
|
if (memcmp(d->ttyName.data(), "/dev/pts/", 9)) {
|
||||||
if (!geteuid()) {
|
if (geteuid() == 0) {
|
||||||
KDE_struct_stat st;
|
KDE_struct_stat st;
|
||||||
if (!KDE_stat(d->ttyName.data(), &st)) {
|
if (KDE_stat(d->ttyName.data(), &st) == 0) {
|
||||||
chown(d->ttyName.data(), 0, st.st_gid == getgid() ? 0 : -1);
|
chown(d->ttyName.data(), 0, st.st_gid == getgid() ? 0 : -1);
|
||||||
chmod(d->ttyName.data(), S_IRUSR|S_IWUSR|S_IRGRP|S_IWGRP|S_IROTH|S_IWOTH);
|
chmod(d->ttyName.data(), S_IRUSR|S_IWUSR|S_IRGRP|S_IWGRP|S_IROTH|S_IWOTH);
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
fcntl(d->masterFd, F_SETFD, 0);
|
fcntl(d->masterFd, F_SETFD, 0);
|
||||||
d->chownpty(false);
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
#endif
|
#endif
|
||||||
|
|
|
@ -33,9 +33,6 @@ class KPtyPrivate {
|
||||||
public:
|
public:
|
||||||
KPtyPrivate(KPty* parent);
|
KPtyPrivate(KPty* parent);
|
||||||
virtual ~KPtyPrivate();
|
virtual ~KPtyPrivate();
|
||||||
#ifndef HAVE_OPENPTY
|
|
||||||
bool chownpty(bool grant);
|
|
||||||
#endif
|
|
||||||
|
|
||||||
int masterFd;
|
int masterFd;
|
||||||
int slaveFd;
|
int slaveFd;
|
||||||
|
|
Loading…
Add table
Reference in a new issue