1 /*
2 * lib/krb5/krb/ser_auth.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_auth.c - Serialize krb5_authenticator structure.
30 */
31 #include "k5-int.h"
32 #include "int-proto.h"
33
34 /*
35 * Routines to deal with externalizing the krb5_authenticator:
36 * krb5_authenticator_size();
37 * krb5_authenticator_externalize();
38 * krb5_authenticator_internalize();
39 */
40 static krb5_error_code krb5_authenticator_size
41 (krb5_context, krb5_pointer, size_t *);
42 static krb5_error_code krb5_authenticator_externalize
43 (krb5_context, krb5_pointer, krb5_octet **, size_t *);
44 static krb5_error_code krb5_authenticator_internalize
45 (krb5_context,krb5_pointer *, krb5_octet **, size_t *);
46
47 /* Local data */
48 static const krb5_ser_entry krb5_authenticator_ser_entry = {
49 KV5M_AUTHENTICATOR, /* Type */
50 krb5_authenticator_size, /* Sizer routine */
51 krb5_authenticator_externalize, /* Externalize routine */
52 krb5_authenticator_internalize /* Internalize routine */
53 };
54
55 /*
56 * krb5_authenticator_size() - Determine the size required to externalize
57 * the krb5_authenticator.
58 */
59 static krb5_error_code
krb5_authenticator_size(krb5_context kcontext,krb5_pointer arg,size_t * sizep)60 krb5_authenticator_size(krb5_context kcontext, krb5_pointer arg, size_t *sizep)
61 {
62 krb5_error_code kret;
63 krb5_authenticator *authenticator;
64 size_t required;
65
66 /*
67 * krb5_authenticator requires at minimum:
68 * krb5_int32 for KV5M_AUTHENTICATOR
69 * krb5_int32 for seconds
70 * krb5_int32 for cusec
71 * krb5_int32 for seq_number
72 * krb5_int32 for number in authorization_data array.
73 * krb5_int32 for KV5M_AUTHENTICATOR
74 */
75 kret = EINVAL;
76 /* Solaris Kerberos */
77 authenticator = (krb5_authenticator *) arg;
78 if (authenticator) {
79 required = sizeof(krb5_int32)*6;
80
81 /* Calculate size required by client, if appropriate */
82 if (authenticator->client)
83 kret = krb5_size_opaque(kcontext,
84 KV5M_PRINCIPAL,
85 (krb5_pointer) authenticator->client,
86 &required);
87 else
88 kret = 0;
89
90 /* Calculate size required by checksum, if appropriate */
91 if (!kret && authenticator->checksum)
92 kret = krb5_size_opaque(kcontext,
93 KV5M_CHECKSUM,
94 (krb5_pointer) authenticator->checksum,
95 &required);
96
97 /* Calculate size required by subkey, if appropriate */
98 if (!kret && authenticator->subkey)
99 kret = krb5_size_opaque(kcontext,
100 KV5M_KEYBLOCK,
101 (krb5_pointer) authenticator->subkey,
102 &required);
103
104 /* Calculate size required by authorization_data, if appropriate */
105 if (!kret && authenticator->authorization_data) {
106 int i;
107
108 for (i=0; !kret && authenticator->authorization_data[i]; i++) {
109 kret = krb5_size_opaque(kcontext,
110 KV5M_AUTHDATA,
111 (krb5_pointer) authenticator->
112 authorization_data[i],
113 &required);
114 }
115 }
116 }
117 if (!kret)
118 *sizep += required;
119 return(kret);
120 }
121
122 /*
123 * krb5_authenticator_externalize() - Externalize the krb5_authenticator.
124 */
125 static krb5_error_code
krb5_authenticator_externalize(krb5_context kcontext,krb5_pointer arg,krb5_octet ** buffer,size_t * lenremain)126 krb5_authenticator_externalize(krb5_context kcontext, krb5_pointer arg, krb5_octet **buffer, size_t *lenremain)
127 {
128 krb5_error_code kret;
129 krb5_authenticator *authenticator;
130 size_t required;
131 krb5_octet *bp;
132 size_t remain;
133 int i;
134
135 required = 0;
136 bp = *buffer;
137 remain = *lenremain;
138 kret = EINVAL;
139 /* Solaris Kerberos */
140 authenticator = (krb5_authenticator *) arg;
141 if (authenticator) {
142 kret = ENOMEM;
143 if (!krb5_authenticator_size(kcontext, arg, &required) &&
144 (required <= remain)) {
145 /* First write our magic number */
146 (void) krb5_ser_pack_int32(KV5M_AUTHENTICATOR, &bp, &remain);
147
148 /* Now ctime */
149 (void) krb5_ser_pack_int32((krb5_int32) authenticator->ctime,
150 &bp, &remain);
151
152 /* Now cusec */
153 (void) krb5_ser_pack_int32((krb5_int32) authenticator->cusec,
154 &bp, &remain);
155
156 /* Now seq_number */
157 (void) krb5_ser_pack_int32(authenticator->seq_number,
158 &bp, &remain);
159
160 /* Now handle client, if appropriate */
161 if (authenticator->client)
162 kret = krb5_externalize_opaque(kcontext,
163 KV5M_PRINCIPAL,
164 (krb5_pointer)
165 authenticator->client,
166 &bp,
167 &remain);
168 else
169 kret = 0;
170
171 /* Now handle checksum, if appropriate */
172 if (!kret && authenticator->checksum)
173 kret = krb5_externalize_opaque(kcontext,
174 KV5M_CHECKSUM,
175 (krb5_pointer)
176 authenticator->checksum,
177 &bp,
178 &remain);
179
180 /* Now handle subkey, if appropriate */
181 if (!kret && authenticator->subkey)
182 kret = krb5_externalize_opaque(kcontext,
183 KV5M_KEYBLOCK,
184 (krb5_pointer)
185 authenticator->subkey,
186 &bp,
187 &remain);
188
189 /* Now handle authorization_data, if appropriate */
190 if (!kret) {
191 if (authenticator->authorization_data)
192 for (i=0; authenticator->authorization_data[i]; i++);
193 else
194 i = 0;
195 (void) krb5_ser_pack_int32((krb5_int32) i, &bp, &remain);
196
197 /* Now pound out the authorization_data */
198 if (authenticator->authorization_data) {
199 for (i=0; !kret && authenticator->authorization_data[i];
200 i++)
201 kret = krb5_externalize_opaque(kcontext,
202 KV5M_AUTHDATA,
203 (krb5_pointer)
204 authenticator->
205 authorization_data[i],
206 &bp,
207 &remain);
208 }
209 }
210
211 /*
212 * If we were successful, write trailer then update the pointer and
213 * remaining length;
214 */
215 if (!kret) {
216 /* Write our trailer */
217 (void) krb5_ser_pack_int32(KV5M_AUTHENTICATOR, &bp, &remain);
218 *buffer = bp;
219 *lenremain = remain;
220 }
221 }
222 }
223 return(kret);
224 }
225
226 /*
227 * krb5_authenticator_internalize() - Internalize the krb5_authenticator.
228 */
229 static krb5_error_code
krb5_authenticator_internalize(krb5_context kcontext,krb5_pointer * argp,krb5_octet ** buffer,size_t * lenremain)230 krb5_authenticator_internalize(krb5_context kcontext, krb5_pointer *argp, krb5_octet **buffer, size_t *lenremain)
231 {
232 krb5_error_code kret;
233 krb5_authenticator *authenticator;
234 krb5_int32 ibuf;
235 krb5_octet *bp;
236 size_t remain;
237 int i;
238 krb5_int32 nadata;
239 size_t len;
240
241 bp = *buffer;
242 remain = *lenremain;
243 kret = EINVAL;
244 /* Read our magic number */
245 if (krb5_ser_unpack_int32(&ibuf, &bp, &remain))
246 ibuf = 0;
247 if (ibuf == KV5M_AUTHENTICATOR) {
248 kret = ENOMEM;
249
250 /* Get memory for the authenticator */
251 if ((remain >= (3*sizeof(krb5_int32))) &&
252 (authenticator = (krb5_authenticator *)
253 MALLOC(sizeof(krb5_authenticator)))) {
254 (void) memset(authenticator, 0, sizeof(krb5_authenticator));
255
256 /* Get ctime */
257 (void) krb5_ser_unpack_int32(&ibuf, &bp, &remain);
258 authenticator->ctime = (krb5_timestamp) ibuf;
259
260 /* Get cusec */
261 (void) krb5_ser_unpack_int32(&ibuf, &bp, &remain);
262 authenticator->cusec = ibuf;
263
264 /* Get seq_number */
265 (void) krb5_ser_unpack_int32(&ibuf, &bp, &remain);
266 authenticator->seq_number = ibuf;
267
268 kret = 0;
269
270 /* Attempt to read in the client */
271 kret = krb5_internalize_opaque(kcontext,
272 KV5M_PRINCIPAL,
273 (krb5_pointer *)
274 &authenticator->client,
275 &bp,
276 &remain);
277 if (kret == EINVAL)
278 kret = 0;
279
280 /* Attempt to read in the checksum */
281 if (!kret) {
282 kret = krb5_internalize_opaque(kcontext,
283 KV5M_CHECKSUM,
284 (krb5_pointer *)
285 &authenticator->checksum,
286 &bp,
287 &remain);
288 if (kret == EINVAL)
289 kret = 0;
290 }
291
292 /* Attempt to read in the subkey */
293 if (!kret) {
294 kret = krb5_internalize_opaque(kcontext,
295 KV5M_KEYBLOCK,
296 (krb5_pointer *)
297 &authenticator->subkey,
298 &bp,
299 &remain);
300 if (kret == EINVAL)
301 kret = 0;
302 }
303
304 /* Attempt to read in the authorization data count */
305 if (!(kret = krb5_ser_unpack_int32(&ibuf, &bp, &remain))) {
306 nadata = ibuf;
307 len = (size_t) (nadata + 1);
308
309 /* Get memory for the authorization data pointers */
310 if ((authenticator->authorization_data = (krb5_authdata **)
311 MALLOC(sizeof(krb5_authdata *) * len))) {
312 (void) memset(authenticator->authorization_data, 0,
313 sizeof(krb5_authdata *) * len);
314
315 for (i=0; !kret && (i<nadata); i++) {
316 kret = krb5_internalize_opaque(kcontext,
317 KV5M_AUTHDATA,
318 (krb5_pointer *)
319 &authenticator->
320 authorization_data[i],
321 &bp,
322 &remain);
323 }
324
325 /* Finally, find the trailer */
326 if (!kret) {
327 kret = krb5_ser_unpack_int32(&ibuf, &bp, &remain);
328 if (!kret && (ibuf == KV5M_AUTHENTICATOR))
329 authenticator->magic = KV5M_AUTHENTICATOR;
330 else
331 kret = EINVAL;
332 }
333 }
334 }
335 if (!kret) {
336 *buffer = bp;
337 *lenremain = remain;
338 *argp = (krb5_pointer) authenticator;
339 }
340 else
341 krb5_free_authenticator(kcontext, authenticator);
342 }
343 }
344 return(kret);
345 }
346
347 /*
348 * Register the authenticator serializer.
349 */
350 krb5_error_code
krb5_ser_authenticator_init(krb5_context kcontext)351 krb5_ser_authenticator_init(krb5_context kcontext)
352 {
353 return(krb5_register_serializer(kcontext, &krb5_authenticator_ser_entry));
354 }
355