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)
48 while (tokens != NULL) {
49 if (tokens->type == type) {
50 return &tokens->content;
52 tokens = tokens->next;
58 * Unlink and free a single token
60 * This will unlink the first token in the given tokenJar, and free that token.
61 * This attempts to perform a secure free, setting all token information to 0
62 * before returning allocated data blocks to the kernel. (Optimizing compilers
63 * may eliminate such a "dead store", though.)
65 * Intended primarily for internal use.
67 * @param[inout] tokenPtr
68 * The token to unlink and free
71 afs_FreeFirstToken(struct tokenJar **tokenPtr)
73 struct tokenJar *token = *tokenPtr;
78 /* Unlink the token. */
79 *tokenPtr = token->next;
82 switch (token->type) {
84 if (token->content.rxkad.ticket != NULL) {
85 memset(token->content.rxkad.ticket, 0, token->content.rxkad.ticketLen);
86 afs_osi_Free(token->content.rxkad.ticket,
87 token->content.rxkad.ticketLen);
93 memset(token, 0, sizeof(*token));
94 afs_osi_Free(token, sizeof(*token));
100 * Free all of the tokens in a given token jar. This will also set the
101 * pointer to the jar to NULL, to indicate that it has been freed.
103 * @param[in] tokenPtr
104 * A pointer to the address of the tokenjar to free.
107 afs_FreeTokens(struct tokenJar **tokenPtr)
109 while (*tokenPtr != NULL) {
110 afs_FreeFirstToken(tokenPtr);
115 * Add a token to a token jar
117 * Add a new token to a token jar. If the jar already exists,
118 * then this token becomes the first in the jar. If it doesn't
119 * exist, then a new jar is created. The contents of the new
120 * token are initialised to 0 upon creation.
123 * A pointer to the address of the token jar to populate
125 * The type of token to create
128 * A pointer to the tokenUnion of the newly created token,
129 * which may then be used to populate the token.
132 afs_AddToken(struct tokenJar **tokens, rx_securityIndex type)
134 struct tokenJar *newToken;
136 newToken = afs_osi_Alloc(sizeof(*newToken));
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)
162 switch (token->type) {
164 if (token->content.rxkad.clearToken.EndTimestamp < now - NOTOKTIMEOUT)
174 * Indicate if a token is usable by the kernel module
176 * This determines whether a token is usable. A usable token is one that
177 * has not expired, and which is otherwise suitable for use.
182 * The time to use for the expiry check
185 * True if the token is usable, false otherwise
188 afs_IsTokenUsable(struct tokenJar *token, afs_int32 now)
191 if (afs_IsTokenExpired(token, now))
194 switch (token->type) {
196 /* We assume that all non-expired rxkad tokens are usable by us */
204 * Discard all expired tokens from a token jar
206 * This permanently removes all tokens which have expired from the token
207 * jar. Note that tokens which are not usable, but which have not expired,
208 * will not be deleted.
210 * @param[in] tokenPtr
211 * A pointer to the address of the token jar to check
213 * The time to use for the expiry check
217 afs_DiscardExpiredTokens(struct tokenJar **tokenPtr, afs_int32 now)
219 while (*tokenPtr != NULL) {
220 if (afs_IsTokenExpired(*tokenPtr, now)) {
221 afs_FreeFirstToken(tokenPtr);
223 tokenPtr = &(*tokenPtr)->next;
229 * Indicate whether a token jar contains one, or more usable tokens
232 * The token jar to check
234 * The cime to use for the expiry check
237 * True if the jar contains usable tokens, otherwise false
240 afs_HasUsableTokens(struct tokenJar *token, afs_int32 now)
242 while (token != NULL) {
243 if (afs_IsTokenUsable(token, now))
251 * Indicate whether a token jar contains a valid (non-expired) token
254 * The token jar to check
256 * The time to use for the expiry check
259 * True if the jar contains valid tokens, otherwise false
263 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)
291 while (token != NULL) {
292 if (!afs_IsTokenExpired(token, now))
300 * Add an rxkad token to the token jar
303 * A pointer to the address of the jar to add the token to
305 * A data block containing the token's opaque ticket
306 * @param[in] ticketLen
307 * The length of the ticket data block
308 * @param[in] clearToken
309 * The cleartext token information
312 afs_AddRxkadToken(struct tokenJar **tokens, char *ticket, int ticketLen,
313 struct ClearToken *clearToken)
315 union tokenUnion *tokenU;
316 struct rxkadToken *rxkad;
318 tokenU = afs_AddToken(tokens, RX_SECIDX_KAD);
319 rxkad = &tokenU->rxkad;
321 rxkad->ticket = afs_osi_Alloc(ticketLen);
322 osi_Assert(rxkad->ticket != NULL);
323 rxkad->ticketLen = ticketLen;
324 memcpy(rxkad->ticket, ticket, ticketLen);
325 rxkad->clearToken = *clearToken;
329 afs_AddRxkadTokenFromPioctl(struct tokenJar **tokens,
330 struct ktc_tokenUnion *pioctlToken)
332 struct ClearToken clear;
334 clear.AuthHandle = pioctlToken->ktc_tokenUnion_u.at_kad.rk_kvno;
335 clear.ViceId = pioctlToken->ktc_tokenUnion_u.at_kad.rk_viceid;
336 clear.BeginTimestamp = pioctlToken->ktc_tokenUnion_u.at_kad.rk_begintime;
337 clear.EndTimestamp = pioctlToken->ktc_tokenUnion_u.at_kad.rk_endtime;
338 memcpy(clear.HandShakeKey, pioctlToken->ktc_tokenUnion_u.at_kad.rk_key, 8);
339 afs_AddRxkadToken(tokens,
340 pioctlToken->ktc_tokenUnion_u.at_kad.rk_ticket.rk_ticket_val,
341 pioctlToken->ktc_tokenUnion_u.at_kad.rk_ticket.rk_ticket_len,
344 /* Security means never having to say you're sorry */
345 memset(clear.HandShakeKey, 0, 8);
351 rxkad_extractTokenForPioctl(struct tokenJar *token,
352 struct ktc_tokenUnion *pioctlToken)
355 struct token_rxkad *rxkadPioctl;
356 struct rxkadToken *rxkadInternal;
358 rxkadPioctl = &pioctlToken->ktc_tokenUnion_u.at_kad;
359 rxkadInternal = &token->content.rxkad;
361 rxkadPioctl->rk_kvno = rxkadInternal->clearToken.AuthHandle;
362 rxkadPioctl->rk_viceid = rxkadInternal->clearToken.ViceId;
363 rxkadPioctl->rk_begintime = rxkadInternal->clearToken.BeginTimestamp;
364 rxkadPioctl->rk_endtime = rxkadInternal->clearToken.EndTimestamp;
365 memcpy(rxkadPioctl->rk_key, rxkadInternal->clearToken.HandShakeKey, 8);
367 rxkadPioctl->rk_ticket.rk_ticket_val = xdr_alloc(rxkadInternal->ticketLen);
368 if (rxkadPioctl->rk_ticket.rk_ticket_val == NULL)
370 rxkadPioctl->rk_ticket.rk_ticket_len = rxkadInternal->ticketLen;
371 memcpy(rxkadPioctl->rk_ticket.rk_ticket_val,
372 rxkadInternal->ticket, rxkadInternal->ticketLen);
378 * Add a token to a token jar based on the input from a new-style
382 * Pointer to the address of a token jar
383 * @param[in] pioctlToken
384 * The token structure obtained through the pioctl (note this
385 * is a single, XDR decoded, token)
388 * 0 on success, an error code on failure
391 afs_AddTokenFromPioctl(struct tokenJar **tokens,
392 struct ktc_tokenUnion *pioctlToken)
395 switch (pioctlToken->at_type) {
397 return afs_AddRxkadTokenFromPioctl(tokens, pioctlToken);
404 extractPioctlToken(struct tokenJar *token,
405 struct token_opaque *opaque)
408 struct ktc_tokenUnion *pioctlToken;
411 memset(opaque, 0, sizeof(token_opaque));
413 pioctlToken = osi_Alloc(sizeof(*pioctlToken));
414 if (pioctlToken == NULL)
417 pioctlToken->at_type = token->type;
419 switch (token->type) {
421 code = rxkad_extractTokenForPioctl(token, pioctlToken);
430 xdrlen_create(&xdrs);
431 if (!xdr_ktc_tokenUnion(&xdrs, pioctlToken)) {
437 opaque->token_opaque_len = xdr_getpos(&xdrs);
440 opaque->token_opaque_val = osi_Alloc(opaque->token_opaque_len);
441 if (opaque->token_opaque_val == NULL) {
447 opaque->token_opaque_val,
448 opaque->token_opaque_len,
450 if (!xdr_ktc_tokenUnion(&xdrs, pioctlToken)) {
458 xdr_free((xdrproc_t) xdr_ktc_tokenUnion, &pioctlToken);
459 osi_Free(pioctlToken, sizeof(*pioctlToken));
462 if (opaque->token_opaque_val != NULL)
463 osi_Free(opaque->token_opaque_val, opaque->token_opaque_len);
464 opaque->token_opaque_val = NULL;
465 opaque->token_opaque_len = 0;
471 afs_ExtractTokensForPioctl(struct tokenJar *token,
473 struct ktc_setTokenData *tokenSet)
478 numTokens = countValidTokens(token, now);
480 tokenSet->tokens.tokens_len = numTokens;
481 tokenSet->tokens.tokens_val
482 = xdr_alloc(sizeof(tokenSet->tokens.tokens_val[0]) * numTokens);
484 if (tokenSet->tokens.tokens_val == NULL)
488 while (token != NULL && pos < numTokens) {
489 code = extractPioctlToken(token, &tokenSet->tokens.tokens_val[pos]);
498 xdr_free((xdrproc_t) xdr_ktc_setTokenData, tokenSet);