1 /*
2 * Copyright (c) 1999, 2010, Oracle and/or its affiliates. All rights reserved.
3 */
4 /*
5 * Copyright 2001 by the Massachusetts Institute of Technology.
6 * Copyright 1993 by OpenVision Technologies, Inc.
7 *
8 * Permission to use, copy, modify, distribute, and sell this software
9 * and its documentation for any purpose is hereby granted without fee,
10 * provided that the above copyright notice appears in all copies and
11 * that both that copyright notice and this permission notice appear in
12 * supporting documentation, and that the name of OpenVision not be used
13 * in advertising or publicity pertaining to distribution of the software
14 * without specific, written prior permission. OpenVision makes no
15 * representations about the suitability of this software for any
16 * purpose. It is provided "as is" without express or implied warranty.
17 *
18 * OPENVISION DISCLAIMS ALL WARRANTIES WITH REGARD TO THIS SOFTWARE,
19 * INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS, IN NO
20 * EVENT SHALL OPENVISION BE LIABLE FOR ANY SPECIAL, INDIRECT OR
21 * CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF
22 * USE, DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR
23 * OTHER TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR
24 * PERFORMANCE OF THIS SOFTWARE.
25 */
26
27 /*
28 * Copyright (C) 1998 by the FundsXpress, INC.
29 *
30 * All rights reserved.
31 *
32 * Export of this software from the United States of America may require
33 * a specific license from the United States Government. It is the
34 * responsibility of any person or organization contemplating export to
35 * obtain such a license before exporting.
36 *
37 * WITHIN THAT CONSTRAINT, permission to use, copy, modify, and
38 * distribute this software and its documentation for any purpose and
39 * without fee is hereby granted, provided that the above copyright
40 * notice appear in all copies and that both that copyright notice and
41 * this permission notice appear in supporting documentation, and that
42 * the name of FundsXpress. not be used in advertising or publicity pertaining
43 * to distribution of the software without specific, written prior
44 * permission. FundsXpress makes no representations about the suitability of
45 * this software for any purpose. It is provided "as is" without express
46 * or implied warranty.
47 *
48 * THIS SOFTWARE IS PROVIDED ``AS IS'' AND WITHOUT ANY EXPRESS OR
49 * IMPLIED WARRANTIES, INCLUDING, WITHOUT LIMITATION, THE IMPLIED
50 * WARRANTIES OF MERCHANTIBILITY AND FITNESS FOR A PARTICULAR PURPOSE.
51 */
52
53 #include "gssapiP_krb5.h"
54 #include "k5-int.h"
55
56 /* message_buffer is an input if SIGN, output if SEAL, and ignored if DEL_CTX
57 conf_state is only valid if SEAL. */
58
59 static OM_uint32
kg_unseal_v1(context,minor_status,ctx,ptr,bodysize,message_buffer,conf_state,qop_state,toktype)60 kg_unseal_v1(context, minor_status, ctx, ptr, bodysize, message_buffer,
61 conf_state, qop_state, toktype)
62 krb5_context context;
63 OM_uint32 *minor_status;
64 krb5_gss_ctx_id_rec *ctx;
65 unsigned char *ptr;
66 int bodysize;
67 gss_buffer_t message_buffer;
68 int *conf_state;
69 int *qop_state;
70 int toktype;
71 {
72 krb5_error_code code;
73 int conflen = 0;
74 int signalg;
75 int sealalg;
76 gss_buffer_desc token;
77 krb5_checksum cksum;
78 krb5_checksum md5cksum;
79 krb5_data plaind;
80 char *data_ptr;
81 krb5_timestamp now;
82 unsigned char *plain;
83 unsigned int cksum_len = 0;
84 size_t plainlen;
85 int direction;
86 krb5_ui_4 seqnum;
87 OM_uint32 retval;
88 size_t sumlen, blocksize;
89 int tmsglen;
90 krb5_keyusage sign_usage = KG_USAGE_SIGN;
91
92 KRB5_LOG0(KRB5_INFO, "kg_unseal_v1() start\n");
93
94 /* Solaris Kerberos: make sure this is initialized */
95 *minor_status = 0;
96
97 if (toktype == KG_TOK_SEAL_MSG) {
98 message_buffer->length = 0;
99 message_buffer->value = NULL;
100 }
101
102 /* get the sign and seal algorithms */
103
104 signalg = ptr[0] + (ptr[1]<<8);
105 sealalg = ptr[2] + (ptr[3]<<8);
106
107 /* Sanity checks */
108
109 if ((ptr[4] != 0xff) || (ptr[5] != 0xff)) {
110 *minor_status = 0;
111 KRB5_LOG0(KRB5_ERR, "kg_unseal_v1() end, error GSS_S_DEFECTIVE_TOKEN\n");
112 return GSS_S_DEFECTIVE_TOKEN;
113 }
114
115 if ((toktype != KG_TOK_SEAL_MSG) &&
116 (sealalg != 0xffff)) {
117 *minor_status = 0;
118 KRB5_LOG0(KRB5_ERR, "kg_unseal_v1() end, error2 GSS_S_DEFECTIVE_TOKEN\n");
119 return GSS_S_DEFECTIVE_TOKEN;
120 }
121
122 /* in the current spec, there is only one valid seal algorithm per
123 key type, so a simple comparison is ok */
124
125 if ((toktype == KG_TOK_SEAL_MSG) &&
126 !((sealalg == 0xffff) ||
127 (sealalg == ctx->sealalg))) {
128 *minor_status = 0;
129 KRB5_LOG0(KRB5_ERR, "kg_unseal_v1() end, error3 GSS_S_DEFECTIVE_TOKEN\n");
130 return GSS_S_DEFECTIVE_TOKEN;
131 }
132
133 /* there are several mappings of seal algorithms to sign algorithms,
134 but few enough that we can try them all. */
135
136 if ((ctx->sealalg == SEAL_ALG_NONE && signalg > 1) ||
137 (ctx->sealalg == SEAL_ALG_1 && signalg != SGN_ALG_3) ||
138 (ctx->sealalg == SEAL_ALG_DES3KD &&
139 signalg != SGN_ALG_HMAC_SHA1_DES3_KD)||
140 (ctx->sealalg == SEAL_ALG_MICROSOFT_RC4 &&
141 signalg != SGN_ALG_HMAC_MD5)) {
142 *minor_status = 0;
143 KRB5_LOG0(KRB5_ERR, "kg_unseal_v1() end, error4 GSS_S_DEFECTIVE_TOKEN\n");
144 return GSS_S_DEFECTIVE_TOKEN;
145 }
146
147 KRB5_LOG(KRB5_INFO, "kg_unseal_v1() signalg = %d\n", signalg);
148
149 switch (signalg) {
150 case SGN_ALG_DES_MAC_MD5:
151 case SGN_ALG_MD2_5:
152 case SGN_ALG_HMAC_MD5:
153 cksum_len = 8;
154 if (toktype != KG_TOK_SEAL_MSG)
155 sign_usage = 15;
156 break;
157 case SGN_ALG_3:
158 cksum_len = 16;
159 break;
160 case SGN_ALG_HMAC_SHA1_DES3_KD:
161 cksum_len = 20;
162 break;
163 default:
164 *minor_status = 0;
165 KRB5_LOG(KRB5_ERR, "kg_unseal_v1() end, error signalg=%d\n", signalg);
166 return GSS_S_DEFECTIVE_TOKEN;
167 }
168
169 #ifdef _KERNEL
170 /*
171 * Because the ARCFOUR code bypasses the standard
172 * crypto interfaces, we must make sure the kernel
173 * crypto framework mechanism types are properly
174 * initialized here.
175 */
176 context->kef_cipher_mt = get_cipher_mech_type(context,
177 ctx->seq);
178 context->kef_hash_mt = get_hash_mech_type(context,
179 ctx->seq);
180 if ((code = init_key_kef(context->kef_cipher_mt,
181 ctx->seq))) {
182 *minor_status = code;
183 return (GSS_S_FAILURE);
184 }
185 if ((code = init_key_kef(context->kef_cipher_mt,
186 ctx->enc))) {
187 *minor_status = code;
188 return (GSS_S_FAILURE);
189 }
190 #endif /* _KERNEL */
191
192 /* get the token parameters */
193
194 if ((code = kg_get_seq_num(context, ctx->seq, ptr+14, ptr+6, &direction,
195 &seqnum))) {
196 *minor_status = code;
197 return(GSS_S_BAD_SIG);
198 }
199
200 /* decode the message, if SEAL */
201
202 if (toktype == KG_TOK_SEAL_MSG) {
203 tmsglen = bodysize-(14+cksum_len);
204 KRB5_LOG1(KRB5_INFO, "kg_unseal_v1() tmsglen = %d cksum_len = %d",
205 tmsglen, cksum_len);
206 KRB5_LOG0(KRB5_INFO, "kg_unseal_v1() toktype == KG_TOK_SEAL_MSG\n");
207
208 if (sealalg != 0xffff) {
209 if ((plain = (unsigned char *) xmalloc(tmsglen)) == NULL) {
210 *minor_status = ENOMEM;
211 KRB5_LOG0(KRB5_ERR, "kg_unseal_v1() end, error ENOMEM\n");
212 return(GSS_S_FAILURE);
213 }
214 if (ctx->enc->enctype == ENCTYPE_ARCFOUR_HMAC) {
215 unsigned char bigend_seqnum[4];
216 krb5_keyblock *enc_key;
217 int i;
218 bigend_seqnum[0] = (seqnum>>24) & 0xff;
219 bigend_seqnum[1] = (seqnum>>16) & 0xff;
220 bigend_seqnum[2] = (seqnum>>8) & 0xff;
221 bigend_seqnum[3] = seqnum & 0xff;
222 code = krb5_copy_keyblock (context, ctx->enc, &enc_key);
223 if (code)
224 {
225 xfree_wrap(plain, tmsglen);
226 *minor_status = code;
227 return(GSS_S_FAILURE);
228 }
229
230 for (i = 0; i <= 15; i++)
231 ((char *) enc_key->contents)[i] ^=0xf0;
232
233 #ifndef _KERNEL
234 /*
235 * The enc_key contents were modified, delete the
236 * key object so it doesn't get used later.
237 */
238 if (enc_key->hKey != CK_INVALID_HANDLE) {
239 (void)C_DestroyObject(krb_ctx_hSession(context),
240 enc_key->hKey);
241 enc_key->hKey = CK_INVALID_HANDLE;
242 }
243 #endif
244 KRB5_LOG(KRB5_INFO, "kg_unseal_v1() enc_key->enctype = %d",
245 enc_key->enctype);
246
247 code = kg_arcfour_docrypt (context,
248 enc_key, 0,
249 &bigend_seqnum[0], 4,
250 ptr+14+cksum_len, tmsglen,
251 plain);
252 krb5_free_keyblock (context, enc_key);
253 } else {
254 code = kg_decrypt(context, ctx->enc, KG_USAGE_SEAL, NULL,
255 ptr+14+cksum_len, plain, tmsglen);
256 }
257 if (code) {
258 xfree_wrap(plain, tmsglen);
259 *minor_status = code;
260 return(GSS_S_FAILURE);
261 }
262 } else {
263 plain = ptr+14+cksum_len;
264 }
265
266 plainlen = tmsglen;
267
268 if ((sealalg == 0xffff) && ctx->big_endian) {
269 token.length = tmsglen;
270 } else {
271 conflen = kg_confounder_size(context, ctx->enc);
272 /*
273 * Solaris Kerberos: we want to perform a sanity check on the
274 * pad length, so we know it can not be more than the blocksize.
275 */
276 code = krb5_c_block_size(context, ctx->enc->enctype, &blocksize);
277 if (code != 0) {
278 if (sealalg != 0xffff)
279 xfree_wrap(plain, tmsglen);
280 *minor_status = code;
281 return(GSS_S_FAILURE);
282 }
283 if (plain[tmsglen-1] > blocksize) {
284 if (sealalg != 0xffff)
285 xfree_wrap(plain, tmsglen);
286 *minor_status = KG_BAD_LENGTH;
287 return(GSS_S_FAILURE);
288 }
289 token.length = tmsglen - conflen - plain[tmsglen-1];
290 }
291
292 if (token.length) {
293 if ((token.value = (void *) xmalloc(token.length)) == NULL) {
294 if (sealalg != 0xffff)
295 xfree_wrap(plain, tmsglen);
296 *minor_status = ENOMEM;
297 KRB5_LOG0(KRB5_ERR, "kg_unseal_v1() end, error2 ENOMEM\n");
298 return(GSS_S_FAILURE);
299 }
300 (void) memcpy(token.value, plain+conflen, token.length);
301 } else {
302 token.value = NULL;
303 }
304 } else if (toktype == KG_TOK_SIGN_MSG) {
305 KRB5_LOG0(KRB5_INFO, "kg_unseal_v1() toktype == KG_TOK_SIGN_MSG\n");
306 token = *message_buffer;
307 plain = token.value;
308 plainlen = token.length;
309 } else {
310 KRB5_LOG0(KRB5_INFO, "kg_unseal_v1() toktype == NULL\n");
311 token.length = 0;
312 token.value = NULL;
313 plain = token.value;
314 plainlen = token.length;
315 }
316
317 /* compute the checksum of the message */
318
319 /* initialize the the cksum */
320 switch (signalg) {
321 case SGN_ALG_DES_MAC_MD5:
322 case SGN_ALG_MD2_5:
323 case SGN_ALG_DES_MAC:
324 case SGN_ALG_3:
325 md5cksum.checksum_type = CKSUMTYPE_RSA_MD5;
326 break;
327 case SGN_ALG_HMAC_MD5:
328 md5cksum.checksum_type = CKSUMTYPE_HMAC_MD5_ARCFOUR;
329 break;
330 case SGN_ALG_HMAC_SHA1_DES3_KD:
331 md5cksum.checksum_type = CKSUMTYPE_HMAC_SHA1_DES3;
332 break;
333 default:
334 KRB5_LOG(KRB5_ERR, "kg_unseal_v1() end, error2 signalg=%d\n", signalg);
335 #ifndef _KERNEL
336 abort ();
337 #else
338 *minor_status = 0;
339 return(GSS_S_DEFECTIVE_TOKEN);
340 #endif /* _KERNEL */
341 }
342
343 code = krb5_c_checksum_length(context, md5cksum.checksum_type, &sumlen);
344 if (code)
345 {
346 KRB5_LOG(KRB5_ERR, "kg_unseal_v1() end, krb5_c_checksum_length() error "
347 "code=%d\n", code);
348 return(code);
349 }
350 md5cksum.length = (size_t)sumlen;
351
352 switch (signalg) {
353 case SGN_ALG_DES_MAC_MD5:
354 case SGN_ALG_3:
355 /* compute the checksum of the message */
356
357 /* 8 = bytes of token body to be checksummed according to spec */
358
359 if (! (data_ptr = (void *)
360 xmalloc(8 + (ctx->big_endian ? token.length : plainlen)))) {
361 if (sealalg != 0xffff)
362 xfree_wrap(plain, tmsglen);
363 if (toktype == KG_TOK_SEAL_MSG) {
364 xfree_wrap(token.value, token.length);
365 /* Solaris Kerberos: just to be safe since token.value is an
366 * output parameter.
367 */
368 token.value = NULL;
369 token.length = 0;
370 }
371 *minor_status = ENOMEM;
372 KRB5_LOG0(KRB5_ERR, "kg_unseal_v1() end, error3 ENOMEM\n");
373 return(GSS_S_FAILURE);
374 }
375
376 (void) memcpy(data_ptr, ptr-2, 8);
377
378 if (ctx->big_endian)
379 (void) memcpy(data_ptr+8, token.value, token.length);
380 else
381 (void) memcpy(data_ptr+8, plain, plainlen);
382
383 plaind.length = 8 + (ctx->big_endian ? token.length : plainlen);
384 plaind.data = data_ptr;
385 code = krb5_c_make_checksum(context, md5cksum.checksum_type,
386 ctx->seq, sign_usage,
387 &plaind, &md5cksum);
388 xfree_wrap(data_ptr, 8 + (ctx->big_endian ? token.length : plainlen));
389
390 if (code) {
391 if (toktype == KG_TOK_SEAL_MSG) {
392 xfree_wrap(token.value, token.length);
393 /* Solaris Kerberos: just to be safe since token.value is an
394 * output parameter.
395 */
396 token.value = NULL;
397 token.length = 0;
398 }
399 *minor_status = code;
400 KRB5_LOG(KRB5_ERR, "kg_unseal_v1() end, krb5_c_make_checksum() "
401 "error code = %d\n", code);
402 return(GSS_S_FAILURE);
403 }
404
405 if ((code = kg_encrypt(context, ctx->seq, KG_USAGE_SEAL,
406 (g_OID_equal(ctx->mech_used, gss_mech_krb5_old) ?
407 ctx->seq->contents : NULL),
408 md5cksum.contents, md5cksum.contents, 16))) {
409 xfree_wrap(md5cksum.contents, md5cksum.length);
410 if (toktype == KG_TOK_SEAL_MSG) {
411 xfree_wrap(token.value, token.length);
412 /* Solaris Kerberos: just to be safe since token.value is an
413 * output parameter.
414 */
415 token.value = NULL;
416 token.length = 0;
417 }
418 *minor_status = code;
419 KRB5_LOG(KRB5_ERR, "kg_unseal_v1() end, kg_encrypt() error"
420 "code = %d\n", code);
421 return GSS_S_FAILURE;
422 }
423
424 if (signalg == 0)
425 cksum.length = 8;
426 else
427 cksum.length = 16;
428 cksum.contents = md5cksum.contents + 16 - cksum.length;
429
430 code = memcmp(cksum.contents, ptr+14, cksum.length);
431 break;
432
433 case SGN_ALG_MD2_5:
434 if (!ctx->seed_init &&
435 (code = kg_make_seed(context, ctx->subkey, ctx->seed))) {
436 xfree_wrap(md5cksum.contents, md5cksum.length);
437 if (sealalg != 0xffff)
438 xfree_wrap(plain, tmsglen);
439 if (toktype == KG_TOK_SEAL_MSG) {
440 xfree_wrap(token.value, token.length);
441 /* Solaris Kerberos: just to be safe since token.value is an
442 * output parameter.
443 */
444 token.value = NULL;
445 token.length = 0;
446 }
447 *minor_status = code;
448 return GSS_S_FAILURE;
449 }
450
451 if (! (data_ptr = (void *)
452 xmalloc(sizeof(ctx->seed) + 8 +
453 (ctx->big_endian ? token.length : plainlen)))) {
454 xfree_wrap(md5cksum.contents, md5cksum.length);
455 if (sealalg == 0)
456 xfree_wrap(plain, tmsglen);
457 if (toktype == KG_TOK_SEAL_MSG) {
458 xfree_wrap(token.value, token.length);
459 /* Solaris Kerberos: just to be safe since token.value is an
460 * output parameter.
461 */
462 token.value = NULL;
463 token.length = 0;
464 }
465 *minor_status = ENOMEM;
466 return(GSS_S_FAILURE);
467 }
468 (void) memcpy(data_ptr, ptr-2, 8);
469 (void) memcpy(data_ptr+8, ctx->seed, sizeof(ctx->seed));
470 if (ctx->big_endian)
471 (void) memcpy(data_ptr+8+sizeof(ctx->seed),
472 token.value, token.length);
473 else
474 (void) memcpy(data_ptr+8+sizeof(ctx->seed),
475 plain, plainlen);
476 plaind.length = 8 + sizeof(ctx->seed) +
477 (ctx->big_endian ? token.length : plainlen);
478 plaind.data = data_ptr;
479 xfree_wrap(md5cksum.contents, md5cksum.length);
480 code = krb5_c_make_checksum(context, md5cksum.checksum_type,
481 ctx->seq, KG_USAGE_SIGN,
482 &plaind, &md5cksum);
483 xfree_wrap(data_ptr, 8 + sizeof(ctx->seed) +
484 (ctx->big_endian ? token.length : plainlen));
485
486 if (code) {
487 if (sealalg == 0)
488 xfree_wrap(plain, tmsglen);
489 if (toktype == KG_TOK_SEAL_MSG) {
490 xfree_wrap(token.value, token.length);
491 /* Solaris Kerberos: just to be safe since token.value is an
492 * output parameter.
493 */
494 token.value = NULL;
495 token.length = 0;
496 }
497 *minor_status = code;
498 return(GSS_S_FAILURE);
499 }
500
501 code = memcmp(md5cksum.contents, ptr+14, 8);
502 /* Falls through to defective-token?? */
503 /* FALLTHROUGH */
504
505 default:
506 *minor_status = 0;
507 KRB5_LOG0(KRB5_ERR, "kg_unseal_v1() end, error SGN_ALG_MD2_5 "
508 "GSS_S_DEFECTIVE_TOKEN\n");
509 return(GSS_S_DEFECTIVE_TOKEN);
510
511 case SGN_ALG_HMAC_SHA1_DES3_KD:
512 case SGN_ALG_HMAC_MD5:
513 /* compute the checksum of the message */
514
515 /* 8 = bytes of token body to be checksummed according to spec */
516
517 if (! (data_ptr = (void *)
518 xmalloc(8 + (ctx->big_endian ? token.length : plainlen)))) {
519 if (sealalg != 0xffff)
520 xfree_wrap(plain, tmsglen);
521 if (toktype == KG_TOK_SEAL_MSG) {
522 xfree_wrap(token.value, token.length);
523 /* Solaris Kerberos: just to be safe since token.value is an
524 * output parameter.
525 */
526 token.value = NULL;
527 token.length = 0;
528 }
529 *minor_status = ENOMEM;
530 return(GSS_S_FAILURE);
531 }
532
533 (void) memcpy(data_ptr, ptr-2, 8);
534
535 if (ctx->big_endian) {
536 KRB5_LOG0(KRB5_INFO, "kg_unseal_v1() ctx->big_endian = 1\n");
537 (void) memcpy(data_ptr+8, token.value, token.length);
538 }
539 else {
540 KRB5_LOG0(KRB5_INFO, "kg_unseal_v1() ctx->big_endian = 0\n");
541 (void) memcpy(data_ptr+8, plain, plainlen);
542 }
543
544 plaind.length = 8 + (ctx->big_endian ? token.length : plainlen);
545 plaind.data = data_ptr;
546
547 code = krb5_c_make_checksum(context, md5cksum.checksum_type,
548 ctx->seq, sign_usage,
549 &plaind, &md5cksum);
550
551 xfree_wrap(data_ptr, 8 + (ctx->big_endian ? token.length : plainlen));
552
553 if (code) {
554 if (toktype == KG_TOK_SEAL_MSG) {
555 xfree_wrap(token.value, token.length);
556 /* Solaris Kerberos: just to be safe since token.value is an
557 * output parameter.
558 */
559 token.value = NULL;
560 token.length = 0;
561 }
562 *minor_status = code;
563 KRB5_LOG0(KRB5_ERR, "kg_unseal_v1() end, error "
564 "SGN_ALG_HMAC_SHA1_DES3_KD GSS_S_FAILURE\n");
565 return(GSS_S_FAILURE);
566 }
567
568 /* compare the computed checksum against the transmitted checksum */
569 code = memcmp(md5cksum.contents, ptr+14, cksum_len);
570 KRB5_LOG(KRB5_INFO, "kg_unseal_v1() memcmp %d bytes", cksum_len);
571 break;
572 }
573
574 xfree_wrap(md5cksum.contents, md5cksum.length);
575 if (sealalg != 0xffff)
576 xfree_wrap(plain, tmsglen);
577
578 if (code) {
579 if (toktype == KG_TOK_SEAL_MSG) {
580 xfree_wrap(token.value, token.length);
581 /* Solaris Kerberos: just to be safe since token.value is an
582 * output parameter.
583 */
584 token.value = NULL;
585 token.length = 0;
586 }
587 *minor_status = 0;
588 KRB5_LOG0(KRB5_ERR, "kg_unseal_v1() end, error GSS_S_BAD_SIG\n");
589 return(GSS_S_BAD_SIG);
590 }
591
592 if (conf_state)
593 *conf_state = (sealalg != 0xffff);
594
595 if (qop_state)
596 *qop_state = GSS_C_QOP_DEFAULT;
597
598 if ((code = krb5_timeofday(context, &now))) {
599 *minor_status = code;
600
601 KRB5_LOG(KRB5_ERR, "kg_unseal_v1() end, krb5_timeofday()"
602 "error code = %d\n", code);
603
604 return(GSS_S_FAILURE);
605 }
606
607 if (now > ctx->endtime) {
608 *minor_status = 0;
609
610 KRB5_LOG1(KRB5_ERR, "kg_unseal_v1() end, error "
611 "now %d > ctx->endtime %d\n", now, ctx->endtime);
612
613 return(GSS_S_CONTEXT_EXPIRED);
614 }
615
616 /* do sequencing checks */
617 if ((ctx->initiate && direction != 0xff) ||
618 (!ctx->initiate && direction != 0)) {
619 if (toktype == KG_TOK_SEAL_MSG) {
620 xfree_wrap(token.value, token.length);
621 /* Solaris Kerberos: just to be safe since token.value is an
622 * output parameter.
623 */
624 token.value = NULL;
625 token.length = 0;
626 }
627 *minor_status = (OM_uint32) G_BAD_DIRECTION;
628
629 KRB5_LOG1(KRB5_ERR, "kg_unseal_v1() end, error GSS_S_BAD_SIG "
630 "G_BAD_DIRECTION ctx->initiate = %d "
631 "direction = %d\n", ctx->initiate, direction);
632
633 return(GSS_S_BAD_SIG);
634 }
635
636 retval = g_order_check(&(ctx->seqstate), (gssint_uint64)seqnum);
637
638 /* It got through unscathed, adjust the output message buffer. */
639 if (retval == 0 && toktype == KG_TOK_SEAL_MSG)
640 *message_buffer = token;
641
642 *minor_status = 0;
643 KRB5_LOG(KRB5_INFO, "kg_unseal_v1() end, retval = %d\n", retval);
644 return(retval);
645 }
646
647 /* message_buffer is an input if SIGN, output if SEAL, and ignored if DEL_CTX
648 conf_state is only valid if SEAL. */
649
650 OM_uint32
kg_unseal(minor_status,context_handle,input_token_buffer,message_buffer,conf_state,qop_state,toktype)651 kg_unseal(minor_status, context_handle, input_token_buffer,
652 message_buffer, conf_state, qop_state, toktype)
653 OM_uint32 *minor_status;
654 gss_ctx_id_t context_handle;
655 gss_buffer_t input_token_buffer;
656 gss_buffer_t message_buffer;
657 int *conf_state;
658 int *qop_state;
659 int toktype;
660 {
661 krb5_gss_ctx_id_rec *ctx;
662 unsigned char *ptr;
663 int bodysize;
664 int err;
665 int toktype2;
666
667 KRB5_LOG0(KRB5_INFO, "kg_unseal() start \n");
668
669 /* validate the context handle */
670 if (! kg_validate_ctx_id(context_handle)) {
671 *minor_status = (OM_uint32) G_VALIDATE_FAILED;
672
673 KRB5_LOG0(KRB5_ERR, "kg_unseal() end, kg_validate_ctx_id() error "
674 "G_VALIDATE_FAILED \n");
675
676 return(GSS_S_NO_CONTEXT);
677 }
678
679 ctx = (krb5_gss_ctx_id_rec *) context_handle;
680
681 if (! ctx->established) {
682 *minor_status = KG_CTX_INCOMPLETE;
683 KRB5_LOG0(KRB5_ERR, "kg_unseal() end, error ! ctx->established \n");
684 return(GSS_S_NO_CONTEXT);
685 }
686
687 /* parse the token, leave the data in message_buffer, setting conf_state */
688
689 /* verify the header */
690 ptr = (unsigned char *) input_token_buffer->value;
691 if (ctx->proto)
692 switch (toktype) {
693 case KG_TOK_SIGN_MSG:
694 toktype2 = 0x0404;
695 break;
696 case KG_TOK_SEAL_MSG:
697 toktype2 = 0x0504;
698 break;
699 case KG_TOK_DEL_CTX:
700 toktype2 = 0x0405;
701 break;
702 default:
703 toktype2 = toktype;
704 break;
705 }
706 else
707 toktype2 = toktype;
708 err = g_verify_token_header(ctx->mech_used,
709 (uint32_t *)&bodysize, &ptr, toktype2,
710 input_token_buffer->length,
711 !ctx->proto);
712 if (err) {
713 *minor_status = err;
714 return GSS_S_DEFECTIVE_TOKEN;
715 }
716
717 if (ctx->proto == 0) {
718 err = kg_unseal_v1(ctx->k5_context, minor_status, ctx, ptr, bodysize,
719 message_buffer, conf_state, qop_state,
720 toktype);
721
722 } else {
723 err = gss_krb5int_unseal_token_v3(&ctx->k5_context, minor_status, ctx,
724 ptr, bodysize, message_buffer,
725 conf_state, qop_state, toktype);
726 }
727
728 *minor_status = err;
729
730 #ifndef _KERNEL
731 if (err != 0)
732 save_error_info (*minor_status, ctx->k5_context);
733 #endif
734
735 KRB5_LOG(KRB5_INFO, "kg_unseal() end, err = %d", err);
736
737 return(err);
738 }
739