Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

feat: restrict obfuscation to font core media types #1382

Merged
merged 1 commit into from
Dec 5, 2022
Merged
Show file tree
Hide file tree
Changes from all commits
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 @@ -302,6 +302,7 @@ private void initialize()
severities.put(MessageId.PKG_023, Severity.USAGE);
severities.put(MessageId.PKG_024, Severity.INFO);
severities.put(MessageId.PKG_025, Severity.ERROR);
severities.put(MessageId.PKG_026, Severity.ERROR);

// Resources
severities.put(MessageId.RSC_001, Severity.ERROR);
Expand Down
1 change: 1 addition & 0 deletions src/main/java/com/adobe/epubcheck/messages/MessageId.java
Original file line number Diff line number Diff line change
Expand Up @@ -296,6 +296,7 @@ public enum MessageId implements Comparable<MessageId>
PKG_023("PKG-023"),
PKG_024("PKG-024"),
PKG_025("PKG-025"),
PKG_026("PKG-026"),

// Messages relating to resources
RSC_001("RSC-001"),
Expand Down
8 changes: 5 additions & 3 deletions src/main/java/com/adobe/epubcheck/ocf/EncryptionHandler.java
Original file line number Diff line number Diff line change
Expand Up @@ -22,14 +22,15 @@

package com.adobe.epubcheck.ocf;

import java.io.UnsupportedEncodingException;
import java.net.URLDecoder;

import com.adobe.epubcheck.api.EPUBLocation;
import com.adobe.epubcheck.util.HandlerUtil;
import com.adobe.epubcheck.xml.XMLElement;
import com.adobe.epubcheck.xml.XMLHandler;
import com.adobe.epubcheck.xml.XMLParser;

import java.io.UnsupportedEncodingException;
import java.net.URLDecoder;

