1<?xml version="1.0" encoding="UTF-8"?>
2<!DOCTYPE egbokdoc SYSTEM "dtd/egbokdoc.dtd">
3<!-- $Id: 2.0arch.xml,v 1.2 2002/05/24 04:05:43 hbo Exp $
4  Description of sudoscript's 2.0 architecture
5-->
6
7<egbokdoc>
8
9<title>
10Sudoscript 2.0 Architecture
11</title>
12
13<maintainer>
14  <name>Howard Owen</name>
15  <affiliation>EGBOK Consultants</affiliation>
16  <email>hbo@egbok.com</email>
17</maintainer>
18<content>
19
20<section title="Introduction">
21<para>
22  The original sudoscript architecture was a simple response to the
23  problem of allowing software engineers to run root shells on their
24  workstations. Generally, these users would be the only ones running
25  sudoshell on their machine. This was fortunate, because the original
26  architecture made no allowance for multiple simultaneous
27  users. There was a single logging FIFO and a single log
28  file. Multiple users could invoke sudoshell, but all their output
29  would be thrown together in the log file, without any separation of
30  the various sessions. As a practical matter, user input could
31  usually be differentiated by looking at the prompt.  But since PS1
32  is settable by the user, and therefore varies quite a bit, it
33  couldn't be counted on to allow such differentiation.
34</para>
35</section>
36<section title="Tommy Smith's Idea">
37<para>
38  Some mechanism was required to allow session differentiation. I got
39  an email from Tommy Smith suggesting that separate log files could be
40  used to allow identification of sessions. This struck me as a very
41  good idea. I started to think about how that could be
42  implemented. Forking a logging daemon per session seemed like it
43  would be fairly easy. I had a prototype doing that pretty quickly.
44  About the same time, I was exploring an idea from Adam Morris that
45  would get rid of sudoscriptd altogether, and replace in with a
46  forked FIFO server in sudoshell. I took a look at his C code that
47  implemented this idea, and tried to replicate it in Perl. I ran into
48  difficulty with keeping the terminal session attached to
49  script(1). Regardless of whether I implemented the daemon in the
50  parent or the child, I couldn't keep stdin/stdout attached to the
51  'system script' call. That, and 22 Dell 1650 servers landing on my
52  desk stopped my experiments for a time.
53</para>
54</section>
55<section title="The Second Idea">
56<para>
57  When I revisited the code, I decided that I didn't want to get rid
58  of the daemon, because it allowed me to manage the size of the logs
59  produced. Using script(1) meant that large quantities of data, far
60  in excess of that produced by sudo, could be produced by
61  sudoscript. Though I couldn't predict how much data a particular
62  user might produce, I was concerned about overflowing logging
63  partitions.  In the 1.0 architecture, the singular daemon kept an
64  eye on the log file. With multiple daemons, I realized, this job
65  would be a lot more complicated. I thought through a couple of
66  schemes that had the front-end daemon orchestrating log file
67  rotation among the back-end loggers. The main difficulty was that
68  the daemon in a position to know about all outstanding sessions
69  didn't &quot;own&quot; the log files. This made it harder to ensure
70  a timely rotation so that data wasn't dropped, while making it easier
71  to miss logs that needed compressing because a back-end daemon had
72  shut down abnormally. I decided that the whole deal was a threat to
73  overall reliability of sudoscript.
74</para>
75<para>
76  I then got the idea of merging all the session data back into
77  another daemon. This daemon would manage a merger FIFO, and coalesce
78  all session data, pre-tagged with a session ID, back into a single
79  log file. The daemon could then manage the log in the same way as
80  the 1.0 daemon did. The overall architecture was significantly more
81  complicated, but it looked to me like it could be reliable if
82  properly implemented. And there were no frills, either. All the
83  complexity had a specific purpose that no simpler architecture I
84  could think of would achieve.
85</para>
86<para>
87
88  I also decided that I would use syslog to track session startup and
89  shutdown. A short digression regarding syslog is in order
90  here. Since I couldn't control the possibly large quantity of data
91  sudoscript would log, I was reluctant to use syslog for the
92  script(1) data itself. When managing my own log, I was able to
93  trade off between longevity and space in a way that made sense to
94  me. But if I was using syslog, I could end up imposing that trade off
95  on a system log file, where it might be less appropriate. For
96  example, sudoscript 2.0 uses the AUTHPRIV syslog facility. On Red
97  Hat Linux, the default syslog.conf puts messages with this facility
98  into /var/log/secure. If sudoscript were to log all of the script(1)
99  data through to /var/log/secure, then that file would have to turn
100  over frequently. This could flush other important security data out
101  of the system more quickly than appropriate. Also, the sheer
102  quantity of data, combined with the ugliness of script(1) output,
103  would make these logs harder to read. I could use a different
104  facility for the data, but another feature of syslog makes me
105  hesitate to use it. At many sites, particularly those that are Sun
106  based, remote loghosts are employed. I think it's a really bad idea
107  to log by-definition sensitive data over the network in the
108  clear. The large quantity is a factor here as well. Given these
109  considerations, I have decided to stick with a private log file.
110</para>
111</section>
112<section title="The 2.0 Architecture">
113<para>
114  I have a <link href="2.0arch.gif" text="rather large GIF image" /> of
115  the 2.0 architecture. If you open this image in a separate window, it
116  might help you understand the explanations that follow.
117</para>
118<para>
119  When sudoscriptd starts, it opens a FIFO called
120  &quot;/var/run/sudoscriptd/rendevous&quot;. It then forks a
121  child. The parent process is the sudoscript &quot;master
122  daemon.&quot; The child process is the &quot;merger daemon&quot;.
123  It opens a FIFO called &quot;/var/run/sudoscriptd/merge&quot;.  It
124  also opens the log file, &quot;/var/log/sudoscript&quot;, for
125  append.  The merger goes into a read loop on the merge FIFO. As data
126  appears on this FIFO, the merger checks the size of the log file and
127  forks a rotator/compressor if the size exceeds 2 MB. Meanwhile, the
128  master daemon has gone into a read loop on its FIFO.
129</para>
130<para>
131  When sudoshell starts, it contacts the master daemon over the
132  rendezvous FIFO. It sends a string like &quot;HELO hbo
133  12345&quot;. The latter two fields are the username that invoked
134  sudoshell (taken from the sudo environment, if sudoshell was run, or
135  ran itself with sudo, or just 'root' if it was invoked with
136  privilege) and sudoshell's own process ID.  Sudoshell then installs
137  a SIGHUP handler and calls Posix::pause to go to sleep. The master
138  daemon spawns a logger for the sudoshell session. This child opens
139  the merge FIFO for write, and creates a session FIFO using the
140  username and PID derived from the HELO string. It then signals the
141  PID given with a SIGHUP, and goes goes into a loop reading the
142  session FIFO, tagging the data received with the username and PID
143  and writing it to the merge FIFO. Sudoshell wakes up when it
144  receives the SIGHUP, and invokes script(1) on the session FIFO,
145  whose name it derives from its own username and PID.
146</para>
147<para>
148  When the user exits from script(1), sudoshell sends another string
149  to the frontend daemon, identical to the first, except that
150  &quot;HELO&quot; is replaced with &quot;GDBY&quot;. Sudoshell then
151  exits. When the master daemon receives the GDBY message, it looks up
152  the session in a table it maintains. It uses the child PID stored
153  there to signal the session daemon with a SIGHUP. It then removes
154  that session from its table. The session daemon cleans up and exits
155  when it receives this signal.
156</para>
157<para>
158  When the master daemon receives a SIGHUP, it loops through its
159  session table and signals each associated logger with a SIGHUP.
160  It then does the same for the merger daemon.
161</para>
162</section>
163<section title="Conclusion">
164<para>
165  So, that's the complete life-cycle of the 2.0
166  sudoscript system. As noted above, important events are logged
167  to syslog with facility AUTHPRIV. This provides a concise record
168  of session activity, which can be used to search the larger log file
169  for particular sessions.
170</para>
171</section>
172</content>
173</egbokdoc>
174
175