Back out the randkey changes (revision 1.11)
[krb5.git] / doc / kadm5 / api-server-design.tex
1 \documentstyle[12pt,fullpage,changebar,rcsid]{article}
2
3 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
4 %% Make _ actually generate an _, and allow line-breaking after it.
5 \let\underscore=\_
6 \catcode`_=13
7 \def_{\underscore\penalty75\relax}
8 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
9
10 \rcs$Id$
11
12 \setlength{\parskip}{.7\baselineskip}
13 \setlength{\parindent}{0pt}
14
15 \def\secure{OV*Secure}
16 \def\v#1{\verb+#1+}
17 \def\k#1{K$_#1$}
18
19 \title{OV*Secure Admin Server \\ Implementation Design\thanks{\rcsId}}
20 \author{Barry Jaspan}
21
22 \begin{document}
23
24 \sloppy
25 \maketitle
26
27 {\setlength{\parskip}{0pt}\tableofcontents}
28
29 \section{Overview}
30
31 The admin server is implemented as a nearly-stateless transaction
32 server, where each admin API function represents a single transaction.
33 No per-client or per-connection information is stored; only local
34 database handles are maintained between requests.
35
36 The admin API is exported via an RPC interface that hides all details
37 about network encoding, authentication, and encryption of data on the
38 wire.  The RPC mechanism does, however, allow the server to access the
39 underlying authentication credentials for authorization purposes.
40
41 The admin server accesses a total of three databases.
42 \begin{itemize}
43 \item The master Kerberos database is used to store all the
44 information that the Kerberos server understands, thus allowing the
45 greatest functionality with no modifications to a standard KDC.  
46
47 \item The admin principal database stores \secure{}-specific per-principal
48 information. 
49
50 \item The policy database stores \secure{} policy information.
51 \end{itemize}
52
53 The per-principal information stored in the admin principal database
54 consists of the principal's policy name and an array of the
55 principal's previous keys.  The old keys are stored encrypted in the
56 key of the special principal ``ovsec_adm/history'' that is created by
57 ovsec_adm_create.  Since a change in ovsec_adm/history's key renders
58 every principal's key history array useless, it can only be changed
59 using the ovsec_adm_edit utility; that program will reencrypt every
60 principal's key history in the new key.\footnote{ovsec_adm_edit has
61 not yet been implemented, and there are currently no plans to
62 implement it.}  The admin server refuses all requests to change
63 ovsec_adm/history's key.
64
65 \section{Main}
66
67 The admin server starts by trapping all fatal signals and directing
68 them to a cleanup-and-exit function.  It then creates and exports the
69 RPC interface and enters its main loop.
70
71 The main loop dispatches all incoming requests to the RPC mechanism.
72 After 15 seconds of inactivity, the server closes all open databases;
73 each database will be automatically reopened by the API function
74 implementations as necessary.
75
76 \section{Remote Procedure Calls}
77
78 The RPC for the Admin system will be based on SUNRPC.  SUNRPC is used
79 because it is a well-known, portable RPC mechanism.  The underlying
80 external data representation (xdr) mechanisms for wire encapsulation
81 are well-known and extensible.
82
83 Authentication to the admin server will be handled by adding a GSS-API
84 authentication type within the existing SUNRPC structure.  This will
85 require code modifications to SUNRPC, but the API and wire protocol do
86 not need to change.  This may affect whether the RPC will use UDP or
87 TCP; although all the admin functions are stateless, the GSS-API
88 authentication binding will not be and it might be easier to use TCP
89 for this reason.
90
91 \section{Database Record Types}
92 \label{sec:db-types}
93
94 \subsection{Admin Principal, osa_princ_ent_t}
95
96 The admin principal database stores records of the type
97 osa_princ_ent_t (declared in $<$ovsec_admin/adb.h$>$), which is the
98 subset of the ovsec_kadm_principal_ent_t structure that is not stored
99 in the Kerberos database plus the necessary bookkeeping information.
100 The records are keyed by the ASCII representation of the principal's
101 name, including the trailing NULL.
102
103 \begin{verbatim}
104 typedef struct _osa_princ_ent_t {
105         krb5_principal name;
106
107         char * policy;
108         u_int32 aux_attributes;
109
110         u_int32 num_old_keys;
111         u_int32 next_old_key;
112         krb5_kvno admin_history_kvno;
113         krb5_encrypted_keyblock *old_keys;
114 } osa_princ_ent_rec, *osa_princ_ent_t;
115 \end{verbatim}
116
117 The fields that are different from ovsec_kadm_principal_ent_t are:
118
119 \begin{description}
120 \item[num_old_keys] The number of previous keys in the old_keys array.
121 This value must be 0 $\le$ num_old_keys $<$ pw_history_num.
122
123 \item[next_old_key] The index into old_keys where the next key should
124 be inserted.  This value must be 0 $\le$ next_old_key $\le$
125 num_old_keys.
126
127 \item[admin_history_kvno] The key version number of the admin/history
128 principal's key used to encrypt the values in old_keys.  If the admin
129 server finds that admin/history's kvno is different from the value in
130 this field, an error message is logged.  (XXX where?)
131
132 \item[old_keys] The array of the principal's previous keys, each
133 encrypted in the admin/history key.  There are num_old_keys elements.
134 \end{description}
135
136 \subsection{Policy, osa_policy_ent_t}
137
138 The policy database stores records of the type osa_policy_ent_t
139 (declared in $<$ovsec_admin/adb.h$>$) , which is all of
140 ovsec_kadm_policy_ent_t plus necessary bookkeeping information.  The
141 records are keyed by the policy name.
142
143 \begin{verbatim}
144 typedef struct _osa_policy_ent_t {
145         char *policy;
146
147         u_int32 pw_min_life;
148         u_int32 pw_max_life;
149         u_int32 pw_min_length;
150         u_int32 pw_min_classes;
151         u_int32 pw_history_num;
152
153         u_int32 refcnt;
154 } osa_policy_ent_rec, *osa_policy_ent_t;
155 \end{verbatim}
156
157 \subsection{Kerberos, krb5_db_entry}
158
159 The Kerberos database stores records of type krb5_db_entry, which is
160 defined in the $<$krb5/kdb.h$>$ header file.
161
162 \begin{verbatim}
163 typedef struct _krb5_encrypted_keyblock {
164     krb5_keytype keytype;
165     int length;
166     krb5_octet *contents;
167 } krb5_encrypted_keyblock;
168
169 typedef struct _krb5_db_entry {
170     krb5_principal principal;
171     krb5_encrypted_keyblock key;
172     krb5_kvno kvno;
173     krb5_deltat max_life;
174     krb5_deltat max_renewable_life;
175     krb5_kvno mkvno;
176     
177     krb5_timestamp expiration;
178     krb5_timestamp pw_expiration;
179     krb5_timestamp last_pwd_change;
180     krb5_timestamp last_success;   
181     
182     krb5_timestamp last_failed;
183     krb5_kvno fail_auth_count;
184     
185     krb5_principal mod_name;
186     krb5_timestamp mod_date;
187     krb5_flags attributes;
188     krb5_int32 salt_type:8,
189                salt_length:24;
190     krb5_octet *salt;
191     krb5_encrypted_keyblock alt_key;
192     krb5_int32 alt_salt_type:8,
193                alt_salt_length:24;
194     krb5_octet *alt_salt;
195     
196     krb5_int32 expansion[8];
197 } krb5_db_entry;
198 \end{verbatim}
199
200 The interpretation of most of these fields is the same as given in the
201 ``Principals, ovsec_kadm_principal_ent_t'' section of the functional
202 specification.  The fields that are not defined there are not used by
203 \secure{}; however, the admin server preserves the value of any fields
204 it does not understand.
205
206 \section{Database Access Methods}
207
208 \subsection{Principal and Policy Databases}
209
210 This section describes the database abstraction used for the admin
211 principal and policy databases.  Since both databases export
212 equivalent functionality, the API is only described once.  The
213 character T is used to represent both ``princ'' and ``policy''. The
214 location of the principal database is defined by the \#define
215 PRINCIPAL_DB (``/krb5/ovsec_principal.db'') in $<$ovsec_admin/adb.h$>$. The
216 location of the policy database is defined by the \#define POLICY_DB
217 (``/krb5/ovsec_policy.db'') in $<$ovsec_admin/adb.h$>$.
218
219 Note that this is {\it only} a database abstraction.  All functional
220 intelligence, such as maintaining policy reference counts or sanity
221 checking, must be implemented above this layer.
222
223 Prototypes for the osa functions are supplied in
224 $<$ovsec_admin/adb.h$>$. The routines can be found (in the first
225 relase) in ``stage/lib/libadb.a''. They require linking with the
226 Berkely DB library (``stage/lib/libdb.a''). [Note: We needed to remove
227 the dbm compatibility routines from libdb.a because we want to leave
228 KDB library alone in case somebody wants to run a stock MIT KDC with
229 our admin server.]
230
231 The database routines use com_err for error codes.  The error code
232 table name is ``adb'' and the offsets are the same as the order
233 presented here. The error table header file is
234 $<$ovsec_admin/adb_err.h$>$. Callers of the OSA routines should first call
235 init_adb_err_tbl() to initialize the database table.
236
237 \begin{description}
238 \item[OSA_ADB_OK] Operation successful.
239 \item[OSA_ADB_FAILURE] General failure.
240 \item[OSA_ADB_DUP] Operation would create a duplicate database entry.
241 \item[OSA_ADB_NOENT] Named entry not in database.
242 \item[OSA_ADB_BAD_PRINC] The krb5_principal structure is invalid.
243 \item[OSA_ADB_BAD_POLICY] The specified policy name is invalid.
244 \item[OSA_ADB_XDR_FAILURE] The principal or policy structure cannot be
245 encoded for storage.
246 \end{description}
247
248 Database functions can also return system errors.  Unless otherwise
249 specified, database functions return OSA_ADB_OK.
250
251 \begin{verbatim}
252 osa_adb_ret_t
253 osa_adb_open_T(osa_adb_T_t *db, char *filename);
254 \end{verbatim}
255 %
256 Open the database named filename.  Returns OSA_ADB_FAILURE if it
257 cannot open the database.
258
259 \begin{verbatim}
260 osa_adb_ret_t
261 osa_adb_close_T(osa_adb_T_t db);
262 \end{verbatim}
263 %
264 Close an open database.
265
266 \begin{verbatim}
267 osa_adb_ret_t
268 osa_adb_create_T(osa_adb_T_t db, osa_T_ent_t entry);
269 \end{verbatim}
270 %
271 Adds the entry to the database.  All fields are defined.  Returns
272 OSA_ADB_DUP if it already exists.
273
274 \begin{verbatim}
275 osa_adb_ret_t
276 osa_adb_destroy_T(osa_adb_T_t db, osa_T_t name);
277 \end{verbatim}
278
279 Removes the named entry from the database.  Returns OSA_ADB_NOENT if
280 it does not exist.
281
282 \begin{verbatim}
283 osa_adb_ret_t
284 osa_adb_get_T(osa_adb_T_t db, osa_T_t name,
285         osa_princ_ent_t *entry); 
286 \end{verbatim}
287
288 Looks up the named entry in the db, and returns it in *entry in
289 allocated storage that must be freed with osa_adb_free_T.  Returns
290 OSA_ADB_NOENT if name does not exist, OSA_ADB_MEM if memory cannot be
291 allocated.
292
293 \begin{verbatim}
294 osa_adb_ret_t
295 osadb_adb_put_T(osa_adb_T_t db, osa_T_ent_t entry);
296 \end{verbatim}
297
298 Modifies the existing entry named in entry.  All fields must be filled
299 in.  Returns OSA_DB_NOENT if the named entry does not exist.  Note
300 that this cannot be used to rename an entry; rename is implemented by
301 deleting the old name and creating the new one (NOT ATOMIC!).
302
303 \begin{verbatim}
304 void osa_adb_free_T(osa_T_ent_t);
305 \end{verbatim}
306
307 Frees the memory associated with an osa_T_ent_t allocated by
308 osa_adb_get_T.
309
310 \begin{verbatim}
311 typedef osa_adb_ret_t (*osa_adb_iter_T_func)(void *data,
312                                     osa_T_ent_t entry);
313
314 osa_adb_ret_t osa_adb_iter_T(osa_adb_T_t db, osa_adb_iter_T_func func, 
315                     void *data);
316 \end{verbatim}
317
318 Iterates over every entry in the database.  For each entry ent in the
319 database db, the function (*func)(data, ent) is called.  If func
320 returns an error code, osa_adb_iter_T returns an error code.  If all
321 invokations of func return OSA_ADB_OK, osa_adb_iter_T returns
322 OSA_ADB_OK.  The function func is permitted to access the database,
323 but the consequences of modifying the database during the iteration
324 are undefined.
325
326 \subsection{Kerberos Database}
327
328 Kerberos uses dbm to store krb5_db_entry records.  It can be accessed
329 and modified in parallel with the Kerberos server, using functions
330 that are defined inside the KDC and the libkdb.a.
331
332 \subsubsection{Database Manipulation Functions}
333
334 The following functions are declared in \v{lib/kdb/kdb_dbm.c} in the
335 Kerberos sources and are available in libkdb.a.  They can return the
336 following error codes; error codes that can be returned by any
337 function are indicated with a ``*'' and are not listed specifically
338 for each function.
339
340 \begin{description}
341 \item[* KRB5_KDB_NOTINITED] The database is not open; call
342 krb5_dbm_db_init.
343 \item[* KRB5_KDB_CANTLOCK_DB] The necessary lock cannot be acquired.  Try
344 again later.
345 \item[* system errors] An error occurred accessing the database files.
346 \item[KRB5_KDB_DB_INUSE] The database was modified without the use
347 of proper locking.\footnote{This error occurs when the entire database
348 is swapped out from the under the process, say by a kdb5_edit restore.
349 It can only be returned by krb5_db_get_principal.  It is not yet clear
350 what a program should do when it gets this error.}
351 \item[KRB5_KDB_NOENTRY] The principal to be deleted is not
352 in the database.
353 \end{description}
354
355 \begin{verbatim}
356 krb5_dbm_db_init(void)
357 \end{verbatim}
358
359 Opens the Kerberos database file (but does not actually call
360 dbm_open).  This can be called even if the database is already open,
361 in which case it just returns success.
362
363 \begin{verbatim}
364 krb5_dbm_db_fini(void)
365 \end{verbatim}
366
367 Closes the database file; this MUST be called before the process
368 exits.  Returns KRB5_KDB_DBNOTINITED if the database isn't open, but
369 that isn't really a fatal error.
370
371 \begin{verbatim}
372 krb5_dbm_get_principal(krb5_principal searchfor, 
373         krb5_db_entry *entries, int *nentries, krb5_boolean *more)
374 \end{verbatim}
375
376 Search the database for the principal searchfor and write the results
377 into *entries.  The interface is set up to handle wildcard gets, but
378 the code doesn't handle it: *nentries is assumed to be 1, and *more is
379 always returned as 0.
380
381 This function does not retry if the database cannot be locked; that is
382 up to the caller.  
383
384 Returns KRB5_KDB_DB_INUSE.
385
386 \begin{verbatim}
387 krb5_dbm_put_principal(krb5_db_entry *entries, int *nentries)
388 \end{verbatim}
389
390 Stores *nentries elements from the entries array into the database.
391 On return *nentries is set to the number of entries actually written;
392 the first *nentries entries will have been written, even if an error
393 pis returned.
394
395 This function does not retry if the database cannot be locked; that is
396 up to the caller.
397
398 \begin{verbatim}
399 krb5_dbm_db_delete_principal(krb5_principal searchfor, int *nentries)
400 \end{verbatim}
401
402 Removes the principal searchfor from the database.  nentries will be
403 set to 0 or 1 on output, indicating the number of entries deleted (the
404 code does not currently support wildcards).
405
406 Returns KRB5_KDB_NOENTRY.
407
408 \begin{verbatim}
409 typedef krb5_error_code (*iter_func)(krb5_pointer, krb5_db_entry *);
410
411 krb5_dbm_db_iterate(iter_func func, krb5_point func_arg)
412 \end{verbatim}
413
414 Calls (*func)(func_arg, entry) for every entry in the database.  If
415 func returns an error code, the iteration stops and that error code is
416 returned.
417
418 Returns func error codes.
419
420 \begin{verbatim}
421 void krb5_dbm_db_free_principal(krb5_db_entry *entries, int nentries)
422 \end{verbatim}
423
424 Frees entries returned by krb5_dbm_db_get_principal.  nentries entries
425 in the array entries will be freed.
426
427 \subsubsection{Initialization and Key Access}
428
429 Keys stored in the Kerberos database are encrypted in the Kerberos
430 master key.  The admin server will therefore have to acquire the key
431 before it can perform any key-changing operations, and will have to
432 decrypt and encrypt the keys retrieved from and placed into the
433 database via krb5_db_get_principal and _put_principal.  This section
434 describes the internal admin server API that will be used to perform
435 these functions.
436
437 \begin{verbatim}
438 krb5_principal master_princ;
439 krb5_encrypt_block master_encblock;
440 krb5_keyblock master_keyblock;
441
442 void kdc_init_master()
443 \end{verbatim}
444
445 kdc_init_master opens the database and acquires the master key.  It
446 also sets the global variables master_princ, master_encblock, and
447 master_keyblock:
448
449 \begin{itemize}
450 \item master_princ is set to the name of the Kerberos master principal
451 (\v{K/M@REALM}).
452
453 \item master_encblock is something I have no idea about.
454
455 \item master_keyblock is the Kerberos master key
456 \end{itemize}
457
458 \begin{verbatim}
459 krb5_error_code kdb_get_entry_and_key(krb5_principal principal,
460                                       krb5_db_entry *entry,
461                                       krb5_keyblock *key)
462 \end{verbatim}
463
464 kdb_get_entry_and_key retrieves the named principal's entry from the
465 database in entry, and decrypts its key into key.  The caller must
466 free entry with krb5_dbm_db_free_principal and free key-$>$contents with
467 free.\footnote{The caller should also \v{memset(key-$>$contents, 0,
468 key-$>$length)}.  There should be a function krb5_free_keyblock_contents
469 for this, but there is not.}
470
471 \begin{verbatim}
472 krb5_error_code kdb_put_entry_pw(krb5_db_entry *entry, char *pw)
473 \end{verbatim}
474
475 kdb_put_entry_pw stores entry in the database.  All the entry values
476 must already be set; this function does not change any of them except
477 the key.  pw, the NULL-terminated password string, is converted to a
478 key using string-to-key with the salt type specified in
479 entry-$>$salt_type.\footnote{The salt_type should be set based on the
480 command line arguments to the kadmin server (see the ``Command Line''
481 section of the functional specification).}
482
483 \section{Admin Principal and Policy Database Implementation}
484
485 The admin principal and policy databases will each be stored in a
486 single hash table, implemented by the Berkeley 4.4BSD db library.
487 Each record will consist of an entire osa_T_ent_t.  The key into the
488 hash table is the entry name (for principals, the ASCII representation
489 of the name).  The value is the T entry structure.  Since the key and
490 data must be self-contained, with no pointers, the Sun xdr mechanisms
491 will be used to marshal and unmarshal data in the database.
492
493 The server in the first release will be single-threaded in that a
494 request will run to completion (or error) before the next will run,
495 but multiple connections will be allowed simultaneously.
496
497 \section{ACLs, acl_check}
498
499 The ACL mechanism described in the ``Authorization ACLs'' section of
500 the functional specifications will be implemented by the acl_check
501 function.
502
503 \begin{verbatim}
504 enum access_t {
505         ACCESS_DENIED = 0,
506         ACCESS_OK = 1,
507 };
508
509 enum access_t acl_check(krb5_principal princ, char *priv);
510 \end{verbatim}
511
512 The priv argument must be one of ``get'', ``add'', ``delete'', or
513 ``modify''.  acl_check returns 1 if the principal princ has the named
514 privilege, 0 if it does not.
515
516 \section{Function Details}
517
518 This section discusses specific design issues for Admin API functions
519 that are not addresed by the functional specifications.
520
521 \subsection{ovsec_kadm_create_principal}
522
523 If the named principal exists in either the Kerberos or admin
524 principal database, but not both, return OVSEC_KADM_BAD_DB.
525
526 The principal's initial key is not stored in the key history array at
527 creation time.
528
529 \subsection{ovsec_kadm_delete_principal}
530
531 If the named principal exists in either the Kerberos or admin
532 principal database, but not both, return OVSEC_KADM_BAD_DB.
533
534 \subsection{ovsec_kadm_modify_principal}
535
536 If the named principal exists in either the Kerberos or admin
537 principal database, but not both, return OVSEC_KADM_BAD_DB.
538
539 If pw_history_num changes and the new value $n$ is smaller than the
540 current value of num_old_keys, old_keys should end up with the $n$
541 most recent keys; these are found by counting backwards $n$ elements
542 in old_keys from next_old_key.  next_old_keys should then be reset to
543 0, the oldest of the saved keys, and num_old_keys set to $n$, the
544 new actual number of old keys in the array.  
545
546 \subsection{ovsec_kadm_chpass_principal, randkey_principal}
547
548 The algorithm for determining whether a password is in the principal's
549 key history is complicated by the use of the kadmin/history \k{h}
550 encrypting key.  
551
552 \begin{enumerate}
553 \item For ovsec_kadm_chpass_principal, convert the password to a key
554 using string-to-key and the salt method specified by the command line
555 arguments.
556
557 \item If the POLICY bit is set and pw_history_num is not zero, check
558 if the new key is in the history.
559 \begin{enumerate}
560 \item Retrieve the principal's current key and decrypt it with \k{M}.
561 If it is the same as the new key, return OVSEC_KADM_PASS_REUSE.
562 \item Retrieve the kadmin/history key \k{h} and decrypt it with \k{M}.
563 \item Encrypt the principal's new key in \k{h}.
564 \item If the principal's new key encrypted in \k{h} is in old_keys,
565 return OVSEC_KADM_PASS_REUSE.
566 \item Encrypt the principal's current key in \k{h} and store it in
567 old_keys.
568 \item Erase the memory containing \k{h}.
569 \end{enumerate}
570
571 \item Encrypt the principal's new key in \k{M} and store it in the
572 database.
573 \item Erase the memory containing \k{M}.
574 \end{enumerate}
575
576 To store the an encrypted key in old_keys, insert it as the
577 next_old_key element of old_keys, and increment next_old_key by one
578 modulo pw_history_num.
579
580 \subsection{ovsec_kadm_get_principal}
581
582 If the named principal exists in either the Kerberos or admin
583 principal database, but not both, return OVSEC_KADM_BAD_DB.
584
585 \end{document}