bug-hurd
[Top][All Lists]
Advanced

[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]

Re: A deferred authorization-granting translator


From: jbranso
Subject: Re: A deferred authorization-granting translator
Date: Sun, 02 Jan 2022 17:47:56 +0000

December 29, 2021 7:27 AM, "Dr. Arne Babenhauserheide" <arne_bab@web.de> wrote:

> Hi,
> 
> I created a project to ask for granting authorization when processes
> access a file. It is built as a translator and a simple permission
> granting program.
> 
> The translator can delegate permission-granting to the program via two
> FIFO files. The goal is to create a simple replacement for the
> use-case of polkit of granting privilege to a process to access some
> resource after user-interaction with a permission-granting daemon.
> 
> This is the simplest structure I could devise for the use-case: The
> whole system is implemented in about 150 lines of C for the translator
> (building on hello-mt) and 30 lines of bash for the permission
> granting program.
> 
> This code is supported by a small nlnet grant to provide one component
> for sound in the Hurd: practical fine-grained access-control:
> https://nlnet.nl/project/Hurd-Audio
> 
> The original plan in that project was to add sound itself. I
> retargeted it last year to access control to avoid running into
> conflicts with the currently running rump-kernel work.
> 
> Code
> ----
> 
> The code for the translator is attached as patch against
> https://git.savannah.gnu.org/cgit/hurd/hurd.git
> 
> It adds the trans/checkperm.c translator and adds it to trans/Makefile.
> 
> The code for the program is provided inline in this email in the
> usage-example.
> 
> Usage Example
> -------------
> 
> We restrict a the node /hello to require explicit permission for every
> PID that does not have the group `user`. This notably does include
> processes started by root.
> 
> ### How it looks
> 
> **First shell** as root:
> 
> settrans -cga /hello $(realpath ~/Dev/hurd/trans/checkperms) --groupname=user
> su - user --shell /bin/bash -c 'cat /hello'
> # ⇒ HELLOWORLD # user has the group user
> cat /hello # root does not have the group user, so 
> # this blocks until positive reply in the other shell
> 
> **Second shell** (run the program):
> 
> Process 732 tries to access file /hello but is not in the required group user.
> USER PID %CPU %MEM SZ RSS TT STAT START TIME COMMAND
> root 732 0.0 0.1 148M 3.55M p2 Sso Mon 1AM 0:01.10 -bash
> Grant permission and add group "user" for 5 minutes? [y/N]> y
> 
> **First shell** as root:
> 
> # ⇒ HELLOWORLD
> # only blocks once despite getting two reads from cat, 
> # because for the second read cat already has the group `user`.
> 
> ### Trying it yourself
> 
> Setup the development environment with the code at ~/Dev similar to
> https://www.draketo.de/software/hurd-development-environment
> 
> Compile and setup the translator:
> 
> cd ~/Dev/hurd && \
> patch -p1 < checkperms.patch && \
> autoreconf -i && \
> ./configure --without-parted && \
> make && \
> touch trans/checkperms.c && \
> CFLAGS="$CFLAGS -g" make && \
> echo HELLOWORLD > /hello && \
> settrans -cga /hello $(realpath ~/Dev/hurd/trans/checkperms) --groupname=user
> 
> Create the FIFOs:
> 
> USER=root
> GROUP=user
> mkdir -p /run/$USER/request-permission
> mkdir -p /run/$USER/grant-permission
> mkfifo /run/$USER/request-permission/$GROUP
> mkfifo /run/$USER/grant-permission/$GROUP
> 
> Setup the permission-granting program in a separate shell:
> 
> USER=root
> GROUP=user
> while true; do
> PID="$(cat /run/$USER/request-permission/$GROUP)"
> echo Process $PID tries to access file /hello but is not in the required 
> group $GROUP.
> ps-hurd -p $PID -aeux
> if [[ "$(read -e -p 'Grant permission and add group "'$GROUP'" for 5 minutes? 
> [y/N]> '; echo
> $REPLY)" == [Yy]* ]]; then
> addauth -p $PID -g $GROUP
> echo 0 > /run/$USER/grant-permission/$GROUP
> (sleep 300 && rmauth -p $PID -g $GROUP 2>/dev/null) &
> else
> echo 1 > /run/$USER/grant-permission/$GROUP
> fi
> done
> 
> Access the translator as user without the required group and with the group:
> 
> su - user --shell /bin/bash -c 'head -n 1 /hello'
> head -n 1 /hello & 
> 
> Grant permission (currently need to do it for every line that is being read):
> 
> USER=root
> GROUP=user
> cat /run/$USER/request-permission/$GROUP ; echo 0 > 
> /run/$USER/grant-permission/$GROUP
> 
> Concept
> -------
> 
> ### The translator
> 
> The translator is started with a GROUP as argument. When the file is
> accessed, the translator checks whether the process has the given
> group. If it does, it returns data read from the underlying file.
> 
> If the process lacks the required group, the translator retrieves its
> USER and PID and writes the PID into a FIFO located at
> 
> /run/USER/request-permission/GROUP
> 
> Then it reads from 
> 
> /run/USER/grant-permission/GROUP
> 
> It blocks until it gets a reply. If it reads a 0 (=success), it reads
> from the file and returns the data.
> 
> ### The permission granting program
> 
> The permission granting program reads the PID from
> 
> /run/USER/request-permission/GROUP
> 
> retrieves information about the PID and asks the user whether to allow
> the program.
> 
> If the USER answers no, the RET value is non-zero.
> 
> If the USER answers yes, the RET value is zero (0) 
> and the program adds the GROUP to the process at PID (using addauth).
> 
> It also starts a daemon that will remove the group again after 5
> minutes (modelled after the temporary permissions to run privileged
> without password granted by sudo).
> 
> The program then writes the RET value into 
> 
> /run/USER/grant-permission/GROUP
> 
> ### What if the translator crashes?
> 
> If the translator crashes, the permissions return to those of the
> underlying node. For every user except root this usually means that
> the process does not have access to the file.
> 
> The failure-mode should therefore be safe.
> 
> Current limitations
> -------------------
> 
> The current implementation only provides read-access, writing is
> prevented. This is not an intrinsic limitation, only an implementation
> artefact.
> 
> The underlying file is currently read by the translator and the data
> returned to the reading process. To reduce delays, it could directly
> delegate to the underlying file. With the long term goal to provide
> multiplexing of access, for example for audio, reading via the
> translator could be preferable, though.
> 
> Writing to and reading from the FIFOs is currently done with
> `system()`. It would be nicer to move to an implementation that does
> not rely on the system-shell.
> 
> Accesses from two different translators can currently race for the
> reply. To fix this, the translator should write the PID and a random
> LABEL into the request. The program should repeat that label for
> replies to ensure that the reply and request can be matched. If
> receiving a non-matching reply, it MUST be written into the grant
> again after a random delay to enable a matching translator to
> retrieve the grant. 
> REQUEST: PID LABEL 
> GRANT: RET LABEL (RET=0 is success) 
> LABEL=$RANDOM
> 
> The system assumes having a single permission granting program per
> user. For a setup with multiple unconnected sessions per user (like
> several TTYs) the permission granting program needs to coordinate
> between these.
> 
> Possibilities
> -------------
> 
> The most important use-case for this translator is to make it easier
> to start programs with reduced permissions and only add these when
> required.
> 
> To setup deferred permissions for a single file, you can create a
> group just for that file. Then each file can have its own permission
> granting program. Having dedicated groups decouples authentication and
> authorization while staying in the conventional *nix permissions
> scheme.
> 
> You can also set this translator on a file that gets accessed first
> when a process accesses a set of related files that all have the same
> group. Since the authorization-program here adds the group for 5
> minutes, the other files can afterwards be accessed, too.
> 
> Since the translator simply defers to a program, that program could do
> any action to get authorization, including `curl`. Administrators for
> a local network could therefore set up terminals for unprivileged
> users that request permissions from a local server when accessing a
> file. That way permissions can easily be coordinated over multiple
> machines. (naturally this does not restrict root who can always use
> settrans -g to get raw access to the file)
> 
> Personal note
> -------------
> 
> There’s a magic in being asked on the second shell whether cat on the
> first shell should be allowed to access a file for 5 minutes — and all
> that in 150 lines of C and 30 lines of shell.
> 
> The Hurd is pretty cool! (but you knew that ;-) )
> 
> (though I have to admit that getting the translator to actually work
> took ages)

Just out of curiosity which bits were difficult to do?  What sort
of debugging tools would have been nice to have?

> 
> Best wishes,
> Arne
> 
> -- 
> Unpolitisch sein
> heißt politisch sein,
> ohne es zu merken.
> draketo.de



reply via email to

[Prev in Thread] Current Thread [Next in Thread]