1613a2f6bSGordon Ross /* 2613a2f6bSGordon Ross * CDDL HEADER START 3613a2f6bSGordon Ross * 4613a2f6bSGordon Ross * The contents of this file are subject to the terms of the 5613a2f6bSGordon Ross * Common Development and Distribution License (the "License"). 6613a2f6bSGordon Ross * You may not use this file except in compliance with the License. 7613a2f6bSGordon Ross * 8613a2f6bSGordon Ross * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE 9613a2f6bSGordon Ross * or http://www.opensolaris.org/os/licensing. 10613a2f6bSGordon Ross * See the License for the specific language governing permissions 11613a2f6bSGordon Ross * and limitations under the License. 12613a2f6bSGordon Ross * 13613a2f6bSGordon Ross * When distributing Covered Code, include this CDDL HEADER in each 14613a2f6bSGordon Ross * file and include the License file at usr/src/OPENSOLARIS.LICENSE. 15613a2f6bSGordon Ross * If applicable, add the following below this CDDL HEADER, with the 16613a2f6bSGordon Ross * fields enclosed by brackets "[]" replaced with your own identifying 17613a2f6bSGordon Ross * information: Portions Copyright [yyyy] [name of copyright owner] 18613a2f6bSGordon Ross * 19613a2f6bSGordon Ross * CDDL HEADER END 20613a2f6bSGordon Ross */ 21613a2f6bSGordon Ross 22613a2f6bSGordon Ross /* 2315359501SGordon Ross * Copyright (c) 2009, 2010, Oracle and/or its affiliates. All rights reserved. 24*85e6b674SGordon Ross * Copyright 2013 Nexenta Systems, Inc. All rights reserved. 25613a2f6bSGordon Ross */ 26613a2f6bSGordon Ross 27613a2f6bSGordon Ross /* 28613a2f6bSGordon Ross * NT Lan Manager Security Support Provider (NTLMSSP) 29613a2f6bSGordon Ross * 30613a2f6bSGordon Ross * Based on information from the "Davenport NTLM" page: 31613a2f6bSGordon Ross * http://davenport.sourceforge.net/ntlm.html 32613a2f6bSGordon Ross */ 33613a2f6bSGordon Ross 34613a2f6bSGordon Ross 35613a2f6bSGordon Ross #include <errno.h> 36613a2f6bSGordon Ross #include <stdio.h> 37613a2f6bSGordon Ross #include <stddef.h> 38613a2f6bSGordon Ross #include <stdlib.h> 39613a2f6bSGordon Ross #include <unistd.h> 40613a2f6bSGordon Ross #include <strings.h> 41613a2f6bSGordon Ross #include <netdb.h> 42613a2f6bSGordon Ross #include <libintl.h> 43613a2f6bSGordon Ross #include <xti.h> 44613a2f6bSGordon Ross #include <assert.h> 45613a2f6bSGordon Ross 46613a2f6bSGordon Ross #include <sys/types.h> 47613a2f6bSGordon Ross #include <sys/time.h> 48613a2f6bSGordon Ross #include <sys/byteorder.h> 49613a2f6bSGordon Ross #include <sys/socket.h> 50613a2f6bSGordon Ross #include <sys/fcntl.h> 51613a2f6bSGordon Ross 52613a2f6bSGordon Ross #include <netinet/in.h> 53613a2f6bSGordon Ross #include <netinet/tcp.h> 54613a2f6bSGordon Ross #include <arpa/inet.h> 55613a2f6bSGordon Ross 56613a2f6bSGordon Ross #include <netsmb/smb.h> 57613a2f6bSGordon Ross #include <netsmb/smb_lib.h> 58613a2f6bSGordon Ross #include <netsmb/mchain.h> 59613a2f6bSGordon Ross 60613a2f6bSGordon Ross #include "private.h" 61613a2f6bSGordon Ross #include "charsets.h" 62*85e6b674SGordon Ross #include "smb_crypt.h" 63613a2f6bSGordon Ross #include "spnego.h" 64613a2f6bSGordon Ross #include "derparse.h" 65613a2f6bSGordon Ross #include "ssp.h" 66613a2f6bSGordon Ross #include "ntlm.h" 67613a2f6bSGordon Ross #include "ntlmssp.h" 68613a2f6bSGordon Ross 69*85e6b674SGordon Ross /* A shorter alias for a crazy long name from [MS-NLMP] */ 70*85e6b674SGordon Ross #define NTLMSSP_NEGOTIATE_NTLM2 \ 71*85e6b674SGordon Ross NTLMSSP_NEGOTIATE_EXTENDED_SESSIONSECURITY 72*85e6b674SGordon Ross 73613a2f6bSGordon Ross typedef struct ntlmssp_state { 74613a2f6bSGordon Ross uint32_t ss_flags; 75*85e6b674SGordon Ross char *ss_target_name; /* Primary domain or server name */ 76613a2f6bSGordon Ross struct mbuf *ss_target_info; 77*85e6b674SGordon Ross uchar_t ss_kxkey[NTLM_HASH_SZ]; 78613a2f6bSGordon Ross } ntlmssp_state_t; 79613a2f6bSGordon Ross 80613a2f6bSGordon Ross /* 81613a2f6bSGordon Ross * So called "security buffer". 82613a2f6bSGordon Ross * A lot like an RPC string. 83613a2f6bSGordon Ross */ 84613a2f6bSGordon Ross struct sec_buf { 85613a2f6bSGordon Ross uint16_t sb_length; 86613a2f6bSGordon Ross uint16_t sb_maxlen; 87613a2f6bSGordon Ross uint32_t sb_offset; 88613a2f6bSGordon Ross }; 89613a2f6bSGordon Ross #define ID_SZ 8 90613a2f6bSGordon Ross static const char ntlmssp_id[ID_SZ] = "NTLMSSP"; 91613a2f6bSGordon Ross 92*85e6b674SGordon Ross static int 93*85e6b674SGordon Ross ntlm_rand_ssn_key(struct smb_ctx *ctx, 94*85e6b674SGordon Ross ntlmssp_state_t *ssp_st, struct mbdata *ek_mbp); 95*85e6b674SGordon Ross 96613a2f6bSGordon Ross /* 97613a2f6bSGordon Ross * Get a "security buffer" (header part) 98613a2f6bSGordon Ross */ 99613a2f6bSGordon Ross static int 10002d09e03SGordon Ross md_get_sb_hdr(struct mbdata *mbp, struct sec_buf *sb) 101613a2f6bSGordon Ross { 102613a2f6bSGordon Ross int err; 103613a2f6bSGordon Ross 10402d09e03SGordon Ross (void) md_get_uint16le(mbp, &sb->sb_length); 10502d09e03SGordon Ross (void) md_get_uint16le(mbp, &sb->sb_maxlen); 10602d09e03SGordon Ross err = md_get_uint32le(mbp, &sb->sb_offset); 107613a2f6bSGordon Ross 108613a2f6bSGordon Ross return (err); 109613a2f6bSGordon Ross } 110613a2f6bSGordon Ross 111613a2f6bSGordon Ross /* 112613a2f6bSGordon Ross * Get a "security buffer" (data part), where 113613a2f6bSGordon Ross * the data is delivered as an mbuf. 114613a2f6bSGordon Ross */ 115613a2f6bSGordon Ross static int 11602d09e03SGordon Ross md_get_sb_data(struct mbdata *mbp, struct sec_buf *sb, struct mbuf **mp) 117613a2f6bSGordon Ross { 118613a2f6bSGordon Ross struct mbdata tmp_mb; 119613a2f6bSGordon Ross int err; 120613a2f6bSGordon Ross 121613a2f6bSGordon Ross /* 122613a2f6bSGordon Ross * Setup tmp_mb to point to the start of the header. 123613a2f6bSGordon Ross * This is a dup ref - do NOT free it. 124613a2f6bSGordon Ross */ 125613a2f6bSGordon Ross mb_initm(&tmp_mb, mbp->mb_top); 126613a2f6bSGordon Ross 127613a2f6bSGordon Ross /* Skip data up to the offset. */ 12802d09e03SGordon Ross err = md_get_mem(&tmp_mb, NULL, sb->sb_offset, MB_MSYSTEM); 129613a2f6bSGordon Ross if (err) 130613a2f6bSGordon Ross return (err); 131613a2f6bSGordon Ross 132613a2f6bSGordon Ross /* Get the data (as an mbuf). */ 13302d09e03SGordon Ross err = md_get_mbuf(&tmp_mb, sb->sb_maxlen, mp); 134613a2f6bSGordon Ross 135613a2f6bSGordon Ross return (err); 136613a2f6bSGordon Ross } 137613a2f6bSGordon Ross 138613a2f6bSGordon Ross /* 139613a2f6bSGordon Ross * Put a "security buffer" (header part) 140613a2f6bSGordon Ross */ 141613a2f6bSGordon Ross static int 142613a2f6bSGordon Ross mb_put_sb_hdr(struct mbdata *mbp, struct sec_buf *sb) 143613a2f6bSGordon Ross { 144613a2f6bSGordon Ross int err; 145613a2f6bSGordon Ross 146613a2f6bSGordon Ross (void) mb_put_uint16le(mbp, sb->sb_length); 147613a2f6bSGordon Ross (void) mb_put_uint16le(mbp, sb->sb_maxlen); 148613a2f6bSGordon Ross err = mb_put_uint32le(mbp, sb->sb_offset); 149613a2f6bSGordon Ross 150613a2f6bSGordon Ross return (err); 151613a2f6bSGordon Ross } 152613a2f6bSGordon Ross 153613a2f6bSGordon Ross /* 154613a2f6bSGordon Ross * Put a "security buffer" (data part), where 155613a2f6bSGordon Ross * the data is an mbuf. Note: consumes m. 156613a2f6bSGordon Ross */ 157613a2f6bSGordon Ross static int 158613a2f6bSGordon Ross mb_put_sb_data(struct mbdata *mbp, struct sec_buf *sb, struct mbuf *m) 159613a2f6bSGordon Ross { 160*85e6b674SGordon Ross int cnt0; 161*85e6b674SGordon Ross int err = 0; 162613a2f6bSGordon Ross 163613a2f6bSGordon Ross sb->sb_offset = cnt0 = mbp->mb_count; 164*85e6b674SGordon Ross if (m != NULL) 165613a2f6bSGordon Ross err = mb_put_mbuf(mbp, m); 166613a2f6bSGordon Ross sb->sb_maxlen = sb->sb_length = mbp->mb_count - cnt0; 167613a2f6bSGordon Ross 168613a2f6bSGordon Ross return (err); 169613a2f6bSGordon Ross } 170613a2f6bSGordon Ross 171613a2f6bSGordon Ross /* 172613a2f6bSGordon Ross * Put a "security buffer" (data part), where 173613a2f6bSGordon Ross * the data is a string (OEM or unicode). 174613a2f6bSGordon Ross * 175613a2f6bSGordon Ross * The string is NOT null terminated. 176613a2f6bSGordon Ross */ 177613a2f6bSGordon Ross static int 178613a2f6bSGordon Ross mb_put_sb_string(struct mbdata *mbp, struct sec_buf *sb, 179*85e6b674SGordon Ross const char *str, int unicode) 180613a2f6bSGordon Ross { 181613a2f6bSGordon Ross int err, trim; 182613a2f6bSGordon Ross struct mbdata tmp_mb; 183613a2f6bSGordon Ross 184*85e6b674SGordon Ross bzero(&tmp_mb, sizeof (tmp_mb)); 185*85e6b674SGordon Ross 186*85e6b674SGordon Ross if (str != NULL && *str != '\0') { 187613a2f6bSGordon Ross /* 188613a2f6bSGordon Ross * Put the string into a temp. mbuf, 189613a2f6bSGordon Ross * then chop off the null terminator 190613a2f6bSGordon Ross * before appending to caller's mbp. 191613a2f6bSGordon Ross */ 19202d09e03SGordon Ross err = mb_init(&tmp_mb); 193613a2f6bSGordon Ross if (err) 194613a2f6bSGordon Ross return (err); 195*85e6b674SGordon Ross err = mb_put_string(&tmp_mb, str, unicode); 196613a2f6bSGordon Ross if (err) 197613a2f6bSGordon Ross return (err); 198613a2f6bSGordon Ross 199613a2f6bSGordon Ross trim = (unicode) ? 2 : 1; 200613a2f6bSGordon Ross if (tmp_mb.mb_cur->m_len < trim) 201*85e6b674SGordon Ross trim = 0; 202613a2f6bSGordon Ross tmp_mb.mb_cur->m_len -= trim; 203*85e6b674SGordon Ross } 204613a2f6bSGordon Ross 205613a2f6bSGordon Ross err = mb_put_sb_data(mbp, sb, tmp_mb.mb_top); 206613a2f6bSGordon Ross /* 207*85e6b674SGordon Ross * Note: tmp_mb.mb_top (if any) is consumed, 208613a2f6bSGordon Ross * so do NOT free it (no mb_done) 209613a2f6bSGordon Ross */ 210613a2f6bSGordon Ross return (err); 211613a2f6bSGordon Ross } 212613a2f6bSGordon Ross 213613a2f6bSGordon Ross /* 214613a2f6bSGordon Ross * Build a Type 1 message 215613a2f6bSGordon Ross * 216613a2f6bSGordon Ross * This message has a header section containing offsets to 217613a2f6bSGordon Ross * data later in the message. We use the common trick of 218613a2f6bSGordon Ross * building it in two parts and then concatenatening. 219613a2f6bSGordon Ross */ 220613a2f6bSGordon Ross int 221613a2f6bSGordon Ross ntlmssp_put_type1(struct ssp_ctx *sp, struct mbdata *out_mb) 222613a2f6bSGordon Ross { 223613a2f6bSGordon Ross struct type1hdr { 224613a2f6bSGordon Ross char h_id[ID_SZ]; 225613a2f6bSGordon Ross uint32_t h_type; 226613a2f6bSGordon Ross uint32_t h_flags; 227613a2f6bSGordon Ross struct sec_buf h_cldom; 228613a2f6bSGordon Ross struct sec_buf h_wksta; 229613a2f6bSGordon Ross } hdr; 230613a2f6bSGordon Ross struct mbdata mb2; /* 2nd part */ 231613a2f6bSGordon Ross int err; 232613a2f6bSGordon Ross struct smb_ctx *ctx = sp->smb_ctx; 233613a2f6bSGordon Ross ntlmssp_state_t *ssp_st = sp->sp_private; 234613a2f6bSGordon Ross 23502d09e03SGordon Ross if ((err = mb_init(&mb2)) != 0) 236613a2f6bSGordon Ross return (err); 237613a2f6bSGordon Ross mb2.mb_count = sizeof (hdr); 238613a2f6bSGordon Ross 239613a2f6bSGordon Ross /* 240*85e6b674SGordon Ross * The initial negotiation flags represent the union of all 241*85e6b674SGordon Ross * options we support. The server selects from these. 242*85e6b674SGordon Ross * See: [MS-NLMP 2.2.2.5 NEGOTIATE] 243613a2f6bSGordon Ross */ 244613a2f6bSGordon Ross ssp_st->ss_flags = 245*85e6b674SGordon Ross NTLMSSP_NEGOTIATE_UNICODE | 246*85e6b674SGordon Ross NTLMSSP_NEGOTIATE_OEM | 247613a2f6bSGordon Ross NTLMSSP_REQUEST_TARGET | 248*85e6b674SGordon Ross NTLMSSP_NEGOTIATE_SIGN | 249*85e6b674SGordon Ross NTLMSSP_NEGOTIATE_SEAL | 250*85e6b674SGordon Ross /* NTLMSSP_NEGOTIATE_LM_KEY (never) */ 251613a2f6bSGordon Ross NTLMSSP_NEGOTIATE_NTLM | 252*85e6b674SGordon Ross /* NTLMSSP_NEGOTIATE_ALWAYS_SIGN (set below) */ 253*85e6b674SGordon Ross NTLMSSP_NEGOTIATE_NTLM2 | 254613a2f6bSGordon Ross NTLMSSP_NEGOTIATE_128 | 255*85e6b674SGordon Ross NTLMSSP_NEGOTIATE_KEY_EXCH | 256613a2f6bSGordon Ross NTLMSSP_NEGOTIATE_56; 257613a2f6bSGordon Ross 258613a2f6bSGordon Ross if (ctx->ct_vcflags & SMBV_WILL_SIGN) { 259613a2f6bSGordon Ross ssp_st->ss_flags |= NTLMSSP_NEGOTIATE_ALWAYS_SIGN; 260613a2f6bSGordon Ross ctx->ct_hflags2 |= SMB_FLAGS2_SECURITY_SIGNATURE; 261613a2f6bSGordon Ross } 262613a2f6bSGordon Ross 263613a2f6bSGordon Ross bcopy(ntlmssp_id, &hdr.h_id, ID_SZ); 264*85e6b674SGordon Ross hdr.h_type = NTLMSSP_MSGTYPE_NEGOTIATE; 265613a2f6bSGordon Ross hdr.h_flags = ssp_st->ss_flags; 266613a2f6bSGordon Ross 267613a2f6bSGordon Ross /* 268*85e6b674SGordon Ross * We could put the client domain, client name strings 269*85e6b674SGordon Ross * here, (always in OEM format, upper-case), and set 270*85e6b674SGordon Ross * NTLMSSP_NEGOTIATE_OEM_..._SUPPLIED, but Windows 271*85e6b674SGordon Ross * leaves these NULL so let's do the same. 272613a2f6bSGordon Ross */ 273*85e6b674SGordon Ross (void) mb_put_sb_string(&mb2, &hdr.h_cldom, NULL, 0); 274*85e6b674SGordon Ross (void) mb_put_sb_string(&mb2, &hdr.h_wksta, NULL, 0); 275613a2f6bSGordon Ross 276613a2f6bSGordon Ross /* 277613a2f6bSGordon Ross * Marshal the header (in LE order) 278613a2f6bSGordon Ross * then concatenate the 2nd part. 279613a2f6bSGordon Ross */ 28002d09e03SGordon Ross (void) mb_put_mem(out_mb, &hdr.h_id, ID_SZ, MB_MSYSTEM); 281613a2f6bSGordon Ross (void) mb_put_uint32le(out_mb, hdr.h_type); 282613a2f6bSGordon Ross (void) mb_put_uint32le(out_mb, hdr.h_flags); 283613a2f6bSGordon Ross (void) mb_put_sb_hdr(out_mb, &hdr.h_cldom); 284613a2f6bSGordon Ross (void) mb_put_sb_hdr(out_mb, &hdr.h_wksta); 285613a2f6bSGordon Ross 286613a2f6bSGordon Ross err = mb_put_mbuf(out_mb, mb2.mb_top); 287613a2f6bSGordon Ross 288613a2f6bSGordon Ross return (err); 289613a2f6bSGordon Ross } 290613a2f6bSGordon Ross 291613a2f6bSGordon Ross /* 292613a2f6bSGordon Ross * Parse a Type 2 message 293613a2f6bSGordon Ross */ 294613a2f6bSGordon Ross int 295613a2f6bSGordon Ross ntlmssp_get_type2(struct ssp_ctx *sp, struct mbdata *in_mb) 296613a2f6bSGordon Ross { 297613a2f6bSGordon Ross struct type2hdr { 298613a2f6bSGordon Ross char h_id[ID_SZ]; 299613a2f6bSGordon Ross uint32_t h_type; 300613a2f6bSGordon Ross struct sec_buf h_target_name; 301613a2f6bSGordon Ross uint32_t h_flags; 302613a2f6bSGordon Ross uint8_t h_challenge[8]; 303613a2f6bSGordon Ross uint32_t h_context[2]; /* optional */ 304613a2f6bSGordon Ross struct sec_buf h_target_info; /* optional */ 305613a2f6bSGordon Ross } hdr; 306613a2f6bSGordon Ross struct mbdata top_mb, tmp_mb; 307613a2f6bSGordon Ross struct mbuf *m; 308613a2f6bSGordon Ross int err, uc; 309613a2f6bSGordon Ross int min_hdr_sz = offsetof(struct type2hdr, h_context); 310613a2f6bSGordon Ross struct smb_ctx *ctx = sp->smb_ctx; 311613a2f6bSGordon Ross ntlmssp_state_t *ssp_st = sp->sp_private; 312613a2f6bSGordon Ross char *buf = NULL; 313613a2f6bSGordon Ross 314613a2f6bSGordon Ross if (m_totlen(in_mb->mb_top) < min_hdr_sz) { 315613a2f6bSGordon Ross err = EBADRPC; 316613a2f6bSGordon Ross goto out; 317613a2f6bSGordon Ross } 318613a2f6bSGordon Ross 319613a2f6bSGordon Ross /* 320613a2f6bSGordon Ross * Save the mbdata pointers before we consume anything. 321613a2f6bSGordon Ross * Careful to NOT free this (would be dup. free) 322613a2f6bSGordon Ross * We use this below to find data based on offsets 323613a2f6bSGordon Ross * from the start of the header. 324613a2f6bSGordon Ross */ 325613a2f6bSGordon Ross top_mb = *in_mb; 326613a2f6bSGordon Ross 327613a2f6bSGordon Ross /* Parse the fixed size header stuff. */ 328613a2f6bSGordon Ross bzero(&hdr, sizeof (hdr)); 32902d09e03SGordon Ross (void) md_get_mem(in_mb, &hdr.h_id, ID_SZ, MB_MSYSTEM); 33002d09e03SGordon Ross (void) md_get_uint32le(in_mb, &hdr.h_type); 331*85e6b674SGordon Ross if (hdr.h_type != NTLMSSP_MSGTYPE_CHALLENGE) { 332613a2f6bSGordon Ross err = EPROTO; 333613a2f6bSGordon Ross goto out; 334613a2f6bSGordon Ross } 33502d09e03SGordon Ross (void) md_get_sb_hdr(in_mb, &hdr.h_target_name); 33602d09e03SGordon Ross (void) md_get_uint32le(in_mb, &hdr.h_flags); 33702d09e03SGordon Ross (void) md_get_mem(in_mb, &hdr.h_challenge, NTLM_CHAL_SZ, MB_MSYSTEM); 338613a2f6bSGordon Ross 339613a2f6bSGordon Ross /* 340*85e6b674SGordon Ross * Save flags, server challenge for later. 341613a2f6bSGordon Ross */ 342613a2f6bSGordon Ross ssp_st->ss_flags = hdr.h_flags; 343*85e6b674SGordon Ross bcopy(&hdr.h_challenge, ctx->ct_srv_chal, NTLM_CHAL_SZ); 344*85e6b674SGordon Ross 345*85e6b674SGordon Ross /* 346*85e6b674SGordon Ross * Turn off flags that might have been given but 347*85e6b674SGordon Ross * that we don't want to send with authenticate. 348*85e6b674SGordon Ross */ 349613a2f6bSGordon Ross uc = hdr.h_flags & NTLMSSP_NEGOTIATE_UNICODE; 350*85e6b674SGordon Ross ssp_st->ss_flags &= ~NTLMSSP_NEGOTIATE_VERSION; 351613a2f6bSGordon Ross 352613a2f6bSGordon Ross /* 353613a2f6bSGordon Ross * Now find out if the optional parts are there. 354613a2f6bSGordon Ross */ 355613a2f6bSGordon Ross if ((m_totlen(top_mb.mb_top) > sizeof (hdr)) && 356613a2f6bSGordon Ross (hdr.h_target_name.sb_offset >= sizeof (hdr))) { 35702d09e03SGordon Ross (void) md_get_uint32le(in_mb, &hdr.h_context[0]); 35802d09e03SGordon Ross (void) md_get_uint32le(in_mb, &hdr.h_context[1]); 35902d09e03SGordon Ross (void) md_get_sb_hdr(in_mb, &hdr.h_target_info); 360613a2f6bSGordon Ross } 361613a2f6bSGordon Ross 362613a2f6bSGordon Ross /* 363*85e6b674SGordon Ross * Get the target name string. (Server name or 364*85e6b674SGordon Ross * Primary domain name.) First get a copy of the 365*85e6b674SGordon Ross * data from the offset/length indicated in the 366613a2f6bSGordon Ross * security buffer header; then parse the string. 367613a2f6bSGordon Ross */ 36802d09e03SGordon Ross err = md_get_sb_data(&top_mb, &hdr.h_target_name, &m); 369613a2f6bSGordon Ross if (err) 370613a2f6bSGordon Ross goto out; 371613a2f6bSGordon Ross mb_initm(&tmp_mb, m); 37202d09e03SGordon Ross err = md_get_string(&tmp_mb, &ssp_st->ss_target_name, uc); 373613a2f6bSGordon Ross mb_done(&tmp_mb); 374613a2f6bSGordon Ross 375613a2f6bSGordon Ross /* 376613a2f6bSGordon Ross * Get the target info blob, if present. 377613a2f6bSGordon Ross */ 378613a2f6bSGordon Ross if (hdr.h_target_info.sb_offset >= sizeof (hdr)) { 37902d09e03SGordon Ross err = md_get_sb_data(&top_mb, &hdr.h_target_info, 380613a2f6bSGordon Ross &ssp_st->ss_target_info); 381613a2f6bSGordon Ross } 382613a2f6bSGordon Ross 383613a2f6bSGordon Ross out: 384613a2f6bSGordon Ross if (buf != NULL) 385613a2f6bSGordon Ross free(buf); 386613a2f6bSGordon Ross 387613a2f6bSGordon Ross return (err); 388613a2f6bSGordon Ross } 389613a2f6bSGordon Ross 390613a2f6bSGordon Ross /* 391613a2f6bSGordon Ross * Build a Type 3 message 392613a2f6bSGordon Ross * 393613a2f6bSGordon Ross * This message has a header section containing offsets to 394613a2f6bSGordon Ross * data later in the message. We use the common trick of 395613a2f6bSGordon Ross * building it in two parts and then concatenatening. 396613a2f6bSGordon Ross */ 397613a2f6bSGordon Ross int 398613a2f6bSGordon Ross ntlmssp_put_type3(struct ssp_ctx *sp, struct mbdata *out_mb) 399613a2f6bSGordon Ross { 400613a2f6bSGordon Ross struct type3hdr { 401613a2f6bSGordon Ross char h_id[ID_SZ]; 402613a2f6bSGordon Ross uint32_t h_type; 403613a2f6bSGordon Ross struct sec_buf h_lm_resp; 404613a2f6bSGordon Ross struct sec_buf h_nt_resp; 405613a2f6bSGordon Ross struct sec_buf h_domain; 406613a2f6bSGordon Ross struct sec_buf h_user; 407613a2f6bSGordon Ross struct sec_buf h_wksta; 40815359501SGordon Ross struct sec_buf h_ssn_key; 40915359501SGordon Ross uint32_t h_flags; 410*85e6b674SGordon Ross /* Version struct (ommitted) */ 411*85e6b674SGordon Ross uchar_t h_mic[NTLM_HASH_SZ]; 412613a2f6bSGordon Ross } hdr; 41315359501SGordon Ross struct mbdata lm_mbc; /* LM response */ 41415359501SGordon Ross struct mbdata nt_mbc; /* NT response */ 41515359501SGordon Ross struct mbdata ti_mbc; /* target info */ 416*85e6b674SGordon Ross struct mbdata ek_mbc; /* encrypted session key */ 41715359501SGordon Ross struct mbdata mb2; /* payload */ 418613a2f6bSGordon Ross int err, uc; 419613a2f6bSGordon Ross struct smb_ctx *ctx = sp->smb_ctx; 420613a2f6bSGordon Ross ntlmssp_state_t *ssp_st = sp->sp_private; 421*85e6b674SGordon Ross uchar_t *pmic; 422613a2f6bSGordon Ross 42315359501SGordon Ross bzero(&hdr, sizeof (hdr)); 424613a2f6bSGordon Ross bzero(&lm_mbc, sizeof (lm_mbc)); 425613a2f6bSGordon Ross bzero(&nt_mbc, sizeof (nt_mbc)); 426613a2f6bSGordon Ross bzero(&ti_mbc, sizeof (ti_mbc)); 427*85e6b674SGordon Ross bzero(&ek_mbc, sizeof (ek_mbc)); 428613a2f6bSGordon Ross bzero(&mb2, sizeof (mb2)); 429613a2f6bSGordon Ross 430613a2f6bSGordon Ross /* 43115359501SGordon Ross * Fill in the NTLMSSP header, etc. 432613a2f6bSGordon Ross */ 43302d09e03SGordon Ross if ((err = mb_init(&mb2)) != 0) 434613a2f6bSGordon Ross goto out; 435613a2f6bSGordon Ross mb2.mb_count = sizeof (hdr); 436613a2f6bSGordon Ross uc = ssp_st->ss_flags & NTLMSSP_NEGOTIATE_UNICODE; 437613a2f6bSGordon Ross 438613a2f6bSGordon Ross bcopy(ntlmssp_id, &hdr.h_id, ID_SZ); 439*85e6b674SGordon Ross hdr.h_type = NTLMSSP_MSGTYPE_AUTHENTICATE; 44015359501SGordon Ross hdr.h_flags = ssp_st->ss_flags; 441613a2f6bSGordon Ross 442613a2f6bSGordon Ross /* 443*85e6b674SGordon Ross * Put the NTLMv2/LMv2 or NTLM/LM (v1) responses, 444*85e6b674SGordon Ross * and compute the session key, etc. 445613a2f6bSGordon Ross */ 446*85e6b674SGordon Ross if (ctx->ct_authflags & SMB_AT_ANON) { 447*85e6b674SGordon Ross /* 448*85e6b674SGordon Ross * We're setting up a NULL session, meaning 449*85e6b674SGordon Ross * the lm_mbc, nt_mbc parts remain empty. 450*85e6b674SGordon Ross * Let's add the "anon" flag (hint). 451*85e6b674SGordon Ross * As there is no session key, disable the 452*85e6b674SGordon Ross * fancy session key stuff. 453*85e6b674SGordon Ross */ 454*85e6b674SGordon Ross hdr.h_flags |= NTLMSSP_NEGOTIATE_NULL_SESSION; 455*85e6b674SGordon Ross ssp_st->ss_flags &= ~( 456*85e6b674SGordon Ross NTLMSSP_NEGOTIATE_NTLM2 | 457*85e6b674SGordon Ross NTLMSSP_NEGOTIATE_KEY_EXCH); 458*85e6b674SGordon Ross err = 0; 459*85e6b674SGordon Ross } else if (ctx->ct_authflags & SMB_AT_NTLM2) { 460*85e6b674SGordon Ross /* 461*85e6b674SGordon Ross * Doing NTLMv2/LMv2 462*85e6b674SGordon Ross */ 463613a2f6bSGordon Ross err = ntlm_build_target_info(ctx, 464613a2f6bSGordon Ross ssp_st->ss_target_info, &ti_mbc); 465613a2f6bSGordon Ross if (err) 466613a2f6bSGordon Ross goto out; 467613a2f6bSGordon Ross err = ntlm_put_v2_responses(ctx, &ti_mbc, 468613a2f6bSGordon Ross &lm_mbc, &nt_mbc); 469613a2f6bSGordon Ross if (err) 470613a2f6bSGordon Ross goto out; 471*85e6b674SGordon Ross /* The "key exg. key" is the session base key */ 472*85e6b674SGordon Ross memcpy(ssp_st->ss_kxkey, ctx->ct_ssn_key, NTLM_HASH_SZ); 473*85e6b674SGordon Ross 474*85e6b674SGordon Ross } else if (ssp_st->ss_flags & NTLMSSP_NEGOTIATE_NTLM2) { 475*85e6b674SGordon Ross /* 476*85e6b674SGordon Ross * Doing NTLM ("v1x") which is NTLM with 477*85e6b674SGordon Ross * "Extended Session Security" 478*85e6b674SGordon Ross */ 479*85e6b674SGordon Ross err = ntlm_put_v1x_responses(ctx, 480*85e6b674SGordon Ross &lm_mbc, &nt_mbc); 481*85e6b674SGordon Ross if (err) 482*85e6b674SGordon Ross goto out; 483*85e6b674SGordon Ross /* Compute the "Key exchange key". */ 484*85e6b674SGordon Ross ntlm2_kxkey(ctx, &lm_mbc, ssp_st->ss_kxkey); 485*85e6b674SGordon Ross } else { 486*85e6b674SGordon Ross /* 487*85e6b674SGordon Ross * Doing plain old NTLM (and LM if enabled) 488*85e6b674SGordon Ross */ 489*85e6b674SGordon Ross err = ntlm_put_v1_responses(ctx, 490*85e6b674SGordon Ross &lm_mbc, &nt_mbc); 491*85e6b674SGordon Ross if (err) 492*85e6b674SGordon Ross goto out; 493*85e6b674SGordon Ross /* The "key exg. key" is the session base key */ 494*85e6b674SGordon Ross memcpy(ssp_st->ss_kxkey, ctx->ct_ssn_key, NTLM_HASH_SZ); 495*85e6b674SGordon Ross } 496*85e6b674SGordon Ross 497*85e6b674SGordon Ross /* 498*85e6b674SGordon Ross * Compute the "Exported Session Key" and (possibly) 499*85e6b674SGordon Ross * the "Encrypted Random Sesion Key". 500*85e6b674SGordon Ross * [MS-NLMP 3.1.5.1.2] 501*85e6b674SGordon Ross */ 502*85e6b674SGordon Ross if (ssp_st->ss_flags & NTLMSSP_NEGOTIATE_KEY_EXCH) { 503*85e6b674SGordon Ross err = ntlm_rand_ssn_key(ctx, ssp_st, &ek_mbc); 504*85e6b674SGordon Ross if (err) 505*85e6b674SGordon Ross goto out; 506*85e6b674SGordon Ross } else { 507*85e6b674SGordon Ross /* ExportedSessionKey is the KeyExchangeKey */ 508*85e6b674SGordon Ross memcpy(ctx->ct_ssn_key, ssp_st->ss_kxkey, NTLM_HASH_SZ); 509*85e6b674SGordon Ross /* EncryptedRandomSessionKey remains NULL */ 510*85e6b674SGordon Ross } 511613a2f6bSGordon Ross 512613a2f6bSGordon Ross err = mb_put_sb_data(&mb2, &hdr.h_lm_resp, lm_mbc.mb_top); 513613a2f6bSGordon Ross lm_mbc.mb_top = NULL; /* consumed */ 514613a2f6bSGordon Ross if (err) 515613a2f6bSGordon Ross goto out; 516613a2f6bSGordon Ross err = mb_put_sb_data(&mb2, &hdr.h_nt_resp, nt_mbc.mb_top); 517613a2f6bSGordon Ross nt_mbc.mb_top = NULL; /* consumed */ 518613a2f6bSGordon Ross if (err) 519613a2f6bSGordon Ross goto out; 520613a2f6bSGordon Ross 521613a2f6bSGordon Ross /* 522613a2f6bSGordon Ross * Put the "target" (domain), user, workstation 523613a2f6bSGordon Ross */ 52415359501SGordon Ross err = mb_put_sb_string(&mb2, &hdr.h_domain, ctx->ct_domain, uc); 525613a2f6bSGordon Ross if (err) 526613a2f6bSGordon Ross goto out; 52715359501SGordon Ross err = mb_put_sb_string(&mb2, &hdr.h_user, ctx->ct_user, uc); 528613a2f6bSGordon Ross if (err) 529613a2f6bSGordon Ross goto out; 53015359501SGordon Ross err = mb_put_sb_string(&mb2, &hdr.h_wksta, ctx->ct_locname, uc); 531613a2f6bSGordon Ross if (err) 532613a2f6bSGordon Ross goto out; 533613a2f6bSGordon Ross 534613a2f6bSGordon Ross /* 535*85e6b674SGordon Ross * Put the "Encrypted Random Session Key", if any. 536*85e6b674SGordon Ross * (ek_mbc.mb_top may be NULL) 53715359501SGordon Ross */ 538*85e6b674SGordon Ross err = mb_put_sb_data(&mb2, &hdr.h_ssn_key, ek_mbc.mb_top); 539*85e6b674SGordon Ross ek_mbc.mb_top = NULL; /* consumed (if any) */ 540*85e6b674SGordon Ross if (err) 541*85e6b674SGordon Ross goto out; 54215359501SGordon Ross 54315359501SGordon Ross /* 544613a2f6bSGordon Ross * Marshal the header (in LE order) 545613a2f6bSGordon Ross * then concatenate the 2nd part. 546613a2f6bSGordon Ross */ 54702d09e03SGordon Ross (void) mb_put_mem(out_mb, &hdr.h_id, ID_SZ, MB_MSYSTEM); 548613a2f6bSGordon Ross (void) mb_put_uint32le(out_mb, hdr.h_type); 549613a2f6bSGordon Ross 550613a2f6bSGordon Ross (void) mb_put_sb_hdr(out_mb, &hdr.h_lm_resp); 551613a2f6bSGordon Ross (void) mb_put_sb_hdr(out_mb, &hdr.h_nt_resp); 552613a2f6bSGordon Ross 553613a2f6bSGordon Ross (void) mb_put_sb_hdr(out_mb, &hdr.h_domain); 554613a2f6bSGordon Ross (void) mb_put_sb_hdr(out_mb, &hdr.h_user); 555613a2f6bSGordon Ross (void) mb_put_sb_hdr(out_mb, &hdr.h_wksta); 556613a2f6bSGordon Ross 55715359501SGordon Ross (void) mb_put_sb_hdr(out_mb, &hdr.h_ssn_key); 55815359501SGordon Ross (void) mb_put_uint32le(out_mb, hdr.h_flags); 55915359501SGordon Ross 560*85e6b674SGordon Ross /* Put zeros for the MIC - filled in later */ 561*85e6b674SGordon Ross pmic = mb_reserve(out_mb, NTLM_HASH_SZ); 562*85e6b674SGordon Ross 563*85e6b674SGordon Ross /* Put the payload. */ 564613a2f6bSGordon Ross err = mb_put_mbuf(out_mb, mb2.mb_top); 565613a2f6bSGordon Ross mb2.mb_top = NULL; /* consumed */ 566613a2f6bSGordon Ross 567*85e6b674SGordon Ross /* 568*85e6b674SGordon Ross * Compute the MIC and stuff that in... 569*85e6b674SGordon Ross * The MIC is apparently optional. 570*85e6b674SGordon Ross */ 571*85e6b674SGordon Ross (void) pmic; 572*85e6b674SGordon Ross 573613a2f6bSGordon Ross out: 574613a2f6bSGordon Ross mb_done(&mb2); 575613a2f6bSGordon Ross mb_done(&lm_mbc); 576613a2f6bSGordon Ross mb_done(&nt_mbc); 57715359501SGordon Ross mb_done(&ti_mbc); 578*85e6b674SGordon Ross mb_done(&ek_mbc); 579*85e6b674SGordon Ross 580*85e6b674SGordon Ross return (err); 581*85e6b674SGordon Ross } 582*85e6b674SGordon Ross 583*85e6b674SGordon Ross /* 584*85e6b674SGordon Ross * Helper for ntlmssp_put_type3 when doing key exchange. 585*85e6b674SGordon Ross * 586*85e6b674SGordon Ross * "ExportedSessionKey" is what we give to the "application" 587*85e6b674SGordon Ross * layer, which in here means the MAC key for SMB signing. 588*85e6b674SGordon Ross * With "key exchange", we replace the ExportedSessionKey 589*85e6b674SGordon Ross * with random data and send that (encrypted) to the peer. 590*85e6b674SGordon Ross */ 591*85e6b674SGordon Ross static int 592*85e6b674SGordon Ross ntlm_rand_ssn_key( 593*85e6b674SGordon Ross struct smb_ctx *ctx, 594*85e6b674SGordon Ross ntlmssp_state_t *ssp_st, 595*85e6b674SGordon Ross struct mbdata *ek_mbp) 596*85e6b674SGordon Ross { 597*85e6b674SGordon Ross 598*85e6b674SGordon Ross uchar_t *encr_ssn_key; 599*85e6b674SGordon Ross int err; 600*85e6b674SGordon Ross 601*85e6b674SGordon Ross if ((err = mb_init(ek_mbp)) != 0) 602*85e6b674SGordon Ross return (err); 603*85e6b674SGordon Ross encr_ssn_key = mb_reserve(ek_mbp, NTLM_HASH_SZ); 604*85e6b674SGordon Ross 605*85e6b674SGordon Ross /* Set "ExportedSessionKey to NONCE(16) */ 606*85e6b674SGordon Ross (void) smb_get_urandom(ctx->ct_ssn_key, NTLM_HASH_SZ); 607*85e6b674SGordon Ross 608*85e6b674SGordon Ross /* Set "EncryptedRandomSessionKey" to RC4(...) */ 609*85e6b674SGordon Ross err = smb_encrypt_RC4(encr_ssn_key, NTLM_HASH_SZ, 610*85e6b674SGordon Ross ssp_st->ss_kxkey, NTLM_HASH_SZ, 611*85e6b674SGordon Ross ctx->ct_ssn_key, NTLM_HASH_SZ); 612613a2f6bSGordon Ross 613613a2f6bSGordon Ross return (err); 614613a2f6bSGordon Ross } 615613a2f6bSGordon Ross 616613a2f6bSGordon Ross /* 617613a2f6bSGordon Ross * ntlmssp_final 618613a2f6bSGordon Ross * 619613a2f6bSGordon Ross * Called after successful authentication. 620613a2f6bSGordon Ross * Setup the MAC key for signing. 621613a2f6bSGordon Ross */ 622613a2f6bSGordon Ross int 623613a2f6bSGordon Ross ntlmssp_final(struct ssp_ctx *sp) 624613a2f6bSGordon Ross { 625613a2f6bSGordon Ross struct smb_ctx *ctx = sp->smb_ctx; 626613a2f6bSGordon Ross int err = 0; 627613a2f6bSGordon Ross 628613a2f6bSGordon Ross /* 629613a2f6bSGordon Ross * MAC_key is just the session key, but 630613a2f6bSGordon Ross * Only on the first successful auth. 631613a2f6bSGordon Ross */ 632613a2f6bSGordon Ross if ((ctx->ct_hflags2 & SMB_FLAGS2_SECURITY_SIGNATURE) && 633613a2f6bSGordon Ross (ctx->ct_mackey == NULL)) { 634613a2f6bSGordon Ross ctx->ct_mackeylen = NTLM_HASH_SZ; 635613a2f6bSGordon Ross ctx->ct_mackey = malloc(ctx->ct_mackeylen); 636613a2f6bSGordon Ross if (ctx->ct_mackey == NULL) { 637613a2f6bSGordon Ross ctx->ct_mackeylen = 0; 638613a2f6bSGordon Ross err = ENOMEM; 639613a2f6bSGordon Ross goto out; 640613a2f6bSGordon Ross } 641613a2f6bSGordon Ross memcpy(ctx->ct_mackey, ctx->ct_ssn_key, NTLM_HASH_SZ); 642613a2f6bSGordon Ross /* 643613a2f6bSGordon Ross * Apparently, the server used seq. no. zero 644613a2f6bSGordon Ross * for our previous message, so next is two. 645613a2f6bSGordon Ross */ 646613a2f6bSGordon Ross ctx->ct_mac_seqno = 2; 647613a2f6bSGordon Ross } 648613a2f6bSGordon Ross 649613a2f6bSGordon Ross out: 650613a2f6bSGordon Ross return (err); 651613a2f6bSGordon Ross } 652613a2f6bSGordon Ross 653613a2f6bSGordon Ross /* 654613a2f6bSGordon Ross * ntlmssp_next_token 655613a2f6bSGordon Ross * 656613a2f6bSGordon Ross * See ssp.c: ssp_ctx_next_token 657613a2f6bSGordon Ross */ 658613a2f6bSGordon Ross int 659613a2f6bSGordon Ross ntlmssp_next_token(struct ssp_ctx *sp, struct mbdata *in_mb, 660613a2f6bSGordon Ross struct mbdata *out_mb) 661613a2f6bSGordon Ross { 662613a2f6bSGordon Ross int err; 663613a2f6bSGordon Ross 664613a2f6bSGordon Ross if (out_mb == NULL) { 665613a2f6bSGordon Ross /* final call on successful auth. */ 666613a2f6bSGordon Ross err = ntlmssp_final(sp); 667613a2f6bSGordon Ross goto out; 668613a2f6bSGordon Ross } 669613a2f6bSGordon Ross 670613a2f6bSGordon Ross /* Will build an ouptut token. */ 67102d09e03SGordon Ross err = mb_init(out_mb); 672613a2f6bSGordon Ross if (err) 673613a2f6bSGordon Ross goto out; 674613a2f6bSGordon Ross 675613a2f6bSGordon Ross /* 676613a2f6bSGordon Ross * When called with in_mb == NULL, it means 677613a2f6bSGordon Ross * this is the first call for this session, 678613a2f6bSGordon Ross * so put a Type 1 (initialize) token. 679613a2f6bSGordon Ross */ 680613a2f6bSGordon Ross if (in_mb == NULL) { 681613a2f6bSGordon Ross err = ntlmssp_put_type1(sp, out_mb); 682613a2f6bSGordon Ross goto out; 683613a2f6bSGordon Ross } 684613a2f6bSGordon Ross 685613a2f6bSGordon Ross /* 686613a2f6bSGordon Ross * This is not the first call, so 687613a2f6bSGordon Ross * parse the response token we received. 688613a2f6bSGordon Ross * It should be a Type 2 (challenge). 689613a2f6bSGordon Ross * Then put a Type 3 (authenticate) 690613a2f6bSGordon Ross */ 691613a2f6bSGordon Ross err = ntlmssp_get_type2(sp, in_mb); 692613a2f6bSGordon Ross if (err) 693613a2f6bSGordon Ross goto out; 694613a2f6bSGordon Ross 695613a2f6bSGordon Ross err = ntlmssp_put_type3(sp, out_mb); 696613a2f6bSGordon Ross 697613a2f6bSGordon Ross out: 698613a2f6bSGordon Ross if (err) 699613a2f6bSGordon Ross DPRINT("ret: %d", err); 700613a2f6bSGordon Ross return (err); 701613a2f6bSGordon Ross } 702613a2f6bSGordon Ross 703613a2f6bSGordon Ross /* 704613a2f6bSGordon Ross * ntlmssp_ctx_destroy 705613a2f6bSGordon Ross * 706613a2f6bSGordon Ross * Destroy mechanism-specific data. 707613a2f6bSGordon Ross */ 708613a2f6bSGordon Ross void 709613a2f6bSGordon Ross ntlmssp_destroy(struct ssp_ctx *sp) 710613a2f6bSGordon Ross { 711613a2f6bSGordon Ross ntlmssp_state_t *ssp_st; 712613a2f6bSGordon Ross 713613a2f6bSGordon Ross ssp_st = sp->sp_private; 714613a2f6bSGordon Ross if (ssp_st != NULL) { 715613a2f6bSGordon Ross sp->sp_private = NULL; 716613a2f6bSGordon Ross free(ssp_st->ss_target_name); 717613a2f6bSGordon Ross m_freem(ssp_st->ss_target_info); 718613a2f6bSGordon Ross free(ssp_st); 719613a2f6bSGordon Ross } 720613a2f6bSGordon Ross } 721613a2f6bSGordon Ross 722613a2f6bSGordon Ross /* 723613a2f6bSGordon Ross * ntlmssp_init_clnt 724613a2f6bSGordon Ross * 725613a2f6bSGordon Ross * Initialize a new NTLMSSP client context. 726613a2f6bSGordon Ross */ 727613a2f6bSGordon Ross int 728613a2f6bSGordon Ross ntlmssp_init_client(struct ssp_ctx *sp) 729613a2f6bSGordon Ross { 730613a2f6bSGordon Ross ntlmssp_state_t *ssp_st; 731613a2f6bSGordon Ross 732613a2f6bSGordon Ross if ((sp->smb_ctx->ct_authflags & 733*85e6b674SGordon Ross (SMB_AT_NTLM2 | SMB_AT_NTLM1 | SMB_AT_ANON)) == 0) { 734613a2f6bSGordon Ross DPRINT("No NTLM authflags"); 735*85e6b674SGordon Ross return (EINVAL); 736613a2f6bSGordon Ross } 737613a2f6bSGordon Ross 738613a2f6bSGordon Ross ssp_st = calloc(1, sizeof (*ssp_st)); 739613a2f6bSGordon Ross if (ssp_st == NULL) 740613a2f6bSGordon Ross return (ENOMEM); 741613a2f6bSGordon Ross 742613a2f6bSGordon Ross sp->sp_nexttok = ntlmssp_next_token; 743613a2f6bSGordon Ross sp->sp_destroy = ntlmssp_destroy; 744613a2f6bSGordon Ross sp->sp_private = ssp_st; 745613a2f6bSGordon Ross 746613a2f6bSGordon Ross return (0); 747613a2f6bSGordon Ross } 748