10

I'm writing a small utility program. I'd like it to attempt to sudo-run something if required.

That is: if file permissions don't allow the current user to operate on a particular file (and sudo rules would allow it) I'd like my utility to sudo-run something as the owner of the file.

I'm hoping to check this ability beforehand, because I'd prefer that system logs don't fill up with noise from failed sudo attempts. As sudo itself reports upon failure: "This incident will be reported".

So, I'm hoping to programatically check: can user <x> run command <y> via sudo?.

Here's the problem: while /etc/sudoers contains that mapping, it's root-owned and not readable by regular users.

I was considering spawning a subprocess to run sudo -l (which outputs commands that the current user can sudo-run). I would then parse the output of this. However, this seems a little fragile. The output contains the information I want, but it seems like it was designed for humans to read (not for programmatic consumption). I don't know if there's any guarantee that the output will follow the same format in future, or across different platforms.

Is programmatic parsing of sudo -l output considered safe? If not, are there any better options, to determine ahead of time whether a sudo command would succeed?


(background on the X/Y: This utility is for use by a limited-access role account. I expect some other users to effectively opt in to allow the limited-access account to operate on their files via sudo rules. However, I won't know ahead of time which of those other users have the relevant sudo rule in place)

migrated from serverfault.com Apr 6 '16 at 12:41

This question came from our site for system and network administrators.

  • 3
    I recommend you take a slightly different approach. Instead of having per-user rules, why not have a group that is allowed to do whatever it is you want it to do. That way, you can simply check if the user is in the group. Would that be a decent alternative? – terdon Apr 6 '16 at 13:02
12

According to the sudo man page:

 -l, --list  If no command is specified, list the allowed (and forbidden)
             commands for the invoking user (or the user specified by the
             -U option) on the current host.  A longer list format is used
             if this option is specified multiple times and the security
             policy supports a verbose output format.

             If a command is specified and is permitted by the security
             policy, the fully-qualified path to the command is displayed
             along with any command line arguments.  If command is
             specified but not allowed, sudo will exit with a status value
             of 1.

so this will boil down to

if sudo -l -U $USER shutdown > /dev/null
then
   ## $USER can
else
   ## $USER cannot
fi 

As pointed out by Muru, use either -U $USER or -U $USERTOTEST or nothing, depending on your need.

  • If you intended $USER to mean the current user, you can just do sudo -l <command>, without -U $USER. – muru Apr 6 '16 at 13:12
  • Thanks - this is useful. One thing I did notice in testing this approach is that it doesn't seem to take care of cases where the sudo rule has been set up to allow ALL commands with particular exceptions, such as (targetUser) ALL, !/usr/bin/foo .. in that case sudo -l -u targetUser /usr/bin/foo still appears to output /usr/bin/foo and exit with status 0. Still, it's basically enough for my simple check, and beats parsing the more verbose sudo -l output. – Peter Martin Apr 8 '16 at 23:03

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service, privacy policy and cookie policy

Not the answer you're looking for? Browse other questions tagged or ask your own question.