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