xref: /illumos-gate/usr/src/uts/common/gssapi/mechs/krb5/krb5/krb/ser_auth.c (revision 03100a6332bd4edc7a53091fcf7c9a7131bcdaa7)
1 #pragma ident	"%Z%%M%	%I%	%E% SMI"
2 /*
3  * lib/krb5/krb/ser_auth.c
4  *
5  * Copyright 1995 by the Massachusetts Institute of Technology.
6  * All Rights Reserved.
7  *
8  * Export of this software from the United States of America may
9  *   require a specific license from the United States Government.
10  *   It is the responsibility of any person or organization contemplating
11  *   export to obtain such a license before exporting.
12  *
13  * WITHIN THAT CONSTRAINT, permission to use, copy, modify, and
14  * distribute this software and its documentation for any purpose and
15  * without fee is hereby granted, provided that the above copyright
16  * notice appear in all copies and that both that copyright notice and
17  * this permission notice appear in supporting documentation, and that
18  * the name of M.I.T. not be used in advertising or publicity pertaining
19  * to distribution of the software without specific, written prior
20  * permission.  M.I.T. makes no representations about the suitability of
21  * this software for any purpose.  It is provided "as is" without express
22  * or implied warranty.
23  *
24  */
25 
26 /*
27  * ser_auth.c - Serialize krb5_authenticator structure.
28  */
29 #include <k5-int.h>
30 #include <int-proto.h>
31 
32 /*
33  * Routines to deal with externalizing the krb5_authenticator:
34  *	krb5_authenticator_size();
35  *	krb5_authenticator_externalize();
36  *	krb5_authenticator_internalize();
37  */
38 static krb5_error_code krb5_authenticator_size
39 	(krb5_context, krb5_pointer, size_t *);
40 static krb5_error_code krb5_authenticator_externalize
41 	(krb5_context, krb5_pointer, krb5_octet **, size_t *);
42 static krb5_error_code krb5_authenticator_internalize
43 	(krb5_context,krb5_pointer *, krb5_octet **, size_t *);
44 
45 /* Local data */
46 static const krb5_ser_entry krb5_authenticator_ser_entry = {
47     KV5M_AUTHENTICATOR,			/* Type			*/
48     krb5_authenticator_size,		/* Sizer routine	*/
49     krb5_authenticator_externalize,	/* Externalize routine	*/
50     krb5_authenticator_internalize	/* Internalize routine	*/
51 };
52 
53 /*
54  * krb5_authenticator_size()	- Determine the size required to externalize
55  *				  the krb5_authenticator.
56  */
57 static krb5_error_code
58 krb5_authenticator_size(krb5_context kcontext, krb5_pointer arg, size_t *sizep)
59 {
60     krb5_error_code	kret;
61     krb5_authenticator	*authenticator;
62     size_t		required;
63 
64     /*
65      * krb5_authenticator requires at minimum:
66      *	krb5_int32		for KV5M_AUTHENTICATOR
67      *	krb5_int32		for seconds
68      *	krb5_int32		for cusec
69      *	krb5_int32		for seq_number
70      *	krb5_int32		for number in authorization_data array.
71      *	krb5_int32		for KV5M_AUTHENTICATOR
72      */
73     kret = EINVAL;
74     authenticator = (krb5_authenticator *) arg;
75     if (authenticator) {
76 	required = sizeof(krb5_int32)*6;
77 
78 	/* Calculate size required by client, if appropriate */
79 	if (authenticator->client)
80 	    kret = krb5_size_opaque(kcontext,
81 				    KV5M_PRINCIPAL,
82 				    (krb5_pointer) authenticator->client,
83 				    &required);
84 	else
85 	    kret = 0;
86 
87 	/* Calculate size required by checksum, if appropriate */
88 	if (!kret && authenticator->checksum)
89 	    kret = krb5_size_opaque(kcontext,
90 				    KV5M_CHECKSUM,
91 				    (krb5_pointer) authenticator->checksum,
92 				    &required);
93 
94 	/* Calculate size required by subkey, if appropriate */
95 	if (!kret && authenticator->subkey)
96 	    kret = krb5_size_opaque(kcontext,
97 				    KV5M_KEYBLOCK,
98 				    (krb5_pointer) authenticator->subkey,
99 				    &required);
100 
101 	/* Calculate size required by authorization_data, if appropriate */
102 	if (!kret && authenticator->authorization_data) {
103 	    int i;
104 
105 	    for (i=0; !kret && authenticator->authorization_data[i]; i++) {
106 		kret = krb5_size_opaque(kcontext,
107 					KV5M_AUTHDATA,
108 					(krb5_pointer) authenticator->
109 					authorization_data[i],
110 					&required);
111 	    }
112 	}
113     }
114     if (!kret)
115 	*sizep += required;
116     return(kret);
117 }
118 
119 /*
120  * krb5_authenticator_externalize()	- Externalize the krb5_authenticator.
121  */
122 static krb5_error_code
123 krb5_authenticator_externalize(krb5_context kcontext, krb5_pointer arg, krb5_octet **buffer, size_t *lenremain)
124 {
125     krb5_error_code	kret;
126     krb5_authenticator	*authenticator;
127     size_t		required;
128     krb5_octet		*bp;
129     size_t		remain;
130     int			i;
131 
132     required = 0;
133     bp = *buffer;
134     remain = *lenremain;
135     kret = EINVAL;
136     authenticator = (krb5_authenticator *) arg;
137     if (authenticator) {
138 	kret = ENOMEM;
139 	if (!krb5_authenticator_size(kcontext, arg, &required) &&
140 	    (required <= remain)) {
141 	    /* First write our magic number */
142 	    (void) krb5_ser_pack_int32(KV5M_AUTHENTICATOR, &bp, &remain);
143 
144 	    /* Now ctime */
145 	    (void) krb5_ser_pack_int32((krb5_int32) authenticator->ctime,
146 				       &bp, &remain);
147 
148 	    /* Now cusec */
149 	    (void) krb5_ser_pack_int32((krb5_int32) authenticator->cusec,
150 				       &bp, &remain);
151 
152 	    /* Now seq_number */
153 	    (void) krb5_ser_pack_int32(authenticator->seq_number,
154 				       &bp, &remain);
155 
156 	    /* Now handle client, if appropriate */
157 	    if (authenticator->client)
158 		kret = krb5_externalize_opaque(kcontext,
159 					       KV5M_PRINCIPAL,
160 					       (krb5_pointer)
161 					       authenticator->client,
162 					       &bp,
163 					       &remain);
164 	    else
165 		kret = 0;
166 
167 	    /* Now handle checksum, if appropriate */
168 	    if (!kret && authenticator->checksum)
169 		kret = krb5_externalize_opaque(kcontext,
170 					       KV5M_CHECKSUM,
171 					       (krb5_pointer)
172 					       authenticator->checksum,
173 					       &bp,
174 					       &remain);
175 
176 	    /* Now handle subkey, if appropriate */
177 	    if (!kret && authenticator->subkey)
178 		kret = krb5_externalize_opaque(kcontext,
179 					       KV5M_KEYBLOCK,
180 					       (krb5_pointer)
181 					       authenticator->subkey,
182 					       &bp,
183 					       &remain);
184 
185 	    /* Now handle authorization_data, if appropriate */
186 	    if (!kret) {
187 		if (authenticator->authorization_data)
188 		    for (i=0; authenticator->authorization_data[i]; i++);
189 		else
190 		    i = 0;
191 		(void) krb5_ser_pack_int32((krb5_int32) i, &bp, &remain);
192 
193 		/* Now pound out the authorization_data */
194 		if (authenticator->authorization_data) {
195 		    for (i=0; !kret && authenticator->authorization_data[i];
196 			 i++)
197 			kret = krb5_externalize_opaque(kcontext,
198 						       KV5M_AUTHDATA,
199 						       (krb5_pointer)
200 						       authenticator->
201 						       authorization_data[i],
202 						       &bp,
203 						       &remain);
204 		}
205 	    }
206 
207 	    /*
208 	     * If we were successful, write trailer then update the pointer and
209 	     * remaining length;
210 	     */
211 	    if (!kret) {
212 		/* Write our trailer */
213 		(void) krb5_ser_pack_int32(KV5M_AUTHENTICATOR, &bp, &remain);
214 		*buffer = bp;
215 		*lenremain = remain;
216 	    }
217 	}
218     }
219     return(kret);
220 }
221 
222 /*
223  * krb5_authenticator_internalize()	- Internalize the krb5_authenticator.
224  */
225 static krb5_error_code
226 krb5_authenticator_internalize(krb5_context kcontext, krb5_pointer *argp, krb5_octet **buffer, size_t *lenremain)
227 {
228     krb5_error_code	kret;
229     krb5_authenticator	*authenticator;
230     krb5_int32		ibuf;
231     krb5_octet		*bp;
232     size_t		remain;
233     int			i;
234     krb5_int32		nadata;
235     size_t		len;
236 
237     bp = *buffer;
238     remain = *lenremain;
239     kret = EINVAL;
240     /* Read our magic number */
241     if (krb5_ser_unpack_int32(&ibuf, &bp, &remain))
242 	ibuf = 0;
243     if (ibuf == KV5M_AUTHENTICATOR) {
244 	kret = ENOMEM;
245 
246 	/* Get memory for the authenticator */
247 	if ((remain >= (3*sizeof(krb5_int32))) &&
248 	    (authenticator = (krb5_authenticator *)
249 	     MALLOC(sizeof(krb5_authenticator)))) {
250 	    (void) memset(authenticator, 0, sizeof(krb5_authenticator));
251 
252 	    /* Get ctime */
253 	    (void) krb5_ser_unpack_int32(&ibuf, &bp, &remain);
254 	    authenticator->ctime = (krb5_timestamp) ibuf;
255 
256 	    /* Get cusec */
257 	    (void) krb5_ser_unpack_int32(&ibuf, &bp, &remain);
258 	    authenticator->cusec = ibuf;
259 
260 	    /* Get seq_number */
261 	    (void) krb5_ser_unpack_int32(&ibuf, &bp, &remain);
262 	    authenticator->seq_number = ibuf;
263 
264 	    kret = 0;
265 
266 	    /* Attempt to read in the client */
267 	    kret = krb5_internalize_opaque(kcontext,
268 					   KV5M_PRINCIPAL,
269 					   (krb5_pointer *)
270 					   &authenticator->client,
271 					   &bp,
272 					   &remain);
273 	    if (kret == EINVAL)
274 		kret = 0;
275 
276 	    /* Attempt to read in the checksum */
277 	    if (!kret) {
278 		kret = krb5_internalize_opaque(kcontext,
279 					       KV5M_CHECKSUM,
280 					       (krb5_pointer *)
281 					       &authenticator->checksum,
282 					       &bp,
283 					       &remain);
284 		if (kret == EINVAL)
285 		    kret = 0;
286 	    }
287 
288 	    /* Attempt to read in the subkey */
289 	    if (!kret) {
290 		kret = krb5_internalize_opaque(kcontext,
291 					       KV5M_KEYBLOCK,
292 					       (krb5_pointer *)
293 					       &authenticator->subkey,
294 					       &bp,
295 					       &remain);
296 		if (kret == EINVAL)
297 		    kret = 0;
298 	    }
299 
300 	    /* Attempt to read in the authorization data count */
301 	    if (!(kret = krb5_ser_unpack_int32(&ibuf, &bp, &remain))) {
302 		nadata = ibuf;
303 		len = (size_t) (nadata + 1);
304 
305 		/* Get memory for the authorization data pointers */
306 		if ((authenticator->authorization_data = (krb5_authdata **)
307 		     MALLOC(sizeof(krb5_authdata *) * len))) {
308 		    (void) memset(authenticator->authorization_data, 0,
309 			   sizeof(krb5_authdata *) * len);
310 
311 		    for (i=0; !kret && (i<nadata); i++) {
312 			kret = krb5_internalize_opaque(kcontext,
313 						       KV5M_AUTHDATA,
314 						       (krb5_pointer *)
315 						       &authenticator->
316 						       authorization_data[i],
317 						       &bp,
318 						       &remain);
319 		    }
320 
321 		    /* Finally, find the trailer */
322 		    if (!kret) {
323 			kret = krb5_ser_unpack_int32(&ibuf, &bp, &remain);
324 			if (!kret && (ibuf == KV5M_AUTHENTICATOR))
325 			    authenticator->magic = KV5M_AUTHENTICATOR;
326 			else
327 			    kret = EINVAL;
328 		    }
329 		}
330 	    }
331 	    if (!kret) {
332 		*buffer = bp;
333 		*lenremain = remain;
334 		*argp = (krb5_pointer) authenticator;
335 	    }
336 	    else
337 		krb5_free_authenticator(kcontext, authenticator);
338 	}
339     }
340     return(kret);
341 }
342 
343 /*
344  * Register the authenticator serializer.
345  */
346 krb5_error_code
347 krb5_ser_authenticator_init(krb5_context kcontext)
348 {
349     return(krb5_register_serializer(kcontext, &krb5_authenticator_ser_entry));
350 }
351