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 /* ticket caching code */
12 #include <afsconfig.h>
13 #include <afs/param.h>
20 #include <afs/pthread_glock.h>
22 #include <afs/smb_iocons.h>
23 #include <afs/pioctl_nt.h>
24 #include "afs/afsrpc.h"
27 #include <afs/afsutil.h>
30 /* TBUFFERSIZE must be at least 512 larger than KTCMAXTICKETSIZE */
31 #define TBUFFERSIZE 12512
33 /* Forward declarations for local token cache. */
34 static int SetLocalToken(struct ktc_principal *aserver,
35 struct ktc_token *atoken,
36 struct ktc_principal *aclient, afs_int32 flags);
37 static int GetLocalToken(struct ktc_principal *aserver,
38 struct ktc_token *atoken, int atokenLen,
39 struct ktc_principal *aclient);
40 static int ForgetLocalTokens();
41 static int ForgetOneLocalToken(struct ktc_principal *aserver);
44 static char AFSConfigKeyName[] =
45 "SYSTEM\\CurrentControlSet\\Services\\TransarcAFSDaemon\\Parameters";
47 static char AFSGlobalKTCMutexName[] = "Global\\AFS_KTC_Mutex";
48 static char AFSKTCMutexName[] = "AFS_KTC_Mutex";
50 #define MAXPIOCTLTOKENLEN \
51 (3*sizeof(afs_int32)+MAXKTCTICKETLEN+sizeof(struct ClearToken)+MAXKTCREALMLEN)
54 * Support for RPC's to send and receive session keys
56 * Session keys must not be sent and received in the clear. We have no
57 * way to piggyback encryption on SMB, so we use a separate RPC, using
58 * packet privacy (when available). In SetToken, the RPC is done first;
59 * in GetToken, the pioctl is done first.
64 void __RPC_FAR *__RPC_USER
65 midl_user_allocate(size_t cBytes)
67 return malloc(cBytes);
71 midl_user_free(void __RPC_FAR * p)
77 * Determine the server name to be used in the RPC binding. If it is
78 * the same as the client (i.e. standalone, non-gateway), NULL can be
79 * used, so it is not necessary to call gethostbyname().
82 getservername(char **snp, unsigned int snSize)
88 RegOpenKeyEx(HKEY_LOCAL_MACHINE, AFSConfigKeyName, 0, KEY_QUERY_VALUE,
90 if (code != ERROR_SUCCESS)
92 code = RegQueryValueEx(parmKey, "Gateway", NULL, NULL, *snp, &snSize);
94 if (code == ERROR_SUCCESS)
97 /* No gateway name in registry; use ourself */
102 send_key(afs_uuid_t uuid, char sessionKey[8])
105 char *stringBinding = NULL;
106 ULONG authnLevel, authnSvc;
107 char serverName[256];
108 char *serverNamep = serverName;
110 BOOL encryptionOff = FALSE;
113 /* Encryption on by default */
114 if (GetEnvironmentVariable("AFS_RPC_ENCRYPT", encrypt, sizeof(encrypt)))
115 if (!_stricmp(encrypt, "OFF"))
116 encryptionOff = TRUE;
118 /* Protocol sequence is local by default */
119 if (!GetEnvironmentVariable("AFS_RPC_PROTSEQ", protseq, sizeof(protseq)))
120 strcpy(protseq, "ncalrpc");
123 getservername(&serverNamep, sizeof(serverName));
125 status = RpcStringBindingCompose("", /* obj uuid */
126 protseq, serverNamep, "", /* endpoint */
127 "", /* protocol options */
129 if (status != RPC_S_OK)
132 status = RpcBindingFromStringBinding(stringBinding, &hAfsHandle);
133 if (status != RPC_S_OK)
137 * On Windows 95/98, we must resolve the binding before calling
138 * SetAuthInfo. On Windows NT, we don't have to resolve yet,
139 * but it does no harm.
141 status = RpcEpResolveBinding(hAfsHandle, afsrpc_v1_0_c_ifspec);
142 if (status != RPC_S_OK)
146 authnLevel = RPC_C_AUTHN_LEVEL_NONE;
147 authnSvc = RPC_C_AUTHN_WINNT;
149 authnLevel = RPC_C_AUTHN_LEVEL_PKT_PRIVACY;
150 authnSvc = RPC_C_AUTHN_WINNT;
154 RpcBindingSetAuthInfo(hAfsHandle, NULL, authnLevel, authnSvc, NULL,
156 if (status != RPC_S_OK)
160 status = AFSRPC_SetToken(uuid, sessionKey);
163 status = RpcExceptionCode();
165 RpcEndExcept cleanup:if (stringBinding)
166 RpcStringFree(&stringBinding);
168 if (hAfsHandle != NULL)
169 RpcBindingFree(&hAfsHandle);
175 receive_key(afs_uuid_t uuid, char sessionKey[8])
178 char *stringBinding = NULL;
179 ULONG authnLevel, authnSvc;
180 char serverName[256];
181 char *serverNamep = serverName;
183 BOOL encryptionOff = FALSE;
186 /* Encryption on by default */
187 if (GetEnvironmentVariable("AFS_RPC_ENCRYPT", encrypt, sizeof(encrypt)))
188 if (!_stricmp(encrypt, "OFF"))
189 encryptionOff = TRUE;
191 /* Protocol sequence is local by default */
192 if (!GetEnvironmentVariable("AFS_RPC_PROTSEQ", protseq, sizeof(protseq)))
193 strcpy(protseq, "ncalrpc");
196 getservername(&serverNamep, sizeof(serverName));
198 status = RpcStringBindingCompose("", /* obj uuid */
199 protseq, serverNamep, "", /* endpoint */
200 "", /* protocol options */
202 if (status != RPC_S_OK)
205 status = RpcBindingFromStringBinding(stringBinding, &hAfsHandle);
206 if (status != RPC_S_OK)
210 * On Windows 95/98, we must resolve the binding before calling
211 * SetAuthInfo. On Windows NT, we don't have to resolve yet,
212 * but it does no harm.
214 status = RpcEpResolveBinding(hAfsHandle, afsrpc_v1_0_c_ifspec);
215 if (status != RPC_S_OK)
219 authnLevel = RPC_C_AUTHN_LEVEL_NONE;
220 authnSvc = RPC_C_AUTHN_WINNT;
222 authnLevel = RPC_C_AUTHN_LEVEL_PKT_PRIVACY;
223 authnSvc = RPC_C_AUTHN_WINNT;
227 RpcBindingSetAuthInfo(hAfsHandle, NULL, authnLevel, authnSvc, NULL,
229 if (status != RPC_S_OK)
233 status = AFSRPC_GetToken(uuid, sessionKey);
236 status = RpcExceptionCode();
238 RpcEndExcept cleanup:if (stringBinding)
239 RpcStringFree(&stringBinding);
241 if (hAfsHandle != NULL)
242 RpcBindingFree(&hAfsHandle);
248 ktc_SetToken(struct ktc_principal *server, struct ktc_token *token,
249 struct ktc_principal *client, int flags)
251 struct ViceIoctl iob;
252 char tbuffer[TBUFFERSIZE];
255 struct ClearToken ct;
260 HANDLE ktcMutex = NULL;
262 if (token->ticketLen < MINKTCTICKETLEN
263 || token->ticketLen > MAXKTCTICKETLEN)
266 if (strcmp(server->name, "afs")) {
267 return SetLocalToken(server, token, client, flags);
273 memcpy(tp, &token->ticketLen, sizeof(token->ticketLen));
274 tp += sizeof(token->ticketLen);
275 len = sizeof(token->ticketLen);
278 if (len + token->ticketLen > TBUFFERSIZE)
280 memcpy(tp, token->ticket, token->ticketLen);
281 tp += token->ticketLen;
282 len += token->ticketLen;
285 ct.AuthHandle = token->kvno;
287 * Instead of sending the session key in the clear, we zero it,
288 * and send it later, via RPC, encrypted.
290 #ifndef AFS_WIN95_ENV
292 * memcpy(ct.HandShakeKey, &token->sessionKey, sizeof(token->sessionKey));
294 memset(ct.HandShakeKey, 0, sizeof(ct.HandShakeKey));
296 memcpy(ct.HandShakeKey, &token->sessionKey, sizeof(token->sessionKey));
298 ct.BeginTimestamp = token->startTime;
299 ct.EndTimestamp = token->endTime;
300 if (ct.BeginTimestamp == 0)
301 ct.BeginTimestamp = 1;
303 /* We don't know from Vice ID's yet */
304 ct.ViceId = 37; /* XXX */
305 if (((ct.EndTimestamp - ct.BeginTimestamp) & 1) == 1)
306 ct.BeginTimestamp++; /* force lifetime to be even */
308 /* size of clear token */
309 if (len + sizeof(temp) > TBUFFERSIZE)
311 temp = sizeof(struct ClearToken);
312 memcpy(tp, &temp, sizeof(temp));
316 /* clear token itself */
317 if (len + sizeof(ct) > TBUFFERSIZE)
319 memcpy(tp, &ct, sizeof(ct));
323 /* flags; on NT there is no setpag flag, but there is an
324 * integrated logon flag */
325 if (len + sizeof(temp) > TBUFFERSIZE)
327 temp = ((flags & AFS_SETTOK_LOGON) ? PIOCTL_LOGON : 0);
328 memcpy(tp, &temp, sizeof(temp));
333 temp = (int)strlen(server->cell) + 1;
334 if (len + temp > TBUFFERSIZE ||
335 temp > MAXKTCREALMLEN)
337 strcpy(tp, server->cell);
342 temp = (int)strlen(client->name) + 1;
343 if (len + temp > TBUFFERSIZE ||
344 temp > MAXKTCNAMELEN)
346 strcpy(tp, client->name);
350 /* we need the SMB user name to associate the tokens with in the
351 * integrated logon case. */
352 if (flags & AFS_SETTOK_LOGON) {
353 if (client->smbname == NULL)
356 temp = (int)strlen(client->smbname) + 1;
358 len + temp > TBUFFERSIZE ||
359 temp > MAXKTCNAMELEN)
361 strcpy(tp, client->smbname);
367 if (len + sizeof(uuid) > TBUFFERSIZE)
369 status = UuidCreate((UUID *) & uuid);
370 memcpy(tp, &uuid, sizeof(uuid));
374 ktcMutex = CreateMutex(NULL, TRUE, AFSGlobalKTCMutexName);
375 if (ktcMutex == NULL)
376 return KTC_TOKEN_MUTEX_FAIL;
377 if (GetLastError() == ERROR_ALREADY_EXISTS) {
378 if (WaitForSingleObject(ktcMutex, INFINITE) != WAIT_OBJECT_0) {
379 CloseHandle(ktcMutex);
380 return KTC_TOKEN_MUTEX_FAIL;
384 /* RPC to send session key */
385 status = send_key(uuid, token->sessionKey.data);
386 if (status != RPC_S_OK) {
388 strcpy(rpcErr, "RPC failure in AFS gateway");
390 DceErrorInqText(status, rpcErr);
392 ReleaseMutex(ktcMutex);
393 CloseHandle(ktcMutex);
395 if (status == RPC_S_SERVER_UNAVAILABLE ||
396 status == EPT_S_NOT_REGISTERED) {
403 /* set up for pioctl */
405 iob.in_size = (long)(tp - tbuffer);
407 iob.out_size = sizeof(tbuffer);
409 code = pioctl(0, VIOCSETTOK, &iob, 0);
411 ReleaseMutex(ktcMutex);
412 CloseHandle(ktcMutex);
418 else if (errno == ENODEV)
420 else if (errno == EINVAL)
423 return KTC_PIOCTLFAIL;
425 return KTC_PIOCTLFAIL;
432 ktc_SetTokenEx(struct ktc_setTokenData *token)
434 /* Not yet implemented */
435 return KTC_PIOCTLFAIL;
439 ktc_GetToken(struct ktc_principal *server, struct ktc_token *token,
440 int tokenLen, struct ktc_principal *client)
442 struct ViceIoctl iob;
443 char tbuffer[TBUFFERSIZE];
448 struct ClearToken ct;
455 HANDLE ktcMutex = NULL;
459 /* check to see if the user is requesting tokens for a principal
460 * other than afs. If so, check the local token cache.
462 if (strcmp(server->name, "afs")) {
463 return GetLocalToken(server, token, tokenLen, client);
467 len = strlen(server->cell) + 1;
468 strcpy(tp, server->cell);
472 status = UuidCreate((UUID *) & uuid);
473 memcpy(tp, &uuid, sizeof(uuid));
478 iob.in_size = (long)(tp - tbuffer);
480 iob.out_size = sizeof(tbuffer);
482 ktcMutex = CreateMutex(NULL, TRUE, AFSGlobalKTCMutexName);
483 if (ktcMutex == NULL)
484 return KTC_TOKEN_MUTEX_FAIL;
485 if (GetLastError() == ERROR_ALREADY_EXISTS) {
486 if (WaitForSingleObject(ktcMutex, INFINITE) != WAIT_OBJECT_0) {
487 CloseHandle(ktcMutex);
488 return KTC_TOKEN_MUTEX_FAIL;
492 code = pioctl(0, VIOCNEWGETTOK, &iob, 0);
494 ReleaseMutex(ktcMutex);
495 CloseHandle(ktcMutex);
500 else if (errno == ENODEV)
502 else if (errno == EINVAL)
504 else if (errno == EDOM)
507 return KTC_PIOCTLFAIL;
509 return KTC_PIOCTLFAIL;
512 /* RPC to receive session key */
513 status = receive_key(uuid, token->sessionKey.data);
515 ReleaseMutex(ktcMutex);
516 CloseHandle(ktcMutex);
518 if (status != RPC_S_OK) {
520 strcpy(rpcErr, "RPC failure in AFS gateway");
522 DceErrorInqText(status, rpcErr);
524 if (status == RPC_S_SERVER_UNAVAILABLE ||
525 status == EPT_S_NOT_REGISTERED)
534 memcpy(&ticketLen, cp, sizeof(ticketLen));
535 cp += sizeof(ticketLen);
536 len = sizeof(ticketLen);
538 /* remember where ticket is and skip over it */
539 if (len + ticketLen > TBUFFERSIZE ||
540 len + ticketLen > iob.out_size)
546 /* size of clear token */
547 if (len + sizeof(temp) > TBUFFERSIZE ||
548 len + sizeof(temp) > iob.out_size)
550 memcpy(&temp, cp, sizeof(temp));
553 if (temp != sizeof(ct))
557 if (len + temp > TBUFFERSIZE ||
558 len + temp > iob.out_size)
560 memcpy(&ct, cp, temp);
564 /* skip over primary flag */
565 if (len + sizeof(temp) > TBUFFERSIZE ||
566 len + sizeof(temp) > iob.out_size)
571 /* remember cell name and skip over it */
573 cellNameSize = (int)strlen(cp);
574 if (len + cellNameSize + 1 > TBUFFERSIZE ||
575 len + cellNameSize + 1 > iob.out_size)
577 cp += cellNameSize + 1;
578 len += cellNameSize + 1;
580 /* user name is here */
582 /* check that ticket will fit
583 * this compares the size of the ktc_token allocated by the app
584 * which might be smaller than the current definition of MAXKTCTICKETLEN
586 maxLen = tokenLen - sizeof(struct ktc_token) + MAXKTCTICKETLEN;
587 if (maxLen < ticketLen)
590 /* set return values */
591 memcpy(token->ticket, ticketP, ticketLen);
592 token->startTime = ct.BeginTimestamp;
593 token->endTime = ct.EndTimestamp;
594 if (ct.AuthHandle == -1)
596 token->kvno = ct.AuthHandle;
597 #ifndef AFS_WIN95_ENV
599 * Session key has already been set via RPC
602 memcpy(&token->sessionKey, ct.HandShakeKey, sizeof(ct.HandShakeKey));
603 #endif /* AFS_WIN95_ENV */
604 token->ticketLen = ticketLen;
606 strcpy(client->name, cp);
607 client->instance[0] = '\0';
608 strcpy(client->cell, cellName);
615 * Get a token, given the cell that we need to get information for
618 * The name of the cell we're getting the token for - if NULL, we'll
619 * get information for the primary cell
622 ktc_GetTokenEx(char *cellName, struct ktc_setTokenData **tokenSet) {
623 struct ViceIoctl iob;
624 char tbuffer[MAXPIOCTLTOKENLEN];
628 HANDLE ktcMutex = NULL;
632 /* If we have a cellName, write it out here */
634 memcpy(tp, cellName, strlen(cellName) +1);
635 tp += strlen(cellName)+1;
639 iob.in_size = tp - tbuffer;
641 iob.out_size = sizeof(tbuffer);
643 ktcMutex = CreateMutex(NULL, TRUE, AFSGlobalKTCMutexName);
644 if (ktcMutex == NULL)
645 return KTC_TOKEN_MUTEX_FAIL;
646 if (GetLastError() == ERROR_ALREADY_EXISTS) {
647 if (WaitForSingleObject(ktcMutex, INFINITE) != WAIT_OBJECT_0) {
648 CloseHandle(ktcMutex);
649 return KTC_TOKEN_MUTEX_FAIL;
654 code = pioctl(0, VIOC_GETTOK2, &iob, 0);
656 code = -1; /* not yet implemented */
660 ReleaseMutex(ktcMutex);
661 CloseHandle(ktcMutex);
663 /* If we can't use the new pioctl, the fall back to the old one. We then
664 * need to convert the rxkad token we get back into the new format
666 if (code == -1 && errno == EINVAL) {
667 struct ktc_principal server;
668 struct ktc_principal client;
669 struct ktc_tokenUnion token;
670 struct ktc_token *ktcToken; /* too huge for the stack */
672 memset(&server, 0, sizeof(server));
673 ktcToken = malloc(sizeof(struct ktc_token));
674 if (ktcToken == NULL)
676 memset(ktcToken, 0, sizeof(struct ktc_token));
678 strcpy(server.name, "afs");
679 strcpy(server.cell, cellName);
680 code = ktc_GetToken(&server, ktcToken, sizeof(struct ktc_token),
683 *tokenSet = token_buildTokenJar(cellName);
684 token.at_type = AFSTOKEN_UNION_KAD;
685 token.ktc_tokenUnion_u.at_kad.rk_kvno = ktcToken->kvno;
686 memcpy(token.ktc_tokenUnion_u.at_kad.rk_key,
687 ktcToken->sessionKey.data, 8);
689 token.ktc_tokenUnion_u.at_kad.rk_begintime = ktcToken->startTime;
690 token.ktc_tokenUnion_u.at_kad.rk_endtime = ktcToken->endTime;
691 token.ktc_tokenUnion_u.at_kad.rk_ticket.rk_ticket_len
692 = ktcToken->ticketLen;
693 token.ktc_tokenUnion_u.at_kad.rk_ticket.rk_ticket_val
696 token_addToken(*tokenSet, &token);
698 memset(ktcToken, 0, sizeof(struct ktc_token));
704 return KTC_PIOCTLFAIL;
706 *tokenSet = malloc(sizeof(struct ktc_setTokenData));
707 if (*tokenSet == NULL)
709 memset(*tokenSet, 0, sizeof(struct ktc_setTokenData));
711 xdrmem_create(&xdrs, iob.out, iob.out_size, XDR_DECODE);
712 if (!xdr_ktc_setTokenData(&xdrs, *tokenSet)) {
723 ktc_ListTokens(int cellNum, int *cellNumP, struct ktc_principal *server)
725 struct ViceIoctl iob;
726 char tbuffer[TBUFFERSIZE];
729 int newIter, ticketLen, temp;
731 HANDLE ktcMutex = NULL;
733 ktcMutex = CreateMutex(NULL, TRUE, AFSGlobalKTCMutexName);
734 if (ktcMutex == NULL)
735 return KTC_TOKEN_MUTEX_FAIL;
736 if (GetLastError() == ERROR_ALREADY_EXISTS) {
737 if (WaitForSingleObject(ktcMutex, INFINITE) != WAIT_OBJECT_0) {
738 CloseHandle(ktcMutex);
739 return KTC_TOKEN_MUTEX_FAIL;
746 memcpy(tp, &cellNum, sizeof(cellNum));
747 tp += sizeof(cellNum);
751 iob.in_size = (long)(tp - tbuffer);
753 iob.out_size = sizeof(tbuffer);
755 code = pioctl(0, VIOCGETTOK, &iob, 0);
757 ReleaseMutex(ktcMutex);
758 CloseHandle(ktcMutex);
764 else if (errno == ENODEV)
766 else if (errno == EINVAL)
768 else if (errno == EDOM)
771 return KTC_PIOCTLFAIL;
773 return KTC_PIOCTLFAIL;
779 memcpy(&newIter, cp, sizeof(newIter));
780 cp += sizeof(newIter);
781 len = sizeof(newIter);
784 if (len + sizeof(ticketLen) > TBUFFERSIZE ||
785 len + sizeof(ticketLen) > iob.out_size)
787 memcpy(&ticketLen, cp, sizeof(ticketLen));
788 cp += sizeof(ticketLen);
789 len += sizeof(ticketLen);
791 /* skip over ticket */
795 /* clear token size */
796 if (len + sizeof(temp) > TBUFFERSIZE ||
797 len + sizeof(temp) > iob.out_size)
799 memcpy(&temp, cp, sizeof(temp));
802 if (temp != sizeof(struct ClearToken))
805 /* skip over clear token */
806 cp += sizeof(struct ClearToken);
807 len += sizeof(struct ClearToken);
809 /* skip over primary flag */
812 if (len > TBUFFERSIZE ||
816 /* cell name is here */
818 /* set return values */
819 if (len + temp > TBUFFERSIZE ||
820 temp > MAXKTCREALMLEN)
822 strcpy(server->cell, cp);
823 server->instance[0] = '\0';
824 strcpy(server->name, "afs");
831 ktc_ForgetToken(struct ktc_principal *server)
833 struct ViceIoctl iob;
834 char tbuffer[TBUFFERSIZE];
837 HANDLE ktcMutex = NULL;
839 if (strcmp(server->name, "afs")) {
840 return ForgetOneLocalToken(server);
842 ktcMutex = CreateMutex(NULL, TRUE, AFSGlobalKTCMutexName);
843 if (ktcMutex == NULL)
844 return KTC_TOKEN_MUTEX_FAIL;
845 if (GetLastError() == ERROR_ALREADY_EXISTS) {
846 if (WaitForSingleObject(ktcMutex, INFINITE) != WAIT_OBJECT_0) {
847 CloseHandle(ktcMutex);
848 return KTC_TOKEN_MUTEX_FAIL;
855 strcpy(tp, server->cell);
856 tp += strlen(tp) + 1;
860 iob.in_size = (long)(tp - tbuffer);
862 iob.out_size = sizeof(tbuffer);
864 code = pioctl(0, VIOCDELTOK, &iob, 0);
865 ReleaseMutex(ktcMutex);
866 CloseHandle(ktcMutex);
872 else if (errno == EDOM)
874 else if (errno == ENODEV)
877 return KTC_PIOCTLFAIL;
879 return KTC_PIOCTLFAIL;
885 ktc_ForgetAllTokens()
887 struct ViceIoctl iob;
888 char tbuffer[TBUFFERSIZE];
890 HANDLE ktcMutex = NULL;
892 (void)ForgetLocalTokens();
894 ktcMutex = CreateMutex(NULL, TRUE, AFSGlobalKTCMutexName);
895 if (ktcMutex == NULL)
896 return KTC_TOKEN_MUTEX_FAIL;
897 if (GetLastError() == ERROR_ALREADY_EXISTS) {
898 if (WaitForSingleObject(ktcMutex, INFINITE) != WAIT_OBJECT_0) {
899 CloseHandle(ktcMutex);
900 return KTC_TOKEN_MUTEX_FAIL;
908 iob.out_size = sizeof(tbuffer);
910 code = pioctl(0, VIOCDELALLTOK, &iob, 0);
911 ReleaseMutex(ktcMutex);
912 CloseHandle(ktcMutex);
919 return KTC_PIOCTLFAIL;
921 return KTC_PIOCTLFAIL;
933 #define MAXLOCALTOKENS 4
937 struct ktc_principal server;
938 struct ktc_principal client;
939 struct ktc_token token;
940 } local_tokens[MAXLOCALTOKENS] = {
944 SetLocalToken(struct ktc_principal *aserver, struct ktc_token *atoken,
945 struct ktc_principal *aclient, afs_int32 flags)
951 for (i = 0; i < MAXLOCALTOKENS; i++)
952 if (local_tokens[i].valid) {
953 if ((strcmp(local_tokens[i].server.name, aserver->name) == 0)
954 && (strcmp(local_tokens[i].server.instance, aserver->instance)
956 && (strcmp(local_tokens[i].server.cell, aserver->cell) == 0)) {
957 found = i; /* replace existing entry */
960 } else if (found == -1)
961 found = i; /* remember empty slot but keep looking for a match */
966 memcpy(&local_tokens[found].token, atoken, sizeof(struct ktc_token));
967 memcpy(&local_tokens[found].server, aserver,
968 sizeof(struct ktc_principal));
969 memcpy(&local_tokens[found].client, aclient,
970 sizeof(struct ktc_principal));
971 local_tokens[found].valid = 1;
978 GetLocalToken(struct ktc_principal *aserver, struct ktc_token *atoken,
979 int atokenLen, struct ktc_principal *aclient)
984 for (i = 0; i < MAXLOCALTOKENS; i++)
985 if (local_tokens[i].valid
986 && (strcmp(local_tokens[i].server.name, aserver->name) == 0)
987 && (strcmp(local_tokens[i].server.instance, aserver->instance) ==
989 && (strcmp(local_tokens[i].server.cell, aserver->cell) == 0)) {
990 memcpy(atoken, &local_tokens[i].token,
991 min(atokenLen, sizeof(struct ktc_token)));
992 memcpy(aclient, &local_tokens[i].client,
993 sizeof(struct ktc_principal));
1008 for (i = 0; i < MAXLOCALTOKENS; i++) {
1009 local_tokens[i].valid = 0;
1010 memset(&local_tokens[i].token.sessionKey, 0,
1011 sizeof(struct ktc_encryptionKey));
1013 UNLOCK_GLOBAL_MUTEX;
1019 ForgetOneLocalToken(struct ktc_principal *aserver)
1024 for (i = 0; i < MAXLOCALTOKENS; i++) {
1025 if (local_tokens[i].valid
1026 && (strcmp(local_tokens[i].server.name, aserver->name) == 0)
1027 && (strcmp(local_tokens[i].server.instance, aserver->instance) ==
1029 && (strcmp(local_tokens[i].server.cell, aserver->cell) == 0)) {
1030 local_tokens[i].valid = 0;
1031 memset(&local_tokens[i].token.sessionKey, 0,
1032 sizeof(struct ktc_encryptionKey));
1033 UNLOCK_GLOBAL_MUTEX;
1037 UNLOCK_GLOBAL_MUTEX;
1042 * An iterator which can list all cells with tokens in the cache
1044 * This function may be used to list the names of all cells for which
1045 * tokens exist in the current cache. The first time that it is called,
1046 * prevIndex should be set to 0. On all subsequent calls, prevIndex
1047 * should be set to the value returned in newIndex by the last call
1048 * to the function. Note that there is no guarantee that the index value
1049 * is monotonically increasing.
1052 * The index returned by the last call, or 0 if this is the first
1053 * call in an iteration
1055 * A pointer to an int which, upon return, will hold the next value
1058 * A pointer to a char * which, upon return, will hold a cellname.
1059 * This must be freed by the caller using free()
1063 ktc_ListTokensEx(int prevIndex, int *newIndex, char **cellName) {
1064 struct ViceIoctl iob;
1065 char tbuffer[MAXPIOCTLTOKENLEN];
1068 struct ktc_setTokenData tokenSet;
1070 HANDLE ktcMutex = NULL;
1072 memset(&tokenSet, 0, sizeof(tokenSet));
1075 *newIndex = prevIndex;
1079 while (index<100) { /* Safety, incase of pioctl failure */
1080 memset(tbuffer, 0, sizeof(tbuffer));
1082 memcpy(tbuffer, &index, sizeof(afs_int32));
1083 iob.in_size = sizeof(afs_int32);
1085 iob.out_size = sizeof(tbuffer);
1088 code = pioctl(0, VIOC_GETTOK2, &iob, 0);
1090 code = -1; /* not yet implemented */
1094 /* Can't use new pioctl, so must use old one */
1095 if (code == -1 && errno == EINVAL) {
1096 struct ktc_principal server;
1098 code = ktc_ListTokens(index, newIndex, &server);
1100 *cellName = strdup(server.cell);
1105 /* Got a token from the pioctl. Now we throw it away,
1106 * so we can return just a cellname. This is rather wasteful,
1107 * but it's what the old API does. Ho hum. */
1109 xdrmem_create(&xdrs, iob.out, iob.out_size, XDR_DECODE);
1110 if (!xdr_ktc_setTokenData(&xdrs, &tokenSet)) {
1115 *cellName = strdup(tokenSet.cell);
1116 xdr_free((xdrproc_t)xdr_ktc_setTokenData, &tokenSet);
1117 *newIndex = index + 1;
1122 return KTC_PIOCTLFAIL;