1c19800e8SDoug Rabson /* 2ae771770SStanislav Sedov * Copyright (c) 2006 Kungliga Tekniska Högskolan 3c19800e8SDoug Rabson * (Royal Institute of Technology, Stockholm, Sweden). 4c19800e8SDoug Rabson * All rights reserved. 5c19800e8SDoug Rabson * 6c19800e8SDoug Rabson * Redistribution and use in source and binary forms, with or without 7c19800e8SDoug Rabson * modification, are permitted provided that the following conditions 8c19800e8SDoug Rabson * are met: 9c19800e8SDoug Rabson * 10c19800e8SDoug Rabson * 1. Redistributions of source code must retain the above copyright 11c19800e8SDoug Rabson * notice, this list of conditions and the following disclaimer. 12c19800e8SDoug Rabson * 13c19800e8SDoug Rabson * 2. Redistributions in binary form must reproduce the above copyright 14c19800e8SDoug Rabson * notice, this list of conditions and the following disclaimer in the 15c19800e8SDoug Rabson * documentation and/or other materials provided with the distribution. 16c19800e8SDoug Rabson * 17c19800e8SDoug Rabson * 3. Neither the name of the Institute nor the names of its contributors 18c19800e8SDoug Rabson * may be used to endorse or promote products derived from this software 19c19800e8SDoug Rabson * without specific prior written permission. 20c19800e8SDoug Rabson * 21c19800e8SDoug Rabson * THIS SOFTWARE IS PROVIDED BY THE INSTITUTE AND CONTRIBUTORS ``AS IS'' AND 22c19800e8SDoug Rabson * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 23c19800e8SDoug Rabson * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE 24c19800e8SDoug Rabson * ARE DISCLAIMED. IN NO EVENT SHALL THE INSTITUTE OR CONTRIBUTORS BE LIABLE 25c19800e8SDoug Rabson * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL 26c19800e8SDoug Rabson * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS 27c19800e8SDoug Rabson * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) 28c19800e8SDoug Rabson * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT 29c19800e8SDoug Rabson * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY 30c19800e8SDoug Rabson * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF 31c19800e8SDoug Rabson * SUCH DAMAGE. 32c19800e8SDoug Rabson */ 33c19800e8SDoug Rabson 34ae771770SStanislav Sedov #include "ntlm.h" 35c19800e8SDoug Rabson 36c19800e8SDoug Rabson uint32_t 37c19800e8SDoug Rabson _krb5_crc_update (const char *p, size_t len, uint32_t res); 38c19800e8SDoug Rabson void 39c19800e8SDoug Rabson _krb5_crc_init_table(void); 40c19800e8SDoug Rabson 41c19800e8SDoug Rabson /* 42c19800e8SDoug Rabson * 43c19800e8SDoug Rabson */ 44c19800e8SDoug Rabson 45c19800e8SDoug Rabson static void 46c19800e8SDoug Rabson encode_le_uint32(uint32_t n, unsigned char *p) 47c19800e8SDoug Rabson { 48c19800e8SDoug Rabson p[0] = (n >> 0) & 0xFF; 49c19800e8SDoug Rabson p[1] = (n >> 8) & 0xFF; 50c19800e8SDoug Rabson p[2] = (n >> 16) & 0xFF; 51c19800e8SDoug Rabson p[3] = (n >> 24) & 0xFF; 52c19800e8SDoug Rabson } 53c19800e8SDoug Rabson 54c19800e8SDoug Rabson 55c19800e8SDoug Rabson static void 56c19800e8SDoug Rabson decode_le_uint32(const void *ptr, uint32_t *n) 57c19800e8SDoug Rabson { 58c19800e8SDoug Rabson const unsigned char *p = ptr; 59c19800e8SDoug Rabson *n = (p[0] << 0) | (p[1] << 8) | (p[2] << 16) | (p[3] << 24); 60c19800e8SDoug Rabson } 61c19800e8SDoug Rabson 62c19800e8SDoug Rabson /* 63c19800e8SDoug Rabson * 64c19800e8SDoug Rabson */ 65c19800e8SDoug Rabson 66c19800e8SDoug Rabson const char a2i_signmagic[] = 67c19800e8SDoug Rabson "session key to server-to-client signing key magic constant"; 68c19800e8SDoug Rabson const char a2i_sealmagic[] = 69c19800e8SDoug Rabson "session key to server-to-client sealing key magic constant"; 70c19800e8SDoug Rabson const char i2a_signmagic[] = 71c19800e8SDoug Rabson "session key to client-to-server signing key magic constant"; 72c19800e8SDoug Rabson const char i2a_sealmagic[] = 73c19800e8SDoug Rabson "session key to client-to-server sealing key magic constant"; 74c19800e8SDoug Rabson 75c19800e8SDoug Rabson 76c19800e8SDoug Rabson void 77c19800e8SDoug Rabson _gss_ntlm_set_key(struct ntlmv2_key *key, int acceptor, int sealsign, 78c19800e8SDoug Rabson unsigned char *data, size_t len) 79c19800e8SDoug Rabson { 80c19800e8SDoug Rabson unsigned char out[16]; 81ae771770SStanislav Sedov EVP_MD_CTX *ctx; 82c19800e8SDoug Rabson const char *signmagic; 83c19800e8SDoug Rabson const char *sealmagic; 84c19800e8SDoug Rabson 85c19800e8SDoug Rabson if (acceptor) { 86c19800e8SDoug Rabson signmagic = a2i_signmagic; 87c19800e8SDoug Rabson sealmagic = a2i_sealmagic; 88c19800e8SDoug Rabson } else { 89c19800e8SDoug Rabson signmagic = i2a_signmagic; 90c19800e8SDoug Rabson sealmagic = i2a_sealmagic; 91c19800e8SDoug Rabson } 92c19800e8SDoug Rabson 93c19800e8SDoug Rabson key->seq = 0; 94c19800e8SDoug Rabson 95ae771770SStanislav Sedov ctx = EVP_MD_CTX_create(); 96ae771770SStanislav Sedov EVP_DigestInit_ex(ctx, EVP_md5(), NULL); 97ae771770SStanislav Sedov EVP_DigestUpdate(ctx, data, len); 98ae771770SStanislav Sedov EVP_DigestUpdate(ctx, signmagic, strlen(signmagic) + 1); 99ae771770SStanislav Sedov EVP_DigestFinal_ex(ctx, key->signkey, NULL); 100c19800e8SDoug Rabson 101ae771770SStanislav Sedov EVP_DigestInit_ex(ctx, EVP_md5(), NULL); 102ae771770SStanislav Sedov EVP_DigestUpdate(ctx, data, len); 103ae771770SStanislav Sedov EVP_DigestUpdate(ctx, sealmagic, strlen(sealmagic) + 1); 104ae771770SStanislav Sedov EVP_DigestFinal_ex(ctx, out, NULL); 105ae771770SStanislav Sedov EVP_MD_CTX_destroy(ctx); 106c19800e8SDoug Rabson 107c19800e8SDoug Rabson RC4_set_key(&key->sealkey, 16, out); 108c19800e8SDoug Rabson if (sealsign) 109c19800e8SDoug Rabson key->signsealkey = &key->sealkey; 110c19800e8SDoug Rabson } 111c19800e8SDoug Rabson 112c19800e8SDoug Rabson /* 113c19800e8SDoug Rabson * 114c19800e8SDoug Rabson */ 115c19800e8SDoug Rabson 116c19800e8SDoug Rabson static OM_uint32 117c19800e8SDoug Rabson v1_sign_message(gss_buffer_t in, 118c19800e8SDoug Rabson RC4_KEY *signkey, 119c19800e8SDoug Rabson uint32_t seq, 120c19800e8SDoug Rabson unsigned char out[16]) 121c19800e8SDoug Rabson { 122c19800e8SDoug Rabson unsigned char sigature[12]; 123c19800e8SDoug Rabson uint32_t crc; 124c19800e8SDoug Rabson 125c19800e8SDoug Rabson _krb5_crc_init_table(); 126c19800e8SDoug Rabson crc = _krb5_crc_update(in->value, in->length, 0); 127c19800e8SDoug Rabson 128c19800e8SDoug Rabson encode_le_uint32(0, &sigature[0]); 129c19800e8SDoug Rabson encode_le_uint32(crc, &sigature[4]); 130c19800e8SDoug Rabson encode_le_uint32(seq, &sigature[8]); 131c19800e8SDoug Rabson 132c19800e8SDoug Rabson encode_le_uint32(1, out); /* version */ 133c19800e8SDoug Rabson RC4(signkey, sizeof(sigature), sigature, out + 4); 134c19800e8SDoug Rabson 135c19800e8SDoug Rabson if (RAND_bytes(out + 4, 4) != 1) 136c19800e8SDoug Rabson return GSS_S_UNAVAILABLE; 137c19800e8SDoug Rabson 138c19800e8SDoug Rabson return 0; 139c19800e8SDoug Rabson } 140c19800e8SDoug Rabson 141c19800e8SDoug Rabson 142c19800e8SDoug Rabson static OM_uint32 143c19800e8SDoug Rabson v2_sign_message(gss_buffer_t in, 144c19800e8SDoug Rabson unsigned char signkey[16], 145c19800e8SDoug Rabson RC4_KEY *sealkey, 146c19800e8SDoug Rabson uint32_t seq, 147c19800e8SDoug Rabson unsigned char out[16]) 148c19800e8SDoug Rabson { 149c19800e8SDoug Rabson unsigned char hmac[16]; 150c19800e8SDoug Rabson unsigned int hmaclen; 151*e4456411SJohn Baldwin HMAC_CTX *c; 152c19800e8SDoug Rabson 153*e4456411SJohn Baldwin c = HMAC_CTX_new(); 154*e4456411SJohn Baldwin if (c == NULL) 155*e4456411SJohn Baldwin return GSS_S_FAILURE; 156*e4456411SJohn Baldwin HMAC_Init_ex(c, signkey, 16, EVP_md5(), NULL); 157c19800e8SDoug Rabson 158c19800e8SDoug Rabson encode_le_uint32(seq, hmac); 159*e4456411SJohn Baldwin HMAC_Update(c, hmac, 4); 160*e4456411SJohn Baldwin HMAC_Update(c, in->value, in->length); 161*e4456411SJohn Baldwin HMAC_Final(c, hmac, &hmaclen); 162*e4456411SJohn Baldwin HMAC_CTX_free(c); 163c19800e8SDoug Rabson 164c19800e8SDoug Rabson encode_le_uint32(1, &out[0]); 165c19800e8SDoug Rabson if (sealkey) 166c19800e8SDoug Rabson RC4(sealkey, 8, hmac, &out[4]); 167c19800e8SDoug Rabson else 168c19800e8SDoug Rabson memcpy(&out[4], hmac, 8); 169c19800e8SDoug Rabson 170c19800e8SDoug Rabson memset(&out[12], 0, 4); 171c19800e8SDoug Rabson 172c19800e8SDoug Rabson return GSS_S_COMPLETE; 173c19800e8SDoug Rabson } 174c19800e8SDoug Rabson 175c19800e8SDoug Rabson static OM_uint32 176c19800e8SDoug Rabson v2_verify_message(gss_buffer_t in, 177c19800e8SDoug Rabson unsigned char signkey[16], 178c19800e8SDoug Rabson RC4_KEY *sealkey, 179c19800e8SDoug Rabson uint32_t seq, 180c19800e8SDoug Rabson const unsigned char checksum[16]) 181c19800e8SDoug Rabson { 182c19800e8SDoug Rabson OM_uint32 ret; 183c19800e8SDoug Rabson unsigned char out[16]; 184c19800e8SDoug Rabson 185c19800e8SDoug Rabson ret = v2_sign_message(in, signkey, sealkey, seq, out); 186c19800e8SDoug Rabson if (ret) 187c19800e8SDoug Rabson return ret; 188c19800e8SDoug Rabson 189c19800e8SDoug Rabson if (memcmp(checksum, out, 16) != 0) 190c19800e8SDoug Rabson return GSS_S_BAD_MIC; 191c19800e8SDoug Rabson 192c19800e8SDoug Rabson return GSS_S_COMPLETE; 193c19800e8SDoug Rabson } 194c19800e8SDoug Rabson 195c19800e8SDoug Rabson static OM_uint32 196c19800e8SDoug Rabson v2_seal_message(const gss_buffer_t in, 197c19800e8SDoug Rabson unsigned char signkey[16], 198c19800e8SDoug Rabson uint32_t seq, 199c19800e8SDoug Rabson RC4_KEY *sealkey, 200c19800e8SDoug Rabson gss_buffer_t out) 201c19800e8SDoug Rabson { 202c19800e8SDoug Rabson unsigned char *p; 203c19800e8SDoug Rabson OM_uint32 ret; 204c19800e8SDoug Rabson 205c19800e8SDoug Rabson if (in->length + 16 < in->length) 206c19800e8SDoug Rabson return EINVAL; 207c19800e8SDoug Rabson 208c19800e8SDoug Rabson p = malloc(in->length + 16); 209c19800e8SDoug Rabson if (p == NULL) 210c19800e8SDoug Rabson return ENOMEM; 211c19800e8SDoug Rabson 212c19800e8SDoug Rabson RC4(sealkey, in->length, in->value, p); 213c19800e8SDoug Rabson 214c19800e8SDoug Rabson ret = v2_sign_message(in, signkey, sealkey, seq, &p[in->length]); 215c19800e8SDoug Rabson if (ret) { 216c19800e8SDoug Rabson free(p); 217c19800e8SDoug Rabson return ret; 218c19800e8SDoug Rabson } 219c19800e8SDoug Rabson 220c19800e8SDoug Rabson out->value = p; 221c19800e8SDoug Rabson out->length = in->length + 16; 222c19800e8SDoug Rabson 223c19800e8SDoug Rabson return 0; 224c19800e8SDoug Rabson } 225c19800e8SDoug Rabson 226c19800e8SDoug Rabson static OM_uint32 227c19800e8SDoug Rabson v2_unseal_message(gss_buffer_t in, 228c19800e8SDoug Rabson unsigned char signkey[16], 229c19800e8SDoug Rabson uint32_t seq, 230c19800e8SDoug Rabson RC4_KEY *sealkey, 231c19800e8SDoug Rabson gss_buffer_t out) 232c19800e8SDoug Rabson { 233c19800e8SDoug Rabson OM_uint32 ret; 234c19800e8SDoug Rabson 235c19800e8SDoug Rabson if (in->length < 16) 236c19800e8SDoug Rabson return GSS_S_BAD_MIC; 237c19800e8SDoug Rabson 238c19800e8SDoug Rabson out->length = in->length - 16; 239c19800e8SDoug Rabson out->value = malloc(out->length); 240c19800e8SDoug Rabson if (out->value == NULL) 241c19800e8SDoug Rabson return GSS_S_BAD_MIC; 242c19800e8SDoug Rabson 243c19800e8SDoug Rabson RC4(sealkey, out->length, in->value, out->value); 244c19800e8SDoug Rabson 245c19800e8SDoug Rabson ret = v2_verify_message(out, signkey, sealkey, seq, 246c19800e8SDoug Rabson ((const unsigned char *)in->value) + out->length); 247c19800e8SDoug Rabson if (ret) { 248c19800e8SDoug Rabson OM_uint32 junk; 249c19800e8SDoug Rabson gss_release_buffer(&junk, out); 250c19800e8SDoug Rabson } 251c19800e8SDoug Rabson return ret; 252c19800e8SDoug Rabson } 253c19800e8SDoug Rabson 254c19800e8SDoug Rabson /* 255c19800e8SDoug Rabson * 256c19800e8SDoug Rabson */ 257c19800e8SDoug Rabson 258c19800e8SDoug Rabson #define CTX_FLAGS_ISSET(_ctx,_flags) \ 259c19800e8SDoug Rabson (((_ctx)->flags & (_flags)) == (_flags)) 260c19800e8SDoug Rabson 261c19800e8SDoug Rabson /* 262c19800e8SDoug Rabson * 263c19800e8SDoug Rabson */ 264c19800e8SDoug Rabson 265ae771770SStanislav Sedov OM_uint32 GSSAPI_CALLCONV 266ae771770SStanislav Sedov _gss_ntlm_get_mic 267c19800e8SDoug Rabson (OM_uint32 * minor_status, 268c19800e8SDoug Rabson const gss_ctx_id_t context_handle, 269c19800e8SDoug Rabson gss_qop_t qop_req, 270c19800e8SDoug Rabson const gss_buffer_t message_buffer, 271c19800e8SDoug Rabson gss_buffer_t message_token 272c19800e8SDoug Rabson ) 273c19800e8SDoug Rabson { 274c19800e8SDoug Rabson ntlm_ctx ctx = (ntlm_ctx)context_handle; 275c19800e8SDoug Rabson OM_uint32 junk; 276c19800e8SDoug Rabson 277c19800e8SDoug Rabson *minor_status = 0; 278c19800e8SDoug Rabson 279c19800e8SDoug Rabson message_token->value = malloc(16); 280c19800e8SDoug Rabson message_token->length = 16; 281c19800e8SDoug Rabson if (message_token->value == NULL) { 282c19800e8SDoug Rabson *minor_status = ENOMEM; 283c19800e8SDoug Rabson return GSS_S_FAILURE; 284c19800e8SDoug Rabson } 285c19800e8SDoug Rabson 286c19800e8SDoug Rabson if (CTX_FLAGS_ISSET(ctx, NTLM_NEG_SIGN|NTLM_NEG_NTLM2_SESSION)) { 287c19800e8SDoug Rabson OM_uint32 ret; 288c19800e8SDoug Rabson 289c19800e8SDoug Rabson if ((ctx->status & STATUS_SESSIONKEY) == 0) { 290c19800e8SDoug Rabson gss_release_buffer(&junk, message_token); 291c19800e8SDoug Rabson return GSS_S_UNAVAILABLE; 292c19800e8SDoug Rabson } 293c19800e8SDoug Rabson 294c19800e8SDoug Rabson ret = v2_sign_message(message_buffer, 295c19800e8SDoug Rabson ctx->u.v2.send.signkey, 296c19800e8SDoug Rabson ctx->u.v2.send.signsealkey, 297c19800e8SDoug Rabson ctx->u.v2.send.seq++, 298c19800e8SDoug Rabson message_token->value); 299c19800e8SDoug Rabson if (ret) 300c19800e8SDoug Rabson gss_release_buffer(&junk, message_token); 301c19800e8SDoug Rabson return ret; 302c19800e8SDoug Rabson 303c19800e8SDoug Rabson } else if (CTX_FLAGS_ISSET(ctx, NTLM_NEG_SIGN)) { 304c19800e8SDoug Rabson OM_uint32 ret; 305c19800e8SDoug Rabson 306c19800e8SDoug Rabson if ((ctx->status & STATUS_SESSIONKEY) == 0) { 307c19800e8SDoug Rabson gss_release_buffer(&junk, message_token); 308c19800e8SDoug Rabson return GSS_S_UNAVAILABLE; 309c19800e8SDoug Rabson } 310c19800e8SDoug Rabson 311c19800e8SDoug Rabson ret = v1_sign_message(message_buffer, 312c19800e8SDoug Rabson &ctx->u.v1.crypto_send.key, 313c19800e8SDoug Rabson ctx->u.v1.crypto_send.seq++, 314c19800e8SDoug Rabson message_token->value); 315c19800e8SDoug Rabson if (ret) 316c19800e8SDoug Rabson gss_release_buffer(&junk, message_token); 317c19800e8SDoug Rabson return ret; 318c19800e8SDoug Rabson 319c19800e8SDoug Rabson } else if (CTX_FLAGS_ISSET(ctx, NTLM_NEG_ALWAYS_SIGN)) { 320c19800e8SDoug Rabson unsigned char *sigature; 321c19800e8SDoug Rabson 322c19800e8SDoug Rabson sigature = message_token->value; 323c19800e8SDoug Rabson 324c19800e8SDoug Rabson encode_le_uint32(1, &sigature[0]); /* version */ 325c19800e8SDoug Rabson encode_le_uint32(0, &sigature[4]); 326c19800e8SDoug Rabson encode_le_uint32(0, &sigature[8]); 327c19800e8SDoug Rabson encode_le_uint32(0, &sigature[12]); 328c19800e8SDoug Rabson 329c19800e8SDoug Rabson return GSS_S_COMPLETE; 330c19800e8SDoug Rabson } 331c19800e8SDoug Rabson gss_release_buffer(&junk, message_token); 332c19800e8SDoug Rabson 333c19800e8SDoug Rabson return GSS_S_UNAVAILABLE; 334c19800e8SDoug Rabson } 335c19800e8SDoug Rabson 336c19800e8SDoug Rabson /* 337c19800e8SDoug Rabson * 338c19800e8SDoug Rabson */ 339c19800e8SDoug Rabson 340ae771770SStanislav Sedov OM_uint32 GSSAPI_CALLCONV 341c19800e8SDoug Rabson _gss_ntlm_verify_mic 342c19800e8SDoug Rabson (OM_uint32 * minor_status, 343c19800e8SDoug Rabson const gss_ctx_id_t context_handle, 344c19800e8SDoug Rabson const gss_buffer_t message_buffer, 345c19800e8SDoug Rabson const gss_buffer_t token_buffer, 346c19800e8SDoug Rabson gss_qop_t * qop_state 347c19800e8SDoug Rabson ) 348c19800e8SDoug Rabson { 349c19800e8SDoug Rabson ntlm_ctx ctx = (ntlm_ctx)context_handle; 350c19800e8SDoug Rabson 351c19800e8SDoug Rabson if (qop_state != NULL) 352c19800e8SDoug Rabson *qop_state = GSS_C_QOP_DEFAULT; 353c19800e8SDoug Rabson *minor_status = 0; 354c19800e8SDoug Rabson 355c19800e8SDoug Rabson if (token_buffer->length != 16) 356c19800e8SDoug Rabson return GSS_S_BAD_MIC; 357c19800e8SDoug Rabson 358c19800e8SDoug Rabson if (CTX_FLAGS_ISSET(ctx, NTLM_NEG_SIGN|NTLM_NEG_NTLM2_SESSION)) { 359c19800e8SDoug Rabson OM_uint32 ret; 360c19800e8SDoug Rabson 361c19800e8SDoug Rabson if ((ctx->status & STATUS_SESSIONKEY) == 0) 362c19800e8SDoug Rabson return GSS_S_UNAVAILABLE; 363c19800e8SDoug Rabson 364c19800e8SDoug Rabson ret = v2_verify_message(message_buffer, 365c19800e8SDoug Rabson ctx->u.v2.recv.signkey, 366c19800e8SDoug Rabson ctx->u.v2.recv.signsealkey, 367c19800e8SDoug Rabson ctx->u.v2.recv.seq++, 368c19800e8SDoug Rabson token_buffer->value); 369c19800e8SDoug Rabson if (ret) 370c19800e8SDoug Rabson return ret; 371c19800e8SDoug Rabson 372c19800e8SDoug Rabson return GSS_S_COMPLETE; 373c19800e8SDoug Rabson } else if (CTX_FLAGS_ISSET(ctx, NTLM_NEG_SIGN)) { 374c19800e8SDoug Rabson 375c19800e8SDoug Rabson unsigned char sigature[12]; 376c19800e8SDoug Rabson uint32_t crc, num; 377c19800e8SDoug Rabson 378c19800e8SDoug Rabson if ((ctx->status & STATUS_SESSIONKEY) == 0) 379c19800e8SDoug Rabson return GSS_S_UNAVAILABLE; 380c19800e8SDoug Rabson 381c19800e8SDoug Rabson decode_le_uint32(token_buffer->value, &num); 382c19800e8SDoug Rabson if (num != 1) 383c19800e8SDoug Rabson return GSS_S_BAD_MIC; 384c19800e8SDoug Rabson 385c19800e8SDoug Rabson RC4(&ctx->u.v1.crypto_recv.key, sizeof(sigature), 386c19800e8SDoug Rabson ((unsigned char *)token_buffer->value) + 4, sigature); 387c19800e8SDoug Rabson 388c19800e8SDoug Rabson _krb5_crc_init_table(); 389c19800e8SDoug Rabson crc = _krb5_crc_update(message_buffer->value, 390c19800e8SDoug Rabson message_buffer->length, 0); 391c19800e8SDoug Rabson /* skip first 4 bytes in the encrypted checksum */ 392c19800e8SDoug Rabson decode_le_uint32(&sigature[4], &num); 393c19800e8SDoug Rabson if (num != crc) 394c19800e8SDoug Rabson return GSS_S_BAD_MIC; 395c19800e8SDoug Rabson decode_le_uint32(&sigature[8], &num); 396c19800e8SDoug Rabson if (ctx->u.v1.crypto_recv.seq != num) 397c19800e8SDoug Rabson return GSS_S_BAD_MIC; 398c19800e8SDoug Rabson ctx->u.v1.crypto_recv.seq++; 399c19800e8SDoug Rabson 400c19800e8SDoug Rabson return GSS_S_COMPLETE; 401c19800e8SDoug Rabson } else if (ctx->flags & NTLM_NEG_ALWAYS_SIGN) { 402c19800e8SDoug Rabson uint32_t num; 403c19800e8SDoug Rabson unsigned char *p; 404c19800e8SDoug Rabson 405c19800e8SDoug Rabson p = (unsigned char*)(token_buffer->value); 406c19800e8SDoug Rabson 407c19800e8SDoug Rabson decode_le_uint32(&p[0], &num); /* version */ 408c19800e8SDoug Rabson if (num != 1) return GSS_S_BAD_MIC; 409c19800e8SDoug Rabson decode_le_uint32(&p[4], &num); 410c19800e8SDoug Rabson if (num != 0) return GSS_S_BAD_MIC; 411c19800e8SDoug Rabson decode_le_uint32(&p[8], &num); 412c19800e8SDoug Rabson if (num != 0) return GSS_S_BAD_MIC; 413c19800e8SDoug Rabson decode_le_uint32(&p[12], &num); 414c19800e8SDoug Rabson if (num != 0) return GSS_S_BAD_MIC; 415c19800e8SDoug Rabson 416c19800e8SDoug Rabson return GSS_S_COMPLETE; 417c19800e8SDoug Rabson } 418c19800e8SDoug Rabson 419c19800e8SDoug Rabson return GSS_S_UNAVAILABLE; 420c19800e8SDoug Rabson } 421c19800e8SDoug Rabson 422c19800e8SDoug Rabson /* 423c19800e8SDoug Rabson * 424c19800e8SDoug Rabson */ 425c19800e8SDoug Rabson 426ae771770SStanislav Sedov OM_uint32 GSSAPI_CALLCONV 427c19800e8SDoug Rabson _gss_ntlm_wrap_size_limit ( 428c19800e8SDoug Rabson OM_uint32 * minor_status, 429c19800e8SDoug Rabson const gss_ctx_id_t context_handle, 430c19800e8SDoug Rabson int conf_req_flag, 431c19800e8SDoug Rabson gss_qop_t qop_req, 432c19800e8SDoug Rabson OM_uint32 req_output_size, 433c19800e8SDoug Rabson OM_uint32 * max_input_size 434c19800e8SDoug Rabson ) 435c19800e8SDoug Rabson { 436c19800e8SDoug Rabson ntlm_ctx ctx = (ntlm_ctx)context_handle; 437c19800e8SDoug Rabson 438c19800e8SDoug Rabson *minor_status = 0; 439c19800e8SDoug Rabson 440c19800e8SDoug Rabson if(ctx->flags & NTLM_NEG_SEAL) { 441c19800e8SDoug Rabson 442c19800e8SDoug Rabson if (req_output_size < 16) 443c19800e8SDoug Rabson *max_input_size = 0; 444c19800e8SDoug Rabson else 445c19800e8SDoug Rabson *max_input_size = req_output_size - 16; 446c19800e8SDoug Rabson 447c19800e8SDoug Rabson return GSS_S_COMPLETE; 448c19800e8SDoug Rabson } 449c19800e8SDoug Rabson 450c19800e8SDoug Rabson return GSS_S_UNAVAILABLE; 451c19800e8SDoug Rabson } 452c19800e8SDoug Rabson 453c19800e8SDoug Rabson /* 454c19800e8SDoug Rabson * 455c19800e8SDoug Rabson */ 456c19800e8SDoug Rabson 457ae771770SStanislav Sedov OM_uint32 GSSAPI_CALLCONV 458ae771770SStanislav Sedov _gss_ntlm_wrap 459c19800e8SDoug Rabson (OM_uint32 * minor_status, 460c19800e8SDoug Rabson const gss_ctx_id_t context_handle, 461c19800e8SDoug Rabson int conf_req_flag, 462c19800e8SDoug Rabson gss_qop_t qop_req, 463c19800e8SDoug Rabson const gss_buffer_t input_message_buffer, 464c19800e8SDoug Rabson int * conf_state, 465c19800e8SDoug Rabson gss_buffer_t output_message_buffer 466c19800e8SDoug Rabson ) 467c19800e8SDoug Rabson { 468c19800e8SDoug Rabson ntlm_ctx ctx = (ntlm_ctx)context_handle; 469c19800e8SDoug Rabson OM_uint32 ret; 470c19800e8SDoug Rabson 471c19800e8SDoug Rabson *minor_status = 0; 472c19800e8SDoug Rabson if (conf_state) 473c19800e8SDoug Rabson *conf_state = 0; 474c19800e8SDoug Rabson if (output_message_buffer == GSS_C_NO_BUFFER) 475c19800e8SDoug Rabson return GSS_S_FAILURE; 476c19800e8SDoug Rabson 477c19800e8SDoug Rabson 478c19800e8SDoug Rabson if (CTX_FLAGS_ISSET(ctx, NTLM_NEG_SEAL|NTLM_NEG_NTLM2_SESSION)) { 479c19800e8SDoug Rabson 480c19800e8SDoug Rabson return v2_seal_message(input_message_buffer, 481c19800e8SDoug Rabson ctx->u.v2.send.signkey, 482c19800e8SDoug Rabson ctx->u.v2.send.seq++, 483c19800e8SDoug Rabson &ctx->u.v2.send.sealkey, 484c19800e8SDoug Rabson output_message_buffer); 485c19800e8SDoug Rabson 486c19800e8SDoug Rabson } else if (CTX_FLAGS_ISSET(ctx, NTLM_NEG_SEAL)) { 487c19800e8SDoug Rabson gss_buffer_desc trailer; 488c19800e8SDoug Rabson OM_uint32 junk; 489c19800e8SDoug Rabson 490c19800e8SDoug Rabson output_message_buffer->length = input_message_buffer->length + 16; 491c19800e8SDoug Rabson output_message_buffer->value = malloc(output_message_buffer->length); 492c19800e8SDoug Rabson if (output_message_buffer->value == NULL) { 493c19800e8SDoug Rabson output_message_buffer->length = 0; 494c19800e8SDoug Rabson return GSS_S_FAILURE; 495c19800e8SDoug Rabson } 496c19800e8SDoug Rabson 497c19800e8SDoug Rabson 498c19800e8SDoug Rabson RC4(&ctx->u.v1.crypto_send.key, input_message_buffer->length, 499c19800e8SDoug Rabson input_message_buffer->value, output_message_buffer->value); 500c19800e8SDoug Rabson 501c19800e8SDoug Rabson ret = _gss_ntlm_get_mic(minor_status, context_handle, 502c19800e8SDoug Rabson 0, input_message_buffer, 503c19800e8SDoug Rabson &trailer); 504c19800e8SDoug Rabson if (ret) { 505c19800e8SDoug Rabson gss_release_buffer(&junk, output_message_buffer); 506c19800e8SDoug Rabson return ret; 507c19800e8SDoug Rabson } 508c19800e8SDoug Rabson if (trailer.length != 16) { 509c19800e8SDoug Rabson gss_release_buffer(&junk, output_message_buffer); 510c19800e8SDoug Rabson gss_release_buffer(&junk, &trailer); 511c19800e8SDoug Rabson return GSS_S_FAILURE; 512c19800e8SDoug Rabson } 513c19800e8SDoug Rabson memcpy(((unsigned char *)output_message_buffer->value) + 514c19800e8SDoug Rabson input_message_buffer->length, 515c19800e8SDoug Rabson trailer.value, trailer.length); 516c19800e8SDoug Rabson gss_release_buffer(&junk, &trailer); 517c19800e8SDoug Rabson 518c19800e8SDoug Rabson return GSS_S_COMPLETE; 519c19800e8SDoug Rabson } 520c19800e8SDoug Rabson 521c19800e8SDoug Rabson return GSS_S_UNAVAILABLE; 522c19800e8SDoug Rabson } 523c19800e8SDoug Rabson 524c19800e8SDoug Rabson /* 525c19800e8SDoug Rabson * 526c19800e8SDoug Rabson */ 527c19800e8SDoug Rabson 528ae771770SStanislav Sedov OM_uint32 GSSAPI_CALLCONV 529ae771770SStanislav Sedov _gss_ntlm_unwrap 530c19800e8SDoug Rabson (OM_uint32 * minor_status, 531c19800e8SDoug Rabson const gss_ctx_id_t context_handle, 532c19800e8SDoug Rabson const gss_buffer_t input_message_buffer, 533c19800e8SDoug Rabson gss_buffer_t output_message_buffer, 534c19800e8SDoug Rabson int * conf_state, 535c19800e8SDoug Rabson gss_qop_t * qop_state 536c19800e8SDoug Rabson ) 537c19800e8SDoug Rabson { 538c19800e8SDoug Rabson ntlm_ctx ctx = (ntlm_ctx)context_handle; 539c19800e8SDoug Rabson OM_uint32 ret; 540c19800e8SDoug Rabson 541c19800e8SDoug Rabson *minor_status = 0; 542c19800e8SDoug Rabson output_message_buffer->value = NULL; 543c19800e8SDoug Rabson output_message_buffer->length = 0; 544ae771770SStanislav Sedov 545c19800e8SDoug Rabson if (conf_state) 546c19800e8SDoug Rabson *conf_state = 0; 547c19800e8SDoug Rabson if (qop_state) 548c19800e8SDoug Rabson *qop_state = 0; 549c19800e8SDoug Rabson 550c19800e8SDoug Rabson if (CTX_FLAGS_ISSET(ctx, NTLM_NEG_SEAL|NTLM_NEG_NTLM2_SESSION)) { 551c19800e8SDoug Rabson 552c19800e8SDoug Rabson return v2_unseal_message(input_message_buffer, 553c19800e8SDoug Rabson ctx->u.v2.recv.signkey, 554c19800e8SDoug Rabson ctx->u.v2.recv.seq++, 555c19800e8SDoug Rabson &ctx->u.v2.recv.sealkey, 556c19800e8SDoug Rabson output_message_buffer); 557c19800e8SDoug Rabson 558c19800e8SDoug Rabson } else if (CTX_FLAGS_ISSET(ctx, NTLM_NEG_SEAL)) { 559c19800e8SDoug Rabson 560c19800e8SDoug Rabson gss_buffer_desc trailer; 561c19800e8SDoug Rabson OM_uint32 junk; 562c19800e8SDoug Rabson 563c19800e8SDoug Rabson if (input_message_buffer->length < 16) 564c19800e8SDoug Rabson return GSS_S_BAD_MIC; 565c19800e8SDoug Rabson 566c19800e8SDoug Rabson output_message_buffer->length = input_message_buffer->length - 16; 567c19800e8SDoug Rabson output_message_buffer->value = malloc(output_message_buffer->length); 568c19800e8SDoug Rabson if (output_message_buffer->value == NULL) { 569c19800e8SDoug Rabson output_message_buffer->length = 0; 570c19800e8SDoug Rabson return GSS_S_FAILURE; 571c19800e8SDoug Rabson } 572c19800e8SDoug Rabson 573c19800e8SDoug Rabson RC4(&ctx->u.v1.crypto_recv.key, output_message_buffer->length, 574c19800e8SDoug Rabson input_message_buffer->value, output_message_buffer->value); 575c19800e8SDoug Rabson 576c19800e8SDoug Rabson trailer.value = ((unsigned char *)input_message_buffer->value) + 577c19800e8SDoug Rabson output_message_buffer->length; 578c19800e8SDoug Rabson trailer.length = 16; 579c19800e8SDoug Rabson 580c19800e8SDoug Rabson ret = _gss_ntlm_verify_mic(minor_status, context_handle, 581c19800e8SDoug Rabson output_message_buffer, 582c19800e8SDoug Rabson &trailer, NULL); 583c19800e8SDoug Rabson if (ret) { 584c19800e8SDoug Rabson gss_release_buffer(&junk, output_message_buffer); 585c19800e8SDoug Rabson return ret; 586c19800e8SDoug Rabson } 587c19800e8SDoug Rabson 588c19800e8SDoug Rabson return GSS_S_COMPLETE; 589c19800e8SDoug Rabson } 590c19800e8SDoug Rabson 591c19800e8SDoug Rabson return GSS_S_UNAVAILABLE; 592c19800e8SDoug Rabson } 593