Updated IPP Opcode/Attribute validation
We no longer validate specific attribute groupings within operations.
Instead we validate at the per-attribute level only, confirming the same
information as before, and leaving any higher-logic validating to
CUPS.
Bug: chromium:945409
Test: manually confirmed valid attribute/opcode set
Change-Id: I8c2541a8b7a1957239c2468526b75b2a77450646
Reviewed-on: https://chromium-review.googlesource.com/c/chromium/src/+/1704696
Reviewed-by: Sean Kau <skau@chromium.org>
Commit-Queue: Luum Habtemariam <luum@chromium.org>
Cr-Commit-Position: refs/heads/master@{#682451}
diff --git a/chrome/services/cups_proxy/ipp_attribute_validator.cc b/chrome/services/cups_proxy/ipp_attribute_validator.cc
index bfd4555..ccddf35 100644
--- a/chrome/services/cups_proxy/ipp_attribute_validator.cc
+++ b/chrome/services/cups_proxy/ipp_attribute_validator.cc
@@ -15,649 +15,188 @@
namespace {
-// represents a type of a single attribute
+using ValueType = cups_ipp_parser::mojom::ValueType;
+
+// Represents the type of a single attribute.
struct AttributeDefinition {
- bool is_a_set;
- cups_ipp_parser::mojom::ValueType type;
+ bool multivalued;
+
+ // Internal serialization type.
+ ValueType type;
};
-// definitions of all known attributes grouped by operations
-std::map<ipp_op_t, std::map<std::string, AttributeDefinition>>
- attributesDefinitions = {
- {IPP_OP_CUPS_GET_PPD,
- {
- {"attributes-charset",
- {false, cups_ipp_parser::mojom::ValueType::STRING}},
- {"attributes-natural-language",
- {false, cups_ipp_parser::mojom::ValueType::STRING}},
- {"printer-uri",
- {false, cups_ipp_parser::mojom::ValueType::STRING}},
- {"attributes-charset",
- {false, cups_ipp_parser::mojom::ValueType::STRING}},
- {"attributes-natural-language",
- {false, cups_ipp_parser::mojom::ValueType::STRING}},
- {"status-message",
- {false, cups_ipp_parser::mojom::ValueType::STRING}},
- {"printer-uri",
- {false, cups_ipp_parser::mojom::ValueType::STRING}},
- }},
- {IPP_OP_CUPS_GET_PRINTERS,
- {
- {"attributes-charset",
- {false, cups_ipp_parser::mojom::ValueType::STRING}},
- {"attributes-natural-language",
- {false, cups_ipp_parser::mojom::ValueType::STRING}},
- {"limit", {false, cups_ipp_parser::mojom::ValueType::INTEGER}},
- {"printer-location",
- {false, cups_ipp_parser::mojom::ValueType::STRING}},
- {"requested-attributes",
- {true, cups_ipp_parser::mojom::ValueType::STRING}},
- {"attributes-charset",
- {false, cups_ipp_parser::mojom::ValueType::STRING}},
- {"attributes-natural-language",
- {false, cups_ipp_parser::mojom::ValueType::STRING}},
- {"status-message",
- {false, cups_ipp_parser::mojom::ValueType::STRING}},
- {"charset-configured",
- {false, cups_ipp_parser::mojom::ValueType::STRING}},
- {"charset-supported",
- {true, cups_ipp_parser::mojom::ValueType::STRING}},
- {"color-supported",
- {false, cups_ipp_parser::mojom::ValueType::BOOLEAN}},
- {"compression-supported",
- {true, cups_ipp_parser::mojom::ValueType::STRING}},
- {"copies-default",
- {false, cups_ipp_parser::mojom::ValueType::INTEGER}},
- {"document-format-default",
- {false, cups_ipp_parser::mojom::ValueType::STRING}},
- {"document-format-supported",
- {true, cups_ipp_parser::mojom::ValueType::STRING}},
- {"finishings-default",
- {true, cups_ipp_parser::mojom::ValueType::INTEGER}},
- {"finishings-supported",
- {true, cups_ipp_parser::mojom::ValueType::INTEGER}},
- {"generated-natural-language-supported",
- {true, cups_ipp_parser::mojom::ValueType::STRING}},
- {"ipp-versions-supported",
- {true, cups_ipp_parser::mojom::ValueType::STRING}},
- {"media-default",
- {false, cups_ipp_parser::mojom::ValueType::STRING}},
- {"media-ready", {true, cups_ipp_parser::mojom::ValueType::STRING}},
- {"media-supported",
- {true, cups_ipp_parser::mojom::ValueType::STRING}},
- {"natural-language-configured",
- {false, cups_ipp_parser::mojom::ValueType::STRING}},
- {"operations-supported",
- {true, cups_ipp_parser::mojom::ValueType::INTEGER}},
- {"orientation-requested-default",
- {false, cups_ipp_parser::mojom::ValueType::INTEGER}},
- {"orientation-requested-supported",
- {true, cups_ipp_parser::mojom::ValueType::INTEGER}},
- {"output-bin-default",
- {false, cups_ipp_parser::mojom::ValueType::STRING}},
- {"output-bin-supported",
- {true, cups_ipp_parser::mojom::ValueType::STRING}},
- {"pdl-override-supported",
- {false, cups_ipp_parser::mojom::ValueType::STRING}},
- {"print-quality-default",
- {false, cups_ipp_parser::mojom::ValueType::INTEGER}},
- {"print-quality-supported",
- {true, cups_ipp_parser::mojom::ValueType::INTEGER}},
- {"printer-device-id",
- {false, cups_ipp_parser::mojom::ValueType::STRING}},
- {"printer-info",
- {false, cups_ipp_parser::mojom::ValueType::STRING}},
- {"printer-location",
- {false, cups_ipp_parser::mojom::ValueType::STRING}},
- {"printer-make-and-model",
- {false, cups_ipp_parser::mojom::ValueType::STRING}},
- {"printer-name",
- {false, cups_ipp_parser::mojom::ValueType::STRING}},
- {"sides-default",
- {false, cups_ipp_parser::mojom::ValueType::STRING}},
- {"sides-supported",
- {true, cups_ipp_parser::mojom::ValueType::STRING}},
- {"uri-authentication-supported",
- {true, cups_ipp_parser::mojom::ValueType::STRING}},
- {"uri-security-supported",
- {true, cups_ipp_parser::mojom::ValueType::STRING}},
- }},
- {IPP_OP_CANCEL_JOB,
- {
- {"attributes-charset",
- {false, cups_ipp_parser::mojom::ValueType::STRING}},
- {"attributes-natural-language",
- {false, cups_ipp_parser::mojom::ValueType::STRING}},
- {"printer-uri",
- {false, cups_ipp_parser::mojom::ValueType::STRING}},
- {"job-id", {false, cups_ipp_parser::mojom::ValueType::INTEGER}},
- {"job-uri", {false, cups_ipp_parser::mojom::ValueType::STRING}},
- {"requesting-user-name",
- {false, cups_ipp_parser::mojom::ValueType::STRING}},
- {"attributes-charset",
- {false, cups_ipp_parser::mojom::ValueType::STRING}},
- {"attributes-natural-language",
- {false, cups_ipp_parser::mojom::ValueType::STRING}},
- {"status-message",
- {false, cups_ipp_parser::mojom::ValueType::STRING}},
- }},
- {IPP_OP_CREATE_JOB,
- {
- {"attributes-charset",
- {false, cups_ipp_parser::mojom::ValueType::STRING}},
- {"attributes-natural-language",
- {false, cups_ipp_parser::mojom::ValueType::STRING}},
- {"printer-uri",
- {false, cups_ipp_parser::mojom::ValueType::STRING}},
- {"requesting-user-name",
- {false, cups_ipp_parser::mojom::ValueType::STRING}},
- {"job-name", {false, cups_ipp_parser::mojom::ValueType::STRING}},
- {"ipp-attribute-fidelity",
- {false, cups_ipp_parser::mojom::ValueType::BOOLEAN}},
- {"copies", {false, cups_ipp_parser::mojom::ValueType::INTEGER}},
- {"finishings", {true, cups_ipp_parser::mojom::ValueType::INTEGER}},
- {"media", {false, cups_ipp_parser::mojom::ValueType::STRING}},
- {"orientation-requested",
- {false, cups_ipp_parser::mojom::ValueType::INTEGER}},
- {"output-bin", {false, cups_ipp_parser::mojom::ValueType::STRING}},
- {"print-quality",
- {false, cups_ipp_parser::mojom::ValueType::INTEGER}},
- {"sides", {false, cups_ipp_parser::mojom::ValueType::STRING}},
- {"attributes-charset",
- {false, cups_ipp_parser::mojom::ValueType::STRING}},
- {"attributes-natural-language",
- {false, cups_ipp_parser::mojom::ValueType::STRING}},
- {"status-message",
- {false, cups_ipp_parser::mojom::ValueType::STRING}},
- {"job-id", {false, cups_ipp_parser::mojom::ValueType::INTEGER}},
- {"job-uri", {false, cups_ipp_parser::mojom::ValueType::STRING}},
- {"job-state", {false, cups_ipp_parser::mojom::ValueType::INTEGER}},
- {"job-state-reasons",
- {true, cups_ipp_parser::mojom::ValueType::STRING}},
- }},
- {IPP_OP_GET_JOB_ATTRIBUTES,
- {
- {"attributes-charset",
- {false, cups_ipp_parser::mojom::ValueType::STRING}},
- {"attributes-natural-language",
- {false, cups_ipp_parser::mojom::ValueType::STRING}},
- {"printer-uri",
- {false, cups_ipp_parser::mojom::ValueType::STRING}},
- {"job-id", {false, cups_ipp_parser::mojom::ValueType::INTEGER}},
- {"job-uri", {false, cups_ipp_parser::mojom::ValueType::STRING}},
- {"requesting-user-name",
- {false, cups_ipp_parser::mojom::ValueType::STRING}},
- {"requested-attributes",
- {true, cups_ipp_parser::mojom::ValueType::STRING}},
- {"attributes-charset",
- {false, cups_ipp_parser::mojom::ValueType::STRING}},
- {"attributes-natural-language",
- {false, cups_ipp_parser::mojom::ValueType::STRING}},
- {"status-message",
- {false, cups_ipp_parser::mojom::ValueType::STRING}},
- {"attributes-charset",
- {false, cups_ipp_parser::mojom::ValueType::STRING}},
- {"attributes-natural-language",
- {false, cups_ipp_parser::mojom::ValueType::STRING}},
- {"copies", {false, cups_ipp_parser::mojom::ValueType::INTEGER}},
- {"finishings", {true, cups_ipp_parser::mojom::ValueType::INTEGER}},
- {"job-id", {false, cups_ipp_parser::mojom::ValueType::INTEGER}},
- {"job-name", {false, cups_ipp_parser::mojom::ValueType::STRING}},
- {"job-originating-user-name",
- {false, cups_ipp_parser::mojom::ValueType::STRING}},
- {"job-printer-up-time",
- {false, cups_ipp_parser::mojom::ValueType::INTEGER}},
- {"job-printer-uri",
- {false, cups_ipp_parser::mojom::ValueType::STRING}},
- {"job-state", {false, cups_ipp_parser::mojom::ValueType::INTEGER}},
- {"job-state-reasons",
- {true, cups_ipp_parser::mojom::ValueType::STRING}},
- {"job-uri", {false, cups_ipp_parser::mojom::ValueType::STRING}},
- {"media", {false, cups_ipp_parser::mojom::ValueType::STRING}},
- {"orientation-requested",
- {false, cups_ipp_parser::mojom::ValueType::INTEGER}},
- {"output-bin", {false, cups_ipp_parser::mojom::ValueType::STRING}},
- {"print-quality",
- {false, cups_ipp_parser::mojom::ValueType::INTEGER}},
- {"sides", {false, cups_ipp_parser::mojom::ValueType::STRING}},
- {"time-at-completed",
- {false, cups_ipp_parser::mojom::ValueType::INTEGER}},
- {"time-at-creation",
- {false, cups_ipp_parser::mojom::ValueType::INTEGER}},
- {"time-at-processing",
- {false, cups_ipp_parser::mojom::ValueType::INTEGER}},
- }},
- {IPP_OP_GET_JOBS,
- {
- {"attributes-charset",
- {false, cups_ipp_parser::mojom::ValueType::STRING}},
- {"attributes-natural-language",
- {false, cups_ipp_parser::mojom::ValueType::STRING}},
- {"printer-uri",
- {false, cups_ipp_parser::mojom::ValueType::STRING}},
- {"requesting-user-name",
- {false, cups_ipp_parser::mojom::ValueType::STRING}},
- {"limit", {false, cups_ipp_parser::mojom::ValueType::INTEGER}},
- {"requested-attributes",
- {true, cups_ipp_parser::mojom::ValueType::STRING}},
- {"which-jobs", {false, cups_ipp_parser::mojom::ValueType::STRING}},
- {"my-jobs", {false, cups_ipp_parser::mojom::ValueType::BOOLEAN}},
- {"attributes-charset",
- {false, cups_ipp_parser::mojom::ValueType::STRING}},
- {"attributes-natural-language",
- {false, cups_ipp_parser::mojom::ValueType::STRING}},
- {"status-message",
- {false, cups_ipp_parser::mojom::ValueType::STRING}},
- {"attributes-charset",
- {false, cups_ipp_parser::mojom::ValueType::STRING}},
- {"attributes-natural-language",
- {false, cups_ipp_parser::mojom::ValueType::STRING}},
- {"copies", {false, cups_ipp_parser::mojom::ValueType::INTEGER}},
- {"finishings", {true, cups_ipp_parser::mojom::ValueType::INTEGER}},
- {"job-id", {false, cups_ipp_parser::mojom::ValueType::INTEGER}},
- {"job-name", {false, cups_ipp_parser::mojom::ValueType::STRING}},
- {"job-originating-user-name",
- {false, cups_ipp_parser::mojom::ValueType::STRING}},
- {"job-printer-up-time",
- {false, cups_ipp_parser::mojom::ValueType::INTEGER}},
- {"job-printer-uri",
- {false, cups_ipp_parser::mojom::ValueType::STRING}},
- {"job-state", {false, cups_ipp_parser::mojom::ValueType::INTEGER}},
- {"job-state-reasons",
- {true, cups_ipp_parser::mojom::ValueType::STRING}},
- {"job-uri", {false, cups_ipp_parser::mojom::ValueType::STRING}},
- {"media", {false, cups_ipp_parser::mojom::ValueType::STRING}},
- {"orientation-requested",
- {false, cups_ipp_parser::mojom::ValueType::INTEGER}},
- {"output-bin", {false, cups_ipp_parser::mojom::ValueType::STRING}},
- {"print-quality",
- {false, cups_ipp_parser::mojom::ValueType::INTEGER}},
- {"sides", {false, cups_ipp_parser::mojom::ValueType::STRING}},
- {"time-at-completed",
- {false, cups_ipp_parser::mojom::ValueType::INTEGER}},
- {"time-at-creation",
- {false, cups_ipp_parser::mojom::ValueType::INTEGER}},
- {"time-at-processing",
- {false, cups_ipp_parser::mojom::ValueType::INTEGER}},
- }},
- {IPP_OP_GET_PRINTER_ATTRIBUTES,
- {
- {"attributes-charset",
- {false, cups_ipp_parser::mojom::ValueType::STRING}},
- {"attributes-natural-language",
- {false, cups_ipp_parser::mojom::ValueType::STRING}},
- {"printer-uri",
- {false, cups_ipp_parser::mojom::ValueType::STRING}},
- {"requesting-user-name",
- {false, cups_ipp_parser::mojom::ValueType::STRING}},
- {"requested-attributes",
- {true, cups_ipp_parser::mojom::ValueType::STRING}},
- {"document-format",
- {false, cups_ipp_parser::mojom::ValueType::STRING}},
- {"attributes-charset",
- {false, cups_ipp_parser::mojom::ValueType::STRING}},
- {"attributes-natural-language",
- {false, cups_ipp_parser::mojom::ValueType::STRING}},
- {"status-message",
- {false, cups_ipp_parser::mojom::ValueType::STRING}},
- {"charset-configured",
- {false, cups_ipp_parser::mojom::ValueType::STRING}},
- {"charset-supported",
- {true, cups_ipp_parser::mojom::ValueType::STRING}},
- {"color-supported",
- {false, cups_ipp_parser::mojom::ValueType::BOOLEAN}},
- {"compression-supported",
- {true, cups_ipp_parser::mojom::ValueType::STRING}},
- {"copies-default",
- {false, cups_ipp_parser::mojom::ValueType::INTEGER}},
- {"document-format-default",
- {false, cups_ipp_parser::mojom::ValueType::STRING}},
- {"document-format-supported",
- {true, cups_ipp_parser::mojom::ValueType::STRING}},
- {"finishings-default",
- {true, cups_ipp_parser::mojom::ValueType::INTEGER}},
- {"finishings-supported",
- {true, cups_ipp_parser::mojom::ValueType::INTEGER}},
- {"generated-natural-language-supported",
- {true, cups_ipp_parser::mojom::ValueType::STRING}},
- {"ipp-versions-supported",
- {true, cups_ipp_parser::mojom::ValueType::STRING}},
- {"media-default",
- {false, cups_ipp_parser::mojom::ValueType::STRING}},
- {"media-ready", {true, cups_ipp_parser::mojom::ValueType::STRING}},
- {"media-supported",
- {true, cups_ipp_parser::mojom::ValueType::STRING}},
- {"natural-language-configured",
- {false, cups_ipp_parser::mojom::ValueType::STRING}},
- {"operations-supported",
- {true, cups_ipp_parser::mojom::ValueType::INTEGER}},
- {"orientation-requested-default",
- {false, cups_ipp_parser::mojom::ValueType::INTEGER}},
- {"orientation-requested-supported",
- {true, cups_ipp_parser::mojom::ValueType::INTEGER}},
- {"output-bin-default",
- {false, cups_ipp_parser::mojom::ValueType::STRING}},
- {"output-bin-supported",
- {true, cups_ipp_parser::mojom::ValueType::STRING}},
- {"pages-per-minute",
- {false, cups_ipp_parser::mojom::ValueType::INTEGER}},
- {"pages-per-minute-color",
- {false, cups_ipp_parser::mojom::ValueType::INTEGER}},
- {"pdl-override-supported",
- {false, cups_ipp_parser::mojom::ValueType::STRING}},
- {"print-quality-default",
- {false, cups_ipp_parser::mojom::ValueType::INTEGER}},
- {"print-quality-supported",
- {true, cups_ipp_parser::mojom::ValueType::INTEGER}},
- {"printer-alert",
- {true, cups_ipp_parser::mojom::ValueType::STRING}},
- {"printer-alert-description",
- {true, cups_ipp_parser::mojom::ValueType::STRING}},
- {"printer-device-id",
- {false, cups_ipp_parser::mojom::ValueType::STRING}},
- {"printer-info",
- {false, cups_ipp_parser::mojom::ValueType::STRING}},
- {"printer-is-accepting-jobs",
- {false, cups_ipp_parser::mojom::ValueType::BOOLEAN}},
- {"printer-location",
- {false, cups_ipp_parser::mojom::ValueType::STRING}},
- {"printer-make-and-model",
- {false, cups_ipp_parser::mojom::ValueType::STRING}},
- {"printer-more-info",
- {false, cups_ipp_parser::mojom::ValueType::STRING}},
- {"printer-name",
- {false, cups_ipp_parser::mojom::ValueType::STRING}},
- {"printer-state",
- {false, cups_ipp_parser::mojom::ValueType::INTEGER}},
- {"printer-state-reasons",
- {true, cups_ipp_parser::mojom::ValueType::STRING}},
- {"printer-up-time",
- {false, cups_ipp_parser::mojom::ValueType::INTEGER}},
- {"printer-uri-supported",
- {true, cups_ipp_parser::mojom::ValueType::STRING}},
- {"queued-job-count",
- {false, cups_ipp_parser::mojom::ValueType::INTEGER}},
- {"sides-default",
- {false, cups_ipp_parser::mojom::ValueType::STRING}},
- {"sides-supported",
- {true, cups_ipp_parser::mojom::ValueType::STRING}},
- {"uri-authentication-supported",
- {true, cups_ipp_parser::mojom::ValueType::STRING}},
- {"uri-security-supported",
- {true, cups_ipp_parser::mojom::ValueType::STRING}},
- }},
- {IPP_OP_HOLD_JOB,
- {
- {"attributes-charset",
- {false, cups_ipp_parser::mojom::ValueType::STRING}},
- {"attributes-natural-language",
- {false, cups_ipp_parser::mojom::ValueType::STRING}},
- {"printer-uri",
- {false, cups_ipp_parser::mojom::ValueType::STRING}},
- {"job-id", {false, cups_ipp_parser::mojom::ValueType::INTEGER}},
- {"job-uri", {false, cups_ipp_parser::mojom::ValueType::STRING}},
- {"requesting-user-name",
- {false, cups_ipp_parser::mojom::ValueType::STRING}},
- {"attributes-charset",
- {false, cups_ipp_parser::mojom::ValueType::STRING}},
- {"attributes-natural-language",
- {false, cups_ipp_parser::mojom::ValueType::STRING}},
- {"status-message",
- {false, cups_ipp_parser::mojom::ValueType::STRING}},
- }},
- {IPP_OP_PAUSE_PRINTER,
- {
- {"attributes-charset",
- {false, cups_ipp_parser::mojom::ValueType::STRING}},
- {"attributes-natural-language",
- {false, cups_ipp_parser::mojom::ValueType::STRING}},
- {"printer-uri",
- {false, cups_ipp_parser::mojom::ValueType::STRING}},
- {"requesting-user-name",
- {false, cups_ipp_parser::mojom::ValueType::STRING}},
- {"attributes-charset",
- {false, cups_ipp_parser::mojom::ValueType::STRING}},
- {"attributes-natural-language",
- {false, cups_ipp_parser::mojom::ValueType::STRING}},
- {"status-message",
- {false, cups_ipp_parser::mojom::ValueType::STRING}},
- }},
- {IPP_OP_PRINT_JOB,
- {
- {"attributes-charset",
- {false, cups_ipp_parser::mojom::ValueType::STRING}},
- {"attributes-natural-language",
- {false, cups_ipp_parser::mojom::ValueType::STRING}},
- {"printer-uri",
- {false, cups_ipp_parser::mojom::ValueType::STRING}},
- {"requesting-user-name",
- {false, cups_ipp_parser::mojom::ValueType::STRING}},
- {"job-name", {false, cups_ipp_parser::mojom::ValueType::STRING}},
- {"ipp-attribute-fidelity",
- {false, cups_ipp_parser::mojom::ValueType::BOOLEAN}},
- {"document-name",
- {false, cups_ipp_parser::mojom::ValueType::STRING}},
- {"compression",
- {false, cups_ipp_parser::mojom::ValueType::STRING}},
- {"document-format",
- {false, cups_ipp_parser::mojom::ValueType::STRING}},
- {"copies", {false, cups_ipp_parser::mojom::ValueType::INTEGER}},
- {"finishings", {true, cups_ipp_parser::mojom::ValueType::INTEGER}},
- {"media", {false, cups_ipp_parser::mojom::ValueType::STRING}},
- {"orientation-requested",
- {false, cups_ipp_parser::mojom::ValueType::INTEGER}},
- {"output-bin", {false, cups_ipp_parser::mojom::ValueType::STRING}},
- {"print-quality",
- {false, cups_ipp_parser::mojom::ValueType::INTEGER}},
- {"sides", {false, cups_ipp_parser::mojom::ValueType::STRING}},
- {"attributes-charset",
- {false, cups_ipp_parser::mojom::ValueType::STRING}},
- {"attributes-natural-language",
- {false, cups_ipp_parser::mojom::ValueType::STRING}},
- {"status-message",
- {false, cups_ipp_parser::mojom::ValueType::STRING}},
- {"job-id", {false, cups_ipp_parser::mojom::ValueType::INTEGER}},
- {"job-uri", {false, cups_ipp_parser::mojom::ValueType::STRING}},
- {"job-state", {false, cups_ipp_parser::mojom::ValueType::INTEGER}},
- {"job-state-reasons",
- {true, cups_ipp_parser::mojom::ValueType::STRING}},
- }},
- {IPP_OP_PRINT_URI,
- {
- {"attributes-charset",
- {false, cups_ipp_parser::mojom::ValueType::STRING}},
- {"attributes-natural-language",
- {false, cups_ipp_parser::mojom::ValueType::STRING}},
- {"printer-uri",
- {false, cups_ipp_parser::mojom::ValueType::STRING}},
- {"requesting-user-name",
- {false, cups_ipp_parser::mojom::ValueType::STRING}},
- {"job-name", {false, cups_ipp_parser::mojom::ValueType::STRING}},
- {"ipp-attribute-fidelity",
- {false, cups_ipp_parser::mojom::ValueType::BOOLEAN}},
- {"document-name",
- {false, cups_ipp_parser::mojom::ValueType::STRING}},
- {"compression",
- {false, cups_ipp_parser::mojom::ValueType::STRING}},
- {"document-format",
- {false, cups_ipp_parser::mojom::ValueType::STRING}},
- {"copies", {false, cups_ipp_parser::mojom::ValueType::INTEGER}},
- {"finishings", {true, cups_ipp_parser::mojom::ValueType::INTEGER}},
- {"media", {false, cups_ipp_parser::mojom::ValueType::STRING}},
- {"orientation-requested",
- {false, cups_ipp_parser::mojom::ValueType::INTEGER}},
- {"output-bin", {false, cups_ipp_parser::mojom::ValueType::STRING}},
- {"print-quality",
- {false, cups_ipp_parser::mojom::ValueType::INTEGER}},
- {"sides", {false, cups_ipp_parser::mojom::ValueType::STRING}},
- {"attributes-charset",
- {false, cups_ipp_parser::mojom::ValueType::STRING}},
- {"attributes-natural-language",
- {false, cups_ipp_parser::mojom::ValueType::STRING}},
- {"status-message",
- {false, cups_ipp_parser::mojom::ValueType::STRING}},
- {"job-id", {false, cups_ipp_parser::mojom::ValueType::INTEGER}},
- {"job-uri", {false, cups_ipp_parser::mojom::ValueType::STRING}},
- {"job-state", {false, cups_ipp_parser::mojom::ValueType::INTEGER}},
- {"job-state-reasons",
- {true, cups_ipp_parser::mojom::ValueType::STRING}},
- }},
- {IPP_OP_RELEASE_JOB,
- {
- {"attributes-charset",
- {false, cups_ipp_parser::mojom::ValueType::STRING}},
- {"attributes-natural-language",
- {false, cups_ipp_parser::mojom::ValueType::STRING}},
- {"printer-uri",
- {false, cups_ipp_parser::mojom::ValueType::STRING}},
- {"job-id", {false, cups_ipp_parser::mojom::ValueType::INTEGER}},
- {"job-uri", {false, cups_ipp_parser::mojom::ValueType::STRING}},
- {"requesting-user-name",
- {false, cups_ipp_parser::mojom::ValueType::STRING}},
- {"attributes-charset",
- {false, cups_ipp_parser::mojom::ValueType::STRING}},
- {"attributes-natural-language",
- {false, cups_ipp_parser::mojom::ValueType::STRING}},
- {"status-message",
- {false, cups_ipp_parser::mojom::ValueType::STRING}},
- }},
- {IPP_OP_RESUME_PRINTER,
- {
- {"attributes-charset",
- {false, cups_ipp_parser::mojom::ValueType::STRING}},
- {"attributes-natural-language",
- {false, cups_ipp_parser::mojom::ValueType::STRING}},
- {"printer-uri",
- {false, cups_ipp_parser::mojom::ValueType::STRING}},
- {"requesting-user-name",
- {false, cups_ipp_parser::mojom::ValueType::STRING}},
- {"attributes-charset",
- {false, cups_ipp_parser::mojom::ValueType::STRING}},
- {"attributes-natural-language",
- {false, cups_ipp_parser::mojom::ValueType::STRING}},
- {"status-message",
- {false, cups_ipp_parser::mojom::ValueType::STRING}},
- }},
- {IPP_OP_SEND_DOCUMENT,
- {
- {"attributes-charset",
- {false, cups_ipp_parser::mojom::ValueType::STRING}},
- {"attributes-natural-language",
- {false, cups_ipp_parser::mojom::ValueType::STRING}},
- {"printer-uri",
- {false, cups_ipp_parser::mojom::ValueType::STRING}},
- {"job-id", {false, cups_ipp_parser::mojom::ValueType::INTEGER}},
- {"job-uri", {false, cups_ipp_parser::mojom::ValueType::STRING}},
- {"requesting-user-name",
- {false, cups_ipp_parser::mojom::ValueType::STRING}},
- {"document-name",
- {false, cups_ipp_parser::mojom::ValueType::STRING}},
- {"compression",
- {false, cups_ipp_parser::mojom::ValueType::STRING}},
- {"document-format",
- {false, cups_ipp_parser::mojom::ValueType::STRING}},
- {"attributes-charset",
- {false, cups_ipp_parser::mojom::ValueType::STRING}},
- {"attributes-natural-language",
- {false, cups_ipp_parser::mojom::ValueType::STRING}},
- {"status-message",
- {false, cups_ipp_parser::mojom::ValueType::STRING}},
- {"job-id", {false, cups_ipp_parser::mojom::ValueType::INTEGER}},
- {"job-uri", {false, cups_ipp_parser::mojom::ValueType::STRING}},
- {"job-state", {false, cups_ipp_parser::mojom::ValueType::INTEGER}},
- {"job-state-reasons",
- {true, cups_ipp_parser::mojom::ValueType::STRING}},
- }},
- {IPP_OP_SEND_URI,
- {
- {"attributes-charset",
- {false, cups_ipp_parser::mojom::ValueType::STRING}},
- {"attributes-natural-language",
- {false, cups_ipp_parser::mojom::ValueType::STRING}},
- {"printer-uri",
- {false, cups_ipp_parser::mojom::ValueType::STRING}},
- {"job-id", {false, cups_ipp_parser::mojom::ValueType::INTEGER}},
- {"job-uri", {false, cups_ipp_parser::mojom::ValueType::STRING}},
- {"requesting-user-name",
- {false, cups_ipp_parser::mojom::ValueType::STRING}},
- {"document-name",
- {false, cups_ipp_parser::mojom::ValueType::STRING}},
- {"compression",
- {false, cups_ipp_parser::mojom::ValueType::STRING}},
- {"document-format",
- {false, cups_ipp_parser::mojom::ValueType::STRING}},
- {"attributes-charset",
- {false, cups_ipp_parser::mojom::ValueType::STRING}},
- {"attributes-natural-language",
- {false, cups_ipp_parser::mojom::ValueType::STRING}},
- {"status-message",
- {false, cups_ipp_parser::mojom::ValueType::STRING}},
- {"job-id", {false, cups_ipp_parser::mojom::ValueType::INTEGER}},
- {"job-uri", {false, cups_ipp_parser::mojom::ValueType::STRING}},
- {"job-state", {false, cups_ipp_parser::mojom::ValueType::INTEGER}},
- {"job-state-reasons",
- {true, cups_ipp_parser::mojom::ValueType::STRING}},
- }},
- {IPP_OP_VALIDATE_JOB,
- {
- {"attributes-charset",
- {false, cups_ipp_parser::mojom::ValueType::STRING}},
- {"attributes-natural-language",
- {false, cups_ipp_parser::mojom::ValueType::STRING}},
- {"printer-uri",
- {false, cups_ipp_parser::mojom::ValueType::STRING}},
- {"requesting-user-name",
- {false, cups_ipp_parser::mojom::ValueType::STRING}},
- {"job-name", {false, cups_ipp_parser::mojom::ValueType::STRING}},
- {"ipp-attribute-fidelity",
- {false, cups_ipp_parser::mojom::ValueType::BOOLEAN}},
- {"document-name",
- {false, cups_ipp_parser::mojom::ValueType::STRING}},
- {"compression",
- {false, cups_ipp_parser::mojom::ValueType::STRING}},
- {"document-format",
- {false, cups_ipp_parser::mojom::ValueType::STRING}},
- {"copies", {false, cups_ipp_parser::mojom::ValueType::INTEGER}},
- {"finishings", {true, cups_ipp_parser::mojom::ValueType::INTEGER}},
- {"media", {false, cups_ipp_parser::mojom::ValueType::STRING}},
- {"orientation-requested",
- {false, cups_ipp_parser::mojom::ValueType::INTEGER}},
- {"output-bin", {false, cups_ipp_parser::mojom::ValueType::STRING}},
- {"print-quality",
- {false, cups_ipp_parser::mojom::ValueType::INTEGER}},
- {"sides", {false, cups_ipp_parser::mojom::ValueType::STRING}},
- {"attributes-charset",
- {false, cups_ipp_parser::mojom::ValueType::STRING}},
- {"attributes-natural-language",
- {false, cups_ipp_parser::mojom::ValueType::STRING}},
- {"status-message",
- {false, cups_ipp_parser::mojom::ValueType::STRING}},
- }}};
+// Definitions of all known attributes.
+const std::map<std::string, AttributeDefinition> kAttributeDefinitions{
+ {"attributes-charset", {false, ValueType::STRING}},
+ {"attributes-natural-language", {false, ValueType::STRING}},
+ {"auth-info", {true, ValueType::STRING}},
+ {"auth-info-required", {true, ValueType::STRING}},
+ {"charset-configured", {false, ValueType::STRING}},
+ {"charset-supported", {true, ValueType::STRING}},
+ {"color-supported", {false, ValueType::BOOLEAN}},
+ {"compression", {false, ValueType::STRING}},
+ {"compression-supported", {true, ValueType::STRING}},
+ {"copies", {false, ValueType::INTEGER}},
+ {"copies-default", {false, ValueType::INTEGER}},
+ {"copies-supported", {true, ValueType::INTEGER}},
+ {"document-format", {false, ValueType::STRING}},
+ {"document-format-default", {false, ValueType::STRING}},
+ {"document-format-supported", {true, ValueType::STRING}},
+ {"document-name", {false, ValueType::STRING}},
+ {"finishings", {true, ValueType::INTEGER}},
+ {"finishings-default", {true, ValueType::INTEGER}},
+ {"finishings-supported", {true, ValueType::INTEGER}},
+ {"generated-natural-language-supported", {true, ValueType::STRING}},
+ {"ipp-attribute-fidelity", {false, ValueType::BOOLEAN}},
+ {"ipp-versions-supported", {true, ValueType::STRING}},
+ {"job-cancel-after", {false, ValueType::INTEGER}},
+ {"job-hold-until", {false, ValueType::STRING}},
+ {"job-hold-until-default", {false, ValueType::STRING}},
+ {"job-hold-until-supported", {true, ValueType::STRING}},
+ {"job-id", {false, ValueType::INTEGER}},
+ {"job-k-limit", {false, ValueType::INTEGER}},
+ {"job-media-progress", {false, ValueType::INTEGER}},
+ {"job-name", {false, ValueType::STRING}},
+ {"job-originating-host-name", {false, ValueType::STRING}},
+ {"job-originating-user-name", {false, ValueType::STRING}},
+ {"job-page-limit", {false, ValueType::INTEGER}},
+ {"job-printer-state-message", {false, ValueType::STRING}},
+ {"job-printer-state-reasons", {true, ValueType::STRING}},
+ {"job-printer-up-time", {false, ValueType::INTEGER}},
+ {"job-printer-uri", {false, ValueType::STRING}},
+ {"job-priority", {false, ValueType::INTEGER}},
+ {"job-priority-default", {false, ValueType::INTEGER}},
+ {"job-priority-supported", {false, ValueType::INTEGER}},
+ {"job-quota-period", {false, ValueType::INTEGER}},
+ {"job-sheets", {false, ValueType::STRING}},
+ {"job-sheets-default", {false, ValueType::STRING}},
+ {"job-sheets-supported", {true, ValueType::STRING}},
+ {"job-state", {false, ValueType::INTEGER}},
+ {"job-state-reasons", {true, ValueType::STRING}},
+ {"job-uri", {false, ValueType::STRING}},
+ {"last-document", {false, ValueType::BOOLEAN}},
+ {"limit", {false, ValueType::INTEGER}},
+ {"marker-change-time", {false, ValueType::INTEGER}},
+ {"marker-colors", {true, ValueType::STRING}},
+ {"marker-high-levels", {true, ValueType::INTEGER}},
+ {"marker-levels", {true, ValueType::INTEGER}},
+ {"marker-low-levels", {true, ValueType::INTEGER}},
+ {"marker-message", {false, ValueType::STRING}},
+ {"marker-names", {true, ValueType::STRING}},
+ {"marker-types", {true, ValueType::STRING}},
+ {"media", {false, ValueType::STRING}},
+ {"media-default", {false, ValueType::STRING}},
+ {"media-ready", {true, ValueType::STRING}},
+ {"media-supported", {true, ValueType::STRING}},
+ {"member-names", {true, ValueType::STRING}},
+ {"member-uris", {true, ValueType::STRING}},
+ {"multiple-document-handling", {false, ValueType::STRING}},
+ {"multiple-document-handling-default", {false, ValueType::STRING}},
+ {"multiple-document-handling-supported", {true, ValueType::STRING}},
+ {"my-jobs", {false, ValueType::BOOLEAN}},
+ {"natural-language-configured", {false, ValueType::STRING}},
+ {"number-up", {false, ValueType::INTEGER}},
+ {"number-up-default", {false, ValueType::INTEGER}},
+ {"number-up-supported", {true, ValueType::INTEGER}},
+ {"operations-supported", {true, ValueType::INTEGER}},
+ {"orientation-requested", {false, ValueType::INTEGER}},
+ {"orientation-requested-default", {false, ValueType::INTEGER}},
+ {"orientation-requested-supported", {true, ValueType::INTEGER}},
+ {"output-bin", {false, ValueType::STRING}},
+ {"output-bin-default", {false, ValueType::STRING}},
+ {"output-bin-supported", {true, ValueType::STRING}},
+ {"page-border", {false, ValueType::STRING}},
+ {"page-ranges", {true, ValueType::INTEGER}},
+ {"page-ranges-supported", {false, ValueType::BOOLEAN}},
+ {"pages-per-minute", {false, ValueType::INTEGER}},
+ {"pages-per-minute-color", {false, ValueType::INTEGER}},
+ {"pdl-override-supported", {false, ValueType::STRING}},
+ {"print-quality", {false, ValueType::INTEGER}},
+ {"print-quality-default", {false, ValueType::INTEGER}},
+ {"print-quality-supported", {true, ValueType::INTEGER}},
+ {"printer-alert", {true, ValueType::STRING}},
+ {"printer-alert-description", {true, ValueType::STRING}},
+ {"printer-device-id", {false, ValueType::STRING}},
+ {"printer-dns-sd-name", {false, ValueType::STRING}},
+ {"printer-id", {false, ValueType::INTEGER}},
+ {"printer-info", {false, ValueType::STRING}},
+ {"printer-is-accepting-jobs", {false, ValueType::BOOLEAN}},
+ {"printer-location", {false, ValueType::STRING}},
+ {"printer-make-and-model", {false, ValueType::STRING}},
+ {"printer-more-info", {false, ValueType::STRING}},
+ {"printer-name", {false, ValueType::STRING}},
+ {"printer-resolution", {true, ValueType::INTEGER}},
+ {"printer-resolution-default", {true, ValueType::INTEGER}},
+ {"printer-resolution-supported", {true, ValueType::INTEGER}},
+ {"printer-state", {false, ValueType::INTEGER}},
+ {"printer-state-reasons", {true, ValueType::STRING}},
+ {"printer-type", {false, ValueType::INTEGER}},
+ {"printer-type-mask", {false, ValueType::INTEGER}},
+ {"printer-up-time", {false, ValueType::INTEGER}},
+ {"printer-uri", {false, ValueType::STRING}},
+ {"printer-uri-supported", {true, ValueType::STRING}},
+ {"queued-job-count", {false, ValueType::INTEGER}},
+ {"requested-attributes", {true, ValueType::STRING}},
+ {"requesting-user-name", {false, ValueType::STRING}},
+ {"requesting-user-name-allowed", {false, ValueType::STRING}},
+ {"requesting-user-name-denied", {false, ValueType::STRING}},
+ {"sides", {false, ValueType::STRING}},
+ {"sides-default", {false, ValueType::STRING}},
+ {"sides-supported", {true, ValueType::STRING}},
+ {"status-message", {false, ValueType::STRING}},
+ {"time-at-completed", {false, ValueType::INTEGER}},
+ {"time-at-creation", {false, ValueType::INTEGER}},
+ {"time-at-processing", {false, ValueType::INTEGER}},
+ {"uri-authentication-supported", {true, ValueType::STRING}},
+ {"uri-security-supported", {true, ValueType::STRING}},
+ {"which-jobs", {false, ValueType::STRING}}};
+
+// Allowed IPP Operations.
+const std::set<ipp_op_t> kOperationIds{
+ IPP_OP_CANCEL_JOB, IPP_OP_CREATE_JOB,
+ IPP_OP_CUPS_GET_DEFAULT, IPP_OP_CUPS_GET_PPD,
+ IPP_OP_CUPS_GET_PRINTERS, IPP_OP_GET_JOBS,
+ IPP_OP_GET_JOB_ATTRIBUTES, IPP_OP_GET_PRINTER_ATTRIBUTES,
+ IPP_OP_HOLD_JOB, IPP_OP_PAUSE_PRINTER,
+ IPP_OP_PRINT_JOB, IPP_OP_PRINT_URI,
+ IPP_OP_RELEASE_JOB, IPP_OP_RESUME_PRINTER,
+ IPP_OP_SEND_DOCUMENT, IPP_OP_SEND_URI,
+ IPP_OP_VALIDATE_JOB,
+};
} // namespace
-bool ValidateAttribute(ipp_op_t ipp_oper_id,
- const std::string& name,
- cups_ipp_parser::mojom::ValueType type,
- size_t values_count) {
- auto it_oper = attributesDefinitions.find(ipp_oper_id);
- if (it_oper == attributesDefinitions.end()) {
- return false;
+ValidateAttributeResult ValidateAttribute(ipp_op_t ipp_oper_id,
+ const std::string& name,
+ ValueType type,
+ size_t values_count) {
+ // Ensure |ipp_oper_id| is an allowed operation.
+ if (!base::Contains(kOperationIds, ipp_oper_id)) {
+ return ValidateAttributeResult::kFatalError;
}
- auto it_attr = it_oper->second.find(name);
- if (it_attr == it_oper->second.end()) {
- return false;
+
+ // Ensure |name| refers to an allowed attribute.
+ auto attr_def = kAttributeDefinitions.find(name);
+ if (attr_def == kAttributeDefinitions.end()) {
+ // TODO(crbug.com/945409): Tell caller to drop this attribute.
+ return ValidateAttributeResult::kUnknownAttribute;
}
- if (it_attr->second.type != type) {
- return false;
- }
+
+ // Ensure every attribute has some value.
if (values_count == 0) {
- return false;
+ return ValidateAttributeResult::kFatalError;
}
- if (!it_attr->second.is_a_set && values_count > 1) {
- return false;
+
+ // Ensure single-valued attributes are single-valued.
+ if (!attr_def->second.multivalued && values_count > 1) {
+ return ValidateAttributeResult::kFatalError;
}
- return true;
+
+ // Ensure every attribute was serialized to the correct type.
+ if (attr_def->second.type != type) {
+ return ValidateAttributeResult::kFatalError;
+ }
+ return ValidateAttributeResult::kSuccess;
}
} // namespace cups_proxy
diff --git a/chrome/services/cups_proxy/ipp_attribute_validator.h b/chrome/services/cups_proxy/ipp_attribute_validator.h
index 0a75eab..3a236a8c 100644
--- a/chrome/services/cups_proxy/ipp_attribute_validator.h
+++ b/chrome/services/cups_proxy/ipp_attribute_validator.h
@@ -13,20 +13,29 @@
namespace cups_proxy {
+enum ValidateAttributeResult {
+ kSuccess = 0,
+
+ // Unknown attribute name.
+ kUnknownAttribute,
+ kFatalError,
+ kMaxValue,
+};
+
// Validates an attribute |name| of type |type| in operation |ipp_oper_id|.
// |values_count| represents number of values in the attribute. The following
// constraints are enforced:
// - only operations from predefined set are accepted
// - only attributes from predefined set are accepted
-// - an attribute must be part of given operation (request or response)
-// - a type of the attribute must match the specification
+// - serialization type of the attribute must match the specification
// - a single-value attribute cannot have more than one value
// - a set-of-values attribute cannot be empty
-// Returns false <=> at least one of the constraints has been violated.
-bool ValidateAttribute(ipp_op_t ipp_oper_id,
- const std::string& name,
- cups_ipp_parser::mojom::ValueType type,
- size_t values_count);
+// Returns kFatalError <=> at least one of the constraints has been violated.
+ValidateAttributeResult ValidateAttribute(
+ ipp_op_t ipp_oper_id,
+ const std::string& name,
+ cups_ipp_parser::mojom::ValueType type,
+ size_t values_count);
} // namespace cups_proxy
diff --git a/chrome/services/cups_proxy/ipp_validator.cc b/chrome/services/cups_proxy/ipp_validator.cc
index 079501e..dce9559d 100644
--- a/chrome/services/cups_proxy/ipp_validator.cc
+++ b/chrome/services/cups_proxy/ipp_validator.cc
@@ -15,6 +15,7 @@
#include "base/containers/span.h"
#include "base/strings/strcat.h"
+#include "base/strings/string_number_conversions.h"
#include "base/strings/string_piece.h"
#include "base/strings/string_util.h"
#include "chrome/services/cups_proxy/ipp_attribute_validator.h"
@@ -121,6 +122,7 @@
base::Optional<std::vector<ipp_converter::HttpHeader>>
IppValidator::ValidateHttpHeaders(
+ const size_t http_content_length,
const base::flat_map<std::string, std::string>& headers) {
// Sane, character-set checks.
for (const auto& header : headers) {
@@ -130,9 +132,20 @@
}
}
- return std::vector<ipp_converter::HttpHeader>(headers.begin(), headers.end());
+ std::vector<ipp_converter::HttpHeader> ret(headers.begin(), headers.end());
+
+ // Update the ContentLength.
+ base::EraseIf(ret, [](const ipp_converter::HttpHeader& header) {
+ return header.first == "Content-Length";
+ });
+ ret.push_back({"Content-Length", base::NumberToString(http_content_length)});
+
+ return ret;
}
+// Note: Since its possible to have valid IPP attributes that our
+// ipp_attribute_validator.cc is unaware of, we drop unknown attributes, rather
+// than fail the request.
ipp_t* IppValidator::ValidateIppMessage(
cups_ipp_parser::mojom::IppMessagePtr ipp_message) {
printing::ScopedIppPtr ipp = printing::WrapIpp(ippNew());
@@ -161,10 +174,17 @@
return nullptr;
}
- if (!ValidateAttribute(ipp_oper_id, attribute->name, attribute->type,
- num_values)) {
+ auto ret = ValidateAttribute(ipp_oper_id, attribute->name, attribute->type,
+ num_values);
+ if (ret == ValidateAttributeResult::kFatalError) {
return nullptr;
}
+ if (ret == ValidateAttributeResult::kUnknownAttribute) {
+ // We drop unknown attributes.
+ DVLOG(1) << "CupsProxy validation: dropping unknown attribute "
+ << attribute->name;
+ continue;
+ }
switch (attribute->type) {
case cups_ipp_parser::mojom::ValueType::BOOLEAN: {
@@ -275,19 +295,6 @@
return base::nullopt;
}
- // Build request line.
- auto request_line = ValidateHttpRequestLine(
- to_validate->method, to_validate->endpoint, to_validate->http_version);
- if (!request_line.has_value()) {
- return base::nullopt;
- }
-
- // Build headers.
- auto headers = ValidateHttpHeaders(to_validate->headers);
- if (!headers.has_value()) {
- return base::nullopt;
- }
-
// Build ipp message.
// Note: Moving ipp here, to_validate->ipp no longer valid below.
printing::ScopedIppPtr ipp =
@@ -302,6 +309,22 @@
return base::nullopt;
}
+ // Build request line.
+ auto request_line = ValidateHttpRequestLine(
+ to_validate->method, to_validate->endpoint, to_validate->http_version);
+ if (!request_line.has_value()) {
+ return base::nullopt;
+ }
+
+ // Build headers; must happen after ipp message/data since it requires the
+ // ContentLength.
+ const size_t http_content_length =
+ ippLength(ipp.get()) + to_validate->data.size();
+ auto headers = ValidateHttpHeaders(http_content_length, to_validate->headers);
+ if (!headers.has_value()) {
+ return base::nullopt;
+ }
+
// Marshall request
IppRequest ret;
ret.request_line = std::move(*request_line);
diff --git a/chrome/services/cups_proxy/ipp_validator.h b/chrome/services/cups_proxy/ipp_validator.h
index 03770c7ef..7b2c1e3d 100644
--- a/chrome/services/cups_proxy/ipp_validator.h
+++ b/chrome/services/cups_proxy/ipp_validator.h
@@ -42,6 +42,7 @@
base::StringPiece http_version);
base::Optional<std::vector<ipp_converter::HttpHeader>> ValidateHttpHeaders(
+ const size_t http_content_length,
const base::flat_map<std::string, std::string>& headers);
ipp_t* ValidateIppMessage(cups_ipp_parser::mojom::IppMessagePtr ipp_message);
diff --git a/chrome/services/cups_proxy/ipp_validator_unittest.cc b/chrome/services/cups_proxy/ipp_validator_unittest.cc
index e9b528f..98ba4f9d 100644
--- a/chrome/services/cups_proxy/ipp_validator_unittest.cc
+++ b/chrome/services/cups_proxy/ipp_validator_unittest.cc
@@ -176,6 +176,26 @@
EXPECT_TRUE(RunValidateIppRequest(request));
}
+// Test that we drop unknown attributes and succeed the request.
+TEST_F(IppValidatorTest, UnknownAttribute) {
+ auto request = GetBasicIppRequest();
+
+ // Add fake attribute.
+ std::string fake_attr_name = "fake-attribute-name";
+ IppAttributePtr fake_attr =
+ BuildAttributePtr(fake_attr_name, IPP_TAG_OPERATION, IPP_TAG_TEXT);
+ fake_attr->type = ValueType::STRING;
+ fake_attr->value->set_strings({"fake_attribute_value"});
+ request->ipp->attributes.push_back(std::move(fake_attr));
+
+ auto result = RunValidateIppRequest(request);
+ ASSERT_TRUE(result);
+
+ // Ensure resulting validated IPP request doesn't contain fake_attr_name.
+ ipp_t* ipp = result->ipp.get();
+ EXPECT_FALSE(ippFindAttribute(ipp, fake_attr_name.c_str(), IPP_TAG_TEXT));
+}
+
// TODO(crbug.com/945409): Test IPP validation.
} // namespace