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 2008 Sun Microsystems, Inc. All rights reserved. 23 * Use is subject to license terms. 24 */ 25 26 #pragma ident "%Z%%M% %I% %E% SMI" 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_incl.h> 215 216 int 217 smb_com_locking_andx(struct smb_request *sr) 218 { 219 unsigned short i; 220 unsigned char lock_type; /* See lock_type table above */ 221 unsigned char oplock_level; /* The new oplock level */ 222 uint32_t timeout; /* Milliseconds to wait for lock */ 223 unsigned short unlock_num; /* # unlock range structs */ 224 unsigned short lock_num; /* # lock range structs */ 225 unsigned short pid; /* Process Id of owner */ 226 uint32_t offset32, length32; 227 uint64_t offset64; 228 uint64_t length64; 229 DWORD result; 230 int rc; 231 uint32_t ltype; 232 233 rc = smbsr_decode_vwv(sr, "4.wbblww", &sr->smb_fid, &lock_type, 234 &oplock_level, &timeout, &unlock_num, &lock_num); 235 if (rc != 0) { 236 smbsr_decode_error(sr); 237 /* NOTREACHED */ 238 } 239 240 sr->fid_ofile = smb_ofile_lookup_by_fid(sr->tid_tree, sr->smb_fid); 241 if (sr->fid_ofile == NULL) { 242 smbsr_error(sr, NT_STATUS_INVALID_HANDLE, ERRDOS, ERRbadfid); 243 /* NOTREACHED */ 244 } 245 246 if (lock_type & LOCKING_ANDX_SHARED_LOCK) 247 ltype = SMB_LOCK_TYPE_READONLY; 248 else 249 ltype = SMB_LOCK_TYPE_READWRITE; 250 251 pid = sr->smb_pid; /* Save the original pid */ 252 253 if (lock_type & LOCKING_ANDX_OPLOCK_RELEASE) { 254 smb_release_oplock(sr->fid_ofile, OPLOCK_RELEASE_LOCK_RELEASED); 255 256 /* 257 * According to the protocol: 258 * 259 * If the client sends an SMB_LOCKING_ANDX request with the 260 * LOCKING_ANDX_OPLOCK_RELEASE flag set 261 * and NumberOfLocks is zero, 262 * the server does not send a response. 263 * 264 * I'm not sure if it's going to break anything if I change 265 * it according to the protocol. So, I leave it unchanged 266 * for now. 267 */ 268 if (unlock_num == 0 && lock_num == 0) 269 return (SDRC_NO_REPLY); 270 } 271 272 /* 273 * No support for changing locktype (although we could probably 274 * implement this) 275 */ 276 if (lock_type & LOCKING_ANDX_CHANGE_LOCK_TYPE) { 277 smbsr_error(sr, 0, ERRDOS, ERRnoatomiclocks); 278 /* NOT REACHED */ 279 } 280 281 /* 282 * No support for cancel lock (smbtorture expects this) 283 */ 284 if (lock_type & LOCKING_ANDX_CANCEL_LOCK) { 285 smbsr_error(sr, NT_STATUS_INVALID_PARAMETER, 286 ERRDOS, ERROR_INVALID_PARAMETER); 287 /* NOT REACHED */ 288 } 289 290 if (lock_type & LOCKING_ANDX_LARGE_FILES) { 291 /* 292 * negotiated protocol should be NT LM 0.12 or later 293 */ 294 if (sr->session->dialect < NT_LM_0_12) { 295 smbsr_error(sr, NT_STATUS_INVALID_PARAMETER, 296 ERRDOS, ERROR_INVALID_PARAMETER); 297 /* NOT REACHED */ 298 } 299 300 for (i = 0; i < unlock_num; i++) { 301 rc = smb_decode_mbc(&sr->smb_data, "w2.QQ", 302 &sr->smb_pid, &offset64, &length64); 303 if (rc) { 304 /* 305 * This is the error returned by Windows 2000 306 * even when STATUS32 has been negotiated. 307 */ 308 smbsr_error(sr, 0, ERRSRV, ERRerror); 309 /* NOT REACHED */ 310 } 311 312 result = smb_unlock_range(sr, sr->fid_ofile->f_node, 313 offset64, length64); 314 if (result != NT_STATUS_SUCCESS) { 315 smbsr_error(sr, NT_STATUS_RANGE_NOT_LOCKED, 316 ERRDOS, ERRnotlocked); 317 /* NOT REACHED */ 318 } 319 } 320 321 for (i = 0; i < lock_num; i++) { 322 rc = smb_decode_mbc(&sr->smb_data, "w2.QQ", 323 &sr->smb_pid, &offset64, &length64); 324 if (rc) { 325 smbsr_error(sr, 0, ERRSRV, ERRerror); 326 /* NOT REACHED */ 327 } 328 329 result = smb_lock_range(sr, sr->fid_ofile, 330 offset64, length64, timeout, ltype); 331 if (result != NT_STATUS_SUCCESS) { 332 smb_lock_range_error(sr, result); 333 /* NOT REACHED */ 334 } 335 } 336 } else { 337 for (i = 0; i < unlock_num; i++) { 338 rc = smb_decode_mbc(&sr->smb_data, "wll", &sr->smb_pid, 339 &offset32, &length32); 340 if (rc) { 341 smbsr_error(sr, 0, ERRSRV, ERRerror); 342 /* NOT REACHED */ 343 } 344 345 result = smb_unlock_range(sr, sr->fid_ofile->f_node, 346 (uint64_t)offset32, (uint64_t)length32); 347 if (result != NT_STATUS_SUCCESS) { 348 smbsr_error(sr, NT_STATUS_RANGE_NOT_LOCKED, 349 ERRDOS, ERRnotlocked); 350 /* NOT REACHED */ 351 } 352 } 353 354 for (i = 0; i < lock_num; i++) { 355 rc = smb_decode_mbc(&sr->smb_data, "wll", &sr->smb_pid, 356 &offset32, &length32); 357 if (rc) { 358 smbsr_error(sr, 0, ERRSRV, ERRerror); 359 /* NOT REACHED */ 360 } 361 362 result = smb_lock_range(sr, sr->fid_ofile, 363 (uint64_t)offset32, 364 (uint64_t)length32, 365 timeout, ltype); 366 if (result != NT_STATUS_SUCCESS) { 367 smb_lock_range_error(sr, result); 368 /* NOT REACHED */ 369 } 370 } 371 } 372 373 sr->smb_pid = pid; 374 smbsr_encode_result(sr, 2, 0, "bb.ww", 2, sr->andx_com, 7, 0); 375 376 return (SDRC_NORMAL_REPLY); 377 } 378