1178825Sdfr/* 2233294Sstas * Copyright (c) 2006 Kungliga Tekniska H��gskolan 3233294Sstas * (Royal Institute of Technology, Stockholm, Sweden). 4233294Sstas * All rights reserved. 5178825Sdfr * 6233294Sstas * Redistribution and use in source and binary forms, with or without 7233294Sstas * modification, are permitted provided that the following conditions 8233294Sstas * are met: 9178825Sdfr * 10233294Sstas * 1. Redistributions of source code must retain the above copyright 11233294Sstas * notice, this list of conditions and the following disclaimer. 12178825Sdfr * 13233294Sstas * 2. Redistributions in binary form must reproduce the above copyright 14233294Sstas * notice, this list of conditions and the following disclaimer in the 15233294Sstas * documentation and/or other materials provided with the distribution. 16178825Sdfr * 17233294Sstas * 3. Neither the name of the Institute nor the names of its contributors 18233294Sstas * may be used to endorse or promote products derived from this software 19233294Sstas * without specific prior written permission. 20178825Sdfr * 21233294Sstas * THIS SOFTWARE IS PROVIDED BY THE INSTITUTE AND CONTRIBUTORS ``AS IS'' AND 22233294Sstas * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 23233294Sstas * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE 24233294Sstas * ARE DISCLAIMED. IN NO EVENT SHALL THE INSTITUTE OR CONTRIBUTORS BE LIABLE 25233294Sstas * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL 26233294Sstas * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS 27233294Sstas * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) 28233294Sstas * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT 29233294Sstas * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY 30233294Sstas * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF 31233294Sstas * SUCH DAMAGE. 32178825Sdfr */ 33178825Sdfr 34233294Sstas#include "ntlm.h" 35178825Sdfr 36178825Sdfruint32_t 37178825Sdfr_krb5_crc_update (const char *p, size_t len, uint32_t res); 38178825Sdfrvoid 39178825Sdfr_krb5_crc_init_table(void); 40178825Sdfr 41178825Sdfr/* 42178825Sdfr * 43178825Sdfr */ 44178825Sdfr 45178825Sdfrstatic void 46178825Sdfrencode_le_uint32(uint32_t n, unsigned char *p) 47178825Sdfr{ 48178825Sdfr p[0] = (n >> 0) & 0xFF; 49178825Sdfr p[1] = (n >> 8) & 0xFF; 50178825Sdfr p[2] = (n >> 16) & 0xFF; 51178825Sdfr p[3] = (n >> 24) & 0xFF; 52178825Sdfr} 53178825Sdfr 54178825Sdfr 55178825Sdfrstatic void 56178825Sdfrdecode_le_uint32(const void *ptr, uint32_t *n) 57178825Sdfr{ 58178825Sdfr const unsigned char *p = ptr; 59178825Sdfr *n = (p[0] << 0) | (p[1] << 8) | (p[2] << 16) | (p[3] << 24); 60178825Sdfr} 61178825Sdfr 62178825Sdfr/* 63178825Sdfr * 64178825Sdfr */ 65178825Sdfr 66178825Sdfrconst char a2i_signmagic[] = 67178825Sdfr "session key to server-to-client signing key magic constant"; 68178825Sdfrconst char a2i_sealmagic[] = 69178825Sdfr "session key to server-to-client sealing key magic constant"; 70178825Sdfrconst char i2a_signmagic[] = 71178825Sdfr "session key to client-to-server signing key magic constant"; 72178825Sdfrconst char i2a_sealmagic[] = 73178825Sdfr "session key to client-to-server sealing key magic constant"; 74178825Sdfr 75178825Sdfr 76178825Sdfrvoid 77178825Sdfr_gss_ntlm_set_key(struct ntlmv2_key *key, int acceptor, int sealsign, 78178825Sdfr unsigned char *data, size_t len) 79178825Sdfr{ 80178825Sdfr unsigned char out[16]; 81233294Sstas EVP_MD_CTX *ctx; 82178825Sdfr const char *signmagic; 83178825Sdfr const char *sealmagic; 84178825Sdfr 85178825Sdfr if (acceptor) { 86178825Sdfr signmagic = a2i_signmagic; 87178825Sdfr sealmagic = a2i_sealmagic; 88178825Sdfr } else { 89178825Sdfr signmagic = i2a_signmagic; 90178825Sdfr sealmagic = i2a_sealmagic; 91178825Sdfr } 92178825Sdfr 93178825Sdfr key->seq = 0; 94178825Sdfr 95233294Sstas ctx = EVP_MD_CTX_create(); 96233294Sstas EVP_DigestInit_ex(ctx, EVP_md5(), NULL); 97233294Sstas EVP_DigestUpdate(ctx, data, len); 98233294Sstas EVP_DigestUpdate(ctx, signmagic, strlen(signmagic) + 1); 99233294Sstas EVP_DigestFinal_ex(ctx, key->signkey, NULL); 100178825Sdfr 101233294Sstas EVP_DigestInit_ex(ctx, EVP_md5(), NULL); 102233294Sstas EVP_DigestUpdate(ctx, data, len); 103233294Sstas EVP_DigestUpdate(ctx, sealmagic, strlen(sealmagic) + 1); 104233294Sstas EVP_DigestFinal_ex(ctx, out, NULL); 105233294Sstas EVP_MD_CTX_destroy(ctx); 106178825Sdfr 107178825Sdfr RC4_set_key(&key->sealkey, 16, out); 108178825Sdfr if (sealsign) 109178825Sdfr key->signsealkey = &key->sealkey; 110178825Sdfr} 111178825Sdfr 112178825Sdfr/* 113178825Sdfr * 114178825Sdfr */ 115178825Sdfr 116178825Sdfrstatic OM_uint32 117178825Sdfrv1_sign_message(gss_buffer_t in, 118178825Sdfr RC4_KEY *signkey, 119178825Sdfr uint32_t seq, 120178825Sdfr unsigned char out[16]) 121178825Sdfr{ 122178825Sdfr unsigned char sigature[12]; 123178825Sdfr uint32_t crc; 124233294Sstas 125178825Sdfr _krb5_crc_init_table(); 126178825Sdfr crc = _krb5_crc_update(in->value, in->length, 0); 127233294Sstas 128178825Sdfr encode_le_uint32(0, &sigature[0]); 129178825Sdfr encode_le_uint32(crc, &sigature[4]); 130178825Sdfr encode_le_uint32(seq, &sigature[8]); 131233294Sstas 132178825Sdfr encode_le_uint32(1, out); /* version */ 133178825Sdfr RC4(signkey, sizeof(sigature), sigature, out + 4); 134233294Sstas 135178825Sdfr if (RAND_bytes(out + 4, 4) != 1) 136178825Sdfr return GSS_S_UNAVAILABLE; 137233294Sstas 138178825Sdfr return 0; 139178825Sdfr} 140178825Sdfr 141178825Sdfr 142178825Sdfrstatic OM_uint32 143178825Sdfrv2_sign_message(gss_buffer_t in, 144178825Sdfr unsigned char signkey[16], 145178825Sdfr RC4_KEY *sealkey, 146178825Sdfr uint32_t seq, 147178825Sdfr unsigned char out[16]) 148178825Sdfr{ 149178825Sdfr unsigned char hmac[16]; 150178825Sdfr unsigned int hmaclen; 151178825Sdfr HMAC_CTX c; 152178825Sdfr 153178825Sdfr HMAC_CTX_init(&c); 154178825Sdfr HMAC_Init_ex(&c, signkey, 16, EVP_md5(), NULL); 155233294Sstas 156178825Sdfr encode_le_uint32(seq, hmac); 157178825Sdfr HMAC_Update(&c, hmac, 4); 158178825Sdfr HMAC_Update(&c, in->value, in->length); 159178825Sdfr HMAC_Final(&c, hmac, &hmaclen); 160178825Sdfr HMAC_CTX_cleanup(&c); 161178825Sdfr 162178825Sdfr encode_le_uint32(1, &out[0]); 163178825Sdfr if (sealkey) 164178825Sdfr RC4(sealkey, 8, hmac, &out[4]); 165178825Sdfr else 166178825Sdfr memcpy(&out[4], hmac, 8); 167178825Sdfr 168178825Sdfr memset(&out[12], 0, 4); 169178825Sdfr 170178825Sdfr return GSS_S_COMPLETE; 171178825Sdfr} 172178825Sdfr 173178825Sdfrstatic OM_uint32 174178825Sdfrv2_verify_message(gss_buffer_t in, 175178825Sdfr unsigned char signkey[16], 176178825Sdfr RC4_KEY *sealkey, 177178825Sdfr uint32_t seq, 178178825Sdfr const unsigned char checksum[16]) 179178825Sdfr{ 180178825Sdfr OM_uint32 ret; 181178825Sdfr unsigned char out[16]; 182178825Sdfr 183178825Sdfr ret = v2_sign_message(in, signkey, sealkey, seq, out); 184178825Sdfr if (ret) 185178825Sdfr return ret; 186178825Sdfr 187178825Sdfr if (memcmp(checksum, out, 16) != 0) 188178825Sdfr return GSS_S_BAD_MIC; 189178825Sdfr 190178825Sdfr return GSS_S_COMPLETE; 191233294Sstas} 192178825Sdfr 193178825Sdfrstatic OM_uint32 194178825Sdfrv2_seal_message(const gss_buffer_t in, 195178825Sdfr unsigned char signkey[16], 196178825Sdfr uint32_t seq, 197178825Sdfr RC4_KEY *sealkey, 198178825Sdfr gss_buffer_t out) 199178825Sdfr{ 200178825Sdfr unsigned char *p; 201178825Sdfr OM_uint32 ret; 202178825Sdfr 203178825Sdfr if (in->length + 16 < in->length) 204178825Sdfr return EINVAL; 205178825Sdfr 206178825Sdfr p = malloc(in->length + 16); 207178825Sdfr if (p == NULL) 208178825Sdfr return ENOMEM; 209178825Sdfr 210178825Sdfr RC4(sealkey, in->length, in->value, p); 211178825Sdfr 212178825Sdfr ret = v2_sign_message(in, signkey, sealkey, seq, &p[in->length]); 213178825Sdfr if (ret) { 214178825Sdfr free(p); 215178825Sdfr return ret; 216178825Sdfr } 217178825Sdfr 218178825Sdfr out->value = p; 219178825Sdfr out->length = in->length + 16; 220178825Sdfr 221178825Sdfr return 0; 222178825Sdfr} 223178825Sdfr 224178825Sdfrstatic OM_uint32 225178825Sdfrv2_unseal_message(gss_buffer_t in, 226178825Sdfr unsigned char signkey[16], 227178825Sdfr uint32_t seq, 228178825Sdfr RC4_KEY *sealkey, 229178825Sdfr gss_buffer_t out) 230178825Sdfr{ 231178825Sdfr OM_uint32 ret; 232178825Sdfr 233178825Sdfr if (in->length < 16) 234178825Sdfr return GSS_S_BAD_MIC; 235178825Sdfr 236178825Sdfr out->length = in->length - 16; 237178825Sdfr out->value = malloc(out->length); 238178825Sdfr if (out->value == NULL) 239178825Sdfr return GSS_S_BAD_MIC; 240178825Sdfr 241178825Sdfr RC4(sealkey, out->length, in->value, out->value); 242178825Sdfr 243178825Sdfr ret = v2_verify_message(out, signkey, sealkey, seq, 244178825Sdfr ((const unsigned char *)in->value) + out->length); 245178825Sdfr if (ret) { 246178825Sdfr OM_uint32 junk; 247178825Sdfr gss_release_buffer(&junk, out); 248178825Sdfr } 249178825Sdfr return ret; 250178825Sdfr} 251178825Sdfr 252178825Sdfr/* 253178825Sdfr * 254178825Sdfr */ 255178825Sdfr 256178825Sdfr#define CTX_FLAGS_ISSET(_ctx,_flags) \ 257178825Sdfr (((_ctx)->flags & (_flags)) == (_flags)) 258178825Sdfr 259178825Sdfr/* 260178825Sdfr * 261178825Sdfr */ 262233294Sstas 263233294SstasOM_uint32 GSSAPI_CALLCONV 264233294Sstas_gss_ntlm_get_mic 265178825Sdfr (OM_uint32 * minor_status, 266178825Sdfr const gss_ctx_id_t context_handle, 267178825Sdfr gss_qop_t qop_req, 268178825Sdfr const gss_buffer_t message_buffer, 269178825Sdfr gss_buffer_t message_token 270178825Sdfr ) 271178825Sdfr{ 272178825Sdfr ntlm_ctx ctx = (ntlm_ctx)context_handle; 273178825Sdfr OM_uint32 junk; 274178825Sdfr 275233294Sstas *minor_status = 0; 276178825Sdfr 277178825Sdfr message_token->value = malloc(16); 278178825Sdfr message_token->length = 16; 279178825Sdfr if (message_token->value == NULL) { 280178825Sdfr *minor_status = ENOMEM; 281178825Sdfr return GSS_S_FAILURE; 282178825Sdfr } 283178825Sdfr 284178825Sdfr if (CTX_FLAGS_ISSET(ctx, NTLM_NEG_SIGN|NTLM_NEG_NTLM2_SESSION)) { 285178825Sdfr OM_uint32 ret; 286178825Sdfr 287178825Sdfr if ((ctx->status & STATUS_SESSIONKEY) == 0) { 288178825Sdfr gss_release_buffer(&junk, message_token); 289178825Sdfr return GSS_S_UNAVAILABLE; 290178825Sdfr } 291178825Sdfr 292178825Sdfr ret = v2_sign_message(message_buffer, 293178825Sdfr ctx->u.v2.send.signkey, 294178825Sdfr ctx->u.v2.send.signsealkey, 295178825Sdfr ctx->u.v2.send.seq++, 296178825Sdfr message_token->value); 297178825Sdfr if (ret) 298178825Sdfr gss_release_buffer(&junk, message_token); 299178825Sdfr return ret; 300178825Sdfr 301178825Sdfr } else if (CTX_FLAGS_ISSET(ctx, NTLM_NEG_SIGN)) { 302178825Sdfr OM_uint32 ret; 303178825Sdfr 304178825Sdfr if ((ctx->status & STATUS_SESSIONKEY) == 0) { 305178825Sdfr gss_release_buffer(&junk, message_token); 306178825Sdfr return GSS_S_UNAVAILABLE; 307178825Sdfr } 308178825Sdfr 309178825Sdfr ret = v1_sign_message(message_buffer, 310178825Sdfr &ctx->u.v1.crypto_send.key, 311178825Sdfr ctx->u.v1.crypto_send.seq++, 312178825Sdfr message_token->value); 313178825Sdfr if (ret) 314178825Sdfr gss_release_buffer(&junk, message_token); 315178825Sdfr return ret; 316178825Sdfr 317178825Sdfr } else if (CTX_FLAGS_ISSET(ctx, NTLM_NEG_ALWAYS_SIGN)) { 318178825Sdfr unsigned char *sigature; 319178825Sdfr 320178825Sdfr sigature = message_token->value; 321178825Sdfr 322178825Sdfr encode_le_uint32(1, &sigature[0]); /* version */ 323178825Sdfr encode_le_uint32(0, &sigature[4]); 324178825Sdfr encode_le_uint32(0, &sigature[8]); 325178825Sdfr encode_le_uint32(0, &sigature[12]); 326178825Sdfr 327178825Sdfr return GSS_S_COMPLETE; 328178825Sdfr } 329178825Sdfr gss_release_buffer(&junk, message_token); 330178825Sdfr 331178825Sdfr return GSS_S_UNAVAILABLE; 332178825Sdfr} 333178825Sdfr 334178825Sdfr/* 335178825Sdfr * 336178825Sdfr */ 337178825Sdfr 338233294SstasOM_uint32 GSSAPI_CALLCONV 339178825Sdfr_gss_ntlm_verify_mic 340178825Sdfr (OM_uint32 * minor_status, 341178825Sdfr const gss_ctx_id_t context_handle, 342178825Sdfr const gss_buffer_t message_buffer, 343178825Sdfr const gss_buffer_t token_buffer, 344178825Sdfr gss_qop_t * qop_state 345178825Sdfr ) 346178825Sdfr{ 347178825Sdfr ntlm_ctx ctx = (ntlm_ctx)context_handle; 348178825Sdfr 349178825Sdfr if (qop_state != NULL) 350178825Sdfr *qop_state = GSS_C_QOP_DEFAULT; 351178825Sdfr *minor_status = 0; 352178825Sdfr 353178825Sdfr if (token_buffer->length != 16) 354178825Sdfr return GSS_S_BAD_MIC; 355178825Sdfr 356178825Sdfr if (CTX_FLAGS_ISSET(ctx, NTLM_NEG_SIGN|NTLM_NEG_NTLM2_SESSION)) { 357178825Sdfr OM_uint32 ret; 358178825Sdfr 359178825Sdfr if ((ctx->status & STATUS_SESSIONKEY) == 0) 360178825Sdfr return GSS_S_UNAVAILABLE; 361178825Sdfr 362178825Sdfr ret = v2_verify_message(message_buffer, 363178825Sdfr ctx->u.v2.recv.signkey, 364178825Sdfr ctx->u.v2.recv.signsealkey, 365178825Sdfr ctx->u.v2.recv.seq++, 366178825Sdfr token_buffer->value); 367178825Sdfr if (ret) 368178825Sdfr return ret; 369178825Sdfr 370178825Sdfr return GSS_S_COMPLETE; 371178825Sdfr } else if (CTX_FLAGS_ISSET(ctx, NTLM_NEG_SIGN)) { 372178825Sdfr 373178825Sdfr unsigned char sigature[12]; 374178825Sdfr uint32_t crc, num; 375178825Sdfr 376178825Sdfr if ((ctx->status & STATUS_SESSIONKEY) == 0) 377178825Sdfr return GSS_S_UNAVAILABLE; 378178825Sdfr 379178825Sdfr decode_le_uint32(token_buffer->value, &num); 380178825Sdfr if (num != 1) 381178825Sdfr return GSS_S_BAD_MIC; 382178825Sdfr 383178825Sdfr RC4(&ctx->u.v1.crypto_recv.key, sizeof(sigature), 384178825Sdfr ((unsigned char *)token_buffer->value) + 4, sigature); 385178825Sdfr 386178825Sdfr _krb5_crc_init_table(); 387233294Sstas crc = _krb5_crc_update(message_buffer->value, 388178825Sdfr message_buffer->length, 0); 389178825Sdfr /* skip first 4 bytes in the encrypted checksum */ 390178825Sdfr decode_le_uint32(&sigature[4], &num); 391178825Sdfr if (num != crc) 392178825Sdfr return GSS_S_BAD_MIC; 393178825Sdfr decode_le_uint32(&sigature[8], &num); 394178825Sdfr if (ctx->u.v1.crypto_recv.seq != num) 395178825Sdfr return GSS_S_BAD_MIC; 396178825Sdfr ctx->u.v1.crypto_recv.seq++; 397178825Sdfr 398178825Sdfr return GSS_S_COMPLETE; 399178825Sdfr } else if (ctx->flags & NTLM_NEG_ALWAYS_SIGN) { 400178825Sdfr uint32_t num; 401178825Sdfr unsigned char *p; 402178825Sdfr 403178825Sdfr p = (unsigned char*)(token_buffer->value); 404178825Sdfr 405178825Sdfr decode_le_uint32(&p[0], &num); /* version */ 406178825Sdfr if (num != 1) return GSS_S_BAD_MIC; 407178825Sdfr decode_le_uint32(&p[4], &num); 408178825Sdfr if (num != 0) return GSS_S_BAD_MIC; 409178825Sdfr decode_le_uint32(&p[8], &num); 410178825Sdfr if (num != 0) return GSS_S_BAD_MIC; 411178825Sdfr decode_le_uint32(&p[12], &num); 412178825Sdfr if (num != 0) return GSS_S_BAD_MIC; 413178825Sdfr 414178825Sdfr return GSS_S_COMPLETE; 415178825Sdfr } 416178825Sdfr 417178825Sdfr return GSS_S_UNAVAILABLE; 418178825Sdfr} 419178825Sdfr 420178825Sdfr/* 421178825Sdfr * 422178825Sdfr */ 423178825Sdfr 424233294SstasOM_uint32 GSSAPI_CALLCONV 425178825Sdfr_gss_ntlm_wrap_size_limit ( 426178825Sdfr OM_uint32 * minor_status, 427178825Sdfr const gss_ctx_id_t context_handle, 428178825Sdfr int conf_req_flag, 429178825Sdfr gss_qop_t qop_req, 430178825Sdfr OM_uint32 req_output_size, 431178825Sdfr OM_uint32 * max_input_size 432178825Sdfr ) 433178825Sdfr{ 434178825Sdfr ntlm_ctx ctx = (ntlm_ctx)context_handle; 435178825Sdfr 436178825Sdfr *minor_status = 0; 437178825Sdfr 438178825Sdfr if(ctx->flags & NTLM_NEG_SEAL) { 439178825Sdfr 440178825Sdfr if (req_output_size < 16) 441178825Sdfr *max_input_size = 0; 442178825Sdfr else 443178825Sdfr *max_input_size = req_output_size - 16; 444178825Sdfr 445178825Sdfr return GSS_S_COMPLETE; 446178825Sdfr } 447178825Sdfr 448178825Sdfr return GSS_S_UNAVAILABLE; 449178825Sdfr} 450178825Sdfr 451178825Sdfr/* 452178825Sdfr * 453178825Sdfr */ 454178825Sdfr 455233294SstasOM_uint32 GSSAPI_CALLCONV 456233294Sstas_gss_ntlm_wrap 457178825Sdfr(OM_uint32 * minor_status, 458178825Sdfr const gss_ctx_id_t context_handle, 459178825Sdfr int conf_req_flag, 460178825Sdfr gss_qop_t qop_req, 461178825Sdfr const gss_buffer_t input_message_buffer, 462178825Sdfr int * conf_state, 463178825Sdfr gss_buffer_t output_message_buffer 464178825Sdfr ) 465178825Sdfr{ 466178825Sdfr ntlm_ctx ctx = (ntlm_ctx)context_handle; 467178825Sdfr OM_uint32 ret; 468178825Sdfr 469233294Sstas *minor_status = 0; 470178825Sdfr if (conf_state) 471178825Sdfr *conf_state = 0; 472178825Sdfr if (output_message_buffer == GSS_C_NO_BUFFER) 473178825Sdfr return GSS_S_FAILURE; 474178825Sdfr 475233294Sstas 476178825Sdfr if (CTX_FLAGS_ISSET(ctx, NTLM_NEG_SEAL|NTLM_NEG_NTLM2_SESSION)) { 477178825Sdfr 478178825Sdfr return v2_seal_message(input_message_buffer, 479178825Sdfr ctx->u.v2.send.signkey, 480178825Sdfr ctx->u.v2.send.seq++, 481178825Sdfr &ctx->u.v2.send.sealkey, 482178825Sdfr output_message_buffer); 483178825Sdfr 484178825Sdfr } else if (CTX_FLAGS_ISSET(ctx, NTLM_NEG_SEAL)) { 485178825Sdfr gss_buffer_desc trailer; 486178825Sdfr OM_uint32 junk; 487178825Sdfr 488178825Sdfr output_message_buffer->length = input_message_buffer->length + 16; 489178825Sdfr output_message_buffer->value = malloc(output_message_buffer->length); 490178825Sdfr if (output_message_buffer->value == NULL) { 491178825Sdfr output_message_buffer->length = 0; 492178825Sdfr return GSS_S_FAILURE; 493178825Sdfr } 494178825Sdfr 495178825Sdfr 496178825Sdfr RC4(&ctx->u.v1.crypto_send.key, input_message_buffer->length, 497178825Sdfr input_message_buffer->value, output_message_buffer->value); 498233294Sstas 499178825Sdfr ret = _gss_ntlm_get_mic(minor_status, context_handle, 500178825Sdfr 0, input_message_buffer, 501178825Sdfr &trailer); 502178825Sdfr if (ret) { 503178825Sdfr gss_release_buffer(&junk, output_message_buffer); 504178825Sdfr return ret; 505178825Sdfr } 506178825Sdfr if (trailer.length != 16) { 507178825Sdfr gss_release_buffer(&junk, output_message_buffer); 508178825Sdfr gss_release_buffer(&junk, &trailer); 509178825Sdfr return GSS_S_FAILURE; 510178825Sdfr } 511233294Sstas memcpy(((unsigned char *)output_message_buffer->value) + 512178825Sdfr input_message_buffer->length, 513178825Sdfr trailer.value, trailer.length); 514178825Sdfr gss_release_buffer(&junk, &trailer); 515178825Sdfr 516178825Sdfr return GSS_S_COMPLETE; 517178825Sdfr } 518178825Sdfr 519178825Sdfr return GSS_S_UNAVAILABLE; 520178825Sdfr} 521178825Sdfr 522178825Sdfr/* 523178825Sdfr * 524178825Sdfr */ 525178825Sdfr 526233294SstasOM_uint32 GSSAPI_CALLCONV 527233294Sstas_gss_ntlm_unwrap 528178825Sdfr (OM_uint32 * minor_status, 529178825Sdfr const gss_ctx_id_t context_handle, 530178825Sdfr const gss_buffer_t input_message_buffer, 531178825Sdfr gss_buffer_t output_message_buffer, 532178825Sdfr int * conf_state, 533178825Sdfr gss_qop_t * qop_state 534178825Sdfr ) 535178825Sdfr{ 536178825Sdfr ntlm_ctx ctx = (ntlm_ctx)context_handle; 537178825Sdfr OM_uint32 ret; 538178825Sdfr 539233294Sstas *minor_status = 0; 540233294Sstas output_message_buffer->value = NULL; 541233294Sstas output_message_buffer->length = 0; 542233294Sstas 543178825Sdfr if (conf_state) 544178825Sdfr *conf_state = 0; 545178825Sdfr if (qop_state) 546178825Sdfr *qop_state = 0; 547178825Sdfr 548178825Sdfr if (CTX_FLAGS_ISSET(ctx, NTLM_NEG_SEAL|NTLM_NEG_NTLM2_SESSION)) { 549178825Sdfr 550178825Sdfr return v2_unseal_message(input_message_buffer, 551178825Sdfr ctx->u.v2.recv.signkey, 552178825Sdfr ctx->u.v2.recv.seq++, 553178825Sdfr &ctx->u.v2.recv.sealkey, 554178825Sdfr output_message_buffer); 555178825Sdfr 556178825Sdfr } else if (CTX_FLAGS_ISSET(ctx, NTLM_NEG_SEAL)) { 557178825Sdfr 558178825Sdfr gss_buffer_desc trailer; 559178825Sdfr OM_uint32 junk; 560178825Sdfr 561178825Sdfr if (input_message_buffer->length < 16) 562178825Sdfr return GSS_S_BAD_MIC; 563178825Sdfr 564178825Sdfr output_message_buffer->length = input_message_buffer->length - 16; 565178825Sdfr output_message_buffer->value = malloc(output_message_buffer->length); 566178825Sdfr if (output_message_buffer->value == NULL) { 567178825Sdfr output_message_buffer->length = 0; 568178825Sdfr return GSS_S_FAILURE; 569178825Sdfr } 570233294Sstas 571178825Sdfr RC4(&ctx->u.v1.crypto_recv.key, output_message_buffer->length, 572178825Sdfr input_message_buffer->value, output_message_buffer->value); 573233294Sstas 574178825Sdfr trailer.value = ((unsigned char *)input_message_buffer->value) + 575178825Sdfr output_message_buffer->length; 576178825Sdfr trailer.length = 16; 577178825Sdfr 578178825Sdfr ret = _gss_ntlm_verify_mic(minor_status, context_handle, 579178825Sdfr output_message_buffer, 580178825Sdfr &trailer, NULL); 581178825Sdfr if (ret) { 582178825Sdfr gss_release_buffer(&junk, output_message_buffer); 583178825Sdfr return ret; 584178825Sdfr } 585178825Sdfr 586178825Sdfr return GSS_S_COMPLETE; 587178825Sdfr } 588178825Sdfr 589178825Sdfr return GSS_S_UNAVAILABLE; 590178825Sdfr} 591