ViewVC Help
View File | Revision Log | Show Annotations | Download File
/cvs/libptytty/src/proxy.C
Revision: 1.13
Committed: Tue Dec 20 13:46:05 2011 UTC (14 years, 8 months ago) by sf-exg
Content type: text/plain
Branch: MAIN
CVS Tags: rel-9_14, rel-1_5
Changes since 1.12: +6 -0 lines
Log Message:
change the semantic of PTYTTY_NO_LIBCPP from undef/def to 0/1 and move
the associated includes in proxy.C.

File Contents

# User Rev Content
1 root 1.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 sf-exg 1.9 * Copyright (c) 2006 Marc Lehmann <schmorp@schmorp.de>
10 root 1.1 *
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 sf-exg 1.8 #include "config.h"
27 root 1.1
28     #include "ptytty.h"
29    
30 sf-exg 1.13 #if !PTYTTY_NO_LIBCPP
31     #include <vector>
32     #include <algorithm>
33     using namespace std;
34     #endif
35    
36 root 1.7 #include <cstdio>
37     #include <cstring>
38 root 1.1 #include <csignal>
39    
40     #include <sys/types.h>
41     #include <sys/socket.h>
42     #include <unistd.h>
43     #include <fcntl.h>
44 root 1.4 #include <errno.h>
45 root 1.1
46     // helper/proxy support
47    
48     #if PTYTTY_HELPER
49    
50     static int sock_fd = -1, lock_fd = -1;
51     static int helper_pid, owner_pid;
52    
53     struct command
54     {
55     enum { get, login, destroy } type;
56    
57     ptytty *id;
58    
59     bool login_shell;
60     int cmd_pid;
61     char hostname[512]; // arbitrary, but should be plenty
62     };
63    
64     struct ptytty_proxy : ptytty
65     {
66     ptytty *id;
67    
68     ptytty_proxy ()
69     : id(0)
70     {
71     }
72    
73     ~ptytty_proxy ();
74    
75     bool get ();
76     void login (int cmd_pid, bool login_shell, const char *hostname);
77     };
78    
79     #if PTYTTY_REENTRANT
80 root 1.11 # define NEED_TOKEN read (lock_fd, &lock_fd, 1)
81     # define GIVE_TOKEN write (lock_fd, &lock_fd, 1)
82 root 1.1 #else
83     # define NEED_TOKEN (void)0
84     # define GIVE_TOKEN (void)0
85     #endif
86    
87     bool
88     ptytty_proxy::get ()
89     {
90     NEED_TOKEN;
91    
92     command cmd;
93    
94     cmd.type = command::get;
95    
96     write (sock_fd, &cmd, sizeof (cmd));
97    
98     if (read (sock_fd, &id, sizeof (id)) != sizeof (id))
99 sf-exg 1.10 PTYTTY_FATAL ("protocol error while creating pty using helper process, aborting.\n");
100 root 1.1
101     if (!id)
102     {
103     GIVE_TOKEN;
104     return false;
105     }
106    
107     if ((pty = recv_fd (sock_fd)) < 0
108     || (tty = recv_fd (sock_fd)) < 0)
109 sf-exg 1.10 PTYTTY_FATAL ("protocol error while reading pty/tty fds from helper process, aborting.\n");
110 root 1.1
111     GIVE_TOKEN;
112     return true;
113     }
114    
115     void
116     ptytty_proxy::login (int cmd_pid, bool login_shell, const char *hostname)
117     {
118     NEED_TOKEN;
119    
120     command cmd;
121    
122     cmd.type = command::login;
123     cmd.id = id;
124     cmd.cmd_pid = cmd_pid;
125     cmd.login_shell = login_shell;
126     strncpy (cmd.hostname, hostname, sizeof (cmd.hostname));
127    
128     write (sock_fd, &cmd, sizeof (cmd));
129    
130     GIVE_TOKEN;
131     }
132    
133     ptytty_proxy::~ptytty_proxy ()
134     {
135     if (id)
136     {
137 ayin 1.3 close_tty ();
138    
139     if (pty >= 0)
140     close (pty);
141 ayin 1.2
142 root 1.1 NEED_TOKEN;
143    
144     command cmd;
145    
146     cmd.type = command::destroy;
147     cmd.id = id;
148    
149     write (sock_fd, &cmd, sizeof (cmd));
150    
151     GIVE_TOKEN;
152     }
153     }
154    
155     static
156     void serve ()
157     {
158     command cmd;
159     vector<ptytty *> ptys;
160    
161     for (;;)
162     {
163     GIVE_TOKEN;
164    
165     if (read (sock_fd, &cmd, sizeof (command)) != sizeof (command))
166     break;
167    
168     if (cmd.type == command::get)
169     {
170     // -> id ptyfd ttyfd
171     cmd.id = new ptytty_unix;
172    
173     if (cmd.id->get ())
174     {
175     write (sock_fd, &cmd.id, sizeof (cmd.id));
176     ptys.push_back (cmd.id);
177    
178     ptytty::send_fd (sock_fd, cmd.id->pty);
179     ptytty::send_fd (sock_fd, cmd.id->tty);
180     }
181     else
182     {
183     delete cmd.id;
184     cmd.id = 0;
185     write (sock_fd, &cmd.id, sizeof (cmd.id));
186     }
187     }
188     else if (cmd.type == command::login)
189     {
190     #if UTMP_SUPPORT
191     if (find (ptys.begin (), ptys.end (), cmd.id) != ptys.end ())
192     {
193     cmd.hostname[sizeof (cmd.hostname) - 1] = 0;
194     cmd.id->login (cmd.cmd_pid, cmd.login_shell, cmd.hostname);
195     }
196     #endif
197     }
198     else if (cmd.type == command::destroy)
199     {
200     vector<ptytty *>::iterator pty = find (ptys.begin (), ptys.end (), cmd.id);
201    
202     if (pty != ptys.end ())
203     {
204     delete *pty;
205     ptys.erase (pty);
206     }
207     }
208     else
209     break;
210    
211     NEED_TOKEN;
212     }
213    
214     // destroy all ptys
215     for (vector<ptytty *>::iterator i = ptys.end (); i-- > ptys.begin (); )
216     delete *i;
217     }
218    
219     void
220     ptytty::use_helper ()
221     {
222     #ifndef PTYTTY_NO_PID_CHECK
223     int pid = getpid ();
224     #endif
225    
226     if (sock_fd >= 0
227     #ifndef PTYTTY_NO_PID_CHECK
228     && pid == owner_pid
229     #endif
230     )
231     return;
232    
233     #ifndef PTYTTY_NO_PID_CHECK
234     owner_pid = pid;
235     #endif
236    
237     int sv[2];
238    
239     if (socketpair (AF_UNIX, SOCK_STREAM, 0, sv))
240 sf-exg 1.10 PTYTTY_FATAL ("could not create socket to communicate with pty/sessiondb helper, aborting.\n");
241 root 1.1
242 sf-exg 1.12 #if PTYTTY_REENTRANT
243 root 1.1 int lv[2];
244    
245     if (socketpair (AF_UNIX, SOCK_STREAM, 0, lv))
246 sf-exg 1.10 PTYTTY_FATAL ("could not create socket to communicate with pty/sessiondb helper, aborting.\n");
247 root 1.1 #endif
248    
249     helper_pid = fork ();
250    
251     if (helper_pid < 0)
252 sf-exg 1.10 PTYTTY_FATAL ("could not create pty/sessiondb helper process, aborting.\n");
253 root 1.1
254     if (helper_pid)
255     {
256     // client, process
257     sock_fd = sv[0];
258     close (sv[1]);
259     fcntl (sock_fd, F_SETFD, FD_CLOEXEC);
260 sf-exg 1.12 #if PTYTTY_REENTRANT
261 root 1.1 lock_fd = lv[0];
262     close (lv[1]);
263     fcntl (lock_fd, F_SETFD, FD_CLOEXEC);
264     #endif
265     }
266     else
267     {
268     // server, pty-helper
269     sock_fd = sv[1];
270 sf-exg 1.12 #if PTYTTY_REENTRANT
271 root 1.1 lock_fd = lv[1];
272     #endif
273    
274     chdir ("/");
275    
276     signal (SIGHUP, SIG_IGN);
277     signal (SIGTERM, SIG_IGN);
278     signal (SIGINT, SIG_IGN);
279     signal (SIGPIPE, SIG_IGN);
280    
281     for (int fd = 0; fd < 1023; fd++)
282     if (fd != sock_fd && fd != lock_fd)
283     close (fd);
284    
285     serve ();
286     _exit (EXIT_SUCCESS);
287     }
288     }
289    
290     #endif
291    
292     ptytty *
293     ptytty::create ()
294     {
295     #if PTYTTY_HELPER
296     if (helper_pid
297     # ifndef PTYTTY_NO_PID_CHECK
298     && getpid () == owner_pid
299     # endif
300     )
301     // use helper process
302     return new ptytty_proxy;
303     else
304     #endif
305     return new ptytty_unix;
306     }
307    
308     void
309 root 1.4 ptytty::sanitise_stdfd ()
310     {
311     // sanitise stdin/stdout/stderr to point to *something*.
312     for (int fd = 0; fd <= 2; ++fd)
313     if (fcntl (fd, F_GETFL) < 0 && errno == EBADF)
314     {
315     int fd2 = open ("/dev/tty", fd ? O_WRONLY : O_RDONLY);
316    
317     if (fd2 < 0)
318 root 1.5 fd2 = open ("/dev/null", fd ? O_WRONLY : O_RDONLY);
319 root 1.4
320     if (fd2 != fd)
321 root 1.5 abort ();
322 root 1.4 }
323     }
324    
325     void
326 root 1.1 ptytty::init ()
327     {
328 root 1.4 sanitise_stdfd ();
329    
330 root 1.1 uid_t uid = getuid ();
331     gid_t gid = getgid ();
332 ayin 1.6
333 root 1.1 // before doing anything else, check for setuid/setgid operation,
334     // start the helper process and drop privileges
335     if (uid != geteuid ()
336     || gid != getegid ())
337     {
338     #if PTYTTY_HELPER
339     use_helper ();
340     #else
341 sf-exg 1.10 PTYTTY_WARN ("running setuid/setgid without pty helper compiled in, continuing unprivileged.\n", 0);
342 root 1.1 #endif
343    
344     drop_privileges ();
345     }
346     }
347    
348     void
349     ptytty::drop_privileges ()
350     {
351     uid_t uid = getuid ();
352     gid_t gid = getgid ();
353    
354     // drop privileges
355     #if HAVE_SETRESUID
356     setresgid (gid, gid, gid);
357     setresuid (uid, uid, uid);
358     #elif HAVE_SETREUID
359     setregid (gid, gid);
360     setreuid (uid, uid);
361     #elif HAVE_SETUID
362     setgid (gid);
363     setuid (uid);
364     #else
365     # error no way to drop privileges, configure failed?
366     #endif
367    
368     if (uid != geteuid ()
369     || gid != getegid ())
370 sf-exg 1.10 PTYTTY_FATAL ("unable to drop privileges, aborting.\n");
371 root 1.1 }
372