c4f2d992 |
1 | %%% -*-LaTeX-*- |
2 | %%% |
151230ea |
3 | %%% $Id: become.tex,v 1.3 1997/08/07 09:37:44 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 $ |
151230ea |
31 | %%% Revision 1.3 1997/08/07 09:37:44 mdw |
32 | %%% Updated to reflect new `become' version. Included description of multiple |
33 | %%% server support, netgroup handling, larger random seed file, and so on. |
34 | %%% |
03f996bd |
35 | %%% Revision 1.2 1997/08/04 10:24:20 mdw |
36 | %%% Sources placed under CVS control. |
c4f2d992 |
37 | %%% |
151230ea |
38 | %%% Revision 1.1 1997/07/21 13:47:54 mdw |
39 | %%% Initial revision |
40 | %%% |
c4f2d992 |
41 | |
42 | %%%----- Document preamble -------------------------------------------------- |
43 | |
44 | |
45 | %% --- Document class and packages --- |
46 | |
47 | \documentclass[a4paper, 10pt]{article} |
48 | \usepackage{array, tabularx} |
49 | \usepackage[rounded]{syntax} |
50 | |
51 | \newif\ifxypic |
52 | % \IfFileExists{xy.sty}{\usepackage[all]{xy}\xypictrue}{\xypicfalse} |
53 | |
54 | \IfFileExists{mdwfonts.sty}{\usepackage{mdwfonts}}{} |
55 | |
56 | |
57 | %% --- Macros and things --- |
58 | |
59 | \newcommand{\become}{\textsf{become}} |
60 | \newcommand{\path}[1]{\texttt{#1}} |
61 | \def\<#1>{\synt{#1}} |
62 | \newcommand{\xor}{\oplus} |
63 | \newcommand{\ror}{\mathbin{>\mskip-6mu>\mskip-6mu>}} |
64 | |
65 | |
66 | %% --- eqalign, from Plain TeX, LaTeXified --- |
67 | |
68 | \makeatletter |
69 | \def\eqalign{% |
70 | \null\,\vcenter\bgroup\openup\jot\m@th% |
71 | \ialign\bgroup% |
72 | \strut\hfil$\displaystyle{##}$&$\displaystyle{{}##}$\hfil\crcr% |
73 | } |
74 | \def\endeqalign{ |
75 | \crcr% |
76 | \egroup\egroup% |
77 | \,% |
78 | } |
79 | \makeatother |
80 | |
81 | |
82 | %% --- Other layout preferences --- |
83 | |
84 | \setlength{\grammarindent}{1in} |
85 | \renewcommand{\arraystretch}{1.2} |
86 | \addtolength{\textwidth}{0.6in} |
87 | \addtolength{\oddsidemargin}{-0.3in} |
88 | \sloppy |
89 | |
90 | \begin{document} |
91 | |
92 | |
93 | %%%----- Introductory matter ------------------------------------------------ |
94 | |
95 | |
96 | %% --- Title and some `brief' acknowledgements --- |
97 | |
98 | \title{The \become\ program} |
99 | \author{Mark Wooding\thanks{ |
100 | The program contains nontrivial pieces of code owned by the European |
101 | Bioinformatics Institute, Mark Wooding and Straylight (even though I |
102 | actually wrote it all). Thanks also to the Free Software Foundation for |
151230ea |
103 | Autoconf; to Ron Rivest for the MD5 message digest algorithm; to Xuejia |
c4f2d992 |
104 | Lai and James Massey for the IDEA cipher; and to Bruce Schneier, for |
105 | writing \emph{Applied Cryptography}, which explained why I'd written the |
106 | first version of all this code wrong.} \\ |
107 | \texttt{mdw@ebi.ac.uk}} |
108 | |
109 | \maketitle |
110 | |
111 | |
112 | %% --- Abstract --- |
113 | |
114 | \begin{abstract} |
115 | This document describes a system for allowing users to `become' other users |
116 | in a secure and controlled way under Unix. The idea is to allow users to |
117 | maintain programs and other resources which require their own accounts |
118 | while removing the need for such accounts to have passwords (which can be |
119 | disclosed, forgotten or otherwise abused in ways that passwords for user |
120 | accounts don't tend to be). |
121 | |
122 | The \become\ program will look up the user's identity, the identity of the |
123 | user he or she wishes to `become', the name of the program which is to be |
124 | executed, and the identity of the current host, consult a configuration |
125 | file, and decide whether the request is permitted before granting it. The |
126 | novel idea is that the table doesn't need to be on the local machine -- |
127 | \become\ will send a request to a server, asking it for permission, |
128 | allowing the information to be held centrally, and making maintenance more |
129 | convenient. Cryptographic protocols are used to ensure the authenticity of |
130 | the server's responses. |
131 | \end{abstract} |
132 | |
133 | |
134 | %% --- Contents --- |
135 | |
136 | \tableofcontents |
137 | |
138 | |
139 | %%%-------------------------------------------------------------------------- |
140 | \section{User guide} |
141 | |
142 | |
143 | \subsection{Introduction} |
144 | |
145 | Running \become\ lets you `become' another user. What this really means is |
146 | that it lets you execute a process with the permissions of another user. |
147 | Which users you're allowed to `become', and exactly what processes you're |
148 | allowed to execute as those users is determined by the people that installed |
149 | \become. |
150 | |
151 | |
152 | \subsection{Invoking \become} |
153 | |
154 | Invoking the \become\ program is impressively simple. There are essentially |
155 | two forms of invocation: |
156 | \begin{syntdiag} |
157 | `become' <user-name> \[ <program> \[ \< <argument> \> \] \] |
158 | \end{syntdiag} |
159 | and |
160 | \begin{syntdiag} |
161 | `become' `-c' <shell-command> <user-name> |
162 | \end{syntdiag} |
163 | The first variant allows you to execute any \<program> as user \<user-name>, |
164 | as limited by your site's configuration. The second variant simply passes |
165 | the \<shell-command> to \path{/bin/sh}, so you must have permission to |
166 | execute the shell as \<user-name>. The latter form doesn't actually allow |
167 | you to do anything the former doesn't: it is in fact entirely equivalent to |
168 | saying `\syntax{"become" <user-name> "/bin/sh -c" <shell-command>}', but |
169 | slightly more compact. |
170 | |
171 | |
172 | %%%-------------------------------------------------------------------------- |
173 | \section{Installation and configuration} |
174 | |
175 | |
176 | \subsection{Unpacking and compiling} |
177 | |
178 | Before you begin, there are some prerequisites you should check: |
179 | \begin{itemize} |
180 | \item You need the Free Software Foundation's gzip program to unpack the |
181 | distribution archive. |
182 | \item You need an ANSI-conformant C~compiler and library to correctly compile |
183 | the source code. No effort at all has been made to support nonstandard |
184 | C~implementations.\footnote{ |
185 | The ANSI~C standard was ratified in 1989. It is now 1997. If your |
186 | system vendor hasn't bothered to comply with an eight year old standard, |
187 | you ought to firstly complain to your vendor, and secondly install the |
188 | GNU~C compiler.} |
c4f2d992 |
189 | \item You'll probably need GNU flex and bison to rebuild the scanner and |
190 | parser. However, prebuilt C~source for these components is provided, and |
191 | will probably work. |
192 | \item A recent version of \LaTeX\ is required for formatting the manual. For |
193 | those without \LaTeX, a formatted version of the manual is supplied, in |
194 | PostScript form. |
195 | \end{itemize} |
196 | |
197 | The \become\ software is distributed as a gzipped tape archive: saying |
198 | \begin{verbatim} |
151230ea |
199 | $ gunzip -c become-1.2.tar.gz | tar xvf - |
c4f2d992 |
200 | \end{verbatim} |
201 | will decompress and unpack the source code into a directory |
151230ea |
202 | \path{become-1.2}. |
c4f2d992 |
203 | |
204 | The software must be configured prior to compilation. The author has used |
205 | the Free Software Foundation's Autoconf system which will (with luck) |
206 | configure \become\ correctly for the host platform. The simplest way to do |
207 | this is to change into the unpacked source directory and say |
208 | \begin{verbatim} |
209 | $ ./configure |
210 | \end{verbatim} |
211 | If you're compiling for several architectures, you can keep the object files |
212 | for each in a separate directory. To do this, create a directory for each |
213 | one, e.g., by saying something like |
214 | \begin{verbatim} |
215 | $ mkdir linux solaris |
216 | \end{verbatim} |
217 | Then make the appropriate directory current, and run the configure script |
218 | from the parent directory: |
219 | \begin{verbatim} |
220 | $ cd linux |
221 | $ ../configure |
222 | \end{verbatim} |
223 | |
224 | Without any arguments, the configure script will attempt to deduce all it |
225 | needs to know about your platform, and it will choose default places to |
226 | install files. You can change the configure script's ideas about where to |
227 | put the files by passing it command line arguments. By default, all of |
228 | \become's files are placed relative to a \emph{prefix} directory (so binaries |
229 | go in \emph{prefix}\path{/bin} and so on). The prefix directory is usually |
230 | \path{/usr/local}, although you can change this by using the |
231 | \texttt{--prefix} option, e.g., |
232 | \begin{verbatim} |
233 | $ ./configure --prefix=/usr/local/become-1.1 |
234 | \end{verbatim} |
235 | (This will keep all of \become's files in a subdirectory of |
236 | \path{/usr/local}, which you may find makes maintenance easier.) |
237 | |
238 | You can also choose different locations for various types of file. Most |
239 | importantly, \become's configuration files are put into a `system |
240 | configuration' directory, which by default is \emph{prefix}\path{/etc}. You |
241 | can change it using the \texttt{--sysconfdir} option, e.g., |
242 | \begin{verbatim} |
243 | $ ./configure --sysconfdir=/etc/become |
244 | \end{verbatim} |
245 | If you're planning to use \become\ in a centralised installation (see |
246 | section~\ref{sec:become.inst-type} on page~\pageref{sec:become.inst-type}) |
247 | then the system configuration directory \emph{must not} be on a remote |
248 | filesystem because cryptographic keys are stored in this directory and |
249 | putting them on a remote filesystem will make them visible on the network. |
250 | |
251 | A complete list of options accepted by the configure script may be displayed |
252 | by passing the \texttt{--help} option: |
253 | \begin{verbatim} |
254 | $ ./configure --help |
255 | \end{verbatim} |
256 | |
151230ea |
257 | You can now build the programs by invoking make. |
c4f2d992 |
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 |
151230ea |
280 | a central trusted server. |
c4f2d992 |
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 | |
151230ea |
419 | \subsubsection{Predefined names} |
c4f2d992 |
420 | |
151230ea |
421 | Before reading the configuration file, \become\ predefines a collection of |
422 | classes: |
423 | \begin{itemize} |
424 | \item For every user $u$, a class `$u$' is created containing that user. |
425 | \item For every group $g$, a class `$g$' is created containing all members of |
426 | that group. |
427 | \item For each netgroup $n$ read from the NIS server, a class `\lit*{u_}$n$' |
428 | is created containing all the users listed in the netgroup, and a class |
429 | `\lit{h_}$n$' containing the IP address of all the hosts listed in the |
430 | netgroup.\footnote{ |
431 | Netgroups don't fit in particularly well with \become's way of thinking. |
432 | The netgroup idea tries to bind users and hosts together in tight little |
433 | bundles, which doesn't help here. The current behaviour of splitting |
434 | the tight little host--user--domain bundles into separate lists of users |
435 | and hosts is, to the author's knowledge, the cleanest way of making |
436 | netgroups useful. |
437 | |
438 | It should probably be pointed out that, in general, NIS should be |
439 | considered insecure. Nothing too terrible should happen if you run your |
440 | \become\ server on the NIS master machine.} |
441 | \end{itemize} |
442 | User and group names can contain characters (e.g., dashes or dots) which |
443 | aren't allowed in \become\ class names; \become\ automatically translates |
444 | any non-alphanumeric characters into underscores. |
445 | |
446 | Note that by the end of this process, each class contains the \emph{union} of |
447 | all the things which are automatically put there. So if your system has a |
448 | `root' group, then the class \lit{root} ends up containing the root user |
449 | together with all members of the root group. You can be sure of referring to |
450 | a single user by enclosing the user name in quotes. Hence |
451 | \begin{verbatim} |
452 | allow HACKERS -> rcs; |
453 | \end{verbatim} |
454 | lets your syshacks become anyone in the rcs group, whereas |
455 | \begin{verbatim} |
456 | allow HACKERS -> "rcs"; |
457 | \end{verbatim} |
458 | lets them become the rcs user only. |
c4f2d992 |
459 | |
460 | |
461 | \subsection{Configuring standalone installations} |
462 | |
463 | That's it, really. Make sure that \become\ can find the configuration file |
464 | on each host. If \become\ can't find a server to talk to (which it can't |
465 | because you haven't configured one) it will parse the local configuration |
466 | file and decide for itself whether to grant the user's request. |
467 | |
468 | If you're only interested in setting up a standalone installation, then |
469 | you're finished, and can get on with doing something interesting. |
151230ea |
470 | Alternatively, read on, and see all the work you don't have to do. You |
471 | should probably note, however, that reading a configuration file for a |
472 | reasonable-sized site takes quite a long while, though; doing this in a |
473 | central server will make your users happier, as well as being less work for |
474 | you. |
c4f2d992 |
475 | |
476 | |
477 | \subsection{Keys and random numbers} |
478 | |
479 | Because \become\ uses cryptographic methods for communicating with its |
480 | server, you must set up some encryption keys for it to use. You need to set |
481 | up two files, both in \become's system configuration directory: |
482 | \begin{itemize} |
483 | \item The file \path{become.key} contains \become's `master' key. Someone |
484 | who knows the master key can fake responses from the server, and grant |
485 | themselves any privileges they like. |
486 | \item The file \path{become.random} contains a `random number seed' which is |
487 | used (together with the master key) to generate random numbers (e.g., |
488 | session keys). Someone who knows the random numbers can fake responses |
489 | from the server, and grant themselves any privileges they like. It's |
490 | difficult to actually predict random numbers given the random number seed |
491 | file, although it's not a good idea to leave the seed lying around. |
492 | \end{itemize} |
493 | Both of these files should be stored on a local filesystem, and they should |
494 | be readable only by the super-user. |
495 | |
151230ea |
496 | The key contains a 128-bit number; the random number file contains a 512-bit |
497 | number. Both numbers are written in hexadecimal. To make the thing more |
498 | readable, you may insert dashes in the number between each chunk of eight digits.\footnote{ |
499 | Actually, you can insert dashes wherever you like in the number, but this |
500 | is only because the parser is rather primitive. The author recommends that |
501 | you stick with every eight digits.} |
c4f2d992 |
502 | Here's an example of a possible key file: |
503 | \begin{verbatim} |
504 | 4fda99b0-fcbd8bcb-d1bcf951-e1ed04c9 |
505 | \end{verbatim} |
506 | |
151230ea |
507 | You should generate 128 genuinely random bits for the key file. It is |
c4f2d992 |
508 | \emph{not} good enough to use a computer random number generator. A program |
509 | will be supplied later which will examine key timings as a source for random |
510 | numbers. Also, don't use the number printed above. That would be really |
151230ea |
511 | silly. To help you do this, a program `keygen' is provided. It uses timings |
512 | of keypresses to generate random numbers. To use the program to generate |
513 | the key file, type |
c4f2d992 |
514 | \begin{verbatim} |
151230ea |
515 | $ keygen -o become.key |
c4f2d992 |
516 | \end{verbatim} |
517 | Keygen will report the number of bits which still need to be generated. Keep |
518 | typing until it says `done'. The program automatically ensures that its |
519 | output file, if it doesn't already exist, is readable only by its owner. The |
520 | command line arguments to keygen are simple: |
521 | \begin{syntdiag} |
522 | `keygen' \< \[ `--bits' <number> \\ `--output' <file-name> \] \> |
523 | \end{syntdiag} |
524 | If you don't specify a \<number> of bits, a default of 128 random bits are |
525 | generated, which is correct for IDEA keys. If you omit the \<file-name>, the |
526 | random key is written to standard output. |
527 | |
151230ea |
528 | The random number file can be generated by saying |
529 | \begin{verbatim} |
530 | keygen -o become.random -b 512 |
531 | \end{verbatim} |
532 | However, \become\ will generate a random number file if it can't find one. |
533 | Note that its randomness acquisition isn't completely wonderful yet; the |
534 | author recommends that you \emph{do} generate a seed file. |
535 | |
c4f2d992 |
536 | |
537 | \subsection{Setting up the server and clients} |
538 | |
151230ea |
539 | As of version 1.2, the \become\ client is capable of sending its request to |
540 | multiple servers, which makes it more resilient to server failures. |
541 | |
c4f2d992 |
542 | You don't need a separate program to run as a \become\ server: the normal |
543 | \become\ is quite capable of behaving as a server all by itself. However, |
544 | before you start the server up, you need to decide on a port to which it will |
545 | listen. The author uses port 9876 for testing purposes, and there's not much |
546 | reason why you couldn't do the same. |
547 | |
548 | There are three ways you can inform \become\ of your choice of port: |
549 | \begin{itemize} |
550 | \item You can pass the port number on the command line, using the |
551 | \texttt{--port} option. |
552 | \item You can add a line saying `\syntax{"port" <number> ";"}' to the |
553 | configuration file. |
554 | \item You can add an entry to your \path{/etc/services} file (or NIS map), |
555 | binding your chosen port number to the name `become'.\footnote{ |
556 | Actually, \become\ searches for the port using the filename with which |
557 | it was invoked, so if you call the \become\ binary \path{splat}, then |
558 | \become will look for a service labelled `splat'.} |
559 | \end{itemize} |
560 | If \become\ still has no idea which port to use, it refuses to start up as a |
561 | server and reports an error message to you. |
562 | |
563 | You can also choose a different key file to use, by writing a line of the |
564 | form `\syntax{"key" <filename> ";"}' in \path{become.conf}. The client won't |
565 | listen to this -- only the server does that. |
566 | |
567 | To make \become\ run as a server, say |
568 | \begin{verbatim} |
569 | $ become --daemon |
570 | \end{verbatim} |
571 | (or to use an explicit port number, say something like |
572 | \begin{verbatim} |
573 | $ become --daemon --port=9876 |
574 | \end{verbatim} |
575 | replacing \texttt{9876} in the example with your chosen port). You can also |
576 | run the daemon with a different configuration file, by using the |
577 | \texttt{--config-file} option, e.g., |
578 | \begin{verbatim} |
579 | $ become --daemon --config-file=/etc/become/server.conf |
580 | \end{verbatim} |
581 | |
582 | Now to configure the clients. All they need is a file saying where to find |
151230ea |
583 | the server or servers. This has the syntax: |
c4f2d992 |
584 | \begin{syntdiag} |
151230ea |
585 | \< <host-name> \[ `:' <port> \] \> |
c4f2d992 |
586 | \end{syntdiag} |
151230ea |
587 | The \<port> can be either a number (which is used directly) or a service |
588 | name, which is looked up in the system's services database (typically |
589 | \texttt{/etc/services}). If you omit the port number, then \become\ looks in |
590 | the services database for a service with the name used to invoke it. This |
591 | usage isn't recommended, however.\footnote{ |
592 | It's not actually a security risk, because even though a user could |
593 | potentially make the client send its request to a different server, the |
594 | server would only be able to build a valid reply if it knew the correct |
595 | key.} |
596 | |
597 | The server wakes up every half an hour to rescan its configuration and |
c4f2d992 |
598 | encryption key. Thus, it should react fairly quickly to changes to the user |
599 | database or to its configuration. However, you can always force the server |
600 | to refetch its configuration files by sending it a SIGHUP signal. To help |
601 | you do this, the server stores its process id in a file \path{become.pid} |
602 | within its system configuration directory. |
603 | |
604 | |
605 | \subsection{Maintaining \become} |
606 | |
607 | There's not much to it really, apart from updating the configuration file |
608 | when your requirements change. |
609 | |
610 | The only other thing you really ought to do is to periodically change the |
611 | master key. This should be done about once a week, I'd suspect. The |
612 | difficult part is distributing the keys over the network: you don't really |
613 | want to trust the old keys. I'd recommend that you investigate `ssh' for key |
614 | distribution. |
615 | |
616 | |
617 | \subsection{Summary of \become\ configuration} |
618 | |
619 | \subsubsection{Table of the configuration files} |
620 | |
621 | \begin{tabularx}{\textwidth}{@{} >{\ttfamily}l X @{}} |
622 | \multicolumn{1}{@{}l}{\textbf{File name}} & |
623 | \multicolumn{1}{l@{}}{\textbf{Contents}} \\ |
624 | become.conf & Main configuration file. See the syntax below for the |
625 | complete reference \\ |
626 | become.key & Master encryption key. Should contain a 128-bit random |
627 | number. \\ |
628 | become.pid & Server's process id (so that you can kill it). The server |
629 | creates this file all by itself. \\ |
630 | become.random & Random number seed for generating session keys. Should |
631 | also contain a 128-bit random number. Don't be surprised |
632 | if the number keeps changing -- it's meant to. \\ |
633 | become.server & Tells the \become\ client where to find the server. \\ |
634 | \end{tabularx} |
635 | |
636 | \subsubsection{Definitive syntax for \path{become.conf}} |
637 | |
638 | The syntax for \path{become.conf} files is shown below. This mainly reprises |
639 | the syntax shown earlier, but in a different order, and without all the |
640 | explanatory text getting in the way. |
641 | |
642 | Firstly, the lexical grammar is as follows: |
643 | |
644 | \begin{grammar} |
645 | |
646 | <comment> ::= \[[ |
647 | `#' \< \tok{any character other than <new-line>} \> <new-line> |
648 | \]] |
649 | |
650 | <name> ::= \[[ |
651 | \tok{letter or `_'} \< \( \tok{letter or `_'} \\ \tok{digit} \) \> |
652 | \]] |
653 | |
654 | <integer> ::= \[[ \< \tok{digit} \> \]] |
655 | |
656 | <string> ::= \[[ |
657 | `"' \< \( \tok{any character other than `"', <new-line> or `\\'} \\ |
658 | `\\' \tok{any character other than <new-line>} \) \> `"' |
659 | \]] |
660 | |
661 | \end{grammar} |
662 | |
663 | All \<comment>s and whitespace are ignored entirely. What's left is parsed |
664 | as follows: |
665 | |
666 | \begin{grammar} |
667 | |
668 | <become-conf> ::= \[[ \< <statement> \> \]] |
669 | |
670 | <statement> ::= \[[ |
671 | \( \( `user' \\ `command' \\ `host' \) <name> `=' <class-expr> `;' \\ |
672 | `allow' <allow-spec> `;' \\ |
673 | `port' <integer> `;' \\ |
674 | `key' <string> `;' \) |
675 | \]] |
676 | |
677 | <allow-spec> ::= \[[ |
678 | \[ `[' <host-class> `]' \] |
679 | <user-class> `->' \[ <user-class> \] |
680 | \[ `:' <command-class> \] |
681 | \]] |
682 | |
683 | <class-expr> ::= \[[ |
684 | \[ \< <class-minus-expr> \\ `,' \> \] <class-minus-expr> |
685 | \]] |
686 | |
687 | <class-minus-expr> ::= \[[ |
688 | \[ \< <class-or-expr> \\ `-' \> \] <class-or-expr> |
689 | \]] |
690 | |
691 | <class-or-expr> ::= \[[ |
692 | \[ \< <class-and-expr> \\ `|' \> \] <class-and-expr> |
693 | \]] |
694 | |
695 | <class-and-expr> ::= \[[ |
696 | \[ \< <class-primary> \\ `&' \> \] <class-primary> |
697 | \]] |
698 | |
699 | <class-primary> ::= \[[ |
700 | \( `(' <class-expr> `)' \\ <name> \\ <integer> \\ <string> \) |
701 | \]] |
702 | |
703 | \end{grammar} |
704 | |
705 | |
706 | %%%-------------------------------------------------------------------------- |
707 | \section{Cryptographic trivia} |
708 | |
709 | |
710 | \subsection{Design requirements} |
711 | |
712 | The way the system works is that the \become\ client program builds a |
713 | \emph{request block} containing all the information needed to decide whether |
714 | the user's request is valid. It then sends this to a server, asking it |
715 | whether this request should be granted. If the server replies `yes', then |
716 | \become\ changes its uid, and runs the user's program. |
717 | |
718 | The really important point is that the client must be able to trust the |
719 | responses it gets from the server: the final decision over whether to grant |
720 | the request lies only with the client. The server doesn't really need to |
721 | worry too much about whether it trusts a request -- it's not going to do |
722 | anything with them anyway except send a reply back. |
723 | |
724 | |
725 | \subsection{Notation} |
726 | |
727 | Some slightly weird mathematical notation is used in the following sections. |
728 | \begin{description} |
729 | \item [$a \xor b$] denotes the exclusive-or (XOR) operation (bitwise addition |
730 | mod 2). |
731 | \item [$(a, b, c)$] denotes concatenation of the quantities $a$, $b$ and $c$. |
732 | \item [$a[x : y]$] denotes bits $x$ up to $y$ of $a$, including bit~$x$ but |
733 | \emph{not} bit~$y$. For example, $a[32:64]$ is a 32-bit quantity. The |
734 | bits are labelled starting from the left at zero, and increasing to the |
735 | right. |
736 | \item [$E_{k, IV}(a)$] denotes encryption of $a$, using the key $k$ and |
737 | initialisation vector $IV$. |
738 | \item [$D_{k, IV}(a)$] denotes decryption of $a$, using the key $k$ and |
739 | initialisation vector $IV$. |
740 | \end{description} |
741 | Encryption is performed using the IDEA algorithm, in 64-bit ciphertext |
742 | feedback mode. |
743 | |
744 | |
745 | \subsection{The actual protocol} |
746 | |
747 | The protocol \become\ uses to communicate with the server is as follows: |
748 | \begin{enumerate} |
749 | |
750 | \item The client and server share a secret key~$k$. |
751 | |
752 | \item The client calculates the following: |
753 | \begin{description} |
754 | \item [$F$] is the `from' user id; |
755 | \item [$T$] is the `to' user id; |
756 | \item [$C$] is the command the user wishes to execute; |
757 | \item [$t$] is the current time, as returned from \texttt{time}(2); and |
758 | \item [$p$] is the client's process id. |
759 | \end{description} |
760 | The fields $t$ and~$p$ are to ensure that the client doesn't get confused |
761 | by replies to the wrong requests. |
762 | |
763 | \item The client generates a session key~$s$ and initialisation vector~$IV$. |
764 | It then calculates a checksum |
765 | \[ X = MD5(F, T, C, t, p)[0:32] \] |
766 | and sends the server a message |
767 | \[ \bigl(IV, E_{k, IV}(s), E_{s, IV'}(F, T, C, t, p, X)\bigr) \] |
768 | where $IV'$ is $E_{k, IV}(s)[64:128]$ (i.e., the last block of ciphertext |
769 | after encrypting the session key, so the whole message is encrypted as one |
770 | ciphertext feedback job, with a key change part-way). |
771 | |
772 | \item The server decrypts the message, and checks it to make sure it's valid: |
773 | \begin{itemize} |
774 | \item It checks that $X$ is the correct checksum. |
775 | \item It ensures that the difference between $t$ and the true time is |
776 | acceptable. (The current implementation allows $t$ to be 15 seconds |
777 | out.) |
778 | \end{itemize} |
779 | If either of these checks fails, the request is rejected without |
780 | acknowledgement. |
781 | |
782 | \item The server decides whether to grant the request. If it gives its |
783 | permission, it sets $a = 1$; otherwise it sets $a = 0$. It calculates a |
784 | checksum |
785 | \[ Y = MD5(t, p, a)[0:32] \] |
786 | and sends the client a message |
787 | \[ \bigl(IV'', E_{s, IV''}(t, p, a, Y)\bigr) \] |
788 | where $IV''$ is the last 64~bits of ciphertext received from the client, |
789 | continuing the ciphertext feedback again. (Later versions of \become\ |
790 | might use a different method for deciding on the initialisation vector.) |
791 | |
792 | \item The client decrypts the reply, and verifies it: |
793 | \begin{itemize} |
794 | \item It checks that $Y$ is a valid checksum. |
795 | \item It checks that the $t$ and $p$ values received match the ones in the |
796 | original request. |
797 | \end{itemize} |
798 | If either fail to match, the reply is discarded, and the client continues |
799 | to wait for a valid reply (possibly timing out). |
800 | |
801 | \item The client accepts the reply. If $a = 1$ it changes uid and executes |
802 | the named process~$C$. |
803 | |
804 | \end{enumerate} |
805 | |
806 | The encryption makes it hard for an attacker to alter the data being |
807 | transmitted in any meaningful way; the 32-bit checksum means that an altered |
808 | message has a $2^{-32}$ probability of not being noticed. |
809 | |
810 | The use of ciphertext feedback mode attempts to prevent chosen-plaintext |
811 | attacks, even though the user can make the client send arbitrary messages. |
812 | |
813 | |
c4f2d992 |
814 | \subsection{The `keygen' program} |
815 | |
816 | The `keygen' program attempts to take advantage of the variations in time |
817 | between your keystrokes to generate random numbers. It's not perfect. It |
818 | may help a little if you know exactly how it works. |
819 | |
820 | Keygen keeps track of the interval between keypresses. It exclusive-ors |
821 | adjacent interval times together, and strips off leading and trailing |
822 | sequences of one- or zero-bits. What's left is shifted into the accumulator. |
823 | The aim of all this complexity is to measure the variation in key timings, |
824 | and then discard any uninteresting bits from the result. |
825 | |
826 | This method works best on machines with very high-resolution clocks |
827 | (preferably with microsecond granularity), although even on the author's |
828 | Linux machine, which uses a clock with centisecond granularity, the number of |
829 | keystrokes required is acceptable. |
830 | |
831 | |
832 | \subsection{How to break \become's security} |
833 | |
834 | The author can't see any obvious weaknesses in the protocol used. Here are |
835 | some possibilities which might occur to an attacker, though: |
836 | \begin{itemize} |
837 | |
838 | \item Forge a server reply packet and send it to the client. Intercept the |
839 | request packet and discard it before it reaches the real server. The |
840 | required contents of the reply packet can be guessed. However, encrypting |
841 | it requires knowledge of the session key sent by the client. Obtaining |
842 | this means you need to break the IDEA cipher, which (to the author's |
843 | knowledge) isn't practical. |
844 | |
845 | \item Send another packet to the server at the same time, altering the sender |
846 | address so that the server replies to the wrong host or port. This won't |
847 | work, because the client will attempt to decrypt the fake reply with the |
848 | wrong session key and will reject the packet when it finds that the |
849 | checksum is incorrect. |
850 | |
851 | \item Find some other back door into the client host, to become root. Read |
852 | the secret key file, and use that to decrypt requests and send back |
853 | replies. If you can already become the super-user, why bother cracking |
854 | \become? |
855 | |
856 | \item Feed the client program bad input to overflow a fixed-size buffer. The |
857 | bad input contains executable code which gives the attacker a privileged |
858 | shell. The author isn't aware of any buffers which might overflow as a |
151230ea |
859 | result of user-supplied data, and has checked the source rather carefully. |
c4f2d992 |
860 | |
861 | \end{itemize} |
862 | |
863 | The above assumes that \become\ has been set up correctly. The following |
864 | attacks rely on misconfiguration: |
865 | \begin{itemize} |
866 | |
867 | \item Watch new secret keys being transmitted over the network when the |
868 | administrator replaces them. Now you can decrypt request packets and send |
869 | back replies. Make sure that the original server's responses are |
870 | corrupted so that the client rejects them. |
871 | |
872 | \item Watch the client or server reading the secret key from a remote |
873 | filesystem. |
874 | |
875 | \item Clobber the configuration file when the server re-reads it from a |
876 | remote filesystem, so that it gives your user account permission to become |
877 | anyone. |
878 | |
879 | \end{itemize} |
880 | |
881 | |
c4f2d992 |
882 | %%%----- That's all, folks -------------------------------------------------- |
883 | |
884 | \end{document} |
885 | |
886 | %%% Local Variables: |
887 | %%% mode: latex |
888 | %%% TeX-master: t |
889 | %%% End: |