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>
27 #include "afs_kasAdmin.h"
28 #include "../adminutil/afs_AdminInternal.h"
29 #include <afs/afs_AdminErrors.h>
30 #include <afs/afs_utilAdmin.h>
31 #include <afs/kauth.h>
32 #include <afs/kautils.h>
33 #include <afs/kaport.h>
41 struct ubik_client *servers;
44 } kas_server_t, *kas_server_p;
47 * IsValidServerHandle - verify the validity of a kas_server_t handle.
51 * IN serverHandle - the handle to be verified.
55 * No locks are obtained or released by this function
59 * Returns != 0 upon successful completion.
63 IsValidServerHandle(const kas_server_p serverHandle, afs_status_p st)
69 * Validate input parameters
72 if (serverHandle == NULL) {
73 tst = ADMKASSERVERHANDLENULL;
74 goto fail_IsValidServerHandle;
77 if ((serverHandle->begin_magic != BEGIN_MAGIC)
78 || (serverHandle->end_magic != END_MAGIC)) {
79 tst = ADMKASSERVERHANDLEBADMAGIC;
80 goto fail_IsValidServerHandle;
83 if (!serverHandle->is_valid) {
84 tst = ADMKASSERVERHANDLENOTVALID;
85 goto fail_IsValidServerHandle;
88 if (serverHandle->servers == NULL) {
89 tst = ADMKASSERVERHANDLENOSERVERS;
90 goto fail_IsValidServerHandle;
94 fail_IsValidServerHandle:
103 * IsValidCellHandle - verify the validity of a afs_cell_handle_t handle
104 * for doing kas related functions.
108 * IN cellHandle - the handle to be verified.
112 * No locks are obtained or released by this function
116 * Returns != 0 upon successful completion.
120 IsValidCellHandle(const afs_cell_handle_p cellHandle, afs_status_p st)
123 afs_status_t tst = 0;
126 * Validate input parameters
129 if (!CellHandleIsValid((void *)cellHandle, &tst)) {
130 goto fail_IsValidCellHandle;
133 if (!cellHandle->kas_valid) {
134 tst = ADMCLIENTCELLKASINVALID;
135 goto fail_IsValidCellHandle;
138 if (cellHandle->kas == NULL) {
139 tst = ADMCLIENTCELLKASNULL;
140 goto fail_IsValidCellHandle;
144 fail_IsValidCellHandle:
153 * For all kas admin functions that take a cellHandle and a serverHandle,
154 * the intention is that is the cellHandle is not NULL, we should use
155 * it. Otherwise, we use the serverHandle. It is an error for both
156 * of these parameters to be non-NULL.
160 * ChooseValidServer - given a serverHandle and a cellHandle, choose the
161 * one that is non-NULL, validate it, and return a ubik_client structure
166 * IN cellHandle - the cell where kas calls are to be made
168 * IN serverHandle - the group of server(s) that should be used to satisfy
173 * No locks are obtained or released by this function
177 * Returns != 0 upon successful completion.
181 ChooseValidServer(const afs_cell_handle_p cellHandle,
182 const kas_server_p serverHandle, kas_server_p kasHandle,
186 afs_status_t tst = 0;
189 * Validate input parameters
192 if (kasHandle == NULL) {
193 tst = ADMKASKASHANDLENULL;
194 goto fail_ChooseValidServer;
198 * Only one of the input handle parameters to this function should
201 if ((cellHandle == NULL) && (serverHandle == NULL)) {
202 tst = ADMKASCELLHANDLEANDSERVERHANDLENULL;
203 goto fail_ChooseValidServer;
206 if ((cellHandle != NULL) && (serverHandle != NULL)) {
207 tst = ADMKASCELLHANDLEANDSERVERHANDLENOTNULL;
208 goto fail_ChooseValidServer;
212 * Validate the non-NULL handle
215 if (cellHandle != NULL) {
216 if (IsValidCellHandle(cellHandle, &tst)) {
217 kasHandle->servers = cellHandle->kas;
218 kasHandle->cell = cellHandle->working_cell;
220 goto fail_ChooseValidServer;
223 if (IsValidServerHandle(serverHandle, &tst)) {
224 kasHandle->servers = serverHandle->servers;
225 kasHandle->cell = serverHandle->cell;
227 goto fail_ChooseValidServer;
231 kasHandle->begin_magic = BEGIN_MAGIC;
232 kasHandle->end_magic = END_MAGIC;
233 kasHandle->is_valid = 1;
236 fail_ChooseValidServer:
246 kaentryinfo_to_kas_principalEntry_t(struct kaentryinfo *from,
247 kas_principalEntry_p to, afs_status_p st)
250 afs_status_t tst = 0;
252 unsigned char misc_stuff[4];
255 tst = ADMKASFROMNULL;
256 goto fail_kaentryinfo_to_kas_principalEntry_t;
261 goto fail_kaentryinfo_to_kas_principalEntry_t;
264 if (from->flags & KAFADMIN) {
265 to->adminSetting = KAS_ADMIN;
267 to->adminSetting = NO_KAS_ADMIN;
270 if (from->flags & KAFNOTGS) {
271 to->tgsSetting = NO_TGS;
273 to->tgsSetting = TGS;
276 if (from->flags & KAFNOSEAL) {
277 to->encSetting = NO_ENCRYPT;
279 to->encSetting = ENCRYPT;
282 if (from->flags & KAFNOCPW) {
283 to->cpwSetting = NO_CHANGE_PASSWORD;
285 to->cpwSetting = CHANGE_PASSWORD;
288 reuse = (short)from->reserved3;
290 to->rpwSetting = REUSE_PASSWORD;
292 to->rpwSetting = NO_REUSE_PASSWORD;
296 if (from->user_expiration == NEVERDATE) {
297 to->userExpiration = 0;
299 to->userExpiration = from->user_expiration;
302 to->lastModTime = from->modification_time;
303 strcpy(to->lastModPrincipal.principal, from->modification_user.name);
304 strcpy(to->lastModPrincipal.instance, from->modification_user.instance);
305 to->lastChangePasswordTime = from->change_password_time;
306 to->maxTicketLifetime = from->max_ticket_lifetime;
307 to->keyVersion = from->key_version;
308 memcpy(&to->key, &from->key, sizeof(to->key));
309 to->keyCheckSum = from->keyCheckSum;
311 unpack_long(from->misc_auth_bytes, misc_stuff);
312 to->daysToPasswordExpire = misc_stuff[0];
313 to->failLoginCount = misc_stuff[2];
314 to->lockTime = misc_stuff[3] << 9;
317 fail_kaentryinfo_to_kas_principalEntry_t:
326 * kas_ServerOpen - open a handle to a set of kaserver's.
330 * IN cellHandle - a previously opened cellHandle that corresponds
331 * to the cell where the server(s) live.
333 * IN serverList - a NULL terminated list (a la argv) of server's that
336 * OUT serverHandleP - a pointer to a void pointer that upon successful
337 * completion contains serverHandle that can be used in other kas functions.
341 * No locks are obtained or released by this function
345 * Returns != 0 upon successful completion.
349 * This function make some assumptions about the afsconf_cell used by
350 * ka_AuthSpecificServersConn (since I just wrote ka_AuthSpecificServersConn).
351 * It only fills in the fields that are required.
353 * Also we assume that the servers listed are members of the cell in
354 * cellHandle without verifying that this is in fact the case. kas itself
355 * always assumes that the -servers parameter lists servers in the current
356 * cell without verifying, so I am no worse than the current
357 * implementation. In fact I'm actually a little more flexible since you
358 * can actually use my serverList to play with servers in another cell.
359 * You can't do that with kas. For certain functions in kas the same
360 * cell assumption can cause things to fail (the ka_StringToKey function in
365 kas_ServerOpen(const void *cellHandle, const char **serverList,
366 void **serverHandleP, afs_status_p st)
369 afs_status_t tst = 0;
370 afs_cell_handle_p c_handle = (afs_cell_handle_p) cellHandle;
371 int server_count = 0, server_addr;
372 struct afsconf_cell server_info;
373 kas_server_p k_handle = (kas_server_p) malloc(sizeof(kas_server_t));
376 * Validate input parameters
379 if (c_handle == NULL) {
380 tst = ADMCLIENTCELLHANDLENULL;
381 goto fail_kas_ServerOpen;
384 if (c_handle->kas_valid == 0) {
385 tst = ADMCLIENTCELLKASINVALID;
386 goto fail_kas_ServerOpen;
389 if (serverList == NULL) {
390 tst = ADMKASSERVERLISTNULL;
391 goto fail_kas_ServerOpen;
394 if (serverHandleP == NULL) {
395 tst = ADMKASSERVERHANDLEPNULL;
396 goto fail_kas_ServerOpen;
399 if (k_handle == NULL) {
401 goto fail_kas_ServerOpen;
404 k_handle->begin_magic = BEGIN_MAGIC;
405 k_handle->end_magic = END_MAGIC;
406 k_handle->is_valid = 0;
407 k_handle->servers = NULL;
410 * Convert serverList to numeric addresses
413 for (server_count = 0; serverList[server_count] != NULL; server_count++) {
414 if (server_count >= MAXHOSTSPERCELL) {
415 tst = ADMKASSERVERLISTTOOLONG;
416 goto fail_kas_ServerOpen;
418 if (util_AdminServerAddressGetFromName
419 (serverList[server_count], &server_addr, &tst)) {
420 server_info.hostAddr[server_count].sin_addr.s_addr =
422 server_info.hostAddr[server_count].sin_port =
423 htons(AFSCONF_KAUTHPORT);
425 goto fail_kas_ServerOpen;
429 if (server_count == 0) {
430 tst = ADMKASSERVERLISTEMPTY;
431 goto fail_kas_ServerOpen;
435 * Get a ubik_client handle for the specified servers
437 server_info.numServers = server_count;
440 ka_AuthSpecificServersConn(KA_MAINTENANCE_SERVICE,
441 &c_handle->tokens->kas_token,
442 &server_info, &k_handle->servers))) {
443 k_handle->is_valid = 1;
444 k_handle->cell = c_handle->working_cell;
445 *serverHandleP = (void *)k_handle;
447 goto fail_kas_ServerOpen;
453 if ((rc == 0) && (k_handle != NULL)) {
464 * kas_ServerClose - close a serverHandle.
468 * IN serverHandle - a serverHandle previously returned by kas_ServerOpen.
472 * No locks are obtained or released by this function
476 * Returns != 0 upon successful completion.
480 kas_ServerClose(const void *serverHandle, afs_status_p st)
483 afs_status_t tst = 0;
484 kas_server_p k_handle = (kas_server_p) serverHandle;
486 if (!IsValidServerHandle(k_handle, &tst)) {
487 goto fail_kas_ServerClose;
490 tst = ubik_ClientDestroy(k_handle->servers);
492 goto fail_kas_ServerClose;
495 k_handle->is_valid = 0;
499 fail_kas_ServerClose:
508 * kas_PrincipalCreate - create a new principal.
512 * IN cellHandle - a cellHandle previously returned by afsclient_CellOpen.
514 * IN serverHandle - a serverHandle previously returned by kas_ServerOpen.
516 * IN who - a kas_identity_p containing the identity of the new principal
519 * IN password - the new principal's initial password.
523 * No locks are obtained or released by this function
527 * Returns != 0 upon successful completion.
531 kas_PrincipalCreate(const void *cellHandle, const void *serverHandle,
532 const kas_identity_p who, const char *password,
536 afs_status_t tst = 0;
537 afs_cell_handle_p c_handle = (afs_cell_handle_p) cellHandle;
538 kas_server_p k_handle = (kas_server_p) serverHandle;
539 kas_server_t kaserver;
541 struct kas_encryptionKey kas_key;
544 * Validate input arguments and make rpc.
549 goto fail_kas_PrincipalCreate;
552 if (password == NULL) {
553 tst = ADMKASPASSWORDNULL;
554 goto fail_kas_PrincipalCreate;
557 if (!ChooseValidServer(c_handle, k_handle, &kaserver, &tst)) {
558 goto fail_kas_PrincipalCreate;
561 if (!kas_StringToKey(kaserver.cell, password, &kas_key, &tst)) {
562 goto fail_kas_PrincipalCreate;
565 memcpy(&key, &kas_key, sizeof(key));
568 ubik_KAM_CreateUser(kaserver.servers, 0, who->principal,
571 goto fail_kas_PrincipalCreate;
576 fail_kas_PrincipalCreate:
585 * kas_PrincipalDelete - delete an existing principal.
589 * IN cellHandle - a cellHandle previously returned by afsclient_CellOpen.
591 * IN serverHandle - a serverHandle previously returned by kas_ServerOpen.
593 * IN who - a kas_identity_p containing the identity of the principal
598 * No locks are obtained or released by this function
602 * Returns != 0 upon successful completion.
606 kas_PrincipalDelete(const void *cellHandle, const void *serverHandle,
607 const kas_identity_p who, afs_status_p st)
610 afs_status_t tst = 0;
611 afs_cell_handle_p c_handle = (afs_cell_handle_p) cellHandle;
612 kas_server_p k_handle = (kas_server_p) serverHandle;
613 kas_server_t kaserver;
616 * Validate input arguments and make rpc.
621 goto fail_kas_PrincipalDelete;
624 if (!ChooseValidServer(c_handle, k_handle, &kaserver, &tst)) {
625 goto fail_kas_PrincipalDelete;
628 ubik_KAM_DeleteUser(kaserver.servers, 0, who->principal,
631 goto fail_kas_PrincipalDelete;
635 fail_kas_PrincipalDelete:
644 * GetPrincipalLockStatus - get the lock status of a principal.
648 * IN kaserver - a valid kaserver handle previously returned by
651 * IN who - a kas_identity_p containing the identity of the principal
654 * OUT lockedUntil - the remaining number of seconds the principal is locked.
658 * No locks are obtained or released by this function
662 * Returns != 0 upon successful completion.
666 GetPrincipalLockStatus(const kas_server_p kaserver, const kas_identity_p who,
667 unsigned int *lockedUntil, afs_status_p st)
670 afs_status_t tst = 0;
676 * Validate input arguments and make rpc.
679 if (kaserver == NULL) {
680 tst = ADMKASKASERVERNULL;
681 goto fail_GetPrincipalLockStatus;
686 goto fail_GetPrincipalLockStatus;
689 if (lockedUntil == NULL) {
690 tst = ADMKASLOCKEDUNTILNULL;
691 goto fail_GetPrincipalLockStatus;
695 * Unlike every other kas rpc we make here, the lock/unlock rpc's
696 * aren't ubik based. So instead of calling ubik_Call, we use
697 * ubik_CallIter. ubik_CallIter steps through the list of hosts
698 * in the ubik_client and calls them one at a time. Since there's
699 * no synchronization of this data across the servers we have to
700 * manually keep track of the shortest time to unlock the user ourselves.
702 * The original inspiration for this function is ka_islocked
703 * in admin_tools.c. I think that function is totally bogus so I'm
706 * This function should contact all the kaservers and request the lock
707 * status of the principal. If any of the servers say the principal is
708 * unlocked, we report it as unlocked. If all the servers say the
709 * principal is locked, we find the server with the shortest lock time
710 * remaining on the principal and return that time.
712 * This is different than kas, but I think kas is buggy.
719 ubik_CallIter(KAM_LockStatus, kaserver->servers, UPUBIKONLY,
720 &count, (long)who->principal, (long)who->instance, (long)&locked, 0,
721 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0);
724 if ((locked < *lockedUntil) || !once) {
725 *lockedUntil = locked;
730 } while ((tst != UNOSERVERS) && (locked != 0));
733 * Check to see if any server reported this principal unlocked.
736 if ((tst == 0) && (locked == 0)) {
739 if ((tst == 0) || (tst == UNOSERVERS)) {
743 fail_GetPrincipalLockStatus:
752 * kas_PrincipalGet - retrieve information about a single principal.
756 * IN cellHandle - a cellHandle previously returned by afsclient_CellOpen.
758 * IN serverHandle - a serverHandle previously returned by kas_ServerOpen.
760 * IN who - a kas_identity_p containing the identity of the principal
763 * OUT principal - upon successful completion contains information
768 * No locks are obtained or released by this function
772 * Returns != 0 upon successful completion.
776 kas_PrincipalGet(const void *cellHandle, const void *serverHandle,
777 const kas_identity_p who, kas_principalEntry_p principal,
781 afs_status_t tst = 0;
782 afs_cell_handle_p c_handle = (afs_cell_handle_p) cellHandle;
783 kas_server_p k_handle = (kas_server_p) serverHandle;
784 kas_server_t kaserver;
785 struct kaentryinfo entry;
788 * Validate input arguments and make rpc.
793 goto fail_kas_PrincipalGet;
796 if (principal == NULL) {
797 tst = ADMKASPRINCIPALNULL;
798 goto fail_kas_PrincipalGet;
801 if (!ChooseValidServer(c_handle, k_handle, &kaserver, &tst)) {
802 goto fail_kas_PrincipalGet;
806 ubik_KAM_GetEntry(kaserver.servers, 0, who->principal,
807 who->instance, KAMAJORVERSION, &entry);
809 goto fail_kas_PrincipalGet;
813 * copy the kaentryinfo structure to our kas_principalEntry_t
816 if (!kaentryinfo_to_kas_principalEntry_t(&entry, principal, &tst)) {
817 goto fail_kas_PrincipalGet;
821 fail_kas_PrincipalGet:
829 typedef struct principal_get {
833 kas_server_t kaserver;
834 kas_identity_t principal[CACHED_ITEMS];
835 } principal_get_t, *principal_get_p;
838 DeletePrincipalSpecificData(void *rpc_specific, afs_status_p st)
841 afs_status_t tst = 0;
842 principal_get_p prin = (principal_get_p) rpc_specific;
844 prin->kaserver.is_valid = 0;
854 GetPrincipalRPC(void *rpc_specific, int slot, int *last_item,
855 int *last_item_contains_data, afs_status_p st)
858 afs_status_t tst = 0;
859 principal_get_p prin = (principal_get_p) rpc_specific;
862 ubik_KAM_ListEntry(prin->kaserver.servers, 0, prin->current,
863 &prin->next, &prin->count, (kaident *)&prin->principal[slot]);
865 prin->current = prin->next;
866 if (prin->next == 0) {
868 *last_item_contains_data = 0;
880 GetPrincipalFromCache(void *rpc_specific, int slot, void *dest,
884 afs_status_t tst = 0;
885 principal_get_p prin = (principal_get_p) rpc_specific;
887 memcpy(dest, &prin->principal[slot], sizeof(kas_identity_t));
897 * kas_PrincipalGetBegin - start the process of iterating over the entire
902 * IN cellHandle - a cellHandle previously returned by afsclient_CellOpen.
904 * IN serverHandle - a serverHandle previously returned by kas_ServerOpen.
906 * OUT iterationIdP - upon successful completion contains a iterator that
907 * can be passed to kas_PrincipalGetNext.
911 * No locks are obtained or released by this function
915 * Returns != 0 upon successful completion.
921 kas_PrincipalGetBegin(const void *cellHandle, const void *serverHandle,
922 void **iterationIdP, afs_status_p st)
925 afs_status_t tst = 0;
926 afs_cell_handle_p c_handle = (afs_cell_handle_p) cellHandle;
927 kas_server_p k_handle = (kas_server_p) serverHandle;
928 afs_admin_iterator_p iter =
929 (afs_admin_iterator_p) malloc(sizeof(afs_admin_iterator_t));
930 principal_get_p principal =
931 (principal_get_p) malloc(sizeof(principal_get_t));
939 goto fail_kas_PrincipalGetBegin;
942 if (principal == NULL) {
944 goto fail_kas_PrincipalGetBegin;
947 if (iterationIdP == NULL) {
948 tst = ADMITERATIONIDPNULL;
949 goto fail_kas_PrincipalGetBegin;
952 if (!ChooseValidServer(c_handle, k_handle, &principal->kaserver, &tst)) {
953 goto fail_kas_PrincipalGetBegin;
957 * Initialize the iterator structure
960 principal->current = 0;
962 principal->count = 0;
964 (iter, (void *)principal, GetPrincipalRPC, GetPrincipalFromCache,
965 NULL, DeletePrincipalSpecificData, &tst)) {
966 *iterationIdP = (void *)iter;
970 fail_kas_PrincipalGetBegin:
976 if (principal != NULL) {
988 * kas_PrincipalGetNext - retrieve the next principal from the kaserver.
992 * IN iterationId - an iterator previously returned by kas_PrincipalGetBegin
994 * OUT who - upon successful completion contains the next principal from the
999 * Hold the iterator mutex across the call to the kaserver.
1003 * Returns != 0 upon successful completion.
1004 * Returns 0 and st == ADMITERATORDONE when the last entry is returned.
1008 kas_PrincipalGetNext(const void *iterationId, kas_identity_p who,
1012 afs_status_t tst = 0;
1013 afs_admin_iterator_p iter = (afs_admin_iterator_p) iterationId;
1016 * Validate arguments
1020 tst = ADMKASWHONULL;
1021 goto fail_kas_PrincipalGetNext;
1025 tst = ADMITERATORNULL;
1026 goto fail_kas_PrincipalGetNext;
1029 rc = IteratorNext(iter, (void *)who, &tst);
1031 fail_kas_PrincipalGetNext:
1040 * kas_PrincipalGetDone - finish using a principal iterator
1044 * IN iterationId - an iterator previously returned by kas_PrincipalGetBegin
1048 * No locks are held by this function.
1052 * Returns != 0 upon successful completion.
1056 * It is the user's responsibility to make sure kas_PrincipalGetDone
1057 * is called only once for each iterator.
1061 kas_PrincipalGetDone(const void *iterationIdP, afs_status_p st)
1064 afs_status_t tst = 0;
1065 afs_admin_iterator_p iter = (afs_admin_iterator_p) iterationIdP;
1072 tst = ADMITERATORNULL;
1073 goto fail_kas_PrincipalGetDone;
1076 rc = IteratorDone(iter, &tst);
1078 fail_kas_PrincipalGetDone:
1087 * kas_PrincipalKeySet - set a principal's password to a known value.
1091 * IN cellHandle - a cellHandle previously returned by afsclient_CellOpen.
1093 * IN serverHandle - a serverHandle previously returned by kas_ServerOpen.
1095 * IN who - the principal for whom the password is being set.
1097 * IN keyVersion - the version number of the new key.
1099 * IN key - the new password.
1103 * No locks are held by this function.
1107 * Returns != 0 upon successful completion.
1111 kas_PrincipalKeySet(const void *cellHandle, const void *serverHandle,
1112 const kas_identity_p who, int keyVersion,
1113 const kas_encryptionKey_p kas_keyp, afs_status_p st)
1116 afs_status_t tst = 0;
1117 afs_cell_handle_p c_handle = (afs_cell_handle_p) cellHandle;
1118 kas_server_p k_handle = (kas_server_p) serverHandle;
1119 kas_server_t kaserver;
1123 * Validate input arguments and make rpc.
1127 tst = ADMKASWHONULL;
1128 goto fail_kas_PrincipalKeySet;
1131 if (kas_keyp == NULL) {
1132 tst = ADMKASKEYNULL;
1133 goto fail_kas_PrincipalKeySet;
1136 if (!ChooseValidServer(c_handle, k_handle, &kaserver, &tst)) {
1137 goto fail_kas_PrincipalKeySet;
1140 memcpy(&key, kas_keyp, sizeof(key));
1143 ubik_KAM_SetPassword(kaserver.servers, 0, who->principal,
1144 who->instance, keyVersion, key);
1145 memset(&key, 0, sizeof(key));
1147 goto fail_kas_PrincipalKeySet;
1150 /* If we failed to fail we must have succeeded */
1153 fail_kas_PrincipalKeySet:
1162 * kas_PrincipalLockStatusGet - determine a principal's lock status.
1166 * IN cellHandle - a cellHandle previously returned by afsclient_CellOpen.
1168 * IN serverHandle - a serverHandle previously returned by kas_ServerOpen.
1170 * IN who - the principal whose lock status is being checked.
1172 * OUT lock_end_timeP - the number of seconds until the principal is unlocked.
1173 * If 0 => user is unlocked.
1177 * No locks are held by this function.
1181 * Returns != 0 upon successful completion.
1185 * See the comments in GetPrincipalLockStatus regarding how the locking data
1186 * is kept INconsistently between servers.
1190 kas_PrincipalLockStatusGet(const void *cellHandle, const void *serverHandle,
1191 const kas_identity_p who,
1192 unsigned int *lock_end_timeP, afs_status_p st)
1195 afs_status_t tst = 0;
1196 afs_cell_handle_p c_handle = (afs_cell_handle_p) cellHandle;
1197 kas_server_p k_handle = (kas_server_p) serverHandle;
1198 kas_server_t kaserver;
1201 * Validate input arguments and make rpc.
1205 tst = ADMKASWHONULL;
1206 goto fail_kas_PrincipalLockStatusGet;
1209 if (lock_end_timeP == NULL) {
1210 tst = ADMKASLOCKENDTIMEPNULL;
1211 goto fail_kas_PrincipalLockStatusGet;
1214 if (!ChooseValidServer(c_handle, k_handle, &kaserver, &tst)) {
1215 goto fail_kas_PrincipalLockStatusGet;
1218 rc = GetPrincipalLockStatus(&kaserver, who, lock_end_timeP, &tst);
1220 fail_kas_PrincipalLockStatusGet:
1229 * kas_PrincipalUnlock - unlock a principal.
1233 * IN cellHandle - a cellHandle previously returned by afsclient_CellOpen.
1235 * IN serverHandle - a serverHandle previously returned by kas_ServerOpen.
1237 * IN who - the principal who is being unlocked.
1241 * No locks are held by this function.
1245 * Returns != 0 upon successful completion.
1249 * See the comments in GetPrincipalLockStatus regarding how the locking data
1250 * is kept INconsistently between servers.
1254 kas_PrincipalUnlock(const void *cellHandle, const void *serverHandle,
1255 const kas_identity_p who, afs_status_p st)
1258 afs_status_t tst = 0;
1259 afs_cell_handle_p c_handle = (afs_cell_handle_p) cellHandle;
1260 kas_server_p k_handle = (kas_server_p) serverHandle;
1261 kas_server_t kaserver;
1263 afs_status_t save_tst = 0;
1266 * Validate input arguments and make rpc.
1270 tst = ADMKASWHONULL;
1271 goto fail_kas_PrincipalUnlock;
1274 if (!ChooseValidServer(c_handle, k_handle, &kaserver, &tst)) {
1275 goto fail_kas_PrincipalUnlock;
1280 ubik_CallIter(KAM_Unlock, kaserver.servers, 0, &count,
1281 (long)who->principal, (long)who->instance, 0, 0, 0,
1282 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0);
1283 if (tst && (tst != UNOSERVERS)) {
1284 if (save_tst == 0) {
1285 save_tst = tst; /* save the first failure */
1288 } while (tst != UNOSERVERS);
1290 if ((tst == 0) || (tst == UNOSERVERS)) {
1294 fail_kas_PrincipalUnlock:
1303 getPrincipalFlags(const void *cellHandle, const void *serverHandle,
1304 const kas_identity_p who, afs_int32 * cur_flags,
1308 afs_status_t tst = 0;
1309 afs_cell_handle_p c_handle = (afs_cell_handle_p) cellHandle;
1310 kas_server_p k_handle = (kas_server_p) serverHandle;
1311 kas_server_t kaserver;
1312 struct kaentryinfo tentry;
1314 if (!ChooseValidServer(c_handle, k_handle, &kaserver, &tst)) {
1315 goto fail_getPrincipalFlags;
1319 ubik_KAM_GetEntry(kaserver.servers, 0, who->principal,
1320 who->instance, KAMAJORVERSION, &tentry);
1322 *cur_flags = tentry.flags;
1326 fail_getPrincipalFlags:
1335 * kas_PrincipalFieldsSet - modify an existing principal.
1339 * IN cellHandle - a cellHandle previously returned by afsclient_CellOpen.
1341 * IN serverHandle - a serverHandle previously returned by kas_ServerOpen.
1343 * IN who - the principal who is being modified.
1345 * IN isAdmin - the admin status of the principal.
1347 * IN grantTickets - should the TGS issue tickets for the principal.
1349 * IN canEncrypt - should the TGS allow the use of encryption via the
1352 * IN canChangePassword - should the principal be allowed to change their
1355 * IN expirationDate - the date when the principal will expire.
1357 * IN maxTicketLifetime - the maximum lifetime of a ticket issued for
1360 * IN passwordExpires - the maximum number of days a particular
1361 * password can be used. The limit is 255, 0 => no expiration.
1363 * IN passwordReuse - can a password be reused by this principal.
1365 * IN failedPasswordAttempts - number of failed login attempts before
1366 * a principal is locked. The limit is 255, 0 => no limit.
1368 * IN failedPasswordLockTime - the number of seconds a principal is
1369 * locked once failedPasswordAttempts is reached. Some bizarre rounding
1370 * occurs for this value, see kas for more details.
1374 * No locks are held by this function.
1378 * Returns != 0 upon successful completion.
1382 * See the comments in GetPrincipalLockStatus regarding how the locking data
1383 * is kept INconsistently between servers.
1387 kas_PrincipalFieldsSet(const void *cellHandle, const void *serverHandle,
1388 const kas_identity_p who, const kas_admin_p isAdmin,
1389 const kas_tgs_p grantTickets,
1390 const kas_enc_p canEncrypt,
1391 const kas_cpw_p canChangePassword,
1392 const unsigned int *expirationDate,
1393 const unsigned int *maxTicketLifetime,
1394 const unsigned int *passwordExpires,
1395 const kas_rpw_p passwordReuse,
1396 const unsigned int *failedPasswordAttempts,
1397 const unsigned int *failedPasswordLockTime,
1401 afs_status_t tst = 0;
1402 afs_cell_handle_p c_handle = (afs_cell_handle_p) cellHandle;
1403 kas_server_p k_handle = (kas_server_p) serverHandle;
1404 kas_server_t kaserver;
1405 afs_int32 flags = 0;
1406 Date expiration = 0;
1407 afs_int32 lifetime = 0;
1409 char spare_bytes[4] = { 0, 0, 0, 0 };
1410 int somethings_changing = 0;
1413 * Validate input arguments.
1417 tst = ADMKASWHONULL;
1418 goto fail_kas_PrincipalFieldsSet;
1422 * set flags based upon input
1424 * If we're changing the flags, we need to get the current value of
1425 * the flags first and then make the changes
1428 if ((isAdmin != NULL) || (grantTickets != NULL) || (canEncrypt != NULL)
1429 || (canChangePassword != NULL)) {
1430 if (!getPrincipalFlags(cellHandle, serverHandle, who, &flags, &tst)) {
1431 goto fail_kas_PrincipalFieldsSet;
1435 if (isAdmin != NULL) {
1436 somethings_changing = 1;
1437 if (*isAdmin == KAS_ADMIN) {
1444 if (grantTickets != NULL) {
1445 somethings_changing = 1;
1446 if (*grantTickets == NO_TGS) {
1453 if (canEncrypt != NULL) {
1454 somethings_changing = 1;
1455 if (*canEncrypt == NO_ENCRYPT) {
1458 flags &= ~KAFNOSEAL;
1462 if (canChangePassword != NULL) {
1463 somethings_changing = 1;
1464 if (*canChangePassword == NO_CHANGE_PASSWORD) {
1471 flags = (flags & KAF_SETTABLE_FLAGS) | KAFNORMAL;
1473 if (expirationDate != NULL) {
1474 somethings_changing = 1;
1475 expiration = *expirationDate;
1478 if (maxTicketLifetime != NULL) {
1479 somethings_changing = 1;
1480 lifetime = *maxTicketLifetime;
1483 if (passwordExpires != NULL) {
1484 if (*passwordExpires > 255) {
1485 tst = ADMKASPASSWORDEXPIRESTOOBIG;
1486 goto fail_kas_PrincipalFieldsSet;
1488 somethings_changing = 1;
1489 spare_bytes[0] = *passwordExpires + 1;
1492 if (passwordReuse != NULL) {
1493 somethings_changing = 1;
1494 if (*passwordReuse == REUSE_PASSWORD) {
1495 spare_bytes[1] = KA_REUSEPW;
1497 spare_bytes[1] = KA_NOREUSEPW;
1501 if (failedPasswordAttempts != NULL) {
1502 if (*failedPasswordAttempts > 255) {
1503 tst = ADMKASFAILEDPASSWORDATTEMPTSTOOBIG;
1504 goto fail_kas_PrincipalFieldsSet;
1506 somethings_changing = 1;
1507 spare_bytes[2] = *failedPasswordAttempts + 1;
1510 if (failedPasswordLockTime != NULL) {
1511 if (*failedPasswordLockTime > 36 * 60 * 60) {
1512 tst = ADMKASFAILEDPASSWORDLOCKTIME;
1513 goto fail_kas_PrincipalFieldsSet;
1515 somethings_changing = 1;
1516 spare_bytes[3] = ((*failedPasswordLockTime + 511) >> 9) + 1;
1519 was_spare = pack_long(spare_bytes);
1521 if (somethings_changing) {
1522 if (!ChooseValidServer(c_handle, k_handle, &kaserver, &tst)) {
1523 goto fail_kas_PrincipalFieldsSet;
1526 ubik_KAM_SetFields(kaserver.servers, 0, who->principal,
1527 who->instance, flags, expiration, lifetime, -1,
1533 tst = ADMKASPRINCIPALFIELDSNOCHANGE;
1536 fail_kas_PrincipalFieldsSet:
1545 * kas_ServerStatsGet - get server statistics.
1549 * IN cellHandle - a cellHandle previously returned by afsclient_CellOpen.
1551 * IN serverHandle - a serverHandle previously returned by kas_ServerOpen.
1553 * OUT stats - the statistics retrieved.
1557 * No locks are held by this function.
1561 * Returns != 0 upon successful completion.
1565 kas_ServerStatsGet(const void *cellHandle, const void *serverHandle,
1566 kas_serverStats_p stats, afs_status_p st)
1569 afs_status_t tst = 0;
1570 afs_cell_handle_p c_handle = (afs_cell_handle_p) cellHandle;
1571 kas_server_p k_handle = (kas_server_p) serverHandle;
1572 kas_server_t kaserver;
1579 * Validate input arguments and make rpc.
1582 if (stats == NULL) {
1583 tst = ADMKASSTATSNULL;
1584 goto fail_kas_ServerStatsGet;
1587 if (!ChooseValidServer(c_handle, k_handle, &kaserver, &tst)) {
1588 goto fail_kas_ServerStatsGet;
1592 ubik_KAM_GetStats(kaserver.servers, 0, KAMAJORVERSION, &admins,
1593 &statics, &dynamics);
1595 goto fail_kas_ServerStatsGet;
1598 stats->allocations = statics.allocs;
1599 stats->frees = statics.frees;
1600 stats->changePasswordRequests = statics.cpws;
1601 stats->adminAccounts = admins;
1602 stats->host = dynamics.host;
1603 stats->serverStartTime = dynamics.start_time;
1604 stats->hashTableUtilization = dynamics.hashTableUtilization;
1606 i = sizeof(kas_serverProcStats_t);
1607 memcpy(&stats->authenticate, &dynamics.Authenticate, i);
1608 memcpy(&stats->changePassword, &dynamics.ChangePassword, i);
1609 memcpy(&stats->getTicket, &dynamics.GetTicket, i);
1610 memcpy(&stats->createUser, &dynamics.CreateUser, i);
1611 memcpy(&stats->setPassword, &dynamics.SetPassword, i);
1612 memcpy(&stats->setFields, &dynamics.SetFields, i);
1613 memcpy(&stats->deleteUser, &dynamics.DeleteUser, i);
1614 memcpy(&stats->getEntry, &dynamics.GetEntry, i);
1615 memcpy(&stats->listEntry, &dynamics.ListEntry, i);
1616 memcpy(&stats->getStats, &dynamics.GetStats, i);
1617 memcpy(&stats->getPassword, &dynamics.GetPassword, i);
1618 memcpy(&stats->getRandomKey, &dynamics.GetRandomKey, i);
1619 memcpy(&stats->debug, &dynamics.Debug, i);
1620 memcpy(&stats->udpAuthenticate, &dynamics.UAuthenticate, i);
1621 memcpy(&stats->udpGetTicket, &dynamics.UGetTicket, i);
1622 memcpy(&stats->unlock, &dynamics.Unlock, i);
1623 memcpy(&stats->lockStatus, &dynamics.LockStatus, i);
1625 stats->stringChecks = dynamics.string_checks;
1628 fail_kas_ServerStatsGet:
1637 * kas_ServerDebugGet - get server debug info.
1641 * IN cellHandle - a cellHandle previously returned by afsclient_CellOpen.
1643 * IN serverHandle - a serverHandle previously returned by kas_ServerOpen.
1645 * OUT stats - the debug info retrieved.
1649 * No locks are held by this function.
1653 * Returns != 0 upon successful completion.
1657 kas_ServerDebugGet(const void *cellHandle, const void *serverHandle,
1658 kas_serverDebugInfo_p debug, afs_status_p st)
1661 afs_status_t tst = 0;
1662 afs_cell_handle_p c_handle = (afs_cell_handle_p) cellHandle;
1663 kas_server_p k_handle = (kas_server_p) serverHandle;
1664 kas_server_t kaserver;
1665 struct ka_debugInfo info;
1669 * Validate input arguments and make rpc.
1672 if (debug == NULL) {
1673 tst = ADMKASDEBUGNULL;
1674 goto fail_kas_ServerDebugGet;
1677 if (!ChooseValidServer(c_handle, k_handle, &kaserver, &tst)) {
1678 goto fail_kas_ServerDebugGet;
1680 tst = ubik_KAM_Debug(kaserver.servers, 0, KAMAJORVERSION, 0, &info);
1682 goto fail_kas_ServerDebugGet;
1684 debug->host = info.host;
1685 debug->serverStartTime = info.startTime;
1686 debug->currentTime = info.reserved1;
1687 debug->noAuth = info.noAuth;
1688 debug->lastTransaction = info.lastTrans;
1689 strcpy(debug->lastOperation, info.lastOperation);
1690 strcpy(debug->lastPrincipalAuth, info.lastAuth);
1691 strcpy(debug->lastPrincipalUDPAuth, info.lastUAuth);
1692 strcpy(debug->lastPrincipalTGS, info.lastTGS);
1693 strcpy(debug->lastPrincipalUDPTGS, info.lastUTGS);
1694 strcpy(debug->lastPrincipalAdmin, info.lastAdmin);
1695 strcpy(debug->lastServerTGS, info.lastTGSServer);
1696 strcpy(debug->lastServerUDPTGS, info.lastUTGSServer);
1697 debug->nextAutoCheckPointWrite = info.nextAutoCPW;
1698 debug->updatesRemainingBeforeAutoCheckPointWrite = info.updatesRemaining;
1699 debug->dbHeaderRead = info.dbHeaderRead;
1700 debug->dbVersion = info.dbVersion;
1701 debug->dbFreePtr = info.dbFreePtr;
1702 debug->dbEOFPtr = info.dbEofPtr;
1703 debug->dbKvnoPtr = info.dbKvnoPtr;
1704 debug->dbSpecialKeysVersion = info.dbSpecialKeysVersion;
1705 debug->dbHeaderLock = info.cheader_lock;
1706 debug->keyCacheLock = info.keycache_lock;
1707 debug->keyCacheVersion = info.kcVersion;
1708 debug->keyCacheSize = info.kcSize;
1709 debug->keyCacheUsed = info.kcUsed;
1710 for (i = 0; i < info.kcUsed; i++) {
1711 debug->keyCache[i].lastUsed = info.kcInfo[i].used;
1712 debug->keyCache[i].keyVersionNumber = info.kcInfo[i].kvno;
1713 debug->keyCache[i].primary = info.kcInfo[i].primary;
1714 debug->keyCache[i].keyCheckSum = info.kcInfo[i].keycksum;
1715 strcpy(debug->keyCache[i].principal, info.kcInfo[i].principal);
1719 fail_kas_ServerDebugGet:
1728 * kas_ServerRandomKeyGet - get a random key from a server.
1732 * IN cellHandle - a cellHandle previously returned by afsclient_CellOpen.
1734 * IN serverHandle - a serverHandle previously returned by kas_ServerOpen.
1736 * OUT key - a random key.
1740 * No locks are held by this function.
1744 * Returns != 0 upon successful completion.
1748 kas_ServerRandomKeyGet(const void *cellHandle, const void *serverHandle,
1749 kas_encryptionKey_p kas_keyp, afs_status_p st)
1752 afs_status_t tst = 0;
1753 afs_cell_handle_p c_handle = (afs_cell_handle_p) cellHandle;
1754 kas_server_p k_handle = (kas_server_p) serverHandle;
1755 kas_server_t kaserver;
1759 * Validate input arguments and make rpc.
1762 if (kas_keyp == NULL) {
1763 tst = ADMKASKEYNULL;
1764 goto fail_kas_ServerRandomKeyGet;
1767 if (!ChooseValidServer(c_handle, k_handle, &kaserver, &tst)) {
1768 goto fail_kas_ServerRandomKeyGet;
1771 tst = ubik_KAM_GetRandomKey(kaserver.servers, 0, &key);
1773 goto fail_kas_ServerRandomKeyGet;
1775 memcpy(kas_keyp, &key, sizeof(*kas_keyp));
1778 fail_kas_ServerRandomKeyGet:
1787 * kas_StringToKey - turn a string key into a key.
1791 * IN cellName - the name of the cell where the key will be used.
1793 * IN string - the string to be converted.
1795 * OUT key - the encryption key.
1799 * No locks are held by this function.
1803 * Returns != 0 upon successful completion.
1807 kas_StringToKey(const char *cellName, const char *string,
1808 kas_encryptionKey_p key, afs_status_p st)
1811 afs_status_t tst = 0;
1813 ka_StringToKey(string, cellName, (struct ktc_encryptionKey *)key);
1824 * kas_KeyCheckSum - compute the checksum of an encryption key.
1828 * IN key - the encryption key.
1830 * OUT cksumP - key checksum
1834 * No locks are held by this function.
1838 * Returns != 0 upon successful completion.
1842 kas_KeyCheckSum(const kas_encryptionKey_p key, unsigned int *cksumP,
1846 afs_status_t tst = 0;
1849 if ((tst = ka_KeyCheckSum((char *)key, &cksum32)) == 0) {