Bug 1813572

Summary: gssproxy doesn't work with freeradius
Product: Red Hat Enterprise Linux 8 Reporter: Tomasz Kepczynski <tomek>
Component: selinux-policyAssignee: Zdenek Pytela <zpytela>
Status: CLOSED ERRATA QA Contact: Milos Malik <mmalik>
Severity: medium Docs Contact:
Priority: medium    
Version: 8.1CC: ascheel, lvrabec, mmalik, plautrba, rharwood, ssekidde
Target Milestone: rcKeywords: Triaged
Target Release: 8.3Flags: pm-rhel: mirror+
Hardware: x86_64   
OS: Linux   
Whiteboard:
Fixed In Version: Doc Type: No Doc Update
Doc Text:
Story Points: ---
Clone Of: Environment:
Last Closed: 2020-11-04 01:56:06 UTC Type: Bug
Regression: --- Mount Type: ---
Documentation: --- CRM:
Verified Versions: Category: ---
oVirt Team: --- RHEL 7.3 requirements from Atomic Host:
Cloudforms Team: --- Target Upstream Version:
Embargoed:

Description Tomasz Kepczynski 2020-03-14 14:12:09 UTC
Description of problem:
AVC denials when trying to use gssproxy for freeradius

Version-Release number of selected component (if applicable):
freeradius-3.0.17-6.module_el8.1.0+198+858eb655.x86_64
freeradius-doc-3.0.17-6.module_el8.1.0+198+858eb655.x86_64
freeradius-ldap-3.0.17-6.module_el8.1.0+198+858eb655.x86_64
freeradius-utils-3.0.17-6.module_el8.1.0+198+858eb655.x86_64
gssproxy-0.8.0-14.el8.x86_64
selinux-policy-targeted-3.14.3-20.el8.noarch

How reproducible:
Always

Steps to Reproduce:
1. Configured ipa & freeradius to leverage LDAP directory. The most importand part is to set:
   ldap sasl mech = GSSAPI
   ldap sasl realm = <IPA REALM>
   ldap server = <ipa server>
2. Created radius service principal in ipa:
   ipa service-add radius/<hostname>
   and stored it in /etc/krb5.keytab
3. Configured gssproxy to maintain client credentials:
# cat /etc/gssproxy/11-radius.conf 
[service/radiusd]
  mechs = krb5
  krb5_principal = radius/<hostname>
  cred_store = keytab:/etc/krb5.keytab
  cred_store = client_keytab:/etc/krb5.keytab
  cred_store = ccache:/tmp/krb5cc-%u
  cred_usage = initiate
  euid = radiusd

Actual results:
radiusd does not start, with the following denials:
time->Sat Mar 14 14:21:35 2020
type=PROCTITLE msg=audit(1584192095.872:3072): proctitle=2F7573722F7362696E2F72616469757364002D64002F6574632F7261646462
type=SYSCALL msg=audit(1584192095.872:3072): arch=c000003e syscall=42 success=yes exit=0 a0=a a1=7ffc81aa1140 a2=6e a3=21 items=0 ppid=584 pid=586 auid=4294967295 uid=0 gid=95 euid=95 suid=0 fsuid=95 egid=95 sgid=95 fsgid=95 tty=(none) ses=4294967295 comm="radiusd" exe="/usr/sbin/radiusd" subj=system_u:system_r:radiusd_t:s0 key=(null)
type=AVC msg=audit(1584192095.872:3072): avc:  denied  { connectto } for  pid=586 comm="radiusd" path="/var/lib/gssproxy/default.sock" scontext=system_u:system_r:radiusd_t:s0 tcontext=system_u:system_r:gssproxy_t:s0 tclass=unix_stream_socket permissive=1
type=AVC msg=audit(1584192095.872:3072): avc:  denied  { write } for  pid=586 comm="radiusd" name="default.sock" dev="dm-1" ino=262587 scontext=system_u:system_r:radiusd_t:s0 tcontext=system_u:object_r:gssproxy_var_lib_t:s0 tclass=sock_file permissive=1
type=AVC msg=audit(1584192095.872:3072): avc:  denied  { search } for  pid=586 comm="radiusd" name="gssproxy" dev="dm-1" ino=263941 scontext=system_u:system_r:radiusd_t:s0 tcontext=system_u:object_r:gssproxy_var_lib_t:s0 tclass=dir permissive=1

