vlserver: Disable regex volume name processing in ListAttributesN2
[openafs.git] / src / libadmin / kas / afs_kasAdmin.c
1 /*
2  * Copyright 2000, International Business Machines Corporation and others.
3  * All Rights Reserved.
4  * 
5  * This software has been released under the terms of the IBM Public
6  * License.  For details, see the LICENSE file in the top-level source
7  * directory or online at http://www.openafs.org/dl/license10.html
8  */
9
10 #include <afsconfig.h>
11 #include <afs/param.h>
12 #include <afs/stds.h>
13
14 #include <roken.h>
15
16 #include <rx/rx.h>
17 #include <rx/rxstat.h>
18 #include "afs_kasAdmin.h"
19 #include "../adminutil/afs_AdminInternal.h"
20 #include <afs/afs_AdminErrors.h>
21 #include <afs/afs_utilAdmin.h>
22 #include <afs/kauth.h>
23 #include <afs/kautils.h>
24 #include <afs/kaport.h>
25 #include <pthread.h>
26
27 #undef ENCRYPT
28
29 typedef struct {
30     int begin_magic;
31     int is_valid;
32     struct ubik_client *servers;
33     char *cell;
34     int end_magic;
35 } kas_server_t, *kas_server_p;
36
37 /*
38  * IsValidServerHandle - verify the validity of a kas_server_t handle.
39  *
40  * PARAMETERS
41  *
42  * IN serverHandle - the handle to be verified.
43  *
44  * LOCKS
45  *
46  * No locks are obtained or released by this function
47  *
48  * RETURN CODES
49  *
50  * Returns != 0 upon successful completion.
51  */
52
53 static int
54 IsValidServerHandle(const kas_server_p serverHandle, afs_status_p st)
55 {
56     int rc = 0;
57     afs_status_t tst = 0;
58
59     /*
60      * Validate input parameters
61      */
62
63     if (serverHandle == NULL) {
64         tst = ADMKASSERVERHANDLENULL;
65         goto fail_IsValidServerHandle;
66     }
67
68     if ((serverHandle->begin_magic != BEGIN_MAGIC)
69         || (serverHandle->end_magic != END_MAGIC)) {
70         tst = ADMKASSERVERHANDLEBADMAGIC;
71         goto fail_IsValidServerHandle;
72     }
73
74     if (!serverHandle->is_valid) {
75         tst = ADMKASSERVERHANDLENOTVALID;
76         goto fail_IsValidServerHandle;
77     }
78
79     if (serverHandle->servers == NULL) {
80         tst = ADMKASSERVERHANDLENOSERVERS;
81         goto fail_IsValidServerHandle;
82     }
83     rc = 1;
84
85   fail_IsValidServerHandle:
86
87     if (st != NULL) {
88         *st = tst;
89     }
90     return rc;
91 }
92
93 /*
94  * IsValidCellHandle - verify the validity of a afs_cell_handle_t handle
95  * for doing kas related functions.
96  *
97  * PARAMETERS
98  *
99  * IN cellHandle - the handle to be verified.
100  *
101  * LOCKS
102  *
103  * No locks are obtained or released by this function
104  *
105  * RETURN CODES
106  *
107  * Returns != 0 upon successful completion.
108  */
109
110 static int
111 IsValidCellHandle(const afs_cell_handle_p cellHandle, afs_status_p st)
112 {
113     int rc = 0;
114     afs_status_t tst = 0;
115
116     /*
117      * Validate input parameters
118      */
119
120     if (!CellHandleIsValid((void *)cellHandle, &tst)) {
121         goto fail_IsValidCellHandle;
122     }
123
124     if (!cellHandle->kas_valid) {
125         tst = ADMCLIENTCELLKASINVALID;
126         goto fail_IsValidCellHandle;
127     }
128
129     if (cellHandle->kas == NULL) {
130         tst = ADMCLIENTCELLKASNULL;
131         goto fail_IsValidCellHandle;
132     }
133     rc = 1;
134
135   fail_IsValidCellHandle:
136
137     if (st != NULL) {
138         *st = tst;
139     }
140     return rc;
141 }
142
143 /*
144  * For all kas admin functions that take a cellHandle and a serverHandle,
145  * the intention is that is the cellHandle is not NULL, we should use
146  * it.  Otherwise, we use the serverHandle.  It is an error for both
147  * of these parameters to be non-NULL.
148  */
149
150 /*
151  * ChooseValidServer - given a serverHandle and a cellHandle, choose the
152  * one that is non-NULL, validate it, and return a ubik_client structure
153  * that contains it.
154  *
155  * PARAMETERS
156  *
157  * IN cellHandle - the cell where kas calls are to be made
158  *
159  * IN serverHandle - the group of server(s) that should be used to satisfy
160  * kas calls.
161  *
162  * LOCKS
163  *
164  * No locks are obtained or released by this function
165  *
166  * RETURN CODES
167  *
168  * Returns != 0 upon successful completion.
169  */
170
171 static int
172 ChooseValidServer(const afs_cell_handle_p cellHandle,
173                   const kas_server_p serverHandle, kas_server_p kasHandle,
174                   afs_status_p st)
175 {
176     int rc = 0;
177     afs_status_t tst = 0;
178
179     /*
180      * Validate input parameters
181      */
182
183     if (kasHandle == NULL) {
184         tst = ADMKASKASHANDLENULL;
185         goto fail_ChooseValidServer;
186     }
187
188     /*
189      * Only one of the input handle parameters to this function should
190      * not be NULL
191      */
192     if ((cellHandle == NULL) && (serverHandle == NULL)) {
193         tst = ADMKASCELLHANDLEANDSERVERHANDLENULL;
194         goto fail_ChooseValidServer;
195     }
196
197     if ((cellHandle != NULL) && (serverHandle != NULL)) {
198         tst = ADMKASCELLHANDLEANDSERVERHANDLENOTNULL;
199         goto fail_ChooseValidServer;
200     }
201
202     /*
203      * Validate the non-NULL handle
204      */
205
206     if (cellHandle != NULL) {
207         if (IsValidCellHandle(cellHandle, &tst)) {
208             kasHandle->servers = cellHandle->kas;
209             kasHandle->cell = cellHandle->working_cell;
210         } else {
211             goto fail_ChooseValidServer;
212         }
213     } else {
214         if (IsValidServerHandle(serverHandle, &tst)) {
215             kasHandle->servers = serverHandle->servers;
216             kasHandle->cell = serverHandle->cell;
217         } else {
218             goto fail_ChooseValidServer;
219         }
220     }
221
222     kasHandle->begin_magic = BEGIN_MAGIC;
223     kasHandle->end_magic = END_MAGIC;
224     kasHandle->is_valid = 1;
225     rc = 1;
226
227   fail_ChooseValidServer:
228
229     if (st != NULL) {
230         *st = tst;
231     }
232     return rc;
233 }
234
235
236 static int
237 kaentryinfo_to_kas_principalEntry_t(struct kaentryinfo *from,
238                                     kas_principalEntry_p to, afs_status_p st)
239 {
240     int rc = 0;
241     afs_status_t tst = 0;
242     int short reuse;
243     unsigned char misc_stuff[4];
244
245     if (from == NULL) {
246         tst = ADMKASFROMNULL;
247         goto fail_kaentryinfo_to_kas_principalEntry_t;
248     }
249
250     if (to == NULL) {
251         tst = ADMKASTONULL;
252         goto fail_kaentryinfo_to_kas_principalEntry_t;
253     }
254
255     if (from->flags & KAFADMIN) {
256         to->adminSetting = KAS_ADMIN;
257     } else {
258         to->adminSetting = NO_KAS_ADMIN;
259     }
260
261     if (from->flags & KAFNOTGS) {
262         to->tgsSetting = NO_TGS;
263     } else {
264         to->tgsSetting = TGS;
265     }
266
267     if (from->flags & KAFNOSEAL) {
268         to->encSetting = NO_ENCRYPT;
269     } else {
270         to->encSetting = ENCRYPT;
271     }
272
273     if (from->flags & KAFNOCPW) {
274         to->cpwSetting = NO_CHANGE_PASSWORD;
275     } else {
276         to->cpwSetting = CHANGE_PASSWORD;
277     }
278
279     reuse = (short)from->reserved3;
280     if (!reuse) {
281         to->rpwSetting = REUSE_PASSWORD;
282     } else {
283         to->rpwSetting = NO_REUSE_PASSWORD;
284     }
285
286
287     if (from->user_expiration == NEVERDATE) {
288         to->userExpiration = 0;
289     } else {
290         to->userExpiration = from->user_expiration;
291     }
292
293     to->lastModTime = from->modification_time;
294     strcpy(to->lastModPrincipal.principal, from->modification_user.name);
295     strcpy(to->lastModPrincipal.instance, from->modification_user.instance);
296     to->lastChangePasswordTime = from->change_password_time;
297     to->maxTicketLifetime = from->max_ticket_lifetime;
298     to->keyVersion = from->key_version;
299     memcpy(&to->key, &from->key, sizeof(to->key));
300     to->keyCheckSum = from->keyCheckSum;
301
302     unpack_long(from->misc_auth_bytes, misc_stuff);
303     to->daysToPasswordExpire = misc_stuff[0];
304     to->failLoginCount = misc_stuff[2];
305     to->lockTime = misc_stuff[3] << 9;
306     rc = 1;
307
308   fail_kaentryinfo_to_kas_principalEntry_t:
309
310     if (st != NULL) {
311         *st = tst;
312     }
313     return rc;
314 }
315
316 /*
317  * kas_ServerOpen - open a handle to a set of kaserver's.
318  *
319  * PARAMETERS
320  *
321  * IN cellHandle - a previously opened cellHandle that corresponds
322  * to the cell where the server(s) live.
323  *
324  * IN serverList - a NULL terminated list (a la argv) of server's that 
325  * should be opened.
326  *
327  * OUT serverHandleP - a pointer to a void pointer that upon successful
328  * completion contains serverHandle that can be used in other kas functions.
329  *
330  * LOCKS
331  *
332  * No locks are obtained or released by this function
333  *
334  * RETURN CODES
335  *
336  * Returns != 0 upon successful completion.
337  * 
338  * ASSUMPTIONS
339  * 
340  * This function make some assumptions about the afsconf_cell used by 
341  * ka_AuthSpecificServersConn (since I just wrote ka_AuthSpecificServersConn).
342  * It only fills in the fields that are required.
343  *
344  * Also we assume that the servers listed are members of the cell in
345  * cellHandle without verifying that this is in fact the case.  kas itself
346  * always assumes that the -servers parameter lists servers in the current
347  * cell without verifying, so I am no worse than the current
348  * implementation.  In fact I'm actually a little more flexible since you
349  * can actually use my serverList to play with servers in another cell.
350  * You can't do that with kas.  For certain functions in kas the same
351  * cell assumption can cause things to fail (the ka_StringToKey function in
352  * UserCreate).
353  */
354
355 int ADMINAPI
356 kas_ServerOpen(const void *cellHandle, const char **serverList,
357                void **serverHandleP, afs_status_p st)
358 {
359     int rc = 0;
360     afs_status_t tst = 0;
361     afs_cell_handle_p c_handle = (afs_cell_handle_p) cellHandle;
362     int server_count = 0, server_addr;
363     struct afsconf_cell server_info;
364     kas_server_p k_handle = malloc(sizeof(kas_server_t));
365
366     /*
367      * Validate input parameters
368      */
369
370     if (c_handle == NULL) {
371         tst = ADMCLIENTCELLHANDLENULL;
372         goto fail_kas_ServerOpen;
373     }
374
375     if (c_handle->kas_valid == 0) {
376         tst = ADMCLIENTCELLKASINVALID;
377         goto fail_kas_ServerOpen;
378     }
379
380     if (serverList == NULL) {
381         tst = ADMKASSERVERLISTNULL;
382         goto fail_kas_ServerOpen;
383     }
384
385     if (serverHandleP == NULL) {
386         tst = ADMKASSERVERHANDLEPNULL;
387         goto fail_kas_ServerOpen;
388     }
389
390     if (k_handle == NULL) {
391         tst = ADMNOMEM;
392         goto fail_kas_ServerOpen;
393     }
394
395     k_handle->begin_magic = BEGIN_MAGIC;
396     k_handle->end_magic = END_MAGIC;
397     k_handle->is_valid = 0;
398     k_handle->servers = NULL;
399
400     /*
401      * Convert serverList to numeric addresses
402      */
403
404     for (server_count = 0; serverList[server_count] != NULL; server_count++) {
405         if (server_count >= MAXHOSTSPERCELL) {
406             tst = ADMKASSERVERLISTTOOLONG;
407             goto fail_kas_ServerOpen;
408         }
409         if (util_AdminServerAddressGetFromName
410             (serverList[server_count], &server_addr, &tst)) {
411             server_info.hostAddr[server_count].sin_addr.s_addr =
412                 htonl(server_addr);
413             server_info.hostAddr[server_count].sin_port =
414                 htons(AFSCONF_KAUTHPORT);
415         } else {
416             goto fail_kas_ServerOpen;
417         }
418     }
419
420     if (server_count == 0) {
421         tst = ADMKASSERVERLISTEMPTY;
422         goto fail_kas_ServerOpen;
423     }
424
425     /*
426      * Get a ubik_client handle for the specified servers
427      */
428     server_info.numServers = server_count;
429     if (!
430         (tst =
431          ka_AuthSpecificServersConn(KA_MAINTENANCE_SERVICE,
432                                     &c_handle->tokens->kas_token,
433                                     &server_info, &k_handle->servers))) {
434         k_handle->is_valid = 1;
435         k_handle->cell = c_handle->working_cell;
436         *serverHandleP = (void *)k_handle;
437     } else {
438         goto fail_kas_ServerOpen;
439     }
440     rc = 1;
441
442   fail_kas_ServerOpen:
443
444     if ((rc == 0) && (k_handle != NULL)) {
445         free(k_handle);
446     }
447
448     if (st != NULL) {
449         *st = tst;
450     }
451     return rc;
452 }
453
454 /*
455  * kas_ServerClose - close a serverHandle.
456  *
457  * PARAMETERS
458  *
459  * IN serverHandle - a serverHandle previously returned by kas_ServerOpen.
460  *
461  * LOCKS
462  *
463  * No locks are obtained or released by this function
464  *
465  * RETURN CODES
466  *
467  * Returns != 0 upon successful completion.
468  */
469
470 int ADMINAPI
471 kas_ServerClose(const void *serverHandle, afs_status_p st)
472 {
473     int rc = 0;
474     afs_status_t tst = 0;
475     kas_server_p k_handle = (kas_server_p) serverHandle;
476
477     if (!IsValidServerHandle(k_handle, &tst)) {
478         goto fail_kas_ServerClose;
479     }
480
481     tst = ubik_ClientDestroy(k_handle->servers);
482     if (tst) {
483         goto fail_kas_ServerClose;
484     }
485
486     k_handle->is_valid = 0;
487     free(k_handle);
488     rc = 1;
489
490   fail_kas_ServerClose:
491
492     if (st != NULL) {
493         *st = tst;
494     }
495     return rc;
496 }
497
498 /*
499  * kas_PrincipalCreate - create a new principal.
500  *
501  * PARAMETERS
502  *
503  * IN cellHandle - a cellHandle previously returned by afsclient_CellOpen.
504  *
505  * IN serverHandle - a serverHandle previously returned by kas_ServerOpen.
506  *
507  * IN who - a kas_identity_p containing the identity of the new principal
508  * to be created.
509  *
510  * IN password - the new principal's initial password.
511  *
512  * LOCKS
513  *
514  * No locks are obtained or released by this function
515  *
516  * RETURN CODES
517  *
518  * Returns != 0 upon successful completion.
519  */
520
521 int ADMINAPI
522 kas_PrincipalCreate(const void *cellHandle, const void *serverHandle,
523                     const kas_identity_p who, const char *password,
524                     afs_status_p st)
525 {
526     int rc = 0;
527     afs_status_t tst = 0;
528     afs_cell_handle_p c_handle = (afs_cell_handle_p) cellHandle;
529     kas_server_p k_handle = (kas_server_p) serverHandle;
530     kas_server_t kaserver;
531     EncryptionKey key;
532     struct kas_encryptionKey kas_key;
533
534     /*
535      * Validate input arguments and make rpc.
536      */
537
538     if (who == NULL) {
539         tst = ADMKASWHONULL;
540         goto fail_kas_PrincipalCreate;
541     }
542
543     if (password == NULL) {
544         tst = ADMKASPASSWORDNULL;
545         goto fail_kas_PrincipalCreate;
546     }
547
548     if (!ChooseValidServer(c_handle, k_handle, &kaserver, &tst)) {
549         goto fail_kas_PrincipalCreate;
550     }
551
552     if (!kas_StringToKey(kaserver.cell, password, &kas_key, &tst)) {
553         goto fail_kas_PrincipalCreate;
554     }
555
556     memcpy(&key, &kas_key, sizeof(key));
557
558     tst =
559         ubik_KAM_CreateUser(kaserver.servers, 0, who->principal,
560                   who->instance, key);
561     if (tst) {
562         goto fail_kas_PrincipalCreate;
563     }
564     rc = 1;
565
566
567   fail_kas_PrincipalCreate:
568
569     if (st != NULL) {
570         *st = tst;
571     }
572     return rc;
573 }
574
575 /*
576  * kas_PrincipalDelete - delete an existing principal.
577  *
578  * PARAMETERS
579  *
580  * IN cellHandle - a cellHandle previously returned by afsclient_CellOpen.
581  *
582  * IN serverHandle - a serverHandle previously returned by kas_ServerOpen.
583  *
584  * IN who - a kas_identity_p containing the identity of the principal
585  * to be deleted.
586  *
587  * LOCKS
588  *
589  * No locks are obtained or released by this function
590  *
591  * RETURN CODES
592  *
593  * Returns != 0 upon successful completion.
594  */
595
596 int ADMINAPI
597 kas_PrincipalDelete(const void *cellHandle, const void *serverHandle,
598                     const kas_identity_p who, afs_status_p st)
599 {
600     int rc = 0;
601     afs_status_t tst = 0;
602     afs_cell_handle_p c_handle = (afs_cell_handle_p) cellHandle;
603     kas_server_p k_handle = (kas_server_p) serverHandle;
604     kas_server_t kaserver;
605
606     /*
607      * Validate input arguments and make rpc.
608      */
609
610     if (who == NULL) {
611         tst = ADMKASWHONULL;
612         goto fail_kas_PrincipalDelete;
613     }
614
615     if (!ChooseValidServer(c_handle, k_handle, &kaserver, &tst)) {
616         goto fail_kas_PrincipalDelete;
617     }
618     tst =
619         ubik_KAM_DeleteUser(kaserver.servers, 0, who->principal,
620                   who->instance);
621     if (tst) {
622         goto fail_kas_PrincipalDelete;
623     }
624     rc = 1;
625
626   fail_kas_PrincipalDelete:
627
628     if (st != NULL) {
629         *st = tst;
630     }
631     return rc;
632 }
633
634 /*
635  * GetPrincipalLockStatus - get the lock status of a principal.
636  *
637  * PARAMETERS
638  *
639  * IN kaserver - a valid kaserver handle previously returned by 
640  * ChooseValidServer
641  *
642  * IN who - a kas_identity_p containing the identity of the principal
643  * to be queried.
644  *
645  * OUT lockedUntil - the remaining number of seconds the principal is locked.
646  *
647  * LOCKS
648  *
649  * No locks are obtained or released by this function
650  *
651  * RETURN CODES
652  *
653  * Returns != 0 upon successful completion.
654  */
655
656 static int
657 GetPrincipalLockStatus(const kas_server_p kaserver, const kas_identity_p who,
658                        unsigned int *lockedUntil, afs_status_p st)
659 {
660     int rc = 0;
661     afs_status_t tst = 0;
662     unsigned int locked;
663     int count = 0;
664     int once = 0;
665
666     /*
667      * Validate input arguments and make rpc.
668      */
669
670     if (kaserver == NULL) {
671         tst = ADMKASKASERVERNULL;
672         goto fail_GetPrincipalLockStatus;
673     }
674
675     if (who == NULL) {
676         tst = ADMKASWHONULL;
677         goto fail_GetPrincipalLockStatus;
678     }
679
680     if (lockedUntil == NULL) {
681         tst = ADMKASLOCKEDUNTILNULL;
682         goto fail_GetPrincipalLockStatus;
683     }
684
685     /*
686      * Unlike every other kas rpc we make here, the lock/unlock rpc's
687      * aren't ubik based.  So instead of calling ubik_Call, we use
688      * ubik_CallIter.  ubik_CallIter steps through the list of hosts
689      * in the ubik_client and calls them one at a time.  Since there's
690      * no synchronization of this data across the servers we have to 
691      * manually keep track of the shortest time to unlock the user ourselves.
692      *
693      * The original inspiration for this function is ka_islocked
694      * in admin_tools.c.  I think that function is totally bogus so I'm
695      * rewriting it here.
696      *
697      * This function should contact all the kaservers and request the lock
698      * status of the principal.  If any of the servers say the principal is
699      * unlocked, we report it as unlocked.  If all the servers say the
700      * principal is locked, we find the server with the shortest lock time
701      * remaining on the principal and return that time.
702      *
703      * This is different than kas, but I think kas is buggy.
704      */
705
706     *lockedUntil = 0;
707     do {
708         locked = 0;
709         tst =
710             ubik_CallIter(KAM_LockStatus, kaserver->servers, UPUBIKONLY,
711                           &count, (long)who->principal, (long)who->instance, (long)&locked, 0,
712                           0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0);
713         if (tst == 0) {
714             if (locked) {
715                 if ((locked < *lockedUntil) || !once) {
716                     *lockedUntil = locked;
717                     once++;
718                 }
719             }
720         }
721     } while ((tst != UNOSERVERS) && (locked != 0));
722
723     /*
724      * Check to see if any server reported this principal unlocked.
725      */
726
727     if ((tst == 0) && (locked == 0)) {
728         *lockedUntil = 0;
729     }
730     if ((tst == 0) || (tst == UNOSERVERS)) {
731         rc = 1;
732     }
733
734   fail_GetPrincipalLockStatus:
735
736     if (st != NULL) {
737         *st = tst;
738     }
739     return rc;
740 }
741
742 /*
743  * kas_PrincipalGet - retrieve information about a single principal.
744  *
745  * PARAMETERS
746  *
747  * IN cellHandle - a cellHandle previously returned by afsclient_CellOpen.
748  *
749  * IN serverHandle - a serverHandle previously returned by kas_ServerOpen.
750  *
751  * IN who - a kas_identity_p containing the identity of the principal
752  * to be retrieved.
753  *
754  * OUT principal - upon successful completion contains information
755  * about who.
756  *
757  * LOCKS
758  *
759  * No locks are obtained or released by this function
760  *
761  * RETURN CODES
762  *
763  * Returns != 0 upon successful completion.
764  */
765
766 int ADMINAPI
767 kas_PrincipalGet(const void *cellHandle, const void *serverHandle,
768                  const kas_identity_p who, kas_principalEntry_p principal,
769                  afs_status_p st)
770 {
771     int rc = 0;
772     afs_status_t tst = 0;
773     afs_cell_handle_p c_handle = (afs_cell_handle_p) cellHandle;
774     kas_server_p k_handle = (kas_server_p) serverHandle;
775     kas_server_t kaserver;
776     struct kaentryinfo entry;
777
778     /*
779      * Validate input arguments and make rpc.
780      */
781
782     if (who == NULL) {
783         tst = ADMKASWHONULL;
784         goto fail_kas_PrincipalGet;
785     }
786
787     if (principal == NULL) {
788         tst = ADMKASPRINCIPALNULL;
789         goto fail_kas_PrincipalGet;
790     }
791
792     if (!ChooseValidServer(c_handle, k_handle, &kaserver, &tst)) {
793         goto fail_kas_PrincipalGet;
794     }
795
796     tst =
797         ubik_KAM_GetEntry(kaserver.servers, 0, who->principal,
798                   who->instance, KAMAJORVERSION, &entry);
799     if (tst) {
800         goto fail_kas_PrincipalGet;
801     }
802
803     /*
804      * copy the kaentryinfo structure to our kas_principalEntry_t
805      * format
806      */
807     if (!kaentryinfo_to_kas_principalEntry_t(&entry, principal, &tst)) {
808         goto fail_kas_PrincipalGet;
809     }
810     rc = 1;
811
812   fail_kas_PrincipalGet:
813
814     if (st != NULL) {
815         *st = tst;
816     }
817     return rc;
818 }
819
820 typedef struct principal_get {
821     int current;
822     int next;
823     int count;
824     kas_server_t kaserver;
825     kas_identity_t principal[CACHED_ITEMS];
826 } principal_get_t, *principal_get_p;
827
828 static int
829 DeletePrincipalSpecificData(void *rpc_specific, afs_status_p st)
830 {
831     int rc = 0;
832     afs_status_t tst = 0;
833     principal_get_p prin = (principal_get_p) rpc_specific;
834
835     prin->kaserver.is_valid = 0;
836     rc = 1;
837
838     if (st != NULL) {
839         *st = tst;
840     }
841     return rc;
842 }
843
844 static int
845 GetPrincipalRPC(void *rpc_specific, int slot, int *last_item,
846                 int *last_item_contains_data, afs_status_p st)
847 {
848     int rc = 0;
849     afs_status_t tst = 0;
850     principal_get_p prin = (principal_get_p) rpc_specific;
851
852     tst =
853         ubik_KAM_ListEntry(prin->kaserver.servers, 0, prin->current,
854                            &prin->next, &prin->count, (kaident *)&prin->principal[slot]);
855     if (tst == 0) {
856         prin->current = prin->next;
857         if (prin->next == 0) {
858             *last_item = 1;
859             *last_item_contains_data = 0;
860         }
861         rc = 1;
862     }
863
864     if (st != NULL) {
865         *st = tst;
866     }
867     return rc;
868 }
869
870 static int
871 GetPrincipalFromCache(void *rpc_specific, int slot, void *dest,
872                       afs_status_p st)
873 {
874     int rc = 0;
875     afs_status_t tst = 0;
876     principal_get_p prin = (principal_get_p) rpc_specific;
877
878     memcpy(dest, &prin->principal[slot], sizeof(kas_identity_t));
879     rc = 1;
880
881     if (st != NULL) {
882         *st = tst;
883     }
884     return rc;
885 }
886
887 /*
888  * kas_PrincipalGetBegin - start the process of iterating over the entire
889  * kas database.
890  *
891  * PARAMETERS
892  *
893  * IN cellHandle - a cellHandle previously returned by afsclient_CellOpen.
894  *
895  * IN serverHandle - a serverHandle previously returned by kas_ServerOpen.
896  *
897  * OUT iterationIdP - upon successful completion contains a iterator that
898  * can be passed to kas_PrincipalGetNext.
899  *
900  * LOCKS
901  *
902  * No locks are obtained or released by this function
903  *
904  * RETURN CODES
905  *
906  * Returns != 0 upon successful completion.
907  *
908  * ASSUMPTIONS
909  */
910
911 int ADMINAPI
912 kas_PrincipalGetBegin(const void *cellHandle, const void *serverHandle,
913                       void **iterationIdP, afs_status_p st)
914 {
915     int rc = 0;
916     afs_status_t tst = 0;
917     afs_cell_handle_p c_handle = (afs_cell_handle_p) cellHandle;
918     kas_server_p k_handle = (kas_server_p) serverHandle;
919     afs_admin_iterator_p iter = malloc(sizeof(afs_admin_iterator_t));
920     principal_get_p principal = malloc(sizeof(principal_get_t));
921
922     /*
923      * Validate arguments
924      */
925
926     if (iter == NULL) {
927         tst = ADMNOMEM;
928         goto fail_kas_PrincipalGetBegin;
929     }
930
931     if (principal == NULL) {
932         tst = ADMNOMEM;
933         goto fail_kas_PrincipalGetBegin;
934     }
935
936     if (iterationIdP == NULL) {
937         tst = ADMITERATIONIDPNULL;
938         goto fail_kas_PrincipalGetBegin;
939     }
940
941     if (!ChooseValidServer(c_handle, k_handle, &principal->kaserver, &tst)) {
942         goto fail_kas_PrincipalGetBegin;
943     }
944
945     /*
946      * Initialize the iterator structure
947      */
948
949     principal->current = 0;
950     principal->next = 0;
951     principal->count = 0;
952     if (IteratorInit
953         (iter, (void *)principal, GetPrincipalRPC, GetPrincipalFromCache,
954          NULL, DeletePrincipalSpecificData, &tst)) {
955         *iterationIdP = (void *)iter;
956         rc = 1;
957     }
958
959   fail_kas_PrincipalGetBegin:
960
961     if (rc == 0) {
962         if (iter != NULL) {
963             free(iter);
964         }
965         if (principal != NULL) {
966             free(principal);
967         }
968     }
969
970     if (st != NULL) {
971         *st = tst;
972     }
973     return rc;
974 }
975
976 /*
977  * kas_PrincipalGetNext - retrieve the next principal from the kaserver.
978  *
979  * PARAMETERS
980  *
981  * IN iterationId - an iterator previously returned by kas_PrincipalGetBegin
982  *
983  * OUT who - upon successful completion contains the next principal from the
984  * kaserver
985  *
986  * LOCKS
987  *
988  * Hold the iterator mutex across the call to the kaserver.
989  *
990  * RETURN CODES
991  *
992  * Returns != 0 upon successful completion.
993  * Returns 0 and st == ADMITERATORDONE when the last entry is returned.
994  */
995
996 int ADMINAPI
997 kas_PrincipalGetNext(const void *iterationId, kas_identity_p who,
998                      afs_status_p st)
999 {
1000     int rc = 0;
1001     afs_status_t tst = 0;
1002     afs_admin_iterator_p iter = (afs_admin_iterator_p) iterationId;
1003
1004     /*
1005      * Validate arguments
1006      */
1007
1008     if (who == NULL) {
1009         tst = ADMKASWHONULL;
1010         goto fail_kas_PrincipalGetNext;
1011     }
1012
1013     if (iter == NULL) {
1014         tst = ADMITERATORNULL;
1015         goto fail_kas_PrincipalGetNext;
1016     }
1017
1018     rc = IteratorNext(iter, (void *)who, &tst);
1019
1020   fail_kas_PrincipalGetNext:
1021
1022     if (st != NULL) {
1023         *st = tst;
1024     }
1025     return rc;
1026 }
1027
1028 /*
1029  * kas_PrincipalGetDone - finish using a principal iterator
1030  *
1031  * PARAMETERS
1032  *
1033  * IN iterationId - an iterator previously returned by kas_PrincipalGetBegin
1034  *
1035  * LOCKS
1036  *
1037  * No locks are held by this function.
1038  *
1039  * RETURN CODES
1040  *
1041  * Returns != 0 upon successful completion.
1042  *
1043  * ASSUMPTIONS
1044  *
1045  * It is the user's responsibility to make sure kas_PrincipalGetDone
1046  * is called only once for each iterator.
1047  */
1048
1049 int ADMINAPI
1050 kas_PrincipalGetDone(const void *iterationIdP, afs_status_p st)
1051 {
1052     int rc = 0;
1053     afs_status_t tst = 0;
1054     afs_admin_iterator_p iter = (afs_admin_iterator_p) iterationIdP;
1055
1056     /*
1057      * Validate argument
1058      */
1059
1060     if (iter == NULL) {
1061         tst = ADMITERATORNULL;
1062         goto fail_kas_PrincipalGetDone;
1063     }
1064
1065     rc = IteratorDone(iter, &tst);
1066
1067   fail_kas_PrincipalGetDone:
1068
1069     if (st != NULL) {
1070         *st = tst;
1071     }
1072     return rc;
1073 }
1074
1075 /*
1076  * kas_PrincipalKeySet - set a principal's password to a known value.
1077  *
1078  * PARAMETERS
1079  *
1080  * IN cellHandle - a cellHandle previously returned by afsclient_CellOpen.
1081  *
1082  * IN serverHandle - a serverHandle previously returned by kas_ServerOpen.
1083  *
1084  * IN who - the principal for whom the password is being set.
1085  *
1086  * IN keyVersion - the version number of the new key.
1087  *
1088  * IN key - the new password.
1089  *
1090  * LOCKS
1091  *
1092  * No locks are held by this function.
1093  *
1094  * RETURN CODES
1095  *
1096  * Returns != 0 upon successful completion.
1097  */
1098
1099 int ADMINAPI
1100 kas_PrincipalKeySet(const void *cellHandle, const void *serverHandle,
1101                     const kas_identity_p who, int keyVersion,
1102                     const kas_encryptionKey_p kas_keyp, afs_status_p st)
1103 {
1104     int rc = 0;
1105     afs_status_t tst = 0;
1106     afs_cell_handle_p c_handle = (afs_cell_handle_p) cellHandle;
1107     kas_server_p k_handle = (kas_server_p) serverHandle;
1108     kas_server_t kaserver;
1109     EncryptionKey key; 
1110
1111     /*
1112      * Validate input arguments and make rpc.
1113      */
1114
1115     if (who == NULL) {
1116         tst = ADMKASWHONULL;
1117         goto fail_kas_PrincipalKeySet;
1118     }
1119
1120     if (kas_keyp == NULL) {
1121         tst = ADMKASKEYNULL;
1122         goto fail_kas_PrincipalKeySet;
1123     }
1124
1125     if (!ChooseValidServer(c_handle, k_handle, &kaserver, &tst)) {
1126         goto fail_kas_PrincipalKeySet;
1127     }
1128
1129     memcpy(&key, kas_keyp, sizeof(key));
1130
1131     tst =
1132         ubik_KAM_SetPassword(kaserver.servers, 0, who->principal,
1133                   who->instance, keyVersion, key);
1134     memset(&key, 0, sizeof(key));
1135     if (tst) {
1136         goto fail_kas_PrincipalKeySet;
1137     }
1138
1139     /* If we failed to fail we must have succeeded */
1140     rc = 1;
1141
1142   fail_kas_PrincipalKeySet:
1143
1144     if (st != NULL) {
1145         *st = tst;
1146     }
1147     return rc;
1148 }
1149
1150 /*
1151  * kas_PrincipalLockStatusGet - determine a principal's lock status.
1152  *
1153  * PARAMETERS
1154  *
1155  * IN cellHandle - a cellHandle previously returned by afsclient_CellOpen.
1156  *
1157  * IN serverHandle - a serverHandle previously returned by kas_ServerOpen.
1158  *
1159  * IN who - the principal whose lock status is being checked.
1160  *
1161  * OUT lock_end_timeP - the number of seconds until the principal is unlocked.
1162  * If 0 => user is unlocked.
1163  *
1164  * LOCKS
1165  *
1166  * No locks are held by this function.
1167  *
1168  * RETURN CODES
1169  *
1170  * Returns != 0 upon successful completion.
1171  *
1172  * ASSUMPTIONS
1173  *
1174  * See the comments in GetPrincipalLockStatus regarding how the locking data
1175  * is kept INconsistently between servers.
1176  */
1177
1178 int ADMINAPI
1179 kas_PrincipalLockStatusGet(const void *cellHandle, const void *serverHandle,
1180                            const kas_identity_p who,
1181                            unsigned int *lock_end_timeP, afs_status_p st)
1182 {
1183     int rc = 0;
1184     afs_status_t tst = 0;
1185     afs_cell_handle_p c_handle = (afs_cell_handle_p) cellHandle;
1186     kas_server_p k_handle = (kas_server_p) serverHandle;
1187     kas_server_t kaserver;
1188
1189     /*
1190      * Validate input arguments and make rpc.
1191      */
1192
1193     if (who == NULL) {
1194         tst = ADMKASWHONULL;
1195         goto fail_kas_PrincipalLockStatusGet;
1196     }
1197
1198     if (lock_end_timeP == NULL) {
1199         tst = ADMKASLOCKENDTIMEPNULL;
1200         goto fail_kas_PrincipalLockStatusGet;
1201     }
1202
1203     if (!ChooseValidServer(c_handle, k_handle, &kaserver, &tst)) {
1204         goto fail_kas_PrincipalLockStatusGet;
1205     }
1206
1207     rc = GetPrincipalLockStatus(&kaserver, who, lock_end_timeP, &tst);
1208
1209   fail_kas_PrincipalLockStatusGet:
1210
1211     if (st != NULL) {
1212         *st = tst;
1213     }
1214     return rc;
1215 }
1216
1217 /*
1218  * kas_PrincipalUnlock - unlock a principal.
1219  *
1220  * PARAMETERS
1221  *
1222  * IN cellHandle - a cellHandle previously returned by afsclient_CellOpen.
1223  *
1224  * IN serverHandle - a serverHandle previously returned by kas_ServerOpen.
1225  *
1226  * IN who - the principal who is being unlocked.
1227  *
1228  * LOCKS
1229  *
1230  * No locks are held by this function.
1231  *
1232  * RETURN CODES
1233  *
1234  * Returns != 0 upon successful completion.
1235  *
1236  * ASSUMPTIONS
1237  *
1238  * See the comments in GetPrincipalLockStatus regarding how the locking data
1239  * is kept INconsistently between servers.
1240  */
1241
1242 int ADMINAPI
1243 kas_PrincipalUnlock(const void *cellHandle, const void *serverHandle,
1244                     const kas_identity_p who, afs_status_p st)
1245 {
1246     int rc = 0;
1247     afs_status_t tst = 0;
1248     afs_cell_handle_p c_handle = (afs_cell_handle_p) cellHandle;
1249     kas_server_p k_handle = (kas_server_p) serverHandle;
1250     kas_server_t kaserver;
1251     int count = 0;
1252     afs_status_t save_tst = 0;
1253
1254     /*
1255      * Validate input arguments and make rpc.
1256      */
1257
1258     if (who == NULL) {
1259         tst = ADMKASWHONULL;
1260         goto fail_kas_PrincipalUnlock;
1261     }
1262
1263     if (!ChooseValidServer(c_handle, k_handle, &kaserver, &tst)) {
1264         goto fail_kas_PrincipalUnlock;
1265     }
1266
1267     do {
1268         tst =
1269             ubik_CallIter(KAM_Unlock, kaserver.servers, 0, &count,
1270                           (long)who->principal, (long)who->instance, 0, 0, 0,
1271                           0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0);
1272         if (tst && (tst != UNOSERVERS)) {
1273             if (save_tst == 0) {
1274                 save_tst = tst; /* save the first failure */
1275             }
1276         }
1277     } while (tst != UNOSERVERS);
1278
1279     if ((tst == 0) || (tst == UNOSERVERS)) {
1280         rc = 1;
1281     }
1282
1283   fail_kas_PrincipalUnlock:
1284
1285     if (st != NULL) {
1286         *st = tst;
1287     }
1288     return rc;
1289 }
1290
1291 static int
1292 getPrincipalFlags(const void *cellHandle, const void *serverHandle,
1293                   const kas_identity_p who, afs_int32 * cur_flags,
1294                   afs_status_p st)
1295 {
1296     int rc = 0;
1297     afs_status_t tst = 0;
1298     afs_cell_handle_p c_handle = (afs_cell_handle_p) cellHandle;
1299     kas_server_p k_handle = (kas_server_p) serverHandle;
1300     kas_server_t kaserver;
1301     struct kaentryinfo tentry;
1302
1303     if (!ChooseValidServer(c_handle, k_handle, &kaserver, &tst)) {
1304         goto fail_getPrincipalFlags;
1305     }
1306
1307     tst =
1308         ubik_KAM_GetEntry(kaserver.servers, 0, who->principal,
1309                   who->instance, KAMAJORVERSION, &tentry);
1310     if (tst == 0) {
1311         *cur_flags = tentry.flags;
1312         rc = 1;
1313     }
1314
1315   fail_getPrincipalFlags:
1316
1317     if (st != NULL) {
1318         *st = tst;
1319     }
1320     return rc;
1321 }
1322
1323 /*
1324  * kas_PrincipalFieldsSet - modify an existing principal.
1325  *
1326  * PARAMETERS
1327  *
1328  * IN cellHandle - a cellHandle previously returned by afsclient_CellOpen.
1329  *
1330  * IN serverHandle - a serverHandle previously returned by kas_ServerOpen.
1331  *
1332  * IN who - the principal who is being modified.
1333  *
1334  * IN isAdmin - the admin status of the principal.
1335  *
1336  * IN grantTickets - should the TGS issue tickets for the principal.
1337  *
1338  * IN canEncrypt - should the TGS allow the use of encryption via the 
1339  * principal's key.
1340  *
1341  * IN canChangePassword - should the principal be allowed to change their
1342  * own password?
1343  *
1344  * IN expirationDate - the date when the principal will expire.
1345  *
1346  * IN maxTicketLifetime - the maximum lifetime of a ticket issued for
1347  * the principal.
1348  *
1349  * IN passwordExpires - the maximum number of days a particular
1350  * password can be used.  The limit is 255, 0 => no expiration.
1351  *
1352  * IN passwordReuse - can a password be reused by this principal.
1353  *
1354  * IN failedPasswordAttempts - number of failed login attempts before
1355  * a principal is locked.  The limit is 255, 0 => no limit.
1356  *
1357  * IN failedPasswordLockTime - the number of seconds a principal is
1358  * locked once failedPasswordAttempts is reached.  Some bizarre rounding
1359  * occurs for this value, see kas for more details.
1360  *
1361  * LOCKS
1362  *
1363  * No locks are held by this function.
1364  *
1365  * RETURN CODES
1366  *
1367  * Returns != 0 upon successful completion.
1368  *
1369  * ASSUMPTIONS
1370  *
1371  * See the comments in GetPrincipalLockStatus regarding how the locking data
1372  * is kept INconsistently between servers.
1373  */
1374
1375 int ADMINAPI
1376 kas_PrincipalFieldsSet(const void *cellHandle, const void *serverHandle,
1377                        const kas_identity_p who, const kas_admin_p isAdmin,
1378                        const kas_tgs_p grantTickets,
1379                        const kas_enc_p canEncrypt,
1380                        const kas_cpw_p canChangePassword,
1381                        const unsigned int *expirationDate,
1382                        const unsigned int *maxTicketLifetime,
1383                        const unsigned int *passwordExpires,
1384                        const kas_rpw_p passwordReuse,
1385                        const unsigned int *failedPasswordAttempts,
1386                        const unsigned int *failedPasswordLockTime,
1387                        afs_status_p st)
1388 {
1389     int rc = 0;
1390     afs_status_t tst = 0;
1391     afs_cell_handle_p c_handle = (afs_cell_handle_p) cellHandle;
1392     kas_server_p k_handle = (kas_server_p) serverHandle;
1393     kas_server_t kaserver;
1394     afs_int32 flags = 0;
1395     Date expiration = 0;
1396     afs_int32 lifetime = 0;
1397     int was_spare;
1398     char spare_bytes[4] = { 0, 0, 0, 0 };
1399     int somethings_changing = 0;
1400
1401     /*
1402      * Validate input arguments.
1403      */
1404
1405     if (who == NULL) {
1406         tst = ADMKASWHONULL;
1407         goto fail_kas_PrincipalFieldsSet;
1408     }
1409
1410     /*
1411      * set flags based upon input
1412      *
1413      * If we're changing the flags, we need to get the current value of
1414      * the flags first and then make the changes
1415      */
1416
1417     if ((isAdmin != NULL) || (grantTickets != NULL) || (canEncrypt != NULL)
1418         || (canChangePassword != NULL)) {
1419         if (!getPrincipalFlags(cellHandle, serverHandle, who, &flags, &tst)) {
1420             goto fail_kas_PrincipalFieldsSet;
1421         }
1422     }
1423
1424     if (isAdmin != NULL) {
1425         somethings_changing = 1;
1426         if (*isAdmin == KAS_ADMIN) {
1427             flags |= KAFADMIN;
1428         } else {
1429             flags &= ~KAFADMIN;
1430         }
1431     }
1432
1433     if (grantTickets != NULL) {
1434         somethings_changing = 1;
1435         if (*grantTickets == NO_TGS) {
1436             flags |= KAFNOTGS;
1437         } else {
1438             flags &= ~KAFNOTGS;
1439         }
1440     }
1441
1442     if (canEncrypt != NULL) {
1443         somethings_changing = 1;
1444         if (*canEncrypt == NO_ENCRYPT) {
1445             flags |= KAFNOSEAL;
1446         } else {
1447             flags &= ~KAFNOSEAL;
1448         }
1449     }
1450
1451     if (canChangePassword != NULL) {
1452         somethings_changing = 1;
1453         if (*canChangePassword == NO_CHANGE_PASSWORD) {
1454             flags |= KAFNOCPW;
1455         } else {
1456             flags &= ~KAFNOCPW;
1457         }
1458     }
1459
1460     flags = (flags & KAF_SETTABLE_FLAGS) | KAFNORMAL;
1461
1462     if (expirationDate != NULL) {
1463         somethings_changing = 1;
1464         expiration = *expirationDate;
1465     }
1466
1467     if (maxTicketLifetime != NULL) {
1468         somethings_changing = 1;
1469         lifetime = *maxTicketLifetime;
1470     }
1471
1472     if (passwordExpires != NULL) {
1473         if (*passwordExpires > 255) {
1474             tst = ADMKASPASSWORDEXPIRESTOOBIG;
1475             goto fail_kas_PrincipalFieldsSet;
1476         }
1477         somethings_changing = 1;
1478         spare_bytes[0] = *passwordExpires + 1;
1479     }
1480
1481     if (passwordReuse != NULL) {
1482         somethings_changing = 1;
1483         if (*passwordReuse == REUSE_PASSWORD) {
1484             spare_bytes[1] = KA_REUSEPW;
1485         } else {
1486             spare_bytes[1] = KA_NOREUSEPW;
1487         }
1488     }
1489
1490     if (failedPasswordAttempts != NULL) {
1491         if (*failedPasswordAttempts > 255) {
1492             tst = ADMKASFAILEDPASSWORDATTEMPTSTOOBIG;
1493             goto fail_kas_PrincipalFieldsSet;
1494         }
1495         somethings_changing = 1;
1496         spare_bytes[2] = *failedPasswordAttempts + 1;
1497     }
1498
1499     if (failedPasswordLockTime != NULL) {
1500         if (*failedPasswordLockTime > 36 * 60 * 60) {
1501             tst = ADMKASFAILEDPASSWORDLOCKTIME;
1502             goto fail_kas_PrincipalFieldsSet;
1503         }
1504         somethings_changing = 1;
1505         spare_bytes[3] = ((*failedPasswordLockTime + 511) >> 9) + 1;
1506     }
1507
1508     was_spare = pack_long(spare_bytes);
1509
1510     if (somethings_changing) {
1511         if (!ChooseValidServer(c_handle, k_handle, &kaserver, &tst)) {
1512             goto fail_kas_PrincipalFieldsSet;
1513         }
1514         tst =
1515             ubik_KAM_SetFields(kaserver.servers, 0, who->principal,
1516                       who->instance, flags, expiration, lifetime, -1,
1517                       was_spare, 0);
1518         if (tst == 0) {
1519             rc = 1;
1520         }
1521     } else {
1522         tst = ADMKASPRINCIPALFIELDSNOCHANGE;
1523     }
1524
1525   fail_kas_PrincipalFieldsSet:
1526
1527     if (st != NULL) {
1528         *st = tst;
1529     }
1530     return rc;
1531 }
1532
1533 /*
1534  * kas_ServerStatsGet - get server statistics.
1535  *
1536  * PARAMETERS
1537  *
1538  * IN cellHandle - a cellHandle previously returned by afsclient_CellOpen.
1539  *
1540  * IN serverHandle - a serverHandle previously returned by kas_ServerOpen.
1541  *
1542  * OUT stats - the statistics retrieved.
1543  *
1544  * LOCKS
1545  *
1546  * No locks are held by this function.
1547  *
1548  * RETURN CODES
1549  *
1550  * Returns != 0 upon successful completion.
1551  */
1552
1553 int ADMINAPI
1554 kas_ServerStatsGet(const void *cellHandle, const void *serverHandle,
1555                    kas_serverStats_p stats, afs_status_p st)
1556 {
1557     int rc = 0;
1558     afs_status_t tst = 0;
1559     afs_cell_handle_p c_handle = (afs_cell_handle_p) cellHandle;
1560     kas_server_p k_handle = (kas_server_p) serverHandle;
1561     kas_server_t kaserver;
1562     afs_int32 admins;
1563     kasstats statics;
1564     kadstats dynamics;
1565     size_t i;
1566
1567     /*
1568      * Validate input arguments and make rpc.
1569      */
1570
1571     if (stats == NULL) {
1572         tst = ADMKASSTATSNULL;
1573         goto fail_kas_ServerStatsGet;
1574     }
1575
1576     if (!ChooseValidServer(c_handle, k_handle, &kaserver, &tst)) {
1577         goto fail_kas_ServerStatsGet;
1578     }
1579
1580     tst =
1581         ubik_KAM_GetStats(kaserver.servers, 0, KAMAJORVERSION, &admins,
1582                   &statics, &dynamics);
1583     if (tst) {
1584         goto fail_kas_ServerStatsGet;
1585     }
1586
1587     stats->allocations = statics.allocs;
1588     stats->frees = statics.frees;
1589     stats->changePasswordRequests = statics.cpws;
1590     stats->adminAccounts = admins;
1591     stats->host = dynamics.host;
1592     stats->serverStartTime = dynamics.start_time;
1593     stats->hashTableUtilization = dynamics.hashTableUtilization;
1594
1595     i = sizeof(kas_serverProcStats_t);
1596     memcpy(&stats->authenticate, &dynamics.Authenticate, i);
1597     memcpy(&stats->changePassword, &dynamics.ChangePassword, i);
1598     memcpy(&stats->getTicket, &dynamics.GetTicket, i);
1599     memcpy(&stats->createUser, &dynamics.CreateUser, i);
1600     memcpy(&stats->setPassword, &dynamics.SetPassword, i);
1601     memcpy(&stats->setFields, &dynamics.SetFields, i);
1602     memcpy(&stats->deleteUser, &dynamics.DeleteUser, i);
1603     memcpy(&stats->getEntry, &dynamics.GetEntry, i);
1604     memcpy(&stats->listEntry, &dynamics.ListEntry, i);
1605     memcpy(&stats->getStats, &dynamics.GetStats, i);
1606     memcpy(&stats->getPassword, &dynamics.GetPassword, i);
1607     memcpy(&stats->getRandomKey, &dynamics.GetRandomKey, i);
1608     memcpy(&stats->debug, &dynamics.Debug, i);
1609     memcpy(&stats->udpAuthenticate, &dynamics.UAuthenticate, i);
1610     memcpy(&stats->udpGetTicket, &dynamics.UGetTicket, i);
1611     memcpy(&stats->unlock, &dynamics.Unlock, i);
1612     memcpy(&stats->lockStatus, &dynamics.LockStatus, i);
1613
1614     stats->stringChecks = dynamics.string_checks;
1615     rc = 1;
1616
1617   fail_kas_ServerStatsGet:
1618
1619     if (st != NULL) {
1620         *st = tst;
1621     }
1622     return rc;
1623 }
1624
1625 /*
1626  * kas_ServerDebugGet - get server debug info.
1627  *
1628  * PARAMETERS
1629  *
1630  * IN cellHandle - a cellHandle previously returned by afsclient_CellOpen.
1631  *
1632  * IN serverHandle - a serverHandle previously returned by kas_ServerOpen.
1633  *
1634  * OUT stats - the debug info retrieved.
1635  *
1636  * LOCKS
1637  *
1638  * No locks are held by this function.
1639  *
1640  * RETURN CODES
1641  *
1642  * Returns != 0 upon successful completion.
1643  */
1644
1645 int ADMINAPI
1646 kas_ServerDebugGet(const void *cellHandle, const void *serverHandle,
1647                    kas_serverDebugInfo_p debug, afs_status_p st)
1648 {
1649     int rc = 0;
1650     afs_status_t tst = 0;
1651     afs_cell_handle_p c_handle = (afs_cell_handle_p) cellHandle;
1652     kas_server_p k_handle = (kas_server_p) serverHandle;
1653     kas_server_t kaserver;
1654     struct ka_debugInfo info;
1655     int i;
1656
1657     /*
1658      * Validate input arguments and make rpc.
1659      */
1660
1661     if (debug == NULL) {
1662         tst = ADMKASDEBUGNULL;
1663         goto fail_kas_ServerDebugGet;
1664     }
1665
1666     if (!ChooseValidServer(c_handle, k_handle, &kaserver, &tst)) {
1667         goto fail_kas_ServerDebugGet;
1668     }
1669     tst = ubik_KAM_Debug(kaserver.servers, 0, KAMAJORVERSION, 0, &info);
1670     if (tst) {
1671         goto fail_kas_ServerDebugGet;
1672     }
1673     debug->host = info.host;
1674     debug->serverStartTime = info.startTime;
1675     debug->currentTime = info.reserved1;
1676     debug->noAuth = info.noAuth;
1677     debug->lastTransaction = info.lastTrans;
1678     strcpy(debug->lastOperation, info.lastOperation);
1679     strcpy(debug->lastPrincipalAuth, info.lastAuth);
1680     strcpy(debug->lastPrincipalUDPAuth, info.lastUAuth);
1681     strcpy(debug->lastPrincipalTGS, info.lastTGS);
1682     strcpy(debug->lastPrincipalUDPTGS, info.lastUTGS);
1683     strcpy(debug->lastPrincipalAdmin, info.lastAdmin);
1684     strcpy(debug->lastServerTGS, info.lastTGSServer);
1685     strcpy(debug->lastServerUDPTGS, info.lastUTGSServer);
1686     debug->nextAutoCheckPointWrite = info.nextAutoCPW;
1687     debug->updatesRemainingBeforeAutoCheckPointWrite = info.updatesRemaining;
1688     debug->dbHeaderRead = info.dbHeaderRead;
1689     debug->dbVersion = info.dbVersion;
1690     debug->dbFreePtr = info.dbFreePtr;
1691     debug->dbEOFPtr = info.dbEofPtr;
1692     debug->dbKvnoPtr = info.dbKvnoPtr;
1693     debug->dbSpecialKeysVersion = info.dbSpecialKeysVersion;
1694     debug->dbHeaderLock = info.cheader_lock;
1695     debug->keyCacheLock = info.keycache_lock;
1696     debug->keyCacheVersion = info.kcVersion;
1697     debug->keyCacheSize = info.kcSize;
1698     debug->keyCacheUsed = info.kcUsed;
1699     for (i = 0; i < info.kcUsed; i++) {
1700         debug->keyCache[i].lastUsed = info.kcInfo[i].used;
1701         debug->keyCache[i].keyVersionNumber = info.kcInfo[i].kvno;
1702         debug->keyCache[i].primary = info.kcInfo[i].primary;
1703         debug->keyCache[i].keyCheckSum = info.kcInfo[i].keycksum;
1704         strcpy(debug->keyCache[i].principal, info.kcInfo[i].principal);
1705     }
1706     rc = 1;
1707
1708   fail_kas_ServerDebugGet:
1709
1710     if (st != NULL) {
1711         *st = tst;
1712     }
1713     return rc;
1714 }
1715
1716 /*
1717  * kas_ServerRandomKeyGet - get a random key from a server.
1718  *
1719  * PARAMETERS
1720  *
1721  * IN cellHandle - a cellHandle previously returned by afsclient_CellOpen.
1722  *
1723  * IN serverHandle - a serverHandle previously returned by kas_ServerOpen.
1724  *
1725  * OUT key - a random key.
1726  *
1727  * LOCKS
1728  *
1729  * No locks are held by this function.
1730  *
1731  * RETURN CODES
1732  *
1733  * Returns != 0 upon successful completion.
1734  */
1735
1736 int ADMINAPI
1737 kas_ServerRandomKeyGet(const void *cellHandle, const void *serverHandle,
1738                        kas_encryptionKey_p kas_keyp, afs_status_p st)
1739 {
1740     int rc = 0;
1741     afs_status_t tst = 0;
1742     afs_cell_handle_p c_handle = (afs_cell_handle_p) cellHandle;
1743     kas_server_p k_handle = (kas_server_p) serverHandle;
1744     kas_server_t kaserver;
1745     EncryptionKey key;
1746
1747     /*
1748      * Validate input arguments and make rpc.
1749      */
1750
1751     if (kas_keyp == NULL) {
1752         tst = ADMKASKEYNULL;
1753         goto fail_kas_ServerRandomKeyGet;
1754     }
1755
1756     if (!ChooseValidServer(c_handle, k_handle, &kaserver, &tst)) {
1757         goto fail_kas_ServerRandomKeyGet;
1758     }
1759
1760     tst = ubik_KAM_GetRandomKey(kaserver.servers, 0, &key);
1761     if (tst) {
1762         goto fail_kas_ServerRandomKeyGet;
1763     }
1764     memcpy(kas_keyp, &key, sizeof(*kas_keyp));
1765     rc = 1;
1766
1767   fail_kas_ServerRandomKeyGet:
1768
1769     if (st != NULL) {
1770         *st = tst;
1771     }
1772     return rc;
1773 }
1774
1775 /*
1776  * kas_StringToKey - turn a string key into a key.
1777  *
1778  * PARAMETERS
1779  *
1780  * IN cellName - the name of the cell where the key will be used.
1781  *
1782  * IN string - the string to be converted.
1783  *
1784  * OUT key - the encryption key.
1785  *
1786  * LOCKS
1787  *
1788  * No locks are held by this function.
1789  *
1790  * RETURN CODES
1791  *
1792  * Returns != 0 upon successful completion.
1793  */
1794
1795 int ADMINAPI
1796 kas_StringToKey(const char *cellName, const char *string,
1797                 kas_encryptionKey_p key, afs_status_p st)
1798 {
1799     int rc = 0;
1800     afs_status_t tst = 0;
1801
1802     ka_StringToKey((char *)string, (char *)cellName, (struct ktc_encryptionKey *)key);
1803     rc = 1;
1804
1805     if (st != NULL) {
1806         *st = tst;
1807     }
1808     return rc;
1809 }
1810
1811
1812 /*
1813  * kas_KeyCheckSum - compute the checksum of an encryption key.
1814  *
1815  * PARAMETERS
1816  *
1817  * IN key - the encryption key.
1818  *
1819  * OUT cksumP - key checksum
1820  *
1821  * LOCKS
1822  *
1823  * No locks are held by this function.
1824  *
1825  * RETURN CODES
1826  *
1827  * Returns != 0 upon successful completion.
1828  */
1829
1830 int ADMINAPI
1831 kas_KeyCheckSum(const kas_encryptionKey_p key, unsigned int *cksumP,
1832                 afs_status_p st)
1833 {
1834     int rc = 0;
1835     afs_status_t tst = 0;
1836     afs_uint32 cksum32;
1837
1838     if ((tst = ka_KeyCheckSum((char *)key, &cksum32)) == 0) {
1839         *cksumP = cksum32;
1840         rc = 1;
1841     }
1842
1843     if (st != NULL) {
1844         *st = tst;
1845     }
1846     return rc;
1847 }