Imported Upstream version 1.15.1
[platform/upstream/krb5.git] / src / lib / krb5 / ccache / ser_cc.c
1 /* -*- mode: c; c-basic-offset: 4; indent-tabs-mode: nil -*- */
2 /* lib/krb5/ccache/ser_cc.c - Serialize credential cache context */
3 /*
4  * Copyright 1995 by the Massachusetts Institute of Technology.
5  * All Rights Reserved.
6  *
7  * Export of this software from the United States of America may
8  *   require a specific license from the United States Government.
9  *   It is the responsibility of any person or organization contemplating
10  *   export to obtain such a license before exporting.
11  *
12  * WITHIN THAT CONSTRAINT, permission to use, copy, modify, and
13  * distribute this software and its documentation for any purpose and
14  * without fee is hereby granted, provided that the above copyright
15  * notice appear in all copies and that both that copyright notice and
16  * this permission notice appear in supporting documentation, and that
17  * the name of M.I.T. not be used in advertising or publicity pertaining
18  * to distribution of the software without specific, written prior
19  * permission.  Furthermore if you modify this software you must label
20  * your software as modified software and not distribute it in such a
21  * fashion that it might be confused with the original M.I.T. software.
22  * M.I.T. makes no representations about the suitability of
23  * this software for any purpose.  It is provided "as is" without express
24  * or implied warranty.
25  */
26
27 #include "k5-int.h"
28 #include "cc-int.h"
29
30 /*
31  * Routines to deal with externalizing krb5_ccache.
32  *      krb5_ccache_size();
33  *      krb5_ccache_externalize();
34  *      krb5_ccache_internalize();
35  */
36 static krb5_error_code krb5_ccache_size
37 (krb5_context, krb5_pointer, size_t *);
38 static krb5_error_code krb5_ccache_externalize
39 (krb5_context, krb5_pointer, krb5_octet **, size_t *);
40 static krb5_error_code krb5_ccache_internalize
41 (krb5_context,krb5_pointer *, krb5_octet **, size_t *);
42
43 /*
44  * Serialization entry for this type.
45  */
46 static const krb5_ser_entry krb5_ccache_ser_entry = {
47     KV5M_CCACHE,                        /* Type                 */
48     krb5_ccache_size,                   /* Sizer routine        */
49     krb5_ccache_externalize,            /* Externalize routine  */
50     krb5_ccache_internalize             /* Internalize routine  */
51 };
52
53 /*
54  * krb5_ccache_size()   - Determine the size required to externalize
55  *                                this krb5_ccache variant.
56  */
57 static krb5_error_code
58 krb5_ccache_size(krb5_context kcontext, krb5_pointer arg, size_t *sizep)
59 {
60     krb5_error_code     kret;
61     krb5_ccache         ccache;
62     size_t              required;
63
64     kret = EINVAL;
65     if ((ccache = (krb5_ccache) arg)) {
66         /*
67          * Saving FILE: variants of krb5_ccache requires at minimum:
68          *      krb5_int32      for KV5M_CCACHE
69          *      krb5_int32      for length of ccache name.
70          *      krb5_int32      for KV5M_CCACHE
71          */
72         required = sizeof(krb5_int32) * 3;
73         if (ccache->ops->prefix)
74             required += (strlen(ccache->ops->prefix)+1);
75
76         /*
77          * The ccache name is formed as follows:
78          *      <prefix>:<name>
79          */
80         required += strlen(krb5_cc_get_name(kcontext, ccache));
81
82         kret = 0;
83         *sizep += required;
84     }
85     return(kret);
86 }
87
88 /*
89  * krb5_ccache_externalize()    - Externalize the krb5_ccache.
90  */
91 static krb5_error_code
92 krb5_ccache_externalize(krb5_context kcontext, krb5_pointer arg, krb5_octet **buffer, size_t *lenremain)
93 {
94     krb5_error_code     kret;
95     krb5_ccache         ccache;
96     size_t              required;
97     krb5_octet          *bp;
98     size_t              remain;
99     char                *ccname;
100     const char          *fnamep;
101
102     required = 0;
103     bp = *buffer;
104     remain = *lenremain;
105     kret = EINVAL;
106     if ((ccache = (krb5_ccache) arg)) {
107         kret = ENOMEM;
108         if (!krb5_ccache_size(kcontext, arg, &required) &&
109             (required <= remain)) {
110             /* Our identifier */
111             (void) krb5_ser_pack_int32(KV5M_CCACHE, &bp, &remain);
112
113             fnamep = krb5_cc_get_name(kcontext, ccache);
114
115             if (ccache->ops->prefix) {
116                 if (asprintf(&ccname, "%s:%s", ccache->ops->prefix, fnamep) < 0)
117                     ccname = NULL;
118             } else
119                 ccname = strdup(fnamep);
120
121             if (ccname) {
122                 /* Put the length of the file name */
123                 (void) krb5_ser_pack_int32((krb5_int32) strlen(ccname),
124                                            &bp, &remain);
125
126                 /* Put the name */
127                 (void) krb5_ser_pack_bytes((krb5_octet *) ccname,
128                                            strlen(ccname),
129                                            &bp, &remain);
130
131                 /* Put the trailer */
132                 (void) krb5_ser_pack_int32(KV5M_CCACHE, &bp, &remain);
133                 kret = 0;
134                 *buffer = bp;
135                 *lenremain = remain;
136                 free(ccname);
137             }
138         }
139     }
140     return(kret);
141 }
142
143 /*
144  * krb5_ccache_internalize()    - Internalize the krb5_ccache.
145  */
146 static krb5_error_code
147 krb5_ccache_internalize(krb5_context kcontext, krb5_pointer *argp, krb5_octet **buffer, size_t *lenremain)
148 {
149     krb5_error_code     kret;
150     krb5_ccache         ccache;
151     krb5_int32          ibuf;
152     krb5_octet          *bp;
153     size_t              remain;
154     char                *ccname = NULL;
155
156     *argp = NULL;
157
158     bp = *buffer;
159     remain = *lenremain;
160
161     /* Read our magic number. */
162     kret = krb5_ser_unpack_int32(&ibuf, &bp, &remain);
163     if (kret)
164         return kret;
165     if (ibuf != KV5M_CCACHE)
166         return EINVAL;
167
168     /* Unpack and validate the length of the ccache name. */
169     kret = krb5_ser_unpack_int32(&ibuf, &bp, &remain);
170     if (kret)
171         return kret;
172     if (ibuf < 0 || (krb5_ui_4) ibuf > remain)
173         return EINVAL;
174
175     /* Allocate and unpack the name. */
176     ccname = malloc(ibuf + 1);
177     if (!ccname)
178         return ENOMEM;
179     kret = krb5_ser_unpack_bytes((krb5_octet *) ccname, (size_t) ibuf,
180                                  &bp, &remain);
181     if (kret)
182         goto cleanup;
183     ccname[ibuf] = '\0';
184
185     /* Read the second magic number. */
186     kret = krb5_ser_unpack_int32(&ibuf, &bp, &remain);
187     if (kret)
188         goto cleanup;
189     if (ibuf != KV5M_CCACHE) {
190         kret = EINVAL;
191         goto cleanup;
192     }
193
194     /* Resolve the named credential cache. */
195     kret = krb5_cc_resolve(kcontext, ccname, &ccache);
196     if (kret)
197         goto cleanup;
198
199     *buffer = bp;
200     *lenremain = remain;
201     *argp = ccache;
202
203 cleanup:
204     free(ccname);
205     return(kret);
206 }
207
208 /*
209  * Register the ccache serializer.
210  */
211 krb5_error_code KRB5_CALLCONV
212 krb5_ser_ccache_init(krb5_context kcontext)
213 {
214     return(krb5_register_serializer(kcontext, &krb5_ccache_ser_entry));
215 }