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