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
;