xref: /illumos-gate/usr/src/uts/common/fs/smbsrv/smb_locking_andx.c (revision afab0816ecb604f0099a09ad8ee398f0d7b77b1c)
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
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
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
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