1 /*
2  * lib/krb5/ccache/ser_rc.c
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 
28 /*
29  * ser_rcdfl.c - Serialize replay cache context.
30  */
31 #include "k5-int.h"
32 
33 /*
34  * Routines to deal with externalizing krb5_ccache.
35  *	krb5_ccache_size();
36  *	krb5_ccache_externalize();
37  *	krb5_ccache_internalize();
38  */
39 static krb5_error_code krb5_ccache_size
40 	(krb5_context, krb5_pointer, size_t *);
41 static krb5_error_code krb5_ccache_externalize
42 	(krb5_context, krb5_pointer, krb5_octet **, size_t *);
43 static krb5_error_code krb5_ccache_internalize
44 	(krb5_context,krb5_pointer *, krb5_octet **, size_t *);
45 
46 /*
47  * Serialization entry for this type.
48  */
49 static const krb5_ser_entry krb5_ccache_ser_entry = {
50     KV5M_CCACHE,			/* Type			*/
51     krb5_ccache_size,			/* Sizer routine	*/
52     krb5_ccache_externalize,		/* Externalize routine	*/
53     krb5_ccache_internalize		/* Internalize routine	*/
54 };
55 
56 /*
57  * krb5_ccache_size()	- Determine the size required to externalize
58  *				  this krb5_ccache variant.
59  */
60 static krb5_error_code
krb5_ccache_size(krb5_context kcontext,krb5_pointer arg,size_t * sizep)61 krb5_ccache_size(krb5_context kcontext, krb5_pointer arg, size_t *sizep)
62 {
63     krb5_error_code	kret;
64     krb5_ccache		ccache;
65     size_t		required;
66 
67     kret = EINVAL;
68     if ((ccache = (krb5_ccache) arg)) {
69 	/*
70 	 * Saving FILE: variants of krb5_ccache requires at minimum:
71 	 *	krb5_int32	for KV5M_CCACHE
72 	 *	krb5_int32	for length of ccache name.
73 	 *	krb5_int32	for KV5M_CCACHE
74 	 */
75 	required = sizeof(krb5_int32) * 3;
76 	if (ccache->ops && ccache->ops->prefix)
77 	    required += (strlen(ccache->ops->prefix)+1);
78 
79 	/*
80 	 * The ccache name is formed as follows:
81 	 *	<prefix>:<name>
82 	 */
83 	required += strlen(krb5_cc_get_name(kcontext, ccache));
84 
85 	kret = 0;
86 	*sizep += required;
87     }
88     return(kret);
89 }
90 
91 /*
92  * krb5_ccache_externalize()	- Externalize the krb5_ccache.
93  */
94 static krb5_error_code
krb5_ccache_externalize(krb5_context kcontext,krb5_pointer arg,krb5_octet ** buffer,size_t * lenremain)95 krb5_ccache_externalize(krb5_context kcontext, krb5_pointer arg, krb5_octet **buffer, size_t *lenremain)
96 {
97     krb5_error_code	kret;
98     krb5_ccache		ccache;
99     size_t		required;
100     krb5_octet		*bp;
101     size_t		remain;
102     char		*ccname;
103     size_t		namelen;
104     const char		*fnamep;
105 
106     required = 0;
107     bp = *buffer;
108     remain = *lenremain;
109     kret = EINVAL;
110     if ((ccache = (krb5_ccache) arg)) {
111 	kret = ENOMEM;
112 	if (!krb5_ccache_size(kcontext, arg, &required) &&
113 	    (required <= remain)) {
114 	    /* Our identifier */
115 	    (void) krb5_ser_pack_int32(KV5M_CCACHE, &bp, &remain);
116 
117 	    /* Calculate the length of the name */
118 	    namelen = (ccache->ops && ccache->ops->prefix) ?
119 		strlen(ccache->ops->prefix)+1 : 0;
120 	    fnamep = krb5_cc_get_name(kcontext, ccache);
121 	    namelen += (strlen(fnamep)+1);
122 
123 	    if ((ccname = (char *) malloc(namelen))) {
124 		/* Format the ccache name. */
125 		if (ccache->ops && ccache->ops->prefix)
126 		    sprintf(ccname, "%s:%s", ccache->ops->prefix, fnamep);
127 		else
128 		    strcpy(ccname, fnamep);
129 
130 		/* Put the length of the file name */
131 		(void) krb5_ser_pack_int32((krb5_int32) strlen(ccname),
132 					   &bp, &remain);
133 
134 		/* Put the name */
135 		(void) krb5_ser_pack_bytes((krb5_octet *) ccname,
136 					   strlen(ccname),
137 					   &bp, &remain);
138 
139 		/* Put the trailer */
140 		(void) krb5_ser_pack_int32(KV5M_CCACHE, &bp, &remain);
141 		kret = 0;
142 		*buffer = bp;
143 		*lenremain = remain;
144 		free(ccname);
145 	    }
146 	}
147     }
148     return(kret);
149 }
150 
151 /*
152  * krb5_ccache_internalize()	- Internalize the krb5_ccache.
153  */
154 static krb5_error_code
krb5_ccache_internalize(krb5_context kcontext,krb5_pointer * argp,krb5_octet ** buffer,size_t * lenremain)155 krb5_ccache_internalize(krb5_context kcontext, krb5_pointer *argp, krb5_octet **buffer, size_t *lenremain)
156 {
157     krb5_error_code	kret;
158     krb5_ccache		ccache;
159     krb5_int32		ibuf;
160     krb5_octet		*bp;
161     size_t		remain;
162     char		*ccname;
163 
164     bp = *buffer;
165     remain = *lenremain;
166     kret = EINVAL;
167     /* Read our magic number */
168     if (krb5_ser_unpack_int32(&ibuf, &bp, &remain))
169 	ibuf = 0;
170     if (ibuf == KV5M_CCACHE) {
171 	kret = ENOMEM;
172 
173 	/* Get the length of the ccache name */
174 	kret = krb5_ser_unpack_int32(&ibuf, &bp, &remain);
175 
176 	if (!kret &&
177 	    (ccname = (char *) malloc((size_t) (ibuf+1))) &&
178 	    !(kret = krb5_ser_unpack_bytes((krb5_octet *) ccname,
179 					   (size_t) ibuf,
180 					   &bp, &remain))) {
181 	    ccname[ibuf] = '\0';
182 	    if (!(kret = krb5_cc_resolve(kcontext, ccname, &ccache)) &&
183 		!(kret = krb5_ser_unpack_int32(&ibuf, &bp, &remain)) &&
184 		(ibuf == KV5M_CCACHE)) {
185 		*buffer = bp;
186 		*lenremain = remain;
187 		*argp = (krb5_pointer) ccache;
188 	    }
189 	    free(ccname);
190 	}
191     }
192     return(kret);
193 }
194 
195 /*
196  * Register the ccache serializer.
197  */
198 krb5_error_code KRB5_CALLCONV
krb5_ser_ccache_init(krb5_context kcontext)199 krb5_ser_ccache_init(krb5_context kcontext)
200 {
201     return(krb5_register_serializer(kcontext, &krb5_ccache_ser_entry));
202 }
203