1*10023SGordon.Ross@Sun.COM /* 2*10023SGordon.Ross@Sun.COM * Copyright (c) 2000-2001 Boris Popov 3*10023SGordon.Ross@Sun.COM * All rights reserved. 4*10023SGordon.Ross@Sun.COM * 5*10023SGordon.Ross@Sun.COM * Redistribution and use in source and binary forms, with or without 6*10023SGordon.Ross@Sun.COM * modification, are permitted provided that the following conditions 7*10023SGordon.Ross@Sun.COM * are met: 8*10023SGordon.Ross@Sun.COM * 1. Redistributions of source code must retain the above copyright 9*10023SGordon.Ross@Sun.COM * notice, this list of conditions and the following disclaimer. 10*10023SGordon.Ross@Sun.COM * 2. Redistributions in binary form must reproduce the above copyright 11*10023SGordon.Ross@Sun.COM * notice, this list of conditions and the following disclaimer in the 12*10023SGordon.Ross@Sun.COM * documentation and/or other materials provided with the distribution. 13*10023SGordon.Ross@Sun.COM * 3. All advertising materials mentioning features or use of this software 14*10023SGordon.Ross@Sun.COM * must display the following acknowledgement: 15*10023SGordon.Ross@Sun.COM * This product includes software developed by Boris Popov. 16*10023SGordon.Ross@Sun.COM * 4. Neither the name of the author nor the names of any co-contributors 17*10023SGordon.Ross@Sun.COM * may be used to endorse or promote products derived from this software 18*10023SGordon.Ross@Sun.COM * without specific prior written permission. 19*10023SGordon.Ross@Sun.COM * 20*10023SGordon.Ross@Sun.COM * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND 21*10023SGordon.Ross@Sun.COM * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 22*10023SGordon.Ross@Sun.COM * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE 23*10023SGordon.Ross@Sun.COM * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE 24*10023SGordon.Ross@Sun.COM * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL 25*10023SGordon.Ross@Sun.COM * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS 26*10023SGordon.Ross@Sun.COM * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) 27*10023SGordon.Ross@Sun.COM * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT 28*10023SGordon.Ross@Sun.COM * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY 29*10023SGordon.Ross@Sun.COM * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF 30*10023SGordon.Ross@Sun.COM * SUCH DAMAGE. 31*10023SGordon.Ross@Sun.COM */ 32*10023SGordon.Ross@Sun.COM 33*10023SGordon.Ross@Sun.COM /* 34*10023SGordon.Ross@Sun.COM * Copyright 2009 Sun Microsystems, Inc. All rights reserved. 35*10023SGordon.Ross@Sun.COM * Use is subject to license terms. 36*10023SGordon.Ross@Sun.COM */ 37*10023SGordon.Ross@Sun.COM 38*10023SGordon.Ross@Sun.COM /* 39*10023SGordon.Ross@Sun.COM * SMB Negotiate Protocol, and related. 40*10023SGordon.Ross@Sun.COM * Copied from the driver: smb_smb.c 41*10023SGordon.Ross@Sun.COM */ 42*10023SGordon.Ross@Sun.COM 43*10023SGordon.Ross@Sun.COM #include <errno.h> 44*10023SGordon.Ross@Sun.COM #include <stdio.h> 45*10023SGordon.Ross@Sun.COM #include <stdlib.h> 46*10023SGordon.Ross@Sun.COM #include <unistd.h> 47*10023SGordon.Ross@Sun.COM #include <strings.h> 48*10023SGordon.Ross@Sun.COM #include <netdb.h> 49*10023SGordon.Ross@Sun.COM #include <libintl.h> 50*10023SGordon.Ross@Sun.COM #include <xti.h> 51*10023SGordon.Ross@Sun.COM #include <assert.h> 52*10023SGordon.Ross@Sun.COM 53*10023SGordon.Ross@Sun.COM #include <sys/types.h> 54*10023SGordon.Ross@Sun.COM #include <sys/time.h> 55*10023SGordon.Ross@Sun.COM #include <sys/byteorder.h> 56*10023SGordon.Ross@Sun.COM #include <sys/socket.h> 57*10023SGordon.Ross@Sun.COM #include <sys/fcntl.h> 58*10023SGordon.Ross@Sun.COM 59*10023SGordon.Ross@Sun.COM #include <netinet/in.h> 60*10023SGordon.Ross@Sun.COM #include <netinet/tcp.h> 61*10023SGordon.Ross@Sun.COM #include <arpa/inet.h> 62*10023SGordon.Ross@Sun.COM 63*10023SGordon.Ross@Sun.COM #include <netsmb/smb.h> 64*10023SGordon.Ross@Sun.COM #include <netsmb/smb_lib.h> 65*10023SGordon.Ross@Sun.COM #include <netsmb/netbios.h> 66*10023SGordon.Ross@Sun.COM #include <netsmb/nb_lib.h> 67*10023SGordon.Ross@Sun.COM #include <netsmb/smb_dev.h> 68*10023SGordon.Ross@Sun.COM 69*10023SGordon.Ross@Sun.COM #include "charsets.h" 70*10023SGordon.Ross@Sun.COM #include "private.h" 71*10023SGordon.Ross@Sun.COM 72*10023SGordon.Ross@Sun.COM /* 73*10023SGordon.Ross@Sun.COM * SMB dialects that we know about. 74*10023SGordon.Ross@Sun.COM */ 75*10023SGordon.Ross@Sun.COM struct smb_dialect { 76*10023SGordon.Ross@Sun.COM int d_id; 77*10023SGordon.Ross@Sun.COM const char *d_name; 78*10023SGordon.Ross@Sun.COM }; 79*10023SGordon.Ross@Sun.COM static struct smb_dialect smb_dialects[] = { 80*10023SGordon.Ross@Sun.COM {SMB_DIALECT_CORE, "PC NETWORK PROGRAM 1.0"}, 81*10023SGordon.Ross@Sun.COM {SMB_DIALECT_LANMAN1_0, "LANMAN1.0"}, 82*10023SGordon.Ross@Sun.COM {SMB_DIALECT_LANMAN2_0, "LM1.2X002"}, 83*10023SGordon.Ross@Sun.COM {SMB_DIALECT_LANMAN2_1, "LANMAN2.1"}, 84*10023SGordon.Ross@Sun.COM {SMB_DIALECT_NTLM0_12, "NT LM 0.12"}, 85*10023SGordon.Ross@Sun.COM {-1, NULL} 86*10023SGordon.Ross@Sun.COM }; 87*10023SGordon.Ross@Sun.COM 88*10023SGordon.Ross@Sun.COM #define SMB_DIALECT_MAX \ 89*10023SGordon.Ross@Sun.COM (sizeof (smb_dialects) / sizeof (struct smb_dialect) - 2) 90*10023SGordon.Ross@Sun.COM 91*10023SGordon.Ross@Sun.COM /* 92*10023SGordon.Ross@Sun.COM * SMB Negotiate Protocol 93*10023SGordon.Ross@Sun.COM * Based on code from the driver: smb_smb.c 94*10023SGordon.Ross@Sun.COM * 95*10023SGordon.Ross@Sun.COM * If using Extended Security, oblob (output) 96*10023SGordon.Ross@Sun.COM * will hold the initial security "hint". 97*10023SGordon.Ross@Sun.COM */ 98*10023SGordon.Ross@Sun.COM int 99*10023SGordon.Ross@Sun.COM smb_negprot(struct smb_ctx *ctx, struct mbdata *oblob) 100*10023SGordon.Ross@Sun.COM { 101*10023SGordon.Ross@Sun.COM struct smb_sopt *sv = &ctx->ct_sopt; 102*10023SGordon.Ross@Sun.COM struct smb_iods *is = &ctx->ct_iods; 103*10023SGordon.Ross@Sun.COM struct smb_rq *rqp; 104*10023SGordon.Ross@Sun.COM struct mbdata *mbp; 105*10023SGordon.Ross@Sun.COM struct smb_dialect *dp; 106*10023SGordon.Ross@Sun.COM int err, len; 107*10023SGordon.Ross@Sun.COM uint8_t wc, stime[8], eklen; 108*10023SGordon.Ross@Sun.COM uint16_t dindex, bc; 109*10023SGordon.Ross@Sun.COM int will_sign = 0; 110*10023SGordon.Ross@Sun.COM 111*10023SGordon.Ross@Sun.COM /* 112*10023SGordon.Ross@Sun.COM * Initialize: vc_hflags and vc_hflags2. 113*10023SGordon.Ross@Sun.COM * Note: ctx->ct_hflags* are copied into the 114*10023SGordon.Ross@Sun.COM * (per request) rqp->rq_hflags* by smb_rq_init, 115*10023SGordon.Ross@Sun.COM * so changing them after that call will not 116*10023SGordon.Ross@Sun.COM * affect THIS request. 117*10023SGordon.Ross@Sun.COM */ 118*10023SGordon.Ross@Sun.COM ctx->ct_hflags = SMB_FLAGS_CASELESS; 119*10023SGordon.Ross@Sun.COM ctx->ct_hflags2 = (SMB_FLAGS2_ERR_STATUS | 120*10023SGordon.Ross@Sun.COM SMB_FLAGS2_KNOWS_LONG_NAMES); 121*10023SGordon.Ross@Sun.COM 122*10023SGordon.Ross@Sun.COM /* 123*10023SGordon.Ross@Sun.COM * Sould we offer extended security? 124*10023SGordon.Ross@Sun.COM * We'll turn this back off below if 125*10023SGordon.Ross@Sun.COM * the server doesn't support it. 126*10023SGordon.Ross@Sun.COM */ 127*10023SGordon.Ross@Sun.COM if (ctx->ct_vopt & SMBVOPT_EXT_SEC) 128*10023SGordon.Ross@Sun.COM ctx->ct_hflags2 |= SMB_FLAGS2_EXT_SEC; 129*10023SGordon.Ross@Sun.COM 130*10023SGordon.Ross@Sun.COM /* 131*10023SGordon.Ross@Sun.COM * The initial UID needs to be zero, 132*10023SGordon.Ross@Sun.COM * or Windows XP says "bad user". 133*10023SGordon.Ross@Sun.COM * The initial TID is all ones, but 134*10023SGordon.Ross@Sun.COM * we don't use it or store it here 135*10023SGordon.Ross@Sun.COM * because the driver handles that. 136*10023SGordon.Ross@Sun.COM */ 137*10023SGordon.Ross@Sun.COM is->is_smbuid = 0; 138*10023SGordon.Ross@Sun.COM 139*10023SGordon.Ross@Sun.COM /* 140*10023SGordon.Ross@Sun.COM * In case we're reconnecting, 141*10023SGordon.Ross@Sun.COM * free previous stuff. 142*10023SGordon.Ross@Sun.COM */ 143*10023SGordon.Ross@Sun.COM ctx->ct_mac_seqno = 0; 144*10023SGordon.Ross@Sun.COM if (ctx->ct_mackey != NULL) { 145*10023SGordon.Ross@Sun.COM free(ctx->ct_mackey); 146*10023SGordon.Ross@Sun.COM ctx->ct_mackey = NULL; 147*10023SGordon.Ross@Sun.COM ctx->ct_mackeylen = 0; 148*10023SGordon.Ross@Sun.COM } 149*10023SGordon.Ross@Sun.COM 150*10023SGordon.Ross@Sun.COM sv = &ctx->ct_sopt; 151*10023SGordon.Ross@Sun.COM bzero(sv, sizeof (struct smb_sopt)); 152*10023SGordon.Ross@Sun.COM 153*10023SGordon.Ross@Sun.COM err = smb_rq_init(ctx, SMB_COM_NEGOTIATE, &rqp); 154*10023SGordon.Ross@Sun.COM if (err) 155*10023SGordon.Ross@Sun.COM return (err); 156*10023SGordon.Ross@Sun.COM 157*10023SGordon.Ross@Sun.COM /* 158*10023SGordon.Ross@Sun.COM * Build the SMB request. 159*10023SGordon.Ross@Sun.COM */ 160*10023SGordon.Ross@Sun.COM mbp = &rqp->rq_rq; 161*10023SGordon.Ross@Sun.COM mb_put_uint8(mbp, 0); /* word count */ 162*10023SGordon.Ross@Sun.COM smb_rq_bstart(rqp); 163*10023SGordon.Ross@Sun.COM for (dp = smb_dialects; dp->d_id != -1; dp++) { 164*10023SGordon.Ross@Sun.COM mb_put_uint8(mbp, SMB_DT_DIALECT); 165*10023SGordon.Ross@Sun.COM mb_put_astring(mbp, dp->d_name); 166*10023SGordon.Ross@Sun.COM } 167*10023SGordon.Ross@Sun.COM smb_rq_bend(rqp); 168*10023SGordon.Ross@Sun.COM 169*10023SGordon.Ross@Sun.COM /* 170*10023SGordon.Ross@Sun.COM * This does the OTW call 171*10023SGordon.Ross@Sun.COM */ 172*10023SGordon.Ross@Sun.COM err = smb_rq_internal(ctx, rqp); 173*10023SGordon.Ross@Sun.COM if (err) { 174*10023SGordon.Ross@Sun.COM DPRINT("call failed, err %d", err); 175*10023SGordon.Ross@Sun.COM goto errout; 176*10023SGordon.Ross@Sun.COM } 177*10023SGordon.Ross@Sun.COM if (rqp->rq_status != 0) { 178*10023SGordon.Ross@Sun.COM DPRINT("nt status 0x%x", rqp->rq_status); 179*10023SGordon.Ross@Sun.COM err = EBADRPC; 180*10023SGordon.Ross@Sun.COM goto errout; 181*10023SGordon.Ross@Sun.COM } 182*10023SGordon.Ross@Sun.COM 183*10023SGordon.Ross@Sun.COM /* 184*10023SGordon.Ross@Sun.COM * Decode the response 185*10023SGordon.Ross@Sun.COM * 186*10023SGordon.Ross@Sun.COM * Comments to right show names as described in 187*10023SGordon.Ross@Sun.COM * The Microsoft SMB Protocol spec. [MS-SMB] 188*10023SGordon.Ross@Sun.COM * section 2.2.3 189*10023SGordon.Ross@Sun.COM */ 190*10023SGordon.Ross@Sun.COM mbp = &rqp->rq_rp; 191*10023SGordon.Ross@Sun.COM (void) mb_get_uint8(mbp, &wc); 192*10023SGordon.Ross@Sun.COM err = mb_get_uint16le(mbp, &dindex); 193*10023SGordon.Ross@Sun.COM if (err || dindex > SMB_DIALECT_MAX) { 194*10023SGordon.Ross@Sun.COM DPRINT("err %d dindex %d", err, (int)dindex); 195*10023SGordon.Ross@Sun.COM goto errout; 196*10023SGordon.Ross@Sun.COM } 197*10023SGordon.Ross@Sun.COM dp = smb_dialects + dindex; 198*10023SGordon.Ross@Sun.COM sv->sv_proto = dp->d_id; 199*10023SGordon.Ross@Sun.COM DPRINT("Dialect %s", dp->d_name); 200*10023SGordon.Ross@Sun.COM if (dp->d_id < SMB_DIALECT_NTLM0_12) { 201*10023SGordon.Ross@Sun.COM /* XXX: User-visible warning too? */ 202*10023SGordon.Ross@Sun.COM DPRINT("old dialect %s", dp->d_name); 203*10023SGordon.Ross@Sun.COM goto errout; 204*10023SGordon.Ross@Sun.COM } 205*10023SGordon.Ross@Sun.COM if (wc != 17) { 206*10023SGordon.Ross@Sun.COM DPRINT("bad wc %d", (int)wc); 207*10023SGordon.Ross@Sun.COM goto errout; 208*10023SGordon.Ross@Sun.COM } 209*10023SGordon.Ross@Sun.COM mb_get_uint8(mbp, &sv->sv_sm); /* SecurityMode */ 210*10023SGordon.Ross@Sun.COM mb_get_uint16le(mbp, &sv->sv_maxmux); /* MaxMpxCount */ 211*10023SGordon.Ross@Sun.COM mb_get_uint16le(mbp, &sv->sv_maxvcs); /* MaxCountVCs */ 212*10023SGordon.Ross@Sun.COM mb_get_uint32le(mbp, &sv->sv_maxtx); /* MaxBufferSize */ 213*10023SGordon.Ross@Sun.COM mb_get_uint32le(mbp, &sv->sv_maxraw); /* MaxRawSize */ 214*10023SGordon.Ross@Sun.COM mb_get_uint32le(mbp, &sv->sv_skey); /* SessionKey */ 215*10023SGordon.Ross@Sun.COM mb_get_uint32le(mbp, &sv->sv_caps); /* Capabilities */ 216*10023SGordon.Ross@Sun.COM mb_get_mem(mbp, (char *)stime, 8); /* SystemTime(s) */ 217*10023SGordon.Ross@Sun.COM mb_get_uint16le(mbp, (uint16_t *)&sv->sv_tz); 218*10023SGordon.Ross@Sun.COM mb_get_uint8(mbp, &eklen); /* EncryptionKeyLength */ 219*10023SGordon.Ross@Sun.COM err = mb_get_uint16le(mbp, &bc); /* ByteCount */ 220*10023SGordon.Ross@Sun.COM if (err) 221*10023SGordon.Ross@Sun.COM goto errout; 222*10023SGordon.Ross@Sun.COM 223*10023SGordon.Ross@Sun.COM /* BEGIN CSTYLED */ 224*10023SGordon.Ross@Sun.COM /* 225*10023SGordon.Ross@Sun.COM * Will we do SMB signing? Or block the connection? 226*10023SGordon.Ross@Sun.COM * The table below describes this logic. References: 227*10023SGordon.Ross@Sun.COM * [Windows Server Protocols: MS-SMB, sec. 3.2.4.2.3] 228*10023SGordon.Ross@Sun.COM * http://msdn.microsoft.com/en-us/library/cc212511.aspx 229*10023SGordon.Ross@Sun.COM * http://msdn.microsoft.com/en-us/library/cc212929.aspx 230*10023SGordon.Ross@Sun.COM * 231*10023SGordon.Ross@Sun.COM * Srv/Cli | Required | Enabled | If Required | Disabled 232*10023SGordon.Ross@Sun.COM * ------------+----------+------------+-------------+----------- 233*10023SGordon.Ross@Sun.COM * Required | Signed | Signed | Signed | Blocked [1] 234*10023SGordon.Ross@Sun.COM * ------------+----------+------------+-------------+----------- 235*10023SGordon.Ross@Sun.COM * Enabled | Signed | Signed | Not Signed | Not Signed 236*10023SGordon.Ross@Sun.COM * ------------+----------+------------+-------------+----------- 237*10023SGordon.Ross@Sun.COM * If Required | Signed | Not Signed | Not Signed | Not Signed 238*10023SGordon.Ross@Sun.COM * ------------+----------+------------+-------------+----------- 239*10023SGordon.Ross@Sun.COM * Disabled | Blocked | Not Signed | Not Signed | Not Signed 240*10023SGordon.Ross@Sun.COM * 241*10023SGordon.Ross@Sun.COM * [1] Like Windows 2003 and later, we don't really implement 242*10023SGordon.Ross@Sun.COM * the "Disabled" setting. Instead we implement "If Required", 243*10023SGordon.Ross@Sun.COM * so we always sign if the server requires signing. 244*10023SGordon.Ross@Sun.COM */ 245*10023SGordon.Ross@Sun.COM /* END CSTYLED */ 246*10023SGordon.Ross@Sun.COM 247*10023SGordon.Ross@Sun.COM if (sv->sv_sm & SMB_SM_SIGS_REQUIRE) { 248*10023SGordon.Ross@Sun.COM /* 249*10023SGordon.Ross@Sun.COM * Server requires signing. We will sign, 250*10023SGordon.Ross@Sun.COM * even if local setting is "disabled". 251*10023SGordon.Ross@Sun.COM */ 252*10023SGordon.Ross@Sun.COM will_sign = 1; 253*10023SGordon.Ross@Sun.COM } else if (sv->sv_sm & SMB_SM_SIGS) { 254*10023SGordon.Ross@Sun.COM /* 255*10023SGordon.Ross@Sun.COM * Server enables signing (client's option). 256*10023SGordon.Ross@Sun.COM * If enabled locally, do signing. 257*10023SGordon.Ross@Sun.COM */ 258*10023SGordon.Ross@Sun.COM if (ctx->ct_vopt & SMBVOPT_SIGNING_ENABLED) 259*10023SGordon.Ross@Sun.COM will_sign = 1; 260*10023SGordon.Ross@Sun.COM /* else not signing. */ 261*10023SGordon.Ross@Sun.COM } else { 262*10023SGordon.Ross@Sun.COM /* 263*10023SGordon.Ross@Sun.COM * Server does not support signing. 264*10023SGordon.Ross@Sun.COM * If we "require" it, bail now. 265*10023SGordon.Ross@Sun.COM */ 266*10023SGordon.Ross@Sun.COM if (ctx->ct_vopt & SMBVOPT_SIGNING_REQUIRED) { 267*10023SGordon.Ross@Sun.COM DPRINT("Client requires signing " 268*10023SGordon.Ross@Sun.COM "but server has it disabled."); 269*10023SGordon.Ross@Sun.COM err = EBADRPC; 270*10023SGordon.Ross@Sun.COM goto errout; 271*10023SGordon.Ross@Sun.COM } 272*10023SGordon.Ross@Sun.COM } 273*10023SGordon.Ross@Sun.COM 274*10023SGordon.Ross@Sun.COM if (will_sign) { 275*10023SGordon.Ross@Sun.COM ctx->ct_vcflags |= SMBV_WILL_SIGN; 276*10023SGordon.Ross@Sun.COM } 277*10023SGordon.Ross@Sun.COM DPRINT("Security signatures: %d", will_sign); 278*10023SGordon.Ross@Sun.COM 279*10023SGordon.Ross@Sun.COM if (sv->sv_caps & SMB_CAP_UNICODE) { 280*10023SGordon.Ross@Sun.COM ctx->ct_vcflags |= SMBV_UNICODE; 281*10023SGordon.Ross@Sun.COM ctx->ct_hflags2 |= SMB_FLAGS2_UNICODE; 282*10023SGordon.Ross@Sun.COM 283*10023SGordon.Ross@Sun.COM } 284*10023SGordon.Ross@Sun.COM if ((sv->sv_caps & SMB_CAP_STATUS32) == 0) { 285*10023SGordon.Ross@Sun.COM /* 286*10023SGordon.Ross@Sun.COM * They don't do NT error codes. 287*10023SGordon.Ross@Sun.COM * 288*10023SGordon.Ross@Sun.COM * If we send requests with 289*10023SGordon.Ross@Sun.COM * SMB_FLAGS2_ERR_STATUS set in 290*10023SGordon.Ross@Sun.COM * Flags2, Windows 98, at least, 291*10023SGordon.Ross@Sun.COM * appears to send replies with that 292*10023SGordon.Ross@Sun.COM * bit set even though it sends back 293*10023SGordon.Ross@Sun.COM * DOS error codes. (They probably 294*10023SGordon.Ross@Sun.COM * just use the request header as 295*10023SGordon.Ross@Sun.COM * a template for the reply header, 296*10023SGordon.Ross@Sun.COM * and don't bother clearing that bit.) 297*10023SGordon.Ross@Sun.COM * 298*10023SGordon.Ross@Sun.COM * Therefore, we clear that bit in 299*10023SGordon.Ross@Sun.COM * our vc_hflags2 field. 300*10023SGordon.Ross@Sun.COM */ 301*10023SGordon.Ross@Sun.COM ctx->ct_hflags2 &= ~SMB_FLAGS2_ERR_STATUS; 302*10023SGordon.Ross@Sun.COM } 303*10023SGordon.Ross@Sun.COM if (dp->d_id == SMB_DIALECT_NTLM0_12 && 304*10023SGordon.Ross@Sun.COM sv->sv_maxtx < 4096 && 305*10023SGordon.Ross@Sun.COM (sv->sv_caps & SMB_CAP_NT_SMBS) == 0) { 306*10023SGordon.Ross@Sun.COM ctx->ct_vcflags |= SMBV_WIN95; 307*10023SGordon.Ross@Sun.COM DPRINT("Win95 detected"); 308*10023SGordon.Ross@Sun.COM } 309*10023SGordon.Ross@Sun.COM 310*10023SGordon.Ross@Sun.COM /* 311*10023SGordon.Ross@Sun.COM * The rest of the message varies depending on 312*10023SGordon.Ross@Sun.COM * whether we've negotiated "extended security". 313*10023SGordon.Ross@Sun.COM * 314*10023SGordon.Ross@Sun.COM * With extended security, we have: 315*10023SGordon.Ross@Sun.COM * Server_GUID (length 16) 316*10023SGordon.Ross@Sun.COM * Security_BLOB 317*10023SGordon.Ross@Sun.COM * Otherwise we have: 318*10023SGordon.Ross@Sun.COM * EncryptionKey (length is eklen) 319*10023SGordon.Ross@Sun.COM * PrimaryDomain 320*10023SGordon.Ross@Sun.COM */ 321*10023SGordon.Ross@Sun.COM if (sv->sv_caps & SMB_CAP_EXT_SECURITY) { 322*10023SGordon.Ross@Sun.COM struct mbuf *m; 323*10023SGordon.Ross@Sun.COM DPRINT("Ext.Security: yes"); 324*10023SGordon.Ross@Sun.COM 325*10023SGordon.Ross@Sun.COM /* 326*10023SGordon.Ross@Sun.COM * Skip the server GUID. 327*10023SGordon.Ross@Sun.COM */ 328*10023SGordon.Ross@Sun.COM err = mb_get_mem(mbp, NULL, SMB_GUIDLEN); 329*10023SGordon.Ross@Sun.COM if (err) 330*10023SGordon.Ross@Sun.COM goto errout; 331*10023SGordon.Ross@Sun.COM /* 332*10023SGordon.Ross@Sun.COM * Remainder is the security blob. 333*10023SGordon.Ross@Sun.COM * Note: eklen "must be ignored" [MS-SMB] 334*10023SGordon.Ross@Sun.COM */ 335*10023SGordon.Ross@Sun.COM len = (int)bc - SMB_GUIDLEN; 336*10023SGordon.Ross@Sun.COM if (len < 0) 337*10023SGordon.Ross@Sun.COM goto errout; 338*10023SGordon.Ross@Sun.COM 339*10023SGordon.Ross@Sun.COM /* 340*10023SGordon.Ross@Sun.COM * Get the (optional) SPNEGO "hint". 341*10023SGordon.Ross@Sun.COM */ 342*10023SGordon.Ross@Sun.COM err = mb_get_mbuf(mbp, len, &m); 343*10023SGordon.Ross@Sun.COM if (err) 344*10023SGordon.Ross@Sun.COM goto errout; 345*10023SGordon.Ross@Sun.COM mb_initm(oblob, m); 346*10023SGordon.Ross@Sun.COM oblob->mb_count = len; 347*10023SGordon.Ross@Sun.COM } else { 348*10023SGordon.Ross@Sun.COM DPRINT("Ext.Security: no"); 349*10023SGordon.Ross@Sun.COM ctx->ct_hflags2 &= ~SMB_FLAGS2_EXT_SEC; 350*10023SGordon.Ross@Sun.COM 351*10023SGordon.Ross@Sun.COM /* 352*10023SGordon.Ross@Sun.COM * Save the "Encryption Key" (the challenge). 353*10023SGordon.Ross@Sun.COM * 354*10023SGordon.Ross@Sun.COM * Sanity check: make sure the sec. blob length 355*10023SGordon.Ross@Sun.COM * isn't bigger than the byte count. 356*10023SGordon.Ross@Sun.COM */ 357*10023SGordon.Ross@Sun.COM if (bc < eklen || eklen < NTLM_CHAL_SZ) { 358*10023SGordon.Ross@Sun.COM err = EBADRPC; 359*10023SGordon.Ross@Sun.COM goto errout; 360*10023SGordon.Ross@Sun.COM } 361*10023SGordon.Ross@Sun.COM err = mb_get_mem(mbp, (char *)ctx->ct_ntlm_chal, NTLM_CHAL_SZ); 362*10023SGordon.Ross@Sun.COM /* 363*10023SGordon.Ross@Sun.COM * Server domain follows (ignored) 364*10023SGordon.Ross@Sun.COM * Note: NOT aligned(2) - unusual! 365*10023SGordon.Ross@Sun.COM */ 366*10023SGordon.Ross@Sun.COM } 367*10023SGordon.Ross@Sun.COM 368*10023SGordon.Ross@Sun.COM smb_rq_done(rqp); 369*10023SGordon.Ross@Sun.COM 370*10023SGordon.Ross@Sun.COM /* 371*10023SGordon.Ross@Sun.COM * A few sanity checks on what we received, 372*10023SGordon.Ross@Sun.COM * becuse we will send these in ssnsetup. 373*10023SGordon.Ross@Sun.COM * 374*10023SGordon.Ross@Sun.COM * Maximum outstanding requests (we care), 375*10023SGordon.Ross@Sun.COM * and Max. VCs (we only use one). Also, 376*10023SGordon.Ross@Sun.COM * MaxBufferSize lower limit per spec. 377*10023SGordon.Ross@Sun.COM */ 378*10023SGordon.Ross@Sun.COM if (sv->sv_maxmux < 1) 379*10023SGordon.Ross@Sun.COM sv->sv_maxmux = 1; 380*10023SGordon.Ross@Sun.COM if (sv->sv_maxvcs < 1) 381*10023SGordon.Ross@Sun.COM sv->sv_maxvcs = 1; 382*10023SGordon.Ross@Sun.COM if (sv->sv_maxtx < 1024) 383*10023SGordon.Ross@Sun.COM sv->sv_maxtx = 1024; 384*10023SGordon.Ross@Sun.COM 385*10023SGordon.Ross@Sun.COM /* 386*10023SGordon.Ross@Sun.COM * Maximum transfer size. 387*10023SGordon.Ross@Sun.COM * Sanity checks: 388*10023SGordon.Ross@Sun.COM * 389*10023SGordon.Ross@Sun.COM * Let's be conservative about an upper limit here. 390*10023SGordon.Ross@Sun.COM * Win2k uses 16644 (and others) so 32k should be a 391*10023SGordon.Ross@Sun.COM * reasonable sanity limit for this value. 392*10023SGordon.Ross@Sun.COM * 393*10023SGordon.Ross@Sun.COM * Note that this limit does NOT affect READX/WRITEX 394*10023SGordon.Ross@Sun.COM * with CAP_LARGE_..., which we nearly always use. 395*10023SGordon.Ross@Sun.COM */ 396*10023SGordon.Ross@Sun.COM is->is_txmax = sv->sv_maxtx; 397*10023SGordon.Ross@Sun.COM if (is->is_txmax > 0x8000) 398*10023SGordon.Ross@Sun.COM is->is_txmax = 0x8000; 399*10023SGordon.Ross@Sun.COM 400*10023SGordon.Ross@Sun.COM /* 401*10023SGordon.Ross@Sun.COM * Max read/write sizes, WITHOUT overhead. 402*10023SGordon.Ross@Sun.COM * This is just the payload size, so we must 403*10023SGordon.Ross@Sun.COM * leave room for the SMB headers, etc. 404*10023SGordon.Ross@Sun.COM * This is just the ct_txmax value, but 405*10023SGordon.Ross@Sun.COM * reduced and rounded down. Tricky bit: 406*10023SGordon.Ross@Sun.COM * 407*10023SGordon.Ross@Sun.COM * Servers typically give us a value that's 408*10023SGordon.Ross@Sun.COM * some nice "round" number, i.e 0x4000 plus 409*10023SGordon.Ross@Sun.COM * some overhead, i.e. Win2k: 16644==0x4104 410*10023SGordon.Ross@Sun.COM * Subtract for the SMB header (32) and the 411*10023SGordon.Ross@Sun.COM * SMB command word and byte vectors (34?), 412*10023SGordon.Ross@Sun.COM * then round down to a 512 byte multiple. 413*10023SGordon.Ross@Sun.COM */ 414*10023SGordon.Ross@Sun.COM len = is->is_txmax - 68; 415*10023SGordon.Ross@Sun.COM len &= 0xFE00; 416*10023SGordon.Ross@Sun.COM /* XXX: Not sure yet which of these to keep. */ 417*10023SGordon.Ross@Sun.COM is->is_rwmax = len; 418*10023SGordon.Ross@Sun.COM is->is_rxmax = len; 419*10023SGordon.Ross@Sun.COM is->is_wxmax = len; 420*10023SGordon.Ross@Sun.COM 421*10023SGordon.Ross@Sun.COM return (0); 422*10023SGordon.Ross@Sun.COM 423*10023SGordon.Ross@Sun.COM errout: 424*10023SGordon.Ross@Sun.COM smb_rq_done(rqp); 425*10023SGordon.Ross@Sun.COM if (err == 0) 426*10023SGordon.Ross@Sun.COM err = EBADRPC; 427*10023SGordon.Ross@Sun.COM return (err); 428*10023SGordon.Ross@Sun.COM } 429