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 "afs_kasAdmin.h"
18 #include "../adminutil/afs_AdminInternal.h"
19 #include <afs/afs_AdminErrors.h>
20 #include <afs/afs_utilAdmin.h>
21 #include <afs/kauth.h>
22 #include <afs/kautils.h>
23 #include <afs/kaport.h>
28 extern int ubik_Call();
29 extern int ubik_Call_New();
30 extern int ubik_CallIter();
35 struct ubik_client *servers;
38 } kas_server_t, *kas_server_p;
41 * IsValidServerHandle - verify the validity of a kas_server_t handle.
45 * IN serverHandle - the handle to be verified.
49 * No locks are obtained or released by this function
53 * Returns != 0 upon successful completion.
56 static int IsValidServerHandle(
57 const kas_server_p serverHandle,
64 * Validate input parameters
67 if (serverHandle == NULL) {
68 tst = ADMKASSERVERHANDLENULL;
69 goto fail_IsValidServerHandle;
72 if ((serverHandle->begin_magic != BEGIN_MAGIC) ||
73 (serverHandle->end_magic != END_MAGIC)) {
74 tst = ADMKASSERVERHANDLEBADMAGIC;
75 goto fail_IsValidServerHandle;
78 if (!serverHandle->is_valid) {
79 tst = ADMKASSERVERHANDLENOTVALID;
80 goto fail_IsValidServerHandle;
83 if (serverHandle->servers == NULL) {
84 tst = ADMKASSERVERHANDLENOSERVERS;
85 goto fail_IsValidServerHandle;
89 fail_IsValidServerHandle:
98 * IsValidCellHandle - verify the validity of a afs_cell_handle_t handle
99 * for doing kas related functions.
103 * IN cellHandle - the handle to be verified.
107 * No locks are obtained or released by this function
111 * Returns != 0 upon successful completion.
114 static int IsValidCellHandle(
115 const afs_cell_handle_p cellHandle,
119 afs_status_t tst = 0;
122 * Validate input parameters
125 if (!CellHandleIsValid((void *) cellHandle, &tst)) {
126 goto fail_IsValidCellHandle;
129 if (!cellHandle->kas_valid) {
130 tst = ADMCLIENTCELLKASINVALID;
131 goto fail_IsValidCellHandle;
134 if (cellHandle->kas == NULL) {
135 tst = ADMCLIENTCELLKASNULL;
136 goto fail_IsValidCellHandle;
140 fail_IsValidCellHandle:
149 * For all kas admin functions that take a cellHandle and a serverHandle,
150 * the intention is that is the cellHandle is not NULL, we should use
151 * it. Otherwise, we use the serverHandle. It is an error for both
152 * of these parameters to be non-NULL.
156 * ChooseValidServer - given a serverHandle and a cellHandle, choose the
157 * one that is non-NULL, validate it, and return a ubik_client structure
162 * IN cellHandle - the cell where kas calls are to be made
164 * IN serverHandle - the group of server(s) that should be used to satisfy
169 * No locks are obtained or released by this function
173 * Returns != 0 upon successful completion.
176 static int ChooseValidServer(
177 const afs_cell_handle_p cellHandle,
178 const kas_server_p serverHandle,
179 kas_server_p kasHandle,
183 afs_status_t tst = 0;
186 * Validate input parameters
189 if (kasHandle == NULL) {
190 tst = ADMKASKASHANDLENULL;
191 goto fail_ChooseValidServer;
195 * Only one of the input handle parameters to this function should
198 if ((cellHandle == NULL) && (serverHandle == NULL)) {
199 tst = ADMKASCELLHANDLEANDSERVERHANDLENULL;
200 goto fail_ChooseValidServer;
203 if ((cellHandle != NULL) && (serverHandle != NULL)) {
204 tst = ADMKASCELLHANDLEANDSERVERHANDLENOTNULL;
205 goto fail_ChooseValidServer;
209 * Validate the non-NULL handle
212 if (cellHandle != NULL) {
213 if (IsValidCellHandle(cellHandle, &tst)) {
214 kasHandle->servers = cellHandle->kas;
215 kasHandle->cell = cellHandle->working_cell;
217 goto fail_ChooseValidServer;
220 if (IsValidServerHandle(serverHandle, &tst)) {
221 kasHandle->servers = serverHandle->servers;
222 kasHandle->cell = serverHandle->cell;
224 goto fail_ChooseValidServer;
228 kasHandle->begin_magic = BEGIN_MAGIC;
229 kasHandle->end_magic = END_MAGIC;
230 kasHandle->is_valid = 1;
233 fail_ChooseValidServer:
242 static int kaentryinfo_to_kas_principalEntry_t(
243 struct kaentryinfo *from,
244 kas_principalEntry_p to,
248 afs_status_t tst = 0;
250 unsigned char misc_stuff[4];
253 tst = ADMKASFROMNULL;
254 goto fail_kaentryinfo_to_kas_principalEntry_t;
259 goto fail_kaentryinfo_to_kas_principalEntry_t;
262 if (from->flags & KAFADMIN) {
263 to->adminSetting = KAS_ADMIN;
265 to->adminSetting = NO_KAS_ADMIN;
268 if (from->flags & KAFNOTGS) {
269 to->tgsSetting = NO_TGS;
271 to->tgsSetting = TGS;
274 if (from->flags & KAFNOSEAL) {
275 to->encSetting = NO_ENCRYPT;
277 to->encSetting = ENCRYPT;
280 if (from->flags & KAFNOCPW) {
281 to->cpwSetting = NO_CHANGE_PASSWORD;
283 to->cpwSetting = CHANGE_PASSWORD;
286 reuse = (short) from->reserved3;
288 to->rpwSetting = REUSE_PASSWORD;
290 to->rpwSetting = NO_REUSE_PASSWORD;
294 if (from->user_expiration == NEVERDATE) {
295 to->userExpiration = 0;
297 to->userExpiration = from->user_expiration;
300 to->lastModTime = from->modification_time;
301 strcpy(to->lastModPrincipal.principal, from->modification_user.name);
302 strcpy(to->lastModPrincipal.instance, from->modification_user.instance);
303 to->lastChangePasswordTime = from->change_password_time;
304 to->maxTicketLifetime = from->max_ticket_lifetime;
305 to->keyVersion = from->key_version;
306 memcpy(&to->key, &from->key, sizeof(to->key));
307 to->keyCheckSum = from->keyCheckSum;
309 unpack_long(from->misc_auth_bytes, misc_stuff);
310 to->daysToPasswordExpire = misc_stuff[0];
311 to->failLoginCount = misc_stuff[2];
312 to->lockTime = misc_stuff[3] << 9;
315 fail_kaentryinfo_to_kas_principalEntry_t:
324 * kas_ServerOpen - open a handle to a set of kaserver's.
328 * IN cellHandle - a previously opened cellHandle that corresponds
329 * to the cell where the server(s) live.
331 * IN serverList - a NULL terminated list (a la argv) of server's that
334 * OUT serverHandleP - a pointer to a void pointer that upon successful
335 * completion contains serverHandle that can be used in other kas functions.
339 * No locks are obtained or released by this function
343 * Returns != 0 upon successful completion.
347 * This function make some assumptions about the afsconf_cell used by
348 * ka_AuthSpecificServersConn (since I just wrote ka_AuthSpecificServersConn).
349 * It only fills in the fields that are required.
351 * Also we assume that the servers listed are members of the cell in
352 * cellHandle without verifying that this is in fact the case. kas itself
353 * always assumes that the -servers parameter lists servers in the current
354 * cell without verifying, so I am no worse than the current
355 * implementation. In fact I'm actually a little more flexible since you
356 * can actually use my serverList to play with servers in another cell.
357 * You can't do that with kas. For certain functions in kas the same
358 * cell assumption can cause things to fail (the ka_StringToKey function in
362 int ADMINAPI kas_ServerOpen(
363 const void *cellHandle,
364 const char **serverList,
365 void **serverHandleP,
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(serverList[server_count],&server_addr,&tst)) {
419 server_info.hostAddr[server_count].sin_addr.s_addr = htonl(server_addr);
420 server_info.hostAddr[server_count].sin_port = htons(AFSCONF_KAUTHPORT);
422 goto fail_kas_ServerOpen;
426 if (server_count == 0) {
427 tst = ADMKASSERVERLISTEMPTY;
428 goto fail_kas_ServerOpen;
432 * Get a ubik_client handle for the specified servers
434 server_info.numServers = server_count;
435 if (!(tst = ka_AuthSpecificServersConn(KA_MAINTENANCE_SERVICE, &c_handle->tokens->kas_token, &server_info, &k_handle->servers))) {
436 k_handle->is_valid = 1;
437 k_handle->cell = c_handle->working_cell;
438 *serverHandleP = (void *) k_handle;
440 goto fail_kas_ServerOpen;
446 if ((rc == 0) && (k_handle != NULL)) {
457 * kas_ServerClose - close a serverHandle.
461 * IN serverHandle - a serverHandle previously returned by kas_ServerOpen.
465 * No locks are obtained or released by this function
469 * Returns != 0 upon successful completion.
472 int ADMINAPI kas_ServerClose(
473 const void *serverHandle,
477 afs_status_t tst = 0;
478 kas_server_p k_handle = (kas_server_p) serverHandle;
480 if (!IsValidServerHandle(k_handle, &tst)) {
481 goto fail_kas_ServerClose;
484 tst = ubik_ClientDestroy(k_handle->servers);
486 goto fail_kas_ServerClose;
489 k_handle->is_valid = 0;
493 fail_kas_ServerClose:
502 * kas_PrincipalCreate - create a new principal.
506 * IN cellHandle - a cellHandle previously returned by afsclient_CellOpen.
508 * IN serverHandle - a serverHandle previously returned by kas_ServerOpen.
510 * IN who - a kas_identity_p containing the identity of the new principal
513 * IN password - the new principal's initial password.
517 * No locks are obtained or released by this function
521 * Returns != 0 upon successful completion.
524 int ADMINAPI kas_PrincipalCreate(
525 const void *cellHandle,
526 const void *serverHandle,
527 const kas_identity_p who,
528 const char *password,
532 afs_status_t tst = 0;
533 afs_cell_handle_p c_handle = (afs_cell_handle_p) cellHandle;
534 kas_server_p k_handle = (kas_server_p) serverHandle;
535 kas_server_t kaserver;
536 struct kas_encryptionKey key;
539 * Validate input arguments and make rpc.
544 goto fail_kas_PrincipalCreate;
547 if (password == NULL) {
548 tst = ADMKASPASSWORDNULL;
549 goto fail_kas_PrincipalCreate;
552 if (!ChooseValidServer(c_handle, k_handle, &kaserver, &tst)) {
553 goto fail_kas_PrincipalCreate;
556 if (!kas_StringToKey(kaserver.cell, password, &key, &tst)) {
557 goto fail_kas_PrincipalCreate;
560 tst = ubik_Call(KAM_CreateUser, kaserver.servers, 0,
561 who->principal, who->instance, key);
563 goto fail_kas_PrincipalCreate;
568 fail_kas_PrincipalCreate:
577 * kas_PrincipalDelete - delete an existing principal.
581 * IN cellHandle - a cellHandle previously returned by afsclient_CellOpen.
583 * IN serverHandle - a serverHandle previously returned by kas_ServerOpen.
585 * IN who - a kas_identity_p containing the identity of the principal
590 * No locks are obtained or released by this function
594 * Returns != 0 upon successful completion.
597 int ADMINAPI kas_PrincipalDelete(
598 const void *cellHandle,
599 const void *serverHandle,
600 const kas_identity_p who,
604 afs_status_t tst = 0;
605 afs_cell_handle_p c_handle = (afs_cell_handle_p) cellHandle;
606 kas_server_p k_handle = (kas_server_p) serverHandle;
607 kas_server_t kaserver;
610 * Validate input arguments and make rpc.
615 goto fail_kas_PrincipalDelete;
618 if (!ChooseValidServer(c_handle, k_handle, &kaserver, &tst)) {
619 goto fail_kas_PrincipalDelete;
621 tst = ubik_Call(KAM_DeleteUser, kaserver.servers, 0,
622 who->principal, who->instance);
624 goto fail_kas_PrincipalDelete;
628 fail_kas_PrincipalDelete:
637 * GetPrincipalLockStatus - get the lock status of a principal.
641 * IN kaserver - a valid kaserver handle previously returned by
644 * IN who - a kas_identity_p containing the identity of the principal
647 * OUT lockedUntil - the remaining number of seconds the principal is locked.
651 * No locks are obtained or released by this function
655 * Returns != 0 upon successful completion.
658 static int GetPrincipalLockStatus(
659 const kas_server_p kaserver,
660 const kas_identity_p who,
661 unsigned int *lockedUntil,
665 afs_status_t tst = 0;
671 * Validate input arguments and make rpc.
674 if (kaserver == NULL) {
675 tst = ADMKASKASERVERNULL;
676 goto fail_GetPrincipalLockStatus;
681 goto fail_GetPrincipalLockStatus;
684 if (lockedUntil == NULL) {
685 tst = ADMKASLOCKEDUNTILNULL;
686 goto fail_GetPrincipalLockStatus;
690 * Unlike every other kas rpc we make here, the lock/unlock rpc's
691 * aren't ubik based. So instead of calling ubik_Call, we use
692 * ubik_CallIter. ubik_CallIter steps through the list of hosts
693 * in the ubik_client and calls them one at a time. Since there's
694 * no synchronization of this data across the servers we have to
695 * manually keep track of the shortest time to unlock the user ourselves.
697 * The original inspiration for this function is ka_islocked
698 * in admin_tools.c. I think that function is totally bogus so I'm
701 * This function should contact all the kaservers and request the lock
702 * status of the principal. If any of the servers say the principal is
703 * unlocked, we report it as unlocked. If all the servers say the
704 * principal is locked, we find the server with the shortest lock time
705 * remaining on the principal and return that time.
707 * This is different than kas, but I think kas is buggy.
713 tst = ubik_CallIter(KAM_LockStatus, kaserver->servers, UPUBIKONLY,
714 &count, who->principal, who->instance,
715 &locked, 0, 0, 0, 0);
718 if ((locked < *lockedUntil) || !once) {
719 *lockedUntil = locked;
724 } while ((tst != UNOSERVERS) && (locked != 0));
727 * Check to see if any server reported this principal unlocked.
730 if ((tst == 0) && (locked == 0)) {
733 if ((tst == 0) || (tst == UNOSERVERS)) {
737 fail_GetPrincipalLockStatus:
746 * kas_PrincipalGet - retrieve information about a single principal.
750 * IN cellHandle - a cellHandle previously returned by afsclient_CellOpen.
752 * IN serverHandle - a serverHandle previously returned by kas_ServerOpen.
754 * IN who - a kas_identity_p containing the identity of the principal
757 * OUT principal - upon successful completion contains information
762 * No locks are obtained or released by this function
766 * Returns != 0 upon successful completion.
769 int ADMINAPI kas_PrincipalGet(
770 const void *cellHandle,
771 const void *serverHandle,
772 const kas_identity_p who,
773 kas_principalEntry_p principal,
777 afs_status_t tst = 0;
778 afs_cell_handle_p c_handle = (afs_cell_handle_p) cellHandle;
779 kas_server_p k_handle = (kas_server_p) serverHandle;
780 kas_server_t kaserver;
781 struct kaentryinfo entry;
784 * Validate input arguments and make rpc.
789 goto fail_kas_PrincipalGet;
792 if (principal == NULL) {
793 tst = ADMKASPRINCIPALNULL;
794 goto fail_kas_PrincipalGet;
797 if (!ChooseValidServer(c_handle, k_handle, &kaserver, &tst)) {
798 goto fail_kas_PrincipalGet;
801 tst = ubik_Call(KAM_GetEntry, kaserver.servers, 0,
802 who->principal, who->instance, KAMAJORVERSION, &entry);
804 goto fail_kas_PrincipalGet;
808 * copy the kaentryinfo structure to our kas_principalEntry_t
811 if (!kaentryinfo_to_kas_principalEntry_t(&entry, principal, &tst)) {
812 goto fail_kas_PrincipalGet;
816 fail_kas_PrincipalGet:
824 typedef struct principal_get {
828 kas_server_t kaserver;
829 kas_identity_t principal[CACHED_ITEMS];
830 } principal_get_t, *principal_get_p;
832 static int DeletePrincipalSpecificData(
837 afs_status_t tst = 0;
838 principal_get_p prin = (principal_get_p) rpc_specific;
840 prin->kaserver.is_valid = 0;
849 static int GetPrincipalRPC(
853 int *last_item_contains_data,
857 afs_status_t tst = 0;
858 principal_get_p prin = (principal_get_p) rpc_specific;
860 tst = ubik_Call(KAM_ListEntry, prin->kaserver.servers, 0,
861 prin->current, &prin->next, &prin->count,
862 &prin->principal[slot]);
864 prin->current = prin->next;
865 if (prin->next == 0) {
867 *last_item_contains_data = 0;
878 static int GetPrincipalFromCache(
885 afs_status_t tst = 0;
886 principal_get_p prin = (principal_get_p) rpc_specific;
888 memcpy(dest, &prin->principal[slot], sizeof(kas_identity_t));
898 * kas_PrincipalGetBegin - start the process of iterating over the entire
903 * IN cellHandle - a cellHandle previously returned by afsclient_CellOpen.
905 * IN serverHandle - a serverHandle previously returned by kas_ServerOpen.
907 * OUT iterationIdP - upon successful completion contains a iterator that
908 * can be passed to kas_PrincipalGetNext.
912 * No locks are obtained or released by this function
916 * Returns != 0 upon successful completion.
921 int ADMINAPI kas_PrincipalGetBegin(
922 const void *cellHandle,
923 const void *serverHandle,
928 afs_status_t tst = 0;
929 afs_cell_handle_p c_handle = (afs_cell_handle_p) cellHandle;
930 kas_server_p k_handle = (kas_server_p) serverHandle;
931 afs_admin_iterator_p iter = (afs_admin_iterator_p) malloc(sizeof(afs_admin_iterator_t));
932 principal_get_p principal = (principal_get_p) malloc(sizeof(principal_get_t));
940 goto fail_kas_PrincipalGetBegin;
943 if (principal == NULL) {
945 goto fail_kas_PrincipalGetBegin;
948 if (iterationIdP == NULL) {
949 tst = ADMITERATIONIDPNULL;
950 goto fail_kas_PrincipalGetBegin;
953 if (!ChooseValidServer(c_handle, k_handle, &principal->kaserver, &tst)) {
954 goto fail_kas_PrincipalGetBegin;
958 * Initialize the iterator structure
961 principal->current = 0;
963 principal->count = 0;
964 if (IteratorInit(iter, (void *) principal, GetPrincipalRPC,
965 GetPrincipalFromCache, NULL,
966 DeletePrincipalSpecificData, &tst)) {
967 *iterationIdP = (void *) iter;
971 fail_kas_PrincipalGetBegin:
977 if (principal != NULL) {
989 * kas_PrincipalGetNext - retrieve the next principal from the kaserver.
993 * IN iterationId - an iterator previously returned by kas_PrincipalGetBegin
995 * OUT who - upon successful completion contains the next principal from the
1000 * Hold the iterator mutex across the call to the kaserver.
1004 * Returns != 0 upon successful completion.
1005 * Returns 0 and st == ADMITERATORDONE when the last entry is returned.
1008 int ADMINAPI kas_PrincipalGetNext(
1009 const void *iterationId,
1014 afs_status_t tst = 0;
1015 afs_admin_iterator_p iter = (afs_admin_iterator_p) iterationId;
1018 * Validate arguments
1022 tst = ADMKASWHONULL;
1023 goto fail_kas_PrincipalGetNext;
1027 tst = ADMITERATORNULL;
1028 goto fail_kas_PrincipalGetNext;
1031 rc = IteratorNext(iter, (void *) who, &tst);
1033 fail_kas_PrincipalGetNext:
1042 * kas_PrincipalGetDone - finish using a principal iterator
1046 * IN iterationId - an iterator previously returned by kas_PrincipalGetBegin
1050 * No locks are held by this function.
1054 * Returns != 0 upon successful completion.
1058 * It is the user's responsibility to make sure kas_PrincipalGetDone
1059 * is called only once for each iterator.
1062 int ADMINAPI kas_PrincipalGetDone(
1063 const void *iterationIdP,
1067 afs_status_t tst = 0;
1068 afs_admin_iterator_p iter = (afs_admin_iterator_p) iterationIdP;
1075 tst = ADMITERATORNULL;
1076 goto fail_kas_PrincipalGetDone;
1079 rc = IteratorDone(iter, &tst);
1081 fail_kas_PrincipalGetDone:
1090 * kas_PrincipalKeySet - set a principal's password to a known value.
1094 * IN cellHandle - a cellHandle previously returned by afsclient_CellOpen.
1096 * IN serverHandle - a serverHandle previously returned by kas_ServerOpen.
1098 * IN who - the principal for whom the password is being set.
1100 * IN keyVersion - the version number of the new key.
1102 * IN key - the new password.
1106 * No locks are held by this function.
1110 * Returns != 0 upon successful completion.
1113 int ADMINAPI kas_PrincipalKeySet(
1114 const void *cellHandle,
1115 const void *serverHandle,
1116 const kas_identity_p who,
1118 const kas_encryptionKey_p key,
1122 afs_status_t tst = 0;
1123 afs_cell_handle_p c_handle = (afs_cell_handle_p) cellHandle;
1124 kas_server_p k_handle = (kas_server_p) serverHandle;
1125 kas_server_t kaserver;
1128 * Validate input arguments and make rpc.
1132 tst = ADMKASWHONULL;
1133 goto fail_kas_PrincipalKeySet;
1137 tst = ADMKASKEYNULL;
1138 goto fail_kas_PrincipalKeySet;
1141 if (!ChooseValidServer(c_handle, k_handle, &kaserver, &tst)) {
1142 goto fail_kas_PrincipalKeySet;
1145 tst = ubik_Call(KAM_SetPassword, kaserver.servers, 0,
1146 who->principal, who->instance, keyVersion, *key);
1148 goto fail_kas_PrincipalKeySet;
1151 /* If we failed to fail we must have succeeded */
1154 fail_kas_PrincipalKeySet:
1163 * kas_PrincipalLockStatusGet - determine a principal's lock status.
1167 * IN cellHandle - a cellHandle previously returned by afsclient_CellOpen.
1169 * IN serverHandle - a serverHandle previously returned by kas_ServerOpen.
1171 * IN who - the principal whose lock status is being checked.
1173 * OUT lock_end_timeP - the number of seconds until the principal is unlocked.
1174 * If 0 => user is unlocked.
1178 * No locks are held by this function.
1182 * Returns != 0 upon successful completion.
1186 * See the comments in GetPrincipalLockStatus regarding how the locking data
1187 * is kept INconsistently between servers.
1190 int ADMINAPI kas_PrincipalLockStatusGet(
1191 const void *cellHandle,
1192 const void *serverHandle,
1193 const kas_identity_p who,
1194 unsigned int *lock_end_timeP,
1198 afs_status_t tst = 0;
1199 afs_cell_handle_p c_handle = (afs_cell_handle_p) cellHandle;
1200 kas_server_p k_handle = (kas_server_p) serverHandle;
1201 kas_server_t kaserver;
1204 * Validate input arguments and make rpc.
1208 tst = ADMKASWHONULL;
1209 goto fail_kas_PrincipalLockStatusGet;
1212 if (lock_end_timeP == NULL) {
1213 tst = ADMKASLOCKENDTIMEPNULL;
1214 goto fail_kas_PrincipalLockStatusGet;
1217 if (!ChooseValidServer(c_handle, k_handle, &kaserver, &tst)) {
1218 goto fail_kas_PrincipalLockStatusGet;
1221 rc = GetPrincipalLockStatus(&kaserver, who, lock_end_timeP, &tst);
1223 fail_kas_PrincipalLockStatusGet:
1232 * kas_PrincipalUnlock - unlock a principal.
1236 * IN cellHandle - a cellHandle previously returned by afsclient_CellOpen.
1238 * IN serverHandle - a serverHandle previously returned by kas_ServerOpen.
1240 * IN who - the principal who is being unlocked.
1244 * No locks are held by this function.
1248 * Returns != 0 upon successful completion.
1252 * See the comments in GetPrincipalLockStatus regarding how the locking data
1253 * is kept INconsistently between servers.
1256 int ADMINAPI kas_PrincipalUnlock(
1257 const void *cellHandle,
1258 const void *serverHandle,
1259 const kas_identity_p who,
1263 afs_status_t tst = 0;
1264 afs_cell_handle_p c_handle = (afs_cell_handle_p) cellHandle;
1265 kas_server_p k_handle = (kas_server_p) serverHandle;
1266 kas_server_t kaserver;
1268 afs_status_t save_tst = 0;
1271 * Validate input arguments and make rpc.
1275 tst = ADMKASWHONULL;
1276 goto fail_kas_PrincipalUnlock;
1279 if (!ChooseValidServer(c_handle, k_handle, &kaserver, &tst)) {
1280 goto fail_kas_PrincipalUnlock;
1284 tst = ubik_CallIter(KAM_Unlock, kaserver.servers, 0,
1285 &count, who->principal, who->instance,
1287 if (tst && (tst != UNOSERVERS)) {
1288 if (save_tst == 0) {
1289 save_tst = tst; /* save the first failure */
1292 } while (tst != UNOSERVERS);
1294 if ((tst == 0) || (tst == UNOSERVERS)){
1298 fail_kas_PrincipalUnlock:
1306 static int getPrincipalFlags(
1307 const void *cellHandle,
1308 const void *serverHandle,
1309 const kas_identity_p who,
1310 afs_int32 *cur_flags,
1314 afs_status_t tst = 0;
1315 afs_cell_handle_p c_handle = (afs_cell_handle_p) cellHandle;
1316 kas_server_p k_handle = (kas_server_p) serverHandle;
1317 kas_server_t kaserver;
1318 struct kaentryinfo tentry;
1320 if (!ChooseValidServer(c_handle, k_handle, &kaserver, &tst)) {
1321 goto fail_getPrincipalFlags;
1324 tst = ubik_Call(KAM_GetEntry, kaserver.servers, 0, who->principal,
1325 who->instance, KAMAJORVERSION, &tentry);
1327 *cur_flags = tentry.flags;
1331 fail_getPrincipalFlags:
1340 * kas_PrincipalFieldsSet - modify an existing principal.
1344 * IN cellHandle - a cellHandle previously returned by afsclient_CellOpen.
1346 * IN serverHandle - a serverHandle previously returned by kas_ServerOpen.
1348 * IN who - the principal who is being modified.
1350 * IN isAdmin - the admin status of the principal.
1352 * IN grantTickets - should the TGS issue tickets for the principal.
1354 * IN canEncrypt - should the TGS allow the use of encryption via the
1357 * IN canChangePassword - should the principal be allowed to change their
1360 * IN expirationDate - the date when the principal will expire.
1362 * IN maxTicketLifetime - the maximum lifetime of a ticket issued for
1365 * IN passwordExpires - the maximum number of days a particular
1366 * password can be used. The limit is 255, 0 => no expiration.
1368 * IN passwordReuse - can a password be reused by this principal.
1370 * IN failedPasswordAttempts - number of failed login attempts before
1371 * a principal is locked. The limit is 255, 0 => no limit.
1373 * IN failedPasswordLockTime - the number of seconds a principal is
1374 * locked once failedPasswordAttempts is reached. Some bizarre rounding
1375 * occurs for this value, see kas for more details.
1379 * No locks are held by this function.
1383 * Returns != 0 upon successful completion.
1387 * See the comments in GetPrincipalLockStatus regarding how the locking data
1388 * is kept INconsistently between servers.
1391 int ADMINAPI kas_PrincipalFieldsSet(
1392 const void *cellHandle,
1393 const void *serverHandle,
1394 const kas_identity_p who,
1395 const kas_admin_p isAdmin,
1396 const kas_tgs_p grantTickets,
1397 const kas_enc_p canEncrypt,
1398 const kas_cpw_p canChangePassword,
1399 const unsigned int *expirationDate,
1400 const unsigned int *maxTicketLifetime,
1401 const unsigned int *passwordExpires,
1402 const kas_rpw_p passwordReuse,
1403 const unsigned int *failedPasswordAttempts,
1404 const unsigned int *failedPasswordLockTime,
1408 afs_status_t tst = 0;
1409 afs_cell_handle_p c_handle = (afs_cell_handle_p) cellHandle;
1410 kas_server_p k_handle = (kas_server_p) serverHandle;
1411 kas_server_t kaserver;
1412 afs_int32 flags = 0;
1413 Date expiration = 0;
1414 afs_int32 lifetime = 0;
1416 char spare_bytes[4] = {0,0,0,0};
1417 int somethings_changing = 0;
1420 * Validate input arguments.
1424 tst = ADMKASWHONULL;
1425 goto fail_kas_PrincipalFieldsSet;
1429 * set flags based upon input
1431 * If we're changing the flags, we need to get the current value of
1432 * the flags first and then make the changes
1435 if ((isAdmin != NULL) || (grantTickets != NULL) ||
1436 (canEncrypt != NULL) || (canChangePassword != NULL)) {
1437 if (!getPrincipalFlags(cellHandle, serverHandle, who, &flags,
1439 goto fail_kas_PrincipalFieldsSet;
1443 if (isAdmin != NULL) {
1444 somethings_changing = 1;
1445 if (*isAdmin == KAS_ADMIN) {
1452 if (grantTickets != NULL) {
1453 somethings_changing = 1;
1454 if (*grantTickets == NO_TGS) {
1461 if (canEncrypt != NULL) {
1462 somethings_changing = 1;
1463 if (*canEncrypt == NO_ENCRYPT) {
1466 flags &= ~KAFNOSEAL;
1470 if (canChangePassword != NULL) {
1471 somethings_changing = 1;
1472 if (*canChangePassword == NO_CHANGE_PASSWORD) {
1479 flags = (flags & KAF_SETTABLE_FLAGS) | KAFNORMAL;
1481 if (expirationDate != NULL) {
1482 somethings_changing = 1;
1483 expiration = *expirationDate;
1486 if (maxTicketLifetime != NULL) {
1487 somethings_changing = 1;
1488 lifetime = *maxTicketLifetime;
1491 if (passwordExpires != NULL) {
1492 if (*passwordExpires > 255) {
1493 tst = ADMKASPASSWORDEXPIRESTOOBIG;
1494 goto fail_kas_PrincipalFieldsSet;
1496 somethings_changing = 1;
1497 spare_bytes[0] = *passwordExpires + 1;
1500 if (passwordReuse != NULL) {
1501 somethings_changing = 1;
1502 if (*passwordReuse == REUSE_PASSWORD) {
1503 spare_bytes[1] = KA_REUSEPW;
1505 spare_bytes[1] = KA_NOREUSEPW;
1509 if (failedPasswordAttempts != NULL) {
1510 if (*failedPasswordAttempts > 255) {
1511 tst = ADMKASFAILEDPASSWORDATTEMPTSTOOBIG;
1512 goto fail_kas_PrincipalFieldsSet;
1514 somethings_changing = 1;
1515 spare_bytes[2] = *failedPasswordAttempts + 1;
1518 if (failedPasswordLockTime != NULL) {
1519 if (*failedPasswordLockTime > 36*60*60) {
1520 tst = ADMKASFAILEDPASSWORDLOCKTIME;
1521 goto fail_kas_PrincipalFieldsSet;
1523 somethings_changing = 1;
1524 spare_bytes[3] = ((*failedPasswordLockTime + 511) >> 9) + 1;
1527 was_spare = pack_long(spare_bytes);
1529 if (somethings_changing) {
1530 if (!ChooseValidServer(c_handle, k_handle, &kaserver, &tst)) {
1531 goto fail_kas_PrincipalFieldsSet;
1533 tst = ubik_Call(KAM_SetFields, kaserver.servers, 0, who->principal,
1534 who->instance, flags, expiration, lifetime,
1540 tst = ADMKASPRINCIPALFIELDSNOCHANGE;
1543 fail_kas_PrincipalFieldsSet:
1552 * kas_ServerStatsGet - get server statistics.
1556 * IN cellHandle - a cellHandle previously returned by afsclient_CellOpen.
1558 * IN serverHandle - a serverHandle previously returned by kas_ServerOpen.
1560 * OUT stats - the statistics retrieved.
1564 * No locks are held by this function.
1568 * Returns != 0 upon successful completion.
1571 int ADMINAPI kas_ServerStatsGet(
1572 const void *cellHandle,
1573 const void *serverHandle,
1574 kas_serverStats_p stats,
1578 afs_status_t tst = 0;
1579 afs_cell_handle_p c_handle = (afs_cell_handle_p) cellHandle;
1580 kas_server_p k_handle = (kas_server_p) serverHandle;
1581 kas_server_t kaserver;
1588 * Validate input arguments and make rpc.
1591 if (stats == NULL) {
1592 tst = ADMKASSTATSNULL;
1593 goto fail_kas_ServerStatsGet;
1596 if (!ChooseValidServer(c_handle, k_handle, &kaserver, &tst)) {
1597 goto fail_kas_ServerStatsGet;
1600 tst = ubik_Call(KAM_GetStats, kaserver.servers, 0, KAMAJORVERSION, &admins,
1601 &statics, &dynamics);
1603 goto fail_kas_ServerStatsGet;
1606 stats->allocations = statics.allocs;
1607 stats->frees = statics.frees;
1608 stats->changePasswordRequests = statics.cpws;
1609 stats->adminAccounts = admins;
1610 stats->host = dynamics.host;
1611 stats->serverStartTime = dynamics.start_time;
1612 stats->hashTableUtilization = dynamics.hashTableUtilization;
1614 i = sizeof(kas_serverProcStats_t);
1615 memcpy(&stats->authenticate, &dynamics.Authenticate, i);
1616 memcpy(&stats->changePassword, &dynamics.ChangePassword, i);
1617 memcpy(&stats->getTicket, &dynamics.GetTicket, i);
1618 memcpy(&stats->createUser, &dynamics.CreateUser, i);
1619 memcpy(&stats->setPassword, &dynamics.SetPassword, i);
1620 memcpy(&stats->setFields, &dynamics.SetFields, i);
1621 memcpy(&stats->deleteUser, &dynamics.DeleteUser, i);
1622 memcpy(&stats->getEntry, &dynamics.GetEntry, i);
1623 memcpy(&stats->listEntry, &dynamics.ListEntry, i);
1624 memcpy(&stats->getStats, &dynamics.GetStats, i);
1625 memcpy(&stats->getPassword, &dynamics.GetPassword, i);
1626 memcpy(&stats->getRandomKey, &dynamics.GetRandomKey, i);
1627 memcpy(&stats->debug, &dynamics.Debug, i);
1628 memcpy(&stats->udpAuthenticate, &dynamics.UAuthenticate, i);
1629 memcpy(&stats->udpGetTicket, &dynamics.UGetTicket, i);
1630 memcpy(&stats->unlock, &dynamics.Unlock, i);
1631 memcpy(&stats->lockStatus, &dynamics.LockStatus, i);
1633 stats->stringChecks = dynamics.string_checks;
1636 fail_kas_ServerStatsGet:
1645 * kas_ServerDebugGet - get server debug info.
1649 * IN cellHandle - a cellHandle previously returned by afsclient_CellOpen.
1651 * IN serverHandle - a serverHandle previously returned by kas_ServerOpen.
1653 * OUT stats - the debug info retrieved.
1657 * No locks are held by this function.
1661 * Returns != 0 upon successful completion.
1664 int ADMINAPI kas_ServerDebugGet(
1665 const void *cellHandle,
1666 const void *serverHandle,
1667 kas_serverDebugInfo_p debug,
1671 afs_status_t tst = 0;
1672 afs_cell_handle_p c_handle = (afs_cell_handle_p) cellHandle;
1673 kas_server_p k_handle = (kas_server_p) serverHandle;
1674 kas_server_t kaserver;
1675 struct ka_debugInfo info;
1679 * Validate input arguments and make rpc.
1682 if (debug == NULL) {
1683 tst = ADMKASDEBUGNULL;
1684 goto fail_kas_ServerDebugGet;
1687 if (!ChooseValidServer(c_handle, k_handle, &kaserver, &tst)) {
1688 goto fail_kas_ServerDebugGet;
1690 tst = ubik_Call(KAM_Debug, kaserver.servers, 0, KAMAJORVERSION, 0, &info);
1692 goto fail_kas_ServerDebugGet;
1694 debug->host = info.host;
1695 debug->serverStartTime = info.startTime;
1696 debug->currentTime = info.reserved1;
1697 debug->noAuth = info.noAuth;
1698 debug->lastTransaction = info.lastTrans;
1699 strcpy(debug->lastOperation, info.lastOperation);
1700 strcpy(debug->lastPrincipalAuth, info.lastAuth);
1701 strcpy(debug->lastPrincipalUDPAuth, info.lastUAuth);
1702 strcpy(debug->lastPrincipalTGS, info.lastTGS);
1703 strcpy(debug->lastPrincipalUDPTGS, info.lastUTGS);
1704 strcpy(debug->lastPrincipalAdmin, info.lastAdmin);
1705 strcpy(debug->lastServerTGS, info.lastTGSServer);
1706 strcpy(debug->lastServerUDPTGS, info.lastUTGSServer);
1707 debug->nextAutoCheckPointWrite = info.nextAutoCPW;
1708 debug->updatesRemainingBeforeAutoCheckPointWrite = info.updatesRemaining;
1709 debug->dbHeaderRead = info.dbHeaderRead;
1710 debug->dbVersion = info.dbVersion;
1711 debug->dbFreePtr = info.dbFreePtr;
1712 debug->dbEOFPtr = info.dbEofPtr;
1713 debug->dbKvnoPtr = info.dbKvnoPtr;
1714 debug->dbSpecialKeysVersion = info.dbSpecialKeysVersion;
1715 debug->dbHeaderLock = info.cheader_lock;
1716 debug->keyCacheLock = info.keycache_lock;
1717 debug->keyCacheVersion = info.kcVersion;
1718 debug->keyCacheSize = info.kcSize;
1719 debug->keyCacheUsed = info.kcUsed;
1720 for(i=0;i<info.kcUsed;i++) {
1721 debug->keyCache[i].lastUsed = info.kcInfo[i].used;
1722 debug->keyCache[i].keyVersionNumber = info.kcInfo[i].kvno;
1723 debug->keyCache[i].primary = info.kcInfo[i].primary;
1724 debug->keyCache[i].keyCheckSum = info.kcInfo[i].keycksum;
1725 strcpy(debug->keyCache[i].principal,info.kcInfo[i].principal);
1729 fail_kas_ServerDebugGet:
1738 * kas_ServerRandomKeyGet - get a random key from a server.
1742 * IN cellHandle - a cellHandle previously returned by afsclient_CellOpen.
1744 * IN serverHandle - a serverHandle previously returned by kas_ServerOpen.
1746 * OUT key - a random key.
1750 * No locks are held by this function.
1754 * Returns != 0 upon successful completion.
1757 int ADMINAPI kas_ServerRandomKeyGet(
1758 const void *cellHandle,
1759 const void *serverHandle,
1760 kas_encryptionKey_p key,
1764 afs_status_t tst = 0;
1765 afs_cell_handle_p c_handle = (afs_cell_handle_p) cellHandle;
1766 kas_server_p k_handle = (kas_server_p) serverHandle;
1767 kas_server_t kaserver;
1770 * Validate input arguments and make rpc.
1774 tst = ADMKASKEYNULL;
1775 goto fail_kas_ServerRandomKeyGet;
1778 if (!ChooseValidServer(c_handle, k_handle, &kaserver, &tst)) {
1779 goto fail_kas_ServerRandomKeyGet;
1782 tst = ubik_Call(KAM_GetRandomKey, kaserver.servers, 0, key);
1784 goto fail_kas_ServerRandomKeyGet;
1788 fail_kas_ServerRandomKeyGet:
1797 * kas_StringToKey - turn a string key into a key.
1801 * IN cellName - the name of the cell where the key will be used.
1803 * IN string - the string to be converted.
1805 * OUT key - the encryption key.
1809 * No locks are held by this function.
1813 * Returns != 0 upon successful completion.
1816 int ADMINAPI kas_StringToKey(
1817 const char *cellName,
1819 kas_encryptionKey_p key,
1823 afs_status_t tst = 0;
1825 ka_StringToKey(string, cellName, (struct ktc_encryptionKey *) key);
1836 * kas_KeyCheckSum - compute the checksum of an encryption key.
1840 * IN key - the encryption key.
1842 * OUT cksumP - key checksum
1846 * No locks are held by this function.
1850 * Returns != 0 upon successful completion.
1853 int ADMINAPI kas_KeyCheckSum(
1854 const kas_encryptionKey_p key,
1855 unsigned int *cksumP,
1859 afs_status_t tst = 0;
1862 if ((tst = ka_KeyCheckSum((char *)key, &cksum32)) == 0) {