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/rcache/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_rcache.
42  *	krb5_rcache_size();
43  *	krb5_rcache_externalize();
44  *	krb5_rcache_internalize();
45  */
46 static krb5_error_code krb5_rcache_size
47 	KRB5_PROTOTYPE((krb5_context, krb5_pointer, size_t *));
48 static krb5_error_code krb5_rcache_externalize
49 	KRB5_PROTOTYPE((krb5_context, krb5_pointer, krb5_octet **, size_t *));
50 static krb5_error_code krb5_rcache_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_rcache_ser_entry = {
57     KV5M_RCACHE,			/* Type			*/
58     krb5_rcache_size,			/* Sizer routine	*/
59     krb5_rcache_externalize,		/* Externalize routine	*/
60     krb5_rcache_internalize		/* Internalize routine	*/
61 };
62 
63 /*
64  * krb5_rcache_size()	- Determine the size required to externalize
65  *				  this krb5_rcache variant.
66  */
67 static krb5_error_code
68 krb5_rcache_size(kcontext, arg, sizep)
69     krb5_context	kcontext;
70     krb5_pointer	arg;
71     size_t		*sizep;
72 {
73     krb5_error_code	kret;
74     krb5_rcache		rcache;
75     size_t		required;
76 
77     kret = EINVAL;
78     if ((rcache = (krb5_rcache) arg) != NULL) {
79 	/*
80 	 * Saving FILE: variants of krb5_rcache requires at minimum:
81 	 *	krb5_int32	for KV5M_RCACHE
82 	 *	krb5_int32	for length of rcache name.
83 	 *	krb5_int32	for KV5M_RCACHE
84 	 */
85 	required = sizeof(krb5_int32) * 3;
86 	if (rcache->ops && rcache->ops->type)
87 	    required += (strlen(rcache->ops->type)+1);
88 
89 	/*
90 	 * The rcache name is formed as follows:
91 	 *	<type>:<name>
92 	 */
93 	required += strlen(krb5_rc_get_name(kcontext, rcache));
94 
95 	kret = 0;
96 	*sizep += required;
97     }
98     return(kret);
99 }
100 
101 /*
102  * krb5_rcache_externalize()	- Externalize the krb5_rcache.
103  */
104 static krb5_error_code
105 krb5_rcache_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_rcache		rcache;
113     size_t		required;
114     krb5_octet		*bp;
115     size_t		remain;
116     char		*rcname;
117     size_t		namelen;
118     char		*fnamep;
119 
120     required = 0;
121     bp = *buffer;
122     remain = *lenremain;
123     kret = EINVAL;
124     if ((rcache = (krb5_rcache) arg) != NULL) {
125 	kret = ENOMEM;
126 	if (!krb5_rcache_size(kcontext, arg, &required) &&
127 	    (required <= remain)) {
128 	    /* Our identifier */
129 	    (void) krb5_ser_pack_int32(KV5M_RCACHE, &bp, &remain);
130 
131 	    /* Calculate the length of the name */
132 	    namelen = (rcache->ops && rcache->ops->type) ?
133 		strlen(rcache->ops->type)+1 : 0;
134 	    fnamep = krb5_rc_get_name(kcontext, rcache);
135 	    namelen += (strlen(fnamep)+1);
136 
137 	    if ((rcname = (char *) malloc(namelen))) {
138 		/* Format the rcache name. */
139 		if (rcache->ops && rcache->ops->type)
140 		    sprintf(rcname, "%s:%s", rcache->ops->type, fnamep);
141 		else
142 		    strcpy(rcname, fnamep);
143 
144 		/* Put the length of the file name */
145 		(void) krb5_ser_pack_int32((krb5_int32) strlen(rcname),
146 					   &bp, &remain);
147 
148 		/* Put the name */
149 		(void) krb5_ser_pack_bytes((krb5_octet *) rcname,
150 					   strlen(rcname),
151 					   &bp, &remain);
152 
153 		/* Put the trailer */
154 		(void) krb5_ser_pack_int32(KV5M_RCACHE, &bp, &remain);
155 		kret = 0;
156 		*buffer = bp;
157 		*lenremain = remain;
158 		free(rcname);
159 	    }
160 	}
161     }
162     return(kret);
163 }
164 
165 /*
166  * krb5_rcache_internalize()	- Internalize the krb5_rcache.
167  */
168 static krb5_error_code
169 krb5_rcache_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_rcache		rcache;
177     krb5_int32		ibuf;
178     krb5_octet		*bp;
179     size_t		remain;
180     char		*rcname;
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_RCACHE) {
189 	kret = ENOMEM;
190 
191 	/* Get the length of the rcache name */
192 	kret = krb5_ser_unpack_int32(&ibuf, &bp, &remain);
193 
194 	if (!kret &&
195 	    (rcname = (char *) malloc((size_t) (ibuf+1))) &&
196 	    !(kret = krb5_ser_unpack_bytes((krb5_octet *) rcname,
197 					   (size_t) ibuf,
198 					   &bp, &remain))) {
199 	    rcname[ibuf] = '\0';
200 	    if (!(kret = krb5_rc_resolve_full(kcontext, &rcache, rcname))) {
201 		(void) krb5_rc_close(kcontext, rcache);
202 		(void) krb5_rc_recover(kcontext, rcache);
203 		if (!kret &&
204 		    !(kret = krb5_ser_unpack_int32(&ibuf, &bp, &remain)) &&
205 		    (ibuf == KV5M_RCACHE)) {
206 		    *buffer = bp;
207 		    *lenremain = remain;
208 		    *argp = (krb5_pointer) rcache;
209 		}
210 		else
211 		    (void)krb5_rc_close(kcontext, rcache);
212 	    }
213 	    free(rcname);
214 	}
215     }
216     return(kret);
217 }
218 
219 /*
220  * Register the rcache serializer.
221  */
222 KRB5_DLLIMP krb5_error_code KRB5_CALLCONV
223 krb5_ser_rcache_init(kcontext)
224     krb5_context	kcontext;
225 {
226     return(krb5_register_serializer(kcontext, &krb5_rcache_ser_entry));
227 }
228