1 /* 2 * Copyright (c) 2003, PADL Software Pty Ltd. 3 * All rights reserved. 4 * 5 * Redistribution and use in source and binary forms, with or without 6 * modification, are permitted provided that the following conditions 7 * are met: 8 * 9 * 1. Redistributions of source code must retain the above copyright 10 * notice, this list of conditions and the following disclaimer. 11 * 12 * 2. Redistributions in binary form must reproduce the above copyright 13 * notice, this list of conditions and the following disclaimer in the 14 * documentation and/or other materials provided with the distribution. 15 * 16 * 3. Neither the name of PADL Software nor the names of its contributors 17 * may be used to endorse or promote products derived from this software 18 * without specific prior written permission. 19 * 20 * THIS SOFTWARE IS PROVIDED BY PADL SOFTWARE AND CONTRIBUTORS ``AS IS'' AND 21 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 22 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE 23 * ARE DISCLAIMED. IN NO EVENT SHALL PADL SOFTWARE OR CONTRIBUTORS BE LIABLE 24 * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL 25 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS 26 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) 27 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT 28 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY 29 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF 30 * SUCH DAMAGE. 31 */ 32 33 #include "gsskrb5_locl.h" 34 35 /* 36 * Implementation of RFC 4121 37 */ 38 39 #define CFXSentByAcceptor (1 << 0) 40 #define CFXSealed (1 << 1) 41 #define CFXAcceptorSubkey (1 << 2) 42 43 krb5_error_code 44 _gsskrb5cfx_wrap_length_cfx(krb5_context context, 45 krb5_crypto crypto, 46 int conf_req_flag, 47 int dce_style, 48 size_t input_length, 49 size_t *output_length, 50 size_t *cksumsize, 51 uint16_t *padlength) 52 { 53 krb5_error_code ret; 54 krb5_cksumtype type; 55 56 /* 16-byte header is always first */ 57 *output_length = sizeof(gss_cfx_wrap_token_desc); 58 *padlength = 0; 59 60 ret = krb5_crypto_get_checksum_type(context, crypto, &type); 61 if (ret) 62 return ret; 63 64 ret = krb5_checksumsize(context, type, cksumsize); 65 if (ret) 66 return ret; 67 68 if (conf_req_flag) { 69 size_t padsize; 70 71 /* Header is concatenated with data before encryption */ 72 input_length += sizeof(gss_cfx_wrap_token_desc); 73 74 if (dce_style) { 75 ret = krb5_crypto_getblocksize(context, crypto, &padsize); 76 } else { 77 ret = krb5_crypto_getpadsize(context, crypto, &padsize); 78 } 79 if (ret) { 80 return ret; 81 } 82 if (padsize > 1) { 83 /* XXX check this */ 84 *padlength = padsize - (input_length % padsize); 85 86 /* We add the pad ourselves (noted here for completeness only) */ 87 input_length += *padlength; 88 } 89 90 *output_length += krb5_get_wrapped_length(context, 91 crypto, input_length); 92 } else { 93 /* Checksum is concatenated with data */ 94 *output_length += input_length + *cksumsize; 95 } 96 97 assert(*output_length > input_length); 98 99 return 0; 100 } 101 102 OM_uint32 103 _gssapi_wrap_size_cfx(OM_uint32 *minor_status, 104 const gsskrb5_ctx ctx, 105 krb5_context context, 106 int conf_req_flag, 107 gss_qop_t qop_req, 108 OM_uint32 req_output_size, 109 OM_uint32 *max_input_size) 110 { 111 krb5_error_code ret; 112 113 *max_input_size = 0; 114 115 /* 16-byte header is always first */ 116 if (req_output_size < 16) 117 return 0; 118 req_output_size -= 16; 119 120 if (conf_req_flag) { 121 size_t wrapped_size, sz; 122 123 wrapped_size = req_output_size + 1; 124 do { 125 wrapped_size--; 126 sz = krb5_get_wrapped_length(context, 127 ctx->crypto, wrapped_size); 128 } while (wrapped_size && sz > req_output_size); 129 if (wrapped_size == 0) 130 return 0; 131 132 /* inner header */ 133 if (wrapped_size < 16) 134 return 0; 135 136 wrapped_size -= 16; 137 138 *max_input_size = wrapped_size; 139 } else { 140 krb5_cksumtype type; 141 size_t cksumsize; 142 143 ret = krb5_crypto_get_checksum_type(context, ctx->crypto, &type); 144 if (ret) 145 return ret; 146 147 ret = krb5_checksumsize(context, type, &cksumsize); 148 if (ret) 149 return ret; 150 151 if (req_output_size < cksumsize) 152 return 0; 153 154 /* Checksum is concatenated with data */ 155 *max_input_size = req_output_size - cksumsize; 156 } 157 158 return 0; 159 } 160 161 /* 162 * Rotate "rrc" bytes to the front or back 163 */ 164 165 static krb5_error_code 166 rrc_rotate(void *data, size_t len, uint16_t rrc, krb5_boolean unrotate) 167 { 168 u_char *tmp, buf[256]; 169 size_t left; 170 171 if (len == 0) 172 return 0; 173 174 rrc %= len; 175 176 if (rrc == 0) 177 return 0; 178 179 left = len - rrc; 180 181 if (rrc <= sizeof(buf)) { 182 tmp = buf; 183 } else { 184 tmp = malloc(rrc); 185 if (tmp == NULL) 186 return ENOMEM; 187 } 188 189 if (unrotate) { 190 memcpy(tmp, data, rrc); 191 memmove(data, (u_char *)data + rrc, left); 192 memcpy((u_char *)data + left, tmp, rrc); 193 } else { 194 memcpy(tmp, (u_char *)data + left, rrc); 195 memmove((u_char *)data + rrc, data, left); 196 memcpy(data, tmp, rrc); 197 } 198 199 if (rrc > sizeof(buf)) 200 free(tmp); 201 202 return 0; 203 } 204 205 gss_iov_buffer_desc * 206 _gk_find_buffer(gss_iov_buffer_desc *iov, int iov_count, OM_uint32 type) 207 { 208 int i; 209 210 for (i = 0; i < iov_count; i++) 211 if (type == GSS_IOV_BUFFER_TYPE(iov[i].type)) 212 return &iov[i]; 213 return NULL; 214 } 215 216 OM_uint32 217 _gk_allocate_buffer(OM_uint32 *minor_status, gss_iov_buffer_desc *buffer, size_t size) 218 { 219 if (buffer->type & GSS_IOV_BUFFER_FLAG_ALLOCATED) { 220 if (buffer->buffer.length == size) 221 return GSS_S_COMPLETE; 222 free(buffer->buffer.value); 223 } 224 225 buffer->buffer.value = malloc(size); 226 buffer->buffer.length = size; 227 if (buffer->buffer.value == NULL) { 228 *minor_status = ENOMEM; 229 return GSS_S_FAILURE; 230 } 231 buffer->type |= GSS_IOV_BUFFER_FLAG_ALLOCATED; 232 233 return GSS_S_COMPLETE; 234 } 235 236 237 OM_uint32 238 _gk_verify_buffers(OM_uint32 *minor_status, 239 const gsskrb5_ctx ctx, 240 const gss_iov_buffer_desc *header, 241 const gss_iov_buffer_desc *padding, 242 const gss_iov_buffer_desc *trailer) 243 { 244 if (header == NULL) { 245 *minor_status = EINVAL; 246 return GSS_S_FAILURE; 247 } 248 249 if (IS_DCE_STYLE(ctx)) { 250 /* 251 * In DCE style mode we reject having a padding or trailer buffer 252 */ 253 if (padding) { 254 *minor_status = EINVAL; 255 return GSS_S_FAILURE; 256 } 257 if (trailer) { 258 *minor_status = EINVAL; 259 return GSS_S_FAILURE; 260 } 261 } else { 262 /* 263 * In non-DCE style mode we require having a padding buffer 264 */ 265 if (padding == NULL) { 266 *minor_status = EINVAL; 267 return GSS_S_FAILURE; 268 } 269 } 270 271 *minor_status = 0; 272 return GSS_S_COMPLETE; 273 } 274 275 #if 0 276 OM_uint32 277 _gssapi_wrap_cfx_iov(OM_uint32 *minor_status, 278 gsskrb5_ctx ctx, 279 krb5_context context, 280 int conf_req_flag, 281 int *conf_state, 282 gss_iov_buffer_desc *iov, 283 int iov_count) 284 { 285 OM_uint32 major_status, junk; 286 gss_iov_buffer_desc *header, *trailer, *padding; 287 size_t gsshsize, k5hsize; 288 size_t gsstsize, k5tsize; 289 size_t rrc = 0, ec = 0; 290 int i; 291 gss_cfx_wrap_token token; 292 krb5_error_code ret; 293 int32_t seq_number; 294 unsigned usage; 295 krb5_crypto_iov *data = NULL; 296 297 header = _gk_find_buffer(iov, iov_count, GSS_IOV_BUFFER_TYPE_HEADER); 298 if (header == NULL) { 299 *minor_status = EINVAL; 300 return GSS_S_FAILURE; 301 } 302 303 padding = _gk_find_buffer(iov, iov_count, GSS_IOV_BUFFER_TYPE_PADDING); 304 if (padding != NULL) { 305 padding->buffer.length = 0; 306 } 307 308 trailer = _gk_find_buffer(iov, iov_count, GSS_IOV_BUFFER_TYPE_TRAILER); 309 310 major_status = _gk_verify_buffers(minor_status, ctx, header, padding, trailer); 311 if (major_status != GSS_S_COMPLETE) { 312 return major_status; 313 } 314 315 if (conf_req_flag) { 316 size_t k5psize = 0; 317 size_t k5pbase = 0; 318 size_t k5bsize = 0; 319 size_t size = 0; 320 321 for (i = 0; i < iov_count; i++) { 322 switch (GSS_IOV_BUFFER_TYPE(iov[i].type)) { 323 case GSS_IOV_BUFFER_TYPE_DATA: 324 size += iov[i].buffer.length; 325 break; 326 default: 327 break; 328 } 329 } 330 331 size += sizeof(gss_cfx_wrap_token_desc); 332 333 *minor_status = krb5_crypto_length(context, ctx->crypto, 334 KRB5_CRYPTO_TYPE_HEADER, 335 &k5hsize); 336 if (*minor_status) 337 return GSS_S_FAILURE; 338 339 *minor_status = krb5_crypto_length(context, ctx->crypto, 340 KRB5_CRYPTO_TYPE_TRAILER, 341 &k5tsize); 342 if (*minor_status) 343 return GSS_S_FAILURE; 344 345 *minor_status = krb5_crypto_length(context, ctx->crypto, 346 KRB5_CRYPTO_TYPE_PADDING, 347 &k5pbase); 348 if (*minor_status) 349 return GSS_S_FAILURE; 350 351 if (k5pbase > 1) { 352 k5psize = k5pbase - (size % k5pbase); 353 } else { 354 k5psize = 0; 355 } 356 357 if (k5psize == 0 && IS_DCE_STYLE(ctx)) { 358 *minor_status = krb5_crypto_getblocksize(context, ctx->crypto, 359 &k5bsize); 360 if (*minor_status) 361 return GSS_S_FAILURE; 362 ec = k5bsize; 363 } else { 364 ec = k5psize; 365 } 366 367 gsshsize = sizeof(gss_cfx_wrap_token_desc) + k5hsize; 368 gsstsize = sizeof(gss_cfx_wrap_token_desc) + ec + k5tsize; 369 } else { 370 if (IS_DCE_STYLE(ctx)) { 371 *minor_status = EINVAL; 372 return GSS_S_FAILURE; 373 } 374 375 k5hsize = 0; 376 *minor_status = krb5_crypto_length(context, ctx->crypto, 377 KRB5_CRYPTO_TYPE_CHECKSUM, 378 &k5tsize); 379 if (*minor_status) 380 return GSS_S_FAILURE; 381 382 gsshsize = sizeof(gss_cfx_wrap_token_desc); 383 gsstsize = k5tsize; 384 } 385 386 /* 387 * 388 */ 389 390 if (trailer == NULL) { 391 rrc = gsstsize; 392 if (IS_DCE_STYLE(ctx)) 393 rrc -= ec; 394 gsshsize += gsstsize; 395 gsstsize = 0; 396 } else if (GSS_IOV_BUFFER_FLAGS(trailer->type) & GSS_IOV_BUFFER_FLAG_ALLOCATE) { 397 major_status = _gk_allocate_buffer(minor_status, trailer, gsstsize); 398 if (major_status) 399 goto failure; 400 } else if (trailer->buffer.length < gsstsize) { 401 *minor_status = KRB5_BAD_MSIZE; 402 major_status = GSS_S_FAILURE; 403 goto failure; 404 } else 405 trailer->buffer.length = gsstsize; 406 407 /* 408 * 409 */ 410 411 if (GSS_IOV_BUFFER_FLAGS(header->type) & GSS_IOV_BUFFER_FLAG_ALLOCATE) { 412 major_status = _gk_allocate_buffer(minor_status, header, gsshsize); 413 if (major_status != GSS_S_COMPLETE) 414 goto failure; 415 } else if (header->buffer.length < gsshsize) { 416 *minor_status = KRB5_BAD_MSIZE; 417 major_status = GSS_S_FAILURE; 418 goto failure; 419 } else 420 header->buffer.length = gsshsize; 421 422 token = (gss_cfx_wrap_token)header->buffer.value; 423 424 token->TOK_ID[0] = 0x05; 425 token->TOK_ID[1] = 0x04; 426 token->Flags = 0; 427 token->Filler = 0xFF; 428 429 if ((ctx->more_flags & LOCAL) == 0) 430 token->Flags |= CFXSentByAcceptor; 431 432 if (ctx->more_flags & ACCEPTOR_SUBKEY) 433 token->Flags |= CFXAcceptorSubkey; 434 435 if (ctx->more_flags & LOCAL) 436 usage = KRB5_KU_USAGE_INITIATOR_SEAL; 437 else 438 usage = KRB5_KU_USAGE_ACCEPTOR_SEAL; 439 440 if (conf_req_flag) { 441 /* 442 * In Wrap tokens with confidentiality, the EC field is 443 * used to encode the size (in bytes) of the random filler. 444 */ 445 token->Flags |= CFXSealed; 446 token->EC[0] = (ec >> 8) & 0xFF; 447 token->EC[1] = (ec >> 0) & 0xFF; 448 449 } else { 450 /* 451 * In Wrap tokens without confidentiality, the EC field is 452 * used to encode the size (in bytes) of the trailing 453 * checksum. 454 * 455 * This is not used in the checksum calcuation itself, 456 * because the checksum length could potentially vary 457 * depending on the data length. 458 */ 459 token->EC[0] = 0; 460 token->EC[1] = 0; 461 } 462 463 /* 464 * In Wrap tokens that provide for confidentiality, the RRC 465 * field in the header contains the hex value 00 00 before 466 * encryption. 467 * 468 * In Wrap tokens that do not provide for confidentiality, 469 * both the EC and RRC fields in the appended checksum 470 * contain the hex value 00 00 for the purpose of calculating 471 * the checksum. 472 */ 473 token->RRC[0] = 0; 474 token->RRC[1] = 0; 475 476 HEIMDAL_MUTEX_lock(&ctx->ctx_id_mutex); 477 krb5_auth_con_getlocalseqnumber(context, 478 ctx->auth_context, 479 &seq_number); 480 _gsskrb5_encode_be_om_uint32(0, &token->SND_SEQ[0]); 481 _gsskrb5_encode_be_om_uint32(seq_number, &token->SND_SEQ[4]); 482 krb5_auth_con_setlocalseqnumber(context, 483 ctx->auth_context, 484 ++seq_number); 485 HEIMDAL_MUTEX_unlock(&ctx->ctx_id_mutex); 486 487 data = calloc(iov_count + 3, sizeof(data[0])); 488 if (data == NULL) { 489 *minor_status = ENOMEM; 490 major_status = GSS_S_FAILURE; 491 goto failure; 492 } 493 494 if (conf_req_flag) { 495 /* 496 plain packet: 497 498 {"header" | encrypt(plaintext-data | ec-padding | E"header")} 499 500 Expanded, this is with with RRC = 0: 501 502 {"header" | krb5-header | plaintext-data | ec-padding | E"header" | krb5-trailer } 503 504 In DCE-RPC mode == no trailer: RRC = gss "trailer" == length(ec-padding | E"header" | krb5-trailer) 505 506 {"header" | ec-padding | E"header" | krb5-trailer | krb5-header | plaintext-data } 507 */ 508 509 i = 0; 510 data[i].flags = KRB5_CRYPTO_TYPE_HEADER; 511 data[i].data.data = ((uint8_t *)header->buffer.value) + header->buffer.length - k5hsize; 512 data[i].data.length = k5hsize; 513 514 for (i = 1; i < iov_count + 1; i++) { 515 switch (GSS_IOV_BUFFER_TYPE(iov[i - 1].type)) { 516 case GSS_IOV_BUFFER_TYPE_DATA: 517 data[i].flags = KRB5_CRYPTO_TYPE_DATA; 518 break; 519 case GSS_IOV_BUFFER_TYPE_SIGN_ONLY: 520 data[i].flags = KRB5_CRYPTO_TYPE_SIGN_ONLY; 521 break; 522 default: 523 data[i].flags = KRB5_CRYPTO_TYPE_EMPTY; 524 break; 525 } 526 data[i].data.length = iov[i - 1].buffer.length; 527 data[i].data.data = iov[i - 1].buffer.value; 528 } 529 530 /* 531 * Any necessary padding is added here to ensure that the 532 * encrypted token header is always at the end of the 533 * ciphertext. 534 */ 535 536 /* encrypted CFX header in trailer (or after the header if in 537 DCE mode). Copy in header into E"header" 538 */ 539 data[i].flags = KRB5_CRYPTO_TYPE_DATA; 540 if (trailer) 541 data[i].data.data = trailer->buffer.value; 542 else 543 data[i].data.data = ((uint8_t *)header->buffer.value) + sizeof(*token); 544 545 data[i].data.length = ec + sizeof(*token); 546 memset(data[i].data.data, 0xFF, ec); 547 memcpy(((uint8_t *)data[i].data.data) + ec, token, sizeof(*token)); 548 i++; 549 550 /* Kerberos trailer comes after the gss trailer */ 551 data[i].flags = KRB5_CRYPTO_TYPE_TRAILER; 552 data[i].data.data = ((uint8_t *)data[i-1].data.data) + ec + sizeof(*token); 553 data[i].data.length = k5tsize; 554 i++; 555 556 ret = krb5_encrypt_iov_ivec(context, ctx->crypto, usage, data, i, NULL); 557 if (ret != 0) { 558 *minor_status = ret; 559 major_status = GSS_S_FAILURE; 560 goto failure; 561 } 562 563 if (rrc) { 564 token->RRC[0] = (rrc >> 8) & 0xFF; 565 token->RRC[1] = (rrc >> 0) & 0xFF; 566 } 567 568 } else { 569 /* 570 plain packet: 571 572 {data | "header" | gss-trailer (krb5 checksum) 573 574 don't do RRC != 0 575 576 */ 577 578 for (i = 0; i < iov_count; i++) { 579 switch (GSS_IOV_BUFFER_TYPE(iov[i].type)) { 580 case GSS_IOV_BUFFER_TYPE_DATA: 581 data[i].flags = KRB5_CRYPTO_TYPE_DATA; 582 break; 583 case GSS_IOV_BUFFER_TYPE_SIGN_ONLY: 584 data[i].flags = KRB5_CRYPTO_TYPE_SIGN_ONLY; 585 break; 586 default: 587 data[i].flags = KRB5_CRYPTO_TYPE_EMPTY; 588 break; 589 } 590 data[i].data.length = iov[i].buffer.length; 591 data[i].data.data = iov[i].buffer.value; 592 } 593 594 data[i].flags = KRB5_CRYPTO_TYPE_DATA; 595 data[i].data.data = header->buffer.value; 596 data[i].data.length = sizeof(gss_cfx_wrap_token_desc); 597 i++; 598 599 data[i].flags = KRB5_CRYPTO_TYPE_CHECKSUM; 600 if (trailer) { 601 data[i].data.data = trailer->buffer.value; 602 } else { 603 data[i].data.data = (uint8_t *)header->buffer.value + 604 sizeof(gss_cfx_wrap_token_desc); 605 } 606 data[i].data.length = k5tsize; 607 i++; 608 609 ret = krb5_create_checksum_iov(context, ctx->crypto, usage, data, i, NULL); 610 if (ret) { 611 *minor_status = ret; 612 major_status = GSS_S_FAILURE; 613 goto failure; 614 } 615 616 if (rrc) { 617 token->RRC[0] = (rrc >> 8) & 0xFF; 618 token->RRC[1] = (rrc >> 0) & 0xFF; 619 } 620 621 token->EC[0] = (k5tsize >> 8) & 0xFF; 622 token->EC[1] = (k5tsize >> 0) & 0xFF; 623 } 624 625 if (conf_state != NULL) 626 *conf_state = conf_req_flag; 627 628 free(data); 629 630 *minor_status = 0; 631 return GSS_S_COMPLETE; 632 633 failure: 634 if (data) 635 free(data); 636 637 gss_release_iov_buffer(&junk, iov, iov_count); 638 639 return major_status; 640 } 641 #endif 642 643 /* This is slowpath */ 644 static OM_uint32 645 unrotate_iov(OM_uint32 *minor_status, size_t rrc, gss_iov_buffer_desc *iov, int iov_count) 646 { 647 uint8_t *p, *q; 648 size_t len = 0, skip; 649 int i; 650 651 for (i = 0; i < iov_count; i++) 652 if (GSS_IOV_BUFFER_TYPE(iov[i].type) == GSS_IOV_BUFFER_TYPE_DATA || 653 GSS_IOV_BUFFER_TYPE(iov[i].type) == GSS_IOV_BUFFER_TYPE_PADDING || 654 GSS_IOV_BUFFER_TYPE(iov[i].type) == GSS_IOV_BUFFER_TYPE_TRAILER) 655 len += iov[i].buffer.length; 656 657 p = malloc(len); 658 if (p == NULL) { 659 *minor_status = ENOMEM; 660 return GSS_S_FAILURE; 661 } 662 q = p; 663 664 /* copy up */ 665 666 for (i = 0; i < iov_count; i++) { 667 if (GSS_IOV_BUFFER_TYPE(iov[i].type) == GSS_IOV_BUFFER_TYPE_DATA || 668 GSS_IOV_BUFFER_TYPE(iov[i].type) == GSS_IOV_BUFFER_TYPE_PADDING || 669 GSS_IOV_BUFFER_TYPE(iov[i].type) == GSS_IOV_BUFFER_TYPE_TRAILER) 670 { 671 memcpy(q, iov[i].buffer.value, iov[i].buffer.length); 672 q += iov[i].buffer.length; 673 } 674 } 675 assert((size_t)(q - p) == len); 676 677 /* unrotate first part */ 678 q = p + rrc; 679 skip = rrc; 680 for (i = 0; i < iov_count; i++) { 681 if (GSS_IOV_BUFFER_TYPE(iov[i].type) == GSS_IOV_BUFFER_TYPE_DATA || 682 GSS_IOV_BUFFER_TYPE(iov[i].type) == GSS_IOV_BUFFER_TYPE_PADDING || 683 GSS_IOV_BUFFER_TYPE(iov[i].type) == GSS_IOV_BUFFER_TYPE_TRAILER) 684 { 685 if (iov[i].buffer.length <= skip) { 686 skip -= iov[i].buffer.length; 687 } else { 688 memcpy(((uint8_t *)iov[i].buffer.value) + skip, q, iov[i].buffer.length - skip); 689 q += iov[i].buffer.length - skip; 690 skip = 0; 691 } 692 } 693 } 694 /* copy trailer */ 695 q = p; 696 skip = rrc; 697 for (i = 0; i < iov_count; i++) { 698 if (GSS_IOV_BUFFER_TYPE(iov[i].type) == GSS_IOV_BUFFER_TYPE_DATA || 699 GSS_IOV_BUFFER_TYPE(iov[i].type) == GSS_IOV_BUFFER_TYPE_PADDING || 700 GSS_IOV_BUFFER_TYPE(iov[i].type) == GSS_IOV_BUFFER_TYPE_TRAILER) 701 { 702 memcpy(q, iov[i].buffer.value, min(iov[i].buffer.length, skip)); 703 if (iov[i].buffer.length > skip) 704 break; 705 skip -= iov[i].buffer.length; 706 q += iov[i].buffer.length; 707 } 708 } 709 return GSS_S_COMPLETE; 710 } 711 712 #if 0 713 714 OM_uint32 715 _gssapi_unwrap_cfx_iov(OM_uint32 *minor_status, 716 gsskrb5_ctx ctx, 717 krb5_context context, 718 int *conf_state, 719 gss_qop_t *qop_state, 720 gss_iov_buffer_desc *iov, 721 int iov_count) 722 { 723 OM_uint32 seq_number_lo, seq_number_hi, major_status, junk; 724 gss_iov_buffer_desc *header, *trailer, *padding; 725 gss_cfx_wrap_token token, ttoken; 726 u_char token_flags; 727 krb5_error_code ret; 728 unsigned usage; 729 uint16_t ec, rrc; 730 krb5_crypto_iov *data = NULL; 731 int i, j; 732 733 *minor_status = 0; 734 735 header = _gk_find_buffer(iov, iov_count, GSS_IOV_BUFFER_TYPE_HEADER); 736 if (header == NULL) { 737 *minor_status = EINVAL; 738 return GSS_S_FAILURE; 739 } 740 741 if (header->buffer.length < sizeof(*token)) /* we check exact below */ 742 return GSS_S_DEFECTIVE_TOKEN; 743 744 padding = _gk_find_buffer(iov, iov_count, GSS_IOV_BUFFER_TYPE_PADDING); 745 if (padding != NULL && padding->buffer.length != 0) { 746 *minor_status = EINVAL; 747 return GSS_S_FAILURE; 748 } 749 750 trailer = _gk_find_buffer(iov, iov_count, GSS_IOV_BUFFER_TYPE_TRAILER); 751 752 major_status = _gk_verify_buffers(minor_status, ctx, header, padding, trailer); 753 if (major_status != GSS_S_COMPLETE) { 754 return major_status; 755 } 756 757 token = (gss_cfx_wrap_token)header->buffer.value; 758 759 if (token->TOK_ID[0] != 0x05 || token->TOK_ID[1] != 0x04) 760 return GSS_S_DEFECTIVE_TOKEN; 761 762 /* Ignore unknown flags */ 763 token_flags = token->Flags & 764 (CFXSentByAcceptor | CFXSealed | CFXAcceptorSubkey); 765 766 if (token_flags & CFXSentByAcceptor) { 767 if ((ctx->more_flags & LOCAL) == 0) 768 return GSS_S_DEFECTIVE_TOKEN; 769 } 770 771 if (ctx->more_flags & ACCEPTOR_SUBKEY) { 772 if ((token_flags & CFXAcceptorSubkey) == 0) 773 return GSS_S_DEFECTIVE_TOKEN; 774 } else { 775 if (token_flags & CFXAcceptorSubkey) 776 return GSS_S_DEFECTIVE_TOKEN; 777 } 778 779 if (token->Filler != 0xFF) 780 return GSS_S_DEFECTIVE_TOKEN; 781 782 if (conf_state != NULL) 783 *conf_state = (token_flags & CFXSealed) ? 1 : 0; 784 785 ec = (token->EC[0] << 8) | token->EC[1]; 786 rrc = (token->RRC[0] << 8) | token->RRC[1]; 787 788 /* 789 * Check sequence number 790 */ 791 _gsskrb5_decode_be_om_uint32(&token->SND_SEQ[0], &seq_number_hi); 792 _gsskrb5_decode_be_om_uint32(&token->SND_SEQ[4], &seq_number_lo); 793 if (seq_number_hi) { 794 /* no support for 64-bit sequence numbers */ 795 *minor_status = ERANGE; 796 return GSS_S_UNSEQ_TOKEN; 797 } 798 799 HEIMDAL_MUTEX_lock(&ctx->ctx_id_mutex); 800 ret = _gssapi_msg_order_check(ctx->order, seq_number_lo); 801 if (ret != 0) { 802 *minor_status = 0; 803 HEIMDAL_MUTEX_unlock(&ctx->ctx_id_mutex); 804 return ret; 805 } 806 HEIMDAL_MUTEX_unlock(&ctx->ctx_id_mutex); 807 808 /* 809 * Decrypt and/or verify checksum 810 */ 811 812 if (ctx->more_flags & LOCAL) { 813 usage = KRB5_KU_USAGE_ACCEPTOR_SEAL; 814 } else { 815 usage = KRB5_KU_USAGE_INITIATOR_SEAL; 816 } 817 818 data = calloc(iov_count + 3, sizeof(data[0])); 819 if (data == NULL) { 820 *minor_status = ENOMEM; 821 major_status = GSS_S_FAILURE; 822 goto failure; 823 } 824 825 if (token_flags & CFXSealed) { 826 size_t k5tsize, k5hsize; 827 828 krb5_crypto_length(context, ctx->crypto, KRB5_CRYPTO_TYPE_HEADER, &k5hsize); 829 krb5_crypto_length(context, ctx->crypto, KRB5_CRYPTO_TYPE_TRAILER, &k5tsize); 830 831 /* Rotate by RRC; bogus to do this in-place XXX */ 832 /* Check RRC */ 833 834 if (trailer == NULL) { 835 size_t gsstsize = k5tsize + sizeof(*token); 836 size_t gsshsize = k5hsize + sizeof(*token); 837 838 if (rrc != gsstsize) { 839 major_status = GSS_S_DEFECTIVE_TOKEN; 840 goto failure; 841 } 842 843 if (IS_DCE_STYLE(ctx)) 844 gsstsize += ec; 845 846 gsshsize += gsstsize; 847 848 if (header->buffer.length != gsshsize) { 849 major_status = GSS_S_DEFECTIVE_TOKEN; 850 goto failure; 851 } 852 } else if (trailer->buffer.length != sizeof(*token) + k5tsize) { 853 major_status = GSS_S_DEFECTIVE_TOKEN; 854 goto failure; 855 } else if (header->buffer.length != sizeof(*token) + k5hsize) { 856 major_status = GSS_S_DEFECTIVE_TOKEN; 857 goto failure; 858 } else if (rrc != 0) { 859 /* go though slowpath */ 860 major_status = unrotate_iov(minor_status, rrc, iov, iov_count); 861 if (major_status) 862 goto failure; 863 } 864 865 i = 0; 866 data[i].flags = KRB5_CRYPTO_TYPE_HEADER; 867 data[i].data.data = ((uint8_t *)header->buffer.value) + header->buffer.length - k5hsize; 868 data[i].data.length = k5hsize; 869 i++; 870 871 for (j = 0; j < iov_count; i++, j++) { 872 switch (GSS_IOV_BUFFER_TYPE(iov[j].type)) { 873 case GSS_IOV_BUFFER_TYPE_DATA: 874 data[i].flags = KRB5_CRYPTO_TYPE_DATA; 875 break; 876 case GSS_IOV_BUFFER_TYPE_SIGN_ONLY: 877 data[i].flags = KRB5_CRYPTO_TYPE_SIGN_ONLY; 878 break; 879 default: 880 data[i].flags = KRB5_CRYPTO_TYPE_EMPTY; 881 break; 882 } 883 data[i].data.length = iov[j].buffer.length; 884 data[i].data.data = iov[j].buffer.value; 885 } 886 887 /* encrypted CFX header in trailer (or after the header if in 888 DCE mode). Copy in header into E"header" 889 */ 890 data[i].flags = KRB5_CRYPTO_TYPE_DATA; 891 if (trailer) { 892 data[i].data.data = trailer->buffer.value; 893 } else { 894 data[i].data.data = ((uint8_t *)header->buffer.value) + 895 header->buffer.length - k5hsize - k5tsize - ec- sizeof(*token); 896 } 897 898 data[i].data.length = ec + sizeof(*token); 899 ttoken = (gss_cfx_wrap_token)(((uint8_t *)data[i].data.data) + ec); 900 i++; 901 902 /* Kerberos trailer comes after the gss trailer */ 903 data[i].flags = KRB5_CRYPTO_TYPE_TRAILER; 904 data[i].data.data = ((uint8_t *)data[i-1].data.data) + ec + sizeof(*token); 905 data[i].data.length = k5tsize; 906 i++; 907 908 ret = krb5_decrypt_iov_ivec(context, ctx->crypto, usage, data, i, NULL); 909 if (ret != 0) { 910 *minor_status = ret; 911 major_status = GSS_S_FAILURE; 912 goto failure; 913 } 914 915 ttoken->RRC[0] = token->RRC[0]; 916 ttoken->RRC[1] = token->RRC[1]; 917 918 /* Check the integrity of the header */ 919 if (ct_memcmp(ttoken, token, sizeof(*token)) != 0) { 920 major_status = GSS_S_BAD_MIC; 921 goto failure; 922 } 923 } else { 924 size_t gsstsize = ec; 925 size_t gsshsize = sizeof(*token); 926 927 if (trailer == NULL) { 928 /* Check RRC */ 929 if (rrc != gsstsize) { 930 *minor_status = EINVAL; 931 major_status = GSS_S_FAILURE; 932 goto failure; 933 } 934 935 gsshsize += gsstsize; 936 gsstsize = 0; 937 } else if (trailer->buffer.length != gsstsize) { 938 major_status = GSS_S_DEFECTIVE_TOKEN; 939 goto failure; 940 } else if (rrc != 0) { 941 /* Check RRC */ 942 *minor_status = EINVAL; 943 major_status = GSS_S_FAILURE; 944 goto failure; 945 } 946 947 if (header->buffer.length != gsshsize) { 948 major_status = GSS_S_DEFECTIVE_TOKEN; 949 goto failure; 950 } 951 952 for (i = 0; i < iov_count; i++) { 953 switch (GSS_IOV_BUFFER_TYPE(iov[i].type)) { 954 case GSS_IOV_BUFFER_TYPE_DATA: 955 data[i].flags = KRB5_CRYPTO_TYPE_DATA; 956 break; 957 case GSS_IOV_BUFFER_TYPE_SIGN_ONLY: 958 data[i].flags = KRB5_CRYPTO_TYPE_SIGN_ONLY; 959 break; 960 default: 961 data[i].flags = KRB5_CRYPTO_TYPE_EMPTY; 962 break; 963 } 964 data[i].data.length = iov[i].buffer.length; 965 data[i].data.data = iov[i].buffer.value; 966 } 967 968 data[i].flags = KRB5_CRYPTO_TYPE_DATA; 969 data[i].data.data = header->buffer.value; 970 data[i].data.length = sizeof(*token); 971 i++; 972 973 data[i].flags = KRB5_CRYPTO_TYPE_CHECKSUM; 974 if (trailer) { 975 data[i].data.data = trailer->buffer.value; 976 } else { 977 data[i].data.data = (uint8_t *)header->buffer.value + 978 sizeof(*token); 979 } 980 data[i].data.length = ec; 981 i++; 982 983 token = (gss_cfx_wrap_token)header->buffer.value; 984 token->EC[0] = 0; 985 token->EC[1] = 0; 986 token->RRC[0] = 0; 987 token->RRC[1] = 0; 988 989 ret = krb5_verify_checksum_iov(context, ctx->crypto, usage, data, i, NULL); 990 if (ret) { 991 *minor_status = ret; 992 major_status = GSS_S_FAILURE; 993 goto failure; 994 } 995 } 996 997 if (qop_state != NULL) { 998 *qop_state = GSS_C_QOP_DEFAULT; 999 } 1000 1001 free(data); 1002 1003 *minor_status = 0; 1004 return GSS_S_COMPLETE; 1005 1006 failure: 1007 if (data) 1008 free(data); 1009 1010 gss_release_iov_buffer(&junk, iov, iov_count); 1011 1012 return major_status; 1013 } 1014 #endif 1015 1016 OM_uint32 1017 _gssapi_wrap_iov_length_cfx(OM_uint32 *minor_status, 1018 gsskrb5_ctx ctx, 1019 krb5_context context, 1020 int conf_req_flag, 1021 gss_qop_t qop_req, 1022 int *conf_state, 1023 gss_iov_buffer_desc *iov, 1024 int iov_count) 1025 { 1026 OM_uint32 major_status; 1027 size_t size; 1028 int i; 1029 gss_iov_buffer_desc *header = NULL; 1030 gss_iov_buffer_desc *padding = NULL; 1031 gss_iov_buffer_desc *trailer = NULL; 1032 size_t gsshsize = 0; 1033 size_t gsstsize = 0; 1034 size_t k5hsize = 0; 1035 size_t k5tsize = 0; 1036 1037 GSSAPI_KRB5_INIT (&context); 1038 *minor_status = 0; 1039 1040 for (size = 0, i = 0; i < iov_count; i++) { 1041 switch(GSS_IOV_BUFFER_TYPE(iov[i].type)) { 1042 case GSS_IOV_BUFFER_TYPE_EMPTY: 1043 break; 1044 case GSS_IOV_BUFFER_TYPE_DATA: 1045 size += iov[i].buffer.length; 1046 break; 1047 case GSS_IOV_BUFFER_TYPE_HEADER: 1048 if (header != NULL) { 1049 *minor_status = 0; 1050 return GSS_S_FAILURE; 1051 } 1052 header = &iov[i]; 1053 break; 1054 case GSS_IOV_BUFFER_TYPE_TRAILER: 1055 if (trailer != NULL) { 1056 *minor_status = 0; 1057 return GSS_S_FAILURE; 1058 } 1059 trailer = &iov[i]; 1060 break; 1061 case GSS_IOV_BUFFER_TYPE_PADDING: 1062 if (padding != NULL) { 1063 *minor_status = 0; 1064 return GSS_S_FAILURE; 1065 } 1066 padding = &iov[i]; 1067 break; 1068 case GSS_IOV_BUFFER_TYPE_SIGN_ONLY: 1069 break; 1070 default: 1071 *minor_status = EINVAL; 1072 return GSS_S_FAILURE; 1073 } 1074 } 1075 1076 major_status = _gk_verify_buffers(minor_status, ctx, header, padding, trailer); 1077 if (major_status != GSS_S_COMPLETE) { 1078 return major_status; 1079 } 1080 1081 if (conf_req_flag) { 1082 size_t k5psize = 0; 1083 size_t k5pbase = 0; 1084 size_t k5bsize = 0; 1085 size_t ec = 0; 1086 1087 size += sizeof(gss_cfx_wrap_token_desc); 1088 1089 *minor_status = krb5_crypto_length(context, ctx->crypto, 1090 KRB5_CRYPTO_TYPE_HEADER, 1091 &k5hsize); 1092 if (*minor_status) 1093 return GSS_S_FAILURE; 1094 1095 *minor_status = krb5_crypto_length(context, ctx->crypto, 1096 KRB5_CRYPTO_TYPE_TRAILER, 1097 &k5tsize); 1098 if (*minor_status) 1099 return GSS_S_FAILURE; 1100 1101 *minor_status = krb5_crypto_length(context, ctx->crypto, 1102 KRB5_CRYPTO_TYPE_PADDING, 1103 &k5pbase); 1104 if (*minor_status) 1105 return GSS_S_FAILURE; 1106 1107 if (k5pbase > 1) { 1108 k5psize = k5pbase - (size % k5pbase); 1109 } else { 1110 k5psize = 0; 1111 } 1112 1113 if (k5psize == 0 && IS_DCE_STYLE(ctx)) { 1114 *minor_status = krb5_crypto_getblocksize(context, ctx->crypto, 1115 &k5bsize); 1116 if (*minor_status) 1117 return GSS_S_FAILURE; 1118 1119 ec = k5bsize; 1120 } else { 1121 ec = k5psize; 1122 } 1123 1124 gsshsize = sizeof(gss_cfx_wrap_token_desc) + k5hsize; 1125 gsstsize = sizeof(gss_cfx_wrap_token_desc) + ec + k5tsize; 1126 } else { 1127 *minor_status = krb5_crypto_length(context, ctx->crypto, 1128 KRB5_CRYPTO_TYPE_CHECKSUM, 1129 &k5tsize); 1130 if (*minor_status) 1131 return GSS_S_FAILURE; 1132 1133 gsshsize = sizeof(gss_cfx_wrap_token_desc); 1134 gsstsize = k5tsize; 1135 } 1136 1137 if (trailer != NULL) { 1138 trailer->buffer.length = gsstsize; 1139 } else { 1140 gsshsize += gsstsize; 1141 } 1142 1143 header->buffer.length = gsshsize; 1144 1145 if (padding) { 1146 /* padding is done via EC and is contained in the header or trailer */ 1147 padding->buffer.length = 0; 1148 } 1149 1150 if (conf_state) { 1151 *conf_state = conf_req_flag; 1152 } 1153 1154 return GSS_S_COMPLETE; 1155 } 1156 1157 1158 1159 1160 OM_uint32 _gssapi_wrap_cfx(OM_uint32 *minor_status, 1161 const gsskrb5_ctx ctx, 1162 krb5_context context, 1163 int conf_req_flag, 1164 const gss_buffer_t input_message_buffer, 1165 int *conf_state, 1166 gss_buffer_t output_message_buffer) 1167 { 1168 gss_cfx_wrap_token token; 1169 krb5_error_code ret; 1170 unsigned usage; 1171 krb5_data cipher; 1172 size_t wrapped_len, cksumsize; 1173 uint16_t padlength, rrc = 0; 1174 int32_t seq_number; 1175 u_char *p; 1176 1177 ret = _gsskrb5cfx_wrap_length_cfx(context, 1178 ctx->crypto, conf_req_flag, 1179 IS_DCE_STYLE(ctx), 1180 input_message_buffer->length, 1181 &wrapped_len, &cksumsize, &padlength); 1182 if (ret != 0) { 1183 *minor_status = ret; 1184 return GSS_S_FAILURE; 1185 } 1186 1187 /* Always rotate encrypted token (if any) and checksum to header */ 1188 rrc = (conf_req_flag ? sizeof(*token) : 0) + (uint16_t)cksumsize; 1189 1190 output_message_buffer->length = wrapped_len; 1191 output_message_buffer->value = malloc(output_message_buffer->length); 1192 if (output_message_buffer->value == NULL) { 1193 *minor_status = ENOMEM; 1194 return GSS_S_FAILURE; 1195 } 1196 1197 p = output_message_buffer->value; 1198 token = (gss_cfx_wrap_token)p; 1199 token->TOK_ID[0] = 0x05; 1200 token->TOK_ID[1] = 0x04; 1201 token->Flags = 0; 1202 token->Filler = 0xFF; 1203 if ((ctx->more_flags & LOCAL) == 0) 1204 token->Flags |= CFXSentByAcceptor; 1205 if (ctx->more_flags & ACCEPTOR_SUBKEY) 1206 token->Flags |= CFXAcceptorSubkey; 1207 if (conf_req_flag) { 1208 /* 1209 * In Wrap tokens with confidentiality, the EC field is 1210 * used to encode the size (in bytes) of the random filler. 1211 */ 1212 token->Flags |= CFXSealed; 1213 token->EC[0] = (padlength >> 8) & 0xFF; 1214 token->EC[1] = (padlength >> 0) & 0xFF; 1215 } else { 1216 /* 1217 * In Wrap tokens without confidentiality, the EC field is 1218 * used to encode the size (in bytes) of the trailing 1219 * checksum. 1220 * 1221 * This is not used in the checksum calcuation itself, 1222 * because the checksum length could potentially vary 1223 * depending on the data length. 1224 */ 1225 token->EC[0] = 0; 1226 token->EC[1] = 0; 1227 } 1228 1229 /* 1230 * In Wrap tokens that provide for confidentiality, the RRC 1231 * field in the header contains the hex value 00 00 before 1232 * encryption. 1233 * 1234 * In Wrap tokens that do not provide for confidentiality, 1235 * both the EC and RRC fields in the appended checksum 1236 * contain the hex value 00 00 for the purpose of calculating 1237 * the checksum. 1238 */ 1239 token->RRC[0] = 0; 1240 token->RRC[1] = 0; 1241 1242 HEIMDAL_MUTEX_lock(&ctx->ctx_id_mutex); 1243 krb5_auth_con_getlocalseqnumber(context, 1244 ctx->auth_context, 1245 &seq_number); 1246 _gsskrb5_encode_be_om_uint32(0, &token->SND_SEQ[0]); 1247 _gsskrb5_encode_be_om_uint32(seq_number, &token->SND_SEQ[4]); 1248 krb5_auth_con_setlocalseqnumber(context, 1249 ctx->auth_context, 1250 ++seq_number); 1251 HEIMDAL_MUTEX_unlock(&ctx->ctx_id_mutex); 1252 1253 /* 1254 * If confidentiality is requested, the token header is 1255 * appended to the plaintext before encryption; the resulting 1256 * token is {"header" | encrypt(plaintext | pad | "header")}. 1257 * 1258 * If no confidentiality is requested, the checksum is 1259 * calculated over the plaintext concatenated with the 1260 * token header. 1261 */ 1262 if (ctx->more_flags & LOCAL) { 1263 usage = KRB5_KU_USAGE_INITIATOR_SEAL; 1264 } else { 1265 usage = KRB5_KU_USAGE_ACCEPTOR_SEAL; 1266 } 1267 1268 if (conf_req_flag) { 1269 /* 1270 * Any necessary padding is added here to ensure that the 1271 * encrypted token header is always at the end of the 1272 * ciphertext. 1273 * 1274 * The specification does not require that the padding 1275 * bytes are initialized. 1276 */ 1277 p += sizeof(*token); 1278 memcpy(p, input_message_buffer->value, input_message_buffer->length); 1279 memset(p + input_message_buffer->length, 0xFF, padlength); 1280 memcpy(p + input_message_buffer->length + padlength, 1281 token, sizeof(*token)); 1282 1283 ret = krb5_encrypt(context, ctx->crypto, 1284 usage, p, 1285 input_message_buffer->length + padlength + 1286 sizeof(*token), 1287 &cipher); 1288 if (ret != 0) { 1289 *minor_status = ret; 1290 _gsskrb5_release_buffer(minor_status, output_message_buffer); 1291 return GSS_S_FAILURE; 1292 } 1293 assert(sizeof(*token) + cipher.length == wrapped_len); 1294 token->RRC[0] = (rrc >> 8) & 0xFF; 1295 token->RRC[1] = (rrc >> 0) & 0xFF; 1296 1297 /* 1298 * this is really ugly, but needed against windows 1299 * for DCERPC, as windows rotates by EC+RRC. 1300 */ 1301 if (IS_DCE_STYLE(ctx)) { 1302 ret = rrc_rotate(cipher.data, cipher.length, rrc+padlength, FALSE); 1303 } else { 1304 ret = rrc_rotate(cipher.data, cipher.length, rrc, FALSE); 1305 } 1306 if (ret != 0) { 1307 *minor_status = ret; 1308 _gsskrb5_release_buffer(minor_status, output_message_buffer); 1309 return GSS_S_FAILURE; 1310 } 1311 memcpy(p, cipher.data, cipher.length); 1312 krb5_data_free(&cipher); 1313 } else { 1314 char *buf; 1315 Checksum cksum; 1316 1317 buf = malloc(input_message_buffer->length + sizeof(*token)); 1318 if (buf == NULL) { 1319 *minor_status = ENOMEM; 1320 _gsskrb5_release_buffer(minor_status, output_message_buffer); 1321 return GSS_S_FAILURE; 1322 } 1323 memcpy(buf, input_message_buffer->value, input_message_buffer->length); 1324 memcpy(buf + input_message_buffer->length, token, sizeof(*token)); 1325 1326 ret = krb5_create_checksum(context, ctx->crypto, 1327 usage, 0, buf, 1328 input_message_buffer->length + 1329 sizeof(*token), 1330 &cksum); 1331 if (ret != 0) { 1332 *minor_status = ret; 1333 _gsskrb5_release_buffer(minor_status, output_message_buffer); 1334 free(buf); 1335 return GSS_S_FAILURE; 1336 } 1337 1338 free(buf); 1339 1340 assert(cksum.checksum.length == cksumsize); 1341 token->EC[0] = (cksum.checksum.length >> 8) & 0xFF; 1342 token->EC[1] = (cksum.checksum.length >> 0) & 0xFF; 1343 token->RRC[0] = (rrc >> 8) & 0xFF; 1344 token->RRC[1] = (rrc >> 0) & 0xFF; 1345 1346 p += sizeof(*token); 1347 memcpy(p, input_message_buffer->value, input_message_buffer->length); 1348 memcpy(p + input_message_buffer->length, 1349 cksum.checksum.data, cksum.checksum.length); 1350 1351 ret = rrc_rotate(p, 1352 input_message_buffer->length + cksum.checksum.length, rrc, FALSE); 1353 if (ret != 0) { 1354 *minor_status = ret; 1355 _gsskrb5_release_buffer(minor_status, output_message_buffer); 1356 free_Checksum(&cksum); 1357 return GSS_S_FAILURE; 1358 } 1359 free_Checksum(&cksum); 1360 } 1361 1362 if (conf_state != NULL) { 1363 *conf_state = conf_req_flag; 1364 } 1365 1366 *minor_status = 0; 1367 return GSS_S_COMPLETE; 1368 } 1369 1370 OM_uint32 _gssapi_unwrap_cfx(OM_uint32 *minor_status, 1371 const gsskrb5_ctx ctx, 1372 krb5_context context, 1373 const gss_buffer_t input_message_buffer, 1374 gss_buffer_t output_message_buffer, 1375 int *conf_state, 1376 gss_qop_t *qop_state) 1377 { 1378 gss_cfx_wrap_token token; 1379 u_char token_flags; 1380 krb5_error_code ret; 1381 unsigned usage; 1382 krb5_data data; 1383 uint16_t ec, rrc; 1384 OM_uint32 seq_number_lo, seq_number_hi; 1385 size_t len; 1386 u_char *p; 1387 1388 *minor_status = 0; 1389 1390 if (input_message_buffer->length < sizeof(*token)) { 1391 return GSS_S_DEFECTIVE_TOKEN; 1392 } 1393 1394 p = input_message_buffer->value; 1395 1396 token = (gss_cfx_wrap_token)p; 1397 1398 if (token->TOK_ID[0] != 0x05 || token->TOK_ID[1] != 0x04) { 1399 return GSS_S_DEFECTIVE_TOKEN; 1400 } 1401 1402 /* Ignore unknown flags */ 1403 token_flags = token->Flags & 1404 (CFXSentByAcceptor | CFXSealed | CFXAcceptorSubkey); 1405 1406 if (token_flags & CFXSentByAcceptor) { 1407 if ((ctx->more_flags & LOCAL) == 0) 1408 return GSS_S_DEFECTIVE_TOKEN; 1409 } 1410 1411 if (ctx->more_flags & ACCEPTOR_SUBKEY) { 1412 if ((token_flags & CFXAcceptorSubkey) == 0) 1413 return GSS_S_DEFECTIVE_TOKEN; 1414 } else { 1415 if (token_flags & CFXAcceptorSubkey) 1416 return GSS_S_DEFECTIVE_TOKEN; 1417 } 1418 1419 if (token->Filler != 0xFF) { 1420 return GSS_S_DEFECTIVE_TOKEN; 1421 } 1422 1423 if (conf_state != NULL) { 1424 *conf_state = (token_flags & CFXSealed) ? 1 : 0; 1425 } 1426 1427 ec = (token->EC[0] << 8) | token->EC[1]; 1428 rrc = (token->RRC[0] << 8) | token->RRC[1]; 1429 1430 /* 1431 * Check sequence number 1432 */ 1433 _gsskrb5_decode_be_om_uint32(&token->SND_SEQ[0], &seq_number_hi); 1434 _gsskrb5_decode_be_om_uint32(&token->SND_SEQ[4], &seq_number_lo); 1435 if (seq_number_hi) { 1436 /* no support for 64-bit sequence numbers */ 1437 *minor_status = ERANGE; 1438 return GSS_S_UNSEQ_TOKEN; 1439 } 1440 1441 HEIMDAL_MUTEX_lock(&ctx->ctx_id_mutex); 1442 ret = _gssapi_msg_order_check(ctx->order, seq_number_lo); 1443 if (ret != 0) { 1444 *minor_status = 0; 1445 HEIMDAL_MUTEX_unlock(&ctx->ctx_id_mutex); 1446 _gsskrb5_release_buffer(minor_status, output_message_buffer); 1447 return ret; 1448 } 1449 HEIMDAL_MUTEX_unlock(&ctx->ctx_id_mutex); 1450 1451 /* 1452 * Decrypt and/or verify checksum 1453 */ 1454 1455 if (ctx->more_flags & LOCAL) { 1456 usage = KRB5_KU_USAGE_ACCEPTOR_SEAL; 1457 } else { 1458 usage = KRB5_KU_USAGE_INITIATOR_SEAL; 1459 } 1460 1461 p += sizeof(*token); 1462 len = input_message_buffer->length; 1463 len -= (p - (u_char *)input_message_buffer->value); 1464 1465 if (token_flags & CFXSealed) { 1466 /* 1467 * this is really ugly, but needed against windows 1468 * for DCERPC, as windows rotates by EC+RRC. 1469 */ 1470 if (IS_DCE_STYLE(ctx)) { 1471 *minor_status = rrc_rotate(p, len, rrc+ec, TRUE); 1472 } else { 1473 *minor_status = rrc_rotate(p, len, rrc, TRUE); 1474 } 1475 if (*minor_status != 0) { 1476 return GSS_S_FAILURE; 1477 } 1478 1479 ret = krb5_decrypt(context, ctx->crypto, usage, 1480 p, len, &data); 1481 if (ret != 0) { 1482 *minor_status = ret; 1483 return GSS_S_BAD_MIC; 1484 } 1485 1486 /* Check that there is room for the pad and token header */ 1487 if (data.length < ec + sizeof(*token)) { 1488 krb5_data_free(&data); 1489 return GSS_S_DEFECTIVE_TOKEN; 1490 } 1491 p = data.data; 1492 p += data.length - sizeof(*token); 1493 1494 /* RRC is unprotected; don't modify input buffer */ 1495 ((gss_cfx_wrap_token)p)->RRC[0] = token->RRC[0]; 1496 ((gss_cfx_wrap_token)p)->RRC[1] = token->RRC[1]; 1497 1498 /* Check the integrity of the header */ 1499 if (ct_memcmp(p, token, sizeof(*token)) != 0) { 1500 krb5_data_free(&data); 1501 return GSS_S_BAD_MIC; 1502 } 1503 1504 output_message_buffer->value = data.data; 1505 output_message_buffer->length = data.length - ec - sizeof(*token); 1506 } else { 1507 Checksum cksum; 1508 1509 /* Rotate by RRC; bogus to do this in-place XXX */ 1510 *minor_status = rrc_rotate(p, len, rrc, TRUE); 1511 if (*minor_status != 0) { 1512 return GSS_S_FAILURE; 1513 } 1514 1515 /* Determine checksum type */ 1516 ret = krb5_crypto_get_checksum_type(context, 1517 ctx->crypto, 1518 &cksum.cksumtype); 1519 if (ret != 0) { 1520 *minor_status = ret; 1521 return GSS_S_FAILURE; 1522 } 1523 1524 cksum.checksum.length = ec; 1525 1526 /* Check we have at least as much data as the checksum */ 1527 if (len < cksum.checksum.length) { 1528 *minor_status = ERANGE; 1529 return GSS_S_BAD_MIC; 1530 } 1531 1532 /* Length now is of the plaintext only, no checksum */ 1533 len -= cksum.checksum.length; 1534 cksum.checksum.data = p + len; 1535 1536 output_message_buffer->length = len; /* for later */ 1537 output_message_buffer->value = malloc(len + sizeof(*token)); 1538 if (output_message_buffer->value == NULL) { 1539 *minor_status = ENOMEM; 1540 return GSS_S_FAILURE; 1541 } 1542 1543 /* Checksum is over (plaintext-data | "header") */ 1544 memcpy(output_message_buffer->value, p, len); 1545 memcpy((u_char *)output_message_buffer->value + len, 1546 token, sizeof(*token)); 1547 1548 /* EC is not included in checksum calculation */ 1549 token = (gss_cfx_wrap_token)((u_char *)output_message_buffer->value + 1550 len); 1551 token->EC[0] = 0; 1552 token->EC[1] = 0; 1553 token->RRC[0] = 0; 1554 token->RRC[1] = 0; 1555 1556 ret = krb5_verify_checksum(context, ctx->crypto, 1557 usage, 1558 output_message_buffer->value, 1559 len + sizeof(*token), 1560 &cksum); 1561 if (ret != 0) { 1562 *minor_status = ret; 1563 _gsskrb5_release_buffer(minor_status, output_message_buffer); 1564 return GSS_S_BAD_MIC; 1565 } 1566 } 1567 1568 if (qop_state != NULL) { 1569 *qop_state = GSS_C_QOP_DEFAULT; 1570 } 1571 1572 *minor_status = 0; 1573 return GSS_S_COMPLETE; 1574 } 1575 1576 OM_uint32 _gssapi_mic_cfx(OM_uint32 *minor_status, 1577 const gsskrb5_ctx ctx, 1578 krb5_context context, 1579 gss_qop_t qop_req, 1580 const gss_buffer_t message_buffer, 1581 gss_buffer_t message_token) 1582 { 1583 gss_cfx_mic_token token; 1584 krb5_error_code ret; 1585 unsigned usage; 1586 Checksum cksum; 1587 u_char *buf; 1588 size_t len; 1589 int32_t seq_number; 1590 1591 len = message_buffer->length + sizeof(*token); 1592 buf = malloc(len); 1593 if (buf == NULL) { 1594 *minor_status = ENOMEM; 1595 return GSS_S_FAILURE; 1596 } 1597 1598 memcpy(buf, message_buffer->value, message_buffer->length); 1599 1600 token = (gss_cfx_mic_token)(buf + message_buffer->length); 1601 token->TOK_ID[0] = 0x04; 1602 token->TOK_ID[1] = 0x04; 1603 token->Flags = 0; 1604 if ((ctx->more_flags & LOCAL) == 0) 1605 token->Flags |= CFXSentByAcceptor; 1606 if (ctx->more_flags & ACCEPTOR_SUBKEY) 1607 token->Flags |= CFXAcceptorSubkey; 1608 memset(token->Filler, 0xFF, 5); 1609 1610 HEIMDAL_MUTEX_lock(&ctx->ctx_id_mutex); 1611 krb5_auth_con_getlocalseqnumber(context, 1612 ctx->auth_context, 1613 &seq_number); 1614 _gsskrb5_encode_be_om_uint32(0, &token->SND_SEQ[0]); 1615 _gsskrb5_encode_be_om_uint32(seq_number, &token->SND_SEQ[4]); 1616 krb5_auth_con_setlocalseqnumber(context, 1617 ctx->auth_context, 1618 ++seq_number); 1619 HEIMDAL_MUTEX_unlock(&ctx->ctx_id_mutex); 1620 1621 if (ctx->more_flags & LOCAL) { 1622 usage = KRB5_KU_USAGE_INITIATOR_SIGN; 1623 } else { 1624 usage = KRB5_KU_USAGE_ACCEPTOR_SIGN; 1625 } 1626 1627 ret = krb5_create_checksum(context, ctx->crypto, 1628 usage, 0, buf, len, &cksum); 1629 if (ret != 0) { 1630 *minor_status = ret; 1631 free(buf); 1632 return GSS_S_FAILURE; 1633 } 1634 1635 /* Determine MIC length */ 1636 message_token->length = sizeof(*token) + cksum.checksum.length; 1637 message_token->value = malloc(message_token->length); 1638 if (message_token->value == NULL) { 1639 *minor_status = ENOMEM; 1640 free_Checksum(&cksum); 1641 free(buf); 1642 return GSS_S_FAILURE; 1643 } 1644 1645 /* Token is { "header" | get_mic("header" | plaintext-data) } */ 1646 memcpy(message_token->value, token, sizeof(*token)); 1647 memcpy((u_char *)message_token->value + sizeof(*token), 1648 cksum.checksum.data, cksum.checksum.length); 1649 1650 free_Checksum(&cksum); 1651 free(buf); 1652 1653 *minor_status = 0; 1654 return GSS_S_COMPLETE; 1655 } 1656 1657 OM_uint32 _gssapi_verify_mic_cfx(OM_uint32 *minor_status, 1658 const gsskrb5_ctx ctx, 1659 krb5_context context, 1660 const gss_buffer_t message_buffer, 1661 const gss_buffer_t token_buffer, 1662 gss_qop_t *qop_state) 1663 { 1664 gss_cfx_mic_token token; 1665 u_char token_flags; 1666 krb5_error_code ret; 1667 unsigned usage; 1668 OM_uint32 seq_number_lo, seq_number_hi; 1669 u_char *buf, *p; 1670 Checksum cksum; 1671 1672 *minor_status = 0; 1673 1674 if (token_buffer->length < sizeof(*token)) { 1675 return GSS_S_DEFECTIVE_TOKEN; 1676 } 1677 1678 p = token_buffer->value; 1679 1680 token = (gss_cfx_mic_token)p; 1681 1682 if (token->TOK_ID[0] != 0x04 || token->TOK_ID[1] != 0x04) { 1683 return GSS_S_DEFECTIVE_TOKEN; 1684 } 1685 1686 /* Ignore unknown flags */ 1687 token_flags = token->Flags & (CFXSentByAcceptor | CFXAcceptorSubkey); 1688 1689 if (token_flags & CFXSentByAcceptor) { 1690 if ((ctx->more_flags & LOCAL) == 0) 1691 return GSS_S_DEFECTIVE_TOKEN; 1692 } 1693 if (ctx->more_flags & ACCEPTOR_SUBKEY) { 1694 if ((token_flags & CFXAcceptorSubkey) == 0) 1695 return GSS_S_DEFECTIVE_TOKEN; 1696 } else { 1697 if (token_flags & CFXAcceptorSubkey) 1698 return GSS_S_DEFECTIVE_TOKEN; 1699 } 1700 1701 if (ct_memcmp(token->Filler, "\xff\xff\xff\xff\xff", 5) != 0) { 1702 return GSS_S_DEFECTIVE_TOKEN; 1703 } 1704 1705 /* 1706 * Check sequence number 1707 */ 1708 _gsskrb5_decode_be_om_uint32(&token->SND_SEQ[0], &seq_number_hi); 1709 _gsskrb5_decode_be_om_uint32(&token->SND_SEQ[4], &seq_number_lo); 1710 if (seq_number_hi) { 1711 *minor_status = ERANGE; 1712 return GSS_S_UNSEQ_TOKEN; 1713 } 1714 1715 HEIMDAL_MUTEX_lock(&ctx->ctx_id_mutex); 1716 ret = _gssapi_msg_order_check(ctx->order, seq_number_lo); 1717 if (ret != 0) { 1718 *minor_status = 0; 1719 HEIMDAL_MUTEX_unlock(&ctx->ctx_id_mutex); 1720 return ret; 1721 } 1722 HEIMDAL_MUTEX_unlock(&ctx->ctx_id_mutex); 1723 1724 /* 1725 * Verify checksum 1726 */ 1727 ret = krb5_crypto_get_checksum_type(context, ctx->crypto, 1728 &cksum.cksumtype); 1729 if (ret != 0) { 1730 *minor_status = ret; 1731 return GSS_S_FAILURE; 1732 } 1733 1734 cksum.checksum.data = p + sizeof(*token); 1735 cksum.checksum.length = token_buffer->length - sizeof(*token); 1736 1737 if (ctx->more_flags & LOCAL) { 1738 usage = KRB5_KU_USAGE_ACCEPTOR_SIGN; 1739 } else { 1740 usage = KRB5_KU_USAGE_INITIATOR_SIGN; 1741 } 1742 1743 buf = malloc(message_buffer->length + sizeof(*token)); 1744 if (buf == NULL) { 1745 *minor_status = ENOMEM; 1746 return GSS_S_FAILURE; 1747 } 1748 memcpy(buf, message_buffer->value, message_buffer->length); 1749 memcpy(buf + message_buffer->length, token, sizeof(*token)); 1750 1751 ret = krb5_verify_checksum(context, ctx->crypto, 1752 usage, 1753 buf, 1754 sizeof(*token) + message_buffer->length, 1755 &cksum); 1756 if (ret != 0) { 1757 *minor_status = ret; 1758 free(buf); 1759 return GSS_S_BAD_MIC; 1760 } 1761 1762 free(buf); 1763 1764 if (qop_state != NULL) { 1765 *qop_state = GSS_C_QOP_DEFAULT; 1766 } 1767 1768 return GSS_S_COMPLETE; 1769 } 1770