c4f2d992 |
1 | %%% -*-LaTeX-*- |
2 | %%% |
03f996bd |
3 | %%% $Id: become.tex,v 1.2 1997/08/04 10:24:20 mdw Exp $ |
c4f2d992 |
4 | %%% |
5 | %%% Documentation for `become' |
6 | %%% |
7 | %%% (c) 1997 EBI |
8 | %%% |
9 | |
10 | %%%----- Licencing notice --------------------------------------------------- |
11 | %%% |
12 | %%% This file is part of `become' |
13 | %%% |
14 | %%% `Become' is free software; you can redistribute it and/or modify |
15 | %%% it under the terms of the GNU General Public License as published by |
16 | %%% the Free Software Foundation; either version 2 of the License, or |
17 | %%% (at your option) any later version. |
18 | %%% |
19 | %%% `Become' is distributed in the hope that it will be useful, |
20 | %%% but WITHOUT ANY WARRANTY; without even the implied warranty of |
21 | %%% MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the |
22 | %%% GNU General Public License for more details. |
23 | %%% |
24 | %%% You should have received a copy of the GNU General Public License |
25 | %%% along with `become'; if not, write to the Free Software |
26 | %%% Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. |
27 | |
28 | %%%----- Revision history --------------------------------------------------- |
29 | %%% |
30 | %%% $Log: become.tex,v $ |
03f996bd |
31 | %%% Revision 1.2 1997/08/04 10:24:20 mdw |
32 | %%% Sources placed under CVS control. |
c4f2d992 |
33 | %%% |
03f996bd |
34 | % Revision 1.1 1997/07/21 13:47:54 mdw |
35 | % Initial revision |
36 | % |
c4f2d992 |
37 | |
38 | %%%----- Document preamble -------------------------------------------------- |
39 | |
40 | |
41 | %% --- Document class and packages --- |
42 | |
43 | \documentclass[a4paper, 10pt]{article} |
44 | \usepackage{array, tabularx} |
45 | \usepackage[rounded]{syntax} |
46 | |
47 | \newif\ifxypic |
48 | % \IfFileExists{xy.sty}{\usepackage[all]{xy}\xypictrue}{\xypicfalse} |
49 | |
50 | \IfFileExists{mdwfonts.sty}{\usepackage{mdwfonts}}{} |
51 | |
52 | |
53 | %% --- Macros and things --- |
54 | |
55 | \newcommand{\become}{\textsf{become}} |
56 | \newcommand{\path}[1]{\texttt{#1}} |
57 | \def\<#1>{\synt{#1}} |
58 | \newcommand{\xor}{\oplus} |
59 | \newcommand{\ror}{\mathbin{>\mskip-6mu>\mskip-6mu>}} |
60 | |
61 | |
62 | %% --- eqalign, from Plain TeX, LaTeXified --- |
63 | |
64 | \makeatletter |
65 | \def\eqalign{% |
66 | \null\,\vcenter\bgroup\openup\jot\m@th% |
67 | \ialign\bgroup% |
68 | \strut\hfil$\displaystyle{##}$&$\displaystyle{{}##}$\hfil\crcr% |
69 | } |
70 | \def\endeqalign{ |
71 | \crcr% |
72 | \egroup\egroup% |
73 | \,% |
74 | } |
75 | \makeatother |
76 | |
77 | |
78 | %% --- Other layout preferences --- |
79 | |
80 | \setlength{\grammarindent}{1in} |
81 | \renewcommand{\arraystretch}{1.2} |
82 | \addtolength{\textwidth}{0.6in} |
83 | \addtolength{\oddsidemargin}{-0.3in} |
84 | \sloppy |
85 | |
86 | \begin{document} |
87 | |
88 | |
89 | %%%----- Introductory matter ------------------------------------------------ |
90 | |
91 | |
92 | %% --- Title and some `brief' acknowledgements --- |
93 | |
94 | \title{The \become\ program} |
95 | \author{Mark Wooding\thanks{ |
96 | The program contains nontrivial pieces of code owned by the European |
97 | Bioinformatics Institute, Mark Wooding and Straylight (even though I |
98 | actually wrote it all). Thanks also to the Free Software Foundation for |
99 | Autoconf; to Ron Rivest for the MD5 message digest algorithm; to Xuekia |
100 | Lai and James Massey for the IDEA cipher; and to Bruce Schneier, for |
101 | writing \emph{Applied Cryptography}, which explained why I'd written the |
102 | first version of all this code wrong.} \\ |
103 | \texttt{mdw@ebi.ac.uk}} |
104 | |
105 | \maketitle |
106 | |
107 | |
108 | %% --- Abstract --- |
109 | |
110 | \begin{abstract} |
111 | This document describes a system for allowing users to `become' other users |
112 | in a secure and controlled way under Unix. The idea is to allow users to |
113 | maintain programs and other resources which require their own accounts |
114 | while removing the need for such accounts to have passwords (which can be |
115 | disclosed, forgotten or otherwise abused in ways that passwords for user |
116 | accounts don't tend to be). |
117 | |
118 | The \become\ program will look up the user's identity, the identity of the |
119 | user he or she wishes to `become', the name of the program which is to be |
120 | executed, and the identity of the current host, consult a configuration |
121 | file, and decide whether the request is permitted before granting it. The |
122 | novel idea is that the table doesn't need to be on the local machine -- |
123 | \become\ will send a request to a server, asking it for permission, |
124 | allowing the information to be held centrally, and making maintenance more |
125 | convenient. Cryptographic protocols are used to ensure the authenticity of |
126 | the server's responses. |
127 | \end{abstract} |
128 | |
129 | |
130 | %% --- Contents --- |
131 | |
132 | \tableofcontents |
133 | |
134 | |
135 | %%%-------------------------------------------------------------------------- |
136 | \section{User guide} |
137 | |
138 | |
139 | \subsection{Introduction} |
140 | |
141 | Running \become\ lets you `become' another user. What this really means is |
142 | that it lets you execute a process with the permissions of another user. |
143 | Which users you're allowed to `become', and exactly what processes you're |
144 | allowed to execute as those users is determined by the people that installed |
145 | \become. |
146 | |
147 | |
148 | \subsection{Invoking \become} |
149 | |
150 | Invoking the \become\ program is impressively simple. There are essentially |
151 | two forms of invocation: |
152 | \begin{syntdiag} |
153 | `become' <user-name> \[ <program> \[ \< <argument> \> \] \] |
154 | \end{syntdiag} |
155 | and |
156 | \begin{syntdiag} |
157 | `become' `-c' <shell-command> <user-name> |
158 | \end{syntdiag} |
159 | The first variant allows you to execute any \<program> as user \<user-name>, |
160 | as limited by your site's configuration. The second variant simply passes |
161 | the \<shell-command> to \path{/bin/sh}, so you must have permission to |
162 | execute the shell as \<user-name>. The latter form doesn't actually allow |
163 | you to do anything the former doesn't: it is in fact entirely equivalent to |
164 | saying `\syntax{"become" <user-name> "/bin/sh -c" <shell-command>}', but |
165 | slightly more compact. |
166 | |
167 | |
168 | %%%-------------------------------------------------------------------------- |
169 | \section{Installation and configuration} |
170 | |
171 | |
172 | \subsection{Unpacking and compiling} |
173 | |
174 | Before you begin, there are some prerequisites you should check: |
175 | \begin{itemize} |
176 | \item You need the Free Software Foundation's gzip program to unpack the |
177 | distribution archive. |
178 | \item You need an ANSI-conformant C~compiler and library to correctly compile |
179 | the source code. No effort at all has been made to support nonstandard |
180 | C~implementations.\footnote{ |
181 | The ANSI~C standard was ratified in 1989. It is now 1997. If your |
182 | system vendor hasn't bothered to comply with an eight year old standard, |
183 | you ought to firstly complain to your vendor, and secondly install the |
184 | GNU~C compiler.} |
185 | \item You need a copy of GNU make to build the software. This can be |
186 | obtained from any GNU software archive. |
187 | \item You'll probably need GNU flex and bison to rebuild the scanner and |
188 | parser. However, prebuilt C~source for these components is provided, and |
189 | will probably work. |
190 | \item A recent version of \LaTeX\ is required for formatting the manual. For |
191 | those without \LaTeX, a formatted version of the manual is supplied, in |
192 | PostScript form. |
193 | \end{itemize} |
194 | |
195 | The \become\ software is distributed as a gzipped tape archive: saying |
196 | \begin{verbatim} |
197 | $ gunzip -c become-1.1.tar.gz | tar xvf - |
198 | \end{verbatim} |
199 | will decompress and unpack the source code into a directory |
200 | \path{become-1.1}. |
201 | |
202 | The software must be configured prior to compilation. The author has used |
203 | the Free Software Foundation's Autoconf system which will (with luck) |
204 | configure \become\ correctly for the host platform. The simplest way to do |
205 | this is to change into the unpacked source directory and say |
206 | \begin{verbatim} |
207 | $ ./configure |
208 | \end{verbatim} |
209 | If you're compiling for several architectures, you can keep the object files |
210 | for each in a separate directory. To do this, create a directory for each |
211 | one, e.g., by saying something like |
212 | \begin{verbatim} |
213 | $ mkdir linux solaris |
214 | \end{verbatim} |
215 | Then make the appropriate directory current, and run the configure script |
216 | from the parent directory: |
217 | \begin{verbatim} |
218 | $ cd linux |
219 | $ ../configure |
220 | \end{verbatim} |
221 | |
222 | Without any arguments, the configure script will attempt to deduce all it |
223 | needs to know about your platform, and it will choose default places to |
224 | install files. You can change the configure script's ideas about where to |
225 | put the files by passing it command line arguments. By default, all of |
226 | \become's files are placed relative to a \emph{prefix} directory (so binaries |
227 | go in \emph{prefix}\path{/bin} and so on). The prefix directory is usually |
228 | \path{/usr/local}, although you can change this by using the |
229 | \texttt{--prefix} option, e.g., |
230 | \begin{verbatim} |
231 | $ ./configure --prefix=/usr/local/become-1.1 |
232 | \end{verbatim} |
233 | (This will keep all of \become's files in a subdirectory of |
234 | \path{/usr/local}, which you may find makes maintenance easier.) |
235 | |
236 | You can also choose different locations for various types of file. Most |
237 | importantly, \become's configuration files are put into a `system |
238 | configuration' directory, which by default is \emph{prefix}\path{/etc}. You |
239 | can change it using the \texttt{--sysconfdir} option, e.g., |
240 | \begin{verbatim} |
241 | $ ./configure --sysconfdir=/etc/become |
242 | \end{verbatim} |
243 | If you're planning to use \become\ in a centralised installation (see |
244 | section~\ref{sec:become.inst-type} on page~\pageref{sec:become.inst-type}) |
245 | then the system configuration directory \emph{must not} be on a remote |
246 | filesystem because cryptographic keys are stored in this directory and |
247 | putting them on a remote filesystem will make them visible on the network. |
248 | |
249 | A complete list of options accepted by the configure script may be displayed |
250 | by passing the \texttt{--help} option: |
251 | \begin{verbatim} |
252 | $ ./configure --help |
253 | \end{verbatim} |
254 | |
255 | You can now build the programs by invoking GNU make. Whether simply typing |
256 | \texttt{make} is sufficient to run GNU make depends on your site: ask around |
257 | if you don't know how to invoke GNU make. |
258 | |
259 | Finally, you can install the various files to their correct directories by |
260 | saying |
261 | \begin{verbatim} |
262 | $ make install |
263 | \end{verbatim} |
264 | (again, using GNU make, so maybe it's not called `\texttt{make}' at your |
265 | site). |
266 | |
267 | Congratulations: \become\ is now compiled. The easy part is now done. |
268 | |
269 | |
270 | \subsection{Different installation types} |
271 | \label{sec:become.inst-type} |
272 | |
273 | There are two types of installation for \become, and which one you choose |
274 | depends on how you want to maintain the configuration file, which contains |
275 | the rules describing who is allowed to become whom: |
276 | \begin{itemize} |
277 | \item a \emph{standalone} installation, where the configuration is stored |
278 | locally, and |
279 | \item a \emph{centralised} installation, where the configuration is stored on |
280 | a central (and trusted) server. |
281 | \end{itemize} |
282 | The difference is basically how you want to maintain the configuration. In |
283 | the standalone case, you have to ensure that the configuration file is copied |
284 | to each participating host each time it gets changed. In the centralised |
285 | case, you only have one copy of the configuration file, and have a different |
286 | problem concerning key distribution. |
287 | |
288 | |
289 | \subsection{The configuration file} |
290 | |
291 | The configuration file for \become is called \path{become.conf}, and it's |
292 | stored in the system configuration directory you set up when compiling the |
293 | program. It defines a set of records, each containing four fields: |
294 | \begin{itemize} |
295 | \item a \emph{from} field, identifying a class of users; |
296 | \item a \emph{to} field, identifying a (possibly different) class of users; |
297 | \item a \emph{commands} field, describing a class of commands; and |
298 | \item a \emph{hosts} field, describing a class of hosts. |
299 | \end{itemize} |
300 | Such a record permits any user in the \emph{from} class to run a command |
301 | contained in the \emph{commands} class as any user in the \emph{to} class, on |
302 | any host in the \emph{hosts} class. If any class fails to match, permission |
303 | is denied. |
304 | |
305 | The configuration file can contain comments, which start with a \lit{\#} |
306 | character and extend to the end of the line; this is the only time when |
307 | newlines are significant in the configuration file. |
308 | |
309 | \subsubsection{Allow records} |
310 | |
311 | A record like the one described above is represented in the configuration |
312 | file by an \emph{allow record}. It has the following syntax: |
313 | \begin{grammar} |
314 | |
315 | <allow> ::= \[[ |
316 | `allow' |
317 | \[ `[' <host-class> `]' \] |
318 | <user-class> `->' \[ <user-class> \] |
319 | \[ `:' <command-class> \] |
320 | `;' |
321 | \]] |
322 | |
323 | \end{grammar} |
324 | The items \<host-class>, \<user-class> and \<command-class> are all |
325 | \emph{class expressions}. If you omit one of the classes, then it will match |
326 | all requests. So saying |
327 | \begin{verbatim} |
328 | allow EVILHACKER -> ; |
329 | \end{verbatim} |
330 | allows anyone in the `EVILHACKER' class to become anyone they like, |
331 | everywhere, and do anything. |
332 | |
333 | \subsubsection{Class expressions} |
334 | |
335 | Class expressions allow you to define classes of users, hosts and commands |
336 | conveniently. |
337 | |
338 | All class expressions have the same high-level syntax, and it's fairly easy |
339 | to understand. It looks a little bit like set notation: you can obtain the |
340 | union of two classes using the \lit{|} character (or), take intersections |
341 | using \lit{\&} (and), and subtract classes using \lit{-}. Finally, you can |
342 | list several classes by separating them with commas \lit{,}. The order of |
343 | precedence, from lowest to highest, is \lit{,}, \lit{-}, \lit{|} and |
344 | \lit{\&}.\footnote{ |
345 | Actually, the \lit{,} and \lit{|} operators do exactly the same thing. The |
346 | only difference is their relative precedence. It probably helps if you |
347 | think of them as being conceptually different, though.} |
348 | You can override the precedence rules by using parentheses. |
349 | |
350 | The whole syntax looks like this: |
351 | \begin{grammar} |
352 | |
353 | <class-expr> ::= \[[ |
354 | \[ \< <class-minus-expr> \\ `,' \> \] <class-minus-expr> |
355 | \]] |
356 | |
357 | <class-minus-expr> ::= \[[ |
358 | \[ \< <class-or-expr> \\ `-' \> \] <class-or-expr> |
359 | \]] |
360 | |
361 | <class-or-expr> ::= \[[ |
362 | \[ \< <class-and-expr> \\ `|' \> \] <class-and-expr> |
363 | \]] |
364 | |
365 | <class-and-expr> ::= \[[ |
366 | \[ \< <class-primary> \\ `&' \> \] <class-primary> |
367 | \]] |
368 | |
369 | <class-primary> ::= \[[ |
370 | \( `(' <class-expr> `)' \\ <class-name> \\ <explicit-item> \) |
371 | \]] |
372 | |
373 | \end{grammar} |
374 | |
375 | \subsubsection{Naming classes} |
376 | |
377 | To save repetition, you can give names to classes, using one of the three |
378 | assignment statements: |
379 | \begin{grammar} |
380 | |
381 | <user-assign> ::= \[[ `user' <name> `=' <user-class> `;' \]] |
382 | |
383 | <host-assign> ::= \[[ `host' <name> `=' <host-class> `;' \]] |
384 | |
385 | <command-assign> ::= \[[ `command' <name> `=' <command-class> `;' \]] |
386 | |
387 | \end{grammar} |
388 | |
389 | Classes can be defined in terms of themselves: saying |
390 | \begin{verbatim} |
391 | user HACKERS = HACKERS | "mdw"; |
392 | \end{verbatim} |
393 | says to add `mdw' to the class of hackers, for example. The configuration |
394 | file is read strictly top-to-bottom, and an allow record already given |
395 | doesn't change its meaning just because you later redefine of the classes it |
396 | refers to. |
397 | |
398 | \subsubsection{Naming users, hosts and commands} |
399 | |
400 | Right: you now know how to define classes in terms of other classes, but |
401 | you've got to start somewhere. Each type of class has its own way of |
402 | identifying members. |
403 | \begin{itemize} |
404 | \item A user may be identified either by writing the user's name in double |
405 | quotes (e.g, \texttt{"mdw"}) or by giving the integer user id (e.g., |
406 | \texttt{272}). |
407 | \item A host may be specified by giving, in quotes, either the host's |
408 | \emph{fully qualified} name (e.g., \texttt{"excessus.hacker.org"}), or its |
409 | IP~address, (e.g., \texttt{"158.152.170.219"}). Note that the IP~address |
410 | must be quoted too: this is slightly unusual. Either form may contain |
411 | wildcards: \lit{?} matches any character, and \lit{*} matches zero or more |
412 | characters. For example, I can name all hosts at hacker.org by saying |
413 | \texttt{"*.hacker.org"}. \emergencystretch=10pt |
414 | \item A command may be specified by giving its \emph{full pathname} in quotes |
415 | (e.g., \texttt{"/sbin/shutdown"}). Again, wildcards can be used to specify |
416 | lots of commands at the same time. |
417 | \end{itemize} |
418 | |
419 | Also, note that lots of user classes come \emph{predefined}. A class is |
420 | defined for every user, named with the user's name, and containing that user. |
421 | Also, for every group, there is a class, named with the group's name, which |
422 | contains all users who are members of that group. You can redefine these |
423 | classes if you like: they're meant to be a convenience, but if you don't like |
424 | them, you don't have to use them. |
425 | |
426 | A warning is in order: some systems have group names which are also user |
427 | names: in this case, a class is defined containing the named user \emph{and} |
428 | all the members of the group. That's probably not desirable. |
429 | |
430 | |
431 | \subsection{Configuring standalone installations} |
432 | |
433 | That's it, really. Make sure that \become\ can find the configuration file |
434 | on each host. If \become\ can't find a server to talk to (which it can't |
435 | because you haven't configured one) it will parse the local configuration |
436 | file and decide for itself whether to grant the user's request. |
437 | |
438 | If you're only interested in setting up a standalone installation, then |
439 | you're finished, and can get on with doing something interesting. |
440 | Alternatively, read on, and see all the work you don't have to do. |
441 | |
442 | |
443 | \subsection{Keys and random numbers} |
444 | |
445 | Because \become\ uses cryptographic methods for communicating with its |
446 | server, you must set up some encryption keys for it to use. You need to set |
447 | up two files, both in \become's system configuration directory: |
448 | \begin{itemize} |
449 | \item The file \path{become.key} contains \become's `master' key. Someone |
450 | who knows the master key can fake responses from the server, and grant |
451 | themselves any privileges they like. |
452 | \item The file \path{become.random} contains a `random number seed' which is |
453 | used (together with the master key) to generate random numbers (e.g., |
454 | session keys). Someone who knows the random numbers can fake responses |
455 | from the server, and grant themselves any privileges they like. It's |
456 | difficult to actually predict random numbers given the random number seed |
457 | file, although it's not a good idea to leave the seed lying around. |
458 | \end{itemize} |
459 | Both of these files should be stored on a local filesystem, and they should |
460 | be readable only by the super-user. |
461 | |
462 | Each of the two files, the key and the random number file, contain a 128-bit |
463 | number, written in hexadecimal. To make the thing more readable, you may |
464 | insert dashes in the number between each chunk of eight digits.\footnote{ |
465 | Actually, you can insert dashes wherever you like in the number, but |
466 | this is only because the parser is rather primitive. The author recommends |
467 | that you stick with every eight digits.} |
468 | Here's an example of a possible key file: |
469 | \begin{verbatim} |
470 | 4fda99b0-fcbd8bcb-d1bcf951-e1ed04c9 |
471 | \end{verbatim} |
472 | |
473 | You should generate 128 genuinely random bits for each file. It is |
474 | \emph{not} good enough to use a computer random number generator. A program |
475 | will be supplied later which will examine key timings as a source for random |
476 | numbers. Also, don't use the number printed above. That would be really |
477 | silly. |
478 | |
479 | To help you do this, a program `keygen' is provided. It uses timings of |
480 | keypresses to generate random numbers. To use the program to generate (for |
481 | example) the random number seed file, type |
482 | \begin{verbatim} |
483 | $ keygen -o become.random |
484 | \end{verbatim} |
485 | Keygen will report the number of bits which still need to be generated. Keep |
486 | typing until it says `done'. The program automatically ensures that its |
487 | output file, if it doesn't already exist, is readable only by its owner. The |
488 | command line arguments to keygen are simple: |
489 | \begin{syntdiag} |
490 | `keygen' \< \[ `--bits' <number> \\ `--output' <file-name> \] \> |
491 | \end{syntdiag} |
492 | If you don't specify a \<number> of bits, a default of 128 random bits are |
493 | generated, which is correct for IDEA keys. If you omit the \<file-name>, the |
494 | random key is written to standard output. |
495 | |
496 | |
497 | \subsection{Setting up the server and clients} |
498 | |
499 | You don't need a separate program to run as a \become\ server: the normal |
500 | \become\ is quite capable of behaving as a server all by itself. However, |
501 | before you start the server up, you need to decide on a port to which it will |
502 | listen. The author uses port 9876 for testing purposes, and there's not much |
503 | reason why you couldn't do the same. |
504 | |
505 | There are three ways you can inform \become\ of your choice of port: |
506 | \begin{itemize} |
507 | \item You can pass the port number on the command line, using the |
508 | \texttt{--port} option. |
509 | \item You can add a line saying `\syntax{"port" <number> ";"}' to the |
510 | configuration file. |
511 | \item You can add an entry to your \path{/etc/services} file (or NIS map), |
512 | binding your chosen port number to the name `become'.\footnote{ |
513 | Actually, \become\ searches for the port using the filename with which |
514 | it was invoked, so if you call the \become\ binary \path{splat}, then |
515 | \become will look for a service labelled `splat'.} |
516 | \end{itemize} |
517 | If \become\ still has no idea which port to use, it refuses to start up as a |
518 | server and reports an error message to you. |
519 | |
520 | You can also choose a different key file to use, by writing a line of the |
521 | form `\syntax{"key" <filename> ";"}' in \path{become.conf}. The client won't |
522 | listen to this -- only the server does that. |
523 | |
524 | To make \become\ run as a server, say |
525 | \begin{verbatim} |
526 | $ become --daemon |
527 | \end{verbatim} |
528 | (or to use an explicit port number, say something like |
529 | \begin{verbatim} |
530 | $ become --daemon --port=9876 |
531 | \end{verbatim} |
532 | replacing \texttt{9876} in the example with your chosen port). You can also |
533 | run the daemon with a different configuration file, by using the |
534 | \texttt{--config-file} option, e.g., |
535 | \begin{verbatim} |
536 | $ become --daemon --config-file=/etc/become/server.conf |
537 | \end{verbatim} |
538 | |
539 | Now to configure the clients. All they need is a file saying where to find |
540 | the server. All this contains is a single line of the form |
541 | \begin{syntdiag} |
542 | <host-name> \[ `:' <port-number> \] |
543 | \end{syntdiag} |
544 | If you omit the port number (or it's otherwise incomprehensible) then |
545 | \become\ looks at the services table (again using the name under which it was |
546 | invoked) to find a port. If it still can't find a port to use, then \become\ |
547 | complains. |
548 | |
549 | The server wakes up every five minutes to rescan its configuration and |
550 | encryption key. Thus, it should react fairly quickly to changes to the user |
551 | database or to its configuration. However, you can always force the server |
552 | to refetch its configuration files by sending it a SIGHUP signal. To help |
553 | you do this, the server stores its process id in a file \path{become.pid} |
554 | within its system configuration directory. |
555 | |
556 | |
557 | \subsection{Maintaining \become} |
558 | |
559 | There's not much to it really, apart from updating the configuration file |
560 | when your requirements change. |
561 | |
562 | The only other thing you really ought to do is to periodically change the |
563 | master key. This should be done about once a week, I'd suspect. The |
564 | difficult part is distributing the keys over the network: you don't really |
565 | want to trust the old keys. I'd recommend that you investigate `ssh' for key |
566 | distribution. |
567 | |
568 | |
569 | \subsection{Summary of \become\ configuration} |
570 | |
571 | \subsubsection{Table of the configuration files} |
572 | |
573 | \begin{tabularx}{\textwidth}{@{} >{\ttfamily}l X @{}} |
574 | \multicolumn{1}{@{}l}{\textbf{File name}} & |
575 | \multicolumn{1}{l@{}}{\textbf{Contents}} \\ |
576 | become.conf & Main configuration file. See the syntax below for the |
577 | complete reference \\ |
578 | become.key & Master encryption key. Should contain a 128-bit random |
579 | number. \\ |
580 | become.pid & Server's process id (so that you can kill it). The server |
581 | creates this file all by itself. \\ |
582 | become.random & Random number seed for generating session keys. Should |
583 | also contain a 128-bit random number. Don't be surprised |
584 | if the number keeps changing -- it's meant to. \\ |
585 | become.server & Tells the \become\ client where to find the server. \\ |
586 | \end{tabularx} |
587 | |
588 | \subsubsection{Definitive syntax for \path{become.conf}} |
589 | |
590 | The syntax for \path{become.conf} files is shown below. This mainly reprises |
591 | the syntax shown earlier, but in a different order, and without all the |
592 | explanatory text getting in the way. |
593 | |
594 | Firstly, the lexical grammar is as follows: |
595 | |
596 | \begin{grammar} |
597 | |
598 | <comment> ::= \[[ |
599 | `#' \< \tok{any character other than <new-line>} \> <new-line> |
600 | \]] |
601 | |
602 | <name> ::= \[[ |
603 | \tok{letter or `_'} \< \( \tok{letter or `_'} \\ \tok{digit} \) \> |
604 | \]] |
605 | |
606 | <integer> ::= \[[ \< \tok{digit} \> \]] |
607 | |
608 | <string> ::= \[[ |
609 | `"' \< \( \tok{any character other than `"', <new-line> or `\\'} \\ |
610 | `\\' \tok{any character other than <new-line>} \) \> `"' |
611 | \]] |
612 | |
613 | \end{grammar} |
614 | |
615 | All \<comment>s and whitespace are ignored entirely. What's left is parsed |
616 | as follows: |
617 | |
618 | \begin{grammar} |
619 | |
620 | <become-conf> ::= \[[ \< <statement> \> \]] |
621 | |
622 | <statement> ::= \[[ |
623 | \( \( `user' \\ `command' \\ `host' \) <name> `=' <class-expr> `;' \\ |
624 | `allow' <allow-spec> `;' \\ |
625 | `port' <integer> `;' \\ |
626 | `key' <string> `;' \) |
627 | \]] |
628 | |
629 | <allow-spec> ::= \[[ |
630 | \[ `[' <host-class> `]' \] |
631 | <user-class> `->' \[ <user-class> \] |
632 | \[ `:' <command-class> \] |
633 | \]] |
634 | |
635 | <class-expr> ::= \[[ |
636 | \[ \< <class-minus-expr> \\ `,' \> \] <class-minus-expr> |
637 | \]] |
638 | |
639 | <class-minus-expr> ::= \[[ |
640 | \[ \< <class-or-expr> \\ `-' \> \] <class-or-expr> |
641 | \]] |
642 | |
643 | <class-or-expr> ::= \[[ |
644 | \[ \< <class-and-expr> \\ `|' \> \] <class-and-expr> |
645 | \]] |
646 | |
647 | <class-and-expr> ::= \[[ |
648 | \[ \< <class-primary> \\ `&' \> \] <class-primary> |
649 | \]] |
650 | |
651 | <class-primary> ::= \[[ |
652 | \( `(' <class-expr> `)' \\ <name> \\ <integer> \\ <string> \) |
653 | \]] |
654 | |
655 | \end{grammar} |
656 | |
657 | |
658 | %%%-------------------------------------------------------------------------- |
659 | \section{Cryptographic trivia} |
660 | |
661 | |
662 | \subsection{Design requirements} |
663 | |
664 | The way the system works is that the \become\ client program builds a |
665 | \emph{request block} containing all the information needed to decide whether |
666 | the user's request is valid. It then sends this to a server, asking it |
667 | whether this request should be granted. If the server replies `yes', then |
668 | \become\ changes its uid, and runs the user's program. |
669 | |
670 | The really important point is that the client must be able to trust the |
671 | responses it gets from the server: the final decision over whether to grant |
672 | the request lies only with the client. The server doesn't really need to |
673 | worry too much about whether it trusts a request -- it's not going to do |
674 | anything with them anyway except send a reply back. |
675 | |
676 | |
677 | \subsection{Notation} |
678 | |
679 | Some slightly weird mathematical notation is used in the following sections. |
680 | \begin{description} |
681 | \item [$a \xor b$] denotes the exclusive-or (XOR) operation (bitwise addition |
682 | mod 2). |
683 | \item [$(a, b, c)$] denotes concatenation of the quantities $a$, $b$ and $c$. |
684 | \item [$a[x : y]$] denotes bits $x$ up to $y$ of $a$, including bit~$x$ but |
685 | \emph{not} bit~$y$. For example, $a[32:64]$ is a 32-bit quantity. The |
686 | bits are labelled starting from the left at zero, and increasing to the |
687 | right. |
688 | \item [$E_{k, IV}(a)$] denotes encryption of $a$, using the key $k$ and |
689 | initialisation vector $IV$. |
690 | \item [$D_{k, IV}(a)$] denotes decryption of $a$, using the key $k$ and |
691 | initialisation vector $IV$. |
692 | \end{description} |
693 | Encryption is performed using the IDEA algorithm, in 64-bit ciphertext |
694 | feedback mode. |
695 | |
696 | |
697 | \subsection{The actual protocol} |
698 | |
699 | The protocol \become\ uses to communicate with the server is as follows: |
700 | \begin{enumerate} |
701 | |
702 | \item The client and server share a secret key~$k$. |
703 | |
704 | \item The client calculates the following: |
705 | \begin{description} |
706 | \item [$F$] is the `from' user id; |
707 | \item [$T$] is the `to' user id; |
708 | \item [$C$] is the command the user wishes to execute; |
709 | \item [$t$] is the current time, as returned from \texttt{time}(2); and |
710 | \item [$p$] is the client's process id. |
711 | \end{description} |
712 | The fields $t$ and~$p$ are to ensure that the client doesn't get confused |
713 | by replies to the wrong requests. |
714 | |
715 | \item The client generates a session key~$s$ and initialisation vector~$IV$. |
716 | It then calculates a checksum |
717 | \[ X = MD5(F, T, C, t, p)[0:32] \] |
718 | and sends the server a message |
719 | \[ \bigl(IV, E_{k, IV}(s), E_{s, IV'}(F, T, C, t, p, X)\bigr) \] |
720 | where $IV'$ is $E_{k, IV}(s)[64:128]$ (i.e., the last block of ciphertext |
721 | after encrypting the session key, so the whole message is encrypted as one |
722 | ciphertext feedback job, with a key change part-way). |
723 | |
724 | \item The server decrypts the message, and checks it to make sure it's valid: |
725 | \begin{itemize} |
726 | \item It checks that $X$ is the correct checksum. |
727 | \item It ensures that the difference between $t$ and the true time is |
728 | acceptable. (The current implementation allows $t$ to be 15 seconds |
729 | out.) |
730 | \end{itemize} |
731 | If either of these checks fails, the request is rejected without |
732 | acknowledgement. |
733 | |
734 | \item The server decides whether to grant the request. If it gives its |
735 | permission, it sets $a = 1$; otherwise it sets $a = 0$. It calculates a |
736 | checksum |
737 | \[ Y = MD5(t, p, a)[0:32] \] |
738 | and sends the client a message |
739 | \[ \bigl(IV'', E_{s, IV''}(t, p, a, Y)\bigr) \] |
740 | where $IV''$ is the last 64~bits of ciphertext received from the client, |
741 | continuing the ciphertext feedback again. (Later versions of \become\ |
742 | might use a different method for deciding on the initialisation vector.) |
743 | |
744 | \item The client decrypts the reply, and verifies it: |
745 | \begin{itemize} |
746 | \item It checks that $Y$ is a valid checksum. |
747 | \item It checks that the $t$ and $p$ values received match the ones in the |
748 | original request. |
749 | \end{itemize} |
750 | If either fail to match, the reply is discarded, and the client continues |
751 | to wait for a valid reply (possibly timing out). |
752 | |
753 | \item The client accepts the reply. If $a = 1$ it changes uid and executes |
754 | the named process~$C$. |
755 | |
756 | \end{enumerate} |
757 | |
758 | The encryption makes it hard for an attacker to alter the data being |
759 | transmitted in any meaningful way; the 32-bit checksum means that an altered |
760 | message has a $2^{-32}$ probability of not being noticed. |
761 | |
762 | The use of ciphertext feedback mode attempts to prevent chosen-plaintext |
763 | attacks, even though the user can make the client send arbitrary messages. |
764 | |
765 | |
766 | \subsection{The random number generator} |
767 | |
768 | The random number generator is used to generate initialisation vectors and |
769 | session keys for the cryptographic protocol above. The random number |
770 | generator might well change in later versions of \become. |
771 | |
772 | The current implementation maintains an $n$-bit random number seed~$R_i$. It |
773 | generates a 128-bit session key~$s$, an initialisation vector~$IV$ and a new |
774 | seed~$R_{i+1}$. |
775 | \[ |
776 | \begin{eqalign} |
777 | s &= MD5(R_i, t, p, k) \cr |
778 | IV &= MD5(R_i, t, p, s)[0:64] \cr |
779 | R_{i + 1} &= (R_i[n - 128 : n] \xor s, R_i[0 : n - 128]) \cr |
780 | \end{eqalign} |
781 | \] |
782 | \ifxypic |
783 | See figure~\ref{fig:become.randgen} for a diagrammatic representation of |
784 | the generator. It's |
785 | \else |
786 | This is |
787 | \fi |
788 | really just a weird sort of feedback shift register, generating 128~bits of |
789 | data at a time. |
790 | |
791 | \ifxypic |
792 | \begin{figure} |
793 | |
794 | \xymatrix{ |
795 | |
796 | } |
797 | |
798 | \caption{The \become\ random number generator} |
799 | \label{fig:become.randgen} |
800 | \end{figure} |
801 | \fi |
802 | |
803 | |
804 | The use of the secret key~$k$ helps to ensure that even if the random number |
805 | seed is compromised, an attacker still needs to know $k$ before he can |
806 | predict session keys. Of course, if the attacker knows $k$, he has no need |
807 | to predict session keys: he can just decrypt them from the messages. The use |
808 | of the values $t$ and $p$ attempts to add a small quantity of randomness to |
809 | the seed in each iteration. |
810 | |
811 | |
812 | \subsection{The `keygen' program} |
813 | |
814 | The `keygen' program attempts to take advantage of the variations in time |
815 | between your keystrokes to generate random numbers. It's not perfect. It |
816 | may help a little if you know exactly how it works. |
817 | |
818 | Keygen keeps track of the interval between keypresses. It exclusive-ors |
819 | adjacent interval times together, and strips off leading and trailing |
820 | sequences of one- or zero-bits. What's left is shifted into the accumulator. |
821 | The aim of all this complexity is to measure the variation in key timings, |
822 | and then discard any uninteresting bits from the result. |
823 | |
824 | This method works best on machines with very high-resolution clocks |
825 | (preferably with microsecond granularity), although even on the author's |
826 | Linux machine, which uses a clock with centisecond granularity, the number of |
827 | keystrokes required is acceptable. |
828 | |
829 | |
830 | \subsection{How to break \become's security} |
831 | |
832 | The author can't see any obvious weaknesses in the protocol used. Here are |
833 | some possibilities which might occur to an attacker, though: |
834 | \begin{itemize} |
835 | |
836 | \item Forge a server reply packet and send it to the client. Intercept the |
837 | request packet and discard it before it reaches the real server. The |
838 | required contents of the reply packet can be guessed. However, encrypting |
839 | it requires knowledge of the session key sent by the client. Obtaining |
840 | this means you need to break the IDEA cipher, which (to the author's |
841 | knowledge) isn't practical. |
842 | |
843 | \item Send another packet to the server at the same time, altering the sender |
844 | address so that the server replies to the wrong host or port. This won't |
845 | work, because the client will attempt to decrypt the fake reply with the |
846 | wrong session key and will reject the packet when it finds that the |
847 | checksum is incorrect. |
848 | |
849 | \item Find some other back door into the client host, to become root. Read |
850 | the secret key file, and use that to decrypt requests and send back |
851 | replies. If you can already become the super-user, why bother cracking |
852 | \become? |
853 | |
854 | \item Feed the client program bad input to overflow a fixed-size buffer. The |
855 | bad input contains executable code which gives the attacker a privileged |
856 | shell. The author isn't aware of any buffers which might overflow as a |
857 | result of user-supplied data. |
858 | |
859 | \end{itemize} |
860 | |
861 | The above assumes that \become\ has been set up correctly. The following |
862 | attacks rely on misconfiguration: |
863 | \begin{itemize} |
864 | |
865 | \item Watch new secret keys being transmitted over the network when the |
866 | administrator replaces them. Now you can decrypt request packets and send |
867 | back replies. Make sure that the original server's responses are |
868 | corrupted so that the client rejects them. |
869 | |
870 | \item Watch the client or server reading the secret key from a remote |
871 | filesystem. |
872 | |
873 | \item Clobber the configuration file when the server re-reads it from a |
874 | remote filesystem, so that it gives your user account permission to become |
875 | anyone. |
876 | |
877 | \end{itemize} |
878 | |
879 | |
880 | %%%----- Licencing conditions ----------------------------------------------- |
881 | |
882 | \input{gpl} |
883 | |
884 | %%%----- That's all, folks -------------------------------------------------- |
885 | |
886 | \end{document} |
887 | |
888 | %%% Local Variables: |
889 | %%% mode: latex |
890 | %%% TeX-master: t |
891 | %%% End: |