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 (c) 2007, 2010, Oracle and/or its affiliates. All rights reserved. 23 * Copyright 2019 Nexenta by DDN, Inc. All rights reserved. 24 */ 25 26 #include <smbsrv/smb_kproto.h> 27 #include <smbsrv/smb_share.h> 28 29 static void 30 smb_tcon_puterror(smb_request_t *sr, uint32_t status) 31 { 32 33 switch (status) { 34 35 case NT_STATUS_BAD_NETWORK_NAME: 36 /* Intentional status=0 */ 37 smbsr_error(sr, 0, ERRSRV, ERRinvnetname); 38 break; 39 40 case NT_STATUS_ACCESS_DENIED: 41 smbsr_error(sr, status, ERRSRV, ERRaccess); 42 break; 43 44 case NT_STATUS_BAD_DEVICE_TYPE: 45 smbsr_error(sr, status, ERRDOS, ERROR_BAD_DEV_TYPE); 46 break; 47 48 default: 49 case NT_STATUS_INTERNAL_ERROR: 50 /* Intentional status=0 */ 51 smbsr_error(sr, 0, ERRSRV, ERRsrverror); 52 break; 53 } 54 } 55 56 /* 57 * SmbTreeConnect: Map a share to a tree and obtain a tree-id (TID). 58 * 59 * Client Request Description 60 * ================================== ================================= 61 * 62 * UCHAR WordCount; Count of parameter words = 0 63 * USHORT ByteCount; Count of data bytes; min = 4 64 * UCHAR BufferFormat1; 0x04 65 * STRING Path[]; Server name and share name 66 * UCHAR BufferFormat2; 0x04 67 * STRING Password[]; Password 68 * UCHAR BufferFormat3; 0x04 69 * STRING Service[]; Service name 70 * 71 * The CIFS server responds with: 72 * 73 * Server Response Description 74 * ================================ ================================= 75 * 76 * UCHAR WordCount; Count of parameter words = 2 77 * USHORT MaxBufferSize; Max size message the server handles 78 * USHORT Tid; Tree ID 79 * USHORT ByteCount; Count of data bytes = 0 80 * 81 * If the negotiated dialect is MICROSOFT NETWORKS 1.03 or earlier, 82 * MaxBufferSize in the response message indicates the maximum size 83 * message that the server can handle. The client should not generate 84 * messages, nor expect to receive responses, larger than this. This 85 * must be constant for a given server. For newer dialects, this field 86 * is ignored. 87 */ 88 smb_sdrc_t 89 smb_pre_tree_connect(smb_request_t *sr) 90 { 91 smb_arg_tcon_t *tcon = &sr->sr_tcon; 92 int rc; 93 94 /* 95 * Perhaps this should be "%A.sA" now that unicode is enabled. 96 */ 97 rc = smbsr_decode_data(sr, "%AAA", sr, &tcon->path, 98 &tcon->password, &tcon->service); 99 100 tcon->flags = 0; 101 tcon->optional_support = 0; 102 103 DTRACE_SMB_START(op__TreeConnect, smb_request_t *, sr); 104 105 return ((rc == 0) ? SDRC_SUCCESS : SDRC_ERROR); 106 } 107 108 void 109 smb_post_tree_connect(smb_request_t *sr) 110 { 111 DTRACE_SMB_DONE(op__TreeConnect, smb_request_t *, sr); 112 } 113 114 smb_sdrc_t 115 smb_com_tree_connect(smb_request_t *sr) 116 { 117 uint32_t status; 118 int rc; 119 120 status = smb_tree_connect(sr); 121 if (status) { 122 smb_tcon_puterror(sr, status); 123 return (SDRC_ERROR); 124 } 125 126 rc = smbsr_encode_result(sr, 2, 0, "bwww", 127 2, /* wct */ 128 (WORD)smb_maxbufsize, /* MaxBufferSize */ 129 sr->smb_tid, /* TID */ 130 0); /* bcc */ 131 132 return ((rc == 0) ? SDRC_SUCCESS : SDRC_ERROR); 133 } 134 135 /* 136 * SmbTreeConnectX: Map a share to a tree and obtain a tree-id (TID). 137 * 138 * Client Request Description 139 * ================================= ================================= 140 * 141 * UCHAR WordCount; Count of parameter words = 4 142 * UCHAR AndXCommand; Secondary (X) command; 0xFF = none 143 * UCHAR AndXReserved; Reserved (must be 0) 144 * USHORT AndXOffset; Offset to next command WordCount 145 * USHORT Flags; Additional information 146 * bit 0 set = disconnect Tid 147 * USHORT PasswordLength; Length of Password[] 148 * USHORT ByteCount; Count of data bytes; min = 3 149 * UCHAR Password[]; Password 150 * STRING Path[]; Server name and share name 151 * STRING Service[]; Service name 152 * 153 * If the negotiated dialect is LANMAN1.0 or later, then it is a protocol 154 * violation for the client to send this message prior to a successful 155 * SMB_COM_SESSION_SETUP_ANDX, and the server ignores Password. 156 * 157 * If the negotiated dialect is prior to LANMAN1.0 and the client has not 158 * sent a successful SMB_COM_SESSION_SETUP_ANDX request when the tree 159 * connect arrives, a user level security mode server must nevertheless 160 * validate the client's credentials. 161 * 162 * Flags (prefix with TREE_CONNECT_ANDX_): 163 * ========================== ======================================== 164 * 0x0001 DISCONECT_TID The tree specified by TID in the SMB header 165 * should be disconnected - disconnect errors 166 * should be ignored. 167 * 168 * 0x0004 EXTENDED_SIGNATURES Client request for signing key protection. 169 * 170 * 0x0008 EXTENDED_RESPONSE Client request for extended information. 171 * 172 * Path follows UNC style syntax (\\server\share) and indicates the name 173 * of the resource to which the client wishes to connect. 174 * 175 * Because Password may be an authentication response, it is a variable 176 * length field with the length specified by PasswordLength. If 177 * authentication is not being used, Password should be a null terminated 178 * ASCII string with PasswordLength set to the string size including the 179 * terminating null. 180 * 181 * The server can enforce whatever policy it desires to govern share 182 * access. Administrative privilege is required for administrative 183 * shares (C$, etc.). 184 * 185 * The Service component indicates the type of resource the client 186 * intends to access. Valid values are: 187 * 188 * Service Description Earliest Dialect Allowed 189 * ======== ======================== ================================ 190 * 191 * A: disk share PC NETWORK PROGRAM 1.0 192 * LPT1: printer PC NETWORK PROGRAM 1.0 193 * IPC named pipe MICROSOFT NETWORKS 3.0 194 * COMM communications device MICROSOFT NETWORKS 3.0 195 * ????? any type of device MICROSOFT NETWORKS 3.0 196 * 197 * If the negotiated dialect is earlier than DOS LANMAN2.1, the response to 198 * this SMB is: 199 * 200 * Server Response Description 201 * ================================ =================================== 202 * 203 * UCHAR WordCount; Count of parameter words = 2 204 * UCHAR AndXCommand; Secondary (X) command; 0xFF = none 205 * UCHAR AndXReserved; Reserved (must be 0) 206 * USHORT AndXOffset; Offset to next command WordCount 207 * USHORT ByteCount; Count of data bytes; min = 3 208 * 209 * If the negotiated is DOS LANMAN2.1 or later, the response to this SMB 210 * is: 211 * 212 * Server Response Description 213 * ================================ =================================== 214 * 215 * UCHAR WordCount; Count of parameter words = 3 216 * UCHAR AndXCommand; Secondary (X) command; 0xFF = none 217 * UCHAR AndXReserved; Reserved (must be 0) 218 * USHORT AndXOffset; Offset to next command WordCount 219 * USHORT OptionalSupport; Optional support bits 220 * USHORT ByteCount; Count of data bytes; min = 3 221 * UCHAR Service[]; Service type connected to. Always 222 * ANSII. 223 * STRING NativeFileSystem[]; Native file system for this tree 224 * 225 * NativeFileSystem is the name of the filesystem; values to be expected 226 * include FAT, NTFS, etc. 227 * 228 * OptionalSupport: 229 * ============================== ========================== 230 * 0x0001 SMB_SUPPORT_SEARCH_BITS The server supports the use of Search 231 * Attributes in client requests. 232 * 0x0002 SMB_SHARE_IS_IN_DFS The share is managed by DFS. 233 * 0x000C SMB_CSC_MASK Offline-caching mask - see CSC flags. 234 * 0x0010 SMB_UNIQUE_FILE_NAME The server uses long names and does not 235 * support short names. Indicator for 236 * clients directory/name-space caching. 237 * 0x0020 SMB_EXTENDED_SIGNATURES The server will use signing key protection. 238 * 239 * Client-side caching (offline files): 240 * ============================== ========================== 241 * 0x0000 SMB_CSC_CACHE_MANUAL_REINT Clients may cache files for offline use 242 * but automatic file-by-file reintegration 243 * is not allowed. 244 * 0x0004 SMB_CSC_CACHE_AUTO_REINT Automatic file-by-file reintegration is 245 * allowed. 246 * 0x0008 SMB_CSC_CACHE_VDO File opens do not need to be flowed. 247 * 0x000C SMB_CSC_CACHE_NONE CSC is disabled for this share. 248 * 249 * Some servers negotiate "DOS LANMAN2.1" dialect or later and still send 250 * the "downlevel" (i.e. wordcount==2) response. Valid AndX following 251 * commands are 252 * 253 * SMB_COM_OPEN SMB_COM_OPEN_ANDX SMB_COM_CREATE 254 * SMB_COM_CREATE_NEW SMB_COM_CREATE_DIRECTORY SMB_COM_DELETE 255 * SMB_COM_DELETE_DIRECTORY SMB_COM_FIND SMB_COM_COPY 256 * SMB_COM_FIND_UNIQUE SMB_COM_RENAME 257 * SMB_COM_CHECK_DIRECTORY SMB_COM_QUERY_INFORMATION 258 * SMB_COM_GET_PRINT_QUEUE SMB_COM_OPEN_PRINT_FILE 259 * SMB_COM_TRANSACTION SMB_COM_NO_ANDX_CMD 260 * SMB_COM_SET_INFORMATION SMB_COM_NT_RENAME 261 * 262 * Errors: 263 * ERRDOS/ERRnomem 264 * ERRDOS/ERRbadpath 265 * ERRDOS/ERRinvdevice 266 * ERRSRV/ERRaccess 267 * ERRSRV/ERRbadpw 268 * ERRSRV/ERRinvnetname 269 */ 270 smb_sdrc_t 271 smb_pre_tree_connect_andx(smb_request_t *sr) 272 { 273 smb_arg_tcon_t *tcon = &sr->sr_tcon; 274 uint8_t *pwbuf = NULL; 275 uint16_t pwlen = 0; 276 int rc; 277 278 rc = smbsr_decode_vwv(sr, "b.www", &sr->andx_com, &sr->andx_off, 279 &tcon->flags, &pwlen); 280 if (rc == 0) { 281 if (pwlen != 0) 282 pwbuf = smb_srm_zalloc(sr, pwlen); 283 284 rc = smbsr_decode_data(sr, "%#cus", sr, pwlen, pwbuf, 285 &tcon->path, &tcon->service); 286 287 tcon->pwdlen = pwlen; 288 tcon->password = (char *)pwbuf; 289 } 290 291 tcon->optional_support = 0; 292 293 DTRACE_SMB_START(op__TreeConnectX, smb_request_t *, sr); 294 295 return ((rc == 0) ? SDRC_SUCCESS : SDRC_ERROR); 296 } 297 298 void 299 smb_post_tree_connect_andx(smb_request_t *sr) 300 { 301 DTRACE_SMB_DONE(op__TreeConnectX, smb_request_t *, sr); 302 } 303 304 smb_sdrc_t 305 smb_com_tree_connect_andx(smb_request_t *sr) 306 { 307 smb_arg_tcon_t *tcon = &sr->sr_tcon; 308 smb_tree_t *tree; 309 char *service; 310 uint32_t status; 311 int rc; 312 313 if (tcon->flags & SMB_TCONX_DISCONECT_TID) { 314 tree = smb_session_lookup_tree(sr->session, sr->smb_tid); 315 if (tree != NULL) { 316 smb_tree_disconnect(tree, B_TRUE); 317 smb_session_cancel_requests(sr->session, tree, sr); 318 smb_tree_release(tree); 319 } 320 } 321 322 status = smb_tree_connect(sr); 323 if (status) { 324 smb_tcon_puterror(sr, status); 325 return (SDRC_ERROR); 326 } 327 tree = sr->tid_tree; 328 329 switch (tree->t_res_type & STYPE_MASK) { 330 case STYPE_IPC: 331 service = "IPC"; 332 break; 333 case STYPE_PRINTQ: 334 service = "LPT1:"; 335 break; 336 case STYPE_DISKTREE: 337 default: 338 service = "A:"; 339 } 340 341 if (sr->session->dialect < NT_LM_0_12) { 342 rc = smbsr_encode_result(sr, 2, VAR_BCC, "bb.ww%ss", 343 (char)2, /* wct */ 344 sr->andx_com, 345 VAR_BCC, 346 VAR_BCC, 347 sr, 348 service, 349 tree->t_typename); 350 } else if ((tcon->flags & SMB_TCONX_EXTENDED_RESPONSE) == 0) { 351 rc = smbsr_encode_result(sr, 3, VAR_BCC, "bb.www%su", 352 (char)3, /* wct */ 353 sr->andx_com, 354 (short)64, 355 tcon->optional_support, 356 VAR_BCC, 357 sr, 358 service, 359 tree->t_typename); 360 361 } else { 362 rc = smbsr_encode_result(sr, 7, VAR_BCC, "bb.wwllw%su", 363 (char)7, /* wct (b) */ 364 sr->andx_com, /* AndXcmd (b) */ 365 (short)72, /* AndXoff (w) */ 366 tcon->optional_support, /* (w) */ 367 tree->t_access, /* (l) */ 368 0, /* guest_access (l) */ 369 VAR_BCC, /* (w) */ 370 sr, /* (%) */ 371 service, /* (s) */ 372 tree->t_typename); /* (u) */ 373 } 374 375 return ((rc == 0) ? SDRC_SUCCESS : SDRC_ERROR); 376 } 377 378 /* 379 * SmbTreeDisconnect: Disconnect a tree. 380 * 381 * Note: SDDF_SUPPRESS_UID is set for this operation, which means the sr 382 * uid_user field will not be valid on entry to these functions. Do not 383 * use it until it is set up in smb_com_tree_disconnect() or the system 384 * will panic. 385 * 386 * Note: there are scenarios in which the client does not send a tree 387 * disconnect request, for example, when ERRbaduid is returned from 388 * SmbReadX after a user has logged off. Any open files will remain 389 * around until the session is destroyed. 390 * 391 * Client Request Description 392 * ================================== ================================= 393 * 394 * UCHAR WordCount; Count of parameter words = 0 395 * USHORT ByteCount; Count of data bytes = 0 396 * 397 * The resource sharing connection identified by Tid in the SMB header is 398 * logically disconnected from the server. Tid is invalidated; it will not 399 * be recognized if used by the client for subsequent requests. All locks, 400 * open files, etc. created on behalf of Tid are released. 401 * 402 * Server Response Description 403 * ================================== ================================= 404 * 405 * UCHAR WordCount; Count of parameter words = 0 406 * USHORT ByteCount; Count of data bytes = 0 407 * 408 * Errors: 409 * ERRSRV/ERRinvnid 410 * ERRSRV/ERRbaduid 411 */ 412 smb_sdrc_t 413 smb_pre_tree_disconnect(smb_request_t *sr) 414 { 415 sr->uid_user = smb_session_lookup_uid(sr->session, sr->smb_uid); 416 sr->tid_tree = smb_session_lookup_tree(sr->session, sr->smb_tid); 417 418 DTRACE_SMB_START(op__TreeDisconnect, smb_request_t *, sr); 419 return (SDRC_SUCCESS); 420 } 421 422 void 423 smb_post_tree_disconnect(smb_request_t *sr) 424 { 425 DTRACE_SMB_DONE(op__TreeDisconnect, smb_request_t *, sr); 426 } 427 428 /* 429 * SmbTreeDisconnect requires a valid UID as well as a valid TID. Some 430 * clients logoff a user and then try to disconnect the trees connected 431 * by the user who has just been logged off, which would normally fail 432 * in the dispatch code with ERRbaduid but, unfortunately, ERRbaduid 433 * causes a problem for some of those clients. Windows returns ERRinvnid. 434 * 435 * To prevent ERRbaduid being returned, the UID and TID are looked up here 436 * rather than prior to dispatching SmbTreeDisconnect requests. If either 437 * the UID or the TID is invalid, ERRinvnid is returned. 438 */ 439 smb_sdrc_t 440 smb_com_tree_disconnect(smb_request_t *sr) 441 { 442 if (sr->uid_user == NULL || sr->tid_tree == NULL) { 443 smbsr_error(sr, NT_STATUS_INVALID_HANDLE, ERRDOS, ERRinvnid); 444 return (SDRC_ERROR); 445 } 446 447 sr->user_cr = smb_user_getcred(sr->uid_user); 448 449 smb_tree_disconnect(sr->tid_tree, B_TRUE); 450 smb_session_cancel_requests(sr->session, sr->tid_tree, sr); 451 452 if (smbsr_encode_empty_result(sr)) 453 return (SDRC_ERROR); 454 455 return (SDRC_SUCCESS); 456 } 457