radiusd starts with permissive selinux mode.

Expected results:
radius starts with gssproxy configured.

Additional info:
1. connectto denial can be rectified with:
setsebool daemons_enable_cluster_mode 1

2. audit2allow suggested module (which does work):
module radiusd-gssproxy 1.0;

require {
        type radiusd_t;
        type gssproxy_var_lib_t;
        type gssproxy_t;
        class unix_stream_socket connectto;
        class sock_file write;
        class dir search;
}

#============= radiusd_t ==============

#!!!! This avc can be allowed using the boolean 'daemons_enable_cluster_mode'
allow radiusd_t gssproxy_t:unix_stream_socket connectto;
allow radiusd_t gssproxy_var_lib_t:dir search;
allow radiusd_t gssproxy_var_lib_t:sock_file write;

3. Things to consider:
- should the credential store be located in /var/lib/gssproxy/clients/ ??? If yes - larger policy (for radius?) is needed.
- should gssproxy be allowed to access separate radius keytab under /etc/raddb (this complicated things for me so for the sake of simplicity I used /etc/krb5.keytab)?

Disclosure: this issue has been found on CentOS 8.1, up to date as of the time of this filing.

Comment 1 Tomasz Kepczynski 2020-03-15 17:11:33 UTC
There is more to it:

type=AVC msg=audit(1584291963.803:4358): avc:  denied  { unlink } for  pid=32736 comm="gssproxy" name="krb5cc-radiusd" dev="dm-1" ino=796884 scontext=system_u:system_r:gssproxy_t:s0 tcontext=system_u:object_r:tmp_t:s0 tclass=file permissive=0                                                                            
type=SYSCALL msg=audit(1584291963.803:4358): arch=c000003e syscall=87 success=no exit=-13 a0=7ff640002c40 a1=0 a2=0 a3=7ff6400008d0 items=0 ppid=1 pid=32736 auid=4294967295 uid=0 gid=0 euid=0 suid=0 fsuid=0 egid=0 sgid=0 fsgid=0 tty=(none) ses=4294967295 comm="gssproxy" exe="/usr/sbin/gssproxy" subj=system_u:system_r:gssproxy_t:s0 key=(null)ARCH=x86_64 SYSCALL=unlink AUID="unset" UID="root" GID="root" EUID="root" SUID="root" FSUID="root" EGID="root" SGID="root" FSGID="root"                                                                                                                                                              
type=PROCTITLE msg=audit(1584291963.803:4358): proctitle=2F7573722F7362696E2F67737370726F7879002D44                                                                                                                                                                                                                           
type=AVC msg=audit(1584291963.817:4359): avc:  denied  { unlink } for  pid=32736 comm="gssproxy" name="krb5cc-radiusd" dev="dm-1" ino=796884 scontext=system_u:system_r:gssproxy_t:s0 tcontext=system_u:object_r:tmp_t:s0 tclass=file permissive=0                                                                            
type=SYSCALL msg=audit(1584291963.817:4359): arch=c000003e syscall=87 success=no exit=-13 a0=7ff640009ff0 a1=0 a2=0 a3=7ff6400008d0 items=0 ppid=1 pid=32736 auid=4294967295 uid=0 gid=0 euid=0 suid=0 fsuid=0 egid=0 sgid=0 fsgid=0 tty=(none) ses=4294967295 comm="gssproxy" exe="/usr/sbin/gssproxy" subj=system_u:system_r:gssproxy_t:s0 key=(null)ARCH=x86_64 SYSCALL=unlink AUID="unset" UID="root" GID="root" EUID="root" SUID="root" FSUID="root" EGID="root" SGID="root" FSGID="root"                                                                                                                                                              
type=PROCTITLE msg=audit(1584291963.817:4359): proctitle=2F7573722F7362696E2F67737370726F7879002D44                                                                                                                                                                                                                           
type=AVC msg=audit(1584292036.228:4361): avc:  denied  { getattr } for  pid=32736 comm="gssproxy" path="/proc/338" dev="proc" ino=738309 scontext=system_u:system_r:gssproxy_t:s0 tcontext=system_u:system_r:radiusd_t:s0 tclass=dir permissive=0                                                                             
type=SYSCALL msg=audit(1584292036.228:4361): arch=c000003e syscall=6 success=no exit=-13 a0=5586444e2190 a1=7fff7df9e090 a2=7fff7df9e090 a3=5586444cd010 items=0 ppid=1 pid=32736 auid=4294967295 uid=0 gid=0 euid=0 suid=0 fsuid=0 egid=0 sgid=0 fsgid=0 tty=(none) ses=4294967295 comm="gssproxy" exe="/usr/sbin/gssproxy" subj=system_u:system_r:gssproxy_t:s0 key=(null)ARCH=x86_64 SYSCALL=lstat AUID="unset" UID="root" GID="root" EUID="root" SUID="root" FSUID="root" EGID="root" SGID="root" FSGID="root"                                                                                                                                          
type=PROCTITLE msg=audit(1584292036.228:4361): proctitle=2F7573722F7362696E2F67737370726F7879002D44                                                                                                                                                                                                                           
type=AVC msg=audit(1584292036.239:4362): avc:  denied  { create } for  pid=32736 comm="gssproxy" name="krb5cc-radiusd" scontext=system_u:system_r:gssproxy_t:s0 tcontext=system_u:object_r:tmp_t:s0 tclass=file permissive=0                                                                                                  
type=SYSCALL msg=audit(1584292036.239:4362): arch=c000003e syscall=257 success=no exit=-13 a0=ffffff9c a1=7ff64002d1e0 a2=800c2 a3=180 items=0 ppid=1 pid=32736 auid=4294967295 uid=0 gid=0 euid=0 suid=0 fsuid=0 egid=0 sgid=0 fsgid=0 tty=(none) ses=4294967295 comm="gssproxy" exe="/usr/sbin/gssproxy" subj=system_u:system_r:gssproxy_t:s0 key=(null)ARCH=x86_64 SYSCALL=openat AUID="unset" UID="root" GID="root" EUID="root" SUID="root" FSUID="root" EGID="root" SGID="root" FSGID="root"                                                                                                                                                           
type=PROCTITLE msg=audit(1584292036.239:4362): proctitle=2F7573722F7362696E2F67737370726F7879002D44                                                                                                                                                                                                                           
type=AVC msg=audit(1584292036.260:4363): avc:  denied  { create } for  pid=32736 comm="gssproxy" name="krb5cc-radiusd" scontext=system_u:system_r:gssproxy_t:s0 tcontext=system_u:object_r:tmp_t:s0 tclass=file permissive=0                                                                                                  
type=SYSCALL msg=audit(1584292036.260:4363): arch=c000003e syscall=257 success=no exit=-13 a0=ffffff9c a1=7ff640002dd0 a2=800c2 a3=180 items=0 ppid=1 pid=32736 auid=4294967295 uid=0 gid=0 euid=0 suid=0 fsuid=0 egid=0 sgid=0 fsgid=0 tty=(none) ses=4294967295 comm="gssproxy" exe="/usr/sbin/gssproxy" subj=system_u:system_r:gssproxy_t:s0 key=(null)ARCH=x86_64 SYSCALL=openat AUID="unset" UID="root" GID="root" EUID="root" SUID="root" FSUID="root" EGID="root" SGID="root" FSGID="root"                                                                                                                                                           
type=PROCTITLE msg=audit(1584292036.260:4363): proctitle=2F7573722F7362696E2F67737370726F7879002D44                                                                                                                                                                                                                           

