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