changed `struct fd_set' to `fd_set'
[heimdal.git] / lib / krb5 / fcache.c
blob3c92afc35c426cfde62c80f18204abd9006cae48
1 /*
2 * Copyright (c) 1997 Kungliga Tekniska Högskolan
3 * (Royal Institute of Technology, Stockholm, Sweden).
4 * All rights reserved.
6 * Redistribution and use in source and binary forms, with or without
7 * modification, are permitted provided that the following conditions
8 * are met:
10 * 1. Redistributions of source code must retain the above copyright
11 * notice, this list of conditions and the following disclaimer.
13 * 2. Redistributions in binary form must reproduce the above copyright
14 * notice, this list of conditions and the following disclaimer in the
15 * documentation and/or other materials provided with the distribution.
17 * 3. All advertising materials mentioning features or use of this software
18 * must display the following acknowledgement:
19 * This product includes software developed by Kungliga Tekniska
20 * Högskolan and its contributors.
22 * 4. Neither the name of the Institute nor the names of its contributors
23 * may be used to endorse or promote products derived from this software
24 * without specific prior written permission.
26 * THIS SOFTWARE IS PROVIDED BY THE INSTITUTE AND CONTRIBUTORS ``AS IS'' AND
27 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
28 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
29 * ARE DISCLAIMED. IN NO EVENT SHALL THE INSTITUTE OR CONTRIBUTORS BE LIABLE
30 * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
31 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
32 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
33 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
34 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
35 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
36 * SUCH DAMAGE.
39 #include "krb5_locl.h"
41 RCSID("$Id$");
43 typedef struct krb5_fcache{
44 char *filename;
45 int version;
46 }krb5_fcache;
48 #define KRB5_FCC_FVNO_3 0x503
49 #define KRB5_FCC_FVNO_4 0x504
51 #define FCC_TAG_DELTATIME 1
53 #define FILENAME(X) (((krb5_fcache*)(X)->data.data)->filename)
55 #define FCACHE(X) ((krb5_fcache*)(X)->data.data)
57 static char*
58 fcc_get_name(krb5_context context,
59 krb5_ccache id)
61 return FILENAME(id);
64 static krb5_error_code
65 fcc_resolve(krb5_context context, krb5_ccache *id, const char *res)
67 krb5_fcache *f;
68 f = malloc(sizeof(*f));
69 if(f == NULL)
70 return KRB5_CC_NOMEM;
71 f->filename = strdup(res);
72 if(f->filename == NULL){
73 free(f);
74 return KRB5_CC_NOMEM;
76 f->version = 0;
77 (*id)->data.data = f;
78 (*id)->data.length = sizeof(*f);
79 return 0;
82 static krb5_error_code
83 erase_file(const char *filename)
85 int fd;
86 off_t pos;
87 char *p;
89 fd = open(filename, O_RDWR);
90 if(fd < 0)
91 if(errno == ENOENT)
92 return 0;
93 else
94 return errno;
95 pos = lseek(fd, 0, SEEK_END);
96 lseek(fd, 0, SEEK_SET);
97 p = (char*) malloc(pos);
98 memset(p, 0, pos);
99 write(fd, p, pos);
100 free(p);
101 close(fd);
102 unlink(filename);
103 return 0;
106 static krb5_error_code
107 fcc_gen_new(krb5_context context, krb5_ccache *id)
109 abort();
112 static krb5_error_code
113 fcc_initialize(krb5_context context,
114 krb5_ccache id,
115 krb5_principal primary_principal)
117 krb5_fcache *f = FCACHE(id);
118 int ret;
119 int fd;
120 char *filename = f->filename;
122 if((ret = erase_file(filename)))
123 return ret;
125 fd = open(filename, O_RDWR | O_CREAT | O_EXCL, 0600);
126 if(fd == -1)
127 return errno;
129 krb5_storage *sp;
130 sp = krb5_storage_from_fd(fd);
131 f->version = KRB5_FCC_FVNO_4;
132 krb5_store_int16(sp, f->version);
133 /* V4 stuff */
134 if (context->kdc_sec_offset) {
135 krb5_store_int16 (sp, 12); /* length */
136 krb5_store_int16 (sp, FCC_TAG_DELTATIME); /* Tag */
137 krb5_store_int16 (sp, 8); /* length of data */
138 krb5_store_int32 (sp, context->kdc_sec_offset);
139 krb5_store_int32 (sp, context->kdc_usec_offset);
140 } else {
141 krb5_store_int16 (sp, 0);
143 krb5_store_principal(sp, primary_principal);
144 krb5_storage_free(sp);
146 close(fd);
148 return 0;
151 static krb5_error_code
152 fcc_close(krb5_context context,
153 krb5_ccache id)
155 free (FILENAME(id));
156 krb5_data_free(&id->data);
157 return 0;
160 static krb5_error_code
161 fcc_destroy(krb5_context context,
162 krb5_ccache id)
164 char *f;
165 f = FILENAME(id);
167 return erase_file(f);
169 return fcc_close (context, id);
172 static krb5_error_code
173 fcc_store_cred(krb5_context context,
174 krb5_ccache id,
175 krb5_creds *creds)
177 int fd;
178 char *f;
180 f = FILENAME(id);
182 fd = open(f, O_WRONLY | O_APPEND);
183 if(fd < 0)
184 return errno;
186 krb5_storage *sp;
187 sp = krb5_storage_from_fd(fd);
188 krb5_store_principal(sp, creds->client);
189 krb5_store_principal(sp, creds->server);
190 krb5_store_keyblock(sp, creds->session);
191 krb5_store_times(sp, creds->times);
192 krb5_store_int8(sp, 0); /* this is probably the
193 enc-tkt-in-skey bit from KDCOptions */
194 krb5_store_int32(sp, creds->flags.i);
195 krb5_store_addrs(sp, creds->addresses);
196 krb5_store_authdata(sp, creds->authdata);
197 krb5_store_data(sp, creds->ticket);
198 krb5_store_data(sp, creds->second_ticket);
199 krb5_storage_free(sp);
201 close(fd);
202 return 0; /* XXX */
205 static krb5_error_code
206 fcc_read_cred (int fd,
207 krb5_creds *creds)
209 int ret = 0;
210 int8_t dummy8;
211 int32_t dummy32;
212 krb5_storage *sp;
214 sp = krb5_storage_from_fd(fd);
216 ret = krb5_ret_principal (sp, &creds->client);
217 if(ret) goto cleanup;
218 ret = krb5_ret_principal (sp, &creds->server);
219 if(ret) goto cleanup;
220 ret = krb5_ret_keyblock (sp, &creds->session);
221 if(ret) goto cleanup;
222 ret = krb5_ret_times (sp, &creds->times);
223 if(ret) goto cleanup;
224 ret = krb5_ret_int8 (sp, &dummy8);
225 if(ret) goto cleanup;
226 ret = krb5_ret_int32 (sp, &dummy32);
227 if(ret) goto cleanup;
228 creds->flags.i = dummy32;
229 ret = krb5_ret_addrs (sp, &creds->addresses);
230 if(ret) goto cleanup;
231 ret = krb5_ret_authdata (sp, &creds->authdata);
232 if(ret) goto cleanup;
233 ret = krb5_ret_data (sp, &creds->ticket);
234 if(ret) goto cleanup;
235 ret = krb5_ret_data (sp, &creds->second_ticket);
237 cleanup:
238 krb5_storage_free(sp);
239 return ret;
242 static krb5_error_code
243 init_fcc (krb5_context context,
244 krb5_fcache *fcache,
245 krb5_storage **ret_sp,
246 int *ret_fd)
248 int fd;
249 int16_t tag;
250 krb5_storage *sp;
252 fd = open(fcache->filename, O_RDONLY);
253 if(fd < 0)
254 return errno;
255 sp = krb5_storage_from_fd(fd);
256 krb5_ret_int16(sp, &tag);
257 fcache->version = tag;
258 switch (tag) {
259 case KRB5_FCC_FVNO_4 : {
260 int16_t length;
262 krb5_ret_int16 (sp, &length);
263 while(length > 0) {
264 int16_t tag, data_len;
265 int i;
266 int8_t dummy;
268 krb5_ret_int16 (sp, &tag);
269 krb5_ret_int16 (sp, &data_len);
270 switch (tag) {
271 case FCC_TAG_DELTATIME :
272 krb5_ret_int32 (sp, &context->kdc_sec_offset);
273 krb5_ret_int32 (sp, &context->kdc_usec_offset);
274 break;
275 default :
276 for (i = 0; i < data_len; ++i)
277 krb5_ret_int8 (sp, &dummy);
278 break;
280 length -= 4 + data_len;
282 break;
284 case KRB5_FCC_FVNO_3 :
285 break;
286 default :
287 krb5_storage_free (sp);
288 close (fd);
289 return KRB5_CCACHE_BADVNO;
291 *ret_sp = sp;
292 *ret_fd = fd;
293 return 0;
296 static krb5_error_code
297 fcc_get_principal(krb5_context context,
298 krb5_ccache id,
299 krb5_principal *principal)
301 krb5_error_code ret;
302 krb5_fcache *f = FCACHE(id);
303 int fd;
304 krb5_storage *sp;
306 ret = init_fcc (context, f, &sp, &fd);
307 if (ret)
308 return ret;
309 krb5_ret_principal(sp, principal);
310 krb5_storage_free(sp);
311 close(fd);
312 return 0;
315 static krb5_error_code
316 fcc_get_first (krb5_context context,
317 krb5_ccache id,
318 krb5_cc_cursor *cursor)
320 krb5_error_code ret;
321 krb5_principal principal;
322 krb5_storage *sp;
323 krb5_fcache *f = FCACHE(id);
325 ret = init_fcc (context, f, &sp, &cursor->u.fd);
326 if (ret)
327 return ret;
328 krb5_ret_principal (sp, &principal);
329 krb5_storage_free(sp);
330 krb5_free_principal (context, principal);
331 return 0;
334 static krb5_error_code
335 fcc_get_next (krb5_context context,
336 krb5_ccache id,
337 krb5_cc_cursor *cursor,
338 krb5_creds *creds)
340 return fcc_read_cred (cursor->u.fd, creds);
343 static krb5_error_code
344 fcc_end_get (krb5_context context,
345 krb5_ccache id,
346 krb5_cc_cursor *cursor)
348 return close (cursor->u.fd);
351 static krb5_error_code
352 fcc_remove_cred(krb5_context context,
353 krb5_ccache id,
354 krb5_flags which,
355 krb5_creds *cred)
357 return 0; /* XXX */
360 static krb5_error_code
361 fcc_set_flags(krb5_context context,
362 krb5_ccache id,
363 krb5_flags flags)
365 return 0; /* XXX */
368 const krb5_cc_ops krb5_fcc_ops = {
369 "FILE",
370 fcc_get_name,
371 fcc_resolve,
372 fcc_gen_new,
373 fcc_initialize,
374 fcc_destroy,
375 fcc_close,
376 fcc_store_cred,
377 NULL, /* fcc_retrieve */
378 fcc_get_principal,
379 fcc_get_first,
380 fcc_get_next,
381 fcc_end_get,
382 fcc_remove_cred,
383 fcc_set_flags