Home | History | Annotate | Download | only in smbsrv
      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_kproto.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