Merged PR 1189137: Add schema validation of [content_types].xml

Change adds three new test cases: 2 w.r.t. [content_types].xml and one w.r.t. an invalid opc container due to an invalid zip archive (something we were otherwise missing in our test collateral).  The opc-contentTypes XSD comes straight from the ECMA 376 standard: https://www.ecma-international.org/publications/standards/Ecma-376.htm  Confirmed that makeappx fails with OPC_E_INVALID_CONTENT_TYPE_XML (0x80510006 ) and OPC_E_NONCONFORMING_CONTENT_TYPES_XML (0x80510008) with both of these packages when using the /nv switch (to get around the fact that technically, the signatures aren't valid).

The only code change required for this validation was to include the XSD, and pass it to the XmlObject, everything else was already wired up (as per blockmap validation).

Related work items: #14986525
This commit is contained in:
Phil Smith 2017-12-08 19:57:41 +00:00
Родитель feca8bdc23
Коммит 03d0425e0d
7 изменённых файлов: 75 добавлений и 2 удалений

3
.gitignore поставляемый
Просмотреть файл

@ -397,4 +397,5 @@ __pycache__/
lib/zlib
# Files generated by CMake
src/inc/AppxCerts.hpp
src/inc/AppxBlockMapSchemas.hpp
src/inc/AppxBlockMapSchemas.hpp
src/inc/ContentTypesSchemas.hpp

Просмотреть файл

@ -0,0 +1,60 @@
<?xml version="1.0" encoding="UTF-8" standalone="no"?>
<xs:schema xmlns="http://schemas.openxmlformats.org/package/2006/content-types" xmlns:xs="http://www.w3.org/2001/XMLSchema" targetNamespace="http://schemas.openxmlformats.org/package/2006/content-types" elementFormDefault="qualified" attributeFormDefault="unqualified" blockDefault="#all">
<!--
Individual patterns for content type grammar
For better readability, each pattern using numbers is also described in a comment using
one of the following pattern designators.
-->
<!--DEFINE [media-type] "([type]/[subtype]([LWS]*;[LWS]*[parameter])*)" -->
<!--DEFINE [parameter] "([attribute]=[value])" -->
<!--DEFINE [attribute] "([token])" -->
<!--DEFINE [value] "([token]|[quoted-string])" -->
<!--DEFINE [subtype] "([token])" -->
<!--DEFINE [type] "([token])" -->
<!--DEFINE [quoted-string] "(&quot;([qdtext]|[quoted-pair])*&quot;)" -->
<!--DEFINE [qdtext] "([\p{IsLatin-1Supplement}\p{IsBasicLatin}-[\p{Cc}[DEL]&quot;\n\r]]|[LWS])" -->
<!--DEFINE [quoted-pair] "(\\[CHAR])" -->
<!--DEFINE [LWS] "([SP]+)" -->
<!--DEFINE [CHAR] "[\p{IsBasicLatin}]" -->
<!--DEFINE [separators] "[\(\)&lt;&gt;@,;:\\&quot;/\[\]\?=\{\} \t]" -->
<!--DEFINE [token] "(([\p{IsBasicLatin}-[\p{Cc}[DEL]\(\)&lt;&gt;@,;:\\&quot;/\[\]\?=\{\}\s\t]])+)" -->
<!--DEFINE [SP] "\s" -->
<!--DEFINE [DEL] "&#127;" -->
<xs:element name="Types" type="CT_Types" />
<xs:element name="Default" type="CT_Default" />
<xs:element name="Override" type="CT_Override" />
<xs:complexType name="CT_Types">
<xs:choice minOccurs="0" maxOccurs="unbounded">
<xs:element ref="Default" />
<xs:element ref="Override" />
</xs:choice>
</xs:complexType>
<xs:complexType name="CT_Default">
<xs:attribute name="Extension" type="ST_Extension" use="required" />
<xs:attribute name="ContentType" type="ST_ContentType" use="required" />
</xs:complexType>
<xs:complexType name="CT_Override">
<xs:attribute name="ContentType" type="ST_ContentType" use="required" />
<xs:attribute name="PartName" type="xs:anyURI" use="required" />
</xs:complexType>
<xs:simpleType name="ST_ContentType">
<xs:restriction base="xs:string">
<!--
<xs:pattern value="[media-type]"/>
-->
<xs:pattern value="(((([\p{IsBasicLatin}-[\p{Cc}&#127;\(\)&lt;&gt;@,;:\\&quot;/\[\]\?=\{\}\s\t]])+))/((([\p{IsBasicLatin}-[\p{Cc}&#127;\(\)&lt;&gt;@,;:\\&quot;/\[\]\?=\{\}\s\t]])+))((\s+)*;(\s+)*(((([\p{IsBasicLatin}-[\p{Cc}&#127;\(\)&lt;&gt;@,;:\\&quot;/\[\]\?=\{\}\s\t]])+))=((([\p{IsBasicLatin}-[\p{Cc}&#127;\(\)&lt;&gt;@,;:\\&quot;/\[\]\?=\{\}\s\t]])+)|(&quot;(([\p{IsLatin-1Supplement}\p{IsBasicLatin}-[\p{Cc}&#127;&quot;\n\r]]|(\s+))|(\\[\p{IsBasicLatin}]))*&quot;))))*)" />
</xs:restriction>
</xs:simpleType>
<xs:simpleType name="ST_Extension">
<xs:restriction base="xs:string">
<xs:pattern value="([!$&amp;'\(\)\*\+,:=]|(%[0-9a-fA-F][0-9a-fA-F])|[:@]|[a-zA-Z0-9\-_~])+" />
</xs:restriction>
</xs:simpleType>
</xs:schema>

