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