1*613a2f6bSGordon Ross /* 2*613a2f6bSGordon Ross * Copyright (c) 2000-2001, Boris Popov 3*613a2f6bSGordon Ross * All rights reserved. 4*613a2f6bSGordon Ross * 5*613a2f6bSGordon Ross * Redistribution and use in source and binary forms, with or without 6*613a2f6bSGordon Ross * modification, are permitted provided that the following conditions 7*613a2f6bSGordon Ross * are met: 8*613a2f6bSGordon Ross * 1. Redistributions of source code must retain the above copyright 9*613a2f6bSGordon Ross * notice, this list of conditions and the following disclaimer. 10*613a2f6bSGordon Ross * 2. Redistributions in binary form must reproduce the above copyright 11*613a2f6bSGordon Ross * notice, this list of conditions and the following disclaimer in the 12*613a2f6bSGordon Ross * documentation and/or other materials provided with the distribution. 13*613a2f6bSGordon Ross * 3. All advertising materials mentioning features or use of this software 14*613a2f6bSGordon Ross * must display the following acknowledgement: 15*613a2f6bSGordon Ross * This product includes software developed by Boris Popov. 16*613a2f6bSGordon Ross * 4. Neither the name of the author nor the names of any co-contributors 17*613a2f6bSGordon Ross * may be used to endorse or promote products derived from this software 18*613a2f6bSGordon Ross * without specific prior written permission. 19*613a2f6bSGordon Ross * 20*613a2f6bSGordon Ross * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND 21*613a2f6bSGordon Ross * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 22*613a2f6bSGordon Ross * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE 23*613a2f6bSGordon Ross * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE 24*613a2f6bSGordon Ross * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL 25*613a2f6bSGordon Ross * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS 26*613a2f6bSGordon Ross * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) 27*613a2f6bSGordon Ross * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT 28*613a2f6bSGordon Ross * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY 29*613a2f6bSGordon Ross * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF 30*613a2f6bSGordon Ross * SUCH DAMAGE. 31*613a2f6bSGordon Ross * 32*613a2f6bSGordon Ross * $Id: smb_crypt.c,v 1.13 2005/01/26 23:50:50 lindak Exp $ 33*613a2f6bSGordon Ross */ 34*613a2f6bSGordon Ross 35*613a2f6bSGordon Ross /* 36*613a2f6bSGordon Ross * Copyright 2009 Sun Microsystems, Inc. All rights reserved. 37*613a2f6bSGordon Ross * Use is subject to license terms. 38*613a2f6bSGordon Ross */ 39*613a2f6bSGordon Ross 40*613a2f6bSGordon Ross /* 41*613a2f6bSGordon Ross * NTLM support functions 42*613a2f6bSGordon Ross * 43*613a2f6bSGordon Ross * Some code from the driver: smb_smb.c, smb_crypt.c 44*613a2f6bSGordon Ross */ 45*613a2f6bSGordon Ross 46*613a2f6bSGordon Ross #include <sys/errno.h> 47*613a2f6bSGordon Ross #include <sys/types.h> 48*613a2f6bSGordon Ross #include <sys/md4.h> 49*613a2f6bSGordon Ross #include <sys/md5.h> 50*613a2f6bSGordon Ross 51*613a2f6bSGordon Ross #include <ctype.h> 52*613a2f6bSGordon Ross #include <stdlib.h> 53*613a2f6bSGordon Ross #include <strings.h> 54*613a2f6bSGordon Ross 55*613a2f6bSGordon Ross #include <netsmb/smb_lib.h> 56*613a2f6bSGordon Ross 57*613a2f6bSGordon Ross #include "private.h" 58*613a2f6bSGordon Ross #include "charsets.h" 59*613a2f6bSGordon Ross #include "smb_crypt.h" 60*613a2f6bSGordon Ross #include "ntlm.h" 61*613a2f6bSGordon Ross 62*613a2f6bSGordon Ross 63*613a2f6bSGordon Ross /* 64*613a2f6bSGordon Ross * ntlm_compute_lm_hash 65*613a2f6bSGordon Ross * 66*613a2f6bSGordon Ross * Compute an LM hash given a password 67*613a2f6bSGordon Ross * 68*613a2f6bSGordon Ross * Output: 69*613a2f6bSGordon Ross * hash: 16-byte "LanMan" (LM) hash. 70*613a2f6bSGordon Ross * Inputs: 71*613a2f6bSGordon Ross * ucpw: User's password, upper-case UTF-8 string. 72*613a2f6bSGordon Ross * 73*613a2f6bSGordon Ross * Source: Implementing CIFS (Chris Hertel) 74*613a2f6bSGordon Ross * 75*613a2f6bSGordon Ross * P14 = UCPW padded to 14-bytes, or truncated (as needed) 76*613a2f6bSGordon Ross * result = Encrypt(Key=P14, Data=MagicString) 77*613a2f6bSGordon Ross */ 78*613a2f6bSGordon Ross int 79*613a2f6bSGordon Ross ntlm_compute_lm_hash(uchar_t *hash, const char *pass) 80*613a2f6bSGordon Ross { 81*613a2f6bSGordon Ross static const uchar_t M8[8] = "KGS!@#$%"; 82*613a2f6bSGordon Ross uchar_t P14[14 + 1]; 83*613a2f6bSGordon Ross int err; 84*613a2f6bSGordon Ross char *ucpw; 85*613a2f6bSGordon Ross 86*613a2f6bSGordon Ross /* First, convert the p/w to upper case. */ 87*613a2f6bSGordon Ross ucpw = utf8_str_toupper(pass); 88*613a2f6bSGordon Ross if (ucpw == NULL) 89*613a2f6bSGordon Ross return (ENOMEM); 90*613a2f6bSGordon Ross 91*613a2f6bSGordon Ross /* Pad or truncate the upper-case P/W as needed. */ 92*613a2f6bSGordon Ross bzero(P14, sizeof (P14)); 93*613a2f6bSGordon Ross (void) strncpy((char *)P14, ucpw, 14); 94*613a2f6bSGordon Ross 95*613a2f6bSGordon Ross /* Compute the hash. */ 96*613a2f6bSGordon Ross err = smb_encrypt_DES(hash, NTLM_HASH_SZ, 97*613a2f6bSGordon Ross P14, 14, M8, 8); 98*613a2f6bSGordon Ross 99*613a2f6bSGordon Ross free(ucpw); 100*613a2f6bSGordon Ross return (err); 101*613a2f6bSGordon Ross } 102*613a2f6bSGordon Ross 103*613a2f6bSGordon Ross /* 104*613a2f6bSGordon Ross * ntlm_compute_nt_hash 105*613a2f6bSGordon Ross * 106*613a2f6bSGordon Ross * Compute an NT hash given a password in UTF-8. 107*613a2f6bSGordon Ross * 108*613a2f6bSGordon Ross * Output: 109*613a2f6bSGordon Ross * hash: 16-byte "NT" hash. 110*613a2f6bSGordon Ross * Inputs: 111*613a2f6bSGordon Ross * upw: User's password, mixed-case UCS-2LE. 112*613a2f6bSGordon Ross * pwlen: Size (in bytes) of upw 113*613a2f6bSGordon Ross */ 114*613a2f6bSGordon Ross int 115*613a2f6bSGordon Ross ntlm_compute_nt_hash(uchar_t *hash, const char *pass) 116*613a2f6bSGordon Ross { 117*613a2f6bSGordon Ross MD4_CTX ctx; 118*613a2f6bSGordon Ross uint16_t *unipw = NULL; 119*613a2f6bSGordon Ross int pwsz; 120*613a2f6bSGordon Ross 121*613a2f6bSGordon Ross /* First, convert the password to unicode. */ 122*613a2f6bSGordon Ross unipw = convert_utf8_to_leunicode(pass); 123*613a2f6bSGordon Ross if (unipw == NULL) 124*613a2f6bSGordon Ross return (ENOMEM); 125*613a2f6bSGordon Ross pwsz = unicode_strlen(unipw) << 1; 126*613a2f6bSGordon Ross 127*613a2f6bSGordon Ross /* Compute the hash. */ 128*613a2f6bSGordon Ross MD4Init(&ctx); 129*613a2f6bSGordon Ross MD4Update(&ctx, unipw, pwsz); 130*613a2f6bSGordon Ross MD4Final(hash, &ctx); 131*613a2f6bSGordon Ross 132*613a2f6bSGordon Ross free(unipw); 133*613a2f6bSGordon Ross return (0); 134*613a2f6bSGordon Ross } 135*613a2f6bSGordon Ross 136*613a2f6bSGordon Ross /* 137*613a2f6bSGordon Ross * ntlm_v1_response 138*613a2f6bSGordon Ross * 139*613a2f6bSGordon Ross * Create an LM response from the given LM hash and challenge, 140*613a2f6bSGordon Ross * or an NTLM repsonse from a given NTLM hash and challenge. 141*613a2f6bSGordon Ross * Both response types are 24 bytes (NTLM_V1_RESP_SZ) 142*613a2f6bSGordon Ross */ 143*613a2f6bSGordon Ross static int 144*613a2f6bSGordon Ross ntlm_v1_response(uchar_t *resp, 145*613a2f6bSGordon Ross const uchar_t *hash, 146*613a2f6bSGordon Ross const uchar_t *chal, int clen) 147*613a2f6bSGordon Ross { 148*613a2f6bSGordon Ross uchar_t S21[21]; 149*613a2f6bSGordon Ross int err; 150*613a2f6bSGordon Ross 151*613a2f6bSGordon Ross /* 152*613a2f6bSGordon Ross * 14-byte LM Hash should be padded with 5 nul bytes to create 153*613a2f6bSGordon Ross * a 21-byte string to be used in producing LM response 154*613a2f6bSGordon Ross */ 155*613a2f6bSGordon Ross bzero(&S21, sizeof (S21)); 156*613a2f6bSGordon Ross bcopy(hash, S21, NTLM_HASH_SZ); 157*613a2f6bSGordon Ross 158*613a2f6bSGordon Ross /* padded LM Hash -> LM Response */ 159*613a2f6bSGordon Ross err = smb_encrypt_DES(resp, NTLM_V1_RESP_SZ, 160*613a2f6bSGordon Ross S21, 21, chal, clen); 161*613a2f6bSGordon Ross return (err); 162*613a2f6bSGordon Ross } 163*613a2f6bSGordon Ross 164*613a2f6bSGordon Ross /* 165*613a2f6bSGordon Ross * Calculate an NTLMv1 session key (16 bytes). 166*613a2f6bSGordon Ross */ 167*613a2f6bSGordon Ross static void 168*613a2f6bSGordon Ross ntlm_v1_session_key(uchar_t *ssn_key, const uchar_t *nt_hash) 169*613a2f6bSGordon Ross { 170*613a2f6bSGordon Ross MD4_CTX md4; 171*613a2f6bSGordon Ross 172*613a2f6bSGordon Ross MD4Init(&md4); 173*613a2f6bSGordon Ross MD4Update(&md4, nt_hash, NTLM_HASH_SZ); 174*613a2f6bSGordon Ross MD4Final(ssn_key, &md4); 175*613a2f6bSGordon Ross } 176*613a2f6bSGordon Ross 177*613a2f6bSGordon Ross /* 178*613a2f6bSGordon Ross * Compute both the LM(v1) response and the NTLM(v1) response, 179*613a2f6bSGordon Ross * and put them in the mbdata chains passed. This allocates 180*613a2f6bSGordon Ross * mbuf chains in the output args, which the caller frees. 181*613a2f6bSGordon Ross */ 182*613a2f6bSGordon Ross int 183*613a2f6bSGordon Ross ntlm_put_v1_responses(struct smb_ctx *ctx, 184*613a2f6bSGordon Ross struct mbdata *lm_mbp, struct mbdata *nt_mbp) 185*613a2f6bSGordon Ross { 186*613a2f6bSGordon Ross uchar_t *lmresp, *ntresp; 187*613a2f6bSGordon Ross int err; 188*613a2f6bSGordon Ross 189*613a2f6bSGordon Ross /* Get mbuf chain for the LM response. */ 190*613a2f6bSGordon Ross if ((err = mb_init(lm_mbp, NTLM_V1_RESP_SZ)) != 0) 191*613a2f6bSGordon Ross return (err); 192*613a2f6bSGordon Ross 193*613a2f6bSGordon Ross /* Get mbuf chain for the NT response. */ 194*613a2f6bSGordon Ross if ((err = mb_init(nt_mbp, NTLM_V1_RESP_SZ)) != 0) 195*613a2f6bSGordon Ross return (err); 196*613a2f6bSGordon Ross 197*613a2f6bSGordon Ross /* 198*613a2f6bSGordon Ross * Compute the LM response, derived 199*613a2f6bSGordon Ross * from the challenge and the ASCII 200*613a2f6bSGordon Ross * password (if authflags allow). 201*613a2f6bSGordon Ross */ 202*613a2f6bSGordon Ross mb_fit(lm_mbp, NTLM_V1_RESP_SZ, (char **)&lmresp); 203*613a2f6bSGordon Ross bzero(lmresp, NTLM_V1_RESP_SZ); 204*613a2f6bSGordon Ross if (ctx->ct_authflags & SMB_AT_LM1) { 205*613a2f6bSGordon Ross /* They asked to send the LM hash too. */ 206*613a2f6bSGordon Ross err = ntlm_v1_response(lmresp, ctx->ct_lmhash, 207*613a2f6bSGordon Ross ctx->ct_ntlm_chal, NTLM_CHAL_SZ); 208*613a2f6bSGordon Ross if (err) 209*613a2f6bSGordon Ross return (err); 210*613a2f6bSGordon Ross } 211*613a2f6bSGordon Ross 212*613a2f6bSGordon Ross /* 213*613a2f6bSGordon Ross * Compute the NTLM response, derived from 214*613a2f6bSGordon Ross * the challenge and the NT hash. 215*613a2f6bSGordon Ross */ 216*613a2f6bSGordon Ross mb_fit(nt_mbp, NTLM_V1_RESP_SZ, (char **)&ntresp); 217*613a2f6bSGordon Ross bzero(ntresp, NTLM_V1_RESP_SZ); 218*613a2f6bSGordon Ross err = ntlm_v1_response(ntresp, ctx->ct_nthash, 219*613a2f6bSGordon Ross ctx->ct_ntlm_chal, NTLM_CHAL_SZ); 220*613a2f6bSGordon Ross 221*613a2f6bSGordon Ross /* 222*613a2f6bSGordon Ross * Compute the session key 223*613a2f6bSGordon Ross */ 224*613a2f6bSGordon Ross ntlm_v1_session_key(ctx->ct_ssn_key, ctx->ct_nthash); 225*613a2f6bSGordon Ross 226*613a2f6bSGordon Ross return (err); 227*613a2f6bSGordon Ross } 228*613a2f6bSGordon Ross 229*613a2f6bSGordon Ross /* 230*613a2f6bSGordon Ross * A variation on HMAC-MD5 known as HMACT64 is used by Windows systems. 231*613a2f6bSGordon Ross * The HMACT64() function is the same as the HMAC-MD5() except that 232*613a2f6bSGordon Ross * it truncates the input key to 64 bytes rather than hashing it down 233*613a2f6bSGordon Ross * to 16 bytes using the MD5() function. 234*613a2f6bSGordon Ross * 235*613a2f6bSGordon Ross * Output: digest (16-bytes) 236*613a2f6bSGordon Ross */ 237*613a2f6bSGordon Ross static void 238*613a2f6bSGordon Ross HMACT64(uchar_t *digest, 239*613a2f6bSGordon Ross const uchar_t *key, size_t key_len, 240*613a2f6bSGordon Ross const uchar_t *data, size_t data_len) 241*613a2f6bSGordon Ross { 242*613a2f6bSGordon Ross MD5_CTX context; 243*613a2f6bSGordon Ross uchar_t k_ipad[64]; /* inner padding - key XORd with ipad */ 244*613a2f6bSGordon Ross uchar_t k_opad[64]; /* outer padding - key XORd with opad */ 245*613a2f6bSGordon Ross int i; 246*613a2f6bSGordon Ross 247*613a2f6bSGordon Ross /* if key is longer than 64 bytes use only the first 64 bytes */ 248*613a2f6bSGordon Ross if (key_len > 64) 249*613a2f6bSGordon Ross key_len = 64; 250*613a2f6bSGordon Ross 251*613a2f6bSGordon Ross /* 252*613a2f6bSGordon Ross * The HMAC-MD5 (and HMACT64) transform looks like: 253*613a2f6bSGordon Ross * 254*613a2f6bSGordon Ross * MD5(K XOR opad, MD5(K XOR ipad, data)) 255*613a2f6bSGordon Ross * 256*613a2f6bSGordon Ross * where K is an n byte key 257*613a2f6bSGordon Ross * ipad is the byte 0x36 repeated 64 times 258*613a2f6bSGordon Ross * opad is the byte 0x5c repeated 64 times 259*613a2f6bSGordon Ross * and data is the data being protected. 260*613a2f6bSGordon Ross */ 261*613a2f6bSGordon Ross 262*613a2f6bSGordon Ross /* start out by storing key in pads */ 263*613a2f6bSGordon Ross bzero(k_ipad, sizeof (k_ipad)); 264*613a2f6bSGordon Ross bzero(k_opad, sizeof (k_opad)); 265*613a2f6bSGordon Ross bcopy(key, k_ipad, key_len); 266*613a2f6bSGordon Ross bcopy(key, k_opad, key_len); 267*613a2f6bSGordon Ross 268*613a2f6bSGordon Ross /* XOR key with ipad and opad values */ 269*613a2f6bSGordon Ross for (i = 0; i < 64; i++) { 270*613a2f6bSGordon Ross k_ipad[i] ^= 0x36; 271*613a2f6bSGordon Ross k_opad[i] ^= 0x5c; 272*613a2f6bSGordon Ross } 273*613a2f6bSGordon Ross 274*613a2f6bSGordon Ross /* 275*613a2f6bSGordon Ross * perform inner MD5 276*613a2f6bSGordon Ross */ 277*613a2f6bSGordon Ross MD5Init(&context); /* init context for 1st pass */ 278*613a2f6bSGordon Ross MD5Update(&context, k_ipad, 64); /* start with inner pad */ 279*613a2f6bSGordon Ross MD5Update(&context, data, data_len); /* then data of datagram */ 280*613a2f6bSGordon Ross MD5Final(digest, &context); /* finish up 1st pass */ 281*613a2f6bSGordon Ross 282*613a2f6bSGordon Ross /* 283*613a2f6bSGordon Ross * perform outer MD5 284*613a2f6bSGordon Ross */ 285*613a2f6bSGordon Ross MD5Init(&context); /* init context for 2nd pass */ 286*613a2f6bSGordon Ross MD5Update(&context, k_opad, 64); /* start with outer pad */ 287*613a2f6bSGordon Ross MD5Update(&context, digest, 16); /* then results of 1st hash */ 288*613a2f6bSGordon Ross MD5Final(digest, &context); /* finish up 2nd pass */ 289*613a2f6bSGordon Ross } 290*613a2f6bSGordon Ross 291*613a2f6bSGordon Ross 292*613a2f6bSGordon Ross /* 293*613a2f6bSGordon Ross * Compute an NTLMv2 hash given the NTLMv1 hash, the user name, 294*613a2f6bSGordon Ross * and the destination (machine or domain name). 295*613a2f6bSGordon Ross * 296*613a2f6bSGordon Ross * Output: 297*613a2f6bSGordon Ross * v2hash: 16-byte NTLMv2 hash. 298*613a2f6bSGordon Ross * Inputs: 299*613a2f6bSGordon Ross * v1hash: 16-byte NTLMv1 hash. 300*613a2f6bSGordon Ross * user: User name, UPPER-case UTF-8 string. 301*613a2f6bSGordon Ross * destination: Domain or server, MIXED-case UTF-8 string. 302*613a2f6bSGordon Ross */ 303*613a2f6bSGordon Ross static int 304*613a2f6bSGordon Ross ntlm_v2_hash(uchar_t *v2hash, const uchar_t *v1hash, 305*613a2f6bSGordon Ross const char *user, const char *destination) 306*613a2f6bSGordon Ross { 307*613a2f6bSGordon Ross int ulen, dlen; 308*613a2f6bSGordon Ross size_t ucs2len; 309*613a2f6bSGordon Ross uint16_t *ucs2data = NULL; 310*613a2f6bSGordon Ross char *utf8data = NULL; 311*613a2f6bSGordon Ross int err = ENOMEM; 312*613a2f6bSGordon Ross 313*613a2f6bSGordon Ross /* 314*613a2f6bSGordon Ross * v2hash = HMACT64(v1hash, 16, concat(upcase(user), dest)) 315*613a2f6bSGordon Ross * where "dest" is the domain or server name ("target name") 316*613a2f6bSGordon Ross * Note: user name is converted to upper-case by the caller. 317*613a2f6bSGordon Ross */ 318*613a2f6bSGordon Ross 319*613a2f6bSGordon Ross /* utf8data = concat(user, dest) */ 320*613a2f6bSGordon Ross ulen = strlen(user); 321*613a2f6bSGordon Ross dlen = strlen(destination); 322*613a2f6bSGordon Ross utf8data = malloc(ulen + dlen + 1); 323*613a2f6bSGordon Ross if (utf8data == NULL) 324*613a2f6bSGordon Ross goto out; 325*613a2f6bSGordon Ross bcopy(user, utf8data, ulen); 326*613a2f6bSGordon Ross bcopy(destination, utf8data + ulen, dlen + 1); 327*613a2f6bSGordon Ross 328*613a2f6bSGordon Ross /* Convert to UCS-2LE */ 329*613a2f6bSGordon Ross ucs2data = convert_utf8_to_leunicode(utf8data); 330*613a2f6bSGordon Ross if (ucs2data == NULL) 331*613a2f6bSGordon Ross goto out; 332*613a2f6bSGordon Ross ucs2len = 2 * unicode_strlen(ucs2data); 333*613a2f6bSGordon Ross 334*613a2f6bSGordon Ross HMACT64(v2hash, v1hash, NTLM_HASH_SZ, 335*613a2f6bSGordon Ross (uchar_t *)ucs2data, ucs2len); 336*613a2f6bSGordon Ross err = 0; 337*613a2f6bSGordon Ross out: 338*613a2f6bSGordon Ross if (ucs2data) 339*613a2f6bSGordon Ross free(ucs2data); 340*613a2f6bSGordon Ross if (utf8data) 341*613a2f6bSGordon Ross free(utf8data); 342*613a2f6bSGordon Ross return (err); 343*613a2f6bSGordon Ross } 344*613a2f6bSGordon Ross 345*613a2f6bSGordon Ross /* 346*613a2f6bSGordon Ross * Compute a partial LMv2 or NTLMv2 response (first 16-bytes). 347*613a2f6bSGordon Ross * The full response is composed by the caller by 348*613a2f6bSGordon Ross * appending the client_data to the returned hash. 349*613a2f6bSGordon Ross * 350*613a2f6bSGordon Ross * Output: 351*613a2f6bSGordon Ross * rhash: _partial_ LMv2/NTLMv2 response (first 16-bytes) 352*613a2f6bSGordon Ross * Inputs: 353*613a2f6bSGordon Ross * v2hash: 16-byte NTLMv2 hash. 354*613a2f6bSGordon Ross * C8: Challenge from server (8 bytes) 355*613a2f6bSGordon Ross * client_data: client nonce (for LMv2) or the 356*613a2f6bSGordon Ross * "blob" from ntlm_build_target_info (NTLMv2) 357*613a2f6bSGordon Ross */ 358*613a2f6bSGordon Ross static int 359*613a2f6bSGordon Ross ntlm_v2_resp_hash(uchar_t *rhash, 360*613a2f6bSGordon Ross const uchar_t *v2hash, const uchar_t *C8, 361*613a2f6bSGordon Ross const uchar_t *client_data, size_t cdlen) 362*613a2f6bSGordon Ross { 363*613a2f6bSGordon Ross size_t dlen; 364*613a2f6bSGordon Ross uchar_t *data = NULL; 365*613a2f6bSGordon Ross 366*613a2f6bSGordon Ross /* data = concat(C8, client_data) */ 367*613a2f6bSGordon Ross dlen = 8 + cdlen; 368*613a2f6bSGordon Ross data = malloc(dlen); 369*613a2f6bSGordon Ross if (data == NULL) 370*613a2f6bSGordon Ross return (ENOMEM); 371*613a2f6bSGordon Ross bcopy(C8, data, 8); 372*613a2f6bSGordon Ross bcopy(client_data, data + 8, cdlen); 373*613a2f6bSGordon Ross 374*613a2f6bSGordon Ross HMACT64(rhash, v2hash, NTLM_HASH_SZ, data, dlen); 375*613a2f6bSGordon Ross 376*613a2f6bSGordon Ross free(data); 377*613a2f6bSGordon Ross return (0); 378*613a2f6bSGordon Ross } 379*613a2f6bSGordon Ross 380*613a2f6bSGordon Ross /* 381*613a2f6bSGordon Ross * Calculate an NTLMv2 session key (16 bytes). 382*613a2f6bSGordon Ross */ 383*613a2f6bSGordon Ross static void 384*613a2f6bSGordon Ross ntlm_v2_session_key(uchar_t *ssn_key, 385*613a2f6bSGordon Ross const uchar_t *v2hash, 386*613a2f6bSGordon Ross const uchar_t *ntresp) 387*613a2f6bSGordon Ross { 388*613a2f6bSGordon Ross 389*613a2f6bSGordon Ross /* session key uses only 1st 16 bytes of ntresp */ 390*613a2f6bSGordon Ross HMACT64(ssn_key, v2hash, NTLM_HASH_SZ, ntresp, NTLM_HASH_SZ); 391*613a2f6bSGordon Ross } 392*613a2f6bSGordon Ross 393*613a2f6bSGordon Ross 394*613a2f6bSGordon Ross /* 395*613a2f6bSGordon Ross * Compute both the LMv2 response and the NTLMv2 response, 396*613a2f6bSGordon Ross * and put them in the mbdata chains passed. This allocates 397*613a2f6bSGordon Ross * mbuf chains in the output args, which the caller frees. 398*613a2f6bSGordon Ross * Also computes the session key. 399*613a2f6bSGordon Ross */ 400*613a2f6bSGordon Ross int 401*613a2f6bSGordon Ross ntlm_put_v2_responses(struct smb_ctx *ctx, struct mbdata *ti_mbp, 402*613a2f6bSGordon Ross struct mbdata *lm_mbp, struct mbdata *nt_mbp) 403*613a2f6bSGordon Ross { 404*613a2f6bSGordon Ross uchar_t *lmresp, *ntresp; 405*613a2f6bSGordon Ross int err; 406*613a2f6bSGordon Ross char *ucdom = NULL; /* user's domain */ 407*613a2f6bSGordon Ross char *ucuser = NULL; /* account name */ 408*613a2f6bSGordon Ross uchar_t v2hash[NTLM_HASH_SZ]; 409*613a2f6bSGordon Ross struct mbuf *tim = ti_mbp->mb_top; 410*613a2f6bSGordon Ross 411*613a2f6bSGordon Ross if ((err = mb_init(lm_mbp, M_MINSIZE)) != 0) 412*613a2f6bSGordon Ross return (err); 413*613a2f6bSGordon Ross if ((err = mb_init(nt_mbp, M_MINSIZE)) != 0) 414*613a2f6bSGordon Ross return (err); 415*613a2f6bSGordon Ross 416*613a2f6bSGordon Ross /* 417*613a2f6bSGordon Ross * Convert the user name to upper-case, as 418*613a2f6bSGordon Ross * that's what's used when computing LMv2 419*613a2f6bSGordon Ross * and NTLMv2 responses. Also the domain. 420*613a2f6bSGordon Ross */ 421*613a2f6bSGordon Ross ucdom = utf8_str_toupper(ctx->ct_domain); 422*613a2f6bSGordon Ross ucuser = utf8_str_toupper(ctx->ct_user); 423*613a2f6bSGordon Ross if (ucdom == NULL || ucuser == NULL) { 424*613a2f6bSGordon Ross err = ENOMEM; 425*613a2f6bSGordon Ross goto out; 426*613a2f6bSGordon Ross } 427*613a2f6bSGordon Ross 428*613a2f6bSGordon Ross /* 429*613a2f6bSGordon Ross * Compute the NTLMv2 hash (see above) 430*613a2f6bSGordon Ross * Needs upper-case user, domain. 431*613a2f6bSGordon Ross */ 432*613a2f6bSGordon Ross err = ntlm_v2_hash(v2hash, ctx->ct_nthash, ucuser, ucdom); 433*613a2f6bSGordon Ross if (err) 434*613a2f6bSGordon Ross goto out; 435*613a2f6bSGordon Ross 436*613a2f6bSGordon Ross /* 437*613a2f6bSGordon Ross * Compute the LMv2 response, derived from 438*613a2f6bSGordon Ross * the v2hash, the server challenge, and 439*613a2f6bSGordon Ross * the client nonce (random bits). 440*613a2f6bSGordon Ross * 441*613a2f6bSGordon Ross * We compose it from two parts: 442*613a2f6bSGordon Ross * 1: 16-byte response hash 443*613a2f6bSGordon Ross * 2: Client nonce 444*613a2f6bSGordon Ross */ 445*613a2f6bSGordon Ross lmresp = (uchar_t *)lm_mbp->mb_pos; 446*613a2f6bSGordon Ross mb_put_mem(lm_mbp, NULL, NTLM_HASH_SZ); 447*613a2f6bSGordon Ross err = ntlm_v2_resp_hash(lmresp, 448*613a2f6bSGordon Ross v2hash, ctx->ct_ntlm_chal, 449*613a2f6bSGordon Ross ctx->ct_clnonce, NTLM_CHAL_SZ); 450*613a2f6bSGordon Ross if (err) 451*613a2f6bSGordon Ross goto out; 452*613a2f6bSGordon Ross mb_put_mem(lm_mbp, ctx->ct_clnonce, NTLM_CHAL_SZ); 453*613a2f6bSGordon Ross 454*613a2f6bSGordon Ross /* 455*613a2f6bSGordon Ross * Compute the NTLMv2 response, derived 456*613a2f6bSGordon Ross * from the server challenge and the 457*613a2f6bSGordon Ross * "target info." blob passed in. 458*613a2f6bSGordon Ross * 459*613a2f6bSGordon Ross * Again composed from two parts: 460*613a2f6bSGordon Ross * 1: 16-byte response hash 461*613a2f6bSGordon Ross * 2: "target info." blob 462*613a2f6bSGordon Ross */ 463*613a2f6bSGordon Ross ntresp = (uchar_t *)nt_mbp->mb_pos; 464*613a2f6bSGordon Ross mb_put_mem(nt_mbp, NULL, NTLM_HASH_SZ); 465*613a2f6bSGordon Ross err = ntlm_v2_resp_hash(ntresp, 466*613a2f6bSGordon Ross v2hash, ctx->ct_ntlm_chal, 467*613a2f6bSGordon Ross (uchar_t *)tim->m_data, tim->m_len); 468*613a2f6bSGordon Ross if (err) 469*613a2f6bSGordon Ross goto out; 470*613a2f6bSGordon Ross mb_put_mem(nt_mbp, tim->m_data, tim->m_len); 471*613a2f6bSGordon Ross 472*613a2f6bSGordon Ross /* 473*613a2f6bSGordon Ross * Compute the session key 474*613a2f6bSGordon Ross */ 475*613a2f6bSGordon Ross ntlm_v2_session_key(ctx->ct_ssn_key, v2hash, ntresp); 476*613a2f6bSGordon Ross 477*613a2f6bSGordon Ross out: 478*613a2f6bSGordon Ross if (err) { 479*613a2f6bSGordon Ross mb_done(lm_mbp); 480*613a2f6bSGordon Ross mb_done(nt_mbp); 481*613a2f6bSGordon Ross } 482*613a2f6bSGordon Ross free(ucdom); 483*613a2f6bSGordon Ross free(ucuser); 484*613a2f6bSGordon Ross 485*613a2f6bSGordon Ross return (err); 486*613a2f6bSGordon Ross } 487*613a2f6bSGordon Ross 488*613a2f6bSGordon Ross /* 489*613a2f6bSGordon Ross * Helper for ntlm_build_target_info below. 490*613a2f6bSGordon Ross * Put a name in the NTLMv2 "target info." blob. 491*613a2f6bSGordon Ross */ 492*613a2f6bSGordon Ross static void 493*613a2f6bSGordon Ross smb_put_blob_name(struct mbdata *mbp, char *name, int type) 494*613a2f6bSGordon Ross { 495*613a2f6bSGordon Ross uint16_t *ucs = NULL; 496*613a2f6bSGordon Ross int nlen; 497*613a2f6bSGordon Ross 498*613a2f6bSGordon Ross if (name) 499*613a2f6bSGordon Ross ucs = convert_utf8_to_leunicode(name); 500*613a2f6bSGordon Ross if (ucs) 501*613a2f6bSGordon Ross nlen = unicode_strlen(ucs); 502*613a2f6bSGordon Ross else 503*613a2f6bSGordon Ross nlen = 0; 504*613a2f6bSGordon Ross 505*613a2f6bSGordon Ross nlen <<= 1; /* length in bytes, without null. */ 506*613a2f6bSGordon Ross 507*613a2f6bSGordon Ross mb_put_uint16le(mbp, type); 508*613a2f6bSGordon Ross mb_put_uint16le(mbp, nlen); 509*613a2f6bSGordon Ross mb_put_mem(mbp, (char *)ucs, nlen); 510*613a2f6bSGordon Ross 511*613a2f6bSGordon Ross if (ucs) 512*613a2f6bSGordon Ross free(ucs); 513*613a2f6bSGordon Ross } 514*613a2f6bSGordon Ross 515*613a2f6bSGordon Ross /* 516*613a2f6bSGordon Ross * Build an NTLMv2 "target info." blob. When called from NTLMSSP, 517*613a2f6bSGordon Ross * the list of names comes from the Type 2 message. Otherwise, 518*613a2f6bSGordon Ross * we create the name list here. 519*613a2f6bSGordon Ross */ 520*613a2f6bSGordon Ross int 521*613a2f6bSGordon Ross ntlm_build_target_info(struct smb_ctx *ctx, struct mbuf *names, 522*613a2f6bSGordon Ross struct mbdata *mbp) 523*613a2f6bSGordon Ross { 524*613a2f6bSGordon Ross struct timeval now; 525*613a2f6bSGordon Ross uint64_t nt_time; 526*613a2f6bSGordon Ross 527*613a2f6bSGordon Ross char *ucdom = NULL; /* user's domain */ 528*613a2f6bSGordon Ross int err; 529*613a2f6bSGordon Ross 530*613a2f6bSGordon Ross /* Get mbuf chain for the "target info". */ 531*613a2f6bSGordon Ross if ((err = mb_init(mbp, M_MINSIZE)) != 0) 532*613a2f6bSGordon Ross return (err); 533*613a2f6bSGordon Ross 534*613a2f6bSGordon Ross /* 535*613a2f6bSGordon Ross * Construct the client nonce by getting 536*613a2f6bSGordon Ross * some random data from /dev/urandom 537*613a2f6bSGordon Ross */ 538*613a2f6bSGordon Ross err = smb_get_urandom(ctx->ct_clnonce, NTLM_CHAL_SZ); 539*613a2f6bSGordon Ross if (err) 540*613a2f6bSGordon Ross goto out; 541*613a2f6bSGordon Ross 542*613a2f6bSGordon Ross /* 543*613a2f6bSGordon Ross * Get the "NT time" for the target info header. 544*613a2f6bSGordon Ross */ 545*613a2f6bSGordon Ross (void) gettimeofday(&now, 0); 546*613a2f6bSGordon Ross smb_time_local2NT(&now, 0, &nt_time); 547*613a2f6bSGordon Ross 548*613a2f6bSGordon Ross /* 549*613a2f6bSGordon Ross * Build the "target info." block. 550*613a2f6bSGordon Ross * 551*613a2f6bSGordon Ross * Based on information at: 552*613a2f6bSGordon Ross * http://davenport.sourceforge.net/ntlm.html#theNtlmv2Response 553*613a2f6bSGordon Ross * 554*613a2f6bSGordon Ross * First the fixed-size part. 555*613a2f6bSGordon Ross */ 556*613a2f6bSGordon Ross mb_put_uint32le(mbp, 0x101); /* Blob signature */ 557*613a2f6bSGordon Ross mb_put_uint32le(mbp, 0); /* reserved */ 558*613a2f6bSGordon Ross mb_put_uint64le(mbp, nt_time); /* NT time stamp */ 559*613a2f6bSGordon Ross mb_put_mem(mbp, ctx->ct_clnonce, NTLM_CHAL_SZ); 560*613a2f6bSGordon Ross mb_put_uint32le(mbp, 0); /* unknown */ 561*613a2f6bSGordon Ross 562*613a2f6bSGordon Ross /* 563*613a2f6bSGordon Ross * Now put the list of names, either from the 564*613a2f6bSGordon Ross * NTLMSSP Type 2 message or composed here. 565*613a2f6bSGordon Ross */ 566*613a2f6bSGordon Ross if (names) { 567*613a2f6bSGordon Ross err = mb_put_mem(mbp, names->m_data, names->m_len); 568*613a2f6bSGordon Ross } else { 569*613a2f6bSGordon Ross /* Get upper-case names. */ 570*613a2f6bSGordon Ross ucdom = utf8_str_toupper(ctx->ct_domain); 571*613a2f6bSGordon Ross if (ucdom == NULL) { 572*613a2f6bSGordon Ross err = ENOMEM; 573*613a2f6bSGordon Ross goto out; 574*613a2f6bSGordon Ross } 575*613a2f6bSGordon Ross smb_put_blob_name(mbp, ucdom, NAMETYPE_DOMAIN_NB); 576*613a2f6bSGordon Ross smb_put_blob_name(mbp, NULL, NAMETYPE_EOL); 577*613a2f6bSGordon Ross /* OK, that's the whole "target info." blob! */ 578*613a2f6bSGordon Ross } 579*613a2f6bSGordon Ross err = 0; 580*613a2f6bSGordon Ross 581*613a2f6bSGordon Ross out: 582*613a2f6bSGordon Ross free(ucdom); 583*613a2f6bSGordon Ross return (err); 584*613a2f6bSGordon Ross } 585