xref: /netbsd-src/crypto/external/bsd/heimdal/dist/lib/krb5/store.c (revision d3273b5b76f5afaafe308cead5511dbb8df8c5e9)
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