155682Smarkm/* 2178825Sdfr * Copyright (c) 1997-2006 Kungliga Tekniska H�gskolan 355682Smarkm * (Royal Institute of Technology, Stockholm, Sweden). 455682Smarkm * All rights reserved. 555682Smarkm * 655682Smarkm * Redistribution and use in source and binary forms, with or without 755682Smarkm * modification, are permitted provided that the following conditions 855682Smarkm * are met: 955682Smarkm * 1055682Smarkm * 1. Redistributions of source code must retain the above copyright 1155682Smarkm * notice, this list of conditions and the following disclaimer. 1255682Smarkm * 1355682Smarkm * 2. Redistributions in binary form must reproduce the above copyright 1455682Smarkm * notice, this list of conditions and the following disclaimer in the 1555682Smarkm * documentation and/or other materials provided with the distribution. 1655682Smarkm * 1755682Smarkm * 3. Neither the name of the Institute nor the names of its contributors 1855682Smarkm * may be used to endorse or promote products derived from this software 1955682Smarkm * without specific prior written permission. 2055682Smarkm * 2155682Smarkm * THIS SOFTWARE IS PROVIDED BY THE INSTITUTE AND CONTRIBUTORS ``AS IS'' AND 2255682Smarkm * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 2355682Smarkm * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE 2455682Smarkm * ARE DISCLAIMED. IN NO EVENT SHALL THE INSTITUTE OR CONTRIBUTORS BE LIABLE 2555682Smarkm * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL 2655682Smarkm * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS 2755682Smarkm * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) 2855682Smarkm * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT 2955682Smarkm * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY 3055682Smarkm * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF 3155682Smarkm * SUCH DAMAGE. 3255682Smarkm */ 3355682Smarkm 3455682Smarkm#include "krb5_locl.h" 35102644Snectar#include "store-int.h" 3655682Smarkm 37178825SdfrRCSID("$Id: store.c 22071 2007-11-14 20:04:50Z lha $"); 3855682Smarkm 3978527Sassar#define BYTEORDER_IS(SP, V) (((SP)->flags & KRB5_STORAGE_BYTEORDER_MASK) == (V)) 4078527Sassar#define BYTEORDER_IS_LE(SP) BYTEORDER_IS((SP), KRB5_STORAGE_BYTEORDER_LE) 4178527Sassar#define BYTEORDER_IS_BE(SP) BYTEORDER_IS((SP), KRB5_STORAGE_BYTEORDER_BE) 4278527Sassar#define BYTEORDER_IS_HOST(SP) (BYTEORDER_IS((SP), KRB5_STORAGE_BYTEORDER_HOST) || \ 4378527Sassar krb5_storage_is_flags((SP), KRB5_STORAGE_HOST_BYTEORDER)) 4478527Sassar 45178825Sdfrvoid KRB5_LIB_FUNCTION 4655682Smarkmkrb5_storage_set_flags(krb5_storage *sp, krb5_flags flags) 4755682Smarkm{ 4855682Smarkm sp->flags |= flags; 4955682Smarkm} 5055682Smarkm 51178825Sdfrvoid KRB5_LIB_FUNCTION 5255682Smarkmkrb5_storage_clear_flags(krb5_storage *sp, krb5_flags flags) 5355682Smarkm{ 5455682Smarkm sp->flags &= ~flags; 5555682Smarkm} 5655682Smarkm 57178825Sdfrkrb5_boolean KRB5_LIB_FUNCTION 5855682Smarkmkrb5_storage_is_flags(krb5_storage *sp, krb5_flags flags) 5955682Smarkm{ 6055682Smarkm return (sp->flags & flags) == flags; 6155682Smarkm} 6255682Smarkm 63178825Sdfrvoid KRB5_LIB_FUNCTION 6478527Sassarkrb5_storage_set_byteorder(krb5_storage *sp, krb5_flags byteorder) 6578527Sassar{ 6678527Sassar sp->flags &= ~KRB5_STORAGE_BYTEORDER_MASK; 6778527Sassar sp->flags |= byteorder; 6878527Sassar} 6978527Sassar 70178825Sdfrkrb5_flags KRB5_LIB_FUNCTION 7178527Sassarkrb5_storage_get_byteorder(krb5_storage *sp, krb5_flags byteorder) 7278527Sassar{ 7378527Sassar return sp->flags & KRB5_STORAGE_BYTEORDER_MASK; 7478527Sassar} 7578527Sassar 76178825Sdfroff_t KRB5_LIB_FUNCTION 77102644Snectarkrb5_storage_seek(krb5_storage *sp, off_t offset, int whence) 78102644Snectar{ 79102644Snectar return (*sp->seek)(sp, offset, whence); 80102644Snectar} 8178527Sassar 82178825Sdfrkrb5_ssize_t KRB5_LIB_FUNCTION 83102644Snectarkrb5_storage_read(krb5_storage *sp, void *buf, size_t len) 84102644Snectar{ 85102644Snectar return sp->fetch(sp, buf, len); 86102644Snectar} 87102644Snectar 88178825Sdfrkrb5_ssize_t KRB5_LIB_FUNCTION 89102644Snectarkrb5_storage_write(krb5_storage *sp, const void *buf, size_t len) 90102644Snectar{ 91102644Snectar return sp->store(sp, buf, len); 92102644Snectar} 93102644Snectar 94178825Sdfrvoid KRB5_LIB_FUNCTION 95102644Snectarkrb5_storage_set_eof_code(krb5_storage *sp, int code) 96102644Snectar{ 97102644Snectar sp->eof_code = code; 98102644Snectar} 99102644Snectar 100178825Sdfrkrb5_ssize_t KRB5_LIB_FUNCTION 10155682Smarkm_krb5_put_int(void *buffer, unsigned long value, size_t size) 10255682Smarkm{ 10355682Smarkm unsigned char *p = buffer; 10455682Smarkm int i; 10555682Smarkm for (i = size - 1; i >= 0; i--) { 10655682Smarkm p[i] = value & 0xff; 10755682Smarkm value >>= 8; 10855682Smarkm } 10955682Smarkm return size; 11055682Smarkm} 11155682Smarkm 112178825Sdfrkrb5_ssize_t KRB5_LIB_FUNCTION 11355682Smarkm_krb5_get_int(void *buffer, unsigned long *value, size_t size) 11455682Smarkm{ 11555682Smarkm unsigned char *p = buffer; 11655682Smarkm unsigned long v = 0; 11755682Smarkm int i; 11855682Smarkm for (i = 0; i < size; i++) 11955682Smarkm v = (v << 8) + p[i]; 12055682Smarkm *value = v; 12155682Smarkm return size; 12255682Smarkm} 12355682Smarkm 124178825Sdfrkrb5_error_code KRB5_LIB_FUNCTION 12555682Smarkmkrb5_storage_free(krb5_storage *sp) 12655682Smarkm{ 12755682Smarkm if(sp->free) 12855682Smarkm (*sp->free)(sp); 12955682Smarkm free(sp->data); 13055682Smarkm free(sp); 13155682Smarkm return 0; 13255682Smarkm} 13355682Smarkm 134178825Sdfrkrb5_error_code KRB5_LIB_FUNCTION 13555682Smarkmkrb5_storage_to_data(krb5_storage *sp, krb5_data *data) 13655682Smarkm{ 13755682Smarkm off_t pos; 13855682Smarkm size_t size; 13955682Smarkm krb5_error_code ret; 14055682Smarkm 14155682Smarkm pos = sp->seek(sp, 0, SEEK_CUR); 14255682Smarkm size = (size_t)sp->seek(sp, 0, SEEK_END); 14355682Smarkm ret = krb5_data_alloc (data, size); 14455682Smarkm if (ret) { 14555682Smarkm sp->seek(sp, pos, SEEK_SET); 14655682Smarkm return ret; 14755682Smarkm } 14855682Smarkm if (size) { 14955682Smarkm sp->seek(sp, 0, SEEK_SET); 15055682Smarkm sp->fetch(sp, data->data, data->length); 15155682Smarkm sp->seek(sp, pos, SEEK_SET); 15255682Smarkm } 15355682Smarkm return 0; 15455682Smarkm} 15555682Smarkm 15655682Smarkmstatic krb5_error_code 15755682Smarkmkrb5_store_int(krb5_storage *sp, 15855682Smarkm int32_t value, 15955682Smarkm size_t len) 16055682Smarkm{ 16155682Smarkm int ret; 16278527Sassar unsigned char v[16]; 16355682Smarkm 16478527Sassar if(len > sizeof(v)) 16578527Sassar return EINVAL; 16655682Smarkm _krb5_put_int(v, value, len); 16755682Smarkm ret = sp->store(sp, v, len); 16855682Smarkm if (ret != len) 169102644Snectar return (ret<0)?errno:sp->eof_code; 17055682Smarkm return 0; 17155682Smarkm} 17255682Smarkm 173178825Sdfrkrb5_error_code KRB5_LIB_FUNCTION 17455682Smarkmkrb5_store_int32(krb5_storage *sp, 17555682Smarkm int32_t value) 17655682Smarkm{ 17778527Sassar if(BYTEORDER_IS_HOST(sp)) 17855682Smarkm value = htonl(value); 17978527Sassar else if(BYTEORDER_IS_LE(sp)) 18078527Sassar value = bswap32(value); 18155682Smarkm return krb5_store_int(sp, value, 4); 18255682Smarkm} 18355682Smarkm 184178825Sdfrkrb5_error_code KRB5_LIB_FUNCTION 185178825Sdfrkrb5_store_uint32(krb5_storage *sp, 186178825Sdfr uint32_t value) 187178825Sdfr{ 188178825Sdfr return krb5_store_int32(sp, (int32_t)value); 189178825Sdfr} 190178825Sdfr 19155682Smarkmstatic krb5_error_code 19255682Smarkmkrb5_ret_int(krb5_storage *sp, 19355682Smarkm int32_t *value, 19455682Smarkm size_t len) 19555682Smarkm{ 19655682Smarkm int ret; 19755682Smarkm unsigned char v[4]; 19855682Smarkm unsigned long w; 19955682Smarkm ret = sp->fetch(sp, v, len); 20055682Smarkm if(ret != len) 201102644Snectar return (ret<0)?errno:sp->eof_code; 20255682Smarkm _krb5_get_int(v, &w, len); 20355682Smarkm *value = w; 20455682Smarkm return 0; 20555682Smarkm} 20655682Smarkm 207178825Sdfrkrb5_error_code KRB5_LIB_FUNCTION 20855682Smarkmkrb5_ret_int32(krb5_storage *sp, 20955682Smarkm int32_t *value) 21055682Smarkm{ 21155682Smarkm krb5_error_code ret = krb5_ret_int(sp, value, 4); 21255682Smarkm if(ret) 21355682Smarkm return ret; 21478527Sassar if(BYTEORDER_IS_HOST(sp)) 21578527Sassar *value = htonl(*value); 21678527Sassar else if(BYTEORDER_IS_LE(sp)) 21778527Sassar *value = bswap32(*value); 21855682Smarkm return 0; 21955682Smarkm} 22055682Smarkm 221178825Sdfrkrb5_error_code KRB5_LIB_FUNCTION 222178825Sdfrkrb5_ret_uint32(krb5_storage *sp, 223178825Sdfr uint32_t *value) 224178825Sdfr{ 225178825Sdfr krb5_error_code ret; 226178825Sdfr int32_t v; 227178825Sdfr 228178825Sdfr ret = krb5_ret_int32(sp, &v); 229178825Sdfr if (ret == 0) 230178825Sdfr *value = (uint32_t)v; 231178825Sdfr 232178825Sdfr return ret; 233178825Sdfr} 234178825Sdfr 235178825Sdfrkrb5_error_code KRB5_LIB_FUNCTION 23655682Smarkmkrb5_store_int16(krb5_storage *sp, 23755682Smarkm int16_t value) 23855682Smarkm{ 23978527Sassar if(BYTEORDER_IS_HOST(sp)) 24055682Smarkm value = htons(value); 24178527Sassar else if(BYTEORDER_IS_LE(sp)) 24278527Sassar value = bswap16(value); 24355682Smarkm return krb5_store_int(sp, value, 2); 24455682Smarkm} 24555682Smarkm 246178825Sdfrkrb5_error_code KRB5_LIB_FUNCTION 247178825Sdfrkrb5_store_uint16(krb5_storage *sp, 248178825Sdfr uint16_t value) 249178825Sdfr{ 250178825Sdfr return krb5_store_int16(sp, (int16_t)value); 251178825Sdfr} 252178825Sdfr 253178825Sdfrkrb5_error_code KRB5_LIB_FUNCTION 25455682Smarkmkrb5_ret_int16(krb5_storage *sp, 25555682Smarkm int16_t *value) 25655682Smarkm{ 25755682Smarkm int32_t v; 25855682Smarkm int ret; 25955682Smarkm ret = krb5_ret_int(sp, &v, 2); 26055682Smarkm if(ret) 26155682Smarkm return ret; 26255682Smarkm *value = v; 26378527Sassar if(BYTEORDER_IS_HOST(sp)) 26478527Sassar *value = htons(*value); 26578527Sassar else if(BYTEORDER_IS_LE(sp)) 26678527Sassar *value = bswap16(*value); 26755682Smarkm return 0; 26855682Smarkm} 26955682Smarkm 270178825Sdfrkrb5_error_code KRB5_LIB_FUNCTION 271178825Sdfrkrb5_ret_uint16(krb5_storage *sp, 272178825Sdfr uint16_t *value) 273178825Sdfr{ 274178825Sdfr krb5_error_code ret; 275178825Sdfr int16_t v; 276178825Sdfr 277178825Sdfr ret = krb5_ret_int16(sp, &v); 278178825Sdfr if (ret == 0) 279178825Sdfr *value = (uint16_t)v; 280178825Sdfr 281178825Sdfr return ret; 282178825Sdfr} 283178825Sdfr 284178825Sdfrkrb5_error_code KRB5_LIB_FUNCTION 28555682Smarkmkrb5_store_int8(krb5_storage *sp, 28655682Smarkm int8_t value) 28755682Smarkm{ 28855682Smarkm int ret; 28955682Smarkm 29055682Smarkm ret = sp->store(sp, &value, sizeof(value)); 29155682Smarkm if (ret != sizeof(value)) 292102644Snectar return (ret<0)?errno:sp->eof_code; 29355682Smarkm return 0; 29455682Smarkm} 29555682Smarkm 296178825Sdfrkrb5_error_code KRB5_LIB_FUNCTION 297178825Sdfrkrb5_store_uint8(krb5_storage *sp, 298178825Sdfr uint8_t value) 299178825Sdfr{ 300178825Sdfr return krb5_store_int8(sp, (int8_t)value); 301178825Sdfr} 302178825Sdfr 303178825Sdfrkrb5_error_code KRB5_LIB_FUNCTION 30455682Smarkmkrb5_ret_int8(krb5_storage *sp, 30555682Smarkm int8_t *value) 30655682Smarkm{ 30755682Smarkm int ret; 30855682Smarkm 30955682Smarkm ret = sp->fetch(sp, value, sizeof(*value)); 31055682Smarkm if (ret != sizeof(*value)) 311102644Snectar return (ret<0)?errno:sp->eof_code; 31255682Smarkm return 0; 31355682Smarkm} 31455682Smarkm 315178825Sdfrkrb5_error_code KRB5_LIB_FUNCTION 316178825Sdfrkrb5_ret_uint8(krb5_storage *sp, 317178825Sdfr uint8_t *value) 318178825Sdfr{ 319178825Sdfr krb5_error_code ret; 320178825Sdfr int8_t v; 321178825Sdfr 322178825Sdfr ret = krb5_ret_int8(sp, &v); 323178825Sdfr if (ret == 0) 324178825Sdfr *value = (uint8_t)v; 325178825Sdfr 326178825Sdfr return ret; 327178825Sdfr} 328178825Sdfr 329178825Sdfrkrb5_error_code KRB5_LIB_FUNCTION 33055682Smarkmkrb5_store_data(krb5_storage *sp, 33155682Smarkm krb5_data data) 33255682Smarkm{ 33355682Smarkm int ret; 33455682Smarkm ret = krb5_store_int32(sp, data.length); 33555682Smarkm if(ret < 0) 33655682Smarkm return ret; 33755682Smarkm ret = sp->store(sp, data.data, data.length); 33855682Smarkm if(ret != data.length){ 33955682Smarkm if(ret < 0) 34055682Smarkm return errno; 341102644Snectar return sp->eof_code; 34255682Smarkm } 34355682Smarkm return 0; 34455682Smarkm} 34555682Smarkm 346178825Sdfrkrb5_error_code KRB5_LIB_FUNCTION 34755682Smarkmkrb5_ret_data(krb5_storage *sp, 34855682Smarkm krb5_data *data) 34955682Smarkm{ 35055682Smarkm int ret; 35155682Smarkm int32_t size; 35255682Smarkm 35355682Smarkm ret = krb5_ret_int32(sp, &size); 35455682Smarkm if(ret) 35555682Smarkm return ret; 35655682Smarkm ret = krb5_data_alloc (data, size); 35755682Smarkm if (ret) 35855682Smarkm return ret; 35955682Smarkm if (size) { 36055682Smarkm ret = sp->fetch(sp, data->data, size); 36155682Smarkm if(ret != size) 362102644Snectar return (ret < 0)? errno : sp->eof_code; 36355682Smarkm } 36455682Smarkm return 0; 36555682Smarkm} 36655682Smarkm 367178825Sdfrkrb5_error_code KRB5_LIB_FUNCTION 36855682Smarkmkrb5_store_string(krb5_storage *sp, const char *s) 36955682Smarkm{ 37055682Smarkm krb5_data data; 37155682Smarkm data.length = strlen(s); 372178825Sdfr data.data = rk_UNCONST(s); 37355682Smarkm return krb5_store_data(sp, data); 37455682Smarkm} 37555682Smarkm 376178825Sdfrkrb5_error_code KRB5_LIB_FUNCTION 37755682Smarkmkrb5_ret_string(krb5_storage *sp, 37855682Smarkm char **string) 37955682Smarkm{ 38055682Smarkm int ret; 38155682Smarkm krb5_data data; 38255682Smarkm ret = krb5_ret_data(sp, &data); 38355682Smarkm if(ret) 38455682Smarkm return ret; 38555682Smarkm *string = realloc(data.data, data.length + 1); 38655682Smarkm if(*string == NULL){ 38755682Smarkm free(data.data); 38855682Smarkm return ENOMEM; 38955682Smarkm } 39055682Smarkm (*string)[data.length] = 0; 39155682Smarkm return 0; 39255682Smarkm} 39355682Smarkm 394178825Sdfrkrb5_error_code KRB5_LIB_FUNCTION 39572445Sassarkrb5_store_stringz(krb5_storage *sp, const char *s) 39655682Smarkm{ 39755682Smarkm size_t len = strlen(s) + 1; 39855682Smarkm ssize_t ret; 39955682Smarkm 40055682Smarkm ret = sp->store(sp, s, len); 40155682Smarkm if(ret != len) { 40255682Smarkm if(ret < 0) 40355682Smarkm return ret; 40455682Smarkm else 405102644Snectar return sp->eof_code; 40655682Smarkm } 40755682Smarkm return 0; 40855682Smarkm} 40955682Smarkm 410178825Sdfrkrb5_error_code KRB5_LIB_FUNCTION 41155682Smarkmkrb5_ret_stringz(krb5_storage *sp, 41255682Smarkm char **string) 41355682Smarkm{ 41455682Smarkm char c; 41555682Smarkm char *s = NULL; 41655682Smarkm size_t len = 0; 41755682Smarkm ssize_t ret; 41855682Smarkm 41955682Smarkm while((ret = sp->fetch(sp, &c, 1)) == 1){ 42055682Smarkm char *tmp; 42155682Smarkm 42255682Smarkm len++; 42355682Smarkm tmp = realloc (s, len); 42455682Smarkm if (tmp == NULL) { 42555682Smarkm free (s); 42655682Smarkm return ENOMEM; 42755682Smarkm } 42855682Smarkm s = tmp; 42955682Smarkm s[len - 1] = c; 43055682Smarkm if(c == 0) 43155682Smarkm break; 43255682Smarkm } 43355682Smarkm if(ret != 1){ 43455682Smarkm free(s); 43555682Smarkm if(ret == 0) 436102644Snectar return sp->eof_code; 43755682Smarkm return ret; 43855682Smarkm } 43955682Smarkm *string = s; 44055682Smarkm return 0; 44155682Smarkm} 44255682Smarkm 443178825Sdfrkrb5_error_code KRB5_LIB_FUNCTION 444178825Sdfrkrb5_store_stringnl(krb5_storage *sp, const char *s) 445178825Sdfr{ 446178825Sdfr size_t len = strlen(s); 447178825Sdfr ssize_t ret; 44855682Smarkm 449178825Sdfr ret = sp->store(sp, s, len); 450178825Sdfr if(ret != len) { 451178825Sdfr if(ret < 0) 452178825Sdfr return ret; 453178825Sdfr else 454178825Sdfr return sp->eof_code; 455178825Sdfr } 456178825Sdfr ret = sp->store(sp, "\n", 1); 457178825Sdfr if(ret != 1) { 458178825Sdfr if(ret < 0) 459178825Sdfr return ret; 460178825Sdfr else 461178825Sdfr return sp->eof_code; 462178825Sdfr } 463178825Sdfr 464178825Sdfr return 0; 465178825Sdfr 466178825Sdfr} 467178825Sdfr 468178825Sdfrkrb5_error_code KRB5_LIB_FUNCTION 469178825Sdfrkrb5_ret_stringnl(krb5_storage *sp, 470178825Sdfr char **string) 471178825Sdfr{ 472178825Sdfr int expect_nl = 0; 473178825Sdfr char c; 474178825Sdfr char *s = NULL; 475178825Sdfr size_t len = 0; 476178825Sdfr ssize_t ret; 477178825Sdfr 478178825Sdfr while((ret = sp->fetch(sp, &c, 1)) == 1){ 479178825Sdfr char *tmp; 480178825Sdfr 481178825Sdfr if (c == '\r') { 482178825Sdfr expect_nl = 1; 483178825Sdfr continue; 484178825Sdfr } 485178825Sdfr if (expect_nl && c != '\n') { 486178825Sdfr free(s); 487178825Sdfr return KRB5_BADMSGTYPE; 488178825Sdfr } 489178825Sdfr 490178825Sdfr len++; 491178825Sdfr tmp = realloc (s, len); 492178825Sdfr if (tmp == NULL) { 493178825Sdfr free (s); 494178825Sdfr return ENOMEM; 495178825Sdfr } 496178825Sdfr s = tmp; 497178825Sdfr if(c == '\n') { 498178825Sdfr s[len - 1] = '\0'; 499178825Sdfr break; 500178825Sdfr } 501178825Sdfr s[len - 1] = c; 502178825Sdfr } 503178825Sdfr if(ret != 1){ 504178825Sdfr free(s); 505178825Sdfr if(ret == 0) 506178825Sdfr return sp->eof_code; 507178825Sdfr return ret; 508178825Sdfr } 509178825Sdfr *string = s; 510178825Sdfr return 0; 511178825Sdfr} 512178825Sdfr 513178825Sdfr 514178825Sdfrkrb5_error_code KRB5_LIB_FUNCTION 51555682Smarkmkrb5_store_principal(krb5_storage *sp, 516178825Sdfr krb5_const_principal p) 51755682Smarkm{ 51855682Smarkm int i; 51955682Smarkm int ret; 52055682Smarkm 52155682Smarkm if(!krb5_storage_is_flags(sp, KRB5_STORAGE_PRINCIPAL_NO_NAME_TYPE)) { 522178825Sdfr ret = krb5_store_int32(sp, p->name.name_type); 523178825Sdfr if(ret) return ret; 52455682Smarkm } 52555682Smarkm if(krb5_storage_is_flags(sp, KRB5_STORAGE_PRINCIPAL_WRONG_NUM_COMPONENTS)) 52655682Smarkm ret = krb5_store_int32(sp, p->name.name_string.len + 1); 52755682Smarkm else 528178825Sdfr ret = krb5_store_int32(sp, p->name.name_string.len); 52955682Smarkm 53055682Smarkm if(ret) return ret; 53155682Smarkm ret = krb5_store_string(sp, p->realm); 53255682Smarkm if(ret) return ret; 53355682Smarkm for(i = 0; i < p->name.name_string.len; i++){ 53455682Smarkm ret = krb5_store_string(sp, p->name.name_string.val[i]); 53555682Smarkm if(ret) return ret; 53655682Smarkm } 53755682Smarkm return 0; 53855682Smarkm} 53955682Smarkm 540178825Sdfrkrb5_error_code KRB5_LIB_FUNCTION 54155682Smarkmkrb5_ret_principal(krb5_storage *sp, 54255682Smarkm krb5_principal *princ) 54355682Smarkm{ 54455682Smarkm int i; 54555682Smarkm int ret; 54655682Smarkm krb5_principal p; 54755682Smarkm int32_t type; 54855682Smarkm int32_t ncomp; 54955682Smarkm 55055682Smarkm p = calloc(1, sizeof(*p)); 55155682Smarkm if(p == NULL) 55255682Smarkm return ENOMEM; 55355682Smarkm 55455682Smarkm if(krb5_storage_is_flags(sp, KRB5_STORAGE_PRINCIPAL_NO_NAME_TYPE)) 55555682Smarkm type = KRB5_NT_UNKNOWN; 556178825Sdfr else if((ret = krb5_ret_int32(sp, &type))){ 55755682Smarkm free(p); 55855682Smarkm return ret; 55955682Smarkm } 56055682Smarkm if((ret = krb5_ret_int32(sp, &ncomp))){ 56155682Smarkm free(p); 56255682Smarkm return ret; 56355682Smarkm } 56455682Smarkm if(krb5_storage_is_flags(sp, KRB5_STORAGE_PRINCIPAL_WRONG_NUM_COMPONENTS)) 56555682Smarkm ncomp--; 566178825Sdfr if (ncomp < 0) { 567178825Sdfr free(p); 568178825Sdfr return EINVAL; 569178825Sdfr } 57055682Smarkm p->name.name_type = type; 57155682Smarkm p->name.name_string.len = ncomp; 57255682Smarkm ret = krb5_ret_string(sp, &p->realm); 573178825Sdfr if(ret) { 574178825Sdfr free(p); 575178825Sdfr return ret; 576178825Sdfr } 57755682Smarkm p->name.name_string.val = calloc(ncomp, sizeof(*p->name.name_string.val)); 578178825Sdfr if(p->name.name_string.val == NULL && ncomp != 0){ 57955682Smarkm free(p->realm); 580178825Sdfr free(p); 58155682Smarkm return ENOMEM; 58255682Smarkm } 58355682Smarkm for(i = 0; i < ncomp; i++){ 58455682Smarkm ret = krb5_ret_string(sp, &p->name.name_string.val[i]); 585178825Sdfr if(ret) { 586178825Sdfr while (i >= 0) 587178825Sdfr free(p->name.name_string.val[i--]); 588178825Sdfr free(p->realm); 589178825Sdfr free(p); 590178825Sdfr return ret; 591178825Sdfr } 59255682Smarkm } 59355682Smarkm *princ = p; 59455682Smarkm return 0; 59555682Smarkm} 59655682Smarkm 597178825Sdfrkrb5_error_code KRB5_LIB_FUNCTION 59855682Smarkmkrb5_store_keyblock(krb5_storage *sp, krb5_keyblock p) 59955682Smarkm{ 60055682Smarkm int ret; 60155682Smarkm ret = krb5_store_int16(sp, p.keytype); 60255682Smarkm if(ret) return ret; 60355682Smarkm 60455682Smarkm if(krb5_storage_is_flags(sp, KRB5_STORAGE_KEYBLOCK_KEYTYPE_TWICE)){ 60555682Smarkm /* this should really be enctype, but it is the same as 60655682Smarkm keytype nowadays */ 60755682Smarkm ret = krb5_store_int16(sp, p.keytype); 60855682Smarkm if(ret) return ret; 60955682Smarkm } 61055682Smarkm 61155682Smarkm ret = krb5_store_data(sp, p.keyvalue); 61255682Smarkm return ret; 61355682Smarkm} 61455682Smarkm 615178825Sdfrkrb5_error_code KRB5_LIB_FUNCTION 61655682Smarkmkrb5_ret_keyblock(krb5_storage *sp, krb5_keyblock *p) 61755682Smarkm{ 61855682Smarkm int ret; 61955682Smarkm int16_t tmp; 62055682Smarkm 62155682Smarkm ret = krb5_ret_int16(sp, &tmp); 62255682Smarkm if(ret) return ret; 62355682Smarkm p->keytype = tmp; 62455682Smarkm 62555682Smarkm if(krb5_storage_is_flags(sp, KRB5_STORAGE_KEYBLOCK_KEYTYPE_TWICE)){ 62655682Smarkm ret = krb5_ret_int16(sp, &tmp); 62755682Smarkm if(ret) return ret; 62855682Smarkm } 62955682Smarkm 63055682Smarkm ret = krb5_ret_data(sp, &p->keyvalue); 63155682Smarkm return ret; 63255682Smarkm} 63355682Smarkm 634178825Sdfrkrb5_error_code KRB5_LIB_FUNCTION 63555682Smarkmkrb5_store_times(krb5_storage *sp, krb5_times times) 63655682Smarkm{ 63755682Smarkm int ret; 63855682Smarkm ret = krb5_store_int32(sp, times.authtime); 63955682Smarkm if(ret) return ret; 64055682Smarkm ret = krb5_store_int32(sp, times.starttime); 64155682Smarkm if(ret) return ret; 64255682Smarkm ret = krb5_store_int32(sp, times.endtime); 64355682Smarkm if(ret) return ret; 64455682Smarkm ret = krb5_store_int32(sp, times.renew_till); 64555682Smarkm return ret; 64655682Smarkm} 64755682Smarkm 648178825Sdfrkrb5_error_code KRB5_LIB_FUNCTION 64955682Smarkmkrb5_ret_times(krb5_storage *sp, krb5_times *times) 65055682Smarkm{ 65155682Smarkm int ret; 65255682Smarkm int32_t tmp; 65355682Smarkm ret = krb5_ret_int32(sp, &tmp); 65455682Smarkm times->authtime = tmp; 65555682Smarkm if(ret) return ret; 65655682Smarkm ret = krb5_ret_int32(sp, &tmp); 65755682Smarkm times->starttime = tmp; 65855682Smarkm if(ret) return ret; 65955682Smarkm ret = krb5_ret_int32(sp, &tmp); 66055682Smarkm times->endtime = tmp; 66155682Smarkm if(ret) return ret; 66255682Smarkm ret = krb5_ret_int32(sp, &tmp); 66355682Smarkm times->renew_till = tmp; 66455682Smarkm return ret; 66555682Smarkm} 66655682Smarkm 667178825Sdfrkrb5_error_code KRB5_LIB_FUNCTION 66855682Smarkmkrb5_store_address(krb5_storage *sp, krb5_address p) 66955682Smarkm{ 67055682Smarkm int ret; 67155682Smarkm ret = krb5_store_int16(sp, p.addr_type); 67255682Smarkm if(ret) return ret; 67355682Smarkm ret = krb5_store_data(sp, p.address); 67455682Smarkm return ret; 67555682Smarkm} 67655682Smarkm 677178825Sdfrkrb5_error_code KRB5_LIB_FUNCTION 67855682Smarkmkrb5_ret_address(krb5_storage *sp, krb5_address *adr) 67955682Smarkm{ 68055682Smarkm int16_t t; 68155682Smarkm int ret; 68255682Smarkm ret = krb5_ret_int16(sp, &t); 68355682Smarkm if(ret) return ret; 68455682Smarkm adr->addr_type = t; 68555682Smarkm ret = krb5_ret_data(sp, &adr->address); 68655682Smarkm return ret; 68755682Smarkm} 68855682Smarkm 689178825Sdfrkrb5_error_code KRB5_LIB_FUNCTION 69055682Smarkmkrb5_store_addrs(krb5_storage *sp, krb5_addresses p) 69155682Smarkm{ 69255682Smarkm int i; 69355682Smarkm int ret; 69455682Smarkm ret = krb5_store_int32(sp, p.len); 69555682Smarkm if(ret) return ret; 69655682Smarkm for(i = 0; i<p.len; i++){ 69755682Smarkm ret = krb5_store_address(sp, p.val[i]); 69855682Smarkm if(ret) break; 69955682Smarkm } 70055682Smarkm return ret; 70155682Smarkm} 70255682Smarkm 703178825Sdfrkrb5_error_code KRB5_LIB_FUNCTION 70455682Smarkmkrb5_ret_addrs(krb5_storage *sp, krb5_addresses *adr) 70555682Smarkm{ 70655682Smarkm int i; 70755682Smarkm int ret; 70855682Smarkm int32_t tmp; 70955682Smarkm 71055682Smarkm ret = krb5_ret_int32(sp, &tmp); 71155682Smarkm if(ret) return ret; 71255682Smarkm adr->len = tmp; 71355682Smarkm ALLOC(adr->val, adr->len); 714178825Sdfr if (adr->val == NULL && adr->len != 0) 715178825Sdfr return ENOMEM; 71655682Smarkm for(i = 0; i < adr->len; i++){ 71755682Smarkm ret = krb5_ret_address(sp, &adr->val[i]); 71855682Smarkm if(ret) break; 71955682Smarkm } 72055682Smarkm return ret; 72155682Smarkm} 72255682Smarkm 723178825Sdfrkrb5_error_code KRB5_LIB_FUNCTION 72455682Smarkmkrb5_store_authdata(krb5_storage *sp, krb5_authdata auth) 72555682Smarkm{ 72655682Smarkm krb5_error_code ret; 72755682Smarkm int i; 72855682Smarkm ret = krb5_store_int32(sp, auth.len); 72955682Smarkm if(ret) return ret; 73055682Smarkm for(i = 0; i < auth.len; i++){ 73155682Smarkm ret = krb5_store_int16(sp, auth.val[i].ad_type); 73255682Smarkm if(ret) break; 73355682Smarkm ret = krb5_store_data(sp, auth.val[i].ad_data); 73455682Smarkm if(ret) break; 73555682Smarkm } 73655682Smarkm return 0; 73755682Smarkm} 73855682Smarkm 739178825Sdfrkrb5_error_code KRB5_LIB_FUNCTION 74055682Smarkmkrb5_ret_authdata(krb5_storage *sp, krb5_authdata *auth) 74155682Smarkm{ 74255682Smarkm krb5_error_code ret; 74355682Smarkm int32_t tmp; 74455682Smarkm int16_t tmp2; 74555682Smarkm int i; 74655682Smarkm ret = krb5_ret_int32(sp, &tmp); 74755682Smarkm if(ret) return ret; 74855682Smarkm ALLOC_SEQ(auth, tmp); 749178825Sdfr if (auth->val == NULL && tmp != 0) 750178825Sdfr return ENOMEM; 75155682Smarkm for(i = 0; i < tmp; i++){ 75255682Smarkm ret = krb5_ret_int16(sp, &tmp2); 75355682Smarkm if(ret) break; 75455682Smarkm auth->val[i].ad_type = tmp2; 75555682Smarkm ret = krb5_ret_data(sp, &auth->val[i].ad_data); 75655682Smarkm if(ret) break; 75755682Smarkm } 75855682Smarkm return ret; 75955682Smarkm} 76055682Smarkm 761127808Snectarstatic int32_t 762127808Snectarbitswap32(int32_t b) 763127808Snectar{ 764127808Snectar int32_t r = 0; 765127808Snectar int i; 766127808Snectar for (i = 0; i < 32; i++) { 767127808Snectar r = r << 1 | (b & 1); 768127808Snectar b = b >> 1; 769127808Snectar } 770127808Snectar return r; 771127808Snectar} 772127808Snectar 773127808Snectar 77472445Sassar/* 775127808Snectar * 77672445Sassar */ 77772445Sassar 778178825Sdfrkrb5_error_code KRB5_LIB_FUNCTION 779178825Sdfrkrb5_store_creds(krb5_storage *sp, krb5_creds *creds) 78055682Smarkm{ 78172445Sassar int ret; 78272445Sassar 78372445Sassar ret = krb5_store_principal(sp, creds->client); 784102644Snectar if(ret) 78572445Sassar return ret; 78672445Sassar ret = krb5_store_principal(sp, creds->server); 787102644Snectar if(ret) 78872445Sassar return ret; 78972445Sassar ret = krb5_store_keyblock(sp, creds->session); 790102644Snectar if(ret) 79172445Sassar return ret; 79272445Sassar ret = krb5_store_times(sp, creds->times); 793102644Snectar if(ret) 79472445Sassar return ret; 795178825Sdfr ret = krb5_store_int8(sp, creds->second_ticket.length != 0); /* is_skey */ 796102644Snectar if(ret) 79772445Sassar return ret; 798178825Sdfr 799178825Sdfr if(krb5_storage_is_flags(sp, KRB5_STORAGE_CREDS_FLAGS_WRONG_BITORDER)) 800127808Snectar ret = krb5_store_int32(sp, creds->flags.i); 801178825Sdfr else 802127808Snectar ret = krb5_store_int32(sp, bitswap32(TicketFlags2int(creds->flags.b))); 803178825Sdfr if(ret) 804178825Sdfr return ret; 805178825Sdfr 80672445Sassar ret = krb5_store_addrs(sp, creds->addresses); 807102644Snectar if(ret) 80872445Sassar return ret; 80972445Sassar ret = krb5_store_authdata(sp, creds->authdata); 810102644Snectar if(ret) 81172445Sassar return ret; 81272445Sassar ret = krb5_store_data(sp, creds->ticket); 813102644Snectar if(ret) 81472445Sassar return ret; 81572445Sassar ret = krb5_store_data(sp, creds->second_ticket); 816102644Snectar return ret; 81755682Smarkm} 81855682Smarkm 819178825Sdfrkrb5_error_code KRB5_LIB_FUNCTION 82055682Smarkmkrb5_ret_creds(krb5_storage *sp, krb5_creds *creds) 82155682Smarkm{ 82255682Smarkm krb5_error_code ret; 82355682Smarkm int8_t dummy8; 82455682Smarkm int32_t dummy32; 82555682Smarkm 82655682Smarkm memset(creds, 0, sizeof(*creds)); 82755682Smarkm ret = krb5_ret_principal (sp, &creds->client); 82855682Smarkm if(ret) goto cleanup; 82955682Smarkm ret = krb5_ret_principal (sp, &creds->server); 83055682Smarkm if(ret) goto cleanup; 83155682Smarkm ret = krb5_ret_keyblock (sp, &creds->session); 83255682Smarkm if(ret) goto cleanup; 83355682Smarkm ret = krb5_ret_times (sp, &creds->times); 83455682Smarkm if(ret) goto cleanup; 83555682Smarkm ret = krb5_ret_int8 (sp, &dummy8); 83655682Smarkm if(ret) goto cleanup; 83755682Smarkm ret = krb5_ret_int32 (sp, &dummy32); 83855682Smarkm if(ret) goto cleanup; 839127808Snectar /* 840127808Snectar * Runtime detect the what is the higher bits of the bitfield. If 841178825Sdfr * any of the higher bits are set in the input data, it's either a 842178825Sdfr * new ticket flag (and this code need to be removed), or it's a 843127808Snectar * MIT cache (or new Heimdal cache), lets change it to our current 844127808Snectar * format. 845127808Snectar */ 846127808Snectar { 847178825Sdfr uint32_t mask = 0xffff0000; 848127808Snectar creds->flags.i = 0; 849127808Snectar creds->flags.b.anonymous = 1; 850127808Snectar if (creds->flags.i & mask) 851127808Snectar mask = ~mask; 852127808Snectar if (dummy32 & mask) 853127808Snectar dummy32 = bitswap32(dummy32); 854127808Snectar } 85555682Smarkm creds->flags.i = dummy32; 85655682Smarkm ret = krb5_ret_addrs (sp, &creds->addresses); 85755682Smarkm if(ret) goto cleanup; 85855682Smarkm ret = krb5_ret_authdata (sp, &creds->authdata); 85955682Smarkm if(ret) goto cleanup; 86055682Smarkm ret = krb5_ret_data (sp, &creds->ticket); 86155682Smarkm if(ret) goto cleanup; 86255682Smarkm ret = krb5_ret_data (sp, &creds->second_ticket); 86355682Smarkmcleanup: 864102644Snectar if(ret) { 86555682Smarkm#if 0 866178825Sdfr krb5_free_cred_contents(context, creds); /* XXX */ 86755682Smarkm#endif 868102644Snectar } 86955682Smarkm return ret; 87055682Smarkm} 871178825Sdfr 872178825Sdfr#define SC_CLIENT_PRINCIPAL 0x0001 873178825Sdfr#define SC_SERVER_PRINCIPAL 0x0002 874178825Sdfr#define SC_SESSION_KEY 0x0004 875178825Sdfr#define SC_TICKET 0x0008 876178825Sdfr#define SC_SECOND_TICKET 0x0010 877178825Sdfr#define SC_AUTHDATA 0x0020 878178825Sdfr#define SC_ADDRESSES 0x0040 879178825Sdfr 880178825Sdfr/* 881178825Sdfr * 882178825Sdfr */ 883178825Sdfr 884178825Sdfrkrb5_error_code KRB5_LIB_FUNCTION 885178825Sdfrkrb5_store_creds_tag(krb5_storage *sp, krb5_creds *creds) 886178825Sdfr{ 887178825Sdfr int ret; 888178825Sdfr int32_t header = 0; 889178825Sdfr 890178825Sdfr if (creds->client) 891178825Sdfr header |= SC_CLIENT_PRINCIPAL; 892178825Sdfr if (creds->server) 893178825Sdfr header |= SC_SERVER_PRINCIPAL; 894178825Sdfr if (creds->session.keytype != ETYPE_NULL) 895178825Sdfr header |= SC_SESSION_KEY; 896178825Sdfr if (creds->ticket.data) 897178825Sdfr header |= SC_TICKET; 898178825Sdfr if (creds->second_ticket.length) 899178825Sdfr header |= SC_SECOND_TICKET; 900178825Sdfr if (creds->authdata.len) 901178825Sdfr header |= SC_AUTHDATA; 902178825Sdfr if (creds->addresses.len) 903178825Sdfr header |= SC_ADDRESSES; 904178825Sdfr 905178825Sdfr ret = krb5_store_int32(sp, header); 906178825Sdfr 907178825Sdfr if (creds->client) { 908178825Sdfr ret = krb5_store_principal(sp, creds->client); 909178825Sdfr if(ret) 910178825Sdfr return ret; 911178825Sdfr } 912178825Sdfr 913178825Sdfr if (creds->server) { 914178825Sdfr ret = krb5_store_principal(sp, creds->server); 915178825Sdfr if(ret) 916178825Sdfr return ret; 917178825Sdfr } 918178825Sdfr 919178825Sdfr if (creds->session.keytype != ETYPE_NULL) { 920178825Sdfr ret = krb5_store_keyblock(sp, creds->session); 921178825Sdfr if(ret) 922178825Sdfr return ret; 923178825Sdfr } 924178825Sdfr 925178825Sdfr ret = krb5_store_times(sp, creds->times); 926178825Sdfr if(ret) 927178825Sdfr return ret; 928178825Sdfr ret = krb5_store_int8(sp, creds->second_ticket.length != 0); /* is_skey */ 929178825Sdfr if(ret) 930178825Sdfr return ret; 931178825Sdfr 932178825Sdfr ret = krb5_store_int32(sp, bitswap32(TicketFlags2int(creds->flags.b))); 933178825Sdfr if(ret) 934178825Sdfr return ret; 935178825Sdfr 936178825Sdfr if (creds->addresses.len) { 937178825Sdfr ret = krb5_store_addrs(sp, creds->addresses); 938178825Sdfr if(ret) 939178825Sdfr return ret; 940178825Sdfr } 941178825Sdfr 942178825Sdfr if (creds->authdata.len) { 943178825Sdfr ret = krb5_store_authdata(sp, creds->authdata); 944178825Sdfr if(ret) 945178825Sdfr return ret; 946178825Sdfr } 947178825Sdfr 948178825Sdfr if (creds->ticket.data) { 949178825Sdfr ret = krb5_store_data(sp, creds->ticket); 950178825Sdfr if(ret) 951178825Sdfr return ret; 952178825Sdfr } 953178825Sdfr 954178825Sdfr if (creds->second_ticket.data) { 955178825Sdfr ret = krb5_store_data(sp, creds->second_ticket); 956178825Sdfr if (ret) 957178825Sdfr return ret; 958178825Sdfr } 959178825Sdfr 960178825Sdfr return ret; 961178825Sdfr} 962178825Sdfr 963178825Sdfrkrb5_error_code KRB5_LIB_FUNCTION 964178825Sdfrkrb5_ret_creds_tag(krb5_storage *sp, 965178825Sdfr krb5_creds *creds) 966178825Sdfr{ 967178825Sdfr krb5_error_code ret; 968178825Sdfr int8_t dummy8; 969178825Sdfr int32_t dummy32, header; 970178825Sdfr 971178825Sdfr memset(creds, 0, sizeof(*creds)); 972178825Sdfr 973178825Sdfr ret = krb5_ret_int32 (sp, &header); 974178825Sdfr if (ret) goto cleanup; 975178825Sdfr 976178825Sdfr if (header & SC_CLIENT_PRINCIPAL) { 977178825Sdfr ret = krb5_ret_principal (sp, &creds->client); 978178825Sdfr if(ret) goto cleanup; 979178825Sdfr } 980178825Sdfr if (header & SC_SERVER_PRINCIPAL) { 981178825Sdfr ret = krb5_ret_principal (sp, &creds->server); 982178825Sdfr if(ret) goto cleanup; 983178825Sdfr } 984178825Sdfr if (header & SC_SESSION_KEY) { 985178825Sdfr ret = krb5_ret_keyblock (sp, &creds->session); 986178825Sdfr if(ret) goto cleanup; 987178825Sdfr } 988178825Sdfr ret = krb5_ret_times (sp, &creds->times); 989178825Sdfr if(ret) goto cleanup; 990178825Sdfr ret = krb5_ret_int8 (sp, &dummy8); 991178825Sdfr if(ret) goto cleanup; 992178825Sdfr ret = krb5_ret_int32 (sp, &dummy32); 993178825Sdfr if(ret) goto cleanup; 994178825Sdfr /* 995178825Sdfr * Runtime detect the what is the higher bits of the bitfield. If 996178825Sdfr * any of the higher bits are set in the input data, it's either a 997178825Sdfr * new ticket flag (and this code need to be removed), or it's a 998178825Sdfr * MIT cache (or new Heimdal cache), lets change it to our current 999178825Sdfr * format. 1000178825Sdfr */ 1001178825Sdfr { 1002178825Sdfr uint32_t mask = 0xffff0000; 1003178825Sdfr creds->flags.i = 0; 1004178825Sdfr creds->flags.b.anonymous = 1; 1005178825Sdfr if (creds->flags.i & mask) 1006178825Sdfr mask = ~mask; 1007178825Sdfr if (dummy32 & mask) 1008178825Sdfr dummy32 = bitswap32(dummy32); 1009178825Sdfr } 1010178825Sdfr creds->flags.i = dummy32; 1011178825Sdfr if (header & SC_ADDRESSES) { 1012178825Sdfr ret = krb5_ret_addrs (sp, &creds->addresses); 1013178825Sdfr if(ret) goto cleanup; 1014178825Sdfr } 1015178825Sdfr if (header & SC_AUTHDATA) { 1016178825Sdfr ret = krb5_ret_authdata (sp, &creds->authdata); 1017178825Sdfr if(ret) goto cleanup; 1018178825Sdfr } 1019178825Sdfr if (header & SC_TICKET) { 1020178825Sdfr ret = krb5_ret_data (sp, &creds->ticket); 1021178825Sdfr if(ret) goto cleanup; 1022178825Sdfr } 1023178825Sdfr if (header & SC_SECOND_TICKET) { 1024178825Sdfr ret = krb5_ret_data (sp, &creds->second_ticket); 1025178825Sdfr if(ret) goto cleanup; 1026178825Sdfr } 1027178825Sdfr 1028178825Sdfrcleanup: 1029178825Sdfr if(ret) { 1030178825Sdfr#if 0 1031178825Sdfr krb5_free_cred_contents(context, creds); /* XXX */ 1032178825Sdfr#endif 1033178825Sdfr } 1034178825Sdfr return ret; 1035178825Sdfr} 1036