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  * Copyright 2017 Nexenta Systems, Inc.  All rights reserved.
  25  */
  26 
  27 /*
  28  * SMB: locking_andx
  29  *
  30  * SMB_COM_LOCKING_ANDX allows both locking and/or unlocking of file range(s).
  31  *
  32  *  Client Request                     Description
  33  *  ================================== =================================
  34  *
  35  *  UCHAR WordCount;                   Count of parameter words = 8
  36  *  UCHAR AndXCommand;                 Secondary (X) command;  0xFF = none
  37  *  UCHAR AndXReserved;                Reserved (must be 0)
  38  *  USHORT AndXOffset;                 Offset to next command WordCount
  39  *  USHORT Fid;                        File handle
  40  *  UCHAR LockType;                    See LockType table below
  41  *  UCHAR OplockLevel;                 The new oplock level
  42  *  ULONG Timeout;                     Milliseconds to wait for unlock
  43  *  USHORT NumberOfUnlocks;            Num. unlock range structs following
  44  *  USHORT NumberOfLocks;              Num. lock range structs following
  45  *  USHORT ByteCount;                  Count of data bytes
  46  *  LOCKING_ANDX_RANGE Unlocks[];      Unlock ranges
  47  *  LOCKING_ANDX_RANGE Locks[];        Lock ranges
  48  *
  49  *  LockType Flag Name            Value Description
  50  *  ============================  ===== ================================
  51  *
  52  *  LOCKING_ANDX_SHARED_LOCK      0x01  Read-only lock
  53  *  LOCKING_ANDX_OPLOCK_RELEASE   0x02  Oplock break notification
  54  *  LOCKING_ANDX_CHANGE_LOCKTYPE  0x04  Change lock type
  55  *  LOCKING_ANDX_CANCEL_LOCK      0x08  Cancel outstanding request
  56  *  LOCKING_ANDX_LARGE_FILES      0x10  Large file locking format
  57  *
  58  *  LOCKING_ANDX_RANGE Format
  59  *  =====================================================================
  60  *
  61  *  USHORT Pid;                        PID of process "owning" lock
  62  *  ULONG Offset;                      Offset to bytes to [un]lock
  63  *  ULONG Length;                      Number of bytes to [un]lock
  64  *
  65  *  Large File LOCKING_ANDX_RANGE Format
  66  *  =====================================================================
  67  *
  68  *  USHORT Pid;                        PID of process "owning" lock
  69  *  USHORT Pad;                        Pad to DWORD align (mbz)
  70  *  ULONG OffsetHigh;                  Offset to bytes to [un]lock
  71  *                                      (high)
  72  *  ULONG OffsetLow;                   Offset to bytes to [un]lock (low)
  73  *  ULONG LengthHigh;                  Number of bytes to [un]lock
  74  *                                      (high)
  75  *  ULONG LengthLow;                   Number of bytes to [un]lock (low)
  76  *
  77  *  Server Response                    Description
  78  *  ================================== =================================
  79  *
  80  *  UCHAR WordCount;                   Count of parameter words = 2
  81  *  UCHAR AndXCommand;                 Secondary (X) command;  0xFF =
  82  *                                      none
  83  *  UCHAR AndXReserved;                Reserved (must be 0)
  84  *  USHORT AndXOffset;                 Offset to next command WordCount
  85  *  USHORT ByteCount;                  Count of data bytes = 0
  86  *
  87  * Locking is a simple mechanism for excluding other processes read/write
  88  * access to regions of a file.  The locked regions can be anywhere in the
  89  * logical file.  Locking beyond end-of-file is permitted.  Any process
  90  * using the Fid specified in this request's Fid has access to the locked
  91  * bytes, other processes will be denied the locking of the same bytes.
  92  *
  93  * The proper method for using locks is not to rely on being denied read or
  94  * write access on any of the read/write protocols but rather to attempt
  95  * the locking protocol and proceed with the read/write only if the locks
  96  * succeeded.
  97  *
  98  * Locking a range of bytes will fail if any subranges or overlapping
  99  * ranges are locked.  In other words, if any of the specified bytes are
 100  * already locked, the lock will fail.
 101  *
 102  * If NumberOfUnlocks is non-zero, the Unlocks vector contains
 103  * NumberOfUnlocks elements.  Each element requests that a lock at Offset
 104  * of Length be released.  If NumberOfLocks is nonzero, the Locks vector
 105  * contains NumberOfLocks elements.  Each element requests the acquisition
 106  * of a lock at Offset of Length.
 107  *
 108  * Timeout is the maximum amount of time to wait for the byte range(s)
 109  * specified to become unlocked.  A timeout value of 0 indicates that the
 110  * server should fail immediately if any lock range specified is locked.  A
 111  *
 112  * timeout value of -1 indicates that the server should wait as long as it
 113  * takes for each byte range specified to become unlocked so that it may be
 114  * again locked by this protocol.  Any other value of smb_timeout specifies
 115  * the maximum number of milliseconds to wait for all lock range(s)
 116  * specified to become available.
 117  *
 118  * If any of the lock ranges timeout because of the area to be locked is
 119  * already locked (or the lock fails), the other ranges in the protocol
 120  * request which were successfully locked as a result of this protocol will
 121  * be unlocked (either all requested ranges will be locked when this
 122  * protocol returns to the client or none).
 123  *
 124  * If LockType has the LOCKING_ANDX_SHARED_LOCK flag set, the lock is
 125  * specified as a shared lock.  Locks for both read and write (where
 126  * LOCKING_ANDX_SHARED_LOCK is clear) should be prohibited, but other
 127  * shared locks should be permitted.  If shared locks can not be supported
 128  * by a server, the server should map the lock to a lock for both read and
 129  * write.  Closing a file with locks still in force causes the locks to be
 130  * released in no defined order.
 131  *
 132  * If LockType has the LOCKING_ANDX_LARGE_FILES flag set and if the
 133  * negotiated protocol is NT LM 0.12 or later, then the Locks and Unlocks
 134  * vectors are in the Large File LOCKING_ANDX_RANGE format.  This allows
 135  * specification of 64 bit offsets for very large files.
 136  *
 137  * If the one and only member of the Locks vector has the
 138  * LOCKING_ANDX_CANCEL_LOCK flag set in the LockType field, the client is
 139  * requesting the server to cancel a previously requested, but not yet
 140  * responded to, lock.
 141  *
 142  * If LockType has the LOCKING_ANDX_CHANGE_LOCKTYPE flag set, the client is
 143  * requesting that the server atomically change the lock type from a shared
 144  * lock to an exclusive lock or vice versa.  If the server can not do this
 145  * in an atomic fashion, the server must reject this request.  NT and W95
 146  * servers do not support this capability.
 147  *
 148  * Oplocks are described in the "Opportunistic Locks" section elsewhere in
 149  * this document.  A client requests an oplock by setting the appropriate
 150  * bit in the SMB_COM_OPEN_ANDX request when the file is being opened in a
 151  * mode which is not exclusive.  The server responds by setting the
 152  * appropriate bit in the response SMB indicating whether or not the oplock
 153  * was granted.  By granting the oplock, the server tells the client the
 154  * file is currently only being used by this one client process at the
 155  * current time.  The client can therefore safely do read ahead and write
 156  * behind as well as local caching of file locks knowing that the file will
 157  * not be accessed/changed in any way by another process while the oplock
 158  * is in effect.  The client will be notified when any other process
 159  * attempts to open or modify the oplocked file.
 160  *
 161  * When another user attempts to open or otherwise modify the file which a
 162  * client has oplocked, the server delays the second attempt and notifies
 163  * the client via an SMB_LOCKING_ANDX SMB asynchronously sent from the
 164  * server to the client.  This message has the LOCKING_ANDX_OPLOCK_RELEASE
 165  * flag set indicating to the client that the oplock is being broken.
 166  *
 167  * OplockLevel indicates the type of oplock the client now owns. If
 168  * OplockLevel is 0, the client possesses no oplocks on the file at all, if
 169  * OplockLevel is 1 the client possesses a Level II oplock.  The client is
 170  * expected to flush any dirty buffers to the server, submit any file locks
 171  * and respond to the server with either an SMB_LOCKING_ANDX SMB having the
 172  * LOCKING_ANDX_OPLOCK_RELEASE flag set, or with a file close if the file
 173  * is no longer in use by the client.  If the client sends an
 174  * SMB_LOCKING_ANDX SMB with the LOCKING_ANDX_OPLOCK_RELEASE flag set and
 175  * NumberOfLocks is zero, the server does not send a response.  Since a
 176  * close being sent to the server and break oplock notification from the
 177  * server could cross on the wire, if the client gets an oplock
 178  * notification on a file which it does not have open, that notification
 179  * should be ignored.
 180  *
 181  * Due to timing, the client could get an "oplock broken" notification in a
 182  * user's data buffer as a result of this notification crossing on the wire
 183  * with a SMB_COM_READ_RAW request.  The client must detect this (use
 184  * length of msg, "FFSMB", MID of -1 and Command of SMB_COM_LOCKING_ANDX)
 185  * and honor the "oplock broken" notification as usual.  The server must
 186  * also note on receipt of an SMB_COM_READ_RAW request that there is an
 187  * outstanding (unanswered) "oplock broken" notification to the client and
 188  * return a zero length response denoting failure of the read raw request.
 189  * The client should (after responding to the "oplock broken"
 190  * notification), use a standard read protocol to redo the read request.
 191  * This allows a file to actually contain data matching an "oplock broken"
 192  * notification and still be read correctly.
 193  *
 194  * The entire message sent and received including the optional second
 195  * protocol must fit in the negotiated maximum transfer size.  The
 196  * following are the only valid SMB commands for AndXCommand for
 197  * SMB_COM_LOCKING_ANDX:
 198  *
 199  *     SMB_COM_READ       SMB_COM_READ_ANDX
 200  *     SMB_COM_WRITE      SMB_COM_WRITE_ANDX
 201  *     SMB_COM_FLUSH
 202  *
 203  * 4.2.6.1   Errors
 204  *
 205  * ERRDOS/ERRbadfile
 206  * ERRDOS/ERRbadfid
 207  * ERRDOS/ERRlock
 208  * ERRDOS/ERRinvdevice
 209  * ERRSRV/ERRinvid
 210  * ERRSRV/ERRbaduid
 211  */
 212 
 213 #include <smbsrv/smb_kproto.h>
 214 
 215 /*
 216  * This is a somewhat arbitrary sanity limit on the length of the
 217  * SMB2_LOCK_ELEMENT array.  It usually has length one or two.
 218  */
 219 int smb_lock_max_elem = 1024;
 220 
 221 smb_sdrc_t
 222 smb_pre_locking_andx(smb_request_t *sr)
 223 {
 224         DTRACE_SMB_START(op__LockingX, smb_request_t *, sr);
 225         return (SDRC_SUCCESS);
 226 }
 227 
 228 void
 229 smb_post_locking_andx(smb_request_t *sr)
 230 {
 231         DTRACE_SMB_DONE(op__LockingX, smb_request_t *, sr);
 232 }
 233 
 234 struct lreq {
 235         uint64_t off;
 236         uint64_t len;
 237         uint32_t pid;
 238         uint32_t _x;
 239 };
 240 
 241 smb_sdrc_t
 242 smb_com_locking_andx(smb_request_t *sr)
 243 {
 244         unsigned short  i;
 245         unsigned char   lock_type;      /* See lock_type table above */
 246         unsigned char   oplock_level;   /* The new oplock level */
 247         uint32_t        timeout;        /* Milliseconds to wait for lock */
 248         unsigned short  unlock_num;     /* # unlock range structs */
 249         unsigned short  lock_num;       /* # lock range structs */
 250         DWORD           result;
 251         int             rc;
 252         uint32_t        ltype;
 253         uint32_t        status;
 254         smb_ofile_t     *ofile;
 255         uint16_t        tmp_pid;        /* locking uses 16-bit pids */
 256         uint32_t        lrv_tot;
 257         struct lreq     *lrv_ul;
 258         struct lreq     *lrv_lk;
 259         struct lreq     *lr;
 260 
 261         rc = smbsr_decode_vwv(sr, "4.wbblww", &sr->smb_fid, &lock_type,
 262             &oplock_level, &timeout, &unlock_num, &lock_num);
 263         if (rc != 0)
 264                 return (SDRC_ERROR);
 265 
 266         smbsr_lookup_file(sr);
 267         if (sr->fid_ofile == NULL) {
 268                 smbsr_error(sr, NT_STATUS_INVALID_HANDLE, ERRDOS, ERRbadfid);
 269                 return (SDRC_ERROR);
 270         }
 271         ofile = sr->fid_ofile;
 272         if (ofile->f_node == NULL) {
 273                 smbsr_error(sr, NT_STATUS_INVALID_PARAMETER,
 274                     ERRDOS, ERROR_INVALID_PARAMETER);
 275                 return (SDRC_ERROR);
 276         }
 277 
 278         if (unlock_num > smb_lock_max_elem ||
 279             lock_num > smb_lock_max_elem) {
 280                 smbsr_error(sr, NT_STATUS_INSUFFICIENT_RESOURCES,
 281                     ERRDOS, ERROR_NO_SYSTEM_RESOURCES);
 282                 return (SDRC_ERROR);
 283         }
 284 
 285         if (lock_type & LOCKING_ANDX_SHARED_LOCK)
 286                 ltype = SMB_LOCK_TYPE_READONLY;
 287         else
 288                 ltype = SMB_LOCK_TYPE_READWRITE;
 289 
 290         if (lock_type & LOCKING_ANDX_OPLOCK_RELEASE) {
 291                 uint32_t NewLevel;
 292                 if (oplock_level == 0)
 293                         NewLevel = OPLOCK_LEVEL_NONE;
 294                 else
 295                         NewLevel = OPLOCK_LEVEL_TWO;
 296                 status = smb_oplock_ack_break(sr, ofile, &NewLevel);
 297                 if (status == NT_STATUS_OPLOCK_BREAK_IN_PROGRESS) {
 298                         (void) smb_oplock_wait_break(ofile->f_node, 0);
 299                         status = 0;
 300                 }
 301                 if (unlock_num == 0 && lock_num == 0)
 302                         return (SDRC_NO_REPLY);
 303         }
 304 
 305         /*
 306          * No support for changing locktype (although we could probably
 307          * implement this)
 308          */
 309         if (lock_type & LOCKING_ANDX_CHANGE_LOCK_TYPE) {
 310                 smbsr_error(sr, 0, ERRDOS,
 311                     ERROR_ATOMIC_LOCKS_NOT_SUPPORTED);
 312                 return (SDRC_ERROR);
 313         }
 314 
 315         if (lock_type & LOCKING_ANDX_LARGE_FILES) {
 316                 /*
 317                  * negotiated protocol should be NT LM 0.12 or later
 318                  */
 319                 if (sr->session->dialect < NT_LM_0_12) {
 320                         smbsr_error(sr, NT_STATUS_INVALID_PARAMETER,
 321                             ERRDOS, ERROR_INVALID_PARAMETER);
 322                         return (SDRC_ERROR);
 323                 }
 324         }
 325 
 326         /*
 327          * Parse the unlock, lock vectors.  Will parse all the
 328          * unlock + lock records into one array, and then use
 329          * pointers to the unlock and lock parts.
 330          */
 331         lrv_tot = unlock_num + lock_num;
 332         lrv_ul = smb_srm_zalloc(sr, lrv_tot * sizeof (*lrv_ul));
 333         lrv_lk = &lrv_ul[unlock_num];
 334 
 335         for (i = 0; i < lrv_tot; i++) {
 336                 lr = &lrv_ul[i];
 337                 if (lock_type & LOCKING_ANDX_LARGE_FILES) {
 338                         rc = smb_mbc_decodef(&sr->smb_data, "w2.QQ",
 339                             &tmp_pid, &lr->off, &lr->len);
 340                 } else {
 341                         uint32_t        offset32, length32;
 342                         rc = smb_mbc_decodef(&sr->smb_data, "wll",
 343                             &tmp_pid, &offset32, &length32);
 344                         lr->off = offset32;
 345                         lr->len = length32;
 346                 }
 347                 lr->pid = tmp_pid;   /* 16-bit PID */
 348                 if (rc) {
 349                         /*
 350                          * This is the error returned by Windows 2000
 351                          * even when STATUS32 has been negotiated.
 352                          */
 353                         smbsr_error(sr, 0, ERRSRV, ERRerror);
 354                         return (SDRC_ERROR);
 355                 }
 356         }
 357 
 358         /*
 359          * Cancel waiting locks.  MS-CIFS says one place that
 360          * this cancels all waiting locks for this FID+PID,
 361          * but smbtorture insists this cancels just one.
 362          * Tests with Windows 7 confirms that.
 363          */
 364         if ((lock_type & LOCKING_ANDX_CANCEL_LOCK) != 0) {
 365                 lr = lrv_lk;
 366 
 367                 result = smb_lock_range_cancel(sr, lr->off, lr->len, lr->pid);
 368 
 369                 if (result != NT_STATUS_SUCCESS) {
 370                         smbsr_error(sr, 0, ERRDOS,
 371                             ERROR_CANCEL_VIOLATION);
 372                         return (SDRC_ERROR);
 373                 }
 374                 goto out;
 375         }
 376 
 377         /*
 378          * Normal unlock and lock list
 379          */
 380         for (i = 0; i < unlock_num; i++) {
 381                 lr = &lrv_ul[i];
 382 
 383                 result = smb_unlock_range(sr, lr->off, lr->len, lr->pid);
 384                 if (result != NT_STATUS_SUCCESS) {
 385                         smbsr_error(sr, NT_STATUS_RANGE_NOT_LOCKED,
 386                             ERRDOS, ERROR_NOT_LOCKED);
 387                         return (SDRC_ERROR);
 388                 }
 389         }
 390         for (i = 0; i < lock_num; i++) {
 391                 lr = &lrv_lk[i];
 392 
 393                 result = smb_lock_range(sr, lr->off, lr->len, lr->pid,
 394                     ltype, timeout);
 395                 if (result != NT_STATUS_SUCCESS) {
 396                         /*
 397                          * Oh... we have to rollback.
 398                          */
 399                         while (i > 0) {
 400                                 --i;
 401                                 lr = &lrv_lk[i];
 402                                 (void) smb_unlock_range(sr,
 403                                     lr->off, lr->len, lr->pid);
 404                         }
 405                         smb_lock_range_error(sr, result);
 406                         return (SDRC_ERROR);
 407                 }
 408         }
 409 
 410 out:
 411         if (smbsr_encode_result(sr, 2, 0, "bb.ww",
 412             2, sr->andx_com, 0x27, 0) != 0)
 413                 return (SDRC_ERROR);
 414         return (SDRC_SUCCESS);
 415 }
 416 
 417 /*
 418  * Compose an SMB1 Oplock Break Notification packet, including
 419  * the SMB1 header and everything, in sr->reply.
 420  * The caller will send it and free the request.
 421  */
 422 void
 423 smb1_oplock_break_notification(smb_request_t *sr, uint32_t NewLevel)
 424 {
 425         smb_ofile_t *ofile = sr->fid_ofile;
 426         uint16_t fid;
 427         uint8_t lock_type;
 428         uint8_t oplock_level;
 429 
 430         /*
 431          * Convert internal level to SMB1
 432          */
 433         switch (NewLevel) {
 434         default:
 435                 ASSERT(0);
 436                 /* FALLTHROUGH */
 437         case OPLOCK_LEVEL_NONE:
 438                 oplock_level = 0;
 439                 break;
 440 
 441         case OPLOCK_LEVEL_TWO:
 442                 oplock_level = 1;
 443                 break;
 444         }
 445 
 446         sr->smb_com = SMB_COM_LOCKING_ANDX;
 447         sr->smb_tid = ofile->f_tree->t_tid;
 448         sr->smb_pid = 0xFFFF;
 449         sr->smb_uid = 0;
 450         sr->smb_mid = 0xFFFF;
 451         fid = ofile->f_fid;
 452         lock_type = LOCKING_ANDX_OPLOCK_RELEASE;
 453 
 454         (void) smb_mbc_encodef(
 455             &sr->reply, "Mb19.wwwwbb3.wbb10.",
 456             /*  "\xffSMB"                  M */
 457             sr->smb_com,             /* b */
 458             /* status, flags, signature  19. */
 459             sr->smb_tid,             /* w */
 460             sr->smb_pid,             /* w */
 461             sr->smb_uid,             /* w */
 462             sr->smb_mid,             /* w */
 463             8,          /* word count      b */
 464             0xFF,       /* AndX cmd        b */
 465             /*  AndX reserved, offset     3. */
 466             fid,
 467             lock_type,
 468             oplock_level);
 469 }