~zulcss/samba/server-dailies-3.4

« back to all changes in this revision

Viewing changes to source4/heimdal/lib/gssapi/krb5/unwrap.c

  • Committer: Chuck Short
  • Date: 2010-09-28 20:38:39 UTC
  • Revision ID: zulcss@ubuntu.com-20100928203839-pgjulytsi9ue63x1
Initial version

Show diffs side-by-side

added added

removed removed

Lines of Context:
 
1
/*
 
2
 * Copyright (c) 1997 - 2004 Kungliga Tekniska Högskolan
 
3
 * (Royal Institute of Technology, Stockholm, Sweden).
 
4
 * All rights reserved.
 
5
 *
 
6
 * Redistribution and use in source and binary forms, with or without
 
7
 * modification, are permitted provided that the following conditions
 
8
 * are met:
 
9
 *
 
10
 * 1. Redistributions of source code must retain the above copyright
 
11
 *    notice, this list of conditions and the following disclaimer.
 
12
 *
 
13
 * 2. Redistributions in binary form must reproduce the above copyright
 
14
 *    notice, this list of conditions and the following disclaimer in the
 
15
 *    documentation and/or other materials provided with the distribution.
 
16
 *
 
17
 * 3. Neither the name of the Institute nor the names of its contributors
 
18
 *    may be used to endorse or promote products derived from this software
 
19
 *    without specific prior written permission.
 
20
 *
 
21
 * THIS SOFTWARE IS PROVIDED BY THE INSTITUTE AND CONTRIBUTORS ``AS IS'' AND
 
22
 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
 
23
 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
 
24
 * ARE DISCLAIMED.  IN NO EVENT SHALL THE INSTITUTE OR CONTRIBUTORS BE LIABLE
 
25
 * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
 
26
 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
 
27
 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
 
28
 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
 
29
 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
 
30
 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
 
31
 * SUCH DAMAGE.
 
32
 */
 
33
 
 
34
#include "krb5/gsskrb5_locl.h"
 
35
 
 
36
RCSID("$Id$");
 
37
 
 
38
static OM_uint32
 
39
unwrap_des
 
40
           (OM_uint32 * minor_status,
 
41
            const gsskrb5_ctx context_handle,
 
42
            const gss_buffer_t input_message_buffer,
 
43
            gss_buffer_t output_message_buffer,
 
44
            int * conf_state,
 
45
            gss_qop_t * qop_state,
 
46
            krb5_keyblock *key
 
47
           )
 
