#include "afs/param.h"
#include "afs/sysincludes.h"
#include "afsincludes.h"
+#include "token.h"
/* A jar for storing tokens in */
* accessed using the appropriate element of the union.
*/
union tokenUnion *
-afs_FindToken(struct tokenJar *tokens, rx_securityIndex type) {
+afs_FindToken(struct tokenJar *tokens, rx_securityIndex type)
+{
while (tokens != NULL) {
if (tokens->type == type) {
- return &tokens->u;
+ return &tokens->content;
}
tokens = tokens->next;
}
}
/*!
- * Free a single token
+ * Unlink and free a single token
*
- * This will free the given token. No attempt is made to unlink
- * the token from its container, and it is an error to attempt to
- * free a token which is still linked.
- *
- * This performs a secure free, setting all token information to 0
- * before returning allocated data blocks to the kernel.
+ * This will unlink the first token in the given tokenJar, and free that token.
+ * This attempts to perform a secure free, setting all token information to 0
+ * before returning allocated data blocks to the kernel. (Optimizing compilers
+ * may eliminate such a "dead store", though.)
*
* Intended primarily for internal use.
*
- * @param[in] token
- * The token to free
+ * @param[inout] tokenPtr
+ * The token to unlink and free
*/
+static void
+afs_FreeFirstToken(struct tokenJar **tokenPtr)
+{
+ struct tokenJar *token = *tokenPtr;
+ if (token == NULL) {
+ return;
+ }
-void
-afs_FreeOneToken(struct tokenJar *token) {
- if (token->next != NULL)
- osi_Panic("Freeing linked token");
+ /* Unlink the token. */
+ *tokenPtr = token->next;
+ token->next = NULL;
switch (token->type) {
case RX_SECIDX_KAD:
- if (token->u.rxkad.ticket != NULL) {
- memset(token->u.rxkad.ticket, 0, token->u.rxkad.ticketLen);
- afs_osi_Free(token->u.rxkad.ticket,
- token->u.rxkad.ticketLen);
+ if (token->content.rxkad.ticket != NULL) {
+ memset(token->content.rxkad.ticket, 0, token->content.rxkad.ticketLen);
+ afs_osi_Free(token->content.rxkad.ticket,
+ token->content.rxkad.ticketLen);
}
break;
default:
break;
}
- memset(token, 0, sizeof(struct tokenJar));
- afs_osi_Free(token, sizeof(struct tokenJar));
+ memset(token, 0, sizeof(*token));
+ afs_osi_Free(token, sizeof(*token));
}
/*!
* A pointer to the address of the tokenjar to free.
*/
void
-afs_FreeTokens(struct tokenJar **tokenPtr) {
- struct tokenJar *next, *tokens;
-
- tokens = *tokenPtr;
- *tokenPtr = NULL;
- while(tokens != NULL) {
- next = tokens->next;
- tokens->next = NULL; /* Unlink from chain */
- afs_FreeOneToken(tokens);
- tokens = next;
+afs_FreeTokens(struct tokenJar **tokenPtr)
+{
+ while (*tokenPtr != NULL) {
+ afs_FreeFirstToken(tokenPtr);
}
}
* which may then be used to populate the token.
*/
union tokenUnion *
-afs_AddToken(struct tokenJar **tokens, rx_securityIndex type) {
+afs_AddToken(struct tokenJar **tokens, rx_securityIndex type)
+{
struct tokenJar *newToken;
- newToken = afs_osi_Alloc(sizeof(struct tokenJar));
+ newToken = afs_osi_Alloc(sizeof(*newToken));
+ osi_Assert(newToken != NULL);
memset(newToken, 0, sizeof(*newToken));
newToken->type = type;
newToken->next = *tokens;
*tokens = newToken;
- return &newToken->u;
+ return &newToken->content;
}
/*!
* @returns
* True if the token has expired, false otherwise
*/
-int
-afs_IsTokenExpired(struct tokenJar *token, afs_int32 now) {
+static int
+afs_IsTokenExpired(struct tokenJar *token, afs_int32 now)
+{
switch (token->type) {
case RX_SECIDX_KAD:
- if (token->u.rxkad.clearToken.EndTimestamp < now - NOTOKTIMEOUT)
+ if (token->content.rxkad.clearToken.EndTimestamp < now - NOTOKTIMEOUT)
return 1;
break;
default:
return 0;
}
- return 0; /* not reached, but keep gcc happy */
+ return 0;
}
/*!
* @returns
* True if the token is usable, false otherwise
*/
-int
-afs_IsTokenUsable(struct tokenJar *token, afs_int32 now) {
+static int
+afs_IsTokenUsable(struct tokenJar *token, afs_int32 now)
+{
if (afs_IsTokenExpired(token, now))
return 0;
*/
void
-afs_DiscardExpiredTokens(struct tokenJar **tokenPtr, afs_int32 now) {
- struct tokenJar *next;
-
+afs_DiscardExpiredTokens(struct tokenJar **tokenPtr, afs_int32 now)
+{
while (*tokenPtr != NULL) {
if (afs_IsTokenExpired(*tokenPtr, now)) {
- next = (*tokenPtr)->next;
- (*tokenPtr)->next = NULL;
- afs_FreeOneToken(*tokenPtr);
- *tokenPtr = next;
+ afs_FreeFirstToken(tokenPtr);
} else {
tokenPtr = &(*tokenPtr)->next;
}
* True if the jar contains usable tokens, otherwise false
*/
int
-afs_HasUsableTokens(struct tokenJar *token, afs_int32 now) {
+afs_HasUsableTokens(struct tokenJar *token, afs_int32 now)
+{
while (token != NULL) {
if (afs_IsTokenUsable(token, now))
return 1;
}
/*!
+ * Indicate whether a token jar contains a valid (non-expired) token
+ *
+ * @param[in] token
+ * The token jar to check
+ * @param[in] now
+ * The time to use for the expiry check
+ *
+ * @returns
+ * True if the jar contains valid tokens, otherwise false
+ *
+ */
+int
+afs_HasValidTokens(struct tokenJar *token, afs_int32 now)
+{
+ while (token != NULL) {
+ if (!afs_IsTokenExpired(token, now))
+ return 1;
+ token = token->next;
+ }
+ return 0;
+}
+
+/*!
+ * Count the number of valid tokens in a jar. A valid token is
+ * one which is not expired - note that valid tokens may not be
+ * usable by the kernel.
+ *
+ * @param[in] token
+ * The token jar to check
+ * @param[in] now
+ * The time to use for the expiry check
+ *
+ * @returns
+ * The number of valid tokens in the jar
+ */
+static int
+countValidTokens(struct tokenJar *token, time_t now)
+{
+ int count = 0;
+
+ while (token != NULL) {
+ if (!afs_IsTokenExpired(token, now))
+ count ++;
+ token = token->next;
+ }
+ return count;
+}
+
+/*!
* Add an rxkad token to the token jar
*
* @param[in] tokens
*/
void
afs_AddRxkadToken(struct tokenJar **tokens, char *ticket, int ticketLen,
- struct ClearToken *clearToken) {
+ struct ClearToken *clearToken)
+{
union tokenUnion *tokenU;
struct rxkadToken *rxkad;
rxkad = &tokenU->rxkad;
rxkad->ticket = afs_osi_Alloc(ticketLen);
+ osi_Assert(rxkad->ticket != NULL);
rxkad->ticketLen = ticketLen;
memcpy(rxkad->ticket, ticket, ticketLen);
rxkad->clearToken = *clearToken;
}
+static int
+afs_AddRxkadTokenFromPioctl(struct tokenJar **tokens,
+ struct ktc_tokenUnion *pioctlToken)
+{
+ struct ClearToken clear;
+
+ clear.AuthHandle = pioctlToken->ktc_tokenUnion_u.at_kad.rk_kvno;
+ clear.ViceId = pioctlToken->ktc_tokenUnion_u.at_kad.rk_viceid;
+ clear.BeginTimestamp = pioctlToken->ktc_tokenUnion_u.at_kad.rk_begintime;
+ clear.EndTimestamp = pioctlToken->ktc_tokenUnion_u.at_kad.rk_endtime;
+ memcpy(clear.HandShakeKey, pioctlToken->ktc_tokenUnion_u.at_kad.rk_key, 8);
+ afs_AddRxkadToken(tokens,
+ pioctlToken->ktc_tokenUnion_u.at_kad.rk_ticket.rk_ticket_val,
+ pioctlToken->ktc_tokenUnion_u.at_kad.rk_ticket.rk_ticket_len,
+ &clear);
+
+ /* Security means never having to say you're sorry */
+ memset(clear.HandShakeKey, 0, 8);
+
+ return 0;
+}
+
+static int
+rxkad_extractTokenForPioctl(struct tokenJar *token,
+ struct ktc_tokenUnion *pioctlToken)
+{
+
+ struct token_rxkad *rxkadPioctl;
+ struct rxkadToken *rxkadInternal;
+
+ rxkadPioctl = &pioctlToken->ktc_tokenUnion_u.at_kad;
+ rxkadInternal = &token->content.rxkad;
+
+ rxkadPioctl->rk_kvno = rxkadInternal->clearToken.AuthHandle;
+ rxkadPioctl->rk_viceid = rxkadInternal->clearToken.ViceId;
+ rxkadPioctl->rk_begintime = rxkadInternal->clearToken.BeginTimestamp;
+ rxkadPioctl->rk_endtime = rxkadInternal->clearToken.EndTimestamp;
+ memcpy(rxkadPioctl->rk_key, rxkadInternal->clearToken.HandShakeKey, 8);
+
+ rxkadPioctl->rk_ticket.rk_ticket_val = xdr_alloc(rxkadInternal->ticketLen);
+ if (rxkadPioctl->rk_ticket.rk_ticket_val == NULL)
+ return ENOMEM;
+ rxkadPioctl->rk_ticket.rk_ticket_len = rxkadInternal->ticketLen;
+ memcpy(rxkadPioctl->rk_ticket.rk_ticket_val,
+ rxkadInternal->ticket, rxkadInternal->ticketLen);
+
+ return 0;
+}
+
+/*!
+ * Add a token to a token jar based on the input from a new-style
+ * SetToken pioctl
+ *
+ * @param[in] tokens
+ * Pointer to the address of a token jar
+ * @param[in] pioctlToken
+ * The token structure obtained through the pioctl (note this
+ * is a single, XDR decoded, token)
+ *
+ * @returns
+ * 0 on success, an error code on failure
+ */
+int
+afs_AddTokenFromPioctl(struct tokenJar **tokens,
+ struct ktc_tokenUnion *pioctlToken)
+{
+
+ switch (pioctlToken->at_type) {
+ case RX_SECIDX_KAD:
+ return afs_AddRxkadTokenFromPioctl(tokens, pioctlToken);
+ }
+
+ return EINVAL;
+}
+
+static int
+extractPioctlToken(struct tokenJar *token,
+ struct token_opaque *opaque)
+{
+ XDR xdrs;
+ struct ktc_tokenUnion *pioctlToken;
+ int code;
+
+ memset(opaque, 0, sizeof(token_opaque));
+
+ pioctlToken = osi_Alloc(sizeof(*pioctlToken));
+ if (pioctlToken == NULL)
+ return ENOMEM;
+
+ pioctlToken->at_type = token->type;
+
+ switch (token->type) {
+ case RX_SECIDX_KAD:
+ code = rxkad_extractTokenForPioctl(token, pioctlToken);
+ break;
+ default:
+ code = EINVAL;;
+ }
+
+ if (code)
+ goto out;
+
+ xdrlen_create(&xdrs);
+ if (!xdr_ktc_tokenUnion(&xdrs, pioctlToken)) {
+ code = EINVAL;
+ xdr_destroy(&xdrs);
+ goto out;
+ }
+
+ opaque->token_opaque_len = xdr_getpos(&xdrs);
+ xdr_destroy(&xdrs);
+
+ opaque->token_opaque_val = osi_Alloc(opaque->token_opaque_len);
+ if (opaque->token_opaque_val == NULL) {
+ code = ENOMEM;
+ goto out;
+ }
+
+ xdrmem_create(&xdrs,
+ opaque->token_opaque_val,
+ opaque->token_opaque_len,
+ XDR_ENCODE);
+ if (!xdr_ktc_tokenUnion(&xdrs, pioctlToken)) {
+ code = EINVAL;
+ xdr_destroy(&xdrs);
+ goto out;
+ }
+ xdr_destroy(&xdrs);
+
+ out:
+ xdr_free((xdrproc_t) xdr_ktc_tokenUnion, pioctlToken);
+ osi_Free(pioctlToken, sizeof(*pioctlToken));
+
+ if (code != 0) {
+ if (opaque->token_opaque_val != NULL)
+ osi_Free(opaque->token_opaque_val, opaque->token_opaque_len);
+ opaque->token_opaque_val = NULL;
+ opaque->token_opaque_len = 0;
+ }
+ return code;
+}
+
+int
+afs_ExtractTokensForPioctl(struct tokenJar *token,
+ time_t now,
+ struct ktc_setTokenData *tokenSet)
+{
+ int numTokens, pos;
+ int code = 0;
+
+ numTokens = countValidTokens(token, now);
+
+ tokenSet->tokens.tokens_len = numTokens;
+ tokenSet->tokens.tokens_val
+ = xdr_alloc(sizeof(tokenSet->tokens.tokens_val[0]) * numTokens);
+
+ if (tokenSet->tokens.tokens_val == NULL)
+ return ENOMEM;
+
+ pos = 0;
+ while (token != NULL && pos < numTokens) {
+ code = extractPioctlToken(token, &tokenSet->tokens.tokens_val[pos]);
+ if (code)
+ goto out;
+ token = token->next;
+ pos++;
+ }
+
+ out:
+ if (code)
+ xdr_free((xdrproc_t) xdr_ktc_setTokenData, tokenSet);
+
+ return code;
+}