Ejemplo n.º 1
0
        public unsafe void RavenDB_15975()
        {
            using (var options = StorageEnvironmentOptions.ForPath(DataDir))
            {
                options.Encryption.MasterKey = Sodium.GenerateRandomBuffer((int)Sodium.crypto_aead_xchacha20poly1305_ietf_keybytes());

                using (var innerPager = LinuxTestUtils.GetNewPager(options, DataDir, "Raven.Voron"))
                {
                    AbstractPager cryptoPager;
                    using (cryptoPager = new CryptoPager(innerPager))
                    {
                        using (var tx = new TempPagerTransaction(isWriteTransaction: true))
                        {
                            var overflowSize = 4 * Constants.Storage.PageSize + 100;

                            cryptoPager.EnsureContinuous(26, 5);
                            var pagePointer = cryptoPager.AcquirePagePointerForNewPage(tx, 26, 5);

                            var header = (PageHeader *)pagePointer;
                            header->PageNumber   = 26;
                            header->Flags        = PageFlags.Overflow;
                            header->OverflowSize = overflowSize;

                            Memory.Set(pagePointer + PageHeader.SizeOf, (byte)'X', overflowSize);
                        }


                        using (var tx = new TempPagerTransaction())
                        {
                            var pagePointer = cryptoPager.AcquirePagePointer(tx, 26);

                            // Making sure that the data was decrypted and still holds those 'X' chars
                            Assert.True(pagePointer[PageHeader.SizeOf] == 'X');
                            Assert.True(pagePointer[666] == 'X');
                            Assert.True(pagePointer[1039] == 'X');
                        }
                    }
                }
            }
        }
Ejemplo n.º 2
0
        public unsafe void WriteAndReadPageUsingCryptoPager()
        {
            using (var options = StorageEnvironmentOptions.ForPath(DataDir))
            {
                options.Encryption.MasterKey = Sodium.GenerateRandomBuffer((int)Sodium.crypto_aead_xchacha20poly1305_ietf_keybytes());

                using (var innerPager = LinuxTestUtils.GetNewPager(options, DataDir, "Raven.Voron"))
                {
                    AbstractPager cryptoPager;
                    using (cryptoPager = new CryptoPager(innerPager))
                    {
                        using (var tx = new TempPagerTransaction(isWriteTransaction: true))
                        {
                            cryptoPager.EnsureContinuous(17, 1); // We're gonna try to read and write to page 17
                            var pagePointer = cryptoPager.AcquirePagePointerForNewPage(tx, 17, 1);

                            var header = (PageHeader *)pagePointer;
                            header->PageNumber = 17;
                            header->Flags      = PageFlags.Single | PageFlags.FixedSizeTreePage;

                            Memory.Set(pagePointer + PageHeader.SizeOf, (byte)'X', Constants.Storage.PageSize - PageHeader.SizeOf);
                        }

                        using (var tx = new TempPagerTransaction())
                        {
                            var pagePointer = cryptoPager.AcquirePagePointer(tx, 17);

                            // Making sure that the data was decrypted and still holds those 'X' chars
                            Assert.True(pagePointer[PageHeader.SizeOf] == 'X');
                            Assert.True(pagePointer[666] == 'X');
                            Assert.True(pagePointer[1039] == 'X');
                        }
                    }
                }
            }
        }
Ejemplo n.º 3
0
        public StreamInfo?GetStreamInfoForReporting(Slice key, out string tag)
        {
            tag = null;

            if (TryGetLastChunkDetailsForStream(key, out var lastChunk) == false)
            {
                return(null);
            }

            var canRemovePage = CanRemovePage(lastChunk.PageNumber);
            var page          = _llt.GetPage(lastChunk.PageNumber);

            try
            {
                var info = (StreamInfo *)(page.DataPointer + lastChunk.ChunkSize);
                tag = GetStreamTag(info);

                return(new StreamInfo
                {
                    TagSize = info->TagSize,
                    TotalSize = info->TotalSize,
                    Version = info->Version
                });
            }
            finally
            {
                RemovePage();
            }

            bool CanRemovePage(long pageNumber)
            {
                // this methods checks if page was not used elsewhere prior executing GetStreamInfoForReporting method
                // if yes then we cannot remove it to avoid releasing used memory

                var lltState = (IPagerLevelTransactionState)_llt;
                var states   = lltState.CryptoPagerTransactionState;

                if (states == null)
                {
                    return(false); // not encrypted
                }
                if (states.Count == 0)
                {
                    return(true); // no states yet
                }
                foreach (var kvp in states)
                {
                    var pagerStates = kvp.Value;
                    if (pagerStates.TryGetValue(pageNumber, out _))
                    {
                        return(false);
                    }
                }

                return(true);
            }

            void RemovePage()
            {
                if (canRemovePage == false)
                {
                    return;
                }

                var lltState = (IPagerLevelTransactionState)_llt;
                var states   = lltState.CryptoPagerTransactionState;

                if (states == null || states.Count == 0)
                {
                    return;
                }

                foreach (var kvp in states)
                {
                    var pager       = kvp.Key;
                    var pagerStates = kvp.Value;
                    if (pagerStates.TryGetValue(page.PageNumber, out var buffer) == false)
                    {
                        continue;
                    }

                    if (buffer.Pointer != page.Pointer)
                    {
                        continue;
                    }

                    if (CryptoPager.CanReturnBuffer(buffer) == false)
                    {
                        return;
                    }

                    _llt._pageLocator.Reset(page.PageNumber);
                    pagerStates.RemoveBuffer(page.PageNumber);

                    var cryptoPager = (CryptoPager)pager;
                    cryptoPager.ReturnBuffer(buffer);
                    return;
                }
            }
        }