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