xref: /illumos-gate/usr/src/uts/common/fs/smbsrv/smb_tree_connect.c (revision 1b8adde7ba7d5e04395c141c5400dc2cffd7d809)
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