Просмотреть файл

@ -5,6 +5,7 @@
#include "StorageObject.hpp"
#include "AppxPackageObject.hpp"
#include "UnicodeConversion.hpp"
#include "ContentTypesSchemas.hpp"
#include <string>
#include <vector>
@ -127,7 +128,7 @@ namespace xPlat {
// 2. Get content type using signature object for validation
// TODO: switch underlying type of m_contentType to something more specific.
auto temp = m_appxSignature->GetValidationStream(CONTENT_TYPES_XML, m_container->GetFile(CONTENT_TYPES_XML));
m_contentType = ComPtr<IVerifierObject>::Make<XmlObject>(temp);
m_contentType = ComPtr<IVerifierObject>::Make<XmlObject>(temp, &contentTypesSchema);
ThrowErrorIfNot(Error::AppxMissingContentTypesXML, (m_contentType->HasStream()), "[Content_Types].xml not in archive!");
// 3. Get blockmap object using signature object for validation

Просмотреть файл

@ -52,6 +52,17 @@ std::map<std::string, std::string> blockMapSchema = {
")
file(WRITE "../inc/AppxBlockMapSchemas.hpp" "${BLOCKMAP_HEADER}")
# Create header for [Content_Types] schema
file(READ "${CMAKE_PROJECT_ROOT}/AppxPackaging/[Content_Types]/opc-contentTypes.xsd" CONTENT_TYPES_SCHEMA)
set(CONTENT_TYPES_HEADER "// This file is generated by CMake and contains XSDs for parsing [Content_Types].xml. Do not edit!!
#include <string>
#include <map>
std::map<std::string, std::string> contentTypesSchema = {
{\"contentTypesSchemaRaw\", R\"###(${CONTENT_TYPES_SCHEMA})###\" }
};
")
file(WRITE "../inc/ContentTypesSchemas.hpp" "${CONTENT_TYPES_HEADER}")
set(LIB_PUBLIC_HEADERS
../inc/AppxPackaging.hpp
../inc/AppxWindows.hpp

Двоичные данные
test/appx/InvalidSignatureBadCodeIntegrity.appx Normal file

Двоичный файл не отображается.

Двоичные данные
test/appx/InvalidSignatureInvalidCodeIntegrityXML.appx Normal file

Двоичный файл не отображается.

Двоичные данные
test/appx/OPC_E_ZIP_CORRUPTED_ARCHIVE.appx Normal file

Двоичный файл не отображается.