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