2 * Copyright (c) 2010 Your Filesystem Inc. All rights reserved.
4 * Redistribution and use in source and binary forms, with or without
5 * modification, are permitted provided that the following conditions
7 * 1. Redistributions of source code must retain the above copyright
8 * notice, this list of conditions and the following disclaimer.
9 * 2. Redistributions in binary form must reproduce the above copyright
10 * notice, this list of conditions and the following disclaimer in the
11 * documentation and/or other materials provided with the distribution.
13 * THIS SOFTWARE IS PROVIDED BY THE AUTHOR `AS IS'' AND ANY EXPRESS OR
14 * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
15 * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
16 * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
17 * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
18 * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
19 * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
20 * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
21 * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
22 * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
25 #include <afsconfig.h>
26 #include "afs/param.h"
27 #include "afs/sysincludes.h"
28 #include "afsincludes.h"
31 /* A jar for storing tokens in */
34 * Return a token of the specified type from the selected tokenjar.
37 * The tokenjar in which to search
39 * The type of token to return
42 * A tokenUnion structure, from which the desired token can be
43 * accessed using the appropriate element of the union.
46 afs_FindToken(struct tokenJar
*tokens
, rx_securityIndex type
) {
47 while (tokens
!= NULL
) {
48 if (tokens
->type
== type
) {
49 return &tokens
->content
;
51 tokens
= tokens
->next
;
59 * This will free the given token. No attempt is made to unlink
60 * the token from its container, and it is an error to attempt to
61 * free a token which is still linked.
63 * This performs a secure free, setting all token information to 0
64 * before returning allocated data blocks to the kernel.
66 * Intended primarily for internal use.
73 afs_FreeOneToken(struct tokenJar
*token
) {
74 if (token
->next
!= NULL
)
75 osi_Panic("Freeing linked token");
77 switch (token
->type
) {
79 if (token
->content
.rxkad
.ticket
!= NULL
) {
80 memset(token
->content
.rxkad
.ticket
, 0, token
->content
.rxkad
.ticketLen
);
81 afs_osi_Free(token
->content
.rxkad
.ticket
,
82 token
->content
.rxkad
.ticketLen
);
88 memset(token
, 0, sizeof(struct tokenJar
));
89 afs_osi_Free(token
, sizeof(struct tokenJar
));
95 * Free all of the tokens in a given token jar. This will also set the
96 * pointer to the jar to NULL, to indicate that it has been freed.
99 * A pointer to the address of the tokenjar to free.
102 afs_FreeTokens(struct tokenJar
**tokenPtr
) {
103 struct tokenJar
*next
, *tokens
;
107 while(tokens
!= NULL
) {
109 tokens
->next
= NULL
; /* Unlink from chain */
110 afs_FreeOneToken(tokens
);
116 * Add a token to a token jar
118 * Add a new token to a token jar. If the jar already exists,
119 * then this token becomes the first in the jar. If it doesn't
120 * exist, then a new jar is created. The contents of the new
121 * token are initialised to 0 upon creation.
124 * A pointer to the address of the token jar to populate
126 * The type of token to create
129 * A pointer to the tokenUnion of the newly created token,
130 * which may then be used to populate the token.
133 afs_AddToken(struct tokenJar
**tokens
, rx_securityIndex type
) {
134 struct tokenJar
*newToken
;
136 newToken
= afs_osi_Alloc(sizeof(struct tokenJar
));
137 osi_Assert(newToken
!= NULL
);
138 memset(newToken
, 0, sizeof(*newToken
));
140 newToken
->type
= type
;
141 newToken
->next
= *tokens
;
144 return &newToken
->content
;
148 * Indicate if a single token is expired
153 * The time to check against for expiry (typically the results of
154 * calling osi_Time())
157 * True if the token has expired, false otherwise
160 afs_IsTokenExpired(struct tokenJar
*token
, afs_int32 now
) {
161 switch (token
->type
) {
163 if (token
->content
.rxkad
.clearToken
.EndTimestamp
< now
- NOTOKTIMEOUT
)
169 return 0; /* not reached, but keep gcc happy */
173 * Indicate if a token is usable by the kernel module
175 * This determines whether a token is usable. A usable token is one that
176 * has not expired, and which is otherwise suitable for use.
181 * The time to use for the expiry check
184 * True if the token is usable, false otherwise
187 afs_IsTokenUsable(struct tokenJar
*token
, afs_int32 now
) {
189 if (afs_IsTokenExpired(token
, now
))
192 switch (token
->type
) {
194 /* We assume that all non-expired rxkad tokens are usable by us */
202 * Discard all expired tokens from a token jar
204 * This permanently removes all tokens which have expired from the token
205 * jar. Note that tokens which are not usable, but which have not expired,
206 * will not be deleted.
208 * @param[in] tokenPtr
209 * A pointer to the address of the token jar to check
211 * The time to use for the expiry check
215 afs_DiscardExpiredTokens(struct tokenJar
**tokenPtr
, afs_int32 now
) {
216 struct tokenJar
*next
;
218 while (*tokenPtr
!= NULL
) {
219 if (afs_IsTokenExpired(*tokenPtr
, now
)) {
220 next
= (*tokenPtr
)->next
;
221 (*tokenPtr
)->next
= NULL
;
222 afs_FreeOneToken(*tokenPtr
);
225 tokenPtr
= &(*tokenPtr
)->next
;
231 * Indicate whether a token jar contains one, or more usable tokens
234 * The token jar to check
236 * The cime to use for the expiry check
239 * True if the jar contains usable tokens, otherwise false
242 afs_HasUsableTokens(struct tokenJar
*token
, afs_int32 now
) {
243 while (token
!= NULL
) {
244 if (afs_IsTokenUsable(token
, now
))
252 * Indicate whether a token jar contains a valid (non-expired) token
255 * The token jar to check
257 * The time to use for the expiry check
260 * True if the jar contains valid tokens, otherwise false
264 afs_HasValidTokens(struct tokenJar
*token
, afs_int32 now
) {
265 while (token
!= NULL
) {
266 if (!afs_IsTokenExpired(token
, now
))
274 * Count the number of valid tokens in a jar. A valid token is
275 * one which is not expired - note that valid tokens may not be
276 * usable by the kernel.
279 * The token jar to check
281 * The time to use for the expiry check
284 * The number of valid tokens in the jar
287 countValidTokens(struct tokenJar
*token
, time_t now
) {
290 while (token
!= NULL
) {
291 if (!afs_IsTokenExpired(token
, now
))
299 * Add an rxkad token to the token jar
302 * A pointer to the address of the jar to add the token to
304 * A data block containing the token's opaque ticket
305 * @param[in] ticketLen
306 * The length of the ticket data block
307 * @param[in] clearToken
308 * The cleartext token information
311 afs_AddRxkadToken(struct tokenJar
**tokens
, char *ticket
, int ticketLen
,
312 struct ClearToken
*clearToken
) {
313 union tokenUnion
*tokenU
;
314 struct rxkadToken
*rxkad
;
316 tokenU
= afs_AddToken(tokens
, RX_SECIDX_KAD
);
317 rxkad
= &tokenU
->rxkad
;
319 rxkad
->ticket
= afs_osi_Alloc(ticketLen
);
320 osi_Assert(rxkad
->ticket
!= NULL
);
321 rxkad
->ticketLen
= ticketLen
;
322 memcpy(rxkad
->ticket
, ticket
, ticketLen
);
323 rxkad
->clearToken
= *clearToken
;
327 afs_AddRxkadTokenFromPioctl(struct tokenJar
**tokens
,
328 struct ktc_tokenUnion
*pioctlToken
) {
329 struct ClearToken clear
;
331 clear
.AuthHandle
= pioctlToken
->ktc_tokenUnion_u
.at_kad
.rk_kvno
;
332 clear
.ViceId
= pioctlToken
->ktc_tokenUnion_u
.at_kad
.rk_viceid
;
333 clear
.BeginTimestamp
= pioctlToken
->ktc_tokenUnion_u
.at_kad
.rk_begintime
;
334 clear
.EndTimestamp
= pioctlToken
->ktc_tokenUnion_u
.at_kad
.rk_endtime
;
335 memcpy(clear
.HandShakeKey
, pioctlToken
->ktc_tokenUnion_u
.at_kad
.rk_key
, 8);
336 afs_AddRxkadToken(tokens
,
337 pioctlToken
->ktc_tokenUnion_u
.at_kad
.rk_ticket
.rk_ticket_val
,
338 pioctlToken
->ktc_tokenUnion_u
.at_kad
.rk_ticket
.rk_ticket_len
,
341 /* Security means never having to say you're sorry */
342 memset(clear
.HandShakeKey
, 0, 8);
348 rxkad_extractTokenForPioctl(struct tokenJar
*token
,
349 struct ktc_tokenUnion
*pioctlToken
) {
351 struct token_rxkad
*rxkadPioctl
;
352 struct rxkadToken
*rxkadInternal
;
354 rxkadPioctl
= &pioctlToken
->ktc_tokenUnion_u
.at_kad
;
355 rxkadInternal
= &token
->content
.rxkad
;
357 rxkadPioctl
->rk_kvno
= rxkadInternal
->clearToken
.AuthHandle
;
358 rxkadPioctl
->rk_viceid
= rxkadInternal
->clearToken
.ViceId
;
359 rxkadPioctl
->rk_begintime
= rxkadInternal
->clearToken
.BeginTimestamp
;
360 rxkadPioctl
->rk_endtime
= rxkadInternal
->clearToken
.EndTimestamp
;
361 memcpy(rxkadPioctl
->rk_key
, rxkadInternal
->clearToken
.HandShakeKey
, 8);
363 rxkadPioctl
->rk_ticket
.rk_ticket_val
= xdr_alloc(rxkadInternal
->ticketLen
);
364 if (rxkadPioctl
->rk_ticket
.rk_ticket_val
== NULL
)
366 rxkadPioctl
->rk_ticket
.rk_ticket_len
= rxkadInternal
->ticketLen
;
367 memcpy(rxkadPioctl
->rk_ticket
.rk_ticket_val
,
368 rxkadInternal
->ticket
, rxkadInternal
->ticketLen
);
374 * Add a token to a token jar based on the input from a new-style
378 * Pointer to the address of a token jar
379 * @param[in] pioctlToken
380 * The token structure obtained through the pioctl (note this
381 * is a single, XDR decoded, token)
384 * 0 on success, an error code on failure
387 afs_AddTokenFromPioctl(struct tokenJar
**tokens
,
388 struct ktc_tokenUnion
*pioctlToken
) {
390 switch (pioctlToken
->at_type
) {
392 return afs_AddRxkadTokenFromPioctl(tokens
, pioctlToken
);
399 extractPioctlToken(struct tokenJar
*token
,
400 struct token_opaque
*opaque
) {
402 struct ktc_tokenUnion
*pioctlToken
;
405 memset(opaque
, 0, sizeof(token_opaque
));
407 pioctlToken
= osi_Alloc(sizeof(struct ktc_tokenUnion
));
408 if (pioctlToken
== NULL
)
411 pioctlToken
->at_type
= token
->type
;
413 switch (token
->type
) {
415 code
= rxkad_extractTokenForPioctl(token
, pioctlToken
);
424 xdrlen_create(&xdrs
);
425 if (!xdr_ktc_tokenUnion(&xdrs
, pioctlToken
)) {
431 opaque
->token_opaque_len
= xdr_getpos(&xdrs
);
434 opaque
->token_opaque_val
= osi_Alloc(opaque
->token_opaque_len
);
435 if (opaque
->token_opaque_val
== NULL
) {
441 opaque
->token_opaque_val
,
442 opaque
->token_opaque_len
,
444 if (!xdr_ktc_tokenUnion(&xdrs
, pioctlToken
)) {
452 xdr_free((xdrproc_t
) xdr_ktc_tokenUnion
, &pioctlToken
);
453 osi_Free(pioctlToken
, sizeof(struct ktc_tokenUnion
));
456 if (opaque
->token_opaque_val
!= NULL
)
457 osi_Free(opaque
->token_opaque_val
, opaque
->token_opaque_len
);
458 opaque
->token_opaque_val
= NULL
;
459 opaque
->token_opaque_len
= 0;
465 afs_ExtractTokensForPioctl(struct tokenJar
*token
,
467 struct ktc_setTokenData
*tokenSet
)
472 numTokens
= countValidTokens(token
, now
);
474 tokenSet
->tokens
.tokens_len
= numTokens
;
475 tokenSet
->tokens
.tokens_val
476 = xdr_alloc(sizeof(struct token_opaque
) * numTokens
);
478 if (tokenSet
->tokens
.tokens_val
== NULL
)
482 while (token
!= NULL
&& pos
< numTokens
) {
483 code
= extractPioctlToken(token
, &tokenSet
->tokens
.tokens_val
[pos
]);
492 xdr_free((xdrproc_t
) xdr_ktc_setTokenData
, tokenSet
);