1da6c28aaSamw /*
2da6c28aaSamw * CDDL HEADER START
3da6c28aaSamw *
4da6c28aaSamw * The contents of this file are subject to the terms of the
5da6c28aaSamw * Common Development and Distribution License (the "License").
6da6c28aaSamw * You may not use this file except in compliance with the License.
7da6c28aaSamw *
8da6c28aaSamw * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
9da6c28aaSamw * or http://www.opensolaris.org/os/licensing.
10da6c28aaSamw * See the License for the specific language governing permissions
11da6c28aaSamw * and limitations under the License.
12da6c28aaSamw *
13da6c28aaSamw * When distributing Covered Code, include this CDDL HEADER in each
14da6c28aaSamw * file and include the License file at usr/src/OPENSOLARIS.LICENSE.
15da6c28aaSamw * If applicable, add the following below this CDDL HEADER, with the
16da6c28aaSamw * fields enclosed by brackets "[]" replaced with your own identifying
17da6c28aaSamw * information: Portions Copyright [yyyy] [name of copyright owner]
18da6c28aaSamw *
19da6c28aaSamw * CDDL HEADER END
20da6c28aaSamw */
21da6c28aaSamw /*
22148c5f43SAlan Wright * Copyright (c) 2007, 2010, Oracle and/or its affiliates. All rights reserved.
2393bc28dbSGordon Ross * Copyright 2017 Nexenta Systems, Inc. All rights reserved.
24da6c28aaSamw */
25da6c28aaSamw
26da6c28aaSamw /*
27da6c28aaSamw * Notes on the virtual circuit (VC) values in the SMB Negotiate
28da6c28aaSamw * response and SessionSetupAndx request.
29da6c28aaSamw *
30da6c28aaSamw * A virtual circuit (VC) represents a connection between a client and a
31da6c28aaSamw * server using a reliable, session oriented transport protocol, such as
32da6c28aaSamw * NetBIOS or TCP/IP. Originally, each SMB session was restricted to a
33da6c28aaSamw * single underlying transport connection, i.e. a single NetBIOS session,
34da6c28aaSamw * which limited performance for raw data transfers.
35da6c28aaSamw *
36da6c28aaSamw * The intention behind multiple VCs was to improve performance by
37da6c28aaSamw * allowing parallelism over each NetBIOS session. For example, raw data
38da6c28aaSamw * could be transmitted using a different VC from other types of SMB
39da6c28aaSamw * requests to remove the interleaving restriction while a raw transfer
40da6c28aaSamw * is in progress. So the MaxNumberVcs field was added to the negotiate
41da6c28aaSamw * response to make the number of VCs configurable and to allow servers
42da6c28aaSamw * to specify how many they were prepared to support per session
43da6c28aaSamw * connection. This turned out to be difficult to manage and, with
44da6c28aaSamw * technology improvements, it has become obsolete.
45da6c28aaSamw *
46da6c28aaSamw * Servers should set the MaxNumberVcs value in the Negotiate response
47da6c28aaSamw * to 1. Clients should probably ignore it. If a server receives a
48da6c28aaSamw * SessionSetupAndx with a VC value of 0, it should close all other
49da6c28aaSamw * VCs to that client. If it receives a non-zero VC, it should leave
50da6c28aaSamw * other VCs in tact.
51da6c28aaSamw *
52da6c28aaSamw */
53da6c28aaSamw
54da6c28aaSamw /*
55da6c28aaSamw * SMB: negotiate
56da6c28aaSamw *
57da6c28aaSamw * Client Request Description
58da6c28aaSamw * ============================ =======================================
59da6c28aaSamw *
60da6c28aaSamw * UCHAR WordCount; Count of parameter words = 0
61da6c28aaSamw * USHORT ByteCount; Count of data bytes; min = 2
62da6c28aaSamw * struct {
63da6c28aaSamw * UCHAR BufferFormat; 0x02 -- Dialect
64da6c28aaSamw * UCHAR DialectName[]; ASCII null-terminated string
65da6c28aaSamw * } Dialects[];
66da6c28aaSamw *
67da6c28aaSamw * The Client sends a list of dialects that it can communicate with. The
68da6c28aaSamw * response is a selection of one of those dialects (numbered 0 through n)
69da6c28aaSamw * or -1 (hex FFFF) indicating that none of the dialects were acceptable.
70da6c28aaSamw * The negotiate message is binding on the virtual circuit and must be
71da6c28aaSamw * sent. One and only one negotiate message may be sent, subsequent
72da6c28aaSamw * negotiate requests will be rejected with an error response and no action
73da6c28aaSamw * will be taken.
74da6c28aaSamw *
75da6c28aaSamw * The protocol does not impose any particular structure to the dialect
76da6c28aaSamw * strings. Implementors of particular protocols may choose to include,
77da6c28aaSamw * for example, version numbers in the string.
78da6c28aaSamw *
79da6c28aaSamw * If the server does not understand any of the dialect strings, or if PC
80da6c28aaSamw * NETWORK PROGRAM 1.0 is the chosen dialect, the response format is
81da6c28aaSamw *
82da6c28aaSamw * Server Response Description
83da6c28aaSamw * ============================ =======================================
84da6c28aaSamw *
85da6c28aaSamw * UCHAR WordCount; Count of parameter words = 1
86da6c28aaSamw * USHORT DialectIndex; Index of selected dialect
87da6c28aaSamw * USHORT ByteCount; Count of data bytes = 0
88da6c28aaSamw *
89da6c28aaSamw * If the chosen dialect is greater than core up to and including
90da6c28aaSamw * LANMAN2.1, the protocol response format is
91da6c28aaSamw *
92da6c28aaSamw * Server Response Description
93da6c28aaSamw * ============================ =======================================
94da6c28aaSamw *
95da6c28aaSamw * UCHAR WordCount; Count of parameter words = 13
96da6c28aaSamw * USHORT DialectIndex; Index of selected dialect
97da6c28aaSamw * USHORT SecurityMode; Security mode:
98da6c28aaSamw * bit 0: 0 = share, 1 = user
99da6c28aaSamw * bit 1: 1 = use challenge/response
100da6c28aaSamw * authentication
101da6c28aaSamw * USHORT MaxBufferSize; Max transmit buffer size (>= 1024)
102da6c28aaSamw * USHORT MaxMpxCount; Max pending multiplexed requests
103da6c28aaSamw * USHORT MaxNumberVcs; Max VCs between client and server
104da6c28aaSamw * USHORT RawMode; Raw modes supported:
105da6c28aaSamw * bit 0: 1 = Read Raw supported
106da6c28aaSamw * bit 1: 1 = Write Raw supported
107da6c28aaSamw * ULONG SessionKey; Unique token identifying this session
108da6c28aaSamw * SMB_TIME ServerTime; Current time at server
109da6c28aaSamw * SMB_DATE ServerDate; Current date at server
110da6c28aaSamw * USHORT ServerTimeZone; Current time zone at server
111da6c28aaSamw * USHORT EncryptionKeyLength; MBZ if this is not LM2.1
112da6c28aaSamw * USHORT Reserved; MBZ
113da6c28aaSamw * USHORT ByteCount Count of data bytes
114da6c28aaSamw * UCHAR EncryptionKey[]; The challenge encryption key
115da6c28aaSamw * STRING PrimaryDomain[]; The server's primary domain
116da6c28aaSamw *
117da6c28aaSamw * MaxBufferSize is the size of the largest message which the client can
118da6c28aaSamw * legitimately send to the server
119da6c28aaSamw *
120da6c28aaSamw * If bit0 of the Flags field is set in the negotiate response, this
121da6c28aaSamw * indicates the server supports the SMB_COM_LOCK_AND_READ and
122da6c28aaSamw * SMB_COM_WRITE_AND_UNLOCK client requests.
123da6c28aaSamw *
124da6c28aaSamw * If the SecurityMode field indicates the server is running in user mode,
125da6c28aaSamw * the client must send appropriate SMB_COM_SESSION_SETUP_ANDX requests
126da6c28aaSamw * before the server will allow the client to access resources. If the
127da6c28aaSamw * SecurityMode fields indicates the client should use challenge/response
128da6c28aaSamw * authentication, the client should use the authentication mechanism
129da6c28aaSamw * specified in section 2.10.
130da6c28aaSamw *
131da6c28aaSamw * Clients should submit no more than MaxMpxCount distinct unanswered SMBs
132da6c28aaSamw * to the server when using multiplexed reads or writes (see sections 5.13
133da6c28aaSamw * and 5.25)
134da6c28aaSamw *
135da6c28aaSamw * Clients using the "MICROSOFT NETWORKS 1.03" dialect use a different
136da6c28aaSamw * form of raw reads than documented here, and servers are better off
137da6c28aaSamw * setting RawMode in this response to 0 for such sessions.
138da6c28aaSamw *
139da6c28aaSamw * If the negotiated dialect is "DOS LANMAN2.1" or "LANMAN2.1", then
140da6c28aaSamw * PrimaryDomain string should be included in this response.
141da6c28aaSamw *
142da6c28aaSamw * If the negotiated dialect is NT LM 0.12, the response format is
143da6c28aaSamw *
144da6c28aaSamw * Server Response Description
145da6c28aaSamw * ========================== =========================================
146da6c28aaSamw *
147da6c28aaSamw * UCHAR WordCount; Count of parameter words = 17
148da6c28aaSamw * USHORT DialectIndex; Index of selected dialect
149da6c28aaSamw * UCHAR SecurityMode; Security mode:
150da6c28aaSamw * bit 0: 0 = share, 1 = user
151da6c28aaSamw * bit 1: 1 = encrypt passwords
152da6c28aaSamw * USHORT MaxMpxCount; Max pending multiplexed requests
153da6c28aaSamw * USHORT MaxNumberVcs; Max VCs between client and server
154da6c28aaSamw * ULONG MaxBufferSize; Max transmit buffer size
155da6c28aaSamw * ULONG MaxRawSize; Maximum raw buffer size
156da6c28aaSamw * ULONG SessionKey; Unique token identifying this session
157da6c28aaSamw * ULONG Capabilities; Server capabilities
158da6c28aaSamw * ULONG SystemTimeLow; System (UTC) time of the server (low).
159da6c28aaSamw * ULONG SystemTimeHigh; System (UTC) time of the server (high).
160da6c28aaSamw * USHORT ServerTimeZone; Time zone of server (min from UTC)
161da6c28aaSamw * UCHAR EncryptionKeyLength; Length of encryption key.
162da6c28aaSamw * USHORT ByteCount; Count of data bytes
163da6c28aaSamw * UCHAR EncryptionKey[]; The challenge encryption key
164da6c28aaSamw * UCHAR OemDomainName[]; The name of the domain (in OEM chars)
165da6c28aaSamw *
166da6c28aaSamw * In addition to the definitions above, MaxBufferSize is the size of the
167da6c28aaSamw * largest message which the client can legitimately send to the server.
168da6c28aaSamw * If the client is using a connectionless protocol, MaxBufferSize must be
169da6c28aaSamw * set to the smaller of the server's internal buffer size and the amount
170da6c28aaSamw * of data which can be placed in a response packet.
171da6c28aaSamw *
172da6c28aaSamw * MaxRawSize specifies the maximum message size the server can send or
173da6c28aaSamw * receive for SMB_COM_WRITE_RAW or SMB_COM_READ_RAW.
174da6c28aaSamw *
175da6c28aaSamw * Connectionless clients must set Sid to 0 in the SMB request header.
176da6c28aaSamw *
177da6c28aaSamw * Capabilities allows the server to tell the client what it supports.
178bbf6f00cSJordan Brown * The bit definitions defined in smb.h. Bit 0x2000 used to be set in
179da6c28aaSamw * the negotiate response capabilities but it caused problems with
180da6c28aaSamw * Windows 2000. It is probably not valid, it doesn't appear in the
181da6c28aaSamw * CIFS spec.
182da6c28aaSamw *
183da6c28aaSamw * 4.1.1.1 Errors
184da6c28aaSamw *
185da6c28aaSamw * SUCCESS/SUCCESS
186da6c28aaSamw * ERRSRV/ERRerror
187da6c28aaSamw */
188da6c28aaSamw #include <sys/types.h>
189da6c28aaSamw #include <sys/socket.h>
190da6c28aaSamw #include <netinet/in.h>
191bbf6f00cSJordan Brown #include <smbsrv/smb_kproto.h>
192da6c28aaSamw #include <smbsrv/smbinfo.h>
193da6c28aaSamw
1948622ec45SGordon Ross static const smb_xlate_t smb_dialect[] = {
195148c5f43SAlan Wright { DIALECT_UNKNOWN, "DIALECT_UNKNOWN" },
196148c5f43SAlan Wright { PC_NETWORK_PROGRAM_1_0, "PC NETWORK PROGRAM 1.0" },
197148c5f43SAlan Wright { PCLAN1_0, "PCLAN1.0" },
198148c5f43SAlan Wright { MICROSOFT_NETWORKS_1_03, "MICROSOFT NETWORKS 1.03" },
199148c5f43SAlan Wright { MICROSOFT_NETWORKS_3_0, "MICROSOFT NETWORKS 3.0" },
200148c5f43SAlan Wright { LANMAN1_0, "LANMAN1.0" },
201148c5f43SAlan Wright { LM1_2X002, "LM1.2X002" },
202148c5f43SAlan Wright { DOS_LM1_2X002, "DOS LM1.2X002" },
203148c5f43SAlan Wright { DOS_LANMAN2_1, "DOS LANMAN2.1" },
204148c5f43SAlan Wright { LANMAN2_1, "LANMAN2.1" },
205148c5f43SAlan Wright { Windows_for_Workgroups_3_1a, "Windows for Workgroups 3.1a" },
206a90cf9f2SGordon Ross { NT_LM_0_12, "NT LM 0.12" },
207a90cf9f2SGordon Ross { DIALECT_SMB2002, "SMB 2.002" },
208a90cf9f2SGordon Ross { DIALECT_SMB2XXX, "SMB 2.???" },
209148c5f43SAlan Wright };
210a90cf9f2SGordon Ross static int smb_ndialects = sizeof (smb_dialect) / sizeof (smb_dialect[0]);
211148c5f43SAlan Wright
212da6c28aaSamw /*
213da6c28aaSamw * Maximum buffer size for DOS: chosen to be the same as NT.
214da6c28aaSamw * Do not change this value, DOS is very sensitive to it.
215da6c28aaSamw */
216da6c28aaSamw #define SMB_DOS_MAXBUF 0x1104
217da6c28aaSamw
218da6c28aaSamw /*
219da6c28aaSamw * The DOS TCP rcvbuf is set to 8700 because DOS 6.1 seems to have problems
220da6c28aaSamw * with other values. DOS 6.1 seems to depend on a window value of 8700 to
221da6c28aaSamw * send the next set of data. If we return a window value of 40KB, after
222da6c28aaSamw * sending 8700 bytes of data, it will start the next set of data from 40KB
223da6c28aaSamw * instead of 8.7k. Why 8.7k? We have no idea; it is the value that NT uses.
224da6c28aaSamw * September 2000.
225da6c28aaSamw *
226da6c28aaSamw * IR104720 Increased smb_nt_tcp_rcvbuf from 40KB to just under 1MB to allow
227da6c28aaSamw * for a larger TCP window sizei based on observations of Windows 2000 and
228da6c28aaSamw * performance testing. March 2003.
229da6c28aaSamw */
230faa1795aSjb static uint32_t smb_dos_tcp_rcvbuf = 8700;
231faa1795aSjb static uint32_t smb_nt_tcp_rcvbuf = 1048560; /* scale factor of 4 */
232da6c28aaSamw
233a90cf9f2SGordon Ross /*
234a90cf9f2SGordon Ross * Maximum number of simultaneously pending SMB requests allowed on
235a90cf9f2SGordon Ross * one connection. This is like "credits" in SMB2, but SMB1 uses a
236a90cf9f2SGordon Ross * fixed limit, having no way to request an increase like SMB2 does.
237a90cf9f2SGordon Ross * Note: Some older clients only handle the low byte of this value,
238a90cf9f2SGordon Ross * so this value should be less than 256.
239a90cf9f2SGordon Ross */
240a90cf9f2SGordon Ross static uint16_t smb_maxmpxcount = 64;
241a90cf9f2SGordon Ross
242148c5f43SAlan Wright static int smb_xlate_dialect(const char *);
243da6c28aaSamw
24412b65585SGordon Ross /*
24512b65585SGordon Ross * "Capabilities" offered by SMB1 Negotiate Protocol.
24612b65585SGordon Ross * See smb.h for descriptions.
24712b65585SGordon Ross *
24812b65585SGordon Ross * CAP_RAW_MODE, CAP_MPX_MODE are obsolete.
24912b65585SGordon Ross * UNICODE support is required for long share names,
25012b65585SGordon Ross * long file names and streams.
25112b65585SGordon Ross *
25212b65585SGordon Ross * For testing, one can patch this, i.e. remove the high bit to
25312b65585SGordon Ross * temporarily disable extended security, etc.
25412b65585SGordon Ross */
25512b65585SGordon Ross uint32_t smb1srv_capabilities =
25612b65585SGordon Ross CAP_UNICODE |
25712b65585SGordon Ross CAP_LARGE_FILES |
25812b65585SGordon Ross CAP_NT_SMBS |
25912b65585SGordon Ross CAP_RPC_REMOTE_APIS |
26012b65585SGordon Ross CAP_STATUS32 |
26112b65585SGordon Ross CAP_LEVEL_II_OPLOCKS |
26212b65585SGordon Ross CAP_LOCK_AND_READ |
26312b65585SGordon Ross CAP_NT_FIND |
26412b65585SGordon Ross CAP_DFS |
26512b65585SGordon Ross CAP_INFOLEVEL_PASSTHRU |
26612b65585SGordon Ross CAP_LARGE_READX |
26712b65585SGordon Ross CAP_LARGE_WRITEX |
26812b65585SGordon Ross CAP_EXTENDED_SECURITY;
2699fb67ea3Safshin salek ardakani - Sun Microsystems - Irvine United States
270a90cf9f2SGordon Ross /*
271a90cf9f2SGordon Ross * SMB Negotiate gets special handling. This is called directly by
272a90cf9f2SGordon Ross * the reader thread (see smbsr_newrq_initial) with what _should_ be
273a90cf9f2SGordon Ross * an SMB1 Negotiate. Only the "\ffSMB" header has been checked
274a90cf9f2SGordon Ross * when this is called, so this needs to check the SMB command,
275a90cf9f2SGordon Ross * if it's Negotiate execute it, then send the reply, etc.
276a90cf9f2SGordon Ross *
277a90cf9f2SGordon Ross * Since this is called directly from the reader thread, we
278a90cf9f2SGordon Ross * know this is the only thread currently using this session.
279a90cf9f2SGordon Ross * This has to duplicate some of what smb1sr_work does as a
280a90cf9f2SGordon Ross * result of bypassing the normal dispatch mechanism.
281a90cf9f2SGordon Ross *
282a90cf9f2SGordon Ross * The caller always frees this request.
28393bc28dbSGordon Ross *
28493bc28dbSGordon Ross * Return value is 0 for success, and anything else will
28593bc28dbSGordon Ross * terminate the reader thread (drop the connection).
286a90cf9f2SGordon Ross */
287a90cf9f2SGordon Ross int
smb1_newrq_negotiate(smb_request_t * sr)288a90cf9f2SGordon Ross smb1_newrq_negotiate(smb_request_t *sr)
289a90cf9f2SGordon Ross {
290a90cf9f2SGordon Ross smb_sdrc_t sdrc;
291a90cf9f2SGordon Ross uint16_t pid_hi, pid_lo;
292a90cf9f2SGordon Ross
293a90cf9f2SGordon Ross /*
294a90cf9f2SGordon Ross * Decode the header
295a90cf9f2SGordon Ross */
296a90cf9f2SGordon Ross if (smb_mbc_decodef(&sr->command, SMB_HEADER_ED_FMT,
297a90cf9f2SGordon Ross &sr->smb_com,
298a90cf9f2SGordon Ross &sr->smb_rcls,
299a90cf9f2SGordon Ross &sr->smb_reh,
300a90cf9f2SGordon Ross &sr->smb_err,
301a90cf9f2SGordon Ross &sr->smb_flg,
302a90cf9f2SGordon Ross &sr->smb_flg2,
303a90cf9f2SGordon Ross &pid_hi,
304a90cf9f2SGordon Ross sr->smb_sig,
305a90cf9f2SGordon Ross &sr->smb_tid,
306a90cf9f2SGordon Ross &pid_lo,
307a90cf9f2SGordon Ross &sr->smb_uid,
308a90cf9f2SGordon Ross &sr->smb_mid) != 0)
309a90cf9f2SGordon Ross return (-1);
310a90cf9f2SGordon Ross if (sr->smb_com != SMB_COM_NEGOTIATE)
311a90cf9f2SGordon Ross return (-1);
312a90cf9f2SGordon Ross
313a90cf9f2SGordon Ross sr->smb_pid = (pid_hi << 16) | pid_lo;
314a90cf9f2SGordon Ross
315a90cf9f2SGordon Ross /*
316a90cf9f2SGordon Ross * Reserve space for the reply header.
317a90cf9f2SGordon Ross */
318a90cf9f2SGordon Ross (void) smb_mbc_encodef(&sr->reply, "#.", SMB_HEADER_LEN);
319a90cf9f2SGordon Ross sr->first_smb_com = sr->smb_com;
320a90cf9f2SGordon Ross
321a90cf9f2SGordon Ross if (smb_mbc_decodef(&sr->command, "b", &sr->smb_wct) != 0)
322a90cf9f2SGordon Ross return (-1);
323a90cf9f2SGordon Ross (void) MBC_SHADOW_CHAIN(&sr->smb_vwv, &sr->command,
324a90cf9f2SGordon Ross sr->command.chain_offset, sr->smb_wct * 2);
325a90cf9f2SGordon Ross
326a90cf9f2SGordon Ross if (smb_mbc_decodef(&sr->command, "#.w", sr->smb_wct*2, &sr->smb_bcc))
327a90cf9f2SGordon Ross return (-1);
328a90cf9f2SGordon Ross (void) MBC_SHADOW_CHAIN(&sr->smb_data, &sr->command,
329a90cf9f2SGordon Ross sr->command.chain_offset, sr->smb_bcc);
330a90cf9f2SGordon Ross
331a90cf9f2SGordon Ross sr->command.chain_offset += sr->smb_bcc;
332a90cf9f2SGordon Ross if (sr->command.chain_offset > sr->command.max_bytes)
333a90cf9f2SGordon Ross return (-1);
334a90cf9f2SGordon Ross
335a90cf9f2SGordon Ross /* Store pointers for later */
336a90cf9f2SGordon Ross sr->cur_reply_offset = sr->reply.chain_offset;
337a90cf9f2SGordon Ross
338a90cf9f2SGordon Ross sdrc = smb_pre_negotiate(sr);
339a90cf9f2SGordon Ross if (sdrc == SDRC_SUCCESS)
340a90cf9f2SGordon Ross sdrc = smb_com_negotiate(sr);
341a90cf9f2SGordon Ross smb_post_negotiate(sr);
342a90cf9f2SGordon Ross
343a90cf9f2SGordon Ross if (sdrc != SDRC_NO_REPLY)
344a90cf9f2SGordon Ross smbsr_send_reply(sr);
345a90cf9f2SGordon Ross if (sdrc == SDRC_DROP_VC)
346a90cf9f2SGordon Ross return (-1);
347a90cf9f2SGordon Ross
348a90cf9f2SGordon Ross return (0);
349a90cf9f2SGordon Ross }
350a90cf9f2SGordon Ross
351faa1795aSjb smb_sdrc_t
smb_pre_negotiate(smb_request_t * sr)352faa1795aSjb smb_pre_negotiate(smb_request_t *sr)
353faa1795aSjb {
354a90cf9f2SGordon Ross smb_kmod_cfg_t *skc;
355148c5f43SAlan Wright smb_arg_negotiate_t *negprot;
356148c5f43SAlan Wright int dialect;
357148c5f43SAlan Wright int pos;
358148c5f43SAlan Wright int rc = 0;
359148c5f43SAlan Wright
360a90cf9f2SGordon Ross skc = &sr->session->s_cfg;
361148c5f43SAlan Wright negprot = smb_srm_zalloc(sr, sizeof (smb_arg_negotiate_t));
362148c5f43SAlan Wright negprot->ni_index = -1;
363148c5f43SAlan Wright sr->sr_negprot = negprot;
364148c5f43SAlan Wright
365148c5f43SAlan Wright for (pos = 0; smbsr_decode_data_avail(sr); pos++) {
366148c5f43SAlan Wright if (smbsr_decode_data(sr, "%L", sr, &negprot->ni_name) != 0) {
367148c5f43SAlan Wright smbsr_error(sr, 0, ERRSRV, ERRerror);
368148c5f43SAlan Wright rc = -1;
369148c5f43SAlan Wright break;
370148c5f43SAlan Wright }
371148c5f43SAlan Wright
372148c5f43SAlan Wright if ((dialect = smb_xlate_dialect(negprot->ni_name)) < 0)
373148c5f43SAlan Wright continue;
374148c5f43SAlan Wright
375a90cf9f2SGordon Ross /*
376a90cf9f2SGordon Ross * Conditionally recognize the SMB2 dialects.
377a90cf9f2SGordon Ross */
378a90cf9f2SGordon Ross if (dialect >= DIALECT_SMB2002 &&
379a90cf9f2SGordon Ross skc->skc_max_protocol < SMB_VERS_2_BASE)
380a90cf9f2SGordon Ross continue;
381a90cf9f2SGordon Ross
382*3e2c0c09SMatt Barden /*
383*3e2c0c09SMatt Barden * We may not support SMB1; skip those dialects if true.
384*3e2c0c09SMatt Barden */
385*3e2c0c09SMatt Barden if (dialect < DIALECT_SMB2002 &&
386*3e2c0c09SMatt Barden skc->skc_min_protocol > SMB_VERS_1)
387*3e2c0c09SMatt Barden continue;
388*3e2c0c09SMatt Barden
389*3e2c0c09SMatt Barden if (dialect == DIALECT_SMB2002 &&
390*3e2c0c09SMatt Barden skc->skc_min_protocol > SMB_VERS_2_002)
391*3e2c0c09SMatt Barden continue;
392*3e2c0c09SMatt Barden
393148c5f43SAlan Wright if (negprot->ni_dialect < dialect) {
394148c5f43SAlan Wright negprot->ni_dialect = dialect;
395148c5f43SAlan Wright negprot->ni_index = pos;
396148c5f43SAlan Wright }
397148c5f43SAlan Wright }
398148c5f43SAlan Wright
39993bc28dbSGordon Ross DTRACE_SMB_START(op__Negotiate, smb_request_t *, sr);
400a90cf9f2SGordon Ross
401148c5f43SAlan Wright return ((rc == 0) ? SDRC_SUCCESS : SDRC_ERROR);
402faa1795aSjb }
403faa1795aSjb
404faa1795aSjb void
smb_post_negotiate(smb_request_t * sr)405faa1795aSjb smb_post_negotiate(smb_request_t *sr)
406faa1795aSjb {
407148c5f43SAlan Wright smb_arg_negotiate_t *negprot = sr->sr_negprot;
408148c5f43SAlan Wright
40993bc28dbSGordon Ross DTRACE_SMB_DONE(op__Negotiate, smb_request_t *, sr);
410148c5f43SAlan Wright
411148c5f43SAlan Wright bzero(negprot, sizeof (smb_arg_negotiate_t));
412faa1795aSjb }
413da6c28aaSamw
4147b59d02dSjb smb_sdrc_t
smb_com_negotiate(smb_request_t * sr)415faa1795aSjb smb_com_negotiate(smb_request_t *sr)
416da6c28aaSamw {
4171160dcf7SMatt Barden smb_session_t *session = sr->session;
418148c5f43SAlan Wright smb_arg_negotiate_t *negprot = sr->sr_negprot;
419148c5f43SAlan Wright uint16_t secmode;
420da6c28aaSamw uint32_t sesskey;
421148c5f43SAlan Wright char *nbdomain;
422148c5f43SAlan Wright uint8_t *wcbuf;
423148c5f43SAlan Wright int wclen;
424b89a8333Snatalie li - Sun Microsystems - Irvine United States smb_msgbuf_t mb;
425148c5f43SAlan Wright int rc;
426da6c28aaSamw
427a90cf9f2SGordon Ross if (session->s_state != SMB_SESSION_STATE_ESTABLISHED) {
428da6c28aaSamw /* The protocol has already been negotiated. */
429dc20a302Sas smbsr_error(sr, 0, ERRSRV, ERRerror);
430faa1795aSjb return (SDRC_ERROR);
431da6c28aaSamw }
432da6c28aaSamw
433*3e2c0c09SMatt Barden if (negprot->ni_index < 0) {
434*3e2c0c09SMatt Barden cmn_err(CE_NOTE, "clnt %s no supported dialect",
435*3e2c0c09SMatt Barden sr->session->ip_addr_str);
436*3e2c0c09SMatt Barden smbsr_error(sr, 0, ERRSRV, ERRerror);
437*3e2c0c09SMatt Barden return (SDRC_DROP_VC);
438*3e2c0c09SMatt Barden }
439*3e2c0c09SMatt Barden
440a90cf9f2SGordon Ross /*
441a90cf9f2SGordon Ross * Special case for negotiating SMB2 from SMB1. The client
442a90cf9f2SGordon Ross * includes the "SMB 2..." dialects in the SMB1 negotiate,
443a90cf9f2SGordon Ross * and if SMB2 is enabled, we choose one of those and then
444a90cf9f2SGordon Ross * send an SMB2 reply to that SMB1 request. Yes, it's very
445a90cf9f2SGordon Ross * strange, but this SMB1 request can have an SMB2 reply!
446a90cf9f2SGordon Ross * To accomplish this, we let the SMB2 code send the reply
447a90cf9f2SGordon Ross * and return the special code SDRC_NO_REPLY to the SMB1
448a90cf9f2SGordon Ross * dispatch logic so it will NOT send an SMB1 reply.
449a90cf9f2SGordon Ross * (Or possibly send an SMB1 error reply.)
450a90cf9f2SGordon Ross */
451a90cf9f2SGordon Ross if (negprot->ni_dialect >= DIALECT_SMB2002) {
452a90cf9f2SGordon Ross rc = smb1_negotiate_smb2(sr);
453a90cf9f2SGordon Ross ASSERT(rc == SDRC_NO_REPLY ||
454a90cf9f2SGordon Ross rc == SDRC_DROP_VC || rc == SDRC_ERROR);
455a90cf9f2SGordon Ross return (rc);
456a90cf9f2SGordon Ross }
457a90cf9f2SGordon Ross
4581160dcf7SMatt Barden session->srv_secmode = NEGOTIATE_ENCRYPT_PASSWORDS |
45912b65585SGordon Ross NEGOTIATE_USER_SECURITY;
4601160dcf7SMatt Barden secmode = session->srv_secmode;
461a90cf9f2SGordon Ross sesskey = session->sesskey;
462da6c28aaSamw
463a90cf9f2SGordon Ross negprot->ni_servertime.tv_sec = gethrestime_sec();
464a90cf9f2SGordon Ross negprot->ni_servertime.tv_nsec = 0;
465148c5f43SAlan Wright negprot->ni_tzcorrection = sr->sr_gmtoff / 60;
466a90cf9f2SGordon Ross negprot->ni_maxmpxcount = smb_maxmpxcount;
467f9bc6dadSDmitry.Savitsky@nexenta.com negprot->ni_keylen = SMB_CHALLENGE_SZ;
468a90cf9f2SGordon Ross bcopy(&session->challenge_key, negprot->ni_key, SMB_CHALLENGE_SZ);
469148c5f43SAlan Wright nbdomain = sr->sr_cfg->skc_nbdomain;
470da6c28aaSamw
47112b65585SGordon Ross negprot->ni_capabilities = smb1srv_capabilities;
472148c5f43SAlan Wright
473148c5f43SAlan Wright switch (negprot->ni_dialect) {
474da6c28aaSamw case PC_NETWORK_PROGRAM_1_0: /* core */
475a90cf9f2SGordon Ross (void) ksocket_setsockopt(session->sock, SOL_SOCKET,
4760f1702c5SYu Xiangning SO_RCVBUF, (const void *)&smb_dos_tcp_rcvbuf,
4770f1702c5SYu Xiangning sizeof (smb_dos_tcp_rcvbuf), CRED());
478148c5f43SAlan Wright rc = smbsr_encode_result(sr, 1, 0, "bww", 1,
479148c5f43SAlan Wright negprot->ni_index, 0);
480da6c28aaSamw break;
481da6c28aaSamw
482da6c28aaSamw case Windows_for_Workgroups_3_1a:
483da6c28aaSamw case PCLAN1_0:
484da6c28aaSamw case MICROSOFT_NETWORKS_1_03:
485da6c28aaSamw case MICROSOFT_NETWORKS_3_0:
486da6c28aaSamw case LANMAN1_0:
487da6c28aaSamw case LM1_2X002:
488da6c28aaSamw case DOS_LM1_2X002:
489a90cf9f2SGordon Ross (void) ksocket_setsockopt(session->sock, SOL_SOCKET,
4900f1702c5SYu Xiangning SO_RCVBUF, (const void *)&smb_dos_tcp_rcvbuf,
4910f1702c5SYu Xiangning sizeof (smb_dos_tcp_rcvbuf), CRED());
492da6c28aaSamw sr->smb_flg |= SMB_FLAGS_LOCK_AND_READ_OK;
4937b59d02dSjb rc = smbsr_encode_result(sr, 13, VAR_BCC,
4943db3f65cSamw "bwwwwwwlYww2.w#c",
495148c5f43SAlan Wright 13, /* wct */
496148c5f43SAlan Wright negprot->ni_index, /* dialect index */
497148c5f43SAlan Wright secmode, /* security mode */
498148c5f43SAlan Wright SMB_DOS_MAXBUF, /* max buffer size */
499148c5f43SAlan Wright 1, /* max MPX */
500148c5f43SAlan Wright 1, /* max VCs */
501a90cf9f2SGordon Ross 0, /* read/write raw */
502148c5f43SAlan Wright sesskey, /* session key */
503148c5f43SAlan Wright negprot->ni_servertime.tv_sec, /* server date/time */
504148c5f43SAlan Wright negprot->ni_tzcorrection,
505148c5f43SAlan Wright (uint16_t)negprot->ni_keylen, /* encryption key length */
506148c5f43SAlan Wright /* reserved field handled 2. */
507da6c28aaSamw VAR_BCC,
508148c5f43SAlan Wright (int)negprot->ni_keylen,
509148c5f43SAlan Wright negprot->ni_key); /* encryption key */
510da6c28aaSamw break;
511da6c28aaSamw
512da6c28aaSamw case DOS_LANMAN2_1:
513da6c28aaSamw case LANMAN2_1:
514a90cf9f2SGordon Ross (void) ksocket_setsockopt(session->sock, SOL_SOCKET,
5150f1702c5SYu Xiangning SO_RCVBUF, (const void *)&smb_dos_tcp_rcvbuf,
5160f1702c5SYu Xiangning sizeof (smb_dos_tcp_rcvbuf), CRED());
517da6c28aaSamw sr->smb_flg |= SMB_FLAGS_LOCK_AND_READ_OK;
5187b59d02dSjb rc = smbsr_encode_result(sr, 13, VAR_BCC,
5193db3f65cSamw "bwwwwwwlYww2.w#cs",
520148c5f43SAlan Wright 13, /* wct */
521148c5f43SAlan Wright negprot->ni_index, /* dialect index */
522148c5f43SAlan Wright secmode, /* security mode */
523148c5f43SAlan Wright SMB_DOS_MAXBUF, /* max buffer size */
524148c5f43SAlan Wright 1, /* max MPX */
525148c5f43SAlan Wright 1, /* max VCs */
526a90cf9f2SGordon Ross 0, /* read/write raw */
527148c5f43SAlan Wright sesskey, /* session key */
528148c5f43SAlan Wright negprot->ni_servertime.tv_sec, /* server date/time */
529148c5f43SAlan Wright negprot->ni_tzcorrection,
530148c5f43SAlan Wright (uint16_t)negprot->ni_keylen, /* encryption key length */
531148c5f43SAlan Wright /* reserved field handled 2. */
532da6c28aaSamw VAR_BCC,
533148c5f43SAlan Wright (int)negprot->ni_keylen,
534148c5f43SAlan Wright negprot->ni_key, /* encryption key */
535148c5f43SAlan Wright nbdomain);
536da6c28aaSamw break;
537da6c28aaSamw
538da6c28aaSamw case NT_LM_0_12:
539a90cf9f2SGordon Ross (void) ksocket_setsockopt(session->sock, SOL_SOCKET,
5400f1702c5SYu Xiangning SO_RCVBUF, (const void *)&smb_nt_tcp_rcvbuf,
5410f1702c5SYu Xiangning sizeof (smb_nt_tcp_rcvbuf), CRED());
542da6c28aaSamw
543da6c28aaSamw /*
54412b65585SGordon Ross * Allow SMB signatures if using encrypted passwords
545da6c28aaSamw */
54612b65585SGordon Ross if ((secmode & NEGOTIATE_ENCRYPT_PASSWORDS) &&
547faa1795aSjb sr->sr_cfg->skc_signing_enable) {
548da6c28aaSamw secmode |= NEGOTIATE_SECURITY_SIGNATURES_ENABLED;
549faa1795aSjb if (sr->sr_cfg->skc_signing_required)
550da6c28aaSamw secmode |=
551da6c28aaSamw NEGOTIATE_SECURITY_SIGNATURES_REQUIRED;
552da6c28aaSamw
5531160dcf7SMatt Barden session->srv_secmode = secmode;
554da6c28aaSamw }
555da6c28aaSamw
55612b65585SGordon Ross /*
55712b65585SGordon Ross * Does the client want Extended Security?
55812b65585SGordon Ross * (and if we have it enabled)
55912b65585SGordon Ross * If so, handle as if a different dialect.
56012b65585SGordon Ross */
56112b65585SGordon Ross if ((sr->smb_flg2 & SMB_FLAGS2_EXT_SEC) != 0 &&
56212b65585SGordon Ross (negprot->ni_capabilities & CAP_EXTENDED_SECURITY) != 0)
56312b65585SGordon Ross goto NT_LM_0_12_ext_sec;
56412b65585SGordon Ross
56512b65585SGordon Ross /* Else deny knowledge of extended security. */
56612b65585SGordon Ross sr->smb_flg2 &= ~SMB_FLAGS2_EXT_SEC;
56712b65585SGordon Ross negprot->ni_capabilities &= ~CAP_EXTENDED_SECURITY;
56812b65585SGordon Ross
569b89a8333Snatalie li - Sun Microsystems - Irvine United States /*
570148c5f43SAlan Wright * nbdomain is not expected to be aligned.
571b89a8333Snatalie li - Sun Microsystems - Irvine United States * Use temporary buffer to avoid alignment padding
572b89a8333Snatalie li - Sun Microsystems - Irvine United States */
573148c5f43SAlan Wright wclen = smb_wcequiv_strlen(nbdomain) + sizeof (smb_wchar_t);
574148c5f43SAlan Wright wcbuf = smb_srm_zalloc(sr, wclen);
575148c5f43SAlan Wright smb_msgbuf_init(&mb, wcbuf, wclen, SMB_MSGBUF_UNICODE);
576148c5f43SAlan Wright if (smb_msgbuf_encode(&mb, "U", nbdomain) < 0) {
577b89a8333Snatalie li - Sun Microsystems - Irvine United States smb_msgbuf_term(&mb);
578b89a8333Snatalie li - Sun Microsystems - Irvine United States smbsr_error(sr, 0, ERRSRV, ERRerror);
579b89a8333Snatalie li - Sun Microsystems - Irvine United States return (SDRC_ERROR);
580b89a8333Snatalie li - Sun Microsystems - Irvine United States }
581b89a8333Snatalie li - Sun Microsystems - Irvine United States
5827b59d02dSjb rc = smbsr_encode_result(sr, 17, VAR_BCC,
583b89a8333Snatalie li - Sun Microsystems - Irvine United States "bwbwwllllTwbw#c#c",
584148c5f43SAlan Wright 17, /* wct */
585148c5f43SAlan Wright negprot->ni_index, /* dialect index */
586148c5f43SAlan Wright secmode, /* security mode */
587148c5f43SAlan Wright negprot->ni_maxmpxcount, /* max MPX */
588148c5f43SAlan Wright 1, /* max VCs */
589da6c28aaSamw (DWORD)smb_maxbufsize, /* max buffer size */
590148c5f43SAlan Wright 0xFFFF, /* max raw size */
591148c5f43SAlan Wright sesskey, /* session key */
592148c5f43SAlan Wright negprot->ni_capabilities,
593148c5f43SAlan Wright &negprot->ni_servertime, /* system time */
594148c5f43SAlan Wright negprot->ni_tzcorrection,
595148c5f43SAlan Wright negprot->ni_keylen, /* encryption key length */
596da6c28aaSamw VAR_BCC,
597148c5f43SAlan Wright (int)negprot->ni_keylen,
598148c5f43SAlan Wright negprot->ni_key, /* encryption key */
599148c5f43SAlan Wright wclen,
600148c5f43SAlan Wright wcbuf); /* nbdomain (unicode) */
601b89a8333Snatalie li - Sun Microsystems - Irvine United States
602b89a8333Snatalie li - Sun Microsystems - Irvine United States smb_msgbuf_term(&mb);
603da6c28aaSamw break;
604da6c28aaSamw
60512b65585SGordon Ross NT_LM_0_12_ext_sec:
60612b65585SGordon Ross /*
60712b65585SGordon Ross * This is the "Extended Security" variant of
60812b65585SGordon Ross * dialect NT_LM_0_12.
60912b65585SGordon Ross */
61012b65585SGordon Ross rc = smbsr_encode_result(sr, 17, VAR_BCC,
61112b65585SGordon Ross "bwbwwllllTwbw#c#c",
61212b65585SGordon Ross 17, /* wct */
61312b65585SGordon Ross negprot->ni_index, /* dialect index */
61412b65585SGordon Ross secmode, /* security mode */
61512b65585SGordon Ross negprot->ni_maxmpxcount, /* max MPX */
61612b65585SGordon Ross 1, /* max VCs */
61712b65585SGordon Ross (DWORD)smb_maxbufsize, /* max buffer size */
61812b65585SGordon Ross 0xFFFF, /* max raw size */
61912b65585SGordon Ross sesskey, /* session key */
62012b65585SGordon Ross negprot->ni_capabilities,
62112b65585SGordon Ross &negprot->ni_servertime, /* system time */
62212b65585SGordon Ross negprot->ni_tzcorrection,
62312b65585SGordon Ross 0, /* encryption key length (MBZ) */
62412b65585SGordon Ross VAR_BCC,
62512b65585SGordon Ross UUID_LEN,
62612b65585SGordon Ross sr->sr_cfg->skc_machine_uuid,
62712b65585SGordon Ross sr->sr_cfg->skc_negtok_len,
62812b65585SGordon Ross sr->sr_cfg->skc_negtok);
62912b65585SGordon Ross break;
63012b65585SGordon Ross
63112b65585SGordon Ross
632da6c28aaSamw default:
633148c5f43SAlan Wright rc = smbsr_encode_result(sr, 1, 0, "bww", 1, -1, 0);
634a90cf9f2SGordon Ross break;
635da6c28aaSamw }
636da6c28aaSamw
6377b59d02dSjb if (rc != 0)
638faa1795aSjb return (SDRC_ERROR);
6397b59d02dSjb
640da6c28aaSamw /*
641a90cf9f2SGordon Ross * Save the agreed dialect. Note that the state is also
642da6c28aaSamw * used to detect and reject attempts to re-negotiate.
643da6c28aaSamw */
644a90cf9f2SGordon Ross session->dialect = negprot->ni_dialect;
645a90cf9f2SGordon Ross session->s_state = SMB_SESSION_STATE_NEGOTIATED;
646a90cf9f2SGordon Ross
647a90cf9f2SGordon Ross /* Allow normal SMB1 requests now. */
648a90cf9f2SGordon Ross session->newrq_func = smb1sr_newrq;
649a90cf9f2SGordon Ross
650faa1795aSjb return (SDRC_SUCCESS);
651da6c28aaSamw }
652da6c28aaSamw
653148c5f43SAlan Wright static int
smb_xlate_dialect(const char * dialect)654148c5f43SAlan Wright smb_xlate_dialect(const char *dialect)
655148c5f43SAlan Wright {
6568622ec45SGordon Ross const smb_xlate_t *dp;
657148c5f43SAlan Wright int i;
658148c5f43SAlan Wright
659a90cf9f2SGordon Ross for (i = 0; i < smb_ndialects; ++i) {
660148c5f43SAlan Wright dp = &smb_dialect[i];
661148c5f43SAlan Wright
662148c5f43SAlan Wright if (strcmp(dp->str, dialect) == 0)
663148c5f43SAlan Wright return (dp->code);
664148c5f43SAlan Wright }
665da6c28aaSamw
666148c5f43SAlan Wright return (-1);
667da6c28aaSamw }
668