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