I would like to revisit the issue of denyhosts and selinux and address it properly. From what I gather from the earlier discussion, it would be best to write a proper policy for denyhosts. Unfortunately, I'm almost completely ignorant of what needs to happen here.
Here's some essential info about denyhosts:
Denyhosts is written in python. It runs as root either as a daemon or spawned from cron. It consists of an executable script (/usr/bin/denyhosts.py), some python modules in /usr/lib/python2.4/site-packages/DenyHosts, a config file (/etc/denyhosts.conf), and some databases under /var/lib/denyhosts.
During its operation it reads /var/log/secure, maintains databases and such under /var/lib/denyhosts, and writes to /etc/hosts.deny. It may also make some xmlrpc calls out over the 'net if so configured (although by default this is not the case).
One complication is that denyhosts can call out to user-supplied scripts which can do pretty much anything. I've no idea how to properly handle that kind of thing.
Could someone perhaps help me to get started with a policy?
- J<
On Tue, 2006-11-28 at 13:58 -0600, Jason L Tibbitts III wrote:
I would like to revisit the issue of denyhosts and selinux and address it properly. From what I gather from the earlier discussion, it would be best to write a proper policy for denyhosts. Unfortunately, I'm almost completely ignorant of what needs to happen here.
Here's some essential info about denyhosts:
Denyhosts is written in python. It runs as root either as a daemon or spawned from cron. It consists of an executable script (/usr/bin/denyhosts.py), some python modules in /usr/lib/python2.4/site-packages/DenyHosts, a config file (/etc/denyhosts.conf), and some databases under /var/lib/denyhosts.
During its operation it reads /var/log/secure, maintains databases and such under /var/lib/denyhosts, and writes to /etc/hosts.deny.
The delicate issue there is that other programs read /etc/hosts.deny, so if we move it into its own type (so that we only have to allow denyhosts to write to it and not other files in /etc), then we have to adjust any other domains that need to read the new type. An intermediate point is to push it into etc_runtime_t, a generic type used for runtime generated or modified etc files.
It may also make some xmlrpc calls out over the 'net if so configured (although by default this is not the case).
So network access could be under a boolean.
One complication is that denyhosts can call out to user-supplied scripts which can do pretty much anything. I've no idea how to properly handle that kind of thing.
User-supplied or admin-supplied? The scripts should run with the full privileges of denyhosts or with a reduced subset?
Could someone perhaps help me to get started with a policy?
Most people start with an existing module from the policy sources (.src.rpm or upstream tarball) and work from it, or use /usr/share/selinux/devel/policygentool (from selinux-policy-devel) to create an initial stub. Or use SLIDE and its module building wizard if you are into Eclipse.
You need to create a .te file with the policy declarations and rules, a .fc file with the file contexts, and an .if file with an interfaces the policy module exports to others (e.g. to access the /etc/hosts.deny file if you put it into a private type, or to transition into the denyhosts domain from a caller).
Incomplete samples below, no guarantees on correctness...
denyhosts.te:
policy_module(denyhosts, 1.0.0)
############## # # Declarations #
type denyhosts_t; # type for the running process type denyhosts_exec_t; # type for the executable on disk init_daemon_domain(denyhosts_t, denyhosts_exec_t) # runs as a daemon cron_system_entry(denyhosts_t, denyhosts_exec_t) # and as a cron job
type denyhosts_conf_t; files_config_file(denyhosts_conf_t)
type denyhosts_var_run_t; files_pid_file(denyhosts_var_run_t)
type denyhosts_var_lib_t; files_type(denyhosts_var_lib_t)
########################### # # Local policy #
allow denyhosts_t denyhosts_conf_t:file r_file_perms; files_search_etc(denyhosts_t)
allow denyhosts_t denyhosts_var_run_t:file create_file_perms; allow denyhosts_t denyhosts_var_run_t:dir rw_dir_perms; files_pid_filetrans(denyhosts_t,denyhosts_var_run_t,file)
allow denyhosts_t denyhosts_var_lib_t:dir rw_dir_perms; allow denyhosts_t denyhosts_var_lib_t:file create_file_perms; files_var_lib_filetrans(denyhosts_t,denyhosts_var_lib_t,file)
corecmd_exec_bin(denyhosts_t) corecmd_exec_shell(denyhosts_t) corecmd_search_sbin(denyhosts_t)
files_read_usr_files(denyhosts_t) files_read_etc_files(denyhosts_t) files_read_etc_runtime_files(denyhosts_t)
denyhosts.fc: /usr/bin/denyhosts.py -- gen_context(system_u:object_r:denyhosts_exec_t,s0) /etc/denyhosts.conf -- gen_context(system_u:object_r:denyhosts_conf_t,s0) /var/lib/denyhosts(/.*)? gen_context(system_u:object_r:denyhosts_var_lib_t,s0)
Thanks for the info!
"SS" == Stephen Smalley sds@tycho.nsa.gov writes:
SS> The delicate issue there is that other programs read SS> /etc/hosts.deny, so if we move it into its own type (so that we SS> only have to allow denyhosts to write to it and not other files in SS> /etc), then we have to adjust any other domains that need to read SS> the new type.
Ah, of course, you can't allow something to read a file by name, just by type. Mighty inconvenient, that.
SS> User-supplied or admin-supplied? The scripts should run with the SS> full privileges of denyhosts or with a reduced subset?
Admin-supplied, I suppose. This is essentially an admin-only application; you have to explicitly modify the root-owned config file in order to enable a particular script.
I can't speak to what the scripts should be able to do. Folks could be doing anything at all with them (as they're called via exec), but I suspect they're not being used at all in the vast majority of cases. Is it possible for the end-user (end-admin?) to do something quick to force an executable to transition into the unconfined domain?
I'll have to dig into the policy bits you sent; most of it is self-explanatory but I'm sure there are many subtleties I'm missing.
- J<
On Tue, 2006-11-28 at 21:01 -0600, Jason L Tibbitts III wrote:
Thanks for the info!
"SS" == Stephen Smalley sds@tycho.nsa.gov writes:
SS> The delicate issue there is that other programs read SS> /etc/hosts.deny, so if we move it into its own type (so that we SS> only have to allow denyhosts to write to it and not other files in SS> /etc), then we have to adjust any other domains that need to read SS> the new type.
Ah, of course, you can't allow something to read a file by name, just by type. Mighty inconvenient, that.
Inconvenient, but correct.
SS> User-supplied or admin-supplied? The scripts should run with the SS> full privileges of denyhosts or with a reduced subset?
Admin-supplied, I suppose. This is essentially an admin-only application; you have to explicitly modify the root-owned config file in order to enable a particular script.
Ok, that simplifies matters.
I can't speak to what the scripts should be able to do. Folks could be doing anything at all with them (as they're called via exec), but I suspect they're not being used at all in the vast majority of cases. Is it possible for the end-user (end-admin?) to do something quick to force an executable to transition into the unconfined domain?
Yes, if you include the following in your denyhosts policy: unconfined_domtrans(denyhosts_t) Then the admin would just need to assign unconfined_exec_t to the executable. But you would likely want that under a boolean too, so that an admin could choose to never allow denyhosts to escalate to unconfined.
Jason L Tibbitts III wrote:
During its operation it reads /var/log/secure, maintains databases and such under /var/lib/denyhosts, and writes to /etc/hosts.deny. It may also make some xmlrpc calls out over the 'net if so configured (although by default this is not the case).
I just wanted to point out that I don't run DenyHosts to write directly to hosts.deny. Here is how I have tcpwrappers configured:
---- hosts.allow ---- # Whitelist my LAN ALL: 192.168.1.0/255.255.255.0
sshd: /etc/hosts.deny.sshd : DENY sshd: /etc/hosts.allow.us # hosts.allow.us is a list of IPs in the USA only, since that's # where I live. No reason to accept SSH from where I don't.
---- hosts.deny ---- ALL: ALL
So, hosts.deny just denies everything, and services need to be whitelisted in hosts.allow. I have DenyHosts write to /etc/hosts.deny.sshd, and any IP not in the US is already denied. As you can see, it would be pointless to append to hosts.deny.
I'm sure there are plenty of other people who do it this way, since it's a configuration option in DenyHosts. I just wanted to point it out so you don't go making changes to the SELinux policy and leave out the possibility of writing to an alternate deny file like I have done.
"JC" == Jeff Carlson jeff@ultimateevil.org writes:
JC> I just wanted to point out that I don't run DenyHosts to write JC> directly to hosts.deny.
And you have selinux enabled, and it already gets the proper context on /etc/hosts.deny.sshd? Because this doesn't seem to be working for others.
JC> I'm sure there are plenty of other people who do it this way, JC> since it's a configuration option in DenyHosts.
There are myriad configuration options in Denyhosts. We have to start somewhere, but I welcome you to test any policy that ends up being written and provide fixes for your particular setup.
- J<
Jason L Tibbitts III wrote:
And you have selinux enabled, and it already gets the proper context on /etc/hosts.deny.sshd? Because this doesn't seem to be working for others.
Well, my SSH gateway is still running FC-4, targeted policy.
$ ls -Z hosts.deny{,.sshd} -rw-r--r-- root root root:object_r:etc_t hosts.deny -rw-r--r-- root root root:object_r:etc_t hosts.deny.sshd
I'm not sure if that was just blind luck or what, but it's working fine for me.
There are myriad configuration options in Denyhosts. We have to start somewhere, but I welcome you to test any policy that ends up being written and provide fixes for your particular setup.
I'm sure that whatever is done, all that I will have to do is copy the context from hosts.deny to hosts.deny.sshd. I'd just hate to be surprised if it stopped working without notice. I'll keep an eye on this list as usual and if a change is made, I'll see if I can implement it on my legacy system (or motivate my lazy self to upgrade).
Jason L Tibbitts III wrote:
"JC" == Jeff Carlson jeff@ultimateevil.org writes:
JC> Well, my SSH gateway is still running FC-4, targeted policy.
Very little chance that this policy would make it into FC4. Probably FC7 only, honestly.
- J<
-- fedora-selinux-list mailing list fedora-selinux-list@redhat.com https://www.redhat.com/mailman/listinfo/fedora-selinux-list
A better solution from the SELinux point of view is to add a new directory. and /etc/denyhosts/ and put your configuration files there. Then the script can read and write that directory. Putting modifiable files in /etc is a bad idea from an SELinux point of view.
"DJW" == Daniel J Walsh dwalsh@redhat.com writes:
DJW> A better solution from the SELinux point of view is to add a new DJW> directory. and /etc/denyhosts/ and put your configuration files DJW> there.
I'm not sure what you're referring to. There's only one configuration file and it's not modified by the program. Surely you can't be saying that every package that has a configuration file in /etc needs to move it into a subdirectory.
If /etc/hosts.deny is the problem, well, that's the location of the file. The denyhosts package doesn't own it.
- J<
On Wed, 2006-11-29 at 12:38 -0600, Jason L Tibbitts III wrote:
"DJW" == Daniel J Walsh dwalsh@redhat.com writes:
DJW> A better solution from the SELinux point of view is to add a new DJW> directory. and /etc/denyhosts/ and put your configuration files DJW> there.
I'm not sure what you're referring to. There's only one configuration file and it's not modified by the program. Surely you can't be saying that every package that has a configuration file in /etc needs to move it into a subdirectory.
If /etc/hosts.deny is the problem, well, that's the location of the file. The denyhosts package doesn't own it.
Yes, /etc/hosts.deny is the issue. The halfway step is to move it into etc_runtime_t and allow denyhosts to write to that type, thereby only opening up access to the set of files in that type and not all of etc_t. The fine-grained step is to move it into its own private type. Either way may involve some changes to other policy modules for processes that need to access that file, but the former should have smaller impact.
Jason L Tibbitts III wrote:
"DJW" == Daniel J Walsh dwalsh@redhat.com writes:
DJW> A better solution from the SELinux point of view is to add a new DJW> directory. and /etc/denyhosts/ and put your configuration files DJW> there.
I'm not sure what you're referring to. There's only one configuration file and it's not modified by the program. Surely you can't be saying that every package that has a configuration file in /etc needs to move it into a subdirectory.
If /etc/hosts.deny is the problem, well, that's the location of the file. The denyhosts package doesn't own it.
- J<
Jeff Carlson used a syntax that looked like you could put the hosts.deny files in a location other than /etc
---- hosts.allow ---- # Whitelist my LAN ALL: 192.168.1.0/255.255.255.0
sshd: /etc/hosts.deny.sshd : DENY sshd: /etc/hosts.allow.us # hosts.allow.us is a list of IPs in the USA only, since that's # where I live. No reason to accept SSH from where I don't.
---- hosts.deny ---- ALL:ALL
I was suggesting you could write the tool in such a way that it had those files in a separate location.
One thing we might want to consider, is adding an attribute ETCFILE or some such and changing files_read_etc_files() to allow reading of these files. This way new tools could define types of files that they want to manage and still allow all of the domains that want to read /etc files succeed. I have a tool right now that wants to manage /etc/fstab.
Dan
"DJW" == Daniel J Walsh dwalsh@redhat.com writes:
DJW> Jeff Carlson used a syntax that looked like you could put the DJW> hosts.deny files in a location other than /etc
Well, you can have denyhosts manage some file other than hosts.deny, but that is not the usual configuration. It might be simpler if that was the default, but I can't really say (since you'd still need to get the context right on that file so that tcp_wrappers could read it) and migrating all existing denyhosts installations on Fedora machines would be nontrivial.
DJW> I was suggesting you could write the tool in such a way that it DJW> had those files in a separate location.
Well, I'm just the maintainer of denyhosts in Fedora Extras. I don't intend to go rewriting it.
- J<
selinux@lists.fedoraproject.org