2 * Copyright (c) 1997-2008 Kungliga Tekniska Högskolan
3 * (Royal Institute of Technology, Stockholm, Sweden).
6 * Redistribution and use in source and binary forms, with or without
7 * modification, are permitted provided that the following conditions
10 * 1. Redistributions of source code must retain the above copyright
11 * notice, this list of conditions and the following disclaimer.
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.
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.
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
34 #include "krb5_locl.h"
35 #include "store-int.h"
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 #define BYTEORDER_IS_PACKED(SP) BYTEORDER_IS((SP), KRB5_STORAGE_BYTEORDER_PACKED)
45 * Add the flags on a storage buffer by or-ing in the flags to the buffer.
47 * @param sp the storage buffer to set the flags on
48 * @param flags the flags to set
50 * @ingroup krb5_storage
53 KRB5_LIB_FUNCTION void KRB5_LIB_CALL
54 krb5_storage_set_flags(krb5_storage *sp, krb5_flags flags)
60 * Clear the flags on a storage buffer
62 * @param sp the storage buffer to clear the flags on
63 * @param flags the flags to clear
65 * @ingroup krb5_storage
68 KRB5_LIB_FUNCTION void KRB5_LIB_CALL
69 krb5_storage_clear_flags(krb5_storage *sp, krb5_flags flags)
75 * Return true or false depending on if the storage flags is set or
76 * not. NB testing for the flag 0 always return true.
78 * @param sp the storage buffer to check flags on
79 * @param flags The flags to test for
81 * @return true if all the flags are set, false if not.
83 * @ingroup krb5_storage
86 KRB5_LIB_FUNCTION krb5_boolean KRB5_LIB_CALL
87 krb5_storage_is_flags(krb5_storage *sp, krb5_flags flags)
89 return (sp->flags & flags) == flags;
93 * Set the new byte order of the storage buffer.
95 * @param sp the storage buffer to set the byte order for.
96 * @param byteorder the new byte order.
98 * The byte order are: KRB5_STORAGE_BYTEORDER_BE,
99 * KRB5_STORAGE_BYTEORDER_LE and KRB5_STORAGE_BYTEORDER_HOST.
101 * @ingroup krb5_storage
104 KRB5_LIB_FUNCTION void KRB5_LIB_CALL
105 krb5_storage_set_byteorder(krb5_storage *sp, krb5_flags byteorder)
107 sp->flags &= ~KRB5_STORAGE_BYTEORDER_MASK;
108 sp->flags |= byteorder;
112 * Return the current byteorder for the buffer. See krb5_storage_set_byteorder() for the list or byte order contants.
114 * @ingroup krb5_storage
117 KRB5_LIB_FUNCTION krb5_flags KRB5_LIB_CALL
118 krb5_storage_get_byteorder(krb5_storage *sp)
120 return sp->flags & KRB5_STORAGE_BYTEORDER_MASK;
124 * Set the max alloc value
126 * @param sp the storage buffer set the max allow for
127 * @param size maximum size to allocate, use 0 to remove limit
129 * @ingroup krb5_storage
132 KRB5_LIB_FUNCTION void KRB5_LIB_CALL
133 krb5_storage_set_max_alloc(krb5_storage *sp, size_t size)
135 sp->max_alloc = size;
138 /* don't allocate unresonable amount of memory */
139 static krb5_error_code
140 size_too_large(krb5_storage *sp, size_t size)
142 if (sp->max_alloc && sp->max_alloc < size)
143 return HEIM_ERR_TOO_BIG;
147 static krb5_error_code
148 size_too_large_num(krb5_storage *sp, size_t count, size_t size)
150 if (sp->max_alloc == 0 || size == 0)
152 size = sp->max_alloc / size;
154 return HEIM_ERR_TOO_BIG;
159 * Seek to a new offset.
161 * @param sp the storage buffer to seek in.
162 * @param offset the offset to seek
163 * @param whence relateive searching, SEEK_CUR from the current
164 * position, SEEK_END from the end, SEEK_SET absolute from the start.
166 * @return The new current offset
168 * @ingroup krb5_storage
171 KRB5_LIB_FUNCTION off_t KRB5_LIB_CALL
172 krb5_storage_seek(krb5_storage *sp, off_t offset, int whence)
174 return (*sp->seek)(sp, offset, whence);
178 * Truncate the storage buffer in sp to offset.
180 * @param sp the storage buffer to truncate.
181 * @param offset the offset to truncate too.
183 * @return An Kerberos 5 error code.
185 * @ingroup krb5_storage
188 KRB5_LIB_FUNCTION int KRB5_LIB_CALL
189 krb5_storage_truncate(krb5_storage *sp, off_t offset)
191 return (*sp->trunc)(sp, offset);
195 * Sync the storage buffer to its backing store. If there is no
196 * backing store this function will return success.
198 * @param sp the storage buffer to sync
200 * @return A Kerberos 5 error code
202 * @ingroup krb5_storage
205 KRB5_LIB_FUNCTION int KRB5_LIB_CALL
206 krb5_storage_fsync(krb5_storage *sp)
208 if (sp->fsync != NULL)
209 return sp->fsync(sp);
214 * Read to the storage buffer.
216 * @param sp the storage buffer to read from
217 * @param buf the buffer to store the data in
218 * @param len the length to read
220 * @return The length of data read (can be shorter then len), or negative on error.
222 * @ingroup krb5_storage
225 KRB5_LIB_FUNCTION krb5_ssize_t KRB5_LIB_CALL
226 krb5_storage_read(krb5_storage *sp, void *buf, size_t len)
228 return sp->fetch(sp, buf, len);
232 * Write to the storage buffer.
234 * @param sp the storage buffer to write to
235 * @param buf the buffer to write to the storage buffer
236 * @param len the length to write
238 * @return The length of data written (can be shorter then len), or negative on error.
240 * @ingroup krb5_storage
243 KRB5_LIB_FUNCTION krb5_ssize_t KRB5_LIB_CALL
244 krb5_storage_write(krb5_storage *sp, const void *buf, size_t len)
246 return sp->store(sp, buf, len);
250 * Set the return code that will be used when end of storage is reached.
252 * @param sp the storage
253 * @param code the error code to return on end of storage
255 * @ingroup krb5_storage
258 KRB5_LIB_FUNCTION void KRB5_LIB_CALL
259 krb5_storage_set_eof_code(krb5_storage *sp, int code)
265 * Get the return code that will be used when end of storage is reached.
267 * @param sp the storage
269 * @return storage error code
271 * @ingroup krb5_storage
274 KRB5_LIB_FUNCTION int KRB5_LIB_CALL
275 krb5_storage_get_eof_code(krb5_storage *sp)
281 * Free a krb5 storage.
283 * @param sp the storage to free.
285 * @return An Kerberos 5 error code.
287 * @ingroup krb5_storage
290 KRB5_LIB_FUNCTION krb5_error_code KRB5_LIB_CALL
291 krb5_storage_free(krb5_storage *sp)
303 * Copy the contnent of storage
305 * @param sp the storage to copy to a data
306 * @param data the copied data, free with krb5_data_free()
308 * @return 0 for success, or a Kerberos 5 error code on failure.
310 * @ingroup krb5_storage
313 KRB5_LIB_FUNCTION krb5_error_code KRB5_LIB_CALL
314 krb5_storage_to_data(krb5_storage *sp, krb5_data *data)
319 pos = sp->seek(sp, 0, SEEK_CUR);
321 return HEIM_ERR_NOT_SEEKABLE;
322 size = sp->seek(sp, 0, SEEK_END);
323 ret = size_too_large(sp, size);
326 ret = krb5_data_alloc(data, size);
328 sp->seek(sp, pos, SEEK_SET);
332 sp->seek(sp, 0, SEEK_SET);
333 sp->fetch(sp, data->data, data->length);
334 sp->seek(sp, pos, SEEK_SET);
340 pack_int(uint8_t *p, uint64_t val)
358 unpack_int_length(uint8_t *v)
371 unpack_int(uint8_t *p, size_t len, uint64_t *val, size_t *size)
394 e = der_get_unsigned64(p, v, &tmp, &l);
403 static krb5_error_code
404 krb5_store_int(krb5_storage *sp,
409 uint8_t v[9], *p = v;
411 if (len > sizeof(value))
414 if (BYTEORDER_IS_PACKED(sp)) {
415 uint64_t mask = ~0ULL >> (64 - len * 8);
418 len = pack_int(p, value);
419 p = v + sizeof(v) - len;
421 _krb5_put_int(v, value, len);
422 ret = sp->store(sp, p, len);
425 if ((size_t)ret != len)
431 * Store a int32 to storage, byte order is controlled by the settings
432 * on the storage, see krb5_storage_set_byteorder().
434 * @param sp the storage to write too
435 * @param value the value to store
437 * @return 0 for success, or a Kerberos 5 error code on failure.
439 * @ingroup krb5_storage
442 KRB5_LIB_FUNCTION krb5_error_code KRB5_LIB_CALL
443 krb5_store_int32(krb5_storage *sp,
446 if(BYTEORDER_IS_HOST(sp))
447 value = htonl(value);
448 else if(BYTEORDER_IS_LE(sp))
449 value = bswap32(value);
450 return krb5_store_int(sp, value, 4);
454 * Store a int64 to storage, byte order is controlled by the settings
455 * on the storage, see krb5_storage_set_byteorder().
457 * @param sp the storage to write too
458 * @param value the value to store
460 * @return 0 for success, or a Kerberos 5 error code on failure.
462 * @ingroup krb5_storage
465 KRB5_LIB_FUNCTION krb5_error_code KRB5_LIB_CALL
466 krb5_store_int64(krb5_storage *sp,
469 if (BYTEORDER_IS_HOST(sp))
470 #ifdef WORDS_BIGENDIAN
473 value = bswap64(value); /* There's no ntohll() */
475 else if (BYTEORDER_IS_LE(sp))
476 value = bswap64(value);
477 return krb5_store_int(sp, value, 8);
481 * Store a uint32 to storage, byte order is controlled by the settings
482 * on the storage, see krb5_storage_set_byteorder().
484 * @param sp the storage to write too
485 * @param value the value to store
487 * @return 0 for success, or a Kerberos 5 error code on failure.
489 * @ingroup krb5_storage
492 KRB5_LIB_FUNCTION krb5_error_code KRB5_LIB_CALL
493 krb5_store_uint32(krb5_storage *sp,
496 return krb5_store_int32(sp, (int32_t)value);
500 * Store a uint64 to storage, byte order is controlled by the settings
501 * on the storage, see krb5_storage_set_byteorder().
503 * @param sp the storage to write too
504 * @param value the value to store
506 * @return 0 for success, or a Kerberos 5 error code on failure.
508 * @ingroup krb5_storage
511 KRB5_LIB_FUNCTION krb5_error_code KRB5_LIB_CALL
512 krb5_store_uint64(krb5_storage *sp,
515 return krb5_store_int64(sp, (int64_t)value);
518 static krb5_error_code
519 krb5_ret_int(krb5_storage *sp,
526 *value = 0; /* quiets warnings */
527 if (BYTEORDER_IS_PACKED(sp)) {
528 ret = sp->fetch(sp, v, 1);
532 len = unpack_int_length(v);
536 ret = sp->fetch(sp, v + 1, len - 1);
540 ret = unpack_int(v, len, &w, &len);
546 ret = sp->fetch(sp, v, len);
549 if ((size_t)ret != len)
551 _krb5_get_int64(v, &w, len);
557 * Read a int64 from storage, byte order is controlled by the settings
558 * on the storage, see krb5_storage_set_byteorder().
560 * @param sp the storage to write too
561 * @param value the value read from the buffer
563 * @return 0 for success, or a Kerberos 5 error code on failure.
565 * @ingroup krb5_storage
568 KRB5_LIB_FUNCTION krb5_error_code KRB5_LIB_CALL
569 krb5_ret_int64(krb5_storage *sp,
572 krb5_error_code ret = krb5_ret_int(sp, value, 8);
575 if(BYTEORDER_IS_HOST(sp))
576 #ifdef WORDS_BIGENDIAN
579 *value = bswap64(*value); /* There's no ntohll() */
581 else if(BYTEORDER_IS_LE(sp))
582 *value = bswap64(*value);
587 * Read a uint64 from storage, byte order is controlled by the settings
588 * on the storage, see krb5_storage_set_byteorder().
590 * @param sp the storage to write too
591 * @param value the value read from the buffer
593 * @return 0 for success, or a Kerberos 5 error code on failure.
595 * @ingroup krb5_storage
598 KRB5_LIB_FUNCTION krb5_error_code KRB5_LIB_CALL
599 krb5_ret_uint64(krb5_storage *sp,
605 ret = krb5_ret_int64(sp, &v);
607 *value = (uint64_t)v;
613 * Read a int32 from storage, byte order is controlled by the settings
614 * on the storage, see krb5_storage_set_byteorder().
616 * @param sp the storage to write too
617 * @param value the value read from the buffer
619 * @return 0 for success, or a Kerberos 5 error code on failure.
621 * @ingroup krb5_storage
624 KRB5_LIB_FUNCTION krb5_error_code KRB5_LIB_CALL
625 krb5_ret_int32(krb5_storage *sp,
630 krb5_error_code ret = krb5_ret_int(sp, &v, 4);
634 if (BYTEORDER_IS_HOST(sp))
635 *value = htonl(*value);
636 else if (BYTEORDER_IS_LE(sp))
637 *value = bswap32(*value);
642 * Read a uint32 from storage, byte order is controlled by the settings
643 * on the storage, see krb5_storage_set_byteorder().
645 * @param sp the storage to write too
646 * @param value the value read from the buffer
648 * @return 0 for success, or a Kerberos 5 error code on failure.
650 * @ingroup krb5_storage
653 KRB5_LIB_FUNCTION krb5_error_code KRB5_LIB_CALL
654 krb5_ret_uint32(krb5_storage *sp, uint32_t *value)
659 ret = krb5_ret_int32(sp, &v);
661 *value = (uint32_t)v;
667 * Store a int16 to storage, byte order is controlled by the settings
668 * on the storage, see krb5_storage_set_byteorder().
670 * @param sp the storage to write too
671 * @param value the value to store
673 * @return 0 for success, or a Kerberos 5 error code on failure.
675 * @ingroup krb5_storage
678 KRB5_LIB_FUNCTION krb5_error_code KRB5_LIB_CALL
679 krb5_store_int16(krb5_storage *sp,
682 if(BYTEORDER_IS_HOST(sp))
683 value = htons(value);
684 else if(BYTEORDER_IS_LE(sp))
685 value = bswap16(value);
686 return krb5_store_int(sp, value, 2);
690 * Store a uint16 to storage, byte order is controlled by the settings
691 * on the storage, see krb5_storage_set_byteorder().
693 * @param sp the storage to write too
694 * @param value the value to store
696 * @return 0 for success, or a Kerberos 5 error code on failure.
698 * @ingroup krb5_storage
701 KRB5_LIB_FUNCTION krb5_error_code KRB5_LIB_CALL
702 krb5_store_uint16(krb5_storage *sp,
705 return krb5_store_int16(sp, (int16_t)value);
709 * Read a int16 from storage, byte order is controlled by the settings
710 * on the storage, see krb5_storage_set_byteorder().
712 * @param sp the storage to write too
713 * @param value the value read from the buffer
715 * @return 0 for success, or a Kerberos 5 error code on failure.
717 * @ingroup krb5_storage
720 KRB5_LIB_FUNCTION krb5_error_code KRB5_LIB_CALL
721 krb5_ret_int16(krb5_storage *sp,
726 ret = krb5_ret_int(sp, &v, 2);
730 if(BYTEORDER_IS_HOST(sp))
731 *value = htons(*value);
732 else if(BYTEORDER_IS_LE(sp))
733 *value = bswap16(*value);
738 * Read a int16 from storage, byte order is controlled by the settings
739 * on the storage, see krb5_storage_set_byteorder().
741 * @param sp the storage to write too
742 * @param value the value read from the buffer
744 * @return 0 for success, or a Kerberos 5 error code on failure.
746 * @ingroup krb5_storage
749 KRB5_LIB_FUNCTION krb5_error_code KRB5_LIB_CALL
750 krb5_ret_uint16(krb5_storage *sp,
756 ret = krb5_ret_int16(sp, &v);
758 *value = (uint16_t)v;
764 * Store a int8 to storage.
766 * @param sp the storage to write too
767 * @param value the value to store
769 * @return 0 for success, or a Kerberos 5 error code on failure.
771 * @ingroup krb5_storage
774 KRB5_LIB_FUNCTION krb5_error_code KRB5_LIB_CALL
775 krb5_store_int8(krb5_storage *sp,
780 ret = sp->store(sp, &value, sizeof(value));
781 if (ret != sizeof(value))
782 return (ret<0)?errno:sp->eof_code;
787 * Store a uint8 to storage.
789 * @param sp the storage to write too
790 * @param value the value to store
792 * @return 0 for success, or a Kerberos 5 error code on failure.
794 * @ingroup krb5_storage
797 KRB5_LIB_FUNCTION krb5_error_code KRB5_LIB_CALL
798 krb5_store_uint8(krb5_storage *sp,
801 return krb5_store_int8(sp, (int8_t)value);
805 * Read a int8 from storage
807 * @param sp the storage to write too
808 * @param value the value read from the buffer
810 * @return 0 for success, or a Kerberos 5 error code on failure.
812 * @ingroup krb5_storage
815 KRB5_LIB_FUNCTION krb5_error_code KRB5_LIB_CALL
816 krb5_ret_int8(krb5_storage *sp,
821 ret = sp->fetch(sp, value, sizeof(*value));
822 if (ret != sizeof(*value))
823 return (ret<0)?errno:sp->eof_code;
828 * Read a uint8 from storage
830 * @param sp the storage to write too
831 * @param value the value read from the buffer
833 * @return 0 for success, or a Kerberos 5 error code on failure.
835 * @ingroup krb5_storage
838 KRB5_LIB_FUNCTION krb5_error_code KRB5_LIB_CALL
839 krb5_ret_uint8(krb5_storage *sp,
845 ret = krb5_ret_int8(sp, &v);
853 * Store a data to the storage. The data is stored with an int32 as
854 * lenght plus the data (not padded).
856 * @param sp the storage buffer to write to
857 * @param data the buffer to store.
859 * @return 0 on success, a Kerberos 5 error code on failure.
861 * @ingroup krb5_storage
864 KRB5_LIB_FUNCTION krb5_error_code KRB5_LIB_CALL
865 krb5_store_data(krb5_storage *sp,
869 ret = krb5_store_int32(sp, data.length);
872 ret = sp->store(sp, data.data, data.length);
875 if((size_t)ret != data.length)
881 * Store a data blob to the storage. The data is stored with an int32 as
882 * length plus the data (not padded). This function only differs from
883 * krb5_store_data() insofar as it takes a void * and a length as parameters.
885 * @param sp the storage buffer to write to
886 * @param s the string to store.
887 * @param len length of the string to be stored.
889 * @return 0 on success, a Kerberos 5 error code on failure.
891 * @ingroup krb5_storage
893 KRB5_LIB_FUNCTION krb5_error_code KRB5_LIB_CALL
894 krb5_store_datalen(krb5_storage *sp, const void *d, size_t len)
898 data.data = (void *)d;
899 return krb5_store_data(sp, data);
903 * Store a data blob to the storage. The data is stored without a length.
905 * @param sp the storage buffer to write to
906 * @param s the string to store.
907 * @param len length of the string to be stored.
909 * @return 0 on success, a Kerberos 5 error code on failure.
911 * @ingroup krb5_storage
913 KRB5_LIB_FUNCTION krb5_error_code KRB5_LIB_CALL
914 krb5_store_bytes(krb5_storage *sp, const void *d, size_t len)
918 ssize = krb5_storage_write(sp, d, len);
926 * Parse a data from the storage.
928 * @param sp the storage buffer to read from
929 * @param data the parsed data
931 * @return 0 on success, a Kerberos 5 error code on failure.
933 * @ingroup krb5_storage
936 KRB5_LIB_FUNCTION krb5_error_code KRB5_LIB_CALL
937 krb5_ret_data(krb5_storage *sp,
943 ret = krb5_ret_int32(sp, &size);
946 ret = size_too_large(sp, size);
949 ret = krb5_data_alloc (data, size);
953 ret = sp->fetch(sp, data->data, size);
955 krb5_data_free(data);
956 return (ret < 0)? errno : sp->eof_code;
963 * Store a string to the buffer. The data is formated as an len:uint32
964 * plus the string itself (not padded).
966 * @param sp the storage buffer to write to
967 * @param s the string to store.
969 * @return 0 on success, a Kerberos 5 error code on failure.
971 * @ingroup krb5_storage
974 KRB5_LIB_FUNCTION krb5_error_code KRB5_LIB_CALL
975 krb5_store_string(krb5_storage *sp, const char *s)
978 data.length = strlen(s);
979 data.data = rk_UNCONST(s);
980 return krb5_store_data(sp, data);
984 * Parse a string from the storage.
986 * @param sp the storage buffer to read from
987 * @param string the parsed string
989 * @return 0 on success, a Kerberos 5 error code on failure.
991 * @ingroup krb5_storage
995 KRB5_LIB_FUNCTION krb5_error_code KRB5_LIB_CALL
996 krb5_ret_string(krb5_storage *sp,
1001 ret = krb5_ret_data(sp, &data);
1004 *string = realloc(data.data, data.length + 1);
1005 if(*string == NULL){
1009 (*string)[data.length] = 0;
1014 * Store a zero terminated string to the buffer. The data is stored
1015 * one character at a time until a NUL is stored.
1017 * @param sp the storage buffer to write to
1018 * @param s the string to store.
1020 * @return 0 on success, a Kerberos 5 error code on failure.
1022 * @ingroup krb5_storage
1025 KRB5_LIB_FUNCTION krb5_error_code KRB5_LIB_CALL
1026 krb5_store_stringz(krb5_storage *sp, const char *s)
1028 size_t len = strlen(s) + 1;
1031 ret = sp->store(sp, s, len);
1034 if((size_t)ret != len)
1035 return sp->eof_code;
1040 * Parse zero terminated string from the storage.
1042 * @param sp the storage buffer to read from
1043 * @param string the parsed string
1045 * @return 0 on success, a Kerberos 5 error code on failure.
1047 * @ingroup krb5_storage
1050 KRB5_LIB_FUNCTION krb5_error_code KRB5_LIB_CALL
1051 krb5_ret_stringz(krb5_storage *sp,
1059 while((ret = sp->fetch(sp, &c, 1)) == 1){
1060 krb5_error_code eret;
1064 eret = size_too_large(sp, len);
1069 tmp = realloc (s, len);
1082 return sp->eof_code;
1089 KRB5_LIB_FUNCTION krb5_error_code KRB5_LIB_CALL
1090 krb5_store_stringnl(krb5_storage *sp, const char *s)
1092 size_t len = strlen(s);
1095 ret = sp->store(sp, s, len);
1098 if((size_t)ret != len)
1099 return sp->eof_code;
1100 ret = sp->store(sp, "\n", 1);
1105 return sp->eof_code;
1112 KRB5_LIB_FUNCTION krb5_error_code KRB5_LIB_CALL
1113 krb5_ret_stringnl(krb5_storage *sp,
1122 while((ret = sp->fetch(sp, &c, 1)) == 1){
1123 krb5_error_code eret;
1130 if (expect_nl && c != '\n') {
1132 return KRB5_BADMSGTYPE;
1136 eret = size_too_large(sp, len);
1141 tmp = realloc (s, len);
1156 return sp->eof_code;
1164 * Write a principal block to storage.
1166 * @param sp the storage buffer to write to
1167 * @param p the principal block to write.
1169 * @return 0 on success, a Kerberos 5 error code on failure.
1171 * @ingroup krb5_storage
1174 KRB5_LIB_FUNCTION krb5_error_code KRB5_LIB_CALL
1175 krb5_store_principal(krb5_storage *sp,
1176 krb5_const_principal p)
1181 if(!krb5_storage_is_flags(sp, KRB5_STORAGE_PRINCIPAL_NO_NAME_TYPE)) {
1182 ret = krb5_store_int32(sp, p->name.name_type);
1185 if(krb5_storage_is_flags(sp, KRB5_STORAGE_PRINCIPAL_WRONG_NUM_COMPONENTS))
1186 ret = krb5_store_int32(sp, p->name.name_string.len + 1);
1188 ret = krb5_store_int32(sp, p->name.name_string.len);
1191 ret = krb5_store_string(sp, p->realm);
1193 for(i = 0; i < p->name.name_string.len; i++){
1194 ret = krb5_store_string(sp, p->name.name_string.val[i]);
1201 * Parse principal from the storage.
1203 * @param sp the storage buffer to read from
1204 * @param princ the parsed principal
1206 * @return 0 on success, a Kerberos 5 error code on failure.
1208 * @ingroup krb5_storage
1211 KRB5_LIB_FUNCTION krb5_error_code KRB5_LIB_CALL
1212 krb5_ret_principal(krb5_storage *sp,
1213 krb5_principal *princ)
1221 p = calloc(1, sizeof(*p));
1225 if(krb5_storage_is_flags(sp, KRB5_STORAGE_PRINCIPAL_NO_NAME_TYPE))
1226 type = KRB5_NT_UNKNOWN;
1227 else if((ret = krb5_ret_int32(sp, &type))){
1231 if((ret = krb5_ret_int32(sp, &ncomp))){
1235 if(krb5_storage_is_flags(sp, KRB5_STORAGE_PRINCIPAL_WRONG_NUM_COMPONENTS))
1241 ret = size_too_large_num(sp, ncomp, sizeof(p->name.name_string.val[0]));
1246 p->name.name_type = type;
1247 p->name.name_string.len = ncomp;
1248 ret = krb5_ret_string(sp, &p->realm);
1253 p->name.name_string.val = calloc(ncomp, sizeof(p->name.name_string.val[0]));
1254 if(p->name.name_string.val == NULL && ncomp != 0){
1259 for(i = 0; i < ncomp; i++){
1260 ret = krb5_ret_string(sp, &p->name.name_string.val[i]);
1263 free(p->name.name_string.val[i--]);
1274 * Store a keyblock to the storage.
1276 * @param sp the storage buffer to write to
1277 * @param p the keyblock to write
1279 * @return 0 on success, a Kerberos 5 error code on failure.
1281 * @ingroup krb5_storage
1284 KRB5_LIB_FUNCTION krb5_error_code KRB5_LIB_CALL
1285 krb5_store_keyblock(krb5_storage *sp, krb5_keyblock p)
1288 ret = krb5_store_int16(sp, p.keytype);
1291 if(krb5_storage_is_flags(sp, KRB5_STORAGE_KEYBLOCK_KEYTYPE_TWICE)){
1292 /* this should really be enctype, but it is the same as
1294 ret = krb5_store_int16(sp, p.keytype);
1298 ret = krb5_store_data(sp, p.keyvalue);
1303 * Read a keyblock from the storage.
1305 * @param sp the storage buffer to write to
1306 * @param p the keyblock read from storage, free using krb5_free_keyblock()
1308 * @return 0 on success, a Kerberos 5 error code on failure.
1310 * @ingroup krb5_storage
1313 KRB5_LIB_FUNCTION krb5_error_code KRB5_LIB_CALL
1314 krb5_ret_keyblock(krb5_storage *sp, krb5_keyblock *p)
1319 ret = krb5_ret_int16(sp, &tmp);
1323 if(krb5_storage_is_flags(sp, KRB5_STORAGE_KEYBLOCK_KEYTYPE_TWICE)){
1324 ret = krb5_ret_int16(sp, &tmp);
1328 ret = krb5_ret_data(sp, &p->keyvalue);
1333 * Write a times block to storage.
1335 * @param sp the storage buffer to write to
1336 * @param times the times block to write.
1338 * @return 0 on success, a Kerberos 5 error code on failure.
1340 * @ingroup krb5_storage
1343 KRB5_LIB_FUNCTION krb5_error_code KRB5_LIB_CALL
1344 krb5_store_times(krb5_storage *sp, krb5_times times)
1347 ret = krb5_store_int32(sp, times.authtime);
1349 ret = krb5_store_int32(sp, times.starttime);
1351 ret = krb5_store_int32(sp, times.endtime);
1353 ret = krb5_store_int32(sp, times.renew_till);
1358 * Read a times block from the storage.
1360 * @param sp the storage buffer to write to
1361 * @param times the times block read from storage
1363 * @return 0 on success, a Kerberos 5 error code on failure.
1365 * @ingroup krb5_storage
1368 KRB5_LIB_FUNCTION krb5_error_code KRB5_LIB_CALL
1369 krb5_ret_times(krb5_storage *sp, krb5_times *times)
1373 ret = krb5_ret_int32(sp, &tmp);
1374 times->authtime = tmp;
1376 ret = krb5_ret_int32(sp, &tmp);
1377 times->starttime = tmp;
1379 ret = krb5_ret_int32(sp, &tmp);
1380 times->endtime = tmp;
1382 ret = krb5_ret_int32(sp, &tmp);
1383 times->renew_till = tmp;
1388 * Write a address block to storage.
1390 * @param sp the storage buffer to write to
1391 * @param p the address block to write.
1393 * @return 0 on success, a Kerberos 5 error code on failure.
1395 * @ingroup krb5_storage
1398 KRB5_LIB_FUNCTION krb5_error_code KRB5_LIB_CALL
1399 krb5_store_address(krb5_storage *sp, krb5_address p)
1402 ret = krb5_store_int16(sp, p.addr_type);
1404 ret = krb5_store_data(sp, p.address);
1409 * Read a address block from the storage.
1411 * @param sp the storage buffer to write to
1412 * @param adr the address block read from storage
1414 * @return 0 on success, a Kerberos 5 error code on failure.
1416 * @ingroup krb5_storage
1419 KRB5_LIB_FUNCTION krb5_error_code KRB5_LIB_CALL
1420 krb5_ret_address(krb5_storage *sp, krb5_address *adr)
1424 ret = krb5_ret_int16(sp, &t);
1427 ret = krb5_ret_data(sp, &adr->address);
1432 * Write a addresses block to storage.
1434 * @param sp the storage buffer to write to
1435 * @param p the addresses block to write.
1437 * @return 0 on success, a Kerberos 5 error code on failure.
1439 * @ingroup krb5_storage
1442 KRB5_LIB_FUNCTION krb5_error_code KRB5_LIB_CALL
1443 krb5_store_addrs(krb5_storage *sp, krb5_addresses p)
1447 ret = krb5_store_int32(sp, p.len);
1449 for(i = 0; i<p.len; i++){
1450 ret = krb5_store_address(sp, p.val[i]);
1457 * Read a addresses block from the storage.
1459 * @param sp the storage buffer to write to
1460 * @param adr the addresses block read from storage
1462 * @return 0 on success, a Kerberos 5 error code on failure.
1464 * @ingroup krb5_storage
1467 KRB5_LIB_FUNCTION krb5_error_code KRB5_LIB_CALL
1468 krb5_ret_addrs(krb5_storage *sp, krb5_addresses *adr)
1474 ret = krb5_ret_int32(sp, &tmp);
1476 ret = size_too_large_num(sp, tmp, sizeof(adr->val[0]));
1477 if (ret) return ret;
1479 ALLOC(adr->val, adr->len);
1480 if (adr->val == NULL && adr->len != 0)
1482 for(i = 0; i < adr->len; i++){
1483 ret = krb5_ret_address(sp, &adr->val[i]);
1490 * Write a auth data block to storage.
1492 * @param sp the storage buffer to write to
1493 * @param auth the auth data block to write.
1495 * @return 0 on success, a Kerberos 5 error code on failure.
1497 * @ingroup krb5_storage
1500 KRB5_LIB_FUNCTION krb5_error_code KRB5_LIB_CALL
1501 krb5_store_authdata(krb5_storage *sp, krb5_authdata auth)
1503 krb5_error_code ret;
1505 ret = krb5_store_int32(sp, auth.len);
1507 for(i = 0; i < auth.len; i++){
1508 ret = krb5_store_int16(sp, auth.val[i].ad_type);
1510 ret = krb5_store_data(sp, auth.val[i].ad_data);
1517 * Read a auth data from the storage.
1519 * @param sp the storage buffer to write to
1520 * @param auth the auth data block read from storage
1522 * @return 0 on success, a Kerberos 5 error code on failure.
1524 * @ingroup krb5_storage
1527 KRB5_LIB_FUNCTION krb5_error_code KRB5_LIB_CALL
1528 krb5_ret_authdata(krb5_storage *sp, krb5_authdata *auth)
1530 krb5_error_code ret;
1534 ret = krb5_ret_int32(sp, &tmp);
1536 ret = size_too_large_num(sp, tmp, sizeof(auth->val[0]));
1537 if (ret) return ret;
1538 ALLOC_SEQ(auth, tmp);
1539 if (auth->val == NULL && tmp != 0)
1541 for(i = 0; i < tmp; i++){
1542 ret = krb5_ret_int16(sp, &tmp2);
1544 auth->val[i].ad_type = tmp2;
1545 ret = krb5_ret_data(sp, &auth->val[i].ad_data);
1552 bitswap32(int32_t b)
1556 for (i = 0; i < 32; i++) {
1557 r = r << 1 | (b & 1);
1564 * Write a credentials block to storage.
1566 * @param sp the storage buffer to write to
1567 * @param creds the creds block to write.
1569 * @return 0 on success, a Kerberos 5 error code on failure.
1571 * @ingroup krb5_storage
1574 KRB5_LIB_FUNCTION krb5_error_code KRB5_LIB_CALL
1575 krb5_store_creds(krb5_storage *sp, krb5_creds *creds)
1579 ret = krb5_store_principal(sp, creds->client);
1582 ret = krb5_store_principal(sp, creds->server);
1585 ret = krb5_store_keyblock(sp, creds->session);
1588 ret = krb5_store_times(sp, creds->times);
1591 ret = krb5_store_int8(sp, creds->second_ticket.length != 0); /* is_skey */
1594 ret = krb5_store_int32(sp, bitswap32(TicketFlags2int(creds->flags.b)));
1597 ret = krb5_store_addrs(sp, creds->addresses);
1600 ret = krb5_store_authdata(sp, creds->authdata);
1603 ret = krb5_store_data(sp, creds->ticket);
1606 ret = krb5_store_data(sp, creds->second_ticket);
1611 * Read a credentials block from the storage.
1613 * @param sp the storage buffer to write to
1614 * @param creds the credentials block read from storage
1616 * @return 0 on success, a Kerberos 5 error code on failure.
1618 * @ingroup krb5_storage
1621 KRB5_LIB_FUNCTION krb5_error_code KRB5_LIB_CALL
1622 krb5_ret_creds(krb5_storage *sp, krb5_creds *creds)
1624 krb5_error_code ret;
1628 memset(creds, 0, sizeof(*creds));
1629 ret = krb5_ret_principal (sp, &creds->client);
1630 if(ret) goto cleanup;
1631 ret = krb5_ret_principal (sp, &creds->server);
1632 if(ret) goto cleanup;
1633 ret = krb5_ret_keyblock (sp, &creds->session);
1634 if(ret) goto cleanup;
1635 ret = krb5_ret_times (sp, &creds->times);
1636 if(ret) goto cleanup;
1637 ret = krb5_ret_int8 (sp, &dummy8);
1638 if(ret) goto cleanup;
1639 ret = krb5_ret_int32 (sp, &dummy32);
1640 if(ret) goto cleanup;
1641 creds->flags.b = int2TicketFlags(bitswap32(dummy32));
1642 ret = krb5_ret_addrs (sp, &creds->addresses);
1643 if(ret) goto cleanup;
1644 ret = krb5_ret_authdata (sp, &creds->authdata);
1645 if(ret) goto cleanup;
1646 ret = krb5_ret_data (sp, &creds->ticket);
1647 if(ret) goto cleanup;
1648 ret = krb5_ret_data (sp, &creds->second_ticket);
1652 krb5_free_cred_contents(context, creds); /* XXX */
1658 #define SC_CLIENT_PRINCIPAL 0x0001
1659 #define SC_SERVER_PRINCIPAL 0x0002
1660 #define SC_SESSION_KEY 0x0004
1661 #define SC_TICKET 0x0008
1662 #define SC_SECOND_TICKET 0x0010
1663 #define SC_AUTHDATA 0x0020
1664 #define SC_ADDRESSES 0x0040
1667 * Write a tagged credentials block to storage.
1669 * @param sp the storage buffer to write to
1670 * @param creds the creds block to write.
1672 * @return 0 on success, a Kerberos 5 error code on failure.
1674 * @ingroup krb5_storage
1677 KRB5_LIB_FUNCTION krb5_error_code KRB5_LIB_CALL
1678 krb5_store_creds_tag(krb5_storage *sp, krb5_creds *creds)
1684 header |= SC_CLIENT_PRINCIPAL;
1686 header |= SC_SERVER_PRINCIPAL;
1687 if (creds->session.keytype != ETYPE_NULL)
1688 header |= SC_SESSION_KEY;
1689 if (creds->ticket.data)
1690 header |= SC_TICKET;
1691 if (creds->second_ticket.length)
1692 header |= SC_SECOND_TICKET;
1693 if (creds->authdata.len)
1694 header |= SC_AUTHDATA;
1695 if (creds->addresses.len)
1696 header |= SC_ADDRESSES;
1698 ret = krb5_store_int32(sp, header);
1702 if (creds->client) {
1703 ret = krb5_store_principal(sp, creds->client);
1708 if (creds->server) {
1709 ret = krb5_store_principal(sp, creds->server);
1714 if (creds->session.keytype != ETYPE_NULL) {
1715 ret = krb5_store_keyblock(sp, creds->session);
1720 ret = krb5_store_times(sp, creds->times);
1723 ret = krb5_store_int8(sp, creds->second_ticket.length != 0); /* is_skey */
1727 ret = krb5_store_int32(sp, bitswap32(TicketFlags2int(creds->flags.b)));
1731 if (creds->addresses.len) {
1732 ret = krb5_store_addrs(sp, creds->addresses);
1737 if (creds->authdata.len) {
1738 ret = krb5_store_authdata(sp, creds->authdata);
1743 if (creds->ticket.data) {
1744 ret = krb5_store_data(sp, creds->ticket);
1749 if (creds->second_ticket.data) {
1750 ret = krb5_store_data(sp, creds->second_ticket);
1759 * Read a tagged credentials block from the storage.
1761 * @param sp the storage buffer to write to
1762 * @param creds the credentials block read from storage
1764 * @return 0 on success, a Kerberos 5 error code on failure.
1766 * @ingroup krb5_storage
1769 KRB5_LIB_FUNCTION krb5_error_code KRB5_LIB_CALL
1770 krb5_ret_creds_tag(krb5_storage *sp,
1773 krb5_error_code ret;
1775 int32_t dummy32, header;
1777 memset(creds, 0, sizeof(*creds));
1779 ret = krb5_ret_int32 (sp, &header);
1780 if (ret) goto cleanup;
1782 if (header & SC_CLIENT_PRINCIPAL) {
1783 ret = krb5_ret_principal (sp, &creds->client);
1784 if(ret) goto cleanup;
1786 if (header & SC_SERVER_PRINCIPAL) {
1787 ret = krb5_ret_principal (sp, &creds->server);
1788 if(ret) goto cleanup;
1790 if (header & SC_SESSION_KEY) {
1791 ret = krb5_ret_keyblock (sp, &creds->session);
1792 if(ret) goto cleanup;
1794 ret = krb5_ret_times (sp, &creds->times);
1795 if(ret) goto cleanup;
1796 ret = krb5_ret_int8 (sp, &dummy8);
1797 if(ret) goto cleanup;
1798 ret = krb5_ret_int32 (sp, &dummy32);
1799 if(ret) goto cleanup;
1800 creds->flags.b = int2TicketFlags(bitswap32(dummy32));
1801 if (header & SC_ADDRESSES) {
1802 ret = krb5_ret_addrs (sp, &creds->addresses);
1803 if(ret) goto cleanup;
1805 if (header & SC_AUTHDATA) {
1806 ret = krb5_ret_authdata (sp, &creds->authdata);
1807 if(ret) goto cleanup;
1809 if (header & SC_TICKET) {
1810 ret = krb5_ret_data (sp, &creds->ticket);
1811 if(ret) goto cleanup;
1813 if (header & SC_SECOND_TICKET) {
1814 ret = krb5_ret_data (sp, &creds->second_ticket);
1815 if(ret) goto cleanup;
1821 krb5_free_cred_contents(context, creds); /* XXX */
1827 KRB5_LIB_FUNCTION krb5_error_code KRB5_LIB_CALL
1828 _krb5_ret_data_at_offset(krb5_storage *sp,
1833 krb5_error_code ret;
1836 krb5_data_zero(data);
1838 cur = sp->seek(sp, 0, SEEK_CUR);
1840 return HEIM_ERR_NOT_SEEKABLE;
1842 size = sp->seek(sp, 0, SEEK_END);
1843 if (offset + length > size) {
1848 ret = krb5_data_alloc(data, length);
1853 sp->seek(sp, offset, SEEK_SET);
1855 size = sp->fetch(sp, data->data, length);
1856 heim_assert(size == length, "incomplete buffer fetched");
1860 sp->seek(sp, cur, SEEK_SET);
1865 KRB5_LIB_FUNCTION krb5_error_code KRB5_LIB_CALL
1866 _krb5_ret_utf8_from_ucs2le_at_offset(krb5_storage *sp,
1871 krb5_error_code ret;
1873 size_t ucs2len = length / 2;
1874 uint16_t *ucs2 = NULL;
1876 unsigned int flags = WIND_RW_LE;
1880 krb5_data_zero(&data);
1882 ret = _krb5_ret_data_at_offset(sp, offset, length, &data);
1886 ucs2 = malloc(sizeof(ucs2[0]) * ucs2len);
1892 ret = wind_ucs2read(data.data, data.length, &flags, ucs2, &ucs2len);
1896 ret = wind_ucs2utf8_length(ucs2, ucs2len, &u8len);
1900 u8len += 1; /* Add space for NUL */
1902 *utf8 = malloc(u8len);
1903 if (*utf8 == NULL) {
1908 ret = wind_ucs2utf8(ucs2, ucs2len, *utf8, &u8len);
1918 krb5_data_free(&data);
1923 KRB5_LIB_FUNCTION krb5_error_code KRB5_LIB_CALL
1924 _krb5_store_data_at_offset(krb5_storage *sp,
1926 const krb5_data *data)
1928 krb5_error_code ret;
1929 krb5_ssize_t nbytes;
1932 if (offset == (off_t)-1) {
1933 if (data == NULL || data->data == NULL) {
1936 pos = sp->seek(sp, 0, SEEK_CUR);
1937 offset = sp->seek(sp, 0, SEEK_END);
1938 sp->seek(sp, pos, SEEK_SET);
1940 if (offset == (off_t)-1)
1941 return HEIM_ERR_NOT_SEEKABLE;
1945 if (offset > 0xFFFF)
1947 else if ((offset != 0) != (data && data->data))
1949 else if (data && data->length > 0xFFFF)
1952 ret = krb5_store_uint16(sp, data ? (uint16_t)data->length : 0);
1954 ret = krb5_store_uint16(sp, (uint16_t)offset);
1955 if (ret == 0 && offset) {
1956 pos = sp->seek(sp, 0, SEEK_CUR);
1957 sp->seek(sp, offset, SEEK_SET);
1958 nbytes = krb5_storage_write(sp, data->data, data->length);
1959 if ((size_t)nbytes != data->length)
1961 sp->seek(sp, pos, SEEK_SET);
1967 KRB5_LIB_FUNCTION krb5_error_code KRB5_LIB_CALL
1968 _krb5_store_utf8_as_ucs2le_at_offset(krb5_storage *sp,
1972 krb5_error_code ret;
1973 size_t ucs2_len, ucs2le_size;
1974 uint16_t *ucs2, *ucs2le;
1978 ret = wind_utf8ucs2_length(utf8, &ucs2_len);
1982 ucs2 = malloc(sizeof(ucs2[0]) * ucs2_len);
1986 ret = wind_utf8ucs2(utf8, ucs2, &ucs2_len);
1992 ucs2le_size = (ucs2_len + 1) * 2;
1993 ucs2le = malloc(ucs2le_size);
1994 if (ucs2le == NULL) {
2000 ret = wind_ucs2write(ucs2, ucs2_len, &flags, ucs2le, &ucs2le_size);
2007 ucs2le_size = ucs2_len * 2;
2019 data.length = ucs2le_size;
2021 ret = _krb5_store_data_at_offset(sp, offset, &data);