48
{
 
49
  u_char *p, *seq;
 
50
  size_t len;
 
51
  MD5_CTX md5;
 
52
  u_char hash[16];
 
53
  DES_key_schedule schedule;
 
54
  DES_cblock deskey;
 
55
  DES_cblock zero;
 
56
  int i;
 
57
  uint32_t seq_number;
 
58
  size_t padlength;
 
59
  OM_uint32 ret;
 
60
  int cstate;
 
61
  int cmp;
 
62
  int token_len;
 
63
 
 
64
  if (IS_DCE_STYLE(context_handle)) {
 
65
     token_len = 22 + 8 + 15; /* 45 */
 
66
  } else {
 
67
     token_len = input_message_buffer->length;
 
68
  }
 
69
 
 
70
  p = input_message_buffer->value;
 
71
  ret = _gsskrb5_verify_header (&p,
 
72
                                   token_len,
 
73
                                   "\x02\x01",
 
74
                                   GSS_KRB5_MECHANISM);
 
75
  if (ret)
 
76
      return ret;
 
77
 
 
78
  if (memcmp (p, "\x00\x00", 2) != 0)
 
79
    return GSS_S_BAD_SIG;
 
80
  p += 2;
 
81
  if (memcmp (p, "\x00\x00", 2) == 0) {
 
82
      cstate = 1;
 
83
  } else if (memcmp (p, "\xFF\xFF", 2) == 0) {
 
84
      cstate = 0;
 
85
  } else
 
86
      return GSS_S_BAD_MIC;
 
87
  p += 2;
 
88
  if(conf_state != NULL)
 
89
      *conf_state = cstate;
 
90
  if (memcmp (p, "\xff\xff", 2) != 0)
 
91
    return GSS_S_DEFECTIVE_TOKEN;
 
92
  p += 2;
 
93
  p += 16;
 
94
 
 
95
  len = p - (u_char *)input_message_buffer->value;
 
96
 
 
97
  if(cstate) {
 
98
      /* decrypt data */
 
99
      memcpy (&deskey, key->keyvalue.data, sizeof(deskey));
 
100
 
 
101
      for (i = 0; i < sizeof(deskey); ++i)
 
102
          deskey[i] ^= 0xf0;
 
103
      DES_set_key_unchecked (&deskey, &schedule);
 
104
      memset (&zero, 0, sizeof(zero));
 
105
      DES_cbc_encrypt ((void *)p,
 
106
                       (void *)p,
 
107
                       input_message_buffer->length - len,
 
108
                       &schedule,
 
109
                       &zero,
 
110
                       DES_DECRYPT);
 
111
 
 
112
      memset (deskey, 0, sizeof(deskey));
 
113
      memset (&schedule, 0, sizeof(schedule));
 
114
  }
 
115
 
 
116
  if (IS_DCE_STYLE(context_handle)) {
 
117
    padlength = 0;
 
118
  } else {
 
119
    /* check pad */
 
120
    ret = _gssapi_verify_pad(input_message_buffer,
 
121
                             input_message_buffer->length - len,
 
122
                             &padlength);
 
123
    if (ret)
 
124
        return ret;
 
125
  }
 
126
 
 
127
  MD5_Init (&md5);
 
128
  MD5_Update (&md5, p - 24, 8);
 
129
  MD5_Update (&md5, p, input_message_buffer->length - len);
 
130
  MD5_Final (hash, &md5);
 
131
 
 
132
  memset (&zero, 0, sizeof(zero));
 
133
  memcpy (&deskey, key->keyvalue.data, sizeof(deskey));
 
134
  DES_set_key_unchecked (&deskey, &schedule);
 
135
  DES_cbc_cksum ((void *)hash, (void *)hash, sizeof(hash),
 
136
                 &schedule, &zero);
 
137
  if (memcmp (p - 8, hash, 8) != 0)
 
138
    return GSS_S_BAD_MIC;
 
139
 
 
140
  /* verify sequence number */
 
141
 
 
142
  HEIMDAL_MUTEX_lock(&context_handle->ctx_id_mutex);
 
143
 
 
144
  p -= 16;
 
145
  DES_set_key_unchecked (&deskey, &schedule);
 
146
  DES_cbc_encrypt ((void *)p, (void *)p, 8,
 
147
                   &schedule, (DES_cblock *)hash, DES_DECRYPT);
 
148
 
 
149
  memset (deskey, 0, sizeof(deskey));
 
150
  memset (&schedule, 0, sizeof(schedule));
 
151
 
 
152
  seq = p;
 
153
  _gsskrb5_decode_om_uint32(seq, &seq_number);
 
154
 
 
155
  if (context_handle->more_flags & LOCAL)
 
156
      cmp = memcmp(&seq[4], "\xff\xff\xff\xff", 4);
 
157
  else
 
158
      cmp = memcmp(&seq[4], "\x00\x00\x00\x00", 4);
 
159
 
 
160
  if (cmp != 0) {
 
161
    HEIMDAL_MUTEX_unlock(&context_handle->ctx_id_mutex);
 
162
    return GSS_S_BAD_MIC;
 
163
  }
 
164
 
 
165
  ret = _gssapi_msg_order_check(context_handle->order, seq_number);
 
166
  if (ret) {
 
167
    HEIMDAL_MUTEX_unlock(&context_handle->ctx_id_mutex);
 
168
    return ret;
 
169
  }
 
170
 
 
171
  HEIMDAL_MUTEX_unlock(&context_handle->ctx_id_mutex);
 
172
 
 
173
  /* copy out data */
 
174
 
 
175
  output_message_buffer->length = input_message_buffer->length
 
176
    - len - padlength - 8;
 
177
  output_message_buffer->value  = malloc(output_message_buffer->length);
 
178
  if(output_message_buffer->length != 0 && output_message_buffer->value == NULL)
 
179
      return GSS_S_FAILURE;
 
180
  memcpy (output_message_buffer->value,
 
181
          p + 24,
 
182
          output_message_buffer->length);
 
183
  return GSS_S_COMPLETE;
 
184
}
 
