2 * Copyright 2000, International Business Machines Corporation and others.
5 * This software has been released under the terms of the IBM Public
6 * License. For details, see the LICENSE file in the top-level source
7 * directory or online at http://www.openafs.org/dl/license10.html
10 #include <afsconfig.h>
11 #include <afs/param.h>
27 #include "afs_kasAdmin.h"
28 #include "../adminutil/afs_AdminInternal.h"
29 #include <afs/afs_AdminErrors.h>
30 #include <afs/afs_utilAdmin.h>
31 #include <afs/kauth.h>
32 #include <afs/kautils.h>
33 #include <afs/kaport.h>
38 extern int ubik_Call();
39 extern int ubik_Call_New();
40 extern int ubik_CallIter();
45 struct ubik_client *servers;
48 } kas_server_t, *kas_server_p;
51 * IsValidServerHandle - verify the validity of a kas_server_t handle.
55 * IN serverHandle - the handle to be verified.
59 * No locks are obtained or released by this function
63 * Returns != 0 upon successful completion.
67 IsValidServerHandle(const kas_server_p serverHandle, afs_status_p st)
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.
124 IsValidCellHandle(const afs_cell_handle_p cellHandle, afs_status_p st)
127 afs_status_t tst = 0;
130 * Validate input parameters
133 if (!CellHandleIsValid((void *)cellHandle, &tst)) {
134 goto fail_IsValidCellHandle;
137 if (!cellHandle->kas_valid) {
138 tst = ADMCLIENTCELLKASINVALID;
139 goto fail_IsValidCellHandle;
142 if (cellHandle->kas == NULL) {
143 tst = ADMCLIENTCELLKASNULL;
144 goto fail_IsValidCellHandle;
148 fail_IsValidCellHandle:
157 * For all kas admin functions that take a cellHandle and a serverHandle,
158 * the intention is that is the cellHandle is not NULL, we should use
159 * it. Otherwise, we use the serverHandle. It is an error for both
160 * of these parameters to be non-NULL.
164 * ChooseValidServer - given a serverHandle and a cellHandle, choose the
165 * one that is non-NULL, validate it, and return a ubik_client structure
170 * IN cellHandle - the cell where kas calls are to be made
172 * IN serverHandle - the group of server(s) that should be used to satisfy
177 * No locks are obtained or released by this function
181 * Returns != 0 upon successful completion.
185 ChooseValidServer(const afs_cell_handle_p cellHandle,
186 const kas_server_p serverHandle, kas_server_p kasHandle,
190 afs_status_t tst = 0;
193 * Validate input parameters
196 if (kasHandle == NULL) {
197 tst = ADMKASKASHANDLENULL;
198 goto fail_ChooseValidServer;
202 * Only one of the input handle parameters to this function should
205 if ((cellHandle == NULL) && (serverHandle == NULL)) {
206 tst = ADMKASCELLHANDLEANDSERVERHANDLENULL;
207 goto fail_ChooseValidServer;
210 if ((cellHandle != NULL) && (serverHandle != NULL)) {
211 tst = ADMKASCELLHANDLEANDSERVERHANDLENOTNULL;
212 goto fail_ChooseValidServer;
216 * Validate the non-NULL handle
219 if (cellHandle != NULL) {
220 if (IsValidCellHandle(cellHandle, &tst)) {
221 kasHandle->servers = cellHandle->kas;
222 kasHandle->cell = cellHandle->working_cell;
224 goto fail_ChooseValidServer;
227 if (IsValidServerHandle(serverHandle, &tst)) {
228 kasHandle->servers = serverHandle->servers;
229 kasHandle->cell = serverHandle->cell;
231 goto fail_ChooseValidServer;
235 kasHandle->begin_magic = BEGIN_MAGIC;
236 kasHandle->end_magic = END_MAGIC;
237 kasHandle->is_valid = 1;
240 fail_ChooseValidServer:
250 kaentryinfo_to_kas_principalEntry_t(struct kaentryinfo *from,
251 kas_principalEntry_p to, afs_status_p st)
254 afs_status_t tst = 0;
256 unsigned char misc_stuff[4];
259 tst = ADMKASFROMNULL;
260 goto fail_kaentryinfo_to_kas_principalEntry_t;
265 goto fail_kaentryinfo_to_kas_principalEntry_t;
268 if (from->flags & KAFADMIN) {
269 to->adminSetting = KAS_ADMIN;
271 to->adminSetting = NO_KAS_ADMIN;
274 if (from->flags & KAFNOTGS) {
275 to->tgsSetting = NO_TGS;
277 to->tgsSetting = TGS;
280 if (from->flags & KAFNOSEAL) {
281 to->encSetting = NO_ENCRYPT;
283 to->encSetting = ENCRYPT;
286 if (from->flags & KAFNOCPW) {
287 to->cpwSetting = NO_CHANGE_PASSWORD;
289 to->cpwSetting = CHANGE_PASSWORD;
292 reuse = (short)from->reserved3;
294 to->rpwSetting = REUSE_PASSWORD;
296 to->rpwSetting = NO_REUSE_PASSWORD;
300 if (from->user_expiration == NEVERDATE) {
301 to->userExpiration = 0;
303 to->userExpiration = from->user_expiration;
306 to->lastModTime = from->modification_time;
307 strcpy(to->lastModPrincipal.principal, from->modification_user.name);
308 strcpy(to->lastModPrincipal.instance, from->modification_user.instance);
309 to->lastChangePasswordTime = from->change_password_time;
310 to->maxTicketLifetime = from->max_ticket_lifetime;
311 to->keyVersion = from->key_version;
312 memcpy(&to->key, &from->key, sizeof(to->key));
313 to->keyCheckSum = from->keyCheckSum;
315 unpack_long(from->misc_auth_bytes, misc_stuff);
316 to->daysToPasswordExpire = misc_stuff[0];
317 to->failLoginCount = misc_stuff[2];
318 to->lockTime = misc_stuff[3] << 9;
321 fail_kaentryinfo_to_kas_principalEntry_t:
330 * kas_ServerOpen - open a handle to a set of kaserver's.
334 * IN cellHandle - a previously opened cellHandle that corresponds
335 * to the cell where the server(s) live.
337 * IN serverList - a NULL terminated list (a la argv) of server's that
340 * OUT serverHandleP - a pointer to a void pointer that upon successful
341 * completion contains serverHandle that can be used in other kas functions.
345 * No locks are obtained or released by this function
349 * Returns != 0 upon successful completion.
353 * This function make some assumptions about the afsconf_cell used by
354 * ka_AuthSpecificServersConn (since I just wrote ka_AuthSpecificServersConn).
355 * It only fills in the fields that are required.
357 * Also we assume that the servers listed are members of the cell in
358 * cellHandle without verifying that this is in fact the case. kas itself
359 * always assumes that the -servers parameter lists servers in the current
360 * cell without verifying, so I am no worse than the current
361 * implementation. In fact I'm actually a little more flexible since you
362 * can actually use my serverList to play with servers in another cell.
363 * You can't do that with kas. For certain functions in kas the same
364 * cell assumption can cause things to fail (the ka_StringToKey function in
369 kas_ServerOpen(const void *cellHandle, const char **serverList,
370 void **serverHandleP, afs_status_p st)
373 afs_status_t tst = 0;
374 afs_cell_handle_p c_handle = (afs_cell_handle_p) cellHandle;
375 int server_count = 0, server_addr;
376 struct afsconf_cell server_info;
377 kas_server_p k_handle = (kas_server_p) malloc(sizeof(kas_server_t));
380 * Validate input parameters
383 if (c_handle == NULL) {
384 tst = ADMCLIENTCELLHANDLENULL;
385 goto fail_kas_ServerOpen;
388 if (c_handle->kas_valid == 0) {
389 tst = ADMCLIENTCELLKASINVALID;
390 goto fail_kas_ServerOpen;
393 if (serverList == NULL) {
394 tst = ADMKASSERVERLISTNULL;
395 goto fail_kas_ServerOpen;
398 if (serverHandleP == NULL) {
399 tst = ADMKASSERVERHANDLEPNULL;
400 goto fail_kas_ServerOpen;
403 if (k_handle == NULL) {
405 goto fail_kas_ServerOpen;
408 k_handle->begin_magic = BEGIN_MAGIC;
409 k_handle->end_magic = END_MAGIC;
410 k_handle->is_valid = 0;
411 k_handle->servers = NULL;
414 * Convert serverList to numeric addresses
417 for (server_count = 0; serverList[server_count] != NULL; server_count++) {
418 if (server_count >= MAXHOSTSPERCELL) {
419 tst = ADMKASSERVERLISTTOOLONG;
420 goto fail_kas_ServerOpen;
422 if (util_AdminServerAddressGetFromName
423 (serverList[server_count], &server_addr, &tst)) {
424 server_info.hostAddr[server_count].sin_addr.s_addr =
426 server_info.hostAddr[server_count].sin_port =
427 htons(AFSCONF_KAUTHPORT);
429 goto fail_kas_ServerOpen;
433 if (server_count == 0) {
434 tst = ADMKASSERVERLISTEMPTY;
435 goto fail_kas_ServerOpen;
439 * Get a ubik_client handle for the specified servers
441 server_info.numServers = server_count;
444 ka_AuthSpecificServersConn(KA_MAINTENANCE_SERVICE,
445 &c_handle->tokens->kas_token,
446 &server_info, &k_handle->servers))) {
447 k_handle->is_valid = 1;
448 k_handle->cell = c_handle->working_cell;
449 *serverHandleP = (void *)k_handle;
451 goto fail_kas_ServerOpen;
457 if ((rc == 0) && (k_handle != NULL)) {
468 * kas_ServerClose - close a serverHandle.
472 * IN serverHandle - a serverHandle previously returned by kas_ServerOpen.
476 * No locks are obtained or released by this function
480 * Returns != 0 upon successful completion.
484 kas_ServerClose(const void *serverHandle, afs_status_p st)
487 afs_status_t tst = 0;
488 kas_server_p k_handle = (kas_server_p) serverHandle;
490 if (!IsValidServerHandle(k_handle, &tst)) {
491 goto fail_kas_ServerClose;
494 tst = ubik_ClientDestroy(k_handle->servers);
496 goto fail_kas_ServerClose;
499 k_handle->is_valid = 0;
503 fail_kas_ServerClose:
512 * kas_PrincipalCreate - create a new principal.
516 * IN cellHandle - a cellHandle previously returned by afsclient_CellOpen.
518 * IN serverHandle - a serverHandle previously returned by kas_ServerOpen.
520 * IN who - a kas_identity_p containing the identity of the new principal
523 * IN password - the new principal's initial password.
527 * No locks are obtained or released by this function
531 * Returns != 0 upon successful completion.
535 kas_PrincipalCreate(const void *cellHandle, const void *serverHandle,
536 const kas_identity_p who, const char *password,
540 afs_status_t tst = 0;
541 afs_cell_handle_p c_handle = (afs_cell_handle_p) cellHandle;
542 kas_server_p k_handle = (kas_server_p) serverHandle;
543 kas_server_t kaserver;
544 struct kas_encryptionKey key;
547 * Validate input arguments and make rpc.
552 goto fail_kas_PrincipalCreate;
555 if (password == NULL) {
556 tst = ADMKASPASSWORDNULL;
557 goto fail_kas_PrincipalCreate;
560 if (!ChooseValidServer(c_handle, k_handle, &kaserver, &tst)) {
561 goto fail_kas_PrincipalCreate;
564 if (!kas_StringToKey(kaserver.cell, password, &key, &tst)) {
565 goto fail_kas_PrincipalCreate;
569 ubik_Call(KAM_CreateUser, kaserver.servers, 0, who->principal,
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.
607 kas_PrincipalDelete(const void *cellHandle, const void *serverHandle,
608 const kas_identity_p who, afs_status_p st)
611 afs_status_t tst = 0;
612 afs_cell_handle_p c_handle = (afs_cell_handle_p) cellHandle;
613 kas_server_p k_handle = (kas_server_p) serverHandle;
614 kas_server_t kaserver;
617 * Validate input arguments and make rpc.
622 goto fail_kas_PrincipalDelete;
625 if (!ChooseValidServer(c_handle, k_handle, &kaserver, &tst)) {
626 goto fail_kas_PrincipalDelete;
629 ubik_Call(KAM_DeleteUser, kaserver.servers, 0, who->principal,
632 goto fail_kas_PrincipalDelete;
636 fail_kas_PrincipalDelete:
645 * GetPrincipalLockStatus - get the lock status of a principal.
649 * IN kaserver - a valid kaserver handle previously returned by
652 * IN who - a kas_identity_p containing the identity of the principal
655 * OUT lockedUntil - the remaining number of seconds the principal is locked.
659 * No locks are obtained or released by this function
663 * Returns != 0 upon successful completion.
667 GetPrincipalLockStatus(const kas_server_p kaserver, const kas_identity_p who,
668 unsigned int *lockedUntil, afs_status_p st)
671 afs_status_t tst = 0;
677 * Validate input arguments and make rpc.
680 if (kaserver == NULL) {
681 tst = ADMKASKASERVERNULL;
682 goto fail_GetPrincipalLockStatus;
687 goto fail_GetPrincipalLockStatus;
690 if (lockedUntil == NULL) {
691 tst = ADMKASLOCKEDUNTILNULL;
692 goto fail_GetPrincipalLockStatus;
696 * Unlike every other kas rpc we make here, the lock/unlock rpc's
697 * aren't ubik based. So instead of calling ubik_Call, we use
698 * ubik_CallIter. ubik_CallIter steps through the list of hosts
699 * in the ubik_client and calls them one at a time. Since there's
700 * no synchronization of this data across the servers we have to
701 * manually keep track of the shortest time to unlock the user ourselves.
703 * The original inspiration for this function is ka_islocked
704 * in admin_tools.c. I think that function is totally bogus so I'm
707 * This function should contact all the kaservers and request the lock
708 * status of the principal. If any of the servers say the principal is
709 * unlocked, we report it as unlocked. If all the servers say the
710 * principal is locked, we find the server with the shortest lock time
711 * remaining on the principal and return that time.
713 * This is different than kas, but I think kas is buggy.
720 ubik_CallIter(KAM_LockStatus, kaserver->servers, UPUBIKONLY,
721 &count, who->principal, who->instance, &locked, 0,
725 if ((locked < *lockedUntil) || !once) {
726 *lockedUntil = locked;
731 } while ((tst != UNOSERVERS) && (locked != 0));
734 * Check to see if any server reported this principal unlocked.
737 if ((tst == 0) && (locked == 0)) {
740 if ((tst == 0) || (tst == UNOSERVERS)) {
744 fail_GetPrincipalLockStatus:
753 * kas_PrincipalGet - retrieve information about a single principal.
757 * IN cellHandle - a cellHandle previously returned by afsclient_CellOpen.
759 * IN serverHandle - a serverHandle previously returned by kas_ServerOpen.
761 * IN who - a kas_identity_p containing the identity of the principal
764 * OUT principal - upon successful completion contains information
769 * No locks are obtained or released by this function
773 * Returns != 0 upon successful completion.
777 kas_PrincipalGet(const void *cellHandle, const void *serverHandle,
778 const kas_identity_p who, kas_principalEntry_p principal,
782 afs_status_t tst = 0;
783 afs_cell_handle_p c_handle = (afs_cell_handle_p) cellHandle;
784 kas_server_p k_handle = (kas_server_p) serverHandle;
785 kas_server_t kaserver;
786 struct kaentryinfo entry;
789 * Validate input arguments and make rpc.
794 goto fail_kas_PrincipalGet;
797 if (principal == NULL) {
798 tst = ADMKASPRINCIPALNULL;
799 goto fail_kas_PrincipalGet;
802 if (!ChooseValidServer(c_handle, k_handle, &kaserver, &tst)) {
803 goto fail_kas_PrincipalGet;
807 ubik_Call(KAM_GetEntry, kaserver.servers, 0, who->principal,
808 who->instance, KAMAJORVERSION, &entry);
810 goto fail_kas_PrincipalGet;
814 * copy the kaentryinfo structure to our kas_principalEntry_t
817 if (!kaentryinfo_to_kas_principalEntry_t(&entry, principal, &tst)) {
818 goto fail_kas_PrincipalGet;
822 fail_kas_PrincipalGet:
830 typedef struct principal_get {
834 kas_server_t kaserver;
835 kas_identity_t principal[CACHED_ITEMS];
836 } principal_get_t, *principal_get_p;
839 DeletePrincipalSpecificData(void *rpc_specific, afs_status_p st)
842 afs_status_t tst = 0;
843 principal_get_p prin = (principal_get_p) rpc_specific;
845 prin->kaserver.is_valid = 0;
855 GetPrincipalRPC(void *rpc_specific, int slot, int *last_item,
856 int *last_item_contains_data, afs_status_p st)
859 afs_status_t tst = 0;
860 principal_get_p prin = (principal_get_p) rpc_specific;
863 ubik_Call(KAM_ListEntry, prin->kaserver.servers, 0, prin->current,
864 &prin->next, &prin->count, &prin->principal[slot]);
866 prin->current = prin->next;
867 if (prin->next == 0) {
869 *last_item_contains_data = 0;
881 GetPrincipalFromCache(void *rpc_specific, int slot, void *dest,
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.
922 kas_PrincipalGetBegin(const void *cellHandle, const void *serverHandle,
923 void **iterationIdP, afs_status_p st)
926 afs_status_t tst = 0;
927 afs_cell_handle_p c_handle = (afs_cell_handle_p) cellHandle;
928 kas_server_p k_handle = (kas_server_p) serverHandle;
929 afs_admin_iterator_p iter =
930 (afs_admin_iterator_p) malloc(sizeof(afs_admin_iterator_t));
931 principal_get_p principal =
932 (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;
965 (iter, (void *)principal, GetPrincipalRPC, GetPrincipalFromCache,
966 NULL, 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.
1009 kas_PrincipalGetNext(const void *iterationId, kas_identity_p who,
1013 afs_status_t tst = 0;
1014 afs_admin_iterator_p iter = (afs_admin_iterator_p) iterationId;
1017 * Validate arguments
1021 tst = ADMKASWHONULL;
1022 goto fail_kas_PrincipalGetNext;
1026 tst = ADMITERATORNULL;
1027 goto fail_kas_PrincipalGetNext;
1030 rc = IteratorNext(iter, (void *)who, &tst);
1032 fail_kas_PrincipalGetNext:
1041 * kas_PrincipalGetDone - finish using a principal iterator
1045 * IN iterationId - an iterator previously returned by kas_PrincipalGetBegin
1049 * No locks are held by this function.
1053 * Returns != 0 upon successful completion.
1057 * It is the user's responsibility to make sure kas_PrincipalGetDone
1058 * is called only once for each iterator.
1062 kas_PrincipalGetDone(const void *iterationIdP, afs_status_p st)
1065 afs_status_t tst = 0;
1066 afs_admin_iterator_p iter = (afs_admin_iterator_p) iterationIdP;
1073 tst = ADMITERATORNULL;
1074 goto fail_kas_PrincipalGetDone;
1077 rc = IteratorDone(iter, &tst);
1079 fail_kas_PrincipalGetDone:
1088 * kas_PrincipalKeySet - set a principal's password to a known value.
1092 * IN cellHandle - a cellHandle previously returned by afsclient_CellOpen.
1094 * IN serverHandle - a serverHandle previously returned by kas_ServerOpen.
1096 * IN who - the principal for whom the password is being set.
1098 * IN keyVersion - the version number of the new key.
1100 * IN key - the new password.
1104 * No locks are held by this function.
1108 * Returns != 0 upon successful completion.
1112 kas_PrincipalKeySet(const void *cellHandle, const void *serverHandle,
1113 const kas_identity_p who, int keyVersion,
1114 const kas_encryptionKey_p key, afs_status_p st)
1117 afs_status_t tst = 0;
1118 afs_cell_handle_p c_handle = (afs_cell_handle_p) cellHandle;
1119 kas_server_p k_handle = (kas_server_p) serverHandle;
1120 kas_server_t kaserver;
1123 * Validate input arguments and make rpc.
1127 tst = ADMKASWHONULL;
1128 goto fail_kas_PrincipalKeySet;
1132 tst = ADMKASKEYNULL;
1133 goto fail_kas_PrincipalKeySet;
1136 if (!ChooseValidServer(c_handle, k_handle, &kaserver, &tst)) {
1137 goto fail_kas_PrincipalKeySet;
1141 ubik_Call(KAM_SetPassword, kaserver.servers, 0, who->principal,
1142 who->instance, keyVersion, *key);
1144 goto fail_kas_PrincipalKeySet;
1147 /* If we failed to fail we must have succeeded */
1150 fail_kas_PrincipalKeySet:
1159 * kas_PrincipalLockStatusGet - determine a principal's lock status.
1163 * IN cellHandle - a cellHandle previously returned by afsclient_CellOpen.
1165 * IN serverHandle - a serverHandle previously returned by kas_ServerOpen.
1167 * IN who - the principal whose lock status is being checked.
1169 * OUT lock_end_timeP - the number of seconds until the principal is unlocked.
1170 * If 0 => user is unlocked.
1174 * No locks are held by this function.
1178 * Returns != 0 upon successful completion.
1182 * See the comments in GetPrincipalLockStatus regarding how the locking data
1183 * is kept INconsistently between servers.
1187 kas_PrincipalLockStatusGet(const void *cellHandle, const void *serverHandle,
1188 const kas_identity_p who,
1189 unsigned int *lock_end_timeP, afs_status_p st)
1192 afs_status_t tst = 0;
1193 afs_cell_handle_p c_handle = (afs_cell_handle_p) cellHandle;
1194 kas_server_p k_handle = (kas_server_p) serverHandle;
1195 kas_server_t kaserver;
1198 * Validate input arguments and make rpc.
1202 tst = ADMKASWHONULL;
1203 goto fail_kas_PrincipalLockStatusGet;
1206 if (lock_end_timeP == NULL) {
1207 tst = ADMKASLOCKENDTIMEPNULL;
1208 goto fail_kas_PrincipalLockStatusGet;
1211 if (!ChooseValidServer(c_handle, k_handle, &kaserver, &tst)) {
1212 goto fail_kas_PrincipalLockStatusGet;
1215 rc = GetPrincipalLockStatus(&kaserver, who, lock_end_timeP, &tst);
1217 fail_kas_PrincipalLockStatusGet:
1226 * kas_PrincipalUnlock - unlock a principal.
1230 * IN cellHandle - a cellHandle previously returned by afsclient_CellOpen.
1232 * IN serverHandle - a serverHandle previously returned by kas_ServerOpen.
1234 * IN who - the principal who is being unlocked.
1238 * No locks are held by this function.
1242 * Returns != 0 upon successful completion.
1246 * See the comments in GetPrincipalLockStatus regarding how the locking data
1247 * is kept INconsistently between servers.
1251 kas_PrincipalUnlock(const void *cellHandle, const void *serverHandle,
1252 const kas_identity_p who, afs_status_p st)
1255 afs_status_t tst = 0;
1256 afs_cell_handle_p c_handle = (afs_cell_handle_p) cellHandle;
1257 kas_server_p k_handle = (kas_server_p) serverHandle;
1258 kas_server_t kaserver;
1260 afs_status_t save_tst = 0;
1263 * Validate input arguments and make rpc.
1267 tst = ADMKASWHONULL;
1268 goto fail_kas_PrincipalUnlock;
1271 if (!ChooseValidServer(c_handle, k_handle, &kaserver, &tst)) {
1272 goto fail_kas_PrincipalUnlock;
1277 ubik_CallIter(KAM_Unlock, kaserver.servers, 0, &count,
1278 who->principal, who->instance, 0, 0, 0, 0);
1279 if (tst && (tst != UNOSERVERS)) {
1280 if (save_tst == 0) {
1281 save_tst = tst; /* save the first failure */
1284 } while (tst != UNOSERVERS);
1286 if ((tst == 0) || (tst == UNOSERVERS)) {
1290 fail_kas_PrincipalUnlock:
1299 getPrincipalFlags(const void *cellHandle, const void *serverHandle,
1300 const kas_identity_p who, afs_int32 * cur_flags,
1304 afs_status_t tst = 0;
1305 afs_cell_handle_p c_handle = (afs_cell_handle_p) cellHandle;
1306 kas_server_p k_handle = (kas_server_p) serverHandle;
1307 kas_server_t kaserver;
1308 struct kaentryinfo tentry;
1310 if (!ChooseValidServer(c_handle, k_handle, &kaserver, &tst)) {
1311 goto fail_getPrincipalFlags;
1315 ubik_Call(KAM_GetEntry, kaserver.servers, 0, who->principal,
1316 who->instance, KAMAJORVERSION, &tentry);
1318 *cur_flags = tentry.flags;
1322 fail_getPrincipalFlags:
1331 * kas_PrincipalFieldsSet - modify an existing principal.
1335 * IN cellHandle - a cellHandle previously returned by afsclient_CellOpen.
1337 * IN serverHandle - a serverHandle previously returned by kas_ServerOpen.
1339 * IN who - the principal who is being modified.
1341 * IN isAdmin - the admin status of the principal.
1343 * IN grantTickets - should the TGS issue tickets for the principal.
1345 * IN canEncrypt - should the TGS allow the use of encryption via the
1348 * IN canChangePassword - should the principal be allowed to change their
1351 * IN expirationDate - the date when the principal will expire.
1353 * IN maxTicketLifetime - the maximum lifetime of a ticket issued for
1356 * IN passwordExpires - the maximum number of days a particular
1357 * password can be used. The limit is 255, 0 => no expiration.
1359 * IN passwordReuse - can a password be reused by this principal.
1361 * IN failedPasswordAttempts - number of failed login attempts before
1362 * a principal is locked. The limit is 255, 0 => no limit.
1364 * IN failedPasswordLockTime - the number of seconds a principal is
1365 * locked once failedPasswordAttempts is reached. Some bizarre rounding
1366 * occurs for this value, see kas for more details.
1370 * No locks are held by this function.
1374 * Returns != 0 upon successful completion.
1378 * See the comments in GetPrincipalLockStatus regarding how the locking data
1379 * is kept INconsistently between servers.
1383 kas_PrincipalFieldsSet(const void *cellHandle, const void *serverHandle,
1384 const kas_identity_p who, const kas_admin_p isAdmin,
1385 const kas_tgs_p grantTickets,
1386 const kas_enc_p canEncrypt,
1387 const kas_cpw_p canChangePassword,
1388 const unsigned int *expirationDate,
1389 const unsigned int *maxTicketLifetime,
1390 const unsigned int *passwordExpires,
1391 const kas_rpw_p passwordReuse,
1392 const unsigned int *failedPasswordAttempts,
1393 const unsigned int *failedPasswordLockTime,
1397 afs_status_t tst = 0;
1398 afs_cell_handle_p c_handle = (afs_cell_handle_p) cellHandle;
1399 kas_server_p k_handle = (kas_server_p) serverHandle;
1400 kas_server_t kaserver;
1401 afs_int32 flags = 0;
1402 Date expiration = 0;
1403 afs_int32 lifetime = 0;
1405 char spare_bytes[4] = { 0, 0, 0, 0 };
1406 int somethings_changing = 0;
1409 * Validate input arguments.
1413 tst = ADMKASWHONULL;
1414 goto fail_kas_PrincipalFieldsSet;
1418 * set flags based upon input
1420 * If we're changing the flags, we need to get the current value of
1421 * the flags first and then make the changes
1424 if ((isAdmin != NULL) || (grantTickets != NULL) || (canEncrypt != NULL)
1425 || (canChangePassword != NULL)) {
1426 if (!getPrincipalFlags(cellHandle, serverHandle, who, &flags, &tst)) {
1427 goto fail_kas_PrincipalFieldsSet;
1431 if (isAdmin != NULL) {
1432 somethings_changing = 1;
1433 if (*isAdmin == KAS_ADMIN) {
1440 if (grantTickets != NULL) {
1441 somethings_changing = 1;
1442 if (*grantTickets == NO_TGS) {
1449 if (canEncrypt != NULL) {
1450 somethings_changing = 1;
1451 if (*canEncrypt == NO_ENCRYPT) {
1454 flags &= ~KAFNOSEAL;
1458 if (canChangePassword != NULL) {
1459 somethings_changing = 1;
1460 if (*canChangePassword == NO_CHANGE_PASSWORD) {
1467 flags = (flags & KAF_SETTABLE_FLAGS) | KAFNORMAL;
1469 if (expirationDate != NULL) {
1470 somethings_changing = 1;
1471 expiration = *expirationDate;
1474 if (maxTicketLifetime != NULL) {
1475 somethings_changing = 1;
1476 lifetime = *maxTicketLifetime;
1479 if (passwordExpires != NULL) {
1480 if (*passwordExpires > 255) {
1481 tst = ADMKASPASSWORDEXPIRESTOOBIG;
1482 goto fail_kas_PrincipalFieldsSet;
1484 somethings_changing = 1;
1485 spare_bytes[0] = *passwordExpires + 1;
1488 if (passwordReuse != NULL) {
1489 somethings_changing = 1;
1490 if (*passwordReuse == REUSE_PASSWORD) {
1491 spare_bytes[1] = KA_REUSEPW;
1493 spare_bytes[1] = KA_NOREUSEPW;
1497 if (failedPasswordAttempts != NULL) {
1498 if (*failedPasswordAttempts > 255) {
1499 tst = ADMKASFAILEDPASSWORDATTEMPTSTOOBIG;
1500 goto fail_kas_PrincipalFieldsSet;
1502 somethings_changing = 1;
1503 spare_bytes[2] = *failedPasswordAttempts + 1;
1506 if (failedPasswordLockTime != NULL) {
1507 if (*failedPasswordLockTime > 36 * 60 * 60) {
1508 tst = ADMKASFAILEDPASSWORDLOCKTIME;
1509 goto fail_kas_PrincipalFieldsSet;
1511 somethings_changing = 1;
1512 spare_bytes[3] = ((*failedPasswordLockTime + 511) >> 9) + 1;
1515 was_spare = pack_long(spare_bytes);
1517 if (somethings_changing) {
1518 if (!ChooseValidServer(c_handle, k_handle, &kaserver, &tst)) {
1519 goto fail_kas_PrincipalFieldsSet;
1522 ubik_Call(KAM_SetFields, kaserver.servers, 0, who->principal,
1523 who->instance, flags, expiration, lifetime, -1,
1529 tst = ADMKASPRINCIPALFIELDSNOCHANGE;
1532 fail_kas_PrincipalFieldsSet:
1541 * kas_ServerStatsGet - get server statistics.
1545 * IN cellHandle - a cellHandle previously returned by afsclient_CellOpen.
1547 * IN serverHandle - a serverHandle previously returned by kas_ServerOpen.
1549 * OUT stats - the statistics retrieved.
1553 * No locks are held by this function.
1557 * Returns != 0 upon successful completion.
1561 kas_ServerStatsGet(const void *cellHandle, const void *serverHandle,
1562 kas_serverStats_p stats, afs_status_p st)
1565 afs_status_t tst = 0;
1566 afs_cell_handle_p c_handle = (afs_cell_handle_p) cellHandle;
1567 kas_server_p k_handle = (kas_server_p) serverHandle;
1568 kas_server_t kaserver;
1575 * Validate input arguments and make rpc.
1578 if (stats == NULL) {
1579 tst = ADMKASSTATSNULL;
1580 goto fail_kas_ServerStatsGet;
1583 if (!ChooseValidServer(c_handle, k_handle, &kaserver, &tst)) {
1584 goto fail_kas_ServerStatsGet;
1588 ubik_Call(KAM_GetStats, kaserver.servers, 0, KAMAJORVERSION, &admins,
1589 &statics, &dynamics);
1591 goto fail_kas_ServerStatsGet;
1594 stats->allocations = statics.allocs;
1595 stats->frees = statics.frees;
1596 stats->changePasswordRequests = statics.cpws;
1597 stats->adminAccounts = admins;
1598 stats->host = dynamics.host;
1599 stats->serverStartTime = dynamics.start_time;
1600 stats->hashTableUtilization = dynamics.hashTableUtilization;
1602 i = sizeof(kas_serverProcStats_t);
1603 memcpy(&stats->authenticate, &dynamics.Authenticate, i);
1604 memcpy(&stats->changePassword, &dynamics.ChangePassword, i);
1605 memcpy(&stats->getTicket, &dynamics.GetTicket, i);
1606 memcpy(&stats->createUser, &dynamics.CreateUser, i);
1607 memcpy(&stats->setPassword, &dynamics.SetPassword, i);
1608 memcpy(&stats->setFields, &dynamics.SetFields, i);
1609 memcpy(&stats->deleteUser, &dynamics.DeleteUser, i);
1610 memcpy(&stats->getEntry, &dynamics.GetEntry, i);
1611 memcpy(&stats->listEntry, &dynamics.ListEntry, i);
1612 memcpy(&stats->getStats, &dynamics.GetStats, i);
1613 memcpy(&stats->getPassword, &dynamics.GetPassword, i);
1614 memcpy(&stats->getRandomKey, &dynamics.GetRandomKey, i);
1615 memcpy(&stats->debug, &dynamics.Debug, i);
1616 memcpy(&stats->udpAuthenticate, &dynamics.UAuthenticate, i);
1617 memcpy(&stats->udpGetTicket, &dynamics.UGetTicket, i);
1618 memcpy(&stats->unlock, &dynamics.Unlock, i);
1619 memcpy(&stats->lockStatus, &dynamics.LockStatus, i);
1621 stats->stringChecks = dynamics.string_checks;
1624 fail_kas_ServerStatsGet:
1633 * kas_ServerDebugGet - get server debug info.
1637 * IN cellHandle - a cellHandle previously returned by afsclient_CellOpen.
1639 * IN serverHandle - a serverHandle previously returned by kas_ServerOpen.
1641 * OUT stats - the debug info retrieved.
1645 * No locks are held by this function.
1649 * Returns != 0 upon successful completion.
1653 kas_ServerDebugGet(const void *cellHandle, const void *serverHandle,
1654 kas_serverDebugInfo_p debug, afs_status_p st)
1657 afs_status_t tst = 0;
1658 afs_cell_handle_p c_handle = (afs_cell_handle_p) cellHandle;
1659 kas_server_p k_handle = (kas_server_p) serverHandle;
1660 kas_server_t kaserver;
1661 struct ka_debugInfo info;
1665 * Validate input arguments and make rpc.
1668 if (debug == NULL) {
1669 tst = ADMKASDEBUGNULL;
1670 goto fail_kas_ServerDebugGet;
1673 if (!ChooseValidServer(c_handle, k_handle, &kaserver, &tst)) {
1674 goto fail_kas_ServerDebugGet;
1676 tst = ubik_Call(KAM_Debug, kaserver.servers, 0, KAMAJORVERSION, 0, &info);
1678 goto fail_kas_ServerDebugGet;
1680 debug->host = info.host;
1681 debug->serverStartTime = info.startTime;
1682 debug->currentTime = info.reserved1;
1683 debug->noAuth = info.noAuth;
1684 debug->lastTransaction = info.lastTrans;
1685 strcpy(debug->lastOperation, info.lastOperation);
1686 strcpy(debug->lastPrincipalAuth, info.lastAuth);
1687 strcpy(debug->lastPrincipalUDPAuth, info.lastUAuth);
1688 strcpy(debug->lastPrincipalTGS, info.lastTGS);
1689 strcpy(debug->lastPrincipalUDPTGS, info.lastUTGS);
1690 strcpy(debug->lastPrincipalAdmin, info.lastAdmin);
1691 strcpy(debug->lastServerTGS, info.lastTGSServer);
1692 strcpy(debug->lastServerUDPTGS, info.lastUTGSServer);
1693 debug->nextAutoCheckPointWrite = info.nextAutoCPW;
1694 debug->updatesRemainingBeforeAutoCheckPointWrite = info.updatesRemaining;
1695 debug->dbHeaderRead = info.dbHeaderRead;
1696 debug->dbVersion = info.dbVersion;
1697 debug->dbFreePtr = info.dbFreePtr;
1698 debug->dbEOFPtr = info.dbEofPtr;
1699 debug->dbKvnoPtr = info.dbKvnoPtr;
1700 debug->dbSpecialKeysVersion = info.dbSpecialKeysVersion;
1701 debug->dbHeaderLock = info.cheader_lock;
1702 debug->keyCacheLock = info.keycache_lock;
1703 debug->keyCacheVersion = info.kcVersion;
1704 debug->keyCacheSize = info.kcSize;
1705 debug->keyCacheUsed = info.kcUsed;
1706 for (i = 0; i < info.kcUsed; i++) {
1707 debug->keyCache[i].lastUsed = info.kcInfo[i].used;
1708 debug->keyCache[i].keyVersionNumber = info.kcInfo[i].kvno;
1709 debug->keyCache[i].primary = info.kcInfo[i].primary;
1710 debug->keyCache[i].keyCheckSum = info.kcInfo[i].keycksum;
1711 strcpy(debug->keyCache[i].principal, info.kcInfo[i].principal);
1715 fail_kas_ServerDebugGet:
1724 * kas_ServerRandomKeyGet - get a random key from a server.
1728 * IN cellHandle - a cellHandle previously returned by afsclient_CellOpen.
1730 * IN serverHandle - a serverHandle previously returned by kas_ServerOpen.
1732 * OUT key - a random key.
1736 * No locks are held by this function.
1740 * Returns != 0 upon successful completion.
1744 kas_ServerRandomKeyGet(const void *cellHandle, const void *serverHandle,
1745 kas_encryptionKey_p key, afs_status_p st)
1748 afs_status_t tst = 0;
1749 afs_cell_handle_p c_handle = (afs_cell_handle_p) cellHandle;
1750 kas_server_p k_handle = (kas_server_p) serverHandle;
1751 kas_server_t kaserver;
1754 * Validate input arguments and make rpc.
1758 tst = ADMKASKEYNULL;
1759 goto fail_kas_ServerRandomKeyGet;
1762 if (!ChooseValidServer(c_handle, k_handle, &kaserver, &tst)) {
1763 goto fail_kas_ServerRandomKeyGet;
1766 tst = ubik_Call(KAM_GetRandomKey, kaserver.servers, 0, key);
1768 goto fail_kas_ServerRandomKeyGet;
1772 fail_kas_ServerRandomKeyGet:
1781 * kas_StringToKey - turn a string key into a key.
1785 * IN cellName - the name of the cell where the key will be used.
1787 * IN string - the string to be converted.
1789 * OUT key - the encryption key.
1793 * No locks are held by this function.
1797 * Returns != 0 upon successful completion.
1801 kas_StringToKey(const char *cellName, const char *string,
1802 kas_encryptionKey_p key, afs_status_p st)
1805 afs_status_t tst = 0;
1807 ka_StringToKey(string, cellName, (struct ktc_encryptionKey *)key);
1818 * kas_KeyCheckSum - compute the checksum of an encryption key.
1822 * IN key - the encryption key.
1824 * OUT cksumP - key checksum
1828 * No locks are held by this function.
1832 * Returns != 0 upon successful completion.
1836 kas_KeyCheckSum(const kas_encryptionKey_p key, unsigned int *cksumP,
1840 afs_status_t tst = 0;
1843 if ((tst = ka_KeyCheckSum((char *)key, &cksum32)) == 0) {