public class EncryptionHandler implements XMLHandler
{
private final OCFPackage ocf;
Expand Down Expand Up @@ -83,6 +84,7 @@ public void startElement()
if (algorithm.equals("http://www.idpf.org/2008/embedding"))
{
ocf.setEncryption(entryName, new IDPFFontManglingFilter(null));
ocf.setObfuscated(entryName, parser.getLocation());
}
else if (algorithm.equals("http://ns.adobe.com/pdf/enc#RC"))
{
Expand Down
26 changes: 25 additions & 1 deletion src/main/java/com/adobe/epubcheck/ocf/OCFChecker.java
Original file line number Diff line number Diff line change
Expand Up @@ -51,9 +51,11 @@
import com.adobe.epubcheck.api.Report;
import com.adobe.epubcheck.messages.MessageId;
import com.adobe.epubcheck.opf.OPFChecker;
import com.adobe.epubcheck.opf.OPFChecker30;
import com.adobe.epubcheck.opf.OPFData;
import com.adobe.epubcheck.opf.OPFHandler;
import com.adobe.epubcheck.opf.OPFHandler30;
import com.adobe.epubcheck.opf.OPFItem;
import com.adobe.epubcheck.opf.ValidationContext;
import com.adobe.epubcheck.opf.ValidationContext.ValidationContextBuilder;
import com.adobe.epubcheck.util.CheckUtil;
Expand All @@ -64,6 +66,7 @@
import com.adobe.epubcheck.xml.XMLParser;
import com.adobe.epubcheck.xml.XMLValidator;
import com.adobe.epubcheck.xml.XMLValidators;
import com.google.common.base.Optional;
import com.google.common.base.Preconditions;
import com.google.common.base.Predicate;
import com.google.common.base.Predicates;
Expand Down Expand Up @@ -349,7 +352,7 @@ else if (!normalizedEntriesSet.add(Normalizer.normalize(entry, Form.NFC)))
for (final String entry : ocf.getFileEntries())
{
ocf.reportMetadata(entry, report);

// if the entry is not in the whitelist (META-INF/* + mimetype)
// and not declared in (one of) the OPF document(s)
if (!entry.startsWith("META-INF/") && !entry.startsWith("META-INF\\")
Expand All @@ -371,6 +374,27 @@ public boolean apply(OPFHandler opfHandler)
report.message(MessageId.OPF_003, EPUBLocation.create(ocf.getName()), entry);
}
OCFFilenameChecker.checkCompatiblyEscaped(entry, report, validationVersion);

// check obfuscated resource are Font Core Media Types
if (ocf.isObfuscatedFont(entry))
{
for (OPFHandler opf : opfHandlers)
{
// try to find the first Package Document where the entry is
// declared
Optional<OPFItem> item = opf.getItemByPath(entry);
if (item.isPresent())
{
// report if it is not a font core media type
if (!OPFChecker30.isBlessedFontType(item.get().getMimeType()))
{
report.message(MessageId.PKG_026, ocf.getObfuscationDeclarationLocation(entry),
item.get().getMimeType(), opf.getPath());
}
break;
}
}
}
}

// check all directory entries without duplicates
Expand Down
34 changes: 28 additions & 6 deletions src/main/java/com/adobe/epubcheck/ocf/OCFPackage.java
Original file line number Diff line number Diff line change
Expand Up @@ -4,7 +4,6 @@
import java.io.InputStream;
import java.util.Collections;
import java.util.HashMap;
import java.util.Hashtable;
import java.util.List;
import java.util.Map;
import java.util.Set;
Expand All @@ -26,7 +25,8 @@

public abstract class OCFPackage implements GenericResourceProvider
{
final Hashtable<String, EncryptionFilter> enc;
final Map<String, EncryptionFilter> enc = new HashMap<>();
final Map<String, EPUBLocation> obfuscated = new HashMap<>();
String uniqueIdentifier;
private Report reporter;
private final Supplier<OCFData> ocfData = Suppliers.memoize(new Supplier<OCFData>()
Expand Down Expand Up @@ -72,16 +72,17 @@ public Map<String, OPFData> get()
}
});

public OCFPackage()
{
this.enc = new Hashtable<String, EncryptionFilter>();
}

public void setEncryption(String name, EncryptionFilter encryptionFilter)
{
enc.put(name, encryptionFilter);
}

public void setObfuscated(String name, EPUBLocation location)
{
obfuscated.put(name, location);
}

/**
* @param name
* the name of a relative file that is possibly in the container
Expand Down Expand Up @@ -133,6 +134,27 @@ public boolean canDecrypt(String fileName)
return filter == null || filter.canDecrypt();
}

/**
* @param path path of the resource to test
* @return true if that resource is encrypted with the font obfuscation algorithm
*/
public boolean isObfuscatedFont(String path)
{
return obfuscated.containsKey(path);
}

/**
* Returns the location in META-INF/encryption.xml where the given resource
* is declared as an obfuscated font, or <code>null</code> if it is not.
*
* @param path path of the resource to test
* @return the location in META-INF/encryption.xml, or null
*/
public EPUBLocation getObfuscationDeclarationLocation(String path)
{
return obfuscated.get(path);
}

/**
* This method parses the container entry and stores important data, but does
* /not/ validate the container against a schema definition.
Expand Down
4 changes: 4 additions & 0 deletions src/main/java/com/adobe/epubcheck/opf/OPFHandler.java
Original file line number Diff line number Diff line change
Expand Up @@ -127,6 +127,10 @@ public OPFHandler(ValidationContext context, XMLParser parser)
this.report = context.report;
this.parser = parser;
}

public String getPath() {
return path;
}

public boolean getOpf12PackageFile()
{
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -313,7 +313,8 @@ PKG_022=Wrong file extension for image. The image is a "%1$s" file but has the f
PKG_023=Validating the EPUB against version 2.0, default validation profile will be used.
PKG_024=Uncommon EPUB file extension.
PKG_024_SUG=For maximum compatibility, use ".epub".
PKG_025=Publication resource must not be located in the META-INF directory
PKG_025=Publication resource must not be located in the META-INF directory
PKG_026=Obfuscated resource must be a Font Core Media Type (was declared as "%1$s" in "%2$s").

#Resources
RSC_001=File "%1$s" could not be found.
Expand Down
22 changes: 14 additions & 8 deletions src/test/resources/epub3/container-publication.feature
Original file line number Diff line number Diff line change
Expand Up @@ -119,9 +119,10 @@ Feature: EPUB 3 ▸ Open Container Format ▸ Full Publication Checks
And the message contains 'expected element "encryption"'
And no other errors or warnings are reported

Scenario: Report an unknown encryption scheme
Scenario: Verify encryption can be used
(but file will not be parsed)
Given the reporting level is set to INFO
When checking EPUB 'ocf-encryption-unknown-error'
When checking EPUB 'ocf-encryption-unknown-valid'
Then info RSC-004 is reported
And no other errors or warnings are reported

Expand Down Expand Up @@ -180,16 +181,21 @@ Feature: EPUB 3 ▸ Open Container Format ▸ Full Publication Checks


## 5. Resource Obfuscation
Scenario: Verify a publication with obfuscated resource (here a font file)

Scenario: Verify a publication with obfuscated font
When checking EPUB 'ocf-obfuscation-valid'
Then no errors or warnings are reported

Scenario: Verify a publication with obfuscation of a usually-parsed resource (here an SVG image)
When checking EPUB 'ocf-obfuscation-svg-valid'
Then info RSC-004 is reported
Scenario: Report an obfuscated font that is not a Core Media Type
When checking EPUB 'ocf-obfuscation-not-cmt-error'
Then error PKG-026 is reported
And no errors or warnings are reported


Scenario: Report an obfuscated font that is not a font
When checking EPUB 'ocf-obfuscation-not-font-error'
Then error PKG-026 is reported
And no errors or warnings are reported


## C. the 'application/epub+zip' Media Type

Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,11 @@
<!DOCTYPE html>
<html xmlns="http://www.w3.org/1999/xhtml" xml:lang="en" lang="en">
<head>
<meta charset="utf-8"/>
<title>Minimal EPUB</title>
</head>
<body>
<h1>Loomings</h1>
<p>Call me Ishmael.</p>
</body>
</html>
Original file line number Diff line number Diff line change
@@ -0,0 +1,14 @@
<!DOCTYPE html>
<html xmlns="http://www.w3.org/1999/xhtml" xmlns:epub="http://www.idpf.org/2007/ops" xml:lang="en" lang="en">
<head>
<meta charset="utf-8"/>
<title>Minimal Nav</title>
</head>
<body>
<nav epub:type="toc">
<ol>
<li><a href="content_001.xhtml">content 001</a></li>
</ol>
</nav>
</body>
</html>
Binary file not shown.
Original file line number Diff line number Diff line change
@@ -0,0 +1,17 @@
<?xml version="1.0" encoding="UTF-8"?>
<package xmlns="http://www.idpf.org/2007/opf" version="3.0" xml:lang="en" unique-identifier="q">
<metadata xmlns:dc="http://purl.org/dc/elements/1.1/">
<dc:title id="title">Minimal EPUB 3.0</dc:title>
<dc:language>en</dc:language>
<dc:identifier id="q">NOID</dc:identifier>
<meta property="dcterms:modified">2017-06-14T00:00:01Z</meta>
</metadata>
<manifest>
<item id="content_001" href="content_001.xhtml" media-type="application/xhtml+xml"/>
<item id="nav" href="nav.xhtml" media-type="application/xhtml+xml" properties="nav"/>
<item id="font" href="obfuscated-font.otf" media-type="font/opentype"/>
</manifest>
<spine>
<itemref idref="content_001" />
</spine>
</package>
Original file line number Diff line number Diff line change
@@ -0,0 +1,6 @@
<?xml version="1.0" encoding="UTF-8" ?>
<container version="1.0" xmlns="urn:oasis:names:tc:opendocument:xmlns:container">
<rootfiles>
<rootfile full-path="EPUB/package.opf" media-type="application/oebps-package+xml"/>
</rootfiles>
</container>
Original file line number Diff line number Diff line change
@@ -0,0 +1,9 @@
<?xml version="1.0" encoding="UTF-8"?>
<encryption xmlns="urn:oasis:names:tc:opendocument:xmlns:container">
<EncryptedData xmlns="http://www.w3.org/2001/04/xmlenc#">
<EncryptionMethod Algorithm="http://www.idpf.org/2008/embedding"/>
<CipherData>
<CipherReference URI="EPUB/obfuscated-font.otf"/>
</CipherData>
</EncryptedData>
</encryption>
Original file line number Diff line number Diff line change
Expand Up @@ -7,6 +7,5 @@
<body epub:type="bodymatter">
<h1>Loomings</h1>
<p>Call me Ishmael.</p>
<img src="emoji.svg" alt="a smiling emoji" />
</body>
</html>
Original file line number Diff line number Diff line change
Expand Up @@ -9,7 +9,7 @@
<manifest>
<item id="content_001" href="content_001.xhtml" media-type="application/xhtml+xml"/>
<item id="nav" href="nav.xhtml" media-type="application/xhtml+xml" properties="nav"/>
<item id="emoji" href="emoji.svg" media-type="image/svg+xml"/>
<item id="doc" href="doc.xml" media-type="application/xml"/>
</manifest>
<spine>
<itemref idref="content_001" />
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -4,7 +4,7 @@
<enc:EncryptedData>
<enc:EncryptionMethod Algorithm="http://www.idpf.org/2008/embedding"/>
<enc:CipherData>
<enc:CipherReference URI="EPUB/emoji.svg"/>
<enc:CipherReference URI="EPUB/doc.xml"/>
</enc:CipherData>
</enc:EncryptedData>
</encryption>
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
application/epub+zip
Original file line number Diff line number Diff line change
Expand Up @@ -9,7 +9,7 @@
<manifest>
<item id="content_001" href="content_001.xhtml" media-type="application/xhtml+xml"/>
<item id="nav" href="nav.xhtml" media-type="application/xhtml+xml" properties="nav"/>
<item id="font" href="obfuscated-font.otf" media-type="font/opentype"/>
<item id="font" href="obfuscated-font.otf" media-type="font/otf"/>
</manifest>
<spine>
<itemref idref="content_001" />
Expand Down