Beispiel #1
0
        public void HasNullHashBeforeClosingAndFinishedReadingInReadMode()
        {
            // Arrange
            var hashing = new HashingStream(new MemoryStream(), SHA1.Create(), true);

            // Act, Assert
            hashing.Hash.Should().BeNull();
        }
Beispiel #2
0
            /// <summary>
            /// Prefixes the data then signs it.
            /// </summary>
            /// <param name="signingStream">The signing stream.</param>
            /// <param name="extra">The extra data passed by prefixData.</param>
            protected override void PrefixDataSign(HashingStream signingStream, object extra)
            {
                base.PrefixDataSign(signingStream, extra);
                var expiration = FromDateTime((DateTime)extra);
                var buffer     = Utility.GetBytes(expiration);

                signingStream.Write(buffer, 0, buffer.Length);
            }
Beispiel #3
0
        public void HasNullHashBeforeClosingInWriteMode()
        {
            // Arrange
            var hashing = new HashingStream(new MemoryStream(), SHA1.Create(), false);

            // Act, Assert
            hashing.Hash.Should().BeNull();
        }
Beispiel #4
0
        public void CannotWriteForWriteMode()
        {
            // Arrange
            var hashing = new HashingStream(new MemoryStream(), SHA1.Create(), false);

            // Act, Assert
            Action action = () => hashing.Read(new byte[1], 0, 1);

            action.ShouldThrow <NotSupportedException>().Which.Message.Should().Be("The hashing stream is configured to write, not read.");
        }
Beispiel #5
0
        public void HasHashAfterFinishedReadingInReadMode()
        {
            // Arrange
            var hashing = new HashingStream(new MemoryStream(new byte[0]), SHA1.Create(), true);

            // Act
            var read = hashing.Read(new byte[1], 0, 1);

            // Assert
            read.Should().Be(0);
            hashing.Hash.Should().NotBeNull();
            GetHash(hashing.Hash).Should().Be("DA39A3EE5E6B4B0D3255BFEF95601890AFD80709");
        }
Beispiel #6
0
        private byte[] GetIndexHash()
        {
            if (this.shouldHashIndex)
            {
                using (Stream fileStream = new FileStream(this.indexLockPath, FileMode.Open, FileAccess.Read, FileShare.Write))
                    using (HashingStream hasher = new HashingStream(fileStream))
                    {
                        hasher.CopyTo(Stream.Null);
                        return(hasher.Hash);
                    }
            }

            return(new byte[20]);
        }
Beispiel #7
0
        public void HashesPartialReadInReadMode()
        {
            // Arrange
            var inner   = new MemoryStream(Encoding.ASCII.GetBytes("foobar"));
            var hashing = new HashingStream(inner, SHA1.Create(), true);
            var buffer  = new byte[3];

            // Act
            var read = hashing.Read(buffer, 0, 3);

            hashing.Close();

            // Assert
            read.Should().Be(3);
            GetHash(hashing.Hash).Should().Be("0BEEC7B5EA3F0FDBC95D0DD47F3C5BC275DA8A33");
        }
Beispiel #8
0
        public void GeneratesHashWhileWriting(HashAlgorithm hashAlgorithm, string expectedContent, int bufferSize, string expectedHash)
        {
            // Arrange
            var inner   = new MemoryStream();
            var hashing = new HashingStream(inner, hashAlgorithm, false);

            // Act
            using (var writer = new StreamWriter(hashing, Encoding.ASCII, bufferSize))
            {
                writer.Write(expectedContent);
            }

            // Assert
            var actualContent = Encoding.ASCII.GetString(inner.ToArray());

            actualContent.Should().Be(expectedContent);
            var actualHash = GetHash(hashing.Hash);

            actualHash.Should().Be(expectedHash);
        }
Beispiel #9
0
        public void GeneratesHashWhileReading(HashAlgorithm hashAlgorithm, string expectedContent, int bufferSize, string expectedHash)
        {
            // Arrange
            var inner   = new MemoryStream(Encoding.ASCII.GetBytes(expectedContent));
            var hashing = new HashingStream(inner, hashAlgorithm, true);

            // Act
            string actualContent;

            using (var reader = new StreamReader(hashing, Encoding.ASCII, false, bufferSize))
            {
                actualContent = reader.ReadToEnd();
            }

            // Assert
            actualContent.Should().Be(expectedContent);
            var actualHash = GetHash(hashing.Hash);

            actualHash.Should().Be(expectedHash);
        }
        private void thread()
        {
            while (true)
            {
                try
                {
                    // Hash metadata of everything in StaticPath
                    var hashStream = new HashingStream(new VoidStream(), MD5.Create()); // no need to dispose of it
                    var writer     = new BinaryWriter(hashStream);
                    foreach (var path in new PathManager(StaticPath).GetFiles().OrderBy(f => f.FullName))
                    {
                        writer.Write(path.FullName);
                        writer.Write(path.Length);
                        writer.Write(path.LastWriteTimeUtc.ToBinary());
                    }
                    var hash = hashStream.Hash.ToHex();

                    SendUpdate(new ReloadDto {
                        ValidUntilUtc = DateTime.UtcNow.AddYears(10), StaticFilesHash = hash
                    });

                    // Sleep until we observe a change, but rescan fully every N minutes even we didn't see any changes
                    var minimumWait = DateTime.UtcNow.AddSeconds(2);
                    var watcher     = new FileSystemWatcher();
                    watcher.IncludeSubdirectories = true;
                    watcher.Path = StaticPath;
                    watcher.WaitForChanged(WatcherChangeTypes.All, 20 * 60 * 1000);
                    // Enforce a minimum wait time in case the watcher breaks and starts firing endlessly for whatever reason
                    if (DateTime.UtcNow < minimumWait)
                    {
                        Thread.Sleep(minimumWait - DateTime.UtcNow);
                    }
                }
                catch
                {
                    Thread.Sleep(TimeSpan.FromSeconds(60));
                }
            }
        }
