Exemple #1
0
        /// <summary>
        /// Determine the negotiated MechType that supported by both sides
        /// </summary>
        /// <param name="localMechList">The local MechType list</param>
        /// <param name="remoteMechList">The remote MechType list</param>
        /// <exception cref="ApplicationException">Throw exception if negotiation failed</exception>
        private void Negotiate(MechTypeList localMechList, MechTypeList remoteMechList)
        {
            // remoteList is the first priority to compare
            for (int i = 0; i < remoteMechList.Elements.Length; i++)
            {
                // find in localList
                for (int j = 0; j < localMechList.Elements.Length; j++)
                {
                    // if support current MechType
                    if (ArrayUtility.CompareArrays <int>(remoteMechList.Elements[i].Value,
                                                         localMechList.Elements[j].Value))
                    {
                        this.Context.NegotiatedMechType = localMechList.Elements[j];

                        if (i == 0)
                        {
                            // "i == 0" means it is the perferred MechType of remote endpoint
                            this.Context.NegotiationState = SpngNegotiationState.AcceptIncomplete;
                        }
                        else
                        {
                            this.Context.NegotiationState = SpngNegotiationState.RequestMic;
                        }
                        return;
                    }
                }
            }

            if (this.Context.NegotiatedMechType == null)
            {
                this.Context.NegotiationState = SpngNegotiationState.Reject;
            }
        }
        /// <summary>
        /// Decrypt in aes128-cts-hmac-sha1-96 or aes256-cts-hmac-sha1-96
        /// </summary>
        /// <param name="key">key data</param>
        /// <param name="cipher">cipher data to be decrypted</param>
        /// <param name="usage">key usage number</param>
        /// <param name="aesKeyType">aes key type (128bit/256bit)</param>
        /// <param name="getToBeSignedDateCallback">
        /// A callback to get to-be-signed data.
        /// The method will use decrypted data directly if this parameter is null.
        /// </param>
        /// <returns>the decrypted data</returns>
        public static byte[] Decrypt(
            byte[] key,
            byte[] cipher,
            int usage,
            AesKeyType aesKeyType,
            GetToBeSignedDataFunc getToBeSignedDateCallback)
        {
            // check inputs
            if (null == key)
            {
                throw new ArgumentNullException("key");
            }
            if (null == cipher)
            {
                throw new ArgumentNullException("cipher");
            }

            // the cipher has two parts: encrypted(confounder + plain) + hmac
            byte[] encryptedData = ArrayUtility.SubArray <byte>(
                cipher, 0, cipher.Length - ConstValue.HMAC_HASH_OUTPUT_SIZE);
            byte[] hmacData = ArrayUtility.SubArray <byte>(
                cipher, cipher.Length - ConstValue.HMAC_HASH_OUTPUT_SIZE);

            // use ke key (the encryption key) to decrypt
            byte[] ke            = AesKey.MakeDerivedKey(key, usage, DerivedKeyType.Ke, aesKeyType);
            byte[] initialVector = new byte[ConstValue.AES_BLOCK_SIZE];
            CipherTextStealingMode aesCtsCrypto = CryptoUtility.CreateAesCtsCrypto(ke, initialVector);

            byte[] decryptedData = aesCtsCrypto.DecryptFinal(encryptedData, 0, encryptedData.Length);

            byte[] toBeSignedData;
            if (getToBeSignedDateCallback != null)
            {
                toBeSignedData = getToBeSignedDateCallback(decryptedData);
            }
            else
            {
                toBeSignedData = decryptedData;
            }

            // use ki key (the integrity key) to verify hmac data
            byte[] ki = AesKey.MakeDerivedKey(key, usage, DerivedKeyType.Ki, aesKeyType);
            byte[] expectedHmacData = CryptoUtility.ComputeHmacSha1(ki, toBeSignedData);
            expectedHmacData = ArrayUtility.SubArray <byte>(expectedHmacData, 0, ConstValue.HMAC_HASH_OUTPUT_SIZE);
            if (!ArrayUtility.CompareArrays <byte>(hmacData, expectedHmacData))
            {
                throw new FormatException(
                          "Decryption: failed integrity check in hmac checksum.");
            }

            // remove confounder data
            decryptedData = ArrayUtility.SubArray <byte>(decryptedData, ConstValue.AES_BLOCK_SIZE,
                                                         decryptedData.Length - ConstValue.AES_BLOCK_SIZE);
            return(decryptedData);
        }
        /// <summary>
        /// RC4-HMAC / RC4-HMAC-EXP decryption
        /// </summary>
        /// <param name="key">the secret key</param>
        /// <param name="cipher">the encrypted cipher data</param>
        /// <param name="usage">key usage number</param>
        /// <param name="encryptionType">encryption type</param>
        /// <param name="getToBeSignedDateCallback">
        /// A callback to get to-be-signed data.
        /// The method will use decrypted data directly if this parameter is null.
        /// </param>
        /// <returns>the decrypted data</returns>
        public static byte[] Decrypt(
            byte[] key,
            byte[] cipher,
            int usage,
            EncryptionType encryptionType,
            GetToBeSignedDataFunc getToBeSignedDateCallback)
        {
            // check inputs
            if (null == key)
            {
                throw new ArgumentNullException("key");
            }
            if (null == cipher)
            {
                throw new ArgumentNullException("cipher");
            }

            // get checksum and encrypted data
            byte[] checksum      = ArrayUtility.SubArray(cipher, 0, ConstValue.MD5_CHECKSUM_SIZE);
            byte[] encryptedData = ArrayUtility.SubArray(cipher, ConstValue.MD5_CHECKSUM_SIZE);

            // get salt and hash
            byte[] salt    = GetSalt(usage, encryptionType);
            byte[] hash    = CryptoUtility.ComputeMd5Hmac(key, salt);
            byte[] hashExp = GetExpHash(hash, encryptionType);

            // get rc4 decryption key
            byte[] rc4Key = CryptoUtility.ComputeMd5Hmac(hashExp, checksum);

            // decrypt
            ICryptoTransform decryptor = CryptoUtility.CreateRc4Decryptor(rc4Key);

            byte[] plain = decryptor.TransformFinalBlock(encryptedData, 0, encryptedData.Length);

            byte[] toBeSignedData;
            if (getToBeSignedDateCallback != null)
            {
                toBeSignedData = getToBeSignedDateCallback(plain);
            }
            else
            {
                toBeSignedData = plain;
            }

            // verify checksum
            byte[] expectedChecksum = CryptoUtility.ComputeMd5Hmac(hash, toBeSignedData);
            if (!ArrayUtility.CompareArrays(checksum, expectedChecksum))
            {
                throw new FormatException("Decryption: invalid checksum.");
            }

            // remove confounder
            return(ArrayUtility.SubArray(plain, ConstValue.CONFOUNDER_SIZE));
        }
        /// <summary>
        /// Verify and remove a token header from AP request/response,
        /// wrap token or getmic token.
        /// </summary>
        /// <param name="completeToken">The complete token got from application message.
        /// This argument can be null. If it is null, null will be returned.</param>
        /// <returns>The token body without the header.</returns>
        /// <exception cref="System.FormatException">Throw FormatException if the token header is incorrect.</exception>
        internal static byte[] VerifyGssApiTokenHeader(byte[] completeToken)
        {
            // kerberos oid (1.2.840.113554.1.2.2)
            byte[] oid = ConstValue.KERBEROS_OID;

            if (completeToken == null || completeToken.Length < ConstValue.KERBEROS_OID.Length)
            {
                throw new FormatException("The GSS-API token header is incomplete!");
            }

            if (completeToken[0] != ConstValue.KERBEROS_TAG)
            {
                throw new FormatException("The GSS-API token header is incorrect!");
            }

            int length = 0;
            int index  = 2;  // the tag and length fields

            // If the length value is 128 or more.
            if ((completeToken[1] & 0x80) == 0x80)
            {
                // If the indicated value is 128 or more, it shall be represented in two or more octets,
                // with bit 8 of the first octet set to "1" and the remaining bits of the first octet
                // specifying the number of additional octets. The subsequent octets carry the value,
                // 8 bits per octet, most significant digit first.
                int num = completeToken[1] & 0x7F;
                index += num;

                if (num < 1 || num > 4)
                {
                    throw new FormatException("The GSS-API token length is incorrect!");
                }

                for (int i = 0; i < num; ++i)
                {
                    length = (length << 8) | completeToken[2 + i];
                }
            }
            else
            {
                // If the indicated value is less than 128, it shall be represented in a single octet with bit 8
                // (high order) set to "0" and the remaining bits representing the value. [rfc 2743]
                length = completeToken[1];
            }

            if (!ArrayUtility.CompareArrays(oid, ArrayUtility.SubArray(completeToken, index, oid.Length)))
            {
                throw new FormatException("The GSS-API token oid is incorrect!");
            }

            byte[] tokenBody = ArrayUtility.SubArray(completeToken, index + oid.Length);
            return(tokenBody);
        }
        /// <summary>
        /// DES-CBC-MD5 / DES-CBC-CRC32 decryption
        /// </summary>
        /// <param name="key">the secret key</param>
        /// <param name="cipher">the encrypted cipher data</param>
        /// <param name="encryptionType">encryption type</param>
        /// <param name="getToBeSignedDateCallback">
        /// A callback to get to-be-signed data.
        /// The method will use decrypted data directly if this parameter is null.
        /// </param>
        /// <returns>the decrypted data</returns>
        public static byte[] Decrypt(
            byte[] key,
            byte[] cipher,
            EncryptionType encryptionType,
            GetToBeSignedDataFunc getToBeSignedDateCallback)
        {
            // check inputs
            if (null == key)
            {
                throw new ArgumentNullException("key");
            }
            if (null == cipher)
            {
                throw new ArgumentNullException("cipher");
            }

            // des-cbc decryption
            byte[]           initialVector = GetInitialVector(key, encryptionType);
            ICryptoTransform decryptor     = CryptoUtility.CreateDesCbcDecryptor(key, initialVector, PaddingMode.None);

            byte[] decryptedData = decryptor.TransformFinalBlock(cipher, 0, cipher.Length);

            // get checksum, set checksum field to zeros
            int checksumSize = GetChecksumSize(encryptionType);

            byte[] checksum = ArrayUtility.SubArray <byte>(decryptedData,
                                                           ConstValue.DES_BLOCK_SIZE, checksumSize);
            Array.Clear(decryptedData, ConstValue.DES_BLOCK_SIZE, checksumSize);

            byte[] toBeSignedData;
            if (getToBeSignedDateCallback != null)
            {
                toBeSignedData = getToBeSignedDateCallback(decryptedData);
            }
            else
            {
                toBeSignedData = decryptedData;
            }

            // verify checksum
            byte[] expectedChecksum = CalculateChecksum(toBeSignedData, encryptionType);
            if (!ArrayUtility.CompareArrays <byte>(checksum, expectedChecksum))
            {
                throw new FormatException(
                          "Decryption: inconsistent checksum.");
            }

            // remove confounder and checksum
            decryptedData = ArrayUtility.SubArray <byte>(decryptedData, ConstValue.DES_BLOCK_SIZE + checksumSize);

            return(decryptedData);
        }
