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