]> CyberLeo.Net >> Repos - FreeBSD/releng/10.0.git/blob - crypto/heimdal/lib/krb5/store.c
- Copy stable/10 (r259064) to releng/10.0 as part of the
[FreeBSD/releng/10.0.git] / crypto / heimdal / lib / krb5 / store.c
1 /*
2  * Copyright (c) 1997-2008 Kungliga Tekniska Högskolan
3  * (Royal Institute of Technology, Stockholm, Sweden).
4  * All rights reserved.
5  *
6  * Redistribution and use in source and binary forms, with or without
7  * modification, are permitted provided that the following conditions
8  * are met:
9  *
10  * 1. Redistributions of source code must retain the above copyright
11  *    notice, this list of conditions and the following disclaimer.
12  *
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.
16  *
17  * 3. Neither the name of the Institute nor the names of its contributors
18  *    may be used to endorse or promote products derived from this software
19  *    without specific prior written permission.
20  *
21  * THIS SOFTWARE IS PROVIDED BY THE INSTITUTE AND CONTRIBUTORS ``AS IS'' AND
22  * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
23  * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
24  * ARE DISCLAIMED.  IN NO EVENT SHALL THE INSTITUTE OR CONTRIBUTORS BE LIABLE
25  * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
26  * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
27  * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
28  * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
29  * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
30  * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
31  * SUCH DAMAGE.
32  */
33
34 #include "krb5_locl.h"
35 #include "store-int.h"
36
37 #define BYTEORDER_IS(SP, V) (((SP)->flags & KRB5_STORAGE_BYTEORDER_MASK) == (V))
38 #define BYTEORDER_IS_LE(SP) BYTEORDER_IS((SP), KRB5_STORAGE_BYTEORDER_LE)
39 #define BYTEORDER_IS_BE(SP) BYTEORDER_IS((SP), KRB5_STORAGE_BYTEORDER_BE)
40 #define BYTEORDER_IS_HOST(SP) (BYTEORDER_IS((SP), KRB5_STORAGE_BYTEORDER_HOST) || \
41                                krb5_storage_is_flags((SP), KRB5_STORAGE_HOST_BYTEORDER))
42
43 /**
44  * Add the flags on a storage buffer by or-ing in the flags to the buffer.
45  *
46  * @param sp the storage buffer to set the flags on
47  * @param flags the flags to set
48  *
49  * @ingroup krb5_storage
50  */
51
52 KRB5_LIB_FUNCTION void KRB5_LIB_CALL
53 krb5_storage_set_flags(krb5_storage *sp, krb5_flags flags)
54 {
55     sp->flags |= flags;
56 }
57
58 /**
59  * Clear the flags on a storage buffer
60  *
61  * @param sp the storage buffer to clear the flags on
62  * @param flags the flags to clear
63  *
64  * @ingroup krb5_storage
65  */
66
67 KRB5_LIB_FUNCTION void KRB5_LIB_CALL
68 krb5_storage_clear_flags(krb5_storage *sp, krb5_flags flags)
69 {
70     sp->flags &= ~flags;
71 }
72
73 /**
74  * Return true or false depending on if the storage flags is set or
75  * not. NB testing for the flag 0 always return true.
76  *
77  * @param sp the storage buffer to check flags on
78  * @param flags The flags to test for
79  *
80  * @return true if all the flags are set, false if not.
81  *
82  * @ingroup krb5_storage
83  */
84
85 KRB5_LIB_FUNCTION krb5_boolean KRB5_LIB_CALL
86 krb5_storage_is_flags(krb5_storage *sp, krb5_flags flags)
87 {
88     return (sp->flags & flags) == flags;
89 }
90
91 /**
92  * Set the new byte order of the storage buffer.
93  *
94  * @param sp the storage buffer to set the byte order for.
95  * @param byteorder the new byte order.
96  *
97  * The byte order are: KRB5_STORAGE_BYTEORDER_BE,
98  * KRB5_STORAGE_BYTEORDER_LE and KRB5_STORAGE_BYTEORDER_HOST.
99  *
100  * @ingroup krb5_storage
101  */
102
103 KRB5_LIB_FUNCTION void KRB5_LIB_CALL
104 krb5_storage_set_byteorder(krb5_storage *sp, krb5_flags byteorder)
105 {
106     sp->flags &= ~KRB5_STORAGE_BYTEORDER_MASK;
107     sp->flags |= byteorder;
108 }
109
110 /**
111  * Return the current byteorder for the buffer. See krb5_storage_set_byteorder() for the list or byte order contants.
112  *
113  * @ingroup krb5_storage
114  */
115
116 KRB5_LIB_FUNCTION krb5_flags KRB5_LIB_CALL
117 krb5_storage_get_byteorder(krb5_storage *sp)
118 {
119     return sp->flags & KRB5_STORAGE_BYTEORDER_MASK;
120 }
121
122 /**
123  * Set the max alloc value
124  *
125  * @param sp the storage buffer set the max allow for
126  * @param size maximum size to allocate, use 0 to remove limit
127  *
128  * @ingroup krb5_storage
129  */
130
131 KRB5_LIB_FUNCTION void KRB5_LIB_CALL
132 krb5_storage_set_max_alloc(krb5_storage *sp, size_t size)
133 {
134     sp->max_alloc = size;
135 }
136
137 /* don't allocate unresonable amount of memory */
138 static krb5_error_code
139 size_too_large(krb5_storage *sp, size_t size)
140 {
141     if (sp->max_alloc && sp->max_alloc < size)
142         return HEIM_ERR_TOO_BIG;
143     return 0;
144 }
145
146 static krb5_error_code
147 size_too_large_num(krb5_storage *sp, size_t count, size_t size)
148 {
149     if (sp->max_alloc == 0 || size == 0)
150         return 0;
151     size = sp->max_alloc / size;
152     if (size < count)
153         return HEIM_ERR_TOO_BIG;
154     return 0;
155 }
156
157 /**
158  * Seek to a new offset.
159  *
160  * @param sp the storage buffer to seek in.
161  * @param offset the offset to seek
162  * @param whence relateive searching, SEEK_CUR from the current
163  * position, SEEK_END from the end, SEEK_SET absolute from the start.
164  *
165  * @return The new current offset
166  *
167  * @ingroup krb5_storage
168  */
169
170 KRB5_LIB_FUNCTION off_t KRB5_LIB_CALL
171 krb5_storage_seek(krb5_storage *sp, off_t offset, int whence)
172 {
173     return (*sp->seek)(sp, offset, whence);
174 }
175
176 /**
177  * Truncate the storage buffer in sp to offset.
178  *
179  * @param sp the storage buffer to truncate.
180  * @param offset the offset to truncate too.
181  *
182  * @return An Kerberos 5 error code.
183  *
184  * @ingroup krb5_storage
185  */
186
187 KRB5_LIB_FUNCTION int KRB5_LIB_CALL
188 krb5_storage_truncate(krb5_storage *sp, off_t offset)
189 {
190     return (*sp->trunc)(sp, offset);
191 }
192
193 /**
194  * Read to the storage buffer.
195  *
196  * @param sp the storage buffer to read from
197  * @param buf the buffer to store the data in
198  * @param len the length to read
199  *
200  * @return The length of data read (can be shorter then len), or negative on error.
201  *
202  * @ingroup krb5_storage
203  */
204
205 KRB5_LIB_FUNCTION krb5_ssize_t KRB5_LIB_CALL
206 krb5_storage_read(krb5_storage *sp, void *buf, size_t len)
207 {
208     return sp->fetch(sp, buf, len);
209 }
210
211 /**
212  * Write to the storage buffer.
213  *
214  * @param sp the storage buffer to write to
215  * @param buf the buffer to write to the storage buffer
216  * @param len the length to write
217  *
218  * @return The length of data written (can be shorter then len), or negative on error.
219  *
220  * @ingroup krb5_storage
221  */
222
223 KRB5_LIB_FUNCTION krb5_ssize_t KRB5_LIB_CALL
224 krb5_storage_write(krb5_storage *sp, const void *buf, size_t len)
225 {
226     return sp->store(sp, buf, len);
227 }
228
229 /**
230  * Set the return code that will be used when end of storage is reached.
231  *
232  * @param sp the storage
233  * @param code the error code to return on end of storage
234  *
235  * @ingroup krb5_storage
236  */
237
238 KRB5_LIB_FUNCTION void KRB5_LIB_CALL
239 krb5_storage_set_eof_code(krb5_storage *sp, int code)
240 {
241     sp->eof_code = code;
242 }
243
244 /**
245  * Get the return code that will be used when end of storage is reached.
246  *
247  * @param sp the storage
248  *
249  * @return storage error code
250  *
251  * @ingroup krb5_storage
252  */
253
254 KRB5_LIB_FUNCTION int KRB5_LIB_CALL
255 krb5_storage_get_eof_code(krb5_storage *sp)
256 {
257     return sp->eof_code;
258 }
259
260 /**
261  * Free a krb5 storage.
262  *
263  * @param sp the storage to free.
264  *
265  * @return An Kerberos 5 error code.
266  *
267  * @ingroup krb5_storage
268  */
269
270 KRB5_LIB_FUNCTION krb5_error_code KRB5_LIB_CALL
271 krb5_storage_free(krb5_storage *sp)
272 {
273     if(sp->free)
274         (*sp->free)(sp);
275     free(sp->data);
276     free(sp);
277     return 0;
278 }
279
280 /**
281  * Copy the contnent of storage
282  *
283  * @param sp the storage to copy to a data
284  * @param data the copied data, free with krb5_data_free()
285  *
286  * @return 0 for success, or a Kerberos 5 error code on failure.
287  *
288  * @ingroup krb5_storage
289  */
290
291 KRB5_LIB_FUNCTION krb5_error_code KRB5_LIB_CALL
292 krb5_storage_to_data(krb5_storage *sp, krb5_data *data)
293 {
294     off_t pos, size;
295     krb5_error_code ret;
296
297     pos = sp->seek(sp, 0, SEEK_CUR);
298     if (pos < 0)
299         return HEIM_ERR_NOT_SEEKABLE;
300     size = sp->seek(sp, 0, SEEK_END);
301     ret = size_too_large(sp, size);
302     if (ret)
303         return ret;
304     ret = krb5_data_alloc(data, size);
305     if (ret) {
306         sp->seek(sp, pos, SEEK_SET);
307         return ret;
308     }
309     if (size) {
310         sp->seek(sp, 0, SEEK_SET);
311         sp->fetch(sp, data->data, data->length);
312         sp->seek(sp, pos, SEEK_SET);
313     }
314     return 0;
315 }
316
317 static krb5_error_code
318 krb5_store_int(krb5_storage *sp,
319                int32_t value,
320                size_t len)
321 {
322     int ret;
323     unsigned char v[16];
324
325     if(len > sizeof(v))
326         return EINVAL;
327     _krb5_put_int(v, value, len);
328     ret = sp->store(sp, v, len);
329     if (ret < 0)
330         return errno;
331     if ((size_t)ret != len)
332         return sp->eof_code;
333     return 0;
334 }
335
336 /**
337  * Store a int32 to storage, byte order is controlled by the settings
338  * on the storage, see krb5_storage_set_byteorder().
339  *
340  * @param sp the storage to write too
341  * @param value the value to store
342  *
343  * @return 0 for success, or a Kerberos 5 error code on failure.
344  *
345  * @ingroup krb5_storage
346  */
347
348 KRB5_LIB_FUNCTION krb5_error_code KRB5_LIB_CALL
349 krb5_store_int32(krb5_storage *sp,
350                  int32_t value)
351 {
352     if(BYTEORDER_IS_HOST(sp))
353         value = htonl(value);
354     else if(BYTEORDER_IS_LE(sp))
355         value = bswap32(value);
356     return krb5_store_int(sp, value, 4);
357 }
358
359 /**
360  * Store a uint32 to storage, byte order is controlled by the settings
361  * on the storage, see krb5_storage_set_byteorder().
362  *
363  * @param sp the storage to write too
364  * @param value the value to store
365  *
366  * @return 0 for success, or a Kerberos 5 error code on failure.
367  *
368  * @ingroup krb5_storage
369  */
370
371 KRB5_LIB_FUNCTION krb5_error_code KRB5_LIB_CALL
372 krb5_store_uint32(krb5_storage *sp,
373                   uint32_t value)
374 {
375     return krb5_store_int32(sp, (int32_t)value);
376 }
377
378 static krb5_error_code
379 krb5_ret_int(krb5_storage *sp,
380              int32_t *value,
381              size_t len)
382 {
383     int ret;
384     unsigned char v[4];
385     unsigned long w;
386     ret = sp->fetch(sp, v, len);
387     if (ret < 0)
388         return errno;
389     if ((size_t)ret != len)
390         return sp->eof_code;
391     _krb5_get_int(v, &w, len);
392     *value = w;
393     return 0;
394 }
395
396 /**
397  * Read a int32 from storage, byte order is controlled by the settings
398  * on the storage, see krb5_storage_set_byteorder().
399  *
400  * @param sp the storage to write too
401  * @param value the value read from the buffer
402  *
403  * @return 0 for success, or a Kerberos 5 error code on failure.
404  *
405  * @ingroup krb5_storage
406  */
407
408 KRB5_LIB_FUNCTION krb5_error_code KRB5_LIB_CALL
409 krb5_ret_int32(krb5_storage *sp,
410                int32_t *value)
411 {
412     krb5_error_code ret = krb5_ret_int(sp, value, 4);
413     if(ret)
414         return ret;
415     if(BYTEORDER_IS_HOST(sp))
416         *value = htonl(*value);
417     else if(BYTEORDER_IS_LE(sp))
418         *value = bswap32(*value);
419     return 0;
420 }
421
422 /**
423  * Read a uint32 from storage, byte order is controlled by the settings
424  * on the storage, see krb5_storage_set_byteorder().
425  *
426  * @param sp the storage to write too
427  * @param value the value read from the buffer
428  *
429  * @return 0 for success, or a Kerberos 5 error code on failure.
430  *
431  * @ingroup krb5_storage
432  */
433
434 KRB5_LIB_FUNCTION krb5_error_code KRB5_LIB_CALL
435 krb5_ret_uint32(krb5_storage *sp,
436                 uint32_t *value)
437 {
438     krb5_error_code ret;
439     int32_t v;
440
441     ret = krb5_ret_int32(sp, &v);
442     if (ret == 0)
443         *value = (uint32_t)v;
444
445     return ret;
446 }
447
448 /**
449  * Store a int16 to storage, byte order is controlled by the settings
450  * on the storage, see krb5_storage_set_byteorder().
451  *
452  * @param sp the storage to write too
453  * @param value the value to store
454  *
455  * @return 0 for success, or a Kerberos 5 error code on failure.
456  *
457  * @ingroup krb5_storage
458  */
459
460 KRB5_LIB_FUNCTION krb5_error_code KRB5_LIB_CALL
461 krb5_store_int16(krb5_storage *sp,
462                  int16_t value)
463 {
464     if(BYTEORDER_IS_HOST(sp))
465         value = htons(value);
466     else if(BYTEORDER_IS_LE(sp))
467         value = bswap16(value);
468     return krb5_store_int(sp, value, 2);
469 }
470
471 /**
472  * Store a uint16 to storage, byte order is controlled by the settings
473  * on the storage, see krb5_storage_set_byteorder().
474  *
475  * @param sp the storage to write too
476  * @param value the value to store
477  *
478  * @return 0 for success, or a Kerberos 5 error code on failure.
479  *
480  * @ingroup krb5_storage
481  */
482
483 KRB5_LIB_FUNCTION krb5_error_code KRB5_LIB_CALL
484 krb5_store_uint16(krb5_storage *sp,
485                   uint16_t value)
486 {
487     return krb5_store_int16(sp, (int16_t)value);
488 }
489
490 /**
491  * Read a int16 from storage, byte order is controlled by the settings
492  * on the storage, see krb5_storage_set_byteorder().
493  *
494  * @param sp the storage to write too
495  * @param value the value read from the buffer
496  *
497  * @return 0 for success, or a Kerberos 5 error code on failure.
498  *
499  * @ingroup krb5_storage
500  */
501
502 KRB5_LIB_FUNCTION krb5_error_code KRB5_LIB_CALL
503 krb5_ret_int16(krb5_storage *sp,
504                int16_t *value)
505 {
506     int32_t v;
507     int ret;
508     ret = krb5_ret_int(sp, &v, 2);
509     if(ret)
510         return ret;
511     *value = v;
512     if(BYTEORDER_IS_HOST(sp))
513         *value = htons(*value);
514     else if(BYTEORDER_IS_LE(sp))
515         *value = bswap16(*value);
516     return 0;
517 }
518
519 /**
520  * Read a int16 from storage, byte order is controlled by the settings
521  * on the storage, see krb5_storage_set_byteorder().
522  *
523  * @param sp the storage to write too
524  * @param value the value read from the buffer
525  *
526  * @return 0 for success, or a Kerberos 5 error code on failure.
527  *
528  * @ingroup krb5_storage
529  */
530
531 KRB5_LIB_FUNCTION krb5_error_code KRB5_LIB_CALL
532 krb5_ret_uint16(krb5_storage *sp,
533                 uint16_t *value)
534 {
535     krb5_error_code ret;
536     int16_t v;
537
538     ret = krb5_ret_int16(sp, &v);
539     if (ret == 0)
540         *value = (uint16_t)v;
541
542     return ret;
543 }
544
545 /**
546  * Store a int8 to storage.
547  *
548  * @param sp the storage to write too
549  * @param value the value to store
550  *
551  * @return 0 for success, or a Kerberos 5 error code on failure.
552  *
553  * @ingroup krb5_storage
554  */
555
556 KRB5_LIB_FUNCTION krb5_error_code KRB5_LIB_CALL
557 krb5_store_int8(krb5_storage *sp,
558                 int8_t value)
559 {
560     int ret;
561
562     ret = sp->store(sp, &value, sizeof(value));
563     if (ret != sizeof(value))
564         return (ret<0)?errno:sp->eof_code;
565     return 0;
566 }
567
568 /**
569  * Store a uint8 to storage.
570  *
571  * @param sp the storage to write too
572  * @param value the value to store
573  *
574  * @return 0 for success, or a Kerberos 5 error code on failure.
575  *
576  * @ingroup krb5_storage
577  */
578
579 KRB5_LIB_FUNCTION krb5_error_code KRB5_LIB_CALL
580 krb5_store_uint8(krb5_storage *sp,
581                  uint8_t value)
582 {
583     return krb5_store_int8(sp, (int8_t)value);
584 }
585
586 /**
587  * Read a int8 from storage
588  *
589  * @param sp the storage to write too
590  * @param value the value read from the buffer
591  *
592  * @return 0 for success, or a Kerberos 5 error code on failure.
593  *
594  * @ingroup krb5_storage
595  */
596
597 KRB5_LIB_FUNCTION krb5_error_code KRB5_LIB_CALL
598 krb5_ret_int8(krb5_storage *sp,
599               int8_t *value)
600 {
601     int ret;
602
603     ret = sp->fetch(sp, value, sizeof(*value));
604     if (ret != sizeof(*value))
605         return (ret<0)?errno:sp->eof_code;
606     return 0;
607 }
608
609 /**
610  * Read a uint8 from storage
611  *
612  * @param sp the storage to write too
613  * @param value the value read from the buffer
614  *
615  * @return 0 for success, or a Kerberos 5 error code on failure.
616  *
617  * @ingroup krb5_storage
618  */
619
620 KRB5_LIB_FUNCTION krb5_error_code KRB5_LIB_CALL
621 krb5_ret_uint8(krb5_storage *sp,
622                uint8_t *value)
623 {
624     krb5_error_code ret;
625     int8_t v;
626
627     ret = krb5_ret_int8(sp, &v);
628     if (ret == 0)
629         *value = (uint8_t)v;
630
631     return ret;
632 }
633
634 /**
635  * Store a data to the storage. The data is stored with an int32 as
636  * lenght plus the data (not padded).
637  *
638  * @param sp the storage buffer to write to
639  * @param data the buffer to store.
640  *
641  * @return 0 on success, a Kerberos 5 error code on failure.
642  *
643  * @ingroup krb5_storage
644  */
645
646 KRB5_LIB_FUNCTION krb5_error_code KRB5_LIB_CALL
647 krb5_store_data(krb5_storage *sp,
648                 krb5_data data)
649 {
650     int ret;
651     ret = krb5_store_int32(sp, data.length);
652     if(ret < 0)
653         return ret;
654     ret = sp->store(sp, data.data, data.length);
655     if(ret < 0)
656         return errno;
657     if((size_t)ret != data.length)
658         return sp->eof_code;
659     return 0;
660 }
661
662 /**
663  * Parse a data from the storage.
664  *
665  * @param sp the storage buffer to read from
666  * @param data the parsed data
667  *
668  * @return 0 on success, a Kerberos 5 error code on failure.
669  *
670  * @ingroup krb5_storage
671  */
672
673 KRB5_LIB_FUNCTION krb5_error_code KRB5_LIB_CALL
674 krb5_ret_data(krb5_storage *sp,
675               krb5_data *data)
676 {
677     int ret;
678     int32_t size;
679
680     ret = krb5_ret_int32(sp, &size);
681     if(ret)
682         return ret;
683     ret = size_too_large(sp, size);
684     if (ret)
685         return ret;
686     ret = krb5_data_alloc (data, size);
687     if (ret)
688         return ret;
689     if (size) {
690         ret = sp->fetch(sp, data->data, size);
691         if(ret != size)
692             return (ret < 0)? errno : sp->eof_code;
693     }
694     return 0;
695 }
696
697 /**
698  * Store a string to the buffer. The data is formated as an len:uint32
699  * plus the string itself (not padded).
700  *
701  * @param sp the storage buffer to write to
702  * @param s the string to store.
703  *
704  * @return 0 on success, a Kerberos 5 error code on failure.
705  *
706  * @ingroup krb5_storage
707  */
708
709 KRB5_LIB_FUNCTION krb5_error_code KRB5_LIB_CALL
710 krb5_store_string(krb5_storage *sp, const char *s)
711 {
712     krb5_data data;
713     data.length = strlen(s);
714     data.data = rk_UNCONST(s);
715     return krb5_store_data(sp, data);
716 }
717
718 /**
719  * Parse a string from the storage.
720  *
721  * @param sp the storage buffer to read from
722  * @param string the parsed string
723  *
724  * @return 0 on success, a Kerberos 5 error code on failure.
725  *
726  * @ingroup krb5_storage
727  */
728
729
730 KRB5_LIB_FUNCTION krb5_error_code KRB5_LIB_CALL
731 krb5_ret_string(krb5_storage *sp,
732                 char **string)
733 {
734     int ret;
735     krb5_data data;
736     ret = krb5_ret_data(sp, &data);
737     if(ret)
738         return ret;
739     *string = realloc(data.data, data.length + 1);
740     if(*string == NULL){
741         free(data.data);
742         return ENOMEM;
743     }
744     (*string)[data.length] = 0;
745     return 0;
746 }
747
748 /**
749  * Store a zero terminated string to the buffer. The data is stored
750  * one character at a time until a NUL is stored.
751  *
752  * @param sp the storage buffer to write to
753  * @param s the string to store.
754  *
755  * @return 0 on success, a Kerberos 5 error code on failure.
756  *
757  * @ingroup krb5_storage
758  */
759
760 KRB5_LIB_FUNCTION krb5_error_code KRB5_LIB_CALL
761 krb5_store_stringz(krb5_storage *sp, const char *s)
762 {
763     size_t len = strlen(s) + 1;
764     ssize_t ret;
765
766     ret = sp->store(sp, s, len);
767     if(ret < 0)
768         return ret;
769     if((size_t)ret != len)
770         return sp->eof_code;
771     return 0;
772 }
773
774 /**
775  * Parse zero terminated string from the storage.
776  *
777  * @param sp the storage buffer to read from
778  * @param string the parsed string
779  *
780  * @return 0 on success, a Kerberos 5 error code on failure.
781  *
782  * @ingroup krb5_storage
783  */
784
785 KRB5_LIB_FUNCTION krb5_error_code KRB5_LIB_CALL
786 krb5_ret_stringz(krb5_storage *sp,
787                 char **string)
788 {
789     char c;
790     char *s = NULL;
791     size_t len = 0;
792     ssize_t ret;
793
794     while((ret = sp->fetch(sp, &c, 1)) == 1){
795         char *tmp;
796
797         len++;
798         ret = size_too_large(sp, len);
799         if (ret)
800             break;
801         tmp = realloc (s, len);
802         if (tmp == NULL) {
803             free (s);
804             return ENOMEM;
805         }
806         s = tmp;
807         s[len - 1] = c;
808         if(c == 0)
809             break;
810     }
811     if(ret != 1){
812         free(s);
813         if(ret == 0)
814             return sp->eof_code;
815         return ret;
816     }
817     *string = s;
818     return 0;
819 }
820
821 KRB5_LIB_FUNCTION krb5_error_code KRB5_LIB_CALL
822 krb5_store_stringnl(krb5_storage *sp, const char *s)
823 {
824     size_t len = strlen(s);
825     ssize_t ret;
826
827     ret = sp->store(sp, s, len);
828     if(ret < 0)
829         return ret;
830     if((size_t)ret != len)
831         return sp->eof_code;
832     ret = sp->store(sp, "\n", 1);
833     if(ret != 1) {
834         if(ret < 0)
835             return ret;
836         else
837             return sp->eof_code;
838     }
839
840     return 0;
841
842 }
843
844 KRB5_LIB_FUNCTION krb5_error_code KRB5_LIB_CALL
845 krb5_ret_stringnl(krb5_storage *sp,
846                   char **string)
847 {
848     int expect_nl = 0;
849     char c;
850     char *s = NULL;
851     size_t len = 0;
852     ssize_t ret;
853
854     while((ret = sp->fetch(sp, &c, 1)) == 1){
855         char *tmp;
856
857         if (c == '\r') {
858             expect_nl = 1;
859             continue;
860         }
861         if (expect_nl && c != '\n') {
862             free(s);
863             return KRB5_BADMSGTYPE;
864         }
865
866         len++;
867         ret = size_too_large(sp, len);
868         if (ret)
869             break;
870         tmp = realloc (s, len);
871         if (tmp == NULL) {
872             free (s);
873             return ENOMEM;
874         }
875         s = tmp;
876         if(c == '\n') {
877             s[len - 1] = '\0';
878             break;
879         }
880         s[len - 1] = c;
881     }
882     if(ret != 1){
883         free(s);
884         if(ret == 0)
885             return sp->eof_code;
886         return ret;
887     }
888     *string = s;
889     return 0;
890 }
891
892 /**
893  * Write a principal block to storage.
894  *
895  * @param sp the storage buffer to write to
896  * @param p the principal block to write.
897  *
898  * @return 0 on success, a Kerberos 5 error code on failure.
899  *
900  * @ingroup krb5_storage
901  */
902
903 KRB5_LIB_FUNCTION krb5_error_code KRB5_LIB_CALL
904 krb5_store_principal(krb5_storage *sp,
905                      krb5_const_principal p)
906 {
907     size_t i;
908     int ret;
909
910     if(!krb5_storage_is_flags(sp, KRB5_STORAGE_PRINCIPAL_NO_NAME_TYPE)) {
911         ret = krb5_store_int32(sp, p->name.name_type);
912         if(ret) return ret;
913     }
914     if(krb5_storage_is_flags(sp, KRB5_STORAGE_PRINCIPAL_WRONG_NUM_COMPONENTS))
915         ret = krb5_store_int32(sp, p->name.name_string.len + 1);
916     else
917         ret = krb5_store_int32(sp, p->name.name_string.len);
918
919     if(ret) return ret;
920     ret = krb5_store_string(sp, p->realm);
921     if(ret) return ret;
922     for(i = 0; i < p->name.name_string.len; i++){
923         ret = krb5_store_string(sp, p->name.name_string.val[i]);
924         if(ret) return ret;
925     }
926     return 0;
927 }
928
929 /**
930  * Parse principal from the storage.
931  *
932  * @param sp the storage buffer to read from
933  * @param princ the parsed principal
934  *
935  * @return 0 on success, a Kerberos 5 error code on failure.
936  *
937  * @ingroup krb5_storage
938  */
939
940 KRB5_LIB_FUNCTION krb5_error_code KRB5_LIB_CALL
941 krb5_ret_principal(krb5_storage *sp,
942                    krb5_principal *princ)
943 {
944     int i;
945     int ret;
946     krb5_principal p;
947     int32_t type;
948     int32_t ncomp;
949
950     p = calloc(1, sizeof(*p));
951     if(p == NULL)
952         return ENOMEM;
953
954     if(krb5_storage_is_flags(sp, KRB5_STORAGE_PRINCIPAL_NO_NAME_TYPE))
955         type = KRB5_NT_UNKNOWN;
956     else if((ret = krb5_ret_int32(sp, &type))){
957         free(p);
958         return ret;
959     }
960     if((ret = krb5_ret_int32(sp, &ncomp))){
961         free(p);
962         return ret;
963     }
964     if(krb5_storage_is_flags(sp, KRB5_STORAGE_PRINCIPAL_WRONG_NUM_COMPONENTS))
965         ncomp--;
966     if (ncomp < 0) {
967         free(p);
968         return EINVAL;
969     }
970     ret = size_too_large_num(sp, ncomp, sizeof(p->name.name_string.val[0]));
971     if (ret) {
972         free(p);
973         return ret;
974     }
975     p->name.name_type = type;
976     p->name.name_string.len = ncomp;
977     ret = krb5_ret_string(sp, &p->realm);
978     if(ret) {
979         free(p);
980         return ret;
981     }
982     p->name.name_string.val = calloc(ncomp, sizeof(p->name.name_string.val[0]));
983     if(p->name.name_string.val == NULL && ncomp != 0){
984         free(p->realm);
985         free(p);
986         return ENOMEM;
987     }
988     for(i = 0; i < ncomp; i++){
989         ret = krb5_ret_string(sp, &p->name.name_string.val[i]);
990         if(ret) {
991             while (i >= 0)
992                 free(p->name.name_string.val[i--]);
993             free(p->realm);
994             free(p);
995             return ret;
996         }
997     }
998     *princ = p;
999     return 0;
1000 }
1001
1002 /**
1003  * Store a keyblock to the storage.
1004  *
1005  * @param sp the storage buffer to write to
1006  * @param p the keyblock to write
1007  *
1008  * @return 0 on success, a Kerberos 5 error code on failure.
1009  *
1010  * @ingroup krb5_storage
1011  */
1012
1013 KRB5_LIB_FUNCTION krb5_error_code KRB5_LIB_CALL
1014 krb5_store_keyblock(krb5_storage *sp, krb5_keyblock p)
1015 {
1016     int ret;
1017     ret = krb5_store_int16(sp, p.keytype);
1018     if(ret) return ret;
1019
1020     if(krb5_storage_is_flags(sp, KRB5_STORAGE_KEYBLOCK_KEYTYPE_TWICE)){
1021         /* this should really be enctype, but it is the same as
1022            keytype nowadays */
1023     ret = krb5_store_int16(sp, p.keytype);
1024     if(ret) return ret;
1025     }
1026
1027     ret = krb5_store_data(sp, p.keyvalue);
1028     return ret;
1029 }
1030
1031 /**
1032  * Read a keyblock from the storage.
1033  *
1034  * @param sp the storage buffer to write to
1035  * @param p the keyblock read from storage, free using krb5_free_keyblock()
1036  *
1037  * @return 0 on success, a Kerberos 5 error code on failure.
1038  *
1039  * @ingroup krb5_storage
1040  */
1041
1042 KRB5_LIB_FUNCTION krb5_error_code KRB5_LIB_CALL
1043 krb5_ret_keyblock(krb5_storage *sp, krb5_keyblock *p)
1044 {
1045     int ret;
1046     int16_t tmp;
1047
1048     ret = krb5_ret_int16(sp, &tmp);
1049     if(ret) return ret;
1050     p->keytype = tmp;
1051
1052     if(krb5_storage_is_flags(sp, KRB5_STORAGE_KEYBLOCK_KEYTYPE_TWICE)){
1053     ret = krb5_ret_int16(sp, &tmp);
1054     if(ret) return ret;
1055     }
1056
1057     ret = krb5_ret_data(sp, &p->keyvalue);
1058     return ret;
1059 }
1060
1061 /**
1062  * Write a times block to storage.
1063  *
1064  * @param sp the storage buffer to write to
1065  * @param times the times block to write.
1066  *
1067  * @return 0 on success, a Kerberos 5 error code on failure.
1068  *
1069  * @ingroup krb5_storage
1070  */
1071
1072 KRB5_LIB_FUNCTION krb5_error_code KRB5_LIB_CALL
1073 krb5_store_times(krb5_storage *sp, krb5_times times)
1074 {
1075     int ret;
1076     ret = krb5_store_int32(sp, times.authtime);
1077     if(ret) return ret;
1078     ret = krb5_store_int32(sp, times.starttime);
1079     if(ret) return ret;
1080     ret = krb5_store_int32(sp, times.endtime);
1081     if(ret) return ret;
1082     ret = krb5_store_int32(sp, times.renew_till);
1083     return ret;
1084 }
1085
1086 /**
1087  * Read a times block from the storage.
1088  *
1089  * @param sp the storage buffer to write to
1090  * @param times the times block read from storage
1091  *
1092  * @return 0 on success, a Kerberos 5 error code on failure.
1093  *
1094  * @ingroup krb5_storage
1095  */
1096
1097 KRB5_LIB_FUNCTION krb5_error_code KRB5_LIB_CALL
1098 krb5_ret_times(krb5_storage *sp, krb5_times *times)
1099 {
1100     int ret;
1101     int32_t tmp;
1102     ret = krb5_ret_int32(sp, &tmp);
1103     times->authtime = tmp;
1104     if(ret) return ret;
1105     ret = krb5_ret_int32(sp, &tmp);
1106     times->starttime = tmp;
1107     if(ret) return ret;
1108     ret = krb5_ret_int32(sp, &tmp);
1109     times->endtime = tmp;
1110     if(ret) return ret;
1111     ret = krb5_ret_int32(sp, &tmp);
1112     times->renew_till = tmp;
1113     return ret;
1114 }
1115
1116 /**
1117  * Write a address block to storage.
1118  *
1119  * @param sp the storage buffer to write to
1120  * @param p the address block to write.
1121  *
1122  * @return 0 on success, a Kerberos 5 error code on failure.
1123  *
1124  * @ingroup krb5_storage
1125  */
1126
1127 KRB5_LIB_FUNCTION krb5_error_code KRB5_LIB_CALL
1128 krb5_store_address(krb5_storage *sp, krb5_address p)
1129 {
1130     int ret;
1131     ret = krb5_store_int16(sp, p.addr_type);
1132     if(ret) return ret;
1133     ret = krb5_store_data(sp, p.address);
1134     return ret;
1135 }
1136
1137 /**
1138  * Read a address block from the storage.
1139  *
1140  * @param sp the storage buffer to write to
1141  * @param adr the address block read from storage
1142  *
1143  * @return 0 on success, a Kerberos 5 error code on failure.
1144  *
1145  * @ingroup krb5_storage
1146  */
1147
1148 KRB5_LIB_FUNCTION krb5_error_code KRB5_LIB_CALL
1149 krb5_ret_address(krb5_storage *sp, krb5_address *adr)
1150 {
1151     int16_t t;
1152     int ret;
1153     ret = krb5_ret_int16(sp, &t);
1154     if(ret) return ret;
1155     adr->addr_type = t;
1156     ret = krb5_ret_data(sp, &adr->address);
1157     return ret;
1158 }
1159
1160 /**
1161  * Write a addresses block to storage.
1162  *
1163  * @param sp the storage buffer to write to
1164  * @param p the addresses block to write.
1165  *
1166  * @return 0 on success, a Kerberos 5 error code on failure.
1167  *
1168  * @ingroup krb5_storage
1169  */
1170
1171 KRB5_LIB_FUNCTION krb5_error_code KRB5_LIB_CALL
1172 krb5_store_addrs(krb5_storage *sp, krb5_addresses p)
1173 {
1174     size_t i;
1175     int ret;
1176     ret = krb5_store_int32(sp, p.len);
1177     if(ret) return ret;
1178     for(i = 0; i<p.len; i++){
1179         ret = krb5_store_address(sp, p.val[i]);
1180         if(ret) break;
1181     }
1182     return ret;
1183 }
1184
1185 /**
1186  * Read a addresses block from the storage.
1187  *
1188  * @param sp the storage buffer to write to
1189  * @param adr the addresses block read from storage
1190  *
1191  * @return 0 on success, a Kerberos 5 error code on failure.
1192  *
1193  * @ingroup krb5_storage
1194  */
1195
1196 KRB5_LIB_FUNCTION krb5_error_code KRB5_LIB_CALL
1197 krb5_ret_addrs(krb5_storage *sp, krb5_addresses *adr)
1198 {
1199     size_t i;
1200     int ret;
1201     int32_t tmp;
1202
1203     ret = krb5_ret_int32(sp, &tmp);
1204     if(ret) return ret;
1205     ret = size_too_large_num(sp, tmp, sizeof(adr->val[0]));
1206     if (ret) return ret;
1207     adr->len = tmp;
1208     ALLOC(adr->val, adr->len);
1209     if (adr->val == NULL && adr->len != 0)
1210         return ENOMEM;
1211     for(i = 0; i < adr->len; i++){
1212         ret = krb5_ret_address(sp, &adr->val[i]);
1213         if(ret) break;
1214     }
1215     return ret;
1216 }
1217
1218 /**
1219  * Write a auth data block to storage.
1220  *
1221  * @param sp the storage buffer to write to
1222  * @param auth the auth data block to write.
1223  *
1224  * @return 0 on success, a Kerberos 5 error code on failure.
1225  *
1226  * @ingroup krb5_storage
1227  */
1228
1229 KRB5_LIB_FUNCTION krb5_error_code KRB5_LIB_CALL
1230 krb5_store_authdata(krb5_storage *sp, krb5_authdata auth)
1231 {
1232     krb5_error_code ret;
1233     size_t i;
1234     ret = krb5_store_int32(sp, auth.len);
1235     if(ret) return ret;
1236     for(i = 0; i < auth.len; i++){
1237         ret = krb5_store_int16(sp, auth.val[i].ad_type);
1238         if(ret) break;
1239         ret = krb5_store_data(sp, auth.val[i].ad_data);
1240         if(ret) break;
1241     }
1242     return 0;
1243 }
1244
1245 /**
1246  * Read a auth data from the storage.
1247  *
1248  * @param sp the storage buffer to write to
1249  * @param auth the auth data block read from storage
1250  *
1251  * @return 0 on success, a Kerberos 5 error code on failure.
1252  *
1253  * @ingroup krb5_storage
1254  */
1255
1256 KRB5_LIB_FUNCTION krb5_error_code KRB5_LIB_CALL
1257 krb5_ret_authdata(krb5_storage *sp, krb5_authdata *auth)
1258 {
1259     krb5_error_code ret;
1260     int32_t tmp;
1261     int16_t tmp2;
1262     int i;
1263     ret = krb5_ret_int32(sp, &tmp);
1264     if(ret) return ret;
1265     ret = size_too_large_num(sp, tmp, sizeof(auth->val[0]));
1266     if (ret) return ret;
1267     ALLOC_SEQ(auth, tmp);
1268     if (auth->val == NULL && tmp != 0)
1269         return ENOMEM;
1270     for(i = 0; i < tmp; i++){
1271         ret = krb5_ret_int16(sp, &tmp2);
1272         if(ret) break;
1273         auth->val[i].ad_type = tmp2;
1274         ret = krb5_ret_data(sp, &auth->val[i].ad_data);
1275         if(ret) break;
1276     }
1277     return ret;
1278 }
1279
1280 static int32_t
1281 bitswap32(int32_t b)
1282 {
1283     int32_t r = 0;
1284     int i;
1285     for (i = 0; i < 32; i++) {
1286         r = r << 1 | (b & 1);
1287         b = b >> 1;
1288     }
1289     return r;
1290 }
1291
1292 /**
1293  * Write a credentials block to storage.
1294  *
1295  * @param sp the storage buffer to write to
1296  * @param creds the creds block to write.
1297  *
1298  * @return 0 on success, a Kerberos 5 error code on failure.
1299  *
1300  * @ingroup krb5_storage
1301  */
1302
1303 KRB5_LIB_FUNCTION krb5_error_code KRB5_LIB_CALL
1304 krb5_store_creds(krb5_storage *sp, krb5_creds *creds)
1305 {
1306     int ret;
1307
1308     ret = krb5_store_principal(sp, creds->client);
1309     if(ret)
1310         return ret;
1311     ret = krb5_store_principal(sp, creds->server);
1312     if(ret)
1313         return ret;
1314     ret = krb5_store_keyblock(sp, creds->session);
1315     if(ret)
1316         return ret;
1317     ret = krb5_store_times(sp, creds->times);
1318     if(ret)
1319         return ret;
1320     ret = krb5_store_int8(sp, creds->second_ticket.length != 0); /* is_skey */
1321     if(ret)
1322         return ret;
1323
1324     if(krb5_storage_is_flags(sp, KRB5_STORAGE_CREDS_FLAGS_WRONG_BITORDER))
1325         ret = krb5_store_int32(sp, creds->flags.i);
1326     else
1327         ret = krb5_store_int32(sp, bitswap32(TicketFlags2int(creds->flags.b)));
1328     if(ret)
1329         return ret;
1330
1331     ret = krb5_store_addrs(sp, creds->addresses);
1332     if(ret)
1333         return ret;
1334     ret = krb5_store_authdata(sp, creds->authdata);
1335     if(ret)
1336         return ret;
1337     ret = krb5_store_data(sp, creds->ticket);
1338     if(ret)
1339         return ret;
1340     ret = krb5_store_data(sp, creds->second_ticket);
1341     return ret;
1342 }
1343
1344 /**
1345  * Read a credentials block from the storage.
1346  *
1347  * @param sp the storage buffer to write to
1348  * @param creds the credentials block read from storage
1349  *
1350  * @return 0 on success, a Kerberos 5 error code on failure.
1351  *
1352  * @ingroup krb5_storage
1353  */
1354
1355 KRB5_LIB_FUNCTION krb5_error_code KRB5_LIB_CALL
1356 krb5_ret_creds(krb5_storage *sp, krb5_creds *creds)
1357 {
1358     krb5_error_code ret;
1359     int8_t dummy8;
1360     int32_t dummy32;
1361
1362     memset(creds, 0, sizeof(*creds));
1363     ret = krb5_ret_principal (sp,  &creds->client);
1364     if(ret) goto cleanup;
1365     ret = krb5_ret_principal (sp,  &creds->server);
1366     if(ret) goto cleanup;
1367     ret = krb5_ret_keyblock (sp,  &creds->session);
1368     if(ret) goto cleanup;
1369     ret = krb5_ret_times (sp,  &creds->times);
1370     if(ret) goto cleanup;
1371     ret = krb5_ret_int8 (sp,  &dummy8);
1372     if(ret) goto cleanup;
1373     ret = krb5_ret_int32 (sp,  &dummy32);
1374     if(ret) goto cleanup;
1375     /*
1376      * Runtime detect the what is the higher bits of the bitfield. If
1377      * any of the higher bits are set in the input data, it's either a
1378      * new ticket flag (and this code need to be removed), or it's a
1379      * MIT cache (or new Heimdal cache), lets change it to our current
1380      * format.
1381      */
1382     {
1383         uint32_t mask = 0xffff0000;
1384         creds->flags.i = 0;
1385         creds->flags.b.anonymous = 1;
1386         if (creds->flags.i & mask)
1387             mask = ~mask;
1388         if (dummy32 & mask)
1389             dummy32 = bitswap32(dummy32);
1390     }
1391     creds->flags.i = dummy32;
1392     ret = krb5_ret_addrs (sp,  &creds->addresses);
1393     if(ret) goto cleanup;
1394     ret = krb5_ret_authdata (sp,  &creds->authdata);
1395     if(ret) goto cleanup;
1396     ret = krb5_ret_data (sp,  &creds->ticket);
1397     if(ret) goto cleanup;
1398     ret = krb5_ret_data (sp,  &creds->second_ticket);
1399 cleanup:
1400     if(ret) {
1401 #if 0
1402         krb5_free_cred_contents(context, creds); /* XXX */
1403 #endif
1404     }
1405     return ret;
1406 }
1407
1408 #define SC_CLIENT_PRINCIPAL         0x0001
1409 #define SC_SERVER_PRINCIPAL         0x0002
1410 #define SC_SESSION_KEY              0x0004
1411 #define SC_TICKET                   0x0008
1412 #define SC_SECOND_TICKET            0x0010
1413 #define SC_AUTHDATA                 0x0020
1414 #define SC_ADDRESSES                0x0040
1415
1416 /**
1417  * Write a tagged credentials block to storage.
1418  *
1419  * @param sp the storage buffer to write to
1420  * @param creds the creds block to write.
1421  *
1422  * @return 0 on success, a Kerberos 5 error code on failure.
1423  *
1424  * @ingroup krb5_storage
1425  */
1426
1427 KRB5_LIB_FUNCTION krb5_error_code KRB5_LIB_CALL
1428 krb5_store_creds_tag(krb5_storage *sp, krb5_creds *creds)
1429 {
1430     int ret;
1431     int32_t header = 0;
1432
1433     if (creds->client)
1434         header |= SC_CLIENT_PRINCIPAL;
1435     if (creds->server)
1436         header |= SC_SERVER_PRINCIPAL;
1437     if (creds->session.keytype != ETYPE_NULL)
1438         header |= SC_SESSION_KEY;
1439     if (creds->ticket.data)
1440         header |= SC_TICKET;
1441     if (creds->second_ticket.length)
1442         header |= SC_SECOND_TICKET;
1443     if (creds->authdata.len)
1444         header |= SC_AUTHDATA;
1445     if (creds->addresses.len)
1446         header |= SC_ADDRESSES;
1447
1448     ret = krb5_store_int32(sp, header);
1449     if (ret)
1450         return ret;
1451
1452     if (creds->client) {
1453         ret = krb5_store_principal(sp, creds->client);
1454         if(ret)
1455             return ret;
1456     }
1457
1458     if (creds->server) {
1459         ret = krb5_store_principal(sp, creds->server);
1460         if(ret)
1461             return ret;
1462     }
1463
1464     if (creds->session.keytype != ETYPE_NULL) {
1465         ret = krb5_store_keyblock(sp, creds->session);
1466         if(ret)
1467             return ret;
1468     }
1469
1470     ret = krb5_store_times(sp, creds->times);
1471     if(ret)
1472         return ret;
1473     ret = krb5_store_int8(sp, creds->second_ticket.length != 0); /* is_skey */
1474     if(ret)
1475         return ret;
1476
1477     ret = krb5_store_int32(sp, bitswap32(TicketFlags2int(creds->flags.b)));
1478     if(ret)
1479         return ret;
1480
1481     if (creds->addresses.len) {
1482         ret = krb5_store_addrs(sp, creds->addresses);
1483         if(ret)
1484             return ret;
1485     }
1486
1487     if (creds->authdata.len) {
1488         ret = krb5_store_authdata(sp, creds->authdata);
1489         if(ret)
1490             return ret;
1491     }
1492
1493     if (creds->ticket.data) {
1494         ret = krb5_store_data(sp, creds->ticket);
1495         if(ret)
1496             return ret;
1497     }
1498
1499     if (creds->second_ticket.data) {
1500         ret = krb5_store_data(sp, creds->second_ticket);
1501         if (ret)
1502             return ret;
1503     }
1504
1505     return ret;
1506 }
1507
1508 /**
1509  * Read a tagged credentials block from the storage.
1510  *
1511  * @param sp the storage buffer to write to
1512  * @param creds the credentials block read from storage
1513  *
1514  * @return 0 on success, a Kerberos 5 error code on failure.
1515  *
1516  * @ingroup krb5_storage
1517  */
1518
1519 KRB5_LIB_FUNCTION krb5_error_code KRB5_LIB_CALL
1520 krb5_ret_creds_tag(krb5_storage *sp,
1521                    krb5_creds *creds)
1522 {
1523     krb5_error_code ret;
1524     int8_t dummy8;
1525     int32_t dummy32, header;
1526
1527     memset(creds, 0, sizeof(*creds));
1528
1529     ret = krb5_ret_int32 (sp, &header);
1530     if (ret) goto cleanup;
1531
1532     if (header & SC_CLIENT_PRINCIPAL) {
1533         ret = krb5_ret_principal (sp,  &creds->client);
1534         if(ret) goto cleanup;
1535     }
1536     if (header & SC_SERVER_PRINCIPAL) {
1537         ret = krb5_ret_principal (sp,  &creds->server);
1538         if(ret) goto cleanup;
1539     }
1540     if (header & SC_SESSION_KEY) {
1541         ret = krb5_ret_keyblock (sp,  &creds->session);
1542         if(ret) goto cleanup;
1543     }
1544     ret = krb5_ret_times (sp,  &creds->times);
1545     if(ret) goto cleanup;
1546     ret = krb5_ret_int8 (sp,  &dummy8);
1547     if(ret) goto cleanup;
1548     ret = krb5_ret_int32 (sp,  &dummy32);
1549     if(ret) goto cleanup;
1550     /*
1551      * Runtime detect the what is the higher bits of the bitfield. If
1552      * any of the higher bits are set in the input data, it's either a
1553      * new ticket flag (and this code need to be removed), or it's a
1554      * MIT cache (or new Heimdal cache), lets change it to our current
1555      * format.
1556      */
1557     {
1558         uint32_t mask = 0xffff0000;
1559         creds->flags.i = 0;
1560         creds->flags.b.anonymous = 1;
1561         if (creds->flags.i & mask)
1562             mask = ~mask;
1563         if (dummy32 & mask)
1564             dummy32 = bitswap32(dummy32);
1565     }
1566     creds->flags.i = dummy32;
1567     if (header & SC_ADDRESSES) {
1568         ret = krb5_ret_addrs (sp,  &creds->addresses);
1569         if(ret) goto cleanup;
1570     }
1571     if (header & SC_AUTHDATA) {
1572         ret = krb5_ret_authdata (sp,  &creds->authdata);
1573         if(ret) goto cleanup;
1574     }
1575     if (header & SC_TICKET) {
1576         ret = krb5_ret_data (sp,  &creds->ticket);
1577         if(ret) goto cleanup;
1578     }
1579     if (header & SC_SECOND_TICKET) {
1580         ret = krb5_ret_data (sp,  &creds->second_ticket);
1581         if(ret) goto cleanup;
1582     }
1583
1584 cleanup:
1585     if(ret) {
1586 #if 0
1587         krb5_free_cred_contents(context, creds); /* XXX */
1588 #endif
1589     }
1590     return ret;
1591 }