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