155682Smarkm/* 2233294Sstas * Copyright (c) 1997-2008 Kungliga Tekniska H��gskolan 3233294Sstas * (Royal Institute of Technology, Stockholm, Sweden). 4233294Sstas * All rights reserved. 555682Smarkm * 6233294Sstas * Redistribution and use in source and binary forms, with or without 7233294Sstas * modification, are permitted provided that the following conditions 8233294Sstas * are met: 955682Smarkm * 10233294Sstas * 1. Redistributions of source code must retain the above copyright 11233294Sstas * notice, this list of conditions and the following disclaimer. 1255682Smarkm * 13233294Sstas * 2. Redistributions in binary form must reproduce the above copyright 14233294Sstas * notice, this list of conditions and the following disclaimer in the 15233294Sstas * documentation and/or other materials provided with the distribution. 1655682Smarkm * 17233294Sstas * 3. Neither the name of the Institute nor the names of its contributors 18233294Sstas * may be used to endorse or promote products derived from this software 19233294Sstas * without specific prior written permission. 2055682Smarkm * 21233294Sstas * THIS SOFTWARE IS PROVIDED BY THE INSTITUTE AND CONTRIBUTORS ``AS IS'' AND 22233294Sstas * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 23233294Sstas * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE 24233294Sstas * ARE DISCLAIMED. IN NO EVENT SHALL THE INSTITUTE OR CONTRIBUTORS BE LIABLE 25233294Sstas * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL 26233294Sstas * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS 27233294Sstas * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) 28233294Sstas * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT 29233294Sstas * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY 30233294Sstas * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF 31233294Sstas * SUCH DAMAGE. 3255682Smarkm */ 3355682Smarkm 3455682Smarkm#include "krb5_locl.h" 35102644Snectar#include "store-int.h" 3655682Smarkm 3778527Sassar#define BYTEORDER_IS(SP, V) (((SP)->flags & KRB5_STORAGE_BYTEORDER_MASK) == (V)) 3878527Sassar#define BYTEORDER_IS_LE(SP) BYTEORDER_IS((SP), KRB5_STORAGE_BYTEORDER_LE) 3978527Sassar#define BYTEORDER_IS_BE(SP) BYTEORDER_IS((SP), KRB5_STORAGE_BYTEORDER_BE) 4078527Sassar#define BYTEORDER_IS_HOST(SP) (BYTEORDER_IS((SP), KRB5_STORAGE_BYTEORDER_HOST) || \ 4178527Sassar krb5_storage_is_flags((SP), KRB5_STORAGE_HOST_BYTEORDER)) 4278527Sassar 43233294Sstas/** 44233294Sstas * Add the flags on a storage buffer by or-ing in the flags to the buffer. 45233294Sstas * 46233294Sstas * @param sp the storage buffer to set the flags on 47233294Sstas * @param flags the flags to set 48233294Sstas * 49233294Sstas * @ingroup krb5_storage 50233294Sstas */ 51233294Sstas 52233294SstasKRB5_LIB_FUNCTION void KRB5_LIB_CALL 5355682Smarkmkrb5_storage_set_flags(krb5_storage *sp, krb5_flags flags) 5455682Smarkm{ 5555682Smarkm sp->flags |= flags; 5655682Smarkm} 5755682Smarkm 58233294Sstas/** 59233294Sstas * Clear the flags on a storage buffer 60233294Sstas * 61233294Sstas * @param sp the storage buffer to clear the flags on 62233294Sstas * @param flags the flags to clear 63233294Sstas * 64233294Sstas * @ingroup krb5_storage 65233294Sstas */ 66233294Sstas 67233294SstasKRB5_LIB_FUNCTION void KRB5_LIB_CALL 6855682Smarkmkrb5_storage_clear_flags(krb5_storage *sp, krb5_flags flags) 6955682Smarkm{ 7055682Smarkm sp->flags &= ~flags; 7155682Smarkm} 7255682Smarkm 73233294Sstas/** 74233294Sstas * Return true or false depending on if the storage flags is set or 75233294Sstas * not. NB testing for the flag 0 always return true. 76233294Sstas * 77233294Sstas * @param sp the storage buffer to check flags on 78233294Sstas * @param flags The flags to test for 79233294Sstas * 80233294Sstas * @return true if all the flags are set, false if not. 81233294Sstas * 82233294Sstas * @ingroup krb5_storage 83233294Sstas */ 84233294Sstas 85233294SstasKRB5_LIB_FUNCTION krb5_boolean KRB5_LIB_CALL 8655682Smarkmkrb5_storage_is_flags(krb5_storage *sp, krb5_flags flags) 8755682Smarkm{ 8855682Smarkm return (sp->flags & flags) == flags; 8955682Smarkm} 9055682Smarkm 91233294Sstas/** 92233294Sstas * Set the new byte order of the storage buffer. 93233294Sstas * 94233294Sstas * @param sp the storage buffer to set the byte order for. 95233294Sstas * @param byteorder the new byte order. 96233294Sstas * 97233294Sstas * The byte order are: KRB5_STORAGE_BYTEORDER_BE, 98233294Sstas * KRB5_STORAGE_BYTEORDER_LE and KRB5_STORAGE_BYTEORDER_HOST. 99233294Sstas * 100233294Sstas * @ingroup krb5_storage 101233294Sstas */ 102233294Sstas 103233294SstasKRB5_LIB_FUNCTION void KRB5_LIB_CALL 10478527Sassarkrb5_storage_set_byteorder(krb5_storage *sp, krb5_flags byteorder) 10578527Sassar{ 10678527Sassar sp->flags &= ~KRB5_STORAGE_BYTEORDER_MASK; 10778527Sassar sp->flags |= byteorder; 10878527Sassar} 10978527Sassar 110233294Sstas/** 111233294Sstas * Return the current byteorder for the buffer. See krb5_storage_set_byteorder() for the list or byte order contants. 112233294Sstas * 113233294Sstas * @ingroup krb5_storage 114233294Sstas */ 115233294Sstas 116233294SstasKRB5_LIB_FUNCTION krb5_flags KRB5_LIB_CALL 117233294Sstaskrb5_storage_get_byteorder(krb5_storage *sp) 11878527Sassar{ 11978527Sassar return sp->flags & KRB5_STORAGE_BYTEORDER_MASK; 12078527Sassar} 12178527Sassar 122233294Sstas/** 123233294Sstas * Set the max alloc value 124233294Sstas * 125233294Sstas * @param sp the storage buffer set the max allow for 126233294Sstas * @param size maximum size to allocate, use 0 to remove limit 127233294Sstas * 128233294Sstas * @ingroup krb5_storage 129233294Sstas */ 130233294Sstas 131233294SstasKRB5_LIB_FUNCTION void KRB5_LIB_CALL 132233294Sstaskrb5_storage_set_max_alloc(krb5_storage *sp, size_t size) 133233294Sstas{ 134233294Sstas sp->max_alloc = size; 135233294Sstas} 136233294Sstas 137233294Sstas/* don't allocate unresonable amount of memory */ 138233294Sstasstatic krb5_error_code 139233294Sstassize_too_large(krb5_storage *sp, size_t size) 140233294Sstas{ 141233294Sstas if (sp->max_alloc && sp->max_alloc < size) 142233294Sstas return HEIM_ERR_TOO_BIG; 143233294Sstas return 0; 144233294Sstas} 145233294Sstas 146233294Sstasstatic krb5_error_code 147233294Sstassize_too_large_num(krb5_storage *sp, size_t count, size_t size) 148233294Sstas{ 149233294Sstas if (sp->max_alloc == 0 || size == 0) 150233294Sstas return 0; 151233294Sstas size = sp->max_alloc / size; 152233294Sstas if (size < count) 153233294Sstas return HEIM_ERR_TOO_BIG; 154233294Sstas return 0; 155233294Sstas} 156233294Sstas 157233294Sstas/** 158233294Sstas * Seek to a new offset. 159233294Sstas * 160233294Sstas * @param sp the storage buffer to seek in. 161233294Sstas * @param offset the offset to seek 162233294Sstas * @param whence relateive searching, SEEK_CUR from the current 163233294Sstas * position, SEEK_END from the end, SEEK_SET absolute from the start. 164233294Sstas * 165233294Sstas * @return The new current offset 166233294Sstas * 167233294Sstas * @ingroup krb5_storage 168233294Sstas */ 169233294Sstas 170233294SstasKRB5_LIB_FUNCTION off_t KRB5_LIB_CALL 171102644Snectarkrb5_storage_seek(krb5_storage *sp, off_t offset, int whence) 172102644Snectar{ 173102644Snectar return (*sp->seek)(sp, offset, whence); 174102644Snectar} 17578527Sassar 176233294Sstas/** 177233294Sstas * Truncate the storage buffer in sp to offset. 178233294Sstas * 179233294Sstas * @param sp the storage buffer to truncate. 180233294Sstas * @param offset the offset to truncate too. 181233294Sstas * 182233294Sstas * @return An Kerberos 5 error code. 183233294Sstas * 184233294Sstas * @ingroup krb5_storage 185233294Sstas */ 186233294Sstas 187233294SstasKRB5_LIB_FUNCTION int KRB5_LIB_CALL 188233294Sstaskrb5_storage_truncate(krb5_storage *sp, off_t offset) 189233294Sstas{ 190233294Sstas return (*sp->trunc)(sp, offset); 191233294Sstas} 192233294Sstas 193233294Sstas/** 194233294Sstas * Read to the storage buffer. 195233294Sstas * 196233294Sstas * @param sp the storage buffer to read from 197233294Sstas * @param buf the buffer to store the data in 198233294Sstas * @param len the length to read 199233294Sstas * 200233294Sstas * @return The length of data read (can be shorter then len), or negative on error. 201233294Sstas * 202233294Sstas * @ingroup krb5_storage 203233294Sstas */ 204233294Sstas 205233294SstasKRB5_LIB_FUNCTION krb5_ssize_t KRB5_LIB_CALL 206102644Snectarkrb5_storage_read(krb5_storage *sp, void *buf, size_t len) 207102644Snectar{ 208102644Snectar return sp->fetch(sp, buf, len); 209102644Snectar} 210102644Snectar 211233294Sstas/** 212233294Sstas * Write to the storage buffer. 213233294Sstas * 214233294Sstas * @param sp the storage buffer to write to 215233294Sstas * @param buf the buffer to write to the storage buffer 216233294Sstas * @param len the length to write 217233294Sstas * 218233294Sstas * @return The length of data written (can be shorter then len), or negative on error. 219233294Sstas * 220233294Sstas * @ingroup krb5_storage 221233294Sstas */ 222233294Sstas 223233294SstasKRB5_LIB_FUNCTION krb5_ssize_t KRB5_LIB_CALL 224102644Snectarkrb5_storage_write(krb5_storage *sp, const void *buf, size_t len) 225102644Snectar{ 226102644Snectar return sp->store(sp, buf, len); 227102644Snectar} 228102644Snectar 229233294Sstas/** 230233294Sstas * Set the return code that will be used when end of storage is reached. 231233294Sstas * 232233294Sstas * @param sp the storage 233233294Sstas * @param code the error code to return on end of storage 234233294Sstas * 235233294Sstas * @ingroup krb5_storage 236233294Sstas */ 237233294Sstas 238233294SstasKRB5_LIB_FUNCTION void KRB5_LIB_CALL 239102644Snectarkrb5_storage_set_eof_code(krb5_storage *sp, int code) 240102644Snectar{ 241102644Snectar sp->eof_code = code; 242102644Snectar} 243102644Snectar 244233294Sstas/** 245233294Sstas * Get the return code that will be used when end of storage is reached. 246233294Sstas * 247233294Sstas * @param sp the storage 248233294Sstas * 249233294Sstas * @return storage error code 250233294Sstas * 251233294Sstas * @ingroup krb5_storage 252233294Sstas */ 25355682Smarkm 254233294SstasKRB5_LIB_FUNCTION int KRB5_LIB_CALL 255233294Sstaskrb5_storage_get_eof_code(krb5_storage *sp) 25655682Smarkm{ 257233294Sstas return sp->eof_code; 25855682Smarkm} 25955682Smarkm 260233294Sstas/** 261233294Sstas * Free a krb5 storage. 262233294Sstas * 263233294Sstas * @param sp the storage to free. 264233294Sstas * 265233294Sstas * @return An Kerberos 5 error code. 266233294Sstas * 267233294Sstas * @ingroup krb5_storage 268233294Sstas */ 269233294Sstas 270233294SstasKRB5_LIB_FUNCTION krb5_error_code KRB5_LIB_CALL 27155682Smarkmkrb5_storage_free(krb5_storage *sp) 27255682Smarkm{ 27355682Smarkm if(sp->free) 27455682Smarkm (*sp->free)(sp); 27555682Smarkm free(sp->data); 27655682Smarkm free(sp); 27755682Smarkm return 0; 27855682Smarkm} 27955682Smarkm 280233294Sstas/** 281233294Sstas * Copy the contnent of storage 282233294Sstas * 283233294Sstas * @param sp the storage to copy to a data 284233294Sstas * @param data the copied data, free with krb5_data_free() 285233294Sstas * 286233294Sstas * @return 0 for success, or a Kerberos 5 error code on failure. 287233294Sstas * 288233294Sstas * @ingroup krb5_storage 289233294Sstas */ 290233294Sstas 291233294SstasKRB5_LIB_FUNCTION krb5_error_code KRB5_LIB_CALL 29255682Smarkmkrb5_storage_to_data(krb5_storage *sp, krb5_data *data) 29355682Smarkm{ 294233294Sstas off_t pos, size; 29555682Smarkm krb5_error_code ret; 29655682Smarkm 29755682Smarkm pos = sp->seek(sp, 0, SEEK_CUR); 298233294Sstas if (pos < 0) 299233294Sstas return HEIM_ERR_NOT_SEEKABLE; 300233294Sstas size = sp->seek(sp, 0, SEEK_END); 301233294Sstas ret = size_too_large(sp, size); 302233294Sstas if (ret) 303233294Sstas return ret; 304233294Sstas ret = krb5_data_alloc(data, size); 30555682Smarkm if (ret) { 30655682Smarkm sp->seek(sp, pos, SEEK_SET); 30755682Smarkm return ret; 30855682Smarkm } 30955682Smarkm if (size) { 31055682Smarkm sp->seek(sp, 0, SEEK_SET); 31155682Smarkm sp->fetch(sp, data->data, data->length); 31255682Smarkm sp->seek(sp, pos, SEEK_SET); 31355682Smarkm } 31455682Smarkm return 0; 31555682Smarkm} 31655682Smarkm 31755682Smarkmstatic krb5_error_code 31855682Smarkmkrb5_store_int(krb5_storage *sp, 31955682Smarkm int32_t value, 32055682Smarkm size_t len) 32155682Smarkm{ 32255682Smarkm int ret; 32378527Sassar unsigned char v[16]; 32455682Smarkm 32578527Sassar if(len > sizeof(v)) 32678527Sassar return EINVAL; 32755682Smarkm _krb5_put_int(v, value, len); 32855682Smarkm ret = sp->store(sp, v, len); 329233294Sstas if (ret < 0) 330233294Sstas return errno; 331233294Sstas if ((size_t)ret != len) 332233294Sstas return sp->eof_code; 33355682Smarkm return 0; 33455682Smarkm} 33555682Smarkm 336233294Sstas/** 337233294Sstas * Store a int32 to storage, byte order is controlled by the settings 338233294Sstas * on the storage, see krb5_storage_set_byteorder(). 339233294Sstas * 340233294Sstas * @param sp the storage to write too 341233294Sstas * @param value the value to store 342233294Sstas * 343233294Sstas * @return 0 for success, or a Kerberos 5 error code on failure. 344233294Sstas * 345233294Sstas * @ingroup krb5_storage 346233294Sstas */ 347233294Sstas 348233294SstasKRB5_LIB_FUNCTION krb5_error_code KRB5_LIB_CALL 34955682Smarkmkrb5_store_int32(krb5_storage *sp, 35055682Smarkm int32_t value) 35155682Smarkm{ 35278527Sassar if(BYTEORDER_IS_HOST(sp)) 35355682Smarkm value = htonl(value); 35478527Sassar else if(BYTEORDER_IS_LE(sp)) 35578527Sassar value = bswap32(value); 35655682Smarkm return krb5_store_int(sp, value, 4); 35755682Smarkm} 35855682Smarkm 359233294Sstas/** 360233294Sstas * Store a uint32 to storage, byte order is controlled by the settings 361233294Sstas * on the storage, see krb5_storage_set_byteorder(). 362233294Sstas * 363233294Sstas * @param sp the storage to write too 364233294Sstas * @param value the value to store 365233294Sstas * 366233294Sstas * @return 0 for success, or a Kerberos 5 error code on failure. 367233294Sstas * 368233294Sstas * @ingroup krb5_storage 369233294Sstas */ 370233294Sstas 371233294SstasKRB5_LIB_FUNCTION krb5_error_code KRB5_LIB_CALL 372178825Sdfrkrb5_store_uint32(krb5_storage *sp, 373178825Sdfr uint32_t value) 374178825Sdfr{ 375178825Sdfr return krb5_store_int32(sp, (int32_t)value); 376178825Sdfr} 377178825Sdfr 37855682Smarkmstatic krb5_error_code 37955682Smarkmkrb5_ret_int(krb5_storage *sp, 38055682Smarkm int32_t *value, 38155682Smarkm size_t len) 38255682Smarkm{ 38355682Smarkm int ret; 38455682Smarkm unsigned char v[4]; 38555682Smarkm unsigned long w; 38655682Smarkm ret = sp->fetch(sp, v, len); 387233294Sstas if (ret < 0) 388233294Sstas return errno; 389233294Sstas if ((size_t)ret != len) 390233294Sstas return sp->eof_code; 39155682Smarkm _krb5_get_int(v, &w, len); 39255682Smarkm *value = w; 39355682Smarkm return 0; 39455682Smarkm} 39555682Smarkm 396233294Sstas/** 397233294Sstas * Read a int32 from storage, byte order is controlled by the settings 398233294Sstas * on the storage, see krb5_storage_set_byteorder(). 399233294Sstas * 400233294Sstas * @param sp the storage to write too 401233294Sstas * @param value the value read from the buffer 402233294Sstas * 403233294Sstas * @return 0 for success, or a Kerberos 5 error code on failure. 404233294Sstas * 405233294Sstas * @ingroup krb5_storage 406233294Sstas */ 407233294Sstas 408233294SstasKRB5_LIB_FUNCTION krb5_error_code KRB5_LIB_CALL 40955682Smarkmkrb5_ret_int32(krb5_storage *sp, 41055682Smarkm int32_t *value) 41155682Smarkm{ 41255682Smarkm krb5_error_code ret = krb5_ret_int(sp, value, 4); 41355682Smarkm if(ret) 41455682Smarkm return ret; 41578527Sassar if(BYTEORDER_IS_HOST(sp)) 41678527Sassar *value = htonl(*value); 41778527Sassar else if(BYTEORDER_IS_LE(sp)) 41878527Sassar *value = bswap32(*value); 41955682Smarkm return 0; 42055682Smarkm} 42155682Smarkm 422233294Sstas/** 423233294Sstas * Read a uint32 from storage, byte order is controlled by the settings 424233294Sstas * on the storage, see krb5_storage_set_byteorder(). 425233294Sstas * 426233294Sstas * @param sp the storage to write too 427233294Sstas * @param value the value read from the buffer 428233294Sstas * 429233294Sstas * @return 0 for success, or a Kerberos 5 error code on failure. 430233294Sstas * 431233294Sstas * @ingroup krb5_storage 432233294Sstas */ 433233294Sstas 434233294SstasKRB5_LIB_FUNCTION krb5_error_code KRB5_LIB_CALL 435178825Sdfrkrb5_ret_uint32(krb5_storage *sp, 436178825Sdfr uint32_t *value) 437178825Sdfr{ 438178825Sdfr krb5_error_code ret; 439178825Sdfr int32_t v; 440178825Sdfr 441178825Sdfr ret = krb5_ret_int32(sp, &v); 442178825Sdfr if (ret == 0) 443178825Sdfr *value = (uint32_t)v; 444178825Sdfr 445178825Sdfr return ret; 446178825Sdfr} 447178825Sdfr 448233294Sstas/** 449233294Sstas * Store a int16 to storage, byte order is controlled by the settings 450233294Sstas * on the storage, see krb5_storage_set_byteorder(). 451233294Sstas * 452233294Sstas * @param sp the storage to write too 453233294Sstas * @param value the value to store 454233294Sstas * 455233294Sstas * @return 0 for success, or a Kerberos 5 error code on failure. 456233294Sstas * 457233294Sstas * @ingroup krb5_storage 458233294Sstas */ 459233294Sstas 460233294SstasKRB5_LIB_FUNCTION krb5_error_code KRB5_LIB_CALL 46155682Smarkmkrb5_store_int16(krb5_storage *sp, 46255682Smarkm int16_t value) 46355682Smarkm{ 46478527Sassar if(BYTEORDER_IS_HOST(sp)) 46555682Smarkm value = htons(value); 46678527Sassar else if(BYTEORDER_IS_LE(sp)) 46778527Sassar value = bswap16(value); 46855682Smarkm return krb5_store_int(sp, value, 2); 46955682Smarkm} 47055682Smarkm 471233294Sstas/** 472233294Sstas * Store a uint16 to storage, byte order is controlled by the settings 473233294Sstas * on the storage, see krb5_storage_set_byteorder(). 474233294Sstas * 475233294Sstas * @param sp the storage to write too 476233294Sstas * @param value the value to store 477233294Sstas * 478233294Sstas * @return 0 for success, or a Kerberos 5 error code on failure. 479233294Sstas * 480233294Sstas * @ingroup krb5_storage 481233294Sstas */ 482233294Sstas 483233294SstasKRB5_LIB_FUNCTION krb5_error_code KRB5_LIB_CALL 484178825Sdfrkrb5_store_uint16(krb5_storage *sp, 485178825Sdfr uint16_t value) 486178825Sdfr{ 487178825Sdfr return krb5_store_int16(sp, (int16_t)value); 488178825Sdfr} 489178825Sdfr 490233294Sstas/** 491233294Sstas * Read a int16 from storage, byte order is controlled by the settings 492233294Sstas * on the storage, see krb5_storage_set_byteorder(). 493233294Sstas * 494233294Sstas * @param sp the storage to write too 495233294Sstas * @param value the value read from the buffer 496233294Sstas * 497233294Sstas * @return 0 for success, or a Kerberos 5 error code on failure. 498233294Sstas * 499233294Sstas * @ingroup krb5_storage 500233294Sstas */ 501233294Sstas 502233294SstasKRB5_LIB_FUNCTION krb5_error_code KRB5_LIB_CALL 50355682Smarkmkrb5_ret_int16(krb5_storage *sp, 50455682Smarkm int16_t *value) 50555682Smarkm{ 50655682Smarkm int32_t v; 50755682Smarkm int ret; 50855682Smarkm ret = krb5_ret_int(sp, &v, 2); 50955682Smarkm if(ret) 51055682Smarkm return ret; 51155682Smarkm *value = v; 51278527Sassar if(BYTEORDER_IS_HOST(sp)) 51378527Sassar *value = htons(*value); 51478527Sassar else if(BYTEORDER_IS_LE(sp)) 51578527Sassar *value = bswap16(*value); 51655682Smarkm return 0; 51755682Smarkm} 51855682Smarkm 519233294Sstas/** 520233294Sstas * Read a int16 from storage, byte order is controlled by the settings 521233294Sstas * on the storage, see krb5_storage_set_byteorder(). 522233294Sstas * 523233294Sstas * @param sp the storage to write too 524233294Sstas * @param value the value read from the buffer 525233294Sstas * 526233294Sstas * @return 0 for success, or a Kerberos 5 error code on failure. 527233294Sstas * 528233294Sstas * @ingroup krb5_storage 529233294Sstas */ 530233294Sstas 531233294SstasKRB5_LIB_FUNCTION krb5_error_code KRB5_LIB_CALL 532178825Sdfrkrb5_ret_uint16(krb5_storage *sp, 533178825Sdfr uint16_t *value) 534178825Sdfr{ 535178825Sdfr krb5_error_code ret; 536178825Sdfr int16_t v; 537178825Sdfr 538178825Sdfr ret = krb5_ret_int16(sp, &v); 539178825Sdfr if (ret == 0) 540178825Sdfr *value = (uint16_t)v; 541178825Sdfr 542178825Sdfr return ret; 543178825Sdfr} 544178825Sdfr 545233294Sstas/** 546233294Sstas * Store a int8 to storage. 547233294Sstas * 548233294Sstas * @param sp the storage to write too 549233294Sstas * @param value the value to store 550233294Sstas * 551233294Sstas * @return 0 for success, or a Kerberos 5 error code on failure. 552233294Sstas * 553233294Sstas * @ingroup krb5_storage 554233294Sstas */ 555233294Sstas 556233294SstasKRB5_LIB_FUNCTION krb5_error_code KRB5_LIB_CALL 55755682Smarkmkrb5_store_int8(krb5_storage *sp, 55855682Smarkm int8_t value) 55955682Smarkm{ 56055682Smarkm int ret; 56155682Smarkm 56255682Smarkm ret = sp->store(sp, &value, sizeof(value)); 56355682Smarkm if (ret != sizeof(value)) 564102644Snectar return (ret<0)?errno:sp->eof_code; 56555682Smarkm return 0; 56655682Smarkm} 56755682Smarkm 568233294Sstas/** 569233294Sstas * Store a uint8 to storage. 570233294Sstas * 571233294Sstas * @param sp the storage to write too 572233294Sstas * @param value the value to store 573233294Sstas * 574233294Sstas * @return 0 for success, or a Kerberos 5 error code on failure. 575233294Sstas * 576233294Sstas * @ingroup krb5_storage 577233294Sstas */ 578233294Sstas 579233294SstasKRB5_LIB_FUNCTION krb5_error_code KRB5_LIB_CALL 580178825Sdfrkrb5_store_uint8(krb5_storage *sp, 581178825Sdfr uint8_t value) 582178825Sdfr{ 583178825Sdfr return krb5_store_int8(sp, (int8_t)value); 584178825Sdfr} 585178825Sdfr 586233294Sstas/** 587233294Sstas * Read a int8 from storage 588233294Sstas * 589233294Sstas * @param sp the storage to write too 590233294Sstas * @param value the value read from the buffer 591233294Sstas * 592233294Sstas * @return 0 for success, or a Kerberos 5 error code on failure. 593233294Sstas * 594233294Sstas * @ingroup krb5_storage 595233294Sstas */ 596233294Sstas 597233294SstasKRB5_LIB_FUNCTION krb5_error_code KRB5_LIB_CALL 59855682Smarkmkrb5_ret_int8(krb5_storage *sp, 59955682Smarkm int8_t *value) 60055682Smarkm{ 60155682Smarkm int ret; 60255682Smarkm 60355682Smarkm ret = sp->fetch(sp, value, sizeof(*value)); 60455682Smarkm if (ret != sizeof(*value)) 605102644Snectar return (ret<0)?errno:sp->eof_code; 60655682Smarkm return 0; 60755682Smarkm} 60855682Smarkm 609233294Sstas/** 610233294Sstas * Read a uint8 from storage 611233294Sstas * 612233294Sstas * @param sp the storage to write too 613233294Sstas * @param value the value read from the buffer 614233294Sstas * 615233294Sstas * @return 0 for success, or a Kerberos 5 error code on failure. 616233294Sstas * 617233294Sstas * @ingroup krb5_storage 618233294Sstas */ 619233294Sstas 620233294SstasKRB5_LIB_FUNCTION krb5_error_code KRB5_LIB_CALL 621178825Sdfrkrb5_ret_uint8(krb5_storage *sp, 622178825Sdfr uint8_t *value) 623178825Sdfr{ 624178825Sdfr krb5_error_code ret; 625178825Sdfr int8_t v; 626178825Sdfr 627178825Sdfr ret = krb5_ret_int8(sp, &v); 628178825Sdfr if (ret == 0) 629178825Sdfr *value = (uint8_t)v; 630178825Sdfr 631178825Sdfr return ret; 632178825Sdfr} 633178825Sdfr 634233294Sstas/** 635233294Sstas * Store a data to the storage. The data is stored with an int32 as 636233294Sstas * lenght plus the data (not padded). 637233294Sstas * 638233294Sstas * @param sp the storage buffer to write to 639233294Sstas * @param data the buffer to store. 640233294Sstas * 641233294Sstas * @return 0 on success, a Kerberos 5 error code on failure. 642233294Sstas * 643233294Sstas * @ingroup krb5_storage 644233294Sstas */ 645233294Sstas 646233294SstasKRB5_LIB_FUNCTION krb5_error_code KRB5_LIB_CALL 64755682Smarkmkrb5_store_data(krb5_storage *sp, 64855682Smarkm krb5_data data) 64955682Smarkm{ 65055682Smarkm int ret; 65155682Smarkm ret = krb5_store_int32(sp, data.length); 65255682Smarkm if(ret < 0) 65355682Smarkm return ret; 65455682Smarkm ret = sp->store(sp, data.data, data.length); 655233294Sstas if(ret < 0) 656233294Sstas return errno; 657233294Sstas if((size_t)ret != data.length) 658102644Snectar return sp->eof_code; 65955682Smarkm return 0; 66055682Smarkm} 66155682Smarkm 662233294Sstas/** 663233294Sstas * Parse a data from the storage. 664233294Sstas * 665233294Sstas * @param sp the storage buffer to read from 666233294Sstas * @param data the parsed data 667233294Sstas * 668233294Sstas * @return 0 on success, a Kerberos 5 error code on failure. 669233294Sstas * 670233294Sstas * @ingroup krb5_storage 671233294Sstas */ 672233294Sstas 673233294SstasKRB5_LIB_FUNCTION krb5_error_code KRB5_LIB_CALL 67455682Smarkmkrb5_ret_data(krb5_storage *sp, 67555682Smarkm krb5_data *data) 67655682Smarkm{ 67755682Smarkm int ret; 67855682Smarkm int32_t size; 67955682Smarkm 68055682Smarkm ret = krb5_ret_int32(sp, &size); 68155682Smarkm if(ret) 68255682Smarkm return ret; 683233294Sstas ret = size_too_large(sp, size); 684233294Sstas if (ret) 685233294Sstas return ret; 68655682Smarkm ret = krb5_data_alloc (data, size); 68755682Smarkm if (ret) 68855682Smarkm return ret; 68955682Smarkm if (size) { 69055682Smarkm ret = sp->fetch(sp, data->data, size); 69155682Smarkm if(ret != size) 692102644Snectar return (ret < 0)? errno : sp->eof_code; 69355682Smarkm } 69455682Smarkm return 0; 69555682Smarkm} 69655682Smarkm 697233294Sstas/** 698233294Sstas * Store a string to the buffer. The data is formated as an len:uint32 699233294Sstas * plus the string itself (not padded). 700233294Sstas * 701233294Sstas * @param sp the storage buffer to write to 702233294Sstas * @param s the string to store. 703233294Sstas * 704233294Sstas * @return 0 on success, a Kerberos 5 error code on failure. 705233294Sstas * 706233294Sstas * @ingroup krb5_storage 707233294Sstas */ 708233294Sstas 709233294SstasKRB5_LIB_FUNCTION krb5_error_code KRB5_LIB_CALL 71055682Smarkmkrb5_store_string(krb5_storage *sp, const char *s) 71155682Smarkm{ 71255682Smarkm krb5_data data; 71355682Smarkm data.length = strlen(s); 714178825Sdfr data.data = rk_UNCONST(s); 71555682Smarkm return krb5_store_data(sp, data); 71655682Smarkm} 71755682Smarkm 718233294Sstas/** 719233294Sstas * Parse a string from the storage. 720233294Sstas * 721233294Sstas * @param sp the storage buffer to read from 722233294Sstas * @param string the parsed string 723233294Sstas * 724233294Sstas * @return 0 on success, a Kerberos 5 error code on failure. 725233294Sstas * 726233294Sstas * @ingroup krb5_storage 727233294Sstas */ 728233294Sstas 729233294Sstas 730233294SstasKRB5_LIB_FUNCTION krb5_error_code KRB5_LIB_CALL 73155682Smarkmkrb5_ret_string(krb5_storage *sp, 73255682Smarkm char **string) 73355682Smarkm{ 73455682Smarkm int ret; 73555682Smarkm krb5_data data; 73655682Smarkm ret = krb5_ret_data(sp, &data); 73755682Smarkm if(ret) 73855682Smarkm return ret; 73955682Smarkm *string = realloc(data.data, data.length + 1); 74055682Smarkm if(*string == NULL){ 74155682Smarkm free(data.data); 74255682Smarkm return ENOMEM; 74355682Smarkm } 74455682Smarkm (*string)[data.length] = 0; 74555682Smarkm return 0; 74655682Smarkm} 74755682Smarkm 748233294Sstas/** 749233294Sstas * Store a zero terminated string to the buffer. The data is stored 750233294Sstas * one character at a time until a NUL is stored. 751233294Sstas * 752233294Sstas * @param sp the storage buffer to write to 753233294Sstas * @param s the string to store. 754233294Sstas * 755233294Sstas * @return 0 on success, a Kerberos 5 error code on failure. 756233294Sstas * 757233294Sstas * @ingroup krb5_storage 758233294Sstas */ 759233294Sstas 760233294SstasKRB5_LIB_FUNCTION krb5_error_code KRB5_LIB_CALL 76172445Sassarkrb5_store_stringz(krb5_storage *sp, const char *s) 76255682Smarkm{ 76355682Smarkm size_t len = strlen(s) + 1; 76455682Smarkm ssize_t ret; 76555682Smarkm 76655682Smarkm ret = sp->store(sp, s, len); 767233294Sstas if(ret < 0) 768233294Sstas return ret; 769233294Sstas if((size_t)ret != len) 770233294Sstas return sp->eof_code; 77155682Smarkm return 0; 77255682Smarkm} 77355682Smarkm 774233294Sstas/** 775233294Sstas * Parse zero terminated string from the storage. 776233294Sstas * 777233294Sstas * @param sp the storage buffer to read from 778233294Sstas * @param string the parsed string 779233294Sstas * 780233294Sstas * @return 0 on success, a Kerberos 5 error code on failure. 781233294Sstas * 782233294Sstas * @ingroup krb5_storage 783233294Sstas */ 784233294Sstas 785233294SstasKRB5_LIB_FUNCTION krb5_error_code KRB5_LIB_CALL 78655682Smarkmkrb5_ret_stringz(krb5_storage *sp, 78755682Smarkm char **string) 78855682Smarkm{ 78955682Smarkm char c; 79055682Smarkm char *s = NULL; 79155682Smarkm size_t len = 0; 79255682Smarkm ssize_t ret; 79355682Smarkm 79455682Smarkm while((ret = sp->fetch(sp, &c, 1)) == 1){ 79555682Smarkm char *tmp; 79655682Smarkm 79755682Smarkm len++; 798233294Sstas ret = size_too_large(sp, len); 799233294Sstas if (ret) 800233294Sstas break; 80155682Smarkm tmp = realloc (s, len); 80255682Smarkm if (tmp == NULL) { 80355682Smarkm free (s); 80455682Smarkm return ENOMEM; 80555682Smarkm } 80655682Smarkm s = tmp; 80755682Smarkm s[len - 1] = c; 80855682Smarkm if(c == 0) 80955682Smarkm break; 81055682Smarkm } 81155682Smarkm if(ret != 1){ 81255682Smarkm free(s); 81355682Smarkm if(ret == 0) 814102644Snectar return sp->eof_code; 81555682Smarkm return ret; 81655682Smarkm } 81755682Smarkm *string = s; 81855682Smarkm return 0; 81955682Smarkm} 82055682Smarkm 821233294SstasKRB5_LIB_FUNCTION krb5_error_code KRB5_LIB_CALL 822178825Sdfrkrb5_store_stringnl(krb5_storage *sp, const char *s) 823178825Sdfr{ 824178825Sdfr size_t len = strlen(s); 825178825Sdfr ssize_t ret; 82655682Smarkm 827178825Sdfr ret = sp->store(sp, s, len); 828233294Sstas if(ret < 0) 829233294Sstas return ret; 830233294Sstas if((size_t)ret != len) 831233294Sstas return sp->eof_code; 832178825Sdfr ret = sp->store(sp, "\n", 1); 833178825Sdfr if(ret != 1) { 834178825Sdfr if(ret < 0) 835178825Sdfr return ret; 836178825Sdfr else 837178825Sdfr return sp->eof_code; 838178825Sdfr } 839178825Sdfr 840178825Sdfr return 0; 841178825Sdfr 842178825Sdfr} 843178825Sdfr 844233294SstasKRB5_LIB_FUNCTION krb5_error_code KRB5_LIB_CALL 845178825Sdfrkrb5_ret_stringnl(krb5_storage *sp, 846178825Sdfr char **string) 847178825Sdfr{ 848178825Sdfr int expect_nl = 0; 849178825Sdfr char c; 850178825Sdfr char *s = NULL; 851178825Sdfr size_t len = 0; 852178825Sdfr ssize_t ret; 853178825Sdfr 854178825Sdfr while((ret = sp->fetch(sp, &c, 1)) == 1){ 855178825Sdfr char *tmp; 856178825Sdfr 857178825Sdfr if (c == '\r') { 858178825Sdfr expect_nl = 1; 859178825Sdfr continue; 860178825Sdfr } 861178825Sdfr if (expect_nl && c != '\n') { 862178825Sdfr free(s); 863178825Sdfr return KRB5_BADMSGTYPE; 864178825Sdfr } 865178825Sdfr 866178825Sdfr len++; 867233294Sstas ret = size_too_large(sp, len); 868233294Sstas if (ret) 869233294Sstas break; 870178825Sdfr tmp = realloc (s, len); 871178825Sdfr if (tmp == NULL) { 872178825Sdfr free (s); 873178825Sdfr return ENOMEM; 874178825Sdfr } 875178825Sdfr s = tmp; 876178825Sdfr if(c == '\n') { 877178825Sdfr s[len - 1] = '\0'; 878178825Sdfr break; 879178825Sdfr } 880178825Sdfr s[len - 1] = c; 881178825Sdfr } 882178825Sdfr if(ret != 1){ 883178825Sdfr free(s); 884178825Sdfr if(ret == 0) 885178825Sdfr return sp->eof_code; 886178825Sdfr return ret; 887178825Sdfr } 888178825Sdfr *string = s; 889178825Sdfr return 0; 890178825Sdfr} 891178825Sdfr 892233294Sstas/** 893233294Sstas * Write a principal block to storage. 894233294Sstas * 895233294Sstas * @param sp the storage buffer to write to 896233294Sstas * @param p the principal block to write. 897233294Sstas * 898233294Sstas * @return 0 on success, a Kerberos 5 error code on failure. 899233294Sstas * 900233294Sstas * @ingroup krb5_storage 901233294Sstas */ 902178825Sdfr 903233294SstasKRB5_LIB_FUNCTION krb5_error_code KRB5_LIB_CALL 90455682Smarkmkrb5_store_principal(krb5_storage *sp, 905178825Sdfr krb5_const_principal p) 90655682Smarkm{ 907233294Sstas size_t i; 90855682Smarkm int ret; 90955682Smarkm 91055682Smarkm if(!krb5_storage_is_flags(sp, KRB5_STORAGE_PRINCIPAL_NO_NAME_TYPE)) { 911178825Sdfr ret = krb5_store_int32(sp, p->name.name_type); 912178825Sdfr if(ret) return ret; 91355682Smarkm } 91455682Smarkm if(krb5_storage_is_flags(sp, KRB5_STORAGE_PRINCIPAL_WRONG_NUM_COMPONENTS)) 91555682Smarkm ret = krb5_store_int32(sp, p->name.name_string.len + 1); 91655682Smarkm else 917178825Sdfr ret = krb5_store_int32(sp, p->name.name_string.len); 918233294Sstas 91955682Smarkm if(ret) return ret; 92055682Smarkm ret = krb5_store_string(sp, p->realm); 92155682Smarkm if(ret) return ret; 92255682Smarkm for(i = 0; i < p->name.name_string.len; i++){ 92355682Smarkm ret = krb5_store_string(sp, p->name.name_string.val[i]); 92455682Smarkm if(ret) return ret; 92555682Smarkm } 92655682Smarkm return 0; 92755682Smarkm} 92855682Smarkm 929233294Sstas/** 930233294Sstas * Parse principal from the storage. 931233294Sstas * 932233294Sstas * @param sp the storage buffer to read from 933233294Sstas * @param princ the parsed principal 934233294Sstas * 935233294Sstas * @return 0 on success, a Kerberos 5 error code on failure. 936233294Sstas * 937233294Sstas * @ingroup krb5_storage 938233294Sstas */ 939233294Sstas 940233294SstasKRB5_LIB_FUNCTION krb5_error_code KRB5_LIB_CALL 94155682Smarkmkrb5_ret_principal(krb5_storage *sp, 94255682Smarkm krb5_principal *princ) 94355682Smarkm{ 94455682Smarkm int i; 94555682Smarkm int ret; 94655682Smarkm krb5_principal p; 94755682Smarkm int32_t type; 94855682Smarkm int32_t ncomp; 949233294Sstas 95055682Smarkm p = calloc(1, sizeof(*p)); 95155682Smarkm if(p == NULL) 95255682Smarkm return ENOMEM; 95355682Smarkm 95455682Smarkm if(krb5_storage_is_flags(sp, KRB5_STORAGE_PRINCIPAL_NO_NAME_TYPE)) 95555682Smarkm type = KRB5_NT_UNKNOWN; 956178825Sdfr else if((ret = krb5_ret_int32(sp, &type))){ 95755682Smarkm free(p); 95855682Smarkm return ret; 95955682Smarkm } 96055682Smarkm if((ret = krb5_ret_int32(sp, &ncomp))){ 96155682Smarkm free(p); 96255682Smarkm return ret; 96355682Smarkm } 96455682Smarkm if(krb5_storage_is_flags(sp, KRB5_STORAGE_PRINCIPAL_WRONG_NUM_COMPONENTS)) 96555682Smarkm ncomp--; 966178825Sdfr if (ncomp < 0) { 967178825Sdfr free(p); 968178825Sdfr return EINVAL; 969178825Sdfr } 970233294Sstas ret = size_too_large_num(sp, ncomp, sizeof(p->name.name_string.val[0])); 971233294Sstas if (ret) { 972233294Sstas free(p); 973233294Sstas return ret; 974233294Sstas } 97555682Smarkm p->name.name_type = type; 97655682Smarkm p->name.name_string.len = ncomp; 97755682Smarkm ret = krb5_ret_string(sp, &p->realm); 978178825Sdfr if(ret) { 979178825Sdfr free(p); 980178825Sdfr return ret; 981178825Sdfr } 982233294Sstas p->name.name_string.val = calloc(ncomp, sizeof(p->name.name_string.val[0])); 983178825Sdfr if(p->name.name_string.val == NULL && ncomp != 0){ 98455682Smarkm free(p->realm); 985178825Sdfr free(p); 98655682Smarkm return ENOMEM; 98755682Smarkm } 98855682Smarkm for(i = 0; i < ncomp; i++){ 98955682Smarkm ret = krb5_ret_string(sp, &p->name.name_string.val[i]); 990178825Sdfr if(ret) { 991178825Sdfr while (i >= 0) 992178825Sdfr free(p->name.name_string.val[i--]); 993178825Sdfr free(p->realm); 994178825Sdfr free(p); 995178825Sdfr return ret; 996178825Sdfr } 99755682Smarkm } 99855682Smarkm *princ = p; 99955682Smarkm return 0; 100055682Smarkm} 100155682Smarkm 1002233294Sstas/** 1003233294Sstas * Store a keyblock to the storage. 1004233294Sstas * 1005233294Sstas * @param sp the storage buffer to write to 1006233294Sstas * @param p the keyblock to write 1007233294Sstas * 1008233294Sstas * @return 0 on success, a Kerberos 5 error code on failure. 1009233294Sstas * 1010233294Sstas * @ingroup krb5_storage 1011233294Sstas */ 1012233294Sstas 1013233294SstasKRB5_LIB_FUNCTION krb5_error_code KRB5_LIB_CALL 101455682Smarkmkrb5_store_keyblock(krb5_storage *sp, krb5_keyblock p) 101555682Smarkm{ 101655682Smarkm int ret; 101755682Smarkm ret = krb5_store_int16(sp, p.keytype); 101855682Smarkm if(ret) return ret; 101955682Smarkm 102055682Smarkm if(krb5_storage_is_flags(sp, KRB5_STORAGE_KEYBLOCK_KEYTYPE_TWICE)){ 102155682Smarkm /* this should really be enctype, but it is the same as 102255682Smarkm keytype nowadays */ 102355682Smarkm ret = krb5_store_int16(sp, p.keytype); 102455682Smarkm if(ret) return ret; 102555682Smarkm } 102655682Smarkm 102755682Smarkm ret = krb5_store_data(sp, p.keyvalue); 102855682Smarkm return ret; 102955682Smarkm} 103055682Smarkm 1031233294Sstas/** 1032233294Sstas * Read a keyblock from the storage. 1033233294Sstas * 1034233294Sstas * @param sp the storage buffer to write to 1035233294Sstas * @param p the keyblock read from storage, free using krb5_free_keyblock() 1036233294Sstas * 1037233294Sstas * @return 0 on success, a Kerberos 5 error code on failure. 1038233294Sstas * 1039233294Sstas * @ingroup krb5_storage 1040233294Sstas */ 1041233294Sstas 1042233294SstasKRB5_LIB_FUNCTION krb5_error_code KRB5_LIB_CALL 104355682Smarkmkrb5_ret_keyblock(krb5_storage *sp, krb5_keyblock *p) 104455682Smarkm{ 104555682Smarkm int ret; 104655682Smarkm int16_t tmp; 104755682Smarkm 104855682Smarkm ret = krb5_ret_int16(sp, &tmp); 104955682Smarkm if(ret) return ret; 105055682Smarkm p->keytype = tmp; 105155682Smarkm 105255682Smarkm if(krb5_storage_is_flags(sp, KRB5_STORAGE_KEYBLOCK_KEYTYPE_TWICE)){ 105355682Smarkm ret = krb5_ret_int16(sp, &tmp); 105455682Smarkm if(ret) return ret; 105555682Smarkm } 105655682Smarkm 105755682Smarkm ret = krb5_ret_data(sp, &p->keyvalue); 105855682Smarkm return ret; 105955682Smarkm} 106055682Smarkm 1061233294Sstas/** 1062233294Sstas * Write a times block to storage. 1063233294Sstas * 1064233294Sstas * @param sp the storage buffer to write to 1065233294Sstas * @param times the times block to write. 1066233294Sstas * 1067233294Sstas * @return 0 on success, a Kerberos 5 error code on failure. 1068233294Sstas * 1069233294Sstas * @ingroup krb5_storage 1070233294Sstas */ 1071233294Sstas 1072233294SstasKRB5_LIB_FUNCTION krb5_error_code KRB5_LIB_CALL 107355682Smarkmkrb5_store_times(krb5_storage *sp, krb5_times times) 107455682Smarkm{ 107555682Smarkm int ret; 107655682Smarkm ret = krb5_store_int32(sp, times.authtime); 107755682Smarkm if(ret) return ret; 107855682Smarkm ret = krb5_store_int32(sp, times.starttime); 107955682Smarkm if(ret) return ret; 108055682Smarkm ret = krb5_store_int32(sp, times.endtime); 108155682Smarkm if(ret) return ret; 108255682Smarkm ret = krb5_store_int32(sp, times.renew_till); 108355682Smarkm return ret; 108455682Smarkm} 108555682Smarkm 1086233294Sstas/** 1087233294Sstas * Read a times block from the storage. 1088233294Sstas * 1089233294Sstas * @param sp the storage buffer to write to 1090233294Sstas * @param times the times block read from storage 1091233294Sstas * 1092233294Sstas * @return 0 on success, a Kerberos 5 error code on failure. 1093233294Sstas * 1094233294Sstas * @ingroup krb5_storage 1095233294Sstas */ 1096233294Sstas 1097233294SstasKRB5_LIB_FUNCTION krb5_error_code KRB5_LIB_CALL 109855682Smarkmkrb5_ret_times(krb5_storage *sp, krb5_times *times) 109955682Smarkm{ 110055682Smarkm int ret; 110155682Smarkm int32_t tmp; 110255682Smarkm ret = krb5_ret_int32(sp, &tmp); 110355682Smarkm times->authtime = tmp; 110455682Smarkm if(ret) return ret; 110555682Smarkm ret = krb5_ret_int32(sp, &tmp); 110655682Smarkm times->starttime = tmp; 110755682Smarkm if(ret) return ret; 110855682Smarkm ret = krb5_ret_int32(sp, &tmp); 110955682Smarkm times->endtime = tmp; 111055682Smarkm if(ret) return ret; 111155682Smarkm ret = krb5_ret_int32(sp, &tmp); 111255682Smarkm times->renew_till = tmp; 111355682Smarkm return ret; 111455682Smarkm} 111555682Smarkm 1116233294Sstas/** 1117233294Sstas * Write a address block to storage. 1118233294Sstas * 1119233294Sstas * @param sp the storage buffer to write to 1120233294Sstas * @param p the address block to write. 1121233294Sstas * 1122233294Sstas * @return 0 on success, a Kerberos 5 error code on failure. 1123233294Sstas * 1124233294Sstas * @ingroup krb5_storage 1125233294Sstas */ 1126233294Sstas 1127233294SstasKRB5_LIB_FUNCTION krb5_error_code KRB5_LIB_CALL 112855682Smarkmkrb5_store_address(krb5_storage *sp, krb5_address p) 112955682Smarkm{ 113055682Smarkm int ret; 113155682Smarkm ret = krb5_store_int16(sp, p.addr_type); 113255682Smarkm if(ret) return ret; 113355682Smarkm ret = krb5_store_data(sp, p.address); 113455682Smarkm return ret; 113555682Smarkm} 113655682Smarkm 1137233294Sstas/** 1138233294Sstas * Read a address block from the storage. 1139233294Sstas * 1140233294Sstas * @param sp the storage buffer to write to 1141233294Sstas * @param adr the address block read from storage 1142233294Sstas * 1143233294Sstas * @return 0 on success, a Kerberos 5 error code on failure. 1144233294Sstas * 1145233294Sstas * @ingroup krb5_storage 1146233294Sstas */ 1147233294Sstas 1148233294SstasKRB5_LIB_FUNCTION krb5_error_code KRB5_LIB_CALL 114955682Smarkmkrb5_ret_address(krb5_storage *sp, krb5_address *adr) 115055682Smarkm{ 115155682Smarkm int16_t t; 115255682Smarkm int ret; 115355682Smarkm ret = krb5_ret_int16(sp, &t); 115455682Smarkm if(ret) return ret; 115555682Smarkm adr->addr_type = t; 115655682Smarkm ret = krb5_ret_data(sp, &adr->address); 115755682Smarkm return ret; 115855682Smarkm} 115955682Smarkm 1160233294Sstas/** 1161233294Sstas * Write a addresses block to storage. 1162233294Sstas * 1163233294Sstas * @param sp the storage buffer to write to 1164233294Sstas * @param p the addresses block to write. 1165233294Sstas * 1166233294Sstas * @return 0 on success, a Kerberos 5 error code on failure. 1167233294Sstas * 1168233294Sstas * @ingroup krb5_storage 1169233294Sstas */ 1170233294Sstas 1171233294SstasKRB5_LIB_FUNCTION krb5_error_code KRB5_LIB_CALL 117255682Smarkmkrb5_store_addrs(krb5_storage *sp, krb5_addresses p) 117355682Smarkm{ 1174233294Sstas size_t i; 117555682Smarkm int ret; 117655682Smarkm ret = krb5_store_int32(sp, p.len); 117755682Smarkm if(ret) return ret; 117855682Smarkm for(i = 0; i<p.len; i++){ 117955682Smarkm ret = krb5_store_address(sp, p.val[i]); 118055682Smarkm if(ret) break; 118155682Smarkm } 118255682Smarkm return ret; 118355682Smarkm} 118455682Smarkm 1185233294Sstas/** 1186233294Sstas * Read a addresses block from the storage. 1187233294Sstas * 1188233294Sstas * @param sp the storage buffer to write to 1189233294Sstas * @param adr the addresses block read from storage 1190233294Sstas * 1191233294Sstas * @return 0 on success, a Kerberos 5 error code on failure. 1192233294Sstas * 1193233294Sstas * @ingroup krb5_storage 1194233294Sstas */ 1195233294Sstas 1196233294SstasKRB5_LIB_FUNCTION krb5_error_code KRB5_LIB_CALL 119755682Smarkmkrb5_ret_addrs(krb5_storage *sp, krb5_addresses *adr) 119855682Smarkm{ 1199233294Sstas size_t i; 120055682Smarkm int ret; 120155682Smarkm int32_t tmp; 120255682Smarkm 120355682Smarkm ret = krb5_ret_int32(sp, &tmp); 120455682Smarkm if(ret) return ret; 1205233294Sstas ret = size_too_large_num(sp, tmp, sizeof(adr->val[0])); 1206233294Sstas if (ret) return ret; 120755682Smarkm adr->len = tmp; 120855682Smarkm ALLOC(adr->val, adr->len); 1209178825Sdfr if (adr->val == NULL && adr->len != 0) 1210178825Sdfr return ENOMEM; 121155682Smarkm for(i = 0; i < adr->len; i++){ 121255682Smarkm ret = krb5_ret_address(sp, &adr->val[i]); 121355682Smarkm if(ret) break; 121455682Smarkm } 121555682Smarkm return ret; 121655682Smarkm} 121755682Smarkm 1218233294Sstas/** 1219233294Sstas * Write a auth data block to storage. 1220233294Sstas * 1221233294Sstas * @param sp the storage buffer to write to 1222233294Sstas * @param auth the auth data block to write. 1223233294Sstas * 1224233294Sstas * @return 0 on success, a Kerberos 5 error code on failure. 1225233294Sstas * 1226233294Sstas * @ingroup krb5_storage 1227233294Sstas */ 1228233294Sstas 1229233294SstasKRB5_LIB_FUNCTION krb5_error_code KRB5_LIB_CALL 123055682Smarkmkrb5_store_authdata(krb5_storage *sp, krb5_authdata auth) 123155682Smarkm{ 123255682Smarkm krb5_error_code ret; 1233233294Sstas size_t i; 123455682Smarkm ret = krb5_store_int32(sp, auth.len); 123555682Smarkm if(ret) return ret; 123655682Smarkm for(i = 0; i < auth.len; i++){ 123755682Smarkm ret = krb5_store_int16(sp, auth.val[i].ad_type); 123855682Smarkm if(ret) break; 123955682Smarkm ret = krb5_store_data(sp, auth.val[i].ad_data); 124055682Smarkm if(ret) break; 124155682Smarkm } 124255682Smarkm return 0; 124355682Smarkm} 124455682Smarkm 1245233294Sstas/** 1246233294Sstas * Read a auth data from the storage. 1247233294Sstas * 1248233294Sstas * @param sp the storage buffer to write to 1249233294Sstas * @param auth the auth data block read from storage 1250233294Sstas * 1251233294Sstas * @return 0 on success, a Kerberos 5 error code on failure. 1252233294Sstas * 1253233294Sstas * @ingroup krb5_storage 1254233294Sstas */ 1255233294Sstas 1256233294SstasKRB5_LIB_FUNCTION krb5_error_code KRB5_LIB_CALL 125755682Smarkmkrb5_ret_authdata(krb5_storage *sp, krb5_authdata *auth) 125855682Smarkm{ 125955682Smarkm krb5_error_code ret; 126055682Smarkm int32_t tmp; 126155682Smarkm int16_t tmp2; 126255682Smarkm int i; 126355682Smarkm ret = krb5_ret_int32(sp, &tmp); 126455682Smarkm if(ret) return ret; 1265233294Sstas ret = size_too_large_num(sp, tmp, sizeof(auth->val[0])); 1266233294Sstas if (ret) return ret; 126755682Smarkm ALLOC_SEQ(auth, tmp); 1268178825Sdfr if (auth->val == NULL && tmp != 0) 1269178825Sdfr return ENOMEM; 127055682Smarkm for(i = 0; i < tmp; i++){ 127155682Smarkm ret = krb5_ret_int16(sp, &tmp2); 127255682Smarkm if(ret) break; 127355682Smarkm auth->val[i].ad_type = tmp2; 127455682Smarkm ret = krb5_ret_data(sp, &auth->val[i].ad_data); 127555682Smarkm if(ret) break; 127655682Smarkm } 127755682Smarkm return ret; 127855682Smarkm} 127955682Smarkm 1280127808Snectarstatic int32_t 1281127808Snectarbitswap32(int32_t b) 1282127808Snectar{ 1283127808Snectar int32_t r = 0; 1284127808Snectar int i; 1285127808Snectar for (i = 0; i < 32; i++) { 1286127808Snectar r = r << 1 | (b & 1); 1287127808Snectar b = b >> 1; 1288127808Snectar } 1289127808Snectar return r; 1290127808Snectar} 1291127808Snectar 1292233294Sstas/** 1293233294Sstas * Write a credentials block to storage. 1294127808Snectar * 1295233294Sstas * @param sp the storage buffer to write to 1296233294Sstas * @param creds the creds block to write. 1297233294Sstas * 1298233294Sstas * @return 0 on success, a Kerberos 5 error code on failure. 1299233294Sstas * 1300233294Sstas * @ingroup krb5_storage 130172445Sassar */ 130272445Sassar 1303233294SstasKRB5_LIB_FUNCTION krb5_error_code KRB5_LIB_CALL 1304178825Sdfrkrb5_store_creds(krb5_storage *sp, krb5_creds *creds) 130555682Smarkm{ 130672445Sassar int ret; 130772445Sassar 130872445Sassar ret = krb5_store_principal(sp, creds->client); 1309102644Snectar if(ret) 131072445Sassar return ret; 131172445Sassar ret = krb5_store_principal(sp, creds->server); 1312102644Snectar if(ret) 131372445Sassar return ret; 131472445Sassar ret = krb5_store_keyblock(sp, creds->session); 1315102644Snectar if(ret) 131672445Sassar return ret; 131772445Sassar ret = krb5_store_times(sp, creds->times); 1318102644Snectar if(ret) 131972445Sassar return ret; 1320178825Sdfr ret = krb5_store_int8(sp, creds->second_ticket.length != 0); /* is_skey */ 1321102644Snectar if(ret) 132272445Sassar return ret; 1323178825Sdfr 1324178825Sdfr if(krb5_storage_is_flags(sp, KRB5_STORAGE_CREDS_FLAGS_WRONG_BITORDER)) 1325127808Snectar ret = krb5_store_int32(sp, creds->flags.i); 1326178825Sdfr else 1327127808Snectar ret = krb5_store_int32(sp, bitswap32(TicketFlags2int(creds->flags.b))); 1328178825Sdfr if(ret) 1329178825Sdfr return ret; 1330178825Sdfr 133172445Sassar ret = krb5_store_addrs(sp, creds->addresses); 1332102644Snectar if(ret) 133372445Sassar return ret; 133472445Sassar ret = krb5_store_authdata(sp, creds->authdata); 1335102644Snectar if(ret) 133672445Sassar return ret; 133772445Sassar ret = krb5_store_data(sp, creds->ticket); 1338102644Snectar if(ret) 133972445Sassar return ret; 134072445Sassar ret = krb5_store_data(sp, creds->second_ticket); 1341102644Snectar return ret; 134255682Smarkm} 134355682Smarkm 1344233294Sstas/** 1345233294Sstas * Read a credentials block from the storage. 1346233294Sstas * 1347233294Sstas * @param sp the storage buffer to write to 1348233294Sstas * @param creds the credentials block read from storage 1349233294Sstas * 1350233294Sstas * @return 0 on success, a Kerberos 5 error code on failure. 1351233294Sstas * 1352233294Sstas * @ingroup krb5_storage 1353233294Sstas */ 1354233294Sstas 1355233294SstasKRB5_LIB_FUNCTION krb5_error_code KRB5_LIB_CALL 135655682Smarkmkrb5_ret_creds(krb5_storage *sp, krb5_creds *creds) 135755682Smarkm{ 135855682Smarkm krb5_error_code ret; 135955682Smarkm int8_t dummy8; 136055682Smarkm int32_t dummy32; 136155682Smarkm 136255682Smarkm memset(creds, 0, sizeof(*creds)); 136355682Smarkm ret = krb5_ret_principal (sp, &creds->client); 136455682Smarkm if(ret) goto cleanup; 136555682Smarkm ret = krb5_ret_principal (sp, &creds->server); 136655682Smarkm if(ret) goto cleanup; 136755682Smarkm ret = krb5_ret_keyblock (sp, &creds->session); 136855682Smarkm if(ret) goto cleanup; 136955682Smarkm ret = krb5_ret_times (sp, &creds->times); 137055682Smarkm if(ret) goto cleanup; 137155682Smarkm ret = krb5_ret_int8 (sp, &dummy8); 137255682Smarkm if(ret) goto cleanup; 137355682Smarkm ret = krb5_ret_int32 (sp, &dummy32); 137455682Smarkm if(ret) goto cleanup; 1375127808Snectar /* 1376127808Snectar * Runtime detect the what is the higher bits of the bitfield. If 1377178825Sdfr * any of the higher bits are set in the input data, it's either a 1378178825Sdfr * new ticket flag (and this code need to be removed), or it's a 1379127808Snectar * MIT cache (or new Heimdal cache), lets change it to our current 1380127808Snectar * format. 1381127808Snectar */ 1382127808Snectar { 1383178825Sdfr uint32_t mask = 0xffff0000; 1384127808Snectar creds->flags.i = 0; 1385127808Snectar creds->flags.b.anonymous = 1; 1386127808Snectar if (creds->flags.i & mask) 1387127808Snectar mask = ~mask; 1388127808Snectar if (dummy32 & mask) 1389127808Snectar dummy32 = bitswap32(dummy32); 1390127808Snectar } 139155682Smarkm creds->flags.i = dummy32; 139255682Smarkm ret = krb5_ret_addrs (sp, &creds->addresses); 139355682Smarkm if(ret) goto cleanup; 139455682Smarkm ret = krb5_ret_authdata (sp, &creds->authdata); 139555682Smarkm if(ret) goto cleanup; 139655682Smarkm ret = krb5_ret_data (sp, &creds->ticket); 139755682Smarkm if(ret) goto cleanup; 139855682Smarkm ret = krb5_ret_data (sp, &creds->second_ticket); 139955682Smarkmcleanup: 1400102644Snectar if(ret) { 1401233294Sstas#if 0 1402178825Sdfr krb5_free_cred_contents(context, creds); /* XXX */ 140355682Smarkm#endif 1404102644Snectar } 140555682Smarkm return ret; 140655682Smarkm} 1407178825Sdfr 1408178825Sdfr#define SC_CLIENT_PRINCIPAL 0x0001 1409178825Sdfr#define SC_SERVER_PRINCIPAL 0x0002 1410178825Sdfr#define SC_SESSION_KEY 0x0004 1411178825Sdfr#define SC_TICKET 0x0008 1412178825Sdfr#define SC_SECOND_TICKET 0x0010 1413178825Sdfr#define SC_AUTHDATA 0x0020 1414178825Sdfr#define SC_ADDRESSES 0x0040 1415178825Sdfr 1416233294Sstas/** 1417233294Sstas * Write a tagged credentials block to storage. 1418178825Sdfr * 1419233294Sstas * @param sp the storage buffer to write to 1420233294Sstas * @param creds the creds block to write. 1421233294Sstas * 1422233294Sstas * @return 0 on success, a Kerberos 5 error code on failure. 1423233294Sstas * 1424233294Sstas * @ingroup krb5_storage 1425178825Sdfr */ 1426178825Sdfr 1427233294SstasKRB5_LIB_FUNCTION krb5_error_code KRB5_LIB_CALL 1428178825Sdfrkrb5_store_creds_tag(krb5_storage *sp, krb5_creds *creds) 1429178825Sdfr{ 1430178825Sdfr int ret; 1431178825Sdfr int32_t header = 0; 1432178825Sdfr 1433178825Sdfr if (creds->client) 1434178825Sdfr header |= SC_CLIENT_PRINCIPAL; 1435178825Sdfr if (creds->server) 1436178825Sdfr header |= SC_SERVER_PRINCIPAL; 1437178825Sdfr if (creds->session.keytype != ETYPE_NULL) 1438178825Sdfr header |= SC_SESSION_KEY; 1439178825Sdfr if (creds->ticket.data) 1440178825Sdfr header |= SC_TICKET; 1441178825Sdfr if (creds->second_ticket.length) 1442178825Sdfr header |= SC_SECOND_TICKET; 1443178825Sdfr if (creds->authdata.len) 1444178825Sdfr header |= SC_AUTHDATA; 1445178825Sdfr if (creds->addresses.len) 1446178825Sdfr header |= SC_ADDRESSES; 1447178825Sdfr 1448178825Sdfr ret = krb5_store_int32(sp, header); 1449233294Sstas if (ret) 1450233294Sstas return ret; 1451178825Sdfr 1452178825Sdfr if (creds->client) { 1453178825Sdfr ret = krb5_store_principal(sp, creds->client); 1454178825Sdfr if(ret) 1455178825Sdfr return ret; 1456178825Sdfr } 1457178825Sdfr 1458178825Sdfr if (creds->server) { 1459178825Sdfr ret = krb5_store_principal(sp, creds->server); 1460178825Sdfr if(ret) 1461178825Sdfr return ret; 1462178825Sdfr } 1463178825Sdfr 1464178825Sdfr if (creds->session.keytype != ETYPE_NULL) { 1465178825Sdfr ret = krb5_store_keyblock(sp, creds->session); 1466178825Sdfr if(ret) 1467178825Sdfr return ret; 1468178825Sdfr } 1469178825Sdfr 1470178825Sdfr ret = krb5_store_times(sp, creds->times); 1471178825Sdfr if(ret) 1472178825Sdfr return ret; 1473178825Sdfr ret = krb5_store_int8(sp, creds->second_ticket.length != 0); /* is_skey */ 1474178825Sdfr if(ret) 1475178825Sdfr return ret; 1476178825Sdfr 1477178825Sdfr ret = krb5_store_int32(sp, bitswap32(TicketFlags2int(creds->flags.b))); 1478178825Sdfr if(ret) 1479178825Sdfr return ret; 1480178825Sdfr 1481178825Sdfr if (creds->addresses.len) { 1482178825Sdfr ret = krb5_store_addrs(sp, creds->addresses); 1483178825Sdfr if(ret) 1484178825Sdfr return ret; 1485178825Sdfr } 1486178825Sdfr 1487178825Sdfr if (creds->authdata.len) { 1488178825Sdfr ret = krb5_store_authdata(sp, creds->authdata); 1489178825Sdfr if(ret) 1490178825Sdfr return ret; 1491178825Sdfr } 1492178825Sdfr 1493178825Sdfr if (creds->ticket.data) { 1494178825Sdfr ret = krb5_store_data(sp, creds->ticket); 1495178825Sdfr if(ret) 1496178825Sdfr return ret; 1497178825Sdfr } 1498178825Sdfr 1499178825Sdfr if (creds->second_ticket.data) { 1500178825Sdfr ret = krb5_store_data(sp, creds->second_ticket); 1501178825Sdfr if (ret) 1502178825Sdfr return ret; 1503178825Sdfr } 1504178825Sdfr 1505178825Sdfr return ret; 1506178825Sdfr} 1507178825Sdfr 1508233294Sstas/** 1509233294Sstas * Read a tagged credentials block from the storage. 1510233294Sstas * 1511233294Sstas * @param sp the storage buffer to write to 1512233294Sstas * @param creds the credentials block read from storage 1513233294Sstas * 1514233294Sstas * @return 0 on success, a Kerberos 5 error code on failure. 1515233294Sstas * 1516233294Sstas * @ingroup krb5_storage 1517233294Sstas */ 1518233294Sstas 1519233294SstasKRB5_LIB_FUNCTION krb5_error_code KRB5_LIB_CALL 1520178825Sdfrkrb5_ret_creds_tag(krb5_storage *sp, 1521178825Sdfr krb5_creds *creds) 1522178825Sdfr{ 1523178825Sdfr krb5_error_code ret; 1524178825Sdfr int8_t dummy8; 1525178825Sdfr int32_t dummy32, header; 1526178825Sdfr 1527178825Sdfr memset(creds, 0, sizeof(*creds)); 1528178825Sdfr 1529178825Sdfr ret = krb5_ret_int32 (sp, &header); 1530178825Sdfr if (ret) goto cleanup; 1531178825Sdfr 1532178825Sdfr if (header & SC_CLIENT_PRINCIPAL) { 1533178825Sdfr ret = krb5_ret_principal (sp, &creds->client); 1534178825Sdfr if(ret) goto cleanup; 1535178825Sdfr } 1536178825Sdfr if (header & SC_SERVER_PRINCIPAL) { 1537178825Sdfr ret = krb5_ret_principal (sp, &creds->server); 1538178825Sdfr if(ret) goto cleanup; 1539178825Sdfr } 1540178825Sdfr if (header & SC_SESSION_KEY) { 1541178825Sdfr ret = krb5_ret_keyblock (sp, &creds->session); 1542178825Sdfr if(ret) goto cleanup; 1543178825Sdfr } 1544178825Sdfr ret = krb5_ret_times (sp, &creds->times); 1545178825Sdfr if(ret) goto cleanup; 1546178825Sdfr ret = krb5_ret_int8 (sp, &dummy8); 1547178825Sdfr if(ret) goto cleanup; 1548178825Sdfr ret = krb5_ret_int32 (sp, &dummy32); 1549178825Sdfr if(ret) goto cleanup; 1550178825Sdfr /* 1551178825Sdfr * Runtime detect the what is the higher bits of the bitfield. If 1552178825Sdfr * any of the higher bits are set in the input data, it's either a 1553178825Sdfr * new ticket flag (and this code need to be removed), or it's a 1554178825Sdfr * MIT cache (or new Heimdal cache), lets change it to our current 1555178825Sdfr * format. 1556178825Sdfr */ 1557178825Sdfr { 1558178825Sdfr uint32_t mask = 0xffff0000; 1559178825Sdfr creds->flags.i = 0; 1560178825Sdfr creds->flags.b.anonymous = 1; 1561178825Sdfr if (creds->flags.i & mask) 1562178825Sdfr mask = ~mask; 1563178825Sdfr if (dummy32 & mask) 1564178825Sdfr dummy32 = bitswap32(dummy32); 1565178825Sdfr } 1566178825Sdfr creds->flags.i = dummy32; 1567178825Sdfr if (header & SC_ADDRESSES) { 1568178825Sdfr ret = krb5_ret_addrs (sp, &creds->addresses); 1569178825Sdfr if(ret) goto cleanup; 1570178825Sdfr } 1571178825Sdfr if (header & SC_AUTHDATA) { 1572178825Sdfr ret = krb5_ret_authdata (sp, &creds->authdata); 1573178825Sdfr if(ret) goto cleanup; 1574178825Sdfr } 1575178825Sdfr if (header & SC_TICKET) { 1576178825Sdfr ret = krb5_ret_data (sp, &creds->ticket); 1577178825Sdfr if(ret) goto cleanup; 1578178825Sdfr } 1579178825Sdfr if (header & SC_SECOND_TICKET) { 1580178825Sdfr ret = krb5_ret_data (sp, &creds->second_ticket); 1581178825Sdfr if(ret) goto cleanup; 1582178825Sdfr } 1583178825Sdfr 1584178825Sdfrcleanup: 1585178825Sdfr if(ret) { 1586233294Sstas#if 0 1587178825Sdfr krb5_free_cred_contents(context, creds); /* XXX */ 1588178825Sdfr#endif 1589178825Sdfr } 1590178825Sdfr return ret; 1591178825Sdfr} 1592