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 = (kas_server_p) 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 =
920 (afs_admin_iterator_p) malloc(sizeof(afs_admin_iterator_t));
921 principal_get_p principal =
922 (principal_get_p) malloc(sizeof(principal_get_t));
930 goto fail_kas_PrincipalGetBegin;
933 if (principal == NULL) {
935 goto fail_kas_PrincipalGetBegin;
938 if (iterationIdP == NULL) {
939 tst = ADMITERATIONIDPNULL;
940 goto fail_kas_PrincipalGetBegin;
943 if (!ChooseValidServer(c_handle, k_handle, &principal->kaserver, &tst)) {
944 goto fail_kas_PrincipalGetBegin;
948 * Initialize the iterator structure
951 principal->current = 0;
953 principal->count = 0;
955 (iter, (void *)principal, GetPrincipalRPC, GetPrincipalFromCache,
956 NULL, DeletePrincipalSpecificData, &tst)) {
957 *iterationIdP = (void *)iter;
961 fail_kas_PrincipalGetBegin:
967 if (principal != NULL) {
979 * kas_PrincipalGetNext - retrieve the next principal from the kaserver.
983 * IN iterationId - an iterator previously returned by kas_PrincipalGetBegin
985 * OUT who - upon successful completion contains the next principal from the
990 * Hold the iterator mutex across the call to the kaserver.
994 * Returns != 0 upon successful completion.
995 * Returns 0 and st == ADMITERATORDONE when the last entry is returned.
999 kas_PrincipalGetNext(const void *iterationId, kas_identity_p who,
1003 afs_status_t tst = 0;
1004 afs_admin_iterator_p iter = (afs_admin_iterator_p) iterationId;
1007 * Validate arguments
1011 tst = ADMKASWHONULL;
1012 goto fail_kas_PrincipalGetNext;
1016 tst = ADMITERATORNULL;
1017 goto fail_kas_PrincipalGetNext;
1020 rc = IteratorNext(iter, (void *)who, &tst);
1022 fail_kas_PrincipalGetNext:
1031 * kas_PrincipalGetDone - finish using a principal iterator
1035 * IN iterationId - an iterator previously returned by kas_PrincipalGetBegin
1039 * No locks are held by this function.
1043 * Returns != 0 upon successful completion.
1047 * It is the user's responsibility to make sure kas_PrincipalGetDone
1048 * is called only once for each iterator.
1052 kas_PrincipalGetDone(const void *iterationIdP, afs_status_p st)
1055 afs_status_t tst = 0;
1056 afs_admin_iterator_p iter = (afs_admin_iterator_p) iterationIdP;
1063 tst = ADMITERATORNULL;
1064 goto fail_kas_PrincipalGetDone;
1067 rc = IteratorDone(iter, &tst);
1069 fail_kas_PrincipalGetDone:
1078 * kas_PrincipalKeySet - set a principal's password to a known value.
1082 * IN cellHandle - a cellHandle previously returned by afsclient_CellOpen.
1084 * IN serverHandle - a serverHandle previously returned by kas_ServerOpen.
1086 * IN who - the principal for whom the password is being set.
1088 * IN keyVersion - the version number of the new key.
1090 * IN key - the new password.
1094 * No locks are held by this function.
1098 * Returns != 0 upon successful completion.
1102 kas_PrincipalKeySet(const void *cellHandle, const void *serverHandle,
1103 const kas_identity_p who, int keyVersion,
1104 const kas_encryptionKey_p kas_keyp, afs_status_p st)
1107 afs_status_t tst = 0;
1108 afs_cell_handle_p c_handle = (afs_cell_handle_p) cellHandle;
1109 kas_server_p k_handle = (kas_server_p) serverHandle;
1110 kas_server_t kaserver;
1114 * Validate input arguments and make rpc.
1118 tst = ADMKASWHONULL;
1119 goto fail_kas_PrincipalKeySet;
1122 if (kas_keyp == NULL) {
1123 tst = ADMKASKEYNULL;
1124 goto fail_kas_PrincipalKeySet;
1127 if (!ChooseValidServer(c_handle, k_handle, &kaserver, &tst)) {
1128 goto fail_kas_PrincipalKeySet;
1131 memcpy(&key, kas_keyp, sizeof(key));
1134 ubik_KAM_SetPassword(kaserver.servers, 0, who->principal,
1135 who->instance, keyVersion, key);
1136 memset(&key, 0, sizeof(key));
1138 goto fail_kas_PrincipalKeySet;
1141 /* If we failed to fail we must have succeeded */
1144 fail_kas_PrincipalKeySet:
1153 * kas_PrincipalLockStatusGet - determine a principal's lock status.
1157 * IN cellHandle - a cellHandle previously returned by afsclient_CellOpen.
1159 * IN serverHandle - a serverHandle previously returned by kas_ServerOpen.
1161 * IN who - the principal whose lock status is being checked.
1163 * OUT lock_end_timeP - the number of seconds until the principal is unlocked.
1164 * If 0 => user is unlocked.
1168 * No locks are held by this function.
1172 * Returns != 0 upon successful completion.
1176 * See the comments in GetPrincipalLockStatus regarding how the locking data
1177 * is kept INconsistently between servers.
1181 kas_PrincipalLockStatusGet(const void *cellHandle, const void *serverHandle,
1182 const kas_identity_p who,
1183 unsigned int *lock_end_timeP, afs_status_p st)
1186 afs_status_t tst = 0;
1187 afs_cell_handle_p c_handle = (afs_cell_handle_p) cellHandle;
1188 kas_server_p k_handle = (kas_server_p) serverHandle;
1189 kas_server_t kaserver;
1192 * Validate input arguments and make rpc.
1196 tst = ADMKASWHONULL;
1197 goto fail_kas_PrincipalLockStatusGet;
1200 if (lock_end_timeP == NULL) {
1201 tst = ADMKASLOCKENDTIMEPNULL;
1202 goto fail_kas_PrincipalLockStatusGet;
1205 if (!ChooseValidServer(c_handle, k_handle, &kaserver, &tst)) {
1206 goto fail_kas_PrincipalLockStatusGet;
1209 rc = GetPrincipalLockStatus(&kaserver, who, lock_end_timeP, &tst);
1211 fail_kas_PrincipalLockStatusGet:
1220 * kas_PrincipalUnlock - unlock a principal.
1224 * IN cellHandle - a cellHandle previously returned by afsclient_CellOpen.
1226 * IN serverHandle - a serverHandle previously returned by kas_ServerOpen.
1228 * IN who - the principal who is being unlocked.
1232 * No locks are held by this function.
1236 * Returns != 0 upon successful completion.
1240 * See the comments in GetPrincipalLockStatus regarding how the locking data
1241 * is kept INconsistently between servers.
1245 kas_PrincipalUnlock(const void *cellHandle, const void *serverHandle,
1246 const kas_identity_p who, afs_status_p st)
1249 afs_status_t tst = 0;
1250 afs_cell_handle_p c_handle = (afs_cell_handle_p) cellHandle;
1251 kas_server_p k_handle = (kas_server_p) serverHandle;
1252 kas_server_t kaserver;
1254 afs_status_t save_tst = 0;
1257 * Validate input arguments and make rpc.
1261 tst = ADMKASWHONULL;
1262 goto fail_kas_PrincipalUnlock;
1265 if (!ChooseValidServer(c_handle, k_handle, &kaserver, &tst)) {
1266 goto fail_kas_PrincipalUnlock;
1271 ubik_CallIter(KAM_Unlock, kaserver.servers, 0, &count,
1272 (long)who->principal, (long)who->instance, 0, 0, 0,
1273 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0);
1274 if (tst && (tst != UNOSERVERS)) {
1275 if (save_tst == 0) {
1276 save_tst = tst; /* save the first failure */
1279 } while (tst != UNOSERVERS);
1281 if ((tst == 0) || (tst == UNOSERVERS)) {
1285 fail_kas_PrincipalUnlock:
1294 getPrincipalFlags(const void *cellHandle, const void *serverHandle,
1295 const kas_identity_p who, afs_int32 * cur_flags,
1299 afs_status_t tst = 0;
1300 afs_cell_handle_p c_handle = (afs_cell_handle_p) cellHandle;
1301 kas_server_p k_handle = (kas_server_p) serverHandle;
1302 kas_server_t kaserver;
1303 struct kaentryinfo tentry;
1305 if (!ChooseValidServer(c_handle, k_handle, &kaserver, &tst)) {
1306 goto fail_getPrincipalFlags;
1310 ubik_KAM_GetEntry(kaserver.servers, 0, who->principal,
1311 who->instance, KAMAJORVERSION, &tentry);
1313 *cur_flags = tentry.flags;
1317 fail_getPrincipalFlags:
1326 * kas_PrincipalFieldsSet - modify an existing principal.
1330 * IN cellHandle - a cellHandle previously returned by afsclient_CellOpen.
1332 * IN serverHandle - a serverHandle previously returned by kas_ServerOpen.
1334 * IN who - the principal who is being modified.
1336 * IN isAdmin - the admin status of the principal.
1338 * IN grantTickets - should the TGS issue tickets for the principal.
1340 * IN canEncrypt - should the TGS allow the use of encryption via the
1343 * IN canChangePassword - should the principal be allowed to change their
1346 * IN expirationDate - the date when the principal will expire.
1348 * IN maxTicketLifetime - the maximum lifetime of a ticket issued for
1351 * IN passwordExpires - the maximum number of days a particular
1352 * password can be used. The limit is 255, 0 => no expiration.
1354 * IN passwordReuse - can a password be reused by this principal.
1356 * IN failedPasswordAttempts - number of failed login attempts before
1357 * a principal is locked. The limit is 255, 0 => no limit.
1359 * IN failedPasswordLockTime - the number of seconds a principal is
1360 * locked once failedPasswordAttempts is reached. Some bizarre rounding
1361 * occurs for this value, see kas for more details.
1365 * No locks are held by this function.
1369 * Returns != 0 upon successful completion.
1373 * See the comments in GetPrincipalLockStatus regarding how the locking data
1374 * is kept INconsistently between servers.
1378 kas_PrincipalFieldsSet(const void *cellHandle, const void *serverHandle,
1379 const kas_identity_p who, const kas_admin_p isAdmin,
1380 const kas_tgs_p grantTickets,
1381 const kas_enc_p canEncrypt,
1382 const kas_cpw_p canChangePassword,
1383 const unsigned int *expirationDate,
1384 const unsigned int *maxTicketLifetime,
1385 const unsigned int *passwordExpires,
1386 const kas_rpw_p passwordReuse,
1387 const unsigned int *failedPasswordAttempts,
1388 const unsigned int *failedPasswordLockTime,
1392 afs_status_t tst = 0;
1393 afs_cell_handle_p c_handle = (afs_cell_handle_p) cellHandle;
1394 kas_server_p k_handle = (kas_server_p) serverHandle;
1395 kas_server_t kaserver;
1396 afs_int32 flags = 0;
1397 Date expiration = 0;
1398 afs_int32 lifetime = 0;
1400 char spare_bytes[4] = { 0, 0, 0, 0 };
1401 int somethings_changing = 0;
1404 * Validate input arguments.
1408 tst = ADMKASWHONULL;
1409 goto fail_kas_PrincipalFieldsSet;
1413 * set flags based upon input
1415 * If we're changing the flags, we need to get the current value of
1416 * the flags first and then make the changes
1419 if ((isAdmin != NULL) || (grantTickets != NULL) || (canEncrypt != NULL)
1420 || (canChangePassword != NULL)) {
1421 if (!getPrincipalFlags(cellHandle, serverHandle, who, &flags, &tst)) {
1422 goto fail_kas_PrincipalFieldsSet;
1426 if (isAdmin != NULL) {
1427 somethings_changing = 1;
1428 if (*isAdmin == KAS_ADMIN) {
1435 if (grantTickets != NULL) {
1436 somethings_changing = 1;
1437 if (*grantTickets == NO_TGS) {
1444 if (canEncrypt != NULL) {
1445 somethings_changing = 1;
1446 if (*canEncrypt == NO_ENCRYPT) {
1449 flags &= ~KAFNOSEAL;
1453 if (canChangePassword != NULL) {
1454 somethings_changing = 1;
1455 if (*canChangePassword == NO_CHANGE_PASSWORD) {
1462 flags = (flags & KAF_SETTABLE_FLAGS) | KAFNORMAL;
1464 if (expirationDate != NULL) {
1465 somethings_changing = 1;
1466 expiration = *expirationDate;
1469 if (maxTicketLifetime != NULL) {
1470 somethings_changing = 1;
1471 lifetime = *maxTicketLifetime;
1474 if (passwordExpires != NULL) {
1475 if (*passwordExpires > 255) {
1476 tst = ADMKASPASSWORDEXPIRESTOOBIG;
1477 goto fail_kas_PrincipalFieldsSet;
1479 somethings_changing = 1;
1480 spare_bytes[0] = *passwordExpires + 1;
1483 if (passwordReuse != NULL) {
1484 somethings_changing = 1;
1485 if (*passwordReuse == REUSE_PASSWORD) {
1486 spare_bytes[1] = KA_REUSEPW;
1488 spare_bytes[1] = KA_NOREUSEPW;
1492 if (failedPasswordAttempts != NULL) {
1493 if (*failedPasswordAttempts > 255) {
1494 tst = ADMKASFAILEDPASSWORDATTEMPTSTOOBIG;
1495 goto fail_kas_PrincipalFieldsSet;
1497 somethings_changing = 1;
1498 spare_bytes[2] = *failedPasswordAttempts + 1;
1501 if (failedPasswordLockTime != NULL) {
1502 if (*failedPasswordLockTime > 36 * 60 * 60) {
1503 tst = ADMKASFAILEDPASSWORDLOCKTIME;
1504 goto fail_kas_PrincipalFieldsSet;
1506 somethings_changing = 1;
1507 spare_bytes[3] = ((*failedPasswordLockTime + 511) >> 9) + 1;
1510 was_spare = pack_long(spare_bytes);
1512 if (somethings_changing) {
1513 if (!ChooseValidServer(c_handle, k_handle, &kaserver, &tst)) {
1514 goto fail_kas_PrincipalFieldsSet;
1517 ubik_KAM_SetFields(kaserver.servers, 0, who->principal,
1518 who->instance, flags, expiration, lifetime, -1,
1524 tst = ADMKASPRINCIPALFIELDSNOCHANGE;
1527 fail_kas_PrincipalFieldsSet:
1536 * kas_ServerStatsGet - get server statistics.
1540 * IN cellHandle - a cellHandle previously returned by afsclient_CellOpen.
1542 * IN serverHandle - a serverHandle previously returned by kas_ServerOpen.
1544 * OUT stats - the statistics retrieved.
1548 * No locks are held by this function.
1552 * Returns != 0 upon successful completion.
1556 kas_ServerStatsGet(const void *cellHandle, const void *serverHandle,
1557 kas_serverStats_p stats, afs_status_p st)
1560 afs_status_t tst = 0;
1561 afs_cell_handle_p c_handle = (afs_cell_handle_p) cellHandle;
1562 kas_server_p k_handle = (kas_server_p) serverHandle;
1563 kas_server_t kaserver;
1570 * Validate input arguments and make rpc.
1573 if (stats == NULL) {
1574 tst = ADMKASSTATSNULL;
1575 goto fail_kas_ServerStatsGet;
1578 if (!ChooseValidServer(c_handle, k_handle, &kaserver, &tst)) {
1579 goto fail_kas_ServerStatsGet;
1583 ubik_KAM_GetStats(kaserver.servers, 0, KAMAJORVERSION, &admins,
1584 &statics, &dynamics);
1586 goto fail_kas_ServerStatsGet;
1589 stats->allocations = statics.allocs;
1590 stats->frees = statics.frees;
1591 stats->changePasswordRequests = statics.cpws;
1592 stats->adminAccounts = admins;
1593 stats->host = dynamics.host;
1594 stats->serverStartTime = dynamics.start_time;
1595 stats->hashTableUtilization = dynamics.hashTableUtilization;
1597 i = sizeof(kas_serverProcStats_t);
1598 memcpy(&stats->authenticate, &dynamics.Authenticate, i);
1599 memcpy(&stats->changePassword, &dynamics.ChangePassword, i);
1600 memcpy(&stats->getTicket, &dynamics.GetTicket, i);
1601 memcpy(&stats->createUser, &dynamics.CreateUser, i);
1602 memcpy(&stats->setPassword, &dynamics.SetPassword, i);
1603 memcpy(&stats->setFields, &dynamics.SetFields, i);
1604 memcpy(&stats->deleteUser, &dynamics.DeleteUser, i);
1605 memcpy(&stats->getEntry, &dynamics.GetEntry, i);
1606 memcpy(&stats->listEntry, &dynamics.ListEntry, i);
1607 memcpy(&stats->getStats, &dynamics.GetStats, i);
1608 memcpy(&stats->getPassword, &dynamics.GetPassword, i);
1609 memcpy(&stats->getRandomKey, &dynamics.GetRandomKey, i);
1610 memcpy(&stats->debug, &dynamics.Debug, i);
1611 memcpy(&stats->udpAuthenticate, &dynamics.UAuthenticate, i);
1612 memcpy(&stats->udpGetTicket, &dynamics.UGetTicket, i);
1613 memcpy(&stats->unlock, &dynamics.Unlock, i);
1614 memcpy(&stats->lockStatus, &dynamics.LockStatus, i);
1616 stats->stringChecks = dynamics.string_checks;
1619 fail_kas_ServerStatsGet:
1628 * kas_ServerDebugGet - get server debug info.
1632 * IN cellHandle - a cellHandle previously returned by afsclient_CellOpen.
1634 * IN serverHandle - a serverHandle previously returned by kas_ServerOpen.
1636 * OUT stats - the debug info retrieved.
1640 * No locks are held by this function.
1644 * Returns != 0 upon successful completion.
1648 kas_ServerDebugGet(const void *cellHandle, const void *serverHandle,
1649 kas_serverDebugInfo_p debug, afs_status_p st)
1652 afs_status_t tst = 0;
1653 afs_cell_handle_p c_handle = (afs_cell_handle_p) cellHandle;
1654 kas_server_p k_handle = (kas_server_p) serverHandle;
1655 kas_server_t kaserver;
1656 struct ka_debugInfo info;
1660 * Validate input arguments and make rpc.
1663 if (debug == NULL) {
1664 tst = ADMKASDEBUGNULL;
1665 goto fail_kas_ServerDebugGet;
1668 if (!ChooseValidServer(c_handle, k_handle, &kaserver, &tst)) {
1669 goto fail_kas_ServerDebugGet;
1671 tst = ubik_KAM_Debug(kaserver.servers, 0, KAMAJORVERSION, 0, &info);
1673 goto fail_kas_ServerDebugGet;
1675 debug->host = info.host;
1676 debug->serverStartTime = info.startTime;
1677 debug->currentTime = info.reserved1;
1678 debug->noAuth = info.noAuth;
1679 debug->lastTransaction = info.lastTrans;
1680 strcpy(debug->lastOperation, info.lastOperation);
1681 strcpy(debug->lastPrincipalAuth, info.lastAuth);
1682 strcpy(debug->lastPrincipalUDPAuth, info.lastUAuth);
1683 strcpy(debug->lastPrincipalTGS, info.lastTGS);
1684 strcpy(debug->lastPrincipalUDPTGS, info.lastUTGS);
1685 strcpy(debug->lastPrincipalAdmin, info.lastAdmin);
1686 strcpy(debug->lastServerTGS, info.lastTGSServer);
1687 strcpy(debug->lastServerUDPTGS, info.lastUTGSServer);
1688 debug->nextAutoCheckPointWrite = info.nextAutoCPW;
1689 debug->updatesRemainingBeforeAutoCheckPointWrite = info.updatesRemaining;
1690 debug->dbHeaderRead = info.dbHeaderRead;
1691 debug->dbVersion = info.dbVersion;
1692 debug->dbFreePtr = info.dbFreePtr;
1693 debug->dbEOFPtr = info.dbEofPtr;
1694 debug->dbKvnoPtr = info.dbKvnoPtr;
1695 debug->dbSpecialKeysVersion = info.dbSpecialKeysVersion;
1696 debug->dbHeaderLock = info.cheader_lock;
1697 debug->keyCacheLock = info.keycache_lock;
1698 debug->keyCacheVersion = info.kcVersion;
1699 debug->keyCacheSize = info.kcSize;
1700 debug->keyCacheUsed = info.kcUsed;
1701 for (i = 0; i < info.kcUsed; i++) {
1702 debug->keyCache[i].lastUsed = info.kcInfo[i].used;
1703 debug->keyCache[i].keyVersionNumber = info.kcInfo[i].kvno;
1704 debug->keyCache[i].primary = info.kcInfo[i].primary;
1705 debug->keyCache[i].keyCheckSum = info.kcInfo[i].keycksum;
1706 strcpy(debug->keyCache[i].principal, info.kcInfo[i].principal);
1710 fail_kas_ServerDebugGet:
1719 * kas_ServerRandomKeyGet - get a random key from a server.
1723 * IN cellHandle - a cellHandle previously returned by afsclient_CellOpen.
1725 * IN serverHandle - a serverHandle previously returned by kas_ServerOpen.
1727 * OUT key - a random key.
1731 * No locks are held by this function.
1735 * Returns != 0 upon successful completion.
1739 kas_ServerRandomKeyGet(const void *cellHandle, const void *serverHandle,
1740 kas_encryptionKey_p kas_keyp, afs_status_p st)
1743 afs_status_t tst = 0;
1744 afs_cell_handle_p c_handle = (afs_cell_handle_p) cellHandle;
1745 kas_server_p k_handle = (kas_server_p) serverHandle;
1746 kas_server_t kaserver;
1750 * Validate input arguments and make rpc.
1753 if (kas_keyp == NULL) {
1754 tst = ADMKASKEYNULL;
1755 goto fail_kas_ServerRandomKeyGet;
1758 if (!ChooseValidServer(c_handle, k_handle, &kaserver, &tst)) {
1759 goto fail_kas_ServerRandomKeyGet;
1762 tst = ubik_KAM_GetRandomKey(kaserver.servers, 0, &key);
1764 goto fail_kas_ServerRandomKeyGet;
1766 memcpy(kas_keyp, &key, sizeof(*kas_keyp));
1769 fail_kas_ServerRandomKeyGet:
1778 * kas_StringToKey - turn a string key into a key.
1782 * IN cellName - the name of the cell where the key will be used.
1784 * IN string - the string to be converted.
1786 * OUT key - the encryption key.
1790 * No locks are held by this function.
1794 * Returns != 0 upon successful completion.
1798 kas_StringToKey(const char *cellName, const char *string,
1799 kas_encryptionKey_p key, afs_status_p st)
1802 afs_status_t tst = 0;
1804 ka_StringToKey((char *)string, (char *)cellName, (struct ktc_encryptionKey *)key);
1815 * kas_KeyCheckSum - compute the checksum of an encryption key.
1819 * IN key - the encryption key.
1821 * OUT cksumP - key checksum
1825 * No locks are held by this function.
1829 * Returns != 0 upon successful completion.
1833 kas_KeyCheckSum(const kas_encryptionKey_p key, unsigned int *cksumP,
1837 afs_status_t tst = 0;
1840 if ((tst = ka_KeyCheckSum((char *)key, &cksum32)) == 0) {