auth: Force correct evenness on rxkad tokens

Rxkad tokens historically have forced odd lifetimes when the given
viceid is actually an AFS ID, and even lifetimes when it is not. Force
this when the new token-handling functions are used (so the viceid is
correctly interpreted by users of the old token format), by creating
rxkad tokens with token_importRxkadViceId.

Slightly reworked by Simon Wilkinson to provide a generic token
destructor function.

Change-Id: I9f6aa518b8ae51a3772b69a0722a28bff6b47128
Reviewed-on: http://gerrit.openafs.org/4481
Tested-by: Simon Wilkinson <sxw@inf.ed.ac.uk>
Reviewed-by: Derrick Brashear <shadow@dementix.org>
This commit is contained in:
Andrew Deason 2011-04-14 15:05:37 -05:00 committed by Derrick Brashear
parent c37a14697d
commit 59b47fba3f
4 changed files with 153 additions and 58 deletions

View File

@ -657,13 +657,12 @@ static int
rxkad_build_native_token(krb5_context context, krb5_creds *v5cred,
struct ktc_tokenUnion **tokenPtr, char **userPtr) {
char username[BUFSIZ];
struct ktc_tokenUnion *token;
struct token_rxkad *rxkadToken;
struct ktc_token token;
int status;
#ifdef HAVE_NO_KRB5_524
char *p;
int len;
#else
int status;
char k4name[ANAME_SZ];
char k4inst[INST_SZ];
char k4realm[REALM_SZ];
@ -706,30 +705,21 @@ rxkad_build_native_token(krb5_context context, krb5_creds *v5cred,
}
#endif
token = malloc(sizeof(struct ktc_tokenUnion));
if (token == NULL)
return ENOMEM;
memset(&token, 0, sizeof(struct ktc_token));
memset(token, 0, sizeof(struct ktc_tokenUnion));
token->at_type = AFSTOKEN_UNION_KAD;
rxkadToken = &token->ktc_tokenUnion_u.at_kad;
rxkadToken->rk_kvno = RXKAD_TKT_TYPE_KERBEROS_V5;
rxkadToken->rk_begintime = v5cred->times.starttime;;
rxkadToken->rk_endtime = v5cred->times.endtime;
memcpy(&rxkadToken->rk_key, get_cred_keydata(v5cred),
token.kvno = RXKAD_TKT_TYPE_KERBEROS_V5;
token.startTime = v5cred->times.starttime;;
token.endTime = v5cred->times.endtime;
memcpy(&token.sessionKey, get_cred_keydata(v5cred),
get_cred_keylen(v5cred));
rxkadToken->rk_ticket.rk_ticket_len = v5cred->ticket.length;
rxkadToken->rk_ticket.rk_ticket_val = malloc(v5cred->ticket.length);
if (rxkadToken->rk_ticket.rk_ticket_val == NULL) {
free(token);
return ENOMEM;
}
memcpy(rxkadToken->rk_ticket.rk_ticket_val, v5cred->ticket.data,
rxkadToken->rk_ticket.rk_ticket_len);
token.ticketLen = v5cred->ticket.length;
memcpy(token.ticket, v5cred->ticket.data, token.ticketLen);
status = token_importRxkadViceId(tokenPtr, &token, 0);
if (status) {
return status;
}
*tokenPtr = token;
*userPtr = strdup(username);
return 0;
@ -771,8 +761,7 @@ rxkad_get_converted_token(krb5_context context, krb5_creds *v5cred,
struct ktc_tokenUnion **tokenPtr, char **userPtr) {
CREDENTIALS cred;
char username[BUFSIZ];
struct ktc_tokenUnion *token;
struct token_rxkad *rxkadToken;
struct ktc_token token;
int status;
*tokenPtr = NULL;
@ -794,16 +783,10 @@ rxkad_get_converted_token(krb5_context context, krb5_creds *v5cred,
strcat (username, cred.pinst);
}
token = malloc(sizeof(struct ktc_tokenUnion));
if (token == NULL)
return ENOMEM;
memset(token, 0, sizeof(struct ktc_tokenUnion));
memset(&token, 0, sizeof(struct ktc_token));
token->at_type = AFSTOKEN_UNION_KAD;
rxkadToken = &token->ktc_tokenUnion_u.at_kad;
rxkadToken->rk_kvno = cred.kvno;
rxkadToken->rk_begintime = cred.issue_date;
token.kvno = cred.kvno;
token.startTime = cred.issue_date;
/*
* It seems silly to go through a bunch of contortions to
* extract the expiration time, when the v5 credentials already
@ -812,18 +795,16 @@ rxkad_get_converted_token(krb5_context context, krb5_creds *v5cred,
* Note that this isn't a security hole, as the expiration time
* is also contained in the encrypted token
*/
rxkadToken->rk_endtime = v5cred->times.endtime;
memcpy(&rxkadToken->rk_key, cred.session, 8);
rxkadToken->rk_ticket.rk_ticket_len = cred.ticket_st.length;
rxkadToken->rk_ticket.rk_ticket_val = malloc(cred.ticket_st.length);
if (rxkadToken->rk_ticket.rk_ticket_val == NULL) {
free(token);
return ENOMEM;
}
memcpy(rxkadToken->rk_ticket.rk_ticket_val, cred.ticket_st.dat,
rxkadToken->rk_ticket.rk_ticket_len);
token.endTime = v5cred->times.endtime;
memcpy(&token.sessionKey, cred.session, 8);
token.ticketLen = cred.ticket_st.length;
memcpy(token.ticket, cred.ticket_st.dat, token.ticketLen);
status = token_importRxkadViceId(tokenPtr, &token, 0);
if (status) {
return status;
}
*tokenPtr = token;
*userPtr = strdup(username);
return 0;
@ -1070,8 +1051,13 @@ auth_to_cell(krb5_context context, const char *config,
#endif /* ALLOW_REGISTER */
if ((status == 0) && (viceId != ANONYMOUSID)) {
rxkadToken->ktc_tokenUnion_u.at_kad.rk_viceid = viceId;
token_replaceToken(token, rxkadToken);
status = token_setRxkadViceId(rxkadToken, viceId);
if (status) {
fprintf(stderr, "Error %d setting rxkad ViceId\n", status);
status = AKLOG_SUCCESS;
} else {
token_replaceToken(token, rxkadToken);
}
}
}
@ -1098,8 +1084,7 @@ auth_to_cell(krb5_context context, const char *config,
out:
if (rxkadToken) {
free(rxkadToken->ktc_tokenUnion_u.at_kad.rk_ticket.rk_ticket_val);
free(rxkadToken);
token_freeToken(&rxkadToken);
}
if (local_cell)

View File

@ -27,9 +27,15 @@ extern int token_SetsEquivalent(struct ktc_setTokenData *,
struct ktc_setTokenData *);
extern void token_setPag(struct ktc_setTokenData *, int);
extern void token_FreeSet(struct ktc_setTokenData **);
extern void token_freeToken(struct ktc_tokenUnion **);
extern void token_freeTokenContents(struct ktc_tokenUnion *);
struct ktc_token;
struct ktc_principal;
extern int token_extractRxkad(struct ktc_setTokenData *, struct ktc_token *,
int *, struct ktc_principal *);
extern int token_importRxkadViceId(struct ktc_tokenUnion **,
struct ktc_token *,
afs_int32);
extern int token_setRxkadViceId(struct ktc_tokenUnion *, afs_int32);
#endif /* AFS_SRC_AUTH_KTC_H */

View File

@ -75,11 +75,6 @@ decodeToken(struct token_opaque *opaque, struct ktc_tokenUnion *token) {
return code;
}
static void
freeToken(struct ktc_tokenUnion *token) {
xdr_free((xdrproc_t)xdr_ktc_tokenUnion, token);
}
static int
rxkadTokenEqual(struct ktc_tokenUnion *tokenA, struct ktc_tokenUnion *tokenB) {
return (tokenA->ktc_tokenUnion_u.at_kad.rk_kvno ==
@ -224,6 +219,99 @@ token_findByType(struct ktc_setTokenData *token,
return 0;
}
static void
SetRxkadViceId(struct token_rxkad *rxkadToken, afs_int32 viceId)
{
rxkadToken->rk_viceid = viceId;
if (viceId) {
if (((rxkadToken->rk_endtime - rxkadToken->rk_begintime) & 1) == 0) {
rxkadToken->rk_begintime++; /* force lifetime to be odd */
}
} else {
if (((rxkadToken->rk_endtime - rxkadToken->rk_begintime) & 1) == 1) {
rxkadToken->rk_begintime++; /* force lifetime to be even */
}
}
}
/**
* Import an rxkad token with a ViceId into a unified token.
*
* @param[out] atoken
* The resultant unified token. Free with token_freeToken.
* @param[in] oldToken
* The rxkad token to import.
* @param[in] viceId
* The optional rxkad ViceId to use. Specify 0 to explicitly not
* specify a ViceId.
*
* @return operation status
* @retval 0 success
*/
int
token_importRxkadViceId(struct ktc_tokenUnion **atoken,
struct ktc_token *oldToken,
afs_int32 viceId)
{
struct ktc_tokenUnion *token;
struct token_rxkad *rxkadToken;
token = malloc(sizeof(struct ktc_tokenUnion));
if (!token)
return ENOMEM;
token->at_type = AFSTOKEN_UNION_KAD;
rxkadToken = &token->ktc_tokenUnion_u.at_kad;
rxkadToken->rk_kvno = oldToken->kvno;
rxkadToken->rk_begintime = oldToken->startTime;
rxkadToken->rk_endtime = oldToken->endTime;
memcpy(&rxkadToken->rk_key, &oldToken->sessionKey,
sizeof(oldToken->sessionKey));
rxkadToken->rk_ticket.rk_ticket_len = oldToken->ticketLen;
rxkadToken->rk_ticket.rk_ticket_val = xdr_alloc(oldToken->ticketLen);
if (!rxkadToken->rk_ticket.rk_ticket_val) {
free(token);
return ENOMEM;
}
memcpy(rxkadToken->rk_ticket.rk_ticket_val, oldToken->ticket, oldToken->ticketLen);
SetRxkadViceId(rxkadToken, viceId);
*atoken = token;
return 0;
}
/**
* Set the optional ViceId for an rxkad token.
*
* @param[in] token
* The token union to change.
* @param[in] viceId
* The ViceId to set. Specify 0 to explicitly set no ViceId.
*
* @return operation status
* @retval EINVAL The given token union is not an rxkad token
* @retval 0 success
*/
int
token_setRxkadViceId(struct ktc_tokenUnion *token,
afs_int32 viceId)
{
struct token_rxkad *rxkadToken;
if (token->at_type != AFSTOKEN_UNION_KAD) {
return EINVAL;
}
rxkadToken = &token->ktc_tokenUnion_u.at_kad;
SetRxkadViceId(rxkadToken, viceId);
return 0;
}
/*!
* Given an unified token, populate an rxkad token from it
*
@ -411,11 +499,11 @@ token_SetsEquivalent(struct ktc_setTokenData *tokenSetA,
found = 1;
break;
}
freeToken(&tokenB);
token_freeTokenContents(&tokenB);
}
}
if (decodedOK)
freeToken(&tokenA);
token_freeTokenContents(&tokenA);
if (!found)
return 0;
@ -433,6 +521,22 @@ token_setPag(struct ktc_setTokenData *jar, int setpag) {
jar->flags &= ~AFSTOKEN_EX_SETPAG;
}
void
token_freeTokenContents(struct ktc_tokenUnion *atoken)
{
xdr_free((xdrproc_t)xdr_ktc_tokenUnion, atoken);
}
void
token_freeToken(struct ktc_tokenUnion **atoken)
{
if (*atoken) {
token_freeTokenContents(*atoken);
free(*atoken);
*atoken = NULL;
}
}
void
token_FreeSet(struct ktc_setTokenData **jar) {
if (*jar) {

View File

@ -690,7 +690,7 @@ auth_to_cell(krb5_context context, char *user, char *cell, char *realm)
done:
if (rxkadToken) {
token_freeImportedToken(&rxkadToken);
token_freeToken(&rxkadToken);
}
token_FreeSet(&token);
return(status);