xref: /illumos-gate/usr/src/uts/common/gssapi/mechs/krb5/krb5/krb/serialize.c (revision 7c478bd95313f5f23a4c958a745db2134aa03244)
1 /*
2  * Copyright 2004 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  * lib/krb5/krb/serialize.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  * Base routines to deal with serialization of Kerberos metadata.
36  */
37 #include <k5-int.h>
38 
39 #include <k5-platform.h>
40 /*
41  * krb5_find_serializer()	- See if a particular type is registered.
42  */
43 krb5_ser_handle
44 krb5_find_serializer(kcontext, odtype)
45     krb5_context	kcontext;
46     krb5_magic		odtype;
47 {
48     krb5_ser_handle	res;
49     krb5_ser_handle	sctx;
50     int			i;
51 
52     res = (krb5_ser_handle) NULL;
53     sctx = (krb5_ser_handle) kcontext->ser_ctx;
54     for (i=0; i<kcontext->ser_ctx_count; i++) {
55 	if (sctx[i].odtype == odtype) {
56 	    res = &sctx[i];
57 	    break;
58 	}
59     }
60     return(res);
61 }
62 
63 /*
64  * krb5_register_serializer()	- Register a particular serializer.
65  */
66 krb5_error_code
67 krb5_register_serializer(kcontext, entry)
68     krb5_context	kcontext;
69     const krb5_ser_entry *entry;
70 {
71     krb5_error_code	kret;
72     krb5_ser_handle	stable;
73 
74     kret = 0;
75     /* See if it's already there, if so, we're good to go. */
76     if (!(stable = krb5_find_serializer(kcontext, entry->odtype))) {
77 	/*
78 	 * Can't find our type.  Create a new entry.
79 	 */
80 	if ((stable = (krb5_ser_handle) MALLOC(sizeof(krb5_ser_entry) *
81 					       (kcontext->ser_ctx_count+1)))) {
82 	    /* Copy in old table */
83 	    if (kcontext->ser_ctx_count)
84 		    (void) memcpy(stable, kcontext->ser_ctx,
85 			   sizeof(krb5_ser_entry) * kcontext->ser_ctx_count);
86 	    /* Copy in new entry */
87 	    (void) memcpy(&stable[kcontext->ser_ctx_count], entry,
88 		   sizeof(krb5_ser_entry));
89 	    if (kcontext->ser_ctx)
90 		krb5_xfree_wrap(kcontext->ser_ctx,
91 			sizeof(krb5_ser_entry) * (kcontext->ser_ctx_count));
92 	    kcontext->ser_ctx = (void *) stable;
93 	    kcontext->ser_ctx_count++;
94 	}
95 	else
96 	    kret = ENOMEM;
97     }
98     else
99 	(void) memcpy(stable, entry, sizeof(krb5_ser_entry));
100     return(kret);
101 }
102 
103 /*
104  * krb5_size_opaque()	- Determine the size necessary to serialize a given
105  *			  piece of opaque data.
106  */
107 krb5_error_code KRB5_CALLCONV
108 krb5_size_opaque(
109     krb5_context	kcontext,
110     krb5_magic		odtype,
111     krb5_pointer	arg,
112     size_t		*sizep)
113 {
114     krb5_error_code	kret;
115     krb5_ser_handle	shandle;
116 
117     kret = ENOENT;
118     /* See if the type is supported, if so, do it */
119     if ((shandle = krb5_find_serializer(kcontext, odtype)))
120 	kret = (shandle->sizer) ? (*shandle->sizer)(kcontext, arg, sizep) : 0;
121     return(kret);
122 }
123 
124 /*
125  * krb5_externalize_opaque()	- Externalize a piece of opaque data.
126  */
127 krb5_error_code KRB5_CALLCONV
128 krb5_externalize_opaque(
129     krb5_context	kcontext,
130     krb5_magic		odtype,
131     krb5_pointer	arg,
132     krb5_octet		* *bufpp,
133     size_t		*sizep)
134 {
135     krb5_error_code	kret;
136     krb5_ser_handle	shandle;
137 
138     kret = ENOENT;
139     /* See if the type is supported, if so, do it */
140     if ((shandle = krb5_find_serializer(kcontext, odtype)))
141 	kret = (shandle->externalizer) ?
142 	    (*shandle->externalizer)(kcontext, arg, bufpp, sizep) : 0;
143     return(kret);
144 }
145 
146 /*
147  * Externalize a piece of arbitrary data.
148  */
149 krb5_error_code
150 krb5_externalize_data(kcontext, arg, bufpp, sizep)
151     krb5_context	kcontext;
152     krb5_pointer	arg;
153     krb5_octet		**bufpp;
154     size_t		*sizep;
155 {
156     krb5_error_code	kret;
157     krb5_magic		*mp;
158     krb5_octet		*buffer, *bp;
159     size_t		bufsize, bsize;
160 
161     mp = (krb5_magic *) arg;
162     bufsize = 0;
163     if (!(kret = krb5_size_opaque(kcontext, *mp, arg, &bufsize))) {
164 	if ((buffer = (krb5_octet *) MALLOC(bufsize))) {
165 	    bp = buffer;
166 	    bsize = bufsize;
167 	    if (!(kret = krb5_externalize_opaque(kcontext,
168 						 *mp,
169 						 arg,
170 						 &bp,
171 						 &bsize))) {
172 		if (bsize != 0)
173 		    bufsize -= bsize;
174 		*bufpp = buffer;
175 		*sizep = bufsize;
176 	    }
177 	}
178 	else
179 	    kret = ENOMEM;
180     }
181     return(kret);
182 }
183 
184 /*
185  * krb5_internalize_opaque()	- Convert external representation into a data
186  *				  structure.
187  */
188 krb5_error_code KRB5_CALLCONV
189 krb5_internalize_opaque(
190     krb5_context	kcontext,
191     krb5_magic		odtype,
192     krb5_pointer	*argp,
193     krb5_octet		* *bufpp,
194     size_t		*sizep)
195 {
196     krb5_error_code	kret;
197     krb5_ser_handle	shandle;
198 
199     kret = ENOENT;
200     /* See if the type is supported, if so, do it */
201     if ((shandle = krb5_find_serializer(kcontext, odtype)))
202 	kret = (shandle->internalizer) ?
203 	    (*shandle->internalizer)(kcontext, argp, bufpp, sizep) : 0;
204     return(kret);
205 }
206 
207 /*
208  * krb5_ser_pack_int32()	- Pack a 4-byte integer if space is availble.
209  *				  Update buffer pointer and remaining space.
210  */
211 krb5_error_code KRB5_CALLCONV
212 krb5_ser_pack_int32(
213     krb5_int32		iarg,
214     krb5_octet		* *bufp,
215     size_t		*remainp)
216 {
217     if (*remainp >= sizeof(krb5_int32)) {
218 	(*bufp)[0] = (krb5_octet) ((iarg >> 24) & 0xff);
219 	(*bufp)[1] = (krb5_octet) ((iarg >> 16) & 0xff);
220 	(*bufp)[2] = (krb5_octet) ((iarg >> 8) & 0xff);
221 	(*bufp)[3] = (krb5_octet) (iarg & 0xff);
222 	*bufp += sizeof(krb5_int32);
223 	*remainp -= sizeof(krb5_int32);
224 	return(0);
225     }
226     else
227 	return(ENOMEM);
228 }
229 
230 /*
231  * krb5_ser_pack_int64()	- Pack an 8-byte integer if space is available.
232  *				  Update buffer pointer and remaining space.
233  */
234 krb5_error_code KRB5_CALLCONV
235 krb5_ser_pack_int64(krb5_int64 iarg, krb5_octet **bufp, size_t *remainp)
236 {
237     if (*remainp >= sizeof(krb5_int64)) {
238 	store_64_be(iarg, (unsigned char *)*bufp);
239 	*bufp += sizeof(krb5_int64);
240 	*remainp -= sizeof(krb5_int64);
241 	return(0);
242     }
243     else
244         return(ENOMEM);
245 }
246 
247 /*
248  * krb5_ser_pack_bytes()	- Pack a string of bytes.
249  */
250 krb5_error_code KRB5_CALLCONV
251 krb5_ser_pack_bytes(
252     krb5_octet	*ostring,
253     size_t	osize,
254     krb5_octet	* *bufp,
255     size_t	*remainp)
256 {
257     if (*remainp >= osize) {
258 	(void) memcpy(*bufp, ostring, osize);
259 	*bufp += osize;
260 	*remainp -= osize;
261 	return(0);
262     }
263     else
264 	return(ENOMEM);
265 }
266 
267 /*
268  * krb5_ser_unpack_int32()	- Unpack a 4-byte integer if it's there.
269  */
270 krb5_error_code KRB5_CALLCONV
271 krb5_ser_unpack_int32(
272     krb5_int32	*intp,
273     krb5_octet	* *bufp,
274     size_t	*remainp)
275 {
276     if (*remainp >= sizeof(krb5_int32)) {
277 	*intp = (((krb5_int32) ((unsigned char) (*bufp)[0]) << 24) |
278 		 ((krb5_int32) ((unsigned char) (*bufp)[1]) << 16) |
279 		 ((krb5_int32) ((unsigned char) (*bufp)[2]) << 8) |
280 		 ((krb5_int32) ((unsigned char) (*bufp)[3])));
281 	*bufp += sizeof(krb5_int32);
282 	*remainp -= sizeof(krb5_int32);
283 	return(0);
284     }
285     else
286 	return(ENOMEM);
287 }
288 
289 /*
290  * krb5_ser_unpack_int64()	- Unpack an 8-byte integer if it's there.
291  */
292 krb5_error_code KRB5_CALLCONV
293 krb5_ser_unpack_int64(krb5_int64 *intp, krb5_octet **bufp, size_t *remainp)
294 {
295     if (*remainp >= sizeof(krb5_int64)) {
296 	*intp = load_64_be((unsigned char *)*bufp);
297 	*bufp += sizeof(krb5_int64);
298 	*remainp -= sizeof(krb5_int64);
299 	return(0);
300     }
301     else
302         return(ENOMEM);
303 }
304 
305 /*
306  * krb5_ser_unpack_bytes()	- Unpack a byte string if it's there.
307  */
308 krb5_error_code KRB5_CALLCONV
309 krb5_ser_unpack_bytes(
310     krb5_octet	*istring,
311     size_t	isize,
312     krb5_octet	* *bufp,
313     size_t	*remainp)
314 {
315     if (*remainp >= isize) {
316 	(void) memcpy(istring, *bufp, isize);
317 	*bufp += isize;
318 	*remainp -= isize;
319 	return(0);
320     }
321     else
322 	return(ENOMEM);
323 }
324