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;
880 kas_identity_p who = (kas_identity_p) dest;
882 memcpy(dest, &prin->principal[slot], sizeof(kas_identity_t));
892 * kas_PrincipalGetBegin - start the process of iterating over the entire
897 * IN cellHandle - a cellHandle previously returned by afsclient_CellOpen.
899 * IN serverHandle - a serverHandle previously returned by kas_ServerOpen.
901 * OUT iterationIdP - upon successful completion contains a iterator that
902 * can be passed to kas_PrincipalGetNext.
906 * No locks are obtained or released by this function
910 * Returns != 0 upon successful completion.
915 int ADMINAPI kas_PrincipalGetBegin(
916 const void *cellHandle,
917 const void *serverHandle,
922 afs_status_t tst = 0;
923 afs_cell_handle_p c_handle = (afs_cell_handle_p) cellHandle;
924 kas_server_p k_handle = (kas_server_p) serverHandle;
925 afs_admin_iterator_p iter = (afs_admin_iterator_p) malloc(sizeof(afs_admin_iterator_t));
926 principal_get_p principal = (principal_get_p) malloc(sizeof(principal_get_t));
934 goto fail_kas_PrincipalGetBegin;
937 if (principal == NULL) {
939 goto fail_kas_PrincipalGetBegin;
942 if (iterationIdP == NULL) {
943 tst = ADMITERATIONIDPNULL;
944 goto fail_kas_PrincipalGetBegin;
947 if (!ChooseValidServer(c_handle, k_handle, &principal->kaserver, &tst)) {
948 goto fail_kas_PrincipalGetBegin;
952 * Initialize the iterator structure
955 principal->current = 0;
957 principal->count = 0;
958 if (IteratorInit(iter, (void *) principal, GetPrincipalRPC,
959 GetPrincipalFromCache, NULL,
960 DeletePrincipalSpecificData, &tst)) {
961 *iterationIdP = (void *) iter;
965 fail_kas_PrincipalGetBegin:
971 if (principal != NULL) {
983 * kas_PrincipalGetNext - retrieve the next principal from the kaserver.
987 * IN iterationId - an iterator previously returned by kas_PrincipalGetBegin
989 * OUT who - upon successful completion contains the next principal from the
994 * Hold the iterator mutex across the call to the kaserver.
998 * Returns != 0 upon successful completion.
999 * Returns 0 and st == ADMITERATORDONE when the last entry is returned.
1002 int ADMINAPI kas_PrincipalGetNext(
1003 const void *iterationId,
1008 afs_status_t tst = 0;
1009 afs_admin_iterator_p iter = (afs_admin_iterator_p) iterationId;
1010 int locked_iter = 0;
1013 * Validate arguments
1017 tst = ADMKASWHONULL;
1018 goto fail_kas_PrincipalGetNext;
1022 tst = ADMITERATORNULL;
1023 goto fail_kas_PrincipalGetNext;
1026 rc = IteratorNext(iter, (void *) who, &tst);
1028 fail_kas_PrincipalGetNext:
1037 * kas_PrincipalGetDone - finish using a principal iterator
1041 * IN iterationId - an iterator previously returned by kas_PrincipalGetBegin
1045 * No locks are held by this function.
1049 * Returns != 0 upon successful completion.
1053 * It is the user's responsibility to make sure kas_PrincipalGetDone
1054 * is called only once for each iterator.
1057 int ADMINAPI kas_PrincipalGetDone(
1058 const void *iterationIdP,
1062 afs_status_t tst = 0;
1063 afs_admin_iterator_p iter = (afs_admin_iterator_p) iterationIdP;
1070 tst = ADMITERATORNULL;
1071 goto fail_kas_PrincipalGetDone;
1074 rc = IteratorDone(iter, &tst);
1076 fail_kas_PrincipalGetDone:
1085 * kas_PrincipalKeySet - set a principal's password to a known value.
1089 * IN cellHandle - a cellHandle previously returned by afsclient_CellOpen.
1091 * IN serverHandle - a serverHandle previously returned by kas_ServerOpen.
1093 * IN who - the principal for whom the password is being set.
1095 * IN keyVersion - the version number of the new key.
1097 * IN key - the new password.
1101 * No locks are held by this function.
1105 * Returns != 0 upon successful completion.
1108 int ADMINAPI kas_PrincipalKeySet(
1109 const void *cellHandle,
1110 const void *serverHandle,
1111 const kas_identity_p who,
1113 const kas_encryptionKey_p key,
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;
1140 tst = ubik_Call(KAM_SetPassword, kaserver.servers, 0,
1141 who->principal, who->instance, keyVersion, *key);
1143 goto fail_kas_PrincipalKeySet;
1146 fail_kas_PrincipalKeySet:
1155 * kas_PrincipalLockStatusGet - determine a principal's lock status.
1159 * IN cellHandle - a cellHandle previously returned by afsclient_CellOpen.
1161 * IN serverHandle - a serverHandle previously returned by kas_ServerOpen.
1163 * IN who - the principal whose lock status is being checked.
1165 * OUT lock_end_timeP - the number of seconds until the principal is unlocked.
1166 * If 0 => user is unlocked.
1170 * No locks are held by this function.
1174 * Returns != 0 upon successful completion.
1178 * See the comments in GetPrincipalLockStatus regarding how the locking data
1179 * is kept INconsistently between servers.
1182 int ADMINAPI kas_PrincipalLockStatusGet(
1183 const void *cellHandle,
1184 const void *serverHandle,
1185 const kas_identity_p who,
1186 unsigned int *lock_end_timeP,
1190 afs_status_t tst = 0;
1191 afs_cell_handle_p c_handle = (afs_cell_handle_p) cellHandle;
1192 kas_server_p k_handle = (kas_server_p) serverHandle;
1193 kas_server_t kaserver;
1196 * Validate input arguments and make rpc.
1200 tst = ADMKASWHONULL;
1201 goto fail_kas_PrincipalLockStatusGet;
1204 if (lock_end_timeP == NULL) {
1205 tst = ADMKASLOCKENDTIMEPNULL;
1206 goto fail_kas_PrincipalLockStatusGet;
1209 if (!ChooseValidServer(c_handle, k_handle, &kaserver, &tst)) {
1210 goto fail_kas_PrincipalLockStatusGet;
1213 rc = GetPrincipalLockStatus(&kaserver, who, lock_end_timeP, &tst);
1215 fail_kas_PrincipalLockStatusGet:
1224 * kas_PrincipalUnlock - unlock a principal.
1228 * IN cellHandle - a cellHandle previously returned by afsclient_CellOpen.
1230 * IN serverHandle - a serverHandle previously returned by kas_ServerOpen.
1232 * IN who - the principal who is being unlocked.
1236 * No locks are held by this function.
1240 * Returns != 0 upon successful completion.
1244 * See the comments in GetPrincipalLockStatus regarding how the locking data
1245 * is kept INconsistently between servers.
1248 int ADMINAPI kas_PrincipalUnlock(
1249 const void *cellHandle,
1250 const void *serverHandle,
1251 const kas_identity_p who,
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;
1276 tst = ubik_CallIter(KAM_Unlock, kaserver.servers, 0,
1277 &count, who->principal, who->instance,
1279 if (tst && (tst != UNOSERVERS)) {
1280 if (save_tst == 0) {
1281 save_tst = tst; /* save the first failure */
1284 } while (tst != UNOSERVERS);
1290 fail_kas_PrincipalUnlock:
1298 static int getPrincipalFlags(
1299 const void *cellHandle,
1300 const void *serverHandle,
1301 const kas_identity_p who,
1302 afs_int32 *cur_flags,
1306 afs_status_t tst = 0;
1307 afs_cell_handle_p c_handle = (afs_cell_handle_p) cellHandle;
1308 kas_server_p k_handle = (kas_server_p) serverHandle;
1309 kas_server_t kaserver;
1310 struct kaentryinfo tentry;
1312 if (!ChooseValidServer(c_handle, k_handle, &kaserver, &tst)) {
1313 goto fail_getPrincipalFlags;
1316 tst = ubik_Call(KAM_GetEntry, kaserver.servers, 0, who->principal,
1317 who->instance, KAMAJORVERSION, &tentry);
1319 *cur_flags = tentry.flags;
1323 fail_getPrincipalFlags:
1332 * kas_PrincipalFieldsSet - modify an existing principal.
1336 * IN cellHandle - a cellHandle previously returned by afsclient_CellOpen.
1338 * IN serverHandle - a serverHandle previously returned by kas_ServerOpen.
1340 * IN who - the principal who is being modified.
1342 * IN isAdmin - the admin status of the principal.
1344 * IN grantTickets - should the TGS issue tickets for the principal.
1346 * IN canEncrypt - should the TGS allow the use of encryption via the
1349 * IN canChangePassword - should the principal be allowed to change their
1352 * IN expirationDate - the date when the principal will expire.
1354 * IN maxTicketLifetime - the maximum lifetime of a ticket issued for
1357 * IN passwordExpires - the maximum number of days a particular
1358 * password can be used. The limit is 255, 0 => no expiration.
1360 * IN passwordReuse - can a password be reused by this principal.
1362 * IN failedPasswordAttempts - number of failed login attempts before
1363 * a principal is locked. The limit is 255, 0 => no limit.
1365 * IN failedPasswordLockTime - the number of seconds a principal is
1366 * locked once failedPasswordAttempts is reached. Some bizarre rounding
1367 * occurs for this value, see kas for more details.
1371 * No locks are held by this function.
1375 * Returns != 0 upon successful completion.
1379 * See the comments in GetPrincipalLockStatus regarding how the locking data
1380 * is kept INconsistently between servers.
1383 int ADMINAPI kas_PrincipalFieldsSet(
1384 const void *cellHandle,
1385 const void *serverHandle,
1386 const kas_identity_p who,
1387 const kas_admin_p isAdmin,
1388 const kas_tgs_p grantTickets,
1389 const kas_enc_p canEncrypt,
1390 const kas_cpw_p canChangePassword,
1391 const unsigned int *expirationDate,
1392 const unsigned int *maxTicketLifetime,
1393 const unsigned int *passwordExpires,
1394 const kas_rpw_p passwordReuse,
1395 const unsigned int *failedPasswordAttempts,
1396 const unsigned int *failedPasswordLockTime,
1400 afs_status_t tst = 0;
1401 afs_cell_handle_p c_handle = (afs_cell_handle_p) cellHandle;
1402 kas_server_p k_handle = (kas_server_p) serverHandle;
1403 kas_server_t kaserver;
1404 afs_int32 flags = 0;
1405 Date expiration = 0;
1406 afs_int32 lifetime = 0;
1408 char spare_bytes[4] = {0,0,0,0};
1409 int somethings_changing = 0;
1410 int have_got_current_flag = 0;
1413 * Validate input arguments.
1417 tst = ADMKASWHONULL;
1418 goto fail_kas_PrincipalFieldsSet;
1422 * set flags based upon input
1424 * If we're changing the flags, we need to get the current value of
1425 * the flags first and then make the changes
1428 if ((isAdmin != NULL) || (grantTickets != NULL) ||
1429 (canEncrypt != NULL) || (canChangePassword != NULL)) {
1430 if (!getPrincipalFlags(cellHandle, serverHandle, who, &flags,
1432 goto fail_kas_PrincipalFieldsSet;
1436 if (isAdmin != NULL) {
1437 somethings_changing = 1;
1438 if (*isAdmin == KAS_ADMIN) {
1445 if (grantTickets != NULL) {
1446 somethings_changing = 1;
1447 if (*grantTickets == NO_TGS) {
1454 if (canEncrypt != NULL) {
1455 somethings_changing = 1;
1456 if (*canEncrypt == NO_ENCRYPT) {
1459 flags &= ~KAFNOSEAL;
1463 if (canChangePassword != NULL) {
1464 somethings_changing = 1;
1465 if (*canChangePassword == NO_CHANGE_PASSWORD) {
1472 flags = (flags & KAF_SETTABLE_FLAGS) | KAFNORMAL;
1474 if (expirationDate != NULL) {
1475 somethings_changing = 1;
1476 expiration = *expirationDate;
1479 if (maxTicketLifetime != NULL) {
1480 somethings_changing = 1;
1481 lifetime = *maxTicketLifetime;
1484 if (passwordExpires != NULL) {
1485 if (*passwordExpires > 255) {
1486 tst = ADMKASPASSWORDEXPIRESTOOBIG;
1487 goto fail_kas_PrincipalFieldsSet;
1489 somethings_changing = 1;
1490 spare_bytes[0] = *passwordExpires + 1;
1493 if (passwordReuse != NULL) {
1494 somethings_changing = 1;
1495 if (*passwordReuse == REUSE_PASSWORD) {
1496 spare_bytes[1] = KA_REUSEPW;
1498 spare_bytes[1] = KA_NOREUSEPW;
1502 if (failedPasswordAttempts != NULL) {
1503 if (*failedPasswordAttempts > 255) {
1504 tst = ADMKASFAILEDPASSWORDATTEMPTSTOOBIG;
1505 goto fail_kas_PrincipalFieldsSet;
1507 somethings_changing = 1;
1508 spare_bytes[2] = *failedPasswordAttempts + 1;
1511 if (failedPasswordLockTime != NULL) {
1512 if (*failedPasswordLockTime > 36*60*60) {
1513 tst = ADMKASFAILEDPASSWORDLOCKTIME;
1514 goto fail_kas_PrincipalFieldsSet;
1516 somethings_changing = 1;
1517 spare_bytes[3] = ((*failedPasswordLockTime + 511) >> 9) + 1;
1520 was_spare = pack_long(spare_bytes);
1522 if (somethings_changing) {
1523 if (!ChooseValidServer(c_handle, k_handle, &kaserver, &tst)) {
1524 goto fail_kas_PrincipalFieldsSet;
1526 tst = ubik_Call(KAM_SetFields, kaserver.servers, 0, who->principal,
1527 who->instance, flags, expiration, lifetime,
1533 tst = ADMKASPRINCIPALFIELDSNOCHANGE;
1536 fail_kas_PrincipalFieldsSet:
1545 * kas_ServerStatsGet - get server statistics.
1549 * IN cellHandle - a cellHandle previously returned by afsclient_CellOpen.
1551 * IN serverHandle - a serverHandle previously returned by kas_ServerOpen.
1553 * OUT stats - the statistics retrieved.
1557 * No locks are held by this function.
1561 * Returns != 0 upon successful completion.
1564 int ADMINAPI kas_ServerStatsGet(
1565 const void *cellHandle,
1566 const void *serverHandle,
1567 kas_serverStats_p stats,
1571 afs_status_t tst = 0;
1572 afs_cell_handle_p c_handle = (afs_cell_handle_p) cellHandle;
1573 kas_server_p k_handle = (kas_server_p) serverHandle;
1574 kas_server_t kaserver;
1581 * Validate input arguments and make rpc.
1584 if (stats == NULL) {
1585 tst = ADMKASSTATSNULL;
1586 goto fail_kas_ServerStatsGet;
1589 if (!ChooseValidServer(c_handle, k_handle, &kaserver, &tst)) {
1590 goto fail_kas_ServerStatsGet;
1593 tst = ubik_Call(KAM_GetStats, kaserver.servers, 0, KAMAJORVERSION, &admins,
1594 &statics, &dynamics);
1596 goto fail_kas_ServerStatsGet;
1599 stats->allocations = statics.allocs;
1600 stats->frees = statics.frees;
1601 stats->changePasswordRequests = statics.cpws;
1602 stats->adminAccounts = admins;
1603 stats->host = dynamics.host;
1604 stats->serverStartTime = dynamics.start_time;
1605 stats->hashTableUtilization = dynamics.hashTableUtilization;
1607 i = sizeof(kas_serverProcStats_t);
1608 memcpy(&stats->authenticate, &dynamics.Authenticate, i);
1609 memcpy(&stats->changePassword, &dynamics.ChangePassword, i);
1610 memcpy(&stats->getTicket, &dynamics.GetTicket, i);
1611 memcpy(&stats->createUser, &dynamics.CreateUser, i);
1612 memcpy(&stats->setPassword, &dynamics.SetPassword, i);
1613 memcpy(&stats->setFields, &dynamics.SetFields, i);
1614 memcpy(&stats->deleteUser, &dynamics.DeleteUser, i);
1615 memcpy(&stats->getEntry, &dynamics.GetEntry, i);
1616 memcpy(&stats->listEntry, &dynamics.ListEntry, i);
1617 memcpy(&stats->getStats, &dynamics.GetStats, i);
1618 memcpy(&stats->getPassword, &dynamics.GetPassword, i);
1619 memcpy(&stats->getRandomKey, &dynamics.GetRandomKey, i);
1620 memcpy(&stats->debug, &dynamics.Debug, i);
1621 memcpy(&stats->udpAuthenticate, &dynamics.UAuthenticate, i);
1622 memcpy(&stats->udpGetTicket, &dynamics.UGetTicket, i);
1623 memcpy(&stats->unlock, &dynamics.Unlock, i);
1624 memcpy(&stats->lockStatus, &dynamics.LockStatus, i);
1626 stats->stringChecks = dynamics.string_checks;
1629 fail_kas_ServerStatsGet:
1638 * kas_ServerDebugGet - get server debug info.
1642 * IN cellHandle - a cellHandle previously returned by afsclient_CellOpen.
1644 * IN serverHandle - a serverHandle previously returned by kas_ServerOpen.
1646 * OUT stats - the debug info retrieved.
1650 * No locks are held by this function.
1654 * Returns != 0 upon successful completion.
1657 int ADMINAPI kas_ServerDebugGet(
1658 const void *cellHandle,
1659 const void *serverHandle,
1660 kas_serverDebugInfo_p debug,
1664 afs_status_t tst = 0;
1665 afs_cell_handle_p c_handle = (afs_cell_handle_p) cellHandle;
1666 kas_server_p k_handle = (kas_server_p) serverHandle;
1667 kas_server_t kaserver;
1668 struct ka_debugInfo info;
1672 * Validate input arguments and make rpc.
1675 if (debug == NULL) {
1676 tst = ADMKASDEBUGNULL;
1677 goto fail_kas_ServerDebugGet;
1680 if (!ChooseValidServer(c_handle, k_handle, &kaserver, &tst)) {
1681 goto fail_kas_ServerDebugGet;
1683 tst = ubik_Call(KAM_Debug, kaserver.servers, 0, KAMAJORVERSION, 0, &info);
1685 goto fail_kas_ServerDebugGet;
1687 debug->host = info.host;
1688 debug->serverStartTime = info.startTime;
1689 debug->currentTime = info.reserved1;
1690 debug->noAuth = info.noAuth;
1691 debug->lastTransaction = info.lastTrans;
1692 strcpy(debug->lastOperation, info.lastOperation);
1693 strcpy(debug->lastPrincipalAuth, info.lastAuth);
1694 strcpy(debug->lastPrincipalUDPAuth, info.lastUAuth);
1695 strcpy(debug->lastPrincipalTGS, info.lastTGS);
1696 strcpy(debug->lastPrincipalUDPTGS, info.lastUTGS);
1697 strcpy(debug->lastPrincipalAdmin, info.lastAdmin);
1698 strcpy(debug->lastServerTGS, info.lastTGSServer);
1699 strcpy(debug->lastServerUDPTGS, info.lastUTGSServer);
1700 debug->nextAutoCheckPointWrite = info.nextAutoCPW;
1701 debug->updatesRemainingBeforeAutoCheckPointWrite = info.updatesRemaining;
1702 debug->dbHeaderRead = info.dbHeaderRead;
1703 debug->dbVersion = info.dbVersion;
1704 debug->dbFreePtr = info.dbFreePtr;
1705 debug->dbEOFPtr = info.dbEofPtr;
1706 debug->dbKvnoPtr = info.dbKvnoPtr;
1707 debug->dbSpecialKeysVersion = info.dbSpecialKeysVersion;
1708 debug->dbHeaderLock = info.cheader_lock;
1709 debug->keyCacheLock = info.keycache_lock;
1710 debug->keyCacheVersion = info.kcVersion;
1711 debug->keyCacheSize = info.kcSize;
1712 debug->keyCacheUsed = info.kcUsed;
1713 for(i=0;i<info.kcUsed;i++) {
1714 debug->keyCache[i].lastUsed = info.kcInfo[i].used;
1715 debug->keyCache[i].keyVersionNumber = info.kcInfo[i].kvno;
1716 debug->keyCache[i].primary = info.kcInfo[i].primary;
1717 debug->keyCache[i].keyCheckSum = info.kcInfo[i].keycksum;
1718 strcpy(debug->keyCache[i].principal,info.kcInfo[i].principal);
1722 fail_kas_ServerDebugGet:
1731 * kas_ServerRandomKeyGet - get a random key from a server.
1735 * IN cellHandle - a cellHandle previously returned by afsclient_CellOpen.
1737 * IN serverHandle - a serverHandle previously returned by kas_ServerOpen.
1739 * OUT key - a random key.
1743 * No locks are held by this function.
1747 * Returns != 0 upon successful completion.
1750 int ADMINAPI kas_ServerRandomKeyGet(
1751 const void *cellHandle,
1752 const void *serverHandle,
1753 kas_encryptionKey_p key,
1757 afs_status_t tst = 0;
1758 afs_cell_handle_p c_handle = (afs_cell_handle_p) cellHandle;
1759 kas_server_p k_handle = (kas_server_p) serverHandle;
1760 kas_server_t kaserver;
1763 * Validate input arguments and make rpc.
1767 tst = ADMKASKEYNULL;
1768 goto fail_kas_ServerRandomKeyGet;
1771 if (!ChooseValidServer(c_handle, k_handle, &kaserver, &tst)) {
1772 goto fail_kas_ServerRandomKeyGet;
1775 tst = ubik_Call(KAM_GetRandomKey, kaserver.servers, 0, key);
1777 goto fail_kas_ServerRandomKeyGet;
1781 fail_kas_ServerRandomKeyGet:
1790 * kas_StringToKey - turn a string key into a key.
1794 * IN cellName - the name of the cell where the key will be used.
1796 * IN string - the string to be converted.
1798 * OUT key - the encryption key.
1802 * No locks are held by this function.
1806 * Returns != 0 upon successful completion.
1809 int ADMINAPI kas_StringToKey(
1810 const char *cellName,
1812 kas_encryptionKey_p key,
1816 afs_status_t tst = 0;
1818 ka_StringToKey(string, cellName, (struct ktc_encryptionKey *) key);
1829 * kas_KeyCheckSum - compute the checksum of an encryption key.
1833 * IN key - the encryption key.
1835 * OUT cksumP - key checksum
1839 * No locks are held by this function.
1843 * Returns != 0 upon successful completion.
1846 int ADMINAPI kas_KeyCheckSum(
1847 const kas_encryptionKey_p key,
1848 unsigned int *cksumP,
1852 afs_status_t tst = 0;
1855 if ((tst = ka_KeyCheckSum((char *)key, &cksum32)) == 0) {