cups-filters/foomaticrip-reject-unknown-values.patch
2025-10-09 17:37:42 +02:00

144 lines
5.0 KiB
Diff

diff --git a/filter/foomatic-rip/foomatic-rip.1.in b/filter/foomatic-rip/foomatic-rip.1.in
index 9685a95..3dff521 100644
--- a/filter/foomatic-rip/foomatic-rip.1.in
+++ b/filter/foomatic-rip/foomatic-rip.1.in
@@ -193,6 +193,15 @@ friends. Several PPD files use shell constructs that require a more
modern shell like \fBbash\fR, \fBzsh\fR, or \fBksh\fR.
+.SH PPD OPTION VALUE RESTRICTIONS AND EXCEPTIONS
+
+The values of PPD options \fBFoomaticRIPCommandLine\fR, \fBFoomaticRIPCommandLinePDF\fR and \fBFoomaticRIPOptionSetting\fR
+are rejected in the default configuration because of security implications. Users can use the tool \fBfoomatic-hash(1)\fR, which provides
+values of affected PPD options from found drivers and hashes of those values in hexadecimal format. User is expected to review the found values,
+and if there is nothing suspicious in the output, copy the file with hashes into into the directory \fB@sysconfdir@/foomatic/hashes.d\fR
+to allow the exceptions for found values.
+
+
.SH FILES
.PD 0
.TP 0
@@ -209,6 +218,13 @@ The PPD files of the currently defined printers
Configuration file for foomatic-rip
+.TP 0
+@sysconfdir@/foomatic/hashes.d
+.TP 0
+@datadir@/foomatic/hashes.d
+
+Directories with hashes of allowed values
+
.PD 0
.\".SH SEE ALSO
diff --git a/filter/foomatic-rip/options.c b/filter/foomatic-rip/options.c
index 3c6b63d..6c5b1a3 100644
--- a/filter/foomatic-rip/options.c
+++ b/filter/foomatic-rip/options.c
@@ -109,6 +109,43 @@ out:
return profile;
}
+
+//
+// 'is_allowed_value' - Check if the option value is allowed.
+//
+
+int // O - Boolean value - true 1 / false 0
+is_allowed_value(cups_array_t *ar, // I - Array of already known hashes from system
+ char *value, // I - Scanned value from PPD file
+ size_t value_len) // I - Value length
+{
+ char hash_string[65]; // Help array to store hexadecimal hashed string
+
+ //
+ // Empty string is allowed...
+ //
+
+ if (!value_len)
+ return (1);
+
+ //
+ // Hash the value and get hexadecimal string for it...
+ //
+
+ if (hash_data((unsigned char*)value, value_len, hash_string, sizeof(hash_string)))
+ return (0);
+
+ //
+ // Check if the found hexadecimal hashed string is in the array -> allowed on the system...
+ //
+
+ if (cupsArrayFind(ar, hash_string))
+ return (1);
+
+ return (0);
+}
+
+
/* a selector is a general tri-dotted specification.
* The 2nd and 3rd elements of the qualifier are optionally modified by
* cupsICCQualifier2 and cupsICCQualifier3:
@@ -1562,12 +1599,19 @@ void read_ppd_file(const char *filename)
option_t *opt, *current_opt = NULL;
param_t *param;
icc_mapping_entry_t *entry;
+ cups_array_t *known_hashes = NULL;
fh = fopen(filename, "r");
if (!fh)
rip_die(EXIT_PRNERR_NORETRY_BAD_SETTINGS, "Unable to open PPD file %s\n", filename);
_log("Parsing PPD file ...\n");
+ if (load_system_hashes(&known_hashes))
+ {
+ fclose(fh);
+ rip_die(EXIT_PRNERR_NORETRY, "Not enough memory for array allocation\n.");
+ }
+
dstrassure(value, 256);
qualifier_data = list_create();
@@ -1642,9 +1686,25 @@ void read_ppd_file(const char *filename)
unhtmlify(postpipe->data, postpipe->alloc, value->data);
}
else if (strcmp(key, "FoomaticRIPCommandLine") == 0) {
+ if (!is_allowed_value(known_hashes, value->data, strlen(value->data)))
+ {
+ cupsArrayDelete(known_hashes);
+ fclose(fh);
+
+ rip_die(EXIT_PRNERR_NOTALLOWED, "ERROR: The value of the key %s is not among the allowed values - see foomatic-rip man page for more instructions.\n", key);
+ }
+
unhtmlify(cmd, 4096, value->data);
}
else if (strcmp(key, "FoomaticRIPCommandLinePDF") == 0) {
+ if (!is_allowed_value(known_hashes, value->data, strlen(value->data)))
+ {
+ cupsArrayDelete(known_hashes);
+ fclose(fh);
+
+ rip_die(EXIT_PRNERR_NOTALLOWED, "ERROR: The value of the key %s is not among the allowed values - see foomatic-rip man page for more instructions.\n", key);
+ }
+
unhtmlify(cmd_pdf, 4096, value->data);
}
else if (!strcmp(key, "cupsFilter")) {
@@ -1765,6 +1825,14 @@ void read_ppd_file(const char *filename)
option_set_choice(current_opt, name, text, value->data);
}
else if (!strcmp(key, "FoomaticRIPOptionSetting")) {
+ if (!is_allowed_value(known_hashes, value->data, strlen(value->data)))
+ {
+ cupsArrayDelete(known_hashes);
+ fclose(fh);
+
+ rip_die(EXIT_PRNERR_NOTALLOWED, "ERROR: The value of the key %s is not among the allowed values - see foomatic-rip man page for more instructions.\n", key);
+ }
+
/* "*FoomaticRIPOptionSetting <option>[=<choice>]: <code>
For boolean options <choice> is not given */
option_set_choice(assure_option(name),