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