1/* 2 * Copyright (c) 1997 - 2000, 2002 Kungliga Tekniska Högskolan 3 * (Royal Institute of Technology, Stockholm, Sweden). 4 * All rights reserved. 5 * 6 * Redistribution and use in source and binary forms, with or without 7 * modification, are permitted provided that the following conditions 8 * are met: 9 * 10 * 1. Redistributions of source code must retain the above copyright 11 * notice, this list of conditions and the following disclaimer. 12 * 13 * 2. Redistributions in binary form must reproduce the above copyright 14 * notice, this list of conditions and the following disclaimer in the 15 * documentation and/or other materials provided with the distribution. 16 * 17 * 3. Neither the name of the Institute nor the names of its contributors 18 * may be used to endorse or promote products derived from this software 19 * without specific prior written permission. 20 * 21 * THIS SOFTWARE IS PROVIDED BY THE INSTITUTE AND CONTRIBUTORS ``AS IS'' AND 22 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 23 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE 24 * ARE DISCLAIMED. IN NO EVENT SHALL THE INSTITUTE OR CONTRIBUTORS BE LIABLE 25 * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL 26 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS 27 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) 28 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT 29 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY 30 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF 31 * SUCH DAMAGE. 32 */ 33 34#include "krb5_locl.h" 35#include "store-int.h" 36 37typedef struct mem_storage{ 38 unsigned char *base; 39 size_t size; 40 unsigned char *ptr; 41}mem_storage; 42 43static ssize_t 44mem_fetch(krb5_storage *sp, void *data, size_t size) 45{ 46 mem_storage *s = (mem_storage*)sp->data; 47 if(size > (size_t)(s->base + s->size - s->ptr)) 48 size = s->base + s->size - s->ptr; 49 memmove(data, s->ptr, size); 50 sp->seek(sp, size, SEEK_CUR); 51 return size; 52} 53 54static ssize_t 55mem_store(krb5_storage *sp, const void *data, size_t size) 56{ 57 mem_storage *s = (mem_storage*)sp->data; 58 if(size > (size_t)(s->base + s->size - s->ptr)) 59 size = s->base + s->size - s->ptr; 60 memmove(s->ptr, data, size); 61 sp->seek(sp, size, SEEK_CUR); 62 return size; 63} 64 65static ssize_t 66mem_no_store(krb5_storage *sp, const void *data, size_t size) 67{ 68 return -1; 69} 70 71static off_t 72mem_seek(krb5_storage *sp, off_t offset, int whence) 73{ 74 mem_storage *s = (mem_storage*)sp->data; 75 switch(whence){ 76 case SEEK_SET: 77 if((size_t)offset > s->size) 78 offset = s->size; 79 if(offset < 0) 80 offset = 0; 81 s->ptr = s->base + offset; 82 break; 83 case SEEK_CUR: 84 return sp->seek(sp, s->ptr - s->base + offset, SEEK_SET); 85 case SEEK_END: 86 return sp->seek(sp, s->size + offset, SEEK_SET); 87 default: 88 errno = EINVAL; 89 return -1; 90 } 91 return s->ptr - s->base; 92} 93 94static int 95mem_trunc(krb5_storage *sp, off_t offset) 96{ 97 mem_storage *s = (mem_storage*)sp->data; 98 /* make SIZE_T_MAX to something that wont turn into -1 */ 99 if(offset > (off_t)(SIZE_T_MAX >> 1) || (size_t)offset > s->size) 100 return ERANGE; 101 s->size = (size_t)offset; 102 if ((s->ptr - s->base) > offset) 103 s->ptr = s->base + offset; 104 return 0; 105} 106 107static int 108mem_no_trunc(krb5_storage *sp, off_t offset) 109{ 110 return EINVAL; 111} 112 113static void 114mem_free(krb5_storage *sp) 115{ 116 mem_storage *s = sp->data; 117 memset(s->base, 0, s->size); 118 free(s->base); 119} 120 121 122/** 123 * Create a fixed size memory storage block 124 * 125 * @return A krb5_storage on success, or NULL on out of memory error. 126 * 127 * @ingroup krb5_storage 128 * 129 * @sa krb5_storage_emem() 130 * @sa krb5_storage_from_readonly_mem() 131 * @sa krb5_storage_from_data() 132 * @sa krb5_storage_from_fd() 133 * @sa krb5_storage_from_mem_copy() 134 */ 135 136KRB5_LIB_FUNCTION krb5_storage * KRB5_LIB_CALL 137krb5_storage_from_mem(void *buf, size_t len) 138{ 139 krb5_storage *sp = malloc(sizeof(krb5_storage)); 140 mem_storage *s; 141 if(sp == NULL) 142 return NULL; 143 s = malloc(sizeof(*s)); 144 if(s == NULL) { 145 free(sp); 146 return NULL; 147 } 148 sp->data = s; 149 sp->flags = 0; 150 sp->eof_code = HEIM_ERR_EOF; 151 s->base = buf; 152 s->size = len; 153 s->ptr = buf; 154 sp->fetch = mem_fetch; 155 sp->store = mem_store; 156 sp->seek = mem_seek; 157 sp->trunc = mem_trunc; 158 sp->free = NULL; 159 sp->max_alloc = UINT_MAX/8; 160 return sp; 161} 162 163/** 164 * Create a fixed size memory storage block 165 * 166 * @return A krb5_storage on success, or NULL on out of memory error. 167 * 168 * @ingroup krb5_storage 169 * 170 * @sa krb5_storage_mem() 171 * @sa krb5_storage_from_mem() 172 * @sa krb5_storage_from_readonly_mem() 173 * @sa krb5_storage_from_fd() 174 * @sa krb5_storage_from_mem_copy() 175 */ 176 177KRB5_LIB_FUNCTION krb5_storage * KRB5_LIB_CALL 178krb5_storage_from_data(krb5_data *data) 179{ 180 return krb5_storage_from_mem(data->data, data->length); 181} 182 183/** 184 * Create a fixed size memory storage block that is read only 185 * 186 * @return A krb5_storage on success, or NULL on out of memory error. 187 * 188 * @ingroup krb5_storage 189 * 190 * @sa krb5_storage_emem() 191 * @sa krb5_storage_from_mem() 192 * @sa krb5_storage_from_data() 193 * @sa krb5_storage_from_fd() 194 * @sa krb5_storage_from_mem_copy() 195 */ 196 197KRB5_LIB_FUNCTION krb5_storage * KRB5_LIB_CALL 198krb5_storage_from_readonly_mem(const void *buf, size_t len) 199{ 200 krb5_storage *sp = malloc(sizeof(krb5_storage)); 201 mem_storage *s; 202 if(sp == NULL) 203 return NULL; 204 s = malloc(sizeof(*s)); 205 if(s == NULL) { 206 free(sp); 207 return NULL; 208 } 209 sp->data = s; 210 sp->flags = 0; 211 sp->eof_code = HEIM_ERR_EOF; 212 s->base = rk_UNCONST(buf); 213 s->size = len; 214 s->ptr = rk_UNCONST(buf); 215 sp->fetch = mem_fetch; 216 sp->store = mem_no_store; 217 sp->seek = mem_seek; 218 sp->trunc = mem_no_trunc; 219 sp->free = NULL; 220 sp->max_alloc = UINT_MAX/8; 221 return sp; 222} 223 224/** 225 * Create a copy of a memory and assign it to a storage block 226 * 227 * The input data buffer is copied and the orignal buffer can be freed 228 * during the life the storage. 229 * 230 * @return A krb5_storage on success, or NULL on out of memory error. 231 * 232 * @ingroup krb5_storage 233 * 234 * @sa krb5_storage_emem() 235 * @sa krb5_storage_from_mem() 236 * @sa krb5_storage_from_data() 237 * @sa krb5_storage_from_fd() 238 */ 239 240krb5_storage * KRB5_LIB_FUNCTION 241krb5_storage_from_mem_copy(void *buf, size_t len) 242{ 243 krb5_storage *sp = malloc(sizeof(krb5_storage)); 244 mem_storage *s; 245 if(sp == NULL) 246 return NULL; 247 s = malloc(sizeof(*s)); 248 if(s == NULL) { 249 free(sp); 250 return NULL; 251 } 252 sp->data = s; 253 sp->flags = 0; 254 sp->eof_code = HEIM_ERR_EOF; 255 s->base = malloc(len); 256 if (s->base == NULL) { 257 free(sp); 258 free(s); 259 return NULL; 260 } 261 memcpy(s->base, buf, len); 262 s->size = len; 263 s->ptr = s->base; 264 sp->fetch = mem_fetch; 265 sp->store = mem_store; 266 sp->seek = mem_seek; 267 sp->trunc = mem_trunc; 268 sp->free = mem_free; 269 return sp; 270} 271