1 /* 2 * Copyright 2004 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; 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 token.length = tmsglen - conflen - plain[tmsglen-1]; 281 } 282 283 if (token.length) { 284 if ((token.value = (void *) xmalloc(token.length)) == NULL) { 285 if (sealalg != 0xffff) 286 xfree_wrap(plain, tmsglen); 287 *minor_status = ENOMEM; 288 KRB5_LOG0(KRB5_ERR, "kg_unseal_v1() end, error2 ENOMEM\n"); 289 return(GSS_S_FAILURE); 290 } 291 (void) memcpy(token.value, plain+conflen, token.length); 292 } else { 293 token.value = NULL; 294 } 295 } else if (toktype == KG_TOK_SIGN_MSG) { 296 KRB5_LOG0(KRB5_INFO, "kg_unseal_v1() toktype == KG_TOK_SIGN_MSG\n"); 297 token = *message_buffer; 298 plain = token.value; 299 plainlen = token.length; 300 } else { 301 KRB5_LOG0(KRB5_INFO, "kg_unseal_v1() toktype == NULL\n"); 302 token.length = 0; 303 token.value = NULL; 304 plain = token.value; 305 plainlen = token.length; 306 } 307 308 /* compute the checksum of the message */ 309 310 /* initialize the the cksum */ 311 switch (signalg) { 312 case SGN_ALG_DES_MAC_MD5: 313 case SGN_ALG_MD2_5: 314 case SGN_ALG_DES_MAC: 315 case SGN_ALG_3: 316 md5cksum.checksum_type = CKSUMTYPE_RSA_MD5; 317 break; 318 case SGN_ALG_HMAC_SHA1_DES3_KD: 319 md5cksum.checksum_type = CKSUMTYPE_HMAC_SHA1_DES3; 320 break; 321 case SGN_ALG_HMAC_MD5: 322 md5cksum.checksum_type = CKSUMTYPE_HMAC_MD5_ARCFOUR; 323 break; 324 default: 325 KRB5_LOG(KRB5_ERR, "kg_unseal_v1() end, error2 signalg=%d\n", signalg); 326 #ifndef _KERNEL 327 abort (); 328 #else 329 *minor_status = 0; 330 return(GSS_S_DEFECTIVE_TOKEN); 331 #endif /* _KERNEL */ 332 } 333 334 if (code = krb5_c_checksum_length(context, md5cksum.checksum_type, 335 &sumlen)) 336 { 337 KRB5_LOG(KRB5_ERR, "kg_unseal_v1() end, krb5_c_checksum_length() error " 338 "code=%d\n", code); 339 return(code); 340 } 341 md5cksum.length = (size_t)sumlen; 342 343 switch (signalg) { 344 case SGN_ALG_DES_MAC_MD5: 345 case SGN_ALG_3: 346 /* compute the checksum of the message */ 347 348 /* 8 = bytes of token body to be checksummed according to spec */ 349 350 if (! (data_ptr = (void *) 351 xmalloc(8 + (ctx->big_endian ? token.length : plainlen)))) { 352 if (sealalg != 0xffff) 353 xfree_wrap(plain, tmsglen); 354 if (toktype == KG_TOK_SEAL_MSG) { 355 xfree_wrap(token.value, token.length); 356 /* Solaris Kerberos: just to be safe since token.value is an 357 * output parameter. 358 */ 359 token.value = NULL; 360 token.length = 0; 361 } 362 *minor_status = ENOMEM; 363 KRB5_LOG0(KRB5_ERR, "kg_unseal_v1() end, error3 ENOMEM\n"); 364 return(GSS_S_FAILURE); 365 } 366 367 (void) memcpy(data_ptr, ptr-2, 8); 368 369 if (ctx->big_endian) 370 (void) memcpy(data_ptr+8, token.value, token.length); 371 else 372 (void) memcpy(data_ptr+8, plain, plainlen); 373 374 plaind.length = 8 + (ctx->big_endian ? token.length : plainlen); 375 plaind.data = data_ptr; 376 code = krb5_c_make_checksum(context, md5cksum.checksum_type, 377 ctx->seq, sign_usage, 378 &plaind, &md5cksum); 379 xfree_wrap(data_ptr, 8 + (ctx->big_endian ? token.length : plainlen)); 380 381 if (code) { 382 if (toktype == KG_TOK_SEAL_MSG) { 383 xfree_wrap(token.value, token.length); 384 /* Solaris Kerberos: just to be safe since token.value is an 385 * output parameter. 386 */ 387 token.value = NULL; 388 token.length = 0; 389 } 390 *minor_status = code; 391 KRB5_LOG(KRB5_ERR, "kg_unseal_v1() end, krb5_c_make_checksum() " 392 "error code = %d\n", code); 393 return(GSS_S_FAILURE); 394 } 395 396 if ((code = kg_encrypt(context, ctx->seq, KG_USAGE_SEAL, 397 (g_OID_equal(ctx->mech_used, gss_mech_krb5_old) ? 398 ctx->seq->contents : NULL), 399 md5cksum.contents, md5cksum.contents, 16))) { 400 xfree_wrap(md5cksum.contents, md5cksum.length); 401 if (toktype == KG_TOK_SEAL_MSG) { 402 xfree_wrap(token.value, token.length); 403 /* Solaris Kerberos: just to be safe since token.value is an 404 * output parameter. 405 */ 406 token.value = NULL; 407 token.length = 0; 408 } 409 *minor_status = code; 410 KRB5_LOG(KRB5_ERR, "kg_unseal_v1() end, kg_encrypt() error" 411 "code = %d\n", code); 412 return GSS_S_FAILURE; 413 } 414 415 if (signalg == 0) 416 cksum.length = 8; 417 else 418 cksum.length = 16; 419 cksum.contents = md5cksum.contents + 16 - cksum.length; 420 421 code = memcmp(cksum.contents, ptr+14, cksum.length); 422 break; 423 424 case SGN_ALG_MD2_5: 425 if (!ctx->seed_init && 426 (code = kg_make_seed(context, ctx->subkey, ctx->seed))) { 427 xfree_wrap(md5cksum.contents, md5cksum.length); 428 if (sealalg != 0xffff) 429 xfree_wrap(plain, tmsglen); 430 if (toktype == KG_TOK_SEAL_MSG) { 431 xfree_wrap(token.value, token.length); 432 /* Solaris Kerberos: just to be safe since token.value is an 433 * output parameter. 434 */ 435 token.value = NULL; 436 token.length = 0; 437 } 438 *minor_status = code; 439 return GSS_S_FAILURE; 440 } 441 442 if (! (data_ptr = (void *) 443 xmalloc(sizeof(ctx->seed) + 8 + 444 (ctx->big_endian ? token.length : plainlen)))) { 445 xfree_wrap(md5cksum.contents, md5cksum.length); 446 if (sealalg == 0) 447 xfree_wrap(plain, tmsglen); 448 if (toktype == KG_TOK_SEAL_MSG) { 449 xfree_wrap(token.value, token.length); 450 /* Solaris Kerberos: just to be safe since token.value is an 451 * output parameter. 452 */ 453 token.value = NULL; 454 token.length = 0; 455 } 456 *minor_status = ENOMEM; 457 return(GSS_S_FAILURE); 458 } 459 (void) memcpy(data_ptr, ptr-2, 8); 460 (void) memcpy(data_ptr+8, ctx->seed, sizeof(ctx->seed)); 461 if (ctx->big_endian) 462 (void) memcpy(data_ptr+8+sizeof(ctx->seed), 463 token.value, token.length); 464 else 465 (void) memcpy(data_ptr+8+sizeof(ctx->seed), 466 plain, plainlen); 467 plaind.length = 8 + sizeof(ctx->seed) + 468 (ctx->big_endian ? token.length : plainlen); 469 plaind.data = data_ptr; 470 xfree_wrap(md5cksum.contents, md5cksum.length); 471 code = krb5_c_make_checksum(context, md5cksum.checksum_type, 472 ctx->seq, KG_USAGE_SIGN, 473 &plaind, &md5cksum); 474 xfree_wrap(data_ptr, 8 + sizeof(ctx->seed) + 475 (ctx->big_endian ? token.length : plainlen)); 476 477 if (code) { 478 if (sealalg == 0) 479 xfree_wrap(plain, tmsglen); 480 if (toktype == KG_TOK_SEAL_MSG) { 481 xfree_wrap(token.value, token.length); 482 /* Solaris Kerberos: just to be safe since token.value is an 483 * output parameter. 484 */ 485 token.value = NULL; 486 token.length = 0; 487 } 488 *minor_status = code; 489 return(GSS_S_FAILURE); 490 } 491 492 code = memcmp(md5cksum.contents, ptr+14, 8); 493 /* Falls through to defective-token?? */ 494 495 default: 496 *minor_status = 0; 497 KRB5_LOG0(KRB5_ERR, "kg_unseal_v1() end, error SGN_ALG_MD2_5 " 498 "GSS_S_DEFECTIVE_TOKEN\n"); 499 return(GSS_S_DEFECTIVE_TOKEN); 500 501 case SGN_ALG_HMAC_SHA1_DES3_KD: 502 case SGN_ALG_HMAC_MD5: 503 /* compute the checksum of the message */ 504 505 /* 8 = bytes of token body to be checksummed according to spec */ 506 507 if (! (data_ptr = (void *) 508 xmalloc(8 + (ctx->big_endian ? token.length : plainlen)))) { 509 if (sealalg != 0xffff) 510 xfree_wrap(plain, tmsglen); 511 if (toktype == KG_TOK_SEAL_MSG) { 512 xfree_wrap(token.value, token.length); 513 /* Solaris Kerberos: just to be safe since token.value is an 514 * output parameter. 515 */ 516 token.value = NULL; 517 token.length = 0; 518 } 519 *minor_status = ENOMEM; 520 return(GSS_S_FAILURE); 521 } 522 523 (void) memcpy(data_ptr, ptr-2, 8); 524 525 if (ctx->big_endian) { 526 KRB5_LOG0(KRB5_INFO, "kg_unseal_v1() ctx->big_endian = 1\n"); 527 (void) memcpy(data_ptr+8, token.value, token.length); 528 } 529 else { 530 KRB5_LOG0(KRB5_INFO, "kg_unseal_v1() ctx->big_endian = 0\n"); 531 (void) memcpy(data_ptr+8, plain, plainlen); 532 } 533 534 plaind.length = 8 + (ctx->big_endian ? token.length : plainlen); 535 plaind.data = data_ptr; 536 537 code = krb5_c_make_checksum(context, md5cksum.checksum_type, 538 ctx->seq, sign_usage, 539 &plaind, &md5cksum); 540 541 xfree_wrap(data_ptr, 8 + (ctx->big_endian ? token.length : plainlen)); 542 543 if (code) { 544 if (toktype == KG_TOK_SEAL_MSG) { 545 xfree_wrap(token.value, token.length); 546 /* Solaris Kerberos: just to be safe since token.value is an 547 * output parameter. 548 */ 549 token.value = NULL; 550 token.length = 0; 551 } 552 *minor_status = code; 553 KRB5_LOG0(KRB5_ERR, "kg_unseal_v1() end, error " 554 "SGN_ALG_HMAC_SHA1_DES3_KD GSS_S_FAILURE\n"); 555 return(GSS_S_FAILURE); 556 } 557 558 /* compare the computed checksum against the transmitted checksum */ 559 code = memcmp(md5cksum.contents, ptr+14, cksum_len); 560 KRB5_LOG(KRB5_INFO, "kg_unseal_v1() memcmp %d bytes", cksum_len); 561 break; 562 } 563 564 xfree_wrap(md5cksum.contents, md5cksum.length); 565 if (sealalg != 0xffff) 566 xfree_wrap(plain, tmsglen); 567 568 if (code) { 569 if (toktype == KG_TOK_SEAL_MSG) { 570 xfree_wrap(token.value, token.length); 571 /* Solaris Kerberos: just to be safe since token.value is an 572 * output parameter. 573 */ 574 token.value = NULL; 575 token.length = 0; 576 } 577 *minor_status = 0; 578 KRB5_LOG0(KRB5_ERR, "kg_unseal_v1() end, error GSS_S_BAD_SIG\n"); 579 return(GSS_S_BAD_SIG); 580 } 581 582 if (conf_state) 583 *conf_state = (sealalg != 0xffff); 584 585 if (qop_state) 586 *qop_state = GSS_C_QOP_DEFAULT; 587 588 if ((code = krb5_timeofday(context, &now))) { 589 *minor_status = code; 590 591 KRB5_LOG(KRB5_ERR, "kg_unseal_v1() end, krb5_timeofday()" 592 "error code = %d\n", code); 593 594 return(GSS_S_FAILURE); 595 } 596 597 if (now > ctx->endtime) { 598 *minor_status = 0; 599 600 KRB5_LOG1(KRB5_ERR, "kg_unseal_v1() end, error " 601 "now %d > ctx->endtime %d\n", now, ctx->endtime); 602 603 return(GSS_S_CONTEXT_EXPIRED); 604 } 605 606 /* do sequencing checks */ 607 if ((ctx->initiate && direction != 0xff) || 608 (!ctx->initiate && direction != 0)) { 609 if (toktype == KG_TOK_SEAL_MSG) { 610 xfree_wrap(token.value, token.length); 611 /* Solaris Kerberos: just to be safe since token.value is an 612 * output parameter. 613 */ 614 token.value = NULL; 615 token.length = 0; 616 } 617 *minor_status = (OM_uint32) G_BAD_DIRECTION; 618 619 KRB5_LOG1(KRB5_ERR, "kg_unseal_v1() end, error GSS_S_BAD_SIG " 620 "G_BAD_DIRECTION ctx->initiate = %d " 621 "direction = %d\n", ctx->initiate, direction); 622 623 return(GSS_S_BAD_SIG); 624 } 625 626 retval = g_order_check(&(ctx->seqstate), (gssint_uint64)seqnum); 627 628 /* It got through unscathed, adjust the output message buffer. */ 629 if (retval == 0 && toktype == KG_TOK_SEAL_MSG) 630 *message_buffer = token; 631 632 *minor_status = 0; 633 KRB5_LOG(KRB5_INFO, "kg_unseal_v1() end, retval = %d\n", retval); 634 return(retval); 635 } 636 637 /* message_buffer is an input if SIGN, output if SEAL, and ignored if DEL_CTX 638 conf_state is only valid if SEAL. */ 639 640 OM_uint32 641 kg_unseal(minor_status, context_handle, input_token_buffer, 642 message_buffer, conf_state, qop_state, toktype) 643 OM_uint32 *minor_status; 644 gss_ctx_id_t context_handle; 645 gss_buffer_t input_token_buffer; 646 gss_buffer_t message_buffer; 647 int *conf_state; 648 int *qop_state; 649 int toktype; 650 { 651 krb5_gss_ctx_id_rec *ctx; 652 unsigned char *ptr; 653 int bodysize; 654 int err; 655 int toktype2; 656 657 KRB5_LOG0(KRB5_INFO, "kg_unseal() start \n"); 658 659 /* validate the context handle */ 660 if (! kg_validate_ctx_id(context_handle)) { 661 *minor_status = (OM_uint32) G_VALIDATE_FAILED; 662 663 KRB5_LOG0(KRB5_ERR, "kg_unseal() end, kg_validate_ctx_id() error " 664 "G_VALIDATE_FAILED \n"); 665 666 return(GSS_S_NO_CONTEXT); 667 } 668 669 ctx = (krb5_gss_ctx_id_rec *) context_handle; 670 671 if (! ctx->established) { 672 *minor_status = KG_CTX_INCOMPLETE; 673 KRB5_LOG0(KRB5_ERR, "kg_unseal() end, error ! ctx->established \n"); 674 return(GSS_S_NO_CONTEXT); 675 } 676 677 /* parse the token, leave the data in message_buffer, setting conf_state */ 678 679 /* verify the header */ 680 ptr = (unsigned char *) input_token_buffer->value; 681 if (ctx->proto) 682 switch (toktype) { 683 case KG_TOK_SIGN_MSG: 684 toktype2 = 0x0404; 685 break; 686 case KG_TOK_SEAL_MSG: 687 toktype2 = 0x0504; 688 break; 689 case KG_TOK_DEL_CTX: 690 toktype2 = 0x0405; 691 break; 692 default: 693 toktype2 = toktype; 694 break; 695 } 696 else 697 toktype2 = toktype; 698 err = g_verify_token_header(ctx->mech_used, 699 (uint32_t *)&bodysize, &ptr, toktype2, 700 input_token_buffer->length, 701 !ctx->proto); 702 if (err) { 703 *minor_status = err; 704 return GSS_S_DEFECTIVE_TOKEN; 705 } 706 707 708 709 if (ctx->proto == 0) { 710 err = kg_unseal_v1(ctx->k5_context, minor_status, ctx, ptr, bodysize, 711 message_buffer, conf_state, qop_state, 712 toktype); 713 714 } else { 715 err = gss_krb5int_unseal_token_v3(ctx->k5_context, minor_status, ctx, 716 ptr, bodysize, message_buffer, 717 conf_state, qop_state, toktype); 718 } 719 720 *minor_status = err; 721 722 KRB5_LOG(KRB5_INFO, "kg_unseal() end, err = %d", err); 723 724 return(err); 725 } 726