Beispiel #11
0
 /// <summary>
 /// Postfixes the data then signs it.
 /// </summary>
 /// <param name="signingStream">The signing stream.</param>
 /// <param name="extra">The extra data passed by postfixData.</param>
 protected virtual void PostfixDataSign(HashingStream signingStream, object extra)
 {
     signingStream.Write(FormatBytes, 0, FormatBytes.Length);
 }
Beispiel #12
0
 /// <summary>
 /// Prefixes the data then signs it.
 /// </summary>
 /// <param name="signingStream">The signing stream.</param>
 /// <param name="extra">The extra data passed by prefixData.</param>
 protected virtual void PrefixDataSign(HashingStream signingStream, object extra)
 {
 }
Beispiel #13
0
 /// <summary>
 /// Postfixes the data then signs it.
 /// </summary>
 /// <param name="signingStream">The signing stream.</param>
 /// <param name="extra">The extra data passed by postfixData.</param>
 protected override void PostfixDataSign(HashingStream signingStream, object extra)
 {
 }
Beispiel #14
0
        private async Task <Possible <IReadOnlyList <ContentHash> > > TryGetBuildManifestHashFromLocalFileAsync(string fullFilePath, ContentHash hash, IList <HashType> requestedTypes, int retryAttempt = 0)
        {
            Contract.Assert(requestedTypes.Count > 0, "Must request at least one hash type");
            var result = new List <ContentHash>();

            if (retryAttempt >= GetBuildManifestHashFromLocalFileRetryLimit)
            {
                string message = $"GetBuildManifestHashFromLocalFileRetryLimit exceeded at path '{fullFilePath}'";
                Tracing.Logger.Log.ApiServerForwardedIpcServerMessage(m_loggingContext, "BuildManifest", message);
                return(new Failure <string>(message));
            }

            if (retryAttempt > 0)
            {
                await Task.Delay(TimeSpan.FromMilliseconds(Math.Pow(2, retryAttempt) * GetBuildManifestHashFromLocalFileRetryMultiplierMs));
            }

            if (!File.Exists(fullFilePath))
            {
                Tracing.Logger.Log.ApiServerForwardedIpcServerMessage(m_loggingContext, "BuildManifest", $"Local file not found at path '{fullFilePath}' while computing BuildManifest Hash. Trying other methods to obtain hash.");
                return(new Failure <string>($"File doesn't exist: '{fullFilePath}'"));
            }

            var           hashers          = new HashingStream[requestedTypes.Count - 1];
            HashingStream validationStream = null;

            try
            {
                using var fs = FileUtilities.CreateFileStream(fullFilePath, FileMode.Open, FileAccess.Read, FileShare.Delete | FileShare.Read, FileOptions.SequentialScan).AssertHasLength();

                // If enabled, create a hashing stream for content validation. Using HashType.Unknown uses the default hashtype
                validationStream = m_verifyFileContentOnBuildManifestHashComputation ? ContentHashingUtilities.GetContentHasher(HashType.Unknown).CreateReadHashingStream(fs) : null;

                // Create a series of nested ReadHashingStream so we compute all the hashes in parallel
                StreamWithLength outerStream = validationStream?.AssertHasLength() ?? fs;
                for (var i = 0; i < hashers.Length; i++)
                {
                    // Hashers has size (requestedTypes.Count - 1)
                    // requestedTypes[0] will be used to hash+consume the resulting outerStream (see below)
                    var hashType = requestedTypes[i + 1];
                    hashers[i]  = ContentHashingUtilities.GetContentHasher(hashType).CreateReadHashingStream(outerStream);
                    outerStream = hashers[i].AssertHasLength();
                }

                // Hashing the outermost stream will cause all the nested hashers to also do their processing
                var firstManifestHash = await ContentHashingUtilities.HashContentStreamAsync(outerStream, requestedTypes[0]);

                result.Add(firstManifestHash);

                for (int i = 0; i < hashers.Length; i++)
                {
                    result.Add(hashers[i].GetContentHash());
                }

                if (m_verifyFileContentOnBuildManifestHashComputation)
                {
                    var actualHash = validationStream.GetContentHash();
                    if (hash != actualHash)
                    {
                        return(new Failure <string>($"Unexpected file content during build manifest hash computation. Path: '{fullFilePath}', expected hash '{hash}', actual hash '{actualHash}'."));
                    }
                }
            }
            catch (Exception ex) when(ex is BuildXLException || ex is IOException)
            {
                Tracing.Logger.Log.ApiServerForwardedIpcServerMessage(m_loggingContext, "BuildManifest",
                                                                      $"Local file found at path '{fullFilePath}' but threw exception while computing BuildManifest Hash. Retry attempt {retryAttempt} out of {GetBuildManifestHashFromLocalFileRetryLimit}. Exception: {ex}");
                return(await TryGetBuildManifestHashFromLocalFileAsync(fullFilePath, hash, requestedTypes, retryAttempt + 1));
            }
            finally
            {
                validationStream?.Dispose();
                for (var i = 0; i < hashers.Length; i++)
                {
                    hashers[i]?.Dispose();
                }
            }

            return(result);
        }