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 <sys/errno.h>
27 #include <afsconfig.h>
28 #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 /* Given a token type, return the entry number of the first token of that
46 findTokenEntry(struct ktc_setTokenData *token,
52 for (i = 0; i < token->tokens.tokens_len; i++) {
54 token->tokens.tokens_val[i].token_opaque_val,
55 token->tokens.tokens_val[i].token_opaque_len,
57 /* Take a peak at the discriminator. */
58 if (!xdr_enum(&xdrs, &type)) {
63 if (type == targetType)
69 /* XDR encode a token union structure, and return data and length information
70 * suitable for stuffing into a token_opaque structure
73 encodeTokenUnion(struct ktc_tokenUnion *token,
74 char **dataPtr, size_t *lenPtr) {
84 if (!xdr_ktc_tokenUnion(&xdrs, token)) {
89 len = xdr_getpos(&xdrs);
97 xdrmem_create(&xdrs, data, len, XDR_ENCODE);
98 if (!xdr_ktc_tokenUnion(&xdrs, token)) {
117 addOpaque(struct ktc_setTokenData *jar, char *data, size_t len)
121 entry = jar->tokens.tokens_len;
122 jar->tokens.tokens_val = realloc(jar->tokens.tokens_val,
123 entry + 1 * sizeof(token_opaque));
124 jar->tokens.tokens_len++;
125 jar->tokens.tokens_val[entry].token_opaque_val = data;
126 jar->tokens.tokens_val[entry].token_opaque_len = len;
130 * Extract a specific token element from a unified token structure
132 * This routine extracts an afsTokenUnion structure from the tokenData
133 * structure used by the SetTokenEx and GetTokenEx pioctls
136 * A ktc_setTokenData structure containing the token to extract from
137 * @param[in] targetType
138 * The securityClass index of the token to be extracted
140 * The decoded token. On entry, this must point to a block of memory
141 * of sufficient size to contain an afsTokenUnion structure. Upon
142 * completion, this block must be passed to xdr_free(), using the
143 * xdr_afsTokenUnion xdrproc_t.
146 token_findByType(struct ktc_setTokenData *token,
148 struct ktc_tokenUnion *output)
154 memset(output, 0, sizeof *output);
155 entry = findTokenEntry(token, targetType);
160 token->tokens.tokens_val[entry].token_opaque_val,
161 token->tokens.tokens_val[entry].token_opaque_len,
164 if (!xdr_ktc_tokenUnion(&xdrs, output)) {
170 if (output->at_type != targetType) {
171 xdr_free((xdrproc_t)xdr_ktc_tokenUnion, output);
182 * Given an unified token, populate an rxkad token from it
184 * This routine populates an rxkad token using information contained
185 * in the tokenData structure used by the SetTokenEx and GetTokenEX
189 * The new format token to extract information from.
190 * @param[out] rxkadToken
191 * The old-style rxkad token. This must be a pointer to an existing
192 * data block of sufficient size
194 * The set of token flags
195 * @param[out] aclient
196 * The client owning the token. This must be a pointer to an existing
197 * data block of sufficient size, or NULL.
201 token_extractRxkad(struct ktc_setTokenData *token,
202 struct ktc_token *rxkadToken,
204 struct ktc_principal *aclient)
206 struct ktc_tokenUnion uToken;
209 memset(&uToken, 0, sizeof(uToken));
211 memset(aclient, 0, sizeof(*aclient));
213 code = token_findByType(token, AFSTOKEN_UNION_KAD, &uToken);
217 rxkadToken->kvno = uToken.ktc_tokenUnion_u.at_kad.rk_kvno;
218 memcpy(rxkadToken->sessionKey.data,
219 uToken.ktc_tokenUnion_u.at_kad.rk_key, 8);
220 rxkadToken->startTime = uToken.ktc_tokenUnion_u.at_kad.rk_begintime;
221 rxkadToken->endTime = uToken.ktc_tokenUnion_u.at_kad.rk_endtime;
222 rxkadToken->ticketLen = uToken.ktc_tokenUnion_u.at_kad.rk_ticket.rk_ticket_len;
224 if (rxkadToken->ticketLen > MAXKTCTICKETLEN) {
229 memcpy(rxkadToken->ticket,
230 uToken.ktc_tokenUnion_u.at_kad.rk_ticket.rk_ticket_val,
231 rxkadToken->ticketLen);
234 *flags = uToken.ktc_tokenUnion_u.at_kad.rk_primary_flag & ~0x8000;
237 strncpy(aclient->cell, token->cell, MAXKTCREALMLEN-1);
238 aclient->cell[MAXKTCREALMLEN-1] = '\0';
240 if ((rxkadToken->kvno == 999) || /* old style bcrypt ticket */
241 (rxkadToken->startTime && /* new w/ prserver lookup */
242 (((rxkadToken->endTime - rxkadToken->startTime) & 1) == 1))) {
243 sprintf(aclient->name, "AFS ID %d",
244 uToken.ktc_tokenUnion_u.at_kad.rk_viceid);
246 sprintf(aclient->name, "Unix UID %d",
247 uToken.ktc_tokenUnion_u.at_kad.rk_viceid);
252 xdr_free((xdrproc_t) xdr_ktc_tokenUnion, &uToken);
256 struct ktc_setTokenData *
257 token_buildTokenJar(char * cellname) {
258 struct ktc_setTokenData *jar;
260 jar = malloc(sizeof(struct ktc_setTokenData));
264 memset(jar, 0, sizeof(struct ktc_setTokenData));
266 jar->cell = strdup(cellname);
272 * Add a token to an existing set of tokens. This will always add the token,
273 * regardless of whether an entry for the security class already exists
276 token_addToken(struct ktc_setTokenData *jar, struct ktc_tokenUnion *token) {
281 code = encodeTokenUnion(token, &data, &len);
285 addOpaque(jar, data, len);
292 * Replace at token in an existing set of tokens. This replaces the first
293 * token stored of a matching type. If no matching tokens are found, then
294 * the new token is added at the end of the list
297 token_replaceToken(struct ktc_setTokenData *jar,
298 struct ktc_tokenUnion *token) {
304 entry = findTokenEntry(jar, token->at_type);
306 return token_addToken(jar, token);
308 code = encodeTokenUnion(token, &data, &len);
312 free(jar->tokens.tokens_val[entry].token_opaque_val);
313 jar->tokens.tokens_val[entry].token_opaque_val = data;
314 jar->tokens.tokens_val[entry].token_opaque_len = len;
321 token_setPag(struct ktc_setTokenData *jar, int setpag) {
323 jar->flags |= AFSTOKEN_EX_SETPAG;
325 jar->flags &= ~AFSTOKEN_EX_SETPAG;