public static bool IsZip64(BinaryReader reader)
        {
            if (reader == null)
            {
                throw new ArgumentNullException(nameof(reader));
            }

            var endOfCentralDirectoryRecord = EndOfCentralDirectoryRecord.Read(reader);

            if (endOfCentralDirectoryRecord.NumberOfThisDisk != endOfCentralDirectoryRecord.NumberOfTheDiskWithTheStartOfTheCentralDirectory)
            {
                return(false);
            }

            var offset = endOfCentralDirectoryRecord.OffsetFromStart - Zip64EndOfCentralDirectoryLocator.SizeInBytes;

            if (offset >= 0)
            {
                reader.BaseStream.Seek(offset, SeekOrigin.Begin);

                if (Zip64EndOfCentralDirectoryLocator.Exists(reader))
                {
                    return(true);
                }
            }

            reader.BaseStream.Seek(endOfCentralDirectoryRecord.OffsetOfStartOfCentralDirectory, SeekOrigin.Begin);

            CentralDirectoryHeader centralDirectoryHeader;

            while (CentralDirectoryHeader.TryRead(reader, out centralDirectoryHeader))
            {
                if (HasZip64ExtendedInformationExtraField(centralDirectoryHeader))
                {
                    return(true);
                }

                if (centralDirectoryHeader.DiskNumberStart != endOfCentralDirectoryRecord.NumberOfThisDisk)
                {
                    continue;
                }

                var savedPosition = reader.BaseStream.Position;

                reader.BaseStream.Position = centralDirectoryHeader.RelativeOffsetOfLocalHeader;

                LocalFileHeader localFileHeader;

                if (LocalFileHeader.TryRead(reader, out localFileHeader) &&
                    HasZip64ExtendedInformationExtraField(localFileHeader))
                {
                    return(true);
                }

                reader.BaseStream.Position = savedPosition;
            }

            return(false);
        }
