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