Branch data Line data Source code
1 : : /* krb5/checksum.c --- (Un)pack checksum fields in Krb5 GSS contexts.
2 : : * Copyright (C) 2003, 2004, 2005, 2006, 2007, 2009, 2010 Simon Josefsson
3 : : *
4 : : * This file is part of the Generic Security Service (GSS).
5 : : *
6 : : * GSS is free software; you can redistribute it and/or modify it
7 : : * under the terms of the GNU General Public License as published by
8 : : * the Free Software Foundation; either version 3 of the License, or
9 : : * (at your option) any later version.
10 : : *
11 : : * GSS is distributed in the hope that it will be useful, but WITHOUT
12 : : * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY
13 : : * or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public
14 : : * License for more details.
15 : : *
16 : : * You should have received a copy of the GNU General Public License
17 : : * along with GSS; if not, see http://www.gnu.org/licenses or write to
18 : : * the Free Software Foundation, Inc., 51 Franklin Street, Fifth
19 : : * Floor, Boston, MA 02110-1301, USA.
20 : : *
21 : : */
22 : :
23 : : /* Get GSS API. */
24 : : #include "k5internal.h"
25 : :
26 : : /* Get specification. */
27 : : #include "checksum.h"
28 : :
29 : : static void
30 : 10 : pack_uint32 (OM_uint32 i, char *buf)
31 : : {
32 : 10 : buf[0] = i & 0xFF;
33 : 10 : buf[1] = (i >> 8) & 0xFF;
34 : 10 : buf[2] = (i >> 16) & 0xFF;
35 : 10 : buf[3] = (i >> 24) & 0xFF;
36 : 10 : }
37 : :
38 : : static int
39 : 2 : hash_cb (OM_uint32 * minor_status,
40 : : gss_ctx_id_t * context_handle,
41 : : const gss_channel_bindings_t input_chan_bindings, char **out)
42 : : {
43 : 2 : gss_ctx_id_t ctx = *context_handle;
44 : 2 : _gss_krb5_ctx_t k5 = ctx->krb5;
45 : : char *buf, *p;
46 : : size_t len;
47 : : int res;
48 : :
49 : : if (input_chan_bindings->initiator_address.length > UINT32_MAX ||
50 : : input_chan_bindings->acceptor_address.length > UINT32_MAX ||
51 : : input_chan_bindings->application_data.length > UINT32_MAX)
52 : : return GSS_S_BAD_BINDINGS;
53 : :
54 : 2 : len = sizeof (OM_uint32) * 5
55 : : + input_chan_bindings->initiator_address.length
56 : : + input_chan_bindings->acceptor_address.length
57 : : + input_chan_bindings->application_data.length;
58 : 2 : p = buf = malloc (len);
59 [ - + ]: 2 : if (!buf)
60 : : {
61 [ # # ]: 0 : if (minor_status)
62 : 0 : *minor_status = ENOMEM;
63 : 0 : return GSS_S_FAILURE;
64 : : }
65 : :
66 : 2 : pack_uint32 (input_chan_bindings->initiator_addrtype, p);
67 : 2 : p += sizeof (OM_uint32);
68 : 2 : pack_uint32 (input_chan_bindings->initiator_address.length, p);
69 : 2 : p += sizeof (OM_uint32);
70 [ - + ]: 2 : if (input_chan_bindings->initiator_address.length > 0)
71 : : {
72 : 0 : memcpy (p, input_chan_bindings->initiator_address.value,
73 : : input_chan_bindings->initiator_address.length);
74 : 0 : p += input_chan_bindings->initiator_address.length;
75 : : }
76 : 2 : pack_uint32 (input_chan_bindings->acceptor_addrtype, p);
77 : 2 : p += sizeof (OM_uint32);
78 : 2 : pack_uint32 (input_chan_bindings->acceptor_address.length, p);
79 : 2 : p += sizeof (OM_uint32);
80 [ - + ]: 2 : if (input_chan_bindings->acceptor_address.length > 0)
81 : : {
82 : 0 : memcpy (p, input_chan_bindings->acceptor_address.value,
83 : : input_chan_bindings->acceptor_address.length);
84 : 0 : p += input_chan_bindings->acceptor_address.length;
85 : : }
86 : 2 : pack_uint32 (input_chan_bindings->application_data.length, p);
87 : 2 : p += sizeof (OM_uint32);
88 [ + - ]: 2 : if (input_chan_bindings->application_data.length > 0)
89 : 2 : memcpy (p, input_chan_bindings->application_data.value,
90 : : input_chan_bindings->application_data.length);
91 : :
92 : 2 : res = shishi_md5 (k5->sh, buf, len, out);
93 : 2 : free (buf);
94 [ - + ]: 2 : if (res != SHISHI_OK)
95 : 0 : return GSS_S_FAILURE;
96 : :
97 : 2 : return GSS_S_COMPLETE;
98 : : }
99 : :
100 : : /* Create the checksum value field from input parameters. */
101 : : OM_uint32
102 : 3 : _gss_krb5_checksum_pack (OM_uint32 * minor_status,
103 : : const gss_cred_id_t initiator_cred_handle,
104 : : gss_ctx_id_t * context_handle,
105 : : const gss_channel_bindings_t input_chan_bindings,
106 : : OM_uint32 req_flags, char **data, size_t * datalen)
107 : : {
108 : : char *p;
109 : :
110 : 3 : *datalen = 24;
111 : 3 : p = *data = malloc (*datalen);
112 [ - + ]: 3 : if (!p)
113 : : {
114 [ # # ]: 0 : if (minor_status)
115 : 0 : *minor_status = ENOMEM;
116 : 0 : return GSS_S_FAILURE;
117 : : }
118 : :
119 : : /*
120 : : * RFC 1964 / gssapi-cfx:
121 : : *
122 : : * The checksum value field's format is as follows:
123 : : *
124 : : * Byte Name Description
125 : : * 0..3 Lgth Number of bytes in Bnd field;
126 : : * Currently contains hex 10 00 00 00
127 : : * (16, represented in little-endian form)
128 : : */
129 : :
130 : 3 : memcpy (&p[0], "\x10\x00\x00\x00", 4); /* length of Bnd */
131 : :
132 : : /*
133 : : * 4..19 Bnd MD5 hash of channel bindings, taken over all non-null
134 : : * components of bindings, in order of declaration.
135 : : * Integer fields within channel bindings are represented
136 : : * in little-endian order for the purposes of the MD5
137 : : * calculation.
138 : : *
139 : : * In computing the contents of the "Bnd" field, the following detailed
140 : : * points apply:
141 : : *
142 : : * (1) Each integer field shall be formatted into four bytes, using
143 : : * little-endian byte ordering, for purposes of MD5 hash
144 : : * computation.
145 : : *
146 : : * (2) All input length fields within gss_buffer_desc elements of a
147 : : * gss_channel_bindings_struct, even those which are zero-valued,
148 : : * shall be included in the hash calculation; the value elements of
149 : : * gss_buffer_desc elements shall be dereferenced, and the
150 : : * resulting data shall be included within the hash computation,
151 : : * only for the case of gss_buffer_desc elements having non-zero
152 : : * length specifiers.
153 : : *
154 : : * (3) If the caller passes the value GSS_C_NO_BINDINGS instead of
155 : : * a valid channel bindings structure, the Bnd field shall be set
156 : : * to 16 zero-valued bytes.
157 : : *
158 : : */
159 : :
160 [ + + ]: 3 : if (input_chan_bindings != GSS_C_NO_CHANNEL_BINDINGS)
161 : : {
162 : : char *md5hash;
163 : : int res;
164 : :
165 : 1 : res = hash_cb (minor_status, context_handle,
166 : : input_chan_bindings, &md5hash);
167 [ - + ]: 1 : if (res != GSS_S_COMPLETE)
168 : : {
169 : 0 : free (p);
170 : 0 : return res;
171 : : }
172 : :
173 : 1 : memcpy (&p[4], md5hash, 16);
174 : 1 : free (md5hash);
175 : : }
176 : : else
177 : 2 : memset (&p[4], 0, 16);
178 : :
179 : : /*
180 : : * 20..23 Flags Bit vector of context-establishment flags,
181 : : * with values consistent with RFC-1509, p. 41:
182 : : * GSS_C_DELEG_FLAG: 1
183 : : * GSS_C_MUTUAL_FLAG: 2
184 : : * GSS_C_REPLAY_FLAG: 4
185 : : * GSS_C_SEQUENCE_FLAG: 8
186 : : * GSS_C_CONF_FLAG: 16
187 : : * GSS_C_INTEG_FLAG: 32
188 : : * The resulting bit vector is encoded into bytes 20..23
189 : : * in little-endian form.
190 : : */
191 : :
192 : 3 : req_flags &= /* GSS_C_DELEG_FLAG | */
193 : : GSS_C_MUTUAL_FLAG |
194 : : GSS_C_REPLAY_FLAG | GSS_C_SEQUENCE_FLAG |
195 : : GSS_C_CONF_FLAG | GSS_C_INTEG_FLAG;
196 : :
197 : 3 : p[20] = req_flags & 0xFF;
198 : 3 : p[21] = (req_flags >> 8) & 0xFF;
199 : 3 : p[22] = (req_flags >> 16) & 0xFF;
200 : 3 : p[23] = (req_flags >> 24) & 0xFF;
201 : :
202 : : /*
203 : : * 24..25 DlgOpt The delegation option identifier (=1) in
204 : : * little-endian order [optional]. This field
205 : : * and the next two fields are present if and
206 : : * only if GSS_C_DELEG_FLAG is set as described
207 : : * in section 4.1.1.1.
208 : : * 26..27 Dlgth The length of the Deleg field in little-
209 : : * endian order [optional].
210 : : * 28..(n-1) Deleg A KRB_CRED message (n = Dlgth + 28)
211 : : * [optional].
212 : : * n..last Exts Extensions [optional].
213 : : *
214 : : */
215 : :
216 : 3 : if (req_flags & GSS_C_DELEG_FLAG)
217 : : {
218 : : /* XXX We don't support credential delegation yet. We should
219 : : not fail here, as GSS_C_DELEG_FLAG is masked out above, and
220 : : in context.c. */
221 : : }
222 : :
223 : 3 : return GSS_S_COMPLETE;
224 : : }
225 : :
226 : : OM_uint32
227 : 3 : _gss_krb5_checksum_parse (OM_uint32 * minor_status,
228 : : gss_ctx_id_t * context_handle,
229 : : const gss_channel_bindings_t input_chan_bindings)
230 : : {
231 : 3 : gss_ctx_id_t ctx = *context_handle;
232 : 3 : _gss_krb5_ctx_t k5 = ctx->krb5;
233 : 3 : char *out = NULL;
234 : 3 : size_t len = 0;
235 : : int rc;
236 : : char *md5hash;
237 : :
238 [ - + ]: 3 : if (shishi_ap_authenticator_cksumtype (k5->ap) != 0x8003)
239 : : {
240 [ # # ]: 0 : if (minor_status)
241 : 0 : *minor_status = GSS_KRB5_S_G_VALIDATE_FAILED;
242 : 0 : return GSS_S_FAILURE;
243 : : }
244 : :
245 : 3 : rc = shishi_ap_authenticator_cksumdata (k5->ap, out, &len);
246 [ - + ]: 3 : if (rc != SHISHI_TOO_SMALL_BUFFER)
247 : 0 : return GSS_S_FAILURE;
248 : :
249 : 3 : out = malloc (len);
250 [ - + ]: 3 : if (!out)
251 : : {
252 [ # # ]: 0 : if (minor_status)
253 : 0 : *minor_status = ENOMEM;
254 : 0 : return GSS_S_FAILURE;
255 : : }
256 : :
257 : 3 : rc = shishi_ap_authenticator_cksumdata (k5->ap, out, &len);
258 [ - + ]: 3 : if (rc != SHISHI_OK)
259 : : {
260 : 0 : free (out);
261 : 0 : return GSS_S_FAILURE;
262 : : }
263 : :
264 [ - + ]: 3 : if (memcmp (out, "\x10\x00\x00\x00", 4) != 0)
265 : : {
266 : 0 : free (out);
267 : 0 : return GSS_S_DEFECTIVE_TOKEN;
268 : : }
269 : :
270 [ + + ]: 3 : if (input_chan_bindings != GSS_C_NO_CHANNEL_BINDINGS)
271 : : {
272 : 1 : rc = hash_cb (minor_status, context_handle,
273 : : input_chan_bindings, &md5hash);
274 [ - + ]: 1 : if (rc != GSS_S_COMPLETE)
275 : : {
276 : 0 : free (out);
277 : 0 : return GSS_S_DEFECTIVE_TOKEN;
278 : : }
279 : :
280 : 1 : rc = memcmp (&out[4], md5hash, 16);
281 : :
282 : 1 : free (md5hash);
283 : : }
284 : : else
285 : : {
286 : : char zeros[16];
287 : 2 : memset (&zeros[0], 0, sizeof zeros);
288 : 2 : rc = memcmp (&out[4], zeros, 16);
289 : : }
290 : :
291 : 3 : free (out);
292 : :
293 [ - + ]: 3 : if (rc != 0)
294 : 0 : return GSS_S_DEFECTIVE_TOKEN;
295 : :
296 : 3 : return GSS_S_COMPLETE;
297 : : }
|