/// </summary> /// <param name="fileId">The fileid for the directory. </param> /// <param name="treeId">The treeId for the directory. </param> /// <param name="sessionId">The sessionId for the directory. </param> /// <param name="searchPattern">A Unicode string containing the file name pattern to match. </param> /// <param name="fileInfoClass">The FileInfoClass to query. </param> /// <param name="returnSingleEntry">A boolean indicating whether the return single entry for query.</param> /// <param name="restartScan">A boolean indicating whether the enumeration should be restarted.</param> /// <param name="isOutBufferSizeLess">True: if OutputBufferSize is less than the size needed to return a single entry</param> /// of section 3.1.5.5.4</param> /// <returns>An NTSTATUS code that specifies the result</returns> public MessageStatus QueryDirectory( Smb2.FILEID fileId, uint treeId, ulong sessionId, string searchPattern = "*", FileInfoClass fileinfoClass = FileInfoClass.FILE_ID_BOTH_DIR_INFORMATION, bool returnSingleEntry = false, bool restartScan = false, bool isOutPutBufferNotEnough = false ) { BaseTestSite.Log.Add(LogEntryKind.TestStep, $"Query a directory information with fileid {fileId}"); MessageStatus status = this.fsaAdapter.QueryDirectoryInfo( fileId, treeId, sessionId, searchPattern, FileInfoClass.FILE_ID_BOTH_DIR_INFORMATION, returnSingleEntry, restartScan, isOutPutBufferNotEnough); BaseTestSite.Log.Add(LogEntryKind.TestStep, $"Query directory with search pattern {searchPattern} and return with status {status}. "); return(status); }
/// <summary> /// Create directory /// </summary> /// <param name="dirName">Direcotry name</param> /// <param name="fileId">The fileid of the created directory</param> /// <param name="treeId">The treeId of the created directory</param> /// <param name="sessionId">The sessionId of the created directory</param> /// <returns>An NTSTATUS code that specifies the result</returns> public MessageStatus CreateDirectory( string dirName, out Smb2.FILEID fileId, out uint treeId, out ulong sessionId) { BaseTestSite.Log.Add(LogEntryKind.TestStep, $"Create a directory with name: {dirName}"); MessageStatus status = MessageStatus.SUCCESS; status = this.fsaAdapter.CreateFile( dirName, FileAttribute.DIRECTORY, CreateOptions.DIRECTORY_FILE, (FileAccess.GENERIC_READ | FileAccess.GENERIC_WRITE), (ShareAccess.FILE_SHARE_READ | ShareAccess.FILE_SHARE_WRITE), CreateDisposition.OPEN_IF, out fileId, out treeId, out sessionId ); BaseTestSite.Log.Add(LogEntryKind.TestStep, $"Create directory and return with status {status}"); return(status); }
protected override void TestInitialize() { base.TestInitialize(); testConfig = new SqosTestConfig(BaseTestSite); BaseTestSite.DefaultProtocolDocShortName = "MS-SQOS"; BaseTestSite.Log.Add(LogEntryKind.Debug, "SecurityPackage for authentication: " + TestConfig.DefaultSecurityPackage); client = new Smb2FunctionalClient(TestConfig.Timeout, TestConfig, BaseTestSite); treeId = 0; fileId = FILEID.Zero; #region Check Applicability TestConfig.CheckIOCTL(CtlCode_Values.FSCTL_STORAGE_QOS_CONTROL); #endregion }
public void CloseFile() { if (fileId.Equals(FILEID.Zero)) { return; } Packet_Header header; TREE_DISCONNECT_Response treeDisconnectResponse; CheckStatusCode( client.TreeDisconnect( 1, 1, headerFlags, messageId++, sessionId, treeId, out header, out treeDisconnectResponse)); LOGOFF_Response logoffResponse; CheckStatusCode( client.LogOff( 1, 1, headerFlags, messageId++, sessionId, out header, out logoffResponse)); client.Disconnect(); fileId = FILEID.Zero; }
/// <summary> /// Create operation for PrepareOpen operation /// </summary> private void PrepareOpenCreate( Smb2FunctionalClient client, uint treeIdBeforeDisconnection, string fileName, out FILEID fileIdBeforDisconnection, out Smb2CreateContextResponse[] serverCreateContexts, RequestedOplockLevel_Values requestedOplocklevel, Smb2CreateContextRequest[] prepareContext) { client.Create( treeIdBeforeDisconnection, fileName, CreateOptions_Values.FILE_NON_DIRECTORY_FILE, out fileIdBeforDisconnection, out serverCreateContexts, requestedOplocklevel, prepareContext, shareAccess: ShareAccess_Values.NONE, checker: (HASH_HEADER, response) => { }); }
public override void Reset() { if (testClientBeforeDisconnection != null) { testClientBeforeDisconnection.Disconnect(); } if (testClientAfterDisconnection != null) { testClientAfterDisconnection.Disconnect(); } fileIdBeforDisconnection = FILEID.Zero; base.Reset(); }
/// <summary> /// Create an open from client, this include NEGOTIATE and SESSION_SETUP with server, TREE_CONNECT to the share and CREATE an open to file/directory /// </summary> /// <param name="client">Client used to take the operation</param> /// <param name="clientGuid">Client GUID for negotiation</param> /// <param name="targetName">File/directory name for the open</param> /// <param name="isDirectory">Set true if create open to a directory, set false if create open to a file</param> /// <param name="accessMask">Desired access when create the open</param> /// <param name="treeId">Out param for tree id used to connect to the share</param> /// <param name="fileId">Out param for file id that is associated with the open</param> /// <param name="shareAccess">Optional param for share access when create the open</param> /// <returns>Status value returned from CREATE request</returns> private uint CreateOpenFromClient(Smb2FunctionalClient client, Guid clientGuid, string targetName, bool isDirectory, LeaseStateValues requestLeaseState, AccessMask accessMask, out uint treeId, out FILEID fileId, ShareAccess_Values shareAccess = ShareAccess_Values.FILE_SHARE_DELETE | ShareAccess_Values.FILE_SHARE_READ | ShareAccess_Values.FILE_SHARE_WRITE) { #region Negotiate BaseTestSite.Log.Add( LogEntryKind.TestStep, "Client {0} sends NEGOTIATE request with the following capabilities: Capabilities_Values.GLOBAL_CAP_DFS | Capabilities_Values.GLOBAL_CAP_DIRECTORY_LEASING | Capabilities_Values.GLOBAL_CAP_LARGE_MTU | Capabilities_Values.GLOBAL_CAP_LEASING | Capabilities_Values.GLOBAL_CAP_MULTI_CHANNEL | Capabilities_Values.GLOBAL_CAP_PERSISTENT_HANDLES.", clientGuid.ToString()); client.Negotiate( TestConfig.RequestDialects, TestConfig.IsSMB1NegotiateEnabled, capabilityValue: Capabilities_Values.GLOBAL_CAP_DFS | Capabilities_Values.GLOBAL_CAP_DIRECTORY_LEASING | Capabilities_Values.GLOBAL_CAP_LARGE_MTU | Capabilities_Values.GLOBAL_CAP_LEASING | Capabilities_Values.GLOBAL_CAP_MULTI_CHANNEL | Capabilities_Values.GLOBAL_CAP_PERSISTENT_HANDLES, clientGuid: clientGuid, checker: (Packet_Header header, NEGOTIATE_Response response) => { BaseTestSite.Assert.AreEqual( Smb2Status.STATUS_SUCCESS, header.Status, "Negotiation is expected success, actually server returns {0}", Smb2Status.GetStatusCode(header.Status)); TestConfig.CheckNegotiateDialect(DialectRevision.Smb30, response); TestConfig.CheckNegotiateCapabilities(NEGOTIATE_Response_Capabilities_Values.GLOBAL_CAP_DIRECTORY_LEASING, response); }); #endregion #region SESSION_SETUP BaseTestSite.Log.Add(LogEntryKind.TestStep, "Client {0} sends SESSION_SETUP request.", clientGuid.ToString()); status = client.SessionSetup( TestConfig.DefaultSecurityPackage, TestConfig.SutComputerName, TestConfig.AccountCredential, TestConfig.UseServerGssToken); #endregion #region TREE_CONNECT to share BaseTestSite.Log.Add(LogEntryKind.TestStep, "Client {0} sends TREE_CONNECT request.", clientGuid.ToString()); status = client.TreeConnect(uncSharePath, out treeId); #endregion #region CREATE Smb2CreateContextResponse[] serverCreateContexts; CreateOptions_Values createOptions; if (isDirectory) { createOptions = CreateOptions_Values.FILE_DIRECTORY_FILE; } else { createOptions = CreateOptions_Values.FILE_NON_DIRECTORY_FILE; } // Include FILE_DELETE_ON_CLOSE if accessMask has DELETE if ((accessMask & AccessMask.DELETE) == AccessMask.DELETE) { createOptions = createOptions | CreateOptions_Values.FILE_DELETE_ON_CLOSE; } BaseTestSite.Log.Add( LogEntryKind.TestStep, "Client {0} sends CREATE request with the lease state in SMB2_CREATE_REQUEST_LEASE_V2 set to {1}.", clientGuid.ToString(), requestLeaseState); status = client.Create( treeId, targetName, createOptions, out fileId, out serverCreateContexts, RequestedOplockLevel_Values.OPLOCK_LEVEL_LEASE, new Smb2CreateContextRequest[] { new Smb2CreateRequestLeaseV2 { LeaseKey = clientGuid, LeaseState = requestLeaseState } }, accessMask: accessMask, shareAccess: shareAccess, checker: (header, response) => { }); return status; #endregion }
private void OpenFileAndResilientRequest( Smb2FunctionalClient client, Guid clientGuid, string fileName, uint timeoutInMilliSeconds, out FILEID fileId) { uint treeId; // connect to share ConnectToShare( client, clientGuid, out treeId); BaseTestSite.Log.Add( LogEntryKind.Debug, "Connect to share '{0}' on server '{1}'", testConfig.BasicFileShare, testConfig.SutComputerName); // open file Smb2CreateContextResponse[] createContextResponse; client.Create( treeId, fileName, CreateOptions_Values.FILE_NON_DIRECTORY_FILE, out fileId, out createContextResponse ); BaseTestSite.Log.Add( LogEntryKind.Debug, "Create Open with file name '{0}'", fileName); // resiliency request Packet_Header ioCtlHeader; IOCTL_Response ioCtlResponse; byte[] inputInResponse; byte[] outputInResponse; client.ResiliencyRequest( treeId, fileId, timeoutInMilliSeconds, (uint)Marshal.SizeOf(typeof(NETWORK_RESILIENCY_Request)), out ioCtlHeader, out ioCtlResponse, out inputInResponse, out outputInResponse ); BaseTestSite.Log.Add( LogEntryKind.Debug, "Resiliency request with timeout {0} milliseconds", timeoutInMilliSeconds); }
public DetectResult CheckIOCTL_ValidateNegotiateInfo(string sharename, ref DetectionInfo info) { logWriter.AddLog(LogLevel.Information, "===== Detecting IOCTL ValidateNegotiateInfo ====="); using (Smb2Client client = new Smb2Client(new TimeSpan(0, 0, defaultTimeoutInSeconds))) { ulong messageId = 1; ulong sessionId = 0; uint treeId; NEGOTIATE_Response negotiateResponse; Guid clientGuid; bool encryptionRequired = false; DialectRevision[] preferredDialects; logWriter.AddLog(LogLevel.Information, "Client connects to server"); client.ConnectOverTCP(SUTIpAddress); if (info.CheckHigherDialect(info.smb2Info.MaxSupportedDialectRevision, DialectRevision.Smb311)) { // VALIDATE_NEGOTIATE_INFO request is only used in 3.0 and 3.0.2 preferredDialects = Smb2Utility.GetDialects(DialectRevision.Smb302); } else { preferredDialects = info.requestDialect; } #region Negotiate DialectRevision selectedDialect; byte[] gssToken; Packet_Header header; clientGuid = Guid.NewGuid(); logWriter.AddLog(LogLevel.Information, "Client sends multi-protocol Negotiate to server"); MultiProtocolNegotiate( client, 1, 1, Packet_Header_Flags_Values.NONE, messageId++, preferredDialects, SecurityMode_Values.NEGOTIATE_SIGNING_ENABLED, Capabilities_Values.GLOBAL_CAP_DFS | Capabilities_Values.GLOBAL_CAP_DIRECTORY_LEASING | Capabilities_Values.GLOBAL_CAP_LARGE_MTU | Capabilities_Values.GLOBAL_CAP_LEASING | Capabilities_Values.GLOBAL_CAP_MULTI_CHANNEL | Capabilities_Values.GLOBAL_CAP_PERSISTENT_HANDLES | Capabilities_Values.GLOBAL_CAP_ENCRYPTION, clientGuid, out selectedDialect, out gssToken, out header, out negotiateResponse); if (header.Status != Smb2Status.STATUS_SUCCESS) { LogFailedStatus("NEGOTIATE", header.Status); throw new Exception(string.Format("NEGOTIATE failed with {0}", Smb2Status.GetStatusCode(header.Status))); } #endregion #region Session Setup SESSION_SETUP_Response sessionSetupResp; SspiClientSecurityContext sspiClientGss = new SspiClientSecurityContext( SecurityPackageType, Credential, Smb2Utility.GetCifsServicePrincipalName(SUTName), ClientSecurityContextAttribute.None, SecurityTargetDataRepresentation.SecurityNativeDrep); // Server GSS token is used only for Negotiate authentication when enabled if (SecurityPackageType == SecurityPackageType.Negotiate) sspiClientGss.Initialize(gssToken); else sspiClientGss.Initialize(null); do { logWriter.AddLog(LogLevel.Information, "Client sends SessionSetup to server"); client.SessionSetup( 1, 64, Packet_Header_Flags_Values.NONE, messageId++, sessionId, SESSION_SETUP_Request_Flags.NONE, SESSION_SETUP_Request_SecurityMode_Values.NEGOTIATE_SIGNING_ENABLED, SESSION_SETUP_Request_Capabilities_Values.GLOBAL_CAP_DFS, 0, sspiClientGss.Token, out sessionId, out gssToken, out header, out sessionSetupResp); if ((header.Status == Smb2Status.STATUS_MORE_PROCESSING_REQUIRED || header.Status == Smb2Status.STATUS_SUCCESS) && gssToken != null && gssToken.Length > 0) { sspiClientGss.Initialize(gssToken); } } while (header.Status == Smb2Status.STATUS_MORE_PROCESSING_REQUIRED); if (header.Status != Smb2Status.STATUS_SUCCESS) { LogFailedStatus("SESSIONSETUP", header.Status); throw new Exception(string.Format("SESSIONSETUP failed with {0}", Smb2Status.GetStatusCode(header.Status))); } byte[] sessionKey; sessionKey = sspiClientGss.SessionKey; encryptionRequired = sessionSetupResp.SessionFlags == SessionFlags_Values.SESSION_FLAG_ENCRYPT_DATA; client.GenerateCryptoKeys( sessionId, sessionKey, info.smb2Info.IsRequireMessageSigning, // Enable signing according to the configuration of SUT encryptionRequired, null, false); #endregion #region TreeConnect TREE_CONNECT_Response treeConnectResp; string uncShare = string.Format(@"\\{0}\{1}", SUTName, sharename); logWriter.AddLog(LogLevel.Information, "Client sends TreeConnect to server"); client.TreeConnect( 1, 1, info.smb2Info.IsRequireMessageSigning ? Packet_Header_Flags_Values.FLAGS_SIGNED : Packet_Header_Flags_Values.NONE, messageId++, sessionId, uncShare, out treeId, out header, out treeConnectResp); if (header.Status != Smb2Status.STATUS_SUCCESS) { LogFailedStatus("TREECONNECT", header.Status); throw new Exception("TREECONNECT failed with " + Smb2Status.GetStatusCode(header.Status)); } #endregion TREE_DISCONNECT_Response treeDisconnectResponse; #region IOCTL FSCTL_VALIDATE_NEGOTIATE_INFO VALIDATE_NEGOTIATE_INFO_Request validateNegotiateInfoReq; validateNegotiateInfoReq.Guid = clientGuid; validateNegotiateInfoReq.Capabilities = Capabilities_Values.GLOBAL_CAP_DFS | Capabilities_Values.GLOBAL_CAP_DIRECTORY_LEASING | Capabilities_Values.GLOBAL_CAP_LARGE_MTU | Capabilities_Values.GLOBAL_CAP_LEASING | Capabilities_Values.GLOBAL_CAP_MULTI_CHANNEL | Capabilities_Values.GLOBAL_CAP_PERSISTENT_HANDLES | Capabilities_Values.GLOBAL_CAP_ENCRYPTION; validateNegotiateInfoReq.SecurityMode = SecurityMode_Values.NEGOTIATE_SIGNING_ENABLED; validateNegotiateInfoReq.DialectCount = (ushort)(preferredDialects.Length); validateNegotiateInfoReq.Dialects = preferredDialects; byte[] inputBuffer = TypeMarshal.ToBytes<VALIDATE_NEGOTIATE_INFO_Request>(validateNegotiateInfoReq); byte[] outputBuffer; VALIDATE_NEGOTIATE_INFO_Response validateNegotiateInfoResp; IOCTL_Response ioCtlResponse; byte[] respInput = new byte[1024]; FILEID ioCtlFileId = new FILEID(); ioCtlFileId.Persistent = 0xFFFFFFFFFFFFFFFF; ioCtlFileId.Volatile = 0xFFFFFFFFFFFFFFFF; logWriter.AddLog(LogLevel.Information, "Client sends FSCTL_VALIDATE_NEGOTIATE_INFO to server"); client.IoCtl( 1, 1, info.smb2Info.IsRequireMessageSigning ? Packet_Header_Flags_Values.FLAGS_SIGNED : Packet_Header_Flags_Values.NONE, messageId++, sessionId, treeId, CtlCode_Values.FSCTL_VALIDATE_NEGOTIATE_INFO, ioCtlFileId, 0, inputBuffer, 64 * 1024, IOCTL_Request_Flags_Values.SMB2_0_IOCTL_IS_FSCTL, out respInput, out outputBuffer, out header, out ioCtlResponse, 0); DetectResult result = DetectResult.UnSupported; if (header.Status != Smb2Status.STATUS_SUCCESS) { LogFailedStatus("Validate Negotiate Information", header.Status); } else { validateNegotiateInfoResp = TypeMarshal.ToStruct<VALIDATE_NEGOTIATE_INFO_Response>(outputBuffer); if ((Capabilities_Values)negotiateResponse.Capabilities != validateNegotiateInfoResp.Capabilities) { logWriter.AddLog(LogLevel.Information, "Capabilities returned in ValidateNegotiateInfo response doesn't eaqual to server capabilities in original Negotiate response"); } if (negotiateResponse.ServerGuid != validateNegotiateInfoResp.Guid) { logWriter.AddLog(LogLevel.Information, "ServerGuid returned in ValidateNegotiateInfo response doesn't eaqual to server ServerGuid in original Negotiate response"); } if ((SecurityMode_Values)negotiateResponse.SecurityMode != validateNegotiateInfoResp.SecurityMode) { logWriter.AddLog(LogLevel.Information, "SecurityMode returned in ValidateNegotiateInfo response doesn't eaqual to server SecurityMode in original Negotiate response"); } if (negotiateResponse.DialectRevision != validateNegotiateInfoResp.Dialect) { logWriter.AddLog(LogLevel.Information, "Validation failed for dialect supported on server"); } result = DetectResult.Supported; logWriter.AddLog(LogLevel.Information, "FSCTL_VALIDATE_NEGOTIATE_INFO is supported"); } #endregion #region Tree Disconnect client.TreeDisconnect( 1, 1, info.smb2Info.IsRequireMessageSigning ? Packet_Header_Flags_Values.FLAGS_SIGNED : Packet_Header_Flags_Values.NONE, messageId++, sessionId, treeId, out header, out treeDisconnectResponse); if (header.Status != Smb2Status.STATUS_SUCCESS) { LogFailedStatus("TREEDISCONNECT", header.Status); } #endregion return result; } }
public Smb2CreateResponsePacket CreateCreateResponseAsync( Smb2Endpoint endpoint, ulong asyncId, ulong messageId, OplockLevel_Values oplockLevel, CreateAction_Values createAction, _FILETIME creationTime, _FILETIME lastAccessTime, _FILETIME lastWriteTime, _FILETIME changeTime, ulong allocationSize, ulong endofFile, File_Attributes fileAttributes, FILEID fileId, params CREATE_CONTEXT_Values[] contexts ) { Smb2CreateResponsePacket packet = CreateCreateResponse(endpoint, messageId, oplockLevel, createAction, creationTime, lastAccessTime, lastWriteTime, changeTime, allocationSize, endofFile, fileAttributes, fileId, contexts); ModifyAsyncHeader(packet, endpoint, asyncId); packet.Sign(); return packet; }
public Smb2CreateResponsePacket CreateCreateResponse( Smb2Endpoint endpoint, ulong messageId, OplockLevel_Values oplockLevel, CreateAction_Values createAction, _FILETIME creationTime, _FILETIME lastAccessTime, _FILETIME lastWriteTime, _FILETIME changeTime, ulong allocationSize, ulong endofFile, File_Attributes fileAttributes, FILEID fileId, params CREATE_CONTEXT_Values[] createContexts ) { Smb2CreateResponsePacket packet = new Smb2CreateResponsePacket(); SetHeader(packet, endpoint, messageId); packet.PayLoad.StructureSize = CREATE_Response_StructureSize_Values.V1; packet.PayLoad.OplockLevel = oplockLevel; packet.PayLoad.Reserved = 0; packet.PayLoad.CreateAction = createAction; packet.PayLoad.CreationTime = creationTime; packet.PayLoad.LastAccessTime = lastAccessTime; packet.PayLoad.LastWriteTime = lastWriteTime; packet.PayLoad.ChangeTime = changeTime; packet.PayLoad.AllocationSize = allocationSize; packet.PayLoad.EndofFile = endofFile; packet.PayLoad.FileAttributes = fileAttributes; packet.PayLoad.Reserved2 = 0; packet.PayLoad.FileId = fileId; if (createContexts == null) { packet.PayLoad.CreateContextsOffset = 0; packet.PayLoad.CreateContextsLength = 0; packet.PayLoad.Buffer = new byte[0]; } else { packet.PayLoad.CreateContextsOffset = Smb2Consts.CreateContextOffsetInCreateResponse; using (MemoryStream ms = new MemoryStream()) { for (int i = 0; i < createContexts.Length; i++) { byte[] createContext = TypeMarshal.ToBytes(createContexts[i]); if (i != (createContexts.Length - 1)) { int alignedLen = Smb2Utility.AlignBy8Bytes(createContext.Length); byte[] nextValue = BitConverter.GetBytes(alignedLen); Array.Copy(nextValue, createContext, nextValue.Length); ms.Write(createContext, 0, createContext.Length); //write the padding 0; for (int j = 0; j < (alignedLen - createContext.Length); j++) { ms.WriteByte(0); } } else { ms.Write(createContext, 0, createContext.Length); } } packet.PayLoad.Buffer = ms.ToArray(); packet.PayLoad.CreateContextsLength = (uint)packet.PayLoad.Buffer.Length; } } packet.Sign(); return packet; }
/// <summary> /// Create Smb2OpLockBreakNotificationPacket /// </summary> /// <param name="endpoint">represents where this packet will be sent</param> /// <param name="oplockLevel">The server MUST set this to the maximum value of the OplockLevel /// that the server will accept for an acknowledgment from the client</param> /// <param name="fileId">An SMB2_FILEID, as specified in section 2.2.14.1</param> /// <returns>A Smb2OpLockBreakNotificationPacket</returns> public Smb2OpLockBreakNotificationPacket CreateOpLockBreakNotificationResponse( Smb2Endpoint endpoint, OPLOCK_BREAK_Notification_Packet_OplockLevel_Values oplockLevel, FILEID fileId ) { Smb2OpLockBreakNotificationPacket packet = new Smb2OpLockBreakNotificationPacket(); packet.Header.Flags = Packet_Header_Flags_Values.FLAGS_SERVER_TO_REDIR; packet.Header.Command = Smb2Command.OPLOCK_BREAK; packet.Header.MessageId = ulong.MaxValue; packet.Header.ProtocolId = Smb2Consts.Smb2ProtocolId; packet.Header.Signature = new byte[Smb2Consts.SignatureSize]; packet.Header.StructureSize = Packet_Header_StructureSize_Values.V1; packet.Endpoint = endpoint; packet.PayLoad.FileId = fileId; packet.PayLoad.OplockLevel = oplockLevel; packet.PayLoad.Reserved = OPLOCK_BREAK_Notification_Packet_Reserved_Values.V1; packet.PayLoad.Reserved2 = OPLOCK_BREAK_Notification_Packet_Reserved2_Values.V1; packet.PayLoad.StructureSize = OPLOCK_BREAK_Notification_Packet_StructureSize_Values.V1; packet.Sign(); return packet; }
public DetectResult CheckIOCTL_ValidateNegotiateInfo(string sharename, ref DetectionInfo info) { logWriter.AddLog(LogLevel.Information, "===== Detecting IOCTL ValidateNegotiateInfo ====="); using (Smb2Client client = new Smb2Client(new TimeSpan(0, 0, defaultTimeoutInSeconds))) { ulong messageId; ulong sessionId; uint treeId; NEGOTIATE_Response negotiateResponse; Guid clientGuid; bool encryptionRequired = false; UserLogon(info, client, out messageId, out sessionId, out clientGuid, out negotiateResponse, out encryptionRequired); #region TreeConnect TREE_CONNECT_Response treeConnectResp; string uncShare = string.Format(@"\\{0}\{1}", SUTName, sharename); Packet_Header header; logWriter.AddLog(LogLevel.Information, "Client sends TreeConnect to server"); if (info.smb2Info.MaxSupportedDialectRevision == DialectRevision.Smb311) // When dialect is 3.11, TreeConnect must be signed or encrypted. { client.EnableSessionSigningAndEncryption(sessionId, true, encryptionRequired); } client.TreeConnect( 1, 1, (info.smb2Info.IsRequireMessageSigning || info.smb2Info.MaxSupportedDialectRevision == DialectRevision.Smb311) ? Packet_Header_Flags_Values.FLAGS_SIGNED : Packet_Header_Flags_Values.NONE, messageId++, sessionId, uncShare, out treeId, out header, out treeConnectResp); if (header.Status != Smb2Status.STATUS_SUCCESS) { LogFailedStatus("TREECONNECT", header.Status); throw new Exception("TREECONNECT failed with " + Smb2Status.GetStatusCode(header.Status)); } // When dialect is 3.11, for the messages other than TreeConnect, signing is not required. // Set it back to the configuration of the SUT. if (info.smb2Info.MaxSupportedDialectRevision == DialectRevision.Smb311) { client.EnableSessionSigningAndEncryption(sessionId, info.smb2Info.IsRequireMessageSigning, encryptionRequired); } #endregion TREE_DISCONNECT_Response treeDisconnectResponse; #region IOCTL FSCTL_VALIDATE_NEGOTIATE_INFO VALIDATE_NEGOTIATE_INFO_Request validateNegotiateInfoReq; validateNegotiateInfoReq.Guid = clientGuid; validateNegotiateInfoReq.Capabilities = Capabilities_Values.GLOBAL_CAP_DFS | Capabilities_Values.GLOBAL_CAP_DIRECTORY_LEASING | Capabilities_Values.GLOBAL_CAP_LARGE_MTU | Capabilities_Values.GLOBAL_CAP_LEASING | Capabilities_Values.GLOBAL_CAP_MULTI_CHANNEL | Capabilities_Values.GLOBAL_CAP_PERSISTENT_HANDLES | Capabilities_Values.GLOBAL_CAP_ENCRYPTION; validateNegotiateInfoReq.SecurityMode = SecurityMode_Values.NEGOTIATE_SIGNING_ENABLED; validateNegotiateInfoReq.DialectCount = (ushort)(info.requestDialect.Length); validateNegotiateInfoReq.Dialects = info.requestDialect; byte[] inputBuffer = TypeMarshal.ToBytes<VALIDATE_NEGOTIATE_INFO_Request>(validateNegotiateInfoReq); byte[] outputBuffer; VALIDATE_NEGOTIATE_INFO_Response validateNegotiateInfoResp; IOCTL_Response ioCtlResponse; byte[] respInput = new byte[1024]; FILEID ioCtlFileId = new FILEID(); ioCtlFileId.Persistent = 0xFFFFFFFFFFFFFFFF; ioCtlFileId.Volatile = 0xFFFFFFFFFFFFFFFF; logWriter.AddLog(LogLevel.Information, "Client sends FSCTL_VALIDATE_NEGOTIATE_INFO to server"); client.IoCtl( 1, 1, info.smb2Info.IsRequireMessageSigning ? Packet_Header_Flags_Values.FLAGS_SIGNED : Packet_Header_Flags_Values.NONE, messageId++, sessionId, treeId, CtlCode_Values.FSCTL_VALIDATE_NEGOTIATE_INFO, ioCtlFileId, 0, inputBuffer, 64 * 1024, IOCTL_Request_Flags_Values.SMB2_0_IOCTL_IS_FSCTL, out respInput, out outputBuffer, out header, out ioCtlResponse, 0); DetectResult result = DetectResult.UnSupported; if (header.Status != Smb2Status.STATUS_SUCCESS) { LogFailedStatus("Validate Negotiate Information", header.Status); } else { validateNegotiateInfoResp = TypeMarshal.ToStruct<VALIDATE_NEGOTIATE_INFO_Response>(outputBuffer); if ((Capabilities_Values)negotiateResponse.Capabilities != validateNegotiateInfoResp.Capabilities) { logWriter.AddLog(LogLevel.Information, "Capabilities returned in ValidateNegotiateInfo response doesn't eaqual to server capabilities in original Negotiate response"); } if (negotiateResponse.ServerGuid != validateNegotiateInfoResp.Guid) { logWriter.AddLog(LogLevel.Information, "ServerGuid returned in ValidateNegotiateInfo response doesn't eaqual to server ServerGuid in original Negotiate response"); } if ((SecurityMode_Values)negotiateResponse.SecurityMode != validateNegotiateInfoResp.SecurityMode) { logWriter.AddLog(LogLevel.Information, "SecurityMode returned in ValidateNegotiateInfo response doesn't eaqual to server SecurityMode in original Negotiate response"); } if (negotiateResponse.DialectRevision != validateNegotiateInfoResp.Dialect) { logWriter.AddLog(LogLevel.Information, "Validation failed for dialect supported on server"); } result = DetectResult.Supported; logWriter.AddLog(LogLevel.Information, "FSCTL_VALIDATE_NEGOTIATE_INFO is supported"); } #endregion #region Tree Disconnect client.TreeDisconnect( 1, 1, info.smb2Info.IsRequireMessageSigning ? Packet_Header_Flags_Values.FLAGS_SIGNED : Packet_Header_Flags_Values.NONE, messageId++, sessionId, treeId, out header, out treeDisconnectResponse); if (header.Status != Smb2Status.STATUS_SUCCESS) { LogFailedStatus("TREEDISCONNECT", header.Status); } #endregion return result; } }
/// <summary> /// Write from Main channel over TCP /// </summary> /// <param name="serverIp">IP Address of Server.</param> /// <param name="clientIp">IP Address of Client.</param> /// <param name="fileName">File name.</param> /// <param name="totalWriteSize">Total Write Size in Bytes.</param> /// <param name="content">Content in the WRITE request.</param> /// <param name="treeId">Tree Connect Id.</param> /// <param name="fileId">File Id.</param> private void WriteFromMainChannel( IPAddress serverIp, IPAddress clientIp, string fileName, uint totalWriteSize, out byte[] content, out uint treeId, out FILEID fileId ) { BaseTestSite.Log.Add(LogEntryKind.TestStep, "Write file from Main channel over TCP."); BaseTestSite.Log.Add(LogEntryKind.Debug, "serverIp: " + serverIp.ToString()); BaseTestSite.Log.Add(LogEntryKind.Debug, "clientIp: " + clientIp.ToString()); BaseTestSite.Log.Add(LogEntryKind.Debug, "fileName: " + fileName); BaseTestSite.Log.Add(LogEntryKind.Debug, "Total write size in Bytes: " + totalWriteSize.ToString()); mainChannelClient.ConnectOverTCP(serverIp, clientIp); // SMB2 Negotiate DialectRevision[] negotiatedDialects = new DialectRevision[] { DialectRevision.Smb30, DialectRevision.Smb2002, DialectRevision.Smb21 }; DialectRevision selectedDialect; NtStatus status = (NtStatus)mainChannelClient.Smb2Negotiate(negotiatedDialects, out selectedDialect); BaseTestSite.Assert.AreEqual<NtStatus>(NtStatus.STATUS_SUCCESS, status, "Status of SMB2 Negotiate is {0}", status); // SMB2 Session Setup status = (NtStatus)mainChannelClient.Smb2SessionSetup( testConfig.SecurityPackageForSmb2UserAuthentication, testConfig.DomainName, testConfig.UserName, testConfig.Password, testConfig.ServerName ); BaseTestSite.Assert.AreEqual<NtStatus>(NtStatus.STATUS_SUCCESS, status, "Status of SMB2 Session Setup is {0}", status); // SMB2 Tree Connect status = (NtStatus)mainChannelClient.Smb2TreeConnect(testConfig.ServerName, testConfig.ShareFolder); BaseTestSite.Assert.AreEqual<NtStatus>(NtStatus.STATUS_SUCCESS, status, "Status of SMB2 Tree Connect is {0}", status); // SMB2 Open File status = (NtStatus)mainChannelClient.Smb2Create(fileName); BaseTestSite.Assert.AreEqual<NtStatus>(NtStatus.STATUS_SUCCESS, status, "Status of SMB2 Create is {0}", status); uint maxWriteSize = mainChannelClient.Smb2MaxWriteSize; content = Encoding.ASCII.GetBytes(Smb2Utility.CreateRandomStringInByte((int)totalWriteSize)); #region SMB2 Write file // Send each write request according SMB2 write file limit uint offset = 0; while (offset < totalWriteSize) { uint length = maxWriteSize; if (offset + length > content.Length) { length = (uint)content.Length - offset; } WRITE_Response writeResponse; status = (NtStatus)mainChannelClient.Smb2Write((UInt64)offset, content, out writeResponse); BaseTestSite.Assert.AreEqual<NtStatus>(NtStatus.STATUS_SUCCESS, status, "Status of SMB2 Write File is {0}", status); BaseTestSite.Assert.AreEqual<uint>((uint)length, writeResponse.Count, "DataLength in WRITE response is {0}", writeResponse.Count); offset += length; } #endregion treeId = mainChannelClient.TreeId; fileId = mainChannelClient.FileId; }
private void ReadFromAlternativeChannel( DialectRevision[] requestDialect, DialectRevision expectedDialect, IPAddress serverIp, IPAddress clientIp, uint lengthRead, uint treeId, FILEID fileId, out string contentRead) { contentRead = ""; alternativeChannelClient.ConnectToServer(TestConfig.UnderlyingTransport, TestConfig.SutComputerName, serverIp, clientIp); #region Negotiate status = alternativeChannelClient.Negotiate( requestDialect, TestConfig.IsSMB1NegotiateEnabled, capabilityValue: Capabilities_Values.GLOBAL_CAP_DFS | Capabilities_Values.GLOBAL_CAP_DIRECTORY_LEASING | Capabilities_Values.GLOBAL_CAP_LARGE_MTU | Capabilities_Values.GLOBAL_CAP_LEASING | Capabilities_Values.GLOBAL_CAP_MULTI_CHANNEL | Capabilities_Values.GLOBAL_CAP_PERSISTENT_HANDLES, clientGuid: clientGuid, checker: (Packet_Header header, NEGOTIATE_Response response) => { BaseTestSite.Assert.AreEqual( Smb2Status.STATUS_SUCCESS, header.Status, "Negotiation should succeed, actually server returns {0}.", Smb2Status.GetStatusCode(header.Status)); TestConfig.CheckNegotiateDialect(expectedDialect, response); if (Smb2Utility.IsSmb3xFamily(expectedDialect)) TestConfig.CheckNegotiateCapabilities(NEGOTIATE_Response_Capabilities_Values.GLOBAL_CAP_MULTI_CHANNEL, response); }); #endregion #region SESSION_SETUP status = alternativeChannelClient.AlternativeChannelSessionSetup( mainChannelClient, TestConfig.DefaultSecurityPackage, TestConfig.SutComputerName, TestConfig.AccountCredential, TestConfig.UseServerGssToken, checker: (header, response) => { }); #endregion if (expectedDialect == DialectRevision.Smb2002 || expectedDialect == DialectRevision.Smb21) { BaseTestSite.Assert.AreEqual( Smb2Status.STATUS_REQUEST_NOT_ACCEPTED, status, "SessionSetup is expected to fail with STATUS_REQUEST_NOT_ACCEPTED."); BaseTestSite.Log.Add( LogEntryKind.Debug, "Dialect " + expectedDialect + " is not supported for multiple channel and fail as expected with STATUS_REQUEST_NOT_ACCEPTED."); } else { BaseTestSite.Assert.AreEqual( Smb2Status.STATUS_SUCCESS, status, "SessionSetup should succeed"); #region READ status = alternativeChannelClient.Read(treeId, fileId, 0, lengthRead, out contentRead); #endregion #region CLOSE file status = alternativeChannelClient.Close(treeId, fileId); #endregion #region TREE_DISCONNECT status = alternativeChannelClient.TreeDisconnect(treeId); #endregion #region LOGOFF status = alternativeChannelClient.LogOff(); #endregion } alternativeChannelClient.Disconnect(); }
/// <summary> /// Read content after failover /// </summary> /// <param name="server">File server name.</param> /// <param name="serverAccessIp">File server access IP.</param> /// <param name="uncSharePath">The share path to read the file.</param> /// <param name="file">The file name for reading content.</param> /// <param name="content">The content to read.</param> /// <param name="clientGuid">Smb2 client Guid.</param> /// <param name="createGuid">The Guid for smb2 create request.</param> /// <returns></returns> protected bool ReadContentAfterFailover(string server, IPAddress serverAccessIp, string uncSharePath, string file, string content, Guid clientGuid, Guid createGuid) { uint status; BaseTestSite.Assert.AreNotEqual( null, serverAccessIp, "Access IP to the file server should not be empty"); BaseTestSite.Log.Add( LogEntryKind.Debug, "Got IP {0} to access the file server", serverAccessIp.ToString()); Smb2FunctionalClient afterFailover = new Smb2FunctionalClient(TestConfig.FailoverTimeout, TestConfig, BaseTestSite); DoUntilSucceed(() => afterFailover.ConnectToServer(TestConfig.UnderlyingTransport, server, serverAccessIp), TestConfig.FailoverTimeout, "Retry to connect to server until succeed within timeout span"); BaseTestSite.Log.Add(LogEntryKind.TestStep, "Client sends NEGOTIATE request with the same clientguid of previous client."); status = afterFailover.Negotiate( TestConfig.RequestDialects, TestConfig.IsSMB1NegotiateEnabled, capabilityValue: Capabilities_Values.GLOBAL_CAP_DFS | Capabilities_Values.GLOBAL_CAP_DIRECTORY_LEASING | Capabilities_Values.GLOBAL_CAP_LARGE_MTU | Capabilities_Values.GLOBAL_CAP_LEASING | Capabilities_Values.GLOBAL_CAP_MULTI_CHANNEL | Capabilities_Values.GLOBAL_CAP_PERSISTENT_HANDLES, clientGuid: clientGuid); if (status != Smb2Status.STATUS_SUCCESS) { BaseTestSite.Log.Add(LogEntryKind.Warning, "Negotiate failed with {0}.", Smb2Status.GetStatusCode(status)); return false; } BaseTestSite.Log.Add(LogEntryKind.TestStep, "Client sends SESSION_SETUP request with the same SESSION_ID of previous client."); status = afterFailover.ReconnectSessionSetup( beforeFailover, TestConfig.DefaultSecurityPackage, server, TestConfig.AccountCredential, TestConfig.UseServerGssToken); if (status != Smb2Status.STATUS_SUCCESS) { BaseTestSite.Log.Add(LogEntryKind.Warning, "ReconnectSessionSetup failed with {0}.", Smb2Status.GetStatusCode(status)); return false; } // Retry TreeConnect because network path may not be available immediately BaseTestSite.Log.Add(LogEntryKind.TestStep, "Client retries TREE_CONNECT to {0} until succeed or timeout in {1} because network path may not be available immediately.", uncSharePath, TestConfig.FailoverTimeout); uint treeId = 0; status = afterFailover.TreeConnect(uncSharePath, out treeId, (header, response) => { }); if (status != Smb2Status.STATUS_SUCCESS) { BaseTestSite.Log.Add(LogEntryKind.Warning, "TreeConnect failed with {0}.", Smb2Status.GetStatusCode(status)); return false; } // Retry Create because file may not be available immediately BaseTestSite.Log.Add(LogEntryKind.TestStep, "Client retries to send CREATE request with SMB2_CREATE_DURABLE_HANDLE_RECONNECT_V2 context with PERSISTENT flag set until succeed or timeout in {0}.", TestConfig.FailoverTimeout); FILEID fileId = new FILEID(); Smb2CreateContextResponse[] serverCreateContexts; status = DoUntilSucceed( () => afterFailover.Create( treeId, file, CreateOptions_Values.FILE_NON_DIRECTORY_FILE, out fileId, out serverCreateContexts, RequestedOplockLevel_Values.OPLOCK_LEVEL_NONE, new Smb2CreateContextRequest[] { new Smb2CreateDurableHandleReconnectV2 { FileId = new FILEID { Persistent = fileId.Persistent }, CreateGuid = createGuid, Flags = CREATE_DURABLE_HANDLE_RECONNECT_V2_Flags.DHANDLE_FLAG_PERSISTENT }, }, checker: (header, response) => { }), TestConfig.FailoverTimeout, "Retry Create until succeed within timeout span"); if (status != Smb2Status.STATUS_SUCCESS) { BaseTestSite.Log.Add(LogEntryKind.Warning, "Create failed with {0}.", Smb2Status.GetStatusCode(status)); return false; } string readContent; BaseTestSite.Log.Add(LogEntryKind.TestStep, "Client sends READ request to read content."); status = afterFailover.Read(treeId, fileId, 0, (uint)content.Length, out readContent); if (status != Smb2Status.STATUS_SUCCESS) { BaseTestSite.Log.Add(LogEntryKind.Warning, "Read failed with {0}.", Smb2Status.GetStatusCode(status)); return false; } BaseTestSite.Assert.IsTrue( content.Equals(readContent), "Content read after failover should be identical to that written before failover"); BaseTestSite.Log.Add(LogEntryKind.TestStep, "Tear down the client by sending the following requests: CLOSE; TREE_DISCONNECT; LOG_OFF"); status = afterFailover.Close(treeId, fileId); status = afterFailover.TreeDisconnect(treeId); status = afterFailover.LogOff(); afterFailover.Disconnect(); return true; }
private void ReadFromAlternativeChannel( IPAddress serverIp, IPAddress clientIp, uint lengthRead, uint treeId, FILEID fileId, out string contentRead) { ReadFromAlternativeChannel( TestConfig.RequestDialects, DialectRevision.Smb30, serverIp, clientIp, lengthRead, treeId, fileId, out contentRead); }
/// <summary> /// Initialize all fields to the default values. /// </summary> private void Initialize() { Flags = testConfig.SendSignedRequest ? Packet_Header_Flags_Values.FLAGS_SIGNED : Packet_Header_Flags_Values.NONE; Dialect = DialectRevision.Smb2Unknown; MessageId = 0; GrantedCredit = 0; SessionKey = null; ServerGssToken = null; unchecked { TreeId = (uint)-1; } SessionId = 0; ParentDirectory = null; File = null; FileId = FILEID.Zero; IsDirectory = false; Locks = null; LockSequence = 0; LeaseState = LeaseStateValues.SMB2_LEASE_NONE; CreateContexts = null; OperationMessageId = 0; Client = new Smb2Client(Timeout); Client.DisableVerifySignature = this.testConfig.DisableVerifySignature; }
private void WriteFromMainChannel( DialectRevision[] requestDialect, DialectRevision expectedDialect, IPAddress serverIp, IPAddress clientIp, string contentWrite, bool isNicRedundantOnServer, out uint treeId, out FILEID fileId) { mainChannelClient.ConnectToServer(TestConfig.UnderlyingTransport, TestConfig.SutComputerName, serverIp, clientIp); #region Negotiate mainChannelClient.Negotiate( requestDialect, TestConfig.IsSMB1NegotiateEnabled, capabilityValue: Capabilities_Values.GLOBAL_CAP_DFS | Capabilities_Values.GLOBAL_CAP_DIRECTORY_LEASING | Capabilities_Values.GLOBAL_CAP_LARGE_MTU | Capabilities_Values.GLOBAL_CAP_LEASING | Capabilities_Values.GLOBAL_CAP_MULTI_CHANNEL | Capabilities_Values.GLOBAL_CAP_PERSISTENT_HANDLES, clientGuid: clientGuid, checker: (Packet_Header header, NEGOTIATE_Response response) => { BaseTestSite.Assert.AreEqual( Smb2Status.STATUS_SUCCESS, header.Status, "Negotiation should succeed, actually server returns {0}.", Smb2Status.GetStatusCode(header.Status)); TestConfig.CheckNegotiateDialect(expectedDialect, response); if (Smb2Utility.IsSmb3xFamily(expectedDialect)) TestConfig.CheckNegotiateCapabilities(NEGOTIATE_Response_Capabilities_Values.GLOBAL_CAP_MULTI_CHANNEL, response); }); #endregion #region SESSION_SETUP mainChannelClient.SessionSetup( TestConfig.DefaultSecurityPackage, TestConfig.SutComputerName, TestConfig.AccountCredential, TestConfig.UseServerGssToken); #endregion #region Retrieve 2nd IP on server for alternative channel if there is if (TestConfig.UnderlyingTransport == Smb2TransportType.Tcp && isNicRedundantOnServer && TestConfig.IsIoCtlCodeSupported(CtlCode_Values.FSCTL_QUERY_NETWORK_INTERFACE_INFO)) { #region TREE_CONNECT to IPC$ string ipcPath = Smb2Utility.GetIPCPath(TestConfig.SutComputerName); mainChannelClient.TreeConnect(ipcPath, out treeId); #endregion #region IOCTL FSCTL_QUERY_NETWORK_INTERFACE_INFO NETWORK_INTERFACE_INFO_Response[] networkInfoResponses; string interfaceAddress; bool secondAddressQueried = false; mainChannelClient.QueryNetworkInterfaceInfo(treeId, out networkInfoResponses); foreach (NETWORK_INTERFACE_INFO_Response netInfoResp in networkInfoResponses) { interfaceAddress = netInfoResp.AddressStorage.Address; if (interfaceAddress != null) { BaseTestSite.Log.Add(LogEntryKind.Debug, "Get NETWORK_INTERFACE_INFO: " + interfaceAddress); if (interfaceAddress == serverIps[1].ToString()) { secondAddressQueried = true; BaseTestSite.Log.Add(LogEntryKind.Debug, "Address queried by IOCTL request with FSCTL_QUERY_NETWORK_INTERFACE_INFO matches server second address {0}", serverIps[1].ToString()); break; } } } BaseTestSite.Assert.IsTrue( secondAddressQueried, "Second address {0} should be queried by IOCTL request with FSCTL_QUERY_NETWORK_INTERFACE_INFO", serverIps[1].ToString()); #endregion } #endregion #region TREE_CONNECT to share string uncSharePath = Smb2Utility.GetUncPath(TestConfig.SutComputerName, TestConfig.BasicFileShare); mainChannelClient.TreeConnect(uncSharePath, out treeId); #endregion #region CREATE Smb2CreateContextResponse[] serverCreateContexts; mainChannelClient.Create( treeId, fileName, CreateOptions_Values.FILE_NON_DIRECTORY_FILE | CreateOptions_Values.FILE_DELETE_ON_CLOSE, out fileId, out serverCreateContexts); #endregion if (Smb2Utility.IsSmb3xFamily(expectedDialect)) { #region WRITE mainChannelClient.Write(treeId, fileId, contentWrite); #endregion } }
private void ReconnectResilientHandle( Smb2FunctionalClient client, Guid clientGuid, string fileName, FILEID fileId, NtStatus expectedReconnectStatus, string message) { uint treeId; ConnectToShare( client, clientGuid, out treeId); BaseTestSite.Log.Add( LogEntryKind.Debug, "Reconnect to resilient handle"); Smb2CreateContextResponse[] createContextResponse; uint status = client.Create( treeId, fileName, CreateOptions_Values.NONE, out fileId, out createContextResponse, createContexts: new Smb2CreateContextRequest[] { new Smb2CreateDurableHandleReconnect() { Data = fileId } }, checker: (header, response) => { // do nothing, skip the exception } ); BaseTestSite.Assert.AreEqual<NtStatus>( expectedReconnectStatus, (NtStatus)status, message); }
private void WriteFromMainChannel( IPAddress serverIp, IPAddress clientIp, string contentWrite, bool isNicRedundantOnServer, out uint treeId, out FILEID fileId) { WriteFromMainChannel( TestConfig.RequestDialects, DialectRevision.Smb30, serverIp, clientIp, contentWrite, isNicRedundantOnServer, out treeId, out fileId); }
/// <summary> /// Reset all member variables before running next test case /// </summary> public override void Reset() { if (firstClient != null) { firstClient.Disconnect(); firstClient = null; } if (secondClient != null) { secondClient.Disconnect(); secondClient = null; } fileName = null; leaseBreakState = LeaseBreakState.NoLeaseBreak; treeId1 = 0; treeId2 = 0; fileId1 = FILEID.Zero; fileId2 = FILEID.Zero; base.Reset(); }
private void PrepareFileForTrimming(out uint treeId, out FILEID fileId) { #region Check Applicability TestConfig.CheckDialect(DialectRevision.Smb30); TestConfig.CheckIOCTL(CtlCode_Values.FSCTL_FILE_LEVEL_TRIM); #endregion client.ConnectToServer(TestConfig.UnderlyingTransport, TestConfig.SutComputerName, TestConfig.SutIPAddress); status = client.Negotiate( TestConfig.RequestDialects, TestConfig.IsSMB1NegotiateEnabled, checker: (Packet_Header header, NEGOTIATE_Response response) => { BaseTestSite.Assert.AreEqual( Smb2Status.STATUS_SUCCESS, header.Status, "CREATE should succeed, actually server returns {0}.", Smb2Status.GetStatusCode(header.Status)); TestConfig.CheckNegotiateDialect(DialectRevision.Smb30, response); }); status = client.SessionSetup( TestConfig.DefaultSecurityPackage, TestConfig.SutComputerName, TestConfig.AccountCredential, TestConfig.UseServerGssToken); status = client.TreeConnect(uncSharePath, out treeId); Smb2CreateContextResponse[] serverCreateContexts; status = client.Create( treeId, fileName, CreateOptions_Values.FILE_NON_DIRECTORY_FILE, out fileId, out serverCreateContexts); status = client.Write(treeId, fileId, contentWrite); status = client.Close(treeId, fileId); status = client.Create( treeId, fileName, CreateOptions_Values.FILE_NON_DIRECTORY_FILE, out fileId, out serverCreateContexts); }
/// <summary> /// Create operation for Open operation /// </summary> private uint OpenCreate( Smb2FunctionalClient client, uint treeIdAfterDisconnection, string fileName, out FILEID fileIdAfterDisconnection, out Smb2CreateContextResponse[] serverCreateContexts, RequestedOplockLevel_Values requestedOplocklevel, Smb2CreateContextRequest[] openContext) { return client.Create( treeIdAfterDisconnection, fileName, CreateOptions_Values.FILE_NON_DIRECTORY_FILE, out fileIdAfterDisconnection, out serverCreateContexts, requestedOplocklevel, openContext, shareAccess: ShareAccess_Values.NONE, checker: (header, response) => { }); }
protected override void TestInitialize() { base.TestInitialize(); smb2client = null; //The SMB2 server MUST reserve -1 for invalid FileId fileId = FILEID.Invalid; // The SMB2 server MUST reserve -1 for invalid TreeId. treeId = 0xFFFF; }
private void ClientTearDown(Smb2FunctionalClient client, uint treeId, FILEID fileId) { status = client.Close(treeId, fileId); status = client.TreeDisconnect(treeId); status = client.LogOff(); }
private void OpenFile( Smb2FunctionalClient client, Guid clientGuid, string fileName, bool isPersistentHandle, out Guid createGuid, out uint treeId, out FILEID fileId) { // connect to share ConnectToShare( client, clientGuid, out treeId); BaseTestSite.Log.Add( LogEntryKind.Debug, "Connect to share '{0}' on scaleout server '{1}'", testConfig.BasicFileShare, testConfig.SutComputerName); #region Construct Create Context List<Smb2CreateContextRequest> createContextList = new List<Smb2CreateContextRequest>(); createGuid = Guid.Empty; if (isPersistentHandle) { // durable handle request context createGuid = Guid.NewGuid(); createContextList.Add(new Smb2CreateDurableHandleRequestV2() { CreateGuid = createGuid, Flags = CREATE_DURABLE_HANDLE_REQUEST_V2_Flags.DHANDLE_FLAG_PERSISTENT, Timeout = 0 // default }); } #endregion // open file Smb2CreateContextResponse[] createContextResponses; client.Create( treeId, fileName, CreateOptions_Values.FILE_NON_DIRECTORY_FILE, out fileId, out createContextResponses, createContexts: createContextList.ToArray<Smb2CreateContextRequest>() ); BaseTestSite.Log.Add( LogEntryKind.Debug, "Create Open with file name '{0}'", fileName); #region check whether Persistent Handle is created successfully with current status if (isPersistentHandle) { BaseTestSite.Assert.IsTrue( CheckDurableCreateContextResponse(createContextResponses), "Create Response should contain Smb2CreateDurableHandleResponseV2."); } #endregion }
/// <summary> /// Disconnect from server. /// Including 3 steps: 1. TreeDisconnect 2. Logoff 3. Tcp disconnection in order. /// </summary> /// <param name="timeout">The pending time to get server's response in step 1 or 2</param> /// <exception cref="System.Net.ProtocolViolationException">Fail to disconnect from server</exception> /// <exception cref="System.InvalidOperationException">The transport is not connected</exception> public override void Disconnect(TimeSpan timeout) { if (this.client == null) { throw new InvalidOperationException("The transport is not connected."); } uint status; // Tree disconnect: Packet_Header header; TREE_DISCONNECT_Response treeDisconnectResponse; status = client.TreeDisconnect( 1, 1, headerFlags, messageId++, sessionId, treeId, out header, out treeDisconnectResponse); if (status != 0) { throw new ProtocolViolationException("Tree Disconnect Failed. ErrorCode: " + status); } // Log off: LOGOFF_Response logoffResponse; status = client.LogOff( 1, 1, headerFlags, messageId++, sessionId, out header, out logoffResponse); if (status != 0) { throw new ProtocolViolationException("Log off Failed. ErrorCode: " + status); } this.client.Disconnect(); fileId = FILEID.Zero; }
private void PrepareTestFile(string fileName, string content, out uint treeId, out FILEID fileId) { client.ConnectToServer(TestConfig.UnderlyingTransport, TestConfig.SutComputerName, TestConfig.SutIPAddress); BaseTestSite.Log.Add(LogEntryKind.TestStep, "Start the client by sending the following requests: NEGOTIATE; SESSION_SETUP; TREE_CONNECT"); client.Negotiate( TestConfig.RequestDialects, TestConfig.IsSMB1NegotiateEnabled, checker: (Packet_Header header, NEGOTIATE_Response response) => { BaseTestSite.Assert.AreEqual( Smb2Status.STATUS_SUCCESS, header.Status, "NEGOTIATE should succeed."); TestConfig.CheckNegotiateDialect(DialectRevision.Smb30, response); }); client.SessionSetup( TestConfig.DefaultSecurityPackage, TestConfig.SutComputerName, TestConfig.AccountCredential, TestConfig.UseServerGssToken); string uncSharePath = Smb2Utility.GetUncPath(TestConfig.SutComputerName, TestConfig.BasicFileShare); client.TreeConnect(uncSharePath, out treeId); BaseTestSite.Log.Add(LogEntryKind.TestStep, "Client writes to the file."); Smb2CreateContextResponse[] serverCreateContexts; client.Create( treeId, fileName, CreateOptions_Values.FILE_NON_DIRECTORY_FILE, out fileId, out serverCreateContexts); client.Write(treeId, fileId, content); // Flush written content to backend storage to avoid cache. client.Flush(treeId, fileId); }
private void SendCreateRequestWithSpecificAppInstanceversion( Smb2FunctionalClient client, Guid appInstanceId, ulong? appInstanceVersionHigh, ulong? appInstanceVersionLow, DialectRevision dialect, uint expectedCreateResponseStatus, out uint treeId, out FILEID fileId ) { #region Client connects to Server BaseTestSite.Log.Add(LogEntryKind.TestStep, "Client connects to the file server by sending the following requests: NEGOTIATE; SESSION_SETUP; TREE_CONNECT"); client.ConnectToServer(TestConfig.UnderlyingTransport, TestConfig.SutComputerName, TestConfig.SutIPAddress, TestConfig.ClientNic1IPAddress); client.Negotiate(Smb2Utility.GetDialects(dialect), TestConfig.IsSMB1NegotiateEnabled); client.SessionSetup( TestConfig.DefaultSecurityPackage, TestConfig.SutComputerName, TestConfig.AccountCredential, TestConfig.UseServerGssToken); client.TreeConnect(uncSharePath, out treeId); Smb2CreateContextResponse[] serverCreateContexts; Smb2CreateAppInstanceVersion appInstanceVersion = new Smb2CreateAppInstanceVersion(); Smb2CreateContextRequest[] clientCreateContexts; if (appInstanceVersionHigh.HasValue && appInstanceVersionLow.HasValue) { appInstanceVersion.AppInstanceVersionHigh = appInstanceVersionHigh.Value; appInstanceVersion.AppInstanceVersionLow = appInstanceVersionLow.Value; clientCreateContexts = new Smb2CreateContextRequest[] { new Smb2CreateAppInstanceId { AppInstanceId = appInstanceId }, appInstanceVersion }; BaseTestSite.Log.Add(LogEntryKind.TestStep, "Client sends CREATE request with AppInstanceVersionHigh = {0}, AppInstanceVersionLow = {1}.", appInstanceVersion.AppInstanceVersionHigh, appInstanceVersion.AppInstanceVersionLow); } else { clientCreateContexts = new Smb2CreateContextRequest[] { new Smb2CreateAppInstanceId { AppInstanceId = appInstanceId } }; BaseTestSite.Log.Add(LogEntryKind.TestStep, "Client sends CREATE request without AppInstanceVersion."); } client.Create( treeId, fileName, CreateOptions_Values.FILE_NON_DIRECTORY_FILE, out fileId, out serverCreateContexts, RequestedOplockLevel_Values.OPLOCK_LEVEL_NONE, clientCreateContexts, shareAccess: ShareAccess_Values.NONE, checker: (header, response) => { BaseTestSite.Assert.AreEqual( expectedCreateResponseStatus, header.Status, (expectedCreateResponseStatus == Smb2Status.STATUS_SUCCESS ? "The open will be closed. Create should succeed. Actually server returns with {0}." : "The open cannot be closed. Create should not succeed. Actually server returns with {0}."), Smb2Status.GetStatusCode(header.Status)); }); #endregion }
/// <summary> /// Read from alternative channel over RDMA /// </summary> /// <param name="content">File content to be compared.</param> /// <param name="lengthRead">Data length to be read.</param> /// <param name="treeId">Tree Connect Id.</param> /// <param name="fileId">File Id.</param> private void ReadFromAlternativeChannel( byte[] content, uint lengthRead, uint treeId, FILEID fileId ) { BaseTestSite.Log.Add(LogEntryKind.TestStep, "Read from alternative channel over RDMA."); BaseTestSite.Log.Add(LogEntryKind.Debug, "ServerRNicIp: " + testConfig.ServerRNicIp); BaseTestSite.Log.Add(LogEntryKind.Debug, "ClientRNicIp: " + testConfig.ClientRNicIp); BaseTestSite.Log.Add(LogEntryKind.Debug, "Data length to be read: " + lengthRead.ToString()); NtStatus status; #region Query Network information NETWORK_INTERFACE_INFO_Response[] networkInterfaceInfos; status = (NtStatus)mainChannelClient.Smb2QueryNetworkInterfaceInfo(out networkInterfaceInfos); BaseTestSite.Assert.AreEqual<NtStatus>( NtStatus.STATUS_SUCCESS, status, "Status of Query Network Interface Info is {0}", status); bool containRdmaNicIPAddress = false; foreach (NETWORK_INTERFACE_INFO_Response networkInterfaceInfo in networkInterfaceInfos) { NETWORK_INTERFACE_INFO_Response_Capabilities capability = networkInterfaceInfo.Capability; capability |= NETWORK_INTERFACE_INFO_Response_Capabilities.RDMA_CAPABLE; if (capability == networkInterfaceInfo.Capability && testConfig.ServerRNicIp.Equals(networkInterfaceInfo.AddressStorage.Address)) { containRdmaNicIPAddress = true; break; } } if (!containRdmaNicIPAddress) { BaseTestSite.Assert.Fail("No RDMA capable network can be found."); } #endregion IPAddress clientIp = IPAddress.Parse(testConfig.ClientRNicIp); status = alternativeChannelClient.ConnectToServerOverRDMA( testConfig.ClientRNicIp, testConfig.ServerRNicIp, testConfig.SmbdTcpPort, clientIp.AddressFamily, testConfig.InboundEntries, testConfig.OutboundEntries, testConfig.InboundReadLimit, testConfig.MaxReceiveSize); BaseTestSite.Assert.AreEqual<NtStatus>( NtStatus.STATUS_SUCCESS, status, "Status of ConnectToServerOverRDMA is {0}", status); // SMBD negotiate SmbdNegotiateResponse response; status = alternativeChannelClient.SmbdNegotiate( SmbdVersion.V1, SmbdVersion.V1, 0, (ushort)testConfig.SendCreditTarget, (ushort)testConfig.ReceiveCreditMax, (uint)testConfig.MaxSendSize, (uint)testConfig.MaxReceiveSize, (uint)testConfig.MaxFragmentedSize, out response ); BaseTestSite.Assert.AreEqual<NtStatus>( NtStatus.STATUS_SUCCESS, status, "Status of SmbdNegotiate is {0}", status); // SMB2 Negotiate DialectRevision[] negotiatedDialects = new DialectRevision[] { DialectRevision.Smb30, DialectRevision.Smb2002, DialectRevision.Smb21 }; DialectRevision selectedDialect; status = (NtStatus)alternativeChannelClient.Smb2Negotiate(negotiatedDialects, out selectedDialect); BaseTestSite.Assert.AreEqual<NtStatus>(NtStatus.STATUS_SUCCESS, status, "Status of SMB2 Negotiate is {0}", status); // SMB2 Session Setup status = (NtStatus)alternativeChannelClient.Smb2AlternativeChannelSessionSetup( mainChannelClient, testConfig.DomainName, testConfig.UserName, testConfig.Password, testConfig.ServerName ); BaseTestSite.Assert.AreEqual<NtStatus>(NtStatus.STATUS_SUCCESS, status, "Status of SMB2 Session Setup is {0}", status); // Set treeId and fileId alternativeChannelClient.TreeId = treeId; alternativeChannelClient.FileId = fileId; // Send each read request according to SMB2 read file limit uint maxReadSize = alternativeChannelClient.Smb2MaxReadSize; uint offset = 0; while (offset < lengthRead) { uint length = maxReadSize; if (offset + length > lengthRead) { length = lengthRead - offset; } // Register Memory for RDMA read byte[] directMemory = new byte[length]; SmbdBufferDescriptorV1 descp; alternativeChannelClient.SmbdRegisterBuffer( length, SmbdBufferReadWrite.RDMA_READ_WRITE_PERMISSION_FOR_WRITE_READ_FILE, testConfig.ReversedBufferDescriptor, out descp); byte[] channelInfo = TypeMarshal.ToBytes<SmbdBufferDescriptorV1>(descp); // Read over RDMA channel READ_Response readResponse; byte[] readData; status = (NtStatus)alternativeChannelClient.Smb2ReadOverRdmaChannel( (UInt64)offset, (uint)length, channelInfo, out readResponse, out readData ); BaseTestSite.Assert.AreEqual<NtStatus>(NtStatus.STATUS_SUCCESS, status, "Status of SMB2 Read File is {0}", status); alternativeChannelClient.SmbdReadRegisteredBuffer(directMemory, descp); BaseTestSite.Assert.IsTrue(SmbdUtilities.CompareByteArray(directMemory, content), "Check file content"); offset += length; } status = (NtStatus)alternativeChannelClient.Smb2CloseFile(); BaseTestSite.Assert.AreEqual<NtStatus>(NtStatus.STATUS_SUCCESS, status, "Status of SMB2 Close file is {0}", status); alternativeChannelClient.Smb2TreeDisconnect(); BaseTestSite.Assert.AreEqual<NtStatus>(NtStatus.STATUS_SUCCESS, status, "Status of SMB2 Tree Disconnect is {0}", status); alternativeChannelClient.Smb2LogOff(); BaseTestSite.Assert.AreEqual<NtStatus>(NtStatus.STATUS_SUCCESS, status, "Status of SMB2 Logoff is {0}", status); }