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