xref: /illumos-gate/usr/src/lib/gss_mechs/mech_krb5/krb5/rcache/ser_rc.c (revision 445f2479fe3d7435daab18bf2cdc310b86cd6738)
1 /*
2  * Copyright 2005 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 #include "rc-int.h"
40 
41 /*
42  * Routines to deal with externalizing krb5_rcache.
43  *	krb5_rcache_size();
44  *	krb5_rcache_externalize();
45  *	krb5_rcache_internalize();
46  */
47 static krb5_error_code krb5_rcache_size
48 	(krb5_context, krb5_pointer, size_t *);
49 static krb5_error_code krb5_rcache_externalize
50 	(krb5_context, krb5_pointer, krb5_octet **, size_t *);
51 static krb5_error_code krb5_rcache_internalize
52 	(krb5_context,krb5_pointer *, krb5_octet **, size_t *);
53 
54 /*
55  * Serialization entry for this type.
56  */
57 static const krb5_ser_entry krb5_rcache_ser_entry = {
58     KV5M_RCACHE,			/* Type			*/
59     krb5_rcache_size,			/* Sizer routine	*/
60     krb5_rcache_externalize,		/* Externalize routine	*/
61     krb5_rcache_internalize		/* Internalize routine	*/
62 };
63 
64 /*
65  * krb5_rcache_size()	- Determine the size required to externalize
66  *				  this krb5_rcache variant.
67  */
68 static krb5_error_code
69 krb5_rcache_size(krb5_context kcontext, krb5_pointer arg, size_t *sizep)
70 {
71     krb5_error_code	kret;
72     krb5_rcache		rcache;
73     size_t		required;
74 
75     kret = EINVAL;
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
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     if ((rcache = (krb5_rcache) arg) != NULL) {
119 	kret = ENOMEM;
120 	if (!krb5_rcache_size(kcontext, arg, &required) &&
121 	    (required <= remain)) {
122 	    /* Our identifier */
123 	    (void) krb5_ser_pack_int32(KV5M_RCACHE, &bp, &remain);
124 
125 	    /* Calculate the length of the name */
126 	    namelen = (rcache->ops && rcache->ops->type) ?
127 		strlen(rcache->ops->type)+1 : 0;
128 	    fnamep = krb5_rc_get_name(kcontext, rcache);
129 	    namelen += (strlen(fnamep)+1);
130 
131 	    if ((rcname = (char *) malloc(namelen))) {
132 		/* Format the rcache name. */
133 		if (rcache->ops && rcache->ops->type)
134 		    sprintf(rcname, "%s:%s", rcache->ops->type, fnamep);
135 		else
136 		    strcpy(rcname, fnamep);
137 
138 		/* Put the length of the file name */
139 		(void) krb5_ser_pack_int32((krb5_int32) strlen(rcname),
140 					   &bp, &remain);
141 
142 		/* Put the name */
143 		(void) krb5_ser_pack_bytes((krb5_octet *) rcname,
144 					   strlen(rcname),
145 					   &bp, &remain);
146 
147 		/* Put the trailer */
148 		(void) krb5_ser_pack_int32(KV5M_RCACHE, &bp, &remain);
149 		kret = 0;
150 		*buffer = bp;
151 		*lenremain = remain;
152 		free(rcname);
153 	    }
154 	}
155     }
156     return(kret);
157 }
158 
159 /*
160  * krb5_rcache_internalize()	- Internalize the krb5_rcache.
161  */
162 static krb5_error_code
163 krb5_rcache_internalize(krb5_context kcontext, krb5_pointer *argp, krb5_octet **buffer, size_t *lenremain)
164 {
165     krb5_error_code	kret;
166     krb5_rcache		rcache;
167     krb5_int32		ibuf;
168     krb5_octet		*bp;
169     size_t		remain;
170     char		*rcname;
171 
172     bp = *buffer;
173     remain = *lenremain;
174     kret = EINVAL;
175     /* Read our magic number */
176     if (krb5_ser_unpack_int32(&ibuf, &bp, &remain))
177 	ibuf = 0;
178     if (ibuf == KV5M_RCACHE) {
179 	kret = ENOMEM;
180 
181 	/* Get the length of the rcache name */
182 	kret = krb5_ser_unpack_int32(&ibuf, &bp, &remain);
183 
184 	if (!kret &&
185 	    (rcname = (char *) malloc((size_t) (ibuf+1))) &&
186 	    !(kret = krb5_ser_unpack_bytes((krb5_octet *) rcname,
187 					   (size_t) ibuf,
188 					   &bp, &remain))) {
189 	    rcname[ibuf] = '\0';
190 	    if (!(kret = krb5_rc_resolve_full(kcontext, &rcache, rcname))) {
191 		(void) krb5_rc_close(kcontext, rcache);
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
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
213 krb5_ser_rcache_init(krb5_context kcontext)
214 {
215     return(krb5_register_serializer(kcontext, &krb5_rcache_ser_entry));
216 }
217