0

There's a script from Gutenprint (/usr/lib/cups/backend/gutenprint53+usb) which, to be used, needs to set an environment variable i.e:

sudo BACKEND=printerModel /usr/lib/cups/backend/gutenprint53+usb -sin

On my root account and with sudo, i'm able to use it without any problem, on the other hand, i'm trying to run this from my web server and i get the following error:

sudo: sorry, you are not allowed to set the following environment variables: BACKEND

gutenprint53+usb needs to be run with sudo, so i already added the following with sudo visudo:

www-data ALL = NOPASSWD: /usr/lib/cups/backend/gutenprint53+usb

My question is: is there a way for www-data to set the needed environment variable?

Important: the value of BACKEND will vary, so it's not something i can set beforehand with my root account and share it with www-data.

OS: Raspbian GNU/Linux 10 (buster)

2 Answers 2

1

As with almost every question about sudo, the answer is to write a wrapper script.

In this case, write a shell script to set the BACKEND variable and then run the program.

e.g.

#!/bin/sh

BACKEND=printerModel
export BACKEND

/usr/lib/cups/backend/gutenprint53+usb -sin

and then allow www-data to run that script (but not .../gutenprint53+usb) with sudo.

If necessary, you can allow the www-data to pass the printer model to the wrapper script, but you should be careful to check that the passed data is valid and safe - especially if the "printerModel" data is supplied (directly or indirectly) by a web user.

I don't know what values are valid for the BACKEND variable with gutenprint53+usb, so I'll leave that up to you to find out and code:

#!/bin/sh

# INSERT CODE HERE TO VALIDATE "$1"
#
# This should not test for "known bad" values, instead it 
# should test for "known GOOD" values and exit immediately
# if there is any doubt, anything it does not recognise.
# e.g.

case "$1" in
  printerModel) data_is_good=1 ;;
  AnotherModel) data_is_good=1 ;;
  *) exit 1 ;;
esac

[ "$data_is_good" -eq 1 ] || exit 1

BACKEND="$1"
export BACKEND

/usr/lib/cups/backend/gutenprint53+usb -sin

Alternatively, it may be simpler/easier to just have multiple wrapper scripts (each one with a different hard-coded BACKEND setting) and allow www-data to run all of them with sudo.

3
  • Worked perfectly, thank you. As for the data validation you suggested, before sending the value to that script, i sanitize it on PHP with a preg_replace and run the command with escapeshellcmd. Would it be enough for you? The list of printer models is long, and if multiple printers of the same model are connected i also need to pass another env variable (SERIAL) which makes it harder to hard-code validate.
    – J-D
    Aug 22, 2021 at 9:09
  • It's not about whether it's enough for me. It's your server that could be compromised by an insecure script, not mine. Personally, I believe in defence in depth - it doesn't hurt to check in both places, and doing so may save your system from being cracked. Also, the fact that your expected php code sanitises its input before passing it on to a sh script run by sudo doesn't mean that there won't be other bits of php code on your site that allow programs to be forked without sanitisation. You'll be giving the www-data user the right to run some progrm(s) as root, not just one php script.
    – cas
    Aug 22, 2021 at 9:47
  • Checking the validity of the serial number should be as easy as validating printer model names. Just check if every character in the string is in the set of valid characters (whatever's appropriate for your printers - generally A-Z, a-z, plus, minus, and maybe some other punctuation) - it should be OK as long as you always double-quote the variables in the shell script when you use it and NEVER use it unquoted (that's the cause of the majority of security errors in shell scripts). You should think of data that comes from a web user as deeply suspicious, and never trust it.
    – cas
    Aug 22, 2021 at 9:52
0

Apache supports environment variables. The simplest approach would be to set it in your httpd.conf or .htaccess

SetEnv BACKEND 'printerModel /usr/lib/cups/backend/gutenprint53+usb -sin'

The question is how will you populate this dynamically. You could set this in your .htaccess file, as it will not require a restart of apache. It would be easier to write to as well.

If some worker or something other than www-data tries to reach that variable it won't work.

Furthermore, if you are running apache on a debian based system, you could also insert the variable into /etc/apache2/envvars.

You must log in to answer this question.

Not the answer you're looking for? Browse other questions tagged .