Ejemplo n.º 2
0
        /// <summary>
        /// Read ZIP's offsets and positions of offsets.
        /// </summary>
        /// <param name="reader">binary reader to zip archive</param>
        /// <returns>metadata with offsets and positions for entries</returns>
        public static SignedPackageArchiveMetadata ReadSignedArchiveMetadata(BinaryReader reader)
        {
            if (reader == null)
            {
                throw new ArgumentNullException(nameof(reader));
            }

            var metadata = new SignedPackageArchiveMetadata()
            {
                StartOfFileHeaders = reader.BaseStream.Length
            };

            var endOfCentralDirectoryRecord = EndOfCentralDirectoryRecord.Read(reader);

            metadata.EndOfCentralDirectoryRecordPosition = endOfCentralDirectoryRecord.OffsetFromStart;

            reader.BaseStream.Seek(endOfCentralDirectoryRecord.OffsetOfStartOfCentralDirectory, SeekOrigin.Begin);

            // Read central directory records
            var centralDirectoryRecords = new List <CentralDirectoryHeaderMetadata>();
            CentralDirectoryHeader header;

            while (CentralDirectoryHeader.TryRead(reader, out header))
            {
                if (header.RelativeOffsetOfLocalHeader < metadata.StartOfFileHeaders)
                {
                    metadata.StartOfFileHeaders = header.RelativeOffsetOfLocalHeader;
                }

                var isPackageSignatureFile = SignedPackageArchiveUtility.IsPackageSignatureFileEntry(
                    header.FileName,
                    header.GeneralPurposeBitFlag);

                var centralDirectoryMetadata = new CentralDirectoryHeaderMetadata()
                {
                    IsPackageSignatureFile = isPackageSignatureFile,
                    HeaderSize             = header.GetSizeInBytes(),
                    OffsetToFileHeader     = header.RelativeOffsetOfLocalHeader,
                    Position = header.OffsetFromStart
                };

                centralDirectoryRecords.Add(centralDirectoryMetadata);
            }

            if (centralDirectoryRecords.Count == 0)
            {
                throw new InvalidDataException(Strings.ErrorInvalidPackageArchive);
            }

            var lastCentralDirectoryRecord = centralDirectoryRecords.Last();

            metadata.EndOfCentralDirectory   = lastCentralDirectoryRecord.Position + lastCentralDirectoryRecord.HeaderSize;
            metadata.CentralDirectoryHeaders = centralDirectoryRecords;

            UpdateSignedPackageArchiveMetadata(reader, metadata);

            return(metadata);
        }
        private static bool HasZip64ExtendedInformationExtraField(CentralDirectoryHeader header)
        {
            IReadOnlyList <ExtraField> extraFields;

            if (ExtraField.TryRead(header, out extraFields))
            {
                return(extraFields.Any(extraField => extraField is Zip64ExtendedInformationExtraField));
            }

            return(false);
        }
        /// <summary>
        /// Utility method to know if a zip archive is signed.
        /// </summary>
        /// <param name="reader">Binary reader pointing to a zip archive.</param>
        /// <returns>true if the given archive is signed</returns>
        public static bool IsSigned(BinaryReader reader)
        {
            if (reader == null)
            {
                throw new ArgumentNullException(nameof(reader));
            }

            try
            {
                var endOfCentralDirectoryRecord = EndOfCentralDirectoryRecord.Read(reader);

                // Look for signature central directory record
                reader.BaseStream.Seek(endOfCentralDirectoryRecord.OffsetOfStartOfCentralDirectory, SeekOrigin.Begin);
                CentralDirectoryHeader centralDirectoryHeader;

                while (CentralDirectoryHeader.TryRead(reader, out centralDirectoryHeader))
                {
                    if (IsPackageSignatureFileEntry(
                            centralDirectoryHeader.FileName,
                            centralDirectoryHeader.GeneralPurposeBitFlag))
                    {
                        // Go to local file header
                        reader.BaseStream.Seek(centralDirectoryHeader.RelativeOffsetOfLocalHeader, SeekOrigin.Begin);

                        // Make sure local file header exists
                        LocalFileHeader localFileHeader;
                        if (!LocalFileHeader.TryRead(reader, out localFileHeader))
                        {
                            throw new InvalidDataException(Strings.ErrorInvalidPackageArchive);
                        }

                        return(IsPackageSignatureFileEntry(
                                   localFileHeader.FileName,
                                   localFileHeader.GeneralPurposeBitFlag));
                    }
                }
            }
            // Ignore any exception. If something is thrown it means the archive is either not valid or not signed
            catch { }

            return(false);
        }
        private static UnsignedPackageArchiveMetadata ReadUnsignedArchiveMetadata(BinaryReader reader)
        {
            if (reader == null)
            {
                throw new ArgumentNullException(nameof(reader));
            }

            var endOfCentralDirectoryRecord         = EndOfCentralDirectoryRecord.Read(reader);
            var endOfCentralDirectoryRecordPosition = endOfCentralDirectoryRecord.OffsetFromStart;

            reader.BaseStream.Seek(endOfCentralDirectoryRecord.OffsetOfStartOfCentralDirectory, SeekOrigin.Begin);

            var centralDirectoryRecords = new List <CentralDirectoryHeaderMetadata>();
            CentralDirectoryHeader header;

            while (CentralDirectoryHeader.TryRead(reader, out header))
            {
                var centralDirectoryMetadata = new CentralDirectoryHeaderMetadata()
                {
                    Position = header.OffsetFromStart,
                    OffsetToLocalFileHeader = header.RelativeOffsetOfLocalHeader,
                    HeaderSize = header.GetSizeInBytes(),
                };

                centralDirectoryRecords.Add(centralDirectoryMetadata);
            }

            if (centralDirectoryRecords.Count == 0)
            {
                throw new InvalidDataException(Strings.ErrorInvalidPackageArchive);
            }

            var lastCentralDirectoryRecord    = centralDirectoryRecords.Last();
            var endOfCentralDirectoryPosition = lastCentralDirectoryRecord.Position + lastCentralDirectoryRecord.HeaderSize;
            var endOfLocalFileHeadersPosition = centralDirectoryRecords.Min(record => record.Position);

            UpdateLocalFileHeadersTotalSize(centralDirectoryRecords, endOfLocalFileHeadersPosition);

            return(new UnsignedPackageArchiveMetadata(endOfLocalFileHeadersPosition, endOfCentralDirectoryPosition));
        }
