MalwareSourceCode/MSIL/Virus/Win32/E/Virus.Win32.Expiro.w-f8f9f26e940480624825f6bddbea86e70fc4aa746c4dd8efa7d98dcb477000ed/Microsoft/InfoCards/FileDataSource.cs
2022-08-18 06:28:56 -05:00

1063 lines
41 KiB
C#

// Decompiled with JetBrains decompiler
// Type: Microsoft.InfoCards.FileDataSource
// Assembly: infocard, Version=3.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089
// MVID: 1D4D5564-A025-490C-AF1D-DF4FBB709D1F
// Assembly location: C:\Users\Administrateur\Downloads\Virusshare-00001-msil\Virus.Win32.Expiro.w-f8f9f26e940480624825f6bddbea86e70fc4aa746c4dd8efa7d98dcb477000ed.exe
using Microsoft.InfoCards.Diagnostics;
using System;
using System.Collections;
using System.ComponentModel;
using System.IO;
using System.Runtime.InteropServices;
using System.Security.AccessControl;
using System.Security.Cryptography;
using System.Security.Principal;
using System.Text;
using System.Threading;
namespace Microsoft.InfoCards
{
internal class FileDataSource : DataSource
{
public const int ENCRYPTIONKEYBUFFERSIZE = 32;
public const int ENCRYPTIONKEYBITLENGTH = 256;
public const int ENCRYPTIONBLOCKBUFFERSIZE = 16;
public const int ENCRYPTIONBLOCKBITLENGTH = 128;
public const int ENCRYPTIONITERATIONS = 1000;
public const int INITIALINDEXITEMCOUNT = 20;
public const int INITIALINDEXAREASIZE = 80;
public const int INITIALBLOBAREASIZE = 2048;
public const int FILEVERSION = 11;
private static readonly SecurityIdentifier AdministratorSid = new SecurityIdentifier(WellKnownSidType.BuiltinAdministratorsSid, (SecurityIdentifier) null);
private int m_variableSignatureLength = 64;
private FileInfo m_fileInfo;
private FileStream m_file;
private FileInfo m_shadowInfo;
private FileStream m_shadow;
private byte[] m_header;
private IndexedDataBuffer m_data;
private SecondaryIndexList m_indexes;
private ReaderWriterLock m_lock;
private SymmetricAlgorithm m_encAlg;
private byte[] m_key;
private bool m_keyProtected;
private WindowsIdentity m_identity;
private bool m_currentTransactionDirty;
private SafeRsaProviderHandle m_provider;
protected FileDataSource()
: base((string) null, (string) null)
{
}
public FileDataSource(WindowsIdentity identity, string fileName)
: this(identity, fileName, Guid.NewGuid().ToString("P"), SecondaryIndexDefinition.MasterIndexes)
{
}
public FileDataSource(
WindowsIdentity identity,
string fileName,
string instanceId,
SecondaryIndexDefinition[] indexDefinitions)
: base(instanceId, fileName)
{
this.m_identity = identity;
this.m_currentTransactionDirty = false;
this.m_fileInfo = new FileInfo(fileName);
this.m_shadowInfo = new FileInfo(this.m_fileInfo.FullName + ".shadow");
this.m_lock = new ReaderWriterLock();
this.m_indexes = new SecondaryIndexList(indexDefinitions);
this.m_encAlg = FileDataSource.CreateEncryptionAlg();
this.SetupProvider();
}
public IndexedDataBuffer Buffer
{
get
{
this.ThrowIfDisposed();
this.ThrowIfNotLoaded();
return this.m_data;
}
}
public byte[] Header
{
get
{
this.ThrowIfDisposed();
this.ThrowIfNotLoaded();
return this.m_header;
}
}
public SecondaryIndexList Indexes
{
get
{
this.ThrowIfDisposed();
this.ThrowIfNotLoaded();
return this.m_indexes;
}
}
protected WindowsIdentity Identity => this.m_identity;
protected internal override void OnClear()
{
using (new SystemIdentity(true))
{
FileDataSource.ResilientDelete(this.m_fileInfo);
FileDataSource.ResilientDelete(this.m_shadowInfo);
}
}
protected internal override void OnLoad()
{
this.ThrowIfDisposed();
try
{
this.CreateDirAndFiles();
if (this.m_shadow.Length > 0L)
{
if (this.m_file.Length > 0L)
{
this.m_shadow.SetLength(0L);
this.LoadFrom((Stream) this.m_file);
}
else
{
this.LoadFrom((Stream) this.m_shadow);
this.FlushToShadow();
this.SwapFileWithShadow();
}
}
else if (this.m_file.Length > 0L)
{
this.LoadFrom((Stream) this.m_file);
}
else
{
this.CreateEmptyStore();
this.FlushToShadow();
this.SwapFileWithShadow();
}
this.m_file.Seek(0L, SeekOrigin.Begin);
}
catch
{
this.CloseFiles();
throw;
}
}
private void CloseFiles()
{
using (new SystemIdentity(false))
{
if (this.m_file != null)
{
this.m_file.Close();
this.m_file = (FileStream) null;
}
if (this.m_shadow == null)
return;
this.m_shadow.Close();
this.m_shadow = (FileStream) null;
}
}
protected void CreateDirAndFiles()
{
this.CheckReparsePoints();
if (NativeMcppMethods.PathSupportsPersistedSecurity(this.m_fileInfo.Directory.FullName))
this.ValidateDirectoryAccess();
using (new SystemIdentity(true))
{
try
{
if (!this.m_fileInfo.Directory.Exists)
{
try
{
if (NativeMcppMethods.PathSupportsPersistedSecurity(this.m_fileInfo.Directory.FullName))
this.m_fileInfo.Directory.Create(FileDataSource.CreateSecurityDescriptor<DirectorySecurity>());
else
this.m_fileInfo.Directory.Create();
this.m_fileInfo.Directory.Attributes |= FileAttributes.Hidden | FileAttributes.NotContentIndexed;
}
catch (UnauthorizedAccessException ex)
{
throw InfoCardTrace.ThrowHelperError((Exception) new DataAccessException(ex.Message));
}
}
else if (NativeMcppMethods.PathSupportsPersistedSecurity(this.m_fileInfo.Directory.FullName) && this.LogIfAclsTampered((FileSystemInfo) this.m_fileInfo.Directory))
this.m_fileInfo.Directory.SetAccessControl(FileDataSource.CreateSecurityDescriptor<DirectorySecurity>());
InfoCardTrace.Assert(this.m_shadowInfo.Directory.Exists, "m_shadowInfo directory should be same as main directory");
this.OpenOrCreateHelper(this.m_fileInfo, out this.m_file);
this.OpenOrCreateHelper(this.m_shadowInfo, out this.m_shadow);
}
catch (IOException ex)
{
throw InfoCardTrace.ThrowHelperError((Exception) new DataAccessException(ex.Message));
}
}
}
private void CheckReparsePoints()
{
using (new SystemIdentity(true))
{
for (DirectoryInfo directoryInfo = this.m_fileInfo.Directory; directoryInfo != null; directoryInfo = directoryInfo.Parent)
{
if (directoryInfo.Exists && (directoryInfo.Attributes & FileAttributes.ReparsePoint) != (FileAttributes) 0)
throw InfoCardTrace.ThrowHelperError((Exception) new DataAccessException(SR.GetString("StoreNoReparsePointAllowed")));
}
if (Directory.Exists(this.m_fileInfo.FullName) && (this.m_fileInfo.Attributes & FileAttributes.ReparsePoint) != (FileAttributes) 0)
throw InfoCardTrace.ThrowHelperError((Exception) new DataAccessException(SR.GetString("StoreNoReparsePointAllowed")));
}
}
private void ValidateDirectoryAccess()
{
InfoCardTrace.Assert(!WindowsIdentity.GetCurrent().IsSystem, "Should not be running as system");
IdentityReference identityReference = WindowsIdentity.GetCurrent().User.Translate(typeof (NTAccount));
bool flag = false;
DirectoryInfo parent = this.m_fileInfo.Directory.Parent;
if (parent.Exists)
{
foreach (FileSystemAccessRule accessRule in (ReadOnlyCollectionBase) parent.GetAccessControl().GetAccessRules(true, true, typeof (NTAccount)))
{
if (accessRule.IdentityReference == identityReference && accessRule.FileSystemRights == FileSystemRights.FullControl && accessRule.AccessControlType == AccessControlType.Allow)
{
flag = true;
break;
}
}
}
if (!flag)
throw InfoCardTrace.ThrowHelperError((Exception) new DataAccessException(SR.GetString("StoreInvalidDataFilePath")));
}
private void OpenOrCreateHelper(FileInfo theFile, out FileStream fileStream)
{
InfoCardTrace.Assert(WindowsIdentity.GetCurrent().IsSystem, "Should be running as system");
if (!File.Exists(theFile.FullName))
{
fileStream = FileDataSource.ResilientOpen(theFile, FileMode.CreateNew, FileAccess.ReadWrite);
theFile.Attributes |= FileAttributes.Hidden | FileAttributes.NotContentIndexed;
theFile.SetAccessControl(FileDataSource.CreateSecurityDescriptor<FileSecurity>());
}
else
{
if (NativeMcppMethods.PathSupportsPersistedSecurity(this.m_fileInfo.Directory.FullName) && this.LogIfAclsTampered((FileSystemInfo) theFile))
{
theFile.SetAccessControl(FileDataSource.CreateSecurityDescriptor<FileSecurity>());
theFile.Attributes |= FileAttributes.Hidden | FileAttributes.NotContentIndexed;
}
fileStream = FileDataSource.ResilientOpen(theFile, FileMode.Open, FileAccess.ReadWrite);
}
}
protected virtual void OnSwapFileWithShadow()
{
using (new SystemIdentity(true))
{
string fullName = this.m_fileInfo.FullName;
FileDataSource.ResilientDelete(this.m_fileInfo);
FileDataSource.ResilientMove(this.m_shadowInfo, this.m_fileInfo);
this.m_fileInfo = new FileInfo(fullName);
this.m_shadowInfo = new FileInfo(fullName + ".shadow");
}
}
protected internal override void OnClose()
{
this.ThrowIfDisposed();
if (this.m_data != null)
{
this.m_data.Close();
this.m_data = (IndexedDataBuffer) null;
}
this.m_indexes.Close();
this.CloseFiles();
this.m_provider.Dispose();
}
protected internal override DataRow ReadRow(int localId, QueryDetails details)
{
DataRow row = (DataRow) null;
if (QueryDetails.Header == (details & QueryDetails.Header))
{
row = this.m_data.CreateDataRow(localId);
if (QueryDetails.DataBlob == (details & QueryDetails.DataBlob))
{
byte[] iv = this.AllocateIvBuffer();
this.m_data.CopyIVFromObject(localId, iv, 0);
using (Stream streamForObjectData = this.m_data.GetStreamForObjectData(localId))
{
using (MemoryStream output = new MemoryStream((int) streamForObjectData.Length))
{
this.DecryptData(iv, streamForObjectData, (Stream) output);
row.SetDataField(output.ToArray());
byte[] buffer = output.GetBuffer();
Array.Clear((Array) buffer, 0, buffer.Length);
}
}
}
if (QueryDetails.IndexData == (details & QueryDetails.IndexData))
this.m_indexes.PopulateRowIndexBuffer(row);
}
return row;
}
protected internal override bool SingleMatch(QueryParameter match, LocalIdCollection localIds)
{
this.ThrowIfDisposed();
this.ThrowIfNotLoaded();
if (localIds == null)
throw InfoCardTrace.ThrowHelperArgumentNull(nameof (localIds));
if (match == null)
throw InfoCardTrace.ThrowHelperArgumentNull(nameof (match));
if (string.IsNullOrEmpty(match.IndexName))
throw InfoCardTrace.ThrowHelperError((Exception) new ArgumentException(SR.GetString("StoreDataSourceInvalidIndexName", (object) match.IndexName), nameof (match)));
bool flag = false;
try
{
try
{
}
finally
{
this.m_lock.AcquireReaderLock(0);
flag = true;
}
return this.m_indexes.Match(match, localIds);
}
finally
{
if (flag)
this.m_lock.ReleaseReaderLock();
}
}
protected internal override void OnBeginTransaction()
{
InfoCardTrace.Assert(!this.m_currentTransactionDirty, "m_currentTransactionDirty should have been set to false before beginning a transaction");
base.OnBeginTransaction();
}
protected internal override void OnRollbackTransaction()
{
try
{
base.OnRollbackTransaction();
this.LoadFrom((Stream) this.m_file);
}
finally
{
this.m_currentTransactionDirty = false;
}
}
protected internal override void OnCommitTransaction()
{
try
{
base.OnCommitTransaction();
if (!this.m_currentTransactionDirty)
return;
this.FlushToShadow();
this.SwapFileWithShadow();
}
finally
{
this.m_currentTransactionDirty = false;
}
}
protected internal override void WriteRow(DataRow row)
{
this.ThrowIfDisposed();
this.ThrowIfNotLoaded();
this.ThrowIfWriteLockNotHeld();
if (row == null)
throw InfoCardTrace.ThrowHelperArgumentNull(nameof (row));
bool flag = false;
try
{
try
{
}
finally
{
this.m_lock.AcquireWriterLock(0);
flag = true;
}
using (MemoryStream output = new MemoryStream())
{
this.m_encAlg.GenerateIV();
byte[] iv = this.m_encAlg.IV;
using (MemoryStream input = new MemoryStream(row.GetDataField()))
{
this.EncryptData(iv, (Stream) input, (Stream) output);
int localId = this.m_data.WriteObject(row.LocalId, iv, output.ToArray(), row.ObjectType, row.LastChange, row.GlobalId);
this.m_indexes.SetValuesForId(localId, row.IndexBuffer, true);
row.SourceId = this.SourceId;
row.InstanceId = this.InstanceId;
row.LocalId = localId;
}
}
}
finally
{
if (flag)
this.m_lock.ReleaseWriterLock();
}
this.m_currentTransactionDirty = true;
}
protected internal override void RemoveObject(int id)
{
if ((uint) id > (uint) (this.m_data.Index.Length / 4 - 1))
throw InfoCardTrace.ThrowHelperError((Exception) new ArgumentOutOfRangeException(nameof (id), (object) id, SR.GetString("StoreDataSourceIdOutOfRange")));
bool flag = false;
try
{
try
{
}
finally
{
this.m_lock.AcquireWriterLock(0);
flag = true;
}
this.m_data.RemoveObject(id);
this.m_indexes.RemoveAllValuesForId(id);
}
finally
{
if (flag)
this.m_lock.ReleaseWriterLock();
}
this.m_currentTransactionDirty = true;
}
private void ProtectKey()
{
if (this.m_keyProtected)
throw InfoCardTrace.ThrowHelperError((Exception) new InvalidOperationException(SR.GetString("StoreKeyAlreadyProtected")));
ProtectedMemory.Protect(this.m_key, MemoryProtectionScope.SameProcess);
this.m_keyProtected = true;
}
private void UnprotectKey()
{
if (!this.m_keyProtected)
throw InfoCardTrace.ThrowHelperError((Exception) new InvalidOperationException(SR.GetString("StoreKeyNotAlreadyProtected")));
ProtectedMemory.Unprotect(this.m_key, MemoryProtectionScope.SameProcess);
this.m_keyProtected = false;
}
private unsafe void DecryptData(byte[] iv, Stream input, Stream output)
{
InfoCardTrace.Assert(input is MemoryStream, "Invalid stream type");
if (iv == null || iv.Length == 0)
throw InfoCardTrace.ThrowHelperArgumentNull(nameof (iv));
if (input == null)
throw InfoCardTrace.ThrowHelperArgumentNull(nameof (input));
if (output == null)
throw InfoCardTrace.ThrowHelperArgumentNull(nameof (output));
using (SafeCryptoKey safeCryptoKey = new SafeCryptoKey(this.m_provider, this.m_key, iv))
{
byte[] buffer = new byte[input.Length];
input.Seek(0L, SeekOrigin.Begin);
input.Read(buffer, 0, (int) input.Length);
uint length = (uint) buffer.Length;
fixed (byte* data = &buffer[0])
{
if (!NativeMethods.CryptDecrypt(safeCryptoKey.Handle, IntPtr.Zero, 1U, 0U, (IntPtr) (void*) data, ref length))
{
Exception e = (Exception) new Win32Exception(Marshal.GetLastWin32Error());
Array.Clear((Array) buffer, 0, buffer.Length);
InfoCardTrace.TraceAndLogException(e);
throw InfoCardTrace.ThrowHelperError(e);
}
}
output.Write(buffer, 0, (int) length);
}
}
private unsafe void EncryptData(byte[] iv, Stream input, Stream output)
{
if (iv == null || iv.Length == 0)
throw InfoCardTrace.ThrowHelperArgumentNull(nameof (iv));
if (input == null)
throw InfoCardTrace.ThrowHelperArgumentNull(nameof (input));
if (output == null)
throw InfoCardTrace.ThrowHelperArgumentNull(nameof (output));
using (SafeCryptoKey safeCryptoKey = new SafeCryptoKey(this.m_provider, this.m_key, iv))
{
byte[] buffer = new byte[input.Length + (long) this.m_key.Length];
input.Seek(0L, SeekOrigin.Begin);
input.Read(buffer, 0, (int) input.Length);
uint length = (uint) input.Length;
fixed (byte* data = &buffer[0])
{
if (!NativeMethods.CryptEncrypt(safeCryptoKey.Handle, IntPtr.Zero, 1U, 0U, (IntPtr) (void*) data, ref length, (uint) buffer.Length))
{
Exception e = (Exception) new Win32Exception(Marshal.GetLastWin32Error());
InfoCardTrace.TraceAndLogException(e);
throw InfoCardTrace.ThrowHelperError(e);
}
}
output.Write(buffer, 0, (int) length);
}
}
private unsafe void CreateEmptyStore()
{
this.m_data = new IndexedDataBuffer(new byte[80], new byte[2048], 0, (DataSource) this);
this.m_encAlg.GenerateKey();
this.m_key = new byte[this.m_encAlg.Key.Length];
Array.Copy((Array) this.m_encAlg.Key, 0, (Array) this.m_key, 0, this.m_encAlg.Key.Length);
this.m_encAlg.GenerateKey();
this.m_keyProtected = false;
this.ProtectKey();
this.m_header = new byte[this.GetTotalHeaderSize()];
fixed (byte* numPtr = &this.m_header[this.GetOffsetToEncryptedFileHeader()])
((EncryptedFileStoreHeader*) numPtr)->Version = 11U;
this.EncryptAndSaveDPAPIKeyToHeader();
}
private void FlushToShadow() => this.FlushToStream((Stream) this.m_shadow);
private int GetTotalHeaderSize() => sizeof (EncryptedFileStoreHeader) + this.GetTotalSignatureSize();
private int GetOffsetToEncryptedFileHeader() => this.m_variableSignatureLength + 4;
private int GetTotalSignatureSize() => this.GetOffsetToEncryptedFileHeader();
private long GetRequiredFileSize()
{
long num = Convert.ToInt64(this.GetTotalHeaderSize()) + Convert.ToInt64(this.m_data.DataLength) + Convert.ToInt64(this.m_data.Index.Length + 4);
foreach (string key in (IEnumerable) this.m_indexes.InnerIndexes.Keys)
{
byte[] buffer = ((SecondaryIndex) this.m_indexes.InnerIndexes[(object) key]).GetBuffer();
num += Convert.ToInt64(8 + buffer.Length);
}
return num + num / 20L;
}
private unsafe void FlushToStream(Stream stream)
{
if (stream == null)
throw InfoCardTrace.ThrowHelperArgumentNull(nameof (stream));
stream.SetLength(this.GetRequiredFileSize());
BinaryWriter binaryWriter1 = new BinaryWriter(stream);
this.m_encAlg.GenerateIV();
byte[] iv = this.m_encAlg.IV;
int dataLength = this.m_data.DataLength;
stream.Seek((long) this.GetTotalHeaderSize(), SeekOrigin.Begin);
binaryWriter1.Write(iv);
long position = stream.Position;
using (BinaryWriter binaryWriter2 = new BinaryWriter((Stream) new MemoryStream()))
{
binaryWriter2.Write(this.m_data.Index.Length / 4);
binaryWriter2.Write(this.m_data.Index);
binaryWriter2.Write(this.m_indexes.Count);
foreach (string key in (IEnumerable) this.m_indexes.InnerIndexes.Keys)
{
SecondaryIndex innerIndex = (SecondaryIndex) this.m_indexes.InnerIndexes[(object) key];
int lastIndex = innerIndex.LastIndex;
binaryWriter2.Write(lastIndex);
int initialSize = SecondaryIndexDefinition.GetByName(key).InitialSize;
if (lastIndex + 1 < initialSize)
{
binaryWriter2.Write(initialSize);
InfoCardTrace.Assert(initialSize * sizeof (SecondaryIndexItem) <= innerIndex.GetBuffer().Length, "Buffer length is at least min capacity");
binaryWriter2.Write(innerIndex.GetBuffer(), 0, initialSize * sizeof (SecondaryIndexItem));
}
else
{
binaryWriter2.Write(lastIndex + 1);
binaryWriter2.Write(innerIndex.GetBuffer(), 0, (lastIndex + 1) * sizeof (SecondaryIndexItem));
}
}
binaryWriter2.Flush();
binaryWriter2.Seek(0, SeekOrigin.Begin);
this.EncryptData(iv, binaryWriter2.BaseStream, binaryWriter1.BaseStream);
}
int int32 = Convert.ToInt32(stream.Position - position);
int num = int32 + this.m_data.DataLength + this.GetTotalHeaderSize() + iv.Length;
binaryWriter1.Write(this.m_data.Data, 0, this.m_data.DataLength);
stream.Seek(0L, SeekOrigin.Begin);
binaryWriter1.Flush();
fixed (byte* numPtr = &this.m_header[this.GetOffsetToEncryptedFileHeader()])
{
((EncryptedFileStoreHeader*) numPtr)->DataSize = dataLength;
((EncryptedFileStoreHeader*) numPtr)->Version = 11U;
((EncryptedFileStoreHeader*) numPtr)->Size = num;
((EncryptedFileStoreHeader*) numPtr)->IndexSize = int32;
}
binaryWriter1.Write(this.m_header);
stream.SetLength(Convert.ToInt64(num));
binaryWriter1.Flush();
this.SignStream(stream);
}
private unsafe void SignStream(Stream input)
{
long offset = input != null ? input.Position : throw InfoCardTrace.ThrowHelperArgumentNull(nameof (input));
this.m_encAlg.GenerateIV();
byte[] sourceArray = this.SignDigest(this.m_encAlg.IV, this.CreateStreamDigest(input));
byte[] numArray = new byte[this.GetTotalSignatureSize()];
fixed (byte* numPtr = &numArray[0])
((SignatureHeader*) numPtr)->SignatureSize = this.m_variableSignatureLength;
Array.Copy((Array) sourceArray, 0, (Array) numArray, 4, sourceArray.Length);
input.Seek(0L, SeekOrigin.Begin);
input.Write(numArray, 0, numArray.Length);
InfoCardTrace.Assert(this.m_variableSignatureLength >= sourceArray.Length, "Generated signature should be less than signature length");
input.Seek(offset, SeekOrigin.Begin);
}
private byte[] CreateStreamDigest(Stream input)
{
input.Seek((long) this.GetOffsetToEncryptedFileHeader(), SeekOrigin.Begin);
byte[] data = new byte[Convert.ToInt32((input.Length / 4096L + 1L) * (long) HashUtility.HashBufferLength)];
int dataIndex = 0;
byte[] numArray = new byte[4096];
int dataToHashSize;
do
{
dataToHashSize = input.Read(numArray, 0, numArray.Length);
if (dataToHashSize > 0)
{
HashUtility.SetHashValue(data, dataIndex, numArray, 0, dataToHashSize);
dataIndex += HashUtility.HashBufferLength;
}
}
while (dataToHashSize == numArray.Length);
return data;
}
private byte[] SignDigest(byte[] iv, byte[] digest)
{
byte[] destinationArray = new byte[this.m_variableSignatureLength];
using (MemoryStream input = new MemoryStream(digest))
{
using (MemoryStream output = new MemoryStream(digest.Length))
{
this.EncryptData(iv, (Stream) input, (Stream) output);
Array.Copy((Array) output.GetBuffer(), Convert.ToInt32(output.Position - 1L) - iv.Length, (Array) destinationArray, 0, iv.Length);
Array.Copy((Array) iv, 0, (Array) destinationArray, iv.Length, iv.Length);
return destinationArray;
}
}
}
private void ValidateSignature(Stream input)
{
long offset = input != null ? input.Position : throw InfoCardTrace.ThrowHelperArgumentNull(nameof (input));
byte[] buffer = new byte[this.m_variableSignatureLength];
byte[] numArray1 = this.AllocateIvBuffer();
input.Seek(20L, SeekOrigin.Begin);
input.Read(numArray1, 0, numArray1.Length);
byte[] numArray2 = this.SignDigest(numArray1, this.CreateStreamDigest(input));
input.Seek(4L, SeekOrigin.Begin);
input.Read(buffer, 0, buffer.Length);
for (int index = 0; index < buffer.Length; ++index)
{
if ((int) buffer[index] != (int) numArray2[index])
throw InfoCardTrace.ThrowHelperError((Exception) new CorruptStoreException(SR.GetString("StoreSignatureNotValid")));
}
input.Seek(offset, SeekOrigin.Begin);
}
protected unsafe void LoadFrom(Stream stream)
{
if (stream == null)
throw InfoCardTrace.ThrowHelperArgumentNull(nameof (stream));
stream.Seek(0L, SeekOrigin.Begin);
BinaryReader binaryReader1 = (BinaryReader) new InfoCardBinaryReader(stream);
this.m_header = new byte[this.GetTotalHeaderSize()];
binaryReader1.Read(this.m_header, 0, this.m_header.Length);
fixed (byte* numPtr1 = &this.m_header[this.GetOffsetToEncryptedFileHeader()])
{
if (11U != ((EncryptedFileStoreHeader*) numPtr1)->Version)
{
CorruptStoreException e = new CorruptStoreException(SR.GetString("StoreVersionNotSupported", (object) ((EncryptedFileStoreHeader*) numPtr1)->Version));
InfoCardTrace.TraceAndLogException((Exception) e);
throw InfoCardTrace.ThrowHelperError((Exception) e);
}
// ISSUE: __unpin statement
__unpin(numPtr1);
fixed (byte* numPtr2 = &this.m_header[0])
{
if (this.m_variableSignatureLength != ((SignatureHeader*) numPtr2)->SignatureSize)
throw InfoCardTrace.ThrowHelperError((Exception) new CorruptStoreException(SR.GetString("StoreSignatureNotValid")));
}
this.ObtainDataKeyFromHeader();
this.ValidateSignature(stream);
fixed (byte* numPtr3 = &this.m_header[this.GetOffsetToEncryptedFileHeader()])
{
byte[] numArray = this.AllocateIvBuffer();
byte[] masterIndex;
using (MemoryStream output = new MemoryStream())
{
binaryReader1.Read(numArray, 0, numArray.Length);
byte[] buffer1 = binaryReader1.ReadBytes(((EncryptedFileStoreHeader*) numPtr3)->IndexSize);
using (MemoryStream input = new MemoryStream(buffer1))
{
this.DecryptData(numArray, (Stream) input, (Stream) output);
Array.Clear((Array) buffer1, 0, buffer1.Length);
}
output.Seek(0L, SeekOrigin.Begin);
BinaryReader binaryReader2 = (BinaryReader) new InfoCardBinaryReader((Stream) output);
int num1 = binaryReader2.ReadInt32();
InfoCardTrace.Assert(num1 > 0, "MasterIndexCount Invalid");
masterIndex = binaryReader2.ReadBytes(num1 * 4);
InfoCardTrace.Assert((uint) binaryReader2.ReadInt32() <= (uint) this.m_indexes.Count, "SecondaryIndexCount Invalid");
foreach (string key in (IEnumerable) this.m_indexes.InnerIndexes.Keys)
{
int lastIndex = binaryReader2.ReadInt32();
int num2 = binaryReader2.ReadInt32();
byte[] buffer2 = new byte[Utility.CalculateIncreaseByPercent(num2 * sizeof (SecondaryIndexItem), sizeof (SecondaryIndexItem), SecondaryIndexDefinition.GetByName(key).GrowthFactor)];
binaryReader2.Read(buffer2, 0, num2 * sizeof (SecondaryIndexItem));
this.m_indexes.SetBuffer(key, buffer2, lastIndex);
}
}
using (MemoryStream memoryStream = new MemoryStream(Utility.CalculateIncreaseByPercent(Convert.ToInt32(binaryReader1.BaseStream.Length - binaryReader1.BaseStream.Position), 1, 5)))
{
byte[] buffer3 = new byte[256];
int num = 0;
int count;
do
{
count = binaryReader1.Read(buffer3, 0, buffer3.Length);
memoryStream.Write(buffer3, 0, count);
num += count;
}
while (count == buffer3.Length);
byte[] buffer4 = memoryStream.GetBuffer();
if (num == 0)
buffer4 = new byte[2048];
this.m_data = new IndexedDataBuffer(masterIndex, buffer4, ((EncryptedFileStoreHeader*) numPtr3)->DataSize, (DataSource) this);
}
}
}
}
protected virtual void SwapFileWithShadow()
{
this.CloseFiles();
this.OnSwapFileWithShadow();
try
{
this.CreateDirAndFiles();
}
catch
{
this.CloseFiles();
throw;
}
}
private unsafe void EncryptAndSaveDPAPIKeyToHeader()
{
DataBlob dataBlob1 = new DataBlob();
DataBlob dataBlob2 = new DataBlob();
byte[] numArray = new byte[32 + HashUtility.HashBufferLength];
this.UnprotectKey();
try
{
Array.Copy((Array) this.m_key, 0, (Array) numArray, 0, 32);
HashUtility.SetHashValue(numArray, 32, this.m_key, 0, 32);
fixed (byte* numPtr1 = &numArray[0])
{
DataBlob dataBlob3;
dataBlob3.pbData = new IntPtr((void*) numPtr1);
dataBlob3.cbData = numArray.Length;
try
{
if (!NativeMethods.CryptProtectData(new IntPtr((void*) &dataBlob3), (string) null, IntPtr.Zero, IntPtr.Zero, IntPtr.Zero, 65, new IntPtr((void*) &dataBlob1)))
throw InfoCardTrace.ThrowHelperError((Exception) new Win32Exception(Marshal.GetLastWin32Error(), SR.GetString("StoreCryptProtectDataFailed")));
using (new SystemIdentity(true))
{
if (!NativeMethods.CryptProtectData(new IntPtr((void*) &dataBlob1), (string) null, IntPtr.Zero, IntPtr.Zero, IntPtr.Zero, 65, new IntPtr((void*) &dataBlob2)))
throw InfoCardTrace.ThrowHelperError((Exception) new Win32Exception(Marshal.GetLastWin32Error(), SR.GetString("StoreCryptProtectDataAsSystemFailed")));
}
InfoCardTrace.Assert(dataBlob2.cbData <= 512, "The size of the encrypted data is larger than EncryptedKeyBlockSize");
fixed (byte* numPtr2 = &this.m_header[this.GetOffsetToEncryptedFileHeader()])
{
((EncryptedFileStoreHeader*) numPtr2)->KeyBlock.KeyType = 0;
((EncryptedFileStoreHeader*) numPtr2)->KeyBlock.EncryptedKeySize = dataBlob2.cbData;
byte* numPtr3 = &((EncryptedFileStoreHeader*) numPtr2)->KeyBlock.EncryptedKey;
for (int index = 0; index < dataBlob2.cbData; ++index)
numPtr3[index] = *(byte*) ((IntPtr) dataBlob2.pbData.ToPointer() + index);
if (dataBlob2.cbData >= 512)
return;
Utility.ClearUnsafeMemory(new IntPtr((void*) (numPtr3 + dataBlob2.cbData)), 512 - dataBlob2.cbData);
}
}
finally
{
Exception e = (Exception) null;
if (IntPtr.Zero != dataBlob1.pbData)
{
Utility.ClearUnsafeMemory(dataBlob1.pbData, dataBlob1.cbData);
if (IntPtr.Zero != NativeMethods.LocalFree(dataBlob1.pbData))
e = (Exception) new Win32Exception(Marshal.GetLastWin32Error());
}
if (IntPtr.Zero != dataBlob2.pbData)
{
Utility.ClearUnsafeMemory(dataBlob2.pbData, dataBlob2.cbData);
if (IntPtr.Zero != NativeMethods.LocalFree(dataBlob2.pbData))
e = (Exception) new Win32Exception(Marshal.GetLastWin32Error());
}
if (e != null)
throw InfoCardTrace.ThrowHelperError(e);
}
}
}
finally
{
this.ProtectKey();
Array.Clear((Array) numArray, 0, numArray.Length);
}
}
private void ObtainDataKeyFromHeader()
{
try
{
this.m_key = this.TryObtainDataKeyFromDPAPI() ?? throw InfoCardTrace.ThrowHelperError((Exception) new InvalidOperationException(SR.GetString("StoreUnableToGetStoreKeyFromDPAPI")));
this.m_keyProtected = false;
this.ProtectKey();
}
catch (Exception ex)
{
if (!InfoCardTrace.IsFatal(ex))
throw InfoCardTrace.ThrowHelperError((Exception) new InvalidStoreProtectionKeyException());
throw;
}
}
private unsafe byte[] TryObtainDataKeyFromDPAPI()
{
DataBlob dataBlob1 = new DataBlob();
DataBlob dataBlob2 = new DataBlob();
fixed (byte* numPtr = &this.m_header[this.GetOffsetToEncryptedFileHeader()])
{
if (((EncryptedFileStoreHeader*) numPtr)->KeyBlock.KeyType != 0)
throw InfoCardTrace.ThrowHelperError((Exception) new InvalidOperationException(SR.GetString("StoreFileNotProtectedWithDPAPI")));
byte[] dataKeyFromDpapi = (byte[]) null;
DataBlob dataBlob3;
dataBlob3.pbData = new IntPtr((void*) &((EncryptedFileStoreHeader*) numPtr)->KeyBlock.EncryptedKey);
dataBlob3.cbData = ((EncryptedFileStoreHeader*) numPtr)->KeyBlock.EncryptedKeySize;
try
{
using (new SystemIdentity(true))
{
if (!NativeMethods.CryptUnprotectData(new IntPtr((void*) &dataBlob3), (StringBuilder) null, IntPtr.Zero, IntPtr.Zero, IntPtr.Zero, 1, new IntPtr((void*) &dataBlob2)))
throw InfoCardTrace.ThrowHelperError((Exception) new Win32Exception(Marshal.GetLastWin32Error(), SR.GetString("StoreCryptUnprotectDataAsSystemFailed")));
}
if (!NativeMethods.CryptUnprotectData(new IntPtr((void*) &dataBlob2), (StringBuilder) null, IntPtr.Zero, IntPtr.Zero, IntPtr.Zero, 1, new IntPtr((void*) &dataBlob1)))
throw InfoCardTrace.ThrowHelperError((Exception) new Win32Exception(Marshal.GetLastWin32Error(), SR.GetString("StoreCryptUnprotectDataFailed")));
InfoCardTrace.Assert(dataBlob1.cbData == 32 + HashUtility.HashBufferLength, "The data size returned by CryptUnprotectData is invalid or corrupt.");
dataKeyFromDpapi = new byte[32];
Marshal.Copy(dataBlob1.pbData, dataKeyFromDpapi, 0, 32);
byte[] data = new byte[HashUtility.HashBufferLength];
HashUtility.SetHashValue(data, 0, dataKeyFromDpapi, 0, 32);
for (int index = 0; index < data.Length; ++index)
{
if ((int) data[index] != (int) *(byte*) ((IntPtr) dataBlob1.pbData.ToPointer() + (32 + index)))
throw InfoCardTrace.ThrowHelperError((Exception) new InvalidOperationException(SR.GetString("StoreDecryptedKeyIsNotValid")));
}
return dataKeyFromDpapi;
}
catch
{
if (dataKeyFromDpapi != null)
Array.Clear((Array) dataKeyFromDpapi, 0, dataKeyFromDpapi.Length);
throw;
}
finally
{
if (IntPtr.Zero != dataBlob2.pbData)
{
Utility.ClearUnsafeMemory(dataBlob2.pbData, dataBlob2.cbData);
NativeMethods.LocalFree(dataBlob2.pbData);
}
if (IntPtr.Zero != dataBlob1.pbData)
{
Utility.ClearUnsafeMemory(dataBlob1.pbData, dataBlob1.cbData);
NativeMethods.LocalFree(dataBlob1.pbData);
}
}
}
}
private bool LogIfAclsTampered(FileSystemInfo fileSysInfo)
{
bool condition = true;
try
{
FileSystemSecurity accessControl;
if (fileSysInfo is DirectoryInfo)
{
accessControl = (FileSystemSecurity) ((DirectoryInfo) fileSysInfo).GetAccessControl(AccessControlSections.Access | AccessControlSections.Owner);
}
else
{
InfoCardTrace.Assert(fileSysInfo is FileInfo, "Only fileinfo possible");
accessControl = (FileSystemSecurity) ((FileInfo) fileSysInfo).GetAccessControl(AccessControlSections.Access | AccessControlSections.Owner);
}
condition = this.LogIfAclsTamperedHelper(accessControl);
}
catch (UnauthorizedAccessException ex)
{
InfoCardTrace.Assert(condition, "ACL must have been tampered with");
}
if (condition)
InfoCardTrace.TraceAndLogException((Exception) new DataAccessException(SR.GetString("StoreAclsTamperedWith")));
return condition;
}
private bool LogIfAclsTamperedHelper(FileSystemSecurity fs)
{
if (SystemIdentity.LsaIdentityReference != fs.GetOwner(typeof (SecurityIdentifier)))
return true;
AuthorizationRuleCollection accessRules = fs.GetAccessRules(true, true, typeof (SecurityIdentifier));
bool flag = fs is DirectorySecurity;
foreach (FileSystemAccessRule systemAccessRule in (ReadOnlyCollectionBase) accessRules)
{
if ((!(SystemIdentity.LsaIdentityReference == systemAccessRule.IdentityReference) || FileSystemRights.FullControl != systemAccessRule.FileSystemRights || systemAccessRule.AccessControlType != AccessControlType.Allow) && (!flag || !((IdentityReference) FileDataSource.AdministratorSid == systemAccessRule.IdentityReference) || systemAccessRule.AccessControlType != AccessControlType.Allow || (FileSystemRights.ReadData | FileSystemRights.DeleteSubdirectoriesAndFiles | FileSystemRights.Synchronize) != systemAccessRule.FileSystemRights))
return true;
}
return false;
}
private static T CreateSecurityDescriptor<T>() where T : FileSystemSecurity, new()
{
T securityDescriptor = new T();
securityDescriptor.SetOwner(SystemIdentity.LsaIdentityReference);
foreach (FileSystemAccessRule accessRule in (ReadOnlyCollectionBase) securityDescriptor.GetAccessRules(true, true, typeof (SecurityIdentifier)))
securityDescriptor.RemoveAccessRuleAll(accessRule);
securityDescriptor.AddAccessRule(new FileSystemAccessRule(SystemIdentity.LsaIdentityReference, FileSystemRights.FullControl, InheritanceFlags.None, PropagationFlags.None, AccessControlType.Allow));
if ((object) securityDescriptor is DirectorySecurity)
securityDescriptor.AddAccessRule(new FileSystemAccessRule((IdentityReference) FileDataSource.AdministratorSid, FileSystemRights.ReadData | FileSystemRights.DeleteSubdirectoriesAndFiles, AccessControlType.Allow));
securityDescriptor.SetAccessRuleProtection(true, false);
return securityDescriptor;
}
private void SetupProvider() => this.m_provider = SafeRsaProviderHandle.Construct();
private byte[] AllocateIvBuffer()
{
InfoCardTrace.Assert(16 == this.m_encAlg.IV.Length, "Must be equal");
InfoCardTrace.Assert(16 == this.m_encAlg.IV.Length, "Must be equal");
return new byte[this.m_encAlg.IV.Length];
}
private static void ResilientDelete(FileInfo toDelete)
{
int millisecondsTimeout = 10;
bool flag = true;
Exception inner = (Exception) null;
do
{
if (!flag)
{
Thread.Sleep(millisecondsTimeout);
millisecondsTimeout *= 2;
}
try
{
toDelete.Delete();
flag = true;
}
catch (IOException ex)
{
inner = (Exception) ex;
flag = false;
}
}
while (!flag && millisecondsTimeout <= 500);
if (!flag)
throw InfoCardTrace.ThrowHelperError((Exception) new DataAccessException(SR.GetString("StoreFileInUse"), inner));
}
private static void ResilientMove(FileInfo fileFrom, FileInfo fileTo)
{
int millisecondsTimeout = 10;
bool flag = true;
do
{
if (!flag)
{
Thread.Sleep(millisecondsTimeout);
millisecondsTimeout *= 2;
}
try
{
fileFrom.MoveTo(fileTo.FullName);
flag = true;
}
catch (IOException ex)
{
flag = false;
}
}
while (!flag && millisecondsTimeout <= 500);
if (flag)
return;
InfoCardTrace.FailFast(SR.GetString("StoreFileInUse"));
}
private static FileStream ResilientOpen(
FileInfo toOpen,
FileMode mode,
FileAccess access)
{
int millisecondsTimeout = 10;
bool flag = true;
Exception inner = (Exception) null;
FileStream fileStream = (FileStream) null;
do
{
if (!flag)
{
Thread.Sleep(millisecondsTimeout);
millisecondsTimeout *= 2;
}
try
{
fileStream = toOpen.Open(mode, access, FileShare.None);
flag = true;
}
catch (IOException ex)
{
inner = (Exception) ex;
flag = false;
}
}
while (!flag && millisecondsTimeout <= 500);
if (!flag)
throw InfoCardTrace.ThrowHelperError((Exception) new DataAccessException(SR.GetString("StoreFileInUse"), inner));
return fileStream;
}
internal static SymmetricAlgorithm CreateEncryptionAlg()
{
RijndaelManaged encryptionAlg = new RijndaelManaged();
encryptionAlg.Mode = CipherMode.CBC;
encryptionAlg.KeySize = 256;
encryptionAlg.BlockSize = 128;
return (SymmetricAlgorithm) encryptionAlg;
}
}
}