sudo-project/sudo

Feature Request - Notify Prompt - Willing to create PR

KaibutsuX opened this issue · 7 comments

I often have multiple terminals open with each terminal running some pipeline, (compiling, linting, installing, etc).

Some of those pipelines take a very long time and other than intermittently checking back in with each terminal, I have no way of knowing if a pipeline is done compiling and waiting to install and sitting at a sudo prompt for installation permission.

I would like to provide a user-configurable way to hook some (pre-approved and defined) external tool to let me know that sudo is waiting for input before it eventually times out the and pipeline fails.

I have a proof of concept which accomplishes exactly what I want:

// in src/tgetpass.c::tgetpass
// right before writing the prompt to output

if (notify) {
    system("notify-send \"sudo\" \"sudo is prompting for a password\"");
}

I realize I don't want the external tool to be any arbitrary executable which could allow an injection and I don't want the notification to be configurable either. I would imagine that the user could specify something in the sudoers conf file something like:

Defaults promptpass_notify=notify-send

And the values for that option would be checked at init time to ensure there are no arbitrary calls to unexpected notifier scripts. (Although I realize someone could just symlink whatever they want, is this even a concern? This would be executed before sudo was even authorized to execute the given command)

I would be willing to do the legwork on this feature, but I got stuck in understanding how to implement this with support for editing with visudo and where a flag like this would live in conf or if it should just be an env flag.

I had a similar issue recently, I was able solve it by creating a quick and dirty python program that I passed to the SUDO_ASKPASS env variable. If sudo is invoked using sudo -A then a the python script runs the notify command and then waits for the user input. Hope that helps :)

I realize that's possible, but 1) I don't really want to have to write my own script which collects and passes back the password, and 2) that assumes that the existing sudo workflow is using -A, which in my case, it isn't.

I don't want the overhead of waiting, collecting a password and passing it back, I just want support for a one-way, async script execution. Just like how sudo has support for BEL, it just prints \a, I just want support for system(script)

I realize that's possible, but 1) I don't really want to have to write my own script which collects and passes back the password, and 2) that assumes that the existing sudo workflow is using -A, which in my case, it isn't.

I don't want the overhead of waiting, collecting a password and passing it back, I just want support for a one-way, async script execution. Just like how sudo has support for BEL, it just prints \a, I just want support for system(script)

I think writing your own python script is probably/possibly easier and safer in this scenario. Allowing for a arbitrary system(script) capability doesn't seem like a good idea for a setuid binary like sudo to engage in especially considering the littany of ways this can compromise system integrity (the system() man page explicitly calls out this behavior Do not use system() from a privileged program (a set-user-ID or set-group-ID program, or a program with capabilities)).

Even if this feature is implemented, it will be behind some kind of flag, and not enabled by default, requiring you to change your workflows. To me it just seems logical to use sudo -A with a python/bash script (or a executable if you want to be extra cautious).

If I were to support it, I would just have sudo check for $SUDO_NOTIFY env and then do it. My proposal specifically says it would not be an arbitrary system call, it would have to be a pre-defined binary that could be run.

Can you explain how I could use sudo -A in a situation where the pre-existing workflow is only using sudo? My only idea is to create a global system-wide replacement where sudo is replaced by sudo -A for all sudo calls.

If I were to support it, I would just have sudo check for $SUDO_NOTIFY env and then do it. My proposal specifically says it would not be an arbitrary system call, it would have to be a pre-defined binary that could be run.

How would you find the specific binary ? How do you check the integrity of the binary that is notifying users (to make sure it is indeed notify-send and not a malicious program) ? (Note that notify-send is not guaranteed to be on Unix systems, especially on non-graphical systems)

Can you explain how I could use sudo -A in a situation where the pre-existing workflow is only using sudo? My only idea is to create a global system-wide replacement where sudo is replaced by sudo -A for all sudo calls.

You could alias sudo to sudo -A on your favourite shell(s). Alternatively, you could create a binary that runs sudo.bck -A $@ when you run it and mv it to /usr/bin/sudo (in this case, you would move the original sudo binary to /usr/bin/sudo.bck)

(I am assuming here that you want this for personal use and do not intend to deploy this on a large scale)

How would you find the specific binary ? How do you check the integrity of the binary that is notifying users (to make sure it is indeed notify-send and not a malicious program) ? (Note that notify-send is not guaranteed to be on Unix systems, especially on non-graphical systems)

The user would supply the full path in the config of the expected binary. If the path doesn't exist, then the config'ed value wouldn't be run. Why would the binary need to be verified? Sudo is already being used to run an arbitrary command with elevated permissions. If I have permission to run sudo rm -rf / then where is the harm in running a config option without elevated privileges like /usr/bin/notify-send or /usr/bin/wall before authenticating?

You could alias sudo to sudo -A on your favourite shell(s). Alternatively, you could create a binary that runs sudo.bck -A $@ when you run it and mv it to /usr/bin/sudo (in this case, you would move the original sudo binary to /usr/bin/sudo.bck)

Yeah, that's what I didn't really want, because now I to supply my own password prompting mechanism. Also, if I have to write my own prompting logic, does that negate sudo's timeout logic for re-prompting for another password within a given time period?