| 1 | %%% -*-LaTeX-*- |
| 2 | %%% |
| 3 | %%% $Id: become.tex,v 1.3 1997/08/07 09:37:44 mdw Exp $ |
| 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 $ |
| 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 | %%% |
| 35 | %%% Revision 1.2 1997/08/04 10:24:20 mdw |
| 36 | %%% Sources placed under CVS control. |
| 37 | %%% |
| 38 | %%% Revision 1.1 1997/07/21 13:47:54 mdw |
| 39 | %%% Initial revision |
| 40 | %%% |
| 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 |
| 103 | Autoconf; to Ron Rivest for the MD5 message digest algorithm; to Xuejia |
| 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.} |
| 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} |
| 199 | $ gunzip -c become-1.2.tar.gz | tar xvf - |
| 200 | \end{verbatim} |
| 201 | will decompress and unpack the source code into a directory |
| 202 | \path{become-1.2}. |
| 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 | |
| 257 | You can now build the programs by invoking 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 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 | \subsubsection{Predefined names} |
| 420 | |
| 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. |
| 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. |
| 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. |
| 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 | |
| 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.} |
| 502 | Here's an example of a possible key file: |
| 503 | \begin{verbatim} |
| 504 | 4fda99b0-fcbd8bcb-d1bcf951-e1ed04c9 |
| 505 | \end{verbatim} |
| 506 | |
| 507 | You should generate 128 genuinely random bits for the key file. It is |
| 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 |
| 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 |
| 514 | \begin{verbatim} |
| 515 | $ keygen -o become.key |
| 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 | |
| 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 | |
| 536 | |
| 537 | \subsection{Setting up the server and clients} |
| 538 | |
| 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 | |
| 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 |
| 583 | the server or servers. This has the syntax: |
| 584 | \begin{syntdiag} |
| 585 | \< <host-name> \[ `:' <port> \] \> |
| 586 | \end{syntdiag} |
| 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 |
| 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 | |
| 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 |
| 859 | result of user-supplied data, and has checked the source rather carefully. |
| 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 | |
| 882 | %%%----- That's all, folks -------------------------------------------------- |
| 883 | |
| 884 | \end{document} |
| 885 | |
| 886 | %%% Local Variables: |
| 887 | %%% mode: latex |
| 888 | %%% TeX-master: t |
| 889 | %%% End: |