xref: /freebsd/crypto/heimdal/lib/krb5/store.c (revision 1c43270ada91f3473174c2bf81fba64963b7e4ac)
1b528cefcSMark Murray /*
28373020dSJacques Vidrine  * Copyright (c) 1997-2002 Kungliga Tekniska H�gskolan
3b528cefcSMark Murray  * (Royal Institute of Technology, Stockholm, Sweden).
4b528cefcSMark Murray  * All rights reserved.
5b528cefcSMark Murray  *
6b528cefcSMark Murray  * Redistribution and use in source and binary forms, with or without
7b528cefcSMark Murray  * modification, are permitted provided that the following conditions
8b528cefcSMark Murray  * are met:
9b528cefcSMark Murray  *
10b528cefcSMark Murray  * 1. Redistributions of source code must retain the above copyright
11b528cefcSMark Murray  *    notice, this list of conditions and the following disclaimer.
12b528cefcSMark Murray  *
13b528cefcSMark Murray  * 2. Redistributions in binary form must reproduce the above copyright
14b528cefcSMark Murray  *    notice, this list of conditions and the following disclaimer in the
15b528cefcSMark Murray  *    documentation and/or other materials provided with the distribution.
16b528cefcSMark Murray  *
17b528cefcSMark Murray  * 3. Neither the name of the Institute nor the names of its contributors
18b528cefcSMark Murray  *    may be used to endorse or promote products derived from this software
19b528cefcSMark Murray  *    without specific prior written permission.
20b528cefcSMark Murray  *
21b528cefcSMark Murray  * THIS SOFTWARE IS PROVIDED BY THE INSTITUTE AND CONTRIBUTORS ``AS IS'' AND
22b528cefcSMark Murray  * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
23b528cefcSMark Murray  * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
24b528cefcSMark Murray  * ARE DISCLAIMED.  IN NO EVENT SHALL THE INSTITUTE OR CONTRIBUTORS BE LIABLE
25b528cefcSMark Murray  * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
26b528cefcSMark Murray  * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
27b528cefcSMark Murray  * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
28b528cefcSMark Murray  * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
29b528cefcSMark Murray  * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
30b528cefcSMark Murray  * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
31b528cefcSMark Murray  * SUCH DAMAGE.
32b528cefcSMark Murray  */
33b528cefcSMark Murray 
34b528cefcSMark Murray #include "krb5_locl.h"
358373020dSJacques Vidrine #include "store-int.h"
36b528cefcSMark Murray 
371c43270aSJacques Vidrine RCSID("$Id: store.c,v 1.38.4.1 2004/03/09 19:32:14 lha Exp $");
38adb0ddaeSAssar Westerlund 
39adb0ddaeSAssar Westerlund #define BYTEORDER_IS(SP, V) (((SP)->flags & KRB5_STORAGE_BYTEORDER_MASK) == (V))
40adb0ddaeSAssar Westerlund #define BYTEORDER_IS_LE(SP) BYTEORDER_IS((SP), KRB5_STORAGE_BYTEORDER_LE)
41adb0ddaeSAssar Westerlund #define BYTEORDER_IS_BE(SP) BYTEORDER_IS((SP), KRB5_STORAGE_BYTEORDER_BE)
42adb0ddaeSAssar Westerlund #define BYTEORDER_IS_HOST(SP) (BYTEORDER_IS((SP), KRB5_STORAGE_BYTEORDER_HOST) || \
43adb0ddaeSAssar Westerlund 			       krb5_storage_is_flags((SP), KRB5_STORAGE_HOST_BYTEORDER))
44b528cefcSMark Murray 
45b528cefcSMark Murray void
46b528cefcSMark Murray krb5_storage_set_flags(krb5_storage *sp, krb5_flags flags)
47b528cefcSMark Murray {
48b528cefcSMark Murray     sp->flags |= flags;
49b528cefcSMark Murray }
50b528cefcSMark Murray 
51b528cefcSMark Murray void
52b528cefcSMark Murray krb5_storage_clear_flags(krb5_storage *sp, krb5_flags flags)
53b528cefcSMark Murray {
54b528cefcSMark Murray     sp->flags &= ~flags;
55b528cefcSMark Murray }
56b528cefcSMark Murray 
57b528cefcSMark Murray krb5_boolean
58b528cefcSMark Murray krb5_storage_is_flags(krb5_storage *sp, krb5_flags flags)
59b528cefcSMark Murray {
60b528cefcSMark Murray     return (sp->flags & flags) == flags;
61b528cefcSMark Murray }
62b528cefcSMark Murray 
63adb0ddaeSAssar Westerlund void
64adb0ddaeSAssar Westerlund krb5_storage_set_byteorder(krb5_storage *sp, krb5_flags byteorder)
65adb0ddaeSAssar Westerlund {
66adb0ddaeSAssar Westerlund     sp->flags &= ~KRB5_STORAGE_BYTEORDER_MASK;
67adb0ddaeSAssar Westerlund     sp->flags |= byteorder;
68adb0ddaeSAssar Westerlund }
69adb0ddaeSAssar Westerlund 
70adb0ddaeSAssar Westerlund krb5_flags
71adb0ddaeSAssar Westerlund krb5_storage_get_byteorder(krb5_storage *sp, krb5_flags byteorder)
72adb0ddaeSAssar Westerlund {
73adb0ddaeSAssar Westerlund     return sp->flags & KRB5_STORAGE_BYTEORDER_MASK;
74adb0ddaeSAssar Westerlund }
75adb0ddaeSAssar Westerlund 
768373020dSJacques Vidrine off_t
778373020dSJacques Vidrine krb5_storage_seek(krb5_storage *sp, off_t offset, int whence)
788373020dSJacques Vidrine {
798373020dSJacques Vidrine     return (*sp->seek)(sp, offset, whence);
808373020dSJacques Vidrine }
81adb0ddaeSAssar Westerlund 
828373020dSJacques Vidrine krb5_ssize_t
838373020dSJacques Vidrine krb5_storage_read(krb5_storage *sp, void *buf, size_t len)
848373020dSJacques Vidrine {
858373020dSJacques Vidrine     return sp->fetch(sp, buf, len);
868373020dSJacques Vidrine }
878373020dSJacques Vidrine 
888373020dSJacques Vidrine krb5_ssize_t
898373020dSJacques Vidrine krb5_storage_write(krb5_storage *sp, const void *buf, size_t len)
908373020dSJacques Vidrine {
918373020dSJacques Vidrine     return sp->store(sp, buf, len);
928373020dSJacques Vidrine }
938373020dSJacques Vidrine 
948373020dSJacques Vidrine void
958373020dSJacques Vidrine krb5_storage_set_eof_code(krb5_storage *sp, int code)
968373020dSJacques Vidrine {
978373020dSJacques Vidrine     sp->eof_code = code;
988373020dSJacques Vidrine }
998373020dSJacques Vidrine 
1008373020dSJacques Vidrine krb5_ssize_t
101b528cefcSMark Murray _krb5_put_int(void *buffer, unsigned long value, size_t size)
102b528cefcSMark Murray {
103b528cefcSMark Murray     unsigned char *p = buffer;
104b528cefcSMark Murray     int i;
105b528cefcSMark Murray     for (i = size - 1; i >= 0; i--) {
106b528cefcSMark Murray 	p[i] = value & 0xff;
107b528cefcSMark Murray 	value >>= 8;
108b528cefcSMark Murray     }
109b528cefcSMark Murray     return size;
110b528cefcSMark Murray }
111b528cefcSMark Murray 
1128373020dSJacques Vidrine krb5_ssize_t
113b528cefcSMark Murray _krb5_get_int(void *buffer, unsigned long *value, size_t size)
114b528cefcSMark Murray {
115b528cefcSMark Murray     unsigned char *p = buffer;
116b528cefcSMark Murray     unsigned long v = 0;
117b528cefcSMark Murray     int i;
118b528cefcSMark Murray     for (i = 0; i < size; i++)
119b528cefcSMark Murray 	v = (v << 8) + p[i];
120b528cefcSMark Murray     *value = v;
121b528cefcSMark Murray     return size;
122b528cefcSMark Murray }
123b528cefcSMark Murray 
124b528cefcSMark Murray krb5_error_code
125b528cefcSMark Murray krb5_storage_free(krb5_storage *sp)
126b528cefcSMark Murray {
127b528cefcSMark Murray     if(sp->free)
128b528cefcSMark Murray 	(*sp->free)(sp);
129b528cefcSMark Murray     free(sp->data);
130b528cefcSMark Murray     free(sp);
131b528cefcSMark Murray     return 0;
132b528cefcSMark Murray }
133b528cefcSMark Murray 
134b528cefcSMark Murray krb5_error_code
135b528cefcSMark Murray krb5_storage_to_data(krb5_storage *sp, krb5_data *data)
136b528cefcSMark Murray {
137b528cefcSMark Murray     off_t pos;
138b528cefcSMark Murray     size_t size;
139b528cefcSMark Murray     krb5_error_code ret;
140b528cefcSMark Murray 
141b528cefcSMark Murray     pos = sp->seek(sp, 0, SEEK_CUR);
142b528cefcSMark Murray     size = (size_t)sp->seek(sp, 0, SEEK_END);
143b528cefcSMark Murray     ret = krb5_data_alloc (data, size);
144b528cefcSMark Murray     if (ret) {
145b528cefcSMark Murray 	sp->seek(sp, pos, SEEK_SET);
146b528cefcSMark Murray 	return ret;
147b528cefcSMark Murray     }
148b528cefcSMark Murray     if (size) {
149b528cefcSMark Murray 	sp->seek(sp, 0, SEEK_SET);
150b528cefcSMark Murray 	sp->fetch(sp, data->data, data->length);
151b528cefcSMark Murray 	sp->seek(sp, pos, SEEK_SET);
152b528cefcSMark Murray     }
153b528cefcSMark Murray     return 0;
154b528cefcSMark Murray }
155b528cefcSMark Murray 
156b528cefcSMark Murray static krb5_error_code
157b528cefcSMark Murray krb5_store_int(krb5_storage *sp,
158b528cefcSMark Murray 	       int32_t value,
159b528cefcSMark Murray 	       size_t len)
160b528cefcSMark Murray {
161b528cefcSMark Murray     int ret;
162adb0ddaeSAssar Westerlund     unsigned char v[16];
163b528cefcSMark Murray 
164adb0ddaeSAssar Westerlund     if(len > sizeof(v))
165adb0ddaeSAssar Westerlund 	return EINVAL;
166b528cefcSMark Murray     _krb5_put_int(v, value, len);
167b528cefcSMark Murray     ret = sp->store(sp, v, len);
168b528cefcSMark Murray     if (ret != len)
1698373020dSJacques Vidrine 	return (ret<0)?errno:sp->eof_code;
170b528cefcSMark Murray     return 0;
171b528cefcSMark Murray }
172b528cefcSMark Murray 
173b528cefcSMark Murray krb5_error_code
174b528cefcSMark Murray krb5_store_int32(krb5_storage *sp,
175b528cefcSMark Murray 		 int32_t value)
176b528cefcSMark Murray {
177adb0ddaeSAssar Westerlund     if(BYTEORDER_IS_HOST(sp))
178b528cefcSMark Murray 	value = htonl(value);
179adb0ddaeSAssar Westerlund     else if(BYTEORDER_IS_LE(sp))
180adb0ddaeSAssar Westerlund 	value = bswap32(value);
181b528cefcSMark Murray     return krb5_store_int(sp, value, 4);
182b528cefcSMark Murray }
183b528cefcSMark Murray 
184b528cefcSMark Murray static krb5_error_code
185b528cefcSMark Murray krb5_ret_int(krb5_storage *sp,
186b528cefcSMark Murray 	     int32_t *value,
187b528cefcSMark Murray 	     size_t len)
188b528cefcSMark Murray {
189b528cefcSMark Murray     int ret;
190b528cefcSMark Murray     unsigned char v[4];
191b528cefcSMark Murray     unsigned long w;
192b528cefcSMark Murray     ret = sp->fetch(sp, v, len);
193b528cefcSMark Murray     if(ret != len)
1948373020dSJacques Vidrine 	return (ret<0)?errno:sp->eof_code;
195b528cefcSMark Murray     _krb5_get_int(v, &w, len);
196b528cefcSMark Murray     *value = w;
197b528cefcSMark Murray     return 0;
198b528cefcSMark Murray }
199b528cefcSMark Murray 
200b528cefcSMark Murray krb5_error_code
201b528cefcSMark Murray krb5_ret_int32(krb5_storage *sp,
202b528cefcSMark Murray 	       int32_t *value)
203b528cefcSMark Murray {
204b528cefcSMark Murray     krb5_error_code ret = krb5_ret_int(sp, value, 4);
205b528cefcSMark Murray     if(ret)
206b528cefcSMark Murray 	return ret;
207adb0ddaeSAssar Westerlund     if(BYTEORDER_IS_HOST(sp))
208adb0ddaeSAssar Westerlund 	*value = htonl(*value);
209adb0ddaeSAssar Westerlund     else if(BYTEORDER_IS_LE(sp))
210adb0ddaeSAssar Westerlund 	*value = bswap32(*value);
211b528cefcSMark Murray     return 0;
212b528cefcSMark Murray }
213b528cefcSMark Murray 
214b528cefcSMark Murray krb5_error_code
215b528cefcSMark Murray krb5_store_int16(krb5_storage *sp,
216b528cefcSMark Murray 		 int16_t value)
217b528cefcSMark Murray {
218adb0ddaeSAssar Westerlund     if(BYTEORDER_IS_HOST(sp))
219b528cefcSMark Murray 	value = htons(value);
220adb0ddaeSAssar Westerlund     else if(BYTEORDER_IS_LE(sp))
221adb0ddaeSAssar Westerlund 	value = bswap16(value);
222b528cefcSMark Murray     return krb5_store_int(sp, value, 2);
223b528cefcSMark Murray }
224b528cefcSMark Murray 
225b528cefcSMark Murray krb5_error_code
226b528cefcSMark Murray krb5_ret_int16(krb5_storage *sp,
227b528cefcSMark Murray 	       int16_t *value)
228b528cefcSMark Murray {
229b528cefcSMark Murray     int32_t v;
230b528cefcSMark Murray     int ret;
231b528cefcSMark Murray     ret = krb5_ret_int(sp, &v, 2);
232b528cefcSMark Murray     if(ret)
233b528cefcSMark Murray 	return ret;
234b528cefcSMark Murray     *value = v;
235adb0ddaeSAssar Westerlund     if(BYTEORDER_IS_HOST(sp))
236adb0ddaeSAssar Westerlund 	*value = htons(*value);
237adb0ddaeSAssar Westerlund     else if(BYTEORDER_IS_LE(sp))
238adb0ddaeSAssar Westerlund 	*value = bswap16(*value);
239b528cefcSMark Murray     return 0;
240b528cefcSMark Murray }
241b528cefcSMark Murray 
242b528cefcSMark Murray krb5_error_code
243b528cefcSMark Murray krb5_store_int8(krb5_storage *sp,
244b528cefcSMark Murray 		int8_t value)
245b528cefcSMark Murray {
246b528cefcSMark Murray     int ret;
247b528cefcSMark Murray 
248b528cefcSMark Murray     ret = sp->store(sp, &value, sizeof(value));
249b528cefcSMark Murray     if (ret != sizeof(value))
2508373020dSJacques Vidrine 	return (ret<0)?errno:sp->eof_code;
251b528cefcSMark Murray     return 0;
252b528cefcSMark Murray }
253b528cefcSMark Murray 
254b528cefcSMark Murray krb5_error_code
255b528cefcSMark Murray krb5_ret_int8(krb5_storage *sp,
256b528cefcSMark Murray 	      int8_t *value)
257b528cefcSMark Murray {
258b528cefcSMark Murray     int ret;
259b528cefcSMark Murray 
260b528cefcSMark Murray     ret = sp->fetch(sp, value, sizeof(*value));
261b528cefcSMark Murray     if (ret != sizeof(*value))
2628373020dSJacques Vidrine 	return (ret<0)?errno:sp->eof_code;
263b528cefcSMark Murray     return 0;
264b528cefcSMark Murray }
265b528cefcSMark Murray 
266b528cefcSMark Murray krb5_error_code
267b528cefcSMark Murray krb5_store_data(krb5_storage *sp,
268b528cefcSMark Murray 		krb5_data data)
269b528cefcSMark Murray {
270b528cefcSMark Murray     int ret;
271b528cefcSMark Murray     ret = krb5_store_int32(sp, data.length);
272b528cefcSMark Murray     if(ret < 0)
273b528cefcSMark Murray 	return ret;
274b528cefcSMark Murray     ret = sp->store(sp, data.data, data.length);
275b528cefcSMark Murray     if(ret != data.length){
276b528cefcSMark Murray 	if(ret < 0)
277b528cefcSMark Murray 	    return errno;
2788373020dSJacques Vidrine 	return sp->eof_code;
279b528cefcSMark Murray     }
280b528cefcSMark Murray     return 0;
281b528cefcSMark Murray }
282b528cefcSMark Murray 
283b528cefcSMark Murray krb5_error_code
284b528cefcSMark Murray krb5_ret_data(krb5_storage *sp,
285b528cefcSMark Murray 	      krb5_data *data)
286b528cefcSMark Murray {
287b528cefcSMark Murray     int ret;
288b528cefcSMark Murray     int32_t size;
289b528cefcSMark Murray 
290b528cefcSMark Murray     ret = krb5_ret_int32(sp, &size);
291b528cefcSMark Murray     if(ret)
292b528cefcSMark Murray 	return ret;
293b528cefcSMark Murray     ret = krb5_data_alloc (data, size);
294b528cefcSMark Murray     if (ret)
295b528cefcSMark Murray 	return ret;
296b528cefcSMark Murray     if (size) {
297b528cefcSMark Murray 	ret = sp->fetch(sp, data->data, size);
298b528cefcSMark Murray 	if(ret != size)
2998373020dSJacques Vidrine 	    return (ret < 0)? errno : sp->eof_code;
300b528cefcSMark Murray     }
301b528cefcSMark Murray     return 0;
302b528cefcSMark Murray }
303b528cefcSMark Murray 
304b528cefcSMark Murray krb5_error_code
305b528cefcSMark Murray krb5_store_string(krb5_storage *sp, const char *s)
306b528cefcSMark Murray {
307b528cefcSMark Murray     krb5_data data;
308b528cefcSMark Murray     data.length = strlen(s);
309b528cefcSMark Murray     data.data = (void*)s;
310b528cefcSMark Murray     return krb5_store_data(sp, data);
311b528cefcSMark Murray }
312b528cefcSMark Murray 
313b528cefcSMark Murray krb5_error_code
314b528cefcSMark Murray krb5_ret_string(krb5_storage *sp,
315b528cefcSMark Murray 		char **string)
316b528cefcSMark Murray {
317b528cefcSMark Murray     int ret;
318b528cefcSMark Murray     krb5_data data;
319b528cefcSMark Murray     ret = krb5_ret_data(sp, &data);
320b528cefcSMark Murray     if(ret)
321b528cefcSMark Murray 	return ret;
322b528cefcSMark Murray     *string = realloc(data.data, data.length + 1);
323b528cefcSMark Murray     if(*string == NULL){
324b528cefcSMark Murray 	free(data.data);
325b528cefcSMark Murray 	return ENOMEM;
326b528cefcSMark Murray     }
327b528cefcSMark Murray     (*string)[data.length] = 0;
328b528cefcSMark Murray     return 0;
329b528cefcSMark Murray }
330b528cefcSMark Murray 
331b528cefcSMark Murray krb5_error_code
3325e9cd1aeSAssar Westerlund krb5_store_stringz(krb5_storage *sp, const char *s)
333b528cefcSMark Murray {
334b528cefcSMark Murray     size_t len = strlen(s) + 1;
335b528cefcSMark Murray     ssize_t ret;
336b528cefcSMark Murray 
337b528cefcSMark Murray     ret = sp->store(sp, s, len);
338b528cefcSMark Murray     if(ret != len) {
339b528cefcSMark Murray 	if(ret < 0)
340b528cefcSMark Murray 	    return ret;
341b528cefcSMark Murray 	else
3428373020dSJacques Vidrine 	    return sp->eof_code;
343b528cefcSMark Murray     }
344b528cefcSMark Murray     return 0;
345b528cefcSMark Murray }
346b528cefcSMark Murray 
347b528cefcSMark Murray krb5_error_code
348b528cefcSMark Murray krb5_ret_stringz(krb5_storage *sp,
349b528cefcSMark Murray 		char **string)
350b528cefcSMark Murray {
351b528cefcSMark Murray     char c;
352b528cefcSMark Murray     char *s = NULL;
353b528cefcSMark Murray     size_t len = 0;
354b528cefcSMark Murray     ssize_t ret;
355b528cefcSMark Murray 
356b528cefcSMark Murray     while((ret = sp->fetch(sp, &c, 1)) == 1){
357b528cefcSMark Murray 	char *tmp;
358b528cefcSMark Murray 
359b528cefcSMark Murray 	len++;
360b528cefcSMark Murray 	tmp = realloc (s, len);
361b528cefcSMark Murray 	if (tmp == NULL) {
362b528cefcSMark Murray 	    free (s);
363b528cefcSMark Murray 	    return ENOMEM;
364b528cefcSMark Murray 	}
365b528cefcSMark Murray 	s = tmp;
366b528cefcSMark Murray 	s[len - 1] = c;
367b528cefcSMark Murray 	if(c == 0)
368b528cefcSMark Murray 	    break;
369b528cefcSMark Murray     }
370b528cefcSMark Murray     if(ret != 1){
371b528cefcSMark Murray 	free(s);
372b528cefcSMark Murray 	if(ret == 0)
3738373020dSJacques Vidrine 	    return sp->eof_code;
374b528cefcSMark Murray 	return ret;
375b528cefcSMark Murray     }
376b528cefcSMark Murray     *string = s;
377b528cefcSMark Murray     return 0;
378b528cefcSMark Murray }
379b528cefcSMark Murray 
380b528cefcSMark Murray 
381b528cefcSMark Murray krb5_error_code
382b528cefcSMark Murray krb5_store_principal(krb5_storage *sp,
383b528cefcSMark Murray 		     krb5_principal p)
384b528cefcSMark Murray {
385b528cefcSMark Murray     int i;
386b528cefcSMark Murray     int ret;
387b528cefcSMark Murray 
388b528cefcSMark Murray     if(!krb5_storage_is_flags(sp, KRB5_STORAGE_PRINCIPAL_NO_NAME_TYPE)) {
389b528cefcSMark Murray     ret = krb5_store_int32(sp, p->name.name_type);
390b528cefcSMark Murray     if(ret) return ret;
391b528cefcSMark Murray     }
392b528cefcSMark Murray     if(krb5_storage_is_flags(sp, KRB5_STORAGE_PRINCIPAL_WRONG_NUM_COMPONENTS))
393b528cefcSMark Murray 	ret = krb5_store_int32(sp, p->name.name_string.len + 1);
394b528cefcSMark Murray     else
395b528cefcSMark Murray     ret = krb5_store_int32(sp, p->name.name_string.len);
396b528cefcSMark Murray 
397b528cefcSMark Murray     if(ret) return ret;
398b528cefcSMark Murray     ret = krb5_store_string(sp, p->realm);
399b528cefcSMark Murray     if(ret) return ret;
400b528cefcSMark Murray     for(i = 0; i < p->name.name_string.len; i++){
401b528cefcSMark Murray 	ret = krb5_store_string(sp, p->name.name_string.val[i]);
402b528cefcSMark Murray 	if(ret) return ret;
403b528cefcSMark Murray     }
404b528cefcSMark Murray     return 0;
405b528cefcSMark Murray }
406b528cefcSMark Murray 
407b528cefcSMark Murray krb5_error_code
408b528cefcSMark Murray krb5_ret_principal(krb5_storage *sp,
409b528cefcSMark Murray 		   krb5_principal *princ)
410b528cefcSMark Murray {
411b528cefcSMark Murray     int i;
412b528cefcSMark Murray     int ret;
413b528cefcSMark Murray     krb5_principal p;
414b528cefcSMark Murray     int32_t type;
415b528cefcSMark Murray     int32_t ncomp;
416b528cefcSMark Murray 
417b528cefcSMark Murray     p = calloc(1, sizeof(*p));
418b528cefcSMark Murray     if(p == NULL)
419b528cefcSMark Murray 	return ENOMEM;
420b528cefcSMark Murray 
421b528cefcSMark Murray     if(krb5_storage_is_flags(sp, KRB5_STORAGE_PRINCIPAL_NO_NAME_TYPE))
422b528cefcSMark Murray 	type = KRB5_NT_UNKNOWN;
423b528cefcSMark Murray     else 	if((ret = krb5_ret_int32(sp, &type))){
424b528cefcSMark Murray 	free(p);
425b528cefcSMark Murray 	return ret;
426b528cefcSMark Murray     }
427b528cefcSMark Murray     if((ret = krb5_ret_int32(sp, &ncomp))){
428b528cefcSMark Murray 	free(p);
429b528cefcSMark Murray 	return ret;
430b528cefcSMark Murray     }
431b528cefcSMark Murray     if(krb5_storage_is_flags(sp, KRB5_STORAGE_PRINCIPAL_WRONG_NUM_COMPONENTS))
432b528cefcSMark Murray 	ncomp--;
433b528cefcSMark Murray     p->name.name_type = type;
434b528cefcSMark Murray     p->name.name_string.len = ncomp;
435b528cefcSMark Murray     ret = krb5_ret_string(sp, &p->realm);
436b528cefcSMark Murray     if(ret) return ret;
437b528cefcSMark Murray     p->name.name_string.val = calloc(ncomp, sizeof(*p->name.name_string.val));
438b528cefcSMark Murray     if(p->name.name_string.val == NULL){
439b528cefcSMark Murray 	free(p->realm);
440b528cefcSMark Murray 	return ENOMEM;
441b528cefcSMark Murray     }
442b528cefcSMark Murray     for(i = 0; i < ncomp; i++){
443b528cefcSMark Murray 	ret = krb5_ret_string(sp, &p->name.name_string.val[i]);
444b528cefcSMark Murray 	if(ret) return ret; /* XXX */
445b528cefcSMark Murray     }
446b528cefcSMark Murray     *princ = p;
447b528cefcSMark Murray     return 0;
448b528cefcSMark Murray }
449b528cefcSMark Murray 
450b528cefcSMark Murray krb5_error_code
451b528cefcSMark Murray krb5_store_keyblock(krb5_storage *sp, krb5_keyblock p)
452b528cefcSMark Murray {
453b528cefcSMark Murray     int ret;
454b528cefcSMark Murray     ret = krb5_store_int16(sp, p.keytype);
455b528cefcSMark Murray     if(ret) return ret;
456b528cefcSMark Murray 
457b528cefcSMark Murray     if(krb5_storage_is_flags(sp, KRB5_STORAGE_KEYBLOCK_KEYTYPE_TWICE)){
458b528cefcSMark Murray 	/* this should really be enctype, but it is the same as
459b528cefcSMark Murray            keytype nowadays */
460b528cefcSMark Murray     ret = krb5_store_int16(sp, p.keytype);
461b528cefcSMark Murray     if(ret) return ret;
462b528cefcSMark Murray     }
463b528cefcSMark Murray 
464b528cefcSMark Murray     ret = krb5_store_data(sp, p.keyvalue);
465b528cefcSMark Murray     return ret;
466b528cefcSMark Murray }
467b528cefcSMark Murray 
468b528cefcSMark Murray krb5_error_code
469b528cefcSMark Murray krb5_ret_keyblock(krb5_storage *sp, krb5_keyblock *p)
470b528cefcSMark Murray {
471b528cefcSMark Murray     int ret;
472b528cefcSMark Murray     int16_t tmp;
473b528cefcSMark Murray 
474b528cefcSMark Murray     ret = krb5_ret_int16(sp, &tmp);
475b528cefcSMark Murray     if(ret) return ret;
476b528cefcSMark Murray     p->keytype = tmp;
477b528cefcSMark Murray 
478b528cefcSMark Murray     if(krb5_storage_is_flags(sp, KRB5_STORAGE_KEYBLOCK_KEYTYPE_TWICE)){
479b528cefcSMark Murray     ret = krb5_ret_int16(sp, &tmp);
480b528cefcSMark Murray     if(ret) return ret;
481b528cefcSMark Murray     }
482b528cefcSMark Murray 
483b528cefcSMark Murray     ret = krb5_ret_data(sp, &p->keyvalue);
484b528cefcSMark Murray     return ret;
485b528cefcSMark Murray }
486b528cefcSMark Murray 
487b528cefcSMark Murray krb5_error_code
488b528cefcSMark Murray krb5_store_times(krb5_storage *sp, krb5_times times)
489b528cefcSMark Murray {
490b528cefcSMark Murray     int ret;
491b528cefcSMark Murray     ret = krb5_store_int32(sp, times.authtime);
492b528cefcSMark Murray     if(ret) return ret;
493b528cefcSMark Murray     ret = krb5_store_int32(sp, times.starttime);
494b528cefcSMark Murray     if(ret) return ret;
495b528cefcSMark Murray     ret = krb5_store_int32(sp, times.endtime);
496b528cefcSMark Murray     if(ret) return ret;
497b528cefcSMark Murray     ret = krb5_store_int32(sp, times.renew_till);
498b528cefcSMark Murray     return ret;
499b528cefcSMark Murray }
500b528cefcSMark Murray 
501b528cefcSMark Murray krb5_error_code
502b528cefcSMark Murray krb5_ret_times(krb5_storage *sp, krb5_times *times)
503b528cefcSMark Murray {
504b528cefcSMark Murray     int ret;
505b528cefcSMark Murray     int32_t tmp;
506b528cefcSMark Murray     ret = krb5_ret_int32(sp, &tmp);
507b528cefcSMark Murray     times->authtime = tmp;
508b528cefcSMark Murray     if(ret) return ret;
509b528cefcSMark Murray     ret = krb5_ret_int32(sp, &tmp);
510b528cefcSMark Murray     times->starttime = tmp;
511b528cefcSMark Murray     if(ret) return ret;
512b528cefcSMark Murray     ret = krb5_ret_int32(sp, &tmp);
513b528cefcSMark Murray     times->endtime = tmp;
514b528cefcSMark Murray     if(ret) return ret;
515b528cefcSMark Murray     ret = krb5_ret_int32(sp, &tmp);
516b528cefcSMark Murray     times->renew_till = tmp;
517b528cefcSMark Murray     return ret;
518b528cefcSMark Murray }
519b528cefcSMark Murray 
520b528cefcSMark Murray krb5_error_code
521b528cefcSMark Murray krb5_store_address(krb5_storage *sp, krb5_address p)
522b528cefcSMark Murray {
523b528cefcSMark Murray     int ret;
524b528cefcSMark Murray     ret = krb5_store_int16(sp, p.addr_type);
525b528cefcSMark Murray     if(ret) return ret;
526b528cefcSMark Murray     ret = krb5_store_data(sp, p.address);
527b528cefcSMark Murray     return ret;
528b528cefcSMark Murray }
529b528cefcSMark Murray 
530b528cefcSMark Murray krb5_error_code
531b528cefcSMark Murray krb5_ret_address(krb5_storage *sp, krb5_address *adr)
532b528cefcSMark Murray {
533b528cefcSMark Murray     int16_t t;
534b528cefcSMark Murray     int ret;
535b528cefcSMark Murray     ret = krb5_ret_int16(sp, &t);
536b528cefcSMark Murray     if(ret) return ret;
537b528cefcSMark Murray     adr->addr_type = t;
538b528cefcSMark Murray     ret = krb5_ret_data(sp, &adr->address);
539b528cefcSMark Murray     return ret;
540b528cefcSMark Murray }
541b528cefcSMark Murray 
542b528cefcSMark Murray krb5_error_code
543b528cefcSMark Murray krb5_store_addrs(krb5_storage *sp, krb5_addresses p)
544b528cefcSMark Murray {
545b528cefcSMark Murray     int i;
546b528cefcSMark Murray     int ret;
547b528cefcSMark Murray     ret = krb5_store_int32(sp, p.len);
548b528cefcSMark Murray     if(ret) return ret;
549b528cefcSMark Murray     for(i = 0; i<p.len; i++){
550b528cefcSMark Murray 	ret = krb5_store_address(sp, p.val[i]);
551b528cefcSMark Murray 	if(ret) break;
552b528cefcSMark Murray     }
553b528cefcSMark Murray     return ret;
554b528cefcSMark Murray }
555b528cefcSMark Murray 
556b528cefcSMark Murray krb5_error_code
557b528cefcSMark Murray krb5_ret_addrs(krb5_storage *sp, krb5_addresses *adr)
558b528cefcSMark Murray {
559b528cefcSMark Murray     int i;
560b528cefcSMark Murray     int ret;
561b528cefcSMark Murray     int32_t tmp;
562b528cefcSMark Murray 
563b528cefcSMark Murray     ret = krb5_ret_int32(sp, &tmp);
564b528cefcSMark Murray     if(ret) return ret;
565b528cefcSMark Murray     adr->len = tmp;
566b528cefcSMark Murray     ALLOC(adr->val, adr->len);
567b528cefcSMark Murray     for(i = 0; i < adr->len; i++){
568b528cefcSMark Murray 	ret = krb5_ret_address(sp, &adr->val[i]);
569b528cefcSMark Murray 	if(ret) break;
570b528cefcSMark Murray     }
571b528cefcSMark Murray     return ret;
572b528cefcSMark Murray }
573b528cefcSMark Murray 
574b528cefcSMark Murray krb5_error_code
575b528cefcSMark Murray krb5_store_authdata(krb5_storage *sp, krb5_authdata auth)
576b528cefcSMark Murray {
577b528cefcSMark Murray     krb5_error_code ret;
578b528cefcSMark Murray     int i;
579b528cefcSMark Murray     ret = krb5_store_int32(sp, auth.len);
580b528cefcSMark Murray     if(ret) return ret;
581b528cefcSMark Murray     for(i = 0; i < auth.len; i++){
582b528cefcSMark Murray 	ret = krb5_store_int16(sp, auth.val[i].ad_type);
583b528cefcSMark Murray 	if(ret) break;
584b528cefcSMark Murray 	ret = krb5_store_data(sp, auth.val[i].ad_data);
585b528cefcSMark Murray 	if(ret) break;
586b528cefcSMark Murray     }
587b528cefcSMark Murray     return 0;
588b528cefcSMark Murray }
589b528cefcSMark Murray 
590b528cefcSMark Murray krb5_error_code
591b528cefcSMark Murray krb5_ret_authdata(krb5_storage *sp, krb5_authdata *auth)
592b528cefcSMark Murray {
593b528cefcSMark Murray     krb5_error_code ret;
594b528cefcSMark Murray     int32_t tmp;
595b528cefcSMark Murray     int16_t tmp2;
596b528cefcSMark Murray     int i;
597b528cefcSMark Murray     ret = krb5_ret_int32(sp, &tmp);
598b528cefcSMark Murray     if(ret) return ret;
599b528cefcSMark Murray     ALLOC_SEQ(auth, tmp);
600b528cefcSMark Murray     for(i = 0; i < tmp; i++){
601b528cefcSMark Murray 	ret = krb5_ret_int16(sp, &tmp2);
602b528cefcSMark Murray 	if(ret) break;
603b528cefcSMark Murray 	auth->val[i].ad_type = tmp2;
604b528cefcSMark Murray 	ret = krb5_ret_data(sp, &auth->val[i].ad_data);
605b528cefcSMark Murray 	if(ret) break;
606b528cefcSMark Murray     }
607b528cefcSMark Murray     return ret;
608b528cefcSMark Murray }
609b528cefcSMark Murray 
6101c43270aSJacques Vidrine static int32_t
6111c43270aSJacques Vidrine bitswap32(int32_t b)
6121c43270aSJacques Vidrine {
6131c43270aSJacques Vidrine     int32_t r = 0;
6141c43270aSJacques Vidrine     int i;
6151c43270aSJacques Vidrine     for (i = 0; i < 32; i++) {
6161c43270aSJacques Vidrine 	r = r << 1 | (b & 1);
6171c43270aSJacques Vidrine 	b = b >> 1;
6181c43270aSJacques Vidrine     }
6191c43270aSJacques Vidrine     return r;
6201c43270aSJacques Vidrine }
6211c43270aSJacques Vidrine 
6221c43270aSJacques Vidrine 
6235e9cd1aeSAssar Westerlund /*
6241c43270aSJacques Vidrine  *
6255e9cd1aeSAssar Westerlund  */
6265e9cd1aeSAssar Westerlund 
627b528cefcSMark Murray krb5_error_code
6281c43270aSJacques Vidrine _krb5_store_creds_internal(krb5_storage *sp, krb5_creds *creds, int v0_6)
629b528cefcSMark Murray {
6305e9cd1aeSAssar Westerlund     int ret;
6315e9cd1aeSAssar Westerlund 
6325e9cd1aeSAssar Westerlund     ret = krb5_store_principal(sp, creds->client);
6335e9cd1aeSAssar Westerlund     if(ret)
6345e9cd1aeSAssar Westerlund 	return ret;
6355e9cd1aeSAssar Westerlund     ret = krb5_store_principal(sp, creds->server);
6365e9cd1aeSAssar Westerlund     if(ret)
6375e9cd1aeSAssar Westerlund 	return ret;
6385e9cd1aeSAssar Westerlund     ret = krb5_store_keyblock(sp, creds->session);
6395e9cd1aeSAssar Westerlund     if(ret)
6405e9cd1aeSAssar Westerlund 	return ret;
6415e9cd1aeSAssar Westerlund     ret = krb5_store_times(sp, creds->times);
6425e9cd1aeSAssar Westerlund     if(ret)
6435e9cd1aeSAssar Westerlund 	return ret;
6445e9cd1aeSAssar Westerlund     ret = krb5_store_int8(sp, 0);  /* this is probably the
645b528cefcSMark Murray 				enc-tkt-in-skey bit from KDCOptions */
6465e9cd1aeSAssar Westerlund     if(ret)
6475e9cd1aeSAssar Westerlund 	return ret;
6481c43270aSJacques Vidrine     if (v0_6) {
6495e9cd1aeSAssar Westerlund 	ret = krb5_store_int32(sp, creds->flags.i);
6505e9cd1aeSAssar Westerlund 	if(ret)
6515e9cd1aeSAssar Westerlund 	    return ret;
6521c43270aSJacques Vidrine     } else {
6531c43270aSJacques Vidrine 	ret = krb5_store_int32(sp, bitswap32(TicketFlags2int(creds->flags.b)));
6541c43270aSJacques Vidrine 	if(ret)
6551c43270aSJacques Vidrine 	    return ret;
6561c43270aSJacques Vidrine     }
6575e9cd1aeSAssar Westerlund     ret = krb5_store_addrs(sp, creds->addresses);
6585e9cd1aeSAssar Westerlund     if(ret)
6595e9cd1aeSAssar Westerlund 	return ret;
6605e9cd1aeSAssar Westerlund     ret = krb5_store_authdata(sp, creds->authdata);
6615e9cd1aeSAssar Westerlund     if(ret)
6625e9cd1aeSAssar Westerlund 	return ret;
6635e9cd1aeSAssar Westerlund     ret = krb5_store_data(sp, creds->ticket);
6645e9cd1aeSAssar Westerlund     if(ret)
6655e9cd1aeSAssar Westerlund 	return ret;
6665e9cd1aeSAssar Westerlund     ret = krb5_store_data(sp, creds->second_ticket);
6675e9cd1aeSAssar Westerlund     return ret;
668b528cefcSMark Murray }
669b528cefcSMark Murray 
6701c43270aSJacques Vidrine /*
6711c43270aSJacques Vidrine  * store `creds' on `sp' returning error or zero
6721c43270aSJacques Vidrine  */
6731c43270aSJacques Vidrine 
6741c43270aSJacques Vidrine krb5_error_code
6751c43270aSJacques Vidrine krb5_store_creds(krb5_storage *sp, krb5_creds *creds)
6761c43270aSJacques Vidrine {
6771c43270aSJacques Vidrine     return _krb5_store_creds_internal(sp, creds, 1);
6781c43270aSJacques Vidrine }
6791c43270aSJacques Vidrine 
6801c43270aSJacques Vidrine krb5_error_code
6811c43270aSJacques Vidrine _krb5_store_creds_heimdal_0_7(krb5_storage *sp, krb5_creds *creds)
6821c43270aSJacques Vidrine {
6831c43270aSJacques Vidrine     return _krb5_store_creds_internal(sp, creds, 0);
6841c43270aSJacques Vidrine }
6851c43270aSJacques Vidrine 
6861c43270aSJacques Vidrine krb5_error_code
6871c43270aSJacques Vidrine _krb5_store_creds_heimdal_pre_0_7(krb5_storage *sp, krb5_creds *creds)
6881c43270aSJacques Vidrine {
6891c43270aSJacques Vidrine     return _krb5_store_creds_internal(sp, creds, 1);
6901c43270aSJacques Vidrine }
6911c43270aSJacques Vidrine 
692b528cefcSMark Murray krb5_error_code
693b528cefcSMark Murray krb5_ret_creds(krb5_storage *sp, krb5_creds *creds)
694b528cefcSMark Murray {
695b528cefcSMark Murray     krb5_error_code ret;
696b528cefcSMark Murray     int8_t dummy8;
697b528cefcSMark Murray     int32_t dummy32;
698b528cefcSMark Murray 
699b528cefcSMark Murray     memset(creds, 0, sizeof(*creds));
700b528cefcSMark Murray     ret = krb5_ret_principal (sp,  &creds->client);
701b528cefcSMark Murray     if(ret) goto cleanup;
702b528cefcSMark Murray     ret = krb5_ret_principal (sp,  &creds->server);
703b528cefcSMark Murray     if(ret) goto cleanup;
704b528cefcSMark Murray     ret = krb5_ret_keyblock (sp,  &creds->session);
705b528cefcSMark Murray     if(ret) goto cleanup;
706b528cefcSMark Murray     ret = krb5_ret_times (sp,  &creds->times);
707b528cefcSMark Murray     if(ret) goto cleanup;
708b528cefcSMark Murray     ret = krb5_ret_int8 (sp,  &dummy8);
709b528cefcSMark Murray     if(ret) goto cleanup;
710b528cefcSMark Murray     ret = krb5_ret_int32 (sp,  &dummy32);
711b528cefcSMark Murray     if(ret) goto cleanup;
7121c43270aSJacques Vidrine     /*
7131c43270aSJacques Vidrine      * Runtime detect the what is the higher bits of the bitfield. If
7141c43270aSJacques Vidrine      * any of the higher bits are set in the input data, its either a
7151c43270aSJacques Vidrine      * new ticket flag (and this code need to be removed), or its a
7161c43270aSJacques Vidrine      * MIT cache (or new Heimdal cache), lets change it to our current
7171c43270aSJacques Vidrine      * format.
7181c43270aSJacques Vidrine      */
7191c43270aSJacques Vidrine     {
7201c43270aSJacques Vidrine 	u_int32_t mask = 0xffff0000;
7211c43270aSJacques Vidrine 	creds->flags.i = 0;
7221c43270aSJacques Vidrine 	creds->flags.b.anonymous = 1;
7231c43270aSJacques Vidrine 	if (creds->flags.i & mask)
7241c43270aSJacques Vidrine 	    mask = ~mask;
7251c43270aSJacques Vidrine 	if (dummy32 & mask)
7261c43270aSJacques Vidrine 	    dummy32 = bitswap32(dummy32);
7271c43270aSJacques Vidrine     }
728b528cefcSMark Murray     creds->flags.i = dummy32;
729b528cefcSMark Murray     ret = krb5_ret_addrs (sp,  &creds->addresses);
730b528cefcSMark Murray     if(ret) goto cleanup;
731b528cefcSMark Murray     ret = krb5_ret_authdata (sp,  &creds->authdata);
732b528cefcSMark Murray     if(ret) goto cleanup;
733b528cefcSMark Murray     ret = krb5_ret_data (sp,  &creds->ticket);
734b528cefcSMark Murray     if(ret) goto cleanup;
735b528cefcSMark Murray     ret = krb5_ret_data (sp,  &creds->second_ticket);
736b528cefcSMark Murray cleanup:
7378373020dSJacques Vidrine     if(ret) {
738b528cefcSMark Murray #if 0
7398373020dSJacques Vidrine 	krb5_free_creds_contents(context, creds); /* XXX */
740b528cefcSMark Murray #endif
7418373020dSJacques Vidrine     }
742b528cefcSMark Murray     return ret;
743b528cefcSMark Murray }
744