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