1libptytty(3) LIBPTYTTY libptytty(3)
2
3
4
6 libptytty - OS independent and secure pty/tty and utmp/wtmp/lastlog
7 handling
8
10 cc ... -lptytty
11
12 #include <libptytty.h>
13
14
15 // C++
16 ptytty *pty = ptytty::create ();
17
18 if (!pty->get ())
19 // error allocating pty
20
21 if (we want utmp)
22 pty->login (process_pid, 0, "remote.host");
23 else if (we want utmp AND wtmp/lastlog)
24 pty->login (process_pid, 1, "remote.host");
25
26 // we are done with it
27 delete pty;
28
29
30 // C
31 PTYTTY pty = ptytty_create ();
32
33 if (!ptytty_get (pty))
34 // error allocating pty
35
36 if (we want utmp)
37 ptytty_login (pty, process_pid, 0, "remote.host");
38 else if (we want utmp AND wtmp/lastlog)
39 ptytty_login (pty, process_pid, 1, "remote.host");
40
41 // we are done with it
42 ptytty_delete (pty);
43
44 See also the eg/ directory, which currently contains the c-sample.c
45 file that spawns a login shell from C using libptytty.
46
48 Libptytty is a small library that offers pseudo-tty management in an
49 OS-independent way. It was created out of frustration over the many
50 differences of pty/tty handling in different operating systems for the
51 use inside "rxvt-unicode".
52
53 In addition to offering mere pty/tty management, it also offers session
54 database support (utmp and optional wtmp/lastlog updates for login
55 shells).
56
57 It also supports fork'ing after startup and dropping privileges in the
58 calling process, so in case the calling process gets compromised by the
59 user starting the program there is less to gain, as only the helper
60 process runs with privileges (e.g. setuid/setgid), which reduces the
61 area of attack immensely.
62
63 Libptytty is written in C++, but it also offers a C-only API.
64
66 libptytty uses "CMake" as build system. To build libptytty, install
67 "CMake" and run the following commands from either the libptytty source
68 directory or a separate build directory:
69
70 cmake -DCMAKE_INSTALL_PREFIX=<prefix> -DBUILD_SHARED_LIBS=ON <path/to/libptytty>
71 cmake --build .
72 cmake --install .
73
75 It is of paramount importance that you at least read the following
76 paragraph!
77
78 If you write a typical terminal-like program that just wants one or
79 more ptys, you should call the "ptytty::init ()" method (C:
80 "ptytty_init ()" function) as the very first thing in your program:
81
82 int main (int argc, char *argv[])
83 {
84 // do nothing here
85 ptytty::init ();
86 // in C: ptytty_init ();
87
88 // initialise, parse arguments, etc.
89 }
90
91 This checks whether the program runs setuid or setgid. If yes then it
92 will fork a helper process and drop privileges.
93
94 Some programs need finer control over if and when this helper process
95 is started, and if and how to drop privileges. For those programs, the
96 methods "ptytty::use_helper" and "ptytty::drop_privileges" (and
97 possibly "ptytty::sanitise_stdfd") are more useful.
98
100 STATIC METHODS
101 ptytty::init ()
102 The default way to initialise libptytty. Must be called immediately
103 as the first thing in the "main" function, or earlier e.g. during
104 static construction time. The earlier, the better.
105
106 This method calls "sanitise_stdfd" and then checks whether the
107 program runs with setuid/setgid permissions and, if yes, spawns a
108 helper process for pty/tty management. It then drops the privileges
109 completely, so the actual program runs without setuid/setgid
110 privileges.
111
112 On failure, this method throws a "ptytty_error" exception.
113
114 ptytty::use_helper ()
115 Tries to start a helper process that retains privileges even when
116 the calling process does not. This is usually called from
117 "ptytty::init" when it detects that the program is running setuid
118 or setgid, but can be called manually if it is inconvenient to drop
119 privileges at startup, or when you are not running setuid/setgid
120 but want to drop privileges (e.g. when running as a root-started
121 daemon).
122
123 This method will try not to start more than one helper process. The
124 same helper process can usually be used both from the process
125 starting it and all its fork'ed (not exec'ed) children.
126
127 On failure, this method throws a "ptytty_error" exception.
128
129 ptytty::drop_privileges ()
130 Drops privileges completely, i.e. sets real, effective and saved
131 user id to the real user id. Useful to make sure that the process
132 doesn't run with special privileges.
133
134 On failure, this method throws a "ptytty_error" exception.
135
136 ptytty::sanitise_stdfd ()
137 Checks whether file descriptors 0, 1 and 2 (stdin, stdout and
138 stderr) are valid (open) and, if not, connects them to /dev/tty or
139 /dev/null if possible. This is necessary because libptytty might
140 want to output error messages to those descriptors, which at the
141 time of outputting the error message, might be connected to
142 something unsuitable opened by the unsuspecting program itself
143 (this can be a security issue).
144
145 On failure, this method throws a "ptytty_error" exception.
146
147 bool success = ptytty::send_fd (int socket, int fd)
148 Utility method to send a file descriptor over a unix domain socket.
149 Returns true if successful, false otherwise. This method is only
150 exposed for your convenience and is not required for normal
151 operation.
152
153 int fd = ptytty::recv_fd (int socket)
154 Utility method to receive a file descriptor over a unix domain
155 socket. Returns the fd if successful and "-1" otherwise. This
156 method is only exposed for your convenience and is not required for
157 normal operation.
158
159 ptytty *pty = ptytty::create ()
160 Creates new ptytty object. Creation does not yet do anything
161 besides allocating the structure.
162
163 A static method is used because the actual ptytty implementation
164 can differ at runtime, so you need a dynamic object creation
165 facility.
166
167 DYNAMIC/SESSION-RELATED DATA MEMBERS AND METHODS
168 int pty_fd = pty->pty
169 int tty_fd = pty->tty
170 These members contain the pty and tty file descriptors,
171 respectively. They initially contain "-1" until a successful call
172 to "ptytty::get".
173
174 bool success = pty->get ()
175 Tries to find, allocate and initialise a new pty/tty pair. Returns
176 "true" when successful.
177
178 If the helper process is running and there is a protocol error,
179 this method throws a "ptytty_error" exception.
180
181 pty->login (int cmd_pid, bool login_shell, const char *hostname)
182 Creates an entry in the systems session database(s) (utmp, wtmp,
183 lastlog). "cmd_pid" must be the pid of the process representing
184 the session (such as the login shell), "login_shell" defines
185 whether the session is associated with a login, which influences
186 whether wtmp and lastlog entries are created, and "hostname" should
187 identify the "hostname" the user logs in from, which often is the
188 value of the "DISPLAY" variable or tty line in case of local
189 logins.
190
191 Calling this method is optional. A session starts at the time of
192 the login call and extends until the ptytty object is destroyed.
193
194 pty->close_tty ()
195 Closes the tty. Useful after forking in the parent/pty process.
196
197 bool success = pty->make_controlling_tty ()
198 Tries to make the pty/tty pair the controlling terminal of the
199 current process. Useful after forking in the child/tty process.
200
201 pty->set_utf8_mode (bool on)
202 On systems supporting special UTF-8 line disciplines (e.g. Linux),
203 this tries to enable this discipline for the given pty. Can be
204 called at any time to change the mode.
205
207 ptytty_init ()
208 See "ptytty::init ()".
209
210 PTYTTY ptytty_create ()
211 Creates a new opaque PTYTTY object and returns it. Do not try to
212 access it in any way except by testing it for truthness (e.g. "if
213 (pty) ...."). See "ptytty::create ()".
214
215 int ptytty_pty (PTYTTY ptytty)
216 Return the pty file descriptor. See "pty->pty".
217
218 int ptytty_tty (PTYTTY ptytty)
219 Return the tty file descriptor. See "pty->tty".
220
221 void ptytty_delete (PTYTTY ptytty)
222 Destroys the PTYTTY object, freeing the pty/tty pair and cleaning
223 up the utmp/wtmp/lastlog databases, if initialised/used. Same as
224 "delete pty" in C++.
225
226 int ptytty_get (PTYTTY ptytty)
227 See "pty->get", returns 0 in case of an error, non-zero otherwise.
228
229 void ptytty_login (PTYTTY ptytty, int cmd_pid, bool login_shell, const
230 char *hostname)
231 See "pty->login".
232
233 void ptytty_close_tty (PTYTTY ptytty)
234 See "pty->close_tty".
235
236 int ptytty_make_controlling_tty (PTYTTY ptytty)
237 See "pty->make_controlling_tty".
238
239 void ptytty_set_utf8_mode (PTYTTY ptytty, int on)
240 See "pty->set_utf8_mode".
241
242 void ptytty_drop_privileges ()
243 See "ptytty::drop_privileges".
244
245 void ptytty_use_helper ()
246 See "ptytty::use_helper".
247
249 To date, libptytty has been tested on the following platforms:
250
251 GNU/Linux
252 FreeBSD
253 NetBSD
254 OpenBSD
255 macOS
256 Solaris
257 AIX
258
260 You kiddin'?
261
263 Emanuele Giaquinta <emanuele.giaquinta@gmail.com>, Marc Alexander
264 Lehmann <rxvt-unicode@schmorp.de>.
265
266
267
2682.0 2021-07-27 libptytty(3)