xref: /freebsd/crypto/heimdal/lib/krb5/fcache.c (revision adb0ddaeac0a71a08d6af3a711387b59efcc94b6)
1b528cefcSMark Murray /*
2adb0ddaeSAssar Westerlund  * Copyright (c) 1997 - 2001 Kungliga Tekniska H�gskolan
3b528cefcSMark Murray  * (Royal Institute of Technology, Stockholm, Sweden).
4b528cefcSMark Murray  * All rights reserved.
5b528cefcSMark Murray  *
6b528cefcSMark Murray  * Redistribution and use in source and binary forms, with or without
7b528cefcSMark Murray  * modification, are permitted provided that the following conditions
8b528cefcSMark Murray  * are met:
9b528cefcSMark Murray  *
10b528cefcSMark Murray  * 1. Redistributions of source code must retain the above copyright
11b528cefcSMark Murray  *    notice, this list of conditions and the following disclaimer.
12b528cefcSMark Murray  *
13b528cefcSMark Murray  * 2. Redistributions in binary form must reproduce the above copyright
14b528cefcSMark Murray  *    notice, this list of conditions and the following disclaimer in the
15b528cefcSMark Murray  *    documentation and/or other materials provided with the distribution.
16b528cefcSMark Murray  *
17b528cefcSMark Murray  * 3. Neither the name of the Institute nor the names of its contributors
18b528cefcSMark Murray  *    may be used to endorse or promote products derived from this software
19b528cefcSMark Murray  *    without specific prior written permission.
20b528cefcSMark Murray  *
21b528cefcSMark Murray  * THIS SOFTWARE IS PROVIDED BY THE INSTITUTE AND CONTRIBUTORS ``AS IS'' AND
22b528cefcSMark Murray  * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
23b528cefcSMark Murray  * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
24b528cefcSMark Murray  * ARE DISCLAIMED.  IN NO EVENT SHALL THE INSTITUTE OR CONTRIBUTORS BE LIABLE
25b528cefcSMark Murray  * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
26b528cefcSMark Murray  * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
27b528cefcSMark Murray  * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
28b528cefcSMark Murray  * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
29b528cefcSMark Murray  * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
30b528cefcSMark Murray  * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
31b528cefcSMark Murray  * SUCH DAMAGE.
32b528cefcSMark Murray  */
33b528cefcSMark Murray 
34b528cefcSMark Murray #include "krb5_locl.h"
35b528cefcSMark Murray 
36adb0ddaeSAssar Westerlund RCSID("$Id: fcache.c,v 1.33 2001/05/14 06:14:46 assar Exp $");
37b528cefcSMark Murray 
38b528cefcSMark Murray typedef struct krb5_fcache{
39b528cefcSMark Murray     char *filename;
40b528cefcSMark Murray     int version;
41b528cefcSMark Murray }krb5_fcache;
42b528cefcSMark Murray 
43b528cefcSMark Murray struct fcc_cursor {
44b528cefcSMark Murray     int fd;
45b528cefcSMark Murray     krb5_storage *sp;
46b528cefcSMark Murray };
47b528cefcSMark Murray 
48b528cefcSMark Murray #define KRB5_FCC_FVNO_1 1
49b528cefcSMark Murray #define KRB5_FCC_FVNO_2 2
50b528cefcSMark Murray #define KRB5_FCC_FVNO_3 3
51b528cefcSMark Murray #define KRB5_FCC_FVNO_4 4
52b528cefcSMark Murray 
53b528cefcSMark Murray #define FCC_TAG_DELTATIME 1
54b528cefcSMark Murray 
55b528cefcSMark Murray #define FCACHE(X) ((krb5_fcache*)(X)->data.data)
56b528cefcSMark Murray 
57b528cefcSMark Murray #define FILENAME(X) (FCACHE(X)->filename)
58b528cefcSMark Murray 
59b528cefcSMark Murray #define FCC_CURSOR(C) ((struct fcc_cursor*)(C))
60b528cefcSMark Murray 
61b528cefcSMark Murray static char*
62b528cefcSMark Murray fcc_get_name(krb5_context context,
63b528cefcSMark Murray 	     krb5_ccache id)
64b528cefcSMark Murray {
65b528cefcSMark Murray     return FILENAME(id);
66b528cefcSMark Murray }
67b528cefcSMark Murray 
68b528cefcSMark Murray static krb5_error_code
69b528cefcSMark Murray fcc_resolve(krb5_context context, krb5_ccache *id, const char *res)
70b528cefcSMark Murray {
71b528cefcSMark Murray     krb5_fcache *f;
72b528cefcSMark Murray     f = malloc(sizeof(*f));
73adb0ddaeSAssar Westerlund     if(f == NULL) {
74adb0ddaeSAssar Westerlund 	krb5_set_error_string(context, "malloc: out of memory");
75b528cefcSMark Murray 	return KRB5_CC_NOMEM;
76adb0ddaeSAssar Westerlund     }
77b528cefcSMark Murray     f->filename = strdup(res);
78b528cefcSMark Murray     if(f->filename == NULL){
79b528cefcSMark Murray 	free(f);
80adb0ddaeSAssar Westerlund 	krb5_set_error_string(context, "malloc: out of memory");
81b528cefcSMark Murray 	return KRB5_CC_NOMEM;
82b528cefcSMark Murray     }
83b528cefcSMark Murray     f->version = 0;
84b528cefcSMark Murray     (*id)->data.data = f;
85b528cefcSMark Murray     (*id)->data.length = sizeof(*f);
86b528cefcSMark Murray     return 0;
87b528cefcSMark Murray }
88b528cefcSMark Murray 
895e9cd1aeSAssar Westerlund /*
905e9cd1aeSAssar Westerlund  * Try to scrub the contents of `filename' safely.
915e9cd1aeSAssar Westerlund  */
925e9cd1aeSAssar Westerlund 
935e9cd1aeSAssar Westerlund static int
945e9cd1aeSAssar Westerlund scrub_file (int fd)
955e9cd1aeSAssar Westerlund {
965e9cd1aeSAssar Westerlund     off_t pos;
975e9cd1aeSAssar Westerlund     char buf[128];
985e9cd1aeSAssar Westerlund 
995e9cd1aeSAssar Westerlund     pos = lseek(fd, 0, SEEK_END);
1005e9cd1aeSAssar Westerlund     if (pos < 0)
1015e9cd1aeSAssar Westerlund         return errno;
1025e9cd1aeSAssar Westerlund     if (lseek(fd, 0, SEEK_SET) < 0)
1035e9cd1aeSAssar Westerlund         return errno;
1045e9cd1aeSAssar Westerlund     memset(buf, 0, sizeof(buf));
1055e9cd1aeSAssar Westerlund     while(pos > 0) {
1065e9cd1aeSAssar Westerlund         ssize_t tmp = write(fd, buf, min(sizeof(buf), pos));
1075e9cd1aeSAssar Westerlund 
1085e9cd1aeSAssar Westerlund 	if (tmp < 0)
1095e9cd1aeSAssar Westerlund 	    return errno;
1105e9cd1aeSAssar Westerlund 	pos -= tmp;
1115e9cd1aeSAssar Westerlund     }
1125e9cd1aeSAssar Westerlund     fsync (fd);
1135e9cd1aeSAssar Westerlund     return 0;
1145e9cd1aeSAssar Westerlund }
1155e9cd1aeSAssar Westerlund 
1165e9cd1aeSAssar Westerlund /*
1175e9cd1aeSAssar Westerlund  * Erase `filename' if it exists, trying to remove the contents if
1185e9cd1aeSAssar Westerlund  * it's `safe'.  We always try to remove the file, it it exists.  It's
1195e9cd1aeSAssar Westerlund  * only overwritten if it's a regular file (not a symlink and not a
1205e9cd1aeSAssar Westerlund  * hardlink)
1215e9cd1aeSAssar Westerlund  */
1225e9cd1aeSAssar Westerlund 
123b528cefcSMark Murray static krb5_error_code
124b528cefcSMark Murray erase_file(const char *filename)
125b528cefcSMark Murray {
126b528cefcSMark Murray     int fd;
1275e9cd1aeSAssar Westerlund     struct stat sb1, sb2;
1285e9cd1aeSAssar Westerlund     int ret;
1295e9cd1aeSAssar Westerlund 
1305e9cd1aeSAssar Westerlund     ret = lstat (filename, &sb1);
1315e9cd1aeSAssar Westerlund     if (ret < 0)
1325e9cd1aeSAssar Westerlund 	return errno;
133b528cefcSMark Murray 
134b528cefcSMark Murray     fd = open(filename, O_RDWR | O_BINARY);
135b528cefcSMark Murray     if(fd < 0) {
136b528cefcSMark Murray 	if(errno == ENOENT)
137b528cefcSMark Murray 	    return 0;
138b528cefcSMark Murray 	else
139b528cefcSMark Murray 	    return errno;
140b528cefcSMark Murray     }
1415e9cd1aeSAssar Westerlund     if (unlink(filename) < 0) {
142b528cefcSMark Murray         close (fd);
1435e9cd1aeSAssar Westerlund         return errno;
1445e9cd1aeSAssar Westerlund     }
1455e9cd1aeSAssar Westerlund 
1465e9cd1aeSAssar Westerlund     ret = fstat (fd, &sb2);
1475e9cd1aeSAssar Westerlund     if (ret < 0) {
1485e9cd1aeSAssar Westerlund 	close (fd);
1495e9cd1aeSAssar Westerlund 	return errno;
1505e9cd1aeSAssar Westerlund     }
1515e9cd1aeSAssar Westerlund 
1525e9cd1aeSAssar Westerlund     /* check if someone was playing with symlinks */
1535e9cd1aeSAssar Westerlund 
1545e9cd1aeSAssar Westerlund     if (sb1.st_dev != sb2.st_dev || sb1.st_ino != sb2.st_ino) {
1555e9cd1aeSAssar Westerlund 	close (fd);
1565e9cd1aeSAssar Westerlund 	return EPERM;
1575e9cd1aeSAssar Westerlund     }
1585e9cd1aeSAssar Westerlund 
1595e9cd1aeSAssar Westerlund     /* there are still hard links to this file */
1605e9cd1aeSAssar Westerlund 
1615e9cd1aeSAssar Westerlund     if (sb2.st_nlink != 0) {
1625e9cd1aeSAssar Westerlund         close (fd);
163b528cefcSMark Murray         return 0;
164b528cefcSMark Murray     }
165b528cefcSMark Murray 
1665e9cd1aeSAssar Westerlund     ret = scrub_file (fd);
1675e9cd1aeSAssar Westerlund     close (fd);
1685e9cd1aeSAssar Westerlund     return ret;
1695e9cd1aeSAssar Westerlund }
1705e9cd1aeSAssar Westerlund 
171b528cefcSMark Murray static krb5_error_code
172b528cefcSMark Murray fcc_gen_new(krb5_context context, krb5_ccache *id)
173b528cefcSMark Murray {
174b528cefcSMark Murray     krb5_fcache *f;
175b528cefcSMark Murray     int fd;
176b528cefcSMark Murray     char *file;
177adb0ddaeSAssar Westerlund 
178b528cefcSMark Murray     f = malloc(sizeof(*f));
179adb0ddaeSAssar Westerlund     if(f == NULL) {
180adb0ddaeSAssar Westerlund 	krb5_set_error_string(context, "malloc: out of memory");
181b528cefcSMark Murray 	return KRB5_CC_NOMEM;
182adb0ddaeSAssar Westerlund     }
1835e9cd1aeSAssar Westerlund     asprintf (&file, "%sXXXXXX", KRB5_DEFAULT_CCFILE_ROOT);
184b528cefcSMark Murray     if(file == NULL) {
185b528cefcSMark Murray 	free(f);
186adb0ddaeSAssar Westerlund 	krb5_set_error_string(context, "malloc: out of memory");
187b528cefcSMark Murray 	return KRB5_CC_NOMEM;
188b528cefcSMark Murray     }
189b528cefcSMark Murray     fd = mkstemp(file);
190b528cefcSMark Murray     if(fd < 0) {
191b528cefcSMark Murray 	free(f);
192b528cefcSMark Murray 	free(file);
193adb0ddaeSAssar Westerlund 	krb5_set_error_string(context, "mkstemp %s", file);
194b528cefcSMark Murray 	return errno;
195b528cefcSMark Murray     }
196b528cefcSMark Murray     close(fd);
197b528cefcSMark Murray     f->filename = file;
198b528cefcSMark Murray     f->version = 0;
199b528cefcSMark Murray     (*id)->data.data = f;
200b528cefcSMark Murray     (*id)->data.length = sizeof(*f);
201b528cefcSMark Murray     return 0;
202b528cefcSMark Murray }
203b528cefcSMark Murray 
204b528cefcSMark Murray static void
205b528cefcSMark Murray storage_set_flags(krb5_context context, krb5_storage *sp, int vno)
206b528cefcSMark Murray {
207b528cefcSMark Murray     int flags = 0;
208b528cefcSMark Murray     switch(vno) {
209b528cefcSMark Murray     case KRB5_FCC_FVNO_1:
210b528cefcSMark Murray 	flags |= KRB5_STORAGE_PRINCIPAL_WRONG_NUM_COMPONENTS;
211b528cefcSMark Murray 	flags |= KRB5_STORAGE_PRINCIPAL_NO_NAME_TYPE;
212b528cefcSMark Murray 	flags |= KRB5_STORAGE_HOST_BYTEORDER;
213b528cefcSMark Murray 	break;
214b528cefcSMark Murray     case KRB5_FCC_FVNO_2:
215b528cefcSMark Murray 	flags |= KRB5_STORAGE_HOST_BYTEORDER;
216b528cefcSMark Murray 	break;
217b528cefcSMark Murray     case KRB5_FCC_FVNO_3:
218b528cefcSMark Murray 	flags |= KRB5_STORAGE_KEYBLOCK_KEYTYPE_TWICE;
219b528cefcSMark Murray 	break;
220b528cefcSMark Murray     case KRB5_FCC_FVNO_4:
221b528cefcSMark Murray 	break;
222b528cefcSMark Murray     default:
223b528cefcSMark Murray 	krb5_abortx(context,
224b528cefcSMark Murray 		    "storage_set_flags called with bad vno (%x)", vno);
225b528cefcSMark Murray     }
226b528cefcSMark Murray     krb5_storage_set_flags(sp, flags);
227b528cefcSMark Murray }
228b528cefcSMark Murray 
229b528cefcSMark Murray static krb5_error_code
230b528cefcSMark Murray fcc_initialize(krb5_context context,
231b528cefcSMark Murray 	       krb5_ccache id,
232b528cefcSMark Murray 	       krb5_principal primary_principal)
233b528cefcSMark Murray {
234b528cefcSMark Murray     krb5_fcache *f = FCACHE(id);
2355e9cd1aeSAssar Westerlund     int ret = 0;
236b528cefcSMark Murray     int fd;
237b528cefcSMark Murray     char *filename = f->filename;
238b528cefcSMark Murray 
2395e9cd1aeSAssar Westerlund     unlink (filename);
240b528cefcSMark Murray 
241b528cefcSMark Murray     fd = open(filename, O_RDWR | O_CREAT | O_EXCL | O_BINARY, 0600);
242adb0ddaeSAssar Westerlund     if(fd == -1) {
243adb0ddaeSAssar Westerlund 	ret = errno;
244adb0ddaeSAssar Westerlund 	krb5_set_error_string(context, "open(%s): %s", filename,
245adb0ddaeSAssar Westerlund 			      strerror(ret));
246adb0ddaeSAssar Westerlund 	return ret;
247adb0ddaeSAssar Westerlund     }
248b528cefcSMark Murray     {
249b528cefcSMark Murray 	krb5_storage *sp;
250b528cefcSMark Murray 	sp = krb5_storage_from_fd(fd);
251b528cefcSMark Murray 	if(context->fcache_vno != 0)
252b528cefcSMark Murray 	    f->version = context->fcache_vno;
253b528cefcSMark Murray 	else
254b528cefcSMark Murray 	    f->version = KRB5_FCC_FVNO_4;
2555e9cd1aeSAssar Westerlund 	ret |= krb5_store_int8(sp, 5);
2565e9cd1aeSAssar Westerlund 	ret |= krb5_store_int8(sp, f->version);
257b528cefcSMark Murray 	storage_set_flags(context, sp, f->version);
2585e9cd1aeSAssar Westerlund 	if(f->version == KRB5_FCC_FVNO_4 && ret == 0) {
259b528cefcSMark Murray 	    /* V4 stuff */
260b528cefcSMark Murray 	    if (context->kdc_sec_offset) {
2615e9cd1aeSAssar Westerlund 		ret |= krb5_store_int16 (sp, 12); /* length */
2625e9cd1aeSAssar Westerlund 		ret |= krb5_store_int16 (sp, FCC_TAG_DELTATIME); /* Tag */
2635e9cd1aeSAssar Westerlund 		ret |= krb5_store_int16 (sp, 8); /* length of data */
2645e9cd1aeSAssar Westerlund 		ret |= krb5_store_int32 (sp, context->kdc_sec_offset);
2655e9cd1aeSAssar Westerlund 		ret |= krb5_store_int32 (sp, context->kdc_usec_offset);
266b528cefcSMark Murray 	    } else {
2675e9cd1aeSAssar Westerlund 		ret |= krb5_store_int16 (sp, 0);
268b528cefcSMark Murray 	    }
269b528cefcSMark Murray 	}
2705e9cd1aeSAssar Westerlund 	ret |= krb5_store_principal(sp, primary_principal);
271b528cefcSMark Murray 	krb5_storage_free(sp);
272b528cefcSMark Murray     }
2735e9cd1aeSAssar Westerlund     if(close(fd) < 0)
274adb0ddaeSAssar Westerlund 	if (ret == 0) {
2755e9cd1aeSAssar Westerlund 	    ret = errno;
276adb0ddaeSAssar Westerlund 	    krb5_set_error_string (context, "close %s: %s", filename,
277adb0ddaeSAssar Westerlund 				   strerror(ret));
278adb0ddaeSAssar Westerlund 	}
279b528cefcSMark Murray 
2805e9cd1aeSAssar Westerlund     return ret;
281b528cefcSMark Murray }
282b528cefcSMark Murray 
283b528cefcSMark Murray static krb5_error_code
284b528cefcSMark Murray fcc_close(krb5_context context,
285b528cefcSMark Murray 	  krb5_ccache id)
286b528cefcSMark Murray {
287b528cefcSMark Murray     free (FILENAME(id));
288b528cefcSMark Murray     krb5_data_free(&id->data);
289b528cefcSMark Murray     return 0;
290b528cefcSMark Murray }
291b528cefcSMark Murray 
292b528cefcSMark Murray static krb5_error_code
293b528cefcSMark Murray fcc_destroy(krb5_context context,
294b528cefcSMark Murray 	    krb5_ccache id)
295b528cefcSMark Murray {
296b528cefcSMark Murray     char *f;
297b528cefcSMark Murray     f = FILENAME(id);
298b528cefcSMark Murray 
299b528cefcSMark Murray     erase_file(f);
300b528cefcSMark Murray 
301b528cefcSMark Murray     return 0;
302b528cefcSMark Murray }
303b528cefcSMark Murray 
304b528cefcSMark Murray static krb5_error_code
305b528cefcSMark Murray fcc_store_cred(krb5_context context,
306b528cefcSMark Murray 	       krb5_ccache id,
307b528cefcSMark Murray 	       krb5_creds *creds)
308b528cefcSMark Murray {
3095e9cd1aeSAssar Westerlund     int ret;
310b528cefcSMark Murray     int fd;
311b528cefcSMark Murray     char *f;
312b528cefcSMark Murray 
313b528cefcSMark Murray     f = FILENAME(id);
314b528cefcSMark Murray 
315b528cefcSMark Murray     fd = open(f, O_WRONLY | O_APPEND | O_BINARY);
316adb0ddaeSAssar Westerlund     if(fd < 0) {
317adb0ddaeSAssar Westerlund 	ret = errno;
318adb0ddaeSAssar Westerlund 	krb5_set_error_string (context, "open(%s): %s", f, strerror(ret));
319adb0ddaeSAssar Westerlund 	return ret;
320adb0ddaeSAssar Westerlund     }
321b528cefcSMark Murray     {
322b528cefcSMark Murray 	krb5_storage *sp;
323b528cefcSMark Murray 	sp = krb5_storage_from_fd(fd);
324b528cefcSMark Murray 	storage_set_flags(context, sp, FCACHE(id)->version);
3255e9cd1aeSAssar Westerlund 	ret = krb5_store_creds(sp, creds);
326b528cefcSMark Murray 	krb5_storage_free(sp);
327b528cefcSMark Murray     }
3285e9cd1aeSAssar Westerlund     if (close(fd) < 0)
329adb0ddaeSAssar Westerlund 	if (ret == 0) {
3305e9cd1aeSAssar Westerlund 	    ret = errno;
331adb0ddaeSAssar Westerlund 	    krb5_set_error_string (context, "close %s: %s", f, strerror(ret));
332adb0ddaeSAssar Westerlund 	}
3335e9cd1aeSAssar Westerlund     return ret;
334b528cefcSMark Murray }
335b528cefcSMark Murray 
336b528cefcSMark Murray static krb5_error_code
337b528cefcSMark Murray fcc_read_cred (krb5_context context,
338b528cefcSMark Murray 	       krb5_fcache *fc,
339b528cefcSMark Murray 	       krb5_storage *sp,
340b528cefcSMark Murray 	       krb5_creds *creds)
341b528cefcSMark Murray {
342b528cefcSMark Murray     krb5_error_code ret;
343b528cefcSMark Murray 
344b528cefcSMark Murray     storage_set_flags(context, sp, fc->version);
345b528cefcSMark Murray 
346b528cefcSMark Murray     ret = krb5_ret_creds(sp, creds);
347b528cefcSMark Murray     return ret;
348b528cefcSMark Murray }
349b528cefcSMark Murray 
350b528cefcSMark Murray static krb5_error_code
351b528cefcSMark Murray init_fcc (krb5_context context,
352b528cefcSMark Murray 	  krb5_fcache *fcache,
353b528cefcSMark Murray 	  krb5_storage **ret_sp,
354b528cefcSMark Murray 	  int *ret_fd)
355b528cefcSMark Murray {
356b528cefcSMark Murray     int fd;
357b528cefcSMark Murray     int8_t pvno, tag;
358b528cefcSMark Murray     krb5_storage *sp;
3595e9cd1aeSAssar Westerlund     krb5_error_code ret;
360b528cefcSMark Murray 
361b528cefcSMark Murray     fd = open(fcache->filename, O_RDONLY | O_BINARY);
362adb0ddaeSAssar Westerlund     if(fd < 0) {
363adb0ddaeSAssar Westerlund 	ret = errno;
364adb0ddaeSAssar Westerlund 	krb5_set_error_string(context, "open(%s): %s", fcache->filename,
365adb0ddaeSAssar Westerlund 			      strerror(ret));
366adb0ddaeSAssar Westerlund 	return ret;
367adb0ddaeSAssar Westerlund     }
368b528cefcSMark Murray     sp = krb5_storage_from_fd(fd);
3695e9cd1aeSAssar Westerlund     ret = krb5_ret_int8(sp, &pvno);
370adb0ddaeSAssar Westerlund     if(ret == KRB5_CC_END) {
371adb0ddaeSAssar Westerlund 
3725e9cd1aeSAssar Westerlund 	return ENOENT;
373adb0ddaeSAssar Westerlund     }
3745e9cd1aeSAssar Westerlund     if(ret)
3755e9cd1aeSAssar Westerlund 	return ret;
376b528cefcSMark Murray     if(pvno != 5) {
377b528cefcSMark Murray 	krb5_storage_free(sp);
378b528cefcSMark Murray 	close(fd);
379b528cefcSMark Murray 	return KRB5_CCACHE_BADVNO;
380b528cefcSMark Murray     }
381b528cefcSMark Murray     krb5_ret_int8(sp, &tag); /* should not be host byte order */
382b528cefcSMark Murray     fcache->version = tag;
383b528cefcSMark Murray     storage_set_flags(context, sp, fcache->version);
384b528cefcSMark Murray     switch (tag) {
385b528cefcSMark Murray     case KRB5_FCC_FVNO_4: {
386b528cefcSMark Murray 	int16_t length;
387b528cefcSMark Murray 
388b528cefcSMark Murray 	krb5_ret_int16 (sp, &length);
389b528cefcSMark Murray 	while(length > 0) {
390b528cefcSMark Murray 	    int16_t tag, data_len;
391b528cefcSMark Murray 	    int i;
392b528cefcSMark Murray 	    int8_t dummy;
393b528cefcSMark Murray 
394b528cefcSMark Murray 	    krb5_ret_int16 (sp, &tag);
395b528cefcSMark Murray 	    krb5_ret_int16 (sp, &data_len);
396b528cefcSMark Murray 	    switch (tag) {
397b528cefcSMark Murray 	    case FCC_TAG_DELTATIME :
398b528cefcSMark Murray 		krb5_ret_int32 (sp, &context->kdc_sec_offset);
399b528cefcSMark Murray 		krb5_ret_int32 (sp, &context->kdc_usec_offset);
400b528cefcSMark Murray 		break;
401b528cefcSMark Murray 	    default :
402b528cefcSMark Murray 		for (i = 0; i < data_len; ++i)
403b528cefcSMark Murray 		    krb5_ret_int8 (sp, &dummy);
404b528cefcSMark Murray 		break;
405b528cefcSMark Murray 	    }
406b528cefcSMark Murray 	    length -= 4 + data_len;
407b528cefcSMark Murray 	}
408b528cefcSMark Murray 	break;
409b528cefcSMark Murray     }
410b528cefcSMark Murray     case KRB5_FCC_FVNO_3:
411b528cefcSMark Murray     case KRB5_FCC_FVNO_2:
412b528cefcSMark Murray     case KRB5_FCC_FVNO_1:
413b528cefcSMark Murray 	break;
414b528cefcSMark Murray     default :
415b528cefcSMark Murray 	krb5_storage_free (sp);
416b528cefcSMark Murray 	close (fd);
417b528cefcSMark Murray 	return KRB5_CCACHE_BADVNO;
418b528cefcSMark Murray     }
419b528cefcSMark Murray     *ret_sp = sp;
420b528cefcSMark Murray     *ret_fd = fd;
421b528cefcSMark Murray     return 0;
422b528cefcSMark Murray }
423b528cefcSMark Murray 
424b528cefcSMark Murray static krb5_error_code
425b528cefcSMark Murray fcc_get_principal(krb5_context context,
426b528cefcSMark Murray 		  krb5_ccache id,
427b528cefcSMark Murray 		  krb5_principal *principal)
428b528cefcSMark Murray {
429b528cefcSMark Murray     krb5_error_code ret;
430b528cefcSMark Murray     krb5_fcache *f = FCACHE(id);
431b528cefcSMark Murray     int fd;
432b528cefcSMark Murray     krb5_storage *sp;
433b528cefcSMark Murray 
434b528cefcSMark Murray     ret = init_fcc (context, f, &sp, &fd);
435b528cefcSMark Murray     if (ret)
436b528cefcSMark Murray 	return ret;
4375e9cd1aeSAssar Westerlund     ret = krb5_ret_principal(sp, principal);
438b528cefcSMark Murray     krb5_storage_free(sp);
439b528cefcSMark Murray     close(fd);
4405e9cd1aeSAssar Westerlund     return ret;
441b528cefcSMark Murray }
442b528cefcSMark Murray 
443b528cefcSMark Murray static krb5_error_code
444b528cefcSMark Murray fcc_get_first (krb5_context context,
445b528cefcSMark Murray 	       krb5_ccache id,
446b528cefcSMark Murray 	       krb5_cc_cursor *cursor)
447b528cefcSMark Murray {
448b528cefcSMark Murray     krb5_error_code ret;
449b528cefcSMark Murray     krb5_principal principal;
450b528cefcSMark Murray     krb5_fcache *f = FCACHE(id);
451b528cefcSMark Murray 
452b528cefcSMark Murray     *cursor = malloc(sizeof(struct fcc_cursor));
453b528cefcSMark Murray 
454b528cefcSMark Murray     ret = init_fcc (context, f, &FCC_CURSOR(*cursor)->sp,
455b528cefcSMark Murray 		    &FCC_CURSOR(*cursor)->fd);
456b528cefcSMark Murray     if (ret)
457b528cefcSMark Murray 	return ret;
458b528cefcSMark Murray     krb5_ret_principal (FCC_CURSOR(*cursor)->sp, &principal);
459b528cefcSMark Murray     krb5_free_principal (context, principal);
460b528cefcSMark Murray     return 0;
461b528cefcSMark Murray }
462b528cefcSMark Murray 
463b528cefcSMark Murray static krb5_error_code
464b528cefcSMark Murray fcc_get_next (krb5_context context,
465b528cefcSMark Murray 	      krb5_ccache id,
466b528cefcSMark Murray 	      krb5_cc_cursor *cursor,
467b528cefcSMark Murray 	      krb5_creds *creds)
468b528cefcSMark Murray {
469b528cefcSMark Murray     return fcc_read_cred (context, FCACHE(id), FCC_CURSOR(*cursor)->sp, creds);
470b528cefcSMark Murray }
471b528cefcSMark Murray 
472b528cefcSMark Murray static krb5_error_code
473b528cefcSMark Murray fcc_end_get (krb5_context context,
474b528cefcSMark Murray 	     krb5_ccache id,
475b528cefcSMark Murray 	     krb5_cc_cursor *cursor)
476b528cefcSMark Murray {
477b528cefcSMark Murray     krb5_storage_free(FCC_CURSOR(*cursor)->sp);
478b528cefcSMark Murray     close (FCC_CURSOR(*cursor)->fd);
479b528cefcSMark Murray     free(*cursor);
480b528cefcSMark Murray     return 0;
481b528cefcSMark Murray }
482b528cefcSMark Murray 
483b528cefcSMark Murray static krb5_error_code
484b528cefcSMark Murray fcc_remove_cred(krb5_context context,
485b528cefcSMark Murray 		 krb5_ccache id,
486b528cefcSMark Murray 		 krb5_flags which,
487b528cefcSMark Murray 		 krb5_creds *cred)
488b528cefcSMark Murray {
489b528cefcSMark Murray     return 0; /* XXX */
490b528cefcSMark Murray }
491b528cefcSMark Murray 
492b528cefcSMark Murray static krb5_error_code
493b528cefcSMark Murray fcc_set_flags(krb5_context context,
494b528cefcSMark Murray 	      krb5_ccache id,
495b528cefcSMark Murray 	      krb5_flags flags)
496b528cefcSMark Murray {
497b528cefcSMark Murray     return 0; /* XXX */
498b528cefcSMark Murray }
499b528cefcSMark Murray 
500b528cefcSMark Murray static krb5_error_code
501b528cefcSMark Murray fcc_get_version(krb5_context context,
502b528cefcSMark Murray 		krb5_ccache id)
503b528cefcSMark Murray {
504b528cefcSMark Murray     return FCACHE(id)->version;
505b528cefcSMark Murray }
506b528cefcSMark Murray 
507b528cefcSMark Murray const krb5_cc_ops krb5_fcc_ops = {
508b528cefcSMark Murray     "FILE",
509b528cefcSMark Murray     fcc_get_name,
510b528cefcSMark Murray     fcc_resolve,
511b528cefcSMark Murray     fcc_gen_new,
512b528cefcSMark Murray     fcc_initialize,
513b528cefcSMark Murray     fcc_destroy,
514b528cefcSMark Murray     fcc_close,
515b528cefcSMark Murray     fcc_store_cred,
516b528cefcSMark Murray     NULL, /* fcc_retrieve */
517b528cefcSMark Murray     fcc_get_principal,
518b528cefcSMark Murray     fcc_get_first,
519b528cefcSMark Murray     fcc_get_next,
520b528cefcSMark Murray     fcc_end_get,
521b528cefcSMark Murray     fcc_remove_cred,
522b528cefcSMark Murray     fcc_set_flags,
523b528cefcSMark Murray     fcc_get_version
524b528cefcSMark Murray };
525