1 /* $NetBSD: store.c,v 1.1.1.2 2014/04/24 12:45:51 pettai 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 * Read to the storage buffer.
197 *
198 * @param sp the storage buffer to read from
199 * @param buf the buffer to store the data in
200 * @param len the length to read
201 *
202 * @return The length of data read (can be shorter then len), or negative on error.
203 *
204 * @ingroup krb5_storage
205 */
206
207 KRB5_LIB_FUNCTION krb5_ssize_t KRB5_LIB_CALL
krb5_storage_read(krb5_storage * sp,void * buf,size_t len)208 krb5_storage_read(krb5_storage *sp, void *buf, size_t len)
209 {
210 return sp->fetch(sp, buf, len);
211 }
212
213 /**
214 * Write to the storage buffer.
215 *
216 * @param sp the storage buffer to write to
217 * @param buf the buffer to write to the storage buffer
218 * @param len the length to write
219 *
220 * @return The length of data written (can be shorter then len), or negative on error.
221 *
222 * @ingroup krb5_storage
223 */
224
225 KRB5_LIB_FUNCTION krb5_ssize_t KRB5_LIB_CALL
krb5_storage_write(krb5_storage * sp,const void * buf,size_t len)226 krb5_storage_write(krb5_storage *sp, const void *buf, size_t len)
227 {
228 return sp->store(sp, buf, len);
229 }
230
231 /**
232 * Set the return code that will be used when end of storage is reached.
233 *
234 * @param sp the storage
235 * @param code the error code to return on end of storage
236 *
237 * @ingroup krb5_storage
238 */
239
240 KRB5_LIB_FUNCTION void KRB5_LIB_CALL
krb5_storage_set_eof_code(krb5_storage * sp,int code)241 krb5_storage_set_eof_code(krb5_storage *sp, int code)
242 {
243 sp->eof_code = code;
244 }
245
246 /**
247 * Get the return code that will be used when end of storage is reached.
248 *
249 * @param sp the storage
250 *
251 * @return storage error code
252 *
253 * @ingroup krb5_storage
254 */
255
256 KRB5_LIB_FUNCTION int KRB5_LIB_CALL
krb5_storage_get_eof_code(krb5_storage * sp)257 krb5_storage_get_eof_code(krb5_storage *sp)
258 {
259 return sp->eof_code;
260 }
261
262 /**
263 * Free a krb5 storage.
264 *
265 * @param sp the storage to free.
266 *
267 * @return An Kerberos 5 error code.
268 *
269 * @ingroup krb5_storage
270 */
271
272 KRB5_LIB_FUNCTION krb5_error_code KRB5_LIB_CALL
krb5_storage_free(krb5_storage * sp)273 krb5_storage_free(krb5_storage *sp)
274 {
275 if(sp->free)
276 (*sp->free)(sp);
277 free(sp->data);
278 free(sp);
279 return 0;
280 }
281
282 /**
283 * Copy the contnent of storage
284 *
285 * @param sp the storage to copy to a data
286 * @param data the copied data, free with krb5_data_free()
287 *
288 * @return 0 for success, or a Kerberos 5 error code on failure.
289 *
290 * @ingroup krb5_storage
291 */
292
293 KRB5_LIB_FUNCTION krb5_error_code KRB5_LIB_CALL
krb5_storage_to_data(krb5_storage * sp,krb5_data * data)294 krb5_storage_to_data(krb5_storage *sp, krb5_data *data)
295 {
296 off_t pos, size;
297 krb5_error_code ret;
298
299 pos = sp->seek(sp, 0, SEEK_CUR);
300 if (pos < 0)
301 return HEIM_ERR_NOT_SEEKABLE;
302 size = sp->seek(sp, 0, SEEK_END);
303 ret = size_too_large(sp, size);
304 if (ret)
305 return ret;
306 ret = krb5_data_alloc(data, size);
307 if (ret) {
308 sp->seek(sp, pos, SEEK_SET);
309 return ret;
310 }
311 if (size) {
312 sp->seek(sp, 0, SEEK_SET);
313 sp->fetch(sp, data->data, data->length);
314 sp->seek(sp, pos, SEEK_SET);
315 }
316 return 0;
317 }
318
319 static krb5_error_code
krb5_store_int(krb5_storage * sp,int32_t value,size_t len)320 krb5_store_int(krb5_storage *sp,
321 int32_t value,
322 size_t len)
323 {
324 int ret;
325 unsigned char v[16];
326
327 if(len > sizeof(v))
328 return EINVAL;
329 _krb5_put_int(v, value, len);
330 ret = sp->store(sp, v, len);
331 if (ret < 0)
332 return errno;
333 if ((size_t)ret != len)
334 return sp->eof_code;
335 return 0;
336 }
337
338 /**
339 * Store a int32 to storage, byte order is controlled by the settings
340 * on the storage, see krb5_storage_set_byteorder().
341 *
342 * @param sp the storage to write too
343 * @param value the value to store
344 *
345 * @return 0 for success, or a Kerberos 5 error code on failure.
346 *
347 * @ingroup krb5_storage
348 */
349
350 KRB5_LIB_FUNCTION krb5_error_code KRB5_LIB_CALL
krb5_store_int32(krb5_storage * sp,int32_t value)351 krb5_store_int32(krb5_storage *sp,
352 int32_t value)
353 {
354 if(BYTEORDER_IS_HOST(sp))
355 value = htonl(value);
356 else if(BYTEORDER_IS_LE(sp))
357 value = bswap32(value);
358 return krb5_store_int(sp, value, 4);
359 }
360
361 /**
362 * Store a uint32 to storage, byte order is controlled by the settings
363 * on the storage, see krb5_storage_set_byteorder().
364 *
365 * @param sp the storage to write too
366 * @param value the value to store
367 *
368 * @return 0 for success, or a Kerberos 5 error code on failure.
369 *
370 * @ingroup krb5_storage
371 */
372
373 KRB5_LIB_FUNCTION krb5_error_code KRB5_LIB_CALL
krb5_store_uint32(krb5_storage * sp,uint32_t value)374 krb5_store_uint32(krb5_storage *sp,
375 uint32_t value)
376 {
377 return krb5_store_int32(sp, (int32_t)value);
378 }
379
380 static krb5_error_code
krb5_ret_int(krb5_storage * sp,int32_t * value,size_t len)381 krb5_ret_int(krb5_storage *sp,
382 int32_t *value,
383 size_t len)
384 {
385 int ret;
386 unsigned char v[4];
387 unsigned long w;
388 ret = sp->fetch(sp, v, len);
389 if (ret < 0)
390 return errno;
391 if ((size_t)ret != len)
392 return sp->eof_code;
393 _krb5_get_int(v, &w, len);
394 *value = w;
395 return 0;
396 }
397
398 /**
399 * Read a int32 from storage, byte order is controlled by the settings
400 * on the storage, see krb5_storage_set_byteorder().
401 *
402 * @param sp the storage to write too
403 * @param value the value read from the buffer
404 *
405 * @return 0 for success, or a Kerberos 5 error code on failure.
406 *
407 * @ingroup krb5_storage
408 */
409
410 KRB5_LIB_FUNCTION krb5_error_code KRB5_LIB_CALL
krb5_ret_int32(krb5_storage * sp,int32_t * value)411 krb5_ret_int32(krb5_storage *sp,
412 int32_t *value)
413 {
414 krb5_error_code ret = krb5_ret_int(sp, value, 4);
415 if(ret)
416 return ret;
417 if(BYTEORDER_IS_HOST(sp))
418 *value = htonl(*value);
419 else if(BYTEORDER_IS_LE(sp))
420 *value = bswap32(*value);
421 return 0;
422 }
423
424 /**
425 * Read a uint32 from storage, byte order is controlled by the settings
426 * on the storage, see krb5_storage_set_byteorder().
427 *
428 * @param sp the storage to write too
429 * @param value the value read from the buffer
430 *
431 * @return 0 for success, or a Kerberos 5 error code on failure.
432 *
433 * @ingroup krb5_storage
434 */
435
436 KRB5_LIB_FUNCTION krb5_error_code KRB5_LIB_CALL
krb5_ret_uint32(krb5_storage * sp,uint32_t * value)437 krb5_ret_uint32(krb5_storage *sp,
438 uint32_t *value)
439 {
440 krb5_error_code ret;
441 int32_t v;
442
443 ret = krb5_ret_int32(sp, &v);
444 if (ret == 0)
445 *value = (uint32_t)v;
446
447 return ret;
448 }
449
450 /**
451 * Store a int16 to storage, byte order is controlled by the settings
452 * on the storage, see krb5_storage_set_byteorder().
453 *
454 * @param sp the storage to write too
455 * @param value the value to store
456 *
457 * @return 0 for success, or a Kerberos 5 error code on failure.
458 *
459 * @ingroup krb5_storage
460 */
461
462 KRB5_LIB_FUNCTION krb5_error_code KRB5_LIB_CALL
krb5_store_int16(krb5_storage * sp,int16_t value)463 krb5_store_int16(krb5_storage *sp,
464 int16_t value)
465 {
466 if(BYTEORDER_IS_HOST(sp))
467 value = htons(value);
468 else if(BYTEORDER_IS_LE(sp))
469 value = bswap16(value);
470 return krb5_store_int(sp, value, 2);
471 }
472
473 /**
474 * Store a uint16 to storage, byte order is controlled by the settings
475 * on the storage, see krb5_storage_set_byteorder().
476 *
477 * @param sp the storage to write too
478 * @param value the value to store
479 *
480 * @return 0 for success, or a Kerberos 5 error code on failure.
481 *
482 * @ingroup krb5_storage
483 */
484
485 KRB5_LIB_FUNCTION krb5_error_code KRB5_LIB_CALL
krb5_store_uint16(krb5_storage * sp,uint16_t value)486 krb5_store_uint16(krb5_storage *sp,
487 uint16_t value)
488 {
489 return krb5_store_int16(sp, (int16_t)value);
490 }
491
492 /**
493 * Read a int16 from storage, byte order is controlled by the settings
494 * on the storage, see krb5_storage_set_byteorder().
495 *
496 * @param sp the storage to write too
497 * @param value the value read from the buffer
498 *
499 * @return 0 for success, or a Kerberos 5 error code on failure.
500 *
501 * @ingroup krb5_storage
502 */
503
504 KRB5_LIB_FUNCTION krb5_error_code KRB5_LIB_CALL
krb5_ret_int16(krb5_storage * sp,int16_t * value)505 krb5_ret_int16(krb5_storage *sp,
506 int16_t *value)
507 {
508 int32_t v;
509 int ret;
510 ret = krb5_ret_int(sp, &v, 2);
511 if(ret)
512 return ret;
513 *value = v;
514 if(BYTEORDER_IS_HOST(sp))
515 *value = htons(*value);
516 else if(BYTEORDER_IS_LE(sp))
517 *value = bswap16(*value);
518 return 0;
519 }
520
521 /**
522 * Read a int16 from storage, byte order is controlled by the settings
523 * on the storage, see krb5_storage_set_byteorder().
524 *
525 * @param sp the storage to write too
526 * @param value the value read from the buffer
527 *
528 * @return 0 for success, or a Kerberos 5 error code on failure.
529 *
530 * @ingroup krb5_storage
531 */
532
533 KRB5_LIB_FUNCTION krb5_error_code KRB5_LIB_CALL
krb5_ret_uint16(krb5_storage * sp,uint16_t * value)534 krb5_ret_uint16(krb5_storage *sp,
535 uint16_t *value)
536 {
537 krb5_error_code ret;
538 int16_t v;
539
540 ret = krb5_ret_int16(sp, &v);
541 if (ret == 0)
542 *value = (uint16_t)v;
543
544 return ret;
545 }
546
547 /**
548 * Store a int8 to storage.
549 *
550 * @param sp the storage to write too
551 * @param value the value to store
552 *
553 * @return 0 for success, or a Kerberos 5 error code on failure.
554 *
555 * @ingroup krb5_storage
556 */
557
558 KRB5_LIB_FUNCTION krb5_error_code KRB5_LIB_CALL
krb5_store_int8(krb5_storage * sp,int8_t value)559 krb5_store_int8(krb5_storage *sp,
560 int8_t value)
561 {
562 int ret;
563
564 ret = sp->store(sp, &value, sizeof(value));
565 if (ret != sizeof(value))
566 return (ret<0)?errno:sp->eof_code;
567 return 0;
568 }
569
570 /**
571 * Store a uint8 to storage.
572 *
573 * @param sp the storage to write too
574 * @param value the value to store
575 *
576 * @return 0 for success, or a Kerberos 5 error code on failure.
577 *
578 * @ingroup krb5_storage
579 */
580
581 KRB5_LIB_FUNCTION krb5_error_code KRB5_LIB_CALL
krb5_store_uint8(krb5_storage * sp,uint8_t value)582 krb5_store_uint8(krb5_storage *sp,
583 uint8_t value)
584 {
585 return krb5_store_int8(sp, (int8_t)value);
586 }
587
588 /**
589 * Read a int8 from storage
590 *
591 * @param sp the storage to write too
592 * @param value the value read from the buffer
593 *
594 * @return 0 for success, or a Kerberos 5 error code on failure.
595 *
596 * @ingroup krb5_storage
597 */
598
599 KRB5_LIB_FUNCTION krb5_error_code KRB5_LIB_CALL
krb5_ret_int8(krb5_storage * sp,int8_t * value)600 krb5_ret_int8(krb5_storage *sp,
601 int8_t *value)
602 {
603 int ret;
604
605 ret = sp->fetch(sp, value, sizeof(*value));
606 if (ret != sizeof(*value))
607 return (ret<0)?errno:sp->eof_code;
608 return 0;
609 }
610
611 /**
612 * Read a uint8 from storage
613 *
614 * @param sp the storage to write too
615 * @param value the value read from the buffer
616 *
617 * @return 0 for success, or a Kerberos 5 error code on failure.
618 *
619 * @ingroup krb5_storage
620 */
621
622 KRB5_LIB_FUNCTION krb5_error_code KRB5_LIB_CALL
krb5_ret_uint8(krb5_storage * sp,uint8_t * value)623 krb5_ret_uint8(krb5_storage *sp,
624 uint8_t *value)
625 {
626 krb5_error_code ret;
627 int8_t v;
628
629 ret = krb5_ret_int8(sp, &v);
630 if (ret == 0)
631 *value = (uint8_t)v;
632
633 return ret;
634 }
635
636 /**
637 * Store a data to the storage. The data is stored with an int32 as
638 * lenght plus the data (not padded).
639 *
640 * @param sp the storage buffer to write to
641 * @param data the buffer to store.
642 *
643 * @return 0 on success, a Kerberos 5 error code on failure.
644 *
645 * @ingroup krb5_storage
646 */
647
648 KRB5_LIB_FUNCTION krb5_error_code KRB5_LIB_CALL
krb5_store_data(krb5_storage * sp,krb5_data data)649 krb5_store_data(krb5_storage *sp,
650 krb5_data data)
651 {
652 int ret;
653 ret = krb5_store_int32(sp, data.length);
654 if(ret < 0)
655 return ret;
656 ret = sp->store(sp, data.data, data.length);
657 if(ret < 0)
658 return errno;
659 if((size_t)ret != data.length)
660 return sp->eof_code;
661 return 0;
662 }
663
664 /**
665 * Parse a data from the storage.
666 *
667 * @param sp the storage buffer to read from
668 * @param data the parsed data
669 *
670 * @return 0 on success, a Kerberos 5 error code on failure.
671 *
672 * @ingroup krb5_storage
673 */
674
675 KRB5_LIB_FUNCTION krb5_error_code KRB5_LIB_CALL
krb5_ret_data(krb5_storage * sp,krb5_data * data)676 krb5_ret_data(krb5_storage *sp,
677 krb5_data *data)
678 {
679 int ret;
680 int32_t size;
681
682 ret = krb5_ret_int32(sp, &size);
683 if(ret)
684 return ret;
685 ret = size_too_large(sp, size);
686 if (ret)
687 return ret;
688 ret = krb5_data_alloc (data, size);
689 if (ret)
690 return ret;
691 if (size) {
692 ret = sp->fetch(sp, data->data, size);
693 if(ret != size)
694 return (ret < 0)? errno : sp->eof_code;
695 }
696 return 0;
697 }
698
699 /**
700 * Store a string to the buffer. The data is formated as an len:uint32
701 * plus the string itself (not padded).
702 *
703 * @param sp the storage buffer to write to
704 * @param s the string to store.
705 *
706 * @return 0 on success, a Kerberos 5 error code on failure.
707 *
708 * @ingroup krb5_storage
709 */
710
711 KRB5_LIB_FUNCTION krb5_error_code KRB5_LIB_CALL
krb5_store_string(krb5_storage * sp,const char * s)712 krb5_store_string(krb5_storage *sp, const char *s)
713 {
714 krb5_data data;
715 data.length = strlen(s);
716 data.data = rk_UNCONST(s);
717 return krb5_store_data(sp, data);
718 }
719
720 /**
721 * Parse a string from the storage.
722 *
723 * @param sp the storage buffer to read from
724 * @param string the parsed string
725 *
726 * @return 0 on success, a Kerberos 5 error code on failure.
727 *
728 * @ingroup krb5_storage
729 */
730
731
732 KRB5_LIB_FUNCTION krb5_error_code KRB5_LIB_CALL
krb5_ret_string(krb5_storage * sp,char ** string)733 krb5_ret_string(krb5_storage *sp,
734 char **string)
735 {
736 int ret;
737 krb5_data data;
738 ret = krb5_ret_data(sp, &data);
739 if(ret)
740 return ret;
741 *string = realloc(data.data, data.length + 1);
742 if(*string == NULL){
743 free(data.data);
744 return ENOMEM;
745 }
746 (*string)[data.length] = 0;
747 return 0;
748 }
749
750 /**
751 * Store a zero terminated string to the buffer. The data is stored
752 * one character at a time until a NUL is stored.
753 *
754 * @param sp the storage buffer to write to
755 * @param s the string to store.
756 *
757 * @return 0 on success, a Kerberos 5 error code on failure.
758 *
759 * @ingroup krb5_storage
760 */
761
762 KRB5_LIB_FUNCTION krb5_error_code KRB5_LIB_CALL
krb5_store_stringz(krb5_storage * sp,const char * s)763 krb5_store_stringz(krb5_storage *sp, const char *s)
764 {
765 size_t len = strlen(s) + 1;
766 ssize_t ret;
767
768 ret = sp->store(sp, s, len);
769 if(ret < 0)
770 return ret;
771 if((size_t)ret != len)
772 return sp->eof_code;
773 return 0;
774 }
775
776 /**
777 * Parse zero terminated string from the storage.
778 *
779 * @param sp the storage buffer to read from
780 * @param string the parsed string
781 *
782 * @return 0 on success, a Kerberos 5 error code on failure.
783 *
784 * @ingroup krb5_storage
785 */
786
787 KRB5_LIB_FUNCTION krb5_error_code KRB5_LIB_CALL
krb5_ret_stringz(krb5_storage * sp,char ** string)788 krb5_ret_stringz(krb5_storage *sp,
789 char **string)
790 {
791 char c;
792 char *s = NULL;
793 size_t len = 0;
794 ssize_t ret;
795
796 while((ret = sp->fetch(sp, &c, 1)) == 1){
797 char *tmp;
798
799 len++;
800 ret = size_too_large(sp, len);
801 if (ret)
802 break;
803 tmp = realloc (s, len);
804 if (tmp == NULL) {
805 free (s);
806 return ENOMEM;
807 }
808 s = tmp;
809 s[len - 1] = c;
810 if(c == 0)
811 break;
812 }
813 if(ret != 1){
814 free(s);
815 if(ret == 0)
816 return sp->eof_code;
817 return ret;
818 }
819 *string = s;
820 return 0;
821 }
822
823 KRB5_LIB_FUNCTION krb5_error_code KRB5_LIB_CALL
krb5_store_stringnl(krb5_storage * sp,const char * s)824 krb5_store_stringnl(krb5_storage *sp, const char *s)
825 {
826 size_t len = strlen(s);
827 ssize_t ret;
828
829 ret = sp->store(sp, s, len);
830 if(ret < 0)
831 return ret;
832 if((size_t)ret != len)
833 return sp->eof_code;
834 ret = sp->store(sp, "\n", 1);
835 if(ret != 1) {
836 if(ret < 0)
837 return ret;
838 else
839 return sp->eof_code;
840 }
841
842 return 0;
843
844 }
845
846 KRB5_LIB_FUNCTION krb5_error_code KRB5_LIB_CALL
krb5_ret_stringnl(krb5_storage * sp,char ** string)847 krb5_ret_stringnl(krb5_storage *sp,
848 char **string)
849 {
850 int expect_nl = 0;
851 char c;
852 char *s = NULL;
853 size_t len = 0;
854 ssize_t ret;
855
856 while((ret = sp->fetch(sp, &c, 1)) == 1){
857 char *tmp;
858
859 if (c == '\r') {
860 expect_nl = 1;
861 continue;
862 }
863 if (expect_nl && c != '\n') {
864 free(s);
865 return KRB5_BADMSGTYPE;
866 }
867
868 len++;
869 ret = size_too_large(sp, len);
870 if (ret)
871 break;
872 tmp = realloc (s, len);
873 if (tmp == NULL) {
874 free (s);
875 return ENOMEM;
876 }
877 s = tmp;
878 if(c == '\n') {
879 s[len - 1] = '\0';
880 break;
881 }
882 s[len - 1] = c;
883 }
884 if(ret != 1){
885 free(s);
886 if(ret == 0)
887 return sp->eof_code;
888 return ret;
889 }
890 *string = s;
891 return 0;
892 }
893
894 /**
895 * Write a principal block to storage.
896 *
897 * @param sp the storage buffer to write to
898 * @param p the principal block to write.
899 *
900 * @return 0 on success, a Kerberos 5 error code on failure.
901 *
902 * @ingroup krb5_storage
903 */
904
905 KRB5_LIB_FUNCTION krb5_error_code KRB5_LIB_CALL
krb5_store_principal(krb5_storage * sp,krb5_const_principal p)906 krb5_store_principal(krb5_storage *sp,
907 krb5_const_principal p)
908 {
909 size_t i;
910 int ret;
911
912 if(!krb5_storage_is_flags(sp, KRB5_STORAGE_PRINCIPAL_NO_NAME_TYPE)) {
913 ret = krb5_store_int32(sp, p->name.name_type);
914 if(ret) return ret;
915 }
916 if(krb5_storage_is_flags(sp, KRB5_STORAGE_PRINCIPAL_WRONG_NUM_COMPONENTS))
917 ret = krb5_store_int32(sp, p->name.name_string.len + 1);
918 else
919 ret = krb5_store_int32(sp, p->name.name_string.len);
920
921 if(ret) return ret;
922 ret = krb5_store_string(sp, p->realm);
923 if(ret) return ret;
924 for(i = 0; i < p->name.name_string.len; i++){
925 ret = krb5_store_string(sp, p->name.name_string.val[i]);
926 if(ret) return ret;
927 }
928 return 0;
929 }
930
931 /**
932 * Parse principal from the storage.
933 *
934 * @param sp the storage buffer to read from
935 * @param princ the parsed principal
936 *
937 * @return 0 on success, a Kerberos 5 error code on failure.
938 *
939 * @ingroup krb5_storage
940 */
941
942 KRB5_LIB_FUNCTION krb5_error_code KRB5_LIB_CALL
krb5_ret_principal(krb5_storage * sp,krb5_principal * princ)943 krb5_ret_principal(krb5_storage *sp,
944 krb5_principal *princ)
945 {
946 int i;
947 int ret;
948 krb5_principal p;
949 int32_t type;
950 int32_t ncomp;
951
952 p = calloc(1, sizeof(*p));
953 if(p == NULL)
954 return ENOMEM;
955
956 if(krb5_storage_is_flags(sp, KRB5_STORAGE_PRINCIPAL_NO_NAME_TYPE))
957 type = KRB5_NT_UNKNOWN;
958 else if((ret = krb5_ret_int32(sp, &type))){
959 free(p);
960 return ret;
961 }
962 if((ret = krb5_ret_int32(sp, &ncomp))){
963 free(p);
964 return ret;
965 }
966 if(krb5_storage_is_flags(sp, KRB5_STORAGE_PRINCIPAL_WRONG_NUM_COMPONENTS))
967 ncomp--;
968 if (ncomp < 0) {
969 free(p);
970 return EINVAL;
971 }
972 ret = size_too_large_num(sp, ncomp, sizeof(p->name.name_string.val[0]));
973 if (ret) {
974 free(p);
975 return ret;
976 }
977 p->name.name_type = type;
978 p->name.name_string.len = ncomp;
979 ret = krb5_ret_string(sp, &p->realm);
980 if(ret) {
981 free(p);
982 return ret;
983 }
984 p->name.name_string.val = calloc(ncomp, sizeof(p->name.name_string.val[0]));
985 if(p->name.name_string.val == NULL && ncomp != 0){
986 free(p->realm);
987 free(p);
988 return ENOMEM;
989 }
990 for(i = 0; i < ncomp; i++){
991 ret = krb5_ret_string(sp, &p->name.name_string.val[i]);
992 if(ret) {
993 while (i >= 0)
994 free(p->name.name_string.val[i--]);
995 free(p->realm);
996 free(p);
997 return ret;
998 }
999 }
1000 *princ = p;
1001 return 0;
1002 }
1003
1004 /**
1005 * Store a keyblock to the storage.
1006 *
1007 * @param sp the storage buffer to write to
1008 * @param p the keyblock to write
1009 *
1010 * @return 0 on success, a Kerberos 5 error code on failure.
1011 *
1012 * @ingroup krb5_storage
1013 */
1014
1015 KRB5_LIB_FUNCTION krb5_error_code KRB5_LIB_CALL
krb5_store_keyblock(krb5_storage * sp,krb5_keyblock p)1016 krb5_store_keyblock(krb5_storage *sp, krb5_keyblock p)
1017 {
1018 int ret;
1019 ret = krb5_store_int16(sp, p.keytype);
1020 if(ret) return ret;
1021
1022 if(krb5_storage_is_flags(sp, KRB5_STORAGE_KEYBLOCK_KEYTYPE_TWICE)){
1023 /* this should really be enctype, but it is the same as
1024 keytype nowadays */
1025 ret = krb5_store_int16(sp, p.keytype);
1026 if(ret) return ret;
1027 }
1028
1029 ret = krb5_store_data(sp, p.keyvalue);
1030 return ret;
1031 }
1032
1033 /**
1034 * Read a keyblock from the storage.
1035 *
1036 * @param sp the storage buffer to write to
1037 * @param p the keyblock read from storage, free using krb5_free_keyblock()
1038 *
1039 * @return 0 on success, a Kerberos 5 error code on failure.
1040 *
1041 * @ingroup krb5_storage
1042 */
1043
1044 KRB5_LIB_FUNCTION krb5_error_code KRB5_LIB_CALL
krb5_ret_keyblock(krb5_storage * sp,krb5_keyblock * p)1045 krb5_ret_keyblock(krb5_storage *sp, krb5_keyblock *p)
1046 {
1047 int ret;
1048 int16_t tmp;
1049
1050 ret = krb5_ret_int16(sp, &tmp);
1051 if(ret) return ret;
1052 p->keytype = tmp;
1053
1054 if(krb5_storage_is_flags(sp, KRB5_STORAGE_KEYBLOCK_KEYTYPE_TWICE)){
1055 ret = krb5_ret_int16(sp, &tmp);
1056 if(ret) return ret;
1057 }
1058
1059 ret = krb5_ret_data(sp, &p->keyvalue);
1060 return ret;
1061 }
1062
1063 /**
1064 * Write a times block to storage.
1065 *
1066 * @param sp the storage buffer to write to
1067 * @param times the times block to write.
1068 *
1069 * @return 0 on success, a Kerberos 5 error code on failure.
1070 *
1071 * @ingroup krb5_storage
1072 */
1073
1074 KRB5_LIB_FUNCTION krb5_error_code KRB5_LIB_CALL
krb5_store_times(krb5_storage * sp,krb5_times times)1075 krb5_store_times(krb5_storage *sp, krb5_times times)
1076 {
1077 int ret;
1078 ret = krb5_store_int32(sp, times.authtime);
1079 if(ret) return ret;
1080 ret = krb5_store_int32(sp, times.starttime);
1081 if(ret) return ret;
1082 ret = krb5_store_int32(sp, times.endtime);
1083 if(ret) return ret;
1084 ret = krb5_store_int32(sp, times.renew_till);
1085 return ret;
1086 }
1087
1088 /**
1089 * Read a times block from the storage.
1090 *
1091 * @param sp the storage buffer to write to
1092 * @param times the times block read from storage
1093 *
1094 * @return 0 on success, a Kerberos 5 error code on failure.
1095 *
1096 * @ingroup krb5_storage
1097 */
1098
1099 KRB5_LIB_FUNCTION krb5_error_code KRB5_LIB_CALL
krb5_ret_times(krb5_storage * sp,krb5_times * times)1100 krb5_ret_times(krb5_storage *sp, krb5_times *times)
1101 {
1102 int ret;
1103 int32_t tmp;
1104 ret = krb5_ret_int32(sp, &tmp);
1105 times->authtime = tmp;
1106 if(ret) return ret;
1107 ret = krb5_ret_int32(sp, &tmp);
1108 times->starttime = tmp;
1109 if(ret) return ret;
1110 ret = krb5_ret_int32(sp, &tmp);
1111 times->endtime = tmp;
1112 if(ret) return ret;
1113 ret = krb5_ret_int32(sp, &tmp);
1114 times->renew_till = tmp;
1115 return ret;
1116 }
1117
1118 /**
1119 * Write a address block to storage.
1120 *
1121 * @param sp the storage buffer to write to
1122 * @param p the address block to write.
1123 *
1124 * @return 0 on success, a Kerberos 5 error code on failure.
1125 *
1126 * @ingroup krb5_storage
1127 */
1128
1129 KRB5_LIB_FUNCTION krb5_error_code KRB5_LIB_CALL
krb5_store_address(krb5_storage * sp,krb5_address p)1130 krb5_store_address(krb5_storage *sp, krb5_address p)
1131 {
1132 int ret;
1133 ret = krb5_store_int16(sp, p.addr_type);
1134 if(ret) return ret;
1135 ret = krb5_store_data(sp, p.address);
1136 return ret;
1137 }
1138
1139 /**
1140 * Read a address block from the storage.
1141 *
1142 * @param sp the storage buffer to write to
1143 * @param adr the address block read from storage
1144 *
1145 * @return 0 on success, a Kerberos 5 error code on failure.
1146 *
1147 * @ingroup krb5_storage
1148 */
1149
1150 KRB5_LIB_FUNCTION krb5_error_code KRB5_LIB_CALL
krb5_ret_address(krb5_storage * sp,krb5_address * adr)1151 krb5_ret_address(krb5_storage *sp, krb5_address *adr)
1152 {
1153 int16_t t;
1154 int ret;
1155 ret = krb5_ret_int16(sp, &t);
1156 if(ret) return ret;
1157 adr->addr_type = t;
1158 ret = krb5_ret_data(sp, &adr->address);
1159 return ret;
1160 }
1161
1162 /**
1163 * Write a addresses block to storage.
1164 *
1165 * @param sp the storage buffer to write to
1166 * @param p the addresses block to write.
1167 *
1168 * @return 0 on success, a Kerberos 5 error code on failure.
1169 *
1170 * @ingroup krb5_storage
1171 */
1172
1173 KRB5_LIB_FUNCTION krb5_error_code KRB5_LIB_CALL
krb5_store_addrs(krb5_storage * sp,krb5_addresses p)1174 krb5_store_addrs(krb5_storage *sp, krb5_addresses p)
1175 {
1176 size_t i;
1177 int ret;
1178 ret = krb5_store_int32(sp, p.len);
1179 if(ret) return ret;
1180 for(i = 0; i<p.len; i++){
1181 ret = krb5_store_address(sp, p.val[i]);
1182 if(ret) break;
1183 }
1184 return ret;
1185 }
1186
1187 /**
1188 * Read a addresses block from the storage.
1189 *
1190 * @param sp the storage buffer to write to
1191 * @param adr the addresses block read from storage
1192 *
1193 * @return 0 on success, a Kerberos 5 error code on failure.
1194 *
1195 * @ingroup krb5_storage
1196 */
1197
1198 KRB5_LIB_FUNCTION krb5_error_code KRB5_LIB_CALL
krb5_ret_addrs(krb5_storage * sp,krb5_addresses * adr)1199 krb5_ret_addrs(krb5_storage *sp, krb5_addresses *adr)
1200 {
1201 size_t i;
1202 int ret;
1203 int32_t tmp;
1204
1205 ret = krb5_ret_int32(sp, &tmp);
1206 if(ret) return ret;
1207 ret = size_too_large_num(sp, tmp, sizeof(adr->val[0]));
1208 if (ret) return ret;
1209 adr->len = tmp;
1210 ALLOC(adr->val, adr->len);
1211 if (adr->val == NULL && adr->len != 0)
1212 return ENOMEM;
1213 for(i = 0; i < adr->len; i++){
1214 ret = krb5_ret_address(sp, &adr->val[i]);
1215 if(ret) break;
1216 }
1217 return ret;
1218 }
1219
1220 /**
1221 * Write a auth data block to storage.
1222 *
1223 * @param sp the storage buffer to write to
1224 * @param auth the auth data block to write.
1225 *
1226 * @return 0 on success, a Kerberos 5 error code on failure.
1227 *
1228 * @ingroup krb5_storage
1229 */
1230
1231 KRB5_LIB_FUNCTION krb5_error_code KRB5_LIB_CALL
krb5_store_authdata(krb5_storage * sp,krb5_authdata auth)1232 krb5_store_authdata(krb5_storage *sp, krb5_authdata auth)
1233 {
1234 krb5_error_code ret;
1235 size_t i;
1236 ret = krb5_store_int32(sp, auth.len);
1237 if(ret) return ret;
1238 for(i = 0; i < auth.len; i++){
1239 ret = krb5_store_int16(sp, auth.val[i].ad_type);
1240 if(ret) break;
1241 ret = krb5_store_data(sp, auth.val[i].ad_data);
1242 if(ret) break;
1243 }
1244 return 0;
1245 }
1246
1247 /**
1248 * Read a auth data from the storage.
1249 *
1250 * @param sp the storage buffer to write to
1251 * @param auth the auth data block read from storage
1252 *
1253 * @return 0 on success, a Kerberos 5 error code on failure.
1254 *
1255 * @ingroup krb5_storage
1256 */
1257
1258 KRB5_LIB_FUNCTION krb5_error_code KRB5_LIB_CALL
krb5_ret_authdata(krb5_storage * sp,krb5_authdata * auth)1259 krb5_ret_authdata(krb5_storage *sp, krb5_authdata *auth)
1260 {
1261 krb5_error_code ret;
1262 int32_t tmp;
1263 int16_t tmp2;
1264 int i;
1265 ret = krb5_ret_int32(sp, &tmp);
1266 if(ret) return ret;
1267 ret = size_too_large_num(sp, tmp, sizeof(auth->val[0]));
1268 if (ret) return ret;
1269 ALLOC_SEQ(auth, tmp);
1270 if (auth->val == NULL && tmp != 0)
1271 return ENOMEM;
1272 for(i = 0; i < tmp; i++){
1273 ret = krb5_ret_int16(sp, &tmp2);
1274 if(ret) break;
1275 auth->val[i].ad_type = tmp2;
1276 ret = krb5_ret_data(sp, &auth->val[i].ad_data);
1277 if(ret) break;
1278 }
1279 return ret;
1280 }
1281
1282 static int32_t
bitswap32(int32_t b)1283 bitswap32(int32_t b)
1284 {
1285 int32_t r = 0;
1286 int i;
1287 for (i = 0; i < 32; i++) {
1288 r = r << 1 | (b & 1);
1289 b = b >> 1;
1290 }
1291 return r;
1292 }
1293
1294 /**
1295 * Write a credentials block to storage.
1296 *
1297 * @param sp the storage buffer to write to
1298 * @param creds the creds block to write.
1299 *
1300 * @return 0 on success, a Kerberos 5 error code on failure.
1301 *
1302 * @ingroup krb5_storage
1303 */
1304
1305 KRB5_LIB_FUNCTION krb5_error_code KRB5_LIB_CALL
krb5_store_creds(krb5_storage * sp,krb5_creds * creds)1306 krb5_store_creds(krb5_storage *sp, krb5_creds *creds)
1307 {
1308 int ret;
1309
1310 ret = krb5_store_principal(sp, creds->client);
1311 if(ret)
1312 return ret;
1313 ret = krb5_store_principal(sp, creds->server);
1314 if(ret)
1315 return ret;
1316 ret = krb5_store_keyblock(sp, creds->session);
1317 if(ret)
1318 return ret;
1319 ret = krb5_store_times(sp, creds->times);
1320 if(ret)
1321 return ret;
1322 ret = krb5_store_int8(sp, creds->second_ticket.length != 0); /* is_skey */
1323 if(ret)
1324 return ret;
1325
1326 if(krb5_storage_is_flags(sp, KRB5_STORAGE_CREDS_FLAGS_WRONG_BITORDER))
1327 ret = krb5_store_int32(sp, creds->flags.i);
1328 else
1329 ret = krb5_store_int32(sp, bitswap32(TicketFlags2int(creds->flags.b)));
1330 if(ret)
1331 return ret;
1332
1333 ret = krb5_store_addrs(sp, creds->addresses);
1334 if(ret)
1335 return ret;
1336 ret = krb5_store_authdata(sp, creds->authdata);
1337 if(ret)
1338 return ret;
1339 ret = krb5_store_data(sp, creds->ticket);
1340 if(ret)
1341 return ret;
1342 ret = krb5_store_data(sp, creds->second_ticket);
1343 return ret;
1344 }
1345
1346 /**
1347 * Read a credentials block from the storage.
1348 *
1349 * @param sp the storage buffer to write to
1350 * @param creds the credentials block read from storage
1351 *
1352 * @return 0 on success, a Kerberos 5 error code on failure.
1353 *
1354 * @ingroup krb5_storage
1355 */
1356
1357 KRB5_LIB_FUNCTION krb5_error_code KRB5_LIB_CALL
krb5_ret_creds(krb5_storage * sp,krb5_creds * creds)1358 krb5_ret_creds(krb5_storage *sp, krb5_creds *creds)
1359 {
1360 krb5_error_code ret;
1361 int8_t dummy8;
1362 int32_t dummy32;
1363
1364 memset(creds, 0, sizeof(*creds));
1365 ret = krb5_ret_principal (sp, &creds->client);
1366 if(ret) goto cleanup;
1367 ret = krb5_ret_principal (sp, &creds->server);
1368 if(ret) goto cleanup;
1369 ret = krb5_ret_keyblock (sp, &creds->session);
1370 if(ret) goto cleanup;
1371 ret = krb5_ret_times (sp, &creds->times);
1372 if(ret) goto cleanup;
1373 ret = krb5_ret_int8 (sp, &dummy8);
1374 if(ret) goto cleanup;
1375 ret = krb5_ret_int32 (sp, &dummy32);
1376 if(ret) goto cleanup;
1377 /*
1378 * Runtime detect the what is the higher bits of the bitfield. If
1379 * any of the higher bits are set in the input data, it's either a
1380 * new ticket flag (and this code need to be removed), or it's a
1381 * MIT cache (or new Heimdal cache), lets change it to our current
1382 * format.
1383 */
1384 {
1385 uint32_t mask = 0xffff0000;
1386 creds->flags.i = 0;
1387 creds->flags.b.anonymous = 1;
1388 if (creds->flags.i & mask)
1389 mask = ~mask;
1390 if (dummy32 & mask)
1391 dummy32 = bitswap32(dummy32);
1392 }
1393 creds->flags.i = dummy32;
1394 ret = krb5_ret_addrs (sp, &creds->addresses);
1395 if(ret) goto cleanup;
1396 ret = krb5_ret_authdata (sp, &creds->authdata);
1397 if(ret) goto cleanup;
1398 ret = krb5_ret_data (sp, &creds->ticket);
1399 if(ret) goto cleanup;
1400 ret = krb5_ret_data (sp, &creds->second_ticket);
1401 cleanup:
1402 if(ret) {
1403 #if 0
1404 krb5_free_cred_contents(context, creds); /* XXX */
1405 #endif
1406 }
1407 return ret;
1408 }
1409
1410 #define SC_CLIENT_PRINCIPAL 0x0001
1411 #define SC_SERVER_PRINCIPAL 0x0002
1412 #define SC_SESSION_KEY 0x0004
1413 #define SC_TICKET 0x0008
1414 #define SC_SECOND_TICKET 0x0010
1415 #define SC_AUTHDATA 0x0020
1416 #define SC_ADDRESSES 0x0040
1417
1418 /**
1419 * Write a tagged credentials block to storage.
1420 *
1421 * @param sp the storage buffer to write to
1422 * @param creds the creds block to write.
1423 *
1424 * @return 0 on success, a Kerberos 5 error code on failure.
1425 *
1426 * @ingroup krb5_storage
1427 */
1428
1429 KRB5_LIB_FUNCTION krb5_error_code KRB5_LIB_CALL
krb5_store_creds_tag(krb5_storage * sp,krb5_creds * creds)1430 krb5_store_creds_tag(krb5_storage *sp, krb5_creds *creds)
1431 {
1432 int ret;
1433 int32_t header = 0;
1434
1435 if (creds->client)
1436 header |= SC_CLIENT_PRINCIPAL;
1437 if (creds->server)
1438 header |= SC_SERVER_PRINCIPAL;
1439 if (creds->session.keytype != ETYPE_NULL)
1440 header |= SC_SESSION_KEY;
1441 if (creds->ticket.data)
1442 header |= SC_TICKET;
1443 if (creds->second_ticket.length)
1444 header |= SC_SECOND_TICKET;
1445 if (creds->authdata.len)
1446 header |= SC_AUTHDATA;
1447 if (creds->addresses.len)
1448 header |= SC_ADDRESSES;
1449
1450 ret = krb5_store_int32(sp, header);
1451 if (ret)
1452 return ret;
1453
1454 if (creds->client) {
1455 ret = krb5_store_principal(sp, creds->client);
1456 if(ret)
1457 return ret;
1458 }
1459
1460 if (creds->server) {
1461 ret = krb5_store_principal(sp, creds->server);
1462 if(ret)
1463 return ret;
1464 }
1465
1466 if (creds->session.keytype != ETYPE_NULL) {
1467 ret = krb5_store_keyblock(sp, creds->session);
1468 if(ret)
1469 return ret;
1470 }
1471
1472 ret = krb5_store_times(sp, creds->times);
1473 if(ret)
1474 return ret;
1475 ret = krb5_store_int8(sp, creds->second_ticket.length != 0); /* is_skey */
1476 if(ret)
1477 return ret;
1478
1479 ret = krb5_store_int32(sp, bitswap32(TicketFlags2int(creds->flags.b)));
1480 if(ret)
1481 return ret;
1482
1483 if (creds->addresses.len) {
1484 ret = krb5_store_addrs(sp, creds->addresses);
1485 if(ret)
1486 return ret;
1487 }
1488
1489 if (creds->authdata.len) {
1490 ret = krb5_store_authdata(sp, creds->authdata);
1491 if(ret)
1492 return ret;
1493 }
1494
1495 if (creds->ticket.data) {
1496 ret = krb5_store_data(sp, creds->ticket);
1497 if(ret)
1498 return ret;
1499 }
1500
1501 if (creds->second_ticket.data) {
1502 ret = krb5_store_data(sp, creds->second_ticket);
1503 if (ret)
1504 return ret;
1505 }
1506
1507 return ret;
1508 }
1509
1510 /**
1511 * Read a tagged credentials block from the storage.
1512 *
1513 * @param sp the storage buffer to write to
1514 * @param creds the credentials block read from storage
1515 *
1516 * @return 0 on success, a Kerberos 5 error code on failure.
1517 *
1518 * @ingroup krb5_storage
1519 */
1520
1521 KRB5_LIB_FUNCTION krb5_error_code KRB5_LIB_CALL
krb5_ret_creds_tag(krb5_storage * sp,krb5_creds * creds)1522 krb5_ret_creds_tag(krb5_storage *sp,
1523 krb5_creds *creds)
1524 {
1525 krb5_error_code ret;
1526 int8_t dummy8;
1527 int32_t dummy32, header;
1528
1529 memset(creds, 0, sizeof(*creds));
1530
1531 ret = krb5_ret_int32 (sp, &header);
1532 if (ret) goto cleanup;
1533
1534 if (header & SC_CLIENT_PRINCIPAL) {
1535 ret = krb5_ret_principal (sp, &creds->client);
1536 if(ret) goto cleanup;
1537 }
1538 if (header & SC_SERVER_PRINCIPAL) {
1539 ret = krb5_ret_principal (sp, &creds->server);
1540 if(ret) goto cleanup;
1541 }
1542 if (header & SC_SESSION_KEY) {
1543 ret = krb5_ret_keyblock (sp, &creds->session);
1544 if(ret) goto cleanup;
1545 }
1546 ret = krb5_ret_times (sp, &creds->times);
1547 if(ret) goto cleanup;
1548 ret = krb5_ret_int8 (sp, &dummy8);
1549 if(ret) goto cleanup;
1550 ret = krb5_ret_int32 (sp, &dummy32);
1551 if(ret) goto cleanup;
1552 /*
1553 * Runtime detect the what is the higher bits of the bitfield. If
1554 * any of the higher bits are set in the input data, it's either a
1555 * new ticket flag (and this code need to be removed), or it's a
1556 * MIT cache (or new Heimdal cache), lets change it to our current
1557 * format.
1558 */
1559 {
1560 uint32_t mask = 0xffff0000;
1561 creds->flags.i = 0;
1562 creds->flags.b.anonymous = 1;
1563 if (creds->flags.i & mask)
1564 mask = ~mask;
1565 if (dummy32 & mask)
1566 dummy32 = bitswap32(dummy32);
1567 }
1568 creds->flags.i = dummy32;
1569 if (header & SC_ADDRESSES) {
1570 ret = krb5_ret_addrs (sp, &creds->addresses);
1571 if(ret) goto cleanup;
1572 }
1573 if (header & SC_AUTHDATA) {
1574 ret = krb5_ret_authdata (sp, &creds->authdata);
1575 if(ret) goto cleanup;
1576 }
1577 if (header & SC_TICKET) {
1578 ret = krb5_ret_data (sp, &creds->ticket);
1579 if(ret) goto cleanup;
1580 }
1581 if (header & SC_SECOND_TICKET) {
1582 ret = krb5_ret_data (sp, &creds->second_ticket);
1583 if(ret) goto cleanup;
1584 }
1585
1586 cleanup:
1587 if(ret) {
1588 #if 0
1589 krb5_free_cred_contents(context, creds); /* XXX */
1590 #endif
1591 }
1592 return ret;
1593 }
1594