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