xref: /illumos-gate/usr/src/uts/common/fs/smbsrv/smb_tree_connect.c (revision 44bc9120699af80bb18366ca474cb2c618608ca9)
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 2012 Nexenta Systems, Inc. All rights reserved.
24  */
25 
26 #include <smbsrv/smb_kproto.h>
27 #include <smbsrv/smb_share.h>
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 	smb_arg_tcon_t	*tcon = &sr->sr_tcon;
65 	int		rc;
66 
67 	/*
68 	 * Perhaps this should be "%A.sA" now that unicode is enabled.
69 	 */
70 	rc = smbsr_decode_data(sr, "%AAA", sr, &tcon->path,
71 	    &tcon->password, &tcon->service);
72 
73 	tcon->flags = 0;
74 	tcon->optional_support = 0;
75 
76 	DTRACE_SMB_2(op__TreeConnect__start, smb_request_t *, sr,
77 	    smb_arg_tcon_t *, 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  * Flags (prefix with TREE_CONNECT_ANDX_):
137  * ==========================  ========================================
138  * 0x0001 DISCONECT_TID        The tree specified by TID in the SMB header
139  *                             should be disconnected - disconnect errors
140  *                             should be ignored.
141  *
142  * 0x0004 EXTENDED_SIGNATURES  Client request for signing key protection.
143  *
144  * 0x0008 EXTENDED_RESPONSE    Client request for extended information.
145  *
146  * Path follows UNC style syntax (\\server\share) and indicates the name
147  * of the resource to which the client wishes to connect.
148  *
149  * Because Password may be an authentication response, it is a variable
150  * length field with the length specified by PasswordLength.   If
151  * authentication is not being used, Password should be a null terminated
152  * ASCII string with PasswordLength set to the string size including the
153  * terminating null.
154  *
155  * The server can enforce whatever policy it desires to govern share
156  * access.  Administrative privilege is required for administrative
157  * shares (C$, etc.).
158  *
159  * The Service component indicates the type of resource the client
160  * intends to access.  Valid values are:
161  *
162  * Service   Description               Earliest Dialect Allowed
163  * ========  ========================  ================================
164  *
165  * A:        disk share                PC NETWORK PROGRAM 1.0
166  * LPT1:     printer                   PC NETWORK PROGRAM 1.0
167  * IPC       named pipe                MICROSOFT NETWORKS 3.0
168  * COMM      communications device     MICROSOFT NETWORKS 3.0
169  * ?????     any type of device        MICROSOFT NETWORKS 3.0
170  *
171  * If the negotiated dialect is earlier than DOS LANMAN2.1, the response to
172  * this SMB is:
173  *
174  * Server Response                  Description
175  * ================================ ===================================
176  *
177  * UCHAR WordCount;                 Count of parameter words = 2
178  * UCHAR AndXCommand;               Secondary (X) command;  0xFF = none
179  * UCHAR AndXReserved;              Reserved (must be 0)
180  * USHORT AndXOffset;               Offset to next command WordCount
181  * USHORT ByteCount;                Count of data bytes;    min = 3
182  *
183  * If the negotiated is DOS LANMAN2.1 or later, the response to this SMB
184  * is:
185  *
186  * Server Response                  Description
187  * ================================ ===================================
188  *
189  * UCHAR WordCount;                 Count of parameter words = 3
190  * UCHAR AndXCommand;               Secondary (X) command;  0xFF = none
191  * UCHAR AndXReserved;              Reserved (must be 0)
192  * USHORT AndXOffset;               Offset to next command WordCount
193  * USHORT OptionalSupport;          Optional support bits
194  * USHORT ByteCount;                Count of data bytes;    min = 3
195  * UCHAR Service[];                 Service type connected to.  Always
196  *                                   ANSII.
197  * STRING NativeFileSystem[];       Native file system for this tree
198  *
199  * NativeFileSystem is the name of the filesystem; values to be expected
200  * include FAT, NTFS, etc.
201  *
202  * OptionalSupport:
203  * ==============================  ==========================
204  * 0x0001 SMB_SUPPORT_SEARCH_BITS  The server supports the use of Search
205  *                                 Attributes in client requests.
206  * 0x0002 SMB_SHARE_IS_IN_DFS      The share is managed by DFS.
207  * 0x000C SMB_CSC_MASK             Offline-caching mask - see CSC flags.
208  * 0x0010 SMB_UNIQUE_FILE_NAME     The server uses long names and does not
209  *                                 support short names.  Indicator for
210  *                                 clients directory/name-space caching.
211  * 0x0020 SMB_EXTENDED_SIGNATURES  The server will use signing key protection.
212  *
213  * Client-side caching (offline files):
214  * ==============================  ==========================
215  * 0x0000 SMB_CSC_CACHE_MANUAL_REINT Clients may cache files for offline use
216  *                                 but automatic file-by-file reintegration
217  *                                 is not allowed.
218  * 0x0004 SMB_CSC_CACHE_AUTO_REINT Automatic file-by-file reintegration is
219  *                                 allowed.
220  * 0x0008 SMB_CSC_CACHE_VDO        File opens do not need to be flowed.
221  * 0x000C SMB_CSC_CACHE_NONE       CSC is disabled for this share.
222  *
223  * Some servers negotiate "DOS LANMAN2.1" dialect or later and still send
224  * the "downlevel" (i.e. wordcount==2) response.  Valid AndX following
225  * commands are
226  *
227  * SMB_COM_OPEN              SMB_COM_OPEN_ANDX          SMB_COM_CREATE
228  * SMB_COM_CREATE_NEW        SMB_COM_CREATE_DIRECTORY   SMB_COM_DELETE
229  * SMB_COM_DELETE_DIRECTORY  SMB_COM_FIND               SMB_COM_COPY
230  * SMB_COM_FIND_UNIQUE       SMB_COM_RENAME
231  * SMB_COM_CHECK_DIRECTORY   SMB_COM_QUERY_INFORMATION
232  * SMB_COM_GET_PRINT_QUEUE   SMB_COM_OPEN_PRINT_FILE
233  * SMB_COM_TRANSACTION       SMB_COM_NO_ANDX_CMD
234  * SMB_COM_SET_INFORMATION   SMB_COM_NT_RENAME
235  *
236  * Errors:
237  * ERRDOS/ERRnomem
238  * ERRDOS/ERRbadpath
239  * ERRDOS/ERRinvdevice
240  * ERRSRV/ERRaccess
241  * ERRSRV/ERRbadpw
242  * ERRSRV/ERRinvnetname
243  */
244 smb_sdrc_t
245 smb_pre_tree_connect_andx(smb_request_t *sr)
246 {
247 	smb_arg_tcon_t	*tcon = &sr->sr_tcon;
248 	uint8_t		*pwbuf = NULL;
249 	uint16_t	pwlen = 0;
250 	int		rc;
251 
252 	rc = smbsr_decode_vwv(sr, "b.www", &sr->andx_com, &sr->andx_off,
253 	    &tcon->flags, &pwlen);
254 	if (rc == 0) {
255 		if (pwlen != 0)
256 			pwbuf = smb_srm_zalloc(sr, pwlen);
257 
258 		rc = smbsr_decode_data(sr, "%#cus", sr, pwlen, pwbuf,
259 		    &tcon->path, &tcon->service);
260 
261 		tcon->pwdlen = pwlen;
262 		tcon->password = (char *)pwbuf;
263 	}
264 
265 	tcon->optional_support = 0;
266 
267 	DTRACE_SMB_2(op__TreeConnectX__start, smb_request_t *, sr,
268 	    smb_arg_tcon_t *, tcon);
269 
270 	return ((rc == 0) ? SDRC_SUCCESS : SDRC_ERROR);
271 }
272 
273 void
274 smb_post_tree_connect_andx(smb_request_t *sr)
275 {
276 	DTRACE_SMB_1(op__TreeConnectX__done, smb_request_t *, sr);
277 }
278 
279 smb_sdrc_t
280 smb_com_tree_connect_andx(smb_request_t *sr)
281 {
282 	smb_arg_tcon_t	*tcon = &sr->sr_tcon;
283 	smb_tree_t	*tree;
284 	char		*service;
285 	int		rc;
286 
287 	if ((tree = smb_tree_connect(sr)) == NULL)
288 		return (SDRC_ERROR);
289 
290 	sr->smb_tid = tree->t_tid;
291 	sr->tid_tree = tree;
292 
293 	switch (tree->t_res_type & STYPE_MASK) {
294 	case STYPE_IPC:
295 		service = "IPC";
296 		break;
297 	case STYPE_PRINTQ:
298 		service = "LPT1:";
299 		break;
300 	case STYPE_DISKTREE:
301 	default:
302 		service = "A:";
303 	}
304 
305 	if (sr->session->dialect < NT_LM_0_12) {
306 		rc = smbsr_encode_result(sr, 2, VAR_BCC, "bb.wwss",
307 		    (char)2,		/* wct */
308 		    sr->andx_com,
309 		    VAR_BCC,
310 		    VAR_BCC,
311 		    service,
312 		    sr->tid_tree->t_typename);
313 	} else {
314 		rc = smbsr_encode_result(sr, 3, VAR_BCC, "bb.wwws%u",
315 		    (char)3,		/* wct */
316 		    sr->andx_com,
317 		    (short)64,
318 		    tcon->optional_support,
319 		    VAR_BCC,
320 		    service,
321 		    sr,
322 		    sr->tid_tree->t_typename);
323 	}
324 
325 	return ((rc == 0) ? SDRC_SUCCESS : SDRC_ERROR);
326 }
327 
328 /*
329  * SmbTreeDisconnect: Disconnect a tree.
330  *
331  * Note: SDDF_SUPPRESS_UID is set for this operation, which means the sr
332  * uid_user field will not be valid on entry to these functions.  Do not
333  * use it until it is set up in smb_com_tree_disconnect() or the system
334  * will panic.
335  *
336  * Note: there are scenarios in which the client does not send a tree
337  * disconnect request, for example, when ERRbaduid is returned from
338  * SmbReadX after a user has logged off.  Any open files will remain
339  * around until the session is destroyed.
340  *
341  * Client Request                     Description
342  * ================================== =================================
343  *
344  * UCHAR WordCount;                   Count of parameter words = 0
345  * USHORT ByteCount;                  Count of data bytes = 0
346  *
347  * The resource sharing connection identified by Tid in the SMB header is
348  * logically disconnected from the server. Tid is invalidated; it will not
349  * be recognized if used by the client for subsequent requests. All locks,
350  * open files, etc. created on behalf of Tid are released.
351  *
352  * Server Response                    Description
353  * ================================== =================================
354  *
355  * UCHAR WordCount;                   Count of parameter words = 0
356  * USHORT ByteCount;                  Count of data bytes = 0
357  *
358  * Errors:
359  * ERRSRV/ERRinvnid
360  * ERRSRV/ERRbaduid
361  */
362 smb_sdrc_t
363 smb_pre_tree_disconnect(smb_request_t *sr)
364 {
365 	sr->uid_user = smb_session_lookup_uid(sr->session, sr->smb_uid);
366 	sr->tid_tree = smb_session_lookup_tree(sr->session, sr->smb_tid);
367 
368 	DTRACE_SMB_1(op__TreeDisconnect__start, smb_request_t *, sr);
369 	return (SDRC_SUCCESS);
370 }
371 
372 void
373 smb_post_tree_disconnect(smb_request_t *sr)
374 {
375 	DTRACE_SMB_1(op__TreeDisconnect__done, smb_request_t *, sr);
376 }
377 
378 /*
379  * SmbTreeDisconnect requires a valid UID as well as a valid TID.  Some
380  * clients logoff a user and then try to disconnect the trees connected
381  * by the user who has just been logged off, which would normally fail
382  * in the dispatch code with ERRbaduid but, unfortunately, ERRbaduid
383  * causes a problem for some of those clients.  Windows returns ERRinvnid.
384  *
385  * To prevent ERRbaduid being returned, the UID and TID are looked up here
386  * rather than prior to dispatching SmbTreeDisconnect requests.  If either
387  * the UID or the TID is invalid, ERRinvnid is returned.
388  */
389 smb_sdrc_t
390 smb_com_tree_disconnect(smb_request_t *sr)
391 {
392 	if (sr->uid_user == NULL || sr->tid_tree == NULL) {
393 		smbsr_error(sr, NT_STATUS_INVALID_HANDLE, ERRDOS, ERRinvnid);
394 		return (SDRC_ERROR);
395 	}
396 
397 	sr->user_cr = smb_user_getcred(sr->uid_user);
398 
399 	smb_session_cancel_requests(sr->session, sr->tid_tree, sr);
400 	smb_tree_disconnect(sr->tid_tree, B_TRUE);
401 
402 	if (smbsr_encode_empty_result(sr))
403 		return (SDRC_ERROR);
404 
405 	return (SDRC_SUCCESS);
406 }
407