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>
35 /* Routines for processing tokens in the new XDR format
37 * The code here is inspired by work done by Jeffrey Hutzelman et al
38 * at the AFSSIG.se hackathon and further refined by Matt
39 * Benjamin and Marcus Watts as part of rxk5. However, unless
40 * otherwise noted, the implementation is new
43 /* Take a peak at the enumerator in a given encoded token, in order to
47 tokenType(struct token_opaque *opaque) {
51 xdrmem_create(&xdrs, opaque->token_opaque_val, opaque->token_opaque_len,
54 if (!xdr_enum(&xdrs, &type))
63 decodeToken(struct token_opaque *opaque, struct ktc_tokenUnion *token) {
67 memset(token, 0, sizeof(struct ktc_tokenUnion));
68 xdrmem_create(&xdrs, opaque->token_opaque_val, opaque->token_opaque_len,
70 code = xdr_ktc_tokenUnion(&xdrs, token);
77 freeToken(struct ktc_tokenUnion *token) {
78 xdr_free((xdrproc_t)xdr_ktc_tokenUnion, token);
82 rxkadTokenEqual(struct ktc_tokenUnion *tokenA, struct ktc_tokenUnion *tokenB) {
83 return (tokenA->ktc_tokenUnion_u.at_kad.rk_kvno ==
84 tokenB->ktc_tokenUnion_u.at_kad.rk_kvno
85 && tokenA->ktc_tokenUnion_u.at_kad.rk_ticket.rk_ticket_len ==
86 tokenB->ktc_tokenUnion_u.at_kad.rk_ticket.rk_ticket_len
87 && !memcmp(tokenA->ktc_tokenUnion_u.at_kad.rk_key,
88 tokenB->ktc_tokenUnion_u.at_kad.rk_key, 8)
89 && !memcmp(tokenA->ktc_tokenUnion_u.at_kad.rk_ticket.rk_ticket_val,
90 tokenB->ktc_tokenUnion_u.at_kad.rk_ticket.rk_ticket_val,
91 tokenA->ktc_tokenUnion_u.at_kad.rk_ticket.rk_ticket_len));
95 tokenEqual(struct ktc_tokenUnion *tokenA,
96 struct ktc_tokenUnion *tokenB) {
97 switch (tokenA->at_type) {
98 case AFSTOKEN_UNION_KAD:
99 return rxkadTokenEqual(tokenA, tokenB);
105 rawTokenEqual(struct token_opaque *tokenA, struct token_opaque *tokenB) {
106 return (tokenA->token_opaque_len == tokenB->token_opaque_len &&
107 !memcmp(tokenA->token_opaque_val, tokenB->token_opaque_val,
108 tokenA->token_opaque_len));
111 /* Given a token type, return the entry number of the first token of that
114 findTokenEntry(struct ktc_setTokenData *token,
119 for (i = 0; i < token->tokens.tokens_len; i++) {
120 if (tokenType(&token->tokens.tokens_val[i]) == targetType)
126 /* XDR encode a token union structure, and return data and length information
127 * suitable for stuffing into a token_opaque structure
130 encodeTokenUnion(struct ktc_tokenUnion *token,
131 char **dataPtr, size_t *lenPtr) {
140 xdrlen_create(&xdrs);
141 if (!xdr_ktc_tokenUnion(&xdrs, token)) {
146 len = xdr_getpos(&xdrs);
154 xdrmem_create(&xdrs, data, len, XDR_ENCODE);
155 if (!xdr_ktc_tokenUnion(&xdrs, token)) {
174 addOpaque(struct ktc_setTokenData *jar, char *data, size_t len)
178 entry = jar->tokens.tokens_len;
179 jar->tokens.tokens_val = realloc(jar->tokens.tokens_val,
180 entry + 1 * sizeof(token_opaque));
181 jar->tokens.tokens_len++;
182 jar->tokens.tokens_val[entry].token_opaque_val = data;
183 jar->tokens.tokens_val[entry].token_opaque_len = len;
187 * Extract a specific token element from a unified token structure
189 * This routine extracts an afsTokenUnion structure from the tokenData
190 * structure used by the SetTokenEx and GetTokenEx pioctls
193 * A ktc_setTokenData structure containing the token to extract from
194 * @param[in] targetType
195 * The securityClass index of the token to be extracted
197 * The decoded token. On entry, this must point to a block of memory
198 * of sufficient size to contain an afsTokenUnion structure. Upon
199 * completion, this block must be passed to xdr_free(), using the
200 * xdr_afsTokenUnion xdrproc_t.
203 token_findByType(struct ktc_setTokenData *token,
205 struct ktc_tokenUnion *output)
209 memset(output, 0, sizeof *output);
210 entry = findTokenEntry(token, targetType);
214 if (!decodeToken(&token->tokens.tokens_val[entry], output))
217 if (output->at_type != targetType) {
218 xdr_free((xdrproc_t)xdr_ktc_tokenUnion, output);
226 * Given an unified token, populate an rxkad token from it
228 * This routine populates an rxkad token using information contained
229 * in the tokenData structure used by the SetTokenEx and GetTokenEX
233 * The new format token to extract information from.
234 * @param[out] rxkadToken
235 * The old-style rxkad token. This must be a pointer to an existing
236 * data block of sufficient size
238 * The set of token flags
239 * @param[out] aclient
240 * The client owning the token. This must be a pointer to an existing
241 * data block of sufficient size, or NULL.
245 token_extractRxkad(struct ktc_setTokenData *token,
246 struct ktc_token *rxkadToken,
248 struct ktc_principal *aclient)
250 struct ktc_tokenUnion uToken;
253 memset(&uToken, 0, sizeof(uToken));
255 memset(aclient, 0, sizeof(*aclient));
257 code = token_findByType(token, AFSTOKEN_UNION_KAD, &uToken);
261 rxkadToken->kvno = uToken.ktc_tokenUnion_u.at_kad.rk_kvno;
262 memcpy(rxkadToken->sessionKey.data,
263 uToken.ktc_tokenUnion_u.at_kad.rk_key, 8);
264 rxkadToken->startTime = uToken.ktc_tokenUnion_u.at_kad.rk_begintime;
265 rxkadToken->endTime = uToken.ktc_tokenUnion_u.at_kad.rk_endtime;
266 rxkadToken->ticketLen = uToken.ktc_tokenUnion_u.at_kad.rk_ticket.rk_ticket_len;
268 if (rxkadToken->ticketLen > MAXKTCTICKETLEN) {
273 memcpy(rxkadToken->ticket,
274 uToken.ktc_tokenUnion_u.at_kad.rk_ticket.rk_ticket_val,
275 rxkadToken->ticketLen);
278 *flags = uToken.ktc_tokenUnion_u.at_kad.rk_primary_flag & ~0x8000;
281 strncpy(aclient->cell, token->cell, MAXKTCREALMLEN-1);
282 aclient->cell[MAXKTCREALMLEN-1] = '\0';
284 if ((rxkadToken->kvno == 999) || /* old style bcrypt ticket */
285 (rxkadToken->startTime && /* new w/ prserver lookup */
286 (((rxkadToken->endTime - rxkadToken->startTime) & 1) == 1))) {
287 sprintf(aclient->name, "AFS ID %d",
288 uToken.ktc_tokenUnion_u.at_kad.rk_viceid);
290 sprintf(aclient->name, "Unix UID %d",
291 uToken.ktc_tokenUnion_u.at_kad.rk_viceid);
296 xdr_free((xdrproc_t) xdr_ktc_tokenUnion, &uToken);
300 struct ktc_setTokenData *
301 token_buildTokenJar(char * cellname) {
302 struct ktc_setTokenData *jar;
304 jar = malloc(sizeof(struct ktc_setTokenData));
308 memset(jar, 0, sizeof(struct ktc_setTokenData));
310 jar->cell = strdup(cellname);
316 * Add a token to an existing set of tokens. This will always add the token,
317 * regardless of whether an entry for the security class already exists
320 token_addToken(struct ktc_setTokenData *jar, struct ktc_tokenUnion *token) {
325 code = encodeTokenUnion(token, &data, &len);
329 addOpaque(jar, data, len);
336 * Replace at token in an existing set of tokens. This replaces the first
337 * token stored of a matching type. If no matching tokens are found, then
338 * the new token is added at the end of the list
341 token_replaceToken(struct ktc_setTokenData *jar,
342 struct ktc_tokenUnion *token) {
348 entry = findTokenEntry(jar, token->at_type);
350 return token_addToken(jar, token);
352 code = encodeTokenUnion(token, &data, &len);
356 free(jar->tokens.tokens_val[entry].token_opaque_val);
357 jar->tokens.tokens_val[entry].token_opaque_val = data;
358 jar->tokens.tokens_val[entry].token_opaque_len = len;
365 * Work out if a pair of token sets are equivalent. Equivalence
366 * is defined as both sets containing the same number of tokens,
367 * and every token in the first set having an equivalent token
368 * in the second set. Cell name and flags value are not compared.
371 * First set of tokens
373 * Second set of tokens
376 * True if token sets are equivalent, false otherwise
379 token_SetsEquivalent(struct ktc_setTokenData *tokenSetA,
380 struct ktc_setTokenData *tokenSetB) {
382 int decodedOK, found;
383 struct ktc_tokenUnion tokenA, tokenB;
385 if (tokenSetA->tokens.tokens_len != tokenSetB->tokens.tokens_len)
388 for (i=0; i<tokenSetA->tokens.tokens_len; i++) {
391 decodedOK = decodeToken(&tokenSetA->tokens.tokens_val[i], &tokenA);
393 for (j=0; j<tokenSetB->tokens.tokens_len && !found; j++) {
394 if (rawTokenEqual(&tokenSetA->tokens.tokens_val[i],
395 &tokenSetB->tokens.tokens_val[j])) {
401 tokenType(&tokenSetB->tokens.tokens_val[j]) == tokenA.at_type
402 && decodeToken(&tokenSetB->tokens.tokens_val[j], &tokenB)) {
404 if (tokenEqual(&tokenA, &tokenB)) {
417 /* If we made it this far without exiting, we must have found equivalents
418 * for all of our tokens */
423 token_setPag(struct ktc_setTokenData *jar, int setpag) {
425 jar->flags |= AFSTOKEN_EX_SETPAG;
427 jar->flags &= ~AFSTOKEN_EX_SETPAG;
431 token_FreeSet(struct ktc_setTokenData **jar) {
433 xdr_free((xdrproc_t)xdr_ktc_setTokenData, *jar);
434 memset(*jar, 0, sizeof(struct ktc_setTokenData));