Exemple #6
0
 /// <summary>
 /// valid the authenticate message
 /// </summary>
 /// <param name="authenticate">
 /// the authenticate packet of client, contains the challenge response calculated by client
 /// </param>
 /// <param name="expectedNtChallengeResponse">the nt challenge response calculated by server</param>
 /// <param name="expectedLmChallengeResponse">the lm challenge response calculated by server</param>
 private static void ValidAuthenticateMessage(
     NlmpAuthenticatePacket authenticate,
     byte[] expectedNtChallengeResponse, byte[] expectedLmChallengeResponse)
 {
     if (authenticate.Payload.NtChallengeResponseFields.Len == 0 ||
         !ArrayUtility.CompareArrays <byte>(expectedNtChallengeResponse,
                                            authenticate.Payload.NtChallengeResponse))
     {
         if (authenticate.Payload.LmChallengeResponseFields.Len == 0 ||
             !ArrayUtility.CompareArrays <byte>(expectedLmChallengeResponse,
                                                authenticate.Payload.LmChallengeResponse))
         {
             throw new InvalidOperationException("INVALID message error");
         }
     }
 }
        /// <summary>
        /// Read null terminate string
        /// </summary>
        /// <param name="payloadBytes">payload byte array</param>
        /// <param name="offset">reading offset value</param>
        /// <param name="textEncoding">text encoding type</param>
        /// <returns></returns>
        private static string ReadNullTerminateString(
            byte[] payloadBytes,
            ref uint offset,
            Encoding textEncoding
            )
        {
            if (offset >= payloadBytes.Length - 1)
            {
                throw new ArgumentException(
                          "invalid offset value",
                          "offset");
            }

            int readBytes = 0;
            int count     = (int)(payloadBytes.Length - offset);

            byte[]        nullBytes = textEncoding.GetBytes(ApdsUtility.NULL_TERMINATOR_STRING);
            StringBuilder sb        = new StringBuilder();

            using (BinaryReader binaryReader = new BinaryReader(
                       new MemoryStream(payloadBytes, (int)offset, count)))
            {
                while (true)
                {
                    byte[] data = binaryReader.ReadBytes(nullBytes.Length);
                    readBytes += nullBytes.Length;
                    if (data == null)
                    {
                        throw new ArgumentException(
                                  "invalid payload byte arrays",
                                  "payloadBytes");
                    }

                    if (ArrayUtility.CompareArrays <byte>(data, nullBytes))
                    {
                        break;
                    }
                    else
                    {
                        sb.Append(textEncoding.GetString(data));
                    }
                }
            }

            offset = offset + (uint)readBytes;
            return(sb.ToString());
        }
