Skip to content
Merged
Show file tree
Hide file tree
Changes from 1 commit
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
Original file line number Diff line number Diff line change
Expand Up @@ -8,6 +8,7 @@
using System.Diagnostics.CodeAnalysis;
using System.IO;
using System.IO.Packaging;
using System.Linq;

namespace DocumentFormat.OpenXml.Features;

Expand Down Expand Up @@ -56,7 +57,12 @@ public StreamPackageFeature(Stream stream, PackageOpenMode openMode, bool isOwne
}
catch when (isOwned)
{
// Ensure that the stream if created is disposed before leaving the constructor so we don't hold onto it
if (_stream is not null && IsEncryptedOfficeFile(_stream))
{
_stream.Dispose();
throw new OpenXmlPackageException(ExceptionMessages.EncryptedPackageNotSupported);
}

_stream?.Dispose();
throw;
}
Expand Down Expand Up @@ -172,4 +178,54 @@ protected override void Register(IFeatureCollection features)
features.Set<IPackageStreamFeature>(this);
features.GetRequired<IDisposableFeature>().Register(this);
}

private static bool IsEncryptedOfficeFile(Stream inputStream)
{
if (!inputStream.CanSeek)
{
throw new ArgumentException("Stream must be seekable.");
}

long originalPosition = inputStream.Position;

try
{
byte[] header = new byte[8];
inputStream.Seek(0, SeekOrigin.Begin);
int read = inputStream.Read(header, 0, header.Length);
inputStream.Seek(originalPosition, SeekOrigin.Begin);

// OLE Compound File signature for encrypted Office files
byte[] oleSignature = { 0xD0, 0xCF, 0x11, 0xE0, 0xA1, 0xB1, 0x1A, 0xE1 };
if (read == 8 && header.SequenceEqual(oleSignature))
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Suggested change
byte[] oleSignature = { 0xD0, 0xCF, 0x11, 0xE0, 0xA1, 0xB1, 0x1A, 0xE1 };
if (read == 8 && header.SequenceEqual(oleSignature))
if (read == 8 && header.SequenceEqual([ 0xD0, 0xCF, 0x11, 0xE0, 0xA1, 0xB1, 0x1A, 0xE1 ]))

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

not a big deal and may make readability worse, but on some platforms it may prevent an allocation (that is probably not a big deal at all)

{
return true;
}

// If not OLE, try to open as package and check for encrypted part
try
{
using (var package = System.IO.Packaging.Package.Open(inputStream, FileMode.Open, FileAccess.Read))
{
foreach (var part in package.GetParts())
{
if (part.ContentType.Equals("application/vnd.openxmlformats-officedocument.encrypted-package", StringComparison.OrdinalIgnoreCase))
{
return true;
}
}
}
}
catch
{
return false;
}

return false;
}
finally
{
inputStream.Seek(originalPosition, SeekOrigin.Begin);
}
}
}

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

Original file line number Diff line number Diff line change
Expand Up @@ -414,4 +414,7 @@
<data name="FirstOrDefaultMaxOne" xml:space="preserve">
<value>The enumerable contained more than a single element when only zero or one are allowed.</value>
</data>
<data name="EncryptedPackageNotSupported" xml:space="preserve">
<value>Encrypted packages are not supported.</value>
</data>
</root>
Original file line number Diff line number Diff line change
Expand Up @@ -10,6 +10,7 @@
using System.IO.Packaging;
using System.Linq;
using Xunit;
using static DocumentFormat.OpenXml.Tests.TestAssets;

Check warning on line 13 in test/DocumentFormat.OpenXml.Framework.Tests/Features/StreamPackageFeatureTests.cs

View workflow job for this annotation

GitHub Actions / Analyze (csharp)

Check warning on line 13 in test/DocumentFormat.OpenXml.Framework.Tests/Features/StreamPackageFeatureTests.cs

View workflow job for this annotation

GitHub Actions / Analyze (csharp)


namespace DocumentFormat.OpenXml.Features.Tests;

Expand Down Expand Up @@ -431,6 +432,18 @@
}
}

[Fact]
public void ThrowsForEncryptedOfficeFile()
{
using (Stream stream = GetStream(TestFiles.Encrypted_pptx, false))
{
// Act & Assert
var ex = Assert.Throws<OpenXmlPackageException>(() => new StreamPackageFeature(stream, PackageOpenMode.Read, isOwned: true));
Assert.Equal(ExceptionMessages.EncryptedPackageNotSupported, ex.Message);
}

}

Check warning on line 445 in test/DocumentFormat.OpenXml.Framework.Tests/Features/StreamPackageFeatureTests.cs

View workflow job for this annotation

GitHub Actions / Analyze (csharp)

Check warning on line 445 in test/DocumentFormat.OpenXml.Framework.Tests/Features/StreamPackageFeatureTests.cs

View workflow job for this annotation

GitHub Actions / Analyze (csharp)


private static readonly PartInfo Part1 = new(new("/part1", UriKind.Relative), "type1/content");
private static readonly PartInfo Part2 = new(new("/part2", UriKind.Relative), "type2/content");
private static readonly PartInfo PartRels = new(new("/_rels/.rels", UriKind.Relative), "application/vnd.openxmlformats-package.relationships+xml");
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -127,6 +127,8 @@ public static class Templates
public const string Of16_09_unknownelement_docx = "TestFiles.Of16-09-UnknownElement.docx";

public const string Of16_10_symex_docx = "TestFiles.Of16-10-SymEx.docx";

public const string Encrypted_pptx = "TestFiles.encrypted_pptx.pptx";
}
}
}
Binary file not shown.
Loading