/[dtapublic]/to_be_filed/webprojs/pamc/gen_a/docs/manual/man_a/c_tbg0/c_tbg0.tex
ViewVC logotype

Contents of /to_be_filed/webprojs/pamc/gen_a/docs/manual/man_a/c_tbg0/c_tbg0.tex

Parent Directory Parent Directory | Revision Log Revision Log


Revision 19 - (show annotations) (download) (as text)
Sat Oct 8 04:30:47 2016 UTC (7 years, 5 months ago) by dashley
File MIME type: application/x-tex
File size: 80129 byte(s)
Initial commit.
1 %$Header: /home/dashley/cvsrep/e3ft_gpl01/e3ft_gpl01/webprojs/pamc/gen_a/docs/manual/man_a/c_tbg0/c_tbg0.tex,v 1.35 2009/11/01 02:42:55 dashley Exp $
2
3 \chapter{Technical Background and Decisions}
4
5 \label{ctbg0}
6
7 \beginchapterquote{``The purpose of computing is insight, not numbers.''}
8 {Richard W. Hamming, 1962}
9
10 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
11 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
12 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
13 \section{Introduction}
14 %Section tag: INT0
15 \label{ctbg0:sint0}
16
17 This chapter provides technical background and describes key
18 \emph{\productbasename{}}
19 technical
20 and design decisions.
21
22
23 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
24 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
25 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
26 \section{Technical Background}
27 %Section tag: tbg0
28 \label{ctbg0:stbg0}
29
30
31 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
32 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
33 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
34 \subsection{The SHA1 Secure Hash Algorithm}
35 %Subsection tag: sha0
36 \label{ctbg0:stbg0:ssha0}
37
38 The SHA1 secure hash algorithm is described by
39 \index{RFC 3174}RFC 3174
40 (available many places on the Internet). The algorithm maps from
41 a block of data of any practical length to a 160-bit hash. The important features of
42 the algorithm are described in the executive summary of RFC 3174:
43
44 \begin{quote}
45 \emph{This document specifies a Secure Hash Algorithm, SHA-1, for computing
46 a condensed representation of a message or a data file. When a
47 message of any length $<$ $2^{64}$ bits is input, the SHA-1 produces a
48 160-bit output called a message digest. The message digest can then,
49 for example, be input to a signature algorithm which generates or
50 verifies the signature for the message. Signing the message digest
51 rather than the message often improves the efficiency of the process
52 because the message digest is usually much smaller in size than the
53 message. The same hash algorithm must be used by the verifier of a
54 digital signature as was used by the creator of the digital
55 signature. Any change to the message in transit will, with very high
56 probability, result in a different message digest, and the signature
57 will fail to verify.}
58
59 \emph{The SHA-1 is called secure because it is computationally infeasible
60 to find a message which corresponds to a given message digest, or to
61 find two different messages which produce the same message digest.
62 Any change to a message in transit will, with very high probability,
63 result in a different message digest, and the signature will fail to
64 verify.}
65 \end{quote}
66
67 The SHA1 algorithm is used for several purposes within
68 \emph{\productbasename{}-\productversion{}}:
69
70 \begin{itemize}
71 \item Rather than storing user passwords plain,
72 the standard hash\index{standard hash function} (\S{}\ref{ctbg0:sddc0:sshf0}) of each
73 user password is stored. The standard hash is
74 based on the SHA1 algorithm. (A hash
75 is used because of the non-reversibility---it isn't
76 possible to go backwards from the hash to the password.)
77 \item Session identifiers (SIDs, \S{}\ref{ctbg0:sdty0:ssid0})
78 are based on the SHA1 function. (It isn't possible for
79 an attacker to guess the exact form of a SID because of
80 the construction of the hash.)
81 \item The SHA1 hash is calculated for files stored in the
82 file repository, and this information is retained in the
83 database record corresponding to the file. This serves
84 three purposes:
85
86 \begin{itemize}
87 \item It allows the file to be periodically checked for corruption
88 (due to hard disk failure or software defects).
89 \item It allows users who upload a file to be sure that it
90 was uploaded without corruption.
91 \item It allows users who download a file to be sure that
92 it was downloaded without corruption.
93 \end{itemize}
94 \end{itemize}
95
96
97 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
98 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
99 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
100 \section{Data Types}
101 %Section tag: dty0
102 \label{ctbg0:sdty0}
103
104 \emph{PHP} has several native data types, including
105 integers and strings. \emph{PHP} handles
106 strings well, and so ``custom'' data types are
107 in most cases most conveniently represented as strings (although
108 sometimes arrays of integers, arrays of strings, or some combination
109 is most convenient). This section for the
110 most part describes the ``custom'' data types
111 used in the \emph{\productbasename{}-\productversion{}} software.
112
113
114 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
115 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
116 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
117 \subsection{Hash Key}
118 %Subsection tag: thk0
119 \label{ctbg0:sdty0:sthk0}
120
121 \index{hash key}Some of the
122 security of \emph{\productbasename{}-\productversion{}} is based
123 on an attacker's inability to determine in advance what hash value will
124 be paired with data by the \emph{\productbasename{}-\productversion{}}.
125 Because the source code of \emph{\productbasename{}-\productversion{}} is
126 public, it is necessary to have an element of hash calculation that is not
127 known to an attacker.
128
129 The unknown random element is called the
130 \index{hash key}\emph{hash key}. The hash key is a string consisting
131 (quite arbitrarily) of printable characters.
132
133 A reasonable guideline for the length $n$ of the hash key is that it
134 should have at least as many possible values as the hash output
135 that it influences. Assuming that lower- and upper-case letters
136 and digits are used (62 possibilities):
137
138 \begin{eqnarray}
139 \label{eq:ctbg0:sdty0:sthk0:01} 62^n & \geq & 2^{160} \\
140 \label{eq:ctbg0:sdty0:sthk0:02} n & \geq & \frac{160 \log 2}{\log 62} \approx 27
141 \end{eqnarray}
142
143 A hash key of 100 characters each chosen from letters and digits
144 should thus be more than adequate to prevent attacks.
145
146 The hash key is most readily generated by the
147 \index{hashkeygen@\emph{hashkeygen}}\emph{hashkeygen} program,
148 described in \S{}\ref{csco0:ssph0:shkg0} (p. \pageref{csco0:ssph0:shkg0})
149 and in \S{}\ref{cist0:scsh0} (p. \pageref{cist0:scsh0}).
150 The \emph{hashkeygen} program generates a hash key substantially
151 longer than the threshold suggested
152 by Eq. \ref{eq:ctbg0:sdty0:sthk0:02} (see
153 Fig. \ref{fig:cist0:scsh0:01}, p. \pageref{fig:cist0:scsh0:01}).
154
155
156 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
157 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
158 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
159 \subsection{AUTIME (Augmented Unix Timestamp)}
160 %Subsection tag: ati0
161 \label{ctbg0:sdty0:sati0}
162
163 \index{AUTIME}%
164 An \emph{augmented Unix timestamp} is a decimal representation of the number of
165 seconds since Jan 1, 1900 GMT, and includes a fractional part. Note that for times
166 after Jan 1, 1970 GMT, the AUTIME can be formed in a straightforward way from
167 the standard Unix time by adding a constant.
168
169 \begin{figure}
170 \centering
171 \includegraphics[width=4.6in]{c_tbg0/autimeformat01.eps}
172 \caption{Format of AUTIME}
173 \label{fig:ctbg0:sdty0:sati0:00}
174 \end{figure}
175
176 Figure \ref{fig:ctbg0:sdty0:sati0:00} illustrates the format of
177 an AUTIME\@. An AUTIME is a string consisting
178 of exactly 19 characters, with the following
179 components.
180
181 \begin{itemize}
182 \item \textbf{Integer seconds since midnight, January 1, 1900 GMT (10 characters):}
183 These 10 characters are a decimal integer, zero-padded on the left as
184 necessary, that represent the integer seconds since midnight, January 1,
185 1900 GMT.
186 \item \textbf{Nanoseconds associated with the integer seconds (9 characters):}
187 These 9 characters are an integer, zero-padded on the left as
188 necessary, that represent the nanoseconds associated with the
189 integer seconds since the midnight, January 1, 1900 GMT.
190 \end{itemize}
191
192 \index{leap second}Leap seconds are handled by ignoring them.
193 In essence, a ``virtual timespace'' is created where every day is exactly
194 86,400 seconds long and leap seconds don't exist. This strategy is
195 very similar to the notion of Unix time except that leap seconds are
196 avoided. The strategy has these components:
197
198 \begin{itemize}
199 \item Past and future times may be translated into an AUTIME that is
200 either ambiguous or non-existent in the presence of leap seconds (this could
201 occur only for a time within one second of midnight).
202 \item When an AUTIME is obtained from the PHP library functions included with
203 \emph{\productbasename{}-\productversion{}}, a time within one
204 second of midnight Unix time\footnote{Midnight UTC.} won't be supplied (instead, the
205 library function will \index{sleep}sleep or spin-lock
206 until the two-second window of vulnerability has passed).
207 This behavior is designed to avoid supplying ambiguous times or
208 reverse-ordered times.
209 \item Time differences calculated using two AUTIMEs may differ from the
210 actual time difference by up to the number of leap seconds that
211 have occurred between the two AUTIMEs.\footnote{In practice, this
212 is a very small error, bounded at several seconds per year.}
213 \end{itemize}
214
215 Note that AUTIMEs as described have the property that the lexical
216 string sort order corresponds to the time sort order.
217
218 The calendaring range of an AUTIME spans:
219
220 \begin{itemize}
221 \item Midnight on January 1, 1900, GMT, \emph{through}
222 \item One nanosecond before midnight on January 1, 2200, UTC.
223 \end{itemize}
224
225 \noindent{}The calendaring range was chosen to allow the representation of
226 past events (such as birthdays), but also to allow dates substantially
227 in the future.
228
229 In addition, the following values are reserved.
230 In each of the descriptions below, each ``X'' character
231 signifies a ``don't care'' (the ``X'' characters
232 are ignored in comparisons).
233
234 \begin{itemize}
235 \item \emph{9999999996XXXXXXXXX} is reserved to
236 indicate an underflow result, i.e. a time
237 before January 1, 1900, GMT.
238 \item \emph{9999999997XXXXXXXXX} is reserved to
239 indicate an overflow result, i.e. a time
240 after one nanosecond before
241 January 1, 1200, UTC.
242 \item \emph{9999999998XXXXXXXXX} is reserved to
243 indicate an indeterminate time, i.e. the
244 time can't be reliably determined.
245 \item \emph{9999999999XXXXXXXXX} is reserved to
246 indicate an otherwise unspecified error.
247 \item Values corresponding to a time of at least
248 midnight, January 1, 2200, UTC but less than
249 \emph{9999999996XXXXXXXXX} are treated
250 as \emph{9999999999XXXXXXXXX}. These
251 values should never occur in practice as the
252 date arithmetic functions should not allow these
253 values to be calculated as output.
254 \end{itemize}
255
256 Note that the AUTIME format can be used for values that:
257
258 \begin{itemize}
259 \item Are used as part of generating a unique or random data value
260 (see, for example, \S{}\ref{ctbg0:sdty0:ssgu0}).
261 \item Are used to determine elapsed time.
262 \end{itemize}
263
264
265 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
266 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
267 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
268 \subsection{AUTIMEIP (Augmented Unix Timestamp Integer Pair)}
269 %Subsection tag: ati2
270 \label{ctbg0:sdty0:sati2}
271
272 \index{AUTIMEIP}The string representation of an AUTIME is most convenient for
273 string manipulation in \emph{PHP}. However, for manipulation
274 in \emph{MySQL} and in CGI-BIN programs it may be more efficient to
275 represent the AUTIME as a pair of integers; one for the whole seconds
276 and one for the fractional nanoseconds. This represesentation as a pair
277 of integers is the AUTIMEIP data type.
278
279 As of January 1, 2200, there will have been approximately
280 9,467,280,000 seconds since January 1, 1900. The whole number
281 of seconds requires 34 bits to represent, and so this is compatible
282 with the \emph{MySQL} \emph{bigint} data type (but incompatible with
283 native \emph{PHP} integers with \emph{PHP} version 4.X on 32-bit
284 platforms).
285
286 The number of fractional nanoseconds $n$ always meets the
287 constraint $0 \leq n \leq 999,999,999$ and thus requires
288 30 bits to represent. This integer is compatible with
289 the \emph{MySQL} \emph{int} data type and with \emph{PHP}
290 integers.
291
292 An AUTIMEIP may be represented in the following ways:
293
294 \begin{itemize}
295 \item A \emph{bigint}/\emph{int} pair in \emph{MySQL}.
296 \item A 64-bit/32-bit integer pair in a compiled C program.
297 \item A string/integer pair in \emph{PHP}, where the string
298 is manipulated using \emph{bcmath} and the integer
299 is manipulated as provided for in the language.
300 \end{itemize}
301
302 The exception values as described in \S{}\ref{ctbg0:sdty0:sati0}
303 also apply to AUTIMEIP values.
304
305
306 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
307 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
308 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
309 \subsection{AUTIMEI (Augmented Unix Timestamp Integer)}
310 %Subsection tag: ati3
311 \label{ctbg0:sdty0:sati3}
312
313 \index{AUTIMEI}On January 1, 2200 UTC, the number of nanoseconds since
314 midnight January 1, 1900 GMT will be approximately
315 $9.4673 \times 10^{18}$, requiring
316 64 bits to represent. The integer representation of
317 the number of nanoseconds since midnight January 1, 1900
318 is the AUTIMEI data type.
319
320 Note that the AUTIMEI data type cannot be represented in a
321 \emph{MySQL} \emph{bigint}, as a \emph{MySQL} \emph{bigint}
322 can represent values only from $-2^{63}$ through $2^{63}-1$.
323
324 The AUTIMEI data type can often be represented in an integer
325 in the C programming langauge, as implementations often provide
326 for unsigned 64-bit integers.
327
328 The exception values as described in \S{}\ref{ctbg0:sdty0:sati0}
329 also apply to AUTIMEIP values.
330
331
332 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
333 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
334 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
335 \subsection{AUTIMELP (Augmented Unix Timestamp, Low Precision)}
336 %Subsection tag: ati1
337 \label{ctbg0:sdty0:sati1}
338
339 \index{AUTIMELP}The augmented Unix time is also manipulated in the
340 software without the fractional part. Such values are used where
341 a precision of one second is adequate.
342
343 An AUTIMELP is a string of exactly 10 characters.
344 The ranges and exception values specified in
345 \S{}\ref{ctbg0:sdty0:sati1} apply.
346
347
348 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
349 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
350 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
351 \subsection{UBDT (Unbound Date)}
352 %Subsection tag: ubd0
353 \label{ctbg0:sdty0:subd0}
354
355 It is occasionally desirable to specify a date in a context where a narrow
356 or unique mark or range in time isn't important or can't be determined.
357 An example would be
358 a birthday---a birthday alone gives no indication of the global time zone
359 where the person was born (and hence the range of times
360 potentially represented by the date
361 would be interpreted differently at different global locations).
362
363 These vague dates are called \index{unbound date}\emph{unbound dates}.
364
365 Unbound dates are in general unsuitable for most applications within
366 \emph{\productbasename{}-\productversion{}}\@. Even software release dates
367 are best maintained as AUTIMEs---for example, a software release on a
368 certain date in the U.S.
369 might be best thought of as occurring on the following day in Europe.
370
371 Unbound dates are always represented within the
372 \emph{\productbasename{}-\productversion{}} software in the form
373 \emph{YYYYMMDD}, and may range from 19000101 to
374 21991231, inclusive.
375
376 The value \emph{00000000} is used to represent an underflow (date before January
377 1, 1900), the value \emph{99999999} is used to represent an overflow (date
378 after December 31, 2199), and the value \emph{--------} is used to represent
379 any other type of error.
380
381 The \emph{PHP} library files in \emph{\productbasename{}-\productversion{}}
382 include functions to perform calculations with unbound dates.
383
384
385 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
386 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
387 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
388 \subsection{SGUID (Server Globally-Unique Identifier)}
389 %Subsection tag: sgu0
390 \label{ctbg0:sdty0:ssgu0}
391
392 It is necessary or helpful in some contexts to have a way to create an
393 identifier that is guaranteed to occur no more often than once in the lifetime
394 of the server. \emph{MySQL} can be used to create such identifiers, and there
395 are also methods based on file and IPC semantics that can be used.
396
397 The method used in the software is a \index{spin lock}spin lock on a precision
398 timestamp; and the timestamp is concatenated with the PID. The method works
399 because:
400
401 \begin{itemize}
402 \item A single process (by virtue of the spin lock) can't generate the same
403 precision timestamp twice.
404 \item No two processes can have the same PID at the same time.
405 \end{itemize}
406
407 \begin{figure}
408 \centering
409 \includegraphics[width=4.6in]{c_tbg0/sguidformat01.eps}
410 \caption{Format of SGUID}
411 \label{fig:ctbg0:sdty0:ssgu0:00}
412 \end{figure}
413
414 Figure \ref{fig:ctbg0:sdty0:ssgu0:00} illustrates the format of
415 an SGUID. An SGUID consists of 29 characters, with the following
416 components.
417
418 \begin{itemize}
419 \item \textbf{Integer seconds since the January 1, 1900 GMT (10 characters):}
420 These 10 characters are an integer, zero-padded on the left as
421 necessary, that represent the integer seconds since January 1, 1900
422 GMT.\footnote{Note that 10 digits comfortably solves the Unix
423 2037 A.D. issue, as this will guarantee SGUIDs
424 beyond 2200 A.D.}
425 \item \textbf{Nanoseconds associated with the integer seconds (9 characters):}
426 These 9 characters are an integer, zero-padded on the left as
427 necessary, that represent the nanoseconds associated with the
428 integer seconds since January 1, 1900,
429 GMT.\footnote{As of this writing, Linux provides time to a resolution
430 of microseconds. It is anticipated that a resolution of nanoseconds will
431 accommodate any hardware speed advances in the foreseeable future, as typical
432 hardware gate propagation delays are on the order of several nanoseconds.}
433 \item \textbf{PID (10 characters):}
434 These 10 characters are an integer, zero-padded on the left as
435 necessary, that represent Unix PID expressed
436 as a decimal number.\footnote{As of this writing, PIDs are 16 bits only.
437 However, it seems inevitable that PIDs will be expanded to 24 or 32 bits in the
438 future.}
439 \end{itemize}
440
441 Note that SGUIDs as described have a very important property in addition to
442 guaranteed uniqueness---the lexical
443 string sort order corresponds to the time sort order.
444
445 Two sample applications of SGUIDs are:
446
447 \begin{itemize}
448 \item The basis for a session identifier (guaranteed unique).
449 \item A field in a database record to detect browser editing collisions---when a record
450 is modified and a new SGUID is assigned to the record, it is \emph{guaranteed}
451 not to be the same as the previous SGUID, and thus detection of the editing collision
452 is guaranteed.
453 \end{itemize}
454
455
456 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
457 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
458 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
459 \subsection{SID (Session Identifier)}
460 %Subsection tag: sid0
461 \label{ctbg0:sdty0:ssid0}
462
463 A \index{session identifier}session identifier (\index{SID}SID) is a
464 string consisting of exactly 69 characters used to uniquely
465 identify a session (Figure \ref{fig:ctbg0:sdty0:ssid0:00}).
466
467 \begin{figure}
468 \centering
469 \includegraphics[width=4.6in]{c_tbg0/sidformat01.eps}
470 \caption{Format of SID}
471 \label{fig:ctbg0:sdty0:ssid0:00}
472 \end{figure}
473
474 The first part of the SID is a SGUID
475 (\S{}\ref{ctbg0:sdty0:ssgu0}). The second part of a SID is
476 the system hash function of the SGUID. The SGUID portion is guaranteed to
477 be unique (this is a defining property of an SGUID),
478 and so each SID is unique within the first 29 characters.
479 The SHA1 hash appended to the SGUID is designed to eliminate an attacker's
480 ability to construct a valid SID. It may be possible to guess an SGUID based
481 on server characteristics; but it should not be possible to guess the corresponding
482 hash (this is a defining property of the system hash function).
483
484 At the time a user logs in (either as a user or a guest), the SID is created
485 and provided to the browser as a cookie.
486
487 The session state changes that occur as \emph{\productbasename{}-\productversion{}}
488 is used are all stored on the server side. The advantages of this approach
489 are:
490
491 \begin{itemize}
492 \item Only one cookie of a very short length is stored in the client's browser.
493 This approach meets the RFC 2109 constraints and is also suitable
494 for mobile devices.
495 \item An attacker's ability to gather information about the internal workings
496 of \emph{\productbasename{}-\productversion{}} by
497 observing cookie reassignments is severely limited
498 (nothing except the SID is exposed, and exposed only once per session).
499 \item An attacker's ability to tamper with cookies is eliminated (only one
500 cookie is provided, and it is tamper-proof).
501 \end{itemize}
502
503
504 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
505 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
506 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
507 \section{Database Design Decisions and Discussion}
508 %Section tag: ddd0
509 \label{ctbg0:sddd0}
510
511
512 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
513 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
514 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
515 \subsection{Global Scope Naming Conventions}
516 %Subsection tag: gsn0
517 \label{ctbg0:sddd0:sgsn0}
518
519 In certain of the database tables and in certain other
520 contexts, a global naming convention is used rather than
521 further indexing information by application and page. (For
522 example, the \emph{upns} and \emph{stns} tables in
523 \S{}\ref{ctbg0:sddd0:scfn0}, Figure
524 \ref{fig:ctbg0:sddd0:scfn0:spga0:00}, p.
525 \pageref{fig:ctbg0:sddd0:scfn0:spga0:00}.)
526
527 The conventions are quite loose, and simply consist of assigning names
528 that suggest, in order, the application, then the page, then the
529 variable within the page.
530 If this convention is followed, applications and pages can easily
531 query for all the database records that affect them by using the
532 SQL \emph{like} clause.\footnote{It was verified that \emph{MySQL} will
533 perform such a query nearly instantly even with a million records, so long
534 as the column involved in the query is indexed and so long as the wildcard
535 part of the name is at the end.}
536
537 For example, a \emph{MySQL} query of the form\\\\
538 \texttt{SELECT * FROM tablename\\WHERE columnname LIKE 'APP\_\%' ORDER BY columnname;}\\\\
539 will very efficiently extract all records whose value in a column
540 begins with ``APP\_'', so long as the column is indexed.
541
542 Using these naming conventions, it is also possible to simulate arrays. For
543 example, a variable named\\\\
544 \texttt{APP\_EMPCOST\_PG\_RECORDDISPLAY\_EMP\_HRS\_000029\_000042}\\\\
545 might be used to represent row 29 and column 42 of the underlying variable.
546
547
548 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
549 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
550 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
551 \subsection{\emph{MySQL} Database Locking}
552 %Subsection tag: mdl0
553 \label{ctbg0:sddd0:smdl0}
554
555 The design of \emph{\productbasename{}-\productversion{}} includes
556 many tables and complex relations. In order to ensure database
557 consistency, it is necessary to ensure atomicity of operations.
558
559 The approach taken to serialize database access is:
560
561 \begin{itemize}
562 \item Serialization is accomplished via the SQL \emph{LOCK TABLES}
563 and \emph{UNLOCK TABLES} statements.
564
565 \begin{itemize}
566 \item At the start of the critical section, \emph{all} tables existing
567 in the database are locked via a single \emph{LOCK TABLES}
568 statement.\footnote{It was determined via newsgroup posts
569 that the practical limit on the number of tables that can
570 be locked in a single SQL statement is much higher---probably
571 thousands of tables---than will be encountered in practice in
572 this product. As a fallback position if locking all tables
573 proves impossible, the \emph{GET\_LOCK()}
574 function and its companion function can be used. \emph{GET\_LOCK()}
575 isn't the first choice because the name is server-global rather
576 than database global, and malicious code (in another database
577 application) could cause denial of service. Additionally, it has
578 been verified that this method handles all the important scenarios
579 such as ordinary contention, dying processes, a process that
580 terminates without releasing the lock, etc.}
581 \item At the end of the critical section, a single \emph{UNLOCK TABLES}
582 statement is executed.
583 \end{itemize}
584 \item Maintenance scripts that run hot will be written to lock and unlock so that
585 if there is collision with a web page, the web page will be delayed for only
586 a small amount of time.
587 \item A recursive locking protocol is employed in the software to simplify the case
588 of a critical section occurring within a critical section. (This ensures
589 in an orderly way
590 that large-scope critical sections are not compromised by small-scope critical
591 sections.)
592 \end{itemize}
593
594
595 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
596 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
597 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
598 \subsection{File Repository Organization}
599 %Subsection tag: fro0
600 \label{ctbg0:sddd0:sfro0}
601
602 The \emph{\productbasename{}} software needs to maintain user-uploaded
603 files in conjunction with a
604 database. All such files are aggregated into one structure
605 called the \emph{file repository}.\index{file repository}
606
607 In the type of file repository described here, each file in the repository
608 has a corresponding database record containing a unique integer index. These indices
609 are assigned automatically by \emph{MySQL} and are assigned sequentially
610 as files are added (i.e. ``1'', ``2'', ``3'', etc.).
611
612 Although
613 \emph{MySQL} has the capability to store files directly as part of
614 the database, the files are stored as distinct files directly
615 under the operating system for the following
616 reasons:
617
618 \begin{itemize}
619 \item The upper limit for the size of the individual and collective
620 files stored directly in
621 \emph{MySQL} is not known or trusted. (The behavior of
622 the *nix filesystem, on the other hand, is well-understood
623 and trusted.)
624 \item The ability to split the file repository across multiple
625 volumes (for disk capacity reasons) via symlinks must
626 be preserved.
627 \item In the event of \emph{MySQL} database corruption, the files must still
628 be easily recoverable. This constraint would not be met if the
629 files were stored directly in \emph{MySQL}.
630 \item If incremental backups are used, it is known that \emph{MySQL} tends
631 to cause an entire table of files to be backed up (this can be tens
632 or hundreds of megabytes or more), whereas an approach relying on discrete
633 files will cause only the new or modified files to be incrementally
634 backed up.
635 \end{itemize}
636
637 The following constraints and design goals for the file repository exist:
638
639 \begin{itemize}
640 \item The differential growth of disk consumption due to overhead (such as
641 directory creation) as files are added
642 should not be excessive under the assumption that indices grow linearly.
643 \item It is known that *nix systems begin to experience performance issues
644 when directories contain more than about 200 files or subdirectories (due to
645 the linear search). Any solution should not place more than about 200 files
646 or subdirectories in a directory.
647 \item The solution should facilitate symlinking to split the file
648 repository across multiple volumes.
649 \item The solution must accommodate logical indices as large as $2^{64}-1$.\footnote{This design
650 goal applies because \emph{MySQL} allows 64-bit integers to be used as the primary
651 key for database tables.}
652 \item The solution must allow files to be aged out or deleted
653 randomly with respect to the integer indices (to comply with records retention
654 policies, because they are removed from the repository, or for other reasons).
655 \end{itemize}
656
657 In order to accommodate the constraints, files are stored in a directory structure
658 based on prime moduli of the database integer index $n$.
659 The lowest level of the directory structure contains a single
660 file per directory, with the lowest-level directory named being the
661 decimal representation of the
662 integer index $n$.
663
664 The definining equations for the directory path components are supplied below.
665
666 \begin{eqnarray}
667 \label{eq:ctbg0:sddd0:sfro0:00} d & = & 160 \\
668 \label{eq:ctbg0:sddd0:sfro0:01} c_0 & = & \lfloor n / d \rfloor \bmod 7 \\
669 \label{eq:ctbg0:sddd0:sfro0:02} c_1 & = & \lfloor n / d \rfloor \bmod 11 \\
670 \label{eq:ctbg0:sddd0:sfro0:03} c_2 & = & \lfloor n / d \rfloor \bmod 13 \\
671 \label{eq:ctbg0:sddd0:sfro0:04} c_3 & = & \lfloor n / d \rfloor \bmod 89 \\
672 \label{eq:ctbg0:sddd0:sfro0:05} c_4 & = & \lfloor n / d \rfloor \bmod 97 \\
673 \label{eq:ctbg0:sddd0:sfro0:06} c_5 & = & \lfloor n / d \rfloor \bmod 101 \\
674 \label{eq:ctbg0:sddd0:sfro0:07} c_6 & = & \lfloor n / d \rfloor \bmod 103 \\
675 \label{eq:ctbg0:sddd0:sfro0:08} c_7 & = & \lfloor n / d \rfloor \bmod 107 \\
676 \label{eq:ctbg0:sddd0:sfro0:09} c_8 & = & \lfloor n / d \rfloor \bmod 109 \\
677 \label{eq:ctbg0:sddd0:sfro0:10} c_9 & = & \lfloor n / d \rfloor \bmod 113
678 \end{eqnarray}
679
680 With reference to (\ref{eq:ctbg0:sddd0:sfro0:01})
681 through (\ref{eq:ctbg0:sddd0:sfro0:10}), the relative path within a file repository
682 to the directory containing a file with database index $n$ is\\
683 ``$c_0$/$c_1$/$c_2$/$c_3$/$c_4$/$c_5$/$c_6$/$c_7$/$c_8$/$c_9$/$n$''\@.
684 Each path component $c_i$ and $n$ is the traditional human-friendly variable-length
685 representation:
686 for example, ``3'', ``25'', ```111', or ``36237456726''.
687
688 Note that the storage scheme proposed will handle indices
689 as large as $2^{64}-1$, i.e.
690
691 \begin{equation}
692 \label{eq:ctbg0:sddd0:sfro0:20}
693 d \times c_0 \times c_1 \times c_2 \times c_3 \times c_4
694 \times c_5 \times c_6 \times c_7 \times c_8 \times c_9 > 2^{64} - 1 .
695 \end{equation}
696
697 Note also that the first three
698 components ($c_0$, $c_1$, and $c_2$) are small and chosen for
699 convenient symlinking, whereas the last seven components ($c_3$ through $c_9$)
700 are chosen to increase the product rapidly while staying clear of the
701 *nix performance limit of approximately 200 entries per directory.
702
703 Two properties of the storage scheme proposed by (\ref{eq:ctbg0:sddd0:sfro0:01})
704 through (\ref{eq:ctbg0:sddd0:sfro0:10}) may require further explanation.
705
706 \begin{itemize}
707 \item The differential cost of storing a file in the repository is
708 approximately the file size (with operating system overhead)
709 plus approximately 1.0625 directories. This comes about because
710 every file requires its own directory, and because
711 every 160 files, 10 directories must be created.
712 \item If the index $n$ increases linearly, the number of files stored in
713 each directory (especially at the top levels) will be approximately
714 equal. (The reason for this is the coprimality of the divisors
715 used. The necessary proof comes from number theory, and isn't
716 included here.) This means that symlinking at the top levels will be
717 effective in evenly dividing storage requirements.
718 \end{itemize}
719
720
721 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
722 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
723 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
724 \subsection{Database Design to Support Core Functionality}
725 %Subsection tag: cfn0
726 \label{ctbg0:sddd0:scfn0}
727
728 The core functionality as described in Chapter \ref{ccfn0} consists of:
729
730 \begin{itemize}
731 \item Site navigation (\S{}\ref{ccfn0:ssng0}).
732 \item Authentication and login (\S{}\ref{ccfn0:salg0}).
733 \item Permission groups and attributes (\S{}\ref{ccfn0:sgra0}).
734 \item Notification (\S{}\ref{ccfn0:snot0}).
735 \item Action list (\S{}\ref{ccfn0:sacl0}).
736 \item Logging (\S{}\ref{ccfn0:slog0}).
737 \end{itemize}
738
739 Figure \ref{fig:ctbg0:sddd0:scfn0:spga0:00} provides an overview of the
740 tables involved in implementing the core functionality. In the figure,
741 for efficiency, note that three of the most frequently
742 used read-only tables (\emph{applications}, \emph{pages},
743 and \emph{navlines}) are implemented as lookup tables in
744 \emph{PHP} rather than
745 as \emph{MySQL} tables.\footnote{Presumably, the \emph{PHP}
746 interpreter parsing these tables is far more efficient than executing
747 an SQL query and processing the results.}
748
749 \begin{figure}
750 \centering
751 \includegraphics[width=4.6in]{c_tbg0/dbdesign01.eps}
752 \caption{User, Permission Group, Application, and Page Database Design}
753 \label{fig:ctbg0:sddd0:scfn0:spga0:00}
754 \end{figure}
755
756
757 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
758 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
759 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
760 \subsubsection{Users and Tokens}
761 %Subsubsection tag: utk0
762 \label{ctbg0:sddd0:scfn0:sutk0}
763
764 The database design includes a table of users (the \emph{users} table
765 in Figure \ref{fig:ctbg0:sddd0:scfn0:spga0:00}). Each user who can log
766 in to the system has one record in this table. As mentioned
767 in \S{}????, each user always logs in using a userid that
768 represents the user---there
769 are no userids used solely for administration.
770
771 The \emph{users} table
772 (Figure \ref{fig:ctbg0:sddd0:scfn0:spga0:00}) is related 1:1 with the
773 \emph{tokens} table.
774 Each user is optionally assigned a cryptographic token to use in
775 authenticating. Token assignment is on a per-user
776 basis, so that \emph{\productbasename{}-\productversion{}} will support:
777
778 \begin{itemize}
779 \item No users authenticating using cryptographic tokens.
780 \item Some users authenticating with cryptographic tokens, and some authenticating
781 without cryptographic tokens.
782 \item All users authenticating with cryptographic tokens.
783 \end{itemize}
784
785
786 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
787 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
788 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
789 \subsubsection{User Permission Attributes}
790 %Subsubsection tag: pga0
791 \label{ctbg0:sddd0:scfn0:spga0}
792
793 Figure \ref{fig:ctbg0:sddd0:scfn0:spga0:00} shows that the \emph{users} and
794 \emph{upermattrs} tables are related by the \emph{userupermattrs} table, providing
795 an $\infty{}:\infty{}$ mapping.
796
797 Each record in the \emph{userupermattrs} table also carries with it an
798 optional string. Such as string is interpreted as a user-specific value of the
799 related record in the \emph{upermattrs} table. As a
800 contrived example, one user may have
801 a value of MAX\_LOGINS of 2, and another user may have a value of 5.
802
803 If the optional string in the \emph{userupermattrs} table is the empty string,
804 then the $\infty{}:\infty{}$ relation effectively specifies a named set
805 of users. Such named sets are typically used to control user permissions
806 in a fine-grained way---a given group may contain the users who can add
807 products to the \emph{products} table, for example.
808
809
810 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
811 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
812 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
813 \subsubsection{User Persistent Named State}
814 %Subsubsection tag: upn0
815 \label{ctbg0:sddd0:scfn0:supn0}
816
817 User permission attributes do not change as the result of ordinary usage of
818 the \emph{\productbasename{}-\productversion{}} system. Although
819 user permission attributes can be modified, this is an administrative action
820 and does not happen often.
821
822 For state bound to a user which may change often, the
823 \emph{upns} table (Figure \ref{fig:ctbg0:sddd0:scfn0:spga0:00}) is
824 provided. This state is very similar in spirit to what may be contained
825 in the \emph{Windows} registry.
826
827 Each record in the \emph{upns} table consists of a name and a value.
828
829 For each user, the names in the \emph{upns} table must be unique (no
830 duplicates are allowed).
831
832 A naming convention is used so that each entry in the \emph{upns} table
833 is bound to a specific application and page. The \emph{upns} table is indexed
834 by name for fast retrieval.
835
836
837 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
838 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
839 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
840 \subsubsection{Sessions}
841 %Subsubsection tag: ses0
842 \label{ctbg0:sddd0:scfn0:sses0}
843
844 A \emph{session} is the relationship between the server and a client during
845 a single login (whether as a named user or a guest).
846
847 Sessions are stored in the \emph{sessions} table
848 (Figure \ref{fig:ctbg0:sddd0:scfn0:spga0:00}). Each record in the
849 \emph{sessions} table contains the session identifier, information about the
850 user, information about the time of the last actions associated with the
851 session, etc.
852
853
854 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
855 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
856 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
857 \subsubsection{Session Temporary Named State}
858 %Subsubsection tag: stn0
859 \label{ctbg0:sddd0:scfn0:sstn0}
860
861 State that should be stored associated with a session rather than a user
862 (i.e. that should be deleted when a session ends) is stored in the
863 \emph{stns} table (Figure \ref{fig:ctbg0:sddd0:scfn0:spga0:00}).
864
865 Each entry in the \emph{stns} table consists of a name and a value.
866 Within each session, each name in the \emph{stns} table must be unique.
867
868 A naming convention is used so that each entry in the \emph{stns} table
869 is bound to a specific application and page. The \emph{stns} table is indexed
870 by name for fast retrieval.
871
872
873 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
874 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
875 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
876 \subsubsection{Chain of Command}
877 %Subsubsection tag: coc0
878 \label{ctbg0:sddd0:scfn0:scoc0}
879
880 In some contexts, \emph{\productbasename{}-\productversion{}} components
881 need to make decisions based on reporting relationships between
882 employees. For example, some information about an employee should only
883 be viewable or editable by those above the employee in the chain of command.
884
885 The database contains an \emph{enterprises} table
886 (Figure \ref{fig:ctbg0:sddd0:scfn0:spga0:00}) and an
887 \emph{usersenterprises} table that provide a
888 $\infty{}:\infty{}$ mapping between \emph{users}
889 and \emph{enterprises}. A given user may belong to more than one
890 enterprise and may exist in reporting relationships in more than
891 one enterprise.
892
893 The database also contains a \emph{cocrels} table
894 (Figure \ref{fig:ctbg0:sddd0:scfn0:spga0:00}) that can capture
895 reporting relationships between employees for each enterprise.
896 Both normal reporting relationships
897 and matrix reporting relationships can be captured.
898
899
900 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
901 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
902 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
903 \subsubsection{Login Attempts}
904 %Subsubsection tag: lat0
905 \label{ctbg0:sddd0:scfn0:slat0}
906
907 The database contains a \emph{loginattempts} table
908 (Figure \ref{fig:ctbg0:sddd0:scfn0:spga0:00}).
909 The \emph{loginattempts} records unsuccessful login attempts that meet criteria
910 in order to implement security policies that involve the maximum number of
911 certain types of login attempts in a period of time.\footnote{In principle,
912 the \emph{logentries} table also contains enough information to implement
913 security policies, but the design is more versatile if a separate table
914 is used for this purpose.}
915
916
917 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
918 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
919 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
920 \subsubsection{User Templates}
921 %Subsubsection tag: utp0
922 \label{ctbg0:sddd0:scfn0:sutp0}
923
924 In a mature deployment of \emph{\productbasename{}-\productversion{}},
925 a typical user may have dozens of associated permission attributes.
926 Creating a new user would be quite tedious if a complex set of permission
927 attributes need to be created at the same time.
928
929 To make this process easier, user templates are provided via the
930 \emph{utemplates} and \emph{utemplatespermgroups} tables depicted in
931 Figure \ref{fig:ctbg0:sddd0:scfn0:spga0:00}. A user template gives
932 a one-click way to create a user with a complex set of permission attributes.
933
934 A user template contains the same type of $\infty{}:\infty{}$
935 relation to the \emph{permattrs} table as a user. Creating a new user
936 from a user template is a relatively straightforward process of copying.
937
938 In general, a user may create another user if and only if:
939
940 \begin{itemize}
941 \item The user has the permission attribute set to be able to create
942 other users.
943 \item The security level integer of the created user is greater than that of
944 the creating user.
945 \item All ranked permission attributes of the created user are inferior to those of
946 the creating user.
947 \end{itemize}
948
949
950 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
951 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
952 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
953 \subsubsection{Site Navigation}
954 %Subsubsection tag: snv0
955 \label{ctbg0:sddd0:scfn0:ssnv0}
956
957 The left navigation pane of the \emph{\productbasename{}-\productversion{}}
958 displays a hierarchical set of links to pages. The left navigation page
959 is hierarchical in the sense that links to pages may be displayed under headings
960 or sub-headings. The logic used to
961 display links is:
962
963 \begin{itemize}
964 \item Each page in the \emph{pages} table contains a set of \emph{permgroups}.
965 Any user must be a member of at least one of the set of \emph{permgroups}
966 in order for the link to the page to be displayed (and in order to use
967 the services of the page at all).
968 \item A heading or sub-heading is displayed if and only if there is at least
969 one page link under the heading or sub-heading that, based on
970 the required \emph{permgroups}, should be displayed. (Headings and
971 sub-headings automatically drop out when there are no page links under
972 them.)
973 \end{itemize}
974
975 The relationship between
976 \emph{applications}, \emph{pages}, and \emph{navlines} shown
977 in Figure \ref{fig:ctbg0:sddd0:scfn0:spga0:00} has these
978 elements:
979
980 \begin{itemize}
981 \item \emph{applications} have a $1:\infty$ relationship with the
982 \emph{pages}. Every page is a member of exactly one application.
983 \item The \emph{navlines} specify the headings and page links that may appear
984 (depending on \emph{permgroups}) in the left navigation pane. A given page
985 may appear in more than one location in the left navigation pane (hence
986 the $\infty{}:1$ relationship\footnote{With the additional caveat that
987 a page is not required to appear in the left navigation pane---some pages
988 can only be reached indirectly.}).
989 \end{itemize}
990
991 Note that the \emph{pages} and \emph{applications} tables are linked to
992 from other tables (these relationships are not shown due to complexity constraints
993 in Figure \ref{fig:ctbg0:sddd0:scfn0:spga0:00}). For
994 example, the \emph{globalvars} table is linked by page and application
995 so that the variables relevant to a page can be extracted more economically.
996
997
998 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
999 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
1000 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
1001 \subsubsection{Products and Product Components}
1002 %Subsubsection tag: pcn0
1003 \label{ctbg0:sddd0:scfn0:spcn0}
1004
1005 The \emph{products}, \emph{pcomponents}, \emph{psubcomponents},
1006 and \emph{pversions} tables in Figure \ref{fig:ctbg0:sddd0:scfn0:spga0:00}
1007 define the products that are produced. Note that a version can only
1008 be associated with a product (rather than a component or subcomponent
1009 of a product).
1010
1011 The exact semantics of what constitutes a product, product component,
1012 and product subcomponent is naturally dependent on the organization.
1013
1014
1015 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
1016 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
1017 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
1018 \subsubsection{File Repository Organization}
1019 %Subsubsection tag: fro0
1020 \label{ctbg0:sddd0:scfn0:sfro0}
1021
1022 The information maintained about the file repository files in the
1023 \emph{MySQL} database is maintained in the \emph{frfiles},
1024 \emph{frfilesfrfusages}, and \emph{frfusages} tables
1025 (Figure \ref{fig:ctbg0:sddd0:scfn0:spga0:00}). These three
1026 tables create a $\infty{}:\infty{}$ mapping between
1027 the \emph{frfiles} and \emph{frfusages} tables.
1028
1029 The \emph{frfiles} table contains one record per file in the
1030 file repository. Each of these records contains all direct information
1031 about the stored file (location, SHA1 hash value, etc.).
1032
1033 The \emph{frfilesfrfusages} and \emph{frfusages} tables are necessary because
1034 there are PHP scripts that:
1035
1036 \begin{itemize}
1037 \item Display information about a file in the file repository.
1038 \item Serve the contents of a file in the file repository.
1039 \end{itemize}
1040
1041 These scripts must be able to determine whether a given user is authorized to
1042 view information about a file repository file or download the file.
1043 The difficulty in making this determination is that the file repository is
1044 is shared among many applications. Without some sort of a hint, the process
1045 of determining whether a user may view information about a repository file
1046 or download it would be an iterative process of checking every
1047 \emph{\productbasename{}-\productversion{}} application to determine if it
1048 has involvement with the repository file and if the user has permissions for the
1049 file. The \emph{frfusages} table is a table of possible usages for a file
1050 repository file. Using this table, the applications to check for file permissions
1051 should be reduced in a typical case to one or two.
1052
1053 At the present time, each usage of a file repository file is simply
1054 an integer, and so the \emph{frfusages} is superfluous (the integer could
1055 simply be stored directly in the \emph{frfilesfrusages} table). However,
1056 the more complex schema is used in case future expansion or enhancement
1057 occurs.
1058
1059
1060 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
1061 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
1062 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
1063 \subsubsection{Global Variables}
1064 %Subsubsection tag: gvr0
1065 \label{ctbg0:sddd0:scfn0:sgvr0}
1066
1067 The database includes a table of global variables
1068 (the \emph{globalvars} table in Figure \ref{fig:ctbg0:sddd0:scfn0:spga0:00},
1069 p. \pageref{fig:ctbg0:sddd0:scfn0:spga0:00}).
1070
1071 Global variables have these uses:
1072
1073 \begin{itemize}
1074 \item Influencing the behavior of applications (global variables often override
1075 default behavior---similar to the typical behavior of \emph{Unix} environment
1076 variables). For example, the web interface to the database can be taken
1077 offline by setting a global variable.
1078 \item Mutual exclusion: for example, a global variable is used to ensure that two instances
1079 of the maintenance script don't run concurrently.
1080 \item Application persistent state: state that is not bound to a user or a session
1081 (discussed later) can be stored in global variables (similar to the behavior of
1082 the \emph{Windows} registry).
1083 \end{itemize}
1084
1085 Global variables have these essential characteristics:
1086
1087 \begin{itemize}
1088 \item The name of a global variable must be unique (duplicate names in the
1089 \emph{globalvars} table are not allowed). In order to facilitate and
1090 guarantee uniqueness, a naming convention
1091 (\S{}\ref{ctbg0:sddd0:sgsn0}, p. \pageref{ctbg0:sddd0:sgsn0}) is used that
1092 names the global variables by application then page.
1093 \item The \emph{globalvars} table is indexed by variable name.
1094 \end{itemize}
1095
1096
1097 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
1098 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
1099 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
1100 \subsubsection{Logging}
1101 %Subsubsection tag: log0
1102 \label{ctbg0:sddd0:scfn0:slog0}
1103
1104 \emph{\productbasename{}-\productversion{}} maintains a log in the form of
1105 a database table (the \emph{logentries} table in Figure \ref{fig:ctbg0:sddd0:scfn0:spga0:00},
1106 p. \pageref{fig:ctbg0:sddd0:scfn0:spga0:00}). This database table
1107 contains indexed columns so that the log can be viewed based on
1108 chronological order, application, log entry type, and security threat level.
1109
1110
1111 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
1112 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
1113 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
1114 \subsubsection{Inbox}
1115 %Subsubsection tag: inb0
1116 \label{ctbg0:sddd0:scfn0:sinb0}
1117
1118 When certain events/actions occur, one or more users should be notified.
1119 The notices are inserted into the \emph{inbox} table
1120 (Figure \ref{fig:ctbg0:sddd0:scfn0:spga0:00}).
1121
1122 Presently, only the \emph{inbox} is implemented, and is used only for
1123 automatic notifications from applications. In the future, a more general messaging
1124 system (with the ability to send/receive e-mail or the ability to send/receive
1125 messages to other users) may be implemented.
1126
1127
1128 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
1129 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
1130 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
1131 \subsubsection{Host E-mail Preferences}
1132 %Subsubsection tag: hep0
1133 \label{ctbg0:sddd0:scfn0:shep0}
1134
1135 Notifications are always sent to the \emph{inbox} and can be viewed by the user.
1136 For each user, it can be configured whether notifications are also sent to
1137 the user's e-mail address(es).
1138
1139 There are two concerns with injecting e-mail bound for remote hosts:
1140
1141 \begin{itemize}
1142 \item Some remote hosts may filter for SPAM by limiting the number of
1143 e-mails that can delivered from a certain host. With these remote hosts,
1144 e-mail injection must be rate-limited.
1145 \item A software bug could result in a large number of notifications erroneously
1146 created. Rate-limiting all e-mail injections for remote hosts is prudent.
1147 \end{itemize}
1148
1149 The \emph{hostemailprefs} table (Figure \ref{fig:ctbg0:sddd0:scfn0:spga0:00})
1150 is a table of regular expressions designed to match e-mail addresses.
1151 During the high-frequency maintenance script, the \emph{hostemailprefs}
1152 records are scanned in a specific order in an attempt to match
1153 the outgoing e-mail address. The data in the first match is used to control
1154 the generation of outgoing e-mail.
1155
1156 Note that generation of outgoing notification e-mail is simply a process of
1157 sending each message in the \emph{inbox} table subject to user preferences
1158 and rules in the \emph{hostemailprefs} table.
1159
1160
1161 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
1162 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
1163 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
1164 \section{Product Design Decisions and Discussion}
1165 %Section tag: ddc0
1166 \label{ctbg0:sddc0}
1167
1168
1169 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
1170 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
1171 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
1172 \subsection{Two-Factor Authentication}\index{two-factor authentication}
1173 %Subection tag: tfa0
1174 \label{ctbg0:sddc0:stfa0}
1175
1176 \emph{Two-factor authentication}\index{two-factor authentication} is the practice of
1177 authenticating users based on both something the user \emph{knows} (typically a password)
1178 and something the user \emph{has} (typically a cryptographic token).
1179
1180 It is anticipated that \emph{\productbasename{}} will be used from airport
1181 kiosks and other locations where password capture is a very tangible possibility.
1182
1183 The best known countermeasure against password capture and password guessing is
1184 one-time passwords\index{one-time password} (OTPs) generated by a
1185 cryptographic token.
1186
1187 OTPs generated by a cryptographic token are effective against password capture because
1188 each one-time password generated can be used only once and is useless in the future.
1189 OTP capture is not helpful to an attacker.
1190
1191 OTPs generated by a cryptographic token are effective against password guessing
1192 because the OTPs generated have an approximately uniform
1193 distribution across the space of all
1194 OTPs that can be generated. This is unlike passwords generated by humans,
1195 which tend to involve language words and may facilitate guessing.
1196
1197
1198 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
1199 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
1200 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
1201 \subsubsection{Overview of the Solution}
1202 %Subsubsection tag: ovs0
1203 \label{ctbg0:sddc0:stfa0:sovs0}
1204
1205 %Note to self: .JPG was converted to .EPS on *nix box using
1206 %"convert cckt1_01.jpg cckt1_01.eps", with no additonal options
1207 %or qualifiers. .EPS ended up to be quite large.
1208 %
1209 \begin{figure}
1210 \centering
1211 \includegraphics[width=4.6in]{c_tbg0/cckt1_01.eps}
1212 \caption{CryptoCard KT-1 Keychain Token}
1213 \label{fig:ctbg0:sddc0:stfa0:sovs0:00}
1214 \end{figure}
1215
1216 The model of token supported by \emph{\productbasename{}}
1217 is the CryptoCard\index{CryptoCard Corporation}
1218 KT-1 keychain token\index{KT-1 keychain cryptographic token}
1219 (Fig. \ref{fig:ctbg0:sddc0:stfa0:sovs0:00}).
1220
1221
1222 On a per-user basis, logins to \emph{\productbasename{}} may be either with:
1223
1224 \begin{itemize}
1225 \item Userid and password.
1226 \item Userid, password, and OTP.
1227 \end{itemize}
1228
1229 The cryptographic basis of the CryptoCard KT-1 token and similar products
1230 is that:
1231
1232 \begin{itemize}
1233 \item The token is programmed with a key that cannot be extracted\footnote{The
1234 ability to extract the key from the token is equivalent to being able
1235 to predict all future OTPs that will be generated by the token, and hence
1236 would render the token useless as a security device.}, and this key is known
1237 to the \emph{\productbasename{}} software.
1238 \item Mathematically, there is no way to reverse-engineer the key by observing
1239 OTPs generated by the token; hence there is no way to predict future
1240 OTPs generated by the token based on observing past OTPs.
1241 \end{itemize}
1242
1243 \emph{\productbasename{}} utilizes the CryptoCard KT-1 token configured
1244 so that each of the 8 displayed OTP characters can be one of 32 different
1245 possibilities.\footnote{The KT-1 token can also be configured so that
1246 each of the 8 OTP characters can be one of 64 possibilities, leading to
1247 $64^8 = 2.8 \times 10^{14}$ OTPs. The base-32
1248 OTPs were chosen because they are case-insensitive and lead to fewer user
1249 data entry errors.}
1250 The number of possible OTPs is thus $32^8 = 1.1 \times 10^{12}$.
1251 The large number of OTPs makes a brute-force attack unattractive---even with 10 guesses
1252 per second, the expected time to guess an OTP would be 1,700 years.
1253
1254 The CryptoCard KT-1 keychain token is an event-driven device---it generates
1255 sequential OTPs according to a mathematical sequence, with one OTP generated
1256 at each activation of the token. The \productbasename{} software, because
1257 it has access to the token key, is able to predict the OTPs that should be
1258 generated by the token. The \productbasename{} software also allows approximately
1259 three\footnote{Configurable: three is the default value.}
1260 of the predicted sequential OTPs to be used, in case the KT-1 token was activated
1261 and the OTP never used.\footnote{This might happen, for example, if the token button
1262 is accidentally pressed by objects in the user's pockets, or if children are
1263 allowed to play with the token.}
1264
1265 It can occur, however, that the KT-1 token falls out of synchronization with
1266 the \productbasename{} software. In this case, the token allows a resynchronization
1267 procedure where the user enters a resynchronization string (8 digits,
1268 allowing for $10^8$ different values). When the token is supplied
1269 with a resynchronization string, it resets its internal state and provides
1270 an OTP. This procedure allows the token and the \productbasename{} software
1271 to be brought back into synchronization.
1272
1273 Note to self: in conversation with Bill LaHam in late October 2009, Bill indicated
1274 that the traditional approach with tokens is to have an inner window and an outer
1275 window. A typical inner window might be of size 3, and a typical outer window might
1276 be of size 1000.
1277
1278 \begin{itemize}
1279 \item If the token value falls within the inner window, it is authenticated without
1280 any other verification steps.
1281 \item If the token value is not within the inner window but is within the outer
1282 window, two (additional?) consecutive values are required for authentication.
1283 \item If the token value is not within the inner window and not within the
1284 outer window, some sort of resynchronization is required.
1285 \end{itemize}
1286
1287 The size of the inner window is a major security risk (it raises the probability
1288 of a successful guess), so it should be small. The outer window is not a security
1289 concern at all.
1290
1291 Need to incorporate the information from Bill into this document and the
1292 strategy in this documennt.
1293
1294
1295 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
1296 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
1297 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
1298 \subsubsection{Additional Prudent User Authentication Practices}
1299 %Subsubsection tag: aap0
1300 \label{ctbg0:sddc0:stfa0:saap0}
1301
1302 Even when OTPs are employed, it is not prudent to allow an attacker
1303 a large number of authentication attempts. The following
1304 prudent practices are also used by the \productbasename{} software.
1305
1306 \begin{enumerate}
1307 \item Resynchronization strings are provided by the server, are generated
1308 as sequential values (``00000000'', ``00000001'', ``00000002'', etc.),
1309 and are only reused with a period of $10^8$. (This is designed to
1310 elmiminate an attacker's ability to observe how a token responds to
1311 a specific resynchronization string and to reuse this information as
1312 part of an attack.)
1313 \item Unsuccessful authentication attempts that involve an invalid userid
1314 are logged but otherwise simply ignored.
1315 \item Unsuccessful authentication attempts that involve a valid userid but
1316 both invalid password and invalid OTP are logged but otherwise
1317 simply ignored.
1318 \item Unsuccessful authentication attempts involving a valid userid and
1319 either a valid password and invalid OTP or invalid password and valid
1320 OTP\footnote{In the case of a user for whom two-factor authentication
1321 is not enabled, valid userid and invalid password are treated as described
1322 here---the key element is that the attacker appears to be ``one piece''
1323 away from a successful attack.}
1324 are treated more aggressively because this case hints at an attacker
1325 who has obtained a user's password but has no token or has obtained a token
1326 but does not have the user's password, and is ``fishing'' for the missing
1327 piece. If a sufficient number of these attacks directed at the userid have
1328 occurred from the same IP in a short period of time, login ability for
1329 this userid from the affected IP is silently disabled for a period of
1330 time.\footnote{\emph{Silently} means that the web interface will only indicate
1331 unsuccessful authentication, and will give no indication that a probable attack
1332 has been detected or that authentication for the affected userid from the
1333 affected IP is temporarily impossible. \emph{Disabled} means that even if
1334 correct authentication credentials are provided, they will be rejected. The
1335 purpose of this policy is to eliminate the ability of an attacker to try large
1336 numbers of attacks in a short period of time, and to deny an attacker information
1337 about how to better mount an attack.}
1338 \end{enumerate}
1339
1340
1341 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
1342 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
1343 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
1344 \subsection{Per-User Authentication and Administrative Rights}
1345 %Subsection tag: pua0
1346 \label{ctbg0:sddc0:spua0}
1347
1348 \emph{\productbasename{}-\productversion{}} has no notion of an
1349 ``administrative'' or ``master'' password. Each individual user
1350 logs in using a user-ID identifying themselves, even to perform
1351 administrative tasks.
1352
1353 Tasks are divided into two groups:
1354
1355 \begin{itemize}
1356 \item Ordinary tasks (that typically view data or moves workproducts
1357 through a process).
1358 \item Administrative tasks that:
1359 \begin{itemize}
1360 \item Represent administration of the \emph{\productbasename{}-\productversion{}}
1361 software, rather than usage of the software; AND/OR
1362 \item Are sensitive to mistakes, and could destroy or corrupt
1363 data.
1364 \end{itemize}
1365 \end{itemize}
1366
1367 \emph{\productbasename{}-\productversion{}} allows two types of logins:
1368
1369 \begin{itemize}
1370 \item \emph{Normal login}: the user has priveleges only to perform
1371 non-administrative tasks.
1372 \item \emph{Administrative login}: the user has priveleges to perform
1373 non-administrative and administrative tasks.
1374 \end{itemize}
1375
1376 In order to perform a normal login, the user simply enters their
1377 user-ID (``\emph{jsmith}'', for example) as the user-ID when logging in.
1378
1379 In order to perform an administrative login, the user enters their
1380 user-ID postfixed with an asterisk (``\emph{jsmith*}'', for
1381 example as the user-ID when logging in. When a user has performed an
1382 administrative login, the color scheme used for the web pages
1383 is based on the color red rather than on blues and grays.
1384
1385 The only way to switch between normal and administrative logins
1386 is by logging out and logging in again.
1387
1388
1389 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
1390 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
1391 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
1392 \subsection{\emph{su} Logins}
1393 %Subsection tag: sul0
1394 \label{ctbg0:sddc0:ssul0}
1395
1396 \index{su login@\emph{su} login}It is helpful in some
1397 situations to be able to log in as a different user. Such logins are
1398 called \emph{su} logins (after the *nix \emph{su} command). These situations
1399 include:
1400
1401 \begin{itemize}
1402 \item Testing.
1403 \item Performing actions on behalf of other users.
1404 \end{itemize}
1405
1406 In order to \emph{su} as another user, the user logging in
1407 must enter a user-ID of the form ``\emph{actualuser as suuser}''
1408 as the user-ID when logging in. ``\emph{actualuser as suuser*}'' can
1409 also be used for an \emph{su} administrative login.
1410
1411 In order to perform an \emph{su} login as another user, a user
1412 must have strictly superior priveleges. Specifically:
1413
1414 \begin{itemize}
1415 \item The \emph{seclvl} of the actual user must be
1416 a smaller integer than the \emph{seclvl} of the \emph{su} user.
1417 \item The actual user must have at least every permission attribute
1418 that the \emph{su} user has.
1419 \item For those permission attributes that are ranked, the ranking
1420 must be at least as great as the \emph{su} user.
1421 \end{itemize}
1422
1423 Once the login is complete, the \emph{su} login is indistinguishable from an
1424 actual login except for the log entries. The session maintained does
1425 not contain any state to indicate that it represents an \emph{su} login.
1426
1427
1428 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
1429 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
1430 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
1431 \subsection{Multiple Logins}
1432 %Subsection tag: mlo0
1433 \label{ctbg0:sddc0:smlo0}
1434
1435 The maximum number of logins per user is a global configuration
1436 constant, defined in the \texttt{config.inc} \emph{PHP} file.
1437 The default value is 3.
1438
1439 If the maximum number of logins is reached and another user
1440 successfully authenticates with the
1441 same user-ID, the session with the oldest creation time is destroyed (forcibly
1442 logging out this instance of the user).
1443
1444
1445 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
1446 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
1447 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
1448 \subsection{The Standard Hash Function}
1449 %Subection tag: shf0
1450 \label{ctbg0:sddc0:sshf0}
1451
1452 The \index{standard hash function}\emph{standard hash function} is the
1453 standard way that the \emph{\productbasename{}-\productversion{}} software
1454 maps between a number of arbitrary input arguments and a 160-bit
1455 SHA1 hash. The standard hash function involves mixing
1456 the input arguments with a secret hash key
1457 (described in \S{}\ref{ctbg0:sdty0:sthk0}).
1458
1459 If `+' is used to represent the string concatenation operation, all
1460 arguments $a_i$ that are not strings are converted to string format, then the
1461 SHA1 hash is applied to the concatenation of the secret hash key $k_h$ and the
1462 arguments $a_i$ as described by the first few patterns below.
1463
1464 \begin{eqnarray}
1465 \nonumber
1466 SHF_1(a_1) & = & SHA1(k_h + a_1 + k_h) \\
1467 \label{eq:ctbg0:sddc0:sshf0:01}
1468 SHF_2(a_1, a_2) & = & SHA1(k_h + a_1 + k_h + a_2 + k_h) \\
1469 \nonumber
1470 SHF_3(a_1, a_2, a_3) & = & SHA1(k_h + a_1 + k_h + a_2 + k_h + a_3 + k_h)
1471 \end{eqnarray}
1472
1473 Note that the hash functions above are designed so that it should be
1474 impossible for an attacker to predict the hash that will be generated
1475 for a given set of input arguments $a_i$ unless the hash key $k_h$ has
1476 been compromised.
1477
1478
1479 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
1480 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
1481 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
1482 \subsection{Storage of User Passwords}
1483 %Subection tag: sup0
1484 \label{ctbg0:sddc0:ssup0}
1485
1486 It is generally known that individuals tend to choose identical or similar
1487 passwords across many different computing applications. For that reason, it
1488 is important to safeguard the passwords used with
1489 \emph{\productbasename{}-\productversion{}}. Although
1490 \emph{\productbasename{}-\productversion{}} may be a relatively unimportant
1491 product to a user, the other software products with which the user is
1492 unwisely using the same password may be important.
1493 It is important to protect passwords.
1494
1495 Passwords are never stored in \emph{\productbasename{}-\productversion{}}.
1496 Instead, the $SHF1(\cdot{})$ of the password (as described in
1497 Eq. \ref{eq:ctbg0:sddc0:sshf0:01}) is stored.
1498
1499 It is possible, although extremely unlikely, that two non-identical
1500 passwords would have the same stored hash. Assuming that
1501 a typical user is comfortable using 62 characters (26 lower-case letters, 26 upper-case
1502 letters, and 10 digits) as part of a password, an approximation of how many
1503 password characters $n$ a 160-bit hash is equivalent to can be obtained by
1504 solving:
1505
1506 \begin{equation}
1507 62^n = 2^{160}
1508 \end{equation}
1509
1510 \begin{equation}
1511 n = \frac{160 \log 2}{\log 62} \approx 27
1512 \end{equation}
1513
1514 \noindent{}Thus, a hash collision involving two different typical passwords is
1515 \emph{very} unlikely.
1516
1517 If the stored password hash is compromised but the hash key is not, no attack
1518 is possible except brute-force password guessing (with no advantage gained
1519 due to compromise of the stored password hash).
1520
1521 If both the stored password hash and the hash key are compromised, the best
1522 attack possible is a dictionary attack. This may or may not be fruitful,
1523 depending on the strength of password chosen by the user.
1524
1525
1526 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
1527 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
1528 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
1529 \subsection{Internal Representation of Time}
1530 %Subection tag: rti0
1531 \label{ctbg0:sddc0:srti0}
1532
1533 It is very common for a project to involve individuals from several
1534 countries. In this context, it is important to have no ambiguity
1535 about the values of time recorded in a database.
1536
1537 The following design decisions have been made:
1538
1539 \begin{itemize}
1540 \item All stored time values corresponding to events will
1541 be in \index{UTC}UTC.
1542 \item In many contexts, the stored time values will also
1543 be presented in local time. (However,
1544 presentation in local time alone is strongly discouraged---UTC should be the norm
1545 for collaboration.)
1546 \item The calendaring range for date functionality will be
1547 from 1900 through 2999.\footnote{This represents a
1548 span of approximately 34,713,000,000 seconds. Although this
1549 exceeds the range of a 32-bit representation, it comfortably
1550 fits in a 64-bit representation.}
1551 \end{itemize}
1552
1553 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
1554 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
1555 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
1556 \section{\emph{PHP} Design Decisions and Discussion}
1557 %Section tag: php0
1558 \label{ctbg0:sphp0}
1559
1560
1561 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
1562 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
1563 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
1564 \subsection{Native Integer Size}
1565 %Subsection tag: nis0
1566 \label{ctbg0:sphp0:snis0}
1567
1568 Prior to \emph{PHP} 5, \emph{PHP} integers were the same size as the native
1569 integer of the underlying machine. With some machines this is 32 bits, and with
1570 other machines this is 64 bits.
1571
1572 In the case of a 32-bit integer, the range of values that can be represented
1573 by an integer $x$ is
1574
1575 \begin{eqnarray}
1576 -(2^{31}) & \leq \; x \; \leq & 2^{31} - 1\\
1577 \nonumber -2,147,483,648 & \leq \; x \; \leq & 2,147,483,647 .
1578 \end{eqnarray}
1579
1580 It is necessary to ensure that 64-bit integer arithmetic is available from
1581 \emph{PHP} for the following reasons:
1582
1583 \begin{itemize}
1584 \item Certain of the database tables may exceed $2^{31}-1$ records or,
1585 due to addition and deletion of records, have key values that
1586 exceed $2^{31}-1$.
1587 \item The number of seconds since the Unix epoch will exceed $2^{31}-1$ seconds
1588 in 2037 A.D\@. \emph{\productbasename{}} must be able to perform
1589 date calculations further into the future than 2037 A.D., and so
1590 integers exceeding 32 bits in size would be convenient.
1591 \end{itemize}
1592
1593 To work around the limitations of 32-bit integers, the following strategy
1594 is used:
1595
1596 \begin{itemize}
1597 \item Integers that may exceed 32 bits are represented as strings rather than
1598 as integers, and \emph{PHP}'s \emph{bcmath} library is used to manipulate
1599 these strings.
1600 \item In issuing \emph{MySQL} statements that specify integers larger than 32 bits,
1601 no special action is required, as an SQL statement is ultimately only a string.
1602 However, when obtaining result sets from \emph{MySQL} that may involve
1603 integers larger than 32 bits, special SQL statements that cast the portions of
1604 the result set to a string are used.
1605 \end{itemize}
1606
1607 The strategy described above will work equally well with \emph{PHP} when
1608 64-bit integers are directly supported, but with slight inefficiency.
1609
1610
1611 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
1612 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
1613 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
1614 \section{Web Interface Design Decisions and Discussion}
1615 %Section tag: wid0
1616 \label{ctbg0:swid0}
1617
1618
1619 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
1620 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
1621 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
1622 \subsection{Client IP Address Modified During Session}
1623 %Subsection tag: ipa0
1624 \label{ctbg0:swid0:sipa0}
1625
1626 Newsgroup posters have identified that an IP address may shift during a
1627 session (due to DHCP lease lifetimes and so on). For this reason, an
1628 IP address that shifts during a session will result in a warning in the
1629 logs rather than termination of the session.\footnote{Termination of the
1630 session is a forced immediate logout.}
1631
1632
1633 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
1634 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
1635 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
1636 \section{\emph{PHP}-Spawned Program Design Decisions and Discussion}
1637 %Section tag: phs0
1638 \label{ctbg0:sphs0}
1639
1640
1641 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
1642 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
1643 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
1644 \section{\emph{cron}-Job Design Decisions and Discussion}
1645 %Section tag: cjd0
1646 \label{ctbg0:scjd0}
1647
1648
1649 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
1650 \noindent\begin{figure}[!b]
1651 \noindent\rule[-0.25in]{\textwidth}{1pt}
1652 \begin{tiny}
1653 \begin{verbatim}
1654 $RCSfile: c_tbg0.tex,v $
1655 $Source: /home/dashley/cvsrep/e3ft_gpl01/e3ft_gpl01/webprojs/pamc/gen_a/docs/manual/man_a/c_tbg0/c_tbg0.tex,v $
1656 $Revision: 1.35 $
1657 $Author: dashley $
1658 $Date: 2009/11/01 02:42:55 $
1659 \end{verbatim}
1660 \end{tiny}
1661 \noindent\rule[0.25in]{\textwidth}{1pt}
1662 \end{figure}
1663
1664 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
1665 %$Log: c_tbg0.tex,v $
1666 %Revision 1.35 2009/11/01 02:42:55 dashley
1667 %Edits.
1668 %
1669 %Revision 1.34 2007/07/13 02:38:04 dashley
1670 %Edits.
1671 %
1672 %Revision 1.33 2007/07/13 01:19:57 dashley
1673 %Edits.
1674 %
1675 %Revision 1.32 2007/07/11 14:31:40 dashley
1676 %Edits.
1677 %
1678 %Revision 1.31 2007/07/07 23:12:54 dashley
1679 %Edits.
1680 %
1681 %Revision 1.30 2007/07/07 03:49:58 dashley
1682 %Edits.
1683 %
1684 %Revision 1.29 2007/07/07 03:31:53 dashley
1685 %Edits.
1686 %
1687 %Revision 1.28 2007/07/04 22:41:27 dashley
1688 %Edits.
1689 %
1690 %Revision 1.27 2007/07/04 05:09:24 dashley
1691 %Edits.
1692 %
1693 %Revision 1.26 2007/07/02 01:32:50 dashley
1694 %Edits.
1695 %
1696 %Revision 1.25 2007/07/01 03:07:14 dashley
1697 %Edits.
1698 %
1699 %Revision 1.24 2007/06/24 20:21:55 dashley
1700 %Edits.
1701 %
1702 %Revision 1.23 2007/06/24 16:35:48 dashley
1703 %Edits.
1704 %
1705 %Revision 1.22 2007/06/24 02:16:50 dashley
1706 %Edits.
1707 %
1708 %Revision 1.21 2007/06/24 00:42:20 dashley
1709 %Edits.
1710 %
1711 %Revision 1.20 2007/06/23 22:16:10 dashley
1712 %Safety checkin before graphics file renaming.
1713 %
1714 %Revision 1.19 2007/06/21 03:26:10 dashley
1715 %Edits.
1716 %
1717 %Revision 1.18 2007/06/21 03:21:32 dashley
1718 %Edits.
1719 %
1720 %Revision 1.17 2007/06/21 03:09:39 dashley
1721 %Edits.
1722 %
1723 %Revision 1.16 2007/06/14 01:59:36 dashley
1724 %Edits.
1725 %
1726 %Revision 1.15 2007/06/10 18:03:20 dashley
1727 %Edits.
1728 %
1729 %Revision 1.14 2007/06/10 16:04:12 dashley
1730 %Edits.
1731 %
1732 %Revision 1.13 2007/06/10 05:01:40 dashley
1733 %Edits.
1734 %
1735 %Revision 1.12 2007/06/10 03:42:30 dashley
1736 %Edits.
1737 %
1738 %Revision 1.11 2007/06/10 02:30:17 dashley
1739 %Initial checkin.phpstatic01.dsf
1740 %
1741 %Revision 1.10 2007/06/07 20:05:20 dashley
1742 %Edits.
1743 %
1744 %Revision 1.9 2007/06/07 05:03:20 dashley
1745 %Edits.
1746 %
1747 %Revision 1.8 2007/06/06 01:55:08 dashley
1748 %Multiply-defined label corrected.
1749 %
1750 %Revision 1.7 2007/06/06 00:32:07 dashley
1751 %Edits.
1752 %
1753 %Revision 1.6 2007/06/05 15:47:12 dashley
1754 %Structural edits.
1755 %
1756 %Revision 1.5 2007/06/05 00:39:55 dashley
1757 %Edits.
1758 %
1759 %Revision 1.4 2007/06/04 03:26:55 dashley
1760 %Edits.
1761 %
1762 %Revision 1.3 2007/06/03 23:15:27 dashley
1763 %Edits.
1764 %
1765 %Revision 1.2 2007/06/03 07:57:10 dashley
1766 %Edits.
1767 %
1768 %Revision 1.1 2007/06/03 07:16:08 dashley
1769 %Initial checkin.
1770 %
1771 %End of $RCSfile: c_tbg0.tex,v $.

dashley@gmail.com
ViewVC Help
Powered by ViewVC 1.1.25