ViewVC Help
View File | Revision Log | Show Annotations | Download File
/cvs/rxvt-unicode/src/proxy.C
Revision: 1.4
Committed: Tue Feb 7 05:32:47 2006 UTC (18 years, 3 months ago) by root
Content type: text/plain
Branch: MAIN
CVS Tags: rel-7_6, rel-7_9, rel-7_8, rel-7_7, rel-8_0, rel-8_1
Changes since 1.3: +4 -4 lines
Log Message:
*** empty log message ***

File Contents

# Content
1 // This file is part of libptytty. Do not make local modifications.
2 // http://software.schmorp.de/pkg/libptytty
3
4 /*----------------------------------------------------------------------*
5 * File: proxy.C
6 *----------------------------------------------------------------------*
7 *
8 * All portions of code are copyright by their respective author/s.
9 * Copyright (c) 2006 Marc Lehmann <pcg@goof.com>
10 *
11 * This program is free software; you can redistribute it and/or modify
12 * it under the terms of the GNU General Public License as published by
13 * the Free Software Foundation; either version 2 of the License, or
14 * (at your option) any later version.
15 *
16 * This program is distributed in the hope that it will be useful,
17 * but WITHOUT ANY WARRANTY; without even the implied warranty of
18 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
19 * GNU General Public License for more details.
20 *
21 * You should have received a copy of the GNU General Public License
22 * along with this program; if not, write to the Free Software
23 * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
24 *---------------------------------------------------------------------*/
25
26 #include "../config.h"
27
28 #include "ptytty.h"
29
30 #include <csignal>
31
32 #include <sys/types.h>
33 #include <sys/socket.h>
34 #include <unistd.h>
35 #include <fcntl.h>
36
37 // helper/proxy support
38
39 #if PTYTTY_HELPER
40
41 static int sock_fd = -1, lock_fd = -1;
42 static int helper_pid, owner_pid;
43
44 struct command
45 {
46 enum { get, login, destroy } type;
47
48 ptytty *id;
49
50 bool login_shell;
51 int cmd_pid;
52 char hostname[512]; // arbitrary, but should be plenty
53 };
54
55 struct ptytty_proxy : ptytty
56 {
57 ptytty *id;
58
59 ptytty_proxy ()
60 : id(0)
61 {
62 }
63
64 ~ptytty_proxy ();
65
66 bool get ();
67 void login (int cmd_pid, bool login_shell, const char *hostname);
68 };
69
70 #if PTYTTY_REENTRANT
71 # define NEED_TOKEN do { char ch; read (lock_fd, &ch, 1); } while (0)
72 # define GIVE_TOKEN do { char ch; write (lock_fd, &ch, 1); } while (0)
73 #else
74 # define NEED_TOKEN (void)0
75 # define GIVE_TOKEN (void)0
76 #endif
77
78 bool
79 ptytty_proxy::get ()
80 {
81 NEED_TOKEN;
82
83 command cmd;
84
85 cmd.type = command::get;
86
87 write (sock_fd, &cmd, sizeof (cmd));
88
89 if (read (sock_fd, &id, sizeof (id)) != sizeof (id))
90 ptytty_fatal ("protocol error while creating pty using helper process, aborting.\n");
91
92 if (!id)
93 {
94 GIVE_TOKEN;
95 return false;
96 }
97
98 if ((pty = recv_fd (sock_fd)) < 0
99 || (tty = recv_fd (sock_fd)) < 0)
100 ptytty_fatal ("protocol error while reading pty/tty fds from helper process, aborting.\n");
101
102 GIVE_TOKEN;
103 return true;
104 }
105
106 void
107 ptytty_proxy::login (int cmd_pid, bool login_shell, const char *hostname)
108 {
109 NEED_TOKEN;
110
111 command cmd;
112
113 cmd.type = command::login;
114 cmd.id = id;
115 cmd.cmd_pid = cmd_pid;
116 cmd.login_shell = login_shell;
117 strncpy (cmd.hostname, hostname, sizeof (cmd.hostname));
118
119 write (sock_fd, &cmd, sizeof (cmd));
120
121 GIVE_TOKEN;
122 }
123
124 ptytty_proxy::~ptytty_proxy ()
125 {
126 if (id)
127 {
128 NEED_TOKEN;
129
130 command cmd;
131
132 cmd.type = command::destroy;
133 cmd.id = id;
134
135 write (sock_fd, &cmd, sizeof (cmd));
136
137 GIVE_TOKEN;
138 }
139 }
140
141 static
142 void serve ()
143 {
144 command cmd;
145 vector<ptytty *> ptys;
146
147 for (;;)
148 {
149 GIVE_TOKEN;
150
151 if (read (sock_fd, &cmd, sizeof (command)) != sizeof (command))
152 break;
153
154 if (cmd.type == command::get)
155 {
156 // -> id ptyfd ttyfd
157 cmd.id = new ptytty_unix;
158
159 if (cmd.id->get ())
160 {
161 write (sock_fd, &cmd.id, sizeof (cmd.id));
162 ptys.push_back (cmd.id);
163
164 ptytty::send_fd (sock_fd, cmd.id->pty);
165 ptytty::send_fd (sock_fd, cmd.id->tty);
166 }
167 else
168 {
169 delete cmd.id;
170 cmd.id = 0;
171 write (sock_fd, &cmd.id, sizeof (cmd.id));
172 }
173 }
174 else if (cmd.type == command::login)
175 {
176 #if UTMP_SUPPORT
177 if (find (ptys.begin (), ptys.end (), cmd.id) != ptys.end ())
178 {
179 cmd.hostname[sizeof (cmd.hostname) - 1] = 0;
180 cmd.id->login (cmd.cmd_pid, cmd.login_shell, cmd.hostname);
181 }
182 #endif
183 }
184 else if (cmd.type == command::destroy)
185 {
186 vector<ptytty *>::iterator pty = find (ptys.begin (), ptys.end (), cmd.id);
187
188 if (pty != ptys.end ())
189 {
190 delete *pty;
191 ptys.erase (pty);
192 }
193 }
194 else
195 break;
196
197 NEED_TOKEN;
198 }
199
200 // destroy all ptys
201 for (vector<ptytty *>::iterator i = ptys.end (); i-- > ptys.begin (); )
202 delete *i;
203 }
204
205 void
206 ptytty::use_helper ()
207 {
208 #ifndef PTYTTY_NO_PID_CHECK
209 int pid = getpid ();
210 #endif
211
212 if (sock_fd >= 0
213 #ifndef PTYTTY_NO_PID_CHECK
214 && pid == owner_pid
215 #endif
216 )
217 return;
218
219 #ifndef PTYTTY_NO_PID_CHECK
220 owner_pid = pid;
221 #endif
222
223 int sv[2];
224
225 if (socketpair (AF_UNIX, SOCK_STREAM, 0, sv))
226 ptytty_fatal ("could not create socket to communicate with pty/sessiondb helper, aborting.\n");
227
228 #ifdef PTYTTY_REENTRANT
229 int lv[2];
230
231 if (socketpair (AF_UNIX, SOCK_STREAM, 0, lv))
232 ptytty_fatal ("could not create socket to communicate with pty/sessiondb helper, aborting.\n");
233 #endif
234
235 helper_pid = fork ();
236
237 if (helper_pid < 0)
238 ptytty_fatal ("could not create pty/sessiondb helper process, aborting.\n");
239
240 if (helper_pid)
241 {
242 // client, process
243 sock_fd = sv[0];
244 close (sv[1]);
245 fcntl (sock_fd, F_SETFD, FD_CLOEXEC);
246 #ifdef PTYTTY_REENTRANT
247 lock_fd = lv[0];
248 close (lv[1]);
249 fcntl (lock_fd, F_SETFD, FD_CLOEXEC);
250 #endif
251 }
252 else
253 {
254 // server, pty-helper
255 sock_fd = sv[1];
256 #ifdef PTYTTY_REENTRANT
257 lock_fd = lv[1];
258 #endif
259
260 chdir ("/");
261
262 signal (SIGHUP, SIG_IGN);
263 signal (SIGTERM, SIG_IGN);
264 signal (SIGINT, SIG_IGN);
265 signal (SIGPIPE, SIG_IGN);
266
267 for (int fd = 0; fd < 1023; fd++)
268 if (fd != sock_fd && fd != lock_fd)
269 close (fd);
270
271 serve ();
272 _exit (EXIT_SUCCESS);
273 }
274 }
275
276 #endif
277
278 ptytty *
279 ptytty::create ()
280 {
281 #if PTYTTY_HELPER
282 if (helper_pid
283 # ifndef PTYTTY_NO_PID_CHECK
284 && getpid () == owner_pid
285 # endif
286 )
287 // use helper process
288 return new ptytty_proxy;
289 else
290 #endif
291 return new ptytty_unix;
292 }
293
294 void
295 ptytty::init ()
296 {
297 uid_t uid = getuid ();
298 gid_t gid = getgid ();
299
300 // before doing anything else, check for setuid/setgid operation,
301 // start the helper process and drop privileges
302 if (uid != geteuid ()
303 || gid != getegid ())
304 {
305 #if PTYTTY_HELPER
306 use_helper ();
307 #else
308 ptytty_warn ("running setuid/setgid without pty helper compiled in, continuing unprivileged.\n", 0);
309 #endif
310
311 drop_privileges ();
312 }
313 }
314
315 void
316 ptytty::drop_privileges ()
317 {
318 uid_t uid = getuid ();
319 gid_t gid = getgid ();
320
321 // drop privileges
322 #if HAVE_SETRESUID
323 setresgid (gid, gid, gid);
324 setresuid (uid, uid, uid);
325 #elif HAVE_SETREUID
326 setregid (gid, gid);
327 setreuid (uid, uid);
328 #elif HAVE_SETUID
329 setgid (gid);
330 setuid (uid);
331 #else
332 # error no way to drop privileges, configure failed?
333 #endif
334
335 if (uid != geteuid ()
336 || gid != getegid ())
337 ptytty_fatal ("unable to drop privileges, aborting.\n");
338 }
339