and related module:

module aaa 1.0;

require {
        type gssproxy_t;
        type tmp_t;
        type radiusd_t;
        class file { create unlink };
        class dir getattr;
}

#============= gssproxy_t ==============
allow gssproxy_t radiusd_t:dir getattr;
allow gssproxy_t tmp_t:file { create unlink };

Comment 3 Zdenek Pytela 2020-06-17 14:13:57 UTC
The AVC from the description will be addressed by the following commit:
https://github.com/fedora-selinux/selinux-policy-contrib/pull/271
No need for a boolean.

c#1 contains two issues:
- gssproxy_t reading processes state is addressed in current RHEL version
- dealing with tmp files requires additional information to decide about the proper approach to fix it


Robert/gssproxy team:
- can you answer the questions asked in item 3. in the description?
- which service is expected to deal (create, read, write, delete) with the krb5cc-radiusd temporary files?

Comment 4 Robbie Harwood 2020-06-17 16:25:23 UTC
My preferred name is Robbie - please use it.

> should the credential store be located in /var/lib/gssproxy/clients/ ??? If yes - larger policy (for radius?) is needed.

That's a gssproxy location - regardless of configuration, freeradius shouldn't be able to read there.  (gssproxy is performing privilege separation.)

> should gssproxy be allowed to access separate radius keytab under /etc/raddb