Exemple #8
0
        /// <summary>
        /// Validates the client credential.
        /// </summary>
        /// <param name="sessionKey">the session key negotiated</param>
        /// <param name="negotiateFlags">the negotiation flags</param>
        ///  <param name="clientChallenge">client challenge received</param>
        /// <param name="clientCredentialReceived">the client credential received</param>
        private void ValidateClientCredential(byte[] sessionKey, uint negotiateFlags, byte[] clientChallenge,
                                              _NETLOGON_CREDENTIAL?clientCredentialReceived)
        {
            if (clientCredentialReceived == null || clientCredentialReceived.Value.data == null)
            {
                throw new InvalidOperationException("Client Credential doesn't match");
            }

            byte[] clientCredentialComputed = NrpcUtility.ComputeNetlogonCredential(sessionKey, negotiateFlags,
                                                                                    clientChallenge);

            bool compareResult = ArrayUtility.CompareArrays <byte>(clientCredentialReceived.Value.data,
                                                                   clientCredentialComputed);

            if (!compareResult)
            {
                throw new InvalidOperationException("Client Credential doesn't match");
            }
            StoredCredential = clientCredentialComputed;
        }
Exemple #9
0
        /// <summary>
        /// Convert MechType to SecurityPackage enum
        /// </summary>
        /// <param name="mechType">The MechType value to be convert</param>
        /// <returns>The converted AuthMech enum value</returns>
        public static SecurityPackageType ConvertMechType(MechType mechType)
        {
            SecurityPackageType authType = SecurityPackageType.Unknown;

            if (ArrayUtility.CompareArrays <int>(mechType.Value, SspiLib.Consts.MsKerbOidInt))
            {
                authType = SecurityPackageType.Kerberos;
            }
            else if (ArrayUtility.CompareArrays <int>(mechType.Value, SspiLib.Consts.NlmpOidInt))
            {
                authType = SecurityPackageType.Ntlm;
            }
            else if (ArrayUtility.CompareArrays <int>(mechType.Value, SspiLib.Consts.KerbOidInt))
            {
                authType = SecurityPackageType.Kerberos;
            }
            else if (ArrayUtility.CompareArrays <int>(mechType.Value, SspiLib.Consts.NegoExOidInt))
            {
                authType = SecurityPackageType.Unknown;
            }

            return(authType);
        }
