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 2016 Nexenta Systems, 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_2(op__TreeConnect__start, smb_request_t *, sr, 104 smb_arg_tcon_t *, tcon); 105 106 return ((rc == 0) ? SDRC_SUCCESS : SDRC_ERROR); 107 } 108 109 void 110 smb_post_tree_connect(smb_request_t *sr) 111 { 112 DTRACE_SMB_1(op__TreeConnect__done, smb_request_t *, sr); 113 } 114 115 smb_sdrc_t 116 smb_com_tree_connect(smb_request_t *sr) 117 { 118 uint32_t status; 119 int rc; 120 121 status = smb_tree_connect(sr); 122 if (status) { 123 smb_tcon_puterror(sr, status); 124 return (SDRC_ERROR); 125 } 126 127 rc = smbsr_encode_result(sr, 2, 0, "bwww", 128 2, /* wct */ 129 (WORD)smb_maxbufsize, /* MaxBufferSize */ 130 sr->smb_tid, /* TID */ 131 0); /* bcc */ 132 133 return ((rc == 0) ? SDRC_SUCCESS : SDRC_ERROR); 134 } 135 136 /* 137 * SmbTreeConnectX: Map a share to a tree and obtain a tree-id (TID). 138 * 139 * Client Request Description 140 * ================================= ================================= 141 * 142 * UCHAR WordCount; Count of parameter words = 4 143 * UCHAR AndXCommand; Secondary (X) command; 0xFF = none 144 * UCHAR AndXReserved; Reserved (must be 0) 145 * USHORT AndXOffset; Offset to next command WordCount 146 * USHORT Flags; Additional information 147 * bit 0 set = disconnect Tid 148 * USHORT PasswordLength; Length of Password[] 149 * USHORT ByteCount; Count of data bytes; min = 3 150 * UCHAR Password[]; Password 151 * STRING Path[]; Server name and share name 152 * STRING Service[]; Service name 153 * 154 * If the negotiated dialect is LANMAN1.0 or later, then it is a protocol 155 * violation for the client to send this message prior to a successful 156 * SMB_COM_SESSION_SETUP_ANDX, and the server ignores Password. 157 * 158 * If the negotiated dialect is prior to LANMAN1.0 and the client has not 159 * sent a successful SMB_COM_SESSION_SETUP_ANDX request when the tree 160 * connect arrives, a user level security mode server must nevertheless 161 * validate the client's credentials. 162 * 163 * Flags (prefix with TREE_CONNECT_ANDX_): 164 * ========================== ======================================== 165 * 0x0001 DISCONECT_TID The tree specified by TID in the SMB header 166 * should be disconnected - disconnect errors 167 * should be ignored. 168 * 169 * 0x0004 EXTENDED_SIGNATURES Client request for signing key protection. 170 * 171 * 0x0008 EXTENDED_RESPONSE Client request for extended information. 172 * 173 * Path follows UNC style syntax (\\server\share) and indicates the name 174 * of the resource to which the client wishes to connect. 175 * 176 * Because Password may be an authentication response, it is a variable 177 * length field with the length specified by PasswordLength. If 178 * authentication is not being used, Password should be a null terminated 179 * ASCII string with PasswordLength set to the string size including the 180 * terminating null. 181 * 182 * The server can enforce whatever policy it desires to govern share 183 * access. Administrative privilege is required for administrative 184 * shares (C$, etc.). 185 * 186 * The Service component indicates the type of resource the client 187 * intends to access. Valid values are: 188 * 189 * Service Description Earliest Dialect Allowed 190 * ======== ======================== ================================ 191 * 192 * A: disk share PC NETWORK PROGRAM 1.0 193 * LPT1: printer PC NETWORK PROGRAM 1.0 194 * IPC named pipe MICROSOFT NETWORKS 3.0 195 * COMM communications device MICROSOFT NETWORKS 3.0 196 * ????? any type of device MICROSOFT NETWORKS 3.0 197 * 198 * If the negotiated dialect is earlier than DOS LANMAN2.1, the response to 199 * this SMB is: 200 * 201 * Server Response Description 202 * ================================ =================================== 203 * 204 * UCHAR WordCount; Count of parameter words = 2 205 * UCHAR AndXCommand; Secondary (X) command; 0xFF = none 206 * UCHAR AndXReserved; Reserved (must be 0) 207 * USHORT AndXOffset; Offset to next command WordCount 208 * USHORT ByteCount; Count of data bytes; min = 3 209 * 210 * If the negotiated is DOS LANMAN2.1 or later, the response to this SMB 211 * is: 212 * 213 * Server Response Description 214 * ================================ =================================== 215 * 216 * UCHAR WordCount; Count of parameter words = 3 217 * UCHAR AndXCommand; Secondary (X) command; 0xFF = none 218 * UCHAR AndXReserved; Reserved (must be 0) 219 * USHORT AndXOffset; Offset to next command WordCount 220 * USHORT OptionalSupport; Optional support bits 221 * USHORT ByteCount; Count of data bytes; min = 3 222 * UCHAR Service[]; Service type connected to. Always 223 * ANSII. 224 * STRING NativeFileSystem[]; Native file system for this tree 225 * 226 * NativeFileSystem is the name of the filesystem; values to be expected 227 * include FAT, NTFS, etc. 228 * 229 * OptionalSupport: 230 * ============================== ========================== 231 * 0x0001 SMB_SUPPORT_SEARCH_BITS The server supports the use of Search 232 * Attributes in client requests. 233 * 0x0002 SMB_SHARE_IS_IN_DFS The share is managed by DFS. 234 * 0x000C SMB_CSC_MASK Offline-caching mask - see CSC flags. 235 * 0x0010 SMB_UNIQUE_FILE_NAME The server uses long names and does not 236 * support short names. Indicator for 237 * clients directory/name-space caching. 238 * 0x0020 SMB_EXTENDED_SIGNATURES The server will use signing key protection. 239 * 240 * Client-side caching (offline files): 241 * ============================== ========================== 242 * 0x0000 SMB_CSC_CACHE_MANUAL_REINT Clients may cache files for offline use 243 * but automatic file-by-file reintegration 244 * is not allowed. 245 * 0x0004 SMB_CSC_CACHE_AUTO_REINT Automatic file-by-file reintegration is 246 * allowed. 247 * 0x0008 SMB_CSC_CACHE_VDO File opens do not need to be flowed. 248 * 0x000C SMB_CSC_CACHE_NONE CSC is disabled for this share. 249 * 250 * Some servers negotiate "DOS LANMAN2.1" dialect or later and still send 251 * the "downlevel" (i.e. wordcount==2) response. Valid AndX following 252 * commands are 253 * 254 * SMB_COM_OPEN SMB_COM_OPEN_ANDX SMB_COM_CREATE 255 * SMB_COM_CREATE_NEW SMB_COM_CREATE_DIRECTORY SMB_COM_DELETE 256 * SMB_COM_DELETE_DIRECTORY SMB_COM_FIND SMB_COM_COPY 257 * SMB_COM_FIND_UNIQUE SMB_COM_RENAME 258 * SMB_COM_CHECK_DIRECTORY SMB_COM_QUERY_INFORMATION 259 * SMB_COM_GET_PRINT_QUEUE SMB_COM_OPEN_PRINT_FILE 260 * SMB_COM_TRANSACTION SMB_COM_NO_ANDX_CMD 261 * SMB_COM_SET_INFORMATION SMB_COM_NT_RENAME 262 * 263 * Errors: 264 * ERRDOS/ERRnomem 265 * ERRDOS/ERRbadpath 266 * ERRDOS/ERRinvdevice 267 * ERRSRV/ERRaccess 268 * ERRSRV/ERRbadpw 269 * ERRSRV/ERRinvnetname 270 */ 271 smb_sdrc_t 272 smb_pre_tree_connect_andx(smb_request_t *sr) 273 { 274 smb_arg_tcon_t *tcon = &sr->sr_tcon; 275 uint8_t *pwbuf = NULL; 276 uint16_t pwlen = 0; 277 int rc; 278 279 rc = smbsr_decode_vwv(sr, "b.www", &sr->andx_com, &sr->andx_off, 280 &tcon->flags, &pwlen); 281 if (rc == 0) { 282 if (pwlen != 0) 283 pwbuf = smb_srm_zalloc(sr, pwlen); 284 285 rc = smbsr_decode_data(sr, "%#cus", sr, pwlen, pwbuf, 286 &tcon->path, &tcon->service); 287 288 tcon->pwdlen = pwlen; 289 tcon->password = (char *)pwbuf; 290 } 291 292 tcon->optional_support = 0; 293 294 DTRACE_SMB_2(op__TreeConnectX__start, smb_request_t *, sr, 295 smb_arg_tcon_t *, tcon); 296 297 return ((rc == 0) ? SDRC_SUCCESS : SDRC_ERROR); 298 } 299 300 void 301 smb_post_tree_connect_andx(smb_request_t *sr) 302 { 303 DTRACE_SMB_1(op__TreeConnectX__done, smb_request_t *, sr); 304 } 305 306 smb_sdrc_t 307 smb_com_tree_connect_andx(smb_request_t *sr) 308 { 309 smb_arg_tcon_t *tcon = &sr->sr_tcon; 310 smb_tree_t *tree; 311 char *service; 312 uint32_t status; 313 int rc; 314 315 if (tcon->flags & SMB_TCONX_DISCONECT_TID) { 316 tree = smb_session_lookup_tree(sr->session, sr->smb_tid); 317 if (tree != NULL) { 318 smb_tree_disconnect(tree, B_TRUE); 319 smb_session_cancel_requests(sr->session, tree, sr); 320 } 321 } 322 323 status = smb_tree_connect(sr); 324 if (status) { 325 smb_tcon_puterror(sr, status); 326 return (SDRC_ERROR); 327 } 328 tree = sr->tid_tree; 329 330 switch (tree->t_res_type & STYPE_MASK) { 331 case STYPE_IPC: 332 service = "IPC"; 333 break; 334 case STYPE_PRINTQ: 335 service = "LPT1:"; 336 break; 337 case STYPE_DISKTREE: 338 default: 339 service = "A:"; 340 } 341 342 if (sr->session->dialect < NT_LM_0_12) { 343 rc = smbsr_encode_result(sr, 2, VAR_BCC, "bb.wwss", 344 (char)2, /* wct */ 345 sr->andx_com, 346 VAR_BCC, 347 VAR_BCC, 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.wwws%u", 352 (char)3, /* wct */ 353 sr->andx_com, 354 (short)64, 355 tcon->optional_support, 356 VAR_BCC, 357 service, 358 sr, 359 tree->t_typename); 360 361 } else { 362 rc = smbsr_encode_result(sr, 7, VAR_BCC, "bb.wwllws%u", 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 service, /* (s) */ 371 sr, /* (%) */ 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_1(op__TreeDisconnect__start, 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_1(op__TreeDisconnect__done, 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 }