Ejemplo n.º 1
0
        public uint AddDescriptor(RawSecurityDescriptor newDescriptor)
        {
            // Search to see if this is a known descriptor
            SecurityDescriptor newDescObj = new SecurityDescriptor(newDescriptor);
            uint newHash = newDescObj.CalcHash();

            byte[] newByteForm = new byte[newDescObj.Size];
            newDescObj.WriteTo(newByteForm, 0);

            foreach (KeyValuePair <HashIndexKey, HashIndexData> entry in _hashIndex.FindAll(new HashFinder(newHash)))
            {
                SecurityDescriptor stored = ReadDescriptor(entry.Value);

                byte[] storedByteForm = new byte[stored.Size];
                stored.WriteTo(storedByteForm, 0);

                if (Utilities.AreEqual(newByteForm, storedByteForm))
                {
                    return(entry.Value.Id);
                }
            }

            long offset = _nextSpace;

            // Write the new descriptor to the end of the existing descriptors
            SecurityDescriptorRecord record = new SecurityDescriptorRecord();

            record.SecurityDescriptor = newByteForm;
            record.Hash = newHash;
            record.Id   = _nextId;

            // If we'd overflow into our duplicate block, skip over it to the
            // start of the next block
            if ((offset + record.Size) / BlockSize % 2 == 1)
            {
                _nextSpace = Utilities.RoundUp(offset, BlockSize * 2);
                offset     = _nextSpace;
            }

            record.OffsetInFile = offset;

            byte[] buffer = new byte[record.Size];
            record.WriteTo(buffer, 0);

            using (Stream s = _file.OpenStream(AttributeType.Data, "$SDS", FileAccess.ReadWrite))
            {
                s.Position = _nextSpace;
                s.Write(buffer, 0, buffer.Length);
                s.Position = BlockSize + _nextSpace;
                s.Write(buffer, 0, buffer.Length);
            }

            // Make the next descriptor land at the end of this one
            _nextSpace = Utilities.RoundUp(_nextSpace + buffer.Length, 16);
            _nextId++;

            // Update the indexes
            HashIndexData hashIndexData = new HashIndexData();

            hashIndexData.Hash      = record.Hash;
            hashIndexData.Id        = record.Id;
            hashIndexData.SdsOffset = record.OffsetInFile;
            hashIndexData.SdsLength = (int)record.EntrySize;

            HashIndexKey hashIndexKey = new HashIndexKey();

            hashIndexKey.Hash = record.Hash;
            hashIndexKey.Id   = record.Id;

            _hashIndex[hashIndexKey] = hashIndexData;

            IdIndexData idIndexData = new IdIndexData();

            idIndexData.Hash      = record.Hash;
            idIndexData.Id        = record.Id;
            idIndexData.SdsOffset = record.OffsetInFile;
            idIndexData.SdsLength = (int)record.EntrySize;

            IdIndexKey idIndexKey = new IdIndexKey();

            idIndexKey.Id = record.Id;

            _idIndex[idIndexKey] = idIndexData;

            _file.UpdateRecordInMft();

            return(record.Id);
        }
Ejemplo n.º 2
0
        public uint AddDescriptor(RawSecurityDescriptor newDescriptor)
        {
            // Search to see if this is a known descriptor
            SecurityDescriptor newDescObj = new SecurityDescriptor(newDescriptor);
            uint newHash = newDescObj.CalcHash();

            byte[] newByteForm = new byte[newDescObj.Size];
            newDescObj.WriteTo(newByteForm, 0);

            foreach (var entry in _hashIndex.FindAll(new HashFinder(newHash)))
            {
                SecurityDescriptor stored = ReadDescriptor(entry.Value);

                byte[] storedByteForm = new byte[stored.Size];
                stored.WriteTo(storedByteForm, 0);

                if (Utilities.AreEqual(newByteForm, storedByteForm))
                {
                    return(entry.Value.Id);
                }
            }

            long offset = _nextSpace;

            // Write the new descriptor to the end of the existing descriptors
            SecurityDescriptorRecord record = new SecurityDescriptorRecord();

            record.SecurityDescriptor = newByteForm;
            record.Hash         = newHash;
            record.Id           = _nextId;
            record.OffsetInFile = offset;

            byte[] buffer = new byte[record.Size];
            record.WriteTo(buffer, 0);

            if (offset + buffer.Length > 0x40000)
            {
                throw new NotImplementedException("Excessive number of security descriptors - running into redundant storage area");
            }

            using (Stream s = _file.OpenStream(AttributeType.Data, "$SDS", FileAccess.ReadWrite))
            {
                s.Position = _nextSpace;
                s.Write(buffer, 0, buffer.Length);
                s.Position = 0x40000 + _nextSpace;
                s.Write(buffer, 0, buffer.Length);
            }

            // Make the next descriptor land at the end of this one
            _nextSpace = Utilities.RoundUp(_nextSpace + buffer.Length, 16);
            _nextId++;

            // Update the indexes
            HashIndexData hashIndexData = new HashIndexData();

            hashIndexData.Hash      = record.Hash;
            hashIndexData.Id        = record.Id;
            hashIndexData.SdsOffset = record.OffsetInFile;
            hashIndexData.SdsLength = (int)record.EntrySize;

            HashIndexKey hashIndexKey = new HashIndexKey();

            hashIndexKey.Hash = record.Hash;
            hashIndexKey.Id   = record.Id;

            _hashIndex[hashIndexKey] = hashIndexData;

            IdIndexData idIndexData = new IdIndexData();

            idIndexData.Hash      = record.Hash;
            idIndexData.Id        = record.Id;
            idIndexData.SdsOffset = record.OffsetInFile;
            idIndexData.SdsLength = (int)record.EntrySize;

            IdIndexKey idIndexKey = new IdIndexKey();

            idIndexKey.Id = record.Id;

            _idIndex[idIndexKey] = idIndexData;

            _file.UpdateRecordInMft();

            return(record.Id);
        }