Add roken/rename.c to fix non-standard rename()
[heimdal.git] / lib / krb5 / store.c
blob49e68ef177587ed7e85c4f1f8e78d5991984ea4c
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 * Seek to a new offset.
125 * @param sp the storage buffer to seek in.
126 * @param offset the offset to seek
127 * @param whence relateive searching, SEEK_CUR from the current
128 * position, SEEK_END from the end, SEEK_SET absolute from the start.
130 * @return The new current offset
132 * @ingroup krb5_storage
135 KRB5_LIB_FUNCTION off_t KRB5_LIB_CALL
136 krb5_storage_seek(krb5_storage *sp, off_t offset, int whence)
138 return (*sp->seek)(sp, offset, whence);
142 * Truncate the storage buffer in sp to offset.
144 * @param sp the storage buffer to truncate.
145 * @param offset the offset to truncate too.
147 * @return An Kerberos 5 error code.
149 * @ingroup krb5_storage
152 KRB5_LIB_FUNCTION int KRB5_LIB_CALL
153 krb5_storage_truncate(krb5_storage *sp, off_t offset)
155 return (*sp->trunc)(sp, offset);
159 * Read to the storage buffer.
161 * @param sp the storage buffer to read from
162 * @param buf the buffer to store the data in
163 * @param len the length to read
165 * @return The length of data read (can be shorter then len), or negative on error.
167 * @ingroup krb5_storage
170 KRB5_LIB_FUNCTION krb5_ssize_t KRB5_LIB_CALL
171 krb5_storage_read(krb5_storage *sp, void *buf, size_t len)
173 return sp->fetch(sp, buf, len);
177 * Write to the storage buffer.
179 * @param sp the storage buffer to write to
180 * @param buf the buffer to write to the storage buffer
181 * @param len the length to write
183 * @return The length of data written (can be shorter then len), or negative on error.
185 * @ingroup krb5_storage
188 KRB5_LIB_FUNCTION krb5_ssize_t KRB5_LIB_CALL
189 krb5_storage_write(krb5_storage *sp, const void *buf, size_t len)
191 return sp->store(sp, buf, len);
195 * Set the return code that will be used when end of storage is reached.
197 * @param sp the storage
198 * @param code the error code to return on end of storage
200 * @ingroup krb5_storage
203 KRB5_LIB_FUNCTION void KRB5_LIB_CALL
204 krb5_storage_set_eof_code(krb5_storage *sp, int code)
206 sp->eof_code = code;
210 * Get the return code that will be used when end of storage is reached.
212 * @param sp the storage
214 * @return storage error code
216 * @ingroup krb5_storage
219 KRB5_LIB_FUNCTION int KRB5_LIB_CALL
220 krb5_storage_get_eof_code(krb5_storage *sp)
222 return sp->eof_code;
225 KRB5_LIB_FUNCTION krb5_ssize_t KRB5_LIB_CALL
226 _krb5_put_int(void *buffer, unsigned long value, size_t size)
228 unsigned char *p = buffer;
229 int i;
230 for (i = size - 1; i >= 0; i--) {
231 p[i] = value & 0xff;
232 value >>= 8;
234 return size;
237 KRB5_LIB_FUNCTION krb5_ssize_t KRB5_LIB_CALL
238 _krb5_get_int(void *buffer, unsigned long *value, size_t size)
240 unsigned char *p = buffer;
241 unsigned long v = 0;
242 int i;
243 for (i = 0; i < size; i++)
244 v = (v << 8) + p[i];
245 *value = v;
246 return size;
250 * Free a krb5 storage.
252 * @param sp the storage to free.
254 * @return An Kerberos 5 error code.
256 * @ingroup krb5_storage
259 KRB5_LIB_FUNCTION krb5_error_code KRB5_LIB_CALL
260 krb5_storage_free(krb5_storage *sp)
262 if(sp->free)
263 (*sp->free)(sp);
264 free(sp->data);
265 free(sp);
266 return 0;
270 * Copy the contnent of storage
272 * @param sp the storage to copy to a data
273 * @param data the copied data, free with krb5_data_free()
275 * @return 0 for success, or a Kerberos 5 error code on failure.
277 * @ingroup krb5_storage
280 KRB5_LIB_FUNCTION krb5_error_code KRB5_LIB_CALL
281 krb5_storage_to_data(krb5_storage *sp, krb5_data *data)
283 off_t pos, size;
284 krb5_error_code ret;
286 pos = sp->seek(sp, 0, SEEK_CUR);
287 if (pos < 0)
288 return HEIM_ERR_NOT_SEEKABLE;
289 size = (size_t)sp->seek(sp, 0, SEEK_END);
290 if (size > (size_t)-1)
291 return HEIM_ERR_TOO_BIG;
292 ret = krb5_data_alloc (data, size);
293 if (ret) {
294 sp->seek(sp, pos, SEEK_SET);
295 return ret;
297 if (size) {
298 sp->seek(sp, 0, SEEK_SET);
299 sp->fetch(sp, data->data, data->length);
300 sp->seek(sp, pos, SEEK_SET);
302 return 0;
305 static krb5_error_code
306 krb5_store_int(krb5_storage *sp,
307 int32_t value,
308 size_t len)
310 int ret;
311 unsigned char v[16];
313 if(len > sizeof(v))
314 return EINVAL;
315 _krb5_put_int(v, value, len);
316 ret = sp->store(sp, v, len);
317 if (ret != len)
318 return (ret<0)?errno:sp->eof_code;
319 return 0;
323 * Store a int32 to storage, byte order is controlled by the settings
324 * on the storage, see krb5_storage_set_byteorder().
326 * @param sp the storage to write too
327 * @param value the value to store
329 * @return 0 for success, or a Kerberos 5 error code on failure.
331 * @ingroup krb5_storage
334 KRB5_LIB_FUNCTION krb5_error_code KRB5_LIB_CALL
335 krb5_store_int32(krb5_storage *sp,
336 int32_t value)
338 if(BYTEORDER_IS_HOST(sp))
339 value = htonl(value);
340 else if(BYTEORDER_IS_LE(sp))
341 value = bswap32(value);
342 return krb5_store_int(sp, value, 4);
346 * Store a uint32 to storage, byte order is controlled by the settings
347 * on the storage, see krb5_storage_set_byteorder().
349 * @param sp the storage to write too
350 * @param value the value to store
352 * @return 0 for success, or a Kerberos 5 error code on failure.
354 * @ingroup krb5_storage
357 KRB5_LIB_FUNCTION krb5_error_code KRB5_LIB_CALL
358 krb5_store_uint32(krb5_storage *sp,
359 uint32_t value)
361 return krb5_store_int32(sp, (int32_t)value);
364 static krb5_error_code
365 krb5_ret_int(krb5_storage *sp,
366 int32_t *value,
367 size_t len)
369 int ret;
370 unsigned char v[4];
371 unsigned long w;
372 ret = sp->fetch(sp, v, len);
373 if(ret != len)
374 return (ret<0)?errno:sp->eof_code;
375 _krb5_get_int(v, &w, len);
376 *value = w;
377 return 0;
381 * Read a int32 from 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 read from the buffer
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_ret_int32(krb5_storage *sp,
394 int32_t *value)
396 krb5_error_code ret = krb5_ret_int(sp, value, 4);
397 if(ret)
398 return ret;
399 if(BYTEORDER_IS_HOST(sp))
400 *value = htonl(*value);
401 else if(BYTEORDER_IS_LE(sp))
402 *value = bswap32(*value);
403 return 0;
407 * Read a uint32 from storage, byte order is controlled by the settings
408 * on the storage, see krb5_storage_set_byteorder().
410 * @param sp the storage to write too
411 * @param value the value read from the buffer
413 * @return 0 for success, or a Kerberos 5 error code on failure.
415 * @ingroup krb5_storage
418 KRB5_LIB_FUNCTION krb5_error_code KRB5_LIB_CALL
419 krb5_ret_uint32(krb5_storage *sp,
420 uint32_t *value)
422 krb5_error_code ret;
423 int32_t v;
425 ret = krb5_ret_int32(sp, &v);
426 if (ret == 0)
427 *value = (uint32_t)v;
429 return ret;
433 * Store a int16 to storage, byte order is controlled by the settings
434 * on the storage, see krb5_storage_set_byteorder().
436 * @param sp the storage to write too
437 * @param value the value to store
439 * @return 0 for success, or a Kerberos 5 error code on failure.
441 * @ingroup krb5_storage
444 KRB5_LIB_FUNCTION krb5_error_code KRB5_LIB_CALL
445 krb5_store_int16(krb5_storage *sp,
446 int16_t value)
448 if(BYTEORDER_IS_HOST(sp))
449 value = htons(value);
450 else if(BYTEORDER_IS_LE(sp))
451 value = bswap16(value);
452 return krb5_store_int(sp, value, 2);
456 * Store a uint16 to storage, byte order is controlled by the settings
457 * on the storage, see krb5_storage_set_byteorder().
459 * @param sp the storage to write too
460 * @param value the value to store
462 * @return 0 for success, or a Kerberos 5 error code on failure.
464 * @ingroup krb5_storage
467 KRB5_LIB_FUNCTION krb5_error_code KRB5_LIB_CALL
468 krb5_store_uint16(krb5_storage *sp,
469 uint16_t value)
471 return krb5_store_int16(sp, (int16_t)value);
475 * Read a int16 from storage, byte order is controlled by the settings
476 * on the storage, see krb5_storage_set_byteorder().
478 * @param sp the storage to write too
479 * @param value the value read from the buffer
481 * @return 0 for success, or a Kerberos 5 error code on failure.
483 * @ingroup krb5_storage
486 KRB5_LIB_FUNCTION krb5_error_code KRB5_LIB_CALL
487 krb5_ret_int16(krb5_storage *sp,
488 int16_t *value)
490 int32_t v;
491 int ret;
492 ret = krb5_ret_int(sp, &v, 2);
493 if(ret)
494 return ret;
495 *value = v;
496 if(BYTEORDER_IS_HOST(sp))
497 *value = htons(*value);
498 else if(BYTEORDER_IS_LE(sp))
499 *value = bswap16(*value);
500 return 0;
504 * Read a int16 from storage, byte order is controlled by the settings
505 * on the storage, see krb5_storage_set_byteorder().
507 * @param sp the storage to write too
508 * @param value the value read from the buffer
510 * @return 0 for success, or a Kerberos 5 error code on failure.
512 * @ingroup krb5_storage
515 KRB5_LIB_FUNCTION krb5_error_code KRB5_LIB_CALL
516 krb5_ret_uint16(krb5_storage *sp,
517 uint16_t *value)
519 krb5_error_code ret;
520 int16_t v;
522 ret = krb5_ret_int16(sp, &v);
523 if (ret == 0)
524 *value = (uint16_t)v;
526 return ret;
530 * Store a int8 to storage.
532 * @param sp the storage to write too
533 * @param value the value to store
535 * @return 0 for success, or a Kerberos 5 error code on failure.
537 * @ingroup krb5_storage
540 KRB5_LIB_FUNCTION krb5_error_code KRB5_LIB_CALL
541 krb5_store_int8(krb5_storage *sp,
542 int8_t value)
544 int ret;
546 ret = sp->store(sp, &value, sizeof(value));
547 if (ret != sizeof(value))
548 return (ret<0)?errno:sp->eof_code;
549 return 0;
553 * Store a uint8 to storage.
555 * @param sp the storage to write too
556 * @param value the value to store
558 * @return 0 for success, or a Kerberos 5 error code on failure.
560 * @ingroup krb5_storage
563 KRB5_LIB_FUNCTION krb5_error_code KRB5_LIB_CALL
564 krb5_store_uint8(krb5_storage *sp,
565 uint8_t value)
567 return krb5_store_int8(sp, (int8_t)value);
571 * Read a int8 from storage
573 * @param sp the storage to write too
574 * @param value the value read from the buffer
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_ret_int8(krb5_storage *sp,
583 int8_t *value)
585 int ret;
587 ret = sp->fetch(sp, value, sizeof(*value));
588 if (ret != sizeof(*value))
589 return (ret<0)?errno:sp->eof_code;
590 return 0;
594 * Read a uint8 from storage
596 * @param sp the storage to write too
597 * @param value the value read from the buffer
599 * @return 0 for success, or a Kerberos 5 error code on failure.
601 * @ingroup krb5_storage
604 KRB5_LIB_FUNCTION krb5_error_code KRB5_LIB_CALL
605 krb5_ret_uint8(krb5_storage *sp,
606 uint8_t *value)
608 krb5_error_code ret;
609 int8_t v;
611 ret = krb5_ret_int8(sp, &v);
612 if (ret == 0)
613 *value = (uint8_t)v;
615 return ret;
619 * Store a data to the storage. The data is stored with an int32 as
620 * lenght plus the data (not padded).
622 * @param sp the storage buffer to write to
623 * @param data the buffer to store.
625 * @return 0 on success, a Kerberos 5 error code on failure.
627 * @ingroup krb5_storage
630 KRB5_LIB_FUNCTION krb5_error_code KRB5_LIB_CALL
631 krb5_store_data(krb5_storage *sp,
632 krb5_data data)
634 int ret;
635 ret = krb5_store_int32(sp, data.length);
636 if(ret < 0)
637 return ret;
638 ret = sp->store(sp, data.data, data.length);
639 if(ret != data.length){
640 if(ret < 0)
641 return errno;
642 return sp->eof_code;
644 return 0;
648 * Parse a data from the storage.
650 * @param sp the storage buffer to read from
651 * @param data the parsed data
653 * @return 0 on success, a Kerberos 5 error code on failure.
655 * @ingroup krb5_storage
658 KRB5_LIB_FUNCTION krb5_error_code KRB5_LIB_CALL
659 krb5_ret_data(krb5_storage *sp,
660 krb5_data *data)
662 int ret;
663 int32_t size;
665 ret = krb5_ret_int32(sp, &size);
666 if(ret)
667 return ret;
668 ret = krb5_data_alloc (data, size);
669 if (ret)
670 return ret;
671 if (size) {
672 ret = sp->fetch(sp, data->data, size);
673 if(ret != size)
674 return (ret < 0)? errno : sp->eof_code;
676 return 0;
680 * Store a string to the buffer. The data is formated as an len:uint32
681 * plus the string itself (not padded).
683 * @param sp the storage buffer to write to
684 * @param s the string to store.
686 * @return 0 on success, a Kerberos 5 error code on failure.
688 * @ingroup krb5_storage
691 KRB5_LIB_FUNCTION krb5_error_code KRB5_LIB_CALL
692 krb5_store_string(krb5_storage *sp, const char *s)
694 krb5_data data;
695 data.length = strlen(s);
696 data.data = rk_UNCONST(s);
697 return krb5_store_data(sp, data);
701 * Parse a string from the storage.
703 * @param sp the storage buffer to read from
704 * @param string the parsed string
706 * @return 0 on success, a Kerberos 5 error code on failure.
708 * @ingroup krb5_storage
712 KRB5_LIB_FUNCTION krb5_error_code KRB5_LIB_CALL
713 krb5_ret_string(krb5_storage *sp,
714 char **string)
716 int ret;
717 krb5_data data;
718 ret = krb5_ret_data(sp, &data);
719 if(ret)
720 return ret;
721 *string = realloc(data.data, data.length + 1);
722 if(*string == NULL){
723 free(data.data);
724 return ENOMEM;
726 (*string)[data.length] = 0;
727 return 0;
731 * Store a zero terminated string to the buffer. The data is stored
732 * one character at a time until a NUL is stored.
734 * @param sp the storage buffer to write to
735 * @param s the string to store.
737 * @return 0 on success, a Kerberos 5 error code on failure.
739 * @ingroup krb5_storage
742 KRB5_LIB_FUNCTION krb5_error_code KRB5_LIB_CALL
743 krb5_store_stringz(krb5_storage *sp, const char *s)
745 size_t len = strlen(s) + 1;
746 ssize_t ret;
748 ret = sp->store(sp, s, len);
749 if(ret != len) {
750 if(ret < 0)
751 return ret;
752 else
753 return sp->eof_code;
755 return 0;
759 * Parse zero terminated string from the storage.
761 * @param sp the storage buffer to read from
762 * @param string the parsed string
764 * @return 0 on success, a Kerberos 5 error code on failure.
766 * @ingroup krb5_storage
769 KRB5_LIB_FUNCTION krb5_error_code KRB5_LIB_CALL
770 krb5_ret_stringz(krb5_storage *sp,
771 char **string)
773 char c;
774 char *s = NULL;
775 size_t len = 0;
776 ssize_t ret;
778 while((ret = sp->fetch(sp, &c, 1)) == 1){
779 char *tmp;
781 len++;
782 tmp = realloc (s, len);
783 if (tmp == NULL) {
784 free (s);
785 return ENOMEM;
787 s = tmp;
788 s[len - 1] = c;
789 if(c == 0)
790 break;
792 if(ret != 1){
793 free(s);
794 if(ret == 0)
795 return sp->eof_code;
796 return ret;
798 *string = s;
799 return 0;
802 KRB5_LIB_FUNCTION krb5_error_code KRB5_LIB_CALL
803 krb5_store_stringnl(krb5_storage *sp, const char *s)
805 size_t len = strlen(s);
806 ssize_t ret;
808 ret = sp->store(sp, s, len);
809 if(ret != len) {
810 if(ret < 0)
811 return ret;
812 else
813 return sp->eof_code;
815 ret = sp->store(sp, "\n", 1);
816 if(ret != 1) {
817 if(ret < 0)
818 return ret;
819 else
820 return sp->eof_code;
823 return 0;
827 KRB5_LIB_FUNCTION krb5_error_code KRB5_LIB_CALL
828 krb5_ret_stringnl(krb5_storage *sp,
829 char **string)
831 int expect_nl = 0;
832 char c;
833 char *s = NULL;
834 size_t len = 0;
835 ssize_t ret;
837 while((ret = sp->fetch(sp, &c, 1)) == 1){
838 char *tmp;
840 if (c == '\r') {
841 expect_nl = 1;
842 continue;
844 if (expect_nl && c != '\n') {
845 free(s);
846 return KRB5_BADMSGTYPE;
849 len++;
850 tmp = realloc (s, len);
851 if (tmp == NULL) {
852 free (s);
853 return ENOMEM;
855 s = tmp;
856 if(c == '\n') {
857 s[len - 1] = '\0';
858 break;
860 s[len - 1] = c;
862 if(ret != 1){
863 free(s);
864 if(ret == 0)
865 return sp->eof_code;
866 return ret;
868 *string = s;
869 return 0;
873 * Write a principal block to storage.
875 * @param sp the storage buffer to write to
876 * @param p the principal block to write.
878 * @return 0 on success, a Kerberos 5 error code on failure.
880 * @ingroup krb5_storage
883 KRB5_LIB_FUNCTION krb5_error_code KRB5_LIB_CALL
884 krb5_store_principal(krb5_storage *sp,
885 krb5_const_principal p)
887 int i;
888 int ret;
890 if(!krb5_storage_is_flags(sp, KRB5_STORAGE_PRINCIPAL_NO_NAME_TYPE)) {
891 ret = krb5_store_int32(sp, p->name.name_type);
892 if(ret) return ret;
894 if(krb5_storage_is_flags(sp, KRB5_STORAGE_PRINCIPAL_WRONG_NUM_COMPONENTS))
895 ret = krb5_store_int32(sp, p->name.name_string.len + 1);
896 else
897 ret = krb5_store_int32(sp, p->name.name_string.len);
899 if(ret) return ret;
900 ret = krb5_store_string(sp, p->realm);
901 if(ret) return ret;
902 for(i = 0; i < p->name.name_string.len; i++){
903 ret = krb5_store_string(sp, p->name.name_string.val[i]);
904 if(ret) return ret;
906 return 0;
910 * Parse principal from the storage.
912 * @param sp the storage buffer to read from
913 * @param princ the parsed principal
915 * @return 0 on success, a Kerberos 5 error code on failure.
917 * @ingroup krb5_storage
920 KRB5_LIB_FUNCTION krb5_error_code KRB5_LIB_CALL
921 krb5_ret_principal(krb5_storage *sp,
922 krb5_principal *princ)
924 int i;
925 int ret;
926 krb5_principal p;
927 int32_t type;
928 int32_t ncomp;
930 p = calloc(1, sizeof(*p));
931 if(p == NULL)
932 return ENOMEM;
934 if(krb5_storage_is_flags(sp, KRB5_STORAGE_PRINCIPAL_NO_NAME_TYPE))
935 type = KRB5_NT_UNKNOWN;
936 else if((ret = krb5_ret_int32(sp, &type))){
937 free(p);
938 return ret;
940 if((ret = krb5_ret_int32(sp, &ncomp))){
941 free(p);
942 return ret;
944 if(krb5_storage_is_flags(sp, KRB5_STORAGE_PRINCIPAL_WRONG_NUM_COMPONENTS))
945 ncomp--;
946 if (ncomp < 0) {
947 free(p);
948 return EINVAL;
950 p->name.name_type = type;
951 p->name.name_string.len = ncomp;
952 ret = krb5_ret_string(sp, &p->realm);
953 if(ret) {
954 free(p);
955 return ret;
957 p->name.name_string.val = calloc(ncomp, sizeof(*p->name.name_string.val));
958 if(p->name.name_string.val == NULL && ncomp != 0){
959 free(p->realm);
960 free(p);
961 return ENOMEM;
963 for(i = 0; i < ncomp; i++){
964 ret = krb5_ret_string(sp, &p->name.name_string.val[i]);
965 if(ret) {
966 while (i >= 0)
967 free(p->name.name_string.val[i--]);
968 free(p->realm);
969 free(p);
970 return ret;
973 *princ = p;
974 return 0;
978 * Store a keyblock to the storage.
980 * @param sp the storage buffer to write to
981 * @param p the keyblock to write
983 * @return 0 on success, a Kerberos 5 error code on failure.
985 * @ingroup krb5_storage
988 KRB5_LIB_FUNCTION krb5_error_code KRB5_LIB_CALL
989 krb5_store_keyblock(krb5_storage *sp, krb5_keyblock p)
991 int ret;
992 ret = krb5_store_int16(sp, p.keytype);
993 if(ret) return ret;
995 if(krb5_storage_is_flags(sp, KRB5_STORAGE_KEYBLOCK_KEYTYPE_TWICE)){
996 /* this should really be enctype, but it is the same as
997 keytype nowadays */
998 ret = krb5_store_int16(sp, p.keytype);
999 if(ret) return ret;
1002 ret = krb5_store_data(sp, p.keyvalue);
1003 return ret;
1007 * Read a keyblock from the storage.
1009 * @param sp the storage buffer to write to
1010 * @param p the keyblock read from storage, free using krb5_free_keyblock()
1012 * @return 0 on success, a Kerberos 5 error code on failure.
1014 * @ingroup krb5_storage
1017 KRB5_LIB_FUNCTION krb5_error_code KRB5_LIB_CALL
1018 krb5_ret_keyblock(krb5_storage *sp, krb5_keyblock *p)
1020 int ret;
1021 int16_t tmp;
1023 ret = krb5_ret_int16(sp, &tmp);
1024 if(ret) return ret;
1025 p->keytype = tmp;
1027 if(krb5_storage_is_flags(sp, KRB5_STORAGE_KEYBLOCK_KEYTYPE_TWICE)){
1028 ret = krb5_ret_int16(sp, &tmp);
1029 if(ret) return ret;
1032 ret = krb5_ret_data(sp, &p->keyvalue);
1033 return ret;
1037 * Write a times block to storage.
1039 * @param sp the storage buffer to write to
1040 * @param times the times block to write.
1042 * @return 0 on success, a Kerberos 5 error code on failure.
1044 * @ingroup krb5_storage
1047 KRB5_LIB_FUNCTION krb5_error_code KRB5_LIB_CALL
1048 krb5_store_times(krb5_storage *sp, krb5_times times)
1050 int ret;
1051 ret = krb5_store_int32(sp, times.authtime);
1052 if(ret) return ret;
1053 ret = krb5_store_int32(sp, times.starttime);
1054 if(ret) return ret;
1055 ret = krb5_store_int32(sp, times.endtime);
1056 if(ret) return ret;
1057 ret = krb5_store_int32(sp, times.renew_till);
1058 return ret;
1062 * Read a times block from the storage.
1064 * @param sp the storage buffer to write to
1065 * @param times the times block read from storage
1067 * @return 0 on success, a Kerberos 5 error code on failure.
1069 * @ingroup krb5_storage
1072 KRB5_LIB_FUNCTION krb5_error_code KRB5_LIB_CALL
1073 krb5_ret_times(krb5_storage *sp, krb5_times *times)
1075 int ret;
1076 int32_t tmp;
1077 ret = krb5_ret_int32(sp, &tmp);
1078 times->authtime = tmp;
1079 if(ret) return ret;
1080 ret = krb5_ret_int32(sp, &tmp);
1081 times->starttime = tmp;
1082 if(ret) return ret;
1083 ret = krb5_ret_int32(sp, &tmp);
1084 times->endtime = tmp;
1085 if(ret) return ret;
1086 ret = krb5_ret_int32(sp, &tmp);
1087 times->renew_till = tmp;
1088 return ret;
1092 * Write a address block to storage.
1094 * @param sp the storage buffer to write to
1095 * @param p the address block to write.
1097 * @return 0 on success, a Kerberos 5 error code on failure.
1099 * @ingroup krb5_storage
1102 KRB5_LIB_FUNCTION krb5_error_code KRB5_LIB_CALL
1103 krb5_store_address(krb5_storage *sp, krb5_address p)
1105 int ret;
1106 ret = krb5_store_int16(sp, p.addr_type);
1107 if(ret) return ret;
1108 ret = krb5_store_data(sp, p.address);
1109 return ret;
1113 * Read a address block from the storage.
1115 * @param sp the storage buffer to write to
1116 * @param adr the address block read from storage
1118 * @return 0 on success, a Kerberos 5 error code on failure.
1120 * @ingroup krb5_storage
1123 KRB5_LIB_FUNCTION krb5_error_code KRB5_LIB_CALL
1124 krb5_ret_address(krb5_storage *sp, krb5_address *adr)
1126 int16_t t;
1127 int ret;
1128 ret = krb5_ret_int16(sp, &t);
1129 if(ret) return ret;
1130 adr->addr_type = t;
1131 ret = krb5_ret_data(sp, &adr->address);
1132 return ret;
1136 * Write a addresses block to storage.
1138 * @param sp the storage buffer to write to
1139 * @param p the addresses block 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_addrs(krb5_storage *sp, krb5_addresses p)
1149 int i;
1150 int ret;
1151 ret = krb5_store_int32(sp, p.len);
1152 if(ret) return ret;
1153 for(i = 0; i<p.len; i++){
1154 ret = krb5_store_address(sp, p.val[i]);
1155 if(ret) break;
1157 return ret;
1161 * Read a addresses block from the storage.
1163 * @param sp the storage buffer to write to
1164 * @param adr the addresses block read from storage
1166 * @return 0 on success, a Kerberos 5 error code on failure.
1168 * @ingroup krb5_storage
1171 KRB5_LIB_FUNCTION krb5_error_code KRB5_LIB_CALL
1172 krb5_ret_addrs(krb5_storage *sp, krb5_addresses *adr)
1174 int i;
1175 int ret;
1176 int32_t tmp;
1178 ret = krb5_ret_int32(sp, &tmp);
1179 if(ret) return ret;
1180 adr->len = tmp;
1181 ALLOC(adr->val, adr->len);
1182 if (adr->val == NULL && adr->len != 0)
1183 return ENOMEM;
1184 for(i = 0; i < adr->len; i++){
1185 ret = krb5_ret_address(sp, &adr->val[i]);
1186 if(ret) break;
1188 return ret;
1192 * Write a auth data block to storage.
1194 * @param sp the storage buffer to write to
1195 * @param auth the auth data block to write.
1197 * @return 0 on success, a Kerberos 5 error code on failure.
1199 * @ingroup krb5_storage
1202 KRB5_LIB_FUNCTION krb5_error_code KRB5_LIB_CALL
1203 krb5_store_authdata(krb5_storage *sp, krb5_authdata auth)
1205 krb5_error_code ret;
1206 int i;
1207 ret = krb5_store_int32(sp, auth.len);
1208 if(ret) return ret;
1209 for(i = 0; i < auth.len; i++){
1210 ret = krb5_store_int16(sp, auth.val[i].ad_type);
1211 if(ret) break;
1212 ret = krb5_store_data(sp, auth.val[i].ad_data);
1213 if(ret) break;
1215 return 0;
1219 * Read a auth data from the storage.
1221 * @param sp the storage buffer to write to
1222 * @param auth the auth data block read from storage
1224 * @return 0 on success, a Kerberos 5 error code on failure.
1226 * @ingroup krb5_storage
1229 KRB5_LIB_FUNCTION krb5_error_code KRB5_LIB_CALL
1230 krb5_ret_authdata(krb5_storage *sp, krb5_authdata *auth)
1232 krb5_error_code ret;
1233 int32_t tmp;
1234 int16_t tmp2;
1235 int i;
1236 ret = krb5_ret_int32(sp, &tmp);
1237 if(ret) return ret;
1238 ALLOC_SEQ(auth, tmp);
1239 if (auth->val == NULL && tmp != 0)
1240 return ENOMEM;
1241 for(i = 0; i < tmp; i++){
1242 ret = krb5_ret_int16(sp, &tmp2);
1243 if(ret) break;
1244 auth->val[i].ad_type = tmp2;
1245 ret = krb5_ret_data(sp, &auth->val[i].ad_data);
1246 if(ret) break;
1248 return ret;
1251 static int32_t
1252 bitswap32(int32_t b)
1254 int32_t r = 0;
1255 int i;
1256 for (i = 0; i < 32; i++) {
1257 r = r << 1 | (b & 1);
1258 b = b >> 1;
1260 return r;
1264 * Write a credentials block to storage.
1266 * @param sp the storage buffer to write to
1267 * @param creds the creds block to write.
1269 * @return 0 on success, a Kerberos 5 error code on failure.
1271 * @ingroup krb5_storage
1274 KRB5_LIB_FUNCTION krb5_error_code KRB5_LIB_CALL
1275 krb5_store_creds(krb5_storage *sp, krb5_creds *creds)
1277 int ret;
1279 ret = krb5_store_principal(sp, creds->client);
1280 if(ret)
1281 return ret;
1282 ret = krb5_store_principal(sp, creds->server);
1283 if(ret)
1284 return ret;
1285 ret = krb5_store_keyblock(sp, creds->session);
1286 if(ret)
1287 return ret;
1288 ret = krb5_store_times(sp, creds->times);
1289 if(ret)
1290 return ret;
1291 ret = krb5_store_int8(sp, creds->second_ticket.length != 0); /* is_skey */
1292 if(ret)
1293 return ret;
1295 if(krb5_storage_is_flags(sp, KRB5_STORAGE_CREDS_FLAGS_WRONG_BITORDER))
1296 ret = krb5_store_int32(sp, creds->flags.i);
1297 else
1298 ret = krb5_store_int32(sp, bitswap32(TicketFlags2int(creds->flags.b)));
1299 if(ret)
1300 return ret;
1302 ret = krb5_store_addrs(sp, creds->addresses);
1303 if(ret)
1304 return ret;
1305 ret = krb5_store_authdata(sp, creds->authdata);
1306 if(ret)
1307 return ret;
1308 ret = krb5_store_data(sp, creds->ticket);
1309 if(ret)
1310 return ret;
1311 ret = krb5_store_data(sp, creds->second_ticket);
1312 return ret;
1316 * Read a credentials block from the storage.
1318 * @param sp the storage buffer to write to
1319 * @param creds the credentials block read from storage
1321 * @return 0 on success, a Kerberos 5 error code on failure.
1323 * @ingroup krb5_storage
1326 KRB5_LIB_FUNCTION krb5_error_code KRB5_LIB_CALL
1327 krb5_ret_creds(krb5_storage *sp, krb5_creds *creds)
1329 krb5_error_code ret;
1330 int8_t dummy8;
1331 int32_t dummy32;
1333 memset(creds, 0, sizeof(*creds));
1334 ret = krb5_ret_principal (sp, &creds->client);
1335 if(ret) goto cleanup;
1336 ret = krb5_ret_principal (sp, &creds->server);
1337 if(ret) goto cleanup;
1338 ret = krb5_ret_keyblock (sp, &creds->session);
1339 if(ret) goto cleanup;
1340 ret = krb5_ret_times (sp, &creds->times);
1341 if(ret) goto cleanup;
1342 ret = krb5_ret_int8 (sp, &dummy8);
1343 if(ret) goto cleanup;
1344 ret = krb5_ret_int32 (sp, &dummy32);
1345 if(ret) goto cleanup;
1347 * Runtime detect the what is the higher bits of the bitfield. If
1348 * any of the higher bits are set in the input data, it's either a
1349 * new ticket flag (and this code need to be removed), or it's a
1350 * MIT cache (or new Heimdal cache), lets change it to our current
1351 * format.
1354 uint32_t mask = 0xffff0000;
1355 creds->flags.i = 0;
1356 creds->flags.b.anonymous = 1;
1357 if (creds->flags.i & mask)
1358 mask = ~mask;
1359 if (dummy32 & mask)
1360 dummy32 = bitswap32(dummy32);
1362 creds->flags.i = dummy32;
1363 ret = krb5_ret_addrs (sp, &creds->addresses);
1364 if(ret) goto cleanup;
1365 ret = krb5_ret_authdata (sp, &creds->authdata);
1366 if(ret) goto cleanup;
1367 ret = krb5_ret_data (sp, &creds->ticket);
1368 if(ret) goto cleanup;
1369 ret = krb5_ret_data (sp, &creds->second_ticket);
1370 cleanup:
1371 if(ret) {
1372 #if 0
1373 krb5_free_cred_contents(context, creds); /* XXX */
1374 #endif
1376 return ret;
1379 #define SC_CLIENT_PRINCIPAL 0x0001
1380 #define SC_SERVER_PRINCIPAL 0x0002
1381 #define SC_SESSION_KEY 0x0004
1382 #define SC_TICKET 0x0008
1383 #define SC_SECOND_TICKET 0x0010
1384 #define SC_AUTHDATA 0x0020
1385 #define SC_ADDRESSES 0x0040
1388 * Write a tagged credentials block to storage.
1390 * @param sp the storage buffer to write to
1391 * @param creds the creds 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_creds_tag(krb5_storage *sp, krb5_creds *creds)
1401 int ret;
1402 int32_t header = 0;
1404 if (creds->client)
1405 header |= SC_CLIENT_PRINCIPAL;
1406 if (creds->server)
1407 header |= SC_SERVER_PRINCIPAL;
1408 if (creds->session.keytype != ETYPE_NULL)
1409 header |= SC_SESSION_KEY;
1410 if (creds->ticket.data)
1411 header |= SC_TICKET;
1412 if (creds->second_ticket.length)
1413 header |= SC_SECOND_TICKET;
1414 if (creds->authdata.len)
1415 header |= SC_AUTHDATA;
1416 if (creds->addresses.len)
1417 header |= SC_ADDRESSES;
1419 ret = krb5_store_int32(sp, header);
1420 if (ret)
1421 return ret;
1423 if (creds->client) {
1424 ret = krb5_store_principal(sp, creds->client);
1425 if(ret)
1426 return ret;
1429 if (creds->server) {
1430 ret = krb5_store_principal(sp, creds->server);
1431 if(ret)
1432 return ret;
1435 if (creds->session.keytype != ETYPE_NULL) {
1436 ret = krb5_store_keyblock(sp, creds->session);
1437 if(ret)
1438 return ret;
1441 ret = krb5_store_times(sp, creds->times);
1442 if(ret)
1443 return ret;
1444 ret = krb5_store_int8(sp, creds->second_ticket.length != 0); /* is_skey */
1445 if(ret)
1446 return ret;
1448 ret = krb5_store_int32(sp, bitswap32(TicketFlags2int(creds->flags.b)));
1449 if(ret)
1450 return ret;
1452 if (creds->addresses.len) {
1453 ret = krb5_store_addrs(sp, creds->addresses);
1454 if(ret)
1455 return ret;
1458 if (creds->authdata.len) {
1459 ret = krb5_store_authdata(sp, creds->authdata);
1460 if(ret)
1461 return ret;
1464 if (creds->ticket.data) {
1465 ret = krb5_store_data(sp, creds->ticket);
1466 if(ret)
1467 return ret;
1470 if (creds->second_ticket.data) {
1471 ret = krb5_store_data(sp, creds->second_ticket);
1472 if (ret)
1473 return ret;
1476 return ret;
1480 * Read a tagged credentials block from the storage.
1482 * @param sp the storage buffer to write to
1483 * @param creds the credentials block read from storage
1485 * @return 0 on success, a Kerberos 5 error code on failure.
1487 * @ingroup krb5_storage
1490 KRB5_LIB_FUNCTION krb5_error_code KRB5_LIB_CALL
1491 krb5_ret_creds_tag(krb5_storage *sp,
1492 krb5_creds *creds)
1494 krb5_error_code ret;
1495 int8_t dummy8;
1496 int32_t dummy32, header;
1498 memset(creds, 0, sizeof(*creds));
1500 ret = krb5_ret_int32 (sp, &header);
1501 if (ret) goto cleanup;
1503 if (header & SC_CLIENT_PRINCIPAL) {
1504 ret = krb5_ret_principal (sp, &creds->client);
1505 if(ret) goto cleanup;
1507 if (header & SC_SERVER_PRINCIPAL) {
1508 ret = krb5_ret_principal (sp, &creds->server);
1509 if(ret) goto cleanup;
1511 if (header & SC_SESSION_KEY) {
1512 ret = krb5_ret_keyblock (sp, &creds->session);
1513 if(ret) goto cleanup;
1515 ret = krb5_ret_times (sp, &creds->times);
1516 if(ret) goto cleanup;
1517 ret = krb5_ret_int8 (sp, &dummy8);
1518 if(ret) goto cleanup;
1519 ret = krb5_ret_int32 (sp, &dummy32);
1520 if(ret) goto cleanup;
1522 * Runtime detect the what is the higher bits of the bitfield. If
1523 * any of the higher bits are set in the input data, it's either a
1524 * new ticket flag (and this code need to be removed), or it's a
1525 * MIT cache (or new Heimdal cache), lets change it to our current
1526 * format.
1529 uint32_t mask = 0xffff0000;
1530 creds->flags.i = 0;
1531 creds->flags.b.anonymous = 1;
1532 if (creds->flags.i & mask)
1533 mask = ~mask;
1534 if (dummy32 & mask)
1535 dummy32 = bitswap32(dummy32);
1537 creds->flags.i = dummy32;
1538 if (header & SC_ADDRESSES) {
1539 ret = krb5_ret_addrs (sp, &creds->addresses);
1540 if(ret) goto cleanup;
1542 if (header & SC_AUTHDATA) {
1543 ret = krb5_ret_authdata (sp, &creds->authdata);
1544 if(ret) goto cleanup;
1546 if (header & SC_TICKET) {
1547 ret = krb5_ret_data (sp, &creds->ticket);
1548 if(ret) goto cleanup;
1550 if (header & SC_SECOND_TICKET) {
1551 ret = krb5_ret_data (sp, &creds->second_ticket);
1552 if(ret) goto cleanup;
1555 cleanup:
1556 if(ret) {
1557 #if 0
1558 krb5_free_cred_contents(context, creds); /* XXX */
1559 #endif
1561 return ret;