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

Annotation 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 - (hide annotations) (download) (as text)
Sat Oct 8 04:30:47 2016 UTC (7 years, 11 months ago) by dashley
File MIME type: application/x-tex
File size: 80129 byte(s)
Initial commit.
1 dashley 19 %$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