/// <summary> /// Verify FSCTL_SRV_ENUMERATE_SNAPSHOTS Server Response. /// </summary> /// <param name="response">The FSCTL_SRV_ENUMERATE_SNAPSHOTS Server Response.</param> private void VerifyMessageSyntaxFsctlSrvEnumerateSnapshotsRequest( SmbNtTransFsctlSrvEnumerateSnapshotsResponsePacket response) { if (response.NtTransData.snapShotMultiSZ != null) { // // The following statement code will be run only when debugging. // Site.Log.Add(LogEntryKind.Debug, @"Verify MS-SMB_R9403,the length of snapShotMultiSZ is {0}", response.NtTransData.snapShotMultiSZ.Length); // // Verify MS-SMB requirement: MS-SMB_R9403. // // The snapshots take the form "@GMT-YYYY.MM.DD-HH.MM.SS." and are terminated by two additional 16-bit // unicode NULL characters, so one snapshot is 50 bytes.The byte length divide 50 is the number // of returned snapshots. Site.CaptureRequirementIfAreEqual<uint>( (uint)response.NtTransData.snapShotMultiSZ.Length / 50, response.NtTransData.NumberOfSnapShotsReturned, 9403, @"[In FSCTL_SRV_ENUMERATE_SNAPSHOTS Response]NumberOfSnapShotsReturned (4 bytes): This value MUST be the number of snapshots that are returned in this response."); // // The following statement code will be run only when debugging. // Site.Log.Add(LogEntryKind.Debug, @"Verify MS-SMB_R9407,SnapShotMultiSZ:{0}", BitConverter.ToString(response.NtTransData.snapShotMultiSZ)); // // Verify MS-SMB requirement: MS-SMB_R9407. // bool isVerifyR9407 = true; // Check if every snapshot is null-terminated. // One snapshot is 50 bytes, and the last two bytes should be '\0'. for (int i = 0; i < response.NtTransData.NumberOfSnapShotsReturned; ++i) { if (!((response.NtTransData.snapShotMultiSZ[i * 50 + 48] == '\0') && (response.NtTransData.snapShotMultiSZ[i * 50 + 49] == '\0'))) { isVerifyR9407 = false; break; } } Site.CaptureRequirementIfIsTrue( isVerifyR9407, 9407, @"[In FSCTL_SRV_ENUMERATE_SNAPSHOTS Response]SnapShotMultiSZ (variable): Each snapshot MUST be encoded as a NULL-terminated sequence of 16-bit Unicode characters."); // // The following statement code will be run only when debugging. // Site.Log.Add(LogEntryKind.Debug, @"Verify MS-SMB_R9408,snapShotMultisz:{0}", BitConverter.ToString(response.NtTransData.snapShotMultiSZ)); // // Verify MS-SMB requirement: MS-SMB_R9408. // bool isVerifyR9408 = true; // Check if every snapshot takes the form: @GMT-YYYY.MM.DD-HH.MM.SS. for (int i = 0; i < response.NtTransData.NumberOfSnapShotsReturned; ++i) { if (!IsSnapShotValid(response.SnapShots[i])) { isVerifyR9408 = false; break; } } Site.CaptureRequirementIfIsTrue( isVerifyR9408, 9408, @"[In FSCTL_SRV_ENUMERATE_SNAPSHOTS Response]SnapShotMultiSZ (variable): Each snapshot MUST take on the following form: @GMT-YYYY.MM.DD-HH.MM.SS."); // // The following statement code will be run only when debugging. // Site.Log.Add(LogEntryKind.Debug, @"Verify MS-SMB_R9409,SnapShotMultiSZ:{0}", BitConverter.ToString(response.NtTransData.snapShotMultiSZ)); // // Verify MS-SMB requirement: MS-SMB_R9409. // bool isVerifyR9409 = true; // For every 50 snapShotMultiSZ combian composing a snapShot, if snapShot is unicode null // characters, the last 2 snapShotMultiSZ must be '0'. for (int i = 0; i < response.NtTransData.NumberOfSnapShotsReturned; ++i) { if (!((response.NtTransData.snapShotMultiSZ[i * 50 + 48] == '\0') && (response.NtTransData.snapShotMultiSZ[i * 50 + 49] == '\0'))) { isVerifyR9409 = false; break; } } Site.CaptureRequirementIfIsTrue( isVerifyR9409, 9409, @"[In FSCTL_SRV_ENUMERATE_SNAPSHOTS Response]SnapShotMultiSZ (variable): The concatenated list MUST be terminated by two additional 16-bit Unicode NULL characters."); if (response.NtTransData.NumberOfSnapShotsReturned == 0) { // // Verify requirement MS-SMB_R9410 and MS-SMB_R109410 // string isR9410Implementated = Site.Properties.Get("SHOULDMAYR9410Implementation"); bool isR109410Satisfied = (('\0' == response.NtTransData.snapShotMultiSZ[0]) && ('\0' == response.NtTransData.snapShotMultiSZ[1])); if (isWindows) { // // The following statement code will be run only when debugging. // Site.Log.Add(LogEntryKind.Debug, @"Verify MS-SMB_R109410,SnapShotMultiSZ:{0}", BitConverter.ToString(response.NtTransData.snapShotMultiSZ)); // // Verify MS-SMB requirement: MS-SMB_R109410. // Site.CaptureRequirementIfIsTrue( isR109410Satisfied, 109410, @"[In FSCTL_SRV_ENUMERATE_SNAPSHOTS Response]SnapShotMultiSZ (variable): If the response contains no snapshots,then the server sets this field to two 16-bit Unicode NULL characters in Windows."); if (null == isR9410Implementated) { Site.Properties.Add("SHOULDMAYR9410Implementation", Boolean.TrueString); isR9410Implementated = Boolean.TrueString; } } if (null != isR9410Implementated) { bool implemented = Boolean.Parse(isR9410Implementated); bool isSatisfied = isR109410Satisfied; // // The following statement code will be run only when debugging. // Site.Log.Add(LogEntryKind.Debug, @"Verify MS-SMB_R9410,SnapShotMultiSZ:{0}", BitConverter.ToString(response.NtTransData.snapShotMultiSZ)); // // Verify MS-SMB requirement: MS-SMB_R9410. // Site.CaptureRequirementIfAreEqual<Boolean>( implemented, isSatisfied, 9410, String.Format("[In FSCTL_SRV_ENUMERATE_SNAPSHOTS Response]SnapShotMultiSZ (variable): If " + "the response contains no snapshots, then the server SHOULD set this field to two 16-bit " + "Unicode NULL characters. This requirement is {0}implemented", implemented ? "" : "not ")); } } } }
/// <summary> /// Create FSCTL_SRV_ENUMERATE_SNAPSHOTS Response /// </summary> /// <param name="connection">the connection identified the client</param> /// <param name="numberOfSnapShots">This value MUST be the number of snapshots for the volume. </param> /// <param name = "snapShotData"> /// A concatenated set of snapshot names. Each snapshot name MUST be formatted as a null-terminated array of /// 16-bit Unicode characters. The concatenated list MUST be terminated by two 16-bit Unicode NULL characters /// </param> /// <returns>The SmbNtTransFsctlSrvEnumerateSnapshotsResponsePacket </returns> /// <exception cref="ArgumentNullException">connection must not be null</exception> public virtual SmbNtTransFsctlSrvEnumerateSnapshotsResponsePacket CreateFsctlSrvEnumerateSnapshotsResponse( SmbServerConnection connection, uint numberOfSnapShots, params string[] snapShotData) { if (snapShotData == null) { snapShotData = new string[0]; } if (connection == null) { throw new ArgumentNullException("connection"); } SmbNtTransFsctlSrvEnumerateSnapshotsResponsePacket packet = new SmbNtTransFsctlSrvEnumerateSnapshotsResponsePacket(); // get the request packet SmbPacket request = connection.GetRequestPacket(connection.MessageId); // create smb packet header packet.SmbHeader = CifsMessageUtils.CreateSmbHeader( SmbCommand.SMB_COM_NT_TRANSACT, connection.ProcessId, connection.MessageId, request.SmbHeader.Uid, request.SmbHeader.Tid, (SmbFlags)connection.Capability.Flag, (SmbFlags2)connection.Capability.Flags2); // update smb parameters SMB_COM_NT_TRANSACT_SuccessResponse_SMB_Parameters smbParameters = packet.SmbParameters; // reserved 3 bytes. smbParameters.Reserved1 = new byte[3]; smbParameters.Setup = new ushort[0]; smbParameters.WordCount = (byte)(CifsMessageUtils.GetSize<SMB_COM_NT_TRANSACT_SuccessResponse_SMB_Parameters>( smbParameters) / SmbCapability.NUM_BYTES_OF_WORD); // update smb data SMB_COM_NT_TRANSACT_SuccessResponse_SMB_Data smbData = packet.SmbData; // update trans2 data NT_TRANSACT_ENUMERATE_SNAPSHOTS_Response_NT_Trans_Data ntTransData = packet.NtTransData; ntTransData.NumberOfSnapShots = numberOfSnapShots; ntTransData.NumberOfSnapShotsReturned = (uint)snapShotData.Length; // initiallize to zero ntTransData.SnapShotArraySize = 0x00; ntTransData.snapShotMultiSZ = new byte[ntTransData.SnapShotArraySize]; // update snapshots packet.SnapShots = new Collection<string>(snapShotData); // store the parameters and data to packet. packet.NtTransData = ntTransData; packet.SmbParameters = smbParameters; packet.SmbData = smbData; packet.UpdateCountAndOffset(); return packet; }
private void VerifyReceiveFsctlSrvEnumerateSnapshotsFunctionCode( SmbNtTransFsctlSrvEnumerateSnapshotsResponsePacket response, int expectedSnapShotsCount, int expectedSnapshotsReturnedCount, bool isMaxDataCountLargeEnough) { // // The following statement code will be run only when debugging. // Site.Log.Add(LogEntryKind.Debug, @"Verify MS-SMB_R2437"); // // Verify MS-SMB requirement: MS-SMB_R2437. // // The total number of previous versions can't be got. Site.CaptureRequirementIfAreEqual<uint>( (uint)response.SnapShots.Count, response.NtTransData.NumberOfSnapShotsReturned, 2437, @"The NumberOfSnapshots MUST contain the total number of previous versions that are available for the volume, and NumberOfSnapshotsReturned contains the number of entries that are returned in this enumeration."); // isMaxDataCountLargeEnough means if MaxDataCount is large enough. if (!isMaxDataCountLargeEnough) { // // Verify requirement MS-SMB_R4980 and MS-SMB_R4981 // string isR4980Implementated = Site.Properties.Get("SHOULDMAYR4980Implementation"); // NumberOfSnapShotsReturned is the number of returned entries. bool isR4981Satisfied = (0 == response.NtTransData.NumberOfSnapShotsReturned); if (isWindows) { // // The following statement code will be run only when debugging. // Site.Log.Add(LogEntryKind.Debug, @"Verify MS-SMB_R4981,NumberOfSnapShotsReturned:{0}", response.NtTransData.NumberOfSnapShotsReturned); // // Verify MS-SMB requirement: MS-SMB_R4981. // Site.CaptureRequirementIfIsTrue( isR4981Satisfied, 4981, @"[In Receiving an FSCTL_SRV_ENUMERATE_SNAPSHOTS Function Code]If MaxDataCount is not large enough to hold all of the entries,then the server does return zero entries in windows."); if (null == isR4980Implementated) { Site.Properties.Add("SHOULDMAYR4980Implementation", Boolean.TrueString); isR4980Implementated = Boolean.TrueString; } } if (null != isR4980Implementated) { bool implemented = Boolean.Parse(isR4980Implementated); bool isSatisfied = isR4981Satisfied; // // The following statement code will be run only when debugging. // Site.Log.Add(LogEntryKind.Debug, @"Verify MS-SMB_R4980,NumberOfSnapShotsReturned:{0}", response.NtTransData.NumberOfSnapShotsReturned); // // Verify MS-SMB requirement: MS-SMB_R4980. // Site.CaptureRequirementIfAreEqual<Boolean>( implemented, isSatisfied, 4980, String.Format("[In Receiving an FSCTL_SRV_ENUMERATE_SNAPSHOTS Function Code]If " + "MaxDataCount is not large enough to hold all of the entries,then the server SHOULD return " + "zero entry. This requirement is {0}implemented", implemented ? "" : "not ")); } } if (response.NtTransData.snapShotMultiSZ != null) { // // The following statement code will be run only when debugging. // Site.Log.Add(LogEntryKind.Debug, @"Verify MS-SMB_R4982"); // // Verify MS-SMB requirement: MS-SMB_R4982. // // The available previous versions are stored in the SnapShotMultiSZ. Once the snapShotArraySize is // equal to the length of SnapShotMultiSZ, this requirement is verified. Site.CaptureRequirementIfAreEqual<int>( response.NtTransData.snapShotMultiSZ.Length, (int)response.NtTransData.SnapShotArraySize, 4982, @"[In Receiving an FSCTL_SRV_ENUMERATE_SNAPSHOTS Function Code]The value returned in SnapShotArraySize MUST be the size required to receive all of the available previous versions."); // // The following statement code will be run only when debugging. // Site.Log.Add(LogEntryKind.Debug, @"Verify MS-SMB_R2436,NumberOfSnapShotsReturned:{0}", response.NtTransData.NumberOfSnapShotsReturned); // // Verify MS-SMB requirement: MS-SMB_R2436. // // NumberOfSnapShotsReturned contains the number of entries that are returned in the enumeration. bool isVerifyR2436 = response.NtTransData.NumberOfSnapShotsReturned >= 0; Site.CaptureRequirementIfIsTrue( isVerifyR2436, 2436, @"[In Receiving an FSCTL_SRV_ENUMERATE_SNAPSHOTS Function Code] The server MUST return an enumeration of available previous versions, as specified in section 2.2.7.2.2."); } }
/// <summary> /// Deep copy constructor. /// </summary> public SmbNtTransFsctlSrvEnumerateSnapshotsResponsePacket( SmbNtTransFsctlSrvEnumerateSnapshotsResponsePacket packet) : base(packet) { }
/// <summary> /// create the nt transaction packet /// </summary> /// <param name="request">the request packet</param> /// <param name="smbHeader">the smb header of response packet</param> /// <param name="channel">the channel contains the packet bytes</param> /// <returns>the response packet</returns> private SmbPacket CreateNtTransactionResponsePacket(SmbPacket request, SmbHeader smbHeader, Channel channel) { SmbPacket smbPacket = null; if (smbHeader.Status == 0 && channel.Peek<byte>(0) == 0 && channel.Peek<ushort>(1) == 0) { return smbPacket; } SmbNtTransactRequestPacket ntTransactRequest = request as SmbNtTransactRequestPacket; if (ntTransactRequest == null) { return smbPacket; } // find regular packet switch ((uint)ntTransactRequest.SmbParameters.Function) { case (uint)NtTransSubCommand.NT_TRANSACT_RENAME: smbPacket = new SmbNtTransRenameResponsePacket(); break; case (uint)NtTransSubCommand.NT_TRANSACT_CREATE: smbPacket = new SmbNtTransactCreateResponsePacket(); break; case (uint)NtTransSubCommand.NT_TRANSACT_IOCTL: NT_TRANSACT_IOCTL_SETUP setup = CifsMessageUtils.ToStuct<NT_TRANSACT_IOCTL_SETUP>( CifsMessageUtils.ToBytesArray<ushort>(ntTransactRequest.SmbParameters.Setup)); switch ((NtTransFunctionCode)setup.FunctionCode) { case NtTransFunctionCode.FSCTL_SRV_ENUMERATE_SNAPSHOTS: smbPacket = new SmbNtTransFsctlSrvEnumerateSnapshotsResponsePacket(); break; case NtTransFunctionCode.FSCTL_SRV_REQUEST_RESUME_KEY: smbPacket = new SmbNtTransFsctlSrvRequestResumeKeyResponsePacket(); break; case NtTransFunctionCode.FSCTL_SRV_COPYCHUNK: smbPacket = new SmbNtTransFsctlSrvCopyChunkResponsePacket(); break; default: smbPacket = new SmbNtTransactIoctlResponsePacket(); break; } break; case (uint)SmbNtTransSubCommand.NT_TRANSACT_QUERY_QUOTA: smbPacket = new SmbNtTransQueryQuotaResponsePacket(); break; case (uint)SmbNtTransSubCommand.NT_TRANSACT_SET_QUOTA: smbPacket = new SmbNtTransSetQuotaResponsePacket(); break; default: break; } return smbPacket; }
/// <summary> /// create the nt transaction packet /// </summary> /// <param name="request">the request packet</param> /// <param name="smbHeader">the smb header of response packet</param> /// <param name="channel">the channel contains the packet bytes</param> /// <returns>the response packet</returns> private SmbPacket CreateNtTransactionResponsePacket(SmbPacket request, SmbHeader smbHeader, Channel channel) { SmbPacket smbPacket = null; if (smbHeader.Status == 0 && channel.Peek <byte>(0) == 0 && channel.Peek <ushort>(1) == 0) { return(smbPacket); } SmbNtTransactRequestPacket ntTransactRequest = request as SmbNtTransactRequestPacket; if (ntTransactRequest == null) { return(smbPacket); } // find regular packet switch ((uint)ntTransactRequest.SmbParameters.Function) { case (uint)NtTransSubCommand.NT_TRANSACT_RENAME: smbPacket = new SmbNtTransRenameResponsePacket(); break; case (uint)NtTransSubCommand.NT_TRANSACT_CREATE: smbPacket = new SmbNtTransactCreateResponsePacket(); break; case (uint)NtTransSubCommand.NT_TRANSACT_IOCTL: NT_TRANSACT_IOCTL_SETUP setup = CifsMessageUtils.ToStuct <NT_TRANSACT_IOCTL_SETUP>( CifsMessageUtils.ToBytesArray <ushort>(ntTransactRequest.SmbParameters.Setup)); switch ((NtTransFunctionCode)setup.FunctionCode) { case NtTransFunctionCode.FSCTL_SRV_ENUMERATE_SNAPSHOTS: smbPacket = new SmbNtTransFsctlSrvEnumerateSnapshotsResponsePacket(); break; case NtTransFunctionCode.FSCTL_SRV_REQUEST_RESUME_KEY: smbPacket = new SmbNtTransFsctlSrvRequestResumeKeyResponsePacket(); break; case NtTransFunctionCode.FSCTL_SRV_COPYCHUNK: smbPacket = new SmbNtTransFsctlSrvCopyChunkResponsePacket(); break; default: smbPacket = new SmbNtTransactIoctlResponsePacket(); break; } break; case (uint)SmbNtTransSubCommand.NT_TRANSACT_QUERY_QUOTA: smbPacket = new SmbNtTransQueryQuotaResponsePacket(); break; case (uint)SmbNtTransSubCommand.NT_TRANSACT_SET_QUOTA: smbPacket = new SmbNtTransSetQuotaResponsePacket(); break; default: break; } return(smbPacket); }