17  *    may be used to endorse or promote products derived from this software
  18  *    without specific prior written permission.
  19  *
  20  * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
  21  * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
  22  * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
  23  * ARE DISCLAIMED.  IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
  24  * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
  25  * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
  26  * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
  27  * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
  28  * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
  29  * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
  30  * SUCH DAMAGE.
  31  *
  32  * $Id: smb_crypt.c,v 1.13 2005/01/26 23:50:50 lindak Exp $
  33  */
  34 
  35 /*
  36  * Copyright (c) 2009, 2010, Oracle and/or its affiliates. All rights reserved.
  37  * Copyright 2013 Nexenta Systems, Inc.  All rights reserved.
  38  */
  39 
  40 /*
  41  * NTLM support functions
  42  *
  43  * Some code from the driver: smb_smb.c, smb_crypt.c
  44  */
  45 
  46 #include <sys/errno.h>
  47 #include <sys/types.h>
  48 #include <sys/md4.h>
  49 #include <sys/md5.h>
  50 
  51 #include <ctype.h>
  52 #include <stdlib.h>
  53 #include <strings.h>
  54 
  55 #include <netsmb/smb_lib.h>
  56 
  57 #include "private.h"
 
 
 167 /*
 168  * Calculate an NTLMv1 session key (16 bytes).
 169  */
 170 static void
 171 ntlm_v1_session_key(uchar_t *ssn_key, const uchar_t *nt_hash)
 172 {
 173         MD4_CTX md4;
 174 
 175         MD4Init(&md4);
 176         MD4Update(&md4, nt_hash, NTLM_HASH_SZ);
 177         MD4Final(ssn_key, &md4);
 178 }
 179 
 180 /*
 181  * Compute both the LM(v1) response and the NTLM(v1) response,
 182  * and put them in the mbdata chains passed.  This allocates
 183  * mbuf chains in the output args, which the caller frees.
 184  */
 185 int
 186 ntlm_put_v1_responses(struct smb_ctx *ctx,
 187         struct mbdata *lm_mbp, struct mbdata *nt_mbp)
 188 {
 189         uchar_t *lmresp, *ntresp;
 190         int err;
 191 
 192         /* Get mbuf chain for the LM response. */
 193         if ((err = mb_init_sz(lm_mbp, NTLM_V1_RESP_SZ)) != 0)
 194                 return (err);
 195 
 196         /* Get mbuf chain for the NT response. */
 197         if ((err = mb_init_sz(nt_mbp, NTLM_V1_RESP_SZ)) != 0)
 198                 return (err);
 199 
 200         /*
 201          * Compute the NTLM response, derived from
 202          * the challenge and the NT hash (a.k.a ResponseKeyNT)
 203          */
 204         err = mb_fit(nt_mbp, NTLM_V1_RESP_SZ, (char **)&ntresp);
 205         if (err)
 206                 return (err);
 207         bzero(ntresp, NTLM_V1_RESP_SZ);
 
 212          * Compute the LM response, derived from
 213          * the challenge and the ASCII password.
 214          * Per. [MS-NLMP 3.3.1] if NoLmResponse,
 215          * send the NT response for both NT+LM.
 216          */
 217         err = mb_fit(lm_mbp, NTLM_V1_RESP_SZ, (char **)&lmresp);
 218         if (err)
 219                 return (err);
 220         memcpy(lmresp, ntresp, NTLM_V1_RESP_SZ);
 221         if (ctx->ct_authflags & SMB_AT_LM1) {
 222                 /* They asked to send the LM hash too. */
 223                 err = ntlm_v1_response(lmresp, ctx->ct_lmhash,
 224                     ctx->ct_srv_chal, NTLM_CHAL_SZ);
 225                 if (err)
 226                         return (err);
 227         }
 228 
 229         /*
 230          * Compute the session key
 231          */
 232         ntlm_v1_session_key(ctx->ct_ssn_key, ctx->ct_nthash);
 233 
 234         return (err);
 235 }
 236 
 237 /*
 238  * Compute both the LM(v1x) response and the NTLM(v1x) response,
 239  * and put them in the mbdata chains passed.  "v1x" here refers to
 240  * NTLMSSP_NEGOTIATE_EXTENDED_SESSIONSECURITY used with NTLMSSP,
 241  * also known by its shorter alias NTLMSSP_NEGOTIATE_NTLM2.
 242  * [MS-NLMP 3.3.1]
 243  *
 244  * This allocates mbuf chains in the output args (caller frees).
 245  */
 246 int
 247 ntlm_put_v1x_responses(struct smb_ctx *ctx,
 248         struct mbdata *lm_mbp, struct mbdata *nt_mbp)
 249 {
 250         MD5_CTX context;
 251         uchar_t challenges[2 * NTLM_CHAL_SZ];
 252         uchar_t digest[NTLM_HASH_SZ];
 253         uchar_t *lmresp, *ntresp;
 254         int err;
 255 
 256         /* Get mbuf chain for the LM response. */
 257         if ((err = mb_init_sz(lm_mbp, NTLM_V1_RESP_SZ)) != 0)
 258                 return (err);
 259 
 260         /* Get mbuf chain for the NT response. */
 261         if ((err = mb_init_sz(nt_mbp, NTLM_V1_RESP_SZ)) != 0)
 262                 return (err);
 263 
 264         /*
 265          * challenges = ConcatenationOf(ServerChallenge, ClientChallenge)
 266          */
 267         memcpy(challenges, ctx->ct_srv_chal, NTLM_CHAL_SZ);
 268         memcpy(challenges + NTLM_CHAL_SZ, ctx->ct_clnonce, NTLM_CHAL_SZ);
 
 282         err = mb_fit(nt_mbp, NTLM_V1_RESP_SZ, (char **)&ntresp);
 283         if (err)
 284                 return (err);
 285         bzero(ntresp, NTLM_V1_RESP_SZ);
 286         err = ntlm_v1_response(ntresp, ctx->ct_nthash,
 287             digest, NTLM_CHAL_SZ);
 288 
 289         /*
 290          * With "Extended Session Security", the LM response
 291          * is simply the client challenge (nonce) padded out.
 292          */
 293         err = mb_fit(lm_mbp, NTLM_V1_RESP_SZ, (char **)&lmresp);
 294         if (err)
 295                 return (err);
 296         bzero(lmresp, NTLM_V1_RESP_SZ);
 297         memcpy(lmresp, ctx->ct_clnonce, NTLM_CHAL_SZ);
 298 
 299         /*
 300          * Compute the session key
 301          */
 302         ntlm_v1_session_key(ctx->ct_ssn_key, ctx->ct_nthash);
 303 
 304         return (err);
 305 }
 306 
 307 /*
 308  * A variation on HMAC-MD5 known as HMACT64 is used by Windows systems.
 309  * The HMACT64() function is the same as the HMAC-MD5() except that
 310  * it truncates the input key to 64 bytes rather than hashing it down
 311  * to 16 bytes using the MD5() function.
 312  *
 313  * Output: digest (16-bytes)
 314  */
 315 static void
 316 HMACT64(uchar_t *digest,
 317     const uchar_t *key, size_t key_len,
 318     const uchar_t *data, size_t data_len)
 319 {
 320         MD5_CTX context;
 321         uchar_t k_ipad[64];     /* inner padding - key XORd with ipad */
 322         uchar_t k_opad[64];     /* outer padding - key XORd with opad */
 
 460  */
 461 static void
 462 ntlm_v2_session_key(uchar_t *ssn_key,
 463         const uchar_t *v2hash,
 464         const uchar_t *ntresp)
 465 {
 466 
 467         /* session key uses only 1st 16 bytes of ntresp */
 468         HMACT64(ssn_key, v2hash, NTLM_HASH_SZ, ntresp, NTLM_HASH_SZ);
 469 }
 470 
 471 
 472 /*
 473  * Compute both the LMv2 response and the NTLMv2 response,
 474  * and put them in the mbdata chains passed.  This allocates
 475  * mbuf chains in the output args, which the caller frees.
 476  * Also computes the session key.
 477  */
 478 int
 479 ntlm_put_v2_responses(struct smb_ctx *ctx, struct mbdata *ti_mbp,
 480         struct mbdata *lm_mbp, struct mbdata *nt_mbp)
 481 {
 482         uchar_t *lmresp, *ntresp;
 483         int err;
 484         char *ucuser = NULL;    /* upper-case user name */
 485         uchar_t v2hash[NTLM_HASH_SZ];
 486         struct mbuf *tim = ti_mbp->mb_top;
 487 
 488         /*
 489          * Convert the user name to upper-case, as
 490          * that's what's used when computing LMv2
 491          * and NTLMv2 responses.  Note that the
 492          * domain name is NOT upper-cased!
 493          */
 494         if (ctx->ct_user[0] == '\0')
 495                 return (EINVAL);
 496         ucuser = utf8_str_toupper(ctx->ct_user);
 497         if (ucuser == NULL)
 498                 return (ENOMEM);
 499 
 500         if ((err = mb_init(lm_mbp)) != 0)
 
 530         /*
 531          * Compute the NTLMv2 response, derived
 532          * from the server challenge and the
 533          * "target info." blob passed in.
 534          *
 535          * Again composed from two parts:
 536          *      1: 16-byte response hash
 537          *      2: "target info." blob
 538          */
 539         ntresp = mb_reserve(nt_mbp, NTLM_HASH_SZ);
 540         err = ntlm_v2_resp_hash(ntresp,
 541             v2hash, ctx->ct_srv_chal,
 542             (uchar_t *)tim->m_data, tim->m_len);
 543         if (err)
 544                 goto out;
 545         mb_put_mem(nt_mbp, tim->m_data, tim->m_len, MB_MSYSTEM);
 546 
 547         /*
 548          * Compute the session key
 549          */
 550         ntlm_v2_session_key(ctx->ct_ssn_key, v2hash, ntresp);
 551 
 552 out:
 553         if (err) {
 554                 mb_done(lm_mbp);
 555                 mb_done(nt_mbp);
 556         }
 557         free(ucuser);
 558 
 559         return (err);
 560 }
 561 
 562 /*
 563  * Helper for ntlm_build_target_info below.
 564  * Put a name in the NTLMv2 "target info." blob.
 565  */
 566 static void
 567 smb_put_blob_name(struct mbdata *mbp, char *name, int type)
 568 {
 569         uint16_t *ucs = NULL;
 570         int nlen;
 
 633                 err = mb_put_mem(mbp, names->m_data, names->m_len, MB_MSYSTEM);
 634         } else {
 635                 /* Get upper-case names. */
 636                 ucdom  = utf8_str_toupper(ctx->ct_domain);
 637                 if (ucdom == NULL) {
 638                         err = ENOMEM;
 639                         goto out;
 640                 }
 641                 smb_put_blob_name(mbp, ucdom, NAMETYPE_DOMAIN_NB);
 642                 smb_put_blob_name(mbp, NULL, NAMETYPE_EOL);
 643                 /* OK, that's the whole "target info." blob! */
 644         }
 645         err = 0;
 646 
 647 out:
 648         free(ucdom);
 649         return (err);
 650 }
 651 
 652 /*
 653  * Build the MAC key (for SMB signing)
 654  */
 655 int
 656 ntlm_build_mac_key(struct smb_ctx *ctx, struct mbdata *ntresp_mbp)
 657 {
 658         struct mbuf *m;
 659         size_t len;
 660         char *p;
 661 
 662         /*
 663          * MAC_key = concat(session_key, nt_response)
 664          */
 665         m = ntresp_mbp->mb_top;
 666         len = NTLM_HASH_SZ + m->m_len;
 667         if ((p = malloc(len)) == NULL)
 668                 return (ENOMEM);
 669         ctx->ct_mackeylen = len;
 670         ctx->ct_mackey = p;
 671         memcpy(p, ctx->ct_ssn_key, NTLM_HASH_SZ);
 672         memcpy(p + NTLM_HASH_SZ, m->m_data, m->m_len);
 673 
 674         return (0);
 675 }
 676 
 677 /*
 678  * Helper for ntlmssp_put_type3 - Build the "key exchange key"
 679  * used when we have both NTLM(v1) and NTLMSSP_NEGOTIATE_NTLM2.
 680  * HMAC_MD5(SessionBaseKey, concat(ServerChallenge, LmResponse[0..7]))
 681  */
 682 void
 683 ntlm2_kxkey(struct smb_ctx *ctx, struct mbdata *lm_mbp, uchar_t *kxkey)
 684 {
 685         uchar_t data[NTLM_HASH_SZ];
 686         uchar_t *p = mtod(lm_mbp->mb_top, uchar_t *);
 687 
 688         /* concat(ServerChallenge, LmResponse[0..7]) */
 689         memcpy(data, ctx->ct_srv_chal, NTLM_CHAL_SZ);
 690         memcpy(data + NTLM_CHAL_SZ, p, NTLM_CHAL_SZ);
 691 
 692         /* HMAC_MD5(SessionBaseKey, concat(...)) */
 693         HMACT64(kxkey, ctx->ct_ssn_key, NTLM_HASH_SZ,
 694             data, NTLM_HASH_SZ);
 695 }
 | 
 
 
  17  *    may be used to endorse or promote products derived from this software
  18  *    without specific prior written permission.
  19  *
  20  * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
  21  * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
  22  * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
  23  * ARE DISCLAIMED.  IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
  24  * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
  25  * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
  26  * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
  27  * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
  28  * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
  29  * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
  30  * SUCH DAMAGE.
  31  *
  32  * $Id: smb_crypt.c,v 1.13 2005/01/26 23:50:50 lindak Exp $
  33  */
  34 
  35 /*
  36  * Copyright (c) 2009, 2010, Oracle and/or its affiliates. All rights reserved.
  37  * Copyright 2018 Nexenta Systems, Inc.  All rights reserved.
  38  */
  39 
  40 /*
  41  * NTLM support functions
  42  *
  43  * Some code from the driver: smb_smb.c, smb_crypt.c
  44  */
  45 
  46 #include <sys/errno.h>
  47 #include <sys/types.h>
  48 #include <sys/md4.h>
  49 #include <sys/md5.h>
  50 
  51 #include <ctype.h>
  52 #include <stdlib.h>
  53 #include <strings.h>
  54 
  55 #include <netsmb/smb_lib.h>
  56 
  57 #include "private.h"
 
 
 167 /*
 168  * Calculate an NTLMv1 session key (16 bytes).
 169  */
 170 static void
 171 ntlm_v1_session_key(uchar_t *ssn_key, const uchar_t *nt_hash)
 172 {
 173         MD4_CTX md4;
 174 
 175         MD4Init(&md4);
 176         MD4Update(&md4, nt_hash, NTLM_HASH_SZ);
 177         MD4Final(ssn_key, &md4);
 178 }
 179 
 180 /*
 181  * Compute both the LM(v1) response and the NTLM(v1) response,
 182  * and put them in the mbdata chains passed.  This allocates
 183  * mbuf chains in the output args, which the caller frees.
 184  */
 185 int
 186 ntlm_put_v1_responses(struct smb_ctx *ctx,
 187         struct mbdata *lm_mbp, struct mbdata *nt_mbp,
 188         uchar_t *ssn_key)
 189 {
 190         uchar_t *lmresp, *ntresp;
 191         int err;
 192 
 193         /* Get mbuf chain for the LM response. */
 194         if ((err = mb_init_sz(lm_mbp, NTLM_V1_RESP_SZ)) != 0)
 195                 return (err);
 196 
 197         /* Get mbuf chain for the NT response. */
 198         if ((err = mb_init_sz(nt_mbp, NTLM_V1_RESP_SZ)) != 0)
 199                 return (err);
 200 
 201         /*
 202          * Compute the NTLM response, derived from
 203          * the challenge and the NT hash (a.k.a ResponseKeyNT)
 204          */
 205         err = mb_fit(nt_mbp, NTLM_V1_RESP_SZ, (char **)&ntresp);
 206         if (err)
 207                 return (err);
 208         bzero(ntresp, NTLM_V1_RESP_SZ);
 
 213          * Compute the LM response, derived from
 214          * the challenge and the ASCII password.
 215          * Per. [MS-NLMP 3.3.1] if NoLmResponse,
 216          * send the NT response for both NT+LM.
 217          */
 218         err = mb_fit(lm_mbp, NTLM_V1_RESP_SZ, (char **)&lmresp);
 219         if (err)
 220                 return (err);
 221         memcpy(lmresp, ntresp, NTLM_V1_RESP_SZ);
 222         if (ctx->ct_authflags & SMB_AT_LM1) {
 223                 /* They asked to send the LM hash too. */
 224                 err = ntlm_v1_response(lmresp, ctx->ct_lmhash,
 225                     ctx->ct_srv_chal, NTLM_CHAL_SZ);
 226                 if (err)
 227                         return (err);
 228         }
 229 
 230         /*
 231          * Compute the session key
 232          */
 233         ntlm_v1_session_key(ssn_key, ctx->ct_nthash);
 234 
 235         return (err);
 236 }
 237 
 238 /*
 239  * Compute both the LM(v1x) response and the NTLM(v1x) response,
 240  * and put them in the mbdata chains passed.  "v1x" here refers to
 241  * NTLMSSP_NEGOTIATE_EXTENDED_SESSIONSECURITY used with NTLMSSP,
 242  * also known by its shorter alias NTLMSSP_NEGOTIATE_NTLM2.
 243  * [MS-NLMP 3.3.1]
 244  *
 245  * This allocates mbuf chains in the output args (caller frees).
 246  */
 247 int
 248 ntlm_put_v1x_responses(struct smb_ctx *ctx,
 249         struct mbdata *lm_mbp, struct mbdata *nt_mbp,
 250         uchar_t *ssn_key)
 251 {
 252         MD5_CTX context;
 253         uchar_t challenges[2 * NTLM_CHAL_SZ];
 254         uchar_t digest[NTLM_HASH_SZ];
 255         uchar_t *lmresp, *ntresp;
 256         int err;
 257 
 258         /* Get mbuf chain for the LM response. */
 259         if ((err = mb_init_sz(lm_mbp, NTLM_V1_RESP_SZ)) != 0)
 260                 return (err);
 261 
 262         /* Get mbuf chain for the NT response. */
 263         if ((err = mb_init_sz(nt_mbp, NTLM_V1_RESP_SZ)) != 0)
 264                 return (err);
 265 
 266         /*
 267          * challenges = ConcatenationOf(ServerChallenge, ClientChallenge)
 268          */
 269         memcpy(challenges, ctx->ct_srv_chal, NTLM_CHAL_SZ);
 270         memcpy(challenges + NTLM_CHAL_SZ, ctx->ct_clnonce, NTLM_CHAL_SZ);
 
 284         err = mb_fit(nt_mbp, NTLM_V1_RESP_SZ, (char **)&ntresp);
 285         if (err)
 286                 return (err);
 287         bzero(ntresp, NTLM_V1_RESP_SZ);
 288         err = ntlm_v1_response(ntresp, ctx->ct_nthash,
 289             digest, NTLM_CHAL_SZ);
 290 
 291         /*
 292          * With "Extended Session Security", the LM response
 293          * is simply the client challenge (nonce) padded out.
 294          */
 295         err = mb_fit(lm_mbp, NTLM_V1_RESP_SZ, (char **)&lmresp);
 296         if (err)
 297                 return (err);
 298         bzero(lmresp, NTLM_V1_RESP_SZ);
 299         memcpy(lmresp, ctx->ct_clnonce, NTLM_CHAL_SZ);
 300 
 301         /*
 302          * Compute the session key
 303          */
 304         ntlm_v1_session_key(ssn_key, ctx->ct_nthash);
 305 
 306         return (err);
 307 }
 308 
 309 /*
 310  * A variation on HMAC-MD5 known as HMACT64 is used by Windows systems.
 311  * The HMACT64() function is the same as the HMAC-MD5() except that
 312  * it truncates the input key to 64 bytes rather than hashing it down
 313  * to 16 bytes using the MD5() function.
 314  *
 315  * Output: digest (16-bytes)
 316  */
 317 static void
 318 HMACT64(uchar_t *digest,
 319     const uchar_t *key, size_t key_len,
 320     const uchar_t *data, size_t data_len)
 321 {
 322         MD5_CTX context;
 323         uchar_t k_ipad[64];     /* inner padding - key XORd with ipad */
 324         uchar_t k_opad[64];     /* outer padding - key XORd with opad */
 
 462  */
 463 static void
 464 ntlm_v2_session_key(uchar_t *ssn_key,
 465         const uchar_t *v2hash,
 466         const uchar_t *ntresp)
 467 {
 468 
 469         /* session key uses only 1st 16 bytes of ntresp */
 470         HMACT64(ssn_key, v2hash, NTLM_HASH_SZ, ntresp, NTLM_HASH_SZ);
 471 }
 472 
 473 
 474 /*
 475  * Compute both the LMv2 response and the NTLMv2 response,
 476  * and put them in the mbdata chains passed.  This allocates
 477  * mbuf chains in the output args, which the caller frees.
 478  * Also computes the session key.
 479  */
 480 int
 481 ntlm_put_v2_responses(struct smb_ctx *ctx, struct mbdata *ti_mbp,
 482         struct mbdata *lm_mbp, struct mbdata *nt_mbp,
 483         uchar_t *ssn_key)
 484 {
 485         uchar_t *lmresp, *ntresp;
 486         int err;
 487         char *ucuser = NULL;    /* upper-case user name */
 488         uchar_t v2hash[NTLM_HASH_SZ];
 489         struct mbuf *tim = ti_mbp->mb_top;
 490 
 491         /*
 492          * Convert the user name to upper-case, as
 493          * that's what's used when computing LMv2
 494          * and NTLMv2 responses.  Note that the
 495          * domain name is NOT upper-cased!
 496          */
 497         if (ctx->ct_user[0] == '\0')
 498                 return (EINVAL);
 499         ucuser = utf8_str_toupper(ctx->ct_user);
 500         if (ucuser == NULL)
 501                 return (ENOMEM);
 502 
 503         if ((err = mb_init(lm_mbp)) != 0)
 
 533         /*
 534          * Compute the NTLMv2 response, derived
 535          * from the server challenge and the
 536          * "target info." blob passed in.
 537          *
 538          * Again composed from two parts:
 539          *      1: 16-byte response hash
 540          *      2: "target info." blob
 541          */
 542         ntresp = mb_reserve(nt_mbp, NTLM_HASH_SZ);
 543         err = ntlm_v2_resp_hash(ntresp,
 544             v2hash, ctx->ct_srv_chal,
 545             (uchar_t *)tim->m_data, tim->m_len);
 546         if (err)
 547                 goto out;
 548         mb_put_mem(nt_mbp, tim->m_data, tim->m_len, MB_MSYSTEM);
 549 
 550         /*
 551          * Compute the session key
 552          */
 553         ntlm_v2_session_key(ssn_key, v2hash, ntresp);
 554 
 555 out:
 556         if (err) {
 557                 mb_done(lm_mbp);
 558                 mb_done(nt_mbp);
 559         }
 560         free(ucuser);
 561 
 562         return (err);
 563 }
 564 
 565 /*
 566  * Helper for ntlm_build_target_info below.
 567  * Put a name in the NTLMv2 "target info." blob.
 568  */
 569 static void
 570 smb_put_blob_name(struct mbdata *mbp, char *name, int type)
 571 {
 572         uint16_t *ucs = NULL;
 573         int nlen;
 
 636                 err = mb_put_mem(mbp, names->m_data, names->m_len, MB_MSYSTEM);
 637         } else {
 638                 /* Get upper-case names. */
 639                 ucdom  = utf8_str_toupper(ctx->ct_domain);
 640                 if (ucdom == NULL) {
 641                         err = ENOMEM;
 642                         goto out;
 643                 }
 644                 smb_put_blob_name(mbp, ucdom, NAMETYPE_DOMAIN_NB);
 645                 smb_put_blob_name(mbp, NULL, NAMETYPE_EOL);
 646                 /* OK, that's the whole "target info." blob! */
 647         }
 648         err = 0;
 649 
 650 out:
 651         free(ucdom);
 652         return (err);
 653 }
 654 
 655 /*
 656  * Helper for ntlmssp_put_type3 - Build the "key exchange key"
 657  * used when we have both NTLM(v1) and NTLMSSP_NEGOTIATE_NTLM2.
 658  * HMAC_MD5(SessionBaseKey, concat(ServerChallenge, LmResponse[0..7]))
 659  */
 660 void
 661 ntlm2_kxkey(struct smb_ctx *ctx, struct mbdata *lm_mbp,
 662         uchar_t *ssn_key, uchar_t *kxkey)
 663 {
 664         uchar_t data[NTLM_HASH_SZ];
 665         uchar_t *p = mtod(lm_mbp->mb_top, uchar_t *);
 666 
 667         /* concat(ServerChallenge, LmResponse[0..7]) */
 668         memcpy(data, ctx->ct_srv_chal, NTLM_CHAL_SZ);
 669         memcpy(data + NTLM_CHAL_SZ, p, NTLM_CHAL_SZ);
 670 
 671         /* HMAC_MD5(SessionBaseKey, concat(...)) */
 672         HMACT64(kxkey, ssn_key, NTLM_HASH_SZ,
 673             data, NTLM_HASH_SZ);
 674 }
 |