Merge pull request #203 from sdigit/patch-1
[heimdal.git] / lib / krb5 / store.c
blob9917d64a9c685d9c811b8c80cebd5089fc46063e
1 /*
2 * Copyright (c) 1997-2008 Kungliga Tekniska Högskolan
3 * (Royal Institute of Technology, Stockholm, Sweden).
4 * All rights reserved.
6 * Redistribution and use in source and binary forms, with or without
7 * modification, are permitted provided that the following conditions
8 * are met:
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
31 * SUCH DAMAGE.
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))
43 /**
44 * Add the flags on a storage buffer by or-ing in the flags to the buffer.
46 * @param sp the storage buffer to set the flags on
47 * @param flags the flags to set
49 * @ingroup krb5_storage
52 KRB5_LIB_FUNCTION void KRB5_LIB_CALL
53 krb5_storage_set_flags(krb5_storage *sp, krb5_flags flags)
55 sp->flags |= flags;
58 /**
59 * Clear the flags on a storage buffer
61 * @param sp the storage buffer to clear the flags on
62 * @param flags the flags to clear
64 * @ingroup krb5_storage
67 KRB5_LIB_FUNCTION void KRB5_LIB_CALL
68 krb5_storage_clear_flags(krb5_storage *sp, krb5_flags flags)
70 sp->flags &= ~flags;
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.
77 * @param sp the storage buffer to check flags on
78 * @param flags The flags to test for
80 * @return true if all the flags are set, false if not.
82 * @ingroup krb5_storage
85 KRB5_LIB_FUNCTION krb5_boolean KRB5_LIB_CALL
86 krb5_storage_is_flags(krb5_storage *sp, krb5_flags flags)
88 return (sp->flags & flags) == flags;
91 /**
92 * Set the new byte order of the storage buffer.
94 * @param sp the storage buffer to set the byte order for.
95 * @param byteorder the new byte order.
97 * The byte order are: KRB5_STORAGE_BYTEORDER_BE,
98 * KRB5_STORAGE_BYTEORDER_LE and KRB5_STORAGE_BYTEORDER_HOST.
100 * @ingroup krb5_storage
103 KRB5_LIB_FUNCTION void KRB5_LIB_CALL
104 krb5_storage_set_byteorder(krb5_storage *sp, krb5_flags byteorder)
106 sp->flags &= ~KRB5_STORAGE_BYTEORDER_MASK;
107 sp->flags |= byteorder;
111 * Return the current byteorder for the buffer. See krb5_storage_set_byteorder() for the list or byte order contants.
113 * @ingroup krb5_storage
116 KRB5_LIB_FUNCTION krb5_flags KRB5_LIB_CALL
117 krb5_storage_get_byteorder(krb5_storage *sp)
119 return sp->flags & KRB5_STORAGE_BYTEORDER_MASK;
123 * Set the max alloc value
125 * @param sp the storage buffer set the max allow for
126 * @param size maximum size to allocate, use 0 to remove limit
128 * @ingroup krb5_storage
131 KRB5_LIB_FUNCTION void KRB5_LIB_CALL
132 krb5_storage_set_max_alloc(krb5_storage *sp, size_t size)
134 sp->max_alloc = size;
137 /* don't allocate unresonable amount of memory */
138 static krb5_error_code
139 size_too_large(krb5_storage *sp, size_t size)
141 if (sp->max_alloc && sp->max_alloc < size)
142 return HEIM_ERR_TOO_BIG;
143 return 0;
146 static krb5_error_code
147 size_too_large_num(krb5_storage *sp, size_t count, size_t size)
149 if (sp->max_alloc == 0 || size == 0)
150 return 0;
151 size = sp->max_alloc / size;
152 if (size < count)
153 return HEIM_ERR_TOO_BIG;
154 return 0;
158 * Seek to a new offset.
160 * @param sp the storage buffer to seek in.
161 * @param offset the offset to seek
162 * @param whence relateive searching, SEEK_CUR from the current
163 * position, SEEK_END from the end, SEEK_SET absolute from the start.
165 * @return The new current offset
167 * @ingroup krb5_storage
170 KRB5_LIB_FUNCTION off_t KRB5_LIB_CALL
171 krb5_storage_seek(krb5_storage *sp, off_t offset, int whence)
173 return (*sp->seek)(sp, offset, whence);
177 * Truncate the storage buffer in sp to offset.
179 * @param sp the storage buffer to truncate.
180 * @param offset the offset to truncate too.
182 * @return An Kerberos 5 error code.
184 * @ingroup krb5_storage
187 KRB5_LIB_FUNCTION int KRB5_LIB_CALL
188 krb5_storage_truncate(krb5_storage *sp, off_t offset)
190 return (*sp->trunc)(sp, offset);
194 * Sync the storage buffer to its backing store. If there is no
195 * backing store this function will return success.
197 * @param sp the storage buffer to sync
199 * @return A Kerberos 5 error code
201 * @ingroup krb5_storage
204 KRB5_LIB_FUNCTION int KRB5_LIB_CALL
205 krb5_storage_fsync(krb5_storage *sp)
207 if (sp->fsync != NULL)
208 return sp->fsync(sp);
209 return 0;
213 * Read to the storage buffer.
215 * @param sp the storage buffer to read from
216 * @param buf the buffer to store the data in
217 * @param len the length to read
219 * @return The length of data read (can be shorter then len), or negative on error.
221 * @ingroup krb5_storage
224 KRB5_LIB_FUNCTION krb5_ssize_t KRB5_LIB_CALL
225 krb5_storage_read(krb5_storage *sp, void *buf, size_t len)
227 return sp->fetch(sp, buf, len);
231 * Write to the storage buffer.
233 * @param sp the storage buffer to write to
234 * @param buf the buffer to write to the storage buffer
235 * @param len the length to write
237 * @return The length of data written (can be shorter then len), or negative on error.
239 * @ingroup krb5_storage
242 KRB5_LIB_FUNCTION krb5_ssize_t KRB5_LIB_CALL
243 krb5_storage_write(krb5_storage *sp, const void *buf, size_t len)
245 return sp->store(sp, buf, len);
249 * Set the return code that will be used when end of storage is reached.
251 * @param sp the storage
252 * @param code the error code to return on end of storage
254 * @ingroup krb5_storage
257 KRB5_LIB_FUNCTION void KRB5_LIB_CALL
258 krb5_storage_set_eof_code(krb5_storage *sp, int code)
260 sp->eof_code = code;
264 * Get the return code that will be used when end of storage is reached.
266 * @param sp the storage
268 * @return storage error code
270 * @ingroup krb5_storage
273 KRB5_LIB_FUNCTION int KRB5_LIB_CALL
274 krb5_storage_get_eof_code(krb5_storage *sp)
276 return sp->eof_code;
280 * Free a krb5 storage.
282 * @param sp the storage to free.
284 * @return An Kerberos 5 error code.
286 * @ingroup krb5_storage
289 KRB5_LIB_FUNCTION krb5_error_code KRB5_LIB_CALL
290 krb5_storage_free(krb5_storage *sp)
292 if (sp == NULL)
293 return 0;
294 if(sp->free)
295 (*sp->free)(sp);
296 free(sp->data);
297 free(sp);
298 return 0;
302 * Copy the contnent of storage
304 * @param sp the storage to copy to a data
305 * @param data the copied data, free with krb5_data_free()
307 * @return 0 for success, or a Kerberos 5 error code on failure.
309 * @ingroup krb5_storage
312 KRB5_LIB_FUNCTION krb5_error_code KRB5_LIB_CALL
313 krb5_storage_to_data(krb5_storage *sp, krb5_data *data)
315 off_t pos, size;
316 krb5_error_code ret;
318 pos = sp->seek(sp, 0, SEEK_CUR);
319 if (pos < 0)
320 return HEIM_ERR_NOT_SEEKABLE;
321 size = sp->seek(sp, 0, SEEK_END);
322 ret = size_too_large(sp, size);
323 if (ret)
324 return ret;
325 ret = krb5_data_alloc(data, size);
326 if (ret) {
327 sp->seek(sp, pos, SEEK_SET);
328 return ret;
330 if (size) {
331 sp->seek(sp, 0, SEEK_SET);
332 sp->fetch(sp, data->data, data->length);
333 sp->seek(sp, pos, SEEK_SET);
335 return 0;
338 static krb5_error_code
339 krb5_store_int(krb5_storage *sp,
340 int64_t value,
341 size_t len)
343 int ret;
344 unsigned char v[8];
346 if (len > sizeof(v))
347 return EINVAL;
348 _krb5_put_int(v, value, len);
349 ret = sp->store(sp, v, len);
350 if (ret < 0)
351 return errno;
352 if ((size_t)ret != len)
353 return sp->eof_code;
354 return 0;
358 * Store a int32 to storage, byte order is controlled by the settings
359 * on the storage, see krb5_storage_set_byteorder().
361 * @param sp the storage to write too
362 * @param value the value to store
364 * @return 0 for success, or a Kerberos 5 error code on failure.
366 * @ingroup krb5_storage
369 KRB5_LIB_FUNCTION krb5_error_code KRB5_LIB_CALL
370 krb5_store_int32(krb5_storage *sp,
371 int32_t value)
373 if(BYTEORDER_IS_HOST(sp))
374 value = htonl(value);
375 else if(BYTEORDER_IS_LE(sp))
376 value = bswap32(value);
377 return krb5_store_int(sp, value, 4);
381 * Store a int64 to storage, byte order is controlled by the settings
382 * on the storage, see krb5_storage_set_byteorder().
384 * @param sp the storage to write too
385 * @param value the value to store
387 * @return 0 for success, or a Kerberos 5 error code on failure.
389 * @ingroup krb5_storage
392 KRB5_LIB_FUNCTION krb5_error_code KRB5_LIB_CALL
393 krb5_store_int64(krb5_storage *sp,
394 int64_t value)
396 if (BYTEORDER_IS_HOST(sp))
397 #ifdef WORDS_BIGENDIAN
399 #else
400 value = bswap64(value); /* There's no ntohll() */
401 #endif
402 else if (BYTEORDER_IS_LE(sp))
403 value = bswap64(value);
404 return krb5_store_int(sp, value, 8);
408 * Store a uint32 to storage, byte order is controlled by the settings
409 * on the storage, see krb5_storage_set_byteorder().
411 * @param sp the storage to write too
412 * @param value the value to store
414 * @return 0 for success, or a Kerberos 5 error code on failure.
416 * @ingroup krb5_storage
419 KRB5_LIB_FUNCTION krb5_error_code KRB5_LIB_CALL
420 krb5_store_uint32(krb5_storage *sp,
421 uint32_t value)
423 return krb5_store_int32(sp, (int32_t)value);
427 * Store a uint64 to storage, byte order is controlled by the settings
428 * on the storage, see krb5_storage_set_byteorder().
430 * @param sp the storage to write too
431 * @param value the value to store
433 * @return 0 for success, or a Kerberos 5 error code on failure.
435 * @ingroup krb5_storage
438 KRB5_LIB_FUNCTION krb5_error_code KRB5_LIB_CALL
439 krb5_store_uint64(krb5_storage *sp,
440 uint64_t value)
442 return krb5_store_int64(sp, (int64_t)value);
445 static krb5_error_code
446 krb5_ret_int(krb5_storage *sp,
447 int64_t *value,
448 size_t len)
450 int ret;
451 unsigned char v[8];
452 uint64_t w;
453 ret = sp->fetch(sp, v, len);
454 if (ret < 0)
455 return errno;
456 if ((size_t)ret != len)
457 return sp->eof_code;
458 _krb5_get_int64(v, &w, len);
459 *value = w;
460 return 0;
464 * Read a int64 from storage, byte order is controlled by the settings
465 * on the storage, see krb5_storage_set_byteorder().
467 * @param sp the storage to write too
468 * @param value the value read from the buffer
470 * @return 0 for success, or a Kerberos 5 error code on failure.
472 * @ingroup krb5_storage
475 KRB5_LIB_FUNCTION krb5_error_code KRB5_LIB_CALL
476 krb5_ret_int64(krb5_storage *sp,
477 int64_t *value)
479 krb5_error_code ret = krb5_ret_int(sp, value, 8);
480 if(ret)
481 return ret;
482 if(BYTEORDER_IS_HOST(sp))
483 #ifdef WORDS_BIGENDIAN
485 #else
486 *value = bswap64(*value); /* There's no ntohll() */
487 #endif
488 else if(BYTEORDER_IS_LE(sp))
489 *value = bswap64(*value);
490 return 0;
494 * Read a uint64 from storage, byte order is controlled by the settings
495 * on the storage, see krb5_storage_set_byteorder().
497 * @param sp the storage to write too
498 * @param value the value read from the buffer
500 * @return 0 for success, or a Kerberos 5 error code on failure.
502 * @ingroup krb5_storage
505 KRB5_LIB_FUNCTION krb5_error_code KRB5_LIB_CALL
506 krb5_ret_uint64(krb5_storage *sp,
507 uint64_t *value)
509 krb5_error_code ret;
510 int64_t v;
512 ret = krb5_ret_int64(sp, &v);
513 if (ret == 0)
514 *value = (uint64_t)v;
516 return ret;
520 * Read a int32 from storage, byte order is controlled by the settings
521 * on the storage, see krb5_storage_set_byteorder().
523 * @param sp the storage to write too
524 * @param value the value read from the buffer
526 * @return 0 for success, or a Kerberos 5 error code on failure.
528 * @ingroup krb5_storage
531 KRB5_LIB_FUNCTION krb5_error_code KRB5_LIB_CALL
532 krb5_ret_int32(krb5_storage *sp,
533 int32_t *value)
535 int64_t v;
537 krb5_error_code ret = krb5_ret_int(sp, &v, 4);
538 if (ret)
539 return ret;
540 *value = v;
541 if (BYTEORDER_IS_HOST(sp))
542 *value = htonl(*value);
543 else if (BYTEORDER_IS_LE(sp))
544 *value = bswap32(*value);
545 return 0;
549 * Read a uint32 from storage, byte order is controlled by the settings
550 * on the storage, see krb5_storage_set_byteorder().
552 * @param sp the storage to write too
553 * @param value the value read from the buffer
555 * @return 0 for success, or a Kerberos 5 error code on failure.
557 * @ingroup krb5_storage
560 KRB5_LIB_FUNCTION krb5_error_code KRB5_LIB_CALL
561 krb5_ret_uint32(krb5_storage *sp, uint32_t *value)
563 krb5_error_code ret;
564 int32_t v;
566 ret = krb5_ret_int32(sp, &v);
567 if (ret == 0)
568 *value = (uint32_t)v;
570 return ret;
574 * Store a int16 to storage, byte order is controlled by the settings
575 * on the storage, see krb5_storage_set_byteorder().
577 * @param sp the storage to write too
578 * @param value the value to store
580 * @return 0 for success, or a Kerberos 5 error code on failure.
582 * @ingroup krb5_storage
585 KRB5_LIB_FUNCTION krb5_error_code KRB5_LIB_CALL
586 krb5_store_int16(krb5_storage *sp,
587 int16_t value)
589 if(BYTEORDER_IS_HOST(sp))
590 value = htons(value);
591 else if(BYTEORDER_IS_LE(sp))
592 value = bswap16(value);
593 return krb5_store_int(sp, value, 2);
597 * Store a uint16 to storage, byte order is controlled by the settings
598 * on the storage, see krb5_storage_set_byteorder().
600 * @param sp the storage to write too
601 * @param value the value to store
603 * @return 0 for success, or a Kerberos 5 error code on failure.
605 * @ingroup krb5_storage
608 KRB5_LIB_FUNCTION krb5_error_code KRB5_LIB_CALL
609 krb5_store_uint16(krb5_storage *sp,
610 uint16_t value)
612 return krb5_store_int16(sp, (int16_t)value);
616 * Read a int16 from storage, byte order is controlled by the settings
617 * on the storage, see krb5_storage_set_byteorder().
619 * @param sp the storage to write too
620 * @param value the value read from the buffer
622 * @return 0 for success, or a Kerberos 5 error code on failure.
624 * @ingroup krb5_storage
627 KRB5_LIB_FUNCTION krb5_error_code KRB5_LIB_CALL
628 krb5_ret_int16(krb5_storage *sp,
629 int16_t *value)
631 int64_t v;
632 int ret;
633 ret = krb5_ret_int(sp, &v, 2);
634 if(ret)
635 return ret;
636 *value = v;
637 if(BYTEORDER_IS_HOST(sp))
638 *value = htons(*value);
639 else if(BYTEORDER_IS_LE(sp))
640 *value = bswap16(*value);
641 return 0;
645 * Read a int16 from storage, byte order is controlled by the settings
646 * on the storage, see krb5_storage_set_byteorder().
648 * @param sp the storage to write too
649 * @param value the value read from the buffer
651 * @return 0 for success, or a Kerberos 5 error code on failure.
653 * @ingroup krb5_storage
656 KRB5_LIB_FUNCTION krb5_error_code KRB5_LIB_CALL
657 krb5_ret_uint16(krb5_storage *sp,
658 uint16_t *value)
660 krb5_error_code ret;
661 int16_t v;
663 ret = krb5_ret_int16(sp, &v);
664 if (ret == 0)
665 *value = (uint16_t)v;
667 return ret;
671 * Store a int8 to storage.
673 * @param sp the storage to write too
674 * @param value the value to store
676 * @return 0 for success, or a Kerberos 5 error code on failure.
678 * @ingroup krb5_storage
681 KRB5_LIB_FUNCTION krb5_error_code KRB5_LIB_CALL
682 krb5_store_int8(krb5_storage *sp,
683 int8_t value)
685 int ret;
687 ret = sp->store(sp, &value, sizeof(value));
688 if (ret != sizeof(value))
689 return (ret<0)?errno:sp->eof_code;
690 return 0;
694 * Store a uint8 to storage.
696 * @param sp the storage to write too
697 * @param value the value to store
699 * @return 0 for success, or a Kerberos 5 error code on failure.
701 * @ingroup krb5_storage
704 KRB5_LIB_FUNCTION krb5_error_code KRB5_LIB_CALL
705 krb5_store_uint8(krb5_storage *sp,
706 uint8_t value)
708 return krb5_store_int8(sp, (int8_t)value);
712 * Read a int8 from storage
714 * @param sp the storage to write too
715 * @param value the value read from the buffer
717 * @return 0 for success, or a Kerberos 5 error code on failure.
719 * @ingroup krb5_storage
722 KRB5_LIB_FUNCTION krb5_error_code KRB5_LIB_CALL
723 krb5_ret_int8(krb5_storage *sp,
724 int8_t *value)
726 int ret;
728 ret = sp->fetch(sp, value, sizeof(*value));
729 if (ret != sizeof(*value))
730 return (ret<0)?errno:sp->eof_code;
731 return 0;
735 * Read a uint8 from storage
737 * @param sp the storage to write too
738 * @param value the value read from the buffer
740 * @return 0 for success, or a Kerberos 5 error code on failure.
742 * @ingroup krb5_storage
745 KRB5_LIB_FUNCTION krb5_error_code KRB5_LIB_CALL
746 krb5_ret_uint8(krb5_storage *sp,
747 uint8_t *value)
749 krb5_error_code ret;
750 int8_t v;
752 ret = krb5_ret_int8(sp, &v);
753 if (ret == 0)
754 *value = (uint8_t)v;
756 return ret;
760 * Store a data to the storage. The data is stored with an int32 as
761 * lenght plus the data (not padded).
763 * @param sp the storage buffer to write to
764 * @param data the buffer to store.
766 * @return 0 on success, a Kerberos 5 error code on failure.
768 * @ingroup krb5_storage
771 KRB5_LIB_FUNCTION krb5_error_code KRB5_LIB_CALL
772 krb5_store_data(krb5_storage *sp,
773 krb5_data data)
775 int ret;
776 ret = krb5_store_int32(sp, data.length);
777 if(ret < 0)
778 return ret;
779 ret = sp->store(sp, data.data, data.length);
780 if(ret < 0)
781 return errno;
782 if((size_t)ret != data.length)
783 return sp->eof_code;
784 return 0;
788 * Parse a data from the storage.
790 * @param sp the storage buffer to read from
791 * @param data the parsed data
793 * @return 0 on success, a Kerberos 5 error code on failure.
795 * @ingroup krb5_storage
798 KRB5_LIB_FUNCTION krb5_error_code KRB5_LIB_CALL
799 krb5_ret_data(krb5_storage *sp,
800 krb5_data *data)
802 int ret;
803 int32_t size;
805 ret = krb5_ret_int32(sp, &size);
806 if(ret)
807 return ret;
808 ret = size_too_large(sp, size);
809 if (ret)
810 return ret;
811 ret = krb5_data_alloc (data, size);
812 if (ret)
813 return ret;
814 if (size) {
815 ret = sp->fetch(sp, data->data, size);
816 if(ret != size) {
817 krb5_data_free(data);
818 return (ret < 0)? errno : sp->eof_code;
821 return 0;
825 * Store a string to the buffer. The data is formated as an len:uint32
826 * plus the string itself (not padded).
828 * @param sp the storage buffer to write to
829 * @param s the string to store.
831 * @return 0 on success, a Kerberos 5 error code on failure.
833 * @ingroup krb5_storage
836 KRB5_LIB_FUNCTION krb5_error_code KRB5_LIB_CALL
837 krb5_store_string(krb5_storage *sp, const char *s)
839 krb5_data data;
840 data.length = strlen(s);
841 data.data = rk_UNCONST(s);
842 return krb5_store_data(sp, data);
846 * Parse a string from the storage.
848 * @param sp the storage buffer to read from
849 * @param string the parsed string
851 * @return 0 on success, a Kerberos 5 error code on failure.
853 * @ingroup krb5_storage
857 KRB5_LIB_FUNCTION krb5_error_code KRB5_LIB_CALL
858 krb5_ret_string(krb5_storage *sp,
859 char **string)
861 int ret;
862 krb5_data data;
863 ret = krb5_ret_data(sp, &data);
864 if(ret)
865 return ret;
866 *string = realloc(data.data, data.length + 1);
867 if(*string == NULL){
868 free(data.data);
869 return ENOMEM;
871 (*string)[data.length] = 0;
872 return 0;
876 * Store a zero terminated string to the buffer. The data is stored
877 * one character at a time until a NUL is stored.
879 * @param sp the storage buffer to write to
880 * @param s the string to store.
882 * @return 0 on success, a Kerberos 5 error code on failure.
884 * @ingroup krb5_storage
887 KRB5_LIB_FUNCTION krb5_error_code KRB5_LIB_CALL
888 krb5_store_stringz(krb5_storage *sp, const char *s)
890 size_t len = strlen(s) + 1;
891 ssize_t ret;
893 ret = sp->store(sp, s, len);
894 if(ret < 0)
895 return ret;
896 if((size_t)ret != len)
897 return sp->eof_code;
898 return 0;
902 * Parse zero terminated string from the storage.
904 * @param sp the storage buffer to read from
905 * @param string the parsed string
907 * @return 0 on success, a Kerberos 5 error code on failure.
909 * @ingroup krb5_storage
912 KRB5_LIB_FUNCTION krb5_error_code KRB5_LIB_CALL
913 krb5_ret_stringz(krb5_storage *sp,
914 char **string)
916 char c;
917 char *s = NULL;
918 size_t len = 0;
919 ssize_t ret;
921 while((ret = sp->fetch(sp, &c, 1)) == 1){
922 krb5_error_code eret;
923 char *tmp;
925 len++;
926 eret = size_too_large(sp, len);
927 if (eret) {
928 free(s);
929 return eret;
931 tmp = realloc (s, len);
932 if (tmp == NULL) {
933 free (s);
934 return ENOMEM;
936 s = tmp;
937 s[len - 1] = c;
938 if(c == 0)
939 break;
941 if(ret != 1){
942 free(s);
943 if(ret == 0)
944 return sp->eof_code;
945 return ret;
947 *string = s;
948 return 0;
951 KRB5_LIB_FUNCTION krb5_error_code KRB5_LIB_CALL
952 krb5_store_stringnl(krb5_storage *sp, const char *s)
954 size_t len = strlen(s);
955 ssize_t ret;
957 ret = sp->store(sp, s, len);
958 if(ret < 0)
959 return ret;
960 if((size_t)ret != len)
961 return sp->eof_code;
962 ret = sp->store(sp, "\n", 1);
963 if(ret != 1) {
964 if(ret < 0)
965 return ret;
966 else
967 return sp->eof_code;
970 return 0;
974 KRB5_LIB_FUNCTION krb5_error_code KRB5_LIB_CALL
975 krb5_ret_stringnl(krb5_storage *sp,
976 char **string)
978 int expect_nl = 0;
979 char c;
980 char *s = NULL;
981 size_t len = 0;
982 ssize_t ret;
984 while((ret = sp->fetch(sp, &c, 1)) == 1){
985 krb5_error_code eret;
986 char *tmp;
988 if (c == '\r') {
989 expect_nl = 1;
990 continue;
992 if (expect_nl && c != '\n') {
993 free(s);
994 return KRB5_BADMSGTYPE;
997 len++;
998 eret = size_too_large(sp, len);
999 if (eret) {
1000 free(s);
1001 return eret;
1003 tmp = realloc (s, len);
1004 if (tmp == NULL) {
1005 free (s);
1006 return ENOMEM;
1008 s = tmp;
1009 if(c == '\n') {
1010 s[len - 1] = '\0';
1011 break;
1013 s[len - 1] = c;
1015 if(ret != 1){
1016 free(s);
1017 if(ret == 0)
1018 return sp->eof_code;
1019 return ret;
1021 *string = s;
1022 return 0;
1026 * Write a principal block to storage.
1028 * @param sp the storage buffer to write to
1029 * @param p the principal block to write.
1031 * @return 0 on success, a Kerberos 5 error code on failure.
1033 * @ingroup krb5_storage
1036 KRB5_LIB_FUNCTION krb5_error_code KRB5_LIB_CALL
1037 krb5_store_principal(krb5_storage *sp,
1038 krb5_const_principal p)
1040 size_t i;
1041 int ret;
1043 if(!krb5_storage_is_flags(sp, KRB5_STORAGE_PRINCIPAL_NO_NAME_TYPE)) {
1044 ret = krb5_store_int32(sp, p->name.name_type);
1045 if(ret) return ret;
1047 if(krb5_storage_is_flags(sp, KRB5_STORAGE_PRINCIPAL_WRONG_NUM_COMPONENTS))
1048 ret = krb5_store_int32(sp, p->name.name_string.len + 1);
1049 else
1050 ret = krb5_store_int32(sp, p->name.name_string.len);
1052 if(ret) return ret;
1053 ret = krb5_store_string(sp, p->realm);
1054 if(ret) return ret;
1055 for(i = 0; i < p->name.name_string.len; i++){
1056 ret = krb5_store_string(sp, p->name.name_string.val[i]);
1057 if(ret) return ret;
1059 return 0;
1063 * Parse principal from the storage.
1065 * @param sp the storage buffer to read from
1066 * @param princ the parsed principal
1068 * @return 0 on success, a Kerberos 5 error code on failure.
1070 * @ingroup krb5_storage
1073 KRB5_LIB_FUNCTION krb5_error_code KRB5_LIB_CALL
1074 krb5_ret_principal(krb5_storage *sp,
1075 krb5_principal *princ)
1077 int i;
1078 int ret;
1079 krb5_principal p;
1080 int32_t type;
1081 int32_t ncomp;
1083 p = calloc(1, sizeof(*p));
1084 if(p == NULL)
1085 return ENOMEM;
1087 if(krb5_storage_is_flags(sp, KRB5_STORAGE_PRINCIPAL_NO_NAME_TYPE))
1088 type = KRB5_NT_UNKNOWN;
1089 else if((ret = krb5_ret_int32(sp, &type))){
1090 free(p);
1091 return ret;
1093 if((ret = krb5_ret_int32(sp, &ncomp))){
1094 free(p);
1095 return ret;
1097 if(krb5_storage_is_flags(sp, KRB5_STORAGE_PRINCIPAL_WRONG_NUM_COMPONENTS))
1098 ncomp--;
1099 if (ncomp < 0) {
1100 free(p);
1101 return EINVAL;
1103 ret = size_too_large_num(sp, ncomp, sizeof(p->name.name_string.val[0]));
1104 if (ret) {
1105 free(p);
1106 return ret;
1108 p->name.name_type = type;
1109 p->name.name_string.len = ncomp;
1110 ret = krb5_ret_string(sp, &p->realm);
1111 if(ret) {
1112 free(p);
1113 return ret;
1115 p->name.name_string.val = calloc(ncomp, sizeof(p->name.name_string.val[0]));
1116 if(p->name.name_string.val == NULL && ncomp != 0){
1117 free(p->realm);
1118 free(p);
1119 return ENOMEM;
1121 for(i = 0; i < ncomp; i++){
1122 ret = krb5_ret_string(sp, &p->name.name_string.val[i]);
1123 if(ret) {
1124 while (i >= 0)
1125 free(p->name.name_string.val[i--]);
1126 free(p->realm);
1127 free(p);
1128 return ret;
1131 *princ = p;
1132 return 0;
1136 * Store a keyblock to the storage.
1138 * @param sp the storage buffer to write to
1139 * @param p the keyblock to write
1141 * @return 0 on success, a Kerberos 5 error code on failure.
1143 * @ingroup krb5_storage
1146 KRB5_LIB_FUNCTION krb5_error_code KRB5_LIB_CALL
1147 krb5_store_keyblock(krb5_storage *sp, krb5_keyblock p)
1149 int ret;
1150 ret = krb5_store_int16(sp, p.keytype);
1151 if(ret) return ret;
1153 if(krb5_storage_is_flags(sp, KRB5_STORAGE_KEYBLOCK_KEYTYPE_TWICE)){
1154 /* this should really be enctype, but it is the same as
1155 keytype nowadays */
1156 ret = krb5_store_int16(sp, p.keytype);
1157 if(ret) return ret;
1160 ret = krb5_store_data(sp, p.keyvalue);
1161 return ret;
1165 * Read a keyblock from the storage.
1167 * @param sp the storage buffer to write to
1168 * @param p the keyblock read from storage, free using krb5_free_keyblock()
1170 * @return 0 on success, a Kerberos 5 error code on failure.
1172 * @ingroup krb5_storage
1175 KRB5_LIB_FUNCTION krb5_error_code KRB5_LIB_CALL
1176 krb5_ret_keyblock(krb5_storage *sp, krb5_keyblock *p)
1178 int ret;
1179 int16_t tmp;
1181 ret = krb5_ret_int16(sp, &tmp);
1182 if(ret) return ret;
1183 p->keytype = tmp;
1185 if(krb5_storage_is_flags(sp, KRB5_STORAGE_KEYBLOCK_KEYTYPE_TWICE)){
1186 ret = krb5_ret_int16(sp, &tmp);
1187 if(ret) return ret;
1190 ret = krb5_ret_data(sp, &p->keyvalue);
1191 return ret;
1195 * Write a times block to storage.
1197 * @param sp the storage buffer to write to
1198 * @param times the times block to write.
1200 * @return 0 on success, a Kerberos 5 error code on failure.
1202 * @ingroup krb5_storage
1205 KRB5_LIB_FUNCTION krb5_error_code KRB5_LIB_CALL
1206 krb5_store_times(krb5_storage *sp, krb5_times times)
1208 int ret;
1209 ret = krb5_store_int32(sp, times.authtime);
1210 if(ret) return ret;
1211 ret = krb5_store_int32(sp, times.starttime);
1212 if(ret) return ret;
1213 ret = krb5_store_int32(sp, times.endtime);
1214 if(ret) return ret;
1215 ret = krb5_store_int32(sp, times.renew_till);
1216 return ret;
1220 * Read a times block from the storage.
1222 * @param sp the storage buffer to write to
1223 * @param times the times block read from storage
1225 * @return 0 on success, a Kerberos 5 error code on failure.
1227 * @ingroup krb5_storage
1230 KRB5_LIB_FUNCTION krb5_error_code KRB5_LIB_CALL
1231 krb5_ret_times(krb5_storage *sp, krb5_times *times)
1233 int ret;
1234 int32_t tmp;
1235 ret = krb5_ret_int32(sp, &tmp);
1236 times->authtime = tmp;
1237 if(ret) return ret;
1238 ret = krb5_ret_int32(sp, &tmp);
1239 times->starttime = tmp;
1240 if(ret) return ret;
1241 ret = krb5_ret_int32(sp, &tmp);
1242 times->endtime = tmp;
1243 if(ret) return ret;
1244 ret = krb5_ret_int32(sp, &tmp);
1245 times->renew_till = tmp;
1246 return ret;
1250 * Write a address block to storage.
1252 * @param sp the storage buffer to write to
1253 * @param p the address block to write.
1255 * @return 0 on success, a Kerberos 5 error code on failure.
1257 * @ingroup krb5_storage
1260 KRB5_LIB_FUNCTION krb5_error_code KRB5_LIB_CALL
1261 krb5_store_address(krb5_storage *sp, krb5_address p)
1263 int ret;
1264 ret = krb5_store_int16(sp, p.addr_type);
1265 if(ret) return ret;
1266 ret = krb5_store_data(sp, p.address);
1267 return ret;
1271 * Read a address block from the storage.
1273 * @param sp the storage buffer to write to
1274 * @param adr the address block read from storage
1276 * @return 0 on success, a Kerberos 5 error code on failure.
1278 * @ingroup krb5_storage
1281 KRB5_LIB_FUNCTION krb5_error_code KRB5_LIB_CALL
1282 krb5_ret_address(krb5_storage *sp, krb5_address *adr)
1284 int16_t t;
1285 int ret;
1286 ret = krb5_ret_int16(sp, &t);
1287 if(ret) return ret;
1288 adr->addr_type = t;
1289 ret = krb5_ret_data(sp, &adr->address);
1290 return ret;
1294 * Write a addresses block to storage.
1296 * @param sp the storage buffer to write to
1297 * @param p the addresses block to write.
1299 * @return 0 on success, a Kerberos 5 error code on failure.
1301 * @ingroup krb5_storage
1304 KRB5_LIB_FUNCTION krb5_error_code KRB5_LIB_CALL
1305 krb5_store_addrs(krb5_storage *sp, krb5_addresses p)
1307 size_t i;
1308 int ret;
1309 ret = krb5_store_int32(sp, p.len);
1310 if(ret) return ret;
1311 for(i = 0; i<p.len; i++){
1312 ret = krb5_store_address(sp, p.val[i]);
1313 if(ret) break;
1315 return ret;
1319 * Read a addresses block from the storage.
1321 * @param sp the storage buffer to write to
1322 * @param adr the addresses block read from storage
1324 * @return 0 on success, a Kerberos 5 error code on failure.
1326 * @ingroup krb5_storage
1329 KRB5_LIB_FUNCTION krb5_error_code KRB5_LIB_CALL
1330 krb5_ret_addrs(krb5_storage *sp, krb5_addresses *adr)
1332 size_t i;
1333 int ret;
1334 int32_t tmp;
1336 ret = krb5_ret_int32(sp, &tmp);
1337 if(ret) return ret;
1338 ret = size_too_large_num(sp, tmp, sizeof(adr->val[0]));
1339 if (ret) return ret;
1340 adr->len = tmp;
1341 ALLOC(adr->val, adr->len);
1342 if (adr->val == NULL && adr->len != 0)
1343 return ENOMEM;
1344 for(i = 0; i < adr->len; i++){
1345 ret = krb5_ret_address(sp, &adr->val[i]);
1346 if(ret) break;
1348 return ret;
1352 * Write a auth data block to storage.
1354 * @param sp the storage buffer to write to
1355 * @param auth the auth data block to write.
1357 * @return 0 on success, a Kerberos 5 error code on failure.
1359 * @ingroup krb5_storage
1362 KRB5_LIB_FUNCTION krb5_error_code KRB5_LIB_CALL
1363 krb5_store_authdata(krb5_storage *sp, krb5_authdata auth)
1365 krb5_error_code ret;
1366 size_t i;
1367 ret = krb5_store_int32(sp, auth.len);
1368 if(ret) return ret;
1369 for(i = 0; i < auth.len; i++){
1370 ret = krb5_store_int16(sp, auth.val[i].ad_type);
1371 if(ret) break;
1372 ret = krb5_store_data(sp, auth.val[i].ad_data);
1373 if(ret) break;
1375 return 0;
1379 * Read a auth data from the storage.
1381 * @param sp the storage buffer to write to
1382 * @param auth the auth data block read from storage
1384 * @return 0 on success, a Kerberos 5 error code on failure.
1386 * @ingroup krb5_storage
1389 KRB5_LIB_FUNCTION krb5_error_code KRB5_LIB_CALL
1390 krb5_ret_authdata(krb5_storage *sp, krb5_authdata *auth)
1392 krb5_error_code ret;
1393 int32_t tmp;
1394 int16_t tmp2;
1395 int i;
1396 ret = krb5_ret_int32(sp, &tmp);
1397 if(ret) return ret;
1398 ret = size_too_large_num(sp, tmp, sizeof(auth->val[0]));
1399 if (ret) return ret;
1400 ALLOC_SEQ(auth, tmp);
1401 if (auth->val == NULL && tmp != 0)
1402 return ENOMEM;
1403 for(i = 0; i < tmp; i++){
1404 ret = krb5_ret_int16(sp, &tmp2);
1405 if(ret) break;
1406 auth->val[i].ad_type = tmp2;
1407 ret = krb5_ret_data(sp, &auth->val[i].ad_data);
1408 if(ret) break;
1410 return ret;
1413 static int32_t
1414 bitswap32(int32_t b)
1416 int32_t r = 0;
1417 int i;
1418 for (i = 0; i < 32; i++) {
1419 r = r << 1 | (b & 1);
1420 b = b >> 1;
1422 return r;
1426 * Write a credentials block to storage.
1428 * @param sp the storage buffer to write to
1429 * @param creds the creds block to write.
1431 * @return 0 on success, a Kerberos 5 error code on failure.
1433 * @ingroup krb5_storage
1436 KRB5_LIB_FUNCTION krb5_error_code KRB5_LIB_CALL
1437 krb5_store_creds(krb5_storage *sp, krb5_creds *creds)
1439 int ret;
1441 ret = krb5_store_principal(sp, creds->client);
1442 if(ret)
1443 return ret;
1444 ret = krb5_store_principal(sp, creds->server);
1445 if(ret)
1446 return ret;
1447 ret = krb5_store_keyblock(sp, creds->session);
1448 if(ret)
1449 return ret;
1450 ret = krb5_store_times(sp, creds->times);
1451 if(ret)
1452 return ret;
1453 ret = krb5_store_int8(sp, creds->second_ticket.length != 0); /* is_skey */
1454 if(ret)
1455 return ret;
1456 ret = krb5_store_int32(sp, bitswap32(TicketFlags2int(creds->flags.b)));
1457 if(ret)
1458 return ret;
1459 ret = krb5_store_addrs(sp, creds->addresses);
1460 if(ret)
1461 return ret;
1462 ret = krb5_store_authdata(sp, creds->authdata);
1463 if(ret)
1464 return ret;
1465 ret = krb5_store_data(sp, creds->ticket);
1466 if(ret)
1467 return ret;
1468 ret = krb5_store_data(sp, creds->second_ticket);
1469 return ret;
1473 * Read a credentials block from the storage.
1475 * @param sp the storage buffer to write to
1476 * @param creds the credentials block read from storage
1478 * @return 0 on success, a Kerberos 5 error code on failure.
1480 * @ingroup krb5_storage
1483 KRB5_LIB_FUNCTION krb5_error_code KRB5_LIB_CALL
1484 krb5_ret_creds(krb5_storage *sp, krb5_creds *creds)
1486 krb5_error_code ret;
1487 int8_t dummy8;
1488 int32_t dummy32;
1490 memset(creds, 0, sizeof(*creds));
1491 ret = krb5_ret_principal (sp, &creds->client);
1492 if(ret) goto cleanup;
1493 ret = krb5_ret_principal (sp, &creds->server);
1494 if(ret) goto cleanup;
1495 ret = krb5_ret_keyblock (sp, &creds->session);
1496 if(ret) goto cleanup;
1497 ret = krb5_ret_times (sp, &creds->times);
1498 if(ret) goto cleanup;
1499 ret = krb5_ret_int8 (sp, &dummy8);
1500 if(ret) goto cleanup;
1501 ret = krb5_ret_int32 (sp, &dummy32);
1502 if(ret) goto cleanup;
1503 creds->flags.b = int2TicketFlags(bitswap32(dummy32));
1504 ret = krb5_ret_addrs (sp, &creds->addresses);
1505 if(ret) goto cleanup;
1506 ret = krb5_ret_authdata (sp, &creds->authdata);
1507 if(ret) goto cleanup;
1508 ret = krb5_ret_data (sp, &creds->ticket);
1509 if(ret) goto cleanup;
1510 ret = krb5_ret_data (sp, &creds->second_ticket);
1511 cleanup:
1512 if(ret) {
1513 #if 0
1514 krb5_free_cred_contents(context, creds); /* XXX */
1515 #endif
1517 return ret;
1520 #define SC_CLIENT_PRINCIPAL 0x0001
1521 #define SC_SERVER_PRINCIPAL 0x0002
1522 #define SC_SESSION_KEY 0x0004
1523 #define SC_TICKET 0x0008
1524 #define SC_SECOND_TICKET 0x0010
1525 #define SC_AUTHDATA 0x0020
1526 #define SC_ADDRESSES 0x0040
1529 * Write a tagged credentials block to storage.
1531 * @param sp the storage buffer to write to
1532 * @param creds the creds block to write.
1534 * @return 0 on success, a Kerberos 5 error code on failure.
1536 * @ingroup krb5_storage
1539 KRB5_LIB_FUNCTION krb5_error_code KRB5_LIB_CALL
1540 krb5_store_creds_tag(krb5_storage *sp, krb5_creds *creds)
1542 int ret;
1543 int32_t header = 0;
1545 if (creds->client)
1546 header |= SC_CLIENT_PRINCIPAL;
1547 if (creds->server)
1548 header |= SC_SERVER_PRINCIPAL;
1549 if (creds->session.keytype != ETYPE_NULL)
1550 header |= SC_SESSION_KEY;
1551 if (creds->ticket.data)
1552 header |= SC_TICKET;
1553 if (creds->second_ticket.length)
1554 header |= SC_SECOND_TICKET;
1555 if (creds->authdata.len)
1556 header |= SC_AUTHDATA;
1557 if (creds->addresses.len)
1558 header |= SC_ADDRESSES;
1560 ret = krb5_store_int32(sp, header);
1561 if (ret)
1562 return ret;
1564 if (creds->client) {
1565 ret = krb5_store_principal(sp, creds->client);
1566 if(ret)
1567 return ret;
1570 if (creds->server) {
1571 ret = krb5_store_principal(sp, creds->server);
1572 if(ret)
1573 return ret;
1576 if (creds->session.keytype != ETYPE_NULL) {
1577 ret = krb5_store_keyblock(sp, creds->session);
1578 if(ret)
1579 return ret;
1582 ret = krb5_store_times(sp, creds->times);
1583 if(ret)
1584 return ret;
1585 ret = krb5_store_int8(sp, creds->second_ticket.length != 0); /* is_skey */
1586 if(ret)
1587 return ret;
1589 ret = krb5_store_int32(sp, bitswap32(TicketFlags2int(creds->flags.b)));
1590 if(ret)
1591 return ret;
1593 if (creds->addresses.len) {
1594 ret = krb5_store_addrs(sp, creds->addresses);
1595 if(ret)
1596 return ret;
1599 if (creds->authdata.len) {
1600 ret = krb5_store_authdata(sp, creds->authdata);
1601 if(ret)
1602 return ret;
1605 if (creds->ticket.data) {
1606 ret = krb5_store_data(sp, creds->ticket);
1607 if(ret)
1608 return ret;
1611 if (creds->second_ticket.data) {
1612 ret = krb5_store_data(sp, creds->second_ticket);
1613 if (ret)
1614 return ret;
1617 return ret;
1621 * Read a tagged credentials block from the storage.
1623 * @param sp the storage buffer to write to
1624 * @param creds the credentials block read from storage
1626 * @return 0 on success, a Kerberos 5 error code on failure.
1628 * @ingroup krb5_storage
1631 KRB5_LIB_FUNCTION krb5_error_code KRB5_LIB_CALL
1632 krb5_ret_creds_tag(krb5_storage *sp,
1633 krb5_creds *creds)
1635 krb5_error_code ret;
1636 int8_t dummy8;
1637 int32_t dummy32, header;
1639 memset(creds, 0, sizeof(*creds));
1641 ret = krb5_ret_int32 (sp, &header);
1642 if (ret) goto cleanup;
1644 if (header & SC_CLIENT_PRINCIPAL) {
1645 ret = krb5_ret_principal (sp, &creds->client);
1646 if(ret) goto cleanup;
1648 if (header & SC_SERVER_PRINCIPAL) {
1649 ret = krb5_ret_principal (sp, &creds->server);
1650 if(ret) goto cleanup;
1652 if (header & SC_SESSION_KEY) {
1653 ret = krb5_ret_keyblock (sp, &creds->session);
1654 if(ret) goto cleanup;
1656 ret = krb5_ret_times (sp, &creds->times);
1657 if(ret) goto cleanup;
1658 ret = krb5_ret_int8 (sp, &dummy8);
1659 if(ret) goto cleanup;
1660 ret = krb5_ret_int32 (sp, &dummy32);
1661 if(ret) goto cleanup;
1662 creds->flags.b = int2TicketFlags(bitswap32(dummy32));
1663 if (header & SC_ADDRESSES) {
1664 ret = krb5_ret_addrs (sp, &creds->addresses);
1665 if(ret) goto cleanup;
1667 if (header & SC_AUTHDATA) {
1668 ret = krb5_ret_authdata (sp, &creds->authdata);
1669 if(ret) goto cleanup;
1671 if (header & SC_TICKET) {
1672 ret = krb5_ret_data (sp, &creds->ticket);
1673 if(ret) goto cleanup;
1675 if (header & SC_SECOND_TICKET) {
1676 ret = krb5_ret_data (sp, &creds->second_ticket);
1677 if(ret) goto cleanup;
1680 cleanup:
1681 if(ret) {
1682 #if 0
1683 krb5_free_cred_contents(context, creds); /* XXX */
1684 #endif
1686 return ret;