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 36 uint32_t 37 _krb5_crc_update (const char *p, size_t len, uint32_t res); 38 void 39 _krb5_crc_init_table(void); 40 41 /* 42 * 43 */ 44 45 static void 46 encode_le_uint32(uint32_t n, unsigned char *p) 47 { 48 p[0] = (n >> 0) & 0xFF; 49 p[1] = (n >> 8) & 0xFF; 50 p[2] = (n >> 16) & 0xFF; 51 p[3] = (n >> 24) & 0xFF; 52 } 53 54 55 static void 56 decode_le_uint32(const void *ptr, uint32_t *n) 57 { 58 const unsigned char *p = ptr; 59 *n = (p[0] << 0) | (p[1] << 8) | (p[2] << 16) | (p[3] << 24); 60 } 61 62 /* 63 * 64 */ 65 66 const char a2i_signmagic[] = 67 "session key to server-to-client signing key magic constant"; 68 const char a2i_sealmagic[] = 69 "session key to server-to-client sealing key magic constant"; 70 const char i2a_signmagic[] = 71 "session key to client-to-server signing key magic constant"; 72 const char i2a_sealmagic[] = 73 "session key to client-to-server sealing key magic constant"; 74 75 76 void 77 _gss_ntlm_set_key(struct ntlmv2_key *key, int acceptor, int sealsign, 78 unsigned char *data, size_t len) 79 { 80 unsigned char out[16]; 81 EVP_MD_CTX *ctx; 82 const char *signmagic; 83 const char *sealmagic; 84 85 if (acceptor) { 86 signmagic = a2i_signmagic; 87 sealmagic = a2i_sealmagic; 88 } else { 89 signmagic = i2a_signmagic; 90 sealmagic = i2a_sealmagic; 91 } 92 93 key->seq = 0; 94 95 ctx = EVP_MD_CTX_create(); 96 EVP_DigestInit_ex(ctx, EVP_md5(), NULL); 97 EVP_DigestUpdate(ctx, data, len); 98 EVP_DigestUpdate(ctx, signmagic, strlen(signmagic) + 1); 99 EVP_DigestFinal_ex(ctx, key->signkey, NULL); 100 101 EVP_DigestInit_ex(ctx, EVP_md5(), NULL); 102 EVP_DigestUpdate(ctx, data, len); 103 EVP_DigestUpdate(ctx, sealmagic, strlen(sealmagic) + 1); 104 EVP_DigestFinal_ex(ctx, out, NULL); 105 EVP_MD_CTX_destroy(ctx); 106 107 RC4_set_key(&key->sealkey, 16, out); 108 if (sealsign) 109 key->signsealkey = &key->sealkey; 110 } 111 112 /* 113 * 114 */ 115 116 static OM_uint32 117 v1_sign_message(gss_buffer_t in, 118 RC4_KEY *signkey, 119 uint32_t seq, 120 unsigned char out[16]) 121 { 122 unsigned char sigature[12]; 123 uint32_t crc; 124 125 _krb5_crc_init_table(); 126 crc = _krb5_crc_update(in->value, in->length, 0); 127 128 encode_le_uint32(0, &sigature[0]); 129 encode_le_uint32(crc, &sigature[4]); 130 encode_le_uint32(seq, &sigature[8]); 131 132 encode_le_uint32(1, out); /* version */ 133 RC4(signkey, sizeof(sigature), sigature, out + 4); 134 135 if (RAND_bytes(out + 4, 4) != 1) 136 return GSS_S_UNAVAILABLE; 137 138 return 0; 139 } 140 141 142 static OM_uint32 143 v2_sign_message(gss_buffer_t in, 144 unsigned char signkey[16], 145 RC4_KEY *sealkey, 146 uint32_t seq, 147 unsigned char out[16]) 148 { 149 unsigned char hmac[16]; 150 unsigned int hmaclen; 151 HMAC_CTX c; 152 153 HMAC_CTX_init(&c); 154 HMAC_Init_ex(&c, signkey, 16, EVP_md5(), NULL); 155 156 encode_le_uint32(seq, hmac); 157 HMAC_Update(&c, hmac, 4); 158 HMAC_Update(&c, in->value, in->length); 159 HMAC_Final(&c, hmac, &hmaclen); 160 HMAC_CTX_cleanup(&c); 161 162 encode_le_uint32(1, &out[0]); 163 if (sealkey) 164 RC4(sealkey, 8, hmac, &out[4]); 165 else 166 memcpy(&out[4], hmac, 8); 167 168 memset(&out[12], 0, 4); 169 170 return GSS_S_COMPLETE; 171 } 172 173 static OM_uint32 174 v2_verify_message(gss_buffer_t in, 175 unsigned char signkey[16], 176 RC4_KEY *sealkey, 177 uint32_t seq, 178 const unsigned char checksum[16]) 179 { 180 OM_uint32 ret; 181 unsigned char out[16]; 182 183 ret = v2_sign_message(in, signkey, sealkey, seq, out); 184 if (ret) 185 return ret; 186 187 if (memcmp(checksum, out, 16) != 0) 188 return GSS_S_BAD_MIC; 189 190 return GSS_S_COMPLETE; 191 } 192 193 static OM_uint32 194 v2_seal_message(const gss_buffer_t in, 195 unsigned char signkey[16], 196 uint32_t seq, 197 RC4_KEY *sealkey, 198 gss_buffer_t out) 199 { 200 unsigned char *p; 201 OM_uint32 ret; 202 203 if (in->length + 16 < in->length) 204 return EINVAL; 205 206 p = malloc(in->length + 16); 207 if (p == NULL) 208 return ENOMEM; 209 210 RC4(sealkey, in->length, in->value, p); 211 212 ret = v2_sign_message(in, signkey, sealkey, seq, &p[in->length]); 213 if (ret) { 214 free(p); 215 return ret; 216 } 217 218 out->value = p; 219 out->length = in->length + 16; 220 221 return 0; 222 } 223 224 static OM_uint32 225 v2_unseal_message(gss_buffer_t in, 226 unsigned char signkey[16], 227 uint32_t seq, 228 RC4_KEY *sealkey, 229 gss_buffer_t out) 230 { 231 OM_uint32 ret; 232 233 if (in->length < 16) 234 return GSS_S_BAD_MIC; 235 236 out->length = in->length - 16; 237 out->value = malloc(out->length); 238 if (out->value == NULL) 239 return GSS_S_BAD_MIC; 240 241 RC4(sealkey, out->length, in->value, out->value); 242 243 ret = v2_verify_message(out, signkey, sealkey, seq, 244 ((const unsigned char *)in->value) + out->length); 245 if (ret) { 246 OM_uint32 junk; 247 gss_release_buffer(&junk, out); 248 } 249 return ret; 250 } 251 252 /* 253 * 254 */ 255 256 #define CTX_FLAGS_ISSET(_ctx,_flags) \ 257 (((_ctx)->flags & (_flags)) == (_flags)) 258 259 /* 260 * 261 */ 262 263 OM_uint32 GSSAPI_CALLCONV 264 _gss_ntlm_get_mic 265 (OM_uint32 * minor_status, 266 const gss_ctx_id_t context_handle, 267 gss_qop_t qop_req, 268 const gss_buffer_t message_buffer, 269 gss_buffer_t message_token 270 ) 271 { 272 ntlm_ctx ctx = (ntlm_ctx)context_handle; 273 OM_uint32 junk; 274 275 *minor_status = 0; 276 277 message_token->value = malloc(16); 278 message_token->length = 16; 279 if (message_token->value == NULL) { 280 *minor_status = ENOMEM; 281 return GSS_S_FAILURE; 282 } 283 284 if (CTX_FLAGS_ISSET(ctx, NTLM_NEG_SIGN|NTLM_NEG_NTLM2_SESSION)) { 285 OM_uint32 ret; 286 287 if ((ctx->status & STATUS_SESSIONKEY) == 0) { 288 gss_release_buffer(&junk, message_token); 289 return GSS_S_UNAVAILABLE; 290 } 291 292 ret = v2_sign_message(message_buffer, 293 ctx->u.v2.send.signkey, 294 ctx->u.v2.send.signsealkey, 295 ctx->u.v2.send.seq++, 296 message_token->value); 297 if (ret) 298 gss_release_buffer(&junk, message_token); 299 return ret; 300 301 } else if (CTX_FLAGS_ISSET(ctx, NTLM_NEG_SIGN)) { 302 OM_uint32 ret; 303 304 if ((ctx->status & STATUS_SESSIONKEY) == 0) { 305 gss_release_buffer(&junk, message_token); 306 return GSS_S_UNAVAILABLE; 307 } 308 309 ret = v1_sign_message(message_buffer, 310 &ctx->u.v1.crypto_send.key, 311 ctx->u.v1.crypto_send.seq++, 312 message_token->value); 313 if (ret) 314 gss_release_buffer(&junk, message_token); 315 return ret; 316 317 } else if (CTX_FLAGS_ISSET(ctx, NTLM_NEG_ALWAYS_SIGN)) { 318 unsigned char *sigature; 319 320 sigature = message_token->value; 321 322 encode_le_uint32(1, &sigature[0]); /* version */ 323 encode_le_uint32(0, &sigature[4]); 324 encode_le_uint32(0, &sigature[8]); 325 encode_le_uint32(0, &sigature[12]); 326 327 return GSS_S_COMPLETE; 328 } 329 gss_release_buffer(&junk, message_token); 330 331 return GSS_S_UNAVAILABLE; 332 } 333 334 /* 335 * 336 */ 337 338 OM_uint32 GSSAPI_CALLCONV 339 _gss_ntlm_verify_mic 340 (OM_uint32 * minor_status, 341 const gss_ctx_id_t context_handle, 342 const gss_buffer_t message_buffer, 343 const gss_buffer_t token_buffer, 344 gss_qop_t * qop_state 345 ) 346 { 347 ntlm_ctx ctx = (ntlm_ctx)context_handle; 348 349 if (qop_state != NULL) 350 *qop_state = GSS_C_QOP_DEFAULT; 351 *minor_status = 0; 352 353 if (token_buffer->length != 16) 354 return GSS_S_BAD_MIC; 355 356 if (CTX_FLAGS_ISSET(ctx, NTLM_NEG_SIGN|NTLM_NEG_NTLM2_SESSION)) { 357 OM_uint32 ret; 358 359 if ((ctx->status & STATUS_SESSIONKEY) == 0) 360 return GSS_S_UNAVAILABLE; 361 362 ret = v2_verify_message(message_buffer, 363 ctx->u.v2.recv.signkey, 364 ctx->u.v2.recv.signsealkey, 365 ctx->u.v2.recv.seq++, 366 token_buffer->value); 367 if (ret) 368 return ret; 369 370 return GSS_S_COMPLETE; 371 } else if (CTX_FLAGS_ISSET(ctx, NTLM_NEG_SIGN)) { 372 373 unsigned char sigature[12]; 374 uint32_t crc, num; 375 376 if ((ctx->status & STATUS_SESSIONKEY) == 0) 377 return GSS_S_UNAVAILABLE; 378 379 decode_le_uint32(token_buffer->value, &num); 380 if (num != 1) 381 return GSS_S_BAD_MIC; 382 383 RC4(&ctx->u.v1.crypto_recv.key, sizeof(sigature), 384 ((unsigned char *)token_buffer->value) + 4, sigature); 385 386 _krb5_crc_init_table(); 387 crc = _krb5_crc_update(message_buffer->value, 388 message_buffer->length, 0); 389 /* skip first 4 bytes in the encrypted checksum */ 390 decode_le_uint32(&sigature[4], &num); 391 if (num != crc) 392 return GSS_S_BAD_MIC; 393 decode_le_uint32(&sigature[8], &num); 394 if (ctx->u.v1.crypto_recv.seq != num) 395 return GSS_S_BAD_MIC; 396 ctx->u.v1.crypto_recv.seq++; 397 398 return GSS_S_COMPLETE; 399 } else if (ctx->flags & NTLM_NEG_ALWAYS_SIGN) { 400 uint32_t num; 401 unsigned char *p; 402 403 p = (unsigned char*)(token_buffer->value); 404 405 decode_le_uint32(&p[0], &num); /* version */ 406 if (num != 1) return GSS_S_BAD_MIC; 407 decode_le_uint32(&p[4], &num); 408 if (num != 0) return GSS_S_BAD_MIC; 409 decode_le_uint32(&p[8], &num); 410 if (num != 0) return GSS_S_BAD_MIC; 411 decode_le_uint32(&p[12], &num); 412 if (num != 0) return GSS_S_BAD_MIC; 413 414 return GSS_S_COMPLETE; 415 } 416 417 return GSS_S_UNAVAILABLE; 418 } 419 420 /* 421 * 422 */ 423 424 OM_uint32 GSSAPI_CALLCONV 425 _gss_ntlm_wrap_size_limit ( 426 OM_uint32 * minor_status, 427 const gss_ctx_id_t context_handle, 428 int conf_req_flag, 429 gss_qop_t qop_req, 430 OM_uint32 req_output_size, 431 OM_uint32 * max_input_size 432 ) 433 { 434 ntlm_ctx ctx = (ntlm_ctx)context_handle; 435 436 *minor_status = 0; 437 438 if(ctx->flags & NTLM_NEG_SEAL) { 439 440 if (req_output_size < 16) 441 *max_input_size = 0; 442 else 443 *max_input_size = req_output_size - 16; 444 445 return GSS_S_COMPLETE; 446 } 447 448 return GSS_S_UNAVAILABLE; 449 } 450 451 /* 452 * 453 */ 454 455 OM_uint32 GSSAPI_CALLCONV 456 _gss_ntlm_wrap 457 (OM_uint32 * minor_status, 458 const gss_ctx_id_t context_handle, 459 int conf_req_flag, 460 gss_qop_t qop_req, 461 const gss_buffer_t input_message_buffer, 462 int * conf_state, 463 gss_buffer_t output_message_buffer 464 ) 465 { 466 ntlm_ctx ctx = (ntlm_ctx)context_handle; 467 OM_uint32 ret; 468 469 *minor_status = 0; 470 if (conf_state) 471 *conf_state = 0; 472 if (output_message_buffer == GSS_C_NO_BUFFER) 473 return GSS_S_FAILURE; 474 475 476 if (CTX_FLAGS_ISSET(ctx, NTLM_NEG_SEAL|NTLM_NEG_NTLM2_SESSION)) { 477 478 return v2_seal_message(input_message_buffer, 479 ctx->u.v2.send.signkey, 480 ctx->u.v2.send.seq++, 481 &ctx->u.v2.send.sealkey, 482 output_message_buffer); 483 484 } else if (CTX_FLAGS_ISSET(ctx, NTLM_NEG_SEAL)) { 485 gss_buffer_desc trailer; 486 OM_uint32 junk; 487 488 output_message_buffer->length = input_message_buffer->length + 16; 489 output_message_buffer->value = malloc(output_message_buffer->length); 490 if (output_message_buffer->value == NULL) { 491 output_message_buffer->length = 0; 492 return GSS_S_FAILURE; 493 } 494 495 496 RC4(&ctx->u.v1.crypto_send.key, input_message_buffer->length, 497 input_message_buffer->value, output_message_buffer->value); 498 499 ret = _gss_ntlm_get_mic(minor_status, context_handle, 500 0, input_message_buffer, 501 &trailer); 502 if (ret) { 503 gss_release_buffer(&junk, output_message_buffer); 504 return ret; 505 } 506 if (trailer.length != 16) { 507 gss_release_buffer(&junk, output_message_buffer); 508 gss_release_buffer(&junk, &trailer); 509 return GSS_S_FAILURE; 510 } 511 memcpy(((unsigned char *)output_message_buffer->value) + 512 input_message_buffer->length, 513 trailer.value, trailer.length); 514 gss_release_buffer(&junk, &trailer); 515 516 return GSS_S_COMPLETE; 517 } 518 519 return GSS_S_UNAVAILABLE; 520 } 521 522 /* 523 * 524 */ 525 526 OM_uint32 GSSAPI_CALLCONV 527 _gss_ntlm_unwrap 528 (OM_uint32 * minor_status, 529 const gss_ctx_id_t context_handle, 530 const gss_buffer_t input_message_buffer, 531 gss_buffer_t output_message_buffer, 532 int * conf_state, 533 gss_qop_t * qop_state 534 ) 535 { 536 ntlm_ctx ctx = (ntlm_ctx)context_handle; 537 OM_uint32 ret; 538 539 *minor_status = 0; 540 output_message_buffer->value = NULL; 541 output_message_buffer->length = 0; 542 543 if (conf_state) 544 *conf_state = 0; 545 if (qop_state) 546 *qop_state = 0; 547 548 if (CTX_FLAGS_ISSET(ctx, NTLM_NEG_SEAL|NTLM_NEG_NTLM2_SESSION)) { 549 550 return v2_unseal_message(input_message_buffer, 551 ctx->u.v2.recv.signkey, 552 ctx->u.v2.recv.seq++, 553 &ctx->u.v2.recv.sealkey, 554 output_message_buffer); 555 556 } else if (CTX_FLAGS_ISSET(ctx, NTLM_NEG_SEAL)) { 557 558 gss_buffer_desc trailer; 559 OM_uint32 junk; 560 561 if (input_message_buffer->length < 16) 562 return GSS_S_BAD_MIC; 563 564 output_message_buffer->length = input_message_buffer->length - 16; 565 output_message_buffer->value = malloc(output_message_buffer->length); 566 if (output_message_buffer->value == NULL) { 567 output_message_buffer->length = 0; 568 return GSS_S_FAILURE; 569 } 570 571 RC4(&ctx->u.v1.crypto_recv.key, output_message_buffer->length, 572 input_message_buffer->value, output_message_buffer->value); 573 574 trailer.value = ((unsigned char *)input_message_buffer->value) + 575 output_message_buffer->length; 576 trailer.length = 16; 577 578 ret = _gss_ntlm_verify_mic(minor_status, context_handle, 579 output_message_buffer, 580 &trailer, NULL); 581 if (ret) { 582 gss_release_buffer(&junk, output_message_buffer); 583 return ret; 584 } 585 586 return GSS_S_COMPLETE; 587 } 588 589 return GSS_S_UNAVAILABLE; 590 } 591