1/* 2 * Copyright (c) 2006 Kungliga Tekniska Högskolan 3 * (Royal Institute of Technology, Stockholm, Sweden). 4 * All rights reserved. 5 * 6 * Redistribution and use in source and binary forms, with or without 7 * modification, are permitted provided that the following conditions 8 * are met: 9 * 10 * 1. Redistributions of source code must retain the above copyright 11 * notice, this list of conditions and the following disclaimer. 12 * 13 * 2. Redistributions in binary form must reproduce the above copyright 14 * notice, this list of conditions and the following disclaimer in the 15 * documentation and/or other materials provided with the distribution. 16 * 17 * 3. Neither the name of the Institute nor the names of its contributors 18 * may be used to endorse or promote products derived from this software 19 * without specific prior written permission. 20 * 21 * THIS SOFTWARE IS PROVIDED BY THE INSTITUTE AND CONTRIBUTORS ``AS IS'' AND 22 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 23 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE 24 * ARE DISCLAIMED. IN NO EVENT SHALL THE INSTITUTE OR CONTRIBUTORS BE LIABLE 25 * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL 26 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS 27 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) 28 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT 29 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY 30 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF 31 * SUCH DAMAGE. 32 */ 33 34#include "ntlm.h" 35 36uint32_t 37_krb5_crc_update (const char *p, size_t len, uint32_t res); 38void 39_krb5_crc_init_table(void); 40 41/* 42 * 43 */ 44 45const char a2i_signmagic[] = 46 "session key to server-to-client signing key magic constant"; 47const char a2i_sealmagic[] = 48 "session key to server-to-client sealing key magic constant"; 49const char i2a_signmagic[] = 50 "session key to client-to-server signing key magic constant"; 51const char i2a_sealmagic[] = 52 "session key to client-to-server sealing key magic constant"; 53 54 55static void 56_gss_ntlm_set_key(struct ntlmv2_key *key, int acceptor, int sealsign, 57 unsigned char *data, size_t len) 58{ 59 unsigned char out[16]; 60 CCDigestRef ctx; 61 const char *signmagic; 62 const char *sealmagic; 63 64 if (acceptor) { 65 signmagic = a2i_signmagic; 66 sealmagic = a2i_sealmagic; 67 } else { 68 signmagic = i2a_signmagic; 69 sealmagic = i2a_sealmagic; 70 } 71 72 key->seq = 0; 73 74 ctx = CCDigestCreate(kCCDigestMD5); 75 CCDigestUpdate(ctx, data, len); 76 CCDigestUpdate(ctx, signmagic, strlen(signmagic) + 1); 77 CCDigestFinal(ctx, key->signkey); 78 79 CCDigestReset(ctx); 80 CCDigestUpdate(ctx, data, len); 81 CCDigestUpdate(ctx, sealmagic, strlen(sealmagic) + 1); 82 CCDigestFinal(ctx, out); 83 CCDigestDestroy(ctx); 84 85 EVP_CIPHER_CTX_cleanup(&key->sealkey); 86 87 EVP_CipherInit_ex(&key->sealkey, EVP_rc4(), NULL, out, NULL, 1); 88 if (sealsign) { 89 key->signsealkey = &key->sealkey; 90 } 91} 92 93/* 94 * Set (or reset) keys 95 */ 96 97void 98_gss_ntlm_set_keys(ntlm_ctx ctx) 99{ 100 int acceptor = (ctx->status & STATUS_CLIENT) ? 0 : 1; 101 102 if (ctx->sessionkey.length == 0) 103 return; 104 105 ctx->status |= STATUS_SESSIONKEY; 106 107 if (ctx->flags & NTLM_NEG_SEAL) 108 ctx->gssflags |= GSS_C_CONF_FLAG; 109 if (ctx->flags & (NTLM_NEG_SIGN|NTLM_NEG_ALWAYS_SIGN)) 110 ctx->gssflags |= GSS_C_INTEG_FLAG; 111 112 if (ctx->flags & NTLM_NEG_NTLM2_SESSION) { 113 _gss_ntlm_set_key(&ctx->u.v2.send, acceptor, 114 (ctx->flags & NTLM_NEG_KEYEX), 115 ctx->sessionkey.data, 116 ctx->sessionkey.length); 117 _gss_ntlm_set_key(&ctx->u.v2.recv, !acceptor, 118 (ctx->flags & NTLM_NEG_KEYEX), 119 ctx->sessionkey.data, 120 ctx->sessionkey.length); 121 } else { 122 EVP_CIPHER_CTX_cleanup(&ctx->u.v1.crypto_send.key); 123 EVP_CIPHER_CTX_cleanup(&ctx->u.v1.crypto_recv.key); 124 125 EVP_CipherInit_ex(&ctx->u.v1.crypto_send.key, EVP_rc4(), NULL, 126 ctx->sessionkey.data, NULL, 1); 127 EVP_CipherInit_ex(&ctx->u.v1.crypto_recv.key, EVP_rc4(), NULL, 128 ctx->sessionkey.data, NULL, 1); 129 } 130} 131 132void 133_gss_ntlm_destroy_crypto(ntlm_ctx ctx) 134{ 135 if ((ctx->status & STATUS_SESSIONKEY) == 0) 136 return; 137 138 if (ctx->flags & NTLM_NEG_NTLM2_SESSION) { 139 EVP_CIPHER_CTX_cleanup(&ctx->u.v2.send.sealkey); 140 EVP_CIPHER_CTX_cleanup(&ctx->u.v2.recv.sealkey); 141 } else { 142 EVP_CIPHER_CTX_cleanup(&ctx->u.v1.crypto_send.key); 143 EVP_CIPHER_CTX_cleanup(&ctx->u.v1.crypto_recv.key); 144 } 145} 146 147 148/* 149 * 150 */ 151 152static OM_uint32 153v1_sign_message(EVP_CIPHER_CTX *signkey, 154 uint32_t seq, 155 gss_iov_buffer_t trailer, 156 gss_iov_buffer_desc *iov, 157 int iov_count) 158{ 159 unsigned char *out = trailer->buffer.value; 160 unsigned char signature[12]; 161 uint32_t crc = 0; 162 int i; 163 164 _krb5_crc_init_table(); 165 166 for (i = 0; i < iov_count; i++) { 167 gss_iov_buffer_t iovp = &iov[i]; 168 169 switch (GSS_IOV_BUFFER_TYPE(iovp->type)) { 170 case GSS_IOV_BUFFER_TYPE_DATA: 171 case GSS_IOV_BUFFER_TYPE_PADDING: 172 case GSS_IOV_BUFFER_TYPE_SIGN_ONLY: 173 crc = _krb5_crc_update(iovp->buffer.value, iovp->buffer.length, crc); 174 break; 175 default: 176 break; 177 } 178 } 179 180 _gss_mg_encode_le_uint32(0, &signature[0]); 181 _gss_mg_encode_le_uint32(crc, &signature[4]); 182 _gss_mg_encode_le_uint32(seq, &signature[8]); 183 184 _gss_mg_encode_le_uint32(1, out); /* version */ 185 186 EVP_Cipher(signkey, out + 4, signature, sizeof(signature)); 187 188 if (CCRandomCopyBytes(kCCRandomDefault, out + 4, 4)) 189 return GSS_S_UNAVAILABLE; 190 191 return 0; 192} 193 194 195static OM_uint32 196v2_sign_message(unsigned char signkey[16], 197 EVP_CIPHER_CTX *sealkey, 198 uint32_t seq, 199 gss_iov_buffer_t trailer, 200 gss_iov_buffer_desc *iov, 201 int iov_count) 202{ 203 unsigned char *out = trailer->buffer.value; 204 unsigned char hmac[16]; 205 CCHmacContext c; 206 int i; 207 208 assert(trailer->buffer.length == 16); 209 210 CCHmacInit(&c, kCCHmacAlgMD5, signkey, 16); 211 212 _gss_mg_encode_le_uint32(seq, hmac); 213 CCHmacUpdate(&c, hmac, 4); 214 for (i = 0; i < iov_count; i++) { 215 gss_iov_buffer_t iovp = &iov[i]; 216 217 /* 218 * We include empty buffers because NTLM2 always does 219 * DCE RPC header signing regardless of whether it was 220 * negotiated at bind time. The DCE RPC runtime will 221 * submit EMPTY header buffers when signing is disabled. 222 */ 223 switch (GSS_IOV_BUFFER_TYPE(iovp->type)) { 224 case GSS_IOV_BUFFER_TYPE_EMPTY: 225 case GSS_IOV_BUFFER_TYPE_DATA: 226 case GSS_IOV_BUFFER_TYPE_PADDING: 227 case GSS_IOV_BUFFER_TYPE_SIGN_ONLY: 228 CCHmacUpdate(&c, iovp->buffer.value, iovp->buffer.length); 229 break; 230 default: 231 break; 232 } 233 } 234 CCHmacFinal(&c, hmac); 235 memset(&c, 0, sizeof(c)); 236 237 _gss_mg_encode_le_uint32(1, &out[0]); 238 if (sealkey) 239 EVP_Cipher(sealkey, out + 4, hmac, 8); 240 else 241 memcpy(&out[4], hmac, 8); 242 243 memset(&out[12], 0, 4); 244 245 return GSS_S_COMPLETE; 246} 247 248static OM_uint32 249v2_verify_message(unsigned char signkey[16], 250 EVP_CIPHER_CTX *sealkey, 251 uint32_t seq, 252 gss_iov_buffer_t trailer, 253 gss_iov_buffer_desc *iov, 254 int iov_count) 255{ 256 OM_uint32 ret; 257 unsigned char outbuf[16]; 258 gss_iov_buffer_desc out; 259 260 if (trailer->buffer.length != 16) 261 return GSS_S_BAD_MIC; 262 263 _gss_mg_decode_be_uint32((uint8_t *)trailer->buffer.value + 12, &seq); 264 265 out.type = GSS_IOV_BUFFER_TYPE_TRAILER; 266 out.buffer.length = sizeof(outbuf); 267 out.buffer.value = outbuf; 268 269 ret = v2_sign_message(signkey, sealkey, seq, &out, iov, iov_count); 270 if (ret) 271 return ret; 272 273 if (ct_memcmp(trailer->buffer.value, outbuf, 16)) 274 return GSS_S_BAD_MIC; 275 276 return GSS_S_COMPLETE; 277} 278 279static OM_uint32 280v2_seal_message(unsigned char signkey[16], 281 uint32_t seq, 282 EVP_CIPHER_CTX *sealkey, 283 gss_iov_buffer_t trailer, 284 gss_iov_buffer_desc *iov, 285 int iov_count) 286{ 287 OM_uint32 ret; 288 int i; 289 290 for (i = 0; i < iov_count; i++) { 291 gss_iov_buffer_t iovp = &iov[i]; 292 293 switch (GSS_IOV_BUFFER_TYPE(iovp->type)) { 294 case GSS_IOV_BUFFER_TYPE_DATA: 295 case GSS_IOV_BUFFER_TYPE_PADDING: 296 EVP_Cipher(sealkey, iovp->buffer.value, iovp->buffer.value, 297 iovp->buffer.length); 298 break; 299 default: 300 break; 301 } 302 } 303 304 assert(trailer->buffer.length == 16); 305 306 ret = v2_sign_message(signkey, sealkey, seq, trailer, iov, iov_count); 307 308 return ret; 309} 310 311static OM_uint32 312v2_unseal_message(unsigned char signkey[16], 313 uint32_t seq, 314 EVP_CIPHER_CTX *sealkey, 315 gss_iov_buffer_t trailer, 316 gss_iov_buffer_desc *iov, 317 int iov_count) 318{ 319 OM_uint32 ret; 320 int i; 321 322 for (i = 0; i < iov_count; i++) { 323 gss_iov_buffer_t iovp = &iov[i]; 324 325 switch (GSS_IOV_BUFFER_TYPE(iovp->type)) { 326 case GSS_IOV_BUFFER_TYPE_DATA: 327 case GSS_IOV_BUFFER_TYPE_PADDING: 328 EVP_Cipher(sealkey, iovp->buffer.value, iovp->buffer.value, 329 iovp->buffer.length); 330 break; 331 default: 332 break; 333 } 334 } 335 336 ret = v2_verify_message(signkey, sealkey, seq, 337 trailer, iov, iov_count); 338 339 return ret; 340} 341 342/* 343 * 344 */ 345 346#define CTX_FLAGS_ISSET(_ctx,_flags) \ 347 (((_ctx)->flags & (_flags)) == (_flags)) 348 349/* 350 * 351 */ 352 353static OM_uint32 get_mic_iov 354 (OM_uint32 * minor_status, 355 const gss_ctx_id_t context_handle, 356 gss_qop_t qop_req, 357 gss_iov_buffer_t trailer, 358 gss_iov_buffer_desc *iov, 359 int iov_count 360 ) 361{ 362 ntlm_ctx ctx = (ntlm_ctx)context_handle; 363 364 *minor_status = 0; 365 366 assert(trailer->buffer.length == 16); 367 assert(trailer->buffer.value != NULL); 368 369 if (CTX_FLAGS_ISSET(ctx, NTLM_NEG_SIGN|NTLM_NEG_NTLM2_SESSION)) { 370 OM_uint32 ret; 371 372 if ((ctx->status & STATUS_SESSIONKEY) == 0) 373 return GSS_S_UNAVAILABLE; 374 375 ret = v2_sign_message(ctx->u.v2.send.signkey, 376 ctx->u.v2.send.signsealkey, 377 ctx->u.v2.send.seq++, 378 trailer, iov, iov_count); 379 return ret; 380 381 } else if (CTX_FLAGS_ISSET(ctx, NTLM_NEG_SIGN)) { 382 OM_uint32 ret; 383 384 if ((ctx->status & STATUS_SESSIONKEY) == 0) 385 return GSS_S_UNAVAILABLE; 386 387 ret = v1_sign_message(&ctx->u.v1.crypto_send.key, 388 ctx->u.v1.crypto_send.seq++, 389 trailer, iov, iov_count); 390 return ret; 391 392 } else if (CTX_FLAGS_ISSET(ctx, NTLM_NEG_ALWAYS_SIGN)) { 393 unsigned char *signature; 394 395 signature = trailer->buffer.value; 396 397 _gss_mg_encode_le_uint32(1, &signature[0]); /* version */ 398 _gss_mg_encode_le_uint32(0, &signature[4]); 399 _gss_mg_encode_le_uint32(0, &signature[8]); 400 _gss_mg_encode_le_uint32(0, &signature[12]); 401 402 return GSS_S_COMPLETE; 403 } 404 405 return GSS_S_UNAVAILABLE; 406} 407 408OM_uint32 _gss_ntlm_get_mic 409 (OM_uint32 * minor_status, 410 const gss_ctx_id_t context_handle, 411 gss_qop_t qop_req, 412 const gss_buffer_t message_buffer, 413 gss_buffer_t message_token 414 ) 415{ 416 gss_iov_buffer_desc iov[2]; 417 OM_uint32 ret, junk; 418 419 iov[0].type = GSS_IOV_BUFFER_TYPE_DATA; 420 iov[0].buffer = *message_buffer; 421 422 iov[1].type = GSS_IOV_BUFFER_TYPE_TRAILER; 423 iov[1].buffer.length = 16; 424 iov[1].buffer.value = malloc(iov[1].buffer.length); 425 if (iov[1].buffer.value == NULL) { 426 *minor_status = ENOMEM; 427 return GSS_S_FAILURE; 428 } 429 430 ret = get_mic_iov(minor_status, context_handle, qop_req, 431 &iov[1], iov, 1); 432 433 if (ret) 434 gss_release_buffer(&junk, &iov[1].buffer); 435 else 436 *message_token = iov[1].buffer; 437 438 return ret; 439} 440 441/* 442 * 443 */ 444 445static OM_uint32 446verify_mic_iov 447 (OM_uint32 * minor_status, 448 const gss_ctx_id_t context_handle, 449 gss_iov_buffer_t trailer, 450 gss_qop_t * qop_state, 451 gss_iov_buffer_desc *iov, 452 int iov_count 453 ) 454{ 455 ntlm_ctx ctx = (ntlm_ctx)context_handle; 456 457 if (qop_state != NULL) 458 *qop_state = GSS_C_QOP_DEFAULT; 459 *minor_status = 0; 460 461 if (trailer->buffer.length != 16) 462 return GSS_S_BAD_MIC; 463 464 if (CTX_FLAGS_ISSET(ctx, NTLM_NEG_SIGN|NTLM_NEG_NTLM2_SESSION)) { 465 OM_uint32 ret; 466 467 if ((ctx->status & STATUS_SESSIONKEY) == 0) 468 return GSS_S_UNAVAILABLE; 469 470 ret = v2_verify_message(ctx->u.v2.recv.signkey, 471 ctx->u.v2.recv.signsealkey, 472 0, 473 trailer, iov, iov_count); 474 if (ret) 475 return ret; 476 477 return GSS_S_COMPLETE; 478 } else if (CTX_FLAGS_ISSET(ctx, NTLM_NEG_SIGN)) { 479 unsigned char signature[12]; 480 uint32_t crc = 0, num; 481 int i; 482 483 if ((ctx->status & STATUS_SESSIONKEY) == 0) 484 return GSS_S_UNAVAILABLE; 485 486 _gss_mg_decode_le_uint32(trailer->buffer.value, &num); 487 if (num != 1) 488 return GSS_S_BAD_MIC; 489 490 EVP_Cipher(&ctx->u.v1.crypto_recv.key, signature, 491 ((unsigned char *)trailer->buffer.value) + 4, 492 sizeof(signature)); 493 494 _krb5_crc_init_table(); 495 496 for (i = 0; i < iov_count; i++) { 497 gss_iov_buffer_t iovp = &iov[i]; 498 499 switch (GSS_IOV_BUFFER_TYPE(iovp->type)) { 500 case GSS_IOV_BUFFER_TYPE_DATA: 501 case GSS_IOV_BUFFER_TYPE_PADDING: 502 case GSS_IOV_BUFFER_TYPE_SIGN_ONLY: 503 crc = _krb5_crc_update(iovp->buffer.value, 504 iovp->buffer.length, crc); 505 break; 506 default: 507 break; 508 } 509 } 510 511 /* skip first 4 bytes in the encrypted checksum */ 512 _gss_mg_decode_le_uint32(&signature[4], &num); 513 if (num != crc) 514 return GSS_S_BAD_MIC; 515 _gss_mg_decode_le_uint32(&signature[8], &num); 516 if (ctx->u.v1.crypto_recv.seq != num) 517 return GSS_S_BAD_MIC; 518 ctx->u.v1.crypto_recv.seq++; 519 520 return GSS_S_COMPLETE; 521 } else if (ctx->flags & NTLM_NEG_ALWAYS_SIGN) { 522 uint32_t num; 523 unsigned char *p; 524 525 p = (unsigned char*)(trailer->buffer.value); 526 527 _gss_mg_decode_le_uint32(&p[0], &num); /* version */ 528 if (num != 1) return GSS_S_BAD_MIC; 529 _gss_mg_decode_le_uint32(&p[4], &num); 530 if (num != 0) return GSS_S_BAD_MIC; 531 _gss_mg_decode_le_uint32(&p[8], &num); 532 if (num != 0) return GSS_S_BAD_MIC; 533 _gss_mg_decode_le_uint32(&p[12], &num); 534 if (num != 0) return GSS_S_BAD_MIC; 535 536 return GSS_S_COMPLETE; 537 } 538 539 return GSS_S_UNAVAILABLE; 540} 541 542OM_uint32 543_gss_ntlm_verify_mic 544 (OM_uint32 * minor_status, 545 const gss_ctx_id_t context_handle, 546 const gss_buffer_t message_buffer, 547 const gss_buffer_t token_buffer, 548 gss_qop_t * qop_state 549 ) 550{ 551 gss_iov_buffer_desc iov[2]; 552 553 iov[0].type = GSS_IOV_BUFFER_TYPE_DATA; 554 iov[0].buffer = *message_buffer; 555 556 iov[1].type = GSS_IOV_BUFFER_TYPE_TRAILER; 557 iov[1].buffer = *token_buffer; 558 559 return verify_mic_iov(minor_status, context_handle, 560 &iov[1], qop_state, iov, 1); 561} 562 563/* 564 * 565 */ 566 567OM_uint32 568_gss_ntlm_wrap_size_limit ( 569 OM_uint32 * minor_status, 570 const gss_ctx_id_t context_handle, 571 int conf_req_flag, 572 gss_qop_t qop_req, 573 OM_uint32 req_output_size, 574 OM_uint32 * max_input_size 575 ) 576{ 577 ntlm_ctx ctx = (ntlm_ctx)context_handle; 578 579 *minor_status = 0; 580 581 if(ctx->flags & NTLM_NEG_SEAL) { 582 583 if (req_output_size < 16) 584 *max_input_size = 0; 585 else 586 *max_input_size = req_output_size - 16; 587 588 return GSS_S_COMPLETE; 589 } 590 591 return GSS_S_UNAVAILABLE; 592} 593 594/* 595 * 596 */ 597 598OM_uint32 _gss_ntlm_wrap_iov 599(OM_uint32 * minor_status, 600 const gss_ctx_id_t context_handle, 601 int conf_req_flag, 602 gss_qop_t qop_req, 603 int * conf_state, 604 gss_iov_buffer_desc *iov, 605 int iov_count 606 ) 607{ 608 ntlm_ctx ctx = (ntlm_ctx)context_handle; 609 OM_uint32 ret; 610 gss_iov_buffer_t trailer; 611 612 *minor_status = 0; 613 if (conf_state) 614 *conf_state = 0; 615 if (iov == GSS_C_NO_IOV_BUFFER) 616 return GSS_S_FAILURE; 617 618 /* TRAILER for normal protocols, HEADER for DCE */ 619 trailer = _gss_mg_find_buffer(iov, iov_count, GSS_IOV_BUFFER_TYPE_TRAILER); 620 if (trailer == NULL) { 621 trailer = _gss_mg_find_buffer(iov, iov_count, GSS_IOV_BUFFER_TYPE_HEADER); 622 if (trailer == NULL) { 623 *minor_status = HNTLM_ERR_MISSING_BUFFER; 624 return gss_mg_set_error_string(GSS_NTLM_MECHANISM, GSS_S_FAILURE, 625 HNTLM_ERR_MISSING_BUFFER, 626 "iov header buffer missing"); 627 } 628 } 629 if (GSS_IOV_BUFFER_FLAGS(trailer->type) & GSS_IOV_BUFFER_TYPE_FLAG_ALLOCATE) { 630 ret = _gss_mg_allocate_buffer(minor_status, trailer, 16); 631 if (ret) 632 return ret; 633 } else if (trailer->buffer.length < 16) { 634 *minor_status = KRB5_BAD_MSIZE; 635 return GSS_S_FAILURE; 636 } else { 637 trailer->buffer.length = 16; 638 } 639 640 if (CTX_FLAGS_ISSET(ctx, NTLM_NEG_SEAL|NTLM_NEG_NTLM2_SESSION)) { 641 642 return v2_seal_message(ctx->u.v2.send.signkey, 643 ctx->u.v2.send.seq++, 644 &ctx->u.v2.send.sealkey, 645 trailer, iov, iov_count); 646 647 } else if (CTX_FLAGS_ISSET(ctx, NTLM_NEG_SEAL)) { 648 int i; 649 650 for (i = 0; i < iov_count; i++) { 651 gss_iov_buffer_t iovp = &iov[i]; 652 653 switch (GSS_IOV_BUFFER_TYPE(iovp->type)) { 654 case GSS_IOV_BUFFER_TYPE_DATA: 655 case GSS_IOV_BUFFER_TYPE_PADDING: 656 EVP_Cipher(&ctx->u.v1.crypto_send.key, 657 iovp->buffer.value, iovp->buffer.value, 658 iovp->buffer.length); 659 break; 660 default: 661 break; 662 } 663 } 664 665 ret = get_mic_iov(minor_status, context_handle, 666 0, trailer, iov, iov_count); 667 668 return ret; 669 } 670 671 return GSS_S_UNAVAILABLE; 672} 673 674OM_uint32 _gss_ntlm_wrap 675(OM_uint32 * minor_status, 676 const gss_ctx_id_t context_handle, 677 int conf_req_flag, 678 gss_qop_t qop_req, 679 const gss_buffer_t input_message_buffer, 680 int * conf_state, 681 gss_buffer_t output_message_buffer) 682{ 683 gss_iov_buffer_desc iov[2]; 684 OM_uint32 ret; 685 686 output_message_buffer->length = input_message_buffer->length + 16; 687 output_message_buffer->value = malloc(output_message_buffer->length); 688 if (output_message_buffer->value == NULL) { 689 *minor_status = ENOMEM; 690 return GSS_S_FAILURE; 691 } 692 693 iov[0].type = GSS_IOV_BUFFER_TYPE_DATA; 694 iov[0].buffer.length = input_message_buffer->length; 695 iov[0].buffer.value = output_message_buffer->value; 696 memcpy(iov[0].buffer.value, input_message_buffer->value, 697 input_message_buffer->length); 698 699 iov[1].type = GSS_IOV_BUFFER_TYPE_TRAILER; 700 iov[1].buffer.length = 16; 701 iov[1].buffer.value = (unsigned char *)output_message_buffer->value + 16; 702 703 ret = _gss_ntlm_wrap_iov(minor_status, context_handle, 704 conf_req_flag, qop_req, 705 conf_state, iov, sizeof(iov)/sizeof(iov[0])); 706 if (GSS_ERROR(ret)) { 707 OM_uint32 tmp; 708 gss_release_buffer(&tmp, output_message_buffer); 709 } 710 711 return ret; 712} 713 714/* 715 * 716 */ 717 718OM_uint32 _gss_ntlm_unwrap_iov 719 (OM_uint32 * minor_status, 720 const gss_ctx_id_t context_handle, 721 int * conf_state, 722 gss_qop_t * qop_state, 723 gss_iov_buffer_desc *iov, 724 int iov_count 725 ) 726{ 727 ntlm_ctx ctx = (ntlm_ctx)context_handle; 728 OM_uint32 ret; 729 gss_iov_buffer_t trailer; 730 731 *minor_status = 0; 732 733 if (conf_state) 734 *conf_state = 0; 735 if (qop_state) 736 *qop_state = 0; 737 738 /* TRAILER for normal protocols, HEADER for DCE */ 739 trailer = _gss_mg_find_buffer(iov, iov_count, GSS_IOV_BUFFER_TYPE_TRAILER); 740 if (trailer == NULL) { 741 trailer = _gss_mg_find_buffer(iov, iov_count, GSS_IOV_BUFFER_TYPE_HEADER); 742 if (trailer == NULL) { 743 *minor_status = HNTLM_ERR_MISSING_BUFFER; 744 return gss_mg_set_error_string(GSS_NTLM_MECHANISM, GSS_S_FAILURE, 745 HNTLM_ERR_MISSING_BUFFER, 746 "iov tailer buffer missing"); 747 } 748 } 749 750 if (trailer->buffer.length < 16) 751 return GSS_S_BAD_MIC; 752 753 if (CTX_FLAGS_ISSET(ctx, NTLM_NEG_SEAL|NTLM_NEG_NTLM2_SESSION)) { 754 755 return v2_unseal_message(ctx->u.v2.recv.signkey, 756 ctx->u.v2.recv.seq++, 757 &ctx->u.v2.recv.sealkey, 758 trailer, 759 iov, 760 iov_count); 761 762 } else if (CTX_FLAGS_ISSET(ctx, NTLM_NEG_SEAL)) { 763 764 int i; 765 766 for (i = 0; i < iov_count; i++) { 767 gss_iov_buffer_t iovp = &iov[i]; 768 769 switch (GSS_IOV_BUFFER_TYPE(iovp->type)) { 770 case GSS_IOV_BUFFER_TYPE_DATA: 771 case GSS_IOV_BUFFER_TYPE_PADDING: 772 EVP_Cipher(&ctx->u.v1.crypto_recv.key, 773 iovp->buffer.value, iovp->buffer.value, 774 iovp->buffer.length); 775 break; 776 default: 777 break; 778 } 779 } 780 781 ret = verify_mic_iov(minor_status, context_handle, 782 trailer, NULL, iov, iov_count); 783 784 return ret; 785 } 786 787 return GSS_S_UNAVAILABLE; 788} 789 790OM_uint32 _gss_ntlm_unwrap 791 (OM_uint32 * minor_status, 792 const gss_ctx_id_t context_handle, 793 const gss_buffer_t input_message_buffer, 794 gss_buffer_t output_message_buffer, 795 int * conf_state, 796 gss_qop_t * qop_state 797 ) 798{ 799 gss_iov_buffer_desc iov[2]; 800 OM_uint32 ret; 801 802 if (input_message_buffer->length < 16) 803 return GSS_S_DEFECTIVE_TOKEN; 804 805 output_message_buffer->length = input_message_buffer->length - 16; 806 output_message_buffer->value = malloc(output_message_buffer->length); 807 if (output_message_buffer->value == NULL) { 808 *minor_status = ENOMEM; 809 return GSS_S_FAILURE; 810 } 811 memcpy(output_message_buffer->value, input_message_buffer->value, 812 output_message_buffer->length); 813 814 iov[0].type = GSS_IOV_BUFFER_TYPE_DATA; 815 iov[0].buffer = *output_message_buffer; 816 817 iov[1].type = GSS_IOV_BUFFER_TYPE_TRAILER; 818 iov[1].buffer.value = (unsigned char *)input_message_buffer->value + 819 input_message_buffer->length - 16; 820 iov[1].buffer.length = 16; 821 822 ret = _gss_ntlm_unwrap_iov(minor_status, context_handle, 823 conf_state, qop_state, iov, 824 sizeof(iov)/sizeof(iov[0])); 825 if (GSS_ERROR(ret)) { 826 OM_uint32 tmp; 827 gss_release_buffer(&tmp, output_message_buffer); 828 } 829 830 return ret; 831} 832 833OM_uint32 834_gss_ntlm_wrap_iov_length(OM_uint32 * minor_status, 835 gss_ctx_id_t context_handle, 836 int conf_req_flag, 837 gss_qop_t qop_req, 838 int *conf_state, 839 gss_iov_buffer_desc *iov, 840 int iov_count) 841{ 842 gss_iov_buffer_t iovp; 843 OM_uint32 ctype; 844 845 /* DCE puts the trailer in the HEADER, other protocols in TRAILER. */ 846 iovp = _gss_mg_find_buffer(iov, iov_count, GSS_IOV_BUFFER_TYPE_TRAILER); 847 if (iovp == NULL) { 848 iovp = _gss_mg_find_buffer(iov, iov_count, GSS_IOV_BUFFER_TYPE_HEADER); 849 if (iovp == NULL) { 850 *minor_status = HNTLM_ERR_MISSING_BUFFER; 851 return gss_mg_set_error_string(GSS_NTLM_MECHANISM, GSS_S_FAILURE, 852 HNTLM_ERR_MISSING_BUFFER, 853 "iov header buffer missing"); 854 } else 855 ctype = GSS_IOV_BUFFER_TYPE_TRAILER; 856 } else 857 ctype = GSS_IOV_BUFFER_TYPE_HEADER; 858 859 iovp->buffer.length = 16; 860 861 iovp = _gss_mg_find_buffer(iov, iov_count, GSS_IOV_BUFFER_TYPE_PADDING); 862 if (iovp != NULL) 863 iovp->buffer.length = 0; 864 865 /* No HEADER if we have a TRAILER and vice versa */ 866 iovp = _gss_mg_find_buffer(iov, iov_count, ctype); 867 if (iovp != NULL) 868 iovp->buffer.length = 0; 869 870 if (conf_state != NULL) 871 *conf_state = conf_req_flag; 872 873 *minor_status = 0; 874 return GSS_S_COMPLETE; 875} 876 877