Warning: That file was not part of the compilation database. It may have many parsing errors.

1/* kgrantpty - helper program for KPty. */
2
3/* This program is based on the glibc2.1 pt_chmod.
4 * It was pulled out from there since both Linux
5 * distributors and other OSes are not able to make
6 * use of the glibc for different reasons.
7 *
8 * THIS IS A ROOT SUID PROGRAM
9 *
10 * Things work as following:
11 *
12 * In konsole we open a master pty. This can be opened
13 * done by at most one process. Prior to opening the
14 * master pty, the slave pty cannot be opened. Then, in
15 * grantpty, we fork to this program. The trick is, that
16 * the parameter is passes as a file handle, which cannot
17 * be faked, so that we get a secure setuid root chmod/chown
18 * with this program.
19 *
20 * We have to chown/chmod the slave pty to prevent eavesdroping.
21 *
22 * Contributed by Zack Weinberg <zack@rabi.phys.columbia.edu>, 1998.
23 * Copyright (c) 1999 by Lars Doelle <lars.doelle@on-line.de>.
24 *
25 * This program is free software; you can redistribute it and/or modify
26 * it under the terms of the GNU General Public License as published by
27 * the Free Software Foundation; either version 2 of the License, or
28 * (at your option) any later version.
29 *
30 * This program is distributed in the hope that it will be useful,
31 * but WITHOUT ANY WARRANTY; without even the implied warranty of
32 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
33 * GNU General Public License for more details.
34 *
35 * You should have received a copy of the GNU General Public License
36 * along with this program; if not, write to the Free Software
37 * Foundation, Inc., 51 Franklin Street, Fifth Floor,
38 * Boston, MA 02110-1301, USA
39 */
40
41#include <config.h>
42#include <config-pty.h>
43
44#include <sys/types.h>
45#include <errno.h>
46#include <grp.h>
47#include <stdio.h>
48#include <stdlib.h>
49#include <string.h>
50#include <sys/stat.h>
51#include <sys/ioctl.h>
52#include <unistd.h>
53#ifdef HAVE_PTY_H
54# include <pty.h>
55#endif
56
57#include <sys/param.h>
58#if defined(__FreeBSD__)
59# define BSD_PTY_HACK
60# include <paths.h>
61# include <dirent.h>
62#endif
63
64#define TTY_GROUP "tty"
65
66int main (int argc, char *argv[])
67{
68 struct stat st;
69 struct group* p;
70 gid_t gid;
71 uid_t uid;
72 mode_t mod;
73 char* tty;
74 int fd;
75#if !defined(HAVE_PTSNAME) && defined(TIOCGPTN)
76 int ptyno;
77 char ttyb[32];
78#endif
79
80 /* check preconditions **************************************************/
81 if (argc != 3 || (strcmp(argv[1],"--grant") && strcmp(argv[1],"--revoke")))
82 {
83 printf("usage: %s (--grant|--revoke) <file descriptor>\n"
84 "%s is a helper for the KDE core libraries.\n"
85 "It is not intended to be called from the command line.\n"
86 "It needs to be installed setuid root to function.\n",
87 argv[0], argv[0]);
88 return 1; /* FAIL */
89 }
90
91 if (geteuid () != 0)
92 {
93 fprintf(stderr, "%s not installed setuid root\n", argv[0]);
94 return 1; /* FAIL */
95 }
96
97 fd = atoi(argv[2]);
98
99 /* get slave pty name from master pty file handle *********/
100#ifdef HAVE_PTSNAME
101 tty = ptsname(fd);
102 if (!tty)
103#elif defined(TIOCGPTN)
104 if (!ioctl(fd, TIOCGPTN, &ptyno)) {
105 sprintf(ttyb, "/dev/pts/%d", ptyno);
106 tty = ttyb;
107 } else
108#endif
109 {
110 /* Check that fd is a valid master pseudo terminal. */
111 char *pty = ttyname(fd);
112
113#ifdef BSD_PTY_HACK
114 if (pty == NULL)
115 {
116 /*
117 Hack to make kgrantpty work on some versions of FreeBSD (and possibly
118 other systems): ttyname(3) does not work with a file descriptor opened
119 on a /dev/pty?? device.
120
121 Instead, this code looks through all the devices in /dev for a device
122 which has the same inode as our PTY_FILENO descriptor... if found, we
123 have the name for our pty.
124 */
125
126 struct dirent *dirp;
127 DIR *dp;
128 struct stat dsb;
129
130 if (fstat(fd, &dsb) != -1) {
131 if ((dp = opendir(_PATH_DEV)) != NULL) {
132 while ((dirp = readdir(dp))) {
133 if (dirp->d_fileno != dsb.st_ino)
134 continue;
135 pty = malloc(sizeof(_PATH_DEV) + strlen(dirp->d_name));
136 if (pty) {
137 strcpy(pty, _PATH_DEV);
138 strcat(pty, dirp->d_name);
139 }
140 break;
141 }
142
143 (void) closedir(dp);
144 }
145 }
146 }
147#endif
148
149 if (pty == NULL)
150 {
151 fprintf(stderr,"%s: cannot determine pty name.\n",argv[0]);
152 return 1; /* FAIL */
153 }
154
155 /* matches /dev/pty?? */
156 if (memcmp(pty,"/dev/pty",8))
157 {
158 fprintf(stderr,"%s: determined a strange pty name '%s'.\n",argv[0],pty);
159 return 1; /* FAIL */
160 }
161
162 tty = malloc(strlen(pty) + 1);
163 strcpy(tty,"/dev/tty");
164 strcat(tty,pty+8);
165 }
166
167 /* Check that the returned slave pseudo terminal is a character device. */
168 if (stat(tty, &st) < 0 || !S_ISCHR(st.st_mode))
169 {
170 fprintf(stderr,"%s: found '%s' not to be a character device.\n",argv[0],tty);
171 return 1; /* FAIL */
172 }
173
174 /* setup parameters for the operation ***********************************/
175
176 if (!strcmp(argv[1],"--grant"))
177 {
178 uid = getuid();
179 p = getgrnam(TTY_GROUP);
180 if (!p)
181 p = getgrnam("wheel");
182 gid = p ? p->gr_gid : getgid ();
183 mod = S_IRUSR | S_IWUSR | S_IWGRP;
184 }
185 else
186 {
187 uid = 0;
188 gid = st.st_gid == getgid () ? 0 : -1;
189 mod = S_IRUSR | S_IWUSR | S_IRGRP | S_IWGRP | S_IROTH | S_IWOTH;
190 }
191
192 /* Perform the actual chown/chmod ************************************/
193
194 if (chown(tty, uid, gid) < 0)
195 {
196 fprintf(stderr,"%s: cannot chown %s: %s\n",argv[0],tty,strerror(errno));
197 return 1; /* FAIL */
198 }
199
200 if (chmod(tty, mod) < 0)
201 {
202 fprintf(stderr,"%s: cannot chmod %s: %s\n",argv[0],tty,strerror(errno));
203 return 1; /* FAIL */
204 }
205
206 return 0; /* OK */
207}
208

Warning: That file was not part of the compilation database. It may have many parsing errors.