1 /* -*- mode: c; c-basic-offset: 4; indent-tabs-mode: nil -*- */
2 /* lib/krb5/krb/ser_auth.c - Serialize krb5_authenticator structure */
3 /*
4 * Copyright 1995, 2008 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 #ifndef LEAN_CLIENT
28
29 #include "k5-int.h"
30 #include "int-proto.h"
31
32 krb5_error_code
k5_size_authenticator(krb5_authenticator * authenticator,size_t * sizep)33 k5_size_authenticator(krb5_authenticator *authenticator, size_t *sizep)
34 {
35 krb5_error_code kret;
36 size_t required;
37
38 /*
39 * krb5_authenticator requires at minimum:
40 * krb5_int32 for KV5M_AUTHENTICATOR
41 * krb5_int32 for seconds
42 * krb5_int32 for cusec
43 * krb5_int32 for seq_number
44 * krb5_int32 for number in authorization_data array.
45 * krb5_int32 for KV5M_AUTHENTICATOR
46 */
47 kret = EINVAL;
48 if (authenticator != NULL) {
49 required = sizeof(krb5_int32)*6;
50
51 /* Calculate size required by client, if appropriate */
52 if (authenticator->client)
53 kret = k5_size_principal(authenticator->client, &required);
54 else
55 kret = 0;
56
57 /* Calculate size required by checksum, if appropriate */
58 if (!kret && authenticator->checksum)
59 kret = k5_size_checksum(authenticator->checksum, &required);
60
61 /* Calculate size required by subkey, if appropriate */
62 if (!kret && authenticator->subkey)
63 kret = k5_size_keyblock(authenticator->subkey, &required);
64
65 /* Calculate size required by authorization_data, if appropriate */
66 if (!kret && authenticator->authorization_data) {
67 int i;
68
69 for (i=0; !kret && authenticator->authorization_data[i]; i++) {
70 kret = k5_size_authdata(authenticator->authorization_data[i],
71 &required);
72 }
73 }
74 }
75 if (!kret)
76 *sizep += required;
77 return(kret);
78 }
79
80 krb5_error_code
k5_externalize_authenticator(krb5_authenticator * authenticator,krb5_octet ** buffer,size_t * lenremain)81 k5_externalize_authenticator(krb5_authenticator *authenticator,
82 krb5_octet **buffer, size_t *lenremain)
83 {
84 krb5_error_code kret;
85 size_t required;
86 krb5_octet *bp;
87 size_t remain;
88 int i;
89
90 required = 0;
91 bp = *buffer;
92 remain = *lenremain;
93 kret = EINVAL;
94 if (authenticator != NULL) {
95 kret = ENOMEM;
96 if (!k5_size_authenticator(authenticator, &required) &&
97 required <= remain) {
98 /* First write our magic number */
99 (void) krb5_ser_pack_int32(KV5M_AUTHENTICATOR, &bp, &remain);
100
101 /* Now ctime */
102 (void) krb5_ser_pack_int32((krb5_int32) authenticator->ctime,
103 &bp, &remain);
104
105 /* Now cusec */
106 (void) krb5_ser_pack_int32((krb5_int32) authenticator->cusec,
107 &bp, &remain);
108
109 /* Now seq_number */
110 (void) krb5_ser_pack_int32(authenticator->seq_number,
111 &bp, &remain);
112
113 /* Now handle client, if appropriate */
114 if (authenticator->client)
115 kret = k5_externalize_principal(authenticator->client,
116 &bp, &remain);
117 else
118 kret = 0;
119
120 /* Now handle checksum, if appropriate */
121 if (!kret && authenticator->checksum)
122 kret = k5_externalize_checksum(authenticator->checksum,
123 &bp, &remain);
124
125 /* Now handle subkey, if appropriate */
126 if (!kret && authenticator->subkey)
127 kret = k5_externalize_keyblock(authenticator->subkey,
128 &bp, &remain);
129
130 /* Now handle authorization_data, if appropriate */
131 if (!kret) {
132 if (authenticator->authorization_data)
133 for (i=0; authenticator->authorization_data[i]; i++);
134 else
135 i = 0;
136 (void) krb5_ser_pack_int32((krb5_int32) i, &bp, &remain);
137
138 /* Now pound out the authorization_data */
139 if (authenticator->authorization_data) {
140 for (i=0; !kret && authenticator->authorization_data[i];
141 i++)
142 kret = k5_externalize_authdata(authenticator->
143 authorization_data[i],
144 &bp, &remain);
145 }
146 }
147
148 /*
149 * If we were successful, write trailer then update the pointer and
150 * remaining length;
151 */
152 if (!kret) {
153 /* Write our trailer */
154 (void) krb5_ser_pack_int32(KV5M_AUTHENTICATOR, &bp, &remain);
155 *buffer = bp;
156 *lenremain = remain;
157 }
158 }
159 }
160 return(kret);
161 }
162
163 krb5_error_code
k5_internalize_authenticator(krb5_authenticator ** argp,krb5_octet ** buffer,size_t * lenremain)164 k5_internalize_authenticator(krb5_authenticator **argp,
165 krb5_octet **buffer, size_t *lenremain)
166 {
167 krb5_error_code kret;
168 krb5_authenticator *authenticator;
169 krb5_int32 ibuf;
170 krb5_octet *bp;
171 size_t remain;
172 int i;
173 krb5_int32 nadata;
174 size_t len;
175
176 bp = *buffer;
177 remain = *lenremain;
178 kret = EINVAL;
179 /* Read our magic number */
180 if (krb5_ser_unpack_int32(&ibuf, &bp, &remain))
181 ibuf = 0;
182 if (ibuf == KV5M_AUTHENTICATOR) {
183 kret = ENOMEM;
184
185 /* Get memory for the authenticator */
186 if ((remain >= (3*sizeof(krb5_int32))) &&
187 (authenticator = (krb5_authenticator *)
188 calloc(1, sizeof(krb5_authenticator)))) {
189
190 /* Get ctime */
191 (void) krb5_ser_unpack_int32(&ibuf, &bp, &remain);
192 authenticator->ctime = (krb5_timestamp) ibuf;
193
194 /* Get cusec */
195 (void) krb5_ser_unpack_int32(&ibuf, &bp, &remain);
196 authenticator->cusec = ibuf;
197
198 /* Get seq_number */
199 (void) krb5_ser_unpack_int32(&ibuf, &bp, &remain);
200 authenticator->seq_number = ibuf;
201
202 kret = 0;
203
204 /* Attempt to read in the client */
205 kret = k5_internalize_principal(&authenticator->client,
206 &bp, &remain);
207 if (kret == EINVAL)
208 kret = 0;
209
210 /* Attempt to read in the checksum */
211 if (!kret) {
212 kret = k5_internalize_checksum(&authenticator->checksum,
213 &bp, &remain);
214 if (kret == EINVAL)
215 kret = 0;
216 }
217
218 /* Attempt to read in the subkey */
219 if (!kret) {
220 kret = k5_internalize_keyblock(&authenticator->subkey,
221 &bp, &remain);
222 if (kret == EINVAL)
223 kret = 0;
224 }
225
226 /* Attempt to read in the authorization data count */
227 if (!(kret = krb5_ser_unpack_int32(&ibuf, &bp, &remain))) {
228 nadata = ibuf;
229 len = (size_t) (nadata + 1);
230
231 /* Get memory for the authorization data pointers */
232 if ((authenticator->authorization_data = (krb5_authdata **)
233 calloc(len, sizeof(krb5_authdata *)))) {
234 for (i=0; !kret && (i<nadata); i++) {
235 kret = k5_internalize_authdata(&authenticator->
236 authorization_data[i],
237 &bp, &remain);
238 }
239
240 /* Finally, find the trailer */
241 if (!kret) {
242 kret = krb5_ser_unpack_int32(&ibuf, &bp, &remain);
243 if (!kret && (ibuf == KV5M_AUTHENTICATOR))
244 authenticator->magic = KV5M_AUTHENTICATOR;
245 else
246 kret = EINVAL;
247 }
248 }
249 }
250 if (!kret) {
251 *buffer = bp;
252 *lenremain = remain;
253 *argp = authenticator;
254 }
255 else
256 krb5_free_authenticator(NULL, authenticator);
257 }
258 }
259 return(kret);
260 }
261
262 #endif
263