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 2014 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 smb_sdrc_t
 216 smb_pre_locking_andx(smb_request_t *sr)
 217 {
 218         DTRACE_SMB_1(op__LockingX__start, smb_request_t *, sr);
 219         return (SDRC_SUCCESS);
 220 }
 221 
 222 void
 223 smb_post_locking_andx(smb_request_t *sr)
 224 {
 225         DTRACE_SMB_1(op__LockingX__done, smb_request_t *, sr);
 226 }
 227 
 228 smb_sdrc_t
 229 smb_com_locking_andx(smb_request_t *sr)
 230 {
 231         unsigned short  i;
 232         unsigned char   lock_type;      /* See lock_type table above */
 233         unsigned char   oplock_level;   /* The new oplock level */
 234         uint32_t        timeout;        /* Milliseconds to wait for lock */
 235         unsigned short  unlock_num;     /* # unlock range structs */
 236         unsigned short  lock_num;       /* # lock range structs */
 237         uint32_t        save_pid;       /* Process Id of owner */
 238         uint32_t        offset32, length32;
 239         uint64_t        offset64;
 240         uint64_t        length64;
 241         DWORD           result;
 242         int             rc;
 243         uint32_t        ltype;
 244         smb_ofile_t     *ofile;
 245         uint16_t        tmp_pid;        /* locking uses 16-bit pids */
 246         uint8_t         brk;
 247 
 248         rc = smbsr_decode_vwv(sr, "4.wbblww", &sr->smb_fid, &lock_type,
 249             &oplock_level, &timeout, &unlock_num, &lock_num);
 250         if (rc != 0)
 251                 return (SDRC_ERROR);
 252 
 253         smbsr_lookup_file(sr);
 254         if (sr->fid_ofile == NULL) {
 255                 smbsr_error(sr, NT_STATUS_INVALID_HANDLE, ERRDOS, ERRbadfid);
 256                 return (SDRC_ERROR);
 257         }
 258         ofile = sr->fid_ofile;
 259         if (ofile->f_node == NULL) {
 260                 smbsr_error(sr, NT_STATUS_INVALID_PARAMETER,
 261                     ERRDOS, ERROR_INVALID_PARAMETER);
 262                 return (SDRC_ERROR);
 263         }
 264 
 265         if (lock_type & LOCKING_ANDX_SHARED_LOCK)
 266                 ltype = SMB_LOCK_TYPE_READONLY;
 267         else
 268                 ltype = SMB_LOCK_TYPE_READWRITE;
 269 
 270         save_pid = sr->smb_pid;      /* Save the original pid */
 271 
 272         if (lock_type & LOCKING_ANDX_OPLOCK_RELEASE) {
 273                 if (oplock_level == 0)
 274                         brk = SMB_OPLOCK_BREAK_TO_NONE;
 275                 else
 276                         brk = SMB_OPLOCK_BREAK_TO_LEVEL_II;
 277                 smb_oplock_ack(ofile->f_node, ofile, brk);
 278                 if (unlock_num == 0 && lock_num == 0)
 279                         return (SDRC_NO_REPLY);
 280         }
 281 
 282         /*
 283          * No support for changing locktype (although we could probably
 284          * implement this)
 285          */
 286         if (lock_type & LOCKING_ANDX_CHANGE_LOCK_TYPE) {
 287                 smbsr_error(sr, 0, ERRDOS,
 288                     ERROR_ATOMIC_LOCKS_NOT_SUPPORTED);
 289                 return (SDRC_ERROR);
 290         }
 291 
 292         /*
 293          * No support for cancel lock (smbtorture expects this)
 294          */
 295         if (lock_type & LOCKING_ANDX_CANCEL_LOCK) {
 296                 smbsr_error(sr, NT_STATUS_INVALID_PARAMETER,
 297                     ERRDOS, ERROR_INVALID_PARAMETER);
 298                 return (SDRC_ERROR);
 299         }
 300 
 301         if (lock_type & LOCKING_ANDX_LARGE_FILES) {
 302                 /*
 303                  * negotiated protocol should be NT LM 0.12 or later
 304                  */
 305                 if (sr->session->dialect < NT_LM_0_12) {
 306                         smbsr_error(sr, NT_STATUS_INVALID_PARAMETER,
 307                             ERRDOS, ERROR_INVALID_PARAMETER);
 308                         return (SDRC_ERROR);
 309                 }
 310 
 311                 for (i = 0; i < unlock_num; i++) {
 312                         rc = smb_mbc_decodef(&sr->smb_data, "w2.QQ",
 313                             &tmp_pid, &offset64, &length64);
 314                         if (rc) {
 315                                 /*
 316                                  * This is the error returned by Windows 2000
 317                                  * even when STATUS32 has been negotiated.
 318                                  */
 319                                 smbsr_error(sr, 0, ERRSRV, ERRerror);
 320                                 return (SDRC_ERROR);
 321                         }
 322                         sr->smb_pid = tmp_pid;       /* NB: 16-bit */
 323 
 324                         result = smb_unlock_range(sr, sr->fid_ofile->f_node,
 325                             offset64, length64);
 326                         if (result != NT_STATUS_SUCCESS) {
 327                                 smbsr_error(sr, NT_STATUS_RANGE_NOT_LOCKED,
 328                                     ERRDOS, ERROR_NOT_LOCKED);
 329                                 return (SDRC_ERROR);
 330                         }
 331                 }
 332 
 333                 for (i = 0; i < lock_num; i++) {
 334                         rc = smb_mbc_decodef(&sr->smb_data, "w2.QQ",
 335                             &tmp_pid, &offset64, &length64);
 336                         if (rc) {
 337                                 smbsr_error(sr, 0, ERRSRV, ERRerror);
 338                                 return (SDRC_ERROR);
 339                         }
 340                         sr->smb_pid = tmp_pid;       /* NB: 16-bit */
 341 
 342                         result = smb_lock_range(sr, offset64, length64, timeout,
 343                             ltype);
 344                         if (result != NT_STATUS_SUCCESS) {
 345                                 smb_lock_range_error(sr, result);
 346                                 return (SDRC_ERROR);
 347                         }
 348                 }
 349         } else {
 350                 for (i = 0; i < unlock_num; i++) {
 351                         rc = smb_mbc_decodef(&sr->smb_data, "wll", &tmp_pid,
 352                             &offset32, &length32);
 353                         if (rc) {
 354                                 smbsr_error(sr, 0, ERRSRV, ERRerror);
 355                                 return (SDRC_ERROR);
 356                         }
 357                         sr->smb_pid = tmp_pid;       /* NB: 16-bit */
 358 
 359                         result = smb_unlock_range(sr, sr->fid_ofile->f_node,
 360                             (uint64_t)offset32, (uint64_t)length32);
 361                         if (result != NT_STATUS_SUCCESS) {
 362                                 smbsr_error(sr, NT_STATUS_RANGE_NOT_LOCKED,
 363                                     ERRDOS, ERROR_NOT_LOCKED);
 364                                 return (SDRC_ERROR);
 365                         }
 366                 }
 367 
 368                 for (i = 0; i < lock_num; i++) {
 369                         rc = smb_mbc_decodef(&sr->smb_data, "wll", &tmp_pid,
 370                             &offset32, &length32);
 371                         if (rc) {
 372                                 smbsr_error(sr, 0, ERRSRV, ERRerror);
 373                                 return (SDRC_ERROR);
 374                         }
 375                         sr->smb_pid = tmp_pid;       /* NB: 16-bit */
 376 
 377                         result = smb_lock_range(sr, (uint64_t)offset32,
 378                             (uint64_t)length32, timeout, ltype);
 379                         if (result != NT_STATUS_SUCCESS) {
 380                                 smb_lock_range_error(sr, result);
 381                                 return (SDRC_ERROR);
 382                         }
 383                 }
 384         }
 385 
 386         sr->smb_pid = save_pid;
 387         if (smbsr_encode_result(sr, 2, 0, "bb.ww", 2, sr->andx_com, 7, 0))
 388                 return (SDRC_ERROR);
 389         return (SDRC_SUCCESS);
 390 }
 391 
 392 /*
 393  * Compose an SMB1 Oplock Break Notification packet, including
 394  * the SMB1 header and everything, in sr->reply.
 395  * The caller will send it and free the request.
 396  */
 397 void
 398 smb1_oplock_break_notification(smb_request_t *sr, uint8_t brk)
 399 {
 400         smb_ofile_t *ofile = sr->fid_ofile;
 401         uint16_t fid;
 402         uint8_t lock_type;
 403         uint8_t oplock_level;
 404 
 405         switch (brk) {
 406         default:
 407                 ASSERT(0);
 408                 /* FALLTHROUGH */
 409         case SMB_OPLOCK_BREAK_TO_NONE:
 410                 oplock_level = 0;
 411                 break;
 412         case SMB_OPLOCK_BREAK_TO_LEVEL_II:
 413                 oplock_level = 1;
 414                 break;
 415         }
 416 
 417         sr->smb_com = SMB_COM_LOCKING_ANDX;
 418         sr->smb_tid = ofile->f_tree->t_tid;
 419         sr->smb_pid = 0xFFFF;
 420         sr->smb_uid = 0;
 421         sr->smb_mid = 0xFFFF;
 422         fid = ofile->f_fid;
 423         lock_type = LOCKING_ANDX_OPLOCK_RELEASE;
 424 
 425         (void) smb_mbc_encodef(
 426             &sr->reply, "Mb19.wwwwbb3.wbb10.",
 427             /*  "\xffSMB"                  M */
 428             sr->smb_com,             /* b */
 429             /* status, flags, signature  19. */
 430             sr->smb_tid,             /* w */
 431             sr->smb_pid,             /* w */
 432             sr->smb_uid,             /* w */
 433             sr->smb_mid,             /* w */
 434             8,          /* word count      b */
 435             0xFF,       /* AndX cmd        b */
 436             /*  AndX reserved, offset     3. */
 437             fid,
 438             lock_type,
 439             oplock_level);
 440 }