110023SGordon.Ross@Sun.COM /* 210023SGordon.Ross@Sun.COM * Copyright (c) 2000-2001 Boris Popov 310023SGordon.Ross@Sun.COM * All rights reserved. 410023SGordon.Ross@Sun.COM * 510023SGordon.Ross@Sun.COM * Redistribution and use in source and binary forms, with or without 610023SGordon.Ross@Sun.COM * modification, are permitted provided that the following conditions 710023SGordon.Ross@Sun.COM * are met: 810023SGordon.Ross@Sun.COM * 1. Redistributions of source code must retain the above copyright 910023SGordon.Ross@Sun.COM * notice, this list of conditions and the following disclaimer. 1010023SGordon.Ross@Sun.COM * 2. Redistributions in binary form must reproduce the above copyright 1110023SGordon.Ross@Sun.COM * notice, this list of conditions and the following disclaimer in the 1210023SGordon.Ross@Sun.COM * documentation and/or other materials provided with the distribution. 1310023SGordon.Ross@Sun.COM * 3. All advertising materials mentioning features or use of this software 1410023SGordon.Ross@Sun.COM * must display the following acknowledgement: 1510023SGordon.Ross@Sun.COM * This product includes software developed by Boris Popov. 1610023SGordon.Ross@Sun.COM * 4. Neither the name of the author nor the names of any co-contributors 1710023SGordon.Ross@Sun.COM * may be used to endorse or promote products derived from this software 1810023SGordon.Ross@Sun.COM * without specific prior written permission. 1910023SGordon.Ross@Sun.COM * 2010023SGordon.Ross@Sun.COM * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND 2110023SGordon.Ross@Sun.COM * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 2210023SGordon.Ross@Sun.COM * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE 2310023SGordon.Ross@Sun.COM * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE 2410023SGordon.Ross@Sun.COM * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL 2510023SGordon.Ross@Sun.COM * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS 2610023SGordon.Ross@Sun.COM * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) 2710023SGordon.Ross@Sun.COM * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT 2810023SGordon.Ross@Sun.COM * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY 2910023SGordon.Ross@Sun.COM * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF 3010023SGordon.Ross@Sun.COM * SUCH DAMAGE. 3110023SGordon.Ross@Sun.COM */ 3210023SGordon.Ross@Sun.COM 3310023SGordon.Ross@Sun.COM /* 3410023SGordon.Ross@Sun.COM * Copyright 2009 Sun Microsystems, Inc. All rights reserved. 3510023SGordon.Ross@Sun.COM * Use is subject to license terms. 3610023SGordon.Ross@Sun.COM */ 3710023SGordon.Ross@Sun.COM 3810023SGordon.Ross@Sun.COM /* 3910023SGordon.Ross@Sun.COM * SMB Negotiate Protocol, and related. 4010023SGordon.Ross@Sun.COM * Copied from the driver: smb_smb.c 4110023SGordon.Ross@Sun.COM */ 4210023SGordon.Ross@Sun.COM 4310023SGordon.Ross@Sun.COM #include <errno.h> 4410023SGordon.Ross@Sun.COM #include <stdio.h> 4510023SGordon.Ross@Sun.COM #include <stdlib.h> 4610023SGordon.Ross@Sun.COM #include <unistd.h> 4710023SGordon.Ross@Sun.COM #include <strings.h> 4810023SGordon.Ross@Sun.COM #include <netdb.h> 4910023SGordon.Ross@Sun.COM #include <libintl.h> 5010023SGordon.Ross@Sun.COM #include <xti.h> 5110023SGordon.Ross@Sun.COM #include <assert.h> 5210023SGordon.Ross@Sun.COM 5310023SGordon.Ross@Sun.COM #include <sys/types.h> 5410023SGordon.Ross@Sun.COM #include <sys/time.h> 5510023SGordon.Ross@Sun.COM #include <sys/byteorder.h> 5610023SGordon.Ross@Sun.COM #include <sys/socket.h> 5710023SGordon.Ross@Sun.COM #include <sys/fcntl.h> 5810023SGordon.Ross@Sun.COM 5910023SGordon.Ross@Sun.COM #include <netinet/in.h> 6010023SGordon.Ross@Sun.COM #include <netinet/tcp.h> 6110023SGordon.Ross@Sun.COM #include <arpa/inet.h> 6210023SGordon.Ross@Sun.COM 6310023SGordon.Ross@Sun.COM #include <netsmb/smb.h> 6410023SGordon.Ross@Sun.COM #include <netsmb/smb_lib.h> 6510023SGordon.Ross@Sun.COM #include <netsmb/netbios.h> 6610023SGordon.Ross@Sun.COM #include <netsmb/nb_lib.h> 6710023SGordon.Ross@Sun.COM #include <netsmb/smb_dev.h> 6810023SGordon.Ross@Sun.COM 6910023SGordon.Ross@Sun.COM #include "charsets.h" 7010023SGordon.Ross@Sun.COM #include "private.h" 7110023SGordon.Ross@Sun.COM 7210023SGordon.Ross@Sun.COM /* 7310023SGordon.Ross@Sun.COM * SMB dialects that we know about. 7410023SGordon.Ross@Sun.COM */ 7510023SGordon.Ross@Sun.COM struct smb_dialect { 7610023SGordon.Ross@Sun.COM int d_id; 7710023SGordon.Ross@Sun.COM const char *d_name; 7810023SGordon.Ross@Sun.COM }; 7910023SGordon.Ross@Sun.COM static struct smb_dialect smb_dialects[] = { 8010023SGordon.Ross@Sun.COM {SMB_DIALECT_CORE, "PC NETWORK PROGRAM 1.0"}, 8110023SGordon.Ross@Sun.COM {SMB_DIALECT_LANMAN1_0, "LANMAN1.0"}, 8210023SGordon.Ross@Sun.COM {SMB_DIALECT_LANMAN2_0, "LM1.2X002"}, 8310023SGordon.Ross@Sun.COM {SMB_DIALECT_LANMAN2_1, "LANMAN2.1"}, 8410023SGordon.Ross@Sun.COM {SMB_DIALECT_NTLM0_12, "NT LM 0.12"}, 8510023SGordon.Ross@Sun.COM {-1, NULL} 8610023SGordon.Ross@Sun.COM }; 8710023SGordon.Ross@Sun.COM 8810023SGordon.Ross@Sun.COM #define SMB_DIALECT_MAX \ 8910023SGordon.Ross@Sun.COM (sizeof (smb_dialects) / sizeof (struct smb_dialect) - 2) 9010023SGordon.Ross@Sun.COM 9110023SGordon.Ross@Sun.COM /* 9210023SGordon.Ross@Sun.COM * SMB Negotiate Protocol 9310023SGordon.Ross@Sun.COM * Based on code from the driver: smb_smb.c 9410023SGordon.Ross@Sun.COM * 9510023SGordon.Ross@Sun.COM * If using Extended Security, oblob (output) 9610023SGordon.Ross@Sun.COM * will hold the initial security "hint". 9710023SGordon.Ross@Sun.COM */ 9810023SGordon.Ross@Sun.COM int 9910023SGordon.Ross@Sun.COM smb_negprot(struct smb_ctx *ctx, struct mbdata *oblob) 10010023SGordon.Ross@Sun.COM { 10110023SGordon.Ross@Sun.COM struct smb_sopt *sv = &ctx->ct_sopt; 10210023SGordon.Ross@Sun.COM struct smb_iods *is = &ctx->ct_iods; 10310023SGordon.Ross@Sun.COM struct smb_rq *rqp; 10410023SGordon.Ross@Sun.COM struct mbdata *mbp; 10510023SGordon.Ross@Sun.COM struct smb_dialect *dp; 10610023SGordon.Ross@Sun.COM int err, len; 107*11332SGordon.Ross@Sun.COM uint8_t wc, eklen; 10810023SGordon.Ross@Sun.COM uint16_t dindex, bc; 10910023SGordon.Ross@Sun.COM int will_sign = 0; 11010023SGordon.Ross@Sun.COM 11110023SGordon.Ross@Sun.COM /* 11210023SGordon.Ross@Sun.COM * Initialize: vc_hflags and vc_hflags2. 11310023SGordon.Ross@Sun.COM * Note: ctx->ct_hflags* are copied into the 11410023SGordon.Ross@Sun.COM * (per request) rqp->rq_hflags* by smb_rq_init, 11510023SGordon.Ross@Sun.COM * so changing them after that call will not 11610023SGordon.Ross@Sun.COM * affect THIS request. 11710023SGordon.Ross@Sun.COM */ 11810023SGordon.Ross@Sun.COM ctx->ct_hflags = SMB_FLAGS_CASELESS; 11910023SGordon.Ross@Sun.COM ctx->ct_hflags2 = (SMB_FLAGS2_ERR_STATUS | 12010023SGordon.Ross@Sun.COM SMB_FLAGS2_KNOWS_LONG_NAMES); 12110023SGordon.Ross@Sun.COM 12210023SGordon.Ross@Sun.COM /* 12310023SGordon.Ross@Sun.COM * Sould we offer extended security? 12410023SGordon.Ross@Sun.COM * We'll turn this back off below if 12510023SGordon.Ross@Sun.COM * the server doesn't support it. 12610023SGordon.Ross@Sun.COM */ 12710023SGordon.Ross@Sun.COM if (ctx->ct_vopt & SMBVOPT_EXT_SEC) 12810023SGordon.Ross@Sun.COM ctx->ct_hflags2 |= SMB_FLAGS2_EXT_SEC; 12910023SGordon.Ross@Sun.COM 13010023SGordon.Ross@Sun.COM /* 13110023SGordon.Ross@Sun.COM * The initial UID needs to be zero, 13210023SGordon.Ross@Sun.COM * or Windows XP says "bad user". 13310023SGordon.Ross@Sun.COM * The initial TID is all ones, but 13410023SGordon.Ross@Sun.COM * we don't use it or store it here 13510023SGordon.Ross@Sun.COM * because the driver handles that. 13610023SGordon.Ross@Sun.COM */ 13710023SGordon.Ross@Sun.COM is->is_smbuid = 0; 13810023SGordon.Ross@Sun.COM 13910023SGordon.Ross@Sun.COM /* 14010023SGordon.Ross@Sun.COM * In case we're reconnecting, 14110023SGordon.Ross@Sun.COM * free previous stuff. 14210023SGordon.Ross@Sun.COM */ 14310023SGordon.Ross@Sun.COM ctx->ct_mac_seqno = 0; 14410023SGordon.Ross@Sun.COM if (ctx->ct_mackey != NULL) { 14510023SGordon.Ross@Sun.COM free(ctx->ct_mackey); 14610023SGordon.Ross@Sun.COM ctx->ct_mackey = NULL; 14710023SGordon.Ross@Sun.COM ctx->ct_mackeylen = 0; 14810023SGordon.Ross@Sun.COM } 14910023SGordon.Ross@Sun.COM 15010023SGordon.Ross@Sun.COM sv = &ctx->ct_sopt; 15110023SGordon.Ross@Sun.COM bzero(sv, sizeof (struct smb_sopt)); 15210023SGordon.Ross@Sun.COM 15310023SGordon.Ross@Sun.COM err = smb_rq_init(ctx, SMB_COM_NEGOTIATE, &rqp); 15410023SGordon.Ross@Sun.COM if (err) 15510023SGordon.Ross@Sun.COM return (err); 15610023SGordon.Ross@Sun.COM 15710023SGordon.Ross@Sun.COM /* 15810023SGordon.Ross@Sun.COM * Build the SMB request. 15910023SGordon.Ross@Sun.COM */ 16010023SGordon.Ross@Sun.COM mbp = &rqp->rq_rq; 16110023SGordon.Ross@Sun.COM mb_put_uint8(mbp, 0); /* word count */ 16210023SGordon.Ross@Sun.COM smb_rq_bstart(rqp); 16310023SGordon.Ross@Sun.COM for (dp = smb_dialects; dp->d_id != -1; dp++) { 16410023SGordon.Ross@Sun.COM mb_put_uint8(mbp, SMB_DT_DIALECT); 16510023SGordon.Ross@Sun.COM mb_put_astring(mbp, dp->d_name); 16610023SGordon.Ross@Sun.COM } 16710023SGordon.Ross@Sun.COM smb_rq_bend(rqp); 16810023SGordon.Ross@Sun.COM 16910023SGordon.Ross@Sun.COM /* 17010023SGordon.Ross@Sun.COM * This does the OTW call 17110023SGordon.Ross@Sun.COM */ 17210023SGordon.Ross@Sun.COM err = smb_rq_internal(ctx, rqp); 17310023SGordon.Ross@Sun.COM if (err) { 17410023SGordon.Ross@Sun.COM DPRINT("call failed, err %d", err); 17510023SGordon.Ross@Sun.COM goto errout; 17610023SGordon.Ross@Sun.COM } 17710023SGordon.Ross@Sun.COM if (rqp->rq_status != 0) { 17810023SGordon.Ross@Sun.COM DPRINT("nt status 0x%x", rqp->rq_status); 17910023SGordon.Ross@Sun.COM err = EBADRPC; 18010023SGordon.Ross@Sun.COM goto errout; 18110023SGordon.Ross@Sun.COM } 18210023SGordon.Ross@Sun.COM 18310023SGordon.Ross@Sun.COM /* 18410023SGordon.Ross@Sun.COM * Decode the response 18510023SGordon.Ross@Sun.COM * 18610023SGordon.Ross@Sun.COM * Comments to right show names as described in 18710023SGordon.Ross@Sun.COM * The Microsoft SMB Protocol spec. [MS-SMB] 18810023SGordon.Ross@Sun.COM * section 2.2.3 18910023SGordon.Ross@Sun.COM */ 19010023SGordon.Ross@Sun.COM mbp = &rqp->rq_rp; 191*11332SGordon.Ross@Sun.COM (void) md_get_uint8(mbp, &wc); 192*11332SGordon.Ross@Sun.COM err = md_get_uint16le(mbp, &dindex); 19310023SGordon.Ross@Sun.COM if (err || dindex > SMB_DIALECT_MAX) { 19410023SGordon.Ross@Sun.COM DPRINT("err %d dindex %d", err, (int)dindex); 19510023SGordon.Ross@Sun.COM goto errout; 19610023SGordon.Ross@Sun.COM } 19710023SGordon.Ross@Sun.COM dp = smb_dialects + dindex; 19810023SGordon.Ross@Sun.COM sv->sv_proto = dp->d_id; 19910023SGordon.Ross@Sun.COM DPRINT("Dialect %s", dp->d_name); 20010023SGordon.Ross@Sun.COM if (dp->d_id < SMB_DIALECT_NTLM0_12) { 20110023SGordon.Ross@Sun.COM /* XXX: User-visible warning too? */ 20210023SGordon.Ross@Sun.COM DPRINT("old dialect %s", dp->d_name); 20310023SGordon.Ross@Sun.COM goto errout; 20410023SGordon.Ross@Sun.COM } 20510023SGordon.Ross@Sun.COM if (wc != 17) { 20610023SGordon.Ross@Sun.COM DPRINT("bad wc %d", (int)wc); 20710023SGordon.Ross@Sun.COM goto errout; 20810023SGordon.Ross@Sun.COM } 209*11332SGordon.Ross@Sun.COM md_get_uint8(mbp, &sv->sv_sm); /* SecurityMode */ 210*11332SGordon.Ross@Sun.COM md_get_uint16le(mbp, &sv->sv_maxmux); /* MaxMpxCount */ 211*11332SGordon.Ross@Sun.COM md_get_uint16le(mbp, &sv->sv_maxvcs); /* MaxCountVCs */ 212*11332SGordon.Ross@Sun.COM md_get_uint32le(mbp, &sv->sv_maxtx); /* MaxBufferSize */ 213*11332SGordon.Ross@Sun.COM md_get_uint32le(mbp, &sv->sv_maxraw); /* MaxRawSize */ 214*11332SGordon.Ross@Sun.COM md_get_uint32le(mbp, &sv->sv_skey); /* SessionKey */ 215*11332SGordon.Ross@Sun.COM md_get_uint32le(mbp, &sv->sv_caps); /* Capabilities */ 216*11332SGordon.Ross@Sun.COM md_get_mem(mbp, NULL, 8, MB_MSYSTEM); /* SystemTime(s) */ 217*11332SGordon.Ross@Sun.COM md_get_uint16le(mbp, (uint16_t *)&sv->sv_tz); 218*11332SGordon.Ross@Sun.COM md_get_uint8(mbp, &eklen); /* EncryptionKeyLength */ 219*11332SGordon.Ross@Sun.COM err = md_get_uint16le(mbp, &bc); /* ByteCount */ 22010023SGordon.Ross@Sun.COM if (err) 22110023SGordon.Ross@Sun.COM goto errout; 22210023SGordon.Ross@Sun.COM 22310023SGordon.Ross@Sun.COM /* BEGIN CSTYLED */ 22410023SGordon.Ross@Sun.COM /* 22510023SGordon.Ross@Sun.COM * Will we do SMB signing? Or block the connection? 22610023SGordon.Ross@Sun.COM * The table below describes this logic. References: 22710023SGordon.Ross@Sun.COM * [Windows Server Protocols: MS-SMB, sec. 3.2.4.2.3] 22810023SGordon.Ross@Sun.COM * http://msdn.microsoft.com/en-us/library/cc212511.aspx 22910023SGordon.Ross@Sun.COM * http://msdn.microsoft.com/en-us/library/cc212929.aspx 23010023SGordon.Ross@Sun.COM * 23110023SGordon.Ross@Sun.COM * Srv/Cli | Required | Enabled | If Required | Disabled 23210023SGordon.Ross@Sun.COM * ------------+----------+------------+-------------+----------- 23310023SGordon.Ross@Sun.COM * Required | Signed | Signed | Signed | Blocked [1] 23410023SGordon.Ross@Sun.COM * ------------+----------+------------+-------------+----------- 23510023SGordon.Ross@Sun.COM * Enabled | Signed | Signed | Not Signed | Not Signed 23610023SGordon.Ross@Sun.COM * ------------+----------+------------+-------------+----------- 23710023SGordon.Ross@Sun.COM * If Required | Signed | Not Signed | Not Signed | Not Signed 23810023SGordon.Ross@Sun.COM * ------------+----------+------------+-------------+----------- 23910023SGordon.Ross@Sun.COM * Disabled | Blocked | Not Signed | Not Signed | Not Signed 24010023SGordon.Ross@Sun.COM * 24110023SGordon.Ross@Sun.COM * [1] Like Windows 2003 and later, we don't really implement 24210023SGordon.Ross@Sun.COM * the "Disabled" setting. Instead we implement "If Required", 24310023SGordon.Ross@Sun.COM * so we always sign if the server requires signing. 24410023SGordon.Ross@Sun.COM */ 24510023SGordon.Ross@Sun.COM /* END CSTYLED */ 24610023SGordon.Ross@Sun.COM 24710023SGordon.Ross@Sun.COM if (sv->sv_sm & SMB_SM_SIGS_REQUIRE) { 24810023SGordon.Ross@Sun.COM /* 24910023SGordon.Ross@Sun.COM * Server requires signing. We will sign, 25010023SGordon.Ross@Sun.COM * even if local setting is "disabled". 25110023SGordon.Ross@Sun.COM */ 25210023SGordon.Ross@Sun.COM will_sign = 1; 25310023SGordon.Ross@Sun.COM } else if (sv->sv_sm & SMB_SM_SIGS) { 25410023SGordon.Ross@Sun.COM /* 25510023SGordon.Ross@Sun.COM * Server enables signing (client's option). 25610023SGordon.Ross@Sun.COM * If enabled locally, do signing. 25710023SGordon.Ross@Sun.COM */ 25810023SGordon.Ross@Sun.COM if (ctx->ct_vopt & SMBVOPT_SIGNING_ENABLED) 25910023SGordon.Ross@Sun.COM will_sign = 1; 26010023SGordon.Ross@Sun.COM /* else not signing. */ 26110023SGordon.Ross@Sun.COM } else { 26210023SGordon.Ross@Sun.COM /* 26310023SGordon.Ross@Sun.COM * Server does not support signing. 26410023SGordon.Ross@Sun.COM * If we "require" it, bail now. 26510023SGordon.Ross@Sun.COM */ 26610023SGordon.Ross@Sun.COM if (ctx->ct_vopt & SMBVOPT_SIGNING_REQUIRED) { 26710023SGordon.Ross@Sun.COM DPRINT("Client requires signing " 26810023SGordon.Ross@Sun.COM "but server has it disabled."); 26910023SGordon.Ross@Sun.COM err = EBADRPC; 27010023SGordon.Ross@Sun.COM goto errout; 27110023SGordon.Ross@Sun.COM } 27210023SGordon.Ross@Sun.COM } 27310023SGordon.Ross@Sun.COM 27410023SGordon.Ross@Sun.COM if (will_sign) { 27510023SGordon.Ross@Sun.COM ctx->ct_vcflags |= SMBV_WILL_SIGN; 27610023SGordon.Ross@Sun.COM } 27710023SGordon.Ross@Sun.COM DPRINT("Security signatures: %d", will_sign); 27810023SGordon.Ross@Sun.COM 27910023SGordon.Ross@Sun.COM if (sv->sv_caps & SMB_CAP_UNICODE) { 28010023SGordon.Ross@Sun.COM ctx->ct_vcflags |= SMBV_UNICODE; 28110023SGordon.Ross@Sun.COM ctx->ct_hflags2 |= SMB_FLAGS2_UNICODE; 28210023SGordon.Ross@Sun.COM 28310023SGordon.Ross@Sun.COM } 28410023SGordon.Ross@Sun.COM if ((sv->sv_caps & SMB_CAP_STATUS32) == 0) { 28510023SGordon.Ross@Sun.COM /* 28610023SGordon.Ross@Sun.COM * They don't do NT error codes. 28710023SGordon.Ross@Sun.COM * 28810023SGordon.Ross@Sun.COM * If we send requests with 28910023SGordon.Ross@Sun.COM * SMB_FLAGS2_ERR_STATUS set in 29010023SGordon.Ross@Sun.COM * Flags2, Windows 98, at least, 29110023SGordon.Ross@Sun.COM * appears to send replies with that 29210023SGordon.Ross@Sun.COM * bit set even though it sends back 29310023SGordon.Ross@Sun.COM * DOS error codes. (They probably 29410023SGordon.Ross@Sun.COM * just use the request header as 29510023SGordon.Ross@Sun.COM * a template for the reply header, 29610023SGordon.Ross@Sun.COM * and don't bother clearing that bit.) 29710023SGordon.Ross@Sun.COM * 29810023SGordon.Ross@Sun.COM * Therefore, we clear that bit in 29910023SGordon.Ross@Sun.COM * our vc_hflags2 field. 30010023SGordon.Ross@Sun.COM */ 30110023SGordon.Ross@Sun.COM ctx->ct_hflags2 &= ~SMB_FLAGS2_ERR_STATUS; 30210023SGordon.Ross@Sun.COM } 30310023SGordon.Ross@Sun.COM if (dp->d_id == SMB_DIALECT_NTLM0_12 && 30410023SGordon.Ross@Sun.COM sv->sv_maxtx < 4096 && 30510023SGordon.Ross@Sun.COM (sv->sv_caps & SMB_CAP_NT_SMBS) == 0) { 30610023SGordon.Ross@Sun.COM ctx->ct_vcflags |= SMBV_WIN95; 30710023SGordon.Ross@Sun.COM DPRINT("Win95 detected"); 30810023SGordon.Ross@Sun.COM } 30910023SGordon.Ross@Sun.COM 31010023SGordon.Ross@Sun.COM /* 31110023SGordon.Ross@Sun.COM * The rest of the message varies depending on 31210023SGordon.Ross@Sun.COM * whether we've negotiated "extended security". 31310023SGordon.Ross@Sun.COM * 31410023SGordon.Ross@Sun.COM * With extended security, we have: 31510023SGordon.Ross@Sun.COM * Server_GUID (length 16) 31610023SGordon.Ross@Sun.COM * Security_BLOB 31710023SGordon.Ross@Sun.COM * Otherwise we have: 31810023SGordon.Ross@Sun.COM * EncryptionKey (length is eklen) 31910023SGordon.Ross@Sun.COM * PrimaryDomain 32010023SGordon.Ross@Sun.COM */ 32110023SGordon.Ross@Sun.COM if (sv->sv_caps & SMB_CAP_EXT_SECURITY) { 32210023SGordon.Ross@Sun.COM struct mbuf *m; 32310023SGordon.Ross@Sun.COM DPRINT("Ext.Security: yes"); 32410023SGordon.Ross@Sun.COM 32510023SGordon.Ross@Sun.COM /* 32610023SGordon.Ross@Sun.COM * Skip the server GUID. 32710023SGordon.Ross@Sun.COM */ 328*11332SGordon.Ross@Sun.COM err = md_get_mem(mbp, NULL, SMB_GUIDLEN, MB_MSYSTEM); 32910023SGordon.Ross@Sun.COM if (err) 33010023SGordon.Ross@Sun.COM goto errout; 33110023SGordon.Ross@Sun.COM /* 33210023SGordon.Ross@Sun.COM * Remainder is the security blob. 33310023SGordon.Ross@Sun.COM * Note: eklen "must be ignored" [MS-SMB] 33410023SGordon.Ross@Sun.COM */ 33510023SGordon.Ross@Sun.COM len = (int)bc - SMB_GUIDLEN; 33610023SGordon.Ross@Sun.COM if (len < 0) 33710023SGordon.Ross@Sun.COM goto errout; 33810023SGordon.Ross@Sun.COM 33910023SGordon.Ross@Sun.COM /* 34010023SGordon.Ross@Sun.COM * Get the (optional) SPNEGO "hint". 34110023SGordon.Ross@Sun.COM */ 342*11332SGordon.Ross@Sun.COM err = md_get_mbuf(mbp, len, &m); 34310023SGordon.Ross@Sun.COM if (err) 34410023SGordon.Ross@Sun.COM goto errout; 34510023SGordon.Ross@Sun.COM mb_initm(oblob, m); 34610023SGordon.Ross@Sun.COM oblob->mb_count = len; 34710023SGordon.Ross@Sun.COM } else { 34810023SGordon.Ross@Sun.COM DPRINT("Ext.Security: no"); 34910023SGordon.Ross@Sun.COM ctx->ct_hflags2 &= ~SMB_FLAGS2_EXT_SEC; 35010023SGordon.Ross@Sun.COM 35110023SGordon.Ross@Sun.COM /* 35210023SGordon.Ross@Sun.COM * Save the "Encryption Key" (the challenge). 35310023SGordon.Ross@Sun.COM * 35410023SGordon.Ross@Sun.COM * Sanity check: make sure the sec. blob length 35510023SGordon.Ross@Sun.COM * isn't bigger than the byte count. 35610023SGordon.Ross@Sun.COM */ 35710023SGordon.Ross@Sun.COM if (bc < eklen || eklen < NTLM_CHAL_SZ) { 35810023SGordon.Ross@Sun.COM err = EBADRPC; 35910023SGordon.Ross@Sun.COM goto errout; 36010023SGordon.Ross@Sun.COM } 361*11332SGordon.Ross@Sun.COM err = md_get_mem(mbp, ctx->ct_ntlm_chal, 362*11332SGordon.Ross@Sun.COM NTLM_CHAL_SZ, MB_MSYSTEM); 36310023SGordon.Ross@Sun.COM /* 36410023SGordon.Ross@Sun.COM * Server domain follows (ignored) 36510023SGordon.Ross@Sun.COM * Note: NOT aligned(2) - unusual! 36610023SGordon.Ross@Sun.COM */ 36710023SGordon.Ross@Sun.COM } 36810023SGordon.Ross@Sun.COM 36910023SGordon.Ross@Sun.COM smb_rq_done(rqp); 37010023SGordon.Ross@Sun.COM 37110023SGordon.Ross@Sun.COM /* 37210023SGordon.Ross@Sun.COM * A few sanity checks on what we received, 37310023SGordon.Ross@Sun.COM * becuse we will send these in ssnsetup. 37410023SGordon.Ross@Sun.COM * 37510023SGordon.Ross@Sun.COM * Maximum outstanding requests (we care), 37610023SGordon.Ross@Sun.COM * and Max. VCs (we only use one). Also, 37710023SGordon.Ross@Sun.COM * MaxBufferSize lower limit per spec. 37810023SGordon.Ross@Sun.COM */ 37910023SGordon.Ross@Sun.COM if (sv->sv_maxmux < 1) 38010023SGordon.Ross@Sun.COM sv->sv_maxmux = 1; 38110023SGordon.Ross@Sun.COM if (sv->sv_maxvcs < 1) 38210023SGordon.Ross@Sun.COM sv->sv_maxvcs = 1; 38310023SGordon.Ross@Sun.COM if (sv->sv_maxtx < 1024) 38410023SGordon.Ross@Sun.COM sv->sv_maxtx = 1024; 38510023SGordon.Ross@Sun.COM 38610023SGordon.Ross@Sun.COM /* 38710023SGordon.Ross@Sun.COM * Maximum transfer size. 38810023SGordon.Ross@Sun.COM * Sanity checks: 38910023SGordon.Ross@Sun.COM * 39010023SGordon.Ross@Sun.COM * Let's be conservative about an upper limit here. 39110023SGordon.Ross@Sun.COM * Win2k uses 16644 (and others) so 32k should be a 39210023SGordon.Ross@Sun.COM * reasonable sanity limit for this value. 39310023SGordon.Ross@Sun.COM * 39410023SGordon.Ross@Sun.COM * Note that this limit does NOT affect READX/WRITEX 39510023SGordon.Ross@Sun.COM * with CAP_LARGE_..., which we nearly always use. 39610023SGordon.Ross@Sun.COM */ 39710023SGordon.Ross@Sun.COM is->is_txmax = sv->sv_maxtx; 39810023SGordon.Ross@Sun.COM if (is->is_txmax > 0x8000) 39910023SGordon.Ross@Sun.COM is->is_txmax = 0x8000; 40010023SGordon.Ross@Sun.COM 40110023SGordon.Ross@Sun.COM /* 40210023SGordon.Ross@Sun.COM * Max read/write sizes, WITHOUT overhead. 40310023SGordon.Ross@Sun.COM * This is just the payload size, so we must 40410023SGordon.Ross@Sun.COM * leave room for the SMB headers, etc. 40510023SGordon.Ross@Sun.COM * This is just the ct_txmax value, but 40610023SGordon.Ross@Sun.COM * reduced and rounded down. Tricky bit: 40710023SGordon.Ross@Sun.COM * 40810023SGordon.Ross@Sun.COM * Servers typically give us a value that's 40910023SGordon.Ross@Sun.COM * some nice "round" number, i.e 0x4000 plus 41010023SGordon.Ross@Sun.COM * some overhead, i.e. Win2k: 16644==0x4104 41110023SGordon.Ross@Sun.COM * Subtract for the SMB header (32) and the 41210023SGordon.Ross@Sun.COM * SMB command word and byte vectors (34?), 41310023SGordon.Ross@Sun.COM * then round down to a 512 byte multiple. 41410023SGordon.Ross@Sun.COM */ 41510023SGordon.Ross@Sun.COM len = is->is_txmax - 68; 41610023SGordon.Ross@Sun.COM len &= 0xFE00; 41710023SGordon.Ross@Sun.COM /* XXX: Not sure yet which of these to keep. */ 41810023SGordon.Ross@Sun.COM is->is_rwmax = len; 41910023SGordon.Ross@Sun.COM is->is_rxmax = len; 42010023SGordon.Ross@Sun.COM is->is_wxmax = len; 42110023SGordon.Ross@Sun.COM 42210023SGordon.Ross@Sun.COM return (0); 42310023SGordon.Ross@Sun.COM 42410023SGordon.Ross@Sun.COM errout: 42510023SGordon.Ross@Sun.COM smb_rq_done(rqp); 42610023SGordon.Ross@Sun.COM if (err == 0) 42710023SGordon.Ross@Sun.COM err = EBADRPC; 42810023SGordon.Ross@Sun.COM return (err); 42910023SGordon.Ross@Sun.COM } 430