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>
26 #include "afs_kasAdmin.h"
27 #include "../adminutil/afs_AdminInternal.h"
28 #include <afs/afs_AdminErrors.h>
29 #include <afs/afs_utilAdmin.h>
30 #include <afs/kauth.h>
31 #include <afs/kautils.h>
32 #include <afs/kaport.h>
37 extern int ubik_Call();
38 extern int ubik_Call_New();
39 extern int ubik_CallIter();
44 struct ubik_client *servers;
47 } kas_server_t, *kas_server_p;
50 * IsValidServerHandle - verify the validity of a kas_server_t handle.
54 * IN serverHandle - the handle to be verified.
58 * No locks are obtained or released by this function
62 * Returns != 0 upon successful completion.
65 static int IsValidServerHandle(
66 const kas_server_p serverHandle,
73 * Validate input parameters
76 if (serverHandle == NULL) {
77 tst = ADMKASSERVERHANDLENULL;
78 goto fail_IsValidServerHandle;
81 if ((serverHandle->begin_magic != BEGIN_MAGIC) ||
82 (serverHandle->end_magic != END_MAGIC)) {
83 tst = ADMKASSERVERHANDLEBADMAGIC;
84 goto fail_IsValidServerHandle;
87 if (!serverHandle->is_valid) {
88 tst = ADMKASSERVERHANDLENOTVALID;
89 goto fail_IsValidServerHandle;
92 if (serverHandle->servers == NULL) {
93 tst = ADMKASSERVERHANDLENOSERVERS;
94 goto fail_IsValidServerHandle;
98 fail_IsValidServerHandle:
107 * IsValidCellHandle - verify the validity of a afs_cell_handle_t handle
108 * for doing kas related functions.
112 * IN cellHandle - the handle to be verified.
116 * No locks are obtained or released by this function
120 * Returns != 0 upon successful completion.
123 static int IsValidCellHandle(
124 const afs_cell_handle_p cellHandle,
128 afs_status_t tst = 0;
131 * Validate input parameters
134 if (!CellHandleIsValid((void *) cellHandle, &tst)) {
135 goto fail_IsValidCellHandle;
138 if (!cellHandle->kas_valid) {
139 tst = ADMCLIENTCELLKASINVALID;
140 goto fail_IsValidCellHandle;
143 if (cellHandle->kas == NULL) {
144 tst = ADMCLIENTCELLKASNULL;
145 goto fail_IsValidCellHandle;
149 fail_IsValidCellHandle:
158 * For all kas admin functions that take a cellHandle and a serverHandle,
159 * the intention is that is the cellHandle is not NULL, we should use
160 * it. Otherwise, we use the serverHandle. It is an error for both
161 * of these parameters to be non-NULL.
165 * ChooseValidServer - given a serverHandle and a cellHandle, choose the
166 * one that is non-NULL, validate it, and return a ubik_client structure
171 * IN cellHandle - the cell where kas calls are to be made
173 * IN serverHandle - the group of server(s) that should be used to satisfy
178 * No locks are obtained or released by this function
182 * Returns != 0 upon successful completion.
185 static int ChooseValidServer(
186 const afs_cell_handle_p cellHandle,
187 const kas_server_p serverHandle,
188 kas_server_p kasHandle,
192 afs_status_t tst = 0;
195 * Validate input parameters
198 if (kasHandle == NULL) {
199 tst = ADMKASKASHANDLENULL;
200 goto fail_ChooseValidServer;
204 * Only one of the input handle parameters to this function should
207 if ((cellHandle == NULL) && (serverHandle == NULL)) {
208 tst = ADMKASCELLHANDLEANDSERVERHANDLENULL;
209 goto fail_ChooseValidServer;
212 if ((cellHandle != NULL) && (serverHandle != NULL)) {
213 tst = ADMKASCELLHANDLEANDSERVERHANDLENOTNULL;
214 goto fail_ChooseValidServer;
218 * Validate the non-NULL handle
221 if (cellHandle != NULL) {
222 if (IsValidCellHandle(cellHandle, &tst)) {
223 kasHandle->servers = cellHandle->kas;
224 kasHandle->cell = cellHandle->working_cell;
226 goto fail_ChooseValidServer;
229 if (IsValidServerHandle(serverHandle, &tst)) {
230 kasHandle->servers = serverHandle->servers;
231 kasHandle->cell = serverHandle->cell;
233 goto fail_ChooseValidServer;
237 kasHandle->begin_magic = BEGIN_MAGIC;
238 kasHandle->end_magic = END_MAGIC;
239 kasHandle->is_valid = 1;
242 fail_ChooseValidServer:
251 static int kaentryinfo_to_kas_principalEntry_t(
252 struct kaentryinfo *from,
253 kas_principalEntry_p to,
257 afs_status_t tst = 0;
259 unsigned char misc_stuff[4];
262 tst = ADMKASFROMNULL;
263 goto fail_kaentryinfo_to_kas_principalEntry_t;
268 goto fail_kaentryinfo_to_kas_principalEntry_t;
271 if (from->flags & KAFADMIN) {
272 to->adminSetting = KAS_ADMIN;
274 to->adminSetting = NO_KAS_ADMIN;
277 if (from->flags & KAFNOTGS) {
278 to->tgsSetting = NO_TGS;
280 to->tgsSetting = TGS;
283 if (from->flags & KAFNOSEAL) {
284 to->encSetting = NO_ENCRYPT;
286 to->encSetting = ENCRYPT;
289 if (from->flags & KAFNOCPW) {
290 to->cpwSetting = NO_CHANGE_PASSWORD;
292 to->cpwSetting = CHANGE_PASSWORD;
295 reuse = (short) from->reserved3;
297 to->rpwSetting = REUSE_PASSWORD;
299 to->rpwSetting = NO_REUSE_PASSWORD;
303 if (from->user_expiration == NEVERDATE) {
304 to->userExpiration = 0;
306 to->userExpiration = from->user_expiration;
309 to->lastModTime = from->modification_time;
310 strcpy(to->lastModPrincipal.principal, from->modification_user.name);
311 strcpy(to->lastModPrincipal.instance, from->modification_user.instance);
312 to->lastChangePasswordTime = from->change_password_time;
313 to->maxTicketLifetime = from->max_ticket_lifetime;
314 to->keyVersion = from->key_version;
315 memcpy(&to->key, &from->key, sizeof(to->key));
316 to->keyCheckSum = from->keyCheckSum;
318 unpack_long(from->misc_auth_bytes, misc_stuff);
319 to->daysToPasswordExpire = misc_stuff[0];
320 to->failLoginCount = misc_stuff[2];
321 to->lockTime = misc_stuff[3] << 9;
324 fail_kaentryinfo_to_kas_principalEntry_t:
333 * kas_ServerOpen - open a handle to a set of kaserver's.
337 * IN cellHandle - a previously opened cellHandle that corresponds
338 * to the cell where the server(s) live.
340 * IN serverList - a NULL terminated list (a la argv) of server's that
343 * OUT serverHandleP - a pointer to a void pointer that upon successful
344 * completion contains serverHandle that can be used in other kas functions.
348 * No locks are obtained or released by this function
352 * Returns != 0 upon successful completion.
356 * This function make some assumptions about the afsconf_cell used by
357 * ka_AuthSpecificServersConn (since I just wrote ka_AuthSpecificServersConn).
358 * It only fills in the fields that are required.
360 * Also we assume that the servers listed are members of the cell in
361 * cellHandle without verifying that this is in fact the case. kas itself
362 * always assumes that the -servers parameter lists servers in the current
363 * cell without verifying, so I am no worse than the current
364 * implementation. In fact I'm actually a little more flexible since you
365 * can actually use my serverList to play with servers in another cell.
366 * You can't do that with kas. For certain functions in kas the same
367 * cell assumption can cause things to fail (the ka_StringToKey function in
371 int ADMINAPI kas_ServerOpen(
372 const void *cellHandle,
373 const char **serverList,
374 void **serverHandleP,
378 afs_status_t tst = 0;
379 afs_cell_handle_p c_handle = (afs_cell_handle_p) cellHandle;
380 int server_count=0, server_addr;
381 struct afsconf_cell server_info;
382 kas_server_p k_handle = (kas_server_p) malloc (sizeof(kas_server_t));
385 * Validate input parameters
388 if (c_handle == NULL) {
389 tst = ADMCLIENTCELLHANDLENULL;
390 goto fail_kas_ServerOpen;
393 if (c_handle->kas_valid == 0) {
394 tst = ADMCLIENTCELLKASINVALID;
395 goto fail_kas_ServerOpen;
398 if (serverList == NULL) {
399 tst = ADMKASSERVERLISTNULL;
400 goto fail_kas_ServerOpen;
403 if (serverHandleP == NULL) {
404 tst = ADMKASSERVERHANDLEPNULL;
405 goto fail_kas_ServerOpen;
408 if (k_handle == NULL) {
410 goto fail_kas_ServerOpen;
413 k_handle->begin_magic = BEGIN_MAGIC;
414 k_handle->end_magic = END_MAGIC;
415 k_handle->is_valid = 0;
416 k_handle->servers = NULL;
419 * Convert serverList to numeric addresses
422 for(server_count=0; serverList[server_count] != NULL; server_count++) {
423 if (server_count >= MAXHOSTSPERCELL) {
424 tst = ADMKASSERVERLISTTOOLONG;
425 goto fail_kas_ServerOpen;
427 if (util_AdminServerAddressGetFromName(serverList[server_count],&server_addr,&tst)) {
428 server_info.hostAddr[server_count].sin_addr.s_addr = htonl(server_addr);
429 server_info.hostAddr[server_count].sin_port = htons(AFSCONF_KAUTHPORT);
431 goto fail_kas_ServerOpen;
435 if (server_count == 0) {
436 tst = ADMKASSERVERLISTEMPTY;
437 goto fail_kas_ServerOpen;
441 * Get a ubik_client handle for the specified servers
443 server_info.numServers = server_count;
444 if (!(tst = ka_AuthSpecificServersConn(KA_MAINTENANCE_SERVICE, &c_handle->tokens->kas_token, &server_info, &k_handle->servers))) {
445 k_handle->is_valid = 1;
446 k_handle->cell = c_handle->working_cell;
447 *serverHandleP = (void *) k_handle;
449 goto fail_kas_ServerOpen;
455 if ((rc == 0) && (k_handle != NULL)) {
466 * kas_ServerClose - close a serverHandle.
470 * IN serverHandle - a serverHandle previously returned by kas_ServerOpen.
474 * No locks are obtained or released by this function
478 * Returns != 0 upon successful completion.
481 int ADMINAPI kas_ServerClose(
482 const void *serverHandle,
486 afs_status_t tst = 0;
487 kas_server_p k_handle = (kas_server_p) serverHandle;
489 if (!IsValidServerHandle(k_handle, &tst)) {
490 goto fail_kas_ServerClose;
493 tst = ubik_ClientDestroy(k_handle->servers);
495 goto fail_kas_ServerClose;
498 k_handle->is_valid = 0;
502 fail_kas_ServerClose:
511 * kas_PrincipalCreate - create a new principal.
515 * IN cellHandle - a cellHandle previously returned by afsclient_CellOpen.
517 * IN serverHandle - a serverHandle previously returned by kas_ServerOpen.
519 * IN who - a kas_identity_p containing the identity of the new principal
522 * IN password - the new principal's initial password.
526 * No locks are obtained or released by this function
530 * Returns != 0 upon successful completion.
533 int ADMINAPI kas_PrincipalCreate(
534 const void *cellHandle,
535 const void *serverHandle,
536 const kas_identity_p who,
537 const char *password,
541 afs_status_t tst = 0;
542 afs_cell_handle_p c_handle = (afs_cell_handle_p) cellHandle;
543 kas_server_p k_handle = (kas_server_p) serverHandle;
544 kas_server_t kaserver;
545 struct kas_encryptionKey key;
548 * Validate input arguments and make rpc.
553 goto fail_kas_PrincipalCreate;
556 if (password == NULL) {
557 tst = ADMKASPASSWORDNULL;
558 goto fail_kas_PrincipalCreate;
561 if (!ChooseValidServer(c_handle, k_handle, &kaserver, &tst)) {
562 goto fail_kas_PrincipalCreate;
565 if (!kas_StringToKey(kaserver.cell, password, &key, &tst)) {
566 goto fail_kas_PrincipalCreate;
569 tst = ubik_Call(KAM_CreateUser, kaserver.servers, 0,
570 who->principal, who->instance, key);
572 goto fail_kas_PrincipalCreate;
577 fail_kas_PrincipalCreate:
586 * kas_PrincipalDelete - delete an existing principal.
590 * IN cellHandle - a cellHandle previously returned by afsclient_CellOpen.
592 * IN serverHandle - a serverHandle previously returned by kas_ServerOpen.
594 * IN who - a kas_identity_p containing the identity of the principal
599 * No locks are obtained or released by this function
603 * Returns != 0 upon successful completion.
606 int ADMINAPI kas_PrincipalDelete(
607 const void *cellHandle,
608 const void *serverHandle,
609 const kas_identity_p who,
613 afs_status_t tst = 0;
614 afs_cell_handle_p c_handle = (afs_cell_handle_p) cellHandle;
615 kas_server_p k_handle = (kas_server_p) serverHandle;
616 kas_server_t kaserver;
619 * Validate input arguments and make rpc.
624 goto fail_kas_PrincipalDelete;
627 if (!ChooseValidServer(c_handle, k_handle, &kaserver, &tst)) {
628 goto fail_kas_PrincipalDelete;
630 tst = ubik_Call(KAM_DeleteUser, kaserver.servers, 0,
631 who->principal, who->instance);
633 goto fail_kas_PrincipalDelete;
637 fail_kas_PrincipalDelete:
646 * GetPrincipalLockStatus - get the lock status of a principal.
650 * IN kaserver - a valid kaserver handle previously returned by
653 * IN who - a kas_identity_p containing the identity of the principal
656 * OUT lockedUntil - the remaining number of seconds the principal is locked.
660 * No locks are obtained or released by this function
664 * Returns != 0 upon successful completion.
667 static int GetPrincipalLockStatus(
668 const kas_server_p kaserver,
669 const kas_identity_p who,
670 unsigned int *lockedUntil,
674 afs_status_t tst = 0;
680 * Validate input arguments and make rpc.
683 if (kaserver == NULL) {
684 tst = ADMKASKASERVERNULL;
685 goto fail_GetPrincipalLockStatus;
690 goto fail_GetPrincipalLockStatus;
693 if (lockedUntil == NULL) {
694 tst = ADMKASLOCKEDUNTILNULL;
695 goto fail_GetPrincipalLockStatus;
699 * Unlike every other kas rpc we make here, the lock/unlock rpc's
700 * aren't ubik based. So instead of calling ubik_Call, we use
701 * ubik_CallIter. ubik_CallIter steps through the list of hosts
702 * in the ubik_client and calls them one at a time. Since there's
703 * no synchronization of this data across the servers we have to
704 * manually keep track of the shortest time to unlock the user ourselves.
706 * The original inspiration for this function is ka_islocked
707 * in admin_tools.c. I think that function is totally bogus so I'm
710 * This function should contact all the kaservers and request the lock
711 * status of the principal. If any of the servers say the principal is
712 * unlocked, we report it as unlocked. If all the servers say the
713 * principal is locked, we find the server with the shortest lock time
714 * remaining on the principal and return that time.
716 * This is different than kas, but I think kas is buggy.
722 tst = ubik_CallIter(KAM_LockStatus, kaserver->servers, UPUBIKONLY,
723 &count, who->principal, who->instance,
724 &locked, 0, 0, 0, 0);
727 if ((locked < *lockedUntil) || !once) {
728 *lockedUntil = locked;
733 } while ((tst != UNOSERVERS) && (locked != 0));
736 * Check to see if any server reported this principal unlocked.
739 if ((tst == 0) && (locked == 0)) {
742 if ((tst == 0) || (tst == UNOSERVERS)) {
746 fail_GetPrincipalLockStatus:
755 * kas_PrincipalGet - retrieve information about a single principal.
759 * IN cellHandle - a cellHandle previously returned by afsclient_CellOpen.
761 * IN serverHandle - a serverHandle previously returned by kas_ServerOpen.
763 * IN who - a kas_identity_p containing the identity of the principal
766 * OUT principal - upon successful completion contains information
771 * No locks are obtained or released by this function
775 * Returns != 0 upon successful completion.
778 int ADMINAPI kas_PrincipalGet(
779 const void *cellHandle,
780 const void *serverHandle,
781 const kas_identity_p who,
782 kas_principalEntry_p principal,
786 afs_status_t tst = 0;
787 afs_cell_handle_p c_handle = (afs_cell_handle_p) cellHandle;
788 kas_server_p k_handle = (kas_server_p) serverHandle;
789 kas_server_t kaserver;
790 struct kaentryinfo entry;
793 * Validate input arguments and make rpc.
798 goto fail_kas_PrincipalGet;
801 if (principal == NULL) {
802 tst = ADMKASPRINCIPALNULL;
803 goto fail_kas_PrincipalGet;
806 if (!ChooseValidServer(c_handle, k_handle, &kaserver, &tst)) {
807 goto fail_kas_PrincipalGet;
810 tst = ubik_Call(KAM_GetEntry, kaserver.servers, 0,
811 who->principal, who->instance, KAMAJORVERSION, &entry);
813 goto fail_kas_PrincipalGet;
817 * copy the kaentryinfo structure to our kas_principalEntry_t
820 if (!kaentryinfo_to_kas_principalEntry_t(&entry, principal, &tst)) {
821 goto fail_kas_PrincipalGet;
825 fail_kas_PrincipalGet:
833 typedef struct principal_get {
837 kas_server_t kaserver;
838 kas_identity_t principal[CACHED_ITEMS];
839 } principal_get_t, *principal_get_p;
841 static int DeletePrincipalSpecificData(
846 afs_status_t tst = 0;
847 principal_get_p prin = (principal_get_p) rpc_specific;
849 prin->kaserver.is_valid = 0;
858 static int GetPrincipalRPC(
862 int *last_item_contains_data,
866 afs_status_t tst = 0;
867 principal_get_p prin = (principal_get_p) rpc_specific;
869 tst = ubik_Call(KAM_ListEntry, prin->kaserver.servers, 0,
870 prin->current, &prin->next, &prin->count,
871 &prin->principal[slot]);
873 prin->current = prin->next;
874 if (prin->next == 0) {
876 *last_item_contains_data = 0;
887 static int GetPrincipalFromCache(
894 afs_status_t tst = 0;
895 principal_get_p prin = (principal_get_p) rpc_specific;
897 memcpy(dest, &prin->principal[slot], sizeof(kas_identity_t));
907 * kas_PrincipalGetBegin - start the process of iterating over the entire
912 * IN cellHandle - a cellHandle previously returned by afsclient_CellOpen.
914 * IN serverHandle - a serverHandle previously returned by kas_ServerOpen.
916 * OUT iterationIdP - upon successful completion contains a iterator that
917 * can be passed to kas_PrincipalGetNext.
921 * No locks are obtained or released by this function
925 * Returns != 0 upon successful completion.
930 int ADMINAPI kas_PrincipalGetBegin(
931 const void *cellHandle,
932 const void *serverHandle,
937 afs_status_t tst = 0;
938 afs_cell_handle_p c_handle = (afs_cell_handle_p) cellHandle;
939 kas_server_p k_handle = (kas_server_p) serverHandle;
940 afs_admin_iterator_p iter = (afs_admin_iterator_p) malloc(sizeof(afs_admin_iterator_t));
941 principal_get_p principal = (principal_get_p) malloc(sizeof(principal_get_t));
949 goto fail_kas_PrincipalGetBegin;
952 if (principal == NULL) {
954 goto fail_kas_PrincipalGetBegin;
957 if (iterationIdP == NULL) {
958 tst = ADMITERATIONIDPNULL;
959 goto fail_kas_PrincipalGetBegin;
962 if (!ChooseValidServer(c_handle, k_handle, &principal->kaserver, &tst)) {
963 goto fail_kas_PrincipalGetBegin;
967 * Initialize the iterator structure
970 principal->current = 0;
972 principal->count = 0;
973 if (IteratorInit(iter, (void *) principal, GetPrincipalRPC,
974 GetPrincipalFromCache, NULL,
975 DeletePrincipalSpecificData, &tst)) {
976 *iterationIdP = (void *) iter;
980 fail_kas_PrincipalGetBegin:
986 if (principal != NULL) {
998 * kas_PrincipalGetNext - retrieve the next principal from the kaserver.
1002 * IN iterationId - an iterator previously returned by kas_PrincipalGetBegin
1004 * OUT who - upon successful completion contains the next principal from the
1009 * Hold the iterator mutex across the call to the kaserver.
1013 * Returns != 0 upon successful completion.
1014 * Returns 0 and st == ADMITERATORDONE when the last entry is returned.
1017 int ADMINAPI kas_PrincipalGetNext(
1018 const void *iterationId,
1023 afs_status_t tst = 0;
1024 afs_admin_iterator_p iter = (afs_admin_iterator_p) iterationId;
1027 * Validate arguments
1031 tst = ADMKASWHONULL;
1032 goto fail_kas_PrincipalGetNext;
1036 tst = ADMITERATORNULL;
1037 goto fail_kas_PrincipalGetNext;
1040 rc = IteratorNext(iter, (void *) who, &tst);
1042 fail_kas_PrincipalGetNext:
1051 * kas_PrincipalGetDone - finish using a principal iterator
1055 * IN iterationId - an iterator previously returned by kas_PrincipalGetBegin
1059 * No locks are held by this function.
1063 * Returns != 0 upon successful completion.
1067 * It is the user's responsibility to make sure kas_PrincipalGetDone
1068 * is called only once for each iterator.
1071 int ADMINAPI kas_PrincipalGetDone(
1072 const void *iterationIdP,
1076 afs_status_t tst = 0;
1077 afs_admin_iterator_p iter = (afs_admin_iterator_p) iterationIdP;
1084 tst = ADMITERATORNULL;
1085 goto fail_kas_PrincipalGetDone;
1088 rc = IteratorDone(iter, &tst);
1090 fail_kas_PrincipalGetDone:
1099 * kas_PrincipalKeySet - set a principal's password to a known value.
1103 * IN cellHandle - a cellHandle previously returned by afsclient_CellOpen.
1105 * IN serverHandle - a serverHandle previously returned by kas_ServerOpen.
1107 * IN who - the principal for whom the password is being set.
1109 * IN keyVersion - the version number of the new key.
1111 * IN key - the new password.
1115 * No locks are held by this function.
1119 * Returns != 0 upon successful completion.
1122 int ADMINAPI kas_PrincipalKeySet(
1123 const void *cellHandle,
1124 const void *serverHandle,
1125 const kas_identity_p who,
1127 const kas_encryptionKey_p key,
1131 afs_status_t tst = 0;
1132 afs_cell_handle_p c_handle = (afs_cell_handle_p) cellHandle;
1133 kas_server_p k_handle = (kas_server_p) serverHandle;
1134 kas_server_t kaserver;
1137 * Validate input arguments and make rpc.
1141 tst = ADMKASWHONULL;
1142 goto fail_kas_PrincipalKeySet;
1146 tst = ADMKASKEYNULL;
1147 goto fail_kas_PrincipalKeySet;
1150 if (!ChooseValidServer(c_handle, k_handle, &kaserver, &tst)) {
1151 goto fail_kas_PrincipalKeySet;
1154 tst = ubik_Call(KAM_SetPassword, kaserver.servers, 0,
1155 who->principal, who->instance, keyVersion, *key);
1157 goto fail_kas_PrincipalKeySet;
1160 /* If we failed to fail we must have succeeded */
1163 fail_kas_PrincipalKeySet:
1172 * kas_PrincipalLockStatusGet - determine a principal's lock status.
1176 * IN cellHandle - a cellHandle previously returned by afsclient_CellOpen.
1178 * IN serverHandle - a serverHandle previously returned by kas_ServerOpen.
1180 * IN who - the principal whose lock status is being checked.
1182 * OUT lock_end_timeP - the number of seconds until the principal is unlocked.
1183 * If 0 => user is unlocked.
1187 * No locks are held by this function.
1191 * Returns != 0 upon successful completion.
1195 * See the comments in GetPrincipalLockStatus regarding how the locking data
1196 * is kept INconsistently between servers.
1199 int ADMINAPI kas_PrincipalLockStatusGet(
1200 const void *cellHandle,
1201 const void *serverHandle,
1202 const kas_identity_p who,
1203 unsigned int *lock_end_timeP,
1207 afs_status_t tst = 0;
1208 afs_cell_handle_p c_handle = (afs_cell_handle_p) cellHandle;
1209 kas_server_p k_handle = (kas_server_p) serverHandle;
1210 kas_server_t kaserver;
1213 * Validate input arguments and make rpc.
1217 tst = ADMKASWHONULL;
1218 goto fail_kas_PrincipalLockStatusGet;
1221 if (lock_end_timeP == NULL) {
1222 tst = ADMKASLOCKENDTIMEPNULL;
1223 goto fail_kas_PrincipalLockStatusGet;
1226 if (!ChooseValidServer(c_handle, k_handle, &kaserver, &tst)) {
1227 goto fail_kas_PrincipalLockStatusGet;
1230 rc = GetPrincipalLockStatus(&kaserver, who, lock_end_timeP, &tst);
1232 fail_kas_PrincipalLockStatusGet:
1241 * kas_PrincipalUnlock - unlock a principal.
1245 * IN cellHandle - a cellHandle previously returned by afsclient_CellOpen.
1247 * IN serverHandle - a serverHandle previously returned by kas_ServerOpen.
1249 * IN who - the principal who is being unlocked.
1253 * No locks are held by this function.
1257 * Returns != 0 upon successful completion.
1261 * See the comments in GetPrincipalLockStatus regarding how the locking data
1262 * is kept INconsistently between servers.
1265 int ADMINAPI kas_PrincipalUnlock(
1266 const void *cellHandle,
1267 const void *serverHandle,
1268 const kas_identity_p who,
1272 afs_status_t tst = 0;
1273 afs_cell_handle_p c_handle = (afs_cell_handle_p) cellHandle;
1274 kas_server_p k_handle = (kas_server_p) serverHandle;
1275 kas_server_t kaserver;
1277 afs_status_t save_tst = 0;
1280 * Validate input arguments and make rpc.
1284 tst = ADMKASWHONULL;
1285 goto fail_kas_PrincipalUnlock;
1288 if (!ChooseValidServer(c_handle, k_handle, &kaserver, &tst)) {
1289 goto fail_kas_PrincipalUnlock;
1293 tst = ubik_CallIter(KAM_Unlock, kaserver.servers, 0,
1294 &count, who->principal, who->instance,
1296 if (tst && (tst != UNOSERVERS)) {
1297 if (save_tst == 0) {
1298 save_tst = tst; /* save the first failure */
1301 } while (tst != UNOSERVERS);
1303 if ((tst == 0) || (tst == UNOSERVERS)){
1307 fail_kas_PrincipalUnlock:
1315 static int getPrincipalFlags(
1316 const void *cellHandle,
1317 const void *serverHandle,
1318 const kas_identity_p who,
1319 afs_int32 *cur_flags,
1323 afs_status_t tst = 0;
1324 afs_cell_handle_p c_handle = (afs_cell_handle_p) cellHandle;
1325 kas_server_p k_handle = (kas_server_p) serverHandle;
1326 kas_server_t kaserver;
1327 struct kaentryinfo tentry;
1329 if (!ChooseValidServer(c_handle, k_handle, &kaserver, &tst)) {
1330 goto fail_getPrincipalFlags;
1333 tst = ubik_Call(KAM_GetEntry, kaserver.servers, 0, who->principal,
1334 who->instance, KAMAJORVERSION, &tentry);
1336 *cur_flags = tentry.flags;
1340 fail_getPrincipalFlags:
1349 * kas_PrincipalFieldsSet - modify an existing principal.
1353 * IN cellHandle - a cellHandle previously returned by afsclient_CellOpen.
1355 * IN serverHandle - a serverHandle previously returned by kas_ServerOpen.
1357 * IN who - the principal who is being modified.
1359 * IN isAdmin - the admin status of the principal.
1361 * IN grantTickets - should the TGS issue tickets for the principal.
1363 * IN canEncrypt - should the TGS allow the use of encryption via the
1366 * IN canChangePassword - should the principal be allowed to change their
1369 * IN expirationDate - the date when the principal will expire.
1371 * IN maxTicketLifetime - the maximum lifetime of a ticket issued for
1374 * IN passwordExpires - the maximum number of days a particular
1375 * password can be used. The limit is 255, 0 => no expiration.
1377 * IN passwordReuse - can a password be reused by this principal.
1379 * IN failedPasswordAttempts - number of failed login attempts before
1380 * a principal is locked. The limit is 255, 0 => no limit.
1382 * IN failedPasswordLockTime - the number of seconds a principal is
1383 * locked once failedPasswordAttempts is reached. Some bizarre rounding
1384 * occurs for this value, see kas for more details.
1388 * No locks are held by this function.
1392 * Returns != 0 upon successful completion.
1396 * See the comments in GetPrincipalLockStatus regarding how the locking data
1397 * is kept INconsistently between servers.
1400 int ADMINAPI kas_PrincipalFieldsSet(
1401 const void *cellHandle,
1402 const void *serverHandle,
1403 const kas_identity_p who,
1404 const kas_admin_p isAdmin,
1405 const kas_tgs_p grantTickets,
1406 const kas_enc_p canEncrypt,
1407 const kas_cpw_p canChangePassword,
1408 const unsigned int *expirationDate,
1409 const unsigned int *maxTicketLifetime,
1410 const unsigned int *passwordExpires,
1411 const kas_rpw_p passwordReuse,
1412 const unsigned int *failedPasswordAttempts,
1413 const unsigned int *failedPasswordLockTime,
1417 afs_status_t tst = 0;
1418 afs_cell_handle_p c_handle = (afs_cell_handle_p) cellHandle;
1419 kas_server_p k_handle = (kas_server_p) serverHandle;
1420 kas_server_t kaserver;
1421 afs_int32 flags = 0;
1422 Date expiration = 0;
1423 afs_int32 lifetime = 0;
1425 char spare_bytes[4] = {0,0,0,0};
1426 int somethings_changing = 0;
1429 * Validate input arguments.
1433 tst = ADMKASWHONULL;
1434 goto fail_kas_PrincipalFieldsSet;
1438 * set flags based upon input
1440 * If we're changing the flags, we need to get the current value of
1441 * the flags first and then make the changes
1444 if ((isAdmin != NULL) || (grantTickets != NULL) ||
1445 (canEncrypt != NULL) || (canChangePassword != NULL)) {
1446 if (!getPrincipalFlags(cellHandle, serverHandle, who, &flags,
1448 goto fail_kas_PrincipalFieldsSet;
1452 if (isAdmin != NULL) {
1453 somethings_changing = 1;
1454 if (*isAdmin == KAS_ADMIN) {
1461 if (grantTickets != NULL) {
1462 somethings_changing = 1;
1463 if (*grantTickets == NO_TGS) {
1470 if (canEncrypt != NULL) {
1471 somethings_changing = 1;
1472 if (*canEncrypt == NO_ENCRYPT) {
1475 flags &= ~KAFNOSEAL;
1479 if (canChangePassword != NULL) {
1480 somethings_changing = 1;
1481 if (*canChangePassword == NO_CHANGE_PASSWORD) {
1488 flags = (flags & KAF_SETTABLE_FLAGS) | KAFNORMAL;
1490 if (expirationDate != NULL) {
1491 somethings_changing = 1;
1492 expiration = *expirationDate;
1495 if (maxTicketLifetime != NULL) {
1496 somethings_changing = 1;
1497 lifetime = *maxTicketLifetime;
1500 if (passwordExpires != NULL) {
1501 if (*passwordExpires > 255) {
1502 tst = ADMKASPASSWORDEXPIRESTOOBIG;
1503 goto fail_kas_PrincipalFieldsSet;
1505 somethings_changing = 1;
1506 spare_bytes[0] = *passwordExpires + 1;
1509 if (passwordReuse != NULL) {
1510 somethings_changing = 1;
1511 if (*passwordReuse == REUSE_PASSWORD) {
1512 spare_bytes[1] = KA_REUSEPW;
1514 spare_bytes[1] = KA_NOREUSEPW;
1518 if (failedPasswordAttempts != NULL) {
1519 if (*failedPasswordAttempts > 255) {
1520 tst = ADMKASFAILEDPASSWORDATTEMPTSTOOBIG;
1521 goto fail_kas_PrincipalFieldsSet;
1523 somethings_changing = 1;
1524 spare_bytes[2] = *failedPasswordAttempts + 1;
1527 if (failedPasswordLockTime != NULL) {
1528 if (*failedPasswordLockTime > 36*60*60) {
1529 tst = ADMKASFAILEDPASSWORDLOCKTIME;
1530 goto fail_kas_PrincipalFieldsSet;
1532 somethings_changing = 1;
1533 spare_bytes[3] = ((*failedPasswordLockTime + 511) >> 9) + 1;
1536 was_spare = pack_long(spare_bytes);
1538 if (somethings_changing) {
1539 if (!ChooseValidServer(c_handle, k_handle, &kaserver, &tst)) {
1540 goto fail_kas_PrincipalFieldsSet;
1542 tst = ubik_Call(KAM_SetFields, kaserver.servers, 0, who->principal,
1543 who->instance, flags, expiration, lifetime,
1549 tst = ADMKASPRINCIPALFIELDSNOCHANGE;
1552 fail_kas_PrincipalFieldsSet:
1561 * kas_ServerStatsGet - get server statistics.
1565 * IN cellHandle - a cellHandle previously returned by afsclient_CellOpen.
1567 * IN serverHandle - a serverHandle previously returned by kas_ServerOpen.
1569 * OUT stats - the statistics retrieved.
1573 * No locks are held by this function.
1577 * Returns != 0 upon successful completion.
1580 int ADMINAPI kas_ServerStatsGet(
1581 const void *cellHandle,
1582 const void *serverHandle,
1583 kas_serverStats_p stats,
1587 afs_status_t tst = 0;
1588 afs_cell_handle_p c_handle = (afs_cell_handle_p) cellHandle;
1589 kas_server_p k_handle = (kas_server_p) serverHandle;
1590 kas_server_t kaserver;
1597 * Validate input arguments and make rpc.
1600 if (stats == NULL) {
1601 tst = ADMKASSTATSNULL;
1602 goto fail_kas_ServerStatsGet;
1605 if (!ChooseValidServer(c_handle, k_handle, &kaserver, &tst)) {
1606 goto fail_kas_ServerStatsGet;
1609 tst = ubik_Call(KAM_GetStats, kaserver.servers, 0, KAMAJORVERSION, &admins,
1610 &statics, &dynamics);
1612 goto fail_kas_ServerStatsGet;
1615 stats->allocations = statics.allocs;
1616 stats->frees = statics.frees;
1617 stats->changePasswordRequests = statics.cpws;
1618 stats->adminAccounts = admins;
1619 stats->host = dynamics.host;
1620 stats->serverStartTime = dynamics.start_time;
1621 stats->hashTableUtilization = dynamics.hashTableUtilization;
1623 i = sizeof(kas_serverProcStats_t);
1624 memcpy(&stats->authenticate, &dynamics.Authenticate, i);
1625 memcpy(&stats->changePassword, &dynamics.ChangePassword, i);
1626 memcpy(&stats->getTicket, &dynamics.GetTicket, i);
1627 memcpy(&stats->createUser, &dynamics.CreateUser, i);
1628 memcpy(&stats->setPassword, &dynamics.SetPassword, i);
1629 memcpy(&stats->setFields, &dynamics.SetFields, i);
1630 memcpy(&stats->deleteUser, &dynamics.DeleteUser, i);
1631 memcpy(&stats->getEntry, &dynamics.GetEntry, i);
1632 memcpy(&stats->listEntry, &dynamics.ListEntry, i);
1633 memcpy(&stats->getStats, &dynamics.GetStats, i);
1634 memcpy(&stats->getPassword, &dynamics.GetPassword, i);
1635 memcpy(&stats->getRandomKey, &dynamics.GetRandomKey, i);
1636 memcpy(&stats->debug, &dynamics.Debug, i);
1637 memcpy(&stats->udpAuthenticate, &dynamics.UAuthenticate, i);
1638 memcpy(&stats->udpGetTicket, &dynamics.UGetTicket, i);
1639 memcpy(&stats->unlock, &dynamics.Unlock, i);
1640 memcpy(&stats->lockStatus, &dynamics.LockStatus, i);
1642 stats->stringChecks = dynamics.string_checks;
1645 fail_kas_ServerStatsGet:
1654 * kas_ServerDebugGet - get server debug info.
1658 * IN cellHandle - a cellHandle previously returned by afsclient_CellOpen.
1660 * IN serverHandle - a serverHandle previously returned by kas_ServerOpen.
1662 * OUT stats - the debug info retrieved.
1666 * No locks are held by this function.
1670 * Returns != 0 upon successful completion.
1673 int ADMINAPI kas_ServerDebugGet(
1674 const void *cellHandle,
1675 const void *serverHandle,
1676 kas_serverDebugInfo_p debug,
1680 afs_status_t tst = 0;
1681 afs_cell_handle_p c_handle = (afs_cell_handle_p) cellHandle;
1682 kas_server_p k_handle = (kas_server_p) serverHandle;
1683 kas_server_t kaserver;
1684 struct ka_debugInfo info;
1688 * Validate input arguments and make rpc.
1691 if (debug == NULL) {
1692 tst = ADMKASDEBUGNULL;
1693 goto fail_kas_ServerDebugGet;
1696 if (!ChooseValidServer(c_handle, k_handle, &kaserver, &tst)) {
1697 goto fail_kas_ServerDebugGet;
1699 tst = ubik_Call(KAM_Debug, kaserver.servers, 0, KAMAJORVERSION, 0, &info);
1701 goto fail_kas_ServerDebugGet;
1703 debug->host = info.host;
1704 debug->serverStartTime = info.startTime;
1705 debug->currentTime = info.reserved1;
1706 debug->noAuth = info.noAuth;
1707 debug->lastTransaction = info.lastTrans;
1708 strcpy(debug->lastOperation, info.lastOperation);
1709 strcpy(debug->lastPrincipalAuth, info.lastAuth);
1710 strcpy(debug->lastPrincipalUDPAuth, info.lastUAuth);
1711 strcpy(debug->lastPrincipalTGS, info.lastTGS);
1712 strcpy(debug->lastPrincipalUDPTGS, info.lastUTGS);
1713 strcpy(debug->lastPrincipalAdmin, info.lastAdmin);
1714 strcpy(debug->lastServerTGS, info.lastTGSServer);
1715 strcpy(debug->lastServerUDPTGS, info.lastUTGSServer);
1716 debug->nextAutoCheckPointWrite = info.nextAutoCPW;
1717 debug->updatesRemainingBeforeAutoCheckPointWrite = info.updatesRemaining;
1718 debug->dbHeaderRead = info.dbHeaderRead;
1719 debug->dbVersion = info.dbVersion;
1720 debug->dbFreePtr = info.dbFreePtr;
1721 debug->dbEOFPtr = info.dbEofPtr;
1722 debug->dbKvnoPtr = info.dbKvnoPtr;
1723 debug->dbSpecialKeysVersion = info.dbSpecialKeysVersion;
1724 debug->dbHeaderLock = info.cheader_lock;
1725 debug->keyCacheLock = info.keycache_lock;
1726 debug->keyCacheVersion = info.kcVersion;
1727 debug->keyCacheSize = info.kcSize;
1728 debug->keyCacheUsed = info.kcUsed;
1729 for(i=0;i<info.kcUsed;i++) {
1730 debug->keyCache[i].lastUsed = info.kcInfo[i].used;
1731 debug->keyCache[i].keyVersionNumber = info.kcInfo[i].kvno;
1732 debug->keyCache[i].primary = info.kcInfo[i].primary;
1733 debug->keyCache[i].keyCheckSum = info.kcInfo[i].keycksum;
1734 strcpy(debug->keyCache[i].principal,info.kcInfo[i].principal);
1738 fail_kas_ServerDebugGet:
1747 * kas_ServerRandomKeyGet - get a random key from a server.
1751 * IN cellHandle - a cellHandle previously returned by afsclient_CellOpen.
1753 * IN serverHandle - a serverHandle previously returned by kas_ServerOpen.
1755 * OUT key - a random key.
1759 * No locks are held by this function.
1763 * Returns != 0 upon successful completion.
1766 int ADMINAPI kas_ServerRandomKeyGet(
1767 const void *cellHandle,
1768 const void *serverHandle,
1769 kas_encryptionKey_p key,
1773 afs_status_t tst = 0;
1774 afs_cell_handle_p c_handle = (afs_cell_handle_p) cellHandle;
1775 kas_server_p k_handle = (kas_server_p) serverHandle;
1776 kas_server_t kaserver;
1779 * Validate input arguments and make rpc.
1783 tst = ADMKASKEYNULL;
1784 goto fail_kas_ServerRandomKeyGet;
1787 if (!ChooseValidServer(c_handle, k_handle, &kaserver, &tst)) {
1788 goto fail_kas_ServerRandomKeyGet;
1791 tst = ubik_Call(KAM_GetRandomKey, kaserver.servers, 0, key);
1793 goto fail_kas_ServerRandomKeyGet;
1797 fail_kas_ServerRandomKeyGet:
1806 * kas_StringToKey - turn a string key into a key.
1810 * IN cellName - the name of the cell where the key will be used.
1812 * IN string - the string to be converted.
1814 * OUT key - the encryption key.
1818 * No locks are held by this function.
1822 * Returns != 0 upon successful completion.
1825 int ADMINAPI kas_StringToKey(
1826 const char *cellName,
1828 kas_encryptionKey_p key,
1832 afs_status_t tst = 0;
1834 ka_StringToKey(string, cellName, (struct ktc_encryptionKey *) key);
1845 * kas_KeyCheckSum - compute the checksum of an encryption key.
1849 * IN key - the encryption key.
1851 * OUT cksumP - key checksum
1855 * No locks are held by this function.
1859 * Returns != 0 upon successful completion.
1862 int ADMINAPI kas_KeyCheckSum(
1863 const kas_encryptionKey_p key,
1864 unsigned int *cksumP,
1868 afs_status_t tst = 0;
1871 if ((tst = ka_KeyCheckSum((char *)key, &cksum32)) == 0) {