1*613a2f6bSGordon Ross /* 2*613a2f6bSGordon Ross * CDDL HEADER START 3*613a2f6bSGordon Ross * 4*613a2f6bSGordon Ross * The contents of this file are subject to the terms of the 5*613a2f6bSGordon Ross * Common Development and Distribution License (the "License"). 6*613a2f6bSGordon Ross * You may not use this file except in compliance with the License. 7*613a2f6bSGordon Ross * 8*613a2f6bSGordon Ross * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE 9*613a2f6bSGordon Ross * or http://www.opensolaris.org/os/licensing. 10*613a2f6bSGordon Ross * See the License for the specific language governing permissions 11*613a2f6bSGordon Ross * and limitations under the License. 12*613a2f6bSGordon Ross * 13*613a2f6bSGordon Ross * When distributing Covered Code, include this CDDL HEADER in each 14*613a2f6bSGordon Ross * file and include the License file at usr/src/OPENSOLARIS.LICENSE. 15*613a2f6bSGordon Ross * If applicable, add the following below this CDDL HEADER, with the 16*613a2f6bSGordon Ross * fields enclosed by brackets "[]" replaced with your own identifying 17*613a2f6bSGordon Ross * information: Portions Copyright [yyyy] [name of copyright owner] 18*613a2f6bSGordon Ross * 19*613a2f6bSGordon Ross * CDDL HEADER END 20*613a2f6bSGordon Ross */ 21*613a2f6bSGordon Ross 22*613a2f6bSGordon Ross /* 23*613a2f6bSGordon Ross * Copyright 2009 Sun Microsystems, Inc. All rights reserved. 24*613a2f6bSGordon Ross * Use is subject to license terms. 25*613a2f6bSGordon Ross */ 26*613a2f6bSGordon Ross 27*613a2f6bSGordon Ross /* 28*613a2f6bSGordon Ross * NT Lan Manager Security Support Provider (NTLMSSP) 29*613a2f6bSGordon Ross * 30*613a2f6bSGordon Ross * Based on information from the "Davenport NTLM" page: 31*613a2f6bSGordon Ross * http://davenport.sourceforge.net/ntlm.html 32*613a2f6bSGordon Ross */ 33*613a2f6bSGordon Ross 34*613a2f6bSGordon Ross 35*613a2f6bSGordon Ross #include <errno.h> 36*613a2f6bSGordon Ross #include <stdio.h> 37*613a2f6bSGordon Ross #include <stddef.h> 38*613a2f6bSGordon Ross #include <stdlib.h> 39*613a2f6bSGordon Ross #include <unistd.h> 40*613a2f6bSGordon Ross #include <strings.h> 41*613a2f6bSGordon Ross #include <netdb.h> 42*613a2f6bSGordon Ross #include <libintl.h> 43*613a2f6bSGordon Ross #include <xti.h> 44*613a2f6bSGordon Ross #include <assert.h> 45*613a2f6bSGordon Ross 46*613a2f6bSGordon Ross #include <sys/types.h> 47*613a2f6bSGordon Ross #include <sys/time.h> 48*613a2f6bSGordon Ross #include <sys/byteorder.h> 49*613a2f6bSGordon Ross #include <sys/socket.h> 50*613a2f6bSGordon Ross #include <sys/fcntl.h> 51*613a2f6bSGordon Ross 52*613a2f6bSGordon Ross #include <netinet/in.h> 53*613a2f6bSGordon Ross #include <netinet/tcp.h> 54*613a2f6bSGordon Ross #include <arpa/inet.h> 55*613a2f6bSGordon Ross 56*613a2f6bSGordon Ross #include <netsmb/smb.h> 57*613a2f6bSGordon Ross #include <netsmb/smb_lib.h> 58*613a2f6bSGordon Ross #include <netsmb/mchain.h> 59*613a2f6bSGordon Ross 60*613a2f6bSGordon Ross #include "private.h" 61*613a2f6bSGordon Ross #include "charsets.h" 62*613a2f6bSGordon Ross #include "spnego.h" 63*613a2f6bSGordon Ross #include "derparse.h" 64*613a2f6bSGordon Ross #include "ssp.h" 65*613a2f6bSGordon Ross #include "ntlm.h" 66*613a2f6bSGordon Ross #include "ntlmssp.h" 67*613a2f6bSGordon Ross 68*613a2f6bSGordon Ross typedef struct ntlmssp_state { 69*613a2f6bSGordon Ross uint32_t ss_flags; 70*613a2f6bSGordon Ross char *ss_target_name; 71*613a2f6bSGordon Ross struct mbuf *ss_target_info; 72*613a2f6bSGordon Ross } ntlmssp_state_t; 73*613a2f6bSGordon Ross 74*613a2f6bSGordon Ross /* 75*613a2f6bSGordon Ross * So called "security buffer". 76*613a2f6bSGordon Ross * A lot like an RPC string. 77*613a2f6bSGordon Ross */ 78*613a2f6bSGordon Ross struct sec_buf { 79*613a2f6bSGordon Ross uint16_t sb_length; 80*613a2f6bSGordon Ross uint16_t sb_maxlen; 81*613a2f6bSGordon Ross uint32_t sb_offset; 82*613a2f6bSGordon Ross }; 83*613a2f6bSGordon Ross #define ID_SZ 8 84*613a2f6bSGordon Ross static const char ntlmssp_id[ID_SZ] = "NTLMSSP"; 85*613a2f6bSGordon Ross 86*613a2f6bSGordon Ross /* 87*613a2f6bSGordon Ross * Get a "security buffer" (header part) 88*613a2f6bSGordon Ross */ 89*613a2f6bSGordon Ross static int 90*613a2f6bSGordon Ross mb_get_sb_hdr(struct mbdata *mbp, struct sec_buf *sb) 91*613a2f6bSGordon Ross { 92*613a2f6bSGordon Ross int err; 93*613a2f6bSGordon Ross 94*613a2f6bSGordon Ross (void) mb_get_uint16le(mbp, &sb->sb_length); 95*613a2f6bSGordon Ross (void) mb_get_uint16le(mbp, &sb->sb_maxlen); 96*613a2f6bSGordon Ross err = mb_get_uint32le(mbp, &sb->sb_offset); 97*613a2f6bSGordon Ross 98*613a2f6bSGordon Ross return (err); 99*613a2f6bSGordon Ross } 100*613a2f6bSGordon Ross 101*613a2f6bSGordon Ross /* 102*613a2f6bSGordon Ross * Get a "security buffer" (data part), where 103*613a2f6bSGordon Ross * the data is delivered as an mbuf. 104*613a2f6bSGordon Ross */ 105*613a2f6bSGordon Ross static int 106*613a2f6bSGordon Ross mb_get_sb_data(struct mbdata *mbp, struct sec_buf *sb, struct mbuf **mp) 107*613a2f6bSGordon Ross { 108*613a2f6bSGordon Ross struct mbdata tmp_mb; 109*613a2f6bSGordon Ross int err; 110*613a2f6bSGordon Ross 111*613a2f6bSGordon Ross /* 112*613a2f6bSGordon Ross * Setup tmp_mb to point to the start of the header. 113*613a2f6bSGordon Ross * This is a dup ref - do NOT free it. 114*613a2f6bSGordon Ross */ 115*613a2f6bSGordon Ross mb_initm(&tmp_mb, mbp->mb_top); 116*613a2f6bSGordon Ross 117*613a2f6bSGordon Ross /* Skip data up to the offset. */ 118*613a2f6bSGordon Ross err = mb_get_mem(&tmp_mb, NULL, sb->sb_offset); 119*613a2f6bSGordon Ross if (err) 120*613a2f6bSGordon Ross return (err); 121*613a2f6bSGordon Ross 122*613a2f6bSGordon Ross /* Get the data (as an mbuf). */ 123*613a2f6bSGordon Ross err = mb_get_mbuf(&tmp_mb, sb->sb_maxlen, mp); 124*613a2f6bSGordon Ross 125*613a2f6bSGordon Ross return (err); 126*613a2f6bSGordon Ross } 127*613a2f6bSGordon Ross 128*613a2f6bSGordon Ross /* 129*613a2f6bSGordon Ross * Put a "security buffer" (header part) 130*613a2f6bSGordon Ross */ 131*613a2f6bSGordon Ross static int 132*613a2f6bSGordon Ross mb_put_sb_hdr(struct mbdata *mbp, struct sec_buf *sb) 133*613a2f6bSGordon Ross { 134*613a2f6bSGordon Ross int err; 135*613a2f6bSGordon Ross 136*613a2f6bSGordon Ross (void) mb_put_uint16le(mbp, sb->sb_length); 137*613a2f6bSGordon Ross (void) mb_put_uint16le(mbp, sb->sb_maxlen); 138*613a2f6bSGordon Ross err = mb_put_uint32le(mbp, sb->sb_offset); 139*613a2f6bSGordon Ross 140*613a2f6bSGordon Ross return (err); 141*613a2f6bSGordon Ross } 142*613a2f6bSGordon Ross 143*613a2f6bSGordon Ross /* 144*613a2f6bSGordon Ross * Put a "security buffer" (data part), where 145*613a2f6bSGordon Ross * the data is an mbuf. Note: consumes m. 146*613a2f6bSGordon Ross */ 147*613a2f6bSGordon Ross static int 148*613a2f6bSGordon Ross mb_put_sb_data(struct mbdata *mbp, struct sec_buf *sb, struct mbuf *m) 149*613a2f6bSGordon Ross { 150*613a2f6bSGordon Ross int cnt0, err; 151*613a2f6bSGordon Ross 152*613a2f6bSGordon Ross sb->sb_offset = cnt0 = mbp->mb_count; 153*613a2f6bSGordon Ross err = mb_put_mbuf(mbp, m); 154*613a2f6bSGordon Ross sb->sb_maxlen = sb->sb_length = mbp->mb_count - cnt0; 155*613a2f6bSGordon Ross 156*613a2f6bSGordon Ross return (err); 157*613a2f6bSGordon Ross } 158*613a2f6bSGordon Ross 159*613a2f6bSGordon Ross /* 160*613a2f6bSGordon Ross * Put a "security buffer" (data part), where 161*613a2f6bSGordon Ross * the data is a string (OEM or unicode). 162*613a2f6bSGordon Ross * 163*613a2f6bSGordon Ross * The string is NOT null terminated. 164*613a2f6bSGordon Ross */ 165*613a2f6bSGordon Ross static int 166*613a2f6bSGordon Ross mb_put_sb_string(struct mbdata *mbp, struct sec_buf *sb, 167*613a2f6bSGordon Ross const char *s, int unicode) 168*613a2f6bSGordon Ross { 169*613a2f6bSGordon Ross int err, trim; 170*613a2f6bSGordon Ross struct mbdata tmp_mb; 171*613a2f6bSGordon Ross 172*613a2f6bSGordon Ross /* 173*613a2f6bSGordon Ross * Put the string into a temp. mbuf, 174*613a2f6bSGordon Ross * then chop off the null terminator 175*613a2f6bSGordon Ross * before appending to caller's mbp. 176*613a2f6bSGordon Ross */ 177*613a2f6bSGordon Ross err = mb_init(&tmp_mb, M_MINSIZE); 178*613a2f6bSGordon Ross if (err) 179*613a2f6bSGordon Ross return (err); 180*613a2f6bSGordon Ross err = mb_put_dstring(&tmp_mb, s, unicode); 181*613a2f6bSGordon Ross if (err) 182*613a2f6bSGordon Ross return (err); 183*613a2f6bSGordon Ross 184*613a2f6bSGordon Ross trim = (unicode) ? 2 : 1; 185*613a2f6bSGordon Ross if (tmp_mb.mb_cur->m_len < trim) 186*613a2f6bSGordon Ross return (EFAULT); 187*613a2f6bSGordon Ross tmp_mb.mb_cur->m_len -= trim; 188*613a2f6bSGordon Ross 189*613a2f6bSGordon Ross err = mb_put_sb_data(mbp, sb, tmp_mb.mb_top); 190*613a2f6bSGordon Ross /* 191*613a2f6bSGordon Ross * Note: tmp_mb.mb_top is consumed, 192*613a2f6bSGordon Ross * so do NOT free it (no mb_done) 193*613a2f6bSGordon Ross */ 194*613a2f6bSGordon Ross return (err); 195*613a2f6bSGordon Ross } 196*613a2f6bSGordon Ross 197*613a2f6bSGordon Ross /* 198*613a2f6bSGordon Ross * Build a Type 1 message 199*613a2f6bSGordon Ross * 200*613a2f6bSGordon Ross * This message has a header section containing offsets to 201*613a2f6bSGordon Ross * data later in the message. We use the common trick of 202*613a2f6bSGordon Ross * building it in two parts and then concatenatening. 203*613a2f6bSGordon Ross */ 204*613a2f6bSGordon Ross int 205*613a2f6bSGordon Ross ntlmssp_put_type1(struct ssp_ctx *sp, struct mbdata *out_mb) 206*613a2f6bSGordon Ross { 207*613a2f6bSGordon Ross struct type1hdr { 208*613a2f6bSGordon Ross char h_id[ID_SZ]; 209*613a2f6bSGordon Ross uint32_t h_type; 210*613a2f6bSGordon Ross uint32_t h_flags; 211*613a2f6bSGordon Ross struct sec_buf h_cldom; 212*613a2f6bSGordon Ross struct sec_buf h_wksta; 213*613a2f6bSGordon Ross } hdr; 214*613a2f6bSGordon Ross struct mbdata mb2; /* 2nd part */ 215*613a2f6bSGordon Ross int err; 216*613a2f6bSGordon Ross struct smb_ctx *ctx = sp->smb_ctx; 217*613a2f6bSGordon Ross ntlmssp_state_t *ssp_st = sp->sp_private; 218*613a2f6bSGordon Ross char *ucdom = NULL; 219*613a2f6bSGordon Ross char *ucwks = NULL; 220*613a2f6bSGordon Ross 221*613a2f6bSGordon Ross if ((err = mb_init(&mb2, M_MINSIZE)) != 0) 222*613a2f6bSGordon Ross return (err); 223*613a2f6bSGordon Ross mb2.mb_count = sizeof (hdr); 224*613a2f6bSGordon Ross 225*613a2f6bSGordon Ross /* 226*613a2f6bSGordon Ross * Initialize the negotiation flags, and 227*613a2f6bSGordon Ross * save what we sent. For reference: 228*613a2f6bSGordon Ross * [MS-NLMP] spec. (also ntlmssp.h) 229*613a2f6bSGordon Ross */ 230*613a2f6bSGordon Ross ssp_st->ss_flags = 231*613a2f6bSGordon Ross NTLMSSP_REQUEST_TARGET | 232*613a2f6bSGordon Ross NTLMSSP_NEGOTIATE_NTLM | 233*613a2f6bSGordon Ross NTLMSSP_NEGOTIATE_TARGET_INFO | 234*613a2f6bSGordon Ross NTLMSSP_NEGOTIATE_128 | 235*613a2f6bSGordon Ross NTLMSSP_NEGOTIATE_56; 236*613a2f6bSGordon Ross 237*613a2f6bSGordon Ross if (ctx->ct_hflags2 & SMB_FLAGS2_UNICODE) 238*613a2f6bSGordon Ross ssp_st->ss_flags |= NTLMSSP_NEGOTIATE_UNICODE; 239*613a2f6bSGordon Ross else 240*613a2f6bSGordon Ross ssp_st->ss_flags |= NTLMSSP_NEGOTIATE_OEM; 241*613a2f6bSGordon Ross 242*613a2f6bSGordon Ross if (ctx->ct_vcflags & SMBV_WILL_SIGN) { 243*613a2f6bSGordon Ross ssp_st->ss_flags |= NTLMSSP_NEGOTIATE_ALWAYS_SIGN; 244*613a2f6bSGordon Ross ctx->ct_hflags2 |= SMB_FLAGS2_SECURITY_SIGNATURE; 245*613a2f6bSGordon Ross } 246*613a2f6bSGordon Ross 247*613a2f6bSGordon Ross bcopy(ntlmssp_id, &hdr.h_id, ID_SZ); 248*613a2f6bSGordon Ross hdr.h_type = 1; /* Type 1 */ 249*613a2f6bSGordon Ross hdr.h_flags = ssp_st->ss_flags; 250*613a2f6bSGordon Ross 251*613a2f6bSGordon Ross /* 252*613a2f6bSGordon Ross * Put the client domain, client name strings. 253*613a2f6bSGordon Ross * These are always in OEM format, upper-case. 254*613a2f6bSGordon Ross */ 255*613a2f6bSGordon Ross ucdom = utf8_str_toupper(ctx->ct_domain); 256*613a2f6bSGordon Ross ucwks = utf8_str_toupper(ctx->ct_locname); 257*613a2f6bSGordon Ross if (ucdom == NULL || ucwks == NULL) { 258*613a2f6bSGordon Ross err = ENOMEM; 259*613a2f6bSGordon Ross goto out; 260*613a2f6bSGordon Ross } 261*613a2f6bSGordon Ross err = mb_put_sb_string(&mb2, &hdr.h_cldom, ucdom, 0); 262*613a2f6bSGordon Ross if (err) 263*613a2f6bSGordon Ross goto out; 264*613a2f6bSGordon Ross err = mb_put_sb_string(&mb2, &hdr.h_wksta, ucwks, 0); 265*613a2f6bSGordon Ross if (err) 266*613a2f6bSGordon Ross goto out; 267*613a2f6bSGordon Ross 268*613a2f6bSGordon Ross /* 269*613a2f6bSGordon Ross * Marshal the header (in LE order) 270*613a2f6bSGordon Ross * then concatenate the 2nd part. 271*613a2f6bSGordon Ross */ 272*613a2f6bSGordon Ross (void) mb_put_mem(out_mb, &hdr.h_id, ID_SZ); 273*613a2f6bSGordon Ross (void) mb_put_uint32le(out_mb, hdr.h_type); 274*613a2f6bSGordon Ross (void) mb_put_uint32le(out_mb, hdr.h_flags); 275*613a2f6bSGordon Ross (void) mb_put_sb_hdr(out_mb, &hdr.h_cldom); 276*613a2f6bSGordon Ross (void) mb_put_sb_hdr(out_mb, &hdr.h_wksta); 277*613a2f6bSGordon Ross 278*613a2f6bSGordon Ross err = mb_put_mbuf(out_mb, mb2.mb_top); 279*613a2f6bSGordon Ross 280*613a2f6bSGordon Ross out: 281*613a2f6bSGordon Ross free(ucdom); 282*613a2f6bSGordon Ross free(ucwks); 283*613a2f6bSGordon Ross 284*613a2f6bSGordon Ross return (err); 285*613a2f6bSGordon Ross } 286*613a2f6bSGordon Ross 287*613a2f6bSGordon Ross /* 288*613a2f6bSGordon Ross * Parse a Type 2 message 289*613a2f6bSGordon Ross */ 290*613a2f6bSGordon Ross int 291*613a2f6bSGordon Ross ntlmssp_get_type2(struct ssp_ctx *sp, struct mbdata *in_mb) 292*613a2f6bSGordon Ross { 293*613a2f6bSGordon Ross struct type2hdr { 294*613a2f6bSGordon Ross char h_id[ID_SZ]; 295*613a2f6bSGordon Ross uint32_t h_type; 296*613a2f6bSGordon Ross struct sec_buf h_target_name; 297*613a2f6bSGordon Ross uint32_t h_flags; 298*613a2f6bSGordon Ross uint8_t h_challenge[8]; 299*613a2f6bSGordon Ross uint32_t h_context[2]; /* optional */ 300*613a2f6bSGordon Ross struct sec_buf h_target_info; /* optional */ 301*613a2f6bSGordon Ross } hdr; 302*613a2f6bSGordon Ross struct mbdata top_mb, tmp_mb; 303*613a2f6bSGordon Ross struct mbuf *m; 304*613a2f6bSGordon Ross int err, uc; 305*613a2f6bSGordon Ross int min_hdr_sz = offsetof(struct type2hdr, h_context); 306*613a2f6bSGordon Ross struct smb_ctx *ctx = sp->smb_ctx; 307*613a2f6bSGordon Ross ntlmssp_state_t *ssp_st = sp->sp_private; 308*613a2f6bSGordon Ross char *buf = NULL; 309*613a2f6bSGordon Ross 310*613a2f6bSGordon Ross if (m_totlen(in_mb->mb_top) < min_hdr_sz) { 311*613a2f6bSGordon Ross err = EBADRPC; 312*613a2f6bSGordon Ross goto out; 313*613a2f6bSGordon Ross } 314*613a2f6bSGordon Ross 315*613a2f6bSGordon Ross /* 316*613a2f6bSGordon Ross * Save the mbdata pointers before we consume anything. 317*613a2f6bSGordon Ross * Careful to NOT free this (would be dup. free) 318*613a2f6bSGordon Ross * We use this below to find data based on offsets 319*613a2f6bSGordon Ross * from the start of the header. 320*613a2f6bSGordon Ross */ 321*613a2f6bSGordon Ross top_mb = *in_mb; 322*613a2f6bSGordon Ross 323*613a2f6bSGordon Ross /* Parse the fixed size header stuff. */ 324*613a2f6bSGordon Ross bzero(&hdr, sizeof (hdr)); 325*613a2f6bSGordon Ross (void) mb_get_mem(in_mb, &hdr.h_id, ID_SZ); 326*613a2f6bSGordon Ross (void) mb_get_uint32le(in_mb, &hdr.h_type); 327*613a2f6bSGordon Ross if (hdr.h_type != 2) { 328*613a2f6bSGordon Ross err = EPROTO; 329*613a2f6bSGordon Ross goto out; 330*613a2f6bSGordon Ross } 331*613a2f6bSGordon Ross (void) mb_get_sb_hdr(in_mb, &hdr.h_target_name); 332*613a2f6bSGordon Ross (void) mb_get_uint32le(in_mb, &hdr.h_flags); 333*613a2f6bSGordon Ross (void) mb_get_mem(in_mb, &hdr.h_challenge, NTLM_CHAL_SZ); 334*613a2f6bSGordon Ross 335*613a2f6bSGordon Ross /* 336*613a2f6bSGordon Ross * Save flags, challenge for later. 337*613a2f6bSGordon Ross */ 338*613a2f6bSGordon Ross ssp_st->ss_flags = hdr.h_flags; 339*613a2f6bSGordon Ross uc = hdr.h_flags & NTLMSSP_NEGOTIATE_UNICODE; 340*613a2f6bSGordon Ross bcopy(&hdr.h_challenge, ctx->ct_ntlm_chal, NTLM_CHAL_SZ); 341*613a2f6bSGordon Ross 342*613a2f6bSGordon Ross /* 343*613a2f6bSGordon Ross * Now find out if the optional parts are there. 344*613a2f6bSGordon Ross */ 345*613a2f6bSGordon Ross if ((m_totlen(top_mb.mb_top) > sizeof (hdr)) && 346*613a2f6bSGordon Ross (hdr.h_target_name.sb_offset >= sizeof (hdr))) { 347*613a2f6bSGordon Ross (void) mb_get_uint32le(in_mb, &hdr.h_context[0]); 348*613a2f6bSGordon Ross (void) mb_get_uint32le(in_mb, &hdr.h_context[1]); 349*613a2f6bSGordon Ross (void) mb_get_sb_hdr(in_mb, &hdr.h_target_info); 350*613a2f6bSGordon Ross } 351*613a2f6bSGordon Ross 352*613a2f6bSGordon Ross /* 353*613a2f6bSGordon Ross * Get the target name string. First get a copy of 354*613a2f6bSGordon Ross * the data from the offset/length indicated in the 355*613a2f6bSGordon Ross * security buffer header; then parse the string. 356*613a2f6bSGordon Ross */ 357*613a2f6bSGordon Ross err = mb_get_sb_data(&top_mb, &hdr.h_target_name, &m); 358*613a2f6bSGordon Ross if (err) 359*613a2f6bSGordon Ross goto out; 360*613a2f6bSGordon Ross mb_initm(&tmp_mb, m); 361*613a2f6bSGordon Ross err = mb_get_string(&tmp_mb, &ssp_st->ss_target_name, uc); 362*613a2f6bSGordon Ross mb_done(&tmp_mb); 363*613a2f6bSGordon Ross 364*613a2f6bSGordon Ross /* 365*613a2f6bSGordon Ross * Get the target info blob, if present. 366*613a2f6bSGordon Ross */ 367*613a2f6bSGordon Ross if (hdr.h_target_info.sb_offset >= sizeof (hdr)) { 368*613a2f6bSGordon Ross err = mb_get_sb_data(&top_mb, &hdr.h_target_info, 369*613a2f6bSGordon Ross &ssp_st->ss_target_info); 370*613a2f6bSGordon Ross } 371*613a2f6bSGordon Ross 372*613a2f6bSGordon Ross out: 373*613a2f6bSGordon Ross if (buf != NULL) 374*613a2f6bSGordon Ross free(buf); 375*613a2f6bSGordon Ross 376*613a2f6bSGordon Ross return (err); 377*613a2f6bSGordon Ross } 378*613a2f6bSGordon Ross 379*613a2f6bSGordon Ross /* 380*613a2f6bSGordon Ross * Build a Type 3 message 381*613a2f6bSGordon Ross * 382*613a2f6bSGordon Ross * This message has a header section containing offsets to 383*613a2f6bSGordon Ross * data later in the message. We use the common trick of 384*613a2f6bSGordon Ross * building it in two parts and then concatenatening. 385*613a2f6bSGordon Ross */ 386*613a2f6bSGordon Ross int 387*613a2f6bSGordon Ross ntlmssp_put_type3(struct ssp_ctx *sp, struct mbdata *out_mb) 388*613a2f6bSGordon Ross { 389*613a2f6bSGordon Ross struct type3hdr { 390*613a2f6bSGordon Ross char h_id[ID_SZ]; 391*613a2f6bSGordon Ross uint32_t h_type; 392*613a2f6bSGordon Ross struct sec_buf h_lm_resp; 393*613a2f6bSGordon Ross struct sec_buf h_nt_resp; 394*613a2f6bSGordon Ross struct sec_buf h_domain; 395*613a2f6bSGordon Ross struct sec_buf h_user; 396*613a2f6bSGordon Ross struct sec_buf h_wksta; 397*613a2f6bSGordon Ross } hdr; 398*613a2f6bSGordon Ross struct mbdata lm_mbc, nt_mbc, ti_mbc; 399*613a2f6bSGordon Ross struct mbdata mb2; /* 2nd part */ 400*613a2f6bSGordon Ross int err, uc; 401*613a2f6bSGordon Ross char *ucdom = NULL; /* user's domain */ 402*613a2f6bSGordon Ross char *ucuser = NULL; /* user name */ 403*613a2f6bSGordon Ross char *ucwksta = NULL; /* workstation */ 404*613a2f6bSGordon Ross struct smb_ctx *ctx = sp->smb_ctx; 405*613a2f6bSGordon Ross ntlmssp_state_t *ssp_st = sp->sp_private; 406*613a2f6bSGordon Ross 407*613a2f6bSGordon Ross bzero(&lm_mbc, sizeof (lm_mbc)); 408*613a2f6bSGordon Ross bzero(&nt_mbc, sizeof (nt_mbc)); 409*613a2f6bSGordon Ross bzero(&ti_mbc, sizeof (ti_mbc)); 410*613a2f6bSGordon Ross bzero(&mb2, sizeof (mb2)); 411*613a2f6bSGordon Ross 412*613a2f6bSGordon Ross /* 413*613a2f6bSGordon Ross * Convert the user name to upper-case, as that's what's 414*613a2f6bSGordon Ross * used when computing LMv2 and NTLMv2 responses. Also 415*613a2f6bSGordon Ross * domain, workstation 416*613a2f6bSGordon Ross */ 417*613a2f6bSGordon Ross ucdom = utf8_str_toupper(ctx->ct_domain); 418*613a2f6bSGordon Ross ucuser = utf8_str_toupper(ctx->ct_user); 419*613a2f6bSGordon Ross ucwksta = utf8_str_toupper(ctx->ct_locname); 420*613a2f6bSGordon Ross if (ucdom == NULL || ucuser == NULL || ucwksta == NULL) { 421*613a2f6bSGordon Ross err = ENOMEM; 422*613a2f6bSGordon Ross goto out; 423*613a2f6bSGordon Ross } 424*613a2f6bSGordon Ross 425*613a2f6bSGordon Ross if ((err = mb_init(&mb2, M_MINSIZE)) != 0) 426*613a2f6bSGordon Ross goto out; 427*613a2f6bSGordon Ross mb2.mb_count = sizeof (hdr); 428*613a2f6bSGordon Ross uc = ssp_st->ss_flags & NTLMSSP_NEGOTIATE_UNICODE; 429*613a2f6bSGordon Ross 430*613a2f6bSGordon Ross bcopy(ntlmssp_id, &hdr.h_id, ID_SZ); 431*613a2f6bSGordon Ross hdr.h_type = 3; /* Type 3 */ 432*613a2f6bSGordon Ross 433*613a2f6bSGordon Ross /* 434*613a2f6bSGordon Ross * Put the LMv2,NTLMv2 responses, or 435*613a2f6bSGordon Ross * possibly LM, NTLM (v1) responses. 436*613a2f6bSGordon Ross */ 437*613a2f6bSGordon Ross if (ctx->ct_authflags & SMB_AT_NTLM2) { 438*613a2f6bSGordon Ross /* Build the NTLMv2 "target info" blob. */ 439*613a2f6bSGordon Ross err = ntlm_build_target_info(ctx, 440*613a2f6bSGordon Ross ssp_st->ss_target_info, &ti_mbc); 441*613a2f6bSGordon Ross if (err) 442*613a2f6bSGordon Ross goto out; 443*613a2f6bSGordon Ross err = ntlm_put_v2_responses(ctx, &ti_mbc, 444*613a2f6bSGordon Ross &lm_mbc, &nt_mbc); 445*613a2f6bSGordon Ross } else { 446*613a2f6bSGordon Ross err = ntlm_put_v1_responses(ctx, 447*613a2f6bSGordon Ross &lm_mbc, &nt_mbc); 448*613a2f6bSGordon Ross } 449*613a2f6bSGordon Ross if (err) 450*613a2f6bSGordon Ross goto out; 451*613a2f6bSGordon Ross 452*613a2f6bSGordon Ross err = mb_put_sb_data(&mb2, &hdr.h_lm_resp, lm_mbc.mb_top); 453*613a2f6bSGordon Ross lm_mbc.mb_top = NULL; /* consumed */ 454*613a2f6bSGordon Ross if (err) 455*613a2f6bSGordon Ross goto out; 456*613a2f6bSGordon Ross err = mb_put_sb_data(&mb2, &hdr.h_nt_resp, nt_mbc.mb_top); 457*613a2f6bSGordon Ross nt_mbc.mb_top = NULL; /* consumed */ 458*613a2f6bSGordon Ross if (err) 459*613a2f6bSGordon Ross goto out; 460*613a2f6bSGordon Ross 461*613a2f6bSGordon Ross /* 462*613a2f6bSGordon Ross * Put the "target" (domain), user, workstation 463*613a2f6bSGordon Ross */ 464*613a2f6bSGordon Ross err = mb_put_sb_string(&mb2, &hdr.h_domain, ucdom, uc); 465*613a2f6bSGordon Ross if (err) 466*613a2f6bSGordon Ross goto out; 467*613a2f6bSGordon Ross err = mb_put_sb_string(&mb2, &hdr.h_user, ucuser, uc); 468*613a2f6bSGordon Ross if (err) 469*613a2f6bSGordon Ross goto out; 470*613a2f6bSGordon Ross err = mb_put_sb_string(&mb2, &hdr.h_wksta, ucwksta, uc); 471*613a2f6bSGordon Ross if (err) 472*613a2f6bSGordon Ross goto out; 473*613a2f6bSGordon Ross 474*613a2f6bSGordon Ross /* 475*613a2f6bSGordon Ross * Marshal the header (in LE order) 476*613a2f6bSGordon Ross * then concatenate the 2nd part. 477*613a2f6bSGordon Ross */ 478*613a2f6bSGordon Ross (void) mb_put_mem(out_mb, &hdr.h_id, ID_SZ); 479*613a2f6bSGordon Ross (void) mb_put_uint32le(out_mb, hdr.h_type); 480*613a2f6bSGordon Ross 481*613a2f6bSGordon Ross (void) mb_put_sb_hdr(out_mb, &hdr.h_lm_resp); 482*613a2f6bSGordon Ross (void) mb_put_sb_hdr(out_mb, &hdr.h_nt_resp); 483*613a2f6bSGordon Ross 484*613a2f6bSGordon Ross (void) mb_put_sb_hdr(out_mb, &hdr.h_domain); 485*613a2f6bSGordon Ross (void) mb_put_sb_hdr(out_mb, &hdr.h_user); 486*613a2f6bSGordon Ross (void) mb_put_sb_hdr(out_mb, &hdr.h_wksta); 487*613a2f6bSGordon Ross 488*613a2f6bSGordon Ross err = mb_put_mbuf(out_mb, mb2.mb_top); 489*613a2f6bSGordon Ross mb2.mb_top = NULL; /* consumed */ 490*613a2f6bSGordon Ross 491*613a2f6bSGordon Ross out: 492*613a2f6bSGordon Ross free(ucdom); 493*613a2f6bSGordon Ross free(ucuser); 494*613a2f6bSGordon Ross free(ucwksta); 495*613a2f6bSGordon Ross 496*613a2f6bSGordon Ross mb_done(&mb2); 497*613a2f6bSGordon Ross mb_done(&lm_mbc); 498*613a2f6bSGordon Ross mb_done(&nt_mbc); 499*613a2f6bSGordon Ross 500*613a2f6bSGordon Ross return (err); 501*613a2f6bSGordon Ross } 502*613a2f6bSGordon Ross 503*613a2f6bSGordon Ross /* 504*613a2f6bSGordon Ross * ntlmssp_final 505*613a2f6bSGordon Ross * 506*613a2f6bSGordon Ross * Called after successful authentication. 507*613a2f6bSGordon Ross * Setup the MAC key for signing. 508*613a2f6bSGordon Ross */ 509*613a2f6bSGordon Ross int 510*613a2f6bSGordon Ross ntlmssp_final(struct ssp_ctx *sp) 511*613a2f6bSGordon Ross { 512*613a2f6bSGordon Ross struct smb_ctx *ctx = sp->smb_ctx; 513*613a2f6bSGordon Ross int err = 0; 514*613a2f6bSGordon Ross 515*613a2f6bSGordon Ross /* 516*613a2f6bSGordon Ross * MAC_key is just the session key, but 517*613a2f6bSGordon Ross * Only on the first successful auth. 518*613a2f6bSGordon Ross */ 519*613a2f6bSGordon Ross if ((ctx->ct_hflags2 & SMB_FLAGS2_SECURITY_SIGNATURE) && 520*613a2f6bSGordon Ross (ctx->ct_mackey == NULL)) { 521*613a2f6bSGordon Ross ctx->ct_mackeylen = NTLM_HASH_SZ; 522*613a2f6bSGordon Ross ctx->ct_mackey = malloc(ctx->ct_mackeylen); 523*613a2f6bSGordon Ross if (ctx->ct_mackey == NULL) { 524*613a2f6bSGordon Ross ctx->ct_mackeylen = 0; 525*613a2f6bSGordon Ross err = ENOMEM; 526*613a2f6bSGordon Ross goto out; 527*613a2f6bSGordon Ross } 528*613a2f6bSGordon Ross memcpy(ctx->ct_mackey, ctx->ct_ssn_key, NTLM_HASH_SZ); 529*613a2f6bSGordon Ross /* 530*613a2f6bSGordon Ross * Apparently, the server used seq. no. zero 531*613a2f6bSGordon Ross * for our previous message, so next is two. 532*613a2f6bSGordon Ross */ 533*613a2f6bSGordon Ross ctx->ct_mac_seqno = 2; 534*613a2f6bSGordon Ross } 535*613a2f6bSGordon Ross 536*613a2f6bSGordon Ross out: 537*613a2f6bSGordon Ross return (err); 538*613a2f6bSGordon Ross } 539*613a2f6bSGordon Ross 540*613a2f6bSGordon Ross /* 541*613a2f6bSGordon Ross * ntlmssp_next_token 542*613a2f6bSGordon Ross * 543*613a2f6bSGordon Ross * See ssp.c: ssp_ctx_next_token 544*613a2f6bSGordon Ross */ 545*613a2f6bSGordon Ross int 546*613a2f6bSGordon Ross ntlmssp_next_token(struct ssp_ctx *sp, struct mbdata *in_mb, 547*613a2f6bSGordon Ross struct mbdata *out_mb) 548*613a2f6bSGordon Ross { 549*613a2f6bSGordon Ross int err; 550*613a2f6bSGordon Ross 551*613a2f6bSGordon Ross if (out_mb == NULL) { 552*613a2f6bSGordon Ross /* final call on successful auth. */ 553*613a2f6bSGordon Ross err = ntlmssp_final(sp); 554*613a2f6bSGordon Ross goto out; 555*613a2f6bSGordon Ross } 556*613a2f6bSGordon Ross 557*613a2f6bSGordon Ross /* Will build an ouptut token. */ 558*613a2f6bSGordon Ross err = mb_init(out_mb, M_MINSIZE); 559*613a2f6bSGordon Ross if (err) 560*613a2f6bSGordon Ross goto out; 561*613a2f6bSGordon Ross 562*613a2f6bSGordon Ross /* 563*613a2f6bSGordon Ross * When called with in_mb == NULL, it means 564*613a2f6bSGordon Ross * this is the first call for this session, 565*613a2f6bSGordon Ross * so put a Type 1 (initialize) token. 566*613a2f6bSGordon Ross */ 567*613a2f6bSGordon Ross if (in_mb == NULL) { 568*613a2f6bSGordon Ross err = ntlmssp_put_type1(sp, out_mb); 569*613a2f6bSGordon Ross goto out; 570*613a2f6bSGordon Ross } 571*613a2f6bSGordon Ross 572*613a2f6bSGordon Ross /* 573*613a2f6bSGordon Ross * This is not the first call, so 574*613a2f6bSGordon Ross * parse the response token we received. 575*613a2f6bSGordon Ross * It should be a Type 2 (challenge). 576*613a2f6bSGordon Ross * Then put a Type 3 (authenticate) 577*613a2f6bSGordon Ross */ 578*613a2f6bSGordon Ross err = ntlmssp_get_type2(sp, in_mb); 579*613a2f6bSGordon Ross if (err) 580*613a2f6bSGordon Ross goto out; 581*613a2f6bSGordon Ross 582*613a2f6bSGordon Ross err = ntlmssp_put_type3(sp, out_mb); 583*613a2f6bSGordon Ross 584*613a2f6bSGordon Ross out: 585*613a2f6bSGordon Ross if (err) 586*613a2f6bSGordon Ross DPRINT("ret: %d", err); 587*613a2f6bSGordon Ross return (err); 588*613a2f6bSGordon Ross } 589*613a2f6bSGordon Ross 590*613a2f6bSGordon Ross /* 591*613a2f6bSGordon Ross * ntlmssp_ctx_destroy 592*613a2f6bSGordon Ross * 593*613a2f6bSGordon Ross * Destroy mechanism-specific data. 594*613a2f6bSGordon Ross */ 595*613a2f6bSGordon Ross void 596*613a2f6bSGordon Ross ntlmssp_destroy(struct ssp_ctx *sp) 597*613a2f6bSGordon Ross { 598*613a2f6bSGordon Ross ntlmssp_state_t *ssp_st; 599*613a2f6bSGordon Ross 600*613a2f6bSGordon Ross ssp_st = sp->sp_private; 601*613a2f6bSGordon Ross if (ssp_st != NULL) { 602*613a2f6bSGordon Ross sp->sp_private = NULL; 603*613a2f6bSGordon Ross free(ssp_st->ss_target_name); 604*613a2f6bSGordon Ross m_freem(ssp_st->ss_target_info); 605*613a2f6bSGordon Ross free(ssp_st); 606*613a2f6bSGordon Ross } 607*613a2f6bSGordon Ross } 608*613a2f6bSGordon Ross 609*613a2f6bSGordon Ross /* 610*613a2f6bSGordon Ross * ntlmssp_init_clnt 611*613a2f6bSGordon Ross * 612*613a2f6bSGordon Ross * Initialize a new NTLMSSP client context. 613*613a2f6bSGordon Ross */ 614*613a2f6bSGordon Ross int 615*613a2f6bSGordon Ross ntlmssp_init_client(struct ssp_ctx *sp) 616*613a2f6bSGordon Ross { 617*613a2f6bSGordon Ross ntlmssp_state_t *ssp_st; 618*613a2f6bSGordon Ross 619*613a2f6bSGordon Ross if ((sp->smb_ctx->ct_authflags & 620*613a2f6bSGordon Ross (SMB_AT_NTLM2 | SMB_AT_NTLM1)) == 0) { 621*613a2f6bSGordon Ross DPRINT("No NTLM authflags"); 622*613a2f6bSGordon Ross return (ENOTSUP); 623*613a2f6bSGordon Ross } 624*613a2f6bSGordon Ross 625*613a2f6bSGordon Ross ssp_st = calloc(1, sizeof (*ssp_st)); 626*613a2f6bSGordon Ross if (ssp_st == NULL) 627*613a2f6bSGordon Ross return (ENOMEM); 628*613a2f6bSGordon Ross 629*613a2f6bSGordon Ross sp->sp_nexttok = ntlmssp_next_token; 630*613a2f6bSGordon Ross sp->sp_destroy = ntlmssp_destroy; 631*613a2f6bSGordon Ross sp->sp_private = ssp_st; 632*613a2f6bSGordon Ross 633*613a2f6bSGordon Ross return (0); 634*613a2f6bSGordon Ross } 635