xref: /titanic_44/usr/src/uts/common/fs/smbsrv/smb_negotiate.c (revision ff456394c7357ca406a78da6ff1c2eed71da259e)
1 /*
2  * CDDL HEADER START
3  *
4  * The contents of this file are subject to the terms of the
5  * Common Development and Distribution License (the "License").
6  * You may not use this file except in compliance with the License.
7  *
8  * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
9  * or http://www.opensolaris.org/os/licensing.
10  * See the License for the specific language governing permissions
11  * and limitations under the License.
12  *
13  * When distributing Covered Code, include this CDDL HEADER in each
14  * file and include the License file at usr/src/OPENSOLARIS.LICENSE.
15  * If applicable, add the following below this CDDL HEADER, with the
16  * fields enclosed by brackets "[]" replaced with your own identifying
17  * information: Portions Copyright [yyyy] [name of copyright owner]
18  *
19  * CDDL HEADER END
20  */
21 /*
22  * Copyright 2008 Sun Microsystems, Inc.  All rights reserved.
23  * Use is subject to license terms.
24  */
25 
26 #pragma ident	"%Z%%M%	%I%	%E% SMI"
27 
28 /*
29  * Notes on the virtual circuit (VC) values in the SMB Negotiate
30  * response and SessionSetupAndx request.
31  *
32  * A virtual circuit (VC) represents a connection between a client and a
33  * server using a reliable, session oriented transport protocol, such as
34  * NetBIOS or TCP/IP. Originally, each SMB session was restricted to a
35  * single underlying transport connection, i.e. a single NetBIOS session,
36  * which limited performance for raw data transfers.
37  *
38  * The intention behind multiple VCs was to improve performance by
39  * allowing parallelism over each NetBIOS session. For example, raw data
40  * could be transmitted using a different VC from other types of SMB
41  * requests to remove the interleaving restriction while a raw transfer
42  * is in progress. So the MaxNumberVcs field was added to the negotiate
43  * response to make the number of VCs configurable and to allow servers
44  * to specify how many they were prepared to support per session
45  * connection. This turned out to be difficult to manage and, with
46  * technology improvements, it has become obsolete.
47  *
48  * Servers should set the MaxNumberVcs value in the Negotiate response
49  * to 1. Clients should probably ignore it. If a server receives a
50  * SessionSetupAndx with a VC value of 0, it should close all other
51  * VCs to that client. If it receives a non-zero VC, it should leave
52  * other VCs in tact.
53  *
54  */
55 
56 /*
57  * SMB: negotiate
58  *
59  * Client Request                Description
60  * ============================  =======================================
61  *
62  * UCHAR WordCount;              Count of parameter words = 0
63  * USHORT ByteCount;             Count of data bytes; min = 2
64  * struct {
65  *    UCHAR BufferFormat;        0x02 -- Dialect
66  *    UCHAR DialectName[];       ASCII null-terminated string
67  * } Dialects[];
68  *
69  * The Client sends a list of dialects that it can communicate with.  The
70  * response is a selection of one of those dialects (numbered 0 through n)
71  * or -1 (hex FFFF) indicating that none of the dialects were acceptable.
72  * The negotiate message is binding on the virtual circuit and must be
73  * sent.  One and only one negotiate message may be sent, subsequent
74  * negotiate requests will be rejected with an error response and no action
75  * will be taken.
76  *
77  * The protocol does not impose any particular structure to the dialect
78  * strings.  Implementors of particular protocols may choose to include,
79  * for example, version numbers in the string.
80  *
81  * If the server does not understand any of the dialect strings, or if PC
82  * NETWORK PROGRAM 1.0 is the chosen dialect, the response format is
83  *
84  * Server Response               Description
85  * ============================  =======================================
86  *
87  * UCHAR WordCount;              Count of parameter words = 1
88  * USHORT DialectIndex;          Index of selected dialect
89  * USHORT ByteCount;             Count of data bytes = 0
90  *
91  * If the chosen dialect is greater than core up to and including
92  * LANMAN2.1, the protocol response format is
93  *
94  * Server Response               Description
95  * ============================  =======================================
96  *
97  * UCHAR WordCount;              Count of parameter words = 13
98  * USHORT  DialectIndex;         Index of selected dialect
99  * USHORT  SecurityMode;         Security mode:
100  *                               bit 0: 0 = share, 1 = user
101  *                               bit 1: 1 = use challenge/response
102  *                               authentication
103  * USHORT  MaxBufferSize;        Max transmit buffer size (>= 1024)
104  * USHORT  MaxMpxCount;          Max pending multiplexed requests
105  * USHORT  MaxNumberVcs;         Max VCs between client and server
106  * USHORT  RawMode;              Raw modes supported:
107  *                                bit 0: 1 = Read Raw supported
108  *                                bit 1: 1 = Write Raw supported
109  * ULONG SessionKey;             Unique token identifying this session
110  * SMB_TIME ServerTime;          Current time at server
111  * SMB_DATE ServerDate;          Current date at server
112  * USHORT ServerTimeZone;        Current time zone at server
113  * USHORT  EncryptionKeyLength;  MBZ if this is not LM2.1
114  * USHORT  Reserved;             MBZ
115  * USHORT  ByteCount             Count of data bytes
116  * UCHAR EncryptionKey[];        The challenge encryption key
117  * STRING PrimaryDomain[];       The server's primary domain
118  *
119  * MaxBufferSize is the size of the largest message which the client can
120  * legitimately send to the server
121  *
122  * If  bit0 of the Flags field is set in the negotiate response, this
123  * indicates the server supports the SMB_COM_LOCK_AND_READ and
124  * SMB_COM_WRITE_AND_UNLOCK client requests.
125  *
126  * If the SecurityMode field indicates the server is running in user mode,
127  * the client must send appropriate SMB_COM_SESSION_SETUP_ANDX requests
128  * before the server will allow the client to access resources.   If the
129  * SecurityMode fields indicates the client should use challenge/response
130  * authentication, the client should use the authentication mechanism
131  * specified in section 2.10.
132  *
133  * Clients should submit no more than MaxMpxCount distinct unanswered SMBs
134  * to the server when using multiplexed reads or writes (see sections 5.13
135  * and 5.25)
136  *
137  * Clients using the  "MICROSOFT NETWORKS 1.03" dialect use a different
138  * form of raw reads than documented here, and servers are better off
139  * setting RawMode in this response to 0 for such sessions.
140  *
141  * If the negotiated dialect is "DOS LANMAN2.1" or "LANMAN2.1", then
142  * PrimaryDomain string should be included in this response.
143  *
144  * If the negotiated dialect is NT LM 0.12, the response format is
145  *
146  * Server Response            Description
147  * ========================== =========================================
148  *
149  * UCHAR WordCount;           Count of parameter words = 17
150  * USHORT DialectIndex;       Index of selected dialect
151  * UCHAR SecurityMode;        Security mode:
152  *                             bit 0: 0 = share, 1 = user
153  *                             bit 1: 1 = encrypt passwords
154  * USHORT MaxMpxCount;        Max pending multiplexed requests
155  * USHORT MaxNumberVcs;       Max VCs between client and server
156  * ULONG MaxBufferSize;       Max transmit buffer size
157  * ULONG MaxRawSize;          Maximum raw buffer size
158  * ULONG SessionKey;          Unique token identifying this session
159  * ULONG Capabilities;        Server capabilities
160  * ULONG SystemTimeLow;       System (UTC) time of the server (low).
161  * ULONG SystemTimeHigh;      System (UTC) time of the server (high).
162  * USHORT ServerTimeZone;     Time zone of server (min from UTC)
163  * UCHAR EncryptionKeyLength; Length of encryption key.
164  * USHORT ByteCount;          Count of data bytes
165  * UCHAR EncryptionKey[];     The challenge encryption key
166  * UCHAR OemDomainName[];     The name of the domain (in OEM chars)
167  *
168  * In addition to the definitions above, MaxBufferSize is the size of the
169  * largest message which the client can legitimately send to the server.
170  * If the client is using a connectionless protocol,  MaxBufferSize must be
171  * set to the smaller of the server's internal buffer size and the amount
172  * of data which can be placed in a response packet.
173  *
174  * MaxRawSize specifies the maximum message size the server can send or
175  * receive for SMB_COM_WRITE_RAW or SMB_COM_READ_RAW.
176  *
177  * Connectionless clients must set Sid to 0 in the SMB request header.
178  *
179  * Capabilities allows the server to tell the client what it supports.
180  * The bit definitions defined in cifs.h. Bit 0x2000 used to be set in
181  * the negotiate response capabilities but it caused problems with
182  * Windows 2000. It is probably not valid, it doesn't appear in the
183  * CIFS spec.
184  *
185  * 4.1.1.1   Errors
186  *
187  * SUCCESS/SUCCESS
188  * ERRSRV/ERRerror
189  */
190 #include <sys/types.h>
191 #include <sys/strsubr.h>
192 #include <sys/socketvar.h>
193 #include <sys/socket.h>
194 #include <sys/random.h>
195 #include <netinet/in.h>
196 #include <smbsrv/smb_incl.h>
197 #include <smbsrv/smbinfo.h>
198 #include <smbsrv/smb_i18n.h>
199 
200 
201 /*
202  * Maximum buffer size for DOS: chosen to be the same as NT.
203  * Do not change this value, DOS is very sensitive to it.
204  */
205 #define	SMB_DOS_MAXBUF			0x1104
206 
207 /*
208  * Maximum buffer size for NT: configurable based on the client environment.
209  * IR104720 Experiments with Windows 2000 indicate that we achieve better
210  * SmbWriteX performance with a buffer size of 64KB instead of the 37KB
211  * used with Windows NT4.0. Previous experiments with NT4.0 resulted in
212  * directory listing problems so this buffer size is configurable based
213  * on the end-user environment. When in doubt use 37KB.
214  */
215 int smb_maxbufsize = SMB_NT_MAXBUF(37);
216 
217 /*
218  * The DOS TCP rcvbuf is set to 8700 because DOS 6.1 seems to have problems
219  * with other values. DOS 6.1 seems to depend on a window value of 8700 to
220  * send the next set of data. If we return a window value of 40KB, after
221  * sending 8700 bytes of data, it will start the next set of data from 40KB
222  * instead of 8.7k. Why 8.7k? We have no idea; it is the value that NT uses.
223  * September 2000.
224  *
225  * IR104720 Increased smb_nt_tcp_rcvbuf from 40KB to just under 1MB to allow
226  * for a larger TCP window sizei based on observations of Windows 2000 and
227  * performance testing. March 2003.
228  */
229 uint32_t	smb_dos_tcp_rcvbuf = 8700;
230 uint32_t	smb_nt_tcp_rcvbuf = 1048560;	/* scale factor of 4 */
231 
232 static void smb_get_security_info(
233     struct smb_request *sr,
234     unsigned short *secmode,
235     unsigned char *key,
236     unsigned char *keylen,
237     uint32_t *sesskey);
238 
239 /*
240  * Function: int smb_com_negotiate(struct smb_request *)
241  */
242 
243 smb_sdrc_t
244 smb_com_negotiate(struct smb_request *sr)
245 {
246 	int			dialect = 0;
247 	int			this_dialect;
248 	unsigned char		keylen;
249 	int			sel_pos = -1;
250 	int			pos;
251 	char 			key[32];
252 	char			*p;
253 	timestruc_t		time_val;
254 	unsigned short		secmode;
255 	uint32_t		sesskey;
256 	uint32_t		capabilities = 0;
257 	int			rc;
258 
259 	unsigned short max_mpx_count;
260 	WORD tz_correction;
261 	char ipaddr_buf[INET_ADDRSTRLEN];
262 
263 	if (sr->session->s_state != SMB_SESSION_STATE_ESTABLISHED) {
264 		/* The protocol has already been negotiated. */
265 		smbsr_error(sr, 0, ERRSRV, ERRerror);
266 		return (SDRC_ERROR_REPLY);
267 	}
268 
269 	for (pos = 0;
270 	    sr->smb_data.chain_offset < sr->smb_data.max_bytes;
271 	    pos++) {
272 		if (smb_decode_mbc(&sr->smb_data, "%L", sr, &p) != 0) {
273 			smbsr_error(sr, 0, ERRSRV, ERRerror);
274 			return (SDRC_ERROR_REPLY);
275 		}
276 
277 		this_dialect = smb_xlate_dialect_str_to_cd(p);
278 
279 		if (this_dialect < 0)
280 			continue;
281 
282 		if (dialect < this_dialect) {
283 			dialect = this_dialect;
284 			sel_pos = pos;
285 		}
286 	}
287 	if (sel_pos < 0) {
288 		smbsr_error(sr, 0, ERRSRV, ERRerror);
289 		return (SDRC_ERROR_REPLY);
290 	}
291 
292 	smb_get_security_info(sr, &secmode, (unsigned char *)key,
293 	    &keylen, &sesskey);
294 
295 	(void) microtime(&time_val);
296 
297 	tz_correction = -(WORD)(smb_get_gmtoff() / 60); /* tz correct. (min) */
298 
299 	switch (dialect) {
300 	case DIALECT_UNKNOWN:
301 	case PC_NETWORK_PROGRAM_1_0:	/* core */
302 		(void) sosetsockopt(sr->session->sock, SOL_SOCKET, SO_RCVBUF,
303 		    (const void *)&smb_dos_tcp_rcvbuf,
304 		    sizeof (smb_dos_tcp_rcvbuf));
305 		rc = smbsr_encode_result(sr, 1, 0, "bww", 1, sel_pos, 0);
306 		break;
307 
308 	case Windows_for_Workgroups_3_1a:
309 	case PCLAN1_0:
310 	case MICROSOFT_NETWORKS_1_03:
311 	case MICROSOFT_NETWORKS_3_0:
312 	case LANMAN1_0:
313 	case LM1_2X002:
314 	case DOS_LM1_2X002:
315 		(void) sosetsockopt(sr->session->sock, SOL_SOCKET, SO_RCVBUF,
316 		    (const void *)&smb_dos_tcp_rcvbuf,
317 		    sizeof (smb_dos_tcp_rcvbuf));
318 		sr->smb_flg |= SMB_FLAGS_LOCK_AND_READ_OK;
319 		rc = smbsr_encode_result(sr, 13, VAR_BCC,
320 		    "(wct) b" "(dix) w" "(sec) w" "(mbs) w"
321 		    "(mmc) w" "(mnv) w" "(raw) w" "(key) l"
322 		    "(tim/dat) Y"       "(tz)  w" "(ekl) w"
323 		    "(mbz) 2.""(bcc) w" "(key) #c",
324 		    13,		/* wct */
325 		    sel_pos,	/* dialect index */
326 		    secmode,		/* security mode */
327 		    SMB_DOS_MAXBUF,	/* max buffer size */
328 		    1,		/* max MPX (temporary) */
329 		    1,		/* max VCs (temporary, ambiguous) */
330 		    3,		/* raw mode (s/b 3) */
331 		    sesskey,	/* session key */
332 		    time_val.tv_sec, /* server time/date */
333 		    tz_correction,  /* see smb_get_gmtoff */
334 		    (short)keylen,	/* Encryption Key Length */
335 				/* reserved field handled 2. */
336 		    VAR_BCC,
337 		    (int)keylen,
338 		    key);		/* encryption key */
339 		break;
340 
341 	case DOS_LANMAN2_1:
342 	case LANMAN2_1:
343 		(void) sosetsockopt(sr->session->sock, SOL_SOCKET, SO_RCVBUF,
344 		    (const void *)&smb_dos_tcp_rcvbuf,
345 		    sizeof (smb_dos_tcp_rcvbuf));
346 		sr->smb_flg |= SMB_FLAGS_LOCK_AND_READ_OK;
347 		rc = smbsr_encode_result(sr, 13, VAR_BCC,
348 		    "(wct) b" "(dix) w" "(sec) w" "(mbs) w"
349 		    "(mmc) w" "(mnv) w" "(raw) w" "(key) l"
350 		    "(tim/dat) Y"       "(tz)  w" "(ekl) w"
351 		    "(mbz) 2.""(bcc) w" "(key) #c" "(dom) s",
352 		    13,		/* wct */
353 		    sel_pos,	/* dialect index */
354 		    secmode,		/* security mode */
355 		    SMB_DOS_MAXBUF,	/* max buffer size */
356 		    1,		/* max MPX (temporary) */
357 		    1,		/* max VCs (temporary, ambiguous) */
358 		    3,		/* raw mode (s/b 3) */
359 		    sesskey,	/* session key */
360 		    time_val.tv_sec, /* server time/date */
361 		    tz_correction,
362 		    (short)keylen,	/* Encryption Key Length */
363 				/* reserved field handled 2. */
364 		    VAR_BCC,
365 		    (int)keylen,
366 		    key,		/* encryption key */
367 		    smb_info.si.skc_resource_domain);
368 		break;
369 
370 	case NT_LM_0_12:
371 		(void) sosetsockopt(sr->session->sock, SOL_SOCKET, SO_RCVBUF,
372 		    (const void *)&smb_nt_tcp_rcvbuf,
373 		    sizeof (smb_nt_tcp_rcvbuf));
374 		capabilities = CAP_LARGE_FILES
375 		    | CAP_NT_SMBS
376 		    | CAP_STATUS32
377 		    | CAP_NT_FIND
378 		    | CAP_RAW_MODE
379 		    | CAP_LEVEL_II_OPLOCKS
380 		    | CAP_LOCK_AND_READ
381 		    | CAP_RPC_REMOTE_APIS
382 		    | CAP_LARGE_READX;
383 
384 		/*
385 		 * UNICODE support is required to enable support for long
386 		 * share names and long file names and streams.
387 		 */
388 
389 		capabilities |= CAP_UNICODE;
390 
391 
392 		/*
393 		 * Turn off Extended Security Negotiation
394 		 */
395 		sr->smb_flg2 &= ~SMB_FLAGS2_EXT_SEC;
396 
397 		/*
398 		 * Allow SMB signatures if security challenge response enabled
399 		 */
400 		if ((secmode & NEGOTIATE_SECURITY_CHALLENGE_RESPONSE) &&
401 		    smb_info.si.skc_signing_enable) {
402 			secmode |= NEGOTIATE_SECURITY_SIGNATURES_ENABLED;
403 			if (smb_info.si.skc_signing_required)
404 				secmode |=
405 				    NEGOTIATE_SECURITY_SIGNATURES_REQUIRED;
406 
407 			sr->session->secmode = secmode;
408 		}
409 
410 		(void) inet_ntop(AF_INET, (char *)&sr->session->ipaddr,
411 		    ipaddr_buf, sizeof (ipaddr_buf));
412 		/*LINTED E_ASSIGN_NARROW_CONV (uint16_t)*/
413 		max_mpx_count = smb_info.si.skc_maxworkers;
414 
415 		rc = smbsr_encode_result(sr, 17, VAR_BCC,
416 		    "(wct) b" "(dix) w" "(sec) b" "(mmc) w"
417 		    "(mnv) w" "(mbs) l" "(raw) l" "(key) l"
418 		    "(cap) l" "(tim) T" "(tz) w" "(ekl) b"
419 		    "(bcc) w" "(key) #c" "(dom) Z",
420 		    17,		/* wct */
421 		    sel_pos,	/* dialect index */
422 		    secmode,	/* security mode */
423 		    max_mpx_count,		/* max MPX (temporary) */
424 		    1,		/* max VCs (temporary, ambiguous) */
425 		    (DWORD)smb_maxbufsize,	/* max buffer size */
426 		    0xFFFF,	/* max raw size */
427 		    sesskey,	/* session key */
428 		    capabilities,
429 		    &time_val,			/* system time */
430 		    tz_correction,
431 		    keylen,			/* Encryption Key Length */
432 		    VAR_BCC,
433 		    (int)keylen,
434 		    key,			/* encryption key */
435 		    smb_info.si.skc_resource_domain);
436 		break;
437 
438 	default:
439 		smbsr_error(sr, 0, ERRSRV, ERRerror);
440 		return (SDRC_ERROR_REPLY);
441 	}
442 
443 	if (rc != 0)
444 		return (SDRC_ERROR_REPLY);
445 
446 	/*
447 	 * Save the agreed dialect. Note that this value is also
448 	 * used to detect and reject attempts to re-negotiate.
449 	 */
450 	sr->session->dialect = dialect;
451 	sr->session->s_state = SMB_SESSION_STATE_NEGOTIATED;
452 	return (SDRC_NORMAL_REPLY);
453 }
454 
455 static void
456 smb_get_security_info(
457     struct smb_request *sr,
458     unsigned short *secmode,
459     unsigned char *key,
460     unsigned char *keylen,
461     uint32_t *sesskey)
462 {
463 	uchar_t tmp_key[8];
464 
465 	(void) random_get_pseudo_bytes(tmp_key, 8);
466 	bcopy(tmp_key, &sr->session->challenge_key, 8);
467 	sr->session->challenge_len = 8;
468 	*keylen = 8;
469 	bcopy(tmp_key, key, 8);
470 
471 	sr->session->secmode = NEGOTIATE_SECURITY_CHALLENGE_RESPONSE|
472 	    NEGOTIATE_SECURITY_USER_LEVEL;
473 
474 	(void) random_get_pseudo_bytes(tmp_key, 4);
475 	sr->session->sesskey = tmp_key[0] | tmp_key[1] << 8 |
476 	    tmp_key[2] << 16 | tmp_key[3] << 24;
477 
478 	*secmode = sr->session->secmode;
479 	*sesskey = sr->session->sesskey;
480 }
481