etc/services - sync with NetBSD-8
[minix.git] / crypto / external / bsd / heimdal / dist / lib / krb5 / store.c
blob6775be7dcff0c4c8351dd3f5414e6da205029b94
1 /* $NetBSD: store.c,v 1.1.1.2 2014/04/24 12:45:51 pettai Exp $ */
3 /*
4 * Copyright (c) 1997-2008 Kungliga Tekniska Högskolan
5 * (Royal Institute of Technology, Stockholm, Sweden).
6 * All rights reserved.
8 * Redistribution and use in source and binary forms, with or without
9 * modification, are permitted provided that the following conditions
10 * are met:
12 * 1. Redistributions of source code must retain the above copyright
13 * notice, this list of conditions and the following disclaimer.
15 * 2. Redistributions in binary form must reproduce the above copyright
16 * notice, this list of conditions and the following disclaimer in the
17 * documentation and/or other materials provided with the distribution.
19 * 3. Neither the name of the Institute nor the names of its contributors
20 * may be used to endorse or promote products derived from this software
21 * without specific prior written permission.
23 * THIS SOFTWARE IS PROVIDED BY THE INSTITUTE AND CONTRIBUTORS ``AS IS'' AND
24 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
25 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
26 * ARE DISCLAIMED. IN NO EVENT SHALL THE INSTITUTE OR CONTRIBUTORS BE LIABLE
27 * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
28 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
29 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
30 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
31 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
32 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
33 * SUCH DAMAGE.
36 #include "krb5_locl.h"
37 #include "store-int.h"
39 #define BYTEORDER_IS(SP, V) (((SP)->flags & KRB5_STORAGE_BYTEORDER_MASK) == (V))
40 #define BYTEORDER_IS_LE(SP) BYTEORDER_IS((SP), KRB5_STORAGE_BYTEORDER_LE)
41 #define BYTEORDER_IS_BE(SP) BYTEORDER_IS((SP), KRB5_STORAGE_BYTEORDER_BE)
42 #define BYTEORDER_IS_HOST(SP) (BYTEORDER_IS((SP), KRB5_STORAGE_BYTEORDER_HOST) || \
43 krb5_storage_is_flags((SP), KRB5_STORAGE_HOST_BYTEORDER))
45 /**
46 * Add the flags on a storage buffer by or-ing in the flags to the buffer.
48 * @param sp the storage buffer to set the flags on
49 * @param flags the flags to set
51 * @ingroup krb5_storage
54 KRB5_LIB_FUNCTION void KRB5_LIB_CALL
55 krb5_storage_set_flags(krb5_storage *sp, krb5_flags flags)
57 sp->flags |= flags;
60 /**
61 * Clear the flags on a storage buffer
63 * @param sp the storage buffer to clear the flags on
64 * @param flags the flags to clear
66 * @ingroup krb5_storage
69 KRB5_LIB_FUNCTION void KRB5_LIB_CALL
70 krb5_storage_clear_flags(krb5_storage *sp, krb5_flags flags)
72 sp->flags &= ~flags;
75 /**
76 * Return true or false depending on if the storage flags is set or
77 * not. NB testing for the flag 0 always return true.
79 * @param sp the storage buffer to check flags on
80 * @param flags The flags to test for
82 * @return true if all the flags are set, false if not.
84 * @ingroup krb5_storage
87 KRB5_LIB_FUNCTION krb5_boolean KRB5_LIB_CALL
88 krb5_storage_is_flags(krb5_storage *sp, krb5_flags flags)
90 return (sp->flags & flags) == flags;
93 /**
94 * Set the new byte order of the storage buffer.
96 * @param sp the storage buffer to set the byte order for.
97 * @param byteorder the new byte order.
99 * The byte order are: KRB5_STORAGE_BYTEORDER_BE,
100 * KRB5_STORAGE_BYTEORDER_LE and KRB5_STORAGE_BYTEORDER_HOST.
102 * @ingroup krb5_storage
105 KRB5_LIB_FUNCTION void KRB5_LIB_CALL
106 krb5_storage_set_byteorder(krb5_storage *sp, krb5_flags byteorder)
108 sp->flags &= ~KRB5_STORAGE_BYTEORDER_MASK;
109 sp->flags |= byteorder;
113 * Return the current byteorder for the buffer. See krb5_storage_set_byteorder() for the list or byte order contants.
115 * @ingroup krb5_storage
118 KRB5_LIB_FUNCTION krb5_flags KRB5_LIB_CALL
119 krb5_storage_get_byteorder(krb5_storage *sp)
121 return sp->flags & KRB5_STORAGE_BYTEORDER_MASK;
125 * Set the max alloc value
127 * @param sp the storage buffer set the max allow for
128 * @param size maximum size to allocate, use 0 to remove limit
130 * @ingroup krb5_storage
133 KRB5_LIB_FUNCTION void KRB5_LIB_CALL
134 krb5_storage_set_max_alloc(krb5_storage *sp, size_t size)
136 sp->max_alloc = size;
139 /* don't allocate unresonable amount of memory */
140 static krb5_error_code
141 size_too_large(krb5_storage *sp, size_t size)
143 if (sp->max_alloc && sp->max_alloc < size)
144 return HEIM_ERR_TOO_BIG;
145 return 0;
148 static krb5_error_code
149 size_too_large_num(krb5_storage *sp, size_t count, size_t size)
151 if (sp->max_alloc == 0 || size == 0)
152 return 0;
153 size = sp->max_alloc / size;
154 if (size < count)
155 return HEIM_ERR_TOO_BIG;
156 return 0;
160 * Seek to a new offset.
162 * @param sp the storage buffer to seek in.
163 * @param offset the offset to seek
164 * @param whence relateive searching, SEEK_CUR from the current
165 * position, SEEK_END from the end, SEEK_SET absolute from the start.
167 * @return The new current offset
169 * @ingroup krb5_storage
172 KRB5_LIB_FUNCTION off_t KRB5_LIB_CALL
173 krb5_storage_seek(krb5_storage *sp, off_t offset, int whence)
175 return (*sp->seek)(sp, offset, whence);
179 * Truncate the storage buffer in sp to offset.
181 * @param sp the storage buffer to truncate.
182 * @param offset the offset to truncate too.
184 * @return An Kerberos 5 error code.
186 * @ingroup krb5_storage
189 KRB5_LIB_FUNCTION int KRB5_LIB_CALL
190 krb5_storage_truncate(krb5_storage *sp, off_t offset)
192 return (*sp->trunc)(sp, offset);
196 * Read to the storage buffer.
198 * @param sp the storage buffer to read from
199 * @param buf the buffer to store the data in
200 * @param len the length to read
202 * @return The length of data read (can be shorter then len), or negative on error.
204 * @ingroup krb5_storage
207 KRB5_LIB_FUNCTION krb5_ssize_t KRB5_LIB_CALL
208 krb5_storage_read(krb5_storage *sp, void *buf, size_t len)
210 return sp->fetch(sp, buf, len);
214 * Write to the storage buffer.
216 * @param sp the storage buffer to write to
217 * @param buf the buffer to write to the storage buffer
218 * @param len the length to write
220 * @return The length of data written (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_write(krb5_storage *sp, const void *buf, size_t len)
228 return sp->store(sp, buf, len);
232 * Set the return code that will be used when end of storage is reached.
234 * @param sp the storage
235 * @param code the error code to return on end of storage
237 * @ingroup krb5_storage
240 KRB5_LIB_FUNCTION void KRB5_LIB_CALL
241 krb5_storage_set_eof_code(krb5_storage *sp, int code)
243 sp->eof_code = code;
247 * Get the return code that will be used when end of storage is reached.
249 * @param sp the storage
251 * @return storage error code
253 * @ingroup krb5_storage
256 KRB5_LIB_FUNCTION int KRB5_LIB_CALL
257 krb5_storage_get_eof_code(krb5_storage *sp)
259 return sp->eof_code;
263 * Free a krb5 storage.
265 * @param sp the storage to free.
267 * @return An Kerberos 5 error code.
269 * @ingroup krb5_storage
272 KRB5_LIB_FUNCTION krb5_error_code KRB5_LIB_CALL
273 krb5_storage_free(krb5_storage *sp)
275 if(sp->free)
276 (*sp->free)(sp);
277 free(sp->data);
278 free(sp);
279 return 0;
283 * Copy the contnent of storage
285 * @param sp the storage to copy to a data
286 * @param data the copied data, free with krb5_data_free()
288 * @return 0 for success, or a Kerberos 5 error code on failure.
290 * @ingroup krb5_storage
293 KRB5_LIB_FUNCTION krb5_error_code KRB5_LIB_CALL
294 krb5_storage_to_data(krb5_storage *sp, krb5_data *data)
296 off_t pos, size;
297 krb5_error_code ret;
299 pos = sp->seek(sp, 0, SEEK_CUR);
300 if (pos < 0)
301 return HEIM_ERR_NOT_SEEKABLE;
302 size = sp->seek(sp, 0, SEEK_END);
303 ret = size_too_large(sp, size);
304 if (ret)
305 return ret;
306 ret = krb5_data_alloc(data, size);
307 if (ret) {
308 sp->seek(sp, pos, SEEK_SET);
309 return ret;
311 if (size) {
312 sp->seek(sp, 0, SEEK_SET);
313 sp->fetch(sp, data->data, data->length);
314 sp->seek(sp, pos, SEEK_SET);
316 return 0;
319 static krb5_error_code
320 krb5_store_int(krb5_storage *sp,
321 int32_t value,
322 size_t len)
324 int ret;
325 unsigned char v[16];
327 if(len > sizeof(v))
328 return EINVAL;
329 _krb5_put_int(v, value, len);
330 ret = sp->store(sp, v, len);
331 if (ret < 0)
332 return errno;
333 if ((size_t)ret != len)
334 return sp->eof_code;
335 return 0;
339 * Store a int32 to storage, byte order is controlled by the settings
340 * on the storage, see krb5_storage_set_byteorder().
342 * @param sp the storage to write too
343 * @param value the value to store
345 * @return 0 for success, or a Kerberos 5 error code on failure.
347 * @ingroup krb5_storage
350 KRB5_LIB_FUNCTION krb5_error_code KRB5_LIB_CALL
351 krb5_store_int32(krb5_storage *sp,
352 int32_t value)
354 if(BYTEORDER_IS_HOST(sp))
355 value = htonl(value);
356 else if(BYTEORDER_IS_LE(sp))
357 value = bswap32(value);
358 return krb5_store_int(sp, value, 4);
362 * Store a uint32 to storage, byte order is controlled by the settings
363 * on the storage, see krb5_storage_set_byteorder().
365 * @param sp the storage to write too
366 * @param value the value to store
368 * @return 0 for success, or a Kerberos 5 error code on failure.
370 * @ingroup krb5_storage
373 KRB5_LIB_FUNCTION krb5_error_code KRB5_LIB_CALL
374 krb5_store_uint32(krb5_storage *sp,
375 uint32_t value)
377 return krb5_store_int32(sp, (int32_t)value);
380 static krb5_error_code
381 krb5_ret_int(krb5_storage *sp,
382 int32_t *value,
383 size_t len)
385 int ret;
386 unsigned char v[4];
387 unsigned long w;
388 ret = sp->fetch(sp, v, len);
389 if (ret < 0)
390 return errno;
391 if ((size_t)ret != len)
392 return sp->eof_code;
393 _krb5_get_int(v, &w, len);
394 *value = w;
395 return 0;
399 * Read a int32 from storage, byte order is controlled by the settings
400 * on the storage, see krb5_storage_set_byteorder().
402 * @param sp the storage to write too
403 * @param value the value read from the buffer
405 * @return 0 for success, or a Kerberos 5 error code on failure.
407 * @ingroup krb5_storage
410 KRB5_LIB_FUNCTION krb5_error_code KRB5_LIB_CALL
411 krb5_ret_int32(krb5_storage *sp,
412 int32_t *value)
414 krb5_error_code ret = krb5_ret_int(sp, value, 4);
415 if(ret)
416 return ret;
417 if(BYTEORDER_IS_HOST(sp))
418 *value = htonl(*value);
419 else if(BYTEORDER_IS_LE(sp))
420 *value = bswap32(*value);
421 return 0;
425 * Read a uint32 from storage, byte order is controlled by the settings
426 * on the storage, see krb5_storage_set_byteorder().
428 * @param sp the storage to write too
429 * @param value the value read from the buffer
431 * @return 0 for success, or a Kerberos 5 error code on failure.
433 * @ingroup krb5_storage
436 KRB5_LIB_FUNCTION krb5_error_code KRB5_LIB_CALL
437 krb5_ret_uint32(krb5_storage *sp,
438 uint32_t *value)
440 krb5_error_code ret;
441 int32_t v;
443 ret = krb5_ret_int32(sp, &v);
444 if (ret == 0)
445 *value = (uint32_t)v;
447 return ret;
451 * Store a int16 to storage, byte order is controlled by the settings
452 * on the storage, see krb5_storage_set_byteorder().
454 * @param sp the storage to write too
455 * @param value the value to store
457 * @return 0 for success, or a Kerberos 5 error code on failure.
459 * @ingroup krb5_storage
462 KRB5_LIB_FUNCTION krb5_error_code KRB5_LIB_CALL
463 krb5_store_int16(krb5_storage *sp,
464 int16_t value)
466 if(BYTEORDER_IS_HOST(sp))
467 value = htons(value);
468 else if(BYTEORDER_IS_LE(sp))
469 value = bswap16(value);
470 return krb5_store_int(sp, value, 2);
474 * Store a uint16 to storage, byte order is controlled by the settings
475 * on the storage, see krb5_storage_set_byteorder().
477 * @param sp the storage to write too
478 * @param value the value to store
480 * @return 0 for success, or a Kerberos 5 error code on failure.
482 * @ingroup krb5_storage
485 KRB5_LIB_FUNCTION krb5_error_code KRB5_LIB_CALL
486 krb5_store_uint16(krb5_storage *sp,
487 uint16_t value)
489 return krb5_store_int16(sp, (int16_t)value);
493 * Read a int16 from storage, byte order is controlled by the settings
494 * on the storage, see krb5_storage_set_byteorder().
496 * @param sp the storage to write too
497 * @param value the value read from the buffer
499 * @return 0 for success, or a Kerberos 5 error code on failure.
501 * @ingroup krb5_storage
504 KRB5_LIB_FUNCTION krb5_error_code KRB5_LIB_CALL
505 krb5_ret_int16(krb5_storage *sp,
506 int16_t *value)
508 int32_t v;
509 int ret;
510 ret = krb5_ret_int(sp, &v, 2);
511 if(ret)
512 return ret;
513 *value = v;
514 if(BYTEORDER_IS_HOST(sp))
515 *value = htons(*value);
516 else if(BYTEORDER_IS_LE(sp))
517 *value = bswap16(*value);
518 return 0;
522 * Read a int16 from storage, byte order is controlled by the settings
523 * on the storage, see krb5_storage_set_byteorder().
525 * @param sp the storage to write too
526 * @param value the value read from the buffer
528 * @return 0 for success, or a Kerberos 5 error code on failure.
530 * @ingroup krb5_storage
533 KRB5_LIB_FUNCTION krb5_error_code KRB5_LIB_CALL
534 krb5_ret_uint16(krb5_storage *sp,
535 uint16_t *value)
537 krb5_error_code ret;
538 int16_t v;
540 ret = krb5_ret_int16(sp, &v);
541 if (ret == 0)
542 *value = (uint16_t)v;
544 return ret;
548 * Store a int8 to storage.
550 * @param sp the storage to write too
551 * @param value the value to store
553 * @return 0 for success, or a Kerberos 5 error code on failure.
555 * @ingroup krb5_storage
558 KRB5_LIB_FUNCTION krb5_error_code KRB5_LIB_CALL
559 krb5_store_int8(krb5_storage *sp,
560 int8_t value)
562 int ret;
564 ret = sp->store(sp, &value, sizeof(value));
565 if (ret != sizeof(value))
566 return (ret<0)?errno:sp->eof_code;
567 return 0;
571 * Store a uint8 to storage.
573 * @param sp the storage to write too
574 * @param value the value to store
576 * @return 0 for success, or a Kerberos 5 error code on failure.
578 * @ingroup krb5_storage
581 KRB5_LIB_FUNCTION krb5_error_code KRB5_LIB_CALL
582 krb5_store_uint8(krb5_storage *sp,
583 uint8_t value)
585 return krb5_store_int8(sp, (int8_t)value);
589 * Read a int8 from storage
591 * @param sp the storage to write too
592 * @param value the value read from the buffer
594 * @return 0 for success, or a Kerberos 5 error code on failure.
596 * @ingroup krb5_storage
599 KRB5_LIB_FUNCTION krb5_error_code KRB5_LIB_CALL
600 krb5_ret_int8(krb5_storage *sp,
601 int8_t *value)
603 int ret;
605 ret = sp->fetch(sp, value, sizeof(*value));
606 if (ret != sizeof(*value))
607 return (ret<0)?errno:sp->eof_code;
608 return 0;
612 * Read a uint8 from storage
614 * @param sp the storage to write too
615 * @param value the value read from the buffer
617 * @return 0 for success, or a Kerberos 5 error code on failure.
619 * @ingroup krb5_storage
622 KRB5_LIB_FUNCTION krb5_error_code KRB5_LIB_CALL
623 krb5_ret_uint8(krb5_storage *sp,
624 uint8_t *value)
626 krb5_error_code ret;
627 int8_t v;
629 ret = krb5_ret_int8(sp, &v);
630 if (ret == 0)
631 *value = (uint8_t)v;
633 return ret;
637 * Store a data to the storage. The data is stored with an int32 as
638 * lenght plus the data (not padded).
640 * @param sp the storage buffer to write to
641 * @param data the buffer to store.
643 * @return 0 on success, a Kerberos 5 error code on failure.
645 * @ingroup krb5_storage
648 KRB5_LIB_FUNCTION krb5_error_code KRB5_LIB_CALL
649 krb5_store_data(krb5_storage *sp,
650 krb5_data data)
652 int ret;
653 ret = krb5_store_int32(sp, data.length);
654 if(ret < 0)
655 return ret;
656 ret = sp->store(sp, data.data, data.length);
657 if(ret < 0)
658 return errno;
659 if((size_t)ret != data.length)
660 return sp->eof_code;
661 return 0;
665 * Parse a data from the storage.
667 * @param sp the storage buffer to read from
668 * @param data the parsed data
670 * @return 0 on success, a Kerberos 5 error code on failure.
672 * @ingroup krb5_storage
675 KRB5_LIB_FUNCTION krb5_error_code KRB5_LIB_CALL
676 krb5_ret_data(krb5_storage *sp,
677 krb5_data *data)
679 int ret;
680 int32_t size;
682 ret = krb5_ret_int32(sp, &size);
683 if(ret)
684 return ret;
685 ret = size_too_large(sp, size);
686 if (ret)
687 return ret;
688 ret = krb5_data_alloc (data, size);
689 if (ret)
690 return ret;
691 if (size) {
692 ret = sp->fetch(sp, data->data, size);
693 if(ret != size)
694 return (ret < 0)? errno : sp->eof_code;
696 return 0;
700 * Store a string to the buffer. The data is formated as an len:uint32
701 * plus the string itself (not padded).
703 * @param sp the storage buffer to write to
704 * @param s the string to store.
706 * @return 0 on success, a Kerberos 5 error code on failure.
708 * @ingroup krb5_storage
711 KRB5_LIB_FUNCTION krb5_error_code KRB5_LIB_CALL
712 krb5_store_string(krb5_storage *sp, const char *s)
714 krb5_data data;
715 data.length = strlen(s);
716 data.data = rk_UNCONST(s);
717 return krb5_store_data(sp, data);
721 * Parse a string from the storage.
723 * @param sp the storage buffer to read from
724 * @param string the parsed string
726 * @return 0 on success, a Kerberos 5 error code on failure.
728 * @ingroup krb5_storage
732 KRB5_LIB_FUNCTION krb5_error_code KRB5_LIB_CALL
733 krb5_ret_string(krb5_storage *sp,
734 char **string)
736 int ret;
737 krb5_data data;
738 ret = krb5_ret_data(sp, &data);
739 if(ret)
740 return ret;
741 *string = realloc(data.data, data.length + 1);
742 if(*string == NULL){
743 free(data.data);
744 return ENOMEM;
746 (*string)[data.length] = 0;
747 return 0;
751 * Store a zero terminated string to the buffer. The data is stored
752 * one character at a time until a NUL is stored.
754 * @param sp the storage buffer to write to
755 * @param s the string to store.
757 * @return 0 on success, a Kerberos 5 error code on failure.
759 * @ingroup krb5_storage
762 KRB5_LIB_FUNCTION krb5_error_code KRB5_LIB_CALL
763 krb5_store_stringz(krb5_storage *sp, const char *s)
765 size_t len = strlen(s) + 1;
766 ssize_t ret;
768 ret = sp->store(sp, s, len);
769 if(ret < 0)
770 return ret;
771 if((size_t)ret != len)
772 return sp->eof_code;
773 return 0;
777 * Parse zero terminated string from the storage.
779 * @param sp the storage buffer to read from
780 * @param string the parsed string
782 * @return 0 on success, a Kerberos 5 error code on failure.
784 * @ingroup krb5_storage
787 KRB5_LIB_FUNCTION krb5_error_code KRB5_LIB_CALL
788 krb5_ret_stringz(krb5_storage *sp,
789 char **string)
791 char c;
792 char *s = NULL;
793 size_t len = 0;
794 ssize_t ret;
796 while((ret = sp->fetch(sp, &c, 1)) == 1){
797 char *tmp;
799 len++;
800 ret = size_too_large(sp, len);
801 if (ret)
802 break;
803 tmp = realloc (s, len);
804 if (tmp == NULL) {
805 free (s);
806 return ENOMEM;
808 s = tmp;
809 s[len - 1] = c;
810 if(c == 0)
811 break;
813 if(ret != 1){
814 free(s);
815 if(ret == 0)
816 return sp->eof_code;
817 return ret;
819 *string = s;
820 return 0;
823 KRB5_LIB_FUNCTION krb5_error_code KRB5_LIB_CALL
824 krb5_store_stringnl(krb5_storage *sp, const char *s)
826 size_t len = strlen(s);
827 ssize_t ret;
829 ret = sp->store(sp, s, len);
830 if(ret < 0)
831 return ret;
832 if((size_t)ret != len)
833 return sp->eof_code;
834 ret = sp->store(sp, "\n", 1);
835 if(ret != 1) {
836 if(ret < 0)
837 return ret;
838 else
839 return sp->eof_code;
842 return 0;
846 KRB5_LIB_FUNCTION krb5_error_code KRB5_LIB_CALL
847 krb5_ret_stringnl(krb5_storage *sp,
848 char **string)
850 int expect_nl = 0;
851 char c;
852 char *s = NULL;
853 size_t len = 0;
854 ssize_t ret;
856 while((ret = sp->fetch(sp, &c, 1)) == 1){
857 char *tmp;
859 if (c == '\r') {
860 expect_nl = 1;
861 continue;
863 if (expect_nl && c != '\n') {
864 free(s);
865 return KRB5_BADMSGTYPE;
868 len++;
869 ret = size_too_large(sp, len);
870 if (ret)
871 break;
872 tmp = realloc (s, len);
873 if (tmp == NULL) {
874 free (s);
875 return ENOMEM;
877 s = tmp;
878 if(c == '\n') {
879 s[len - 1] = '\0';
880 break;
882 s[len - 1] = c;
884 if(ret != 1){
885 free(s);
886 if(ret == 0)
887 return sp->eof_code;
888 return ret;
890 *string = s;
891 return 0;
895 * Write a principal block to storage.
897 * @param sp the storage buffer to write to
898 * @param p the principal block to write.
900 * @return 0 on success, a Kerberos 5 error code on failure.
902 * @ingroup krb5_storage
905 KRB5_LIB_FUNCTION krb5_error_code KRB5_LIB_CALL
906 krb5_store_principal(krb5_storage *sp,
907 krb5_const_principal p)
909 size_t i;
910 int ret;
912 if(!krb5_storage_is_flags(sp, KRB5_STORAGE_PRINCIPAL_NO_NAME_TYPE)) {
913 ret = krb5_store_int32(sp, p->name.name_type);
914 if(ret) return ret;
916 if(krb5_storage_is_flags(sp, KRB5_STORAGE_PRINCIPAL_WRONG_NUM_COMPONENTS))
917 ret = krb5_store_int32(sp, p->name.name_string.len + 1);
918 else
919 ret = krb5_store_int32(sp, p->name.name_string.len);
921 if(ret) return ret;
922 ret = krb5_store_string(sp, p->realm);
923 if(ret) return ret;
924 for(i = 0; i < p->name.name_string.len; i++){
925 ret = krb5_store_string(sp, p->name.name_string.val[i]);
926 if(ret) return ret;
928 return 0;
932 * Parse principal from the storage.
934 * @param sp the storage buffer to read from
935 * @param princ the parsed principal
937 * @return 0 on success, a Kerberos 5 error code on failure.
939 * @ingroup krb5_storage
942 KRB5_LIB_FUNCTION krb5_error_code KRB5_LIB_CALL
943 krb5_ret_principal(krb5_storage *sp,
944 krb5_principal *princ)
946 int i;
947 int ret;
948 krb5_principal p;
949 int32_t type;
950 int32_t ncomp;
952 p = calloc(1, sizeof(*p));
953 if(p == NULL)
954 return ENOMEM;
956 if(krb5_storage_is_flags(sp, KRB5_STORAGE_PRINCIPAL_NO_NAME_TYPE))
957 type = KRB5_NT_UNKNOWN;
958 else if((ret = krb5_ret_int32(sp, &type))){
959 free(p);
960 return ret;
962 if((ret = krb5_ret_int32(sp, &ncomp))){
963 free(p);
964 return ret;
966 if(krb5_storage_is_flags(sp, KRB5_STORAGE_PRINCIPAL_WRONG_NUM_COMPONENTS))
967 ncomp--;
968 if (ncomp < 0) {
969 free(p);
970 return EINVAL;
972 ret = size_too_large_num(sp, ncomp, sizeof(p->name.name_string.val[0]));
973 if (ret) {
974 free(p);
975 return ret;
977 p->name.name_type = type;
978 p->name.name_string.len = ncomp;
979 ret = krb5_ret_string(sp, &p->realm);
980 if(ret) {
981 free(p);
982 return ret;
984 p->name.name_string.val = calloc(ncomp, sizeof(p->name.name_string.val[0]));
985 if(p->name.name_string.val == NULL && ncomp != 0){
986 free(p->realm);
987 free(p);
988 return ENOMEM;
990 for(i = 0; i < ncomp; i++){
991 ret = krb5_ret_string(sp, &p->name.name_string.val[i]);
992 if(ret) {
993 while (i >= 0)
994 free(p->name.name_string.val[i--]);
995 free(p->realm);
996 free(p);
997 return ret;
1000 *princ = p;
1001 return 0;
1005 * Store a keyblock to the storage.
1007 * @param sp the storage buffer to write to
1008 * @param p the keyblock to write
1010 * @return 0 on success, a Kerberos 5 error code on failure.
1012 * @ingroup krb5_storage
1015 KRB5_LIB_FUNCTION krb5_error_code KRB5_LIB_CALL
1016 krb5_store_keyblock(krb5_storage *sp, krb5_keyblock p)
1018 int ret;
1019 ret = krb5_store_int16(sp, p.keytype);
1020 if(ret) return ret;
1022 if(krb5_storage_is_flags(sp, KRB5_STORAGE_KEYBLOCK_KEYTYPE_TWICE)){
1023 /* this should really be enctype, but it is the same as
1024 keytype nowadays */
1025 ret = krb5_store_int16(sp, p.keytype);
1026 if(ret) return ret;
1029 ret = krb5_store_data(sp, p.keyvalue);
1030 return ret;
1034 * Read a keyblock from the storage.
1036 * @param sp the storage buffer to write to
1037 * @param p the keyblock read from storage, free using krb5_free_keyblock()
1039 * @return 0 on success, a Kerberos 5 error code on failure.
1041 * @ingroup krb5_storage
1044 KRB5_LIB_FUNCTION krb5_error_code KRB5_LIB_CALL
1045 krb5_ret_keyblock(krb5_storage *sp, krb5_keyblock *p)
1047 int ret;
1048 int16_t tmp;
1050 ret = krb5_ret_int16(sp, &tmp);
1051 if(ret) return ret;
1052 p->keytype = tmp;
1054 if(krb5_storage_is_flags(sp, KRB5_STORAGE_KEYBLOCK_KEYTYPE_TWICE)){
1055 ret = krb5_ret_int16(sp, &tmp);
1056 if(ret) return ret;
1059 ret = krb5_ret_data(sp, &p->keyvalue);
1060 return ret;
1064 * Write a times block to storage.
1066 * @param sp the storage buffer to write to
1067 * @param times the times block to write.
1069 * @return 0 on success, a Kerberos 5 error code on failure.
1071 * @ingroup krb5_storage
1074 KRB5_LIB_FUNCTION krb5_error_code KRB5_LIB_CALL
1075 krb5_store_times(krb5_storage *sp, krb5_times times)
1077 int ret;
1078 ret = krb5_store_int32(sp, times.authtime);
1079 if(ret) return ret;
1080 ret = krb5_store_int32(sp, times.starttime);
1081 if(ret) return ret;
1082 ret = krb5_store_int32(sp, times.endtime);
1083 if(ret) return ret;
1084 ret = krb5_store_int32(sp, times.renew_till);
1085 return ret;
1089 * Read a times block from the storage.
1091 * @param sp the storage buffer to write to
1092 * @param times the times block read from storage
1094 * @return 0 on success, a Kerberos 5 error code on failure.
1096 * @ingroup krb5_storage
1099 KRB5_LIB_FUNCTION krb5_error_code KRB5_LIB_CALL
1100 krb5_ret_times(krb5_storage *sp, krb5_times *times)
1102 int ret;
1103 int32_t tmp;
1104 ret = krb5_ret_int32(sp, &tmp);
1105 times->authtime = tmp;
1106 if(ret) return ret;
1107 ret = krb5_ret_int32(sp, &tmp);
1108 times->starttime = tmp;
1109 if(ret) return ret;
1110 ret = krb5_ret_int32(sp, &tmp);
1111 times->endtime = tmp;
1112 if(ret) return ret;
1113 ret = krb5_ret_int32(sp, &tmp);
1114 times->renew_till = tmp;
1115 return ret;
1119 * Write a address block to storage.
1121 * @param sp the storage buffer to write to
1122 * @param p the address block to write.
1124 * @return 0 on success, a Kerberos 5 error code on failure.
1126 * @ingroup krb5_storage
1129 KRB5_LIB_FUNCTION krb5_error_code KRB5_LIB_CALL
1130 krb5_store_address(krb5_storage *sp, krb5_address p)
1132 int ret;
1133 ret = krb5_store_int16(sp, p.addr_type);
1134 if(ret) return ret;
1135 ret = krb5_store_data(sp, p.address);
1136 return ret;
1140 * Read a address block from the storage.
1142 * @param sp the storage buffer to write to
1143 * @param adr the address block read from storage
1145 * @return 0 on success, a Kerberos 5 error code on failure.
1147 * @ingroup krb5_storage
1150 KRB5_LIB_FUNCTION krb5_error_code KRB5_LIB_CALL
1151 krb5_ret_address(krb5_storage *sp, krb5_address *adr)
1153 int16_t t;
1154 int ret;
1155 ret = krb5_ret_int16(sp, &t);
1156 if(ret) return ret;
1157 adr->addr_type = t;
1158 ret = krb5_ret_data(sp, &adr->address);
1159 return ret;
1163 * Write a addresses block to storage.
1165 * @param sp the storage buffer to write to
1166 * @param p the addresses block to write.
1168 * @return 0 on success, a Kerberos 5 error code on failure.
1170 * @ingroup krb5_storage
1173 KRB5_LIB_FUNCTION krb5_error_code KRB5_LIB_CALL
1174 krb5_store_addrs(krb5_storage *sp, krb5_addresses p)
1176 size_t i;
1177 int ret;
1178 ret = krb5_store_int32(sp, p.len);
1179 if(ret) return ret;
1180 for(i = 0; i<p.len; i++){
1181 ret = krb5_store_address(sp, p.val[i]);
1182 if(ret) break;
1184 return ret;
1188 * Read a addresses block from the storage.
1190 * @param sp the storage buffer to write to
1191 * @param adr the addresses block read from storage
1193 * @return 0 on success, a Kerberos 5 error code on failure.
1195 * @ingroup krb5_storage
1198 KRB5_LIB_FUNCTION krb5_error_code KRB5_LIB_CALL
1199 krb5_ret_addrs(krb5_storage *sp, krb5_addresses *adr)
1201 size_t i;
1202 int ret;
1203 int32_t tmp;
1205 ret = krb5_ret_int32(sp, &tmp);
1206 if(ret) return ret;
1207 ret = size_too_large_num(sp, tmp, sizeof(adr->val[0]));
1208 if (ret) return ret;
1209 adr->len = tmp;
1210 ALLOC(adr->val, adr->len);
1211 if (adr->val == NULL && adr->len != 0)
1212 return ENOMEM;
1213 for(i = 0; i < adr->len; i++){
1214 ret = krb5_ret_address(sp, &adr->val[i]);
1215 if(ret) break;
1217 return ret;
1221 * Write a auth data block to storage.
1223 * @param sp the storage buffer to write to
1224 * @param auth the auth data block to write.
1226 * @return 0 on success, a Kerberos 5 error code on failure.
1228 * @ingroup krb5_storage
1231 KRB5_LIB_FUNCTION krb5_error_code KRB5_LIB_CALL
1232 krb5_store_authdata(krb5_storage *sp, krb5_authdata auth)
1234 krb5_error_code ret;
1235 size_t i;
1236 ret = krb5_store_int32(sp, auth.len);
1237 if(ret) return ret;
1238 for(i = 0; i < auth.len; i++){
1239 ret = krb5_store_int16(sp, auth.val[i].ad_type);
1240 if(ret) break;
1241 ret = krb5_store_data(sp, auth.val[i].ad_data);
1242 if(ret) break;
1244 return 0;
1248 * Read a auth data from the storage.
1250 * @param sp the storage buffer to write to
1251 * @param auth the auth data block read from storage
1253 * @return 0 on success, a Kerberos 5 error code on failure.
1255 * @ingroup krb5_storage
1258 KRB5_LIB_FUNCTION krb5_error_code KRB5_LIB_CALL
1259 krb5_ret_authdata(krb5_storage *sp, krb5_authdata *auth)
1261 krb5_error_code ret;
1262 int32_t tmp;
1263 int16_t tmp2;
1264 int i;
1265 ret = krb5_ret_int32(sp, &tmp);
1266 if(ret) return ret;
1267 ret = size_too_large_num(sp, tmp, sizeof(auth->val[0]));
1268 if (ret) return ret;
1269 ALLOC_SEQ(auth, tmp);
1270 if (auth->val == NULL && tmp != 0)
1271 return ENOMEM;
1272 for(i = 0; i < tmp; i++){
1273 ret = krb5_ret_int16(sp, &tmp2);
1274 if(ret) break;
1275 auth->val[i].ad_type = tmp2;
1276 ret = krb5_ret_data(sp, &auth->val[i].ad_data);
1277 if(ret) break;
1279 return ret;
1282 static int32_t
1283 bitswap32(int32_t b)
1285 int32_t r = 0;
1286 int i;
1287 for (i = 0; i < 32; i++) {
1288 r = r << 1 | (b & 1);
1289 b = b >> 1;
1291 return r;
1295 * Write a credentials block to storage.
1297 * @param sp the storage buffer to write to
1298 * @param creds the creds block to write.
1300 * @return 0 on success, a Kerberos 5 error code on failure.
1302 * @ingroup krb5_storage
1305 KRB5_LIB_FUNCTION krb5_error_code KRB5_LIB_CALL
1306 krb5_store_creds(krb5_storage *sp, krb5_creds *creds)
1308 int ret;
1310 ret = krb5_store_principal(sp, creds->client);
1311 if(ret)
1312 return ret;
1313 ret = krb5_store_principal(sp, creds->server);
1314 if(ret)
1315 return ret;
1316 ret = krb5_store_keyblock(sp, creds->session);
1317 if(ret)
1318 return ret;
1319 ret = krb5_store_times(sp, creds->times);
1320 if(ret)
1321 return ret;
1322 ret = krb5_store_int8(sp, creds->second_ticket.length != 0); /* is_skey */
1323 if(ret)
1324 return ret;
1326 if(krb5_storage_is_flags(sp, KRB5_STORAGE_CREDS_FLAGS_WRONG_BITORDER))
1327 ret = krb5_store_int32(sp, creds->flags.i);
1328 else
1329 ret = krb5_store_int32(sp, bitswap32(TicketFlags2int(creds->flags.b)));
1330 if(ret)
1331 return ret;
1333 ret = krb5_store_addrs(sp, creds->addresses);
1334 if(ret)
1335 return ret;
1336 ret = krb5_store_authdata(sp, creds->authdata);
1337 if(ret)
1338 return ret;
1339 ret = krb5_store_data(sp, creds->ticket);
1340 if(ret)
1341 return ret;
1342 ret = krb5_store_data(sp, creds->second_ticket);
1343 return ret;
1347 * Read a credentials block from the storage.
1349 * @param sp the storage buffer to write to
1350 * @param creds the credentials block read from storage
1352 * @return 0 on success, a Kerberos 5 error code on failure.
1354 * @ingroup krb5_storage
1357 KRB5_LIB_FUNCTION krb5_error_code KRB5_LIB_CALL
1358 krb5_ret_creds(krb5_storage *sp, krb5_creds *creds)
1360 krb5_error_code ret;
1361 int8_t dummy8;
1362 int32_t dummy32;
1364 memset(creds, 0, sizeof(*creds));
1365 ret = krb5_ret_principal (sp, &creds->client);
1366 if(ret) goto cleanup;
1367 ret = krb5_ret_principal (sp, &creds->server);
1368 if(ret) goto cleanup;
1369 ret = krb5_ret_keyblock (sp, &creds->session);
1370 if(ret) goto cleanup;
1371 ret = krb5_ret_times (sp, &creds->times);
1372 if(ret) goto cleanup;
1373 ret = krb5_ret_int8 (sp, &dummy8);
1374 if(ret) goto cleanup;
1375 ret = krb5_ret_int32 (sp, &dummy32);
1376 if(ret) goto cleanup;
1378 * Runtime detect the what is the higher bits of the bitfield. If
1379 * any of the higher bits are set in the input data, it's either a
1380 * new ticket flag (and this code need to be removed), or it's a
1381 * MIT cache (or new Heimdal cache), lets change it to our current
1382 * format.
1385 uint32_t mask = 0xffff0000;
1386 creds->flags.i = 0;
1387 creds->flags.b.anonymous = 1;
1388 if (creds->flags.i & mask)
1389 mask = ~mask;
1390 if (dummy32 & mask)
1391 dummy32 = bitswap32(dummy32);
1393 creds->flags.i = dummy32;
1394 ret = krb5_ret_addrs (sp, &creds->addresses);
1395 if(ret) goto cleanup;
1396 ret = krb5_ret_authdata (sp, &creds->authdata);
1397 if(ret) goto cleanup;
1398 ret = krb5_ret_data (sp, &creds->ticket);
1399 if(ret) goto cleanup;
1400 ret = krb5_ret_data (sp, &creds->second_ticket);
1401 cleanup:
1402 if(ret) {
1403 #if 0
1404 krb5_free_cred_contents(context, creds); /* XXX */
1405 #endif
1407 return ret;
1410 #define SC_CLIENT_PRINCIPAL 0x0001
1411 #define SC_SERVER_PRINCIPAL 0x0002
1412 #define SC_SESSION_KEY 0x0004
1413 #define SC_TICKET 0x0008
1414 #define SC_SECOND_TICKET 0x0010
1415 #define SC_AUTHDATA 0x0020
1416 #define SC_ADDRESSES 0x0040
1419 * Write a tagged credentials block to storage.
1421 * @param sp the storage buffer to write to
1422 * @param creds the creds block to write.
1424 * @return 0 on success, a Kerberos 5 error code on failure.
1426 * @ingroup krb5_storage
1429 KRB5_LIB_FUNCTION krb5_error_code KRB5_LIB_CALL
1430 krb5_store_creds_tag(krb5_storage *sp, krb5_creds *creds)
1432 int ret;
1433 int32_t header = 0;
1435 if (creds->client)
1436 header |= SC_CLIENT_PRINCIPAL;
1437 if (creds->server)
1438 header |= SC_SERVER_PRINCIPAL;
1439 if (creds->session.keytype != ETYPE_NULL)
1440 header |= SC_SESSION_KEY;
1441 if (creds->ticket.data)
1442 header |= SC_TICKET;
1443 if (creds->second_ticket.length)
1444 header |= SC_SECOND_TICKET;
1445 if (creds->authdata.len)
1446 header |= SC_AUTHDATA;
1447 if (creds->addresses.len)
1448 header |= SC_ADDRESSES;
1450 ret = krb5_store_int32(sp, header);
1451 if (ret)
1452 return ret;
1454 if (creds->client) {
1455 ret = krb5_store_principal(sp, creds->client);
1456 if(ret)
1457 return ret;
1460 if (creds->server) {
1461 ret = krb5_store_principal(sp, creds->server);
1462 if(ret)
1463 return ret;
1466 if (creds->session.keytype != ETYPE_NULL) {
1467 ret = krb5_store_keyblock(sp, creds->session);
1468 if(ret)
1469 return ret;
1472 ret = krb5_store_times(sp, creds->times);
1473 if(ret)
1474 return ret;
1475 ret = krb5_store_int8(sp, creds->second_ticket.length != 0); /* is_skey */
1476 if(ret)
1477 return ret;
1479 ret = krb5_store_int32(sp, bitswap32(TicketFlags2int(creds->flags.b)));
1480 if(ret)
1481 return ret;
1483 if (creds->addresses.len) {
1484 ret = krb5_store_addrs(sp, creds->addresses);
1485 if(ret)
1486 return ret;
1489 if (creds->authdata.len) {
1490 ret = krb5_store_authdata(sp, creds->authdata);
1491 if(ret)
1492 return ret;
1495 if (creds->ticket.data) {
1496 ret = krb5_store_data(sp, creds->ticket);
1497 if(ret)
1498 return ret;
1501 if (creds->second_ticket.data) {
1502 ret = krb5_store_data(sp, creds->second_ticket);
1503 if (ret)
1504 return ret;
1507 return ret;
1511 * Read a tagged credentials block from the storage.
1513 * @param sp the storage buffer to write to
1514 * @param creds the credentials block read from storage
1516 * @return 0 on success, a Kerberos 5 error code on failure.
1518 * @ingroup krb5_storage
1521 KRB5_LIB_FUNCTION krb5_error_code KRB5_LIB_CALL
1522 krb5_ret_creds_tag(krb5_storage *sp,
1523 krb5_creds *creds)
1525 krb5_error_code ret;
1526 int8_t dummy8;
1527 int32_t dummy32, header;
1529 memset(creds, 0, sizeof(*creds));
1531 ret = krb5_ret_int32 (sp, &header);
1532 if (ret) goto cleanup;
1534 if (header & SC_CLIENT_PRINCIPAL) {
1535 ret = krb5_ret_principal (sp, &creds->client);
1536 if(ret) goto cleanup;
1538 if (header & SC_SERVER_PRINCIPAL) {
1539 ret = krb5_ret_principal (sp, &creds->server);
1540 if(ret) goto cleanup;
1542 if (header & SC_SESSION_KEY) {
1543 ret = krb5_ret_keyblock (sp, &creds->session);
1544 if(ret) goto cleanup;
1546 ret = krb5_ret_times (sp, &creds->times);
1547 if(ret) goto cleanup;
1548 ret = krb5_ret_int8 (sp, &dummy8);
1549 if(ret) goto cleanup;
1550 ret = krb5_ret_int32 (sp, &dummy32);
1551 if(ret) goto cleanup;
1553 * Runtime detect the what is the higher bits of the bitfield. If
1554 * any of the higher bits are set in the input data, it's either a
1555 * new ticket flag (and this code need to be removed), or it's a
1556 * MIT cache (or new Heimdal cache), lets change it to our current
1557 * format.
1560 uint32_t mask = 0xffff0000;
1561 creds->flags.i = 0;
1562 creds->flags.b.anonymous = 1;
1563 if (creds->flags.i & mask)
1564 mask = ~mask;
1565 if (dummy32 & mask)
1566 dummy32 = bitswap32(dummy32);
1568 creds->flags.i = dummy32;
1569 if (header & SC_ADDRESSES) {
1570 ret = krb5_ret_addrs (sp, &creds->addresses);
1571 if(ret) goto cleanup;
1573 if (header & SC_AUTHDATA) {
1574 ret = krb5_ret_authdata (sp, &creds->authdata);
1575 if(ret) goto cleanup;
1577 if (header & SC_TICKET) {
1578 ret = krb5_ret_data (sp, &creds->ticket);
1579 if(ret) goto cleanup;
1581 if (header & SC_SECOND_TICKET) {
1582 ret = krb5_ret_data (sp, &creds->second_ticket);
1583 if(ret) goto cleanup;
1586 cleanup:
1587 if(ret) {
1588 #if 0
1589 krb5_free_cred_contents(context, creds); /* XXX */
1590 #endif
1592 return ret;