As far as I know, we don't ship gssproxy configuration for freeradius by default.  (Alex, please correct me if I'm wrong here.)  So this doesn't really matter.

> (this complicated things for me so for the sake of simplicity I used /etc/krb5.keytab)?

In general, each service should have its own keytab.  If you're making them gssproxy-enabled, you should probably put them in a place the service can't access - /etc/gssproxy/radius.keytab would work, for instance.

> which service is expected to deal (create, read, write, delete) with the krb5cc-radiusd temporary files?

I don't understand this question, sorry.  Can you rephrase (possibly assuming I know less about selinux)?

Comment 5 Robbie Harwood 2020-06-17 16:26:42 UTC
Hit send too early.  Clarifying the first:

> should the credential store be located in /var/lib/gssproxy/clients/ ??? If yes - larger policy (for radius?) is needed.

Yes, that's a good place for it.  But freeradius shouldn't be able to read there - that's gssproxy's storage.

Comment 6 Zdenek Pytela 2020-06-19 08:48:45 UTC
Robbie,

Thank you for the answers.

(In reply to Robbie Harwood from comment #4)
> > which service is expected to deal (create, read, write, delete) with the krb5cc-radiusd temporary files?
> 
> I don't understand this question, sorry.  Can you rephrase (possibly
> assuming I know less about selinux)?
SELinux confines processes to separate them in domains and gives a domain access only to files with some labels. If an interaction between 2 domains is required, policy needs to have a rule like this one:

  gssproxy_stream_connect(radiusd_t)

My questions are based on denials in c#1: gssproxy wants to create and unlink /tmp/krb5cc-radiusd which is not allowed in current policy. We probably need to assign a particular label to krb5cc-radiusd, so which other processes will need access to it? gssproxy already has access to krb5_host_rcache_t, assigned e. g. to /var/cache/krb5rcache.

  allow gssproxy_t krb5_host_rcache_t:file { append create getattr ioctl link lock open read rename setattr unlink write };

> > (this complicated things for me so for the sake of simplicity I used /etc/krb5.keytab)?
> 
> In general, each service should have its own keytab.  If you're making them
> gssproxy-enabled, you should probably put them in a place the service can't
> access - /etc/gssproxy/radius.keytab would work, for instance.
It would be good to have it documented so that we can adjust selinux policy rules accordingly, too.

Comment 8 Robbie Harwood 2020-06-19 18:23:57 UTC
Thanks for clarifying - I think I understand the question now.

/tmp/krb5cc-radiusd is a location that the reporter has configured (`cred_store = ccache:/tmp/krb5cc-%u`), not a default.  I don't think selinux needs to allow that by default - I've opened https://github.com/gssapi/gssproxy/issues/5 to further discourage people from doing this regularly.

Comment 9 Zdenek Pytela 2020-06-19 21:43:42 UTC
Robbie,

Thanks for your comment. Switching to POST as the other part has been addressed.

Comment 16 errata-xmlrpc 2020-11-04 01:56:06 UTC
Since the problem described in this bug report should be
resolved in a recent advisory, it has been closed with a
resolution of ERRATA.

For information on the advisory (selinux-policy bug fix and enhancement update), and where to find the updated
files, follow the link below.

If the solution does not work for you, open a new bug report.

https://access.redhat.com/errata/RHBA-2020:4528