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
12 #include "afs_kasAdmin.h"
13 #include "../adminutil/afs_AdminInternal.h"
14 #include <afs/afs_AdminErrors.h>
15 #include <afs/afs_utilAdmin.h>
16 #include <afs/kauth.h>
17 #include <afs/kautils.h>
18 #include <afs/kaport.h>
23 extern int ubik_Call();
24 extern int ubik_Call_New();
25 extern int ubik_CallIter();
30 struct ubik_client *servers;
33 } kas_server_t, *kas_server_p;
36 * IsValidServerHandle - verify the validity of a kas_server_t handle.
40 * IN serverHandle - the handle to be verified.
44 * No locks are obtained or released by this function
48 * Returns != 0 upon successful completion.
51 static int IsValidServerHandle(
52 const kas_server_p serverHandle,
59 * Validate input parameters
62 if (serverHandle == NULL) {
63 tst = ADMKASSERVERHANDLENULL;
64 goto fail_IsValidServerHandle;
67 if ((serverHandle->begin_magic != BEGIN_MAGIC) ||
68 (serverHandle->end_magic != END_MAGIC)) {
69 tst = ADMKASSERVERHANDLEBADMAGIC;
70 goto fail_IsValidServerHandle;
73 if (!serverHandle->is_valid) {
74 tst = ADMKASSERVERHANDLENOTVALID;
75 goto fail_IsValidServerHandle;
78 if (serverHandle->servers == NULL) {
79 tst = ADMKASSERVERHANDLENOSERVERS;
80 goto fail_IsValidServerHandle;
84 fail_IsValidServerHandle:
93 * IsValidCellHandle - verify the validity of a afs_cell_handle_t handle
94 * for doing kas related functions.
98 * IN cellHandle - the handle to be verified.
102 * No locks are obtained or released by this function
106 * Returns != 0 upon successful completion.
109 static int IsValidCellHandle(
110 const afs_cell_handle_p cellHandle,
114 afs_status_t tst = 0;
117 * Validate input parameters
120 if (!CellHandleIsValid((void *) cellHandle, &tst)) {
121 goto fail_IsValidCellHandle;
124 if (!cellHandle->kas_valid) {
125 tst = ADMCLIENTCELLKASINVALID;
126 goto fail_IsValidCellHandle;
129 if (cellHandle->kas == NULL) {
130 tst = ADMCLIENTCELLKASNULL;
131 goto fail_IsValidCellHandle;
135 fail_IsValidCellHandle:
144 * For all kas admin functions that take a cellHandle and a serverHandle,
145 * the intention is that is the cellHandle is not NULL, we should use
146 * it. Otherwise, we use the serverHandle. It is an error for both
147 * of these parameters to be non-NULL.
151 * ChooseValidServer - given a serverHandle and a cellHandle, choose the
152 * one that is non-NULL, validate it, and return a ubik_client structure
157 * IN cellHandle - the cell where kas calls are to be made
159 * IN serverHandle - the group of server(s) that should be used to satisfy
164 * No locks are obtained or released by this function
168 * Returns != 0 upon successful completion.
171 static int ChooseValidServer(
172 const afs_cell_handle_p cellHandle,
173 const kas_server_p serverHandle,
174 kas_server_p kasHandle,
178 afs_status_t tst = 0;
181 * Validate input parameters
184 if (kasHandle == NULL) {
185 tst = ADMKASKASHANDLENULL;
186 goto fail_ChooseValidServer;
190 * Only one of the input handle parameters to this function should
193 if ((cellHandle == NULL) && (serverHandle == NULL)) {
194 tst = ADMKASCELLHANDLEANDSERVERHANDLENULL;
195 goto fail_ChooseValidServer;
198 if ((cellHandle != NULL) && (serverHandle != NULL)) {
199 tst = ADMKASCELLHANDLEANDSERVERHANDLENOTNULL;
200 goto fail_ChooseValidServer;
204 * Validate the non-NULL handle
207 if (cellHandle != NULL) {
208 if (IsValidCellHandle(cellHandle, &tst)) {
209 kasHandle->servers = cellHandle->kas;
210 kasHandle->cell = cellHandle->working_cell;
212 goto fail_ChooseValidServer;
215 if (IsValidServerHandle(serverHandle, &tst)) {
216 kasHandle->servers = serverHandle->servers;
217 kasHandle->cell = serverHandle->cell;
219 goto fail_ChooseValidServer;
223 kasHandle->begin_magic = BEGIN_MAGIC;
224 kasHandle->end_magic = END_MAGIC;
225 kasHandle->is_valid = 1;
228 fail_ChooseValidServer:
237 static int kaentryinfo_to_kas_principalEntry_t(
238 struct kaentryinfo *from,
239 kas_principalEntry_p to,
243 afs_status_t tst = 0;
245 unsigned char misc_stuff[4];
248 tst = ADMKASFROMNULL;
249 goto fail_kaentryinfo_to_kas_principalEntry_t;
254 goto fail_kaentryinfo_to_kas_principalEntry_t;
257 if (from->flags & KAFADMIN) {
258 to->adminSetting = KAS_ADMIN;
260 to->adminSetting = NO_KAS_ADMIN;
263 if (from->flags & KAFNOTGS) {
264 to->tgsSetting = NO_TGS;
266 to->tgsSetting = TGS;
269 if (from->flags & KAFNOSEAL) {
270 to->encSetting = NO_ENCRYPT;
272 to->encSetting = ENCRYPT;
275 if (from->flags & KAFNOCPW) {
276 to->cpwSetting = NO_CHANGE_PASSWORD;
278 to->cpwSetting = CHANGE_PASSWORD;
281 reuse = (short) from->reserved3;
283 to->rpwSetting = REUSE_PASSWORD;
285 to->rpwSetting = NO_REUSE_PASSWORD;
289 if (from->user_expiration == NEVERDATE) {
290 to->userExpiration = 0;
292 to->userExpiration = from->user_expiration;
295 to->lastModTime = from->modification_time;
296 strcpy(to->lastModPrincipal.principal, from->modification_user.name);
297 strcpy(to->lastModPrincipal.instance, from->modification_user.instance);
298 to->lastChangePasswordTime = from->change_password_time;
299 to->maxTicketLifetime = from->max_ticket_lifetime;
300 to->keyVersion = from->key_version;
301 memcpy(&to->key, &from->key, sizeof(to->key));
302 to->keyCheckSum = from->keyCheckSum;
304 unpack_long(from->misc_auth_bytes, misc_stuff);
305 to->daysToPasswordExpire = misc_stuff[0];
306 to->failLoginCount = misc_stuff[2];
307 to->lockTime = misc_stuff[3] << 9;
310 fail_kaentryinfo_to_kas_principalEntry_t:
319 * kas_ServerOpen - open a handle to a set of kaserver's.
323 * IN cellHandle - a previously opened cellHandle that corresponds
324 * to the cell where the server(s) live.
326 * IN serverList - a NULL terminated list (a la argv) of server's that
329 * OUT serverHandleP - a pointer to a void pointer that upon successful
330 * completion contains serverHandle that can be used in other kas functions.
334 * No locks are obtained or released by this function
338 * Returns != 0 upon successful completion.
342 * This function make some assumptions about the afsconf_cell used by
343 * ka_AuthSpecificServersConn (since I just wrote ka_AuthSpecificServersConn).
344 * It only fills in the fields that are required.
346 * Also we assume that the servers listed are members of the cell in
347 * cellHandle without verifying that this is in fact the case. kas itself
348 * always assumes that the -servers parameter lists servers in the current
349 * cell without verifying, so I am no worse than the current
350 * implementation. In fact I'm actually a little more flexible since you
351 * can actually use my serverList to play with servers in another cell.
352 * You can't do that with kas. For certain functions in kas the same
353 * cell assumption can cause things to fail (the ka_StringToKey function in
357 int ADMINAPI kas_ServerOpen(
358 const void *cellHandle,
359 const char **serverList,
360 void **serverHandleP,
364 afs_status_t tst = 0;
365 afs_cell_handle_p c_handle = (afs_cell_handle_p) cellHandle;
366 int server_count=0, server_addr;
367 struct afsconf_cell server_info;
368 kas_server_p k_handle = (kas_server_p) malloc (sizeof(kas_server_t));
371 * Validate input parameters
374 if (c_handle == NULL) {
375 tst = ADMCLIENTCELLHANDLENULL;
376 goto fail_kas_ServerOpen;
379 if (c_handle->kas_valid == 0) {
380 tst = ADMCLIENTCELLKASINVALID;
381 goto fail_kas_ServerOpen;
384 if (serverList == NULL) {
385 tst = ADMKASSERVERLISTNULL;
386 goto fail_kas_ServerOpen;
389 if (serverHandleP == NULL) {
390 tst = ADMKASSERVERHANDLEPNULL;
391 goto fail_kas_ServerOpen;
394 if (k_handle == NULL) {
396 goto fail_kas_ServerOpen;
399 k_handle->begin_magic = BEGIN_MAGIC;
400 k_handle->end_magic = END_MAGIC;
401 k_handle->is_valid = 0;
402 k_handle->servers = NULL;
405 * Convert serverList to numeric addresses
408 for(server_count=0; serverList[server_count] != NULL; server_count++) {
409 if (server_count >= MAXHOSTSPERCELL) {
410 tst = ADMKASSERVERLISTTOOLONG;
411 goto fail_kas_ServerOpen;
413 if (util_AdminServerAddressGetFromName(serverList[server_count],&server_addr,&tst)) {
414 server_info.hostAddr[server_count].sin_addr.s_addr = htonl(server_addr);
415 server_info.hostAddr[server_count].sin_port = htons(AFSCONF_KAUTHPORT);
417 goto fail_kas_ServerOpen;
421 if (server_count == 0) {
422 tst = ADMKASSERVERLISTEMPTY;
423 goto fail_kas_ServerOpen;
427 * Get a ubik_client handle for the specified servers
429 server_info.numServers = server_count;
430 if (!(tst = ka_AuthSpecificServersConn(KA_MAINTENANCE_SERVICE, &c_handle->tokens->kas_token, &server_info, &k_handle->servers))) {
431 k_handle->is_valid = 1;
432 k_handle->cell = c_handle->working_cell;
433 *serverHandleP = (void *) k_handle;
435 goto fail_kas_ServerOpen;
441 if ((rc == 0) && (k_handle != NULL)) {
452 * kas_ServerClose - close a serverHandle.
456 * IN serverHandle - a serverHandle previously returned by kas_ServerOpen.
460 * No locks are obtained or released by this function
464 * Returns != 0 upon successful completion.
467 int ADMINAPI kas_ServerClose(
468 const void *serverHandle,
472 afs_status_t tst = 0;
473 kas_server_p k_handle = (kas_server_p) serverHandle;
475 if (!IsValidServerHandle(k_handle, &tst)) {
476 goto fail_kas_ServerClose;
479 tst = ubik_ClientDestroy(k_handle->servers);
481 goto fail_kas_ServerClose;
484 k_handle->is_valid = 0;
488 fail_kas_ServerClose:
497 * kas_PrincipalCreate - create a new principal.
501 * IN cellHandle - a cellHandle previously returned by afsclient_CellOpen.
503 * IN serverHandle - a serverHandle previously returned by kas_ServerOpen.
505 * IN who - a kas_identity_p containing the identity of the new principal
508 * IN password - the new principal's initial password.
512 * No locks are obtained or released by this function
516 * Returns != 0 upon successful completion.
519 int ADMINAPI kas_PrincipalCreate(
520 const void *cellHandle,
521 const void *serverHandle,
522 const kas_identity_p who,
523 const char *password,
527 afs_status_t tst = 0;
528 afs_cell_handle_p c_handle = (afs_cell_handle_p) cellHandle;
529 kas_server_p k_handle = (kas_server_p) serverHandle;
530 kas_server_t kaserver;
531 struct kas_encryptionKey key;
534 * Validate input arguments and make rpc.
539 goto fail_kas_PrincipalCreate;
542 if (password == NULL) {
543 tst = ADMKASPASSWORDNULL;
544 goto fail_kas_PrincipalCreate;
547 if (!ChooseValidServer(c_handle, k_handle, &kaserver, &tst)) {
548 goto fail_kas_PrincipalCreate;
551 if (!kas_StringToKey(kaserver.cell, password, &key, &tst)) {
552 goto fail_kas_PrincipalCreate;
555 tst = ubik_Call(KAM_CreateUser, kaserver.servers, 0,
556 who->principal, who->instance, key);
558 goto fail_kas_PrincipalCreate;
563 fail_kas_PrincipalCreate:
572 * kas_PrincipalDelete - delete an existing principal.
576 * IN cellHandle - a cellHandle previously returned by afsclient_CellOpen.
578 * IN serverHandle - a serverHandle previously returned by kas_ServerOpen.
580 * IN who - a kas_identity_p containing the identity of the principal
585 * No locks are obtained or released by this function
589 * Returns != 0 upon successful completion.
592 int ADMINAPI kas_PrincipalDelete(
593 const void *cellHandle,
594 const void *serverHandle,
595 const kas_identity_p who,
599 afs_status_t tst = 0;
600 afs_cell_handle_p c_handle = (afs_cell_handle_p) cellHandle;
601 kas_server_p k_handle = (kas_server_p) serverHandle;
602 kas_server_t kaserver;
605 * Validate input arguments and make rpc.
610 goto fail_kas_PrincipalDelete;
613 if (!ChooseValidServer(c_handle, k_handle, &kaserver, &tst)) {
614 goto fail_kas_PrincipalDelete;
616 tst = ubik_Call(KAM_DeleteUser, kaserver.servers, 0,
617 who->principal, who->instance);
619 goto fail_kas_PrincipalDelete;
623 fail_kas_PrincipalDelete:
632 * GetPrincipalLockStatus - get the lock status of a principal.
636 * IN kaserver - a valid kaserver handle previously returned by
639 * IN who - a kas_identity_p containing the identity of the principal
642 * OUT lockedUntil - the remaining number of seconds the principal is locked.
646 * No locks are obtained or released by this function
650 * Returns != 0 upon successful completion.
653 static int GetPrincipalLockStatus(
654 const kas_server_p kaserver,
655 const kas_identity_p who,
656 unsigned int *lockedUntil,
660 afs_status_t tst = 0;
665 * Validate input arguments and make rpc.
668 if (kaserver == NULL) {
669 tst = ADMKASKASERVERNULL;
670 goto fail_GetPrincipalLockStatus;
675 goto fail_GetPrincipalLockStatus;
678 if (lockedUntil == NULL) {
679 tst = ADMKASLOCKEDUNTILNULL;
680 goto fail_GetPrincipalLockStatus;
684 * Unlike every other kas rpc we make here, the lock/unlock rpc's
685 * aren't ubik based. So instead of calling ubik_Call, we use
686 * ubik_CallIter. ubik_CallIter steps through the list of hosts
687 * in the ubik_client and calls them one at a time. Since there's
688 * no synchronization of this data across the servers we have to
689 * manually keep track of the shortest time to unlock the user ourselves.
691 * The original inspiration for this function is ka_islocked
692 * in admin_tools.c. I think that function is totally bogus so I'm
695 * This function should contact all the kaservers and request the lock
696 * status of the principal. If any of the servers say the principal is
697 * unlocked, we report it as unlocked. If all the servers say the
698 * principal is locked, we find the server with the shortest lock time
699 * remaining on the principal and return that time.
701 * This is different than kas, but I think kas is buggy.
707 tst = ubik_CallIter(KAM_LockStatus, kaserver->servers, UPUBIKONLY,
708 &count, who->principal, who->instance,
709 &locked, 0, 0, 0, 0);
712 if (locked < *lockedUntil) {
713 *lockedUntil = locked;
717 } while ((tst != UNOSERVERS) && (locked != 0));
720 * Check to see if any server reported this principal unlocked.
723 if ((tst == 0) && (locked == 0)) {
730 fail_GetPrincipalLockStatus:
739 * kas_PrincipalGet - retrieve information about a single principal.
743 * IN cellHandle - a cellHandle previously returned by afsclient_CellOpen.
745 * IN serverHandle - a serverHandle previously returned by kas_ServerOpen.
747 * IN who - a kas_identity_p containing the identity of the principal
750 * OUT principal - upon successful completion contains information
755 * No locks are obtained or released by this function
759 * Returns != 0 upon successful completion.
762 int ADMINAPI kas_PrincipalGet(
763 const void *cellHandle,
764 const void *serverHandle,
765 const kas_identity_p who,
766 kas_principalEntry_p principal,
770 afs_status_t tst = 0;
771 afs_cell_handle_p c_handle = (afs_cell_handle_p) cellHandle;
772 kas_server_p k_handle = (kas_server_p) serverHandle;
773 kas_server_t kaserver;
774 struct kaentryinfo entry;
777 * Validate input arguments and make rpc.
782 goto fail_kas_PrincipalGet;
785 if (principal == NULL) {
786 tst = ADMKASPRINCIPALNULL;
787 goto fail_kas_PrincipalGet;
790 if (!ChooseValidServer(c_handle, k_handle, &kaserver, &tst)) {
791 goto fail_kas_PrincipalGet;
794 tst = ubik_Call(KAM_GetEntry, kaserver.servers, 0,
795 who->principal, who->instance, KAMAJORVERSION, &entry);
797 goto fail_kas_PrincipalGet;
801 * copy the kaentryinfo structure to our kas_principalEntry_t
804 if (!kaentryinfo_to_kas_principalEntry_t(&entry, principal, &tst)) {
805 goto fail_kas_PrincipalGet;
809 fail_kas_PrincipalGet:
817 typedef struct principal_get {
821 kas_server_t kaserver;
822 kas_identity_t principal[CACHED_ITEMS];
823 } principal_get_t, *principal_get_p;
825 static int DeletePrincipalSpecificData(
830 afs_status_t tst = 0;
831 principal_get_p prin = (principal_get_p) rpc_specific;
833 prin->kaserver.is_valid = 0;
842 static int GetPrincipalRPC(
846 int *last_item_contains_data,
850 afs_status_t tst = 0;
851 principal_get_p prin = (principal_get_p) rpc_specific;
853 tst = ubik_Call(KAM_ListEntry, prin->kaserver.servers, 0,
854 prin->current, &prin->next, &prin->count,
855 &prin->principal[slot]);
857 prin->current = prin->next;
858 if (prin->next == 0) {
860 *last_item_contains_data = 0;
871 static int GetPrincipalFromCache(
878 afs_status_t tst = 0;
879 principal_get_p prin = (principal_get_p) rpc_specific;
881 memcpy(dest, &prin->principal[slot], sizeof(kas_identity_t));
891 * kas_PrincipalGetBegin - start the process of iterating over the entire
896 * IN cellHandle - a cellHandle previously returned by afsclient_CellOpen.
898 * IN serverHandle - a serverHandle previously returned by kas_ServerOpen.
900 * OUT iterationIdP - upon successful completion contains a iterator that
901 * can be passed to kas_PrincipalGetNext.
905 * No locks are obtained or released by this function
909 * Returns != 0 upon successful completion.
914 int ADMINAPI kas_PrincipalGetBegin(
915 const void *cellHandle,
916 const void *serverHandle,
921 afs_status_t tst = 0;
922 afs_cell_handle_p c_handle = (afs_cell_handle_p) cellHandle;
923 kas_server_p k_handle = (kas_server_p) serverHandle;
924 afs_admin_iterator_p iter = (afs_admin_iterator_p) malloc(sizeof(afs_admin_iterator_t));
925 principal_get_p principal = (principal_get_p) malloc(sizeof(principal_get_t));
933 goto fail_kas_PrincipalGetBegin;
936 if (principal == NULL) {
938 goto fail_kas_PrincipalGetBegin;
941 if (iterationIdP == NULL) {
942 tst = ADMITERATIONIDPNULL;
943 goto fail_kas_PrincipalGetBegin;
946 if (!ChooseValidServer(c_handle, k_handle, &principal->kaserver, &tst)) {
947 goto fail_kas_PrincipalGetBegin;
951 * Initialize the iterator structure
954 principal->current = 0;
956 principal->count = 0;
957 if (IteratorInit(iter, (void *) principal, GetPrincipalRPC,
958 GetPrincipalFromCache, NULL,
959 DeletePrincipalSpecificData, &tst)) {
960 *iterationIdP = (void *) iter;
964 fail_kas_PrincipalGetBegin:
970 if (principal != NULL) {
982 * kas_PrincipalGetNext - retrieve the next principal from the kaserver.
986 * IN iterationId - an iterator previously returned by kas_PrincipalGetBegin
988 * OUT who - upon successful completion contains the next principal from the
993 * Hold the iterator mutex across the call to the kaserver.
997 * Returns != 0 upon successful completion.
998 * Returns 0 and st == ADMITERATORDONE when the last entry is returned.
1001 int ADMINAPI kas_PrincipalGetNext(
1002 const void *iterationId,
1007 afs_status_t tst = 0;
1008 afs_admin_iterator_p iter = (afs_admin_iterator_p) iterationId;
1011 * Validate arguments
1015 tst = ADMKASWHONULL;
1016 goto fail_kas_PrincipalGetNext;
1020 tst = ADMITERATORNULL;
1021 goto fail_kas_PrincipalGetNext;
1024 rc = IteratorNext(iter, (void *) who, &tst);
1026 fail_kas_PrincipalGetNext:
1035 * kas_PrincipalGetDone - finish using a principal iterator
1039 * IN iterationId - an iterator previously returned by kas_PrincipalGetBegin
1043 * No locks are held by this function.
1047 * Returns != 0 upon successful completion.
1051 * It is the user's responsibility to make sure kas_PrincipalGetDone
1052 * is called only once for each iterator.
1055 int ADMINAPI kas_PrincipalGetDone(
1056 const void *iterationIdP,
1060 afs_status_t tst = 0;
1061 afs_admin_iterator_p iter = (afs_admin_iterator_p) iterationIdP;
1068 tst = ADMITERATORNULL;
1069 goto fail_kas_PrincipalGetDone;
1072 rc = IteratorDone(iter, &tst);
1074 fail_kas_PrincipalGetDone:
1083 * kas_PrincipalKeySet - set a principal's password to a known value.
1087 * IN cellHandle - a cellHandle previously returned by afsclient_CellOpen.
1089 * IN serverHandle - a serverHandle previously returned by kas_ServerOpen.
1091 * IN who - the principal for whom the password is being set.
1093 * IN keyVersion - the version number of the new key.
1095 * IN key - the new password.
1099 * No locks are held by this function.
1103 * Returns != 0 upon successful completion.
1106 int ADMINAPI kas_PrincipalKeySet(
1107 const void *cellHandle,
1108 const void *serverHandle,
1109 const kas_identity_p who,
1111 const kas_encryptionKey_p key,
1115 afs_status_t tst = 0;
1116 afs_cell_handle_p c_handle = (afs_cell_handle_p) cellHandle;
1117 kas_server_p k_handle = (kas_server_p) serverHandle;
1118 kas_server_t kaserver;
1121 * Validate input arguments and make rpc.
1125 tst = ADMKASWHONULL;
1126 goto fail_kas_PrincipalKeySet;
1130 tst = ADMKASKEYNULL;
1131 goto fail_kas_PrincipalKeySet;
1134 if (!ChooseValidServer(c_handle, k_handle, &kaserver, &tst)) {
1135 goto fail_kas_PrincipalKeySet;
1138 tst = ubik_Call(KAM_SetPassword, kaserver.servers, 0,
1139 who->principal, who->instance, keyVersion, *key);
1141 goto fail_kas_PrincipalKeySet;
1144 fail_kas_PrincipalKeySet:
1153 * kas_PrincipalLockStatusGet - determine a principal's lock status.
1157 * IN cellHandle - a cellHandle previously returned by afsclient_CellOpen.
1159 * IN serverHandle - a serverHandle previously returned by kas_ServerOpen.
1161 * IN who - the principal whose lock status is being checked.
1163 * OUT lock_end_timeP - the number of seconds until the principal is unlocked.
1164 * If 0 => user is unlocked.
1168 * No locks are held by this function.
1172 * Returns != 0 upon successful completion.
1176 * See the comments in GetPrincipalLockStatus regarding how the locking data
1177 * is kept INconsistently between servers.
1180 int ADMINAPI kas_PrincipalLockStatusGet(
1181 const void *cellHandle,
1182 const void *serverHandle,
1183 const kas_identity_p who,
1184 unsigned int *lock_end_timeP,
1188 afs_status_t tst = 0;
1189 afs_cell_handle_p c_handle = (afs_cell_handle_p) cellHandle;
1190 kas_server_p k_handle = (kas_server_p) serverHandle;
1191 kas_server_t kaserver;
1194 * Validate input arguments and make rpc.
1198 tst = ADMKASWHONULL;
1199 goto fail_kas_PrincipalLockStatusGet;
1202 if (lock_end_timeP == NULL) {
1203 tst = ADMKASLOCKENDTIMEPNULL;
1204 goto fail_kas_PrincipalLockStatusGet;
1207 if (!ChooseValidServer(c_handle, k_handle, &kaserver, &tst)) {
1208 goto fail_kas_PrincipalLockStatusGet;
1211 rc = GetPrincipalLockStatus(&kaserver, who, lock_end_timeP, &tst);
1213 fail_kas_PrincipalLockStatusGet:
1222 * kas_PrincipalUnlock - unlock a principal.
1226 * IN cellHandle - a cellHandle previously returned by afsclient_CellOpen.
1228 * IN serverHandle - a serverHandle previously returned by kas_ServerOpen.
1230 * IN who - the principal who is being unlocked.
1234 * No locks are held by this function.
1238 * Returns != 0 upon successful completion.
1242 * See the comments in GetPrincipalLockStatus regarding how the locking data
1243 * is kept INconsistently between servers.
1246 int ADMINAPI kas_PrincipalUnlock(
1247 const void *cellHandle,
1248 const void *serverHandle,
1249 const kas_identity_p who,
1253 afs_status_t tst = 0;
1254 afs_cell_handle_p c_handle = (afs_cell_handle_p) cellHandle;
1255 kas_server_p k_handle = (kas_server_p) serverHandle;
1256 kas_server_t kaserver;
1258 afs_status_t save_tst = 0;
1261 * Validate input arguments and make rpc.
1265 tst = ADMKASWHONULL;
1266 goto fail_kas_PrincipalUnlock;
1269 if (!ChooseValidServer(c_handle, k_handle, &kaserver, &tst)) {
1270 goto fail_kas_PrincipalUnlock;
1274 tst = ubik_CallIter(KAM_Unlock, kaserver.servers, 0,
1275 &count, who->principal, who->instance,
1277 if (tst && (tst != UNOSERVERS)) {
1278 if (save_tst == 0) {
1279 save_tst = tst; /* save the first failure */
1282 } while (tst != UNOSERVERS);
1288 fail_kas_PrincipalUnlock:
1296 static int getPrincipalFlags(
1297 const void *cellHandle,
1298 const void *serverHandle,
1299 const kas_identity_p who,
1300 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;
1314 tst = ubik_Call(KAM_GetEntry, kaserver.servers, 0, who->principal,
1315 who->instance, KAMAJORVERSION, &tentry);
1317 *cur_flags = tentry.flags;
1321 fail_getPrincipalFlags:
1330 * kas_PrincipalFieldsSet - modify an existing principal.
1334 * IN cellHandle - a cellHandle previously returned by afsclient_CellOpen.
1336 * IN serverHandle - a serverHandle previously returned by kas_ServerOpen.
1338 * IN who - the principal who is being modified.
1340 * IN isAdmin - the admin status of the principal.
1342 * IN grantTickets - should the TGS issue tickets for the principal.
1344 * IN canEncrypt - should the TGS allow the use of encryption via the
1347 * IN canChangePassword - should the principal be allowed to change their
1350 * IN expirationDate - the date when the principal will expire.
1352 * IN maxTicketLifetime - the maximum lifetime of a ticket issued for
1355 * IN passwordExpires - the maximum number of days a particular
1356 * password can be used. The limit is 255, 0 => no expiration.
1358 * IN passwordReuse - can a password be reused by this principal.
1360 * IN failedPasswordAttempts - number of failed login attempts before
1361 * a principal is locked. The limit is 255, 0 => no limit.
1363 * IN failedPasswordLockTime - the number of seconds a principal is
1364 * locked once failedPasswordAttempts is reached. Some bizarre rounding
1365 * occurs for this value, see kas for more details.
1369 * No locks are held by this function.
1373 * Returns != 0 upon successful completion.
1377 * See the comments in GetPrincipalLockStatus regarding how the locking data
1378 * is kept INconsistently between servers.
1381 int ADMINAPI kas_PrincipalFieldsSet(
1382 const void *cellHandle,
1383 const void *serverHandle,
1384 const kas_identity_p who,
1385 const kas_admin_p isAdmin,
1386 const kas_tgs_p grantTickets,
1387 const kas_enc_p canEncrypt,
1388 const kas_cpw_p canChangePassword,
1389 const unsigned int *expirationDate,
1390 const unsigned int *maxTicketLifetime,
1391 const unsigned int *passwordExpires,
1392 const kas_rpw_p passwordReuse,
1393 const unsigned int *failedPasswordAttempts,
1394 const unsigned int *failedPasswordLockTime,
1398 afs_status_t tst = 0;
1399 afs_cell_handle_p c_handle = (afs_cell_handle_p) cellHandle;
1400 kas_server_p k_handle = (kas_server_p) serverHandle;
1401 kas_server_t kaserver;
1402 afs_int32 flags = 0;
1403 Date expiration = 0;
1404 afs_int32 lifetime = 0;
1406 char spare_bytes[4] = {0,0,0,0};
1407 int somethings_changing = 0;
1410 * Validate input arguments.
1414 tst = ADMKASWHONULL;
1415 goto fail_kas_PrincipalFieldsSet;
1419 * set flags based upon input
1421 * If we're changing the flags, we need to get the current value of
1422 * the flags first and then make the changes
1425 if ((isAdmin != NULL) || (grantTickets != NULL) ||
1426 (canEncrypt != NULL) || (canChangePassword != NULL)) {
1427 if (!getPrincipalFlags(cellHandle, serverHandle, who, &flags,
1429 goto fail_kas_PrincipalFieldsSet;
1433 if (isAdmin != NULL) {
1434 somethings_changing = 1;
1435 if (*isAdmin == KAS_ADMIN) {
1442 if (grantTickets != NULL) {
1443 somethings_changing = 1;
1444 if (*grantTickets == NO_TGS) {
1451 if (canEncrypt != NULL) {
1452 somethings_changing = 1;
1453 if (*canEncrypt == NO_ENCRYPT) {
1456 flags &= ~KAFNOSEAL;
1460 if (canChangePassword != NULL) {
1461 somethings_changing = 1;
1462 if (*canChangePassword == NO_CHANGE_PASSWORD) {
1469 flags = (flags & KAF_SETTABLE_FLAGS) | KAFNORMAL;
1471 if (expirationDate != NULL) {
1472 somethings_changing = 1;
1473 expiration = *expirationDate;
1476 if (maxTicketLifetime != NULL) {
1477 somethings_changing = 1;
1478 lifetime = *maxTicketLifetime;
1481 if (passwordExpires != NULL) {
1482 if (*passwordExpires > 255) {
1483 tst = ADMKASPASSWORDEXPIRESTOOBIG;
1484 goto fail_kas_PrincipalFieldsSet;
1486 somethings_changing = 1;
1487 spare_bytes[0] = *passwordExpires + 1;
1490 if (passwordReuse != NULL) {
1491 somethings_changing = 1;
1492 if (*passwordReuse == REUSE_PASSWORD) {
1493 spare_bytes[1] = KA_REUSEPW;
1495 spare_bytes[1] = KA_NOREUSEPW;
1499 if (failedPasswordAttempts != NULL) {
1500 if (*failedPasswordAttempts > 255) {
1501 tst = ADMKASFAILEDPASSWORDATTEMPTSTOOBIG;
1502 goto fail_kas_PrincipalFieldsSet;
1504 somethings_changing = 1;
1505 spare_bytes[2] = *failedPasswordAttempts + 1;
1508 if (failedPasswordLockTime != NULL) {
1509 if (*failedPasswordLockTime > 36*60*60) {
1510 tst = ADMKASFAILEDPASSWORDLOCKTIME;
1511 goto fail_kas_PrincipalFieldsSet;
1513 somethings_changing = 1;
1514 spare_bytes[3] = ((*failedPasswordLockTime + 511) >> 9) + 1;
1517 was_spare = pack_long(spare_bytes);
1519 if (somethings_changing) {
1520 if (!ChooseValidServer(c_handle, k_handle, &kaserver, &tst)) {
1521 goto fail_kas_PrincipalFieldsSet;
1523 tst = ubik_Call(KAM_SetFields, kaserver.servers, 0, who->principal,
1524 who->instance, flags, expiration, lifetime,
1530 tst = ADMKASPRINCIPALFIELDSNOCHANGE;
1533 fail_kas_PrincipalFieldsSet:
1542 * kas_ServerStatsGet - get server statistics.
1546 * IN cellHandle - a cellHandle previously returned by afsclient_CellOpen.
1548 * IN serverHandle - a serverHandle previously returned by kas_ServerOpen.
1550 * OUT stats - the statistics retrieved.
1554 * No locks are held by this function.
1558 * Returns != 0 upon successful completion.
1561 int ADMINAPI kas_ServerStatsGet(
1562 const void *cellHandle,
1563 const void *serverHandle,
1564 kas_serverStats_p stats,
1568 afs_status_t tst = 0;
1569 afs_cell_handle_p c_handle = (afs_cell_handle_p) cellHandle;
1570 kas_server_p k_handle = (kas_server_p) serverHandle;
1571 kas_server_t kaserver;
1578 * Validate input arguments and make rpc.
1581 if (stats == NULL) {
1582 tst = ADMKASSTATSNULL;
1583 goto fail_kas_ServerStatsGet;
1586 if (!ChooseValidServer(c_handle, k_handle, &kaserver, &tst)) {
1587 goto fail_kas_ServerStatsGet;
1590 tst = ubik_Call(KAM_GetStats, kaserver.servers, 0, KAMAJORVERSION, &admins,
1591 &statics, &dynamics);
1593 goto fail_kas_ServerStatsGet;
1596 stats->allocations = statics.allocs;
1597 stats->frees = statics.frees;
1598 stats->changePasswordRequests = statics.cpws;
1599 stats->adminAccounts = admins;
1600 stats->host = dynamics.host;
1601 stats->serverStartTime = dynamics.start_time;
1602 stats->hashTableUtilization = dynamics.hashTableUtilization;
1604 i = sizeof(kas_serverProcStats_t);
1605 memcpy(&stats->authenticate, &dynamics.Authenticate, i);
1606 memcpy(&stats->changePassword, &dynamics.ChangePassword, i);
1607 memcpy(&stats->getTicket, &dynamics.GetTicket, i);
1608 memcpy(&stats->createUser, &dynamics.CreateUser, i);
1609 memcpy(&stats->setPassword, &dynamics.SetPassword, i);
1610 memcpy(&stats->setFields, &dynamics.SetFields, i);
1611 memcpy(&stats->deleteUser, &dynamics.DeleteUser, i);
1612 memcpy(&stats->getEntry, &dynamics.GetEntry, i);
1613 memcpy(&stats->listEntry, &dynamics.ListEntry, i);
1614 memcpy(&stats->getStats, &dynamics.GetStats, i);
1615 memcpy(&stats->getPassword, &dynamics.GetPassword, i);
1616 memcpy(&stats->getRandomKey, &dynamics.GetRandomKey, i);
1617 memcpy(&stats->debug, &dynamics.Debug, i);
1618 memcpy(&stats->udpAuthenticate, &dynamics.UAuthenticate, i);
1619 memcpy(&stats->udpGetTicket, &dynamics.UGetTicket, i);
1620 memcpy(&stats->unlock, &dynamics.Unlock, i);
1621 memcpy(&stats->lockStatus, &dynamics.LockStatus, i);
1623 stats->stringChecks = dynamics.string_checks;
1626 fail_kas_ServerStatsGet:
1635 * kas_ServerDebugGet - get server debug info.
1639 * IN cellHandle - a cellHandle previously returned by afsclient_CellOpen.
1641 * IN serverHandle - a serverHandle previously returned by kas_ServerOpen.
1643 * OUT stats - the debug info retrieved.
1647 * No locks are held by this function.
1651 * Returns != 0 upon successful completion.
1654 int ADMINAPI kas_ServerDebugGet(
1655 const void *cellHandle,
1656 const void *serverHandle,
1657 kas_serverDebugInfo_p debug,
1661 afs_status_t tst = 0;
1662 afs_cell_handle_p c_handle = (afs_cell_handle_p) cellHandle;
1663 kas_server_p k_handle = (kas_server_p) serverHandle;
1664 kas_server_t kaserver;
1665 struct ka_debugInfo info;
1669 * Validate input arguments and make rpc.
1672 if (debug == NULL) {
1673 tst = ADMKASDEBUGNULL;
1674 goto fail_kas_ServerDebugGet;
1677 if (!ChooseValidServer(c_handle, k_handle, &kaserver, &tst)) {
1678 goto fail_kas_ServerDebugGet;
1680 tst = ubik_Call(KAM_Debug, kaserver.servers, 0, KAMAJORVERSION, 0, &info);
1682 goto fail_kas_ServerDebugGet;
1684 debug->host = info.host;
1685 debug->serverStartTime = info.startTime;
1686 debug->currentTime = info.reserved1;
1687 debug->noAuth = info.noAuth;
1688 debug->lastTransaction = info.lastTrans;
1689 strcpy(debug->lastOperation, info.lastOperation);
1690 strcpy(debug->lastPrincipalAuth, info.lastAuth);
1691 strcpy(debug->lastPrincipalUDPAuth, info.lastUAuth);
1692 strcpy(debug->lastPrincipalTGS, info.lastTGS);
1693 strcpy(debug->lastPrincipalUDPTGS, info.lastUTGS);
1694 strcpy(debug->lastPrincipalAdmin, info.lastAdmin);
1695 strcpy(debug->lastServerTGS, info.lastTGSServer);
1696 strcpy(debug->lastServerUDPTGS, info.lastUTGSServer);
1697 debug->nextAutoCheckPointWrite = info.nextAutoCPW;
1698 debug->updatesRemainingBeforeAutoCheckPointWrite = info.updatesRemaining;
1699 debug->dbHeaderRead = info.dbHeaderRead;
1700 debug->dbVersion = info.dbVersion;
1701 debug->dbFreePtr = info.dbFreePtr;
1702 debug->dbEOFPtr = info.dbEofPtr;
1703 debug->dbKvnoPtr = info.dbKvnoPtr;
1704 debug->dbSpecialKeysVersion = info.dbSpecialKeysVersion;
1705 debug->dbHeaderLock = info.cheader_lock;
1706 debug->keyCacheLock = info.keycache_lock;
1707 debug->keyCacheVersion = info.kcVersion;
1708 debug->keyCacheSize = info.kcSize;
1709 debug->keyCacheUsed = info.kcUsed;
1710 for(i=0;i<info.kcUsed;i++) {
1711 debug->keyCache[i].lastUsed = info.kcInfo[i].used;
1712 debug->keyCache[i].keyVersionNumber = info.kcInfo[i].kvno;
1713 debug->keyCache[i].primary = info.kcInfo[i].primary;
1714 debug->keyCache[i].keyCheckSum = info.kcInfo[i].keycksum;
1715 strcpy(debug->keyCache[i].principal,info.kcInfo[i].principal);
1719 fail_kas_ServerDebugGet:
1728 * kas_ServerRandomKeyGet - get a random key from a server.
1732 * IN cellHandle - a cellHandle previously returned by afsclient_CellOpen.
1734 * IN serverHandle - a serverHandle previously returned by kas_ServerOpen.
1736 * OUT key - a random key.
1740 * No locks are held by this function.
1744 * Returns != 0 upon successful completion.
1747 int ADMINAPI kas_ServerRandomKeyGet(
1748 const void *cellHandle,
1749 const void *serverHandle,
1750 kas_encryptionKey_p key,
1754 afs_status_t tst = 0;
1755 afs_cell_handle_p c_handle = (afs_cell_handle_p) cellHandle;
1756 kas_server_p k_handle = (kas_server_p) serverHandle;
1757 kas_server_t kaserver;
1760 * Validate input arguments and make rpc.
1764 tst = ADMKASKEYNULL;
1765 goto fail_kas_ServerRandomKeyGet;
1768 if (!ChooseValidServer(c_handle, k_handle, &kaserver, &tst)) {
1769 goto fail_kas_ServerRandomKeyGet;
1772 tst = ubik_Call(KAM_GetRandomKey, kaserver.servers, 0, key);
1774 goto fail_kas_ServerRandomKeyGet;
1778 fail_kas_ServerRandomKeyGet:
1787 * kas_StringToKey - turn a string key into a key.
1791 * IN cellName - the name of the cell where the key will be used.
1793 * IN string - the string to be converted.
1795 * OUT key - the encryption key.
1799 * No locks are held by this function.
1803 * Returns != 0 upon successful completion.
1806 int ADMINAPI kas_StringToKey(
1807 const char *cellName,
1809 kas_encryptionKey_p key,
1813 afs_status_t tst = 0;
1815 ka_StringToKey(string, cellName, (struct ktc_encryptionKey *) key);
1826 * kas_KeyCheckSum - compute the checksum of an encryption key.
1830 * IN key - the encryption key.
1832 * OUT cksumP - key checksum
1836 * No locks are held by this function.
1840 * Returns != 0 upon successful completion.
1843 int ADMINAPI kas_KeyCheckSum(
1844 const kas_encryptionKey_p key,
1845 unsigned int *cksumP,
1849 afs_status_t tst = 0;
1852 if ((tst = ka_KeyCheckSum((char *)key, &cksum32)) == 0) {