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