LCOV - code coverage report
Current view: top level - third_party/heimdal/lib/krb5 - store.c (source / functions) Hit Total Coverage
Test: coverage report for master 98b443d9 Lines: 392 886 44.2 %
Date: 2024-05-31 13:13:24 Functions: 47 69 68.1 %

          Line data    Source code
       1             : /*
       2             :  * Copyright (c) 1997-2008 Kungliga Tekniska Högskolan
       3             :  * (Royal Institute of Technology, Stockholm, Sweden).
       4             :  * All rights reserved.
       5             :  *
       6             :  * Redistribution and use in source and binary forms, with or without
       7             :  * modification, are permitted provided that the following conditions
       8             :  * are met:
       9             :  *
      10             :  * 1. Redistributions of source code must retain the above copyright
      11             :  *    notice, this list of conditions and the following disclaimer.
      12             :  *
      13             :  * 2. Redistributions in binary form must reproduce the above copyright
      14             :  *    notice, this list of conditions and the following disclaimer in the
      15             :  *    documentation and/or other materials provided with the distribution.
      16             :  *
      17             :  * 3. Neither the name of the Institute nor the names of its contributors
      18             :  *    may be used to endorse or promote products derived from this software
      19             :  *    without specific prior written permission.
      20             :  *
      21             :  * THIS SOFTWARE IS PROVIDED BY THE INSTITUTE AND CONTRIBUTORS ``AS IS'' AND
      22             :  * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
      23             :  * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
      24             :  * ARE DISCLAIMED.  IN NO EVENT SHALL THE INSTITUTE OR CONTRIBUTORS BE LIABLE
      25             :  * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
      26             :  * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
      27             :  * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
      28             :  * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
      29             :  * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
      30             :  * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
      31             :  * SUCH DAMAGE.
      32             :  */
      33             : 
      34             : #include "krb5_locl.h"
      35             : #include "store-int.h"
      36             : 
      37             : #define BYTEORDER_IS(SP, V) (((SP)->flags & KRB5_STORAGE_BYTEORDER_MASK) == (V))
      38             : #define BYTEORDER_IS_LE(SP) BYTEORDER_IS((SP), KRB5_STORAGE_BYTEORDER_LE)
      39             : #define BYTEORDER_IS_BE(SP) BYTEORDER_IS((SP), KRB5_STORAGE_BYTEORDER_BE)
      40             : #define BYTEORDER_IS_HOST(SP) (BYTEORDER_IS((SP), KRB5_STORAGE_BYTEORDER_HOST) || \
      41             :                                krb5_storage_is_flags((SP), KRB5_STORAGE_HOST_BYTEORDER))
      42             : #define BYTEORDER_IS_PACKED(SP) BYTEORDER_IS((SP), KRB5_STORAGE_BYTEORDER_PACKED)
      43             : 
      44             : /**
      45             :  * Add the flags on a storage buffer by or-ing in the flags to the buffer.
      46             :  *
      47             :  * @param sp the storage buffer to set the flags on
      48             :  * @param flags the flags to set
      49             :  *
      50             :  * @ingroup krb5_storage
      51             :  */
      52             : 
      53             : KRB5_LIB_FUNCTION void KRB5_LIB_CALL
      54      827542 : krb5_storage_set_flags(krb5_storage *sp, krb5_flags flags)
      55             : {
      56      827542 :     sp->flags |= flags;
      57      827542 : }
      58             : 
      59             : /**
      60             :  * Clear the flags on a storage buffer
      61             :  *
      62             :  * @param sp the storage buffer to clear the flags on
      63             :  * @param flags the flags to clear
      64             :  *
      65             :  * @ingroup krb5_storage
      66             :  */
      67             : 
      68             : KRB5_LIB_FUNCTION void KRB5_LIB_CALL
      69           0 : krb5_storage_clear_flags(krb5_storage *sp, krb5_flags flags)
      70             : {
      71           0 :     sp->flags &= ~flags;
      72           0 : }
      73             : 
      74             : /**
      75             :  * Return true or false depending on if the storage flags is set or
      76             :  * not. NB testing for the flag 0 always return true.
      77             :  *
      78             :  * @param sp the storage buffer to check flags on
      79             :  * @param flags The flags to test for
      80             :  *
      81             :  * @return true if all the flags are set, false if not.
      82             :  *
      83             :  * @ingroup krb5_storage
      84             :  */
      85             : 
      86             : KRB5_LIB_FUNCTION krb5_boolean KRB5_LIB_CALL
      87    12756664 : krb5_storage_is_flags(krb5_storage *sp, krb5_flags flags)
      88             : {
      89    12756664 :     return (sp->flags & flags) == flags;
      90             : }
      91             : 
      92             : /**
      93             :  * Set the new byte order of the storage buffer.
      94             :  *
      95             :  * @param sp the storage buffer to set the byte order for.
      96             :  * @param byteorder the new byte order.
      97             :  *
      98             :  * The byte order are: KRB5_STORAGE_BYTEORDER_BE,
      99             :  * KRB5_STORAGE_BYTEORDER_LE and KRB5_STORAGE_BYTEORDER_HOST.
     100             :  *
     101             :  * @ingroup krb5_storage
     102             :  */
     103             : 
     104             : KRB5_LIB_FUNCTION void KRB5_LIB_CALL
     105           0 : krb5_storage_set_byteorder(krb5_storage *sp, krb5_flags byteorder)
     106             : {
     107           0 :     sp->flags &= ~KRB5_STORAGE_BYTEORDER_MASK;
     108           0 :     sp->flags |= byteorder;
     109           0 : }
     110             : 
     111             : /**
     112             :  * Return the current byteorder for the buffer. See krb5_storage_set_byteorder() for the list or byte order contants.
     113             :  *
     114             :  * @ingroup krb5_storage
     115             :  */
     116             : 
     117             : KRB5_LIB_FUNCTION krb5_flags KRB5_LIB_CALL
     118           0 : krb5_storage_get_byteorder(krb5_storage *sp)
     119             : {
     120           0 :     return sp->flags & KRB5_STORAGE_BYTEORDER_MASK;
     121             : }
     122             : 
     123             : /**
     124             :  * Set the max alloc value
     125             :  *
     126             :  * @param sp the storage buffer set the max allow for
     127             :  * @param size maximum size to allocate, use 0 to remove limit
     128             :  *
     129             :  * @ingroup krb5_storage
     130             :  */
     131             : 
     132             : KRB5_LIB_FUNCTION void KRB5_LIB_CALL
     133           0 : krb5_storage_set_max_alloc(krb5_storage *sp, size_t size)
     134             : {
     135           0 :     sp->max_alloc = size;
     136           0 : }
     137             : 
     138             : /* don't allocate unresonable amount of memory */
     139             : static krb5_error_code
     140     1052917 : size_too_large(krb5_storage *sp, size_t size)
     141             : {
     142     1052917 :     if (sp->max_alloc && sp->max_alloc < size)
     143           0 :         return HEIM_ERR_TOO_BIG;
     144     1028780 :     return 0;
     145             : }
     146             : 
     147             : static krb5_error_code
     148      128340 : size_too_large_num(krb5_storage *sp, size_t count, size_t size)
     149             : {
     150      128340 :     if (sp->max_alloc == 0 || size == 0)
     151           0 :         return 0;
     152      128340 :     size = sp->max_alloc / size;
     153      128340 :     if (size < count)
     154           0 :         return HEIM_ERR_TOO_BIG;
     155      128340 :     return 0;
     156             : }
     157             : 
     158             : /**
     159             :  * Seek to a new offset.
     160             :  *
     161             :  * @param sp the storage buffer to seek in.
     162             :  * @param offset the offset to seek
     163             :  * @param whence relateive searching, SEEK_CUR from the current
     164             :  * position, SEEK_END from the end, SEEK_SET absolute from the start.
     165             :  *
     166             :  * @return The new current offset
     167             :  *
     168             :  * @ingroup krb5_storage
     169             :  */
     170             : 
     171             : KRB5_LIB_FUNCTION off_t KRB5_LIB_CALL
     172      797166 : krb5_storage_seek(krb5_storage *sp, off_t offset, int whence)
     173             : {
     174      797166 :     return (*sp->seek)(sp, offset, whence);
     175             : }
     176             : 
     177             : /**
     178             :  * Truncate the storage buffer in sp to offset.
     179             :  *
     180             :  * @param sp the storage buffer to truncate.
     181             :  * @param offset the offset to truncate to.
     182             :  *
     183             :  * @return An Kerberos 5 error code.
     184             :  *
     185             :  * @ingroup krb5_storage
     186             :  */
     187             : 
     188             : KRB5_LIB_FUNCTION int KRB5_LIB_CALL
     189        1850 : krb5_storage_truncate(krb5_storage *sp, off_t offset)
     190             : {
     191        1850 :     return (*sp->trunc)(sp, offset);
     192             : }
     193             : 
     194             : /**
     195             :  * Sync the storage buffer to its backing store.  If there is no
     196             :  * backing store this function will return success.
     197             :  *
     198             :  * @param sp the storage buffer to sync
     199             :  *
     200             :  * @return A Kerberos 5 error code
     201             :  *
     202             :  * @ingroup krb5_storage
     203             :  */
     204             : 
     205             : KRB5_LIB_FUNCTION int KRB5_LIB_CALL
     206        2316 : krb5_storage_fsync(krb5_storage *sp)
     207             : {
     208        2316 :     if (sp->fsync != NULL)
     209        2316 :         return sp->fsync(sp);
     210           0 :     return 0;
     211             : }
     212             : 
     213             : /**
     214             :  * Read to the storage buffer.
     215             :  *
     216             :  * @param sp the storage buffer to read from
     217             :  * @param buf the buffer to store the data in
     218             :  * @param len the length to read
     219             :  *
     220             :  * @return The length of data read (can be shorter then len), or negative on error.
     221             :  *
     222             :  * @ingroup krb5_storage
     223             :  */
     224             : 
     225             : KRB5_LIB_FUNCTION krb5_ssize_t KRB5_LIB_CALL
     226      981965 : krb5_storage_read(krb5_storage *sp, void *buf, size_t len)
     227             : {
     228      981965 :     return sp->fetch(sp, buf, len);
     229             : }
     230             : 
     231             : /**
     232             :  * Write to the storage buffer.
     233             :  *
     234             :  * @param sp the storage buffer to write to
     235             :  * @param buf the buffer to write to the storage buffer
     236             :  * @param len the length to write
     237             :  *
     238             :  * @return The length of data written (can be shorter then len), or negative on error.
     239             :  *
     240             :  * @ingroup krb5_storage
     241             :  */
     242             : 
     243             : KRB5_LIB_FUNCTION krb5_ssize_t KRB5_LIB_CALL
     244     1167529 : krb5_storage_write(krb5_storage *sp, const void *buf, size_t len)
     245             : {
     246     1167529 :     return sp->store(sp, buf, len);
     247             : }
     248             : 
     249             : /**
     250             :  * Set the return code that will be used when end of storage is reached.
     251             :  *
     252             :  * @param sp the storage
     253             :  * @param code the error code to return on end of storage
     254             :  *
     255             :  * @ingroup krb5_storage
     256             :  */
     257             : 
     258             : KRB5_LIB_FUNCTION void KRB5_LIB_CALL
     259       66401 : krb5_storage_set_eof_code(krb5_storage *sp, int code)
     260             : {
     261       66401 :     sp->eof_code = code;
     262       66401 : }
     263             : 
     264             : /**
     265             :  * Get the return code that will be used when end of storage is reached.
     266             :  *
     267             :  * @param sp the storage
     268             :  *
     269             :  * @return storage error code
     270             :  *
     271             :  * @ingroup krb5_storage
     272             :  */
     273             : 
     274             : KRB5_LIB_FUNCTION int KRB5_LIB_CALL
     275           0 : krb5_storage_get_eof_code(krb5_storage *sp)
     276             : {
     277           0 :     return sp->eof_code;
     278             : }
     279             : 
     280             : /**
     281             :  * Free a krb5 storage.
     282             :  *
     283             :  * @param sp the storage to free.
     284             :  *
     285             :  * @return An Kerberos 5 error code.
     286             :  *
     287             :  * @ingroup krb5_storage
     288             :  */
     289             : 
     290             : KRB5_LIB_FUNCTION krb5_error_code KRB5_LIB_CALL
     291     1240747 : krb5_storage_free(krb5_storage *sp)
     292             : {
     293     1240747 :     if (sp == NULL)
     294           0 :         return 0;
     295     1240747 :     if(sp->free)
     296      509595 :         (*sp->free)(sp);
     297     1240747 :     free(sp->data);
     298     1240747 :     free(sp);
     299     1240747 :     return 0;
     300             : }
     301             : 
     302             : /**
     303             :  * Copy the content of storage to a krb5_data.
     304             :  *
     305             :  * @param sp the storage to copy to a data
     306             :  * @param data the copied data, free with krb5_data_free()
     307             :  *
     308             :  * @return 0 for success, or a Kerberos 5 error code on failure.
     309             :  *
     310             :  * @ingroup krb5_storage
     311             :  */
     312             : 
     313             : KRB5_LIB_FUNCTION krb5_error_code KRB5_LIB_CALL
     314      444611 : krb5_storage_to_data(krb5_storage *sp, krb5_data *data)
     315             : {
     316       14824 :     off_t pos, size;
     317       14824 :     krb5_error_code ret;
     318             : 
     319      444611 :     pos = sp->seek(sp, 0, SEEK_CUR);
     320      444611 :     if (pos < 0)
     321           0 :         return HEIM_ERR_NOT_SEEKABLE;
     322      444611 :     size = sp->seek(sp, 0, SEEK_END);
     323      444611 :     ret = size_too_large(sp, size);
     324      429787 :     if (ret)
     325           0 :         return ret;
     326      444611 :     ret = krb5_data_alloc(data, size);
     327      444611 :     if (ret) {
     328           0 :         sp->seek(sp, pos, SEEK_SET);
     329           0 :         return ret;
     330             :     }
     331      444611 :     if (size) {
     332       14824 :         ssize_t bytes;
     333             : 
     334      444611 :         sp->seek(sp, 0, SEEK_SET);
     335      444611 :         bytes = sp->fetch(sp, data->data, data->length);
     336      444611 :         sp->seek(sp, pos, SEEK_SET);
     337             : 
     338             :         /* sp->fetch() really shouldn't fail */
     339      444611 :         if (bytes < 0)
     340           0 :             return sp->eof_code;
     341             : 
     342             :         /* Maybe the underlying file (or whatever) got truncated? */
     343      444611 :         data->length = bytes;
     344             :     }
     345      429787 :     return 0;
     346             : }
     347             : 
     348             : static size_t
     349           0 : pack_int(uint8_t *p, uint64_t val)
     350             : {
     351           0 :     size_t l = 0;
     352             : 
     353           0 :     if (val < 128) {
     354           0 :         *p = val;
     355             :     } else {
     356           0 :         while (val > 0) {
     357           0 :             *p-- = val % 256;
     358           0 :             val /= 256;
     359           0 :             l++;
     360             :         }
     361           0 :         *p = 0x80 | l;
     362             :     }
     363           0 :     return l + 1;
     364             : }
     365             : 
     366             : static size_t
     367           0 : unpack_int_length(uint8_t *v)
     368             : {
     369           0 :     size_t size;
     370             : 
     371           0 :     if (*v < 128)
     372           0 :         size = 0;
     373             :     else
     374           0 :         size = *v & 0x7f;
     375             : 
     376           0 :     return size + 1;
     377             : }
     378             : 
     379             : static int
     380           0 : unpack_int(uint8_t *p, size_t len, uint64_t *val, size_t *size)
     381             : {
     382           0 :     size_t v;
     383             : 
     384           0 :     if (len == 0)
     385           0 :         return EINVAL;
     386           0 :     --len;
     387           0 :     v = *p++;
     388           0 :     if (v < 128) {
     389           0 :         *val = v;
     390           0 :         *size = 1;
     391             :     } else {
     392           0 :         int e;
     393           0 :         size_t l;
     394           0 :         uint64_t tmp;
     395             : 
     396           0 :         if (v == 0x80) {
     397           0 :             *size = 1;
     398           0 :             return EINVAL;
     399             :         }
     400           0 :         v &= 0x7F;
     401           0 :         if (len < v)
     402           0 :             return ERANGE;
     403           0 :         e = der_get_unsigned64(p, v, &tmp, &l);
     404           0 :         if (e)
     405           0 :             return ERANGE;
     406           0 :         *val = tmp;
     407           0 :         *size = l + 1;
     408             :     }
     409           0 :     return 0;
     410             : }
     411             : 
     412             : static krb5_error_code
     413     3058109 : krb5_store_int(krb5_storage *sp,
     414             :                int64_t value,
     415             :                size_t len)
     416             : {
     417      107808 :     int ret;
     418     3058109 :     uint8_t v[9], *p = v;
     419             : 
     420     3058109 :     if (len > sizeof(value))
     421           0 :         return EINVAL;
     422             : 
     423     3058109 :     if (BYTEORDER_IS_PACKED(sp)) {
     424           0 :         uint64_t mask = ~0ULL >> (64 - len * 8);
     425           0 :         value &= mask;
     426           0 :         p += sizeof(v) - 1;
     427           0 :         len = pack_int(p, value);
     428           0 :         p = v + sizeof(v) - len;
     429             :     } else
     430     3058109 :         _krb5_put_int(v, value, len);
     431     3058109 :     ret = sp->store(sp, p, len);
     432     3058109 :     if (ret < 0)
     433           0 :         return errno;
     434     3058109 :     if ((size_t)ret != len)
     435           0 :         return sp->eof_code;
     436     2950301 :     return 0;
     437             : }
     438             : 
     439             : /**
     440             :  * Store a int32 to storage, byte order is controlled by the settings
     441             :  * on the storage, see krb5_storage_set_byteorder().
     442             :  *
     443             :  * @param sp the storage to write to
     444             :  * @param value the value to store
     445             :  *
     446             :  * @return 0 for success, or a Kerberos 5 error code on failure.
     447             :  *
     448             :  * @ingroup krb5_storage
     449             :  */
     450             : 
     451             : KRB5_LIB_FUNCTION krb5_error_code KRB5_LIB_CALL
     452     2253870 : krb5_store_int32(krb5_storage *sp,
     453             :                  int32_t value)
     454             : {
     455     2253870 :     if(BYTEORDER_IS_HOST(sp))
     456           0 :         value = htonl(value);
     457     2253870 :     else if(BYTEORDER_IS_LE(sp))
     458     1786706 :         value = bswap32(value);
     459     2253870 :     return krb5_store_int(sp, value, 4);
     460             : }
     461             : 
     462             : /**
     463             :  * Store a int64 to storage, byte order is controlled by the settings
     464             :  * on the storage, see krb5_storage_set_byteorder().
     465             :  *
     466             :  * @param sp the storage to write to
     467             :  * @param value the value to store
     468             :  *
     469             :  * @return 0 for success, or a Kerberos 5 error code on failure.
     470             :  *
     471             :  * @ingroup krb5_storage
     472             :  */
     473             : 
     474             : KRB5_LIB_FUNCTION krb5_error_code KRB5_LIB_CALL
     475      631955 : krb5_store_int64(krb5_storage *sp,
     476             :                  int64_t value)
     477             : {
     478      631955 :     if (BYTEORDER_IS_HOST(sp))
     479             : #ifdef WORDS_BIGENDIAN
     480             :         ;
     481             : #else
     482           0 :         value = bswap64(value); /* There's no ntohll() */
     483             : #endif
     484      631955 :     else if (BYTEORDER_IS_LE(sp))
     485      631955 :         value = bswap64(value);
     486      631955 :     return krb5_store_int(sp, value, 8);
     487             : }
     488             : 
     489             : /**
     490             :  * Store a uint32 to storage, byte order is controlled by the settings
     491             :  * on the storage, see krb5_storage_set_byteorder().
     492             :  *
     493             :  * @param sp the storage to write to
     494             :  * @param value the value to store
     495             :  *
     496             :  * @return 0 for success, or a Kerberos 5 error code on failure.
     497             :  *
     498             :  * @ingroup krb5_storage
     499             :  */
     500             : 
     501             : KRB5_LIB_FUNCTION krb5_error_code KRB5_LIB_CALL
     502     1788231 : krb5_store_uint32(krb5_storage *sp,
     503             :                   uint32_t value)
     504             : {
     505     1788231 :     return krb5_store_int32(sp, (int32_t)value);
     506             : }
     507             : 
     508             : /**
     509             :  * Store a uint64 to storage, byte order is controlled by the settings
     510             :  * on the storage, see krb5_storage_set_byteorder().
     511             :  *
     512             :  * @param sp the storage to write to
     513             :  * @param value the value to store
     514             :  *
     515             :  * @return 0 for success, or a Kerberos 5 error code on failure.
     516             :  *
     517             :  * @ingroup krb5_storage
     518             :  */
     519             : 
     520             : KRB5_LIB_FUNCTION krb5_error_code KRB5_LIB_CALL
     521      631955 : krb5_store_uint64(krb5_storage *sp,
     522             :                   uint64_t value)
     523             : {
     524      631955 :     return krb5_store_int64(sp, (int64_t)value);
     525             : }
     526             : 
     527             : static krb5_error_code
     528     8980581 : krb5_ret_int(krb5_storage *sp,
     529             :              int64_t *value,
     530             :              size_t len)
     531             : {
     532      189341 :     int ret;
     533      189341 :     unsigned char v[9];
     534     8980581 :     uint64_t w = 0;
     535     8980581 :     *value = 0; /* quiets warnings */
     536     8980581 :     if (BYTEORDER_IS_PACKED(sp)) {
     537           0 :         ret = sp->fetch(sp, v, 1);
     538           0 :         if (ret < 0)
     539           0 :             return errno;
     540           0 :         if (ret != 1)
     541           0 :             return sp->eof_code;
     542             : 
     543           0 :         len = unpack_int_length(v);
     544           0 :         if (len < 1)
     545           0 :             return ERANGE;
     546           0 :         else if (len > 1) {
     547           0 :             ret = sp->fetch(sp, v + 1, len - 1);
     548           0 :             if (ret < 0)
     549           0 :                 return errno;
     550           0 :             if (ret != len - 1)
     551           0 :                 return sp->eof_code;
     552             :         }
     553           0 :         ret = unpack_int(v, len, &w, &len);
     554           0 :         if (ret)
     555           0 :             return ret;
     556           0 :         *value = w;
     557           0 :         return 0;
     558             :     }
     559     8980581 :     ret = sp->fetch(sp, v, len);
     560     8980581 :     if (ret < 0)
     561           0 :         return errno;
     562     8980581 :     if ((size_t)ret != len)
     563       29519 :         return sp->eof_code;
     564     8951062 :     _krb5_get_int64(v, &w, len);
     565     8951062 :     *value = w;
     566     8951062 :     return 0;
     567             : }
     568             : 
     569             : /**
     570             :  * Read a int64 from storage, byte order is controlled by the settings
     571             :  * on the storage, see krb5_storage_set_byteorder().
     572             :  *
     573             :  * @param sp the storage to write to
     574             :  * @param value the value read from the buffer
     575             :  *
     576             :  * @return 0 for success, or a Kerberos 5 error code on failure.
     577             :  *
     578             :  * @ingroup krb5_storage
     579             :  */
     580             : 
     581             : KRB5_LIB_FUNCTION krb5_error_code KRB5_LIB_CALL
     582     1249817 : krb5_ret_int64(krb5_storage *sp,
     583             :                int64_t *value)
     584             : {
     585     1249817 :     krb5_error_code ret = krb5_ret_int(sp, value, 8);
     586     1249817 :     if(ret)
     587           0 :         return ret;
     588     1249817 :     if(BYTEORDER_IS_HOST(sp))
     589             : #ifdef WORDS_BIGENDIAN
     590             :         ;
     591             : #else
     592           0 :         *value = bswap64(*value); /* There's no ntohll() */
     593             : #endif
     594     1249817 :     else if(BYTEORDER_IS_LE(sp))
     595     1249817 :         *value = bswap64(*value);
     596     1222225 :     return 0;
     597             : }
     598             : 
     599             : /**
     600             :  * Read a uint64 from storage, byte order is controlled by the settings
     601             :  * on the storage, see krb5_storage_set_byteorder().
     602             :  *
     603             :  * @param sp the storage to write to
     604             :  * @param value the value read from the buffer
     605             :  *
     606             :  * @return 0 for success, or a Kerberos 5 error code on failure.
     607             :  *
     608             :  * @ingroup krb5_storage
     609             :  */
     610             : 
     611             : KRB5_LIB_FUNCTION krb5_error_code KRB5_LIB_CALL
     612     1249817 : krb5_ret_uint64(krb5_storage *sp,
     613             :                 uint64_t *value)
     614             : {
     615       27592 :     krb5_error_code ret;
     616       27592 :     int64_t v;
     617             : 
     618     1249817 :     ret = krb5_ret_int64(sp, &v);
     619     1249817 :     if (ret == 0)
     620     1249817 :         *value = (uint64_t)v;
     621             : 
     622     1249817 :     return ret;
     623             : }
     624             : 
     625             : /**
     626             :  * Read a int32 from storage, byte order is controlled by the settings
     627             :  * on the storage, see krb5_storage_set_byteorder().
     628             :  *
     629             :  * @param sp the storage to write to
     630             :  * @param value the value read from the buffer
     631             :  *
     632             :  * @return 0 for success, or a Kerberos 5 error code on failure.
     633             :  *
     634             :  * @ingroup krb5_storage
     635             :  */
     636             : 
     637             : KRB5_LIB_FUNCTION krb5_error_code KRB5_LIB_CALL
     638     5490104 : krb5_ret_int32(krb5_storage *sp,
     639             :                int32_t *value)
     640             : {
     641      112584 :     int64_t v;
     642             : 
     643     5490104 :     krb5_error_code ret = krb5_ret_int(sp, &v, 4);
     644     5490104 :     if (ret)
     645       29075 :         return ret;
     646     5460585 :     *value = v;
     647     5460585 :     if (BYTEORDER_IS_HOST(sp))
     648           0 :         *value = htonl(*value);
     649     5460585 :     else if (BYTEORDER_IS_LE(sp))
     650     3328209 :         *value = bswap32(*value);
     651     5348445 :     return 0;
     652             : }
     653             : 
     654             : /**
     655             :  * Read a uint32 from storage, byte order is controlled by the settings
     656             :  * on the storage, see krb5_storage_set_byteorder().
     657             :  *
     658             :  * @param sp the storage to write to
     659             :  * @param value the value read from the buffer
     660             :  *
     661             :  * @return 0 for success, or a Kerberos 5 error code on failure.
     662             :  *
     663             :  * @ingroup krb5_storage
     664             :  */
     665             : 
     666             : KRB5_LIB_FUNCTION krb5_error_code KRB5_LIB_CALL
     667     3772897 : krb5_ret_uint32(krb5_storage *sp, uint32_t *value)
     668             : {
     669       84518 :     krb5_error_code ret;
     670       84518 :     int32_t v;
     671             : 
     672     3772897 :     ret = krb5_ret_int32(sp, &v);
     673     3772897 :     if (ret == 0)
     674     3772897 :         *value = (uint32_t)v;
     675             : 
     676     3772897 :     return ret;
     677             : }
     678             : 
     679             : /**
     680             :  * Store a int16 to storage, byte order is controlled by the settings
     681             :  * on the storage, see krb5_storage_set_byteorder().
     682             :  *
     683             :  * @param sp the storage to write to
     684             :  * @param value the value to store
     685             :  *
     686             :  * @return 0 for success, or a Kerberos 5 error code on failure.
     687             :  *
     688             :  * @ingroup krb5_storage
     689             :  */
     690             : 
     691             : KRB5_LIB_FUNCTION krb5_error_code KRB5_LIB_CALL
     692      172284 : krb5_store_int16(krb5_storage *sp,
     693             :                  int16_t value)
     694             : {
     695      172284 :     if(BYTEORDER_IS_HOST(sp))
     696           0 :         value = htons(value);
     697      172284 :     else if(BYTEORDER_IS_LE(sp))
     698       84962 :         value = bswap16(value);
     699      172284 :     return krb5_store_int(sp, value, 2);
     700             : }
     701             : 
     702             : /**
     703             :  * Store a uint16 to storage, byte order is controlled by the settings
     704             :  * on the storage, see krb5_storage_set_byteorder().
     705             :  *
     706             :  * @param sp the storage to write to
     707             :  * @param value the value to store
     708             :  *
     709             :  * @return 0 for success, or a Kerberos 5 error code on failure.
     710             :  *
     711             :  * @ingroup krb5_storage
     712             :  */
     713             : 
     714             : KRB5_LIB_FUNCTION krb5_error_code KRB5_LIB_CALL
     715       84962 : krb5_store_uint16(krb5_storage *sp,
     716             :                   uint16_t value)
     717             : {
     718       84962 :     return krb5_store_int16(sp, (int16_t)value);
     719             : }
     720             : 
     721             : /**
     722             :  * Read a int16 from storage, byte order is controlled by the settings
     723             :  * on the storage, see krb5_storage_set_byteorder().
     724             :  *
     725             :  * @param sp the storage to write to
     726             :  * @param value the value read from the buffer
     727             :  *
     728             :  * @return 0 for success, or a Kerberos 5 error code on failure.
     729             :  *
     730             :  * @ingroup krb5_storage
     731             :  */
     732             : 
     733             : KRB5_LIB_FUNCTION krb5_error_code KRB5_LIB_CALL
     734     2240660 : krb5_ret_int16(krb5_storage *sp,
     735             :                int16_t *value)
     736             : {
     737       49165 :     int64_t v;
     738       49165 :     int ret;
     739     2240660 :     ret = krb5_ret_int(sp, &v, 2);
     740     2240660 :     if(ret)
     741           0 :         return ret;
     742     2240660 :     *value = v;
     743     2240660 :     if(BYTEORDER_IS_HOST(sp))
     744           0 :         *value = htons(*value);
     745     2240660 :     else if(BYTEORDER_IS_LE(sp))
     746      932628 :         *value = bswap16(*value);
     747     2191495 :     return 0;
     748             : }
     749             : 
     750             : /**
     751             :  * Read a int16 from storage, byte order is controlled by the settings
     752             :  * on the storage, see krb5_storage_set_byteorder().
     753             :  *
     754             :  * @param sp the storage to write to
     755             :  * @param value the value read from the buffer
     756             :  *
     757             :  * @return 0 for success, or a Kerberos 5 error code on failure.
     758             :  *
     759             :  * @ingroup krb5_storage
     760             :  */
     761             : 
     762             : KRB5_LIB_FUNCTION krb5_error_code KRB5_LIB_CALL
     763      932628 : krb5_ret_uint16(krb5_storage *sp,
     764             :                 uint16_t *value)
     765             : {
     766       23040 :     krb5_error_code ret;
     767       23040 :     int16_t v;
     768             : 
     769      932628 :     ret = krb5_ret_int16(sp, &v);
     770      932628 :     if (ret == 0)
     771      932628 :         *value = (uint16_t)v;
     772             : 
     773      932628 :     return ret;
     774             : }
     775             : 
     776             : /**
     777             :  * Store a int8 to storage.
     778             :  *
     779             :  * @param sp the storage to write to
     780             :  * @param value the value to store
     781             :  *
     782             :  * @return 0 for success, or a Kerberos 5 error code on failure.
     783             :  *
     784             :  * @ingroup krb5_storage
     785             :  */
     786             : 
     787             : KRB5_LIB_FUNCTION krb5_error_code KRB5_LIB_CALL
     788        5296 : krb5_store_int8(krb5_storage *sp,
     789             :                 int8_t value)
     790             : {
     791         275 :     int ret;
     792             : 
     793        5296 :     ret = sp->store(sp, &value, sizeof(value));
     794        5296 :     if (ret != sizeof(value))
     795           0 :         return (ret<0)?errno:sp->eof_code;
     796        5021 :     return 0;
     797             : }
     798             : 
     799             : /**
     800             :  * Store a uint8 to storage.
     801             :  *
     802             :  * @param sp the storage to write to
     803             :  * @param value the value to store
     804             :  *
     805             :  * @return 0 for success, or a Kerberos 5 error code on failure.
     806             :  *
     807             :  * @ingroup krb5_storage
     808             :  */
     809             : 
     810             : KRB5_LIB_FUNCTION krb5_error_code KRB5_LIB_CALL
     811           0 : krb5_store_uint8(krb5_storage *sp,
     812             :                  uint8_t value)
     813             : {
     814           0 :     return krb5_store_int8(sp, (int8_t)value);
     815             : }
     816             : 
     817             : /**
     818             :  * Read a int8 from storage
     819             :  *
     820             :  * @param sp the storage to write to
     821             :  * @param value the value read from the buffer
     822             :  *
     823             :  * @return 0 for success, or a Kerberos 5 error code on failure.
     824             :  *
     825             :  * @ingroup krb5_storage
     826             :  */
     827             : 
     828             : KRB5_LIB_FUNCTION krb5_error_code KRB5_LIB_CALL
     829      370734 : krb5_ret_int8(krb5_storage *sp,
     830             :               int8_t *value)
     831             : {
     832        7153 :     ssize_t ret;
     833             : 
     834      370734 :     ret = sp->fetch(sp, value, sizeof(*value));
     835      370734 :     if (ret < 0 || (size_t)ret != sizeof(*value))
     836           0 :         return (ret<0)?errno:sp->eof_code;
     837      363581 :     return 0;
     838             : }
     839             : 
     840             : /**
     841             :  * Read a uint8 from storage
     842             :  *
     843             :  * @param sp the storage to write to
     844             :  * @param value the value read from the buffer
     845             :  *
     846             :  * @return 0 for success, or a Kerberos 5 error code on failure.
     847             :  *
     848             :  * @ingroup krb5_storage
     849             :  */
     850             : 
     851             : KRB5_LIB_FUNCTION krb5_error_code KRB5_LIB_CALL
     852           0 : krb5_ret_uint8(krb5_storage *sp,
     853             :                uint8_t *value)
     854             : {
     855           0 :     krb5_error_code ret;
     856           0 :     int8_t v;
     857             : 
     858           0 :     ret = krb5_ret_int8(sp, &v);
     859           0 :     if (ret == 0)
     860           0 :         *value = (uint8_t)v;
     861             : 
     862           0 :     return ret;
     863             : }
     864             : 
     865             : /**
     866             :  * Store a data to the storage. The data is stored with an int32 as
     867             :  * lenght plus the data (not padded).
     868             :  *
     869             :  * @param sp the storage buffer to write to
     870             :  * @param data the buffer to store.
     871             :  *
     872             :  * @return 0 on success, a Kerberos 5 error code on failure.
     873             :  *
     874             :  * @ingroup krb5_storage
     875             :  */
     876             : 
     877             : KRB5_LIB_FUNCTION krb5_error_code KRB5_LIB_CALL
     878      358944 : krb5_store_data(krb5_storage *sp,
     879             :                 krb5_data data)
     880             : {
     881       10985 :     int ret;
     882      358944 :     ret = krb5_store_int32(sp, data.length);
     883      358944 :     if(ret < 0)
     884           0 :         return ret;
     885      358944 :     ret = sp->store(sp, data.data, data.length);
     886      358944 :     if(ret < 0)
     887           0 :         return errno;
     888      358944 :     if((size_t)ret != data.length)
     889           0 :         return sp->eof_code;
     890      347959 :     return 0;
     891             : }
     892             : 
     893             : /**
     894             :  * Store a data blob to the storage. The data is stored with an int32 as
     895             :  * length plus the data (not padded).  This function only differs from
     896             :  * krb5_store_data() insofar as it takes a void * and a length as parameters.
     897             :  *
     898             :  * @param sp the storage buffer to write to
     899             :  * @param s the string to store.
     900             :  * @param len length of the string to be stored.
     901             :  *
     902             :  * @return 0 on success, a Kerberos 5 error code on failure.
     903             :  *
     904             :  * @ingroup krb5_storage
     905             :  */
     906             : KRB5_LIB_FUNCTION krb5_error_code KRB5_LIB_CALL
     907           0 : krb5_store_datalen(krb5_storage *sp, const void *d, size_t len)
     908             : {
     909           0 :     krb5_data data;
     910           0 :     data.length = len;
     911           0 :     data.data = (void *)d;
     912           0 :     return krb5_store_data(sp, data);
     913             : }
     914             : 
     915             : /**
     916             :  * Store a data blob to the storage. The data is stored without a length.
     917             :  *
     918             :  * @param sp the storage buffer to write to
     919             :  * @param s the string to store.
     920             :  * @param len length of the string to be stored.
     921             :  *
     922             :  * @return 0 on success, a Kerberos 5 error code on failure.
     923             :  *
     924             :  * @ingroup krb5_storage
     925             :  */
     926             : KRB5_LIB_FUNCTION krb5_error_code KRB5_LIB_CALL
     927           0 : krb5_store_bytes(krb5_storage *sp, const void *d, size_t len)
     928             : {
     929           0 :     ssize_t ssize;
     930             : 
     931           0 :     ssize = krb5_storage_write(sp, d, len);
     932           0 :     if (ssize != len)
     933           0 :         return ENOMEM;
     934             : 
     935           0 :     return 0;
     936             : }
     937             : 
     938             : /**
     939             :  * Parse a data from the storage.
     940             :  *
     941             :  * @param sp the storage buffer to read from
     942             :  * @param data the parsed data
     943             :  *
     944             :  * @return 0 on success, a Kerberos 5 error code on failure.
     945             :  *
     946             :  * @ingroup krb5_storage
     947             :  */
     948             : 
     949             : KRB5_LIB_FUNCTION krb5_error_code KRB5_LIB_CALL
     950      631392 : krb5_ret_data(krb5_storage *sp,
     951             :               krb5_data *data)
     952             : {
     953        9313 :     krb5_error_code ret;
     954        9313 :     int32_t size;
     955             : 
     956      631392 :     ret = krb5_ret_int32(sp, &size);
     957      631392 :     if(ret)
     958       23086 :         return ret;
     959      608306 :     ret = size_too_large(sp, size);
     960      598993 :     if (ret)
     961           0 :         return ret;
     962      608306 :     ret = krb5_data_alloc (data, size);
     963      608306 :     if (ret)
     964           0 :         return ret;
     965      608306 :     if (size) {
     966        5945 :         ssize_t bytes;
     967             : 
     968      481759 :         bytes = sp->fetch(sp, data->data, size);
     969      481759 :         if (bytes < 0 || bytes != size) {
     970           0 :             krb5_data_free(data);
     971           0 :             return (bytes < 0)? errno : sp->eof_code;
     972             :         }
     973             :     }
     974      598993 :     return 0;
     975             : }
     976             : 
     977             : /**
     978             :  * Store a string to the buffer. The data is formated as an len:uint32
     979             :  * plus the string itself (not padded).
     980             :  *
     981             :  * @param sp the storage buffer to write to
     982             :  * @param s the string to store.
     983             :  *
     984             :  * @return 0 on success, a Kerberos 5 error code on failure.
     985             :  *
     986             :  * @ingroup krb5_storage
     987             :  */
     988             : 
     989             : KRB5_LIB_FUNCTION krb5_error_code KRB5_LIB_CALL
     990      242133 : krb5_store_string(krb5_storage *sp, const char *s)
     991             : {
     992        8328 :     krb5_data data;
     993             : 
     994      242133 :     if (s == NULL)
     995           0 :         return EINVAL;
     996             : 
     997      242133 :     data.length = strlen(s);
     998      242133 :     data.data = rk_UNCONST(s);
     999      242133 :     return krb5_store_data(sp, data);
    1000             : }
    1001             : 
    1002             : /**
    1003             :  * Parse a string from the storage.
    1004             :  *
    1005             :  * @param sp the storage buffer to read from
    1006             :  * @param string the parsed string
    1007             :  *
    1008             :  * @return 0 on success, a Kerberos 5 error code on failure.
    1009             :  *
    1010             :  * @ingroup krb5_storage
    1011             :  */
    1012             : 
    1013             : 
    1014             : KRB5_LIB_FUNCTION krb5_error_code KRB5_LIB_CALL
    1015      399048 : krb5_ret_string(krb5_storage *sp,
    1016             :                 char **string)
    1017             : {
    1018        8328 :     int ret;
    1019        8328 :     krb5_data data;
    1020             : 
    1021      399048 :     *string = NULL;
    1022      399048 :     ret = krb5_ret_data(sp, &data);
    1023      399048 :     if(ret)
    1024           0 :         return ret;
    1025      399048 :     *string = realloc(data.data, data.length + 1);
    1026      399048 :     if(*string == NULL){
    1027           0 :         free(data.data);
    1028           0 :         return ENOMEM;
    1029             :     }
    1030      399048 :     (*string)[data.length] = 0;
    1031      399048 :     return 0;
    1032             : }
    1033             : 
    1034             : /**
    1035             :  * Store a zero terminated string to the buffer. The data is stored
    1036             :  * one character at a time until a NUL is stored.
    1037             :  *
    1038             :  * @param sp the storage buffer to write to
    1039             :  * @param s the string to store.
    1040             :  *
    1041             :  * @return 0 on success, a Kerberos 5 error code on failure.
    1042             :  *
    1043             :  * @ingroup krb5_storage
    1044             :  */
    1045             : 
    1046             : KRB5_LIB_FUNCTION krb5_error_code KRB5_LIB_CALL
    1047           0 : krb5_store_stringz(krb5_storage *sp, const char *s)
    1048             : {
    1049           0 :     size_t len;
    1050           0 :     ssize_t ret;
    1051             : 
    1052           0 :     if (s == NULL)
    1053           0 :         return EINVAL;
    1054             : 
    1055           0 :     len = strlen(s) + 1;
    1056           0 :     ret = sp->store(sp, s, len);
    1057           0 :     if(ret < 0)
    1058           0 :         return ret;
    1059           0 :     if((size_t)ret != len)
    1060           0 :         return sp->eof_code;
    1061           0 :     return 0;
    1062             : }
    1063             : 
    1064             : /**
    1065             :  * Parse zero terminated string from the storage.
    1066             :  *
    1067             :  * @param sp the storage buffer to read from
    1068             :  * @param string the parsed string
    1069             :  *
    1070             :  * @return 0 on success, a Kerberos 5 error code on failure.
    1071             :  *
    1072             :  * @ingroup krb5_storage
    1073             :  */
    1074             : 
    1075             : KRB5_LIB_FUNCTION krb5_error_code KRB5_LIB_CALL
    1076           0 : krb5_ret_stringz(krb5_storage *sp,
    1077             :                 char **string)
    1078             : {
    1079           0 :     char c;
    1080           0 :     char *s = NULL;
    1081           0 :     size_t len = 0;
    1082           0 :     ssize_t ret;
    1083             : 
    1084           0 :     while((ret = sp->fetch(sp, &c, 1)) == 1){
    1085           0 :         krb5_error_code eret;
    1086           0 :         char *tmp;
    1087             : 
    1088           0 :         len++;
    1089           0 :         eret = size_too_large(sp, len);
    1090           0 :         if (eret) {
    1091           0 :             free(s);
    1092           0 :             return eret;
    1093             :         }
    1094           0 :         tmp = realloc (s, len);
    1095           0 :         if (tmp == NULL) {
    1096           0 :             free (s);
    1097           0 :             return ENOMEM;
    1098             :         }
    1099           0 :         s = tmp;
    1100           0 :         s[len - 1] = c;
    1101           0 :         if(c == 0)
    1102           0 :             break;
    1103             :     }
    1104           0 :     if(ret != 1){
    1105           0 :         free(s);
    1106           0 :         if(ret == 0)
    1107           0 :             return sp->eof_code;
    1108           0 :         return ret;
    1109             :     }
    1110           0 :     *string = s;
    1111           0 :     return 0;
    1112             : }
    1113             : 
    1114             : KRB5_LIB_FUNCTION krb5_error_code KRB5_LIB_CALL
    1115           0 : krb5_store_stringnl(krb5_storage *sp, const char *s)
    1116             : {
    1117           0 :     size_t len;
    1118           0 :     ssize_t ret;
    1119             : 
    1120           0 :     if (s == NULL)
    1121           0 :         return EINVAL;
    1122             : 
    1123           0 :     len = strlen(s);
    1124           0 :     ret = sp->store(sp, s, len);
    1125           0 :     if(ret < 0)
    1126           0 :         return ret;
    1127           0 :     if((size_t)ret != len)
    1128           0 :         return sp->eof_code;
    1129           0 :     ret = sp->store(sp, "\n", 1);
    1130           0 :     if(ret != 1) {
    1131           0 :         if(ret < 0)
    1132           0 :             return ret;
    1133             :         else
    1134           0 :             return sp->eof_code;
    1135             :     }
    1136             : 
    1137           0 :     return 0;
    1138             : 
    1139             : }
    1140             : 
    1141             : KRB5_LIB_FUNCTION krb5_error_code KRB5_LIB_CALL
    1142           0 : krb5_ret_stringnl(krb5_storage *sp,
    1143             :                   char **string)
    1144             : {
    1145           0 :     int expect_nl = 0;
    1146           0 :     char c;
    1147           0 :     char *s = NULL;
    1148           0 :     size_t len = 0;
    1149           0 :     ssize_t ret;
    1150             : 
    1151           0 :     while((ret = sp->fetch(sp, &c, 1)) == 1){
    1152           0 :         krb5_error_code eret;
    1153           0 :         char *tmp;
    1154             : 
    1155           0 :         if (c == '\r') {
    1156           0 :             expect_nl = 1;
    1157           0 :             continue;
    1158             :         }
    1159           0 :         if (expect_nl && c != '\n') {
    1160           0 :             free(s);
    1161           0 :             return KRB5_BADMSGTYPE;
    1162             :         }
    1163             : 
    1164           0 :         len++;
    1165           0 :         eret = size_too_large(sp, len);
    1166           0 :         if (eret) {
    1167           0 :             free(s);
    1168           0 :             return eret;
    1169             :         }
    1170           0 :         tmp = realloc (s, len);
    1171           0 :         if (tmp == NULL) {
    1172           0 :             free (s);
    1173           0 :             return ENOMEM;
    1174             :         }
    1175           0 :         s = tmp;
    1176           0 :         if(c == '\n') {
    1177           0 :             s[len - 1] = '\0';
    1178           0 :             break;
    1179             :         }
    1180           0 :         s[len - 1] = c;
    1181             :     }
    1182           0 :     if(ret != 1){
    1183           0 :         free(s);
    1184           0 :         if(ret == 0)
    1185           0 :             return sp->eof_code;
    1186           0 :         return ret;
    1187             :     }
    1188           0 :     *string = s;
    1189           0 :     return 0;
    1190             : }
    1191             : 
    1192             : /**
    1193             :  * Write a principal block to storage.
    1194             :  *
    1195             :  * @param sp the storage buffer to write to
    1196             :  * @param p the principal block to write.
    1197             :  *
    1198             :  * @return 0 on success, a Kerberos 5 error code on failure.
    1199             :  *
    1200             :  * @ingroup krb5_storage
    1201             :  */
    1202             : 
    1203             : KRB5_LIB_FUNCTION krb5_error_code KRB5_LIB_CALL
    1204        3936 : krb5_store_principal(krb5_storage *sp,
    1205             :                      krb5_const_principal p)
    1206             : {
    1207           0 :     size_t i;
    1208           0 :     int ret;
    1209             : 
    1210        3936 :     if(!krb5_storage_is_flags(sp, KRB5_STORAGE_PRINCIPAL_NO_NAME_TYPE)) {
    1211        3936 :         ret = krb5_store_int32(sp, p->name.name_type);
    1212        3936 :         if(ret) return ret;
    1213             :     }
    1214        3936 :     if(krb5_storage_is_flags(sp, KRB5_STORAGE_PRINCIPAL_WRONG_NUM_COMPONENTS))
    1215           0 :         ret = krb5_store_int32(sp, p->name.name_string.len + 1);
    1216             :     else
    1217        3936 :         ret = krb5_store_int32(sp, p->name.name_string.len);
    1218             : 
    1219        3936 :     if(ret) return ret;
    1220        3936 :     ret = krb5_store_string(sp, p->realm);
    1221        3936 :     if(ret) return ret;
    1222        9933 :     for(i = 0; i < p->name.name_string.len; i++){
    1223        5997 :         ret = krb5_store_string(sp, p->name.name_string.val[i]);
    1224        5997 :         if(ret) return ret;
    1225             :     }
    1226        3936 :     return 0;
    1227             : }
    1228             : 
    1229             : /**
    1230             :  * Parse principal from the storage.
    1231             :  *
    1232             :  * @param sp the storage buffer to read from
    1233             :  * @param princ the parsed principal
    1234             :  *
    1235             :  * @return 0 on success, a Kerberos 5 error code on failure.
    1236             :  *
    1237             :  * @ingroup krb5_storage
    1238             :  */
    1239             : 
    1240             : KRB5_LIB_FUNCTION krb5_error_code KRB5_LIB_CALL
    1241       69466 : krb5_ret_principal(krb5_storage *sp,
    1242             :                    krb5_principal *princ)
    1243             : {
    1244           0 :     int i;
    1245           0 :     int ret;
    1246           0 :     krb5_principal p;
    1247           0 :     int32_t type;
    1248           0 :     int32_t ncomp;
    1249             : 
    1250       69466 :     p = calloc(1, sizeof(*p));
    1251       69466 :     if(p == NULL)
    1252           0 :         return ENOMEM;
    1253             : 
    1254       69466 :     if(krb5_storage_is_flags(sp, KRB5_STORAGE_PRINCIPAL_NO_NAME_TYPE))
    1255           0 :         type = KRB5_NT_UNKNOWN;
    1256       69466 :     else if((ret = krb5_ret_int32(sp, &type))){
    1257        1796 :         free(p);
    1258        1796 :         return ret;
    1259             :     }
    1260       67670 :     if((ret = krb5_ret_int32(sp, &ncomp))){
    1261           0 :         free(p);
    1262           0 :         return ret;
    1263             :     }
    1264       67670 :     if(krb5_storage_is_flags(sp, KRB5_STORAGE_PRINCIPAL_WRONG_NUM_COMPONENTS))
    1265           0 :         ncomp--;
    1266       67670 :     if (ncomp < 0) {
    1267           0 :         free(p);
    1268           0 :         return EINVAL;
    1269             :     }
    1270       67670 :     ret = size_too_large_num(sp, ncomp, sizeof(p->name.name_string.val[0]));
    1271       67670 :     if (ret) {
    1272           0 :         free(p);
    1273           0 :         return ret;
    1274             :     }
    1275       67670 :     p->name.name_type = type;
    1276       67670 :     p->name.name_string.len = ncomp;
    1277       67670 :     ret = krb5_ret_string(sp, &p->realm);
    1278       67670 :     if(ret) {
    1279           0 :         free(p);
    1280           0 :         return ret;
    1281             :     }
    1282       67670 :     p->name.name_string.val = calloc(ncomp, sizeof(p->name.name_string.val[0]));
    1283       67670 :     if(p->name.name_string.val == NULL && ncomp != 0){
    1284           0 :         free(p->realm);
    1285           0 :         free(p);
    1286           0 :         return ENOMEM;
    1287             :     }
    1288      166848 :     for(i = 0; i < ncomp; i++){
    1289       99178 :         ret = krb5_ret_string(sp, &p->name.name_string.val[i]);
    1290       99178 :         if(ret) {
    1291           0 :             while (i >= 0)
    1292           0 :                 free(p->name.name_string.val[i--]);
    1293           0 :             free(p->realm);
    1294           0 :             free(p);
    1295           0 :             return ret;
    1296             :         }
    1297             :     }
    1298       67670 :     *princ = p;
    1299       67670 :     return 0;
    1300             : }
    1301             : 
    1302             : /**
    1303             :  * Store a keyblock to the storage.
    1304             :  *
    1305             :  * @param sp the storage buffer to write to
    1306             :  * @param p the keyblock to write
    1307             :  *
    1308             :  * @return 0 on success, a Kerberos 5 error code on failure.
    1309             :  *
    1310             :  * @ingroup krb5_storage
    1311             :  */
    1312             : 
    1313             : KRB5_LIB_FUNCTION krb5_error_code KRB5_LIB_CALL
    1314       73835 : krb5_store_keyblock(krb5_storage *sp, krb5_keyblock p)
    1315             : {
    1316         985 :     int ret;
    1317       73835 :     ret = krb5_store_int16(sp, p.keytype);
    1318       73835 :     if(ret) return ret;
    1319             : 
    1320       73835 :     if(krb5_storage_is_flags(sp, KRB5_STORAGE_KEYBLOCK_KEYTYPE_TWICE)){
    1321             :         /* this should really be enctype, but it is the same as
    1322             :            keytype nowadays */
    1323           0 :     ret = krb5_store_int16(sp, p.keytype);
    1324           0 :     if(ret) return ret;
    1325             :     }
    1326             : 
    1327       73835 :     ret = krb5_store_data(sp, p.keyvalue);
    1328       73835 :     return ret;
    1329             : }
    1330             : 
    1331             : /**
    1332             :  * Read a keyblock from the storage.
    1333             :  *
    1334             :  * @param sp the storage buffer to write to
    1335             :  * @param p the keyblock read from storage, free using krb5_free_keyblock()
    1336             :  *
    1337             :  * @return 0 on success, a Kerberos 5 error code on failure.
    1338             :  *
    1339             :  * @ingroup krb5_storage
    1340             :  */
    1341             : 
    1342             : KRB5_LIB_FUNCTION krb5_error_code KRB5_LIB_CALL
    1343      102416 : krb5_ret_keyblock(krb5_storage *sp, krb5_keyblock *p)
    1344             : {
    1345         985 :     int ret;
    1346         985 :     int16_t tmp;
    1347             : 
    1348      102416 :     ret = krb5_ret_int16(sp, &tmp);
    1349      102416 :     if(ret) return ret;
    1350      102416 :     p->keytype = tmp;
    1351             : 
    1352      102416 :     if(krb5_storage_is_flags(sp, KRB5_STORAGE_KEYBLOCK_KEYTYPE_TWICE)){
    1353           0 :     ret = krb5_ret_int16(sp, &tmp);
    1354           0 :     if(ret) return ret;
    1355             :     }
    1356             : 
    1357      102416 :     ret = krb5_ret_data(sp, &p->keyvalue);
    1358      102416 :     return ret;
    1359             : }
    1360             : 
    1361             : /**
    1362             :  * Write a times block to storage.
    1363             :  *
    1364             :  * @param sp the storage buffer to write to
    1365             :  * @param times the times block to write.
    1366             :  *
    1367             :  * @return 0 on success, a Kerberos 5 error code on failure.
    1368             :  *
    1369             :  * @ingroup krb5_storage
    1370             :  */
    1371             : 
    1372             : KRB5_LIB_FUNCTION krb5_error_code KRB5_LIB_CALL
    1373        1754 : krb5_store_times(krb5_storage *sp, krb5_times times)
    1374             : {
    1375           0 :     int ret;
    1376        1754 :     ret = krb5_store_int32(sp, times.authtime);
    1377        1754 :     if(ret) return ret;
    1378        1754 :     ret = krb5_store_int32(sp, times.starttime);
    1379        1754 :     if(ret) return ret;
    1380        1754 :     ret = krb5_store_int32(sp, times.endtime);
    1381        1754 :     if(ret) return ret;
    1382        1754 :     ret = krb5_store_int32(sp, times.renew_till);
    1383        1754 :     return ret;
    1384             : }
    1385             : 
    1386             : /**
    1387             :  * Read a times block from the storage.
    1388             :  *
    1389             :  * @param sp the storage buffer to write to
    1390             :  * @param times the times block read from storage
    1391             :  *
    1392             :  * @return 0 on success, a Kerberos 5 error code on failure.
    1393             :  *
    1394             :  * @ingroup krb5_storage
    1395             :  */
    1396             : 
    1397             : KRB5_LIB_FUNCTION krb5_error_code KRB5_LIB_CALL
    1398       30335 : krb5_ret_times(krb5_storage *sp, krb5_times *times)
    1399             : {
    1400           0 :     int ret;
    1401           0 :     int32_t tmp;
    1402             : 
    1403       30335 :     ret = krb5_ret_int32(sp, &tmp);
    1404       30335 :     if (ret) return ret;
    1405       30335 :     times->authtime = tmp;
    1406       30335 :     ret = krb5_ret_int32(sp, &tmp);
    1407       30335 :     if (ret) return ret;
    1408       30335 :     times->starttime = tmp;
    1409       30335 :     ret = krb5_ret_int32(sp, &tmp);
    1410       30335 :     if (ret) return ret;
    1411       30335 :     times->endtime = tmp;
    1412       30335 :     ret = krb5_ret_int32(sp, &tmp);
    1413       30335 :     if (ret) return ret;
    1414       30335 :     times->renew_till = tmp;
    1415       30335 :     return ret;
    1416             : }
    1417             : 
    1418             : /**
    1419             :  * Write a address block to storage.
    1420             :  *
    1421             :  * @param sp the storage buffer to write to
    1422             :  * @param p the address block to write.
    1423             :  *
    1424             :  * @return 0 on success, a Kerberos 5 error code on failure.
    1425             :  *
    1426             :  * @ingroup krb5_storage
    1427             :  */
    1428             : 
    1429             : KRB5_LIB_FUNCTION krb5_error_code KRB5_LIB_CALL
    1430           0 : krb5_store_address(krb5_storage *sp, krb5_address p)
    1431             : {
    1432           0 :     int ret;
    1433           0 :     ret = krb5_store_int16(sp, p.addr_type);
    1434           0 :     if(ret) return ret;
    1435           0 :     ret = krb5_store_data(sp, p.address);
    1436           0 :     return ret;
    1437             : }
    1438             : 
    1439             : /**
    1440             :  * Read a address block from the storage.
    1441             :  *
    1442             :  * @param sp the storage buffer to write to
    1443             :  * @param adr the address block read from storage
    1444             :  *
    1445             :  * @return 0 on success, a Kerberos 5 error code on failure.
    1446             :  *
    1447             :  * @ingroup krb5_storage
    1448             :  */
    1449             : 
    1450             : KRB5_LIB_FUNCTION krb5_error_code KRB5_LIB_CALL
    1451           0 : krb5_ret_address(krb5_storage *sp, krb5_address *adr)
    1452             : {
    1453           0 :     int16_t t;
    1454           0 :     int ret;
    1455           0 :     ret = krb5_ret_int16(sp, &t);
    1456           0 :     if(ret) return ret;
    1457           0 :     adr->addr_type = t;
    1458           0 :     ret = krb5_ret_data(sp, &adr->address);
    1459           0 :     return ret;
    1460             : }
    1461             : 
    1462             : /**
    1463             :  * Write a addresses block to storage.
    1464             :  *
    1465             :  * @param sp the storage buffer to write to
    1466             :  * @param p the addresses block to write.
    1467             :  *
    1468             :  * @return 0 on success, a Kerberos 5 error code on failure.
    1469             :  *
    1470             :  * @ingroup krb5_storage
    1471             :  */
    1472             : 
    1473             : KRB5_LIB_FUNCTION krb5_error_code KRB5_LIB_CALL
    1474        1754 : krb5_store_addrs(krb5_storage *sp, krb5_addresses p)
    1475             : {
    1476           0 :     size_t i;
    1477           0 :     int ret;
    1478        1754 :     ret = krb5_store_int32(sp, p.len);
    1479        1754 :     if(ret) return ret;
    1480        1754 :     for(i = 0; i<p.len; i++){
    1481           0 :         ret = krb5_store_address(sp, p.val[i]);
    1482           0 :         if(ret) break;
    1483             :     }
    1484        1754 :     return ret;
    1485             : }
    1486             : 
    1487             : /**
    1488             :  * Read a addresses block from the storage.
    1489             :  *
    1490             :  * @param sp the storage buffer to write to
    1491             :  * @param adr the addresses block read from storage
    1492             :  *
    1493             :  * @return 0 on success, a Kerberos 5 error code on failure.
    1494             :  *
    1495             :  * @ingroup krb5_storage
    1496             :  */
    1497             : 
    1498             : KRB5_LIB_FUNCTION krb5_error_code KRB5_LIB_CALL
    1499       30335 : krb5_ret_addrs(krb5_storage *sp, krb5_addresses *adr)
    1500             : {
    1501           0 :     size_t i;
    1502           0 :     int ret;
    1503           0 :     int32_t tmp;
    1504             : 
    1505       30335 :     ret = krb5_ret_int32(sp, &tmp);
    1506       30335 :     if(ret) return ret;
    1507       30335 :     ret = size_too_large_num(sp, tmp, sizeof(adr->val[0]));
    1508       30335 :     if (ret) return ret;
    1509       30335 :     adr->len = tmp;
    1510       30335 :     ALLOC(adr->val, adr->len);
    1511       30335 :     if (adr->val == NULL && adr->len != 0)
    1512           0 :         return ENOMEM;
    1513       30335 :     for(i = 0; i < adr->len; i++){
    1514           0 :         ret = krb5_ret_address(sp, &adr->val[i]);
    1515           0 :         if(ret) break;
    1516             :     }
    1517       30335 :     return ret;
    1518             : }
    1519             : 
    1520             : /**
    1521             :  * Write a auth data block to storage.
    1522             :  *
    1523             :  * @param sp the storage buffer to write to
    1524             :  * @param auth the auth data block to write.
    1525             :  *
    1526             :  * @return 0 on success, a Kerberos 5 error code on failure.
    1527             :  *
    1528             :  * @ingroup krb5_storage
    1529             :  */
    1530             : 
    1531             : KRB5_LIB_FUNCTION krb5_error_code KRB5_LIB_CALL
    1532        1754 : krb5_store_authdata(krb5_storage *sp, krb5_authdata auth)
    1533             : {
    1534           0 :     krb5_error_code ret;
    1535           0 :     size_t i;
    1536        1754 :     ret = krb5_store_int32(sp, auth.len);
    1537        1754 :     if(ret) return ret;
    1538        1754 :     for(i = 0; i < auth.len; i++){
    1539           0 :         ret = krb5_store_int16(sp, auth.val[i].ad_type);
    1540           0 :         if(ret) break;
    1541           0 :         ret = krb5_store_data(sp, auth.val[i].ad_data);
    1542           0 :         if(ret) break;
    1543             :     }
    1544        1754 :     return 0;
    1545             : }
    1546             : 
    1547             : /**
    1548             :  * Read a auth data from the storage.
    1549             :  *
    1550             :  * @param sp the storage buffer to write to
    1551             :  * @param auth the auth data block read from storage
    1552             :  *
    1553             :  * @return 0 on success, a Kerberos 5 error code on failure.
    1554             :  *
    1555             :  * @ingroup krb5_storage
    1556             :  */
    1557             : 
    1558             : KRB5_LIB_FUNCTION krb5_error_code KRB5_LIB_CALL
    1559       30335 : krb5_ret_authdata(krb5_storage *sp, krb5_authdata *auth)
    1560             : {
    1561           0 :     krb5_error_code ret;
    1562           0 :     int32_t tmp;
    1563           0 :     int16_t tmp2;
    1564           0 :     int i;
    1565       30335 :     ret = krb5_ret_int32(sp, &tmp);
    1566       30335 :     if(ret) return ret;
    1567       30335 :     ret = size_too_large_num(sp, tmp, sizeof(auth->val[0]));
    1568       30335 :     if (ret) return ret;
    1569       30335 :     ALLOC_SEQ(auth, tmp);
    1570       30335 :     if (auth->val == NULL && tmp != 0)
    1571           0 :         return ENOMEM;
    1572       30335 :     for(i = 0; i < tmp; i++){
    1573           0 :         ret = krb5_ret_int16(sp, &tmp2);
    1574           0 :         if(ret) break;
    1575           0 :         auth->val[i].ad_type = tmp2;
    1576           0 :         ret = krb5_ret_data(sp, &auth->val[i].ad_data);
    1577           0 :         if(ret) break;
    1578             :     }
    1579       30335 :     return ret;
    1580             : }
    1581             : 
    1582             : static int32_t
    1583       32089 : bitswap32(int32_t b)
    1584             : {
    1585       32089 :     int32_t r = 0;
    1586           0 :     int i;
    1587     1058937 :     for (i = 0; i < 32; i++) {
    1588     1026848 :         r = r << 1 | (b & 1);
    1589     1026848 :         b = b >> 1;
    1590             :     }
    1591       32089 :     return r;
    1592             : }
    1593             : 
    1594             : /**
    1595             :  * Write a credentials block to storage.
    1596             :  *
    1597             :  * @param sp the storage buffer to write to
    1598             :  * @param creds the creds block to write.
    1599             :  *
    1600             :  * @return 0 on success, a Kerberos 5 error code on failure.
    1601             :  *
    1602             :  * @ingroup krb5_storage
    1603             :  */
    1604             : 
    1605             : KRB5_LIB_FUNCTION krb5_error_code KRB5_LIB_CALL
    1606        1754 : krb5_store_creds(krb5_storage *sp, krb5_creds *creds)
    1607             : {
    1608           0 :     int ret;
    1609             : 
    1610        1754 :     ret = krb5_store_principal(sp, creds->client);
    1611        1754 :     if(ret)
    1612           0 :         return ret;
    1613        1754 :     ret = krb5_store_principal(sp, creds->server);
    1614        1754 :     if(ret)
    1615           0 :         return ret;
    1616        1754 :     ret = krb5_store_keyblock(sp, creds->session);
    1617        1754 :     if(ret)
    1618           0 :         return ret;
    1619        1754 :     ret = krb5_store_times(sp, creds->times);
    1620        1754 :     if(ret)
    1621           0 :         return ret;
    1622        1754 :     ret = krb5_store_int8(sp, creds->second_ticket.length != 0); /* is_skey */
    1623        1754 :     if(ret)
    1624           0 :         return ret;
    1625        1754 :     ret = krb5_store_int32(sp, bitswap32(TicketFlags2int(creds->flags.b)));
    1626        1754 :     if(ret)
    1627           0 :         return ret;
    1628        1754 :     ret = krb5_store_addrs(sp, creds->addresses);
    1629        1754 :     if(ret)
    1630           0 :         return ret;
    1631        1754 :     ret = krb5_store_authdata(sp, creds->authdata);
    1632        1754 :     if(ret)
    1633           0 :         return ret;
    1634        1754 :     ret = krb5_store_data(sp, creds->ticket);
    1635        1754 :     if(ret)
    1636           0 :         return ret;
    1637        1754 :     ret = krb5_store_data(sp, creds->second_ticket);
    1638        1754 :     return ret;
    1639             : }
    1640             : 
    1641             : /**
    1642             :  * Read a credentials block from the storage.
    1643             :  *
    1644             :  * @param sp the storage buffer to write to
    1645             :  * @param creds the credentials block read from storage
    1646             :  *
    1647             :  * @return 0 on success, a Kerberos 5 error code on failure.
    1648             :  *
    1649             :  * @ingroup krb5_storage
    1650             :  */
    1651             : 
    1652             : KRB5_LIB_FUNCTION krb5_error_code KRB5_LIB_CALL
    1653       32131 : krb5_ret_creds(krb5_storage *sp, krb5_creds *creds)
    1654             : {
    1655           0 :     krb5_error_code ret;
    1656           0 :     int8_t dummy8;
    1657           0 :     int32_t dummy32;
    1658             : 
    1659       32131 :     memset(creds, 0, sizeof(*creds));
    1660       32131 :     ret = krb5_ret_principal (sp,  &creds->client);
    1661       32131 :     if(ret) goto cleanup;
    1662       30335 :     ret = krb5_ret_principal (sp,  &creds->server);
    1663       30335 :     if(ret) goto cleanup;
    1664       30335 :     ret = krb5_ret_keyblock (sp,  &creds->session);
    1665       30335 :     if(ret) goto cleanup;
    1666       30335 :     ret = krb5_ret_times (sp,  &creds->times);
    1667       30335 :     if(ret) goto cleanup;
    1668       30335 :     ret = krb5_ret_int8 (sp,  &dummy8);
    1669       30335 :     if(ret) goto cleanup;
    1670       30335 :     ret = krb5_ret_int32 (sp,  &dummy32);
    1671       30335 :     if(ret) goto cleanup;
    1672       30335 :     creds->flags.b = int2TicketFlags(bitswap32(dummy32));
    1673       30335 :     ret = krb5_ret_addrs (sp,  &creds->addresses);
    1674       30335 :     if(ret) goto cleanup;
    1675       30335 :     ret = krb5_ret_authdata (sp,  &creds->authdata);
    1676       30335 :     if(ret) goto cleanup;
    1677       30335 :     ret = krb5_ret_data (sp,  &creds->ticket);
    1678       30335 :     if(ret) goto cleanup;
    1679       30335 :     ret = krb5_ret_data (sp,  &creds->second_ticket);
    1680       32131 : cleanup:
    1681           0 :     if(ret) {
    1682             : #if 0
    1683             :         krb5_free_cred_contents(context, creds); /* XXX */
    1684             : #endif
    1685           0 :     }
    1686       32131 :     return ret;
    1687             : }
    1688             : 
    1689             : #define SC_CLIENT_PRINCIPAL         0x0001
    1690             : #define SC_SERVER_PRINCIPAL         0x0002
    1691             : #define SC_SESSION_KEY              0x0004
    1692             : #define SC_TICKET                   0x0008
    1693             : #define SC_SECOND_TICKET            0x0010
    1694             : #define SC_AUTHDATA                 0x0020
    1695             : #define SC_ADDRESSES                0x0040
    1696             : 
    1697             : /**
    1698             :  * Write a tagged credentials block to storage.
    1699             :  *
    1700             :  * @param sp the storage buffer to write to
    1701             :  * @param creds the creds block to write.
    1702             :  *
    1703             :  * @return 0 on success, a Kerberos 5 error code on failure.
    1704             :  *
    1705             :  * @ingroup krb5_storage
    1706             :  */
    1707             : 
    1708             : KRB5_LIB_FUNCTION krb5_error_code KRB5_LIB_CALL
    1709           0 : krb5_store_creds_tag(krb5_storage *sp, krb5_creds *creds)
    1710             : {
    1711           0 :     int ret;
    1712           0 :     int32_t header = 0;
    1713             : 
    1714           0 :     if (creds->client)
    1715           0 :         header |= SC_CLIENT_PRINCIPAL;
    1716           0 :     if (creds->server)
    1717           0 :         header |= SC_SERVER_PRINCIPAL;
    1718           0 :     if (creds->session.keytype != ETYPE_NULL)
    1719           0 :         header |= SC_SESSION_KEY;
    1720           0 :     if (creds->ticket.data)
    1721           0 :         header |= SC_TICKET;
    1722           0 :     if (creds->second_ticket.length)
    1723           0 :         header |= SC_SECOND_TICKET;
    1724           0 :     if (creds->authdata.len)
    1725           0 :         header |= SC_AUTHDATA;
    1726           0 :     if (creds->addresses.len)
    1727           0 :         header |= SC_ADDRESSES;
    1728             : 
    1729           0 :     ret = krb5_store_int32(sp, header);
    1730           0 :     if (ret)
    1731           0 :         return ret;
    1732             : 
    1733           0 :     if (creds->client) {
    1734           0 :         ret = krb5_store_principal(sp, creds->client);
    1735           0 :         if(ret)
    1736           0 :             return ret;
    1737             :     }
    1738             : 
    1739           0 :     if (creds->server) {
    1740           0 :         ret = krb5_store_principal(sp, creds->server);
    1741           0 :         if(ret)
    1742           0 :             return ret;
    1743             :     }
    1744             : 
    1745           0 :     if (creds->session.keytype != ETYPE_NULL) {
    1746           0 :         ret = krb5_store_keyblock(sp, creds->session);
    1747           0 :         if(ret)
    1748           0 :             return ret;
    1749             :     }
    1750             : 
    1751           0 :     ret = krb5_store_times(sp, creds->times);
    1752           0 :     if(ret)
    1753           0 :         return ret;
    1754           0 :     ret = krb5_store_int8(sp, creds->second_ticket.length != 0); /* is_skey */
    1755           0 :     if(ret)
    1756           0 :         return ret;
    1757             : 
    1758           0 :     ret = krb5_store_int32(sp, bitswap32(TicketFlags2int(creds->flags.b)));
    1759           0 :     if(ret)
    1760           0 :         return ret;
    1761             : 
    1762           0 :     if (creds->addresses.len) {
    1763           0 :         ret = krb5_store_addrs(sp, creds->addresses);
    1764           0 :         if(ret)
    1765           0 :             return ret;
    1766             :     }
    1767             : 
    1768           0 :     if (creds->authdata.len) {
    1769           0 :         ret = krb5_store_authdata(sp, creds->authdata);
    1770           0 :         if(ret)
    1771           0 :             return ret;
    1772             :     }
    1773             : 
    1774           0 :     if (creds->ticket.data) {
    1775           0 :         ret = krb5_store_data(sp, creds->ticket);
    1776           0 :         if(ret)
    1777           0 :             return ret;
    1778             :     }
    1779             : 
    1780           0 :     if (creds->second_ticket.data) {
    1781           0 :         ret = krb5_store_data(sp, creds->second_ticket);
    1782           0 :         if (ret)
    1783           0 :             return ret;
    1784             :     }
    1785             : 
    1786           0 :     return ret;
    1787             : }
    1788             : 
    1789             : /**
    1790             :  * Read a tagged credentials block from the storage.
    1791             :  *
    1792             :  * @param sp the storage buffer to write to
    1793             :  * @param creds the credentials block read from storage
    1794             :  *
    1795             :  * @return 0 on success, a Kerberos 5 error code on failure.
    1796             :  *
    1797             :  * @ingroup krb5_storage
    1798             :  */
    1799             : 
    1800             : KRB5_LIB_FUNCTION krb5_error_code KRB5_LIB_CALL
    1801           0 : krb5_ret_creds_tag(krb5_storage *sp,
    1802             :                    krb5_creds *creds)
    1803             : {
    1804           0 :     krb5_error_code ret;
    1805           0 :     int8_t dummy8;
    1806           0 :     int32_t dummy32, header;
    1807             : 
    1808           0 :     memset(creds, 0, sizeof(*creds));
    1809             : 
    1810           0 :     ret = krb5_ret_int32 (sp, &header);
    1811           0 :     if (ret) goto cleanup;
    1812             : 
    1813           0 :     if (header & SC_CLIENT_PRINCIPAL) {
    1814           0 :         ret = krb5_ret_principal (sp,  &creds->client);
    1815           0 :         if(ret) goto cleanup;
    1816             :     }
    1817           0 :     if (header & SC_SERVER_PRINCIPAL) {
    1818           0 :         ret = krb5_ret_principal (sp,  &creds->server);
    1819           0 :         if(ret) goto cleanup;
    1820             :     }
    1821           0 :     if (header & SC_SESSION_KEY) {
    1822           0 :         ret = krb5_ret_keyblock (sp,  &creds->session);
    1823           0 :         if(ret) goto cleanup;
    1824             :     }
    1825           0 :     ret = krb5_ret_times (sp,  &creds->times);
    1826           0 :     if(ret) goto cleanup;
    1827           0 :     ret = krb5_ret_int8 (sp,  &dummy8);
    1828           0 :     if(ret) goto cleanup;
    1829           0 :     ret = krb5_ret_int32 (sp,  &dummy32);
    1830           0 :     if(ret) goto cleanup;
    1831           0 :     creds->flags.b = int2TicketFlags(bitswap32(dummy32));
    1832           0 :     if (header & SC_ADDRESSES) {
    1833           0 :         ret = krb5_ret_addrs (sp,  &creds->addresses);
    1834           0 :         if(ret) goto cleanup;
    1835             :     }
    1836           0 :     if (header & SC_AUTHDATA) {
    1837           0 :         ret = krb5_ret_authdata (sp,  &creds->authdata);
    1838           0 :         if(ret) goto cleanup;
    1839             :     }
    1840           0 :     if (header & SC_TICKET) {
    1841           0 :         ret = krb5_ret_data (sp,  &creds->ticket);
    1842           0 :         if(ret) goto cleanup;
    1843             :     }
    1844           0 :     if (header & SC_SECOND_TICKET) {
    1845           0 :         ret = krb5_ret_data (sp,  &creds->second_ticket);
    1846           0 :         if(ret) goto cleanup;
    1847             :     }
    1848             : 
    1849           0 : cleanup:
    1850           0 :     if(ret) {
    1851             : #if 0
    1852             :         krb5_free_cred_contents(context, creds); /* XXX */
    1853             : #endif
    1854           0 :     }
    1855           0 :     return ret;
    1856             : }
    1857             : 
    1858             : KRB5_LIB_FUNCTION krb5_error_code KRB5_LIB_CALL
    1859      414468 : _krb5_ret_data_at_offset(krb5_storage *sp,
    1860             :                          size_t offset,
    1861             :                          size_t length,
    1862             :                          krb5_data *data)
    1863             : {
    1864       10240 :     krb5_error_code ret;
    1865       10240 :     off_t cur, size;
    1866             : 
    1867      414468 :     krb5_data_zero(data);
    1868             : 
    1869      414468 :     cur = sp->seek(sp, 0, SEEK_CUR);
    1870      414468 :     if (cur < 0)
    1871           0 :         return HEIM_ERR_NOT_SEEKABLE;
    1872             : 
    1873      414468 :     size = sp->seek(sp, 0, SEEK_END);
    1874      414468 :     if (offset + length > size) {
    1875           0 :         ret = ERANGE;
    1876           0 :         goto cleanup;
    1877             :     }
    1878             : 
    1879      414468 :     ret = krb5_data_alloc(data, length);
    1880      414468 :     if (ret)
    1881           0 :         goto cleanup;
    1882             : 
    1883      414468 :     if (length) {
    1884      414468 :         sp->seek(sp, offset, SEEK_SET);
    1885             : 
    1886      414468 :         size = sp->fetch(sp, data->data, length);
    1887      414468 :         if (size < 0 || (size_t)size != length)
    1888           0 :             return sp->eof_code;
    1889             :     }
    1890             : 
    1891      414468 : cleanup:
    1892      414468 :     sp->seek(sp, cur, SEEK_SET);
    1893             : 
    1894      414468 :     return ret;
    1895             : }
    1896             : 
    1897             : KRB5_LIB_FUNCTION krb5_error_code KRB5_LIB_CALL
    1898      310851 : _krb5_ret_utf8_from_ucs2le_at_offset(krb5_storage *sp,
    1899             :                                      off_t offset,
    1900             :                                      size_t length,
    1901             :                                      char **utf8)
    1902             : {
    1903        7680 :     krb5_error_code ret;
    1904        7680 :     krb5_data data;
    1905      310851 :     size_t ucs2len = length / 2;
    1906      310851 :     uint16_t *ucs2 = NULL;
    1907        7680 :     size_t u8len;
    1908      310851 :     unsigned int flags = WIND_RW_LE;
    1909             : 
    1910      310851 :     *utf8 = NULL;
    1911             : 
    1912      310851 :     krb5_data_zero(&data);
    1913             : 
    1914      310851 :     ret = _krb5_ret_data_at_offset(sp, offset, length, &data);
    1915      310851 :     if (ret)
    1916           0 :         goto out;
    1917             : 
    1918      310851 :     ucs2 = malloc(sizeof(ucs2[0]) * ucs2len);
    1919      310851 :     if (ucs2 == NULL) {
    1920           0 :         ret = ENOMEM;
    1921           0 :         goto out;
    1922             :     }
    1923             : 
    1924      310851 :     ret = wind_ucs2read(data.data, data.length, &flags, ucs2, &ucs2len);
    1925      310851 :     if (ret)
    1926           0 :         goto out;
    1927             : 
    1928      310851 :     ret = wind_ucs2utf8_length(ucs2, ucs2len, &u8len);
    1929      310851 :     if (ret)
    1930           0 :         goto out;
    1931             : 
    1932      310851 :     u8len += 1; /* Add space for NUL */
    1933             : 
    1934      310851 :     *utf8 = malloc(u8len);
    1935      310851 :     if (*utf8 == NULL) {
    1936           0 :         ret = ENOMEM;
    1937           0 :         goto out;
    1938             :     }
    1939             : 
    1940      310851 :     ret = wind_ucs2utf8(ucs2, ucs2len, *utf8, &u8len);
    1941      310851 :     if (ret)
    1942           0 :         goto out;
    1943             : 
    1944      310851 : out:
    1945      310851 :     if (ret && *utf8) {
    1946           0 :         free(*utf8);
    1947           0 :         *utf8 = NULL;
    1948             :     }
    1949      310851 :     free(ucs2);
    1950      310851 :     krb5_data_free(&data);
    1951             : 
    1952      310851 :     return ret;
    1953             : }
    1954             : 
    1955             : KRB5_LIB_FUNCTION krb5_error_code KRB5_LIB_CALL
    1956           0 : _krb5_store_data_at_offset(krb5_storage *sp,
    1957             :                            size_t offset,
    1958             :                            const krb5_data *data)
    1959             : {
    1960           0 :     krb5_error_code ret;
    1961           0 :     krb5_ssize_t nbytes;
    1962           0 :     off_t pos;
    1963             : 
    1964           0 :     if (offset == (size_t)-1) {
    1965           0 :         if (data == NULL || data->data == NULL) {
    1966           0 :             offset = 0;
    1967             :         } else {
    1968           0 :             pos = sp->seek(sp, 0, SEEK_CUR);
    1969           0 :             offset = sp->seek(sp, 0, SEEK_END);
    1970           0 :             sp->seek(sp, pos, SEEK_SET);
    1971             : 
    1972           0 :             if (offset == (size_t)-1)
    1973           0 :                 return HEIM_ERR_NOT_SEEKABLE;
    1974             :         }
    1975             :     }
    1976             : 
    1977           0 :     if (offset > 0xFFFF)
    1978           0 :         return ERANGE;
    1979           0 :     else if ((offset != 0) != (data && data->data))
    1980           0 :         return EINVAL;
    1981           0 :     else if (data && data->length > 0xFFFF)
    1982           0 :         return ERANGE;
    1983             : 
    1984           0 :     ret = krb5_store_uint16(sp, data ? (uint16_t)data->length : 0);
    1985           0 :     if (ret == 0)
    1986           0 :         ret = krb5_store_uint16(sp, (uint16_t)offset);
    1987           0 :     if (ret == 0 && offset) {
    1988           0 :         pos = sp->seek(sp, 0, SEEK_CUR);
    1989           0 :         sp->seek(sp, offset, SEEK_SET);
    1990           0 :         nbytes = krb5_storage_write(sp, data->data, data->length);
    1991           0 :         if ((size_t)nbytes != data->length)
    1992           0 :             ret = sp->eof_code;
    1993           0 :         sp->seek(sp, pos, SEEK_SET);
    1994             :     }
    1995             : 
    1996           0 :     return ret;
    1997             : }
    1998             : 
    1999             : KRB5_LIB_FUNCTION krb5_error_code KRB5_LIB_CALL
    2000           0 : _krb5_store_utf8_as_ucs2le_at_offset(krb5_storage *sp,
    2001             :                                      off_t offset,
    2002             :                                      const char *utf8)
    2003             : {
    2004           0 :     krb5_error_code ret;
    2005           0 :     size_t ucs2_len, ucs2le_size;
    2006           0 :     uint16_t *ucs2, *ucs2le;
    2007           0 :     unsigned int flags;
    2008             : 
    2009           0 :     if (utf8) {
    2010           0 :         ret = wind_utf8ucs2_length(utf8, &ucs2_len);
    2011           0 :         if (ret)
    2012           0 :             return ret;
    2013             : 
    2014           0 :         ucs2 = malloc(sizeof(ucs2[0]) * ucs2_len);
    2015           0 :         if (ucs2 == NULL)
    2016           0 :             return ENOMEM;
    2017             : 
    2018           0 :         ret = wind_utf8ucs2(utf8, ucs2, &ucs2_len);
    2019           0 :         if (ret) {
    2020           0 :             free(ucs2);
    2021           0 :             return ret;
    2022             :         }
    2023             : 
    2024           0 :         ucs2le_size = (ucs2_len + 1) * 2;
    2025           0 :         ucs2le = malloc(ucs2le_size);
    2026           0 :             if (ucs2le == NULL) {
    2027           0 :                 free(ucs2);
    2028           0 :                 return ENOMEM;
    2029             :         }
    2030             : 
    2031           0 :         flags = WIND_RW_LE;
    2032           0 :         ret = wind_ucs2write(ucs2, ucs2_len, &flags, ucs2le, &ucs2le_size);
    2033           0 :         free(ucs2);
    2034           0 :         if (ret) {
    2035           0 :             free(ucs2le);
    2036           0 :             return ret;
    2037             :         }
    2038             : 
    2039           0 :         ucs2le_size = ucs2_len * 2;
    2040             :     } else {
    2041           0 :         ucs2le = NULL;
    2042           0 :         ucs2le_size = 0;
    2043           0 :         offset = 0;
    2044             :     }
    2045             : 
    2046             :     {
    2047           0 :         krb5_data data;
    2048             : 
    2049           0 :         data.data = ucs2le;
    2050           0 :         data.length = ucs2le_size;
    2051             : 
    2052           0 :         ret = _krb5_store_data_at_offset(sp, offset, &data);
    2053             :     }
    2054             : 
    2055           0 :     free(ucs2le);
    2056             : 
    2057           0 :     return ret;
    2058             : }

Generated by: LCOV version 1.14