185
 
 
186
static OM_uint32
 
187
unwrap_des3
 
188
           (OM_uint32 * minor_status,
 
189
            const gsskrb5_ctx context_handle,
 
190
            krb5_context context,
 
191
            const gss_buffer_t input_message_buffer,
 
192
            gss_buffer_t output_message_buffer,
 
193
            int * conf_state,
 
194
            gss_qop_t * qop_state,
 
195
            krb5_keyblock *key
 
196
           )
 
197
{
 
198
  u_char *p;
 
199
  size_t len;
 
200
  u_char *seq;
 
201
  krb5_data seq_data;
 
202
  u_char cksum[20];
 
203
  uint32_t seq_number;
 
204
  size_t padlength;
 
205
  OM_uint32 ret;
 
206
  int cstate;
 
207
  krb5_crypto crypto;
 
208
  Checksum csum;
 
209
  int cmp;
 
210
  int token_len;
 
211
 
 
212
  if (IS_DCE_STYLE(context_handle)) {
 
213
     token_len = 34 + 8 + 15; /* 57 */
 
214
  } else {
 
215
     token_len = input_message_buffer->length;
 
216
  }
 
217
 
 
218
  p = input_message_buffer->value;
 
219
  ret = _gsskrb5_verify_header (&p,
 
220
                                   token_len,
 
221
                                   "\x02\x01",
 
222
                                   GSS_KRB5_MECHANISM);
 
223
  if (ret)
 
224
      return ret;
 
225
 
 
226
  if (memcmp (p, "\x04\x00", 2) != 0) /* HMAC SHA1 DES3_KD */
 
227
    return GSS_S_BAD_SIG;
 
228
  p += 2;
 
229
  if (memcmp (p, "\x02\x00", 2) == 0) {
 
230
    cstate = 1;
 
231
  } else if (memcmp (p, "\xff\xff", 2) == 0) {
 
232
    cstate = 0;
 
233
  } else
 
234
    return GSS_S_BAD_MIC;
 
235
  p += 2;
 
236
  if(conf_state != NULL)
 
237
    *conf_state = cstate;
 
238
  if (memcmp (p, "\xff\xff", 2) != 0)
 
239
    return GSS_S_DEFECTIVE_TOKEN;
 
240
  p += 2;
 
241
  p += 28;
 
242
 
 
243
  len = p - (u_char *)input_message_buffer->value;
 
244
 
 
245
  if(cstate) {
 
246
      /* decrypt data */
 
247
      krb5_data tmp;
 
248
 
 
249
      ret = krb5_crypto_init(context, key,
 
250
                             ETYPE_DES3_CBC_NONE, &crypto);
 
251
      if (ret) {
 
252
          *minor_status = ret;
 
253
          return GSS_S_FAILURE;
 
254
      }
 
255
      ret = krb5_decrypt(context, crypto, KRB5_KU_USAGE_SEAL,
 
256
                         p, input_message_buffer->length - len, &tmp);
 
257
      krb5_crypto_destroy(context, crypto);
 
258
      if (ret) {
 
259
          *minor_status = ret;
 
260
          return GSS_S_FAILURE;
 
261
      }
 
262
      assert (tmp.length == input_message_buffer->length - len);
 
263
 
 
264
      memcpy (p, tmp.data, tmp.length);
 
265
      krb5_data_free(&tmp);
 
266
  }
 
267
 
 
268
  if (IS_DCE_STYLE(context_handle)) {
 
269
    padlength = 0;
 
270
  } else {
 
271
    /* check pad */
 
272
    ret = _gssapi_verify_pad(input_message_buffer,
 
273
                             input_message_buffer->length - len,
 
274
                             &padlength);
 
275
    if (ret)
 
276
        return ret;
 
277
  }
 
278
 
 
279
  /* verify sequence number */
 
280
 
 
281
  HEIMDAL_MUTEX_lock(&context_handle->ctx_id_mutex);
 
282
 
 
283
  p -= 28;
 
284
 
 
285
  ret = krb5_crypto_init(context, key,
 
286
                         ETYPE_DES3_CBC_NONE, &crypto);
 
287
  if (ret) {
 
288
      *minor_status = ret;
 
289
      HEIMDAL_MUTEX_unlock(&context_handle->ctx_id_mutex);
 
290
      return GSS_S_FAILURE;
 
291
  }
 
292
  {
 
293
      DES_cblock ivec;
 
294
 
 
295
      memcpy(&ivec, p + 8, 8);
 
296
      ret = krb5_decrypt_ivec (context,
 
297
                               crypto,
 
298
                               KRB5_KU_USAGE_SEQ,
 
299
                               p, 8, &seq_data,
 
300
                               &ivec);
 
301
  }
 
302
  krb5_crypto_destroy (context, crypto);
 
303
  if (ret) {
 
304
      *minor_status = ret;
 
305
      HEIMDAL_MUTEX_unlock(&context_handle->ctx_id_mutex);
 
306
      return GSS_S_FAILURE;
 
307
  }
 
308
  if (seq_data.length != 8) {
 
309
      krb5_data_free (&seq_data);
 
310
      *minor_status = 0;
 
311
      HEIMDAL_MUTEX_unlock(&context_handle->ctx_id_mutex);
 
312
      return GSS_S_BAD_MIC;
 
313
  }
 
314
 
 
315
  seq = seq_data.data;
 
316
  _gsskrb5_decode_om_uint32(seq, &seq_number);
 
317
 
 
318
  if (context_handle->more_flags & LOCAL)
 
319
      cmp = memcmp(&seq[4], "\xff\xff\xff\xff", 4);
 
320
  else
 
321
      cmp = memcmp(&seq[4], "\x00\x00\x00\x00", 4);
 
322
 
 
323
  krb5_data_free (&seq_data);
 
324
  if (cmp != 0) {
 
325
      *minor_status = 0;
 
326
      HEIMDAL_MUTEX_unlock(&context_handle->ctx_id_mutex);
 
327
      return GSS_S_BAD_MIC;
 
328
  }
 
329
 
 
330
  ret = _gssapi_msg_order_check(context_handle->order, seq_number);
 
331
  if (ret) {
 
332
      *minor_status = 0;
 
333
      HEIMDAL_MUTEX_unlock(&context_handle->ctx_id_mutex);
 
334
      return ret;
 
335
  }
 
336
 
 
337
  HEIMDAL_MUTEX_unlock(&context_handle->ctx_id_mutex);
 
338
 
 
339
  /* verify checksum */
 
340
 
 
341
  memcpy (cksum, p + 8, 20);
 
342
 
 
343
  memcpy (p + 20, p - 8, 8);
 
344
 
 
345
  csum.cksumtype = CKSUMTYPE_HMAC_SHA1_DES3;
 
346
  csum.checksum.length = 20;
 
347
  csum.checksum.data   = cksum;
 
348
 
 
349
  ret = krb5_crypto_init(context, key, 0, &crypto);
 
350
  if (ret) {
 
351
      *minor_status = ret;
 
352
      return GSS_S_FAILURE;
 
353
  }
 
354
 
 
355
  ret = krb5_verify_checksum (context, crypto,
 
356
                              KRB5_KU_USAGE_SIGN,
 
357
                              p + 20,
 
358
                              input_message_buffer->length - len + 8,
 
359
                              &csum);
 
360
  krb5_crypto_destroy (context, crypto);
 
361
  if (ret) {
 
362
      *minor_status = ret;
 
363
      return GSS_S_FAILURE;
 
364
  }
 
365
 
 
366
  /* copy out data */
 
367
 
 
368
  output_message_buffer->length = input_message_buffer->length
 
369
    - len - padlength - 8;
 
370
  output_message_buffer->value  = malloc(output_message_buffer->length);
 
371
  if(output_message_buffer->length != 0 && output_message_buffer->value == NULL)
 
372
      return GSS_S_FAILURE;
 
373
  memcpy (output_message_buffer->value,
 
374
          p + 36,
 
375
          output_message_buffer->length);
 
376
  return GSS_S_COMPLETE;
 
377
}
 
