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 c = HMAC_CTX_new(); 154 if (c == NULL) 155 return GSS_S_FAILURE; 156 HMAC_Init_ex(c, signkey, 16, EVP_md5(), NULL); 157 158 encode_le_uint32(seq, hmac); 159 HMAC_Update(c, hmac, 4); 160 HMAC_Update(c, in->value, in->length); 161 HMAC_Final(c, hmac, &hmaclen); 162 HMAC_CTX_free(c); 163 164 encode_le_uint32(1, &out[0]); 165 if (sealkey) 166 RC4(sealkey, 8, hmac, &out[4]); 167 else 168 memcpy(&out[4], hmac, 8); 169 170 memset(&out[12], 0, 4); 171 172 return GSS_S_COMPLETE; 173 } 174 175 static OM_uint32 176 v2_verify_message(gss_buffer_t in, 177 unsigned char signkey[16], 178 RC4_KEY *sealkey, 179 uint32_t seq, 180 const unsigned char checksum[16]) 181 { 182 OM_uint32 ret; 183 unsigned char out[16]; 184 185 ret = v2_sign_message(in, signkey, sealkey, seq, out); 186 if (ret) 187 return ret; 188 189 if (memcmp(checksum, out, 16) != 0) 190 return GSS_S_BAD_MIC; 191 192 return GSS_S_COMPLETE; 193 } 194 195 static OM_uint32 196 v2_seal_message(const gss_buffer_t in, 197 unsigned char signkey[16], 198 uint32_t seq, 199 RC4_KEY *sealkey, 200 gss_buffer_t out) 201 { 202 unsigned char *p; 203 OM_uint32 ret; 204 205 if (in->length + 16 < in->length) 206 return EINVAL; 207 208 p = malloc(in->length + 16); 209 if (p == NULL) 210 return ENOMEM; 211 212 RC4(sealkey, in->length, in->value, p); 213 214 ret = v2_sign_message(in, signkey, sealkey, seq, &p[in->length]); 215 if (ret) { 216 free(p); 217 return ret; 218 } 219 220 out->value = p; 221 out->length = in->length + 16; 222 223 return 0; 224 } 225 226 static OM_uint32 227 v2_unseal_message(gss_buffer_t in, 228 unsigned char signkey[16], 229 uint32_t seq, 230 RC4_KEY *sealkey, 231 gss_buffer_t out) 232 { 233 OM_uint32 ret; 234 235 if (in->length < 16) 236 return GSS_S_BAD_MIC; 237 238 out->length = in->length - 16; 239 out->value = malloc(out->length); 240 if (out->value == NULL) 241 return GSS_S_BAD_MIC; 242 243 RC4(sealkey, out->length, in->value, out->value); 244 245 ret = v2_verify_message(out, signkey, sealkey, seq, 246 ((const unsigned char *)in->value) + out->length); 247 if (ret) { 248 OM_uint32 junk; 249 gss_release_buffer(&junk, out); 250 } 251 return ret; 252 } 253 254 /* 255 * 256 */ 257 258 #define CTX_FLAGS_ISSET(_ctx,_flags) \ 259 (((_ctx)->flags & (_flags)) == (_flags)) 260 261 /* 262 * 263 */ 264 265 OM_uint32 GSSAPI_CALLCONV 266 _gss_ntlm_get_mic 267 (OM_uint32 * minor_status, 268 const gss_ctx_id_t context_handle, 269 gss_qop_t qop_req, 270 const gss_buffer_t message_buffer, 271 gss_buffer_t message_token 272 ) 273 { 274 ntlm_ctx ctx = (ntlm_ctx)context_handle; 275 OM_uint32 junk; 276 277 *minor_status = 0; 278 279 message_token->value = malloc(16); 280 message_token->length = 16; 281 if (message_token->value == NULL) { 282 *minor_status = ENOMEM; 283 return GSS_S_FAILURE; 284 } 285 286 if (CTX_FLAGS_ISSET(ctx, NTLM_NEG_SIGN|NTLM_NEG_NTLM2_SESSION)) { 287 OM_uint32 ret; 288 289 if ((ctx->status & STATUS_SESSIONKEY) == 0) { 290 gss_release_buffer(&junk, message_token); 291 return GSS_S_UNAVAILABLE; 292 } 293 294 ret = v2_sign_message(message_buffer, 295 ctx->u.v2.send.signkey, 296 ctx->u.v2.send.signsealkey, 297 ctx->u.v2.send.seq++, 298 message_token->value); 299 if (ret) 300 gss_release_buffer(&junk, message_token); 301 return ret; 302 303 } else if (CTX_FLAGS_ISSET(ctx, NTLM_NEG_SIGN)) { 304 OM_uint32 ret; 305 306 if ((ctx->status & STATUS_SESSIONKEY) == 0) { 307 gss_release_buffer(&junk, message_token); 308 return GSS_S_UNAVAILABLE; 309 } 310 311 ret = v1_sign_message(message_buffer, 312 &ctx->u.v1.crypto_send.key, 313 ctx->u.v1.crypto_send.seq++, 314 message_token->value); 315 if (ret) 316 gss_release_buffer(&junk, message_token); 317 return ret; 318 319 } else if (CTX_FLAGS_ISSET(ctx, NTLM_NEG_ALWAYS_SIGN)) { 320 unsigned char *sigature; 321 322 sigature = message_token->value; 323 324 encode_le_uint32(1, &sigature[0]); /* version */ 325 encode_le_uint32(0, &sigature[4]); 326 encode_le_uint32(0, &sigature[8]); 327 encode_le_uint32(0, &sigature[12]); 328 329 return GSS_S_COMPLETE; 330 } 331 gss_release_buffer(&junk, message_token); 332 333 return GSS_S_UNAVAILABLE; 334 } 335 336 /* 337 * 338 */ 339 340 OM_uint32 GSSAPI_CALLCONV 341 _gss_ntlm_verify_mic 342 (OM_uint32 * minor_status, 343 const gss_ctx_id_t context_handle, 344 const gss_buffer_t message_buffer, 345 const gss_buffer_t token_buffer, 346 gss_qop_t * qop_state 347 ) 348 { 349 ntlm_ctx ctx = (ntlm_ctx)context_handle; 350 351 if (qop_state != NULL) 352 *qop_state = GSS_C_QOP_DEFAULT; 353 *minor_status = 0; 354 355 if (token_buffer->length != 16) 356 return GSS_S_BAD_MIC; 357 358 if (CTX_FLAGS_ISSET(ctx, NTLM_NEG_SIGN|NTLM_NEG_NTLM2_SESSION)) { 359 OM_uint32 ret; 360 361 if ((ctx->status & STATUS_SESSIONKEY) == 0) 362 return GSS_S_UNAVAILABLE; 363 364 ret = v2_verify_message(message_buffer, 365 ctx->u.v2.recv.signkey, 366 ctx->u.v2.recv.signsealkey, 367 ctx->u.v2.recv.seq++, 368 token_buffer->value); 369 if (ret) 370 return ret; 371 372 return GSS_S_COMPLETE; 373 } else if (CTX_FLAGS_ISSET(ctx, NTLM_NEG_SIGN)) { 374 375 unsigned char sigature[12]; 376 uint32_t crc, num; 377 378 if ((ctx->status & STATUS_SESSIONKEY) == 0) 379 return GSS_S_UNAVAILABLE; 380 381 decode_le_uint32(token_buffer->value, &num); 382 if (num != 1) 383 return GSS_S_BAD_MIC; 384 385 RC4(&ctx->u.v1.crypto_recv.key, sizeof(sigature), 386 ((unsigned char *)token_buffer->value) + 4, sigature); 387 388 _krb5_crc_init_table(); 389 crc = _krb5_crc_update(message_buffer->value, 390 message_buffer->length, 0); 391 /* skip first 4 bytes in the encrypted checksum */ 392 decode_le_uint32(&sigature[4], &num); 393 if (num != crc) 394 return GSS_S_BAD_MIC; 395 decode_le_uint32(&sigature[8], &num); 396 if (ctx->u.v1.crypto_recv.seq != num) 397 return GSS_S_BAD_MIC; 398 ctx->u.v1.crypto_recv.seq++; 399 400 return GSS_S_COMPLETE; 401 } else if (ctx->flags & NTLM_NEG_ALWAYS_SIGN) { 402 uint32_t num; 403 unsigned char *p; 404 405 p = (unsigned char*)(token_buffer->value); 406 407 decode_le_uint32(&p[0], &num); /* version */ 408 if (num != 1) return GSS_S_BAD_MIC; 409 decode_le_uint32(&p[4], &num); 410 if (num != 0) return GSS_S_BAD_MIC; 411 decode_le_uint32(&p[8], &num); 412 if (num != 0) return GSS_S_BAD_MIC; 413 decode_le_uint32(&p[12], &num); 414 if (num != 0) return GSS_S_BAD_MIC; 415 416 return GSS_S_COMPLETE; 417 } 418 419 return GSS_S_UNAVAILABLE; 420 } 421 422 /* 423 * 424 */ 425 426 OM_uint32 GSSAPI_CALLCONV 427 _gss_ntlm_wrap_size_limit ( 428 OM_uint32 * minor_status, 429 const gss_ctx_id_t context_handle, 430 int conf_req_flag, 431 gss_qop_t qop_req, 432 OM_uint32 req_output_size, 433 OM_uint32 * max_input_size 434 ) 435 { 436 ntlm_ctx ctx = (ntlm_ctx)context_handle; 437 438 *minor_status = 0; 439 440 if(ctx->flags & NTLM_NEG_SEAL) { 441 442 if (req_output_size < 16) 443 *max_input_size = 0; 444 else 445 *max_input_size = req_output_size - 16; 446 447 return GSS_S_COMPLETE; 448 } 449 450 return GSS_S_UNAVAILABLE; 451 } 452 453 /* 454 * 455 */ 456 457 OM_uint32 GSSAPI_CALLCONV 458 _gss_ntlm_wrap 459 (OM_uint32 * minor_status, 460 const gss_ctx_id_t context_handle, 461 int conf_req_flag, 462 gss_qop_t qop_req, 463 const gss_buffer_t input_message_buffer, 464 int * conf_state, 465 gss_buffer_t output_message_buffer 466 ) 467 { 468 ntlm_ctx ctx = (ntlm_ctx)context_handle; 469 OM_uint32 ret; 470 471 *minor_status = 0; 472 if (conf_state) 473 *conf_state = 0; 474 if (output_message_buffer == GSS_C_NO_BUFFER) 475 return GSS_S_FAILURE; 476 477 478 if (CTX_FLAGS_ISSET(ctx, NTLM_NEG_SEAL|NTLM_NEG_NTLM2_SESSION)) { 479 480 return v2_seal_message(input_message_buffer, 481 ctx->u.v2.send.signkey, 482 ctx->u.v2.send.seq++, 483 &ctx->u.v2.send.sealkey, 484 output_message_buffer); 485 486 } else if (CTX_FLAGS_ISSET(ctx, NTLM_NEG_SEAL)) { 487 gss_buffer_desc trailer; 488 OM_uint32 junk; 489 490 output_message_buffer->length = input_message_buffer->length + 16; 491 output_message_buffer->value = malloc(output_message_buffer->length); 492 if (output_message_buffer->value == NULL) { 493 output_message_buffer->length = 0; 494 return GSS_S_FAILURE; 495 } 496 497 498 RC4(&ctx->u.v1.crypto_send.key, input_message_buffer->length, 499 input_message_buffer->value, output_message_buffer->value); 500 501 ret = _gss_ntlm_get_mic(minor_status, context_handle, 502 0, input_message_buffer, 503 &trailer); 504 if (ret) { 505 gss_release_buffer(&junk, output_message_buffer); 506 return ret; 507 } 508 if (trailer.length != 16) { 509 gss_release_buffer(&junk, output_message_buffer); 510 gss_release_buffer(&junk, &trailer); 511 return GSS_S_FAILURE; 512 } 513 memcpy(((unsigned char *)output_message_buffer->value) + 514 input_message_buffer->length, 515 trailer.value, trailer.length); 516 gss_release_buffer(&junk, &trailer); 517 518 return GSS_S_COMPLETE; 519 } 520 521 return GSS_S_UNAVAILABLE; 522 } 523 524 /* 525 * 526 */ 527 528 OM_uint32 GSSAPI_CALLCONV 529 _gss_ntlm_unwrap 530 (OM_uint32 * minor_status, 531 const gss_ctx_id_t context_handle, 532 const gss_buffer_t input_message_buffer, 533 gss_buffer_t output_message_buffer, 534 int * conf_state, 535 gss_qop_t * qop_state 536 ) 537 { 538 ntlm_ctx ctx = (ntlm_ctx)context_handle; 539 OM_uint32 ret; 540 541 *minor_status = 0; 542 output_message_buffer->value = NULL; 543 output_message_buffer->length = 0; 544 545 if (conf_state) 546 *conf_state = 0; 547 if (qop_state) 548 *qop_state = 0; 549 550 if (CTX_FLAGS_ISSET(ctx, NTLM_NEG_SEAL|NTLM_NEG_NTLM2_SESSION)) { 551 552 return v2_unseal_message(input_message_buffer, 553 ctx->u.v2.recv.signkey, 554 ctx->u.v2.recv.seq++, 555 &ctx->u.v2.recv.sealkey, 556 output_message_buffer); 557 558 } else if (CTX_FLAGS_ISSET(ctx, NTLM_NEG_SEAL)) { 559 560 gss_buffer_desc trailer; 561 OM_uint32 junk; 562 563 if (input_message_buffer->length < 16) 564 return GSS_S_BAD_MIC; 565 566 output_message_buffer->length = input_message_buffer->length - 16; 567 output_message_buffer->value = malloc(output_message_buffer->length); 568 if (output_message_buffer->value == NULL) { 569 output_message_buffer->length = 0; 570 return GSS_S_FAILURE; 571 } 572 573 RC4(&ctx->u.v1.crypto_recv.key, output_message_buffer->length, 574 input_message_buffer->value, output_message_buffer->value); 575 576 trailer.value = ((unsigned char *)input_message_buffer->value) + 577 output_message_buffer->length; 578 trailer.length = 16; 579 580 ret = _gss_ntlm_verify_mic(minor_status, context_handle, 581 output_message_buffer, 582 &trailer, NULL); 583 if (ret) { 584 gss_release_buffer(&junk, output_message_buffer); 585 return ret; 586 } 587 588 return GSS_S_COMPLETE; 589 } 590 591 return GSS_S_UNAVAILABLE; 592 } 593