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 #include <smbsrv/smb_incl.h> 27 28 29 /* 30 * SmbTreeConnect: Map a share to a tree and obtain a tree-id (TID). 31 * 32 * Client Request Description 33 * ================================== ================================= 34 * 35 * UCHAR WordCount; Count of parameter words = 0 36 * USHORT ByteCount; Count of data bytes; min = 4 37 * UCHAR BufferFormat1; 0x04 38 * STRING Path[]; Server name and share name 39 * UCHAR BufferFormat2; 0x04 40 * STRING Password[]; Password 41 * UCHAR BufferFormat3; 0x04 42 * STRING Service[]; Service name 43 * 44 * The CIFS server responds with: 45 * 46 * Server Response Description 47 * ================================ ================================= 48 * 49 * UCHAR WordCount; Count of parameter words = 2 50 * USHORT MaxBufferSize; Max size message the server handles 51 * USHORT Tid; Tree ID 52 * USHORT ByteCount; Count of data bytes = 0 53 * 54 * If the negotiated dialect is MICROSOFT NETWORKS 1.03 or earlier, 55 * MaxBufferSize in the response message indicates the maximum size 56 * message that the server can handle. The client should not generate 57 * messages, nor expect to receive responses, larger than this. This 58 * must be constant for a given server. For newer dialects, this field 59 * is ignored. 60 */ 61 smb_sdrc_t 62 smb_pre_tree_connect(smb_request_t *sr) 63 { 64 int rc; 65 66 /* 67 * Perhaps this should be "%A.sA" now that unicode is enabled. 68 */ 69 rc = smbsr_decode_data(sr, "%AAA", sr, &sr->arg.tcon.path, 70 &sr->arg.tcon.password, &sr->arg.tcon.service); 71 72 sr->arg.tcon.flags = 0; 73 74 DTRACE_SMB_2(op__TreeConnect__start, smb_request_t *, sr, 75 struct tcon *, &sr->arg.tcon); 76 77 return ((rc == 0) ? SDRC_SUCCESS : SDRC_ERROR); 78 } 79 80 void 81 smb_post_tree_connect(smb_request_t *sr) 82 { 83 DTRACE_SMB_1(op__TreeConnect__done, smb_request_t *, sr); 84 } 85 86 smb_sdrc_t 87 smb_com_tree_connect(smb_request_t *sr) 88 { 89 smb_tree_t *tree; 90 int rc; 91 92 if ((tree = smb_tree_connect(sr)) == NULL) 93 return (SDRC_ERROR); 94 95 sr->smb_tid = tree->t_tid; 96 sr->tid_tree = tree; 97 98 rc = smbsr_encode_result(sr, 2, 0, "bwww", 99 2, /* wct */ 100 (WORD)smb_maxbufsize, /* MaxBufferSize */ 101 sr->smb_tid, /* TID */ 102 0); /* bcc */ 103 104 return ((rc == 0) ? SDRC_SUCCESS : SDRC_ERROR); 105 } 106 107 /* 108 * SmbTreeConnectX: Map a share to a tree and obtain a tree-id (TID). 109 * 110 * Client Request Description 111 * ================================= ================================= 112 * 113 * UCHAR WordCount; Count of parameter words = 4 114 * UCHAR AndXCommand; Secondary (X) command; 0xFF = none 115 * UCHAR AndXReserved; Reserved (must be 0) 116 * USHORT AndXOffset; Offset to next command WordCount 117 * USHORT Flags; Additional information 118 * bit 0 set = disconnect Tid 119 * USHORT PasswordLength; Length of Password[] 120 * USHORT ByteCount; Count of data bytes; min = 3 121 * UCHAR Password[]; Password 122 * STRING Path[]; Server name and share name 123 * STRING Service[]; Service name 124 * 125 * If the negotiated dialect is LANMAN1.0 or later, then it is a protocol 126 * violation for the client to send this message prior to a successful 127 * SMB_COM_SESSION_SETUP_ANDX, and the server ignores Password. 128 * 129 * If the negotiated dialect is prior to LANMAN1.0 and the client has not 130 * sent a successful SMB_COM_SESSION_SETUP_ANDX request when the tree 131 * connect arrives, a user level security mode server must nevertheless 132 * validate the client's credentials. 133 * 134 * Path follows UNC style syntax, that is to say it is encoded as 135 * \\server\share and indicates the name of the resource to which the 136 * client wishes to connect. 137 * 138 * Because Password may be an authentication response, it is a variable 139 * length field with the length specified by PasswordLength. If 140 * authentication is not being used, Password should be a null terminated 141 * ASCII string with PasswordLength set to the string size including the 142 * terminating null. 143 * 144 * The server can enforce whatever policy it desires to govern share 145 * access. Administrative privilege is required for administrative 146 * shares (C$, etc.). 147 * 148 * The Service component indicates the type of resource the client 149 * intends to access. Valid values are: 150 * 151 * Service Description Earliest Dialect Allowed 152 * ======== ======================== ================================ 153 * 154 * A: disk share PC NETWORK PROGRAM 1.0 155 * LPT1: printer PC NETWORK PROGRAM 1.0 156 * IPC named pipe MICROSOFT NETWORKS 3.0 157 * COMM communications device MICROSOFT NETWORKS 3.0 158 * ????? any type of device MICROSOFT NETWORKS 3.0 159 * 160 * If bit0 of Flags is set, the tree connection to Tid in the SMB header 161 * should be disconnected. If this tree disconnect fails, the error should 162 * be ignored. 163 * 164 * If the negotiated dialect is earlier than DOS LANMAN2.1, the response to 165 * this SMB is: 166 * 167 * Server Response Description 168 * ================================ =================================== 169 * 170 * UCHAR WordCount; Count of parameter words = 2 171 * UCHAR AndXCommand; Secondary (X) command; 0xFF = none 172 * UCHAR AndXReserved; Reserved (must be 0) 173 * USHORT AndXOffset; Offset to next command WordCount 174 * USHORT ByteCount; Count of data bytes; min = 3 175 * 176 * If the negotiated is DOS LANMAN2.1 or later, the response to this SMB 177 * is: 178 * 179 * Server Response Description 180 * ================================ =================================== 181 * 182 * UCHAR WordCount; Count of parameter words = 3 183 * UCHAR AndXCommand; Secondary (X) command; 0xFF = none 184 * UCHAR AndXReserved; Reserved (must be 0) 185 * USHORT AndXOffset; Offset to next command WordCount 186 * USHORT OptionalSupport; Optional support bits 187 * USHORT ByteCount; Count of data bytes; min = 3 188 * UCHAR Service[]; Service type connected to. Always 189 * ANSII. 190 * STRING NativeFileSystem[]; Native file system for this tree 191 * 192 * NativeFileSystem is the name of the filesystem; values to be expected 193 * include FAT, NTFS, etc. 194 * 195 * OptionalSupport bits has the encoding: 196 * 197 * Name Encoding Description 198 * ============================= ========= ========================== 199 * SMB_SUPPORT_SEARCH_BITS 0x0001 200 * SMB_SHARE_IS_IN_DFS 0x0002 201 * 202 * Some servers negotiate "DOS LANMAN2.1" dialect or later and still send 203 * the "downlevel" (i.e. wordcount==2) response. Valid AndX following 204 * commands are 205 * 206 * SMB_COM_OPEN SMB_COM_OPEN_ANDX SMB_COM_CREATE 207 * SMB_COM_CREATE_NEW SMB_COM_CREATE_DIRECTORY SMB_COM_DELETE 208 * SMB_COM_DELETE_DIRECTORY SMB_COM_FIND SMB_COM_COPY 209 * SMB_COM_FIND_UNIQUE SMB_COM_RENAME 210 * SMB_COM_CHECK_DIRECTORY SMB_COM_QUERY_INFORMATION 211 * SMB_COM_GET_PRINT_QUEUE SMB_COM_OPEN_PRINT_FILE 212 * SMB_COM_TRANSACTION SMB_COM_NO_ANDX_CMD 213 * SMB_COM_SET_INFORMATION SMB_COM_NT_RENAME 214 * 215 * Errors: 216 * ERRDOS/ERRnomem 217 * ERRDOS/ERRbadpath 218 * ERRDOS/ERRinvdevice 219 * ERRSRV/ERRaccess 220 * ERRSRV/ERRbadpw 221 * ERRSRV/ERRinvnetname 222 */ 223 smb_sdrc_t 224 smb_pre_tree_connect_andx(smb_request_t *sr) 225 { 226 uint8_t *pwbuf = NULL; 227 uint16_t pwlen = 0; 228 int rc; 229 230 rc = smbsr_decode_vwv(sr, "b.www", &sr->andx_com, &sr->andx_off, 231 &sr->arg.tcon.flags, &pwlen); 232 if (rc == 0) { 233 if (pwlen != 0) { 234 pwbuf = (uint8_t *)smbsr_malloc(&sr->request_storage, 235 pwlen); 236 bzero(pwbuf, pwlen); 237 } 238 239 rc = smbsr_decode_data(sr, "%#cus", sr, pwlen, pwbuf, 240 &sr->arg.tcon.path, &sr->arg.tcon.service); 241 242 sr->arg.tcon.pwdlen = pwlen; 243 sr->arg.tcon.password = (char *)pwbuf; 244 } 245 246 DTRACE_SMB_2(op__TreeConnectX__start, smb_request_t *, sr, 247 struct tcon *, &sr->arg.tcon); 248 249 return ((rc == 0) ? SDRC_SUCCESS : SDRC_ERROR); 250 } 251 252 void 253 smb_post_tree_connect_andx(smb_request_t *sr) 254 { 255 DTRACE_SMB_1(op__TreeConnectX__done, smb_request_t *, sr); 256 } 257 258 smb_sdrc_t 259 smb_com_tree_connect_andx(smb_request_t *sr) 260 { 261 smb_tree_t *tree; 262 char *service; 263 int rc; 264 265 if ((tree = smb_tree_connect(sr)) == NULL) 266 return (SDRC_ERROR); 267 268 sr->smb_tid = tree->t_tid; 269 sr->tid_tree = tree; 270 271 if (STYPE_ISIPC(tree->t_res_type)) 272 service = "IPC"; 273 else 274 service = "A:"; 275 276 if (sr->session->dialect < NT_LM_0_12) { 277 rc = smbsr_encode_result(sr, 2, VAR_BCC, "bb.wwss", 278 (char)2, /* wct */ 279 sr->andx_com, 280 VAR_BCC, 281 VAR_BCC, 282 service, 283 sr->tid_tree->t_typename); 284 } else { 285 rc = smbsr_encode_result(sr, 3, VAR_BCC, "bb.wwws%u", 286 (char)3, /* wct */ 287 sr->andx_com, 288 (short)64, 289 (short)SMB_TREE_SUPPORT_SEARCH_BITS, 290 VAR_BCC, 291 service, 292 sr, 293 sr->tid_tree->t_typename); 294 } 295 296 return ((rc == 0) ? SDRC_SUCCESS : SDRC_ERROR); 297 } 298 299 /* 300 * SmbTreeDisconnect: Disconnect a tree. 301 * 302 * Note: SDDF_SUPPRESS_UID is set for this operation, which means the sr 303 * uid_user field will not be valid on entry to these functions. Do not 304 * use it until it is set up in smb_com_tree_disconnect() or the system 305 * will panic. 306 * 307 * Note: there are scenarios in which the client does not send a tree 308 * disconnect request, for example, when ERRbaduid is returned from 309 * SmbReadX after a user has logged off. Any open files will remain 310 * around until the session is destroyed. 311 * 312 * Client Request Description 313 * ================================== ================================= 314 * 315 * UCHAR WordCount; Count of parameter words = 0 316 * USHORT ByteCount; Count of data bytes = 0 317 * 318 * The resource sharing connection identified by Tid in the SMB header is 319 * logically disconnected from the server. Tid is invalidated; it will not 320 * be recognized if used by the client for subsequent requests. All locks, 321 * open files, etc. created on behalf of Tid are released. 322 * 323 * Server Response Description 324 * ================================== ================================= 325 * 326 * UCHAR WordCount; Count of parameter words = 0 327 * USHORT ByteCount; Count of data bytes = 0 328 * 329 * Errors: 330 * ERRSRV/ERRinvnid 331 * ERRSRV/ERRbaduid 332 */ 333 smb_sdrc_t 334 smb_pre_tree_disconnect(smb_request_t *sr) 335 { 336 DTRACE_SMB_1(op__TreeDisconnect__start, smb_request_t *, sr); 337 return (SDRC_SUCCESS); 338 } 339 340 void 341 smb_post_tree_disconnect(smb_request_t *sr) 342 { 343 DTRACE_SMB_1(op__TreeDisconnect__done, smb_request_t *, sr); 344 } 345 346 /* 347 * SmbTreeDisconnect requires a valid UID as well as a valid TID. Some 348 * clients logoff a user and then try to disconnect the trees connected 349 * by the user who has just been logged off, which would normally fail 350 * in the dispatch code with ERRbaduid but, unfortunately, ERRbaduid 351 * causes a problem for some of those clients. Windows returns ERRinvnid. 352 * 353 * To prevent ERRbaduid being returned, the UID and TID are looked up here 354 * rather than prior to dispatching SmbTreeDisconnect requests. If either 355 * the UID or the TID is invalid, ERRinvnid is returned. 356 */ 357 smb_sdrc_t 358 smb_com_tree_disconnect(smb_request_t *sr) 359 { 360 sr->uid_user = smb_user_lookup_by_uid(sr->session, sr->smb_uid); 361 if (sr->uid_user != NULL) 362 sr->tid_tree = smb_user_lookup_tree(sr->uid_user, 363 sr->smb_tid); 364 365 if (sr->uid_user == NULL || sr->tid_tree == NULL) { 366 smbsr_error(sr, NT_STATUS_INVALID_HANDLE, ERRDOS, ERRinvnid); 367 return (SDRC_ERROR); 368 } 369 370 sr->user_cr = smb_user_getcred(sr->uid_user); 371 372 smb_session_cancel_requests(sr->session, sr->tid_tree, sr); 373 smb_tree_disconnect(sr->tid_tree); 374 375 if (smbsr_encode_empty_result(sr)) 376 return (SDRC_ERROR); 377 378 return (SDRC_SUCCESS); 379 } 380