2 * Copyright 2000, International Business Machines Corporation and others.
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
10 #include <afsconfig.h>
11 #include <afs/param.h>
17 #include <rx/rxstat.h>
18 #include "afs_kasAdmin.h"
19 #include "../adminutil/afs_AdminInternal.h"
20 #include <afs/afs_AdminErrors.h>
21 #include <afs/afs_utilAdmin.h>
22 #include <afs/kauth.h>
23 #include <afs/kautils.h>
24 #include <afs/kaport.h>
32 struct ubik_client *servers;
35 } kas_server_t, *kas_server_p;
38 * IsValidServerHandle - verify the validity of a kas_server_t handle.
42 * IN serverHandle - the handle to be verified.
46 * No locks are obtained or released by this function
50 * Returns != 0 upon successful completion.
54 IsValidServerHandle(const kas_server_p serverHandle, afs_status_p st)
60 * Validate input parameters
63 if (serverHandle == NULL) {
64 tst = ADMKASSERVERHANDLENULL;
65 goto fail_IsValidServerHandle;
68 if ((serverHandle->begin_magic != BEGIN_MAGIC)
69 || (serverHandle->end_magic != END_MAGIC)) {
70 tst = ADMKASSERVERHANDLEBADMAGIC;
71 goto fail_IsValidServerHandle;
74 if (!serverHandle->is_valid) {
75 tst = ADMKASSERVERHANDLENOTVALID;
76 goto fail_IsValidServerHandle;
79 if (serverHandle->servers == NULL) {
80 tst = ADMKASSERVERHANDLENOSERVERS;
81 goto fail_IsValidServerHandle;
85 fail_IsValidServerHandle:
94 * IsValidCellHandle - verify the validity of a afs_cell_handle_t handle
95 * for doing kas related functions.
99 * IN cellHandle - the handle to be verified.
103 * No locks are obtained or released by this function
107 * Returns != 0 upon successful completion.
111 IsValidCellHandle(const afs_cell_handle_p cellHandle, afs_status_p st)
114 afs_status_t tst = 0;
117 * Validate input parameters
120 if (!CellHandleIsValid((void *)cellHandle, &tst)) {
121 goto fail_IsValidCellHandle;
124 if (!cellHandle->kas_valid) {
125 tst = ADMCLIENTCELLKASINVALID;
126 goto fail_IsValidCellHandle;
129 if (cellHandle->kas == NULL) {
130 tst = ADMCLIENTCELLKASNULL;
131 goto fail_IsValidCellHandle;
135 fail_IsValidCellHandle:
144 * For all kas admin functions that take a cellHandle and a serverHandle,
145 * the intention is that is the cellHandle is not NULL, we should use
146 * it. Otherwise, we use the serverHandle. It is an error for both
147 * of these parameters to be non-NULL.
151 * ChooseValidServer - given a serverHandle and a cellHandle, choose the
152 * one that is non-NULL, validate it, and return a ubik_client structure
157 * IN cellHandle - the cell where kas calls are to be made
159 * IN serverHandle - the group of server(s) that should be used to satisfy
164 * No locks are obtained or released by this function
168 * Returns != 0 upon successful completion.
172 ChooseValidServer(const afs_cell_handle_p cellHandle,
173 const kas_server_p serverHandle, kas_server_p kasHandle,
177 afs_status_t tst = 0;
180 * Validate input parameters
183 if (kasHandle == NULL) {
184 tst = ADMKASKASHANDLENULL;
185 goto fail_ChooseValidServer;
189 * Only one of the input handle parameters to this function should
192 if ((cellHandle == NULL) && (serverHandle == NULL)) {
193 tst = ADMKASCELLHANDLEANDSERVERHANDLENULL;
194 goto fail_ChooseValidServer;
197 if ((cellHandle != NULL) && (serverHandle != NULL)) {
198 tst = ADMKASCELLHANDLEANDSERVERHANDLENOTNULL;
199 goto fail_ChooseValidServer;
203 * Validate the non-NULL handle
206 if (cellHandle != NULL) {
207 if (IsValidCellHandle(cellHandle, &tst)) {
208 kasHandle->servers = cellHandle->kas;
209 kasHandle->cell = cellHandle->working_cell;
211 goto fail_ChooseValidServer;
214 if (IsValidServerHandle(serverHandle, &tst)) {
215 kasHandle->servers = serverHandle->servers;
216 kasHandle->cell = serverHandle->cell;
218 goto fail_ChooseValidServer;
222 kasHandle->begin_magic = BEGIN_MAGIC;
223 kasHandle->end_magic = END_MAGIC;
224 kasHandle->is_valid = 1;
227 fail_ChooseValidServer:
237 kaentryinfo_to_kas_principalEntry_t(struct kaentryinfo *from,
238 kas_principalEntry_p to, afs_status_p st)
241 afs_status_t tst = 0;
243 unsigned char misc_stuff[4];
246 tst = ADMKASFROMNULL;
247 goto fail_kaentryinfo_to_kas_principalEntry_t;
252 goto fail_kaentryinfo_to_kas_principalEntry_t;
255 if (from->flags & KAFADMIN) {
256 to->adminSetting = KAS_ADMIN;
258 to->adminSetting = NO_KAS_ADMIN;
261 if (from->flags & KAFNOTGS) {
262 to->tgsSetting = NO_TGS;
264 to->tgsSetting = TGS;
267 if (from->flags & KAFNOSEAL) {
268 to->encSetting = NO_ENCRYPT;
270 to->encSetting = ENCRYPT;
273 if (from->flags & KAFNOCPW) {
274 to->cpwSetting = NO_CHANGE_PASSWORD;
276 to->cpwSetting = CHANGE_PASSWORD;
279 reuse = (short)from->reserved3;
281 to->rpwSetting = REUSE_PASSWORD;
283 to->rpwSetting = NO_REUSE_PASSWORD;
287 if (from->user_expiration == NEVERDATE) {
288 to->userExpiration = 0;
290 to->userExpiration = from->user_expiration;
293 to->lastModTime = from->modification_time;
294 strcpy(to->lastModPrincipal.principal, from->modification_user.name);
295 strcpy(to->lastModPrincipal.instance, from->modification_user.instance);
296 to->lastChangePasswordTime = from->change_password_time;
297 to->maxTicketLifetime = from->max_ticket_lifetime;
298 to->keyVersion = from->key_version;
299 memcpy(&to->key, &from->key, sizeof(to->key));
300 to->keyCheckSum = from->keyCheckSum;
302 unpack_long(from->misc_auth_bytes, misc_stuff);
303 to->daysToPasswordExpire = misc_stuff[0];
304 to->failLoginCount = misc_stuff[2];
305 to->lockTime = misc_stuff[3] << 9;
308 fail_kaentryinfo_to_kas_principalEntry_t:
317 * kas_ServerOpen - open a handle to a set of kaserver's.
321 * IN cellHandle - a previously opened cellHandle that corresponds
322 * to the cell where the server(s) live.
324 * IN serverList - a NULL terminated list (a la argv) of server's that
327 * OUT serverHandleP - a pointer to a void pointer that upon successful
328 * completion contains serverHandle that can be used in other kas functions.
332 * No locks are obtained or released by this function
336 * Returns != 0 upon successful completion.
340 * This function make some assumptions about the afsconf_cell used by
341 * ka_AuthSpecificServersConn (since I just wrote ka_AuthSpecificServersConn).
342 * It only fills in the fields that are required.
344 * Also we assume that the servers listed are members of the cell in
345 * cellHandle without verifying that this is in fact the case. kas itself
346 * always assumes that the -servers parameter lists servers in the current
347 * cell without verifying, so I am no worse than the current
348 * implementation. In fact I'm actually a little more flexible since you
349 * can actually use my serverList to play with servers in another cell.
350 * You can't do that with kas. For certain functions in kas the same
351 * cell assumption can cause things to fail (the ka_StringToKey function in
356 kas_ServerOpen(const void *cellHandle, const char **serverList,
357 void **serverHandleP, afs_status_p st)
360 afs_status_t tst = 0;
361 afs_cell_handle_p c_handle = (afs_cell_handle_p) cellHandle;
362 int server_count = 0, server_addr;
363 struct afsconf_cell server_info;
364 kas_server_p k_handle = malloc(sizeof(kas_server_t));
367 * Validate input parameters
370 if (c_handle == NULL) {
371 tst = ADMCLIENTCELLHANDLENULL;
372 goto fail_kas_ServerOpen;
375 if (c_handle->kas_valid == 0) {
376 tst = ADMCLIENTCELLKASINVALID;
377 goto fail_kas_ServerOpen;
380 if (serverList == NULL) {
381 tst = ADMKASSERVERLISTNULL;
382 goto fail_kas_ServerOpen;
385 if (serverHandleP == NULL) {
386 tst = ADMKASSERVERHANDLEPNULL;
387 goto fail_kas_ServerOpen;
390 if (k_handle == NULL) {
392 goto fail_kas_ServerOpen;
395 k_handle->begin_magic = BEGIN_MAGIC;
396 k_handle->end_magic = END_MAGIC;
397 k_handle->is_valid = 0;
398 k_handle->servers = NULL;
401 * Convert serverList to numeric addresses
404 for (server_count = 0; serverList[server_count] != NULL; server_count++) {
405 if (server_count >= MAXHOSTSPERCELL) {
406 tst = ADMKASSERVERLISTTOOLONG;
407 goto fail_kas_ServerOpen;
409 if (util_AdminServerAddressGetFromName
410 (serverList[server_count], &server_addr, &tst)) {
411 server_info.hostAddr[server_count].sin_addr.s_addr =
413 server_info.hostAddr[server_count].sin_port =
414 htons(AFSCONF_KAUTHPORT);
416 goto fail_kas_ServerOpen;
420 if (server_count == 0) {
421 tst = ADMKASSERVERLISTEMPTY;
422 goto fail_kas_ServerOpen;
426 * Get a ubik_client handle for the specified servers
428 server_info.numServers = server_count;
431 ka_AuthSpecificServersConn(KA_MAINTENANCE_SERVICE,
432 &c_handle->tokens->kas_token,
433 &server_info, &k_handle->servers))) {
434 k_handle->is_valid = 1;
435 k_handle->cell = c_handle->working_cell;
436 *serverHandleP = (void *)k_handle;
438 goto fail_kas_ServerOpen;
444 if ((rc == 0) && (k_handle != NULL)) {
455 * kas_ServerClose - close a serverHandle.
459 * IN serverHandle - a serverHandle previously returned by kas_ServerOpen.
463 * No locks are obtained or released by this function
467 * Returns != 0 upon successful completion.
471 kas_ServerClose(const void *serverHandle, afs_status_p st)
474 afs_status_t tst = 0;
475 kas_server_p k_handle = (kas_server_p) serverHandle;
477 if (!IsValidServerHandle(k_handle, &tst)) {
478 goto fail_kas_ServerClose;
481 tst = ubik_ClientDestroy(k_handle->servers);
483 goto fail_kas_ServerClose;
486 k_handle->is_valid = 0;
490 fail_kas_ServerClose:
499 * kas_PrincipalCreate - create a new principal.
503 * IN cellHandle - a cellHandle previously returned by afsclient_CellOpen.
505 * IN serverHandle - a serverHandle previously returned by kas_ServerOpen.
507 * IN who - a kas_identity_p containing the identity of the new principal
510 * IN password - the new principal's initial password.
514 * No locks are obtained or released by this function
518 * Returns != 0 upon successful completion.
522 kas_PrincipalCreate(const void *cellHandle, const void *serverHandle,
523 const kas_identity_p who, const char *password,
527 afs_status_t tst = 0;
528 afs_cell_handle_p c_handle = (afs_cell_handle_p) cellHandle;
529 kas_server_p k_handle = (kas_server_p) serverHandle;
530 kas_server_t kaserver;
532 struct kas_encryptionKey kas_key;
535 * Validate input arguments and make rpc.
540 goto fail_kas_PrincipalCreate;
543 if (password == NULL) {
544 tst = ADMKASPASSWORDNULL;
545 goto fail_kas_PrincipalCreate;
548 if (!ChooseValidServer(c_handle, k_handle, &kaserver, &tst)) {
549 goto fail_kas_PrincipalCreate;
552 if (!kas_StringToKey(kaserver.cell, password, &kas_key, &tst)) {
553 goto fail_kas_PrincipalCreate;
556 memcpy(&key, &kas_key, sizeof(key));
559 ubik_KAM_CreateUser(kaserver.servers, 0, who->principal,
562 goto fail_kas_PrincipalCreate;
567 fail_kas_PrincipalCreate:
576 * kas_PrincipalDelete - delete an existing principal.
580 * IN cellHandle - a cellHandle previously returned by afsclient_CellOpen.
582 * IN serverHandle - a serverHandle previously returned by kas_ServerOpen.
584 * IN who - a kas_identity_p containing the identity of the principal
589 * No locks are obtained or released by this function
593 * Returns != 0 upon successful completion.
597 kas_PrincipalDelete(const void *cellHandle, const void *serverHandle,
598 const kas_identity_p who, afs_status_p st)
601 afs_status_t tst = 0;
602 afs_cell_handle_p c_handle = (afs_cell_handle_p) cellHandle;
603 kas_server_p k_handle = (kas_server_p) serverHandle;
604 kas_server_t kaserver;
607 * Validate input arguments and make rpc.
612 goto fail_kas_PrincipalDelete;
615 if (!ChooseValidServer(c_handle, k_handle, &kaserver, &tst)) {
616 goto fail_kas_PrincipalDelete;
619 ubik_KAM_DeleteUser(kaserver.servers, 0, who->principal,
622 goto fail_kas_PrincipalDelete;
626 fail_kas_PrincipalDelete:
635 * GetPrincipalLockStatus - get the lock status of a principal.
639 * IN kaserver - a valid kaserver handle previously returned by
642 * IN who - a kas_identity_p containing the identity of the principal
645 * OUT lockedUntil - the remaining number of seconds the principal is locked.
649 * No locks are obtained or released by this function
653 * Returns != 0 upon successful completion.
657 GetPrincipalLockStatus(const kas_server_p kaserver, const kas_identity_p who,
658 unsigned int *lockedUntil, afs_status_p st)
661 afs_status_t tst = 0;
667 * Validate input arguments and make rpc.
670 if (kaserver == NULL) {
671 tst = ADMKASKASERVERNULL;
672 goto fail_GetPrincipalLockStatus;
677 goto fail_GetPrincipalLockStatus;
680 if (lockedUntil == NULL) {
681 tst = ADMKASLOCKEDUNTILNULL;
682 goto fail_GetPrincipalLockStatus;
686 * Unlike every other kas rpc we make here, the lock/unlock rpc's
687 * aren't ubik based. So instead of calling ubik_Call, we use
688 * ubik_CallIter. ubik_CallIter steps through the list of hosts
689 * in the ubik_client and calls them one at a time. Since there's
690 * no synchronization of this data across the servers we have to
691 * manually keep track of the shortest time to unlock the user ourselves.
693 * The original inspiration for this function is ka_islocked
694 * in admin_tools.c. I think that function is totally bogus so I'm
697 * This function should contact all the kaservers and request the lock
698 * status of the principal. If any of the servers say the principal is
699 * unlocked, we report it as unlocked. If all the servers say the
700 * principal is locked, we find the server with the shortest lock time
701 * remaining on the principal and return that time.
703 * This is different than kas, but I think kas is buggy.
710 ubik_CallIter(KAM_LockStatus, kaserver->servers, UPUBIKONLY,
711 &count, (long)who->principal, (long)who->instance, (long)&locked, 0,
712 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0);
715 if ((locked < *lockedUntil) || !once) {
716 *lockedUntil = locked;
721 } while ((tst != UNOSERVERS) && (locked != 0));
724 * Check to see if any server reported this principal unlocked.
727 if ((tst == 0) && (locked == 0)) {
730 if ((tst == 0) || (tst == UNOSERVERS)) {
734 fail_GetPrincipalLockStatus:
743 * kas_PrincipalGet - retrieve information about a single principal.
747 * IN cellHandle - a cellHandle previously returned by afsclient_CellOpen.
749 * IN serverHandle - a serverHandle previously returned by kas_ServerOpen.
751 * IN who - a kas_identity_p containing the identity of the principal
754 * OUT principal - upon successful completion contains information
759 * No locks are obtained or released by this function
763 * Returns != 0 upon successful completion.
767 kas_PrincipalGet(const void *cellHandle, const void *serverHandle,
768 const kas_identity_p who, kas_principalEntry_p principal,
772 afs_status_t tst = 0;
773 afs_cell_handle_p c_handle = (afs_cell_handle_p) cellHandle;
774 kas_server_p k_handle = (kas_server_p) serverHandle;
775 kas_server_t kaserver;
776 struct kaentryinfo entry;
779 * Validate input arguments and make rpc.
784 goto fail_kas_PrincipalGet;
787 if (principal == NULL) {
788 tst = ADMKASPRINCIPALNULL;
789 goto fail_kas_PrincipalGet;
792 if (!ChooseValidServer(c_handle, k_handle, &kaserver, &tst)) {
793 goto fail_kas_PrincipalGet;
797 ubik_KAM_GetEntry(kaserver.servers, 0, who->principal,
798 who->instance, KAMAJORVERSION, &entry);
800 goto fail_kas_PrincipalGet;
804 * copy the kaentryinfo structure to our kas_principalEntry_t
807 if (!kaentryinfo_to_kas_principalEntry_t(&entry, principal, &tst)) {
808 goto fail_kas_PrincipalGet;
812 fail_kas_PrincipalGet:
820 typedef struct principal_get {
824 kas_server_t kaserver;
825 kas_identity_t principal[CACHED_ITEMS];
826 } principal_get_t, *principal_get_p;
829 DeletePrincipalSpecificData(void *rpc_specific, afs_status_p st)
832 afs_status_t tst = 0;
833 principal_get_p prin = (principal_get_p) rpc_specific;
835 prin->kaserver.is_valid = 0;
845 GetPrincipalRPC(void *rpc_specific, int slot, int *last_item,
846 int *last_item_contains_data, afs_status_p st)
849 afs_status_t tst = 0;
850 principal_get_p prin = (principal_get_p) rpc_specific;
853 ubik_KAM_ListEntry(prin->kaserver.servers, 0, prin->current,
854 &prin->next, &prin->count, (kaident *)&prin->principal[slot]);
856 prin->current = prin->next;
857 if (prin->next == 0) {
859 *last_item_contains_data = 0;
871 GetPrincipalFromCache(void *rpc_specific, int slot, void *dest,
875 afs_status_t tst = 0;
876 principal_get_p prin = (principal_get_p) rpc_specific;
878 memcpy(dest, &prin->principal[slot], sizeof(kas_identity_t));
888 * kas_PrincipalGetBegin - start the process of iterating over the entire
893 * IN cellHandle - a cellHandle previously returned by afsclient_CellOpen.
895 * IN serverHandle - a serverHandle previously returned by kas_ServerOpen.
897 * OUT iterationIdP - upon successful completion contains a iterator that
898 * can be passed to kas_PrincipalGetNext.
902 * No locks are obtained or released by this function
906 * Returns != 0 upon successful completion.
912 kas_PrincipalGetBegin(const void *cellHandle, const void *serverHandle,
913 void **iterationIdP, afs_status_p st)
916 afs_status_t tst = 0;
917 afs_cell_handle_p c_handle = (afs_cell_handle_p) cellHandle;
918 kas_server_p k_handle = (kas_server_p) serverHandle;
919 afs_admin_iterator_p iter = malloc(sizeof(afs_admin_iterator_t));
920 principal_get_p principal = malloc(sizeof(principal_get_t));
928 goto fail_kas_PrincipalGetBegin;
931 if (principal == NULL) {
933 goto fail_kas_PrincipalGetBegin;
936 if (iterationIdP == NULL) {
937 tst = ADMITERATIONIDPNULL;
938 goto fail_kas_PrincipalGetBegin;
941 if (!ChooseValidServer(c_handle, k_handle, &principal->kaserver, &tst)) {
942 goto fail_kas_PrincipalGetBegin;
946 * Initialize the iterator structure
949 principal->current = 0;
951 principal->count = 0;
953 (iter, (void *)principal, GetPrincipalRPC, GetPrincipalFromCache,
954 NULL, DeletePrincipalSpecificData, &tst)) {
955 *iterationIdP = (void *)iter;
959 fail_kas_PrincipalGetBegin:
965 if (principal != NULL) {
977 * kas_PrincipalGetNext - retrieve the next principal from the kaserver.
981 * IN iterationId - an iterator previously returned by kas_PrincipalGetBegin
983 * OUT who - upon successful completion contains the next principal from the
988 * Hold the iterator mutex across the call to the kaserver.
992 * Returns != 0 upon successful completion.
993 * Returns 0 and st == ADMITERATORDONE when the last entry is returned.
997 kas_PrincipalGetNext(const void *iterationId, kas_identity_p who,
1001 afs_status_t tst = 0;
1002 afs_admin_iterator_p iter = (afs_admin_iterator_p) iterationId;
1005 * Validate arguments
1009 tst = ADMKASWHONULL;
1010 goto fail_kas_PrincipalGetNext;
1014 tst = ADMITERATORNULL;
1015 goto fail_kas_PrincipalGetNext;
1018 rc = IteratorNext(iter, (void *)who, &tst);
1020 fail_kas_PrincipalGetNext:
1029 * kas_PrincipalGetDone - finish using a principal iterator
1033 * IN iterationId - an iterator previously returned by kas_PrincipalGetBegin
1037 * No locks are held by this function.
1041 * Returns != 0 upon successful completion.
1045 * It is the user's responsibility to make sure kas_PrincipalGetDone
1046 * is called only once for each iterator.
1050 kas_PrincipalGetDone(const void *iterationIdP, afs_status_p st)
1053 afs_status_t tst = 0;
1054 afs_admin_iterator_p iter = (afs_admin_iterator_p) iterationIdP;
1061 tst = ADMITERATORNULL;
1062 goto fail_kas_PrincipalGetDone;
1065 rc = IteratorDone(iter, &tst);
1067 fail_kas_PrincipalGetDone:
1076 * kas_PrincipalKeySet - set a principal's password to a known value.
1080 * IN cellHandle - a cellHandle previously returned by afsclient_CellOpen.
1082 * IN serverHandle - a serverHandle previously returned by kas_ServerOpen.
1084 * IN who - the principal for whom the password is being set.
1086 * IN keyVersion - the version number of the new key.
1088 * IN key - the new password.
1092 * No locks are held by this function.
1096 * Returns != 0 upon successful completion.
1100 kas_PrincipalKeySet(const void *cellHandle, const void *serverHandle,
1101 const kas_identity_p who, int keyVersion,
1102 const kas_encryptionKey_p kas_keyp, afs_status_p st)
1105 afs_status_t tst = 0;
1106 afs_cell_handle_p c_handle = (afs_cell_handle_p) cellHandle;
1107 kas_server_p k_handle = (kas_server_p) serverHandle;
1108 kas_server_t kaserver;
1112 * Validate input arguments and make rpc.
1116 tst = ADMKASWHONULL;
1117 goto fail_kas_PrincipalKeySet;
1120 if (kas_keyp == NULL) {
1121 tst = ADMKASKEYNULL;
1122 goto fail_kas_PrincipalKeySet;
1125 if (!ChooseValidServer(c_handle, k_handle, &kaserver, &tst)) {
1126 goto fail_kas_PrincipalKeySet;
1129 memcpy(&key, kas_keyp, sizeof(key));
1132 ubik_KAM_SetPassword(kaserver.servers, 0, who->principal,
1133 who->instance, keyVersion, key);
1134 memset(&key, 0, sizeof(key));
1136 goto fail_kas_PrincipalKeySet;
1139 /* If we failed to fail we must have succeeded */
1142 fail_kas_PrincipalKeySet:
1151 * kas_PrincipalLockStatusGet - determine a principal's lock status.
1155 * IN cellHandle - a cellHandle previously returned by afsclient_CellOpen.
1157 * IN serverHandle - a serverHandle previously returned by kas_ServerOpen.
1159 * IN who - the principal whose lock status is being checked.
1161 * OUT lock_end_timeP - the number of seconds until the principal is unlocked.
1162 * If 0 => user is unlocked.
1166 * No locks are held by this function.
1170 * Returns != 0 upon successful completion.
1174 * See the comments in GetPrincipalLockStatus regarding how the locking data
1175 * is kept INconsistently between servers.
1179 kas_PrincipalLockStatusGet(const void *cellHandle, const void *serverHandle,
1180 const kas_identity_p who,
1181 unsigned int *lock_end_timeP, afs_status_p st)
1184 afs_status_t tst = 0;
1185 afs_cell_handle_p c_handle = (afs_cell_handle_p) cellHandle;
1186 kas_server_p k_handle = (kas_server_p) serverHandle;
1187 kas_server_t kaserver;
1190 * Validate input arguments and make rpc.
1194 tst = ADMKASWHONULL;
1195 goto fail_kas_PrincipalLockStatusGet;
1198 if (lock_end_timeP == NULL) {
1199 tst = ADMKASLOCKENDTIMEPNULL;
1200 goto fail_kas_PrincipalLockStatusGet;
1203 if (!ChooseValidServer(c_handle, k_handle, &kaserver, &tst)) {
1204 goto fail_kas_PrincipalLockStatusGet;
1207 rc = GetPrincipalLockStatus(&kaserver, who, lock_end_timeP, &tst);
1209 fail_kas_PrincipalLockStatusGet:
1218 * kas_PrincipalUnlock - unlock a principal.
1222 * IN cellHandle - a cellHandle previously returned by afsclient_CellOpen.
1224 * IN serverHandle - a serverHandle previously returned by kas_ServerOpen.
1226 * IN who - the principal who is being unlocked.
1230 * No locks are held by this function.
1234 * Returns != 0 upon successful completion.
1238 * See the comments in GetPrincipalLockStatus regarding how the locking data
1239 * is kept INconsistently between servers.
1243 kas_PrincipalUnlock(const void *cellHandle, const void *serverHandle,
1244 const kas_identity_p who, afs_status_p st)
1247 afs_status_t tst = 0;
1248 afs_cell_handle_p c_handle = (afs_cell_handle_p) cellHandle;
1249 kas_server_p k_handle = (kas_server_p) serverHandle;
1250 kas_server_t kaserver;
1252 afs_status_t save_tst = 0;
1255 * Validate input arguments and make rpc.
1259 tst = ADMKASWHONULL;
1260 goto fail_kas_PrincipalUnlock;
1263 if (!ChooseValidServer(c_handle, k_handle, &kaserver, &tst)) {
1264 goto fail_kas_PrincipalUnlock;
1269 ubik_CallIter(KAM_Unlock, kaserver.servers, 0, &count,
1270 (long)who->principal, (long)who->instance, 0, 0, 0,
1271 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0);
1272 if (tst && (tst != UNOSERVERS)) {
1273 if (save_tst == 0) {
1274 save_tst = tst; /* save the first failure */
1277 } while (tst != UNOSERVERS);
1279 if ((tst == 0) || (tst == UNOSERVERS)) {
1283 fail_kas_PrincipalUnlock:
1292 getPrincipalFlags(const void *cellHandle, const void *serverHandle,
1293 const kas_identity_p who, afs_int32 * cur_flags,
1297 afs_status_t tst = 0;
1298 afs_cell_handle_p c_handle = (afs_cell_handle_p) cellHandle;
1299 kas_server_p k_handle = (kas_server_p) serverHandle;
1300 kas_server_t kaserver;
1301 struct kaentryinfo tentry;
1303 if (!ChooseValidServer(c_handle, k_handle, &kaserver, &tst)) {
1304 goto fail_getPrincipalFlags;
1308 ubik_KAM_GetEntry(kaserver.servers, 0, who->principal,
1309 who->instance, KAMAJORVERSION, &tentry);
1311 *cur_flags = tentry.flags;
1315 fail_getPrincipalFlags:
1324 * kas_PrincipalFieldsSet - modify an existing principal.
1328 * IN cellHandle - a cellHandle previously returned by afsclient_CellOpen.
1330 * IN serverHandle - a serverHandle previously returned by kas_ServerOpen.
1332 * IN who - the principal who is being modified.
1334 * IN isAdmin - the admin status of the principal.
1336 * IN grantTickets - should the TGS issue tickets for the principal.
1338 * IN canEncrypt - should the TGS allow the use of encryption via the
1341 * IN canChangePassword - should the principal be allowed to change their
1344 * IN expirationDate - the date when the principal will expire.
1346 * IN maxTicketLifetime - the maximum lifetime of a ticket issued for
1349 * IN passwordExpires - the maximum number of days a particular
1350 * password can be used. The limit is 255, 0 => no expiration.
1352 * IN passwordReuse - can a password be reused by this principal.
1354 * IN failedPasswordAttempts - number of failed login attempts before
1355 * a principal is locked. The limit is 255, 0 => no limit.
1357 * IN failedPasswordLockTime - the number of seconds a principal is
1358 * locked once failedPasswordAttempts is reached. Some bizarre rounding
1359 * occurs for this value, see kas for more details.
1363 * No locks are held by this function.
1367 * Returns != 0 upon successful completion.
1371 * See the comments in GetPrincipalLockStatus regarding how the locking data
1372 * is kept INconsistently between servers.
1376 kas_PrincipalFieldsSet(const void *cellHandle, const void *serverHandle,
1377 const kas_identity_p who, const kas_admin_p isAdmin,
1378 const kas_tgs_p grantTickets,
1379 const kas_enc_p canEncrypt,
1380 const kas_cpw_p canChangePassword,
1381 const unsigned int *expirationDate,
1382 const unsigned int *maxTicketLifetime,
1383 const unsigned int *passwordExpires,
1384 const kas_rpw_p passwordReuse,
1385 const unsigned int *failedPasswordAttempts,
1386 const unsigned int *failedPasswordLockTime,
1390 afs_status_t tst = 0;
1391 afs_cell_handle_p c_handle = (afs_cell_handle_p) cellHandle;
1392 kas_server_p k_handle = (kas_server_p) serverHandle;
1393 kas_server_t kaserver;
1394 afs_int32 flags = 0;
1395 Date expiration = 0;
1396 afs_int32 lifetime = 0;
1398 char spare_bytes[4] = { 0, 0, 0, 0 };
1399 int somethings_changing = 0;
1402 * Validate input arguments.
1406 tst = ADMKASWHONULL;
1407 goto fail_kas_PrincipalFieldsSet;
1411 * set flags based upon input
1413 * If we're changing the flags, we need to get the current value of
1414 * the flags first and then make the changes
1417 if ((isAdmin != NULL) || (grantTickets != NULL) || (canEncrypt != NULL)
1418 || (canChangePassword != NULL)) {
1419 if (!getPrincipalFlags(cellHandle, serverHandle, who, &flags, &tst)) {
1420 goto fail_kas_PrincipalFieldsSet;
1424 if (isAdmin != NULL) {
1425 somethings_changing = 1;
1426 if (*isAdmin == KAS_ADMIN) {
1433 if (grantTickets != NULL) {
1434 somethings_changing = 1;
1435 if (*grantTickets == NO_TGS) {
1442 if (canEncrypt != NULL) {
1443 somethings_changing = 1;
1444 if (*canEncrypt == NO_ENCRYPT) {
1447 flags &= ~KAFNOSEAL;
1451 if (canChangePassword != NULL) {
1452 somethings_changing = 1;
1453 if (*canChangePassword == NO_CHANGE_PASSWORD) {
1460 flags = (flags & KAF_SETTABLE_FLAGS) | KAFNORMAL;
1462 if (expirationDate != NULL) {
1463 somethings_changing = 1;
1464 expiration = *expirationDate;
1467 if (maxTicketLifetime != NULL) {
1468 somethings_changing = 1;
1469 lifetime = *maxTicketLifetime;
1472 if (passwordExpires != NULL) {
1473 if (*passwordExpires > 255) {
1474 tst = ADMKASPASSWORDEXPIRESTOOBIG;
1475 goto fail_kas_PrincipalFieldsSet;
1477 somethings_changing = 1;
1478 spare_bytes[0] = *passwordExpires + 1;
1481 if (passwordReuse != NULL) {
1482 somethings_changing = 1;
1483 if (*passwordReuse == REUSE_PASSWORD) {
1484 spare_bytes[1] = KA_REUSEPW;
1486 spare_bytes[1] = KA_NOREUSEPW;
1490 if (failedPasswordAttempts != NULL) {
1491 if (*failedPasswordAttempts > 255) {
1492 tst = ADMKASFAILEDPASSWORDATTEMPTSTOOBIG;
1493 goto fail_kas_PrincipalFieldsSet;
1495 somethings_changing = 1;
1496 spare_bytes[2] = *failedPasswordAttempts + 1;
1499 if (failedPasswordLockTime != NULL) {
1500 if (*failedPasswordLockTime > 36 * 60 * 60) {
1501 tst = ADMKASFAILEDPASSWORDLOCKTIME;
1502 goto fail_kas_PrincipalFieldsSet;
1504 somethings_changing = 1;
1505 spare_bytes[3] = ((*failedPasswordLockTime + 511) >> 9) + 1;
1508 was_spare = pack_long(spare_bytes);
1510 if (somethings_changing) {
1511 if (!ChooseValidServer(c_handle, k_handle, &kaserver, &tst)) {
1512 goto fail_kas_PrincipalFieldsSet;
1515 ubik_KAM_SetFields(kaserver.servers, 0, who->principal,
1516 who->instance, flags, expiration, lifetime, -1,
1522 tst = ADMKASPRINCIPALFIELDSNOCHANGE;
1525 fail_kas_PrincipalFieldsSet:
1534 * kas_ServerStatsGet - get server statistics.
1538 * IN cellHandle - a cellHandle previously returned by afsclient_CellOpen.
1540 * IN serverHandle - a serverHandle previously returned by kas_ServerOpen.
1542 * OUT stats - the statistics retrieved.
1546 * No locks are held by this function.
1550 * Returns != 0 upon successful completion.
1554 kas_ServerStatsGet(const void *cellHandle, const void *serverHandle,
1555 kas_serverStats_p stats, afs_status_p st)
1558 afs_status_t tst = 0;
1559 afs_cell_handle_p c_handle = (afs_cell_handle_p) cellHandle;
1560 kas_server_p k_handle = (kas_server_p) serverHandle;
1561 kas_server_t kaserver;
1568 * Validate input arguments and make rpc.
1571 if (stats == NULL) {
1572 tst = ADMKASSTATSNULL;
1573 goto fail_kas_ServerStatsGet;
1576 if (!ChooseValidServer(c_handle, k_handle, &kaserver, &tst)) {
1577 goto fail_kas_ServerStatsGet;
1581 ubik_KAM_GetStats(kaserver.servers, 0, KAMAJORVERSION, &admins,
1582 &statics, &dynamics);
1584 goto fail_kas_ServerStatsGet;
1587 stats->allocations = statics.allocs;
1588 stats->frees = statics.frees;
1589 stats->changePasswordRequests = statics.cpws;
1590 stats->adminAccounts = admins;
1591 stats->host = dynamics.host;
1592 stats->serverStartTime = dynamics.start_time;
1593 stats->hashTableUtilization = dynamics.hashTableUtilization;
1595 i = sizeof(kas_serverProcStats_t);
1596 memcpy(&stats->authenticate, &dynamics.Authenticate, i);
1597 memcpy(&stats->changePassword, &dynamics.ChangePassword, i);
1598 memcpy(&stats->getTicket, &dynamics.GetTicket, i);
1599 memcpy(&stats->createUser, &dynamics.CreateUser, i);
1600 memcpy(&stats->setPassword, &dynamics.SetPassword, i);
1601 memcpy(&stats->setFields, &dynamics.SetFields, i);
1602 memcpy(&stats->deleteUser, &dynamics.DeleteUser, i);
1603 memcpy(&stats->getEntry, &dynamics.GetEntry, i);
1604 memcpy(&stats->listEntry, &dynamics.ListEntry, i);
1605 memcpy(&stats->getStats, &dynamics.GetStats, i);
1606 memcpy(&stats->getPassword, &dynamics.GetPassword, i);
1607 memcpy(&stats->getRandomKey, &dynamics.GetRandomKey, i);
1608 memcpy(&stats->debug, &dynamics.Debug, i);
1609 memcpy(&stats->udpAuthenticate, &dynamics.UAuthenticate, i);
1610 memcpy(&stats->udpGetTicket, &dynamics.UGetTicket, i);
1611 memcpy(&stats->unlock, &dynamics.Unlock, i);
1612 memcpy(&stats->lockStatus, &dynamics.LockStatus, i);
1614 stats->stringChecks = dynamics.string_checks;
1617 fail_kas_ServerStatsGet:
1626 * kas_ServerDebugGet - get server debug info.
1630 * IN cellHandle - a cellHandle previously returned by afsclient_CellOpen.
1632 * IN serverHandle - a serverHandle previously returned by kas_ServerOpen.
1634 * OUT stats - the debug info retrieved.
1638 * No locks are held by this function.
1642 * Returns != 0 upon successful completion.
1646 kas_ServerDebugGet(const void *cellHandle, const void *serverHandle,
1647 kas_serverDebugInfo_p debug, afs_status_p st)
1650 afs_status_t tst = 0;
1651 afs_cell_handle_p c_handle = (afs_cell_handle_p) cellHandle;
1652 kas_server_p k_handle = (kas_server_p) serverHandle;
1653 kas_server_t kaserver;
1654 struct ka_debugInfo info;
1658 * Validate input arguments and make rpc.
1661 if (debug == NULL) {
1662 tst = ADMKASDEBUGNULL;
1663 goto fail_kas_ServerDebugGet;
1666 if (!ChooseValidServer(c_handle, k_handle, &kaserver, &tst)) {
1667 goto fail_kas_ServerDebugGet;
1669 tst = ubik_KAM_Debug(kaserver.servers, 0, KAMAJORVERSION, 0, &info);
1671 goto fail_kas_ServerDebugGet;
1673 debug->host = info.host;
1674 debug->serverStartTime = info.startTime;
1675 debug->currentTime = info.reserved1;
1676 debug->noAuth = info.noAuth;
1677 debug->lastTransaction = info.lastTrans;
1678 strcpy(debug->lastOperation, info.lastOperation);
1679 strcpy(debug->lastPrincipalAuth, info.lastAuth);
1680 strcpy(debug->lastPrincipalUDPAuth, info.lastUAuth);
1681 strcpy(debug->lastPrincipalTGS, info.lastTGS);
1682 strcpy(debug->lastPrincipalUDPTGS, info.lastUTGS);
1683 strcpy(debug->lastPrincipalAdmin, info.lastAdmin);
1684 strcpy(debug->lastServerTGS, info.lastTGSServer);
1685 strcpy(debug->lastServerUDPTGS, info.lastUTGSServer);
1686 debug->nextAutoCheckPointWrite = info.nextAutoCPW;
1687 debug->updatesRemainingBeforeAutoCheckPointWrite = info.updatesRemaining;
1688 debug->dbHeaderRead = info.dbHeaderRead;
1689 debug->dbVersion = info.dbVersion;
1690 debug->dbFreePtr = info.dbFreePtr;
1691 debug->dbEOFPtr = info.dbEofPtr;
1692 debug->dbKvnoPtr = info.dbKvnoPtr;
1693 debug->dbSpecialKeysVersion = info.dbSpecialKeysVersion;
1694 debug->dbHeaderLock = info.cheader_lock;
1695 debug->keyCacheLock = info.keycache_lock;
1696 debug->keyCacheVersion = info.kcVersion;
1697 debug->keyCacheSize = info.kcSize;
1698 debug->keyCacheUsed = info.kcUsed;
1699 for (i = 0; i < info.kcUsed; i++) {
1700 debug->keyCache[i].lastUsed = info.kcInfo[i].used;
1701 debug->keyCache[i].keyVersionNumber = info.kcInfo[i].kvno;
1702 debug->keyCache[i].primary = info.kcInfo[i].primary;
1703 debug->keyCache[i].keyCheckSum = info.kcInfo[i].keycksum;
1704 strcpy(debug->keyCache[i].principal, info.kcInfo[i].principal);
1708 fail_kas_ServerDebugGet:
1717 * kas_ServerRandomKeyGet - get a random key from a server.
1721 * IN cellHandle - a cellHandle previously returned by afsclient_CellOpen.
1723 * IN serverHandle - a serverHandle previously returned by kas_ServerOpen.
1725 * OUT key - a random key.
1729 * No locks are held by this function.
1733 * Returns != 0 upon successful completion.
1737 kas_ServerRandomKeyGet(const void *cellHandle, const void *serverHandle,
1738 kas_encryptionKey_p kas_keyp, afs_status_p st)
1741 afs_status_t tst = 0;
1742 afs_cell_handle_p c_handle = (afs_cell_handle_p) cellHandle;
1743 kas_server_p k_handle = (kas_server_p) serverHandle;
1744 kas_server_t kaserver;
1748 * Validate input arguments and make rpc.
1751 if (kas_keyp == NULL) {
1752 tst = ADMKASKEYNULL;
1753 goto fail_kas_ServerRandomKeyGet;
1756 if (!ChooseValidServer(c_handle, k_handle, &kaserver, &tst)) {
1757 goto fail_kas_ServerRandomKeyGet;
1760 tst = ubik_KAM_GetRandomKey(kaserver.servers, 0, &key);
1762 goto fail_kas_ServerRandomKeyGet;
1764 memcpy(kas_keyp, &key, sizeof(*kas_keyp));
1767 fail_kas_ServerRandomKeyGet:
1776 * kas_StringToKey - turn a string key into a key.
1780 * IN cellName - the name of the cell where the key will be used.
1782 * IN string - the string to be converted.
1784 * OUT key - the encryption key.
1788 * No locks are held by this function.
1792 * Returns != 0 upon successful completion.
1796 kas_StringToKey(const char *cellName, const char *string,
1797 kas_encryptionKey_p key, afs_status_p st)
1800 afs_status_t tst = 0;
1802 ka_StringToKey((char *)string, (char *)cellName, (struct ktc_encryptionKey *)key);
1813 * kas_KeyCheckSum - compute the checksum of an encryption key.
1817 * IN key - the encryption key.
1819 * OUT cksumP - key checksum
1823 * No locks are held by this function.
1827 * Returns != 0 upon successful completion.
1831 kas_KeyCheckSum(const kas_encryptionKey_p key, unsigned int *cksumP,
1835 afs_status_t tst = 0;
1838 if ((tst = ka_KeyCheckSum((char *)key, &cksum32)) == 0) {