Exemple #10
0
        /// <summary>
        /// Verify the authenticate packet locally
        /// </summary>
        /// <param name="authenticatePacket">actual authenticate packet</param>
        /// <param name="authenticateInformation">expected authenticate information</param>
        /// <param name="exportedSessionKey">exported session key</param>
        /// <returns></returns>
        private ClientAuthenticateInfomation VerifyAuthenticatePacketLocally(
            NlmpAuthenticatePacket authenticatePacket,
            ClientAuthenticateInfomation authenticateInformation,
            out byte[] exportedSessionKey)
        {
            // valid user name
            if (authenticateInformation.UserName.ToUpper() != this.nlmpServer.Context.ClientCredential.AccountName.ToUpper())
            {
                throw new InvalidOperationException(
                          "the user name is invalid!"
                          + " the user name retrieved form authenticate packet is not equal to the context.");
            }

            // calc the basekeys
            byte[] responseKeyLm;
            byte[] expectedNtChallengeResponse;
            byte[] expectedLmChallengeResponse;
            byte[] sessionBaseKey;
            byte[] keyExchangeKey;
            CalculateBaseKeys(
                authenticateInformation.ClientChallenge,
                this.systemTime,
                authenticateInformation.ServerName,
                authenticateInformation.DomainName,
                authenticateInformation.UserName,
                this.nlmpServer.Context.ClientCredential.Password,
                out responseKeyLm, out expectedNtChallengeResponse, out expectedLmChallengeResponse,
                out sessionBaseKey, out keyExchangeKey);

            // valid message
            ValidAuthenticateMessage(authenticatePacket, expectedNtChallengeResponse, expectedLmChallengeResponse);

            // generate keys.
            if (NlmpUtility.IsKeyExch(this.nlmpServer.Context.NegFlg))
            {
                exportedSessionKey = NlmpUtility.RC4(
                    keyExchangeKey, authenticatePacket.Payload.EncryptedRandomSessionKey);
            }
            else
            {
                exportedSessionKey = keyExchangeKey;
            }

            // validate mic
            byte[] messageMic = authenticatePacket.Payload.MIC;
            byte[] zeroMic    = new byte[16];
            if (messageMic != null && !ArrayUtility.CompareArrays <byte>(messageMic, zeroMic))
            {
                AUTHENTICATE_MESSAGE payload = authenticatePacket.Payload;
                payload.MIC = zeroMic;
                authenticatePacket.Payload = payload;

                byte[] mic = NlmpUtility.GetMic(exportedSessionKey, this.negotiate, this.challenge, this.authenticate);

                if (!ArrayUtility.CompareArrays <byte>(messageMic, mic))
                {
                    throw new InvalidOperationException("mic of authenticate packet is invalid");
                }
            }
            return(authenticateInformation);
        }
