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 504 default: 505 *minor_status = 0; 506 KRB5_LOG0(KRB5_ERR, "kg_unseal_v1() end, error SGN_ALG_MD2_5 " 507 "GSS_S_DEFECTIVE_TOKEN\n"); 508 return(GSS_S_DEFECTIVE_TOKEN); 509 510 case SGN_ALG_HMAC_SHA1_DES3_KD: 511 case SGN_ALG_HMAC_MD5: 512 /* compute the checksum of the message */ 513 514 /* 8 = bytes of token body to be checksummed according to spec */ 515 516 if (! (data_ptr = (void *) 517 xmalloc(8 + (ctx->big_endian ? token.length : plainlen)))) { 518 if (sealalg != 0xffff) 519 xfree_wrap(plain, tmsglen); 520 if (toktype == KG_TOK_SEAL_MSG) { 521 xfree_wrap(token.value, token.length); 522 /* Solaris Kerberos: just to be safe since token.value is an 523 * output parameter. 524 */ 525 token.value = NULL; 526 token.length = 0; 527 } 528 *minor_status = ENOMEM; 529 return(GSS_S_FAILURE); 530 } 531 532 (void) memcpy(data_ptr, ptr-2, 8); 533 534 if (ctx->big_endian) { 535 KRB5_LOG0(KRB5_INFO, "kg_unseal_v1() ctx->big_endian = 1\n"); 536 (void) memcpy(data_ptr+8, token.value, token.length); 537 } 538 else { 539 KRB5_LOG0(KRB5_INFO, "kg_unseal_v1() ctx->big_endian = 0\n"); 540 (void) memcpy(data_ptr+8, plain, plainlen); 541 } 542 543 plaind.length = 8 + (ctx->big_endian ? token.length : plainlen); 544 plaind.data = data_ptr; 545 546 code = krb5_c_make_checksum(context, md5cksum.checksum_type, 547 ctx->seq, sign_usage, 548 &plaind, &md5cksum); 549 550 xfree_wrap(data_ptr, 8 + (ctx->big_endian ? token.length : plainlen)); 551 552 if (code) { 553 if (toktype == KG_TOK_SEAL_MSG) { 554 xfree_wrap(token.value, token.length); 555 /* Solaris Kerberos: just to be safe since token.value is an 556 * output parameter. 557 */ 558 token.value = NULL; 559 token.length = 0; 560 } 561 *minor_status = code; 562 KRB5_LOG0(KRB5_ERR, "kg_unseal_v1() end, error " 563 "SGN_ALG_HMAC_SHA1_DES3_KD GSS_S_FAILURE\n"); 564 return(GSS_S_FAILURE); 565 } 566 567 /* compare the computed checksum against the transmitted checksum */ 568 code = memcmp(md5cksum.contents, ptr+14, cksum_len); 569 KRB5_LOG(KRB5_INFO, "kg_unseal_v1() memcmp %d bytes", cksum_len); 570 break; 571 } 572 573 xfree_wrap(md5cksum.contents, md5cksum.length); 574 if (sealalg != 0xffff) 575 xfree_wrap(plain, tmsglen); 576 577 if (code) { 578 if (toktype == KG_TOK_SEAL_MSG) { 579 xfree_wrap(token.value, token.length); 580 /* Solaris Kerberos: just to be safe since token.value is an 581 * output parameter. 582 */ 583 token.value = NULL; 584 token.length = 0; 585 } 586 *minor_status = 0; 587 KRB5_LOG0(KRB5_ERR, "kg_unseal_v1() end, error GSS_S_BAD_SIG\n"); 588 return(GSS_S_BAD_SIG); 589 } 590 591 if (conf_state) 592 *conf_state = (sealalg != 0xffff); 593 594 if (qop_state) 595 *qop_state = GSS_C_QOP_DEFAULT; 596 597 if ((code = krb5_timeofday(context, &now))) { 598 *minor_status = code; 599 600 KRB5_LOG(KRB5_ERR, "kg_unseal_v1() end, krb5_timeofday()" 601 "error code = %d\n", code); 602 603 return(GSS_S_FAILURE); 604 } 605 606 if (now > ctx->endtime) { 607 *minor_status = 0; 608 609 KRB5_LOG1(KRB5_ERR, "kg_unseal_v1() end, error " 610 "now %d > ctx->endtime %d\n", now, ctx->endtime); 611 612 return(GSS_S_CONTEXT_EXPIRED); 613 } 614 615 /* do sequencing checks */ 616 if ((ctx->initiate && direction != 0xff) || 617 (!ctx->initiate && direction != 0)) { 618 if (toktype == KG_TOK_SEAL_MSG) { 619 xfree_wrap(token.value, token.length); 620 /* Solaris Kerberos: just to be safe since token.value is an 621 * output parameter. 622 */ 623 token.value = NULL; 624 token.length = 0; 625 } 626 *minor_status = (OM_uint32) G_BAD_DIRECTION; 627 628 KRB5_LOG1(KRB5_ERR, "kg_unseal_v1() end, error GSS_S_BAD_SIG " 629 "G_BAD_DIRECTION ctx->initiate = %d " 630 "direction = %d\n", ctx->initiate, direction); 631 632 return(GSS_S_BAD_SIG); 633 } 634 635 retval = g_order_check(&(ctx->seqstate), (gssint_uint64)seqnum); 636 637 /* It got through unscathed, adjust the output message buffer. */ 638 if (retval == 0 && toktype == KG_TOK_SEAL_MSG) 639 *message_buffer = token; 640 641 *minor_status = 0; 642 KRB5_LOG(KRB5_INFO, "kg_unseal_v1() end, retval = %d\n", retval); 643 return(retval); 644 } 645 646 /* message_buffer is an input if SIGN, output if SEAL, and ignored if DEL_CTX 647 conf_state is only valid if SEAL. */ 648 649 OM_uint32 650 kg_unseal(minor_status, context_handle, input_token_buffer, 651 message_buffer, conf_state, qop_state, toktype) 652 OM_uint32 *minor_status; 653 gss_ctx_id_t context_handle; 654 gss_buffer_t input_token_buffer; 655 gss_buffer_t message_buffer; 656 int *conf_state; 657 int *qop_state; 658 int toktype; 659 { 660 krb5_gss_ctx_id_rec *ctx; 661 unsigned char *ptr; 662 int bodysize; 663 int err; 664 int toktype2; 665 666 KRB5_LOG0(KRB5_INFO, "kg_unseal() start \n"); 667 668 /* validate the context handle */ 669 if (! kg_validate_ctx_id(context_handle)) { 670 *minor_status = (OM_uint32) G_VALIDATE_FAILED; 671 672 KRB5_LOG0(KRB5_ERR, "kg_unseal() end, kg_validate_ctx_id() error " 673 "G_VALIDATE_FAILED \n"); 674 675 return(GSS_S_NO_CONTEXT); 676 } 677 678 ctx = (krb5_gss_ctx_id_rec *) context_handle; 679 680 if (! ctx->established) { 681 *minor_status = KG_CTX_INCOMPLETE; 682 KRB5_LOG0(KRB5_ERR, "kg_unseal() end, error ! ctx->established \n"); 683 return(GSS_S_NO_CONTEXT); 684 } 685 686 /* parse the token, leave the data in message_buffer, setting conf_state */ 687 688 /* verify the header */ 689 ptr = (unsigned char *) input_token_buffer->value; 690 if (ctx->proto) 691 switch (toktype) { 692 case KG_TOK_SIGN_MSG: 693 toktype2 = 0x0404; 694 break; 695 case KG_TOK_SEAL_MSG: 696 toktype2 = 0x0504; 697 break; 698 case KG_TOK_DEL_CTX: 699 toktype2 = 0x0405; 700 break; 701 default: 702 toktype2 = toktype; 703 break; 704 } 705 else 706 toktype2 = toktype; 707 err = g_verify_token_header(ctx->mech_used, 708 (uint32_t *)&bodysize, &ptr, toktype2, 709 input_token_buffer->length, 710 !ctx->proto); 711 if (err) { 712 *minor_status = err; 713 return GSS_S_DEFECTIVE_TOKEN; 714 } 715 716 if (ctx->proto == 0) { 717 err = kg_unseal_v1(ctx->k5_context, minor_status, ctx, ptr, bodysize, 718 message_buffer, conf_state, qop_state, 719 toktype); 720 721 } else { 722 err = gss_krb5int_unseal_token_v3(&ctx->k5_context, minor_status, ctx, 723 ptr, bodysize, message_buffer, 724 conf_state, qop_state, toktype); 725 } 726 727 *minor_status = err; 728 729 #ifndef _KERNEL 730 if (err != 0) 731 save_error_info (*minor_status, ctx->k5_context); 732 #endif 733 734 KRB5_LOG(KRB5_INFO, "kg_unseal() end, err = %d", err); 735 736 return(err); 737 } 738