Check the peer credentials when opening a remote socket#1580
Conversation
bjorn3
left a comment
There was a problem hiding this comment.
I didn't review the parsing code and tests too closely.
|
|
||
| [features] | ||
| apparmor = [] | ||
| unstable-remote-sudoers = [] |
There was a problem hiding this comment.
unstable-remote-sudoers is already unconditionally enabled for the sudo binary we test:
| When managing enterprise-wide sudoers rules, it is sometimes preferable to store them in a centralized repository. The @socket directive can be used to include the contents provided by a server application over a Unix domain socket. For example, providing: | ||
|
|
||
| @socket /var/run/providers/sudoers.socket | ||
| @socket /var/run/providers/sudoers.socket (sssd:%sssd) |
There was a problem hiding this comment.
Requiring a % is inconsistent with Runas_Spec.
There was a problem hiding this comment.
Oh! Sorry. I followed a limited version of Runas_Member for each component.
So far I was accepting a single user and group. Do you want to accept a Runas_List for each of them?
Also, the user was mandatory, but I see that for Runas_spec the user is optional. Should I also accept an empty user?
| if stream.peek() != Some('\n') { | ||
| // Allow newline, '(' for @socket peer spec, or whitespace | ||
| let next = stream.peek(); | ||
| if next != Some('\n') && next != Some('(') && next != Some(' ') && next != Some('\t') { |
There was a problem hiding this comment.
Maybe use skip_trailing_whitespace(stream)?;? That will also handle line continuation using \.
| peer_spec: Option<&'a ast::PeerSpec>, | ||
| } | ||
|
|
||
| fn include(cfg: &mut Sudoers, ctx: &mut IncludeContext) { |
There was a problem hiding this comment.
IncludeContext can be passed by-value, right?
There was a problem hiding this comment.
I think it is not possible because ctx.diagnostics needs to be mutable to call push(). Do you agree?
| uid: 0, | ||
| gid: 0, | ||
| }; | ||
| let mut ucred_size = std::mem::size_of::<UserCreds>() as libc::socklen_t; |
There was a problem hiding this comment.
I believe size_of is already in the prelude with rust 1.85.
There was a problem hiding this comment.
You are absolutely right. I missed that.
| libc::SO_PEERCRED, | ||
| &mut ucred as *mut _ as *mut libc::c_void, | ||
| &mut ucred_size, | ||
| ) |
There was a problem hiding this comment.
Maybe do unsafe { cerr(libc::getsockopt(...))?; }?
| pid: libc::pid_t, | ||
| uid: libc::uid_t, | ||
| gid: libc::gid_t, | ||
| } |
There was a problem hiding this comment.
libc::ucred can be used instead, right? There is no guarantee that every target we will support uses this exact layout.
| // SAFETY: | ||
| // For the moment we use getsockopt() from libc passing a pointer to the | ||
| // correct C structure. Data is written to this structure. | ||
| // In the future this will be replaced by UnixStream::peer_cred() |
There was a problem hiding this comment.
| // SAFETY: | |
| // For the moment we use getsockopt() from libc passing a pointer to the | |
| // correct C structure. Data is written to this structure. | |
| // In the future this will be replaced by UnixStream::peer_cred() | |
| // SAFETY: An out pointer for the correct type and length are passed. | |
| // FIXME use UnixStream::peer_cred() once stable in our MSRV. |
This feature was introduced not long ago and needs to be applied also for the e2e socket tests.
The directive @socket now takes the expect user and possibly group that the peer at the other en of the socket must be running as. This information must follow the socket path and be enclosed in parentheses: @socket /path/to/socket (user:%group) Non-posix groups are not accepted (%:). Numeric values are accepted preceded by #. Existing tests where updated and a new unit test was added fori the parsing. Man pages were also updated.
The previous commit added an 8th paramters to include(). To reduce this number, an IncludeContext structure was created and used to pass only two parameters to the function (the configuration and this structure with all the other parameters).
The PR fixes the TOCTOU introduced with the socket reading by checking the credentials of the peer process at the other side of the socket.
The directive is now:
These changes are introduced in the second commit. Tests and man pages are updated and a new unit test was added. Please see the commit message for more details.
The first commit makes remote sudoers 2e2 tests use the
unstable-remote-sudoersfeature that was previously introduced.The third commit is an add-on to the second one. Because the second commit added an 8th parameter to the
include()function,cargo clippycomplains about having too many parameters. This commit is my proposition to fix this, but I'm not sure you agree with it. Basically it introduces a newIncludeContextstructure where the parameters are stored and this context is passed as the second parameter (the first one being the configuration). If you agree with this solution, I will merge both commits into a single one as it is useless to have them separate.Resolves: #1549