Exemple #11
0
        /// <summary>
        /// update context on receiving RPCE CO Bind PDU.
        /// </summary>
        /// <param name="bindPdu">Bind PDU to receive.</param>
        internal void UpdateContextOnReceivingBindPdu(RpceCoBindPdu bindPdu)
        {
            this.MaxTransmitFragmentSize = bindPdu.max_xmit_frag;
            this.MaxReceiveFragmentSize  = bindPdu.max_recv_frag;

            if (bindPdu.assoc_group_id != 0)
            {
                this.AssociateGroupId = bindPdu.assoc_group_id;
            }
            else
            {
                if (this.associateGroupIdList.Count == 0)
                {
                    this.AssociateGroupId = bindPdu.assoc_group_id + 1;
                }
                else
                {
                    this.associateGroupIdList.Sort();
                    this.AssociateGroupId = this.associateGroupIdList[this.associateGroupIdList.Count - 1] + 1;
                }
            }

            associateGroupIdList.Add(this.AssociateGroupId);

            if (bindPdu.p_context_elem.p_cont_elem != null &&
                bindPdu.p_context_elem.p_cont_elem.Length > 0)
            {
                this.InterfaceId
                    = bindPdu.p_context_elem.p_cont_elem[0].abstract_syntax.if_uuid;
                this.InterfaceMajorVersion
                    = bindPdu.p_context_elem.p_cont_elem[0].abstract_syntax.if_vers_major;
                this.InterfaceMinorVersion
                    = bindPdu.p_context_elem.p_cont_elem[0].abstract_syntax.if_vers_minor;

                this.NdrVersion = RpceNdrVersion.None;
                this.PresentationContextsTable.Clear();
                for (int i = 0; i < bindPdu.p_context_elem.p_cont_elem.Length; i++)
                {
                    p_cont_elem_t p_cont_elem = bindPdu.p_context_elem.p_cont_elem[i];

                    if (p_cont_elem.transfer_syntaxes == null)
                    {
                        continue;
                    }
                    for (int j = 0; j < p_cont_elem.transfer_syntaxes.Length; j++)
                    {
                        p_syntax_id_t transfer_syntax = p_cont_elem.transfer_syntaxes[j];

                        if (transfer_syntax.if_uuid == RpceUtility.NDR_INTERFACE_UUID
                            &&
                            transfer_syntax.if_vers_major == RpceUtility.NDR_INTERFACE_MAJOR_VERSION
                            &&
                            transfer_syntax.if_vers_minor == RpceUtility.NDR_INTERFACE_MINOR_VERSION)
                        {
                            this.NdrVersion |= RpceNdrVersion.NDR;
                            this.PresentationContextsTable.Add(p_cont_elem.p_cont_id, RpceNdrVersion.NDR);
                        }
                        else if (transfer_syntax.if_uuid == RpceUtility.NDR64_INTERFACE_UUID
                                 &&
                                 transfer_syntax.if_vers_major == RpceUtility.NDR64_INTERFACE_MAJOR_VERSION
                                 &&
                                 transfer_syntax.if_vers_minor == RpceUtility.NDR64_INTERFACE_MINOR_VERSION)
                        {
                            this.NdrVersion |= RpceNdrVersion.NDR64;
                            this.PresentationContextsTable.Add(p_cont_elem.p_cont_id, RpceNdrVersion.NDR64);
                        }
                        else
                        {
                            byte[] uuid = transfer_syntax.if_uuid.ToByteArray();
                            if (ArrayUtility.CompareArrays(
                                    ArrayUtility.SubArray(
                                        uuid,
                                        0,
                                        RpceUtility.BIND_TIME_FEATURE_NEGOTIATION_BITMASK_PREFIX_LENGTH),
                                    ArrayUtility.SubArray(
                                        RpceUtility.BIND_TIME_FEATURE_NEGOTIATION_BITMASK_GUID_BYTES,
                                        0,
                                        RpceUtility.BIND_TIME_FEATURE_NEGOTIATION_BITMASK_PREFIX_LENGTH))
                                &&
                                transfer_syntax.if_vers_major == 1
                                &&
                                transfer_syntax.if_vers_minor == 0)
                            {
                                this.BindTimeFeatureNegotiationBitmask = (RpceBindTimeFeatureNegotiationBitmask)
                                                                         uuid[RpceUtility.BIND_TIME_FEATURE_NEGOTIATION_BITMASK_PREFIX_LENGTH];
                            }
                        }
                    }
                }
            }
        }
        public void BVT_ApplySnapshot()
        {
            BaseTestSite.Log.Add(LogEntryKind.TestStep, "1.	Client opens a shared virtual disk file and expects success.");
            OpenSharedVHD(TestConfig.NameOfSharedVHDS, RSVD_PROTOCOL_VERSION.RSVD_PROTOCOL_VERSION_2);

            BaseTestSite.Log.Add(LogEntryKind.TestStep, "2. Client reads 512 bytes and saves it for later comparation.");
            byte[] byteBeforeChanged = null;
            uint   status            = client.Read(0, 512, out byteBeforeChanged);

            BaseTestSite.Assert.AreEqual(
                (uint)0,
                status,
                "Read Status should be {0}, actual is {1}", GetStatus(0), GetStatus(status));

            Guid snapshotId = Guid.NewGuid();

            BaseTestSite.Log.Add(LogEntryKind.TestStep, "3.	Client creates a snapshot.");
            CreateSnapshot(snapshotId);

            BaseTestSite.Log.Add(LogEntryKind.TestStep, "4.	Client closes the file.");
            client.CloseSharedVirtualDisk();

            BaseTestSite.Log.Add(LogEntryKind.TestStep, "5.	Client reopens the shared virtual disk file and expects success.");

            RequestIdentifier = 0;
            OpenSharedVHD(TestConfig.NameOfSharedVHDS, RSVD_PROTOCOL_VERSION.RSVD_PROTOCOL_VERSION_2);

            BaseTestSite.Log.Add(LogEntryKind.TestStep, "6.	Client sends Write request to change the file and expects success.");
            byte[] payload = Smb2Utility.CreateRandomByteArray(512);
            status = client.Write(0, payload);
            BaseTestSite.Assert.AreEqual(
                (uint)0,
                status,
                "Write Status should be {0}, actual is {1}", GetStatus(0), GetStatus(status));

            BaseTestSite.Log.Add(LogEntryKind.TestStep, "7.	Client sends Apply Snapshot request to apply the previous snapshot.");

            SVHDX_APPLY_SNAPSHOT_PARAMS applySnapshot = new SVHDX_APPLY_SNAPSHOT_PARAMS();

            applySnapshot.SnapshotID   = snapshotId;
            applySnapshot.SnapshotType = Snapshot_Type.SvhdxSnapshotTypeVM;
            SVHDX_META_OPERATION_START_REQUEST startRequest = new SVHDX_META_OPERATION_START_REQUEST();

            startRequest.TransactionId = Guid.NewGuid();
            startRequest.OperationType = Operation_Type.SvhdxMetaOperationTypeApplySnapshot;
            payload = client.CreateTunnelMetaOperationStartApplySnapshotRequest(startRequest, applySnapshot);
            SVHDX_TUNNEL_OPERATION_HEADER?header;
            SVHDX_TUNNEL_OPERATION_HEADER?response;

            status = client.TunnelOperation <SVHDX_TUNNEL_OPERATION_HEADER>(
                true,            //true for Async operation, false for non-async operation
                RSVD_TUNNEL_OPERATION_CODE.RSVD_TUNNEL_META_OPERATION_START,
                ++RequestIdentifier,
                payload,
                out header,
                out response);
            BaseTestSite.Assert.AreEqual(
                (uint)Smb2Status.STATUS_SUCCESS,
                status,
                "Ioctl should succeed, actual status: {0}",
                GetStatus(status));
            VerifyTunnelOperationHeader(header.Value, RSVD_TUNNEL_OPERATION_CODE.RSVD_TUNNEL_META_OPERATION_START, (uint)RsvdStatus.STATUS_SVHDX_SUCCESS, RequestIdentifier);

            BaseTestSite.Log.Add(LogEntryKind.TestStep, "8.	Client rereads 512 bytes and compares it with the previously saved bytes.");
            byte[] byteAfterApplied = null;
            status = client.Read(0, 512, out byteAfterApplied);
            BaseTestSite.Assert.AreEqual(
                (uint)0,
                status,
                "Read Status should be {0}, actual is {1}", GetStatus(0), GetStatus(status));

            bool equal = ArrayUtility.CompareArrays(byteBeforeChanged, byteAfterApplied);

            BaseTestSite.Assert.AreEqual(
                true,
                equal,
                "The bytes after snapshot applied should be the same with the original.");

            BaseTestSite.Log.Add(LogEntryKind.TestStep, "9.	Client deletes the snapshot.");
            DeleteSnapshot(snapshotId);

            BaseTestSite.Log.Add(LogEntryKind.TestStep, "10. Client closes the file.");
            client.CloseSharedVirtualDisk();
        }
