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>
38 /* Routines for processing tokens in the new XDR format
40 * The code here is inspired by work done by Jeffrey Hutzelman et al
41 * at the AFSSIG.se hackathon and further refined by Matt
42 * Benjamin and Marcus Watts as part of rxk5. However, unless
43 * otherwise noted, the implementation is new
46 /* Take a peak at the enumerator in a given encoded token, in order to
50 tokenType(struct token_opaque *opaque) {
54 xdrmem_create(&xdrs, opaque->token_opaque_val, opaque->token_opaque_len,
57 if (!xdr_enum(&xdrs, &type))
66 decodeToken(struct token_opaque *opaque, struct ktc_tokenUnion *token) {
70 memset(token, 0, sizeof(struct ktc_tokenUnion));
71 xdrmem_create(&xdrs, opaque->token_opaque_val, opaque->token_opaque_len,
73 code = xdr_ktc_tokenUnion(&xdrs, token);
80 freeToken(struct ktc_tokenUnion *token) {
81 xdr_free((xdrproc_t)xdr_ktc_tokenUnion, token);
85 rxkadTokenEqual(struct ktc_tokenUnion *tokenA, struct ktc_tokenUnion *tokenB) {
86 return (tokenA->ktc_tokenUnion_u.at_kad.rk_kvno ==
87 tokenB->ktc_tokenUnion_u.at_kad.rk_kvno
88 && tokenA->ktc_tokenUnion_u.at_kad.rk_ticket.rk_ticket_len ==
89 tokenB->ktc_tokenUnion_u.at_kad.rk_ticket.rk_ticket_len
90 && !memcmp(tokenA->ktc_tokenUnion_u.at_kad.rk_key,
91 tokenB->ktc_tokenUnion_u.at_kad.rk_key, 8)
92 && !memcmp(tokenA->ktc_tokenUnion_u.at_kad.rk_ticket.rk_ticket_val,
93 tokenB->ktc_tokenUnion_u.at_kad.rk_ticket.rk_ticket_val,
94 tokenA->ktc_tokenUnion_u.at_kad.rk_ticket.rk_ticket_len));
98 tokenEqual(struct ktc_tokenUnion *tokenA,
99 struct ktc_tokenUnion *tokenB) {
100 switch (tokenA->at_type) {
101 case AFSTOKEN_UNION_KAD:
102 return rxkadTokenEqual(tokenA, tokenB);
108 rawTokenEqual(struct token_opaque *tokenA, struct token_opaque *tokenB) {
109 return (tokenA->token_opaque_len == tokenB->token_opaque_len &&
110 !memcmp(tokenA->token_opaque_val, tokenB->token_opaque_val,
111 tokenA->token_opaque_len));
114 /* Given a token type, return the entry number of the first token of that
117 findTokenEntry(struct ktc_setTokenData *token,
122 for (i = 0; i < token->tokens.tokens_len; i++) {
123 if (tokenType(&token->tokens.tokens_val[i]) == targetType)
129 /* XDR encode a token union structure, and return data and length information
130 * suitable for stuffing into a token_opaque structure
133 encodeTokenUnion(struct ktc_tokenUnion *token,
134 char **dataPtr, size_t *lenPtr) {
143 xdrlen_create(&xdrs);
144 if (!xdr_ktc_tokenUnion(&xdrs, token)) {
149 len = xdr_getpos(&xdrs);
157 xdrmem_create(&xdrs, data, len, XDR_ENCODE);
158 if (!xdr_ktc_tokenUnion(&xdrs, token)) {
177 addOpaque(struct ktc_setTokenData *jar, char *data, size_t len)
181 entry = jar->tokens.tokens_len;
182 jar->tokens.tokens_val = realloc(jar->tokens.tokens_val,
183 entry + 1 * sizeof(token_opaque));
184 jar->tokens.tokens_len++;
185 jar->tokens.tokens_val[entry].token_opaque_val = data;
186 jar->tokens.tokens_val[entry].token_opaque_len = len;
190 * Extract a specific token element from a unified token structure
192 * This routine extracts an afsTokenUnion structure from the tokenData
193 * structure used by the SetTokenEx and GetTokenEx pioctls
196 * A ktc_setTokenData structure containing the token to extract from
197 * @param[in] targetType
198 * The securityClass index of the token to be extracted
200 * The decoded token. On entry, this must point to a block of memory
201 * of sufficient size to contain an afsTokenUnion structure. Upon
202 * completion, this block must be passed to xdr_free(), using the
203 * xdr_afsTokenUnion xdrproc_t.
206 token_findByType(struct ktc_setTokenData *token,
208 struct ktc_tokenUnion *output)
212 memset(output, 0, sizeof *output);
213 entry = findTokenEntry(token, targetType);
217 if (!decodeToken(&token->tokens.tokens_val[entry], output))
220 if (output->at_type != targetType) {
221 xdr_free((xdrproc_t)xdr_ktc_tokenUnion, output);
229 * Given an unified token, populate an rxkad token from it
231 * This routine populates an rxkad token using information contained
232 * in the tokenData structure used by the SetTokenEx and GetTokenEX
236 * The new format token to extract information from.
237 * @param[out] rxkadToken
238 * The old-style rxkad token. This must be a pointer to an existing
239 * data block of sufficient size
241 * The set of token flags
242 * @param[out] aclient
243 * The client owning the token. This must be a pointer to an existing
244 * data block of sufficient size, or NULL.
248 token_extractRxkad(struct ktc_setTokenData *token,
249 struct ktc_token *rxkadToken,
251 struct ktc_principal *aclient)
253 struct ktc_tokenUnion uToken;
256 memset(&uToken, 0, sizeof(uToken));
258 memset(aclient, 0, sizeof(*aclient));
260 code = token_findByType(token, AFSTOKEN_UNION_KAD, &uToken);
264 rxkadToken->kvno = uToken.ktc_tokenUnion_u.at_kad.rk_kvno;
265 memcpy(rxkadToken->sessionKey.data,
266 uToken.ktc_tokenUnion_u.at_kad.rk_key, 8);
267 rxkadToken->startTime = uToken.ktc_tokenUnion_u.at_kad.rk_begintime;
268 rxkadToken->endTime = uToken.ktc_tokenUnion_u.at_kad.rk_endtime;
269 rxkadToken->ticketLen = uToken.ktc_tokenUnion_u.at_kad.rk_ticket.rk_ticket_len;
271 if (rxkadToken->ticketLen > MAXKTCTICKETLEN) {
276 memcpy(rxkadToken->ticket,
277 uToken.ktc_tokenUnion_u.at_kad.rk_ticket.rk_ticket_val,
278 rxkadToken->ticketLen);
281 *flags = uToken.ktc_tokenUnion_u.at_kad.rk_primary_flag & ~0x8000;
284 strncpy(aclient->cell, token->cell, MAXKTCREALMLEN-1);
285 aclient->cell[MAXKTCREALMLEN-1] = '\0';
287 if ((rxkadToken->kvno == 999) || /* old style bcrypt ticket */
288 (rxkadToken->startTime && /* new w/ prserver lookup */
289 (((rxkadToken->endTime - rxkadToken->startTime) & 1) == 1))) {
290 sprintf(aclient->name, "AFS ID %d",
291 uToken.ktc_tokenUnion_u.at_kad.rk_viceid);
293 sprintf(aclient->name, "Unix UID %d",
294 uToken.ktc_tokenUnion_u.at_kad.rk_viceid);
299 xdr_free((xdrproc_t) xdr_ktc_tokenUnion, &uToken);
303 struct ktc_setTokenData *
304 token_buildTokenJar(char * cellname) {
305 struct ktc_setTokenData *jar;
307 jar = malloc(sizeof(struct ktc_setTokenData));
311 memset(jar, 0, sizeof(struct ktc_setTokenData));
313 jar->cell = strdup(cellname);
319 * Add a token to an existing set of tokens. This will always add the token,
320 * regardless of whether an entry for the security class already exists
323 token_addToken(struct ktc_setTokenData *jar, struct ktc_tokenUnion *token) {
328 code = encodeTokenUnion(token, &data, &len);
332 addOpaque(jar, data, len);
339 * Replace at token in an existing set of tokens. This replaces the first
340 * token stored of a matching type. If no matching tokens are found, then
341 * the new token is added at the end of the list
344 token_replaceToken(struct ktc_setTokenData *jar,
345 struct ktc_tokenUnion *token) {
351 entry = findTokenEntry(jar, token->at_type);
353 return token_addToken(jar, token);
355 code = encodeTokenUnion(token, &data, &len);
359 free(jar->tokens.tokens_val[entry].token_opaque_val);
360 jar->tokens.tokens_val[entry].token_opaque_val = data;
361 jar->tokens.tokens_val[entry].token_opaque_len = len;
368 * Work out if a pair of token sets are equivalent. Equivalence
369 * is defined as both sets containing the same number of tokens,
370 * and every token in the first set having an equivalent token
371 * in the second set. Cell name and flags value are not compared.
374 * First set of tokens
376 * Second set of tokens
379 * True if token sets are equivalent, false otherwise
382 token_SetsEquivalent(struct ktc_setTokenData *tokenSetA,
383 struct ktc_setTokenData *tokenSetB) {
385 int decodedOK, found;
386 struct ktc_tokenUnion tokenA, tokenB;
388 if (tokenSetA->tokens.tokens_len != tokenSetB->tokens.tokens_len)
391 for (i=0; i<tokenSetA->tokens.tokens_len; i++) {
394 decodedOK = decodeToken(&tokenSetA->tokens.tokens_val[i], &tokenA);
396 for (j=0; j<tokenSetB->tokens.tokens_len && !found; j++) {
397 if (rawTokenEqual(&tokenSetA->tokens.tokens_val[i],
398 &tokenSetB->tokens.tokens_val[j])) {
404 tokenType(&tokenSetB->tokens.tokens_val[j]) == tokenA.at_type
405 && decodeToken(&tokenSetB->tokens.tokens_val[j], &tokenB)) {
407 if (tokenEqual(&tokenA, &tokenB)) {
420 /* If we made it this far without exiting, we must have found equivalents
421 * for all of our tokens */
426 token_setPag(struct ktc_setTokenData *jar, int setpag) {
428 jar->flags |= AFSTOKEN_EX_SETPAG;
430 jar->flags &= ~AFSTOKEN_EX_SETPAG;
434 token_FreeSet(struct ktc_setTokenData **jar) {
436 xdr_free((xdrproc_t)xdr_ktc_setTokenData, *jar);
437 memset(*jar, 0, sizeof(struct ktc_setTokenData));