155682Smarkm/*
2178825Sdfr * Copyright (c) 1997-2006 Kungliga Tekniska H�gskolan
355682Smarkm * (Royal Institute of Technology, Stockholm, Sweden).
455682Smarkm * All rights reserved.
555682Smarkm *
655682Smarkm * Redistribution and use in source and binary forms, with or without
755682Smarkm * modification, are permitted provided that the following conditions
855682Smarkm * are met:
955682Smarkm *
1055682Smarkm * 1. Redistributions of source code must retain the above copyright
1155682Smarkm *    notice, this list of conditions and the following disclaimer.
1255682Smarkm *
1355682Smarkm * 2. Redistributions in binary form must reproduce the above copyright
1455682Smarkm *    notice, this list of conditions and the following disclaimer in the
1555682Smarkm *    documentation and/or other materials provided with the distribution.
1655682Smarkm *
1755682Smarkm * 3. Neither the name of the Institute nor the names of its contributors
1855682Smarkm *    may be used to endorse or promote products derived from this software
1955682Smarkm *    without specific prior written permission.
2055682Smarkm *
2155682Smarkm * THIS SOFTWARE IS PROVIDED BY THE INSTITUTE AND CONTRIBUTORS ``AS IS'' AND
2255682Smarkm * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
2355682Smarkm * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
2455682Smarkm * ARE DISCLAIMED.  IN NO EVENT SHALL THE INSTITUTE OR CONTRIBUTORS BE LIABLE
2555682Smarkm * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
2655682Smarkm * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
2755682Smarkm * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
2855682Smarkm * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
2955682Smarkm * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
3055682Smarkm * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
3155682Smarkm * SUCH DAMAGE.
3255682Smarkm */
3355682Smarkm
3455682Smarkm#include "krb5_locl.h"
35102644Snectar#include "store-int.h"
3655682Smarkm
37178825SdfrRCSID("$Id: store.c 22071 2007-11-14 20:04:50Z lha $");
3855682Smarkm
3978527Sassar#define BYTEORDER_IS(SP, V) (((SP)->flags & KRB5_STORAGE_BYTEORDER_MASK) == (V))
4078527Sassar#define BYTEORDER_IS_LE(SP) BYTEORDER_IS((SP), KRB5_STORAGE_BYTEORDER_LE)
4178527Sassar#define BYTEORDER_IS_BE(SP) BYTEORDER_IS((SP), KRB5_STORAGE_BYTEORDER_BE)
4278527Sassar#define BYTEORDER_IS_HOST(SP) (BYTEORDER_IS((SP), KRB5_STORAGE_BYTEORDER_HOST) || \
4378527Sassar			       krb5_storage_is_flags((SP), KRB5_STORAGE_HOST_BYTEORDER))
4478527Sassar
45178825Sdfrvoid KRB5_LIB_FUNCTION
4655682Smarkmkrb5_storage_set_flags(krb5_storage *sp, krb5_flags flags)
4755682Smarkm{
4855682Smarkm    sp->flags |= flags;
4955682Smarkm}
5055682Smarkm
51178825Sdfrvoid KRB5_LIB_FUNCTION
5255682Smarkmkrb5_storage_clear_flags(krb5_storage *sp, krb5_flags flags)
5355682Smarkm{
5455682Smarkm    sp->flags &= ~flags;
5555682Smarkm}
5655682Smarkm
57178825Sdfrkrb5_boolean KRB5_LIB_FUNCTION
5855682Smarkmkrb5_storage_is_flags(krb5_storage *sp, krb5_flags flags)
5955682Smarkm{
6055682Smarkm    return (sp->flags & flags) == flags;
6155682Smarkm}
6255682Smarkm
63178825Sdfrvoid KRB5_LIB_FUNCTION
6478527Sassarkrb5_storage_set_byteorder(krb5_storage *sp, krb5_flags byteorder)
6578527Sassar{
6678527Sassar    sp->flags &= ~KRB5_STORAGE_BYTEORDER_MASK;
6778527Sassar    sp->flags |= byteorder;
6878527Sassar}
6978527Sassar
70178825Sdfrkrb5_flags KRB5_LIB_FUNCTION
7178527Sassarkrb5_storage_get_byteorder(krb5_storage *sp, krb5_flags byteorder)
7278527Sassar{
7378527Sassar    return sp->flags & KRB5_STORAGE_BYTEORDER_MASK;
7478527Sassar}
7578527Sassar
76178825Sdfroff_t KRB5_LIB_FUNCTION
77102644Snectarkrb5_storage_seek(krb5_storage *sp, off_t offset, int whence)
78102644Snectar{
79102644Snectar    return (*sp->seek)(sp, offset, whence);
80102644Snectar}
8178527Sassar
82178825Sdfrkrb5_ssize_t KRB5_LIB_FUNCTION
83102644Snectarkrb5_storage_read(krb5_storage *sp, void *buf, size_t len)
84102644Snectar{
85102644Snectar    return sp->fetch(sp, buf, len);
86102644Snectar}
87102644Snectar
88178825Sdfrkrb5_ssize_t KRB5_LIB_FUNCTION
89102644Snectarkrb5_storage_write(krb5_storage *sp, const void *buf, size_t len)
90102644Snectar{
91102644Snectar    return sp->store(sp, buf, len);
92102644Snectar}
93102644Snectar
94178825Sdfrvoid KRB5_LIB_FUNCTION
95102644Snectarkrb5_storage_set_eof_code(krb5_storage *sp, int code)
96102644Snectar{
97102644Snectar    sp->eof_code = code;
98102644Snectar}
99102644Snectar
100178825Sdfrkrb5_ssize_t KRB5_LIB_FUNCTION
10155682Smarkm_krb5_put_int(void *buffer, unsigned long value, size_t size)
10255682Smarkm{
10355682Smarkm    unsigned char *p = buffer;
10455682Smarkm    int i;
10555682Smarkm    for (i = size - 1; i >= 0; i--) {
10655682Smarkm	p[i] = value & 0xff;
10755682Smarkm	value >>= 8;
10855682Smarkm    }
10955682Smarkm    return size;
11055682Smarkm}
11155682Smarkm
112178825Sdfrkrb5_ssize_t KRB5_LIB_FUNCTION
11355682Smarkm_krb5_get_int(void *buffer, unsigned long *value, size_t size)
11455682Smarkm{
11555682Smarkm    unsigned char *p = buffer;
11655682Smarkm    unsigned long v = 0;
11755682Smarkm    int i;
11855682Smarkm    for (i = 0; i < size; i++)
11955682Smarkm	v = (v << 8) + p[i];
12055682Smarkm    *value = v;
12155682Smarkm    return size;
12255682Smarkm}
12355682Smarkm
124178825Sdfrkrb5_error_code KRB5_LIB_FUNCTION
12555682Smarkmkrb5_storage_free(krb5_storage *sp)
12655682Smarkm{
12755682Smarkm    if(sp->free)
12855682Smarkm	(*sp->free)(sp);
12955682Smarkm    free(sp->data);
13055682Smarkm    free(sp);
13155682Smarkm    return 0;
13255682Smarkm}
13355682Smarkm
134178825Sdfrkrb5_error_code KRB5_LIB_FUNCTION
13555682Smarkmkrb5_storage_to_data(krb5_storage *sp, krb5_data *data)
13655682Smarkm{
13755682Smarkm    off_t pos;
13855682Smarkm    size_t size;
13955682Smarkm    krb5_error_code ret;
14055682Smarkm
14155682Smarkm    pos = sp->seek(sp, 0, SEEK_CUR);
14255682Smarkm    size = (size_t)sp->seek(sp, 0, SEEK_END);
14355682Smarkm    ret = krb5_data_alloc (data, size);
14455682Smarkm    if (ret) {
14555682Smarkm	sp->seek(sp, pos, SEEK_SET);
14655682Smarkm	return ret;
14755682Smarkm    }
14855682Smarkm    if (size) {
14955682Smarkm	sp->seek(sp, 0, SEEK_SET);
15055682Smarkm	sp->fetch(sp, data->data, data->length);
15155682Smarkm	sp->seek(sp, pos, SEEK_SET);
15255682Smarkm    }
15355682Smarkm    return 0;
15455682Smarkm}
15555682Smarkm
15655682Smarkmstatic krb5_error_code
15755682Smarkmkrb5_store_int(krb5_storage *sp,
15855682Smarkm	       int32_t value,
15955682Smarkm	       size_t len)
16055682Smarkm{
16155682Smarkm    int ret;
16278527Sassar    unsigned char v[16];
16355682Smarkm
16478527Sassar    if(len > sizeof(v))
16578527Sassar	return EINVAL;
16655682Smarkm    _krb5_put_int(v, value, len);
16755682Smarkm    ret = sp->store(sp, v, len);
16855682Smarkm    if (ret != len)
169102644Snectar	return (ret<0)?errno:sp->eof_code;
17055682Smarkm    return 0;
17155682Smarkm}
17255682Smarkm
173178825Sdfrkrb5_error_code KRB5_LIB_FUNCTION
17455682Smarkmkrb5_store_int32(krb5_storage *sp,
17555682Smarkm		 int32_t value)
17655682Smarkm{
17778527Sassar    if(BYTEORDER_IS_HOST(sp))
17855682Smarkm	value = htonl(value);
17978527Sassar    else if(BYTEORDER_IS_LE(sp))
18078527Sassar	value = bswap32(value);
18155682Smarkm    return krb5_store_int(sp, value, 4);
18255682Smarkm}
18355682Smarkm
184178825Sdfrkrb5_error_code KRB5_LIB_FUNCTION
185178825Sdfrkrb5_store_uint32(krb5_storage *sp,
186178825Sdfr		  uint32_t value)
187178825Sdfr{
188178825Sdfr    return krb5_store_int32(sp, (int32_t)value);
189178825Sdfr}
190178825Sdfr
19155682Smarkmstatic krb5_error_code
19255682Smarkmkrb5_ret_int(krb5_storage *sp,
19355682Smarkm	     int32_t *value,
19455682Smarkm	     size_t len)
19555682Smarkm{
19655682Smarkm    int ret;
19755682Smarkm    unsigned char v[4];
19855682Smarkm    unsigned long w;
19955682Smarkm    ret = sp->fetch(sp, v, len);
20055682Smarkm    if(ret != len)
201102644Snectar	return (ret<0)?errno:sp->eof_code;
20255682Smarkm    _krb5_get_int(v, &w, len);
20355682Smarkm    *value = w;
20455682Smarkm    return 0;
20555682Smarkm}
20655682Smarkm
207178825Sdfrkrb5_error_code KRB5_LIB_FUNCTION
20855682Smarkmkrb5_ret_int32(krb5_storage *sp,
20955682Smarkm	       int32_t *value)
21055682Smarkm{
21155682Smarkm    krb5_error_code ret = krb5_ret_int(sp, value, 4);
21255682Smarkm    if(ret)
21355682Smarkm	return ret;
21478527Sassar    if(BYTEORDER_IS_HOST(sp))
21578527Sassar	*value = htonl(*value);
21678527Sassar    else if(BYTEORDER_IS_LE(sp))
21778527Sassar	*value = bswap32(*value);
21855682Smarkm    return 0;
21955682Smarkm}
22055682Smarkm
221178825Sdfrkrb5_error_code KRB5_LIB_FUNCTION
222178825Sdfrkrb5_ret_uint32(krb5_storage *sp,
223178825Sdfr		uint32_t *value)
224178825Sdfr{
225178825Sdfr    krb5_error_code ret;
226178825Sdfr    int32_t v;
227178825Sdfr
228178825Sdfr    ret = krb5_ret_int32(sp, &v);
229178825Sdfr    if (ret == 0)
230178825Sdfr	*value = (uint32_t)v;
231178825Sdfr
232178825Sdfr    return ret;
233178825Sdfr}
234178825Sdfr
235178825Sdfrkrb5_error_code KRB5_LIB_FUNCTION
23655682Smarkmkrb5_store_int16(krb5_storage *sp,
23755682Smarkm		 int16_t value)
23855682Smarkm{
23978527Sassar    if(BYTEORDER_IS_HOST(sp))
24055682Smarkm	value = htons(value);
24178527Sassar    else if(BYTEORDER_IS_LE(sp))
24278527Sassar	value = bswap16(value);
24355682Smarkm    return krb5_store_int(sp, value, 2);
24455682Smarkm}
24555682Smarkm
246178825Sdfrkrb5_error_code KRB5_LIB_FUNCTION
247178825Sdfrkrb5_store_uint16(krb5_storage *sp,
248178825Sdfr		  uint16_t value)
249178825Sdfr{
250178825Sdfr    return krb5_store_int16(sp, (int16_t)value);
251178825Sdfr}
252178825Sdfr
253178825Sdfrkrb5_error_code KRB5_LIB_FUNCTION
25455682Smarkmkrb5_ret_int16(krb5_storage *sp,
25555682Smarkm	       int16_t *value)
25655682Smarkm{
25755682Smarkm    int32_t v;
25855682Smarkm    int ret;
25955682Smarkm    ret = krb5_ret_int(sp, &v, 2);
26055682Smarkm    if(ret)
26155682Smarkm	return ret;
26255682Smarkm    *value = v;
26378527Sassar    if(BYTEORDER_IS_HOST(sp))
26478527Sassar	*value = htons(*value);
26578527Sassar    else if(BYTEORDER_IS_LE(sp))
26678527Sassar	*value = bswap16(*value);
26755682Smarkm    return 0;
26855682Smarkm}
26955682Smarkm
270178825Sdfrkrb5_error_code KRB5_LIB_FUNCTION
271178825Sdfrkrb5_ret_uint16(krb5_storage *sp,
272178825Sdfr		uint16_t *value)
273178825Sdfr{
274178825Sdfr    krb5_error_code ret;
275178825Sdfr    int16_t v;
276178825Sdfr
277178825Sdfr    ret = krb5_ret_int16(sp, &v);
278178825Sdfr    if (ret == 0)
279178825Sdfr	*value = (uint16_t)v;
280178825Sdfr
281178825Sdfr    return ret;
282178825Sdfr}
283178825Sdfr
284178825Sdfrkrb5_error_code KRB5_LIB_FUNCTION
28555682Smarkmkrb5_store_int8(krb5_storage *sp,
28655682Smarkm		int8_t value)
28755682Smarkm{
28855682Smarkm    int ret;
28955682Smarkm
29055682Smarkm    ret = sp->store(sp, &value, sizeof(value));
29155682Smarkm    if (ret != sizeof(value))
292102644Snectar	return (ret<0)?errno:sp->eof_code;
29355682Smarkm    return 0;
29455682Smarkm}
29555682Smarkm
296178825Sdfrkrb5_error_code KRB5_LIB_FUNCTION
297178825Sdfrkrb5_store_uint8(krb5_storage *sp,
298178825Sdfr		 uint8_t value)
299178825Sdfr{
300178825Sdfr    return krb5_store_int8(sp, (int8_t)value);
301178825Sdfr}
302178825Sdfr
303178825Sdfrkrb5_error_code KRB5_LIB_FUNCTION
30455682Smarkmkrb5_ret_int8(krb5_storage *sp,
30555682Smarkm	      int8_t *value)
30655682Smarkm{
30755682Smarkm    int ret;
30855682Smarkm
30955682Smarkm    ret = sp->fetch(sp, value, sizeof(*value));
31055682Smarkm    if (ret != sizeof(*value))
311102644Snectar	return (ret<0)?errno:sp->eof_code;
31255682Smarkm    return 0;
31355682Smarkm}
31455682Smarkm
315178825Sdfrkrb5_error_code KRB5_LIB_FUNCTION
316178825Sdfrkrb5_ret_uint8(krb5_storage *sp,
317178825Sdfr	       uint8_t *value)
318178825Sdfr{
319178825Sdfr    krb5_error_code ret;
320178825Sdfr    int8_t v;
321178825Sdfr
322178825Sdfr    ret = krb5_ret_int8(sp, &v);
323178825Sdfr    if (ret == 0)
324178825Sdfr	*value = (uint8_t)v;
325178825Sdfr
326178825Sdfr    return ret;
327178825Sdfr}
328178825Sdfr
329178825Sdfrkrb5_error_code KRB5_LIB_FUNCTION
33055682Smarkmkrb5_store_data(krb5_storage *sp,
33155682Smarkm		krb5_data data)
33255682Smarkm{
33355682Smarkm    int ret;
33455682Smarkm    ret = krb5_store_int32(sp, data.length);
33555682Smarkm    if(ret < 0)
33655682Smarkm	return ret;
33755682Smarkm    ret = sp->store(sp, data.data, data.length);
33855682Smarkm    if(ret != data.length){
33955682Smarkm	if(ret < 0)
34055682Smarkm	    return errno;
341102644Snectar	return sp->eof_code;
34255682Smarkm    }
34355682Smarkm    return 0;
34455682Smarkm}
34555682Smarkm
346178825Sdfrkrb5_error_code KRB5_LIB_FUNCTION
34755682Smarkmkrb5_ret_data(krb5_storage *sp,
34855682Smarkm	      krb5_data *data)
34955682Smarkm{
35055682Smarkm    int ret;
35155682Smarkm    int32_t size;
35255682Smarkm
35355682Smarkm    ret = krb5_ret_int32(sp, &size);
35455682Smarkm    if(ret)
35555682Smarkm	return ret;
35655682Smarkm    ret = krb5_data_alloc (data, size);
35755682Smarkm    if (ret)
35855682Smarkm	return ret;
35955682Smarkm    if (size) {
36055682Smarkm	ret = sp->fetch(sp, data->data, size);
36155682Smarkm	if(ret != size)
362102644Snectar	    return (ret < 0)? errno : sp->eof_code;
36355682Smarkm    }
36455682Smarkm    return 0;
36555682Smarkm}
36655682Smarkm
367178825Sdfrkrb5_error_code KRB5_LIB_FUNCTION
36855682Smarkmkrb5_store_string(krb5_storage *sp, const char *s)
36955682Smarkm{
37055682Smarkm    krb5_data data;
37155682Smarkm    data.length = strlen(s);
372178825Sdfr    data.data = rk_UNCONST(s);
37355682Smarkm    return krb5_store_data(sp, data);
37455682Smarkm}
37555682Smarkm
376178825Sdfrkrb5_error_code KRB5_LIB_FUNCTION
37755682Smarkmkrb5_ret_string(krb5_storage *sp,
37855682Smarkm		char **string)
37955682Smarkm{
38055682Smarkm    int ret;
38155682Smarkm    krb5_data data;
38255682Smarkm    ret = krb5_ret_data(sp, &data);
38355682Smarkm    if(ret)
38455682Smarkm	return ret;
38555682Smarkm    *string = realloc(data.data, data.length + 1);
38655682Smarkm    if(*string == NULL){
38755682Smarkm	free(data.data);
38855682Smarkm	return ENOMEM;
38955682Smarkm    }
39055682Smarkm    (*string)[data.length] = 0;
39155682Smarkm    return 0;
39255682Smarkm}
39355682Smarkm
394178825Sdfrkrb5_error_code KRB5_LIB_FUNCTION
39572445Sassarkrb5_store_stringz(krb5_storage *sp, const char *s)
39655682Smarkm{
39755682Smarkm    size_t len = strlen(s) + 1;
39855682Smarkm    ssize_t ret;
39955682Smarkm
40055682Smarkm    ret = sp->store(sp, s, len);
40155682Smarkm    if(ret != len) {
40255682Smarkm	if(ret < 0)
40355682Smarkm	    return ret;
40455682Smarkm	else
405102644Snectar	    return sp->eof_code;
40655682Smarkm    }
40755682Smarkm    return 0;
40855682Smarkm}
40955682Smarkm
410178825Sdfrkrb5_error_code KRB5_LIB_FUNCTION
41155682Smarkmkrb5_ret_stringz(krb5_storage *sp,
41255682Smarkm		char **string)
41355682Smarkm{
41455682Smarkm    char c;
41555682Smarkm    char *s = NULL;
41655682Smarkm    size_t len = 0;
41755682Smarkm    ssize_t ret;
41855682Smarkm
41955682Smarkm    while((ret = sp->fetch(sp, &c, 1)) == 1){
42055682Smarkm	char *tmp;
42155682Smarkm
42255682Smarkm	len++;
42355682Smarkm	tmp = realloc (s, len);
42455682Smarkm	if (tmp == NULL) {
42555682Smarkm	    free (s);
42655682Smarkm	    return ENOMEM;
42755682Smarkm	}
42855682Smarkm	s = tmp;
42955682Smarkm	s[len - 1] = c;
43055682Smarkm	if(c == 0)
43155682Smarkm	    break;
43255682Smarkm    }
43355682Smarkm    if(ret != 1){
43455682Smarkm	free(s);
43555682Smarkm	if(ret == 0)
436102644Snectar	    return sp->eof_code;
43755682Smarkm	return ret;
43855682Smarkm    }
43955682Smarkm    *string = s;
44055682Smarkm    return 0;
44155682Smarkm}
44255682Smarkm
443178825Sdfrkrb5_error_code KRB5_LIB_FUNCTION
444178825Sdfrkrb5_store_stringnl(krb5_storage *sp, const char *s)
445178825Sdfr{
446178825Sdfr    size_t len = strlen(s);
447178825Sdfr    ssize_t ret;
44855682Smarkm
449178825Sdfr    ret = sp->store(sp, s, len);
450178825Sdfr    if(ret != len) {
451178825Sdfr	if(ret < 0)
452178825Sdfr	    return ret;
453178825Sdfr	else
454178825Sdfr	    return sp->eof_code;
455178825Sdfr    }
456178825Sdfr    ret = sp->store(sp, "\n", 1);
457178825Sdfr    if(ret != 1) {
458178825Sdfr	if(ret < 0)
459178825Sdfr	    return ret;
460178825Sdfr	else
461178825Sdfr	    return sp->eof_code;
462178825Sdfr    }
463178825Sdfr
464178825Sdfr    return 0;
465178825Sdfr
466178825Sdfr}
467178825Sdfr
468178825Sdfrkrb5_error_code KRB5_LIB_FUNCTION
469178825Sdfrkrb5_ret_stringnl(krb5_storage *sp,
470178825Sdfr		  char **string)
471178825Sdfr{
472178825Sdfr    int expect_nl = 0;
473178825Sdfr    char c;
474178825Sdfr    char *s = NULL;
475178825Sdfr    size_t len = 0;
476178825Sdfr    ssize_t ret;
477178825Sdfr
478178825Sdfr    while((ret = sp->fetch(sp, &c, 1)) == 1){
479178825Sdfr	char *tmp;
480178825Sdfr
481178825Sdfr	if (c == '\r') {
482178825Sdfr	    expect_nl = 1;
483178825Sdfr	    continue;
484178825Sdfr	}
485178825Sdfr	if (expect_nl && c != '\n') {
486178825Sdfr	    free(s);
487178825Sdfr	    return KRB5_BADMSGTYPE;
488178825Sdfr	}
489178825Sdfr
490178825Sdfr	len++;
491178825Sdfr	tmp = realloc (s, len);
492178825Sdfr	if (tmp == NULL) {
493178825Sdfr	    free (s);
494178825Sdfr	    return ENOMEM;
495178825Sdfr	}
496178825Sdfr	s = tmp;
497178825Sdfr	if(c == '\n') {
498178825Sdfr	    s[len - 1] = '\0';
499178825Sdfr	    break;
500178825Sdfr	}
501178825Sdfr	s[len - 1] = c;
502178825Sdfr    }
503178825Sdfr    if(ret != 1){
504178825Sdfr	free(s);
505178825Sdfr	if(ret == 0)
506178825Sdfr	    return sp->eof_code;
507178825Sdfr	return ret;
508178825Sdfr    }
509178825Sdfr    *string = s;
510178825Sdfr    return 0;
511178825Sdfr}
512178825Sdfr
513178825Sdfr
514178825Sdfrkrb5_error_code KRB5_LIB_FUNCTION
51555682Smarkmkrb5_store_principal(krb5_storage *sp,
516178825Sdfr		     krb5_const_principal p)
51755682Smarkm{
51855682Smarkm    int i;
51955682Smarkm    int ret;
52055682Smarkm
52155682Smarkm    if(!krb5_storage_is_flags(sp, KRB5_STORAGE_PRINCIPAL_NO_NAME_TYPE)) {
522178825Sdfr	ret = krb5_store_int32(sp, p->name.name_type);
523178825Sdfr	if(ret) return ret;
52455682Smarkm    }
52555682Smarkm    if(krb5_storage_is_flags(sp, KRB5_STORAGE_PRINCIPAL_WRONG_NUM_COMPONENTS))
52655682Smarkm	ret = krb5_store_int32(sp, p->name.name_string.len + 1);
52755682Smarkm    else
528178825Sdfr	ret = krb5_store_int32(sp, p->name.name_string.len);
52955682Smarkm
53055682Smarkm    if(ret) return ret;
53155682Smarkm    ret = krb5_store_string(sp, p->realm);
53255682Smarkm    if(ret) return ret;
53355682Smarkm    for(i = 0; i < p->name.name_string.len; i++){
53455682Smarkm	ret = krb5_store_string(sp, p->name.name_string.val[i]);
53555682Smarkm	if(ret) return ret;
53655682Smarkm    }
53755682Smarkm    return 0;
53855682Smarkm}
53955682Smarkm
540178825Sdfrkrb5_error_code KRB5_LIB_FUNCTION
54155682Smarkmkrb5_ret_principal(krb5_storage *sp,
54255682Smarkm		   krb5_principal *princ)
54355682Smarkm{
54455682Smarkm    int i;
54555682Smarkm    int ret;
54655682Smarkm    krb5_principal p;
54755682Smarkm    int32_t type;
54855682Smarkm    int32_t ncomp;
54955682Smarkm
55055682Smarkm    p = calloc(1, sizeof(*p));
55155682Smarkm    if(p == NULL)
55255682Smarkm	return ENOMEM;
55355682Smarkm
55455682Smarkm    if(krb5_storage_is_flags(sp, KRB5_STORAGE_PRINCIPAL_NO_NAME_TYPE))
55555682Smarkm	type = KRB5_NT_UNKNOWN;
556178825Sdfr    else if((ret = krb5_ret_int32(sp, &type))){
55755682Smarkm	free(p);
55855682Smarkm	return ret;
55955682Smarkm    }
56055682Smarkm    if((ret = krb5_ret_int32(sp, &ncomp))){
56155682Smarkm	free(p);
56255682Smarkm	return ret;
56355682Smarkm    }
56455682Smarkm    if(krb5_storage_is_flags(sp, KRB5_STORAGE_PRINCIPAL_WRONG_NUM_COMPONENTS))
56555682Smarkm	ncomp--;
566178825Sdfr    if (ncomp < 0) {
567178825Sdfr	free(p);
568178825Sdfr	return EINVAL;
569178825Sdfr    }
57055682Smarkm    p->name.name_type = type;
57155682Smarkm    p->name.name_string.len = ncomp;
57255682Smarkm    ret = krb5_ret_string(sp, &p->realm);
573178825Sdfr    if(ret) {
574178825Sdfr	free(p);
575178825Sdfr	return ret;
576178825Sdfr    }
57755682Smarkm    p->name.name_string.val = calloc(ncomp, sizeof(*p->name.name_string.val));
578178825Sdfr    if(p->name.name_string.val == NULL && ncomp != 0){
57955682Smarkm	free(p->realm);
580178825Sdfr	free(p);
58155682Smarkm	return ENOMEM;
58255682Smarkm    }
58355682Smarkm    for(i = 0; i < ncomp; i++){
58455682Smarkm	ret = krb5_ret_string(sp, &p->name.name_string.val[i]);
585178825Sdfr	if(ret) {
586178825Sdfr	    while (i >= 0)
587178825Sdfr		free(p->name.name_string.val[i--]);
588178825Sdfr	    free(p->realm);
589178825Sdfr	    free(p);
590178825Sdfr	    return ret;
591178825Sdfr	}
59255682Smarkm    }
59355682Smarkm    *princ = p;
59455682Smarkm    return 0;
59555682Smarkm}
59655682Smarkm
597178825Sdfrkrb5_error_code KRB5_LIB_FUNCTION
59855682Smarkmkrb5_store_keyblock(krb5_storage *sp, krb5_keyblock p)
59955682Smarkm{
60055682Smarkm    int ret;
60155682Smarkm    ret = krb5_store_int16(sp, p.keytype);
60255682Smarkm    if(ret) return ret;
60355682Smarkm
60455682Smarkm    if(krb5_storage_is_flags(sp, KRB5_STORAGE_KEYBLOCK_KEYTYPE_TWICE)){
60555682Smarkm	/* this should really be enctype, but it is the same as
60655682Smarkm           keytype nowadays */
60755682Smarkm    ret = krb5_store_int16(sp, p.keytype);
60855682Smarkm    if(ret) return ret;
60955682Smarkm    }
61055682Smarkm
61155682Smarkm    ret = krb5_store_data(sp, p.keyvalue);
61255682Smarkm    return ret;
61355682Smarkm}
61455682Smarkm
615178825Sdfrkrb5_error_code KRB5_LIB_FUNCTION
61655682Smarkmkrb5_ret_keyblock(krb5_storage *sp, krb5_keyblock *p)
61755682Smarkm{
61855682Smarkm    int ret;
61955682Smarkm    int16_t tmp;
62055682Smarkm
62155682Smarkm    ret = krb5_ret_int16(sp, &tmp);
62255682Smarkm    if(ret) return ret;
62355682Smarkm    p->keytype = tmp;
62455682Smarkm
62555682Smarkm    if(krb5_storage_is_flags(sp, KRB5_STORAGE_KEYBLOCK_KEYTYPE_TWICE)){
62655682Smarkm    ret = krb5_ret_int16(sp, &tmp);
62755682Smarkm    if(ret) return ret;
62855682Smarkm    }
62955682Smarkm
63055682Smarkm    ret = krb5_ret_data(sp, &p->keyvalue);
63155682Smarkm    return ret;
63255682Smarkm}
63355682Smarkm
634178825Sdfrkrb5_error_code KRB5_LIB_FUNCTION
63555682Smarkmkrb5_store_times(krb5_storage *sp, krb5_times times)
63655682Smarkm{
63755682Smarkm    int ret;
63855682Smarkm    ret = krb5_store_int32(sp, times.authtime);
63955682Smarkm    if(ret) return ret;
64055682Smarkm    ret = krb5_store_int32(sp, times.starttime);
64155682Smarkm    if(ret) return ret;
64255682Smarkm    ret = krb5_store_int32(sp, times.endtime);
64355682Smarkm    if(ret) return ret;
64455682Smarkm    ret = krb5_store_int32(sp, times.renew_till);
64555682Smarkm    return ret;
64655682Smarkm}
64755682Smarkm
648178825Sdfrkrb5_error_code KRB5_LIB_FUNCTION
64955682Smarkmkrb5_ret_times(krb5_storage *sp, krb5_times *times)
65055682Smarkm{
65155682Smarkm    int ret;
65255682Smarkm    int32_t tmp;
65355682Smarkm    ret = krb5_ret_int32(sp, &tmp);
65455682Smarkm    times->authtime = tmp;
65555682Smarkm    if(ret) return ret;
65655682Smarkm    ret = krb5_ret_int32(sp, &tmp);
65755682Smarkm    times->starttime = tmp;
65855682Smarkm    if(ret) return ret;
65955682Smarkm    ret = krb5_ret_int32(sp, &tmp);
66055682Smarkm    times->endtime = tmp;
66155682Smarkm    if(ret) return ret;
66255682Smarkm    ret = krb5_ret_int32(sp, &tmp);
66355682Smarkm    times->renew_till = tmp;
66455682Smarkm    return ret;
66555682Smarkm}
66655682Smarkm
667178825Sdfrkrb5_error_code KRB5_LIB_FUNCTION
66855682Smarkmkrb5_store_address(krb5_storage *sp, krb5_address p)
66955682Smarkm{
67055682Smarkm    int ret;
67155682Smarkm    ret = krb5_store_int16(sp, p.addr_type);
67255682Smarkm    if(ret) return ret;
67355682Smarkm    ret = krb5_store_data(sp, p.address);
67455682Smarkm    return ret;
67555682Smarkm}
67655682Smarkm
677178825Sdfrkrb5_error_code KRB5_LIB_FUNCTION
67855682Smarkmkrb5_ret_address(krb5_storage *sp, krb5_address *adr)
67955682Smarkm{
68055682Smarkm    int16_t t;
68155682Smarkm    int ret;
68255682Smarkm    ret = krb5_ret_int16(sp, &t);
68355682Smarkm    if(ret) return ret;
68455682Smarkm    adr->addr_type = t;
68555682Smarkm    ret = krb5_ret_data(sp, &adr->address);
68655682Smarkm    return ret;
68755682Smarkm}
68855682Smarkm
689178825Sdfrkrb5_error_code KRB5_LIB_FUNCTION
69055682Smarkmkrb5_store_addrs(krb5_storage *sp, krb5_addresses p)
69155682Smarkm{
69255682Smarkm    int i;
69355682Smarkm    int ret;
69455682Smarkm    ret = krb5_store_int32(sp, p.len);
69555682Smarkm    if(ret) return ret;
69655682Smarkm    for(i = 0; i<p.len; i++){
69755682Smarkm	ret = krb5_store_address(sp, p.val[i]);
69855682Smarkm	if(ret) break;
69955682Smarkm    }
70055682Smarkm    return ret;
70155682Smarkm}
70255682Smarkm
703178825Sdfrkrb5_error_code KRB5_LIB_FUNCTION
70455682Smarkmkrb5_ret_addrs(krb5_storage *sp, krb5_addresses *adr)
70555682Smarkm{
70655682Smarkm    int i;
70755682Smarkm    int ret;
70855682Smarkm    int32_t tmp;
70955682Smarkm
71055682Smarkm    ret = krb5_ret_int32(sp, &tmp);
71155682Smarkm    if(ret) return ret;
71255682Smarkm    adr->len = tmp;
71355682Smarkm    ALLOC(adr->val, adr->len);
714178825Sdfr    if (adr->val == NULL && adr->len != 0)
715178825Sdfr	return ENOMEM;
71655682Smarkm    for(i = 0; i < adr->len; i++){
71755682Smarkm	ret = krb5_ret_address(sp, &adr->val[i]);
71855682Smarkm	if(ret) break;
71955682Smarkm    }
72055682Smarkm    return ret;
72155682Smarkm}
72255682Smarkm
723178825Sdfrkrb5_error_code KRB5_LIB_FUNCTION
72455682Smarkmkrb5_store_authdata(krb5_storage *sp, krb5_authdata auth)
72555682Smarkm{
72655682Smarkm    krb5_error_code ret;
72755682Smarkm    int i;
72855682Smarkm    ret = krb5_store_int32(sp, auth.len);
72955682Smarkm    if(ret) return ret;
73055682Smarkm    for(i = 0; i < auth.len; i++){
73155682Smarkm	ret = krb5_store_int16(sp, auth.val[i].ad_type);
73255682Smarkm	if(ret) break;
73355682Smarkm	ret = krb5_store_data(sp, auth.val[i].ad_data);
73455682Smarkm	if(ret) break;
73555682Smarkm    }
73655682Smarkm    return 0;
73755682Smarkm}
73855682Smarkm
739178825Sdfrkrb5_error_code KRB5_LIB_FUNCTION
74055682Smarkmkrb5_ret_authdata(krb5_storage *sp, krb5_authdata *auth)
74155682Smarkm{
74255682Smarkm    krb5_error_code ret;
74355682Smarkm    int32_t tmp;
74455682Smarkm    int16_t tmp2;
74555682Smarkm    int i;
74655682Smarkm    ret = krb5_ret_int32(sp, &tmp);
74755682Smarkm    if(ret) return ret;
74855682Smarkm    ALLOC_SEQ(auth, tmp);
749178825Sdfr    if (auth->val == NULL && tmp != 0)
750178825Sdfr	return ENOMEM;
75155682Smarkm    for(i = 0; i < tmp; i++){
75255682Smarkm	ret = krb5_ret_int16(sp, &tmp2);
75355682Smarkm	if(ret) break;
75455682Smarkm	auth->val[i].ad_type = tmp2;
75555682Smarkm	ret = krb5_ret_data(sp, &auth->val[i].ad_data);
75655682Smarkm	if(ret) break;
75755682Smarkm    }
75855682Smarkm    return ret;
75955682Smarkm}
76055682Smarkm
761127808Snectarstatic int32_t
762127808Snectarbitswap32(int32_t b)
763127808Snectar{
764127808Snectar    int32_t r = 0;
765127808Snectar    int i;
766127808Snectar    for (i = 0; i < 32; i++) {
767127808Snectar	r = r << 1 | (b & 1);
768127808Snectar	b = b >> 1;
769127808Snectar    }
770127808Snectar    return r;
771127808Snectar}
772127808Snectar
773127808Snectar
77472445Sassar/*
775127808Snectar *
77672445Sassar */
77772445Sassar
778178825Sdfrkrb5_error_code KRB5_LIB_FUNCTION
779178825Sdfrkrb5_store_creds(krb5_storage *sp, krb5_creds *creds)
78055682Smarkm{
78172445Sassar    int ret;
78272445Sassar
78372445Sassar    ret = krb5_store_principal(sp, creds->client);
784102644Snectar    if(ret)
78572445Sassar	return ret;
78672445Sassar    ret = krb5_store_principal(sp, creds->server);
787102644Snectar    if(ret)
78872445Sassar	return ret;
78972445Sassar    ret = krb5_store_keyblock(sp, creds->session);
790102644Snectar    if(ret)
79172445Sassar	return ret;
79272445Sassar    ret = krb5_store_times(sp, creds->times);
793102644Snectar    if(ret)
79472445Sassar	return ret;
795178825Sdfr    ret = krb5_store_int8(sp, creds->second_ticket.length != 0); /* is_skey */
796102644Snectar    if(ret)
79772445Sassar	return ret;
798178825Sdfr
799178825Sdfr    if(krb5_storage_is_flags(sp, KRB5_STORAGE_CREDS_FLAGS_WRONG_BITORDER))
800127808Snectar	ret = krb5_store_int32(sp, creds->flags.i);
801178825Sdfr    else
802127808Snectar	ret = krb5_store_int32(sp, bitswap32(TicketFlags2int(creds->flags.b)));
803178825Sdfr    if(ret)
804178825Sdfr	return ret;
805178825Sdfr
80672445Sassar    ret = krb5_store_addrs(sp, creds->addresses);
807102644Snectar    if(ret)
80872445Sassar	return ret;
80972445Sassar    ret = krb5_store_authdata(sp, creds->authdata);
810102644Snectar    if(ret)
81172445Sassar	return ret;
81272445Sassar    ret = krb5_store_data(sp, creds->ticket);
813102644Snectar    if(ret)
81472445Sassar	return ret;
81572445Sassar    ret = krb5_store_data(sp, creds->second_ticket);
816102644Snectar    return ret;
81755682Smarkm}
81855682Smarkm
819178825Sdfrkrb5_error_code KRB5_LIB_FUNCTION
82055682Smarkmkrb5_ret_creds(krb5_storage *sp, krb5_creds *creds)
82155682Smarkm{
82255682Smarkm    krb5_error_code ret;
82355682Smarkm    int8_t dummy8;
82455682Smarkm    int32_t dummy32;
82555682Smarkm
82655682Smarkm    memset(creds, 0, sizeof(*creds));
82755682Smarkm    ret = krb5_ret_principal (sp,  &creds->client);
82855682Smarkm    if(ret) goto cleanup;
82955682Smarkm    ret = krb5_ret_principal (sp,  &creds->server);
83055682Smarkm    if(ret) goto cleanup;
83155682Smarkm    ret = krb5_ret_keyblock (sp,  &creds->session);
83255682Smarkm    if(ret) goto cleanup;
83355682Smarkm    ret = krb5_ret_times (sp,  &creds->times);
83455682Smarkm    if(ret) goto cleanup;
83555682Smarkm    ret = krb5_ret_int8 (sp,  &dummy8);
83655682Smarkm    if(ret) goto cleanup;
83755682Smarkm    ret = krb5_ret_int32 (sp,  &dummy32);
83855682Smarkm    if(ret) goto cleanup;
839127808Snectar    /*
840127808Snectar     * Runtime detect the what is the higher bits of the bitfield. If
841178825Sdfr     * any of the higher bits are set in the input data, it's either a
842178825Sdfr     * new ticket flag (and this code need to be removed), or it's a
843127808Snectar     * MIT cache (or new Heimdal cache), lets change it to our current
844127808Snectar     * format.
845127808Snectar     */
846127808Snectar    {
847178825Sdfr	uint32_t mask = 0xffff0000;
848127808Snectar	creds->flags.i = 0;
849127808Snectar	creds->flags.b.anonymous = 1;
850127808Snectar	if (creds->flags.i & mask)
851127808Snectar	    mask = ~mask;
852127808Snectar	if (dummy32 & mask)
853127808Snectar	    dummy32 = bitswap32(dummy32);
854127808Snectar    }
85555682Smarkm    creds->flags.i = dummy32;
85655682Smarkm    ret = krb5_ret_addrs (sp,  &creds->addresses);
85755682Smarkm    if(ret) goto cleanup;
85855682Smarkm    ret = krb5_ret_authdata (sp,  &creds->authdata);
85955682Smarkm    if(ret) goto cleanup;
86055682Smarkm    ret = krb5_ret_data (sp,  &creds->ticket);
86155682Smarkm    if(ret) goto cleanup;
86255682Smarkm    ret = krb5_ret_data (sp,  &creds->second_ticket);
86355682Smarkmcleanup:
864102644Snectar    if(ret) {
86555682Smarkm#if 0
866178825Sdfr	krb5_free_cred_contents(context, creds); /* XXX */
86755682Smarkm#endif
868102644Snectar    }
86955682Smarkm    return ret;
87055682Smarkm}
871178825Sdfr
872178825Sdfr#define SC_CLIENT_PRINCIPAL	    0x0001
873178825Sdfr#define SC_SERVER_PRINCIPAL	    0x0002
874178825Sdfr#define SC_SESSION_KEY		    0x0004
875178825Sdfr#define SC_TICKET		    0x0008
876178825Sdfr#define SC_SECOND_TICKET	    0x0010
877178825Sdfr#define SC_AUTHDATA		    0x0020
878178825Sdfr#define SC_ADDRESSES		    0x0040
879178825Sdfr
880178825Sdfr/*
881178825Sdfr *
882178825Sdfr */
883178825Sdfr
884178825Sdfrkrb5_error_code KRB5_LIB_FUNCTION
885178825Sdfrkrb5_store_creds_tag(krb5_storage *sp, krb5_creds *creds)
886178825Sdfr{
887178825Sdfr    int ret;
888178825Sdfr    int32_t header = 0;
889178825Sdfr
890178825Sdfr    if (creds->client)
891178825Sdfr	header |= SC_CLIENT_PRINCIPAL;
892178825Sdfr    if (creds->server)
893178825Sdfr	header |= SC_SERVER_PRINCIPAL;
894178825Sdfr    if (creds->session.keytype != ETYPE_NULL)
895178825Sdfr	header |= SC_SESSION_KEY;
896178825Sdfr    if (creds->ticket.data)
897178825Sdfr	header |= SC_TICKET;
898178825Sdfr    if (creds->second_ticket.length)
899178825Sdfr	header |= SC_SECOND_TICKET;
900178825Sdfr    if (creds->authdata.len)
901178825Sdfr	header |= SC_AUTHDATA;
902178825Sdfr    if (creds->addresses.len)
903178825Sdfr	header |= SC_ADDRESSES;
904178825Sdfr
905178825Sdfr    ret = krb5_store_int32(sp, header);
906178825Sdfr
907178825Sdfr    if (creds->client) {
908178825Sdfr	ret = krb5_store_principal(sp, creds->client);
909178825Sdfr	if(ret)
910178825Sdfr	    return ret;
911178825Sdfr    }
912178825Sdfr
913178825Sdfr    if (creds->server) {
914178825Sdfr	ret = krb5_store_principal(sp, creds->server);
915178825Sdfr	if(ret)
916178825Sdfr	    return ret;
917178825Sdfr    }
918178825Sdfr
919178825Sdfr    if (creds->session.keytype != ETYPE_NULL) {
920178825Sdfr	ret = krb5_store_keyblock(sp, creds->session);
921178825Sdfr	if(ret)
922178825Sdfr	    return ret;
923178825Sdfr    }
924178825Sdfr
925178825Sdfr    ret = krb5_store_times(sp, creds->times);
926178825Sdfr    if(ret)
927178825Sdfr	return ret;
928178825Sdfr    ret = krb5_store_int8(sp, creds->second_ticket.length != 0); /* is_skey */
929178825Sdfr    if(ret)
930178825Sdfr	return ret;
931178825Sdfr
932178825Sdfr    ret = krb5_store_int32(sp, bitswap32(TicketFlags2int(creds->flags.b)));
933178825Sdfr    if(ret)
934178825Sdfr	return ret;
935178825Sdfr
936178825Sdfr    if (creds->addresses.len) {
937178825Sdfr	ret = krb5_store_addrs(sp, creds->addresses);
938178825Sdfr	if(ret)
939178825Sdfr	    return ret;
940178825Sdfr    }
941178825Sdfr
942178825Sdfr    if (creds->authdata.len) {
943178825Sdfr	ret = krb5_store_authdata(sp, creds->authdata);
944178825Sdfr	if(ret)
945178825Sdfr	    return ret;
946178825Sdfr    }
947178825Sdfr
948178825Sdfr    if (creds->ticket.data) {
949178825Sdfr	ret = krb5_store_data(sp, creds->ticket);
950178825Sdfr	if(ret)
951178825Sdfr	    return ret;
952178825Sdfr    }
953178825Sdfr
954178825Sdfr    if (creds->second_ticket.data) {
955178825Sdfr	ret = krb5_store_data(sp, creds->second_ticket);
956178825Sdfr	if (ret)
957178825Sdfr	    return ret;
958178825Sdfr    }
959178825Sdfr
960178825Sdfr    return ret;
961178825Sdfr}
962178825Sdfr
963178825Sdfrkrb5_error_code KRB5_LIB_FUNCTION
964178825Sdfrkrb5_ret_creds_tag(krb5_storage *sp,
965178825Sdfr		   krb5_creds *creds)
966178825Sdfr{
967178825Sdfr    krb5_error_code ret;
968178825Sdfr    int8_t dummy8;
969178825Sdfr    int32_t dummy32, header;
970178825Sdfr
971178825Sdfr    memset(creds, 0, sizeof(*creds));
972178825Sdfr
973178825Sdfr    ret = krb5_ret_int32 (sp, &header);
974178825Sdfr    if (ret) goto cleanup;
975178825Sdfr
976178825Sdfr    if (header & SC_CLIENT_PRINCIPAL) {
977178825Sdfr	ret = krb5_ret_principal (sp,  &creds->client);
978178825Sdfr	if(ret) goto cleanup;
979178825Sdfr    }
980178825Sdfr    if (header & SC_SERVER_PRINCIPAL) {
981178825Sdfr	ret = krb5_ret_principal (sp,  &creds->server);
982178825Sdfr	if(ret) goto cleanup;
983178825Sdfr    }
984178825Sdfr    if (header & SC_SESSION_KEY) {
985178825Sdfr	ret = krb5_ret_keyblock (sp,  &creds->session);
986178825Sdfr	if(ret) goto cleanup;
987178825Sdfr    }
988178825Sdfr    ret = krb5_ret_times (sp,  &creds->times);
989178825Sdfr    if(ret) goto cleanup;
990178825Sdfr    ret = krb5_ret_int8 (sp,  &dummy8);
991178825Sdfr    if(ret) goto cleanup;
992178825Sdfr    ret = krb5_ret_int32 (sp,  &dummy32);
993178825Sdfr    if(ret) goto cleanup;
994178825Sdfr    /*
995178825Sdfr     * Runtime detect the what is the higher bits of the bitfield. If
996178825Sdfr     * any of the higher bits are set in the input data, it's either a
997178825Sdfr     * new ticket flag (and this code need to be removed), or it's a
998178825Sdfr     * MIT cache (or new Heimdal cache), lets change it to our current
999178825Sdfr     * format.
1000178825Sdfr     */
1001178825Sdfr    {
1002178825Sdfr	uint32_t mask = 0xffff0000;
1003178825Sdfr	creds->flags.i = 0;
1004178825Sdfr	creds->flags.b.anonymous = 1;
1005178825Sdfr	if (creds->flags.i & mask)
1006178825Sdfr	    mask = ~mask;
1007178825Sdfr	if (dummy32 & mask)
1008178825Sdfr	    dummy32 = bitswap32(dummy32);
1009178825Sdfr    }
1010178825Sdfr    creds->flags.i = dummy32;
1011178825Sdfr    if (header & SC_ADDRESSES) {
1012178825Sdfr	ret = krb5_ret_addrs (sp,  &creds->addresses);
1013178825Sdfr	if(ret) goto cleanup;
1014178825Sdfr    }
1015178825Sdfr    if (header & SC_AUTHDATA) {
1016178825Sdfr	ret = krb5_ret_authdata (sp,  &creds->authdata);
1017178825Sdfr	if(ret) goto cleanup;
1018178825Sdfr    }
1019178825Sdfr    if (header & SC_TICKET) {
1020178825Sdfr	ret = krb5_ret_data (sp,  &creds->ticket);
1021178825Sdfr	if(ret) goto cleanup;
1022178825Sdfr    }
1023178825Sdfr    if (header & SC_SECOND_TICKET) {
1024178825Sdfr	ret = krb5_ret_data (sp,  &creds->second_ticket);
1025178825Sdfr	if(ret) goto cleanup;
1026178825Sdfr    }
1027178825Sdfr
1028178825Sdfrcleanup:
1029178825Sdfr    if(ret) {
1030178825Sdfr#if 0
1031178825Sdfr	krb5_free_cred_contents(context, creds); /* XXX */
1032178825Sdfr#endif
1033178825Sdfr    }
1034178825Sdfr    return ret;
1035178825Sdfr}
1036