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