3.3.5.9 Receiving an SMB2 CREATE Request
When the server receives a request with an SMB2 header with a Command value equal to SMB2 CREATE, message handling proceeds as described in the following sections.
If Connection.Dialect belongs to the SMB 3.x dialect family and the request does not contain SMB2_CREATE_DURABLE_HANDLE_RECONNECT Create Context or SMB2_CREATE_DURABLE_HANDLE_RECONNECT_V2 Create Context, the server MUST look up an existing open in the GlobalOpenTable where Open.FileName matches the file name in the Buffer field of the request. If an Open entry is found, and if all the following conditions are satisfied, the server SHOULD<297> fail the request with STATUS_FILE_NOT_AVAILABLE.
Open.IsPersistent is TRUE
Open.Connection is NULL
The server MAY<298> validate the create contexts before session verification.
Session Verification:
The server MUST locate the session, as specified in section 3.3.5.2.9.
Tree Connect Verification:
The server MUST locate the tree connection, as specified in section 3.3.5.2.11.
The server MUST fail the request with STATUS_INVALID_PARAMETER in the following cases:
If NameLength number of bytes in the Buffer field extends beyond the CREATE request received.
If NameLength is not a multiple of 2.
If NameOffset is less than the Buffer field offset.
Path Name Validation:
The server MUST verify the request size. If the size of the SMB2 CREATE Request (excluding the SMB2 header) is less than specified in the StructureSize field, then the request MUST be failed with STATUS_INVALID_PARAMETER.
The server MUST extract the target path name for the create from the SMB2 CREATE Request.
If the request received has SMB2_FLAGS_DFS_OPERATIONS set in the Flags field of the SMB2 header, and TreeConnect.Share.IsDfs is TRUE, the server MUST verify the value of IsDfsCapable:
If IsDfsCapable is TRUE, the server MUST invoke the interface defined in [MS-DFSC] section 3.2.4.1 to normalize the path name by supplying the target path name.
If IsDfsCapable is FALSE, the server MUST fail the request with STATUS_FS_DRIVER_REQUIRED.
If the request received does not have the SMB2_FLAGS_DFS_OPERATIONS flag set in the Flags field of the SMB2 header, or TreeConnect.Share.IsDfs is FALSE, the server MUST NOT invoke normalization and continue the create process.
If normalization fails, the server MUST fail the create request with the error code returned by the DFS normalization routine.
If the normalization procedure succeeds, returning an altered target name, the modified name MUST be used for further operations.
If the file name in the Buffer field of the request fails to resolve the pathname components as specified in [MS-FSCC] section 2.1.5.1, the server SHOULD<299> fail the request with STATUS_INVALID_PARAMETER.
The server MUST verify the file name in an implementation-specific manner.<300>
For pipe opens, the server MUST ignore FileAttributes.
For print files, if the FileAttributes field includes FILE_ATTRIBUTE_DIRECTORY, the server MUST fail the open with the error code STATUS_NOT_SUPPORTED.
If the share that is the target of the create request is the IPC$ share and Session.IsAnonymous is TRUE, the server MUST invoke the event specified in [MS-SRVS] section 3.1.6.17 by providing the target name as the input parameter. If the event returns FALSE, indicating that no matching named pipe is found that allows an anonymous user, the server MUST fail the request with STATUS_ACCESS_DENIED and increase ServerStatistics.sts0_permerrors by 1. Otherwise, the server MUST continue the open processing.
If the share that is the target of the create request is a printer, the server MUST validate the DesiredAccess and CreateDisposition fields of the request. If the DesiredAccess value does not include one or more of the FILE_WRITE_DATA, FILE_APPEND_DATA, or GENERIC_WRITE bits, the server SHOULD<301> fail the request with STATUS_NOT_SUPPORTED. If the DesiredAccess value contains any other bits, the server MUST fail the request with STATUS_NOT_SUPPORTED. If the CreateDisposition value is other than FILE_CREATE, the server SHOULD<302> fail the request with STATUS_OBJECT_NAME_NOT_FOUND.
If any intermediate component of the path specified in the create request is a symbolic link, the server MUST return an error as specified in section 2.2.2.2.1. Symbolic links MUST NOT be evaluated by the server.
If the final component of the path is a symbolic link, the server behavior depends on whether the flag FILE_OPEN_REPARSE_POINT was specified in the CreateOptions field of the request. If FILE_OPEN_REPARSE_POINT was specified, the server MUST open the underlying file or directory and return a handle to it. Otherwise, the server MUST return an error as specified in section 2.2.2.2.1.
Create Context Validation:
The server MUST fail create contexts having a NameLength less than 4 with a STATUS_INVALID_PARAMETER error.
If the size of each individual create context is not equal to the DataLength of the create context, the server MUST fail the request with STATUS_INVALID_PARAMETER.
The following subsections detail server behavior when various create contexts are provided in the request and describe how that affects server operation.
If the server implements the SMB 3.x dialect family and all of the following conditions are TRUE, the server MUST look up an Open in GlobalOpenTable where Open.IsReplayEligible is TRUE and Open.CreateGuid matches the CreateGuid in the SMB2_CREATE_DURABLE_HANDLE_REQUEST_V2 create context and Open.ClientGuid matches the ClientGuid of the connection that received this request:
The SMB2_FLAGS_REPLAY_OPERATION bit is set in the SMB2 header.
The request includes an SMB2_CREATE_DURABLE_HANDLE_REQUEST_V2 create context.
The Treeconnect.Share.Type is STYPE_DISKTREE as specified in [MS-SRVS] section 2.2.2.4.
If an Open is found, the server MUST perform the following:
The server MUST fail the create request with STATUS_ACCESS_DENIED in the following cases:
Open.DurableOwner is NULL or is not the user represented by Session.SecurityContext.
If Open.Lease is not NULL and Open.Lease.LeaseKey is not equal to the LeaseKey specified in the SMB2_CREATE_REQUEST_LEASE or SMB2_CREATE_REQUEST_LEASE_V2 Create Context.
If Open.Session.SessionId is not equal to the current Session.SessionId, the server MUST fail the request with STATUS_DUPLICATE_OBJECTID.
If Open.IsPersistent is TRUE and the SMB2_DHANDLE_FLAG_PERSISTENT bit is not set in the Flags field of the SMB2_CREATE_DURABLE_HANDLE_REQUEST_V2 Create Context, the server SHOULD<303> fail the request with STATUS_INVALID_PARAMETER.
Construct the create response from Open, as specified in the "Response Construction" phase; the remaining create processing MUST be skipped.
Open Execution:
If the FILE_DELETE_ON_CLOSE flag is set in CreateOptions and Treeconnect.MaximalAccess does not include DELETE or GENERIC, the server SHOULD<304> fail the request with STATUS_ACCESS_DENIED.
When opening a named pipe, if the ImpersonationLevel level is Delegate, the server MUST fail the request with STATUS_BAD_IMPERSONATION_LEVEL.
If the connection is over QUIC, IsMutualAuthOverQUICSupported is FALSE, AllowNamedPipeAccessOverQUIC is FALSE, and a named pipe is being opened, the server MUST fail the request with STATUS_ACCESS_DENIED.
If the connection is over QUIC, IsMutualAuthOverQUICSupported is TRUE, and a named pipe is being opened, and Connection.ServerCertificateMappingEntry.AllowNamedPipe is FALSE, the server MUST fail the request with STATUS_ACCESS_DENIED.
If TreeConnect.Share.Type is STYPE_DISKTREE as specified in [MS-SRVS] section 2.2.2.4, the server MUST do the following:
If DesiredAccess is zero, the server SHOULD<305> fail the request with STATUS_ACCESS_DENIED.
If TreeConnect.Share.RestrictExclusiveOpens is TRUE and the ShareAccess field does not include FILE_SHARE_READ, and the DesiredAccess field does not include GENERIC_ALL, GENERIC_WRITE, FILE_WRITE_DATA, FILE_WRITE_ATTRIBUTES, FILE_WRITE_EA, or FILE_APPEND_DATA, the server SHOULD<306> set FILE_SHARE_READ in the ShareAccess field.
If TreeConnect.Share.ForceSharedDelete is TRUE, the server MUST set FILE_SHARE_DELETE in the ShareAccess field.
If DesiredAccess is not equal to TreeConnect.MaximalAccess and TreeConnect.Share.ConnectSecurity is not empty, the server MUST perform as below:
Clear ACCESS_SYSTEM_SECURITY in DesiredAccess. If DesiredAccess is zero, the server MUST fail the request with STATUS_ACCESS_DENIED.
If Session.SecurityContext is empty, the server MUST fail the request with STATUS_ACCESS_DENIED.
The server MUST perform access check for the share in the underlying object store using the parameters Session.SecurityContext, TreeConnect.Share.ConnectSecurity and DesiredAccess.<307> If the underlying object store returns a failure and TreeConnect.Share.DoAccessBasedDirectoryEnumeration is TRUE and CreateDisposition is FILE_OPEN, the server MUST fail the request with STATUS_OBJECT_NAME_NOT_FOUND. Otherwise, if the underlying object store returns a failure, the server MUST fail the request with STATUS_ACCESS_DENIED.
If TreeConnect.Share.ForceLevel2Oplock is TRUE, and RequestedOplockLevel is SMB2_OPLOCK_LEVEL_BATCH or SMB2_OPLOCK_LEVEL_EXCLUSIVE, the server SHOULD<308> set RequestedOplockLevel to SMB2_OPLOCK_LEVEL_II.
If Connection.Dialect belongs to the SMB 3.x dialect family, TreeConnect.Share.Type is STYPE_CLUSTER_SOFS as specified in [MS-SRVS] section 2.2.2.4, and the RequestedOplockLevel is SMB2_OPLOCK_LEVEL_BATCH, the server MUST set RequestedOplockLevel to SMB2_OPLOCK_LEVEL_II.
If CreateOptions includes FILE_NO_INTERMEDIATE_BUFFERING, the server MUST set FILE_APPEND_DATA to zero in the DesiredAccess field in the request.
The server MUST set the following flags to zero in the CreateOptions field:
FILE_COMPLETE_IF_OPLOCKED
FILE_SYNCHRONOUS_IO_ALERT
FILE_SYNCHRONOUS_IO_NONALERT
FILE_OPEN_FOR_FREE_SPACE_QUERY
The server MUST use TreeConnect.RemotedIdentitySecurityContext if present, otherwise the server MUST use the security context of the session in Session.SecurityContext to attempt to open the named object in the underlying object store using the parameters specified for DesiredAccess, FileAttributes, ShareAccess, CreateDisposition, CreateOptions, and the PathName. The PathName MUST be parsed relative to TreeConnect.Share.LocalPath. The server MUST map these flags to match the semantics of its implementation-specific object store [MS-FSA].<309> See section 2.2.13 for more details on the exact meaning of the various flags and options. If the underlying object store returns a failure for the attempted Open, the server MUST send an SMB2 ERROR response with an error code as specified in section 2.2.2. The same rules apply when opening named pipe and print files, except that some flags and options are not supported when opening named pipes and print files. The flags and options that are not supported when opening named pipes and print files are specified in section 2.2.13.
Failed Open Handling:
If the underlying object store returns a failure indicating that the attempted open operation failed due to the presence of a symbolic link in the target path name, the server MUST fail the create operation with the error code STATUS_STOPPED_ON_SYMLINK, and pass back the error to the client by constructing an error response as specified in section 2.2.2.2.1.<310>
If the underlying object store returns STATUS_ACCESS_DENIED, ServerStatistics.sts0_permerrors MUST be increased by 1.
Successful Open Initialization:
If the open is successful, the server MUST allocate an open object for this open and insert it into Session.OpenTable and GlobalOpenTable. If TreeConnect.Share.Type is not equal to STYPE_PRINTQ as specified in [MS-SRVS] section 2.2.2.4, ServerStatistics.sts0_fopens MUST be increased by 1. If TreeConnect.Share.Type is equal to STYPE_PRINTQ as specified in [MS-SRVS] section 2.2.2.4, ServerStatistics.sts0_jobsqueued MUST be increased by 1. The server MUST also register the Open by invoking the event specified in [MS-SRVS] section 3.1.6.4 and assign the return value to Open.FileGlobalId. The other initial values MUST be set as follows:
Open.FileId is set to a generated value that uniquely identifies this Open in Session.OpenTable. The SMB2 server MUST reserve -1 for invalid FileId.
Open.DurableFileId is set to a generated value that uniquely identifies this open in GlobalOpenTable.
Open.Session is set to refer to the session that performed the open.
Open.Connection is set to refer to the connection on which the open request was received.
Open.ClientGuid is set to Open.Connection.ClientGuid.
Open.LocalOpen is set to the open of the object in the local resource received as part of the local create operation.
If DesiredAccess is equal to TreeConnect.MaximalAccess, the server MUST set Open.GrantedAccess to TreeConnect.MaximalAccess.
If DesiredAccess is not equal to TreeConnect.MaximalAccess and TreeConnect.Share.ConnectSecurity is empty, the server MUST set Open.GrantedAccess to FILE_READ_DATA | FILE_WRITE_DATA | FILE_APPEND_DATA | FILE_READ_EA | FILE_WRITE_EA | FILE_DELETE_CHILD | FILE_EXECUTE | FILE_READ_ATTRIBUTES | FILE_WRITE_ATTRIBUTES | DELETE | READ_CONTROL | WRITE_DAC | WRITE_OWNER | SYNCHRONIZE.
Otherwise,
If MAXIMUM_ALLOWED is not included in the DesiredAccess, the server MUST set Open.GrantedAccess to the DesiredAccess specified in the request. Otherwise, the server MUST set Open.GrantedAccess to DesiredAccess with GENERIC_ALL set.
If DesiredAccess received in the request includes ACCESS_SYSTEM_SECURITY, the server MUST set ACCESS_SYSTEM_SECURITY in Open.GrantedAccess.
If Open.GrantedAccess includes FILE_EXECUTE, the server MUST set FILE_READ_DATA in Open.GrantedAccess.
Open.OplockLevel is set to SMB2_OPLOCK_LEVEL_NONE.
Open.OplockState is set to None.
Open.OplockTimeout is set to 0.
Open.IsDurable is set to FALSE.
Open.DurableOpenTimeout is set to 0.
Open.DurableOwner is set to NULL.
Open.CurrentEaIndex is set to 1.
Open.CurrentQuotaIndex is set to 1.
Open.TreeConnect is set to refer to the TreeConnect on which the open request was performed and Open.TreeConnect.OpenCount MUST be increased by 1.
Open.LockCount is set to 0.
Open.PathName is set to the full local path that the current open is performed on.
Open.FileName MUST be set to the file name in the Buffer field of the request.
Open.CreateOptions MUST be set to the CreateOptions field of the request.
Open.FileAttributes MUST be set to the FileAttributes field of the request.
If Connection.Dialect is not "2.0.2" and the server supports leasing, the server MUST initialize the following:
Open.Lease MUST be set to NULL.
If Connection.Dialect is not "2.0.2" and the server supports resiliency, the server MUST initialize the following:
Open.IsResilient MUST be set to FALSE.
Open.ResilientOpenTimeout MUST be set to 0.
Each entry of Open.LockSequenceArray MUST be initialized as follows:
Set Valid to FALSE.
If the server implements the SMB 3.x dialect family, the server MUST initialize the following:
If the server does not implement the SMB 3.1.1 dialect, Open.AppInstanceId MUST be set to AppInstanceId in the SMB2_CREATE_APP_INSTANCE_ID create context request if the create request includes the SMB2_CREATE_DURABLE_HANDLE_REQUEST_V2 and SMB2_CREATE_APP_INSTANCE_ID create contexts. Otherwise, Open.AppInstanceId MUST be set to the AppInstanceId field in the SMB2_CREATE_APP_INSTANCE_ID create context request.
Open.CreateGuid MUST be set to NULL.
Open.IsPersistent MUST be set to FALSE.
Open.ChannelSequence MUST be set to ChannelSequence in the SMB2 Header of the request.
If both an SMB2_CREATE_APP_INSTANCE_ID and an SMB2_CREATE_APP_INSTANCE_VERSION are present in the request and Open.Connection.Dialect is not 2.0.2, 2.1, 3.0, or 3.0.2:
Open.ApplicationInstanceVersionHigh MUST be set to the AppInstanceVersionHigh in the SMB2_CREATE_APP_INSTANCE_VERSION create context.
Open.ApplicationInstanceVersionLow MUST be set to the AppInstanceVersionLow in the SMB2_CREATE_APP_INSTANCE_VERSION create context request.
The server MUST locate the Request in Connection.RequestList for which Request.MessageId matches the MessageId value in the SMB2 header, and set Request.Open to the Open.
Oplock Acquisition:
If the server does not support leasing and RequestedOplockLevel is set to SMB2_OPLOCK_LEVEL_LEASE, the server MUST ignore the "RqLs" create context.
If the server supports leasing, the name of the create context is "RqLs" as defined in section 2.2.13.2, and RequestedOplockLevel is set to SMB2_OPLOCK_LEVEL_LEASE, the server MUST do the following:
If the size of the Buffer, in bytes, of the SMB2_CREATE_CONTEXT is not equal to the size of the SMB2_CREATE_REQUEST_LEASE (0x20) or the size of the SMB2_CREATE_REQUEST_LEASE_V2 ( 0x34), the server MUST fail the request with STATUS_INVALID_PARAMETER.
If Connection.Dialect is "2.1" or belongs to the "3.x" dialect family, and the DataLength field equals 0x20, the server MUST attempt to acquire a lease on the open from the underlying object store as described in section 3.3.5.9.8.
If Connection.Dialect belongs to the "3.x" dialect family, and the DataLength field equals 0x34, the server MUST attempt to acquire a lease on the open from the underlying object store, as described in section 3.3.5.9.11.
If the lease level is not granted and if the lease level requested contains SMB2_LEASE_WRITE_CACHING, the server will remove the SMB2_LEASE_WRITE_CACHING bit and if there are still any bits left, it will try to acquire the lease again with reduced bits. If that fails, the server will take away the SMB2_LEASE_HANDLE_CACHING bit and see if any bits are left. If yes, then it will try to acquire the lease again.
Otherwise, the server MUST fail the request with STATUS_INVALID_PARAMETER.
If the open is successful, the shared resource is not a named pipe, and the RequestedOplockLevel is not SMB2_OPLOCK_LEVEL_NONE, the server MUST attempt to acquire an oplock on the open from the underlying object store.<311> If the underlying object store grants the oplock, then Open.OplockState MUST be set to Held and Open.OplockLevel MUST be set to the level of the oplock acquired. Otherwise, the server MUST perform the following steps:
If the RequestedOplockLevel is SMB2_OPLOCK_LEVEL_II, then the server MUST set RequestedOplockLevel to SMB2_OPLOCK_LEVEL_NONE.
Otherwise, the server MUST set the RequestedOplockLevel to SMB2_OPLOCK_LEVEL_II, and attempt to acquire an oplock on the open from the underlying object store.
If the underlying object store grants an oplock for SMB2_OPLOCK_LEVEL_II, then Open.OplockState MUST be set to Held and Open.OplockLevel MUST be set to the level of the oplock acquired.
Otherwise, the server MUST set RequestedOplockLevel to SMB2_OPLOCK_LEVEL_NONE.
Response Construction:
The server MUST construct a response following the syntax specified in section 2.2.14. The values MUST be set as follows:
OplockLevel is set to Open.OplockLevel.
If Connection.Dialect belongs to the SMB 3.x dialect family and Open.LocalOpen is a reparse point, and the create request Create Options do not contain FILE_OPEN_REPARSE_POINT, set the SMB2_CREATE_FLAG_REPARSEPOINT bit in the Flags field.
CreateAction is set to the action taken by the create following the syntax specified in section 2.2.14.
CreationTime is set to the value queried from the object store for when the object was created.<312>
LastAccessTime is set to the value queried from the object store for when the object was last accessed.<313>
LastWriteTime is set to the value queried from the object store for when the object was last written to.<314>
ChangeTime is set to the value queried from the object store for when the object was last modified, including attribute changes.<315>
AllocationSize is set to the amount of space reserved for the object, in bytes, on the underlying object store.<316> If this is a named pipe, AllocationSize SHOULD be 0.<317>
EndofFile is set to the size of the requested stream of the object in bytes.<318> For named pipes this value SHOULD be 0.<319>
FileAttributes MUST be set to the attributes of the object following the syntax specified in section 2.2.14.<320>
FileId.Persistent MUST be set to Open.DurableFileId.
FileId.Volatile MUST be set to Open.FileId.
CreateContextsOffset MUST be set to the offset, in bytes, from the beginning of the SMB2 header to the first SMB2_CREATE_CONTEXT response. If no SMB2_CREATE_CONTEXT response is returned, this value MUST be set to 0.
CreateContextsLength MUST be set to the length, in bytes, of the list of SMB2_CREATE_CONTEXT response structures. If no SMB2_CREATE_CONTEXT response structure is returned, this value MUST be set to 0.
This response MUST be sent back to the client.
The status code returned by this operation MUST be one of those defined in [MS-ERREF]. Common status codes returned by this operation include:
STATUS_SUCCESS
STATUS_INSUFFICIENT_RESOURCES
STATUS_ACCESS_DENIED
STATUS_OBJECT_NAME_NOT_FOUND
STATUS_INVALID_PARAMETER
STATUS_STOPPED_ON_SYMLINK
STATUS_USER_SESSION_DELETED
STATUS_NETWORK_NAME_DELETED
STATUS_NETWORK_SESSION_EXPIRED
STATUS_NOT_SUPPORTED
STATUS_EAS_NOT_SUPPORTED
STATUS_DISK_FULL
STATUS_FILE_CLOSED
The following create contexts are potentially received as part of the create request. In each subsection, handling this create context is outlined.