Ejemplo n.º 6
0
        internal static bool TryRead(BinaryReader reader, out CentralDirectoryHeader header)
        {
            header = null;

            var signature = reader.ReadUInt32();

            if (signature != Signature)
            {
                reader.BaseStream.Seek(offset: -sizeof(uint), origin: SeekOrigin.Current);

                return(false);
            }

            header = new CentralDirectoryHeader();

            header.OffsetFromStart = reader.BaseStream.Position - sizeof(uint);

            header.VersionMadeBy          = reader.ReadUInt16();
            header.VersionNeededToExtract = reader.ReadUInt16();
            header.GeneralPurposeBitFlag  = reader.ReadUInt16();
            header.CompressionMethod      = reader.ReadUInt16();
            header.LastModFileTime        = reader.ReadUInt16();
            header.LastModFileDate        = reader.ReadUInt16();
            header.Crc32                       = reader.ReadUInt32();
            header.CompressedSize              = reader.ReadUInt32();
            header.UncompressedSize            = reader.ReadUInt32();
            header.FileNameLength              = reader.ReadUInt16();
            header.ExtraFieldLength            = reader.ReadUInt16();
            header.FileCommentLength           = reader.ReadUInt16();
            header.DiskNumberStart             = reader.ReadUInt16();
            header.InternalFileAttributes      = reader.ReadUInt16();
            header.ExternalFileAttributes      = reader.ReadUInt32();
            header.RelativeOffsetOfLocalHeader = reader.ReadUInt32();
            header.FileName                    = reader.ReadBytes(header.FileNameLength);
            header.ExtraField                  = reader.ReadBytes(header.ExtraFieldLength);
            header.FileComment                 = reader.ReadBytes(header.FileCommentLength);

            return(true);
        }
        internal static bool TryRead(CentralDirectoryHeader header, out IReadOnlyList <ExtraField> extraFields)
        {
            extraFields = null;

            if (header.ExtraFieldLength == 0)
            {
                return(false);
            }

            var readUncompressedFileSize        = header.UncompressedSize == ZipConstants.Mask32Bit;
            var readCompressedFileSize          = header.CompressedSize == ZipConstants.Mask32Bit;
            var readRelativeOffsetOfLocalHeader = header.RelativeOffsetOfLocalHeader == ZipConstants.Mask32Bit;
            var readDiskNumberStart             = header.DiskNumberStart == ZipConstants.Mask16Bit;

            return(TryRead(
                       header.ExtraField,
                       readUncompressedFileSize,
                       readCompressedFileSize,
                       readRelativeOffsetOfLocalHeader,
                       readDiskNumberStart,
                       out extraFields));
        }
