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>
19 #include <afs/pthread_glock.h>
20 #include <sys/types.h>
26 #include <afs/smb_iocons.h>
27 #include <afs/pioctl_nt.h>
28 #include "afs/afsrpc.h"
31 #include <afs/afsutil.h>
34 /* TBUFFERSIZE must be at least 512 larger than KTCMAXTICKETSIZE */
35 #define TBUFFERSIZE 12512
37 /* Forward declarations for local token cache. */
38 static int SetLocalToken(struct ktc_principal *aserver,
39 struct ktc_token *atoken,
40 struct ktc_principal *aclient, afs_int32 flags);
41 static int GetLocalToken(struct ktc_principal *aserver,
42 struct ktc_token *atoken, int atokenLen,
43 struct ktc_principal *aclient);
44 static int ForgetLocalTokens();
45 static int ForgetOneLocalToken(struct ktc_principal *aserver);
48 static char AFSConfigKeyName[] =
49 "SYSTEM\\CurrentControlSet\\Services\\TransarcAFSDaemon\\Parameters";
51 static char AFSGlobalKTCMutexName[] = "Global\\AFS_KTC_Mutex";
52 static char AFSKTCMutexName[] = "AFS_KTC_Mutex";
54 #define MAXPIOCTLTOKENLEN \
55 (3*sizeof(afs_int32)+MAXKTCTICKETLEN+sizeof(struct ClearToken)+MAXKTCREALMLEN)
58 * Support for RPC's to send and receive session keys
60 * Session keys must not be sent and received in the clear. We have no
61 * way to piggyback encryption on SMB, so we use a separate RPC, using
62 * packet privacy (when available). In SetToken, the RPC is done first;
63 * in GetToken, the pioctl is done first.
68 void __RPC_FAR *__RPC_USER
69 midl_user_allocate(size_t cBytes)
71 return ((void __RPC_FAR *)malloc(cBytes));
75 midl_user_free(void __RPC_FAR * p)
81 * Determine the server name to be used in the RPC binding. If it is
82 * the same as the client (i.e. standalone, non-gateway), NULL can be
83 * used, so it is not necessary to call gethostbyname().
86 getservername(char **snp, unsigned int snSize)
92 RegOpenKeyEx(HKEY_LOCAL_MACHINE, AFSConfigKeyName, 0, KEY_QUERY_VALUE,
94 if (code != ERROR_SUCCESS)
96 code = RegQueryValueEx(parmKey, "Gateway", NULL, NULL, *snp, &snSize);
98 if (code == ERROR_SUCCESS)
101 /* No gateway name in registry; use ourself */
106 send_key(afs_uuid_t uuid, char sessionKey[8])
109 char *stringBinding = NULL;
110 ULONG authnLevel, authnSvc;
111 char serverName[256];
112 char *serverNamep = serverName;
114 BOOL encryptionOff = FALSE;
117 /* Encryption on by default */
118 if (GetEnvironmentVariable("AFS_RPC_ENCRYPT", encrypt, sizeof(encrypt)))
119 if (!_stricmp(encrypt, "OFF"))
120 encryptionOff = TRUE;
122 /* Protocol sequence is local by default */
123 if (!GetEnvironmentVariable("AFS_RPC_PROTSEQ", protseq, sizeof(protseq)))
124 strcpy(protseq, "ncalrpc");
127 getservername(&serverNamep, sizeof(serverName));
129 status = RpcStringBindingCompose("", /* obj uuid */
130 protseq, serverNamep, "", /* endpoint */
131 "", /* protocol options */
133 if (status != RPC_S_OK)
136 status = RpcBindingFromStringBinding(stringBinding, &hAfsHandle);
137 if (status != RPC_S_OK)
141 * On Windows 95/98, we must resolve the binding before calling
142 * SetAuthInfo. On Windows NT, we don't have to resolve yet,
143 * but it does no harm.
145 status = RpcEpResolveBinding(hAfsHandle, afsrpc_v1_0_c_ifspec);
146 if (status != RPC_S_OK)
150 authnLevel = RPC_C_AUTHN_LEVEL_NONE;
151 authnSvc = RPC_C_AUTHN_WINNT;
153 authnLevel = RPC_C_AUTHN_LEVEL_PKT_PRIVACY;
154 authnSvc = RPC_C_AUTHN_WINNT;
158 RpcBindingSetAuthInfo(hAfsHandle, NULL, authnLevel, authnSvc, NULL,
160 if (status != RPC_S_OK)
164 status = AFSRPC_SetToken(uuid, sessionKey);
167 status = RpcExceptionCode();
169 RpcEndExcept cleanup:if (stringBinding)
170 RpcStringFree(&stringBinding);
172 if (hAfsHandle != NULL)
173 RpcBindingFree(&hAfsHandle);
179 receive_key(afs_uuid_t uuid, char sessionKey[8])
182 char *stringBinding = NULL;
183 ULONG authnLevel, authnSvc;
184 char serverName[256];
185 char *serverNamep = serverName;
187 BOOL encryptionOff = FALSE;
190 /* Encryption on by default */
191 if (GetEnvironmentVariable("AFS_RPC_ENCRYPT", encrypt, sizeof(encrypt)))
192 if (!_stricmp(encrypt, "OFF"))
193 encryptionOff = TRUE;
195 /* Protocol sequence is local by default */
196 if (!GetEnvironmentVariable("AFS_RPC_PROTSEQ", protseq, sizeof(protseq)))
197 strcpy(protseq, "ncalrpc");
200 getservername(&serverNamep, sizeof(serverName));
202 status = RpcStringBindingCompose("", /* obj uuid */
203 protseq, serverNamep, "", /* endpoint */
204 "", /* protocol options */
206 if (status != RPC_S_OK)
209 status = RpcBindingFromStringBinding(stringBinding, &hAfsHandle);
210 if (status != RPC_S_OK)
214 * On Windows 95/98, we must resolve the binding before calling
215 * SetAuthInfo. On Windows NT, we don't have to resolve yet,
216 * but it does no harm.
218 status = RpcEpResolveBinding(hAfsHandle, afsrpc_v1_0_c_ifspec);
219 if (status != RPC_S_OK)
223 authnLevel = RPC_C_AUTHN_LEVEL_NONE;
224 authnSvc = RPC_C_AUTHN_WINNT;
226 authnLevel = RPC_C_AUTHN_LEVEL_PKT_PRIVACY;
227 authnSvc = RPC_C_AUTHN_WINNT;
231 RpcBindingSetAuthInfo(hAfsHandle, NULL, authnLevel, authnSvc, NULL,
233 if (status != RPC_S_OK)
237 status = AFSRPC_GetToken(uuid, sessionKey);
240 status = RpcExceptionCode();
242 RpcEndExcept cleanup:if (stringBinding)
243 RpcStringFree(&stringBinding);
245 if (hAfsHandle != NULL)
246 RpcBindingFree(&hAfsHandle);
252 ktc_SetToken(struct ktc_principal *server, struct ktc_token *token,
253 struct ktc_principal *client, int flags)
255 struct ViceIoctl iob;
256 char tbuffer[TBUFFERSIZE];
259 struct ClearToken ct;
264 HANDLE ktcMutex = NULL;
266 if (token->ticketLen < MINKTCTICKETLEN
267 || token->ticketLen > MAXKTCTICKETLEN)
270 if (strcmp(server->name, "afs")) {
271 return SetLocalToken(server, token, client, flags);
277 memcpy(tp, &token->ticketLen, sizeof(token->ticketLen));
278 tp += sizeof(token->ticketLen);
279 len = sizeof(token->ticketLen);
282 if (len + token->ticketLen > TBUFFERSIZE)
284 memcpy(tp, token->ticket, token->ticketLen);
285 tp += token->ticketLen;
286 len += token->ticketLen;
289 ct.AuthHandle = token->kvno;
291 * Instead of sending the session key in the clear, we zero it,
292 * and send it later, via RPC, encrypted.
294 #ifndef AFS_WIN95_ENV
296 * memcpy(ct.HandShakeKey, &token->sessionKey, sizeof(token->sessionKey));
298 memset(ct.HandShakeKey, 0, sizeof(ct.HandShakeKey));
300 memcpy(ct.HandShakeKey, &token->sessionKey, sizeof(token->sessionKey));
302 ct.BeginTimestamp = token->startTime;
303 ct.EndTimestamp = token->endTime;
304 if (ct.BeginTimestamp == 0)
305 ct.BeginTimestamp = 1;
307 /* We don't know from Vice ID's yet */
308 ct.ViceId = 37; /* XXX */
309 if (((ct.EndTimestamp - ct.BeginTimestamp) & 1) == 1)
310 ct.BeginTimestamp++; /* force lifetime to be even */
312 /* size of clear token */
313 if (len + sizeof(temp) > TBUFFERSIZE)
315 temp = sizeof(struct ClearToken);
316 memcpy(tp, &temp, sizeof(temp));
320 /* clear token itself */
321 if (len + sizeof(ct) > TBUFFERSIZE)
323 memcpy(tp, &ct, sizeof(ct));
327 /* flags; on NT there is no setpag flag, but there is an
328 * integrated logon flag */
329 if (len + sizeof(temp) > TBUFFERSIZE)
331 temp = ((flags & AFS_SETTOK_LOGON) ? PIOCTL_LOGON : 0);
332 memcpy(tp, &temp, sizeof(temp));
337 temp = (int)strlen(server->cell) + 1;
338 if (len + temp > TBUFFERSIZE ||
339 temp > MAXKTCREALMLEN)
341 strcpy(tp, server->cell);
346 temp = (int)strlen(client->name) + 1;
347 if (len + temp > TBUFFERSIZE ||
348 temp > MAXKTCNAMELEN)
350 strcpy(tp, client->name);
354 /* we need the SMB user name to associate the tokens with in the
355 * integrated logon case. */
356 if (flags & AFS_SETTOK_LOGON) {
357 if (client->smbname == NULL)
360 temp = (int)strlen(client->smbname) + 1;
362 len + temp > TBUFFERSIZE ||
363 temp > MAXKTCNAMELEN)
365 strcpy(tp, client->smbname);
371 if (len + sizeof(uuid) > TBUFFERSIZE)
373 status = UuidCreate((UUID *) & uuid);
374 memcpy(tp, &uuid, sizeof(uuid));
378 #ifndef AFS_WIN95_ENV
379 ktcMutex = CreateMutex(NULL, TRUE, AFSGlobalKTCMutexName);
380 if (ktcMutex == NULL)
381 return KTC_PIOCTLFAIL;
382 if (GetLastError() == ERROR_ALREADY_EXISTS) {
383 if (WaitForSingleObject(ktcMutex, INFINITE) != WAIT_OBJECT_0) {
384 CloseHandle(ktcMutex);
385 return KTC_PIOCTLFAIL;
389 /* RPC to send session key */
390 status = send_key(uuid, token->sessionKey.data);
391 if (status != RPC_S_OK) {
393 strcpy(rpcErr, "RPC failure in AFS gateway");
395 DceErrorInqText(status, rpcErr);
396 if (status == RPC_S_SERVER_UNAVAILABLE ||
397 status == EPT_S_NOT_REGISTERED) {
398 ReleaseMutex(ktcMutex);
399 CloseHandle(ktcMutex);
402 ReleaseMutex(ktcMutex);
403 CloseHandle(ktcMutex);
407 #endif /* AFS_WIN95_ENV */
409 /* set up for pioctl */
411 iob.in_size = (long)(tp - tbuffer);
413 iob.out_size = sizeof(tbuffer);
415 code = pioctl(0, VIOCSETTOK, &iob, 0);
417 #ifndef AFS_WIN95_ENV
418 ReleaseMutex(ktcMutex);
419 CloseHandle(ktcMutex);
420 #endif /* AFS_WIN95_ENV */
426 else if (errno == ENODEV)
428 else if (errno == EINVAL)
431 return KTC_PIOCTLFAIL;
433 return KTC_PIOCTLFAIL;
440 ktc_SetTokenEx(struct ktc_setTokenData *token)
442 /* Not yet implemented */
443 return KTC_PIOCTLFAIL;
447 ktc_GetToken(struct ktc_principal *server, struct ktc_token *token,
448 int tokenLen, struct ktc_principal *client)
450 struct ViceIoctl iob;
451 char tbuffer[TBUFFERSIZE];
456 struct ClearToken ct;
463 HANDLE ktcMutex = NULL;
467 /* check to see if the user is requesting tokens for a principal
468 * other than afs. If so, check the local token cache.
470 if (strcmp(server->name, "afs")) {
471 return GetLocalToken(server, token, tokenLen, client);
475 len = strlen(server->cell) + 1;
476 strcpy(tp, server->cell);
480 status = UuidCreate((UUID *) & uuid);
481 memcpy(tp, &uuid, sizeof(uuid));
486 iob.in_size = (long)(tp - tbuffer);
488 iob.out_size = sizeof(tbuffer);
490 #ifndef AFS_WIN95_ENV
491 ktcMutex = CreateMutex(NULL, TRUE, AFSGlobalKTCMutexName);
492 if (ktcMutex == NULL)
493 return KTC_PIOCTLFAIL;
494 if (GetLastError() == ERROR_ALREADY_EXISTS) {
495 if (WaitForSingleObject(ktcMutex, INFINITE) != WAIT_OBJECT_0) {
496 CloseHandle(ktcMutex);
497 return KTC_PIOCTLFAIL;
500 #endif /* AFS_WIN95_ENV */
502 code = pioctl(0, VIOCNEWGETTOK, &iob, 0);
504 #ifndef AFS_WIN95_ENV
505 ReleaseMutex(ktcMutex);
506 CloseHandle(ktcMutex);
507 #endif /* AFS_WIN95_ENV */
511 else if (errno == ENODEV)
513 else if (errno == EINVAL)
515 else if (errno == EDOM)
518 return KTC_PIOCTLFAIL;
520 return KTC_PIOCTLFAIL;
522 #ifndef AFS_WIN95_ENV
523 /* get rid of RPC for win95 build */
524 /* RPC to receive session key */
525 status = receive_key(uuid, token->sessionKey.data);
527 ReleaseMutex(ktcMutex);
528 CloseHandle(ktcMutex);
530 if (status != RPC_S_OK) {
532 strcpy(rpcErr, "RPC failure in AFS gateway");
534 DceErrorInqText(status, rpcErr);
535 if (status == RPC_S_SERVER_UNAVAILABLE
536 || status == EPT_S_NOT_REGISTERED)
541 #endif /* AFS_WIN95_ENV */
546 memcpy(&ticketLen, cp, sizeof(ticketLen));
547 cp += sizeof(ticketLen);
548 len = sizeof(ticketLen);
550 /* remember where ticket is and skip over it */
551 if (len + ticketLen > TBUFFERSIZE ||
552 len + ticketLen > iob.out_size)
558 /* size of clear token */
559 if (len + sizeof(temp) > TBUFFERSIZE ||
560 len + sizeof(temp) > iob.out_size)
562 memcpy(&temp, cp, sizeof(temp));
565 if (temp != sizeof(ct))
569 if (len + temp > TBUFFERSIZE ||
570 len + temp > iob.out_size)
572 memcpy(&ct, cp, temp);
576 /* skip over primary flag */
577 if (len + sizeof(temp) > TBUFFERSIZE ||
578 len + sizeof(temp) > iob.out_size)
583 /* remember cell name and skip over it */
585 cellNameSize = (int)strlen(cp);
586 if (len + cellNameSize + 1 > TBUFFERSIZE ||
587 len + cellNameSize + 1 > iob.out_size)
589 cp += cellNameSize + 1;
590 len += cellNameSize + 1;
592 /* user name is here */
594 /* check that ticket will fit
595 * this compares the size of the ktc_token allocated by the app
596 * which might be smaller than the current definition of MAXKTCTICKETLEN
598 maxLen = tokenLen - sizeof(struct ktc_token) + MAXKTCTICKETLEN;
599 if (maxLen < ticketLen)
602 /* set return values */
603 memcpy(token->ticket, ticketP, ticketLen);
604 token->startTime = ct.BeginTimestamp;
605 token->endTime = ct.EndTimestamp;
606 if (ct.AuthHandle == -1)
608 token->kvno = ct.AuthHandle;
609 #ifndef AFS_WIN95_ENV
611 * Session key has already been set via RPC
614 memcpy(&token->sessionKey, ct.HandShakeKey, sizeof(ct.HandShakeKey));
615 #endif /* AFS_WIN95_ENV */
616 token->ticketLen = ticketLen;
618 strcpy(client->name, cp);
619 client->instance[0] = '\0';
620 strcpy(client->cell, cellName);
627 * Get a token, given the cell that we need to get information for
630 * The name of the cell we're getting the token for - if NULL, we'll
631 * get information for the primary cell
634 ktc_GetTokenEx(char *cellName, struct ktc_setTokenData **tokenSet) {
635 struct ViceIoctl iob;
636 char tbuffer[MAXPIOCTLTOKENLEN];
640 HANDLE ktcMutex = NULL;
644 /* If we have a cellName, write it out here */
646 memcpy(tp, cellName, strlen(cellName) +1);
647 tp += strlen(cellName)+1;
651 iob.in_size = tp - tbuffer;
653 iob.out_size = sizeof(tbuffer);
655 #ifndef AFS_WIN95_ENV
656 ktcMutex = CreateMutex(NULL, TRUE, AFSGlobalKTCMutexName);
657 if (ktcMutex == NULL)
658 return KTC_PIOCTLFAIL;
659 if (GetLastError() == ERROR_ALREADY_EXISTS) {
660 if (WaitForSingleObject(ktcMutex, INFINITE) != WAIT_OBJECT_0) {
661 CloseHandle(ktcMutex);
662 return KTC_PIOCTLFAIL;
665 #endif /* AFS_WIN95_ENV */
668 code = pioctl(0, VIOC_GETTOK2, &iob, 0);
670 code = -1; /* not yet implemented */
674 #ifndef AFS_WIN95_ENV
675 ReleaseMutex(ktcMutex);
676 CloseHandle(ktcMutex);
677 #endif /* AFS_WIN95_ENV */
679 /* If we can't use the new pioctl, the fall back to the old one. We then
680 * need to convert the rxkad token we get back into the new format
682 if (code == -1 && errno == EINVAL) {
683 struct ktc_principal server;
684 struct ktc_principal client;
685 struct ktc_tokenUnion token;
686 struct ktc_token *ktcToken; /* too huge for the stack */
688 memset(&server, 0, sizeof(server));
689 ktcToken = malloc(sizeof(struct ktc_token));
690 if (ktcToken == NULL)
692 memset(ktcToken, 0, sizeof(struct ktc_token));
694 strcpy(server.name, "afs");
695 strcpy(server.cell, cellName);
696 code = ktc_GetToken(&server, ktcToken, sizeof(struct ktc_token),
699 *tokenSet = token_buildTokenJar(cellName);
700 token.at_type = AFSTOKEN_UNION_KAD;
701 token.ktc_tokenUnion_u.at_kad.rk_kvno = ktcToken->kvno;
702 memcpy(token.ktc_tokenUnion_u.at_kad.rk_key,
703 ktcToken->sessionKey.data, 8);
705 token.ktc_tokenUnion_u.at_kad.rk_begintime = ktcToken->startTime;
706 token.ktc_tokenUnion_u.at_kad.rk_endtime = ktcToken->endTime;
707 token.ktc_tokenUnion_u.at_kad.rk_ticket.rk_ticket_len
708 = ktcToken->ticketLen;
709 token.ktc_tokenUnion_u.at_kad.rk_ticket.rk_ticket_val
712 token_addToken(*tokenSet, &token);
714 memset(ktcToken, 0, sizeof(struct ktc_token));
720 return KTC_PIOCTLFAIL;
722 *tokenSet = malloc(sizeof(struct ktc_setTokenData));
723 if (*tokenSet == NULL)
725 memset(*tokenSet, 0, sizeof(struct ktc_setTokenData));
727 xdrmem_create(&xdrs, iob.out, iob.out_size, XDR_DECODE);
728 if (!xdr_ktc_setTokenData(&xdrs, *tokenSet)) {
739 ktc_ListTokens(int cellNum, int *cellNumP, struct ktc_principal *server)
741 struct ViceIoctl iob;
742 char tbuffer[TBUFFERSIZE];
745 int newIter, ticketLen, temp;
747 HANDLE ktcMutex = NULL;
749 #ifndef AFS_WIN95_ENV
750 ktcMutex = CreateMutex(NULL, TRUE, AFSGlobalKTCMutexName);
751 if (ktcMutex == NULL)
752 return KTC_PIOCTLFAIL;
753 if (GetLastError() == ERROR_ALREADY_EXISTS) {
754 if (WaitForSingleObject(ktcMutex, INFINITE) != WAIT_OBJECT_0) {
755 CloseHandle(ktcMutex);
756 return KTC_PIOCTLFAIL;
759 #endif /* AFS_WIN95_ENV */
764 memcpy(tp, &cellNum, sizeof(cellNum));
765 tp += sizeof(cellNum);
769 iob.in_size = (long)(tp - tbuffer);
771 iob.out_size = sizeof(tbuffer);
773 code = pioctl(0, VIOCGETTOK, &iob, 0);
775 #ifndef AFS_WIN95_ENV
776 ReleaseMutex(ktcMutex);
777 CloseHandle(ktcMutex);
778 #endif /* AFS_WIN95_ENV */
784 else if (errno == ENODEV)
786 else if (errno == EINVAL)
788 else if (errno == EDOM)
791 return KTC_PIOCTLFAIL;
793 return KTC_PIOCTLFAIL;
799 memcpy(&newIter, cp, sizeof(newIter));
800 cp += sizeof(newIter);
801 len = sizeof(newIter);
804 if (len + sizeof(ticketLen) > TBUFFERSIZE ||
805 len + sizeof(ticketLen) > iob.out_size)
807 memcpy(&ticketLen, cp, sizeof(ticketLen));
808 cp += sizeof(ticketLen);
809 len += sizeof(ticketLen);
811 /* skip over ticket */
815 /* clear token size */
816 if (len + sizeof(temp) > TBUFFERSIZE ||
817 len + sizeof(temp) > iob.out_size)
819 memcpy(&temp, cp, sizeof(temp));
822 if (temp != sizeof(struct ClearToken))
825 /* skip over clear token */
826 cp += sizeof(struct ClearToken);
827 len += sizeof(struct ClearToken);
829 /* skip over primary flag */
832 if (len > TBUFFERSIZE ||
836 /* cell name is here */
838 /* set return values */
839 if (len + temp > TBUFFERSIZE ||
840 temp > MAXKTCREALMLEN)
842 strcpy(server->cell, cp);
843 server->instance[0] = '\0';
844 strcpy(server->name, "afs");
851 ktc_ForgetToken(struct ktc_principal *server)
853 struct ViceIoctl iob;
854 char tbuffer[TBUFFERSIZE];
857 HANDLE ktcMutex = NULL;
859 if (strcmp(server->name, "afs")) {
860 return ForgetOneLocalToken(server);
862 #ifndef AFS_WIN95_ENV
863 ktcMutex = CreateMutex(NULL, TRUE, AFSGlobalKTCMutexName);
864 if (ktcMutex == NULL)
865 return KTC_PIOCTLFAIL;
866 if (GetLastError() == ERROR_ALREADY_EXISTS) {
867 if (WaitForSingleObject(ktcMutex, INFINITE) != WAIT_OBJECT_0) {
868 CloseHandle(ktcMutex);
869 return KTC_PIOCTLFAIL;
872 #endif /* AFS_WIN95_ENV */
877 strcpy(tp, server->cell);
878 tp += strlen(tp) + 1;
882 iob.in_size = (long)(tp - tbuffer);
884 iob.out_size = sizeof(tbuffer);
886 code = pioctl(0, VIOCDELTOK, &iob, 0);
887 #ifndef AFS_WIN95_ENV
888 ReleaseMutex(ktcMutex);
889 CloseHandle(ktcMutex);
890 #endif /* AFS_WIN95_ENV */
895 else if (errno == EDOM)
897 else if (errno == ENODEV)
900 return KTC_PIOCTLFAIL;
902 return KTC_PIOCTLFAIL;
908 ktc_ForgetAllTokens()
910 struct ViceIoctl iob;
911 char tbuffer[TBUFFERSIZE];
913 HANDLE ktcMutex = NULL;
915 (void)ForgetLocalTokens();
917 #ifndef AFS_WIN95_ENV
918 ktcMutex = CreateMutex(NULL, TRUE, AFSGlobalKTCMutexName);
919 if (ktcMutex == NULL)
920 return KTC_PIOCTLFAIL;
921 if (GetLastError() == ERROR_ALREADY_EXISTS) {
922 if (WaitForSingleObject(ktcMutex, INFINITE) != WAIT_OBJECT_0) {
923 CloseHandle(ktcMutex);
924 return KTC_PIOCTLFAIL;
927 #endif /* AFS_WIN95_ENV */
933 iob.out_size = sizeof(tbuffer);
935 code = pioctl(0, VIOCDELALLTOK, &iob, 0);
936 #ifndef AFS_WIN95_ENV
937 ReleaseMutex(ktcMutex);
938 CloseHandle(ktcMutex);
939 #endif /* AFS_WIN95_ENV */
945 return KTC_PIOCTLFAIL;
947 return KTC_PIOCTLFAIL;
959 #define MAXLOCALTOKENS 4
963 struct ktc_principal server;
964 struct ktc_principal client;
965 struct ktc_token token;
966 } local_tokens[MAXLOCALTOKENS] = {
970 SetLocalToken(struct ktc_principal *aserver, struct ktc_token *atoken,
971 struct ktc_principal *aclient, afs_int32 flags)
977 for (i = 0; i < MAXLOCALTOKENS; i++)
978 if (local_tokens[i].valid) {
979 if ((strcmp(local_tokens[i].server.name, aserver->name) == 0)
980 && (strcmp(local_tokens[i].server.instance, aserver->instance)
982 && (strcmp(local_tokens[i].server.cell, aserver->cell) == 0)) {
983 found = i; /* replace existing entry */
986 } else if (found == -1)
987 found = i; /* remember empty slot but keep looking for a match */
992 memcpy(&local_tokens[found].token, atoken, sizeof(struct ktc_token));
993 memcpy(&local_tokens[found].server, aserver,
994 sizeof(struct ktc_principal));
995 memcpy(&local_tokens[found].client, aclient,
996 sizeof(struct ktc_principal));
997 local_tokens[found].valid = 1;
1004 GetLocalToken(struct ktc_principal *aserver, struct ktc_token *atoken,
1005 int atokenLen, struct ktc_principal *aclient)
1010 for (i = 0; i < MAXLOCALTOKENS; i++)
1011 if (local_tokens[i].valid
1012 && (strcmp(local_tokens[i].server.name, aserver->name) == 0)
1013 && (strcmp(local_tokens[i].server.instance, aserver->instance) ==
1015 && (strcmp(local_tokens[i].server.cell, aserver->cell) == 0)) {
1016 memcpy(atoken, &local_tokens[i].token,
1017 min(atokenLen, sizeof(struct ktc_token)));
1018 memcpy(aclient, &local_tokens[i].client,
1019 sizeof(struct ktc_principal));
1020 UNLOCK_GLOBAL_MUTEX;
1023 UNLOCK_GLOBAL_MUTEX;
1034 for (i = 0; i < MAXLOCALTOKENS; i++) {
1035 local_tokens[i].valid = 0;
1036 memset(&local_tokens[i].token.sessionKey, 0,
1037 sizeof(struct ktc_encryptionKey));
1039 UNLOCK_GLOBAL_MUTEX;
1045 ForgetOneLocalToken(struct ktc_principal *aserver)
1050 for (i = 0; i < MAXLOCALTOKENS; i++) {
1051 if (local_tokens[i].valid
1052 && (strcmp(local_tokens[i].server.name, aserver->name) == 0)
1053 && (strcmp(local_tokens[i].server.instance, aserver->instance) ==
1055 && (strcmp(local_tokens[i].server.cell, aserver->cell) == 0)) {
1056 local_tokens[i].valid = 0;
1057 memset(&local_tokens[i].token.sessionKey, 0,
1058 sizeof(struct ktc_encryptionKey));
1059 UNLOCK_GLOBAL_MUTEX;
1063 UNLOCK_GLOBAL_MUTEX;
1068 * An iterator which can list all cells with tokens in the cache
1070 * This function may be used to list the names of all cells for which
1071 * tokens exist in the current cache. The first time that it is called,
1072 * prevIndex should be set to 0. On all subsequent calls, prevIndex
1073 * should be set to the value returned in newIndex by the last call
1074 * to the function. Note that there is no guarantee that the index value
1075 * is monotonically increasing.
1078 * The index returned by the last call, or 0 if this is the first
1079 * call in an iteration
1081 * A pointer to an int which, upon return, will hold the next value
1084 * A pointer to a char * which, upon return, will hold a cellname.
1085 * This must be freed by the caller using free()
1089 ktc_ListTokensEx(int prevIndex, int *newIndex, char **cellName) {
1090 struct ViceIoctl iob;
1091 char tbuffer[MAXPIOCTLTOKENLEN];
1094 struct ktc_setTokenData tokenSet;
1096 HANDLE ktcMutex = NULL;
1098 memset(&tokenSet, 0, sizeof(tokenSet));
1101 *newIndex = prevIndex;
1105 while (index<100) { /* Safety, incase of pioctl failure */
1106 memset(tbuffer, 0, sizeof(tbuffer));
1108 memcpy(tbuffer, &index, sizeof(afs_int32));
1109 iob.in_size = sizeof(afs_int32);
1111 iob.out_size = sizeof(tbuffer);
1114 code = pioctl(0, VIOC_GETTOK2, &iob, 0);
1116 code = -1; /* not yet implemented */
1120 /* Can't use new pioctl, so must use old one */
1121 if (code == -1 && errno == EINVAL) {
1122 struct ktc_principal server;
1124 code = ktc_ListTokens(index, newIndex, &server);
1126 *cellName = strdup(server.cell);
1131 /* Got a token from the pioctl. Now we throw it away,
1132 * so we can return just a cellname. This is rather wasteful,
1133 * but it's what the old API does. Ho hum. */
1135 xdrmem_create(&xdrs, iob.out, iob.out_size, XDR_DECODE);
1136 if (!xdr_ktc_setTokenData(&xdrs, &tokenSet)) {
1141 *cellName = strdup(tokenSet.cell);
1142 xdr_free((xdrproc_t)xdr_ktc_setTokenData, &tokenSet);
1143 *newIndex = index + 1;
1148 return KTC_PIOCTLFAIL;