Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Daemon not running with all groups when "UserID usr:grp" is used #40

Open
rseichter opened this issue Apr 1, 2019 · 17 comments
Open

Daemon not running with all groups when "UserID usr:grp" is used #40

rseichter opened this issue Apr 1, 2019 · 17 comments

Comments

@rseichter
Copy link

We're currently making several changes to the Gentoo Linux ebuild of OpenDKIM to address security issues. While doing so, we came across a problem which is bugging us. We have a user opendkim which is member of groups opendkim and dkimsocket. Group opendkim is meant to regulate read access to the private key file:

$ ls -l /var/lib/opendkim/
total 8.2M
-r--r----- 1 root     opendkim 1.7K Feb  3  2019 mumble.key
-r--r--r-- 1 root     opendkim  451 Feb  3  2019 mumble.pub
...

Group dkimsocket is meant to regulate write access to a local socket file via the following settings:

$ cat /etc/opendkim/opendkim.conf
Socket local:/run/opendkim/socket
UserID opendkim:dkimsocket
UMask 0117
...

$ ls -l /run/opendkim/
total 0
srw-rw---- 1 opendkim dkimsocket 0 Apr  1 19:38 socket=

Unfortunately the resulting process runs as only one group, namely dkimsocket, instead of running as both opendkim and dkimsocket:

$ cat /proc/26389/status
Name:    opendkim
...
Uid:    108   108   108   108
Gid:    1007  1007  1007  1007
FDSize: 64
Groups: 1007

When using only UserID opendkim (no group), and when dkimsocket is that user's primary group, the process picks up both groups, dkimsocket and opendkim:

$ cat /proc/26778/status
Name:    opendkim
...
Uid:    108   108   108   108
Gid:    1007  1007  1007  1007
FDSize: 64
Groups: 108 1007

The combined result is that we cannot enforce access to the private key and the local socket using distinct groups. This matters because the MTA needs to write to the socket but should not have access to the key file, while OpenDKIM should not be able to access any of the MTA's files.

I can set the owner of mumble.key to opendkim:opendkim instead of root:opendkim, but from a security standpoint this means that if some adversary manages to run code as opendkim he can overwrite the key material.

@dilyanpalauzov
Copy link

dilyanpalauzov commented May 2, 2019

You wrote, that if no groups are explicitly provided in the configuration file, the process runs under both groups. Isn’t that good?

What do you propose to do here?

@rseichter
Copy link
Author

We need UserID opendkim:dkimsocket because this is currently the only way to specify a group (shared with the MTA) for the local socket file. Alas, if we use this setting, the process is not using group opendkim and thus cannot read the private key file.

A possible solution is to make OpenDKIM's process run with all groups assigned to the opendkim user.

@dilyanpalauzov
Copy link

Why UserID opendkim does not help?

Why don’t you set the user and groups before starting opendkim, so that the latter is started with the correct identity and does not have to change anything?

@rseichter
Copy link
Author

Why UserID opendkim does not help?

As I already wrote, we need to specify the group for the local socket, and that can only be done using UserID opendkim:dkimsocket.

Why don’t you set the user and groups before starting opendkim, so that the latter is started with the correct identity and does not have to change anything?

I don't know what you mean? OpenDKIM is started as root and then drops privileges. This is standard daemon behaviour, and it means the OpenDKIM process is responsible for handling this correctly.

@dilyanpalauzov
Copy link

You wrote, that with just UserId opendkim the process has two runtime groups and this implies that the process can access both keys and socket.

OpenDKIM could be started with dropped privileges (e.g. by systemd) and not drop them further by itself.

@dilyanpalauzov
Copy link

dilyanpalauzov commented May 2, 2019

Does it help, if the primary and secondary groups are switched?

@dilyanpalauzov
Copy link

dilyanpalauzov commented May 2, 2019

Does Gentoo use the develop branch from here, as it contains fixes, not on master?

@rseichter
Copy link
Author

You wrote, that with just UserId opendkim the process has two runtime groups and this implies that the process can access both keys and socket.

If no group is specified via UserId, we cannot be certain which of the two groups is used for the socket.

OpenDKIM could be started with dropped privileges (e.g. by systemd)
and not drop them further by itself.