Ejemplo n.º 8
0
        /// <summary>
        /// Utility method to know if a zip archive is signed.
        /// </summary>
        /// <param name="reader">Binary reader pointing to a zip archive.</param>
        /// <returns>true if the given archive is signed</returns>
        private static bool IsSigned(BinaryReader reader)
        {
            try
            {
                var endOfCentralDirectoryRecord = EndOfCentralDirectoryRecord.Read(reader);

                // Look for signature central directory record
                reader.BaseStream.Seek(endOfCentralDirectoryRecord.OffsetOfStartOfCentralDirectory, SeekOrigin.Begin);
                CentralDirectoryHeader header;

                while (CentralDirectoryHeader.TryRead(reader, out header))
                {
                    var isUtf8   = IsUtf8(header.GeneralPurposeBitFlag);
                    var fileName = GetString(header.FileName, isUtf8);

                    if (string.Equals(fileName, _signingSpecification.SignaturePath, StringComparison.Ordinal))
                    {
                        // Go to local file header
                        reader.BaseStream.Seek(header.RelativeOffsetOfLocalHeader, SeekOrigin.Begin);

                        // Make sure file header exists there
                        var fileHeaderSignature = reader.ReadUInt32();
                        if (fileHeaderSignature != LocalFileHeader.Signature)
                        {
                            throw new InvalidDataException(Strings.ErrorInvalidPackageArchive);
                        }

                        return(true);
                    }
                }
            }
            // Ignore any exception. If something is thrown it means the archive is either not valid or not signed
            catch { }

            return(false);
        }
        /// <summary>
        /// Read ZIP's offsets and positions of offsets.
        /// </summary>
        /// <param name="reader">binary reader to zip archive</param>
        /// <returns>metadata with offsets and positions for entries</returns>
        public static SignedPackageArchiveMetadata ReadSignedArchiveMetadata(BinaryReader reader)
        {
            if (reader == null)
            {
                throw new ArgumentNullException(nameof(reader));
            }

            var metadata = new SignedPackageArchiveMetadata()
            {
                StartOfLocalFileHeaders = reader.BaseStream.Length
            };

            var endOfCentralDirectoryRecord         = EndOfCentralDirectoryRecord.Read(reader);
            var endOfCentralDirectoryRecordPosition = endOfCentralDirectoryRecord.OffsetFromStart;

            reader.BaseStream.Seek(endOfCentralDirectoryRecord.OffsetOfStartOfCentralDirectory, SeekOrigin.Begin);

            var centralDirectoryRecords           = new List <CentralDirectoryHeaderMetadata>();
            var packageSignatureFileMetadataIndex = -1;
            var index = 0;

            while (CentralDirectoryHeader.TryRead(reader, out var header))
            {
                metadata.StartOfLocalFileHeaders = Math.Min(metadata.StartOfLocalFileHeaders, header.RelativeOffsetOfLocalHeader);

                var isPackageSignatureFile = SignedPackageArchiveUtility.IsPackageSignatureFileEntry(
                    header.FileName,
                    header.GeneralPurposeBitFlag);

                if (isPackageSignatureFile)
                {
                    if (packageSignatureFileMetadataIndex != -1)
                    {
                        throw new SignatureException(NuGetLogCode.NU3005, Strings.MultiplePackageSignatureFiles);
                    }

                    packageSignatureFileMetadataIndex = index;
                }

                var centralDirectoryMetadata = new CentralDirectoryHeaderMetadata()
                {
                    Position = header.OffsetFromStart,
                    OffsetToLocalFileHeader = header.RelativeOffsetOfLocalHeader,
                    IsPackageSignatureFile  = isPackageSignatureFile,
                    HeaderSize     = header.GetSizeInBytes(),
                    IndexInHeaders = index
                };

                centralDirectoryRecords.Add(centralDirectoryMetadata);

                ++index;
            }

            if (centralDirectoryRecords.Count == 0)
            {
                throw new InvalidDataException(Strings.ErrorInvalidPackageArchive);
            }

            if (packageSignatureFileMetadataIndex == -1)
            {
                throw new SignatureException(NuGetLogCode.NU3005, Strings.NoPackageSignatureFile);
            }

            var lastCentralDirectoryRecord    = centralDirectoryRecords.Last();
            var endOfCentralDirectoryPosition = lastCentralDirectoryRecord.Position + lastCentralDirectoryRecord.HeaderSize;
            var endOfLocalFileHeadersPosition = GetEndOfLocalFileHeadersPosition(reader, centralDirectoryRecords);

            metadata.EndOfCentralDirectory   = lastCentralDirectoryRecord.Position + lastCentralDirectoryRecord.HeaderSize;
            metadata.CentralDirectoryHeaders = centralDirectoryRecords;
            metadata.EndOfLocalFileHeaders   = endOfLocalFileHeadersPosition;
            metadata.SignatureCentralDirectoryHeaderIndex = packageSignatureFileMetadataIndex;

            AssertSignatureEntryMetadata(reader, metadata);

            return(metadata);
        }