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