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 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 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