378
 
 
379
OM_uint32 _gsskrb5_unwrap
 
380
           (OM_uint32 * minor_status,
 
381
            const gss_ctx_id_t context_handle,
 
382
            const gss_buffer_t input_message_buffer,
 
383
            gss_buffer_t output_message_buffer,
 
384
            int * conf_state,
 
385
            gss_qop_t * qop_state
 
386
           )
 
387
{
 
388
  krb5_keyblock *key;
 
389
  krb5_context context;
 
390
  OM_uint32 ret;
 
391
  krb5_keytype keytype;
 
392
  gsskrb5_ctx ctx = (gsskrb5_ctx) context_handle;
 
393
 
 
394
  output_message_buffer->value = NULL;
 
395
  output_message_buffer->length = 0;
 
396
 
 
397
  GSSAPI_KRB5_INIT (&context);
 
398
 
 
399
  if (qop_state != NULL)
 
400
      *qop_state = GSS_C_QOP_DEFAULT;
 
401
  HEIMDAL_MUTEX_lock(&ctx->ctx_id_mutex);
 
402
  ret = _gsskrb5i_get_token_key(ctx, context, &key);
 
403
  HEIMDAL_MUTEX_unlock(&ctx->ctx_id_mutex);
 
404
  if (ret) {
 
405
      *minor_status = ret;
 
406
      return GSS_S_FAILURE;
 
407
  }
 
408
  krb5_enctype_to_keytype (context, key->keytype, &keytype);
 
409
 
 
410
  *minor_status = 0;
 
411
 
 
412
  switch (keytype) {
 
413
  case KEYTYPE_DES :
 
414
      ret = unwrap_des (minor_status, ctx,
 
415
                        input_message_buffer, output_message_buffer,
 
416
                        conf_state, qop_state, key);
 
417
      break;
 
418
  case KEYTYPE_DES3 :
 
419
      ret = unwrap_des3 (minor_status, ctx, context,
 
420
                         input_message_buffer, output_message_buffer,
 
421
                         conf_state, qop_state, key);
 
422
      break;
 
423
  case KEYTYPE_ARCFOUR:
 
424
  case KEYTYPE_ARCFOUR_56:
 
425
      ret = _gssapi_unwrap_arcfour (minor_status, ctx, context,
 
426
                                    input_message_buffer, output_message_buffer,
 
427
                                    conf_state, qop_state, key);
 
428
      break;
 
429
  default :
 
430
      ret = _gssapi_unwrap_cfx (minor_status, ctx, context,
 
431
                                input_message_buffer, output_message_buffer,
 
432
                                conf_state, qop_state, key);
 
433
      break;
 
434
  }
 
435
  krb5_free_keyblock (context, key);
 
436
  return ret;
 
437
}