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 /*
23 * Copyright (c) 2007, 2010, Oracle and/or its affiliates. All rights reserved.
24 * Copyright 2020 Tintri by DDN, Inc. All rights reserved.
25 * Copyright 2022 RackTop Systems, Inc.
26 */
27
28 /*
29 * SMB: locking_andx
30 *
31 * SMB_COM_LOCKING_ANDX allows both locking and/or unlocking of file range(s).
32 *
33 * Client Request Description
34 * ================================== =================================
35 *
36 * UCHAR WordCount; Count of parameter words = 8
37 * UCHAR AndXCommand; Secondary (X) command; 0xFF = none
38 * UCHAR AndXReserved; Reserved (must be 0)
39 * USHORT AndXOffset; Offset to next command WordCount
40 * USHORT Fid; File handle
41 * UCHAR LockType; See LockType table below
42 * UCHAR OplockLevel; The new oplock level
43 * ULONG Timeout; Milliseconds to wait for unlock
44 * USHORT NumberOfUnlocks; Num. unlock range structs following
45 * USHORT NumberOfLocks; Num. lock range structs following
46 * USHORT ByteCount; Count of data bytes
47 * LOCKING_ANDX_RANGE Unlocks[]; Unlock ranges
48 * LOCKING_ANDX_RANGE Locks[]; Lock ranges
49 *
50 * LockType Flag Name Value Description
51 * ============================ ===== ================================
52 *
53 * LOCKING_ANDX_SHARED_LOCK 0x01 Read-only lock
54 * LOCKING_ANDX_OPLOCK_RELEASE 0x02 Oplock break notification
55 * LOCKING_ANDX_CHANGE_LOCKTYPE 0x04 Change lock type
56 * LOCKING_ANDX_CANCEL_LOCK 0x08 Cancel outstanding request
57 * LOCKING_ANDX_LARGE_FILES 0x10 Large file locking format
58 *
59 * LOCKING_ANDX_RANGE Format
60 * =====================================================================
61 *
62 * USHORT Pid; PID of process "owning" lock
63 * ULONG Offset; Offset to bytes to [un]lock
64 * ULONG Length; Number of bytes to [un]lock
65 *
66 * Large File LOCKING_ANDX_RANGE Format
67 * =====================================================================
68 *
69 * USHORT Pid; PID of process "owning" lock
70 * USHORT Pad; Pad to DWORD align (mbz)
71 * ULONG OffsetHigh; Offset to bytes to [un]lock
72 * (high)
73 * ULONG OffsetLow; Offset to bytes to [un]lock (low)
74 * ULONG LengthHigh; Number of bytes to [un]lock
75 * (high)
76 * ULONG LengthLow; Number of bytes to [un]lock (low)
77 *
78 * Server Response Description
79 * ================================== =================================
80 *
81 * UCHAR WordCount; Count of parameter words = 2
82 * UCHAR AndXCommand; Secondary (X) command; 0xFF =
83 * none
84 * UCHAR AndXReserved; Reserved (must be 0)
85 * USHORT AndXOffset; Offset to next command WordCount
86 * USHORT ByteCount; Count of data bytes = 0
87 *
88 * Locking is a simple mechanism for excluding other processes read/write
89 * access to regions of a file. The locked regions can be anywhere in the
90 * logical file. Locking beyond end-of-file is permitted. Any process
91 * using the Fid specified in this request's Fid has access to the locked
92 * bytes, other processes will be denied the locking of the same bytes.
93 *
94 * The proper method for using locks is not to rely on being denied read or
95 * write access on any of the read/write protocols but rather to attempt
96 * the locking protocol and proceed with the read/write only if the locks
97 * succeeded.
98 *
99 * Locking a range of bytes will fail if any subranges or overlapping
100 * ranges are locked. In other words, if any of the specified bytes are
101 * already locked, the lock will fail.
102 *
103 * If NumberOfUnlocks is non-zero, the Unlocks vector contains
104 * NumberOfUnlocks elements. Each element requests that a lock at Offset
105 * of Length be released. If NumberOfLocks is nonzero, the Locks vector
106 * contains NumberOfLocks elements. Each element requests the acquisition
107 * of a lock at Offset of Length.
108 *
109 * Timeout is the maximum amount of time to wait for the byte range(s)
110 * specified to become unlocked. A timeout value of 0 indicates that the
111 * server should fail immediately if any lock range specified is locked. A
112 *
113 * timeout value of -1 indicates that the server should wait as long as it
114 * takes for each byte range specified to become unlocked so that it may be
115 * again locked by this protocol. Any other value of smb_timeout specifies
116 * the maximum number of milliseconds to wait for all lock range(s)
117 * specified to become available.
118 *
119 * If any of the lock ranges timeout because of the area to be locked is
120 * already locked (or the lock fails), the other ranges in the protocol
121 * request which were successfully locked as a result of this protocol will
122 * be unlocked (either all requested ranges will be locked when this
123 * protocol returns to the client or none).
124 *
125 * If LockType has the LOCKING_ANDX_SHARED_LOCK flag set, the lock is
126 * specified as a shared lock. Locks for both read and write (where
127 * LOCKING_ANDX_SHARED_LOCK is clear) should be prohibited, but other
128 * shared locks should be permitted. If shared locks can not be supported
129 * by a server, the server should map the lock to a lock for both read and
130 * write. Closing a file with locks still in force causes the locks to be
131 * released in no defined order.
132 *
133 * If LockType has the LOCKING_ANDX_LARGE_FILES flag set and if the
134 * negotiated protocol is NT LM 0.12 or later, then the Locks and Unlocks
135 * vectors are in the Large File LOCKING_ANDX_RANGE format. This allows
136 * specification of 64 bit offsets for very large files.
137 *
138 * If the one and only member of the Locks vector has the
139 * LOCKING_ANDX_CANCEL_LOCK flag set in the LockType field, the client is
140 * requesting the server to cancel a previously requested, but not yet
141 * responded to, lock.
142 *
143 * If LockType has the LOCKING_ANDX_CHANGE_LOCKTYPE flag set, the client is
144 * requesting that the server atomically change the lock type from a shared
145 * lock to an exclusive lock or vice versa. If the server can not do this
146 * in an atomic fashion, the server must reject this request. NT and W95
147 * servers do not support this capability.
148 *
149 * Oplocks are described in the "Opportunistic Locks" section elsewhere in
150 * this document. A client requests an oplock by setting the appropriate
151 * bit in the SMB_COM_OPEN_ANDX request when the file is being opened in a
152 * mode which is not exclusive. The server responds by setting the
153 * appropriate bit in the response SMB indicating whether or not the oplock
154 * was granted. By granting the oplock, the server tells the client the
155 * file is currently only being used by this one client process at the
156 * current time. The client can therefore safely do read ahead and write
157 * behind as well as local caching of file locks knowing that the file will
158 * not be accessed/changed in any way by another process while the oplock
159 * is in effect. The client will be notified when any other process
160 * attempts to open or modify the oplocked file.
161 *
162 * When another user attempts to open or otherwise modify the file which a
163 * client has oplocked, the server delays the second attempt and notifies
164 * the client via an SMB_LOCKING_ANDX SMB asynchronously sent from the
165 * server to the client. This message has the LOCKING_ANDX_OPLOCK_RELEASE
166 * flag set indicating to the client that the oplock is being broken.
167 *
168 * OplockLevel indicates the type of oplock the client now owns. If
169 * OplockLevel is 0, the client possesses no oplocks on the file at all, if
170 * OplockLevel is 1 the client possesses a Level II oplock. The client is
171 * expected to flush any dirty buffers to the server, submit any file locks
172 * and respond to the server with either an SMB_LOCKING_ANDX SMB having the
173 * LOCKING_ANDX_OPLOCK_RELEASE flag set, or with a file close if the file
174 * is no longer in use by the client. If the client sends an
175 * SMB_LOCKING_ANDX SMB with the LOCKING_ANDX_OPLOCK_RELEASE flag set and
176 * NumberOfLocks is zero, the server does not send a response. Since a
177 * close being sent to the server and break oplock notification from the
178 * server could cross on the wire, if the client gets an oplock
179 * notification on a file which it does not have open, that notification
180 * should be ignored.
181 *
182 * Due to timing, the client could get an "oplock broken" notification in a
183 * user's data buffer as a result of this notification crossing on the wire
184 * with a SMB_COM_READ_RAW request. The client must detect this (use
185 * length of msg, "FFSMB", MID of -1 and Command of SMB_COM_LOCKING_ANDX)
186 * and honor the "oplock broken" notification as usual. The server must
187 * also note on receipt of an SMB_COM_READ_RAW request that there is an
188 * outstanding (unanswered) "oplock broken" notification to the client and
189 * return a zero length response denoting failure of the read raw request.
190 * The client should (after responding to the "oplock broken"
191 * notification), use a standard read protocol to redo the read request.
192 * This allows a file to actually contain data matching an "oplock broken"
193 * notification and still be read correctly.
194 *
195 * The entire message sent and received including the optional second
196 * protocol must fit in the negotiated maximum transfer size. The
197 * following are the only valid SMB commands for AndXCommand for
198 * SMB_COM_LOCKING_ANDX:
199 *
200 * SMB_COM_READ SMB_COM_READ_ANDX
201 * SMB_COM_WRITE SMB_COM_WRITE_ANDX
202 * SMB_COM_FLUSH
203 *
204 * 4.2.6.1 Errors
205 *
206 * ERRDOS/ERRbadfile
207 * ERRDOS/ERRbadfid
208 * ERRDOS/ERRlock
209 * ERRDOS/ERRinvdevice
210 * ERRSRV/ERRinvid
211 * ERRSRV/ERRbaduid
212 */
213
214 #include <smbsrv/smb_kproto.h>
215
216 /*
217 * This is a somewhat arbitrary sanity limit on the length of the
218 * SMB2_LOCK_ELEMENT array. It usually has length one or two.
219 */
220 int smb_lock_max_elem = 1024;
221
222 smb_sdrc_t
smb_pre_locking_andx(smb_request_t * sr)223 smb_pre_locking_andx(smb_request_t *sr)
224 {
225 DTRACE_SMB_START(op__LockingX, smb_request_t *, sr);
226 return (SDRC_SUCCESS);
227 }
228
229 void
smb_post_locking_andx(smb_request_t * sr)230 smb_post_locking_andx(smb_request_t *sr)
231 {
232 DTRACE_SMB_DONE(op__LockingX, smb_request_t *, sr);
233 }
234
235 struct lreq {
236 uint64_t off;
237 uint64_t len;
238 uint32_t pid;
239 uint32_t reserved;
240 };
241
242 smb_sdrc_t
smb_com_locking_andx(smb_request_t * sr)243 smb_com_locking_andx(smb_request_t *sr)
244 {
245 unsigned short i;
246 unsigned char lock_type; /* See lock_type table above */
247 unsigned char oplock_level; /* The new oplock level */
248 uint32_t timeout; /* Milliseconds to wait for lock */
249 unsigned short unlock_num; /* # unlock range structs */
250 unsigned short lock_num; /* # lock range structs */
251 DWORD result;
252 int rc;
253 uint32_t ltype;
254 smb_ofile_t *ofile;
255 uint16_t tmp_pid; /* locking uses 16-bit pids */
256 uint32_t lrv_tot;
257 struct lreq *lrv_ul;
258 struct lreq *lrv_lk;
259 struct lreq *lr;
260
261 rc = smbsr_decode_vwv(sr, "4.wbblww", &sr->smb_fid, &lock_type,
262 &oplock_level, &timeout, &unlock_num, &lock_num);
263 if (rc != 0)
264 return (SDRC_ERROR);
265
266 smbsr_lookup_file(sr);
267 if (sr->fid_ofile == NULL) {
268 smbsr_error(sr, NT_STATUS_INVALID_HANDLE, ERRDOS, ERRbadfid);
269 return (SDRC_ERROR);
270 }
271 ofile = sr->fid_ofile;
272 if (ofile->f_node == NULL) {
273 smbsr_error(sr, NT_STATUS_INVALID_PARAMETER,
274 ERRDOS, ERROR_INVALID_PARAMETER);
275 return (SDRC_ERROR);
276 }
277
278 if (unlock_num > smb_lock_max_elem ||
279 lock_num > smb_lock_max_elem) {
280 smbsr_error(sr, NT_STATUS_INSUFFICIENT_RESOURCES,
281 ERRDOS, ERROR_NO_SYSTEM_RESOURCES);
282 return (SDRC_ERROR);
283 }
284
285 if (lock_type & LOCKING_ANDX_SHARED_LOCK)
286 ltype = SMB_LOCK_TYPE_READONLY;
287 else
288 ltype = SMB_LOCK_TYPE_READWRITE;
289
290 if (lock_type & LOCKING_ANDX_OPLOCK_RELEASE) {
291 smb1_oplock_ack_break(sr, oplock_level);
292 if (unlock_num == 0 && lock_num == 0)
293 return (SDRC_NO_REPLY);
294 /*
295 * Don't allow combining other lock/unlock actions
296 * with an oplock ACK (normally don't get here).
297 */
298 smbsr_error(sr, NT_STATUS_INVALID_PARAMETER,
299 ERRDOS, ERROR_INVALID_PARAMETER);
300 return (SDRC_ERROR);
301 }
302
303 /*
304 * No support for changing locktype (although we could probably
305 * implement this)
306 */
307 if (lock_type & LOCKING_ANDX_CHANGE_LOCK_TYPE) {
308 smbsr_error(sr, 0, ERRDOS,
309 ERROR_ATOMIC_LOCKS_NOT_SUPPORTED);
310 return (SDRC_ERROR);
311 }
312
313 if (lock_type & LOCKING_ANDX_LARGE_FILES) {
314 /*
315 * negotiated protocol should be NT LM 0.12 or later
316 */
317 if (sr->session->dialect < NT_LM_0_12) {
318 smbsr_error(sr, NT_STATUS_INVALID_PARAMETER,
319 ERRDOS, ERROR_INVALID_PARAMETER);
320 return (SDRC_ERROR);
321 }
322 }
323
324 /*
325 * Parse the unlock, lock vectors. Will parse all the
326 * unlock + lock records into one array, and then use
327 * pointers to the unlock and lock parts.
328 */
329 lrv_tot = unlock_num + lock_num;
330 lrv_ul = smb_srm_zalloc(sr, lrv_tot * sizeof (*lrv_ul));
331 lrv_lk = &lrv_ul[unlock_num];
332
333 for (i = 0; i < lrv_tot; i++) {
334 lr = &lrv_ul[i];
335 if (lock_type & LOCKING_ANDX_LARGE_FILES) {
336 rc = smb_mbc_decodef(&sr->smb_data, "w2.QQ",
337 &tmp_pid, &lr->off, &lr->len);
338 } else {
339 uint32_t offset32, length32;
340 rc = smb_mbc_decodef(&sr->smb_data, "wll",
341 &tmp_pid, &offset32, &length32);
342 lr->off = offset32;
343 lr->len = length32;
344 }
345 lr->pid = tmp_pid; /* 16-bit PID */
346 if (rc) {
347 /*
348 * This is the error returned by Windows 2000
349 * even when STATUS32 has been negotiated.
350 */
351 smbsr_error(sr, 0, ERRSRV, ERRerror);
352 return (SDRC_ERROR);
353 }
354 }
355
356 /*
357 * Cancel waiting locks. MS-CIFS says one place that
358 * this cancels all waiting locks for this FID+PID,
359 * but smbtorture insists this cancels just one.
360 * Tests with Windows 7 confirms that.
361 */
362 if ((lock_type & LOCKING_ANDX_CANCEL_LOCK) != 0) {
363 lr = lrv_lk;
364
365 result = smb_lock_range_cancel(sr, lr->off, lr->len, lr->pid);
366
367 if (result != NT_STATUS_SUCCESS) {
368 smbsr_error(sr, 0, ERRDOS,
369 ERROR_CANCEL_VIOLATION);
370 return (SDRC_ERROR);
371 }
372 goto out;
373 }
374
375 /*
376 * Normal unlock and lock list
377 */
378 for (i = 0; i < unlock_num; i++) {
379 lr = &lrv_ul[i];
380
381 result = smb_unlock_range(sr, lr->off, lr->len, lr->pid);
382 if (result != NT_STATUS_SUCCESS) {
383 smbsr_error(sr, NT_STATUS_RANGE_NOT_LOCKED,
384 ERRDOS, ERROR_NOT_LOCKED);
385 return (SDRC_ERROR);
386 }
387 }
388 for (i = 0; i < lock_num; i++) {
389 lr = &lrv_lk[i];
390
391 result = smb_lock_range(sr, lr->off, lr->len, lr->pid,
392 ltype, timeout);
393 if (result != NT_STATUS_SUCCESS) {
394 /*
395 * Oh... we have to rollback.
396 */
397 while (i > 0) {
398 --i;
399 lr = &lrv_lk[i];
400 (void) smb_unlock_range(sr,
401 lr->off, lr->len, lr->pid);
402 }
403 smb_lock_range_error(sr, result);
404 return (SDRC_ERROR);
405 }
406 }
407
408 out:
409 if (smbsr_encode_result(sr, 2, 0, "bb.ww",
410 2, sr->andx_com, 0x27, 0) != 0)
411 return (SDRC_ERROR);
412 return (SDRC_SUCCESS);
413 }
414