/// <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 void AssertSignatureEntryCommonHeaderFields( BinaryReader reader, CentralDirectoryHeaderMetadata signatureCentralDirectoryHeader, string errorPrefix, string errorSuffix) { var signatureEntryErrorCode = NuGetLogCode.NU3005; // Assert general purpose bits to 0 uint actualValue = reader.ReadUInt16(); AssertValue( expectedValue: 0U, actualValue: actualValue, errorCode: signatureEntryErrorCode, errorMessagePrefix: errorPrefix, errorMessageSuffix: errorSuffix, fieldName: "general purpose bit"); // Assert compression method to 0 actualValue = reader.ReadUInt16(); AssertValue( expectedValue: 0U, actualValue: actualValue, errorCode: signatureEntryErrorCode, errorMessagePrefix: errorPrefix, errorMessageSuffix: errorSuffix, fieldName: "compression method"); // skip date (2 bytes), time (2 bytes) and crc32 (4 bytes) reader.BaseStream.Seek(offset: 8L, origin: SeekOrigin.Current); // assert that file compressed and uncompressed sizes are the same var compressedSize = reader.ReadUInt32(); var uncompressedSize = reader.ReadUInt32(); if (compressedSize != uncompressedSize) { var failureCause = string.Format( CultureInfo.CurrentCulture, errorSuffix, "compressed size", compressedSize); throw new SignatureException( signatureEntryErrorCode, string.Format(CultureInfo.CurrentCulture, errorPrefix, failureCause)); } }
private static LocalFileHeader ReadPackageSignatureFileLocalFileHeader( BinaryReader reader, CentralDirectoryHeaderMetadata signatureCentralDirectoryHeader) { reader.BaseStream.Seek(signatureCentralDirectoryHeader.OffsetToLocalFileHeader, SeekOrigin.Begin); LocalFileHeader header; if (!LocalFileHeader.TryRead(reader, out header)) { throw new SignatureException(NuGetLogCode.NU3005, Strings.InvalidPackageSignatureFile); } return(header); }
private static Stream GetPackageSignatureFile( BinaryReader reader, CentralDirectoryHeaderMetadata signatureCentralDirectoryHeader) { var localFileHeader = ReadPackageSignatureFileLocalFileHeader(reader, signatureCentralDirectoryHeader); var offsetToData = signatureCentralDirectoryHeader.OffsetToLocalFileHeader + LocalFileHeader.SizeInBytesOfFixedLengthFields + localFileHeader.FileNameLength + localFileHeader.ExtraFieldLength; var buffer = new byte[localFileHeader.UncompressedSize]; reader.BaseStream.Seek(offsetToData, SeekOrigin.Begin); reader.BaseStream.Read(buffer, offset: 0, count: buffer.Length); return(new MemoryStream(buffer, writable: 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)); }
/// <summary> /// Asserts the validity of central directory header and local file header for the package signature file entry. /// </summary> /// <param name="reader">BinaryReader on the package.</param> /// <param name="signatureCentralDirectoryHeader">Metadata for the package signature file's central directory header.</param> /// <exception cref="SignatureException">Thrown if either header is invalid.</exception> public static void AssertSignatureEntryMetadata(BinaryReader reader, CentralDirectoryHeaderMetadata signatureCentralDirectoryHeader) { // Move to central directory header and skip header signature (4 bytes) and version fields (2 entries of 2 bytes each) reader.BaseStream.Seek(offset: signatureCentralDirectoryHeader.Position + 8L, origin: SeekOrigin.Begin); // check central directory file header AssertSignatureEntryCommonHeaderFields( reader, signatureCentralDirectoryHeader, Strings.InvalidPackageSignatureFileEntry, Strings.InvalidPackageSignatureFileEntryCentralDirectoryHeader); // Skip file name length (2 bytes), extra field length (2 bytes), file comment length (2 bytes), // disk number start (2 bytes), and internal file attributes (2 bytes) reader.BaseStream.Seek(offset: 10, origin: SeekOrigin.Current); var externalFileAttributes = reader.ReadUInt32(); AssertValue( expectedValue: 0U, actualValue: externalFileAttributes, errorCode: NuGetLogCode.NU3005, errorMessagePrefix: Strings.InvalidPackageSignatureFileEntry, errorMessageSuffix: Strings.InvalidPackageSignatureFileEntryCentralDirectoryHeader, fieldName: "external file attributes"); // Move to local file header and skip header signature (4 bytes) and version field (2 bytes) reader.BaseStream.Seek(offset: signatureCentralDirectoryHeader.OffsetToFileHeader + 6L, origin: SeekOrigin.Begin); // check local file header AssertSignatureEntryCommonHeaderFields( reader, signatureCentralDirectoryHeader, Strings.InvalidPackageSignatureFileEntry, Strings.InvalidPackageSignatureFileEntryLocalFileHeader); }
/// <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); }