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 memset(newToken, 0, sizeof(*newToken));
139 newToken->type = type;
140 newToken->next = *tokens;
143 return &newToken->content;
147 * Indicate if a single token is expired
152 * The time to check against for expiry (typically the results of
153 * calling osi_Time())
156 * True if the token has expired, false otherwise
159 afs_IsTokenExpired(struct tokenJar *token, afs_int32 now) {
160 switch (token->type) {
162 if (token->content.rxkad.clearToken.EndTimestamp < now - NOTOKTIMEOUT)
168 return 0; /* not reached, but keep gcc happy */
172 * Indicate if a token is usable by the kernel module
174 * This determines whether a token is usable. A usable token is one that
175 * has not expired, and which is otherwise suitable for use.
180 * The time to use for the expiry check
183 * True if the token is usable, false otherwise
186 afs_IsTokenUsable(struct tokenJar *token, afs_int32 now) {
188 if (afs_IsTokenExpired(token, now))
191 switch (token->type) {
193 /* We assume that all non-expired rxkad tokens are usable by us */
201 * Discard all expired tokens from a token jar
203 * This permanently removes all tokens which have expired from the token
204 * jar. Note that tokens which are not usable, but which have not expired,
205 * will not be deleted.
207 * @param[in] tokenPtr
208 * A pointer to the address of the token jar to check
210 * The time to use for the expiry check
214 afs_DiscardExpiredTokens(struct tokenJar **tokenPtr, afs_int32 now) {
215 struct tokenJar *next;
217 while (*tokenPtr != NULL) {
218 if (afs_IsTokenExpired(*tokenPtr, now)) {
219 next = (*tokenPtr)->next;
220 (*tokenPtr)->next = NULL;
221 afs_FreeOneToken(*tokenPtr);
224 tokenPtr = &(*tokenPtr)->next;
230 * Indicate whether a token jar contains one, or more usable tokens
233 * The token jar to check
235 * The cime to use for the expiry check
238 * True if the jar contains usable tokens, otherwise false
241 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) {
264 while (token != NULL) {
265 if (!afs_IsTokenExpired(token, now))
273 * Count the number of valid tokens in a jar. A valid token is
274 * one which is not expired - note that valid tokens may not be
275 * usable by the kernel.
278 * The token jar to check
280 * The time to use for the expiry check
283 * The number of valid tokens in the jar
286 countValidTokens(struct tokenJar *token, time_t now) {
289 while (token != NULL) {
290 if (!afs_IsTokenExpired(token, now))
298 * Add an rxkad token to the token jar
301 * A pointer to the address of the jar to add the token to
303 * A data block containing the token's opaque ticket
304 * @param[in] ticketLen
305 * The length of the ticket data block
306 * @param[in] clearToken
307 * The cleartext token information
310 afs_AddRxkadToken(struct tokenJar **tokens, char *ticket, int ticketLen,
311 struct ClearToken *clearToken) {
312 union tokenUnion *tokenU;
313 struct rxkadToken *rxkad;
315 tokenU = afs_AddToken(tokens, RX_SECIDX_KAD);
316 rxkad = &tokenU->rxkad;
318 rxkad->ticket = afs_osi_Alloc(ticketLen);
319 rxkad->ticketLen = ticketLen;
320 memcpy(rxkad->ticket, ticket, ticketLen);
321 rxkad->clearToken = *clearToken;
325 afs_AddRxkadTokenFromPioctl(struct tokenJar **tokens,
326 struct ktc_tokenUnion *pioctlToken) {
327 struct ClearToken clear;
329 clear.AuthHandle = pioctlToken->ktc_tokenUnion_u.at_kad.rk_kvno;
330 clear.ViceId = pioctlToken->ktc_tokenUnion_u.at_kad.rk_viceid;
331 clear.BeginTimestamp = pioctlToken->ktc_tokenUnion_u.at_kad.rk_begintime;
332 clear.EndTimestamp = pioctlToken->ktc_tokenUnion_u.at_kad.rk_endtime;
333 memcpy(clear.HandShakeKey, pioctlToken->ktc_tokenUnion_u.at_kad.rk_key, 8);
334 afs_AddRxkadToken(tokens,
335 pioctlToken->ktc_tokenUnion_u.at_kad.rk_ticket.rk_ticket_val,
336 pioctlToken->ktc_tokenUnion_u.at_kad.rk_ticket.rk_ticket_len,
339 /* Security means never having to say you're sorry */
340 memset(clear.HandShakeKey, 0, 8);
346 rxkad_extractTokenForPioctl(struct tokenJar *token,
347 struct ktc_tokenUnion *pioctlToken) {
349 struct token_rxkad *rxkadPioctl;
350 struct rxkadToken *rxkadInternal;
352 rxkadPioctl = &pioctlToken->ktc_tokenUnion_u.at_kad;
353 rxkadInternal = &token->content.rxkad;
355 rxkadPioctl->rk_kvno = rxkadInternal->clearToken.AuthHandle;
356 rxkadPioctl->rk_viceid = rxkadInternal->clearToken.ViceId;
357 rxkadPioctl->rk_begintime = rxkadInternal->clearToken.BeginTimestamp;
358 rxkadPioctl->rk_endtime = rxkadInternal->clearToken.EndTimestamp;
359 memcpy(rxkadPioctl->rk_key, rxkadInternal->clearToken.HandShakeKey, 8);
361 rxkadPioctl->rk_ticket.rk_ticket_val = xdr_alloc(rxkadInternal->ticketLen);
362 if (rxkadPioctl->rk_ticket.rk_ticket_val == NULL)
364 rxkadPioctl->rk_ticket.rk_ticket_len = rxkadInternal->ticketLen;
365 memcpy(rxkadPioctl->rk_ticket.rk_ticket_val,
366 rxkadInternal->ticket, rxkadInternal->ticketLen);
372 * Add a token to a token jar based on the input from a new-style
376 * Pointer to the address of a token jar
377 * @param[in] pioctlToken
378 * The token structure obtained through the pioctl (note this
379 * is a single, XDR decoded, token)
382 * 0 on success, an error code on failure
385 afs_AddTokenFromPioctl(struct tokenJar **tokens,
386 struct ktc_tokenUnion *pioctlToken) {
388 switch (pioctlToken->at_type) {
390 return afs_AddRxkadTokenFromPioctl(tokens, pioctlToken);
397 extractPioctlToken(struct tokenJar *token,
398 struct token_opaque *opaque) {
400 struct ktc_tokenUnion *pioctlToken;
403 memset(opaque, 0, sizeof(token_opaque));
405 pioctlToken = osi_Alloc(sizeof(struct ktc_tokenUnion));
406 if (pioctlToken == NULL)
409 pioctlToken->at_type = token->type;
411 switch (token->type) {
413 code = rxkad_extractTokenForPioctl(token, pioctlToken);
422 xdrlen_create(&xdrs);
423 if (!xdr_ktc_tokenUnion(&xdrs, pioctlToken)) {
429 opaque->token_opaque_len = xdr_getpos(&xdrs);
432 opaque->token_opaque_val = osi_Alloc(opaque->token_opaque_len);
433 if (opaque->token_opaque_val == NULL) {
439 opaque->token_opaque_val,
440 opaque->token_opaque_len,
442 if (!xdr_ktc_tokenUnion(&xdrs, pioctlToken)) {
450 xdr_free((xdrproc_t) xdr_ktc_tokenUnion, &pioctlToken);
451 osi_Free(pioctlToken, sizeof(struct ktc_tokenUnion));
454 osi_Free(opaque->token_opaque_val, opaque->token_opaque_len);
455 opaque->token_opaque_val = NULL;
456 opaque->token_opaque_len = 0;
462 afs_ExtractTokensForPioctl(struct tokenJar *token,
464 struct ktc_setTokenData *tokenSet)
469 numTokens = countValidTokens(token, now);
471 tokenSet->tokens.tokens_len = numTokens;
472 tokenSet->tokens.tokens_val
473 = xdr_alloc(sizeof(struct token_opaque) * numTokens);
475 if (tokenSet->tokens.tokens_val == NULL)
479 while (token != NULL && pos < numTokens) {
480 code = extractPioctlToken(token, &tokenSet->tokens.tokens_val[pos]);
489 xdr_free((xdrproc_t) xdr_ktc_setTokenData, tokenSet);