Add new SetTokenEx pioctl
[openafs.git] / src / afs / afs_tokens.c
1 /*
2  * Copyright (c) 2010 Your Filesystem Inc. All rights reserved.
3  *
4  * Redistribution and use in source and binary forms, with or without
5  * modification, are permitted provided that the following conditions
6  * are met:
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.
12  *
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.
23  */
24
25 #include <afsconfig.h>
26 #include "afs/param.h"
27 #include "afs/sysincludes.h"
28 #include "afsincludes.h"
29 #include "token.h"
30
31 /* A jar for storing tokens in */
32
33 /*!
34  * Return a token of the specified type from the selected tokenjar.
35  *
36  * @param[in] tokens
37  *      The tokenjar in which to search
38  * @param[in] type
39  *      The type of token to return
40  *
41  * @return
42  *      A tokenUnion structure, from which the desired token can be
43  *      accessed using the appropriate element of the union.
44  */
45 union tokenUnion *
46 afs_FindToken(struct tokenJar *tokens, rx_securityIndex type) {
47     while (tokens != NULL) {
48         if (tokens->type == type) {
49             return &tokens->u;
50         }
51         tokens = tokens->next;
52     }
53     return NULL;
54 }
55
56 /*!
57  * Free a single token
58  *
59  * This will free the given token. No attempt is made to unlink
60  * the token from its container, and it is an error to attempt to
61  * free a token which is still linked.
62  *
63  * This performs a secure free, setting all token information to 0
64  * before returning allocated data blocks to the kernel.
65  *
66  * Intended primarily for internal use.
67  *
68  * @param[in] token
69  *      The token to free
70  */
71
72 void
73 afs_FreeOneToken(struct tokenJar *token) {
74     if (token->next != NULL)
75         osi_Panic("Freeing linked token");
76
77     switch (token->type) {
78       case RX_SECIDX_KAD:
79         if (token->u.rxkad.ticket != NULL) {
80                 memset(token->u.rxkad.ticket, 0, token->u.rxkad.ticketLen);
81                 afs_osi_Free(token->u.rxkad.ticket,
82                              token->u.rxkad.ticketLen);
83         }
84         break;
85       default:
86         break;
87     }
88     memset(token, 0, sizeof(struct tokenJar));
89     afs_osi_Free(token, sizeof(struct tokenJar));
90 }
91
92 /*!
93  * Free a token jar
94  *
95  * Free all of the tokens in a given token jar. This will also set the
96  * pointer to the jar to NULL, to indicate that it has been freed.
97  *
98  * @param[in] tokenPtr
99  *      A pointer to the address of the tokenjar to free.
100  */
101 void
102 afs_FreeTokens(struct tokenJar **tokenPtr) {
103     struct tokenJar *next, *tokens;
104
105     tokens = *tokenPtr;
106     *tokenPtr = NULL;
107     while(tokens != NULL) {
108         next = tokens->next;
109         tokens->next = NULL; /* Unlink from chain */
110         afs_FreeOneToken(tokens);
111         tokens = next;
112     }
113 }
114
115 /*!
116  * Add a token to a token jar
117  *
118  * Add a new token to a token jar. If the jar already exists,
119  * then this token becomes the first in the jar. If it doesn't
120  * exist, then a new jar is created. The contents of the new
121  * token are initialised to 0 upon creation.
122  *
123  * @param[in] tokens
124  *      A pointer to the address of the token jar to populate
125  * @param[in] type
126  *      The type of token to create
127  *
128  * @return
129  *      A pointer to the tokenUnion of the newly created token,
130  *      which may then be used to populate the token.
131  */
132 union tokenUnion *
133 afs_AddToken(struct tokenJar **tokens, rx_securityIndex type) {
134     struct tokenJar *newToken;
135
136     newToken = afs_osi_Alloc(sizeof(struct tokenJar));
137     memset(newToken, 0, sizeof(*newToken));
138
139     newToken->type = type;
140     newToken->next = *tokens;
141     *tokens = newToken;
142
143     return &newToken->u;
144 }
145
146 /*!
147  * Indicate if a single token is expired
148  *
149  * @param[in] token
150  *      The token to check
151  * @param[in] now
152  *      The time to check against for expiry (typically the results of
153  *      calling osi_Time())
154  *
155  * @returns
156  *      True if the token has expired, false otherwise
157  */
158 int
159 afs_IsTokenExpired(struct tokenJar *token, afs_int32 now) {
160     switch (token->type) {
161       case RX_SECIDX_KAD:
162         if (token->u.rxkad.clearToken.EndTimestamp < now - NOTOKTIMEOUT)
163             return 1;
164         break;
165       default:
166         return 0;
167     }
168     return 0; /* not reached, but keep gcc happy */
169 }
170
171 /*!
172  * Indicate if a token is usable by the kernel module
173  *
174  * This determines whether a token is usable. A usable token is one that
175  * has not expired, and which is otherwise suitable for use.
176  *
177  * @param[in] token
178  *      The token to check
179  * @param[in] now
180  *      The time to use for the expiry check
181  *
182  * @returns
183  *      True if the token is usable, false otherwise
184  */
185 int
186 afs_IsTokenUsable(struct tokenJar *token, afs_int32 now) {
187
188     if (afs_IsTokenExpired(token, now))
189         return 0;
190
191     switch (token->type) {
192       case RX_SECIDX_KAD:
193         /* We assume that all non-expired rxkad tokens are usable by us */
194         return 1;
195       default :
196         return 0;
197     }
198 }
199
200 /*!
201  * Discard all expired tokens from a token jar
202  *
203  * This permanently removes all tokens which have expired from the token
204  * jar. Note that tokens which are not usable, but which have not expired,
205  * will not be deleted.
206  *
207  * @param[in] tokenPtr
208  *      A pointer to the address of the token jar to check
209  * @param[in] now
210  *      The time to use for the expiry check
211  */
212
213 void
214 afs_DiscardExpiredTokens(struct tokenJar **tokenPtr, afs_int32 now) {
215     struct tokenJar *next;
216
217     while (*tokenPtr != NULL) {
218         if (afs_IsTokenExpired(*tokenPtr, now)) {
219             next = (*tokenPtr)->next;
220             (*tokenPtr)->next = NULL;
221             afs_FreeOneToken(*tokenPtr);
222             *tokenPtr = next;
223         } else {
224             tokenPtr = &(*tokenPtr)->next;
225         }
226     }
227 }
228
229 /*!
230  * Indicate whether a token jar contains one, or more usable tokens
231  *
232  * @param[in] token
233  *      The token jar to check
234  * @param[in] now
235  *      The cime to use for the expiry check
236  *
237  * @returns
238  *      True if the jar contains usable tokens, otherwise false
239  */
240 int
241 afs_HasUsableTokens(struct tokenJar *token, afs_int32 now) {
242     while (token != NULL) {
243         if (afs_IsTokenUsable(token, now))
244             return 1;
245         token = token->next;
246     }
247     return 0;
248 }
249
250 /*!
251  * Add an rxkad token to the token jar
252  *
253  * @param[in] tokens
254  *      A pointer to the address of the jar to add the token to
255  * @param[in] ticket
256  *      A data block containing the token's opaque ticket
257  * @param[in] ticketLen
258  *      The length of the ticket data block
259  * @param[in] clearToken
260  *      The cleartext token information
261  */
262 void
263 afs_AddRxkadToken(struct tokenJar **tokens, char *ticket, int ticketLen,
264                   struct ClearToken *clearToken) {
265     union tokenUnion *tokenU;
266     struct rxkadToken *rxkad;
267
268     tokenU = afs_AddToken(tokens, RX_SECIDX_KAD);
269     rxkad = &tokenU->rxkad;
270
271     rxkad->ticket = afs_osi_Alloc(ticketLen);
272     rxkad->ticketLen = ticketLen;
273     memcpy(rxkad->ticket, ticket, ticketLen);
274     rxkad->clearToken = *clearToken;
275 }
276
277 static int
278 afs_AddRxkadTokenFromPioctl(struct tokenJar **tokens,
279                             struct ktc_tokenUnion *pioctlToken) {
280     struct ClearToken clear;
281
282     clear.AuthHandle = pioctlToken->ktc_tokenUnion_u.at_kad.rk_kvno;
283     clear.ViceId = pioctlToken->ktc_tokenUnion_u.at_kad.rk_viceid;
284     clear.BeginTimestamp = pioctlToken->ktc_tokenUnion_u.at_kad.rk_begintime;
285     clear.EndTimestamp = pioctlToken->ktc_tokenUnion_u.at_kad.rk_endtime;
286     memcpy(clear.HandShakeKey, pioctlToken->ktc_tokenUnion_u.at_kad.rk_key, 8);
287     afs_AddRxkadToken(tokens,
288                       pioctlToken->ktc_tokenUnion_u.at_kad.rk_ticket.rk_ticket_val,
289                       pioctlToken->ktc_tokenUnion_u.at_kad.rk_ticket.rk_ticket_len,
290                       &clear);
291
292     /* Security means never having to say you're sorry */
293     memset(clear.HandShakeKey, 0, 8);
294
295     return 0;
296 }
297
298
299 /*!
300  * Add a token to a token jar based on the input from a new-style
301  * SetToken pioctl
302  *
303  * @param[in] tokens
304  *      Pointer to the address of a token jar
305  * @param[in] pioctlToken
306  *      The token structure obtained through the pioctl (note this
307  *      is a single, XDR decoded, token)
308  *
309  * @returns
310  *      0 on success, an error code on failure
311  */
312 int
313 afs_AddTokenFromPioctl(struct tokenJar **tokens,
314                        struct ktc_tokenUnion *pioctlToken) {
315
316     switch (pioctlToken->at_type) {
317       case RX_SECIDX_KAD:
318         return afs_AddRxkadTokenFromPioctl(tokens, pioctlToken);
319     }
320
321     return EINVAL;
322 }