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 2013 Nexenta Systems, 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_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
smb_post_tree_connect(smb_request_t * sr)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
smb_com_tree_connect(smb_request_t * sr)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
smb_pre_tree_connect_andx(smb_request_t * sr)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
smb_post_tree_connect_andx(smb_request_t * sr)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
smb_com_tree_connect_andx(smb_request_t * sr)307 smb_com_tree_connect_andx(smb_request_t *sr)
308 {
309 smb_arg_tcon_t *tcon = &sr->sr_tcon;
310 char *service;
311 uint32_t status;
312 int rc;
313
314 status = smb_tree_connect(sr);
315 if (status) {
316 smb_tcon_puterror(sr, status);
317 return (SDRC_ERROR);
318 }
319
320 switch (sr->tid_tree->t_res_type & STYPE_MASK) {
321 case STYPE_IPC:
322 service = "IPC";
323 break;
324 case STYPE_PRINTQ:
325 service = "LPT1:";
326 break;
327 case STYPE_DISKTREE:
328 default:
329 service = "A:";
330 }
331
332 if (sr->session->dialect < NT_LM_0_12) {
333 rc = smbsr_encode_result(sr, 2, VAR_BCC, "bb.wwss",
334 (char)2, /* wct */
335 sr->andx_com,
336 VAR_BCC,
337 VAR_BCC,
338 service,
339 sr->tid_tree->t_typename);
340 } else {
341 rc = smbsr_encode_result(sr, 3, VAR_BCC, "bb.wwws%u",
342 (char)3, /* wct */
343 sr->andx_com,
344 (short)64,
345 tcon->optional_support,
346 VAR_BCC,
347 service,
348 sr,
349 sr->tid_tree->t_typename);
350 }
351
352 return ((rc == 0) ? SDRC_SUCCESS : SDRC_ERROR);
353 }
354
355 /*
356 * SmbTreeDisconnect: Disconnect a tree.
357 *
358 * Note: SDDF_SUPPRESS_UID is set for this operation, which means the sr
359 * uid_user field will not be valid on entry to these functions. Do not
360 * use it until it is set up in smb_com_tree_disconnect() or the system
361 * will panic.
362 *
363 * Note: there are scenarios in which the client does not send a tree
364 * disconnect request, for example, when ERRbaduid is returned from
365 * SmbReadX after a user has logged off. Any open files will remain
366 * around until the session is destroyed.
367 *
368 * Client Request Description
369 * ================================== =================================
370 *
371 * UCHAR WordCount; Count of parameter words = 0
372 * USHORT ByteCount; Count of data bytes = 0
373 *
374 * The resource sharing connection identified by Tid in the SMB header is
375 * logically disconnected from the server. Tid is invalidated; it will not
376 * be recognized if used by the client for subsequent requests. All locks,
377 * open files, etc. created on behalf of Tid are released.
378 *
379 * Server Response Description
380 * ================================== =================================
381 *
382 * UCHAR WordCount; Count of parameter words = 0
383 * USHORT ByteCount; Count of data bytes = 0
384 *
385 * Errors:
386 * ERRSRV/ERRinvnid
387 * ERRSRV/ERRbaduid
388 */
389 smb_sdrc_t
smb_pre_tree_disconnect(smb_request_t * sr)390 smb_pre_tree_disconnect(smb_request_t *sr)
391 {
392 sr->uid_user = smb_session_lookup_uid(sr->session, sr->smb_uid);
393 sr->tid_tree = smb_session_lookup_tree(sr->session, sr->smb_tid);
394
395 DTRACE_SMB_1(op__TreeDisconnect__start, smb_request_t *, sr);
396 return (SDRC_SUCCESS);
397 }
398
399 void
smb_post_tree_disconnect(smb_request_t * sr)400 smb_post_tree_disconnect(smb_request_t *sr)
401 {
402 DTRACE_SMB_1(op__TreeDisconnect__done, smb_request_t *, sr);
403 }
404
405 /*
406 * SmbTreeDisconnect requires a valid UID as well as a valid TID. Some
407 * clients logoff a user and then try to disconnect the trees connected
408 * by the user who has just been logged off, which would normally fail
409 * in the dispatch code with ERRbaduid but, unfortunately, ERRbaduid
410 * causes a problem for some of those clients. Windows returns ERRinvnid.
411 *
412 * To prevent ERRbaduid being returned, the UID and TID are looked up here
413 * rather than prior to dispatching SmbTreeDisconnect requests. If either
414 * the UID or the TID is invalid, ERRinvnid is returned.
415 */
416 smb_sdrc_t
smb_com_tree_disconnect(smb_request_t * sr)417 smb_com_tree_disconnect(smb_request_t *sr)
418 {
419 if (sr->uid_user == NULL || sr->tid_tree == NULL) {
420 smbsr_error(sr, NT_STATUS_INVALID_HANDLE, ERRDOS, ERRinvnid);
421 return (SDRC_ERROR);
422 }
423
424 sr->user_cr = smb_user_getcred(sr->uid_user);
425
426 smb_session_cancel_requests(sr->session, sr->tid_tree, sr);
427 smb_tree_disconnect(sr->tid_tree, B_TRUE);
428
429 if (smbsr_encode_empty_result(sr))
430 return (SDRC_ERROR);
431
432 return (SDRC_SUCCESS);
433 }
434