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 #include <smbsrv/smb_kproto.h>
     27 #include <smbsrv/smb_vops.h>
     28 
     29 int smb_open_dsize_check = 0;
     30 
     31 /*
     32  *  Client Request                     Description
     33  *  ================================== =================================
     34  *
     35  *  UCHAR WordCount;                   Count of parameter words = 15
     36  *  UCHAR AndXCommand;                 Secondary (X) command;  0xFF =
     37  *                                      none
     38  *  UCHAR AndXReserved;                Reserved (must be 0)
     39  *  USHORT AndXOffset;                 Offset to next command WordCount
     40  *  USHORT Flags;                      Additional information: bit set-
     41  *                                      0 - return additional info
     42  *                                      1 - exclusive oplock requested
     43  *                                      2 - batch oplock requested
     44  *  USHORT DesiredAccess;              File open mode
     45  *  USHORT SearchAttributes;
     46  *  USHORT FileAttributes;
     47  *  UTIME CreationTime;                Creation timestamp for file if it
     48  *                                      gets created
     49  *  USHORT OpenFunction;               Action to take if file exists
     50  *  ULONG AllocationSize;              Bytes to reserve on create or
     51  *                                      truncate
     52  *  ULONG Reserved[2];                 Must be 0
     53  *  USHORT ByteCount;                  Count of data bytes;    min = 1
     54  *  UCHAR BufferFormat                 0x04
     55  *  STRING FileName;
     56  *
     57  *  Server Response                    Description
     58  *  ================================== =================================
     59  *
     60  *  UCHAR WordCount;                   Count of parameter words = 15
     61  *  UCHAR AndXCommand;                 Secondary (X) command;  0xFF =
     62  *                                      none
     63  *  UCHAR AndXReserved;                Reserved (must be 0)
     64  *  USHORT AndXOffset;                 Offset to next command WordCount
     65  *  USHORT Fid;                        File handle
     66  *  USHORT FileAttributes;
     67  *  UTIME LastWriteTime;
     68  *  ULONG DataSize;                    Current file size
     69  *  USHORT GrantedAccess;              Access permissions actually
     70  *                                      allowed
     71  *  USHORT FileType;                   Type of file opened
     72  *  USHORT DeviceState;                State of the named pipe
     73  *  USHORT Action;                     Action taken
     74  *  ULONG ServerFid;                   Server unique file id
     75  *  USHORT Reserved;                   Reserved (must be 0)
     76  *  USHORT ByteCount;                  Count of data bytes = 0
     77  *
     78  * DesiredAccess describes the access the client desires for the file (see
     79  * section 3.6 -  Access Mode Encoding).
     80  *
     81  * OpenFunction specifies the action to be taken depending on whether or
     82  * not the file exists (see section 3.8 -  Open Function Encoding).  Action
     83  *
     84  * in the response specifies the action as a result of the Open request
     85  * (see section 3.9 -  Open Action Encoding).
     86  *
     87  * SearchAttributes indicates the attributes that the file must have to be
     88  * found while searching to see if it exists.  The encoding of this field
     89  * is described in the "File Attribute Encoding" section elsewhere in this
     90  * document.  If SearchAttributes is zero then only normal files are
     91  * returned.  If the system file, hidden or directory attributes are
     92  * specified then the search is inclusive -- both the specified type(s) of
     93  * files and normal files are returned.
     94  *
     95  * FileType returns the kind of resource actually opened:
     96  *
     97  *  Name                       Value  Description
     98  *  ========================== ====== ==================================
     99  *
    100  *  FileTypeDisk               0      Disk file or directory as defined
    101  *                                     in the attribute field
    102  *  FileTypeByteModePipe       1      Named pipe in byte mode
    103  *  FileTypeMessageModePipe    2      Named pipe in message mode
    104  *  FileTypePrinter            3      Spooled printer
    105  *  FileTypeUnknown            0xFFFF Unrecognized resource type
    106  *
    107  * If bit0 of Flags is clear, the FileAttributes, LastWriteTime, DataSize,
    108  * FileType, and DeviceState have indeterminate values in the response.
    109  *
    110  * This SMB can request an oplock on the opened file.  Oplocks are fully
    111  * described in the "Oplocks" section elsewhere in this document, and there
    112  * is also discussion of oplocks in the SMB_COM_LOCKING_ANDX SMB
    113  * description.  Bit1 and bit2 of the Flags field are used to request
    114  * oplocks during open.
    115  *
    116  * The following SMBs may follow SMB_COM_OPEN_ANDX:
    117  *
    118  *    SMB_COM_READ    SMB_COM_READ_ANDX
    119  *    SMB_COM_IOCTL
    120  */
    121 
    122 /*
    123  * This message is sent to obtain a file handle for a data file.  This
    124  * returned Fid is used in subsequent client requests such as read, write,
    125  * close, etc.
    126  *
    127  * Client Request                     Description
    128  * ================================== =================================
    129  *
    130  * UCHAR WordCount;                   Count of parameter words = 2
    131  * USHORT DesiredAccess;              Mode - read/write/share
    132  * USHORT SearchAttributes;
    133  * USHORT ByteCount;                  Count of data bytes;    min = 2
    134  * UCHAR BufferFormat;                0x04
    135  * STRING FileName[];                 File name
    136  *
    137  * FileName is the fully qualified file name, relative to the root of the
    138  * share specified in the Tid field of the SMB header.  If Tid in the SMB
    139  * header refers to a print share, this SMB creates a new file which will
    140  * be spooled to the printer when closed.  In this case, FileName is
    141  * ignored.
    142  *
    143  * SearchAttributes specifies the type of file desired.  The encoding is
    144  * described in the "File Attribute Encoding" section.
    145  *
    146  * DesiredAccess controls the mode under which the file is opened, and the
    147  * file will be opened only if the client has the appropriate permissions.
    148  * The encoding of DesiredAccess is discussed in the section entitled
    149  * "Access Mode Encoding".
    150  *
    151  * Server Response                    Description
    152  * ================================== =================================
    153  *
    154  * UCHAR WordCount;                   Count of parameter words = 7
    155  * USHORT Fid;                        File handle
    156  * USHORT FileAttributes;             Attributes of opened file
    157  * UTIME LastWriteTime;               Time file was last written
    158  * ULONG DataSize;                    File size
    159  * USHORT GrantedAccess;              Access allowed
    160  * USHORT ByteCount;                  Count of data bytes = 0
    161  *
    162  * Fid is the handle value which should be used for subsequent file
    163  * operations.
    164  *
    165  * FileAttributes specifies the type of file obtained.  The encoding is
    166  * described in the "File Attribute Encoding" section.
    167  *
    168  * GrantedAccess indicates the access permissions actually allowed, and may
    169  * have one of the following values:
    170  *
    171  *    0  read-only
    172  *    1  write-only
    173  *    2 read/write
    174  *
    175  * File Handles (Fids) are scoped per client.  A Pid may reference any Fid
    176  * established by itself or any other Pid on the client (so far as the
    177  * server is concerned).  The actual accesses allowed through the Fid
    178  * depends on the open and deny modes specified when the file was opened
    179  * (see below).
    180  *
    181  * The MS-DOS compatibility mode of file open provides exclusion at the
    182  * client level.  A file open in compatibility mode may be opened (also in
    183  * compatibility mode) any number of times for any combination of reading
    184  * and writing (subject to the user's permissions) by any Pid on the same
    185  * client.  If the first client has the file open for writing, then the
    186  * file may not be opened in any way by any other client.  If the first
    187  * client has the file open only for reading, then other clients may open
    188  * the file, in compatibility mode, for reading..  The above
    189  * notwithstanding, if the filename has an extension of .EXE, .DLL, .SYM,
    190  * or .COM other clients are permitted to open the file regardless of
    191  * read/write open modes of other compatibility mode opens.  However, once
    192  * multiple clients have the file open for reading, no client is permitted
    193  * to open the file for writing and no other client may open the file in
    194  * any mode other than compatibility mode.
    195  *
    196  * The other file exclusion modes (Deny read/write, Deny write, Deny read,
    197  * Deny none) provide exclusion at the file level.  A file opened in any
    198  * "Deny" mode may be opened again only for the accesses allowed by the
    199  * Deny mode (subject to the user's permissions).  This is true regardless
    200  * of the identity of the second opener -a different client, a Pid from the
    201  * same client, or the Pid that already has the file open.  For example, if
    202  * a file is open in "Deny write" mode a second open may only obtain read
    203  * permission to the file.
    204  *
    205  * Although Fids are available to all Pids on a client, Pids other than the
    206  * owner may not have the full access rights specified in the open mode by
    207  * the Fid's creator.  If the open creating the Fid specified a deny mode,
    208  * then any Pid using the Fid, other than the creating Pid, will have only
    209  * those access rights determined by "anding" the open mode rights and the
    210  * deny mode rights, i.e., the deny mode is checked on all file accesses.
    211  * For example, if a file is opened for Read/Write in Deny write mode, then
    212  * other clients may only read the file and cannot write; if a file is
    213  * opened for Read in Deny read mode, then the other clients can neither
    214  * read nor write the file.
    215  */
    216 
    217 smb_sdrc_t
    218 smb_pre_open(smb_request_t *sr)
    219 {
    220 	struct open_param *op = &sr->arg.open;
    221 	int rc;
    222 
    223 	bzero(op, sizeof (sr->arg.open));
    224 
    225 	rc = smbsr_decode_vwv(sr, "ww", &op->omode, &op->fqi.fq_sattr);
    226 	if (rc == 0)
    227 		rc = smbsr_decode_data(sr, "%S", sr, &op->fqi.fq_path.pn_path);
    228 
    229 	DTRACE_SMB_2(op__Open__start, smb_request_t *, sr,
    230 	    struct open_param *, op);
    231 
    232 	return ((rc == 0) ? SDRC_SUCCESS : SDRC_ERROR);
    233 }
    234 
    235 void
    236 smb_post_open(smb_request_t *sr)
    237 {
    238 	DTRACE_SMB_1(op__Open__done, smb_request_t *, sr);
    239 }
    240 
    241 smb_sdrc_t
    242 smb_com_open(smb_request_t *sr)
    243 {
    244 	struct open_param *op = &sr->arg.open;
    245 	smb_node_t *node;
    246 	smb_attr_t attr;
    247 	uint16_t file_attr;
    248 	int rc;
    249 
    250 	op->desired_access = smb_omode_to_amask(op->omode);
    251 	op->share_access = smb_denymode_to_sharemode(op->omode,
    252 	    op->fqi.fq_path.pn_path);
    253 	op->crtime.tv_sec = op->crtime.tv_nsec = 0;
    254 	op->create_disposition = FILE_OPEN;
    255 	op->create_options = FILE_NON_DIRECTORY_FILE;
    256 	if (op->omode & SMB_DA_WRITE_THROUGH)
    257 		op->create_options |= FILE_WRITE_THROUGH;
    258 
    259 	if (sr->smb_flg & SMB_FLAGS_OPLOCK) {
    260 		if (sr->smb_flg & SMB_FLAGS_OPLOCK_NOTIFY_ANY)
    261 			op->op_oplock_level = SMB_OPLOCK_BATCH;
    262 		else
    263 			op->op_oplock_level = SMB_OPLOCK_EXCLUSIVE;
    264 	} else {
    265 		op->op_oplock_level = SMB_OPLOCK_NONE;
    266 	}
    267 
    268 	if (smb_common_open(sr) != NT_STATUS_SUCCESS)
    269 		return (SDRC_ERROR);
    270 
    271 	if (op->op_oplock_level == SMB_OPLOCK_NONE) {
    272 		sr->smb_flg &=
    273 		    ~(SMB_FLAGS_OPLOCK | SMB_FLAGS_OPLOCK_NOTIFY_ANY);
    274 	}
    275 
    276 	if (smb_open_dsize_check && op->dsize > UINT_MAX) {
    277 		smbsr_error(sr, 0, ERRDOS, ERRbadaccess);
    278 		return (SDRC_ERROR);
    279 	}
    280 
    281 	file_attr = op->dattr  & FILE_ATTRIBUTE_MASK;
    282 	node = sr->fid_ofile->f_node;
    283 	if (smb_node_getattr(sr, node, &attr) != 0) {
    284 		smbsr_error(sr, NT_STATUS_INTERNAL_ERROR,
    285 		    ERRDOS, ERROR_INTERNAL_ERROR);
    286 		return (SDRC_ERROR);
    287 	}
    288 
    289 	rc = smbsr_encode_result(sr, 7, 0, "bwwllww",
    290 	    7,
    291 	    sr->smb_fid,
    292 	    file_attr,
    293 	    smb_time_gmt_to_local(sr, attr.sa_vattr.va_mtime.tv_sec),
    294 	    (uint32_t)op->dsize,
    295 	    op->omode,
    296 	    (uint16_t)0);	/* bcc */
    297 
    298 	return ((rc == 0) ? SDRC_SUCCESS : SDRC_ERROR);
    299 }
    300 
    301 /*
    302  * smb_pre_open_andx
    303  * For compatibility with windows servers, the search attributes
    304  * specified in the request are ignored.
    305  */
    306 smb_sdrc_t
    307 smb_pre_open_andx(smb_request_t *sr)
    308 {
    309 	struct open_param *op = &sr->arg.open;
    310 	uint16_t flags;
    311 	uint32_t creation_time;
    312 	uint16_t file_attr, sattr;
    313 	int rc;
    314 
    315 	bzero(op, sizeof (sr->arg.open));
    316 
    317 	rc = smbsr_decode_vwv(sr, "b.wwwwwlwll4.", &sr->andx_com,
    318 	    &sr->andx_off, &flags, &op->omode, &sattr,
    319 	    &file_attr, &creation_time, &op->ofun, &op->dsize, &op->timeo);
    320 
    321 	if (rc == 0) {
    322 		rc = smbsr_decode_data(sr, "%u", sr, &op->fqi.fq_path.pn_path);
    323 
    324 		op->dattr = file_attr;
    325 
    326 		if (flags & 2)
    327 			op->op_oplock_level = SMB_OPLOCK_EXCLUSIVE;
    328 		else if (flags & 4)
    329 			op->op_oplock_level = SMB_OPLOCK_BATCH;
    330 		else
    331 			op->op_oplock_level = SMB_OPLOCK_NONE;
    332 
    333 		if ((creation_time != 0) && (creation_time != UINT_MAX))
    334 			op->crtime.tv_sec =
    335 			    smb_time_local_to_gmt(sr, creation_time);
    336 		op->crtime.tv_nsec = 0;
    337 
    338 		op->create_disposition = smb_ofun_to_crdisposition(op->ofun);
    339 	}
    340 
    341 	DTRACE_SMB_2(op__OpenX__start, smb_request_t *, sr,
    342 	    struct open_param *, op);
    343 
    344 	return ((rc == 0) ? SDRC_SUCCESS : SDRC_ERROR);
    345 }
    346 
    347 void
    348 smb_post_open_andx(smb_request_t *sr)
    349 {
    350 	DTRACE_SMB_1(op__OpenX__done, smb_request_t *, sr);
    351 }
    352 
    353 smb_sdrc_t
    354 smb_com_open_andx(smb_request_t *sr)
    355 {
    356 	struct open_param	*op = &sr->arg.open;
    357 	uint16_t		file_attr;
    358 	smb_attr_t		attr;
    359 	int rc;
    360 
    361 	op->desired_access = smb_omode_to_amask(op->omode);
    362 	op->share_access = smb_denymode_to_sharemode(op->omode,
    363 	    op->fqi.fq_path.pn_path);
    364 
    365 	if (op->create_disposition > FILE_MAXIMUM_DISPOSITION) {
    366 		smbsr_error(sr, 0, ERRDOS, ERRbadaccess);
    367 		return (SDRC_ERROR);
    368 	}
    369 
    370 	op->create_options = FILE_NON_DIRECTORY_FILE;
    371 	if (op->omode & SMB_DA_WRITE_THROUGH)
    372 		op->create_options |= FILE_WRITE_THROUGH;
    373 
    374 	if (smb_common_open(sr) != NT_STATUS_SUCCESS)
    375 		return (SDRC_ERROR);
    376 
    377 	if (smb_open_dsize_check && op->dsize > UINT_MAX) {
    378 		smbsr_error(sr, 0, ERRDOS, ERRbadaccess);
    379 		return (SDRC_ERROR);
    380 	}
    381 
    382 	if (op->op_oplock_level != SMB_OPLOCK_NONE)
    383 		op->action_taken |= SMB_OACT_LOCK;
    384 	else
    385 		op->action_taken &= ~SMB_OACT_LOCK;
    386 
    387 	file_attr = op->dattr & FILE_ATTRIBUTE_MASK;
    388 	if (STYPE_ISDSK(sr->tid_tree->t_res_type)) {
    389 
    390 		smb_node_t *node = sr->fid_ofile->f_node;
    391 		if (smb_node_getattr(sr, node, &attr) != 0) {
    392 			smbsr_error(sr, NT_STATUS_INTERNAL_ERROR,
    393 			    ERRDOS, ERROR_INTERNAL_ERROR);
    394 			return (SDRC_ERROR);
    395 		}
    396 
    397 		rc = smbsr_encode_result(sr, 15, 0,
    398 		    "bb.wwwllwwwwl2.w",
    399 		    15,
    400 		    sr->andx_com, VAR_BCC,
    401 		    sr->smb_fid,
    402 		    file_attr,
    403 		    smb_time_gmt_to_local(sr, attr.sa_vattr.va_mtime.tv_sec),
    404 		    (uint32_t)op->dsize,
    405 		    op->omode, op->ftype,
    406 		    op->devstate,
    407 		    op->action_taken, op->fileid,
    408 		    0);
    409 	} else {
    410 		rc = smbsr_encode_result(sr, 15, 0,
    411 		    "bb.wwwllwwwwl2.w",
    412 		    15,
    413 		    sr->andx_com, VAR_BCC,
    414 		    sr->smb_fid,
    415 		    file_attr,
    416 		    0L,
    417 		    0L,
    418 		    op->omode, op->ftype,
    419 		    op->devstate,
    420 		    op->action_taken, op->fileid,
    421 		    0);
    422 	}
    423 
    424 	return ((rc == 0) ? SDRC_SUCCESS : SDRC_ERROR);
    425 }
    426 
    427 smb_sdrc_t
    428 smb_com_trans2_open2(smb_request_t *sr, smb_xa_t *xa)
    429 {
    430 	struct open_param *op = &sr->arg.open;
    431 	uint32_t	creation_time;
    432 	uint32_t	alloc_size;
    433 	uint16_t	flags;
    434 	uint16_t	file_attr;
    435 	int		rc;
    436 
    437 	bzero(op, sizeof (sr->arg.open));
    438 
    439 	rc = smb_mbc_decodef(&xa->req_param_mb, "%wwwwlwl10.u",
    440 	    sr, &flags, &op->omode, &op->fqi.fq_sattr, &file_attr,
    441 	    &creation_time, &op->ofun, &alloc_size, &op->fqi.fq_path.pn_path);
    442 	if (rc != 0)
    443 		return (SDRC_ERROR);
    444 
    445 	if ((creation_time != 0) && (creation_time != UINT_MAX))
    446 		op->crtime.tv_sec = smb_time_local_to_gmt(sr, creation_time);
    447 	op->crtime.tv_nsec = 0;
    448 
    449 	op->dattr = file_attr;
    450 	op->dsize = alloc_size;
    451 	op->create_options = FILE_NON_DIRECTORY_FILE;
    452 
    453 	op->desired_access = smb_omode_to_amask(op->omode);
    454 	op->share_access = smb_denymode_to_sharemode(op->omode,
    455 	    op->fqi.fq_path.pn_path);
    456 
    457 	op->create_disposition = smb_ofun_to_crdisposition(op->ofun);
    458 	if (op->create_disposition > FILE_MAXIMUM_DISPOSITION)
    459 		op->create_disposition = FILE_CREATE;
    460 
    461 	if (op->omode & SMB_DA_WRITE_THROUGH)
    462 		op->create_options |= FILE_WRITE_THROUGH;
    463 
    464 	if (sr->smb_flg & SMB_FLAGS_OPLOCK) {
    465 		if (sr->smb_flg & SMB_FLAGS_OPLOCK_NOTIFY_ANY)
    466 			op->op_oplock_level = SMB_OPLOCK_BATCH;
    467 		else
    468 			op->op_oplock_level = SMB_OPLOCK_EXCLUSIVE;
    469 	} else {
    470 		op->op_oplock_level = SMB_OPLOCK_NONE;
    471 	}
    472 
    473 	if (smb_common_open(sr) != NT_STATUS_SUCCESS)
    474 		return (SDRC_ERROR);
    475 
    476 	if (op->op_oplock_level != SMB_OPLOCK_NONE)
    477 		op->action_taken |= SMB_OACT_LOCK;
    478 	else
    479 		op->action_taken &= ~SMB_OACT_LOCK;
    480 
    481 	file_attr = op->dattr & FILE_ATTRIBUTE_MASK;
    482 
    483 	if (!STYPE_ISDSK(sr->tid_tree->t_res_type))
    484 		op->dsize = 0;
    485 
    486 	(void) smb_mbc_encodef(&xa->rep_param_mb, "wwllwwwwlwl",
    487 	    sr->smb_fid,
    488 	    file_attr,
    489 	    (uint32_t)0,	/* creation time */
    490 	    (uint32_t)op->dsize,
    491 	    op->omode,
    492 	    op->ftype,
    493 	    op->devstate,
    494 	    op->action_taken,
    495 	    op->fileid,
    496 	    (uint16_t)0,	/* EA error offset */
    497 	    (uint32_t)0);	/* EA list length */
    498 
    499 	return (SDRC_SUCCESS);
    500 }
    501