xref: /illumos-gate/usr/src/uts/common/fs/smbsrv/smb_tree_connect.c (revision 0897f7fbb62326e60e858c62a1654b2ca3e2667e)
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 2016 Nexenta Systems, Inc. All rights reserved.
24  */
25 
26 #include <smbsrv/smb_kproto.h>
27 #include <smbsrv/smb_share.h>
28 
29 static void
30 smb_tcon_puterror(smb_request_t *sr, uint32_t status)
31 {
32 
33 	switch (status) {
34 
35 	case NT_STATUS_BAD_NETWORK_NAME:
36 		/* Intentional status=0 */
37 		smbsr_error(sr, 0, ERRSRV, ERRinvnetname);
38 		break;
39 
40 	case NT_STATUS_ACCESS_DENIED:
41 		smbsr_error(sr, status, ERRSRV, ERRaccess);
42 		break;
43 
44 	case NT_STATUS_BAD_DEVICE_TYPE:
45 		smbsr_error(sr, status, ERRDOS, ERROR_BAD_DEV_TYPE);
46 		break;
47 
48 	default:
49 	case NT_STATUS_INTERNAL_ERROR:
50 		/* Intentional status=0 */
51 		smbsr_error(sr, 0, ERRSRV, ERRsrverror);
52 		break;
53 	}
54 }
55 
56 /*
57  * SmbTreeConnect: Map a share to a tree and obtain a tree-id (TID).
58  *
59  * Client Request                     Description
60  * ================================== =================================
61  *
62  * UCHAR WordCount;                   Count of parameter words = 0
63  * USHORT ByteCount;                  Count of data bytes;    min = 4
64  * UCHAR BufferFormat1;               0x04
65  * STRING Path[];                     Server name and share name
66  * UCHAR BufferFormat2;               0x04
67  * STRING Password[];                 Password
68  * UCHAR BufferFormat3;               0x04
69  * STRING Service[];                  Service name
70  *
71  * The CIFS server responds with:
72  *
73  * Server Response                  Description
74  * ================================ =================================
75  *
76  * UCHAR WordCount;                 Count of parameter words = 2
77  * USHORT MaxBufferSize;            Max size message the server handles
78  * USHORT Tid;                      Tree ID
79  * USHORT ByteCount;                Count of data bytes = 0
80  *
81  * If the negotiated dialect is MICROSOFT NETWORKS 1.03 or earlier,
82  * MaxBufferSize in the response message indicates the maximum size
83  * message that the server can handle.  The client should not generate
84  * messages, nor expect to receive responses, larger than this.  This
85  * must be constant for a given server. For newer dialects, this field
86  * is ignored.
87  */
88 smb_sdrc_t
89 smb_pre_tree_connect(smb_request_t *sr)
90 {
91 	smb_arg_tcon_t	*tcon = &sr->sr_tcon;
92 	int		rc;
93 
94 	/*
95 	 * Perhaps this should be "%A.sA" now that unicode is enabled.
96 	 */
97 	rc = smbsr_decode_data(sr, "%AAA", sr, &tcon->path,
98 	    &tcon->password, &tcon->service);
99 
100 	tcon->flags = 0;
101 	tcon->optional_support = 0;
102 
103 	DTRACE_SMB_2(op__TreeConnect__start, smb_request_t *, sr,
104 	    smb_arg_tcon_t *, tcon);
105 
106 	return ((rc == 0) ? SDRC_SUCCESS : SDRC_ERROR);
107 }
108 
109 void
110 smb_post_tree_connect(smb_request_t *sr)
111 {
112 	DTRACE_SMB_1(op__TreeConnect__done, smb_request_t *, sr);
113 }
114 
115 smb_sdrc_t
116 smb_com_tree_connect(smb_request_t *sr)
117 {
118 	uint32_t status;
119 	int rc;
120 
121 	status = smb_tree_connect(sr);
122 	if (status) {
123 		smb_tcon_puterror(sr, status);
124 		return (SDRC_ERROR);
125 	}
126 
127 	rc = smbsr_encode_result(sr, 2, 0, "bwww",
128 	    2,				/* wct */
129 	    (WORD)smb_maxbufsize,	/* MaxBufferSize */
130 	    sr->smb_tid,		/* TID */
131 	    0);				/* bcc */
132 
133 	return ((rc == 0) ? SDRC_SUCCESS : SDRC_ERROR);
134 }
135 
136 /*
137  * SmbTreeConnectX: Map a share to a tree and obtain a tree-id (TID).
138  *
139  * Client Request                     Description
140  * =================================  =================================
141  *
142  * UCHAR WordCount;                   Count of parameter words = 4
143  * UCHAR AndXCommand;                 Secondary (X) command; 0xFF = none
144  * UCHAR AndXReserved;                Reserved (must be 0)
145  * USHORT AndXOffset;                 Offset to next command WordCount
146  * USHORT Flags;                      Additional information
147  *                                    bit 0 set = disconnect Tid
148  * USHORT PasswordLength;             Length of Password[]
149  * USHORT ByteCount;                  Count of data bytes;    min = 3
150  * UCHAR Password[];                  Password
151  * STRING Path[];                     Server name and share name
152  * STRING Service[];                  Service name
153  *
154  * If the negotiated dialect is LANMAN1.0 or later, then it is a protocol
155  * violation for the client to send this message prior to a successful
156  * SMB_COM_SESSION_SETUP_ANDX, and the server ignores Password.
157  *
158  * If the negotiated dialect is prior to LANMAN1.0 and the client has not
159  * sent a successful SMB_COM_SESSION_SETUP_ANDX request when the tree
160  * connect arrives, a user level security mode server must nevertheless
161  * validate the client's credentials.
162  *
163  * Flags (prefix with TREE_CONNECT_ANDX_):
164  * ==========================  ========================================
165  * 0x0001 DISCONECT_TID        The tree specified by TID in the SMB header
166  *                             should be disconnected - disconnect errors
167  *                             should be ignored.
168  *
169  * 0x0004 EXTENDED_SIGNATURES  Client request for signing key protection.
170  *
171  * 0x0008 EXTENDED_RESPONSE    Client request for extended information.
172  *
173  * Path follows UNC style syntax (\\server\share) and indicates the name
174  * of the resource to which the client wishes to connect.
175  *
176  * Because Password may be an authentication response, it is a variable
177  * length field with the length specified by PasswordLength.   If
178  * authentication is not being used, Password should be a null terminated
179  * ASCII string with PasswordLength set to the string size including the
180  * terminating null.
181  *
182  * The server can enforce whatever policy it desires to govern share
183  * access.  Administrative privilege is required for administrative
184  * shares (C$, etc.).
185  *
186  * The Service component indicates the type of resource the client
187  * intends to access.  Valid values are:
188  *
189  * Service   Description               Earliest Dialect Allowed
190  * ========  ========================  ================================
191  *
192  * A:        disk share                PC NETWORK PROGRAM 1.0
193  * LPT1:     printer                   PC NETWORK PROGRAM 1.0
194  * IPC       named pipe                MICROSOFT NETWORKS 3.0
195  * COMM      communications device     MICROSOFT NETWORKS 3.0
196  * ?????     any type of device        MICROSOFT NETWORKS 3.0
197  *
198  * If the negotiated dialect is earlier than DOS LANMAN2.1, the response to
199  * this SMB is:
200  *
201  * Server Response                  Description
202  * ================================ ===================================
203  *
204  * UCHAR WordCount;                 Count of parameter words = 2
205  * UCHAR AndXCommand;               Secondary (X) command;  0xFF = none
206  * UCHAR AndXReserved;              Reserved (must be 0)
207  * USHORT AndXOffset;               Offset to next command WordCount
208  * USHORT ByteCount;                Count of data bytes;    min = 3
209  *
210  * If the negotiated is DOS LANMAN2.1 or later, the response to this SMB
211  * is:
212  *
213  * Server Response                  Description
214  * ================================ ===================================
215  *
216  * UCHAR WordCount;                 Count of parameter words = 3
217  * UCHAR AndXCommand;               Secondary (X) command;  0xFF = none
218  * UCHAR AndXReserved;              Reserved (must be 0)
219  * USHORT AndXOffset;               Offset to next command WordCount
220  * USHORT OptionalSupport;          Optional support bits
221  * USHORT ByteCount;                Count of data bytes;    min = 3
222  * UCHAR Service[];                 Service type connected to.  Always
223  *                                   ANSII.
224  * STRING NativeFileSystem[];       Native file system for this tree
225  *
226  * NativeFileSystem is the name of the filesystem; values to be expected
227  * include FAT, NTFS, etc.
228  *
229  * OptionalSupport:
230  * ==============================  ==========================
231  * 0x0001 SMB_SUPPORT_SEARCH_BITS  The server supports the use of Search
232  *                                 Attributes in client requests.
233  * 0x0002 SMB_SHARE_IS_IN_DFS      The share is managed by DFS.
234  * 0x000C SMB_CSC_MASK             Offline-caching mask - see CSC flags.
235  * 0x0010 SMB_UNIQUE_FILE_NAME     The server uses long names and does not
236  *                                 support short names.  Indicator for
237  *                                 clients directory/name-space caching.
238  * 0x0020 SMB_EXTENDED_SIGNATURES  The server will use signing key protection.
239  *
240  * Client-side caching (offline files):
241  * ==============================  ==========================
242  * 0x0000 SMB_CSC_CACHE_MANUAL_REINT Clients may cache files for offline use
243  *                                 but automatic file-by-file reintegration
244  *                                 is not allowed.
245  * 0x0004 SMB_CSC_CACHE_AUTO_REINT Automatic file-by-file reintegration is
246  *                                 allowed.
247  * 0x0008 SMB_CSC_CACHE_VDO        File opens do not need to be flowed.
248  * 0x000C SMB_CSC_CACHE_NONE       CSC is disabled for this share.
249  *
250  * Some servers negotiate "DOS LANMAN2.1" dialect or later and still send
251  * the "downlevel" (i.e. wordcount==2) response.  Valid AndX following
252  * commands are
253  *
254  * SMB_COM_OPEN              SMB_COM_OPEN_ANDX          SMB_COM_CREATE
255  * SMB_COM_CREATE_NEW        SMB_COM_CREATE_DIRECTORY   SMB_COM_DELETE
256  * SMB_COM_DELETE_DIRECTORY  SMB_COM_FIND               SMB_COM_COPY
257  * SMB_COM_FIND_UNIQUE       SMB_COM_RENAME
258  * SMB_COM_CHECK_DIRECTORY   SMB_COM_QUERY_INFORMATION
259  * SMB_COM_GET_PRINT_QUEUE   SMB_COM_OPEN_PRINT_FILE
260  * SMB_COM_TRANSACTION       SMB_COM_NO_ANDX_CMD
261  * SMB_COM_SET_INFORMATION   SMB_COM_NT_RENAME
262  *
263  * Errors:
264  * ERRDOS/ERRnomem
265  * ERRDOS/ERRbadpath
266  * ERRDOS/ERRinvdevice
267  * ERRSRV/ERRaccess
268  * ERRSRV/ERRbadpw
269  * ERRSRV/ERRinvnetname
270  */
271 smb_sdrc_t
272 smb_pre_tree_connect_andx(smb_request_t *sr)
273 {
274 	smb_arg_tcon_t	*tcon = &sr->sr_tcon;
275 	uint8_t		*pwbuf = NULL;
276 	uint16_t	pwlen = 0;
277 	int		rc;
278 
279 	rc = smbsr_decode_vwv(sr, "b.www", &sr->andx_com, &sr->andx_off,
280 	    &tcon->flags, &pwlen);
281 	if (rc == 0) {
282 		if (pwlen != 0)
283 			pwbuf = smb_srm_zalloc(sr, pwlen);
284 
285 		rc = smbsr_decode_data(sr, "%#cus", sr, pwlen, pwbuf,
286 		    &tcon->path, &tcon->service);
287 
288 		tcon->pwdlen = pwlen;
289 		tcon->password = (char *)pwbuf;
290 	}
291 
292 	tcon->optional_support = 0;
293 
294 	DTRACE_SMB_2(op__TreeConnectX__start, smb_request_t *, sr,
295 	    smb_arg_tcon_t *, tcon);
296 
297 	return ((rc == 0) ? SDRC_SUCCESS : SDRC_ERROR);
298 }
299 
300 void
301 smb_post_tree_connect_andx(smb_request_t *sr)
302 {
303 	DTRACE_SMB_1(op__TreeConnectX__done, smb_request_t *, sr);
304 }
305 
306 smb_sdrc_t
307 smb_com_tree_connect_andx(smb_request_t *sr)
308 {
309 	smb_arg_tcon_t	*tcon = &sr->sr_tcon;
310 	smb_tree_t	*tree;
311 	char		*service;
312 	uint32_t	status;
313 	int		rc;
314 
315 	if (tcon->flags & SMB_TCONX_DISCONECT_TID) {
316 		tree = smb_session_lookup_tree(sr->session, sr->smb_tid);
317 		if (tree != NULL) {
318 			smb_tree_disconnect(tree, B_TRUE);
319 			smb_session_cancel_requests(sr->session, tree, sr);
320 		}
321 	}
322 
323 	status = smb_tree_connect(sr);
324 	if (status) {
325 		smb_tcon_puterror(sr, status);
326 		return (SDRC_ERROR);
327 	}
328 	tree = sr->tid_tree;
329 
330 	switch (tree->t_res_type & STYPE_MASK) {
331 	case STYPE_IPC:
332 		service = "IPC";
333 		break;
334 	case STYPE_PRINTQ:
335 		service = "LPT1:";
336 		break;
337 	case STYPE_DISKTREE:
338 	default:
339 		service = "A:";
340 	}
341 
342 	if (sr->session->dialect < NT_LM_0_12) {
343 		rc = smbsr_encode_result(sr, 2, VAR_BCC, "bb.ww%ss",
344 		    (char)2,		/* wct */
345 		    sr->andx_com,
346 		    VAR_BCC,
347 		    VAR_BCC,
348 		    sr,
349 		    service,
350 		    tree->t_typename);
351 	} else if ((tcon->flags & SMB_TCONX_EXTENDED_RESPONSE) == 0) {
352 		rc = smbsr_encode_result(sr, 3, VAR_BCC, "bb.www%su",
353 		    (char)3,		/* wct */
354 		    sr->andx_com,
355 		    (short)64,
356 		    tcon->optional_support,
357 		    VAR_BCC,
358 		    sr,
359 		    service,
360 		    tree->t_typename);
361 
362 	} else {
363 		rc = smbsr_encode_result(sr, 7, VAR_BCC, "bb.wwllw%su",
364 		    (char)7,		/* wct (b) */
365 		    sr->andx_com,	/* AndXcmd (b) */
366 		    (short)72,		/* AndXoff (w) */
367 		    tcon->optional_support,	/* (w) */
368 		    tree->t_access,		/* (l) */
369 		    0,		/*    guest_access (l) */
370 		    VAR_BCC,		/* (w) */
371 		    sr,			/* (%) */
372 		    service,		/* (s) */
373 		    tree->t_typename);	/* (u) */
374 	}
375 
376 	return ((rc == 0) ? SDRC_SUCCESS : SDRC_ERROR);
377 }
378 
379 /*
380  * SmbTreeDisconnect: Disconnect a tree.
381  *
382  * Note: SDDF_SUPPRESS_UID is set for this operation, which means the sr
383  * uid_user field will not be valid on entry to these functions.  Do not
384  * use it until it is set up in smb_com_tree_disconnect() or the system
385  * will panic.
386  *
387  * Note: there are scenarios in which the client does not send a tree
388  * disconnect request, for example, when ERRbaduid is returned from
389  * SmbReadX after a user has logged off.  Any open files will remain
390  * around until the session is destroyed.
391  *
392  * Client Request                     Description
393  * ================================== =================================
394  *
395  * UCHAR WordCount;                   Count of parameter words = 0
396  * USHORT ByteCount;                  Count of data bytes = 0
397  *
398  * The resource sharing connection identified by Tid in the SMB header is
399  * logically disconnected from the server. Tid is invalidated; it will not
400  * be recognized if used by the client for subsequent requests. All locks,
401  * open files, etc. created on behalf of Tid are released.
402  *
403  * Server Response                    Description
404  * ================================== =================================
405  *
406  * UCHAR WordCount;                   Count of parameter words = 0
407  * USHORT ByteCount;                  Count of data bytes = 0
408  *
409  * Errors:
410  * ERRSRV/ERRinvnid
411  * ERRSRV/ERRbaduid
412  */
413 smb_sdrc_t
414 smb_pre_tree_disconnect(smb_request_t *sr)
415 {
416 	sr->uid_user = smb_session_lookup_uid(sr->session, sr->smb_uid);
417 	sr->tid_tree = smb_session_lookup_tree(sr->session, sr->smb_tid);
418 
419 	DTRACE_SMB_1(op__TreeDisconnect__start, smb_request_t *, sr);
420 	return (SDRC_SUCCESS);
421 }
422 
423 void
424 smb_post_tree_disconnect(smb_request_t *sr)
425 {
426 	DTRACE_SMB_1(op__TreeDisconnect__done, smb_request_t *, sr);
427 }
428 
429 /*
430  * SmbTreeDisconnect requires a valid UID as well as a valid TID.  Some
431  * clients logoff a user and then try to disconnect the trees connected
432  * by the user who has just been logged off, which would normally fail
433  * in the dispatch code with ERRbaduid but, unfortunately, ERRbaduid
434  * causes a problem for some of those clients.  Windows returns ERRinvnid.
435  *
436  * To prevent ERRbaduid being returned, the UID and TID are looked up here
437  * rather than prior to dispatching SmbTreeDisconnect requests.  If either
438  * the UID or the TID is invalid, ERRinvnid is returned.
439  */
440 smb_sdrc_t
441 smb_com_tree_disconnect(smb_request_t *sr)
442 {
443 	if (sr->uid_user == NULL || sr->tid_tree == NULL) {
444 		smbsr_error(sr, NT_STATUS_INVALID_HANDLE, ERRDOS, ERRinvnid);
445 		return (SDRC_ERROR);
446 	}
447 
448 	sr->user_cr = smb_user_getcred(sr->uid_user);
449 
450 	smb_tree_disconnect(sr->tid_tree, B_TRUE);
451 	smb_session_cancel_requests(sr->session, sr->tid_tree, sr);
452 
453 	if (smbsr_encode_empty_result(sr))
454 		return (SDRC_ERROR);
455 
456 	return (SDRC_SUCCESS);
457 }
458