Gentoo allows users to choose between various init systems. Writing workarounds for each of these is not a practical solution.

Does Gentoo use the develop branch from here, as it contains fixes, not on master?

We currently only package stable OpenDKIM relases. I can of course build manually if you need help with testing changes.

@dilyanpalauzov
Copy link

I would say that for the socket (file creation) the primary group is used, so is a matter of having opendkim belonging to two groups. The primary group is shared with the socket file, the secondary group is shared with the dkim key files.

OpenDKIM on the master branch, does not normalize correctly headers, if there is immediately new line after the colon; does not work properly in sign+verify mode for emails bigger that 64kb, does not document how to tweak sendmail not to break signatures, when relaying emails to other servers, does not compile with recent gnutls, has concurrent races… You better distribute the code from the develop branch.

@rseichter
Copy link
Author

The primary group is shared with the socket file, the secondary group is shared with the dkim key files.

How difficult would it be to add a config parameter like SocketId SocketOwner:SocketGroup to specifically set ownership of a local socket file? We cannot reliably enforce primary or secondary group membership. The user may choose one or the other as primary group, or altogether different groups, depending on his personal setup. For example, a user could use the postfix or milter groups for the local socket.

You better distribute the code from the develop branch.

Well, we need some form of stability, because we are patching OpenDKIM to better integrate with our various init systems. We have provided our changes in pull request #41 but have not had any response at all so far. 🙁

@dilyanpalauzov
Copy link

dilyanpalauzov commented May 3, 2019

OpenDKIM on github is not maintained, therefore doing any change is very difficult. E.g. replacing == with = in configure.ac for better portability is very difficult.

How many more programs you have that require running under two groups?

The master branch/tagged releases do not offer the stability you are looking for. You better put your time in offereng OpenDKIM which has no known errors, mitigating the fact, that the project is not maintained, rather than running the process under several groups.

@dilyanpalauzov
Copy link

Just call chgrp of the socket in the start script with the right group, once OpenDKIM is started.

@rseichter
Copy link
Author

Thanks, but like I already wrote, adding workarounds for multiple init systems is not a practical solution. I hope @mskucherawy will eventually comment on this issue.

@mskucherawy
Copy link
Member

Hi, sorry for the delay in getting back to you. I don't have a Gentoo environment so I'm left to guess a bit as to what's going on here.

If I understand correctly, you're hoping that the process of changing to the opendkim user will inherit not only the group specified for it in the password file, but the groups listed for it in /etc/group.

The code in main() that does this follows this sequence when you're running as root and requested a user that is not root:

  • call initgroups() to set your group memberships to those of the requested user and group
  • call setgid() to change your real and effective gid to that of the requested user
  • call setuid() to change your real and effective uid to that of the requested user

These calls are all completing, because we consider it fatal if any of them fail, and you're not reporting a crash. So all of the groups you need should in theory be there in the process.

@mskucherawy
Copy link
Member

@rseichter
Copy link
Author

I don't have a Gentoo environment so I'm left to guess a bit as to what's going on here.

@mskucherawy If you like, I can provide you with a VirtualBox based Gentoo VM (which I am using with macOS host systems) to save you the effort of setting up Gentoo yourself.

If I understand correctly, you're hoping that the process of changing to the opendkim user will inherit not only the group specified for it in the password file, but the groups listed for it in /etc/group.

Yes. That's the expected behaviour on our end, and it would solve our problems. Also, because it is related to this issue, please consider our pull request #41.

https://archives.gentoo.org/gentoo-user/message/434564ff134f8400bf080822200dfb4d

That could indeed be related. You wrote that you are already using initgroups() et al, but this does not seem to suffice. Gentoo is not really exotic in that regard, and I don't know what is causing the problems.

@dilyanpalauzov
Copy link

My understanding of the problem is, that each process and user have a primary group (per /etc/passwd) and other groups (from /etc/group). Newly created files are owned by the primary group. Gentoo wants to specify in the configuration file the primary group (the group owning the milter socket), and not extract the information by default (from /etc/passwd). The reason is, that the user can change the primary group in /etc/passwd as the user wants, but this shall not have impact on the owning group of the milter socket.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

No branches or pull requests

3 participants