1/* 2 * Copyright (c) 2010 Kungliga Tekniska Högskolan 3 * (Royal Institute of Technology, Stockholm, Sweden). 4 * All rights reserved. 5 * 6 * Portions Copyright (c) 2010 Apple Inc. All rights reserved. 7 * 8 * Redistribution and use in source and binary forms, with or without 9 * modification, are permitted provided that the following conditions 10 * are met: 11 * 12 * 1. Redistributions of source code must retain the above copyright 13 * notice, this list of conditions and the following disclaimer. 14 * 15 * 2. Redistributions in binary form must reproduce the above copyright 16 * notice, this list of conditions and the following disclaimer in the 17 * documentation and/or other materials provided with the distribution. 18 * 19 * 3. Neither the name of the Institute nor the names of its contributors 20 * may be used to endorse or promote products derived from this software 21 * without specific prior written permission. 22 * 23 * THIS SOFTWARE IS PROVIDED BY THE INSTITUTE AND CONTRIBUTORS ``AS IS'' AND 24 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 25 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE 26 * ARE DISCLAIMED. IN NO EVENT SHALL THE INSTITUTE OR CONTRIBUTORS BE LIABLE 27 * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL 28 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS 29 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) 30 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT 31 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY 32 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF 33 * SUCH DAMAGE. 34 */ 35 36#include "netlogon.h" 37 38static uint8_t zeros[4]; 39 40static void 41_netlogon_encode_sequence_number(uint64_t SequenceNumber, uint8_t *p, 42 int initiatorFlag) 43{ 44 uint32_t LowPart, HighPart; 45 46 LowPart = (SequenceNumber >> 0 ) & 0xFFFFFFFF; 47 HighPart = (SequenceNumber >> 32) & 0xFFFFFFFF; 48 49 _gss_mg_encode_be_uint32(LowPart, &p[0]); 50 _gss_mg_encode_be_uint32(HighPart, &p[4]); 51 52 if (initiatorFlag) 53 p[4] |= 0x80; 54} 55 56static int 57_netlogon_decode_sequence_number(void *ptr, uint64_t *n, 58 int initiatorFlag) 59{ 60 uint8_t *p = ptr; 61 uint32_t LowPart, HighPart; 62 int gotInitiatorFlag; 63 64 gotInitiatorFlag = (p[4] & 0x80) != 0; 65 if (gotInitiatorFlag != initiatorFlag) 66 return -1; 67 68 p[4] &= 0x7F; /* clear initiator bit */ 69 70 _gss_mg_decode_be_uint32(&p[0], &LowPart); 71 _gss_mg_decode_be_uint32(&p[4], &HighPart); 72 73 *n = (LowPart << 0) | ((uint64_t)HighPart << 32); 74 75 return 0; 76} 77 78static inline size_t 79_netlogon_checksum_length(NL_AUTH_SIGNATURE *sig) 80{ 81#if 0 82 return (sig->SignatureAlgorithm == NL_SIGN_ALG_SHA256) ? 32 : 8; 83#else 84 /* Owing to a bug in Windows it always uses the old value */ 85 return 8; 86#endif 87} 88 89static inline size_t 90_netlogon_signature_length(uint16_t alg, int conf_req_flag) 91{ 92 return NL_AUTH_SIGNATURE_COMMON_LENGTH + 93 (alg == NL_SIGN_ALG_SHA256 ? 32 : 8) + 94 (conf_req_flag ? 8 : 0); 95} 96 97static inline uint8_t * 98_netlogon_confounder(NL_AUTH_SIGNATURE *sig) 99{ 100 size_t cksumlen = _netlogon_checksum_length(sig); 101 102 return &sig->Checksum[cksumlen]; 103} 104 105static int 106_netlogon_encode_NL_AUTH_SIGNATURE(NL_AUTH_SIGNATURE *sig, 107 uint8_t *p, size_t len) 108{ 109 *p++ = (sig->SignatureAlgorithm >> 0) & 0xFF; 110 *p++ = (sig->SignatureAlgorithm >> 8) & 0xFF; 111 *p++ = (sig->SealAlgorithm >> 0) & 0xFF; 112 *p++ = (sig->SealAlgorithm >> 8) & 0xFF; 113 *p++ = (sig->Pad >> 0) & 0xFF; 114 *p++ = (sig->Pad >> 8) & 0xFF; 115 *p++ = (sig->Flags >> 0) & 0xFF; 116 *p++ = (sig->Flags >> 8) & 0xFF; 117 118 if (len > NL_AUTH_SIGNATURE_HEADER_LENGTH) { 119 memcpy(p, sig->SequenceNumber, 8); 120 p += 8; 121 } 122 123 if (len > NL_AUTH_SIGNATURE_COMMON_LENGTH) { 124 size_t cksumlen = _netlogon_checksum_length(sig); 125 126 memcpy(p, sig->Checksum, cksumlen); 127 p += cksumlen; 128 129 /* Confounder, if present, is immediately after checksum */ 130 if (sig->SealAlgorithm != NL_SEAL_ALG_NONE) { 131 memcpy(p, &sig->Checksum[cksumlen], 8); 132 } 133 } 134 135 return 0; 136} 137 138static int 139_netlogon_decode_NL_AUTH_SIGNATURE(const uint8_t *ptr, 140 size_t len, 141 NL_AUTH_SIGNATURE *sig) 142{ 143 const uint8_t *p = ptr; 144 size_t cksumlen; 145 146 if (len < NL_AUTH_SIGNATURE_COMMON_LENGTH) 147 return KRB5_BAD_MSIZE; 148 149 sig->SignatureAlgorithm = (p[0] << 0) | (p[1] << 8); 150 sig->SealAlgorithm = (p[2] << 0) | (p[3] << 8); 151 sig->Pad = (p[4] << 0) | (p[5] << 8); 152 sig->Flags = (p[6] << 0) | (p[7] << 8); 153 p += 8; 154 155 memcpy(sig->SequenceNumber, p, 8); 156 p += 8; 157 158 /* Validate signature algorithm is known and matches enctype */ 159 switch (sig->SignatureAlgorithm) { 160 case NL_SIGN_ALG_HMAC_MD5: 161 cksumlen = NL_AUTH_SIGNATURE_LENGTH; 162 break; 163 case NL_SIGN_ALG_SHA256: 164 cksumlen = NL_AUTH_SHA2_SIGNATURE_LENGTH; 165 break; 166 default: 167 return EINVAL; 168 } 169 170 if (sig->SealAlgorithm == NL_SEAL_ALG_NONE) 171 cksumlen -= 8; /* confounder is optional if no sealing */ 172 173 if (len < cksumlen) 174 return KRB5_BAD_MSIZE; 175 176 /* Copy variable length checksum */ 177 cksumlen = _netlogon_checksum_length(sig); 178 memcpy(sig->Checksum, p, cksumlen); 179 p += cksumlen; 180 181 /* Copy confounder in past checksum */ 182 if (sig->SealAlgorithm != NL_SEAL_ALG_NONE) 183 memcpy(&sig->Checksum[cksumlen], p, 8); 184 185 return 0; 186} 187 188static void 189_netlogon_derive_rc4_hmac_key(uint8_t key[16], 190 uint8_t *salt, 191 size_t saltLength, 192 EVP_CIPHER_CTX *rc4Key, 193 int enc) 194{ 195 uint8_t tmpData[CC_MD5_DIGEST_LENGTH]; 196 uint8_t derivedKey[CC_MD5_DIGEST_LENGTH]; 197 198 CCHmac(kCCHmacAlgMD5, key, 16, zeros, sizeof(zeros), tmpData); 199 CCHmac(kCCHmacAlgMD5, tmpData, sizeof(tmpData), salt, saltLength, derivedKey); 200 201 EVP_CipherInit_ex(rc4Key, EVP_rc4(), NULL, derivedKey, NULL, enc); 202 203 memset(tmpData, 0, sizeof(tmpData)); 204 memset(derivedKey, 0, sizeof(derivedKey)); 205} 206 207static void 208_netlogon_derive_rc4_seal_key(gssnetlogon_ctx ctx, 209 NL_AUTH_SIGNATURE *sig, 210 EVP_CIPHER_CTX *sealkey, 211 int enc) 212{ 213 uint8_t xorKey[16]; 214 size_t i; 215 216 for (i = 0; i < sizeof(xorKey); i++) { 217 xorKey[i] = ctx->SessionKey[i] ^ 0xF0; 218 } 219 220 _netlogon_derive_rc4_hmac_key(xorKey, 221 sig->SequenceNumber, sizeof(sig->SequenceNumber), sealkey, enc); 222 223 memset(xorKey, 0, sizeof(xorKey)); 224} 225 226static void 227_netlogon_derive_rc4_seq_key(gssnetlogon_ctx ctx, 228 NL_AUTH_SIGNATURE *sig, 229 EVP_CIPHER_CTX *seqkey, 230 int enc) 231{ 232 _netlogon_derive_rc4_hmac_key(ctx->SessionKey, 233 sig->Checksum, sizeof(sig->Checksum), seqkey, enc); 234} 235 236static void 237_netlogon_derive_aes_seal_key(gssnetlogon_ctx ctx, 238 NL_AUTH_SIGNATURE *sig, 239 EVP_CIPHER_CTX *sealkey, 240 int enc) 241{ 242 uint8_t encryptionKey[16]; 243 uint8_t ivec[16]; 244 size_t i; 245 246 for (i = 0; i < sizeof(encryptionKey); i++) { 247 encryptionKey[i] = ctx->SessionKey[i] ^ 0xF0; 248 } 249 250 memcpy(&ivec[0], sig->SequenceNumber, 8); 251 memcpy(&ivec[8], sig->SequenceNumber, 8); 252 253 EVP_CipherInit_ex(sealkey, EVP_aes_128_cfb8(), 254 NULL, encryptionKey, ivec, enc); 255 256 memset(encryptionKey, 0, sizeof(encryptionKey)); 257} 258 259static void 260_netlogon_derive_aes_seq_key(gssnetlogon_ctx ctx, 261 NL_AUTH_SIGNATURE *sig, 262 EVP_CIPHER_CTX *seqkey, 263 int enc) 264{ 265 uint8_t ivec[16]; 266 267 memcpy(&ivec[0], sig->Checksum, 8); 268 memcpy(&ivec[8], sig->Checksum, 8); 269 270 EVP_CipherInit_ex(seqkey, EVP_aes_128_cfb8(), 271 NULL, ctx->SessionKey, ivec, enc); 272} 273 274static void 275_netlogon_seal(gssnetlogon_ctx ctx, 276 NL_AUTH_SIGNATURE *sig, 277 gss_iov_buffer_desc *iov, 278 int iov_count, 279 int enc) 280{ 281 EVP_CIPHER_CTX sealkey; 282 int i; 283 uint8_t *confounder = _netlogon_confounder(sig); 284 285 EVP_CIPHER_CTX_init(&sealkey); 286 287 if (sig->SealAlgorithm == NL_SEAL_ALG_AES128) 288 _netlogon_derive_aes_seal_key(ctx, sig, &sealkey, enc); 289 else 290 _netlogon_derive_rc4_seal_key(ctx, sig, &sealkey, enc); 291 292 EVP_Cipher(&sealkey, confounder, confounder, 8); 293 294 /* 295 * For RC4, Windows resets the cipherstate after encrypting 296 * the confounder, thus defeating the purpose of the confounder 297 */ 298 if (sig->SealAlgorithm == NL_SEAL_ALG_RC4) { 299 EVP_CipherFinal_ex(&sealkey, NULL, &i); 300 _netlogon_derive_rc4_seal_key(ctx, sig, &sealkey, enc); 301 } 302 303 for (i = 0; i < iov_count; i++) { 304 gss_iov_buffer_t iovp = &iov[i]; 305 306 switch (GSS_IOV_BUFFER_TYPE(iovp->type)) { 307 case GSS_IOV_BUFFER_TYPE_DATA: 308 case GSS_IOV_BUFFER_TYPE_PADDING: 309 EVP_Cipher(&sealkey, iovp->buffer.value, iovp->buffer.value, 310 iovp->buffer.length); 311 break; 312 default: 313 break; 314 } 315 } 316 317 EVP_CipherFinal_ex(&sealkey, NULL, &i); 318 EVP_CIPHER_CTX_cleanup(&sealkey); 319} 320 321static void 322_netlogon_seq(gssnetlogon_ctx ctx, 323 NL_AUTH_SIGNATURE *sig, 324 int enc) 325{ 326 EVP_CIPHER_CTX seqkey; 327 328 EVP_CIPHER_CTX_init(&seqkey); 329 330 if (sig->SignatureAlgorithm == NL_SIGN_ALG_SHA256) 331 _netlogon_derive_aes_seq_key(ctx, sig, &seqkey, enc); 332 else 333 _netlogon_derive_rc4_seq_key(ctx, sig, &seqkey, enc); 334 335 EVP_Cipher(&seqkey, sig->SequenceNumber, sig->SequenceNumber, 8); 336 337 EVP_CIPHER_CTX_cleanup(&seqkey); 338} 339 340static void 341_netlogon_digest_md5(gssnetlogon_ctx ctx, 342 NL_AUTH_SIGNATURE *sig, 343 gss_iov_buffer_desc *iov, 344 int iov_count, 345 uint8_t *md) 346{ 347 CCDigestRef md5; 348 uint8_t header[NL_AUTH_SIGNATURE_HEADER_LENGTH]; 349 uint8_t digest[CC_MD5_DIGEST_LENGTH]; 350 int i; 351 352 _netlogon_encode_NL_AUTH_SIGNATURE(sig, header, sizeof(header)); 353 354 md5 = CCDigestCreate(kCCDigestMD5); 355 CCDigestUpdate(md5, zeros, sizeof(zeros)); 356 CCDigestUpdate(md5, header, sizeof(header)); 357 358 if (sig->SealAlgorithm != NL_SEAL_ALG_NONE) { 359 CCDigestUpdate(md5, sig->Confounder, sizeof(sig->Confounder)); 360 } 361 362 for (i = 0; i < iov_count; i++) { 363 gss_iov_buffer_t iovp = &iov[i]; 364 365 switch (GSS_IOV_BUFFER_TYPE(iovp->type)) { 366 case GSS_IOV_BUFFER_TYPE_DATA: 367 case GSS_IOV_BUFFER_TYPE_PADDING: 368 case GSS_IOV_BUFFER_TYPE_SIGN_ONLY: 369 CCDigestUpdate(md5, iovp->buffer.value, iovp->buffer.length); 370 break; 371 default: 372 break; 373 } 374 } 375 376 CCDigestFinal(md5, digest); 377 CCDigestDestroy(md5); 378 379 CCHmac(kCCHmacAlgMD5, ctx->SessionKey, sizeof(ctx->SessionKey), digest, sizeof(digest), digest); 380 memcpy(md, digest, 8); 381} 382 383static void 384_netlogon_digest_sha256(gssnetlogon_ctx ctx, 385 NL_AUTH_SIGNATURE *sig, 386 gss_iov_buffer_desc *iov, 387 int iov_count, 388 uint8_t *md) 389{ 390 CCHmacContext hmac; 391 uint8_t header[NL_AUTH_SIGNATURE_HEADER_LENGTH]; 392 uint8_t digest[CC_SHA256_DIGEST_LENGTH]; 393 int i; 394 395 /* Encode first 8 bytes of signature into header */ 396 _netlogon_encode_NL_AUTH_SIGNATURE(sig, header, sizeof(header)); 397 398 CCHmacInit(&hmac, kCCHmacAlgSHA256, ctx->SessionKey, sizeof(ctx->SessionKey)); 399 CCHmacUpdate(&hmac, header, sizeof(header)); 400 401 if (sig->SealAlgorithm != NL_SEAL_ALG_NONE) { 402 /* 403 * If the checksum length bug is ever fixed, then be sure to 404 * update this code to point to &sig->Checksum[32] as that is 405 * where the confounder is supposed to be. 406 */ 407 CCHmacUpdate(&hmac, sig->Confounder, 8); 408 } 409 410 for (i = 0; i < iov_count; i++) { 411 gss_iov_buffer_t iovp = &iov[i]; 412 413 switch (GSS_IOV_BUFFER_TYPE(iovp->type)) { 414 case GSS_IOV_BUFFER_TYPE_DATA: 415 case GSS_IOV_BUFFER_TYPE_PADDING: 416 case GSS_IOV_BUFFER_TYPE_SIGN_ONLY: 417 CCHmacUpdate(&hmac, iovp->buffer.value, iovp->buffer.length); 418 break; 419 default: 420 break; 421 } 422 } 423 424 CCHmacFinal(&hmac, digest); 425 memset(&hmac, 0, sizeof(hmac)); 426 memcpy(md, digest, 8); 427} 428 429static void 430_netlogon_digest(gssnetlogon_ctx ctx, 431 NL_AUTH_SIGNATURE *sig, 432 gss_iov_buffer_desc *iov, 433 int iov_count, 434 uint8_t *md) 435{ 436 if (sig->SignatureAlgorithm == NL_SIGN_ALG_SHA256) 437 _netlogon_digest_sha256(ctx, sig, iov, iov_count, md); 438 else 439 _netlogon_digest_md5(ctx, sig, iov, iov_count, md); 440} 441 442OM_uint32 443_netlogon_wrap_iov(OM_uint32 * minor_status, 444 gss_ctx_id_t context_handle, 445 int conf_req_flag, 446 gss_qop_t qop_req, 447 int *conf_state, 448 gss_iov_buffer_desc *iov, 449 int iov_count) 450{ 451 OM_uint32 ret; 452 gss_iov_buffer_t header; 453 NL_AUTH_SIGNATURE_U sigbuf = { { 0 } }; 454 NL_AUTH_SIGNATURE *sig = NL_AUTH_SIGNATURE_P(&sigbuf); 455 gssnetlogon_ctx ctx = (gssnetlogon_ctx)context_handle; 456 size_t size; 457 458 if (ctx->State != NL_AUTH_ESTABLISHED) { 459 *minor_status = EINVAL; 460 return GSS_S_FAILURE; 461 } 462 463 header = _gss_mg_find_buffer(iov, iov_count, GSS_IOV_BUFFER_TYPE_HEADER); 464 if (header == NULL) { 465 *minor_status = EINVAL; 466 return GSS_S_FAILURE; 467 } 468 469 size = _netlogon_signature_length(ctx->SignatureAlgorithm, conf_req_flag); 470 471 if (GSS_IOV_BUFFER_FLAGS(header->type) & GSS_IOV_BUFFER_FLAG_ALLOCATE) { 472 ret = _gss_mg_allocate_buffer(minor_status, header, size); 473 if (GSS_ERROR(ret)) 474 return ret; 475 } else if (header->buffer.length < size) { 476 *minor_status = KRB5_BAD_MSIZE; 477 return GSS_S_FAILURE; 478 } else { 479 header->buffer.length = size; 480 } 481 482 memset(header->buffer.value, 0, header->buffer.length); 483 484 sig->SignatureAlgorithm = ctx->SignatureAlgorithm; 485 sig->SealAlgorithm = conf_req_flag ? ctx->SealAlgorithm : NL_SEAL_ALG_NONE; 486 487 if (conf_req_flag) 488 krb5_generate_random_block(_netlogon_confounder(sig), 8); 489 490 sig->Pad = 0xFFFF; /* [MS-NRPC] 3.3.4.2.1.3 */ 491 sig->Flags = 0; /* [MS-NRPC] 3.3.4.2.1.4 */ 492 HEIMDAL_MUTEX_lock(&ctx->Mutex); 493 _netlogon_encode_sequence_number(ctx->SequenceNumber, sig->SequenceNumber, 494 ctx->LocallyInitiated); 495 ctx->SequenceNumber++; 496 HEIMDAL_MUTEX_unlock(&ctx->Mutex); 497 498 /* [MS-NRPC] 3.3.4.2.1.7: sign header, optional confounder and data */ 499 _netlogon_digest(ctx, sig, iov, iov_count, sig->Checksum); 500 501 /* [MS-NRPC] 3.3.4.2.1.8: optionally encrypt confounder and data */ 502 if (conf_req_flag) 503 _netlogon_seal(ctx, sig, iov, iov_count, 1); 504 505 /* [MS-NRPC] 3.3.4.2.1.9: encrypt sequence number */ 506 _netlogon_seq(ctx, sig, 1); 507 508 _netlogon_encode_NL_AUTH_SIGNATURE(sig, header->buffer.value, 509 header->buffer.length); 510 511 if (conf_state != NULL) 512 *conf_state = conf_req_flag; 513 514 *minor_status = 0; 515 return GSS_S_COMPLETE; 516} 517 518OM_uint32 519_netlogon_unwrap_iov(OM_uint32 *minor_status, 520 gss_ctx_id_t context_handle, 521 int *conf_state, 522 gss_qop_t *qop_state, 523 gss_iov_buffer_desc *iov, 524 int iov_count) 525{ 526 OM_uint32 ret; 527 gss_iov_buffer_t header; 528 NL_AUTH_SIGNATURE_U sigbuf; 529 NL_AUTH_SIGNATURE *sig = NL_AUTH_SIGNATURE_P(&sigbuf); 530 gssnetlogon_ctx ctx = (gssnetlogon_ctx)context_handle; 531 uint8_t checksum[CC_SHA256_DIGEST_LENGTH]; 532 uint64_t SequenceNumber; 533 534 if (ctx->State != NL_AUTH_ESTABLISHED) { 535 *minor_status = EINVAL; 536 return GSS_S_FAILURE; 537 } 538 539 header = _gss_mg_find_buffer(iov, iov_count, GSS_IOV_BUFFER_TYPE_HEADER); 540 if (header == NULL) { 541 *minor_status = EINVAL; 542 return GSS_S_FAILURE; 543 } 544 545 ret = _netlogon_decode_NL_AUTH_SIGNATURE(header->buffer.value, 546 header->buffer.length, 547 sig); 548 if (ret != 0) { 549 *minor_status = ret; 550 return GSS_S_DEFECTIVE_TOKEN; 551 } 552 553 /* [MS-NRPC] 3.3.4.2.2.1: verify signature algorithm selection */ 554 if (sig->SignatureAlgorithm != ctx->SignatureAlgorithm) 555 return GSS_S_BAD_SIG; 556 557 /* [MS-NRPC] 3.3.4.2.2.2: verify encryption algorithm selection */ 558 if (sig->SealAlgorithm != NL_SEAL_ALG_NONE && 559 sig->SealAlgorithm != ctx->SealAlgorithm) 560 return GSS_S_DEFECTIVE_TOKEN; 561 562 /* [MS-NRPC] 3.3.4.2.2.3: verify Pad bytes */ 563 if (sig->Pad != 0xFFFF) 564 return GSS_S_DEFECTIVE_TOKEN; 565 566 /* [MS-NRPC] 3.3.4.2.2.5: decrypt sequence number */ 567 _netlogon_seq(ctx, sig, 0); 568 569 /* [MS-NRPC] 3.3.4.2.2.6: decode sequence number */ 570 if (_netlogon_decode_sequence_number(sig->SequenceNumber, &SequenceNumber, 571 !ctx->LocallyInitiated) != 0) 572 return GSS_S_UNSEQ_TOKEN; 573 574 /* [MS-NRPC] 3.3.4.2.2.9: decrypt confounder and data */ 575 if (sig->SealAlgorithm != NL_SEAL_ALG_NONE) 576 _netlogon_seal(ctx, sig, iov, iov_count, 0); 577 578 /* [MS-NRPC] 3.3.4.2.2.10: verify signature */ 579 _netlogon_digest(ctx, sig, iov, iov_count, checksum); 580 if (memcmp(sig->Checksum, checksum, _netlogon_checksum_length(sig)) != 0) 581 return GSS_S_BAD_SIG; 582 583 HEIMDAL_MUTEX_lock(&ctx->Mutex); 584 if (SequenceNumber != ctx->SequenceNumber) { 585 /* [MS-NRPC] 3.3.4.2.2.7: check sequence number */ 586 ret = GSS_S_UNSEQ_TOKEN; 587 } else { 588 /* [MS-NRPC] 3.3.4.2.2.8: increment sequence number */ 589 ctx->SequenceNumber++; 590 ret = GSS_S_COMPLETE; 591 } 592 HEIMDAL_MUTEX_unlock(&ctx->Mutex); 593 594 if (conf_state != NULL) 595 *conf_state = (sig->SealAlgorithm != NL_SEAL_ALG_NONE); 596 if (qop_state != NULL) 597 *qop_state = GSS_C_QOP_DEFAULT; 598 599 *minor_status = 0; 600 return ret; 601} 602 603OM_uint32 604_netlogon_wrap_iov_length(OM_uint32 * minor_status, 605 gss_ctx_id_t context_handle, 606 int conf_req_flag, 607 gss_qop_t qop_req, 608 int *conf_state, 609 gss_iov_buffer_desc *iov, 610 int iov_count) 611{ 612 gss_iov_buffer_t iovp; 613 gssnetlogon_ctx ctx = (gssnetlogon_ctx)context_handle; 614 size_t len; 615 616 iovp = _gss_mg_find_buffer(iov, iov_count, GSS_IOV_BUFFER_TYPE_HEADER); 617 if (iovp == NULL) { 618 *minor_status = EINVAL; 619 return GSS_S_FAILURE; 620 } 621 622 len = NL_AUTH_SIGNATURE_COMMON_LENGTH; 623 if (ctx->SignatureAlgorithm == NL_SIGN_ALG_SHA256) 624 len += 32; /* SHA2 checksum size */ 625 else 626 len += 8; /* HMAC checksum size */ 627 if (conf_req_flag) 628 len += 8; /* counfounder */ 629 630 iovp->buffer.length = len; 631 632 iovp = _gss_mg_find_buffer(iov, iov_count, GSS_IOV_BUFFER_TYPE_PADDING); 633 if (iovp != NULL) 634 iovp->buffer.length = 0; 635 636 iovp = _gss_mg_find_buffer(iov, iov_count, GSS_IOV_BUFFER_TYPE_TRAILER); 637 if (iovp != NULL) 638 iovp->buffer.length = 0; 639 640 if (conf_state != NULL) 641 *conf_state = conf_req_flag; 642 643 *minor_status = 0; 644 return GSS_S_COMPLETE; 645} 646 647OM_uint32 _netlogon_get_mic 648 (OM_uint32 * minor_status, 649 const gss_ctx_id_t context_handle, 650 gss_qop_t qop_req, 651 const gss_buffer_t message_buffer, 652 gss_buffer_t message_token 653 ) 654{ 655 gss_iov_buffer_desc iov[2]; 656 OM_uint32 ret; 657 658 iov[0].type = GSS_IOV_BUFFER_TYPE_DATA; 659 iov[0].buffer = *message_buffer; 660 iov[1].type = GSS_IOV_BUFFER_TYPE_HEADER | GSS_IOV_BUFFER_FLAG_ALLOCATE; 661 iov[1].buffer.length = 0; 662 iov[1].buffer.value = NULL; 663 664 ret = _netlogon_wrap_iov(minor_status, context_handle, 0, 665 qop_req, NULL, iov, 2); 666 if (ret == GSS_S_COMPLETE) 667 *message_token = iov[1].buffer; 668 669 return ret; 670} 671 672OM_uint32 673_netlogon_verify_mic 674 (OM_uint32 * minor_status, 675 const gss_ctx_id_t context_handle, 676 const gss_buffer_t message_buffer, 677 const gss_buffer_t token_buffer, 678 gss_qop_t * qop_state 679 ) 680{ 681 gss_iov_buffer_desc iov[2]; 682 683 iov[0].type = GSS_IOV_BUFFER_TYPE_DATA; 684 iov[0].buffer = *message_buffer; 685 iov[1].type = GSS_IOV_BUFFER_TYPE_HEADER; 686 iov[1].buffer = *token_buffer; 687 688 return _netlogon_unwrap_iov(minor_status, context_handle, 689 NULL, qop_state, iov, 2); 690} 691 692OM_uint32 693_netlogon_wrap_size_limit ( 694 OM_uint32 * minor_status, 695 const gss_ctx_id_t context_handle, 696 int conf_req_flag, 697 gss_qop_t qop_req, 698 OM_uint32 req_output_size, 699 OM_uint32 *max_input_size 700 ) 701{ 702 gss_iov_buffer_desc iov[1]; 703 OM_uint32 ret; 704 705 iov[0].type = GSS_IOV_BUFFER_TYPE_HEADER; 706 iov[0].buffer.length = 0; 707 708 ret = _netlogon_wrap_iov_length(minor_status, context_handle, 709 conf_req_flag, qop_req, NULL, 710 iov, sizeof(iov)/sizeof(iov[0])); 711 if (GSS_ERROR(ret)) 712 return ret; 713 714 if (req_output_size < iov[0].buffer.length) 715 *max_input_size = 0; 716 else 717 *max_input_size = (OM_uint32)(req_output_size - iov[0].buffer.length); 718 719 return GSS_S_COMPLETE; 720} 721 722