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