Exemple #13
0
        /// <summary>
        /// Verify Server checksum (TD section 2.8.1) and KDC checksum (TD section 2.8.2)
        /// of the PAC message.
        /// </summary>
        /// <param name="serverSignKey">The server signature key used to generate server signature.</param>
        /// <param name="kdcSignKey">The KDC signature key used to generate KDC signature.</param>
        /// <param name="isServerSignValid">true if server signature is valid.</param>
        /// <param name="isKdcSignValid">true if KDC signature is valid.</param>
        /// <exception cref="ArgumentNullException">serverSignkey or kdcSignKey is null.</exception>
        public void ValidateSign(byte[] serverSignKey, byte[] kdcSignKey,
                                 out bool isServerSignValid, out bool isKdcSignValid)
        {
            if (serverSignKey == null)
            {
                throw new ArgumentNullException("serverSignKey");
            }
            if (kdcSignKey == null)
            {
                throw new ArgumentNullException("kdcSignKey");
            }

            // locate server and KDC signatures.
            PacSignatureData serverSign;
            PacSignatureData kdcSign;

            FindSignatures(out serverSign, out kdcSign);

            // these validate operation will change signature values, so must backup and restore.
            byte[] oldServerSign = null;
            byte[] oldKdcSign    = null;

            isServerSignValid = false;
            isKdcSignValid    = false;

            try
            {
                // types
                PAC_SIGNATURE_DATA_SignatureType_Values serverSignType = serverSign.NativePacSignatureData.SignatureType;
                PAC_SIGNATURE_DATA_SignatureType_Values kdcSignType    = kdcSign.NativePacSignatureData.SignatureType;

                // backup and clear signatures.
                int serverLength = PacSignatureData.CalculateSignatureLength(serverSignType);
                oldServerSign = serverSign.NativePacSignatureData.Signature;
                serverSign.NativePacSignatureData.Signature = new byte[serverLength];

                int kdcLength = PacSignatureData.CalculateSignatureLength(kdcSignType);
                oldKdcSign = kdcSign.NativePacSignatureData.Signature;
                kdcSign.NativePacSignatureData.Signature = new byte[kdcLength];

                // validate server sign
                byte[] serverSignResult = PacSignatureData.Sign(
                    ToBytes(), serverSignType, serverSignKey);
                isServerSignValid = ArrayUtility.CompareArrays <byte>(serverSignResult, oldServerSign);

                // validate KDC sign
                byte[] kdcSignResult = PacSignatureData.Sign(
                    serverSignResult, kdcSignType, kdcSignKey);
                isKdcSignValid = ArrayUtility.CompareArrays <byte>(kdcSignResult, oldKdcSign);
            }
            finally
            {
                // restore server signature
                if (oldServerSign != null)
                {
                    serverSign.NativePacSignatureData.Signature = oldServerSign;
                }
                // restore KDC signature
                if (oldKdcSign != null)
                {
                    kdcSign.NativePacSignatureData.Signature = oldKdcSign;
                }
            }
        }