February 21, 2012

Enterprise Linux 5.7 to 5.8 risk report
Red Hat Enterprise Linux 5.8 was released today (February 2012), seven months since the release of 5.7 in July 2011. So let's use this opportunity to take a quick look back over the vulnerabilities and security updates made in that time, specifically for Red Hat Enterprise Linux 5 Server.

Red Hat Enterprise Linux 5 is coming up to its fifth year since release, and is supported for another five years, until 2017.

Errata count

The chart below illustrates the total number of security updates issued for Red Hat Enterprise Linux 5 Server if you had installed 5.7, up to and including the 5.8 release, broken down by severity. It's split into two columns, one for the packages you'd get if you did a default install, and the other if you installed every single package (which is unlikely as it would involve quite a bit of manual effort to select every one). For a given installation, the number of package updates and vulnerabilities that affected you will depend on exactly what packages you have installed or removed.

Number of security errata between      5.7 and 5.8

So, for a default install, from release of 5.7 up to and including 5.8, we shipped 42 advisories to address 118 vulnerabilities. 4 advisories were rated critical, 13 were important, and the remaining 25 were moderate and low.

Or, for all packages, from release of 5.7 up to and including 5.8, we shipped 71 advisories to address 177 vulnerabilities. 7 advisories were rated critical, 16 were important, and the remaining 48 were moderate and low.

Critical vulnerabilities

The 7 critical advisories addressed 20 critical vulnerabilities across 4 different packages:

  1. An update to OpenJDK 6 Java Runtime Environment, (October 2011) where a web site hosting a malicious Java applet could potentially run arbitrary code as the user.
  2. An update to the MIT krb5 telnet daemon (December 2011) where a remote attacker who can access the telnet port of a target machine could use this flaw to execute arbitrary code as root. Note that the krb5 telnet daemon is not installed or enabled by default, and the default firewall rules block remote access to the telnet port. This flaw did not affect the more commonly used telnet daemon distributed in the telnet-server package.
  3. Updates to PHP and PHP 5.3 (February 2012) where a remote attacker could send a specially-crafted HTTP request to cause the PHP interpreter to crash or, possibly, execute arbitrary code. This flaw was caused by the fix for CVE-2011-4885.
  4. Three updates to Firefox (August 2011, September 2011, November 2011) where a malicious web site could potentially run arbitrary code as the user running Firefox.

Updates to correct 19 out of the 20 critical vulnerabilities were available via Red Hat Network either the same day or the next calendar day after the issues were public. The update to krb5 took 2 calendar days because it was public on Christmas day.

Overall, for Red Hat Enterprise Linux 5 since release until 5.8, 98% of critical vulnerabilities have had an update available to address them available from the Red Hat Network either the same day or the next calendar day after the issue was public.

Other significant vulnerabilities

Although not in the definition of critical severity, also of interest during this period were a couple of remote denial of service flaws that were easily exploitable:

In addition, updates to Firefox, NSS, and Thunderbird were made to blacklist a compromised Certificate Authority.

Previous update releases

To compare these statistics with previous update releases we need to take into account that the time between each update release is different. So looking at a default installation and calculating the number of advisories per month gives the following chart:

Errata per month for each update release

This data is interesting to get a feel for the risk of running Enterprise Linux 5 Server, but isn't really useful for comparisons with other major versions, distributions, or operating systems -- for example, a default install of Red Hat Enterprise Linux 4AS did not include Firefox, but 5 Server does. You can use our public security measurement data and tools, and run your own custom metrics for any given Red Hat product, package set, timescales, and severity range of interest.

See also: 5.7, 5.6, 5.5, 5.4, 5.3, 5.2, and 5.1 risk reports.

February 20, 2012

How can I allow a process to listing all processes on a system.
SELinux blocks lots of domains from listing all processes on the system. 

Lots of useful information can be optained from reading the process info on a machine, so we would like to block this by default.  But sometimes users/policy writers really need to allow their domains to be able to list the processes on a system.

Ole on the Fedora SELinux Users Mail list asked:

I have a problem with SELinux not allowing PHP to list other users' processes with the "ps" command.
If I disable SELinux with "setenforce 0" it works immediately.
Is it possible to allow PHP to do this without disabling SELinux completely?

Processes are listed by reading all of the contents of /proc.  SELinux linux labels everything in /proc based on the label of the process.

ps -eZ | grep sshd | head -1
system_u:system_r:sshd_t:s0-s0:c0.c1023 853 ?  00:00:00 sshd

ls -lZ /proc/853 | head -1
dr-xr-xr-x. root root system_u:system_r:sshd_t:s0-s0:c0.c1023 attr


If you want a confined process to run ps, it needs to list /proc/PID, it needs to read certain files in this directory, needs to read symbolic links in this directory and needs to getattr on the process.   When writing policy we have added a macro for this access.

define(`ps_process_pattern',`
    allow $1 $2:dir list_dir_perms;
    allow $1 $2:file read_file_perms;
    allow $1 $2:lnk_file read_lnk_file_perms;
    allow $1 $2:process getattr;
')


If we wanted to allow one process type (myuser_t) to read another process /proc data on sshd (sshd_t), we would need to write a line like:

ps_process_pattern(myuser_t, sshd_t)

What if I want to allow a type to list all processes types?

In SELinux policy language we use attributes are used to group multiple types together. 
SELinux calls processes "domains".  When we write policy we always give process types the domain attribute.

So if you wanted to allow a process myuser_t to  list all the processes on a system, you would write a rule like.

ps_process_pattern(myuser_t, domain)

Dominic Grift answered Ole question by suggesting he install a local policy module that looked like:
policy_module(mytest, 1.0.0)
gen_require(` 
  type httpd_t; 
  attribute domain; 
')
ps_process_pattern(httpd_t, domain)

This works great.  Note that the apache daemon runs all php scripts within its process space, to they run as httpd_t.

Another solution would be to use an interface that we have defined in policy to allow this, domain_read_all_domains_state.  

The /usr/share/selinux/devel/include/kernel/domain.if interface file defines several interfaces that can be used to interact with all domains.  An alternative policy module could have been written:

policy_module(mytest, 1.0.0)
gen_require(` 
  type httpd_t; 
')
domain_read_all_domains_state(httpd_t)

February 17, 2012

Working with Keystone Authenticate

Here is a little utility I’ve worked up while working with the Openstack Keystone code.

To extract the token out of the JSON, use the following pyton script

#!/usr/bin/python

from sys import stdin
import json
print json.load(stdin)['access']['token']['id']

Which I save in ~/bin/extract_keystone_id.py

Here’s the Curl to fetch a token from Keystone, assuming you ‘ve loaded up the sample data from the unit tests:

curl -v   -H "Content-Type:application/json"  -s  -H "Accept:applicaton/json"  -d '{"auth":{"passwordCredentials":{"userId":"foo", "password":"foo2"} ,"tenantName":"bar"}}'   -X POST  http://0.0.0.0:35357/v2.0/tokens  | ~/bin/extract_keystone_id.py
Openstack Keystone LDAP Redux

A recent change in the structure of the Openstack Keystone architecture resulted in the loss of support for an LDAP Backend. I’ve been working to rectify that.  Here’s my set up and the design decisions I’ve made so far.  Since this code is not yet submitted for code review,  there is a good chance that it will change prior to deployment.

Users will be stored in a flat collection. ou=Users,$SUBTREE and be based on the standard LDAP objectClass inetOrgPerson which is defined in /etc/openldap/schema/inetorgperson.ldif. Currently, only two fields are used: cn and sn. cn is used for the bind call, and is the id field in the user object.

Tenants are in a collection that is a peer to Users. Tenants are instancs of the groupOfNames object class defined in /etc/openldap/schema/core.ldif. Tenant membership is indicated by the presence of the User’s DN in the tenant’s members attribute.

Roles are instances of the LDAP object class organizationalRole defined in /etc/openldap/schema/core.ldif. Role assignment is indicated by the presence of the User’s DN in the roleOccupant attribute.

Configuration of LDAP for the Keystone server is provided by the [LDAP] stanza in the appropriate keystone.conf file. Here are the supported values

  • url
  • user
  • password
  • suffix
  • use_dumb_member
  • user_tree_dn
  • tenant_tree_dn
  • role_tree_dn

And an example of what my config file looks like:

[ldap]
url = ldap://localhost
tree_dn = dc=younglogic,dc=com
user_tree_dn = ou=Users,dc=younglogic,dc=com
role_tree_dn = ou=Roles,dc=younglogic,dc=com
tenant_tree_dn = ou=Groups,dc=younglogic,dc=com
user = dc=Manager,dc=younglogic,dc=com
password = freeipa4all
backend_entities = ['Tenant', 'User', 'UserRoleAssociation', 'Role']
suffix =cn=younglogic,cn=com

[identity]
driver = keystone.identity.backends.ldap.Identity

Not all of these fields need to be specified. It is expected that the user will supply simply the suffix field, and not override the values of user_tree_dn,role_tree_dn, or tenant_tree_dn.

backend_entities is not currently honored. It is expected that LDAP will instead either manage all of these or non e of them, with token management handled by a different backend provider.

use_dumb_member is still honored from the previous incarnation, but has not been tested, nor do I understand the intention of this code.

The unit tests for the LDAP code use a common code sournce with the other Identity management backends. To run just the LDAP unit tests, from the Keystone directory, run

 python ./run_tests.py  test_backend_ldap

Additionally, the unit tests can be run against a live OpenLDAP server by running.

 python ./run_tests.py  _ldap_livetest

All tests pass successfully on my development machine as of this posting.

 

I’m running Fedora 16, which supports OpenLDAP. Specifically I am running openldap-servers-2.4.26-5.fc16.x86_64. To start the service, run

sudo service slapd start

To configure the server, I use a file I call manager.ldif:

dn:  olcDatabase={2}hdb,cn=config
changetype: modify
replace: olcSuffix
olcSuffix: dc=younglogic,dc=com
-
replace: olcRootDN
olcRootDN: dc=Manager,dc=younglogic,dc=com
-
add: olcRootPW
olcRootPW: {SSHA}lBDIdfwvZkITal0k9tdhiCUolxpf6anu

You should modify the suffix for your organization.
Execute the configuration with:

 sudo ldapmodify -Y EXTERNAL -H ldapi:///  -f ./manager.ldif

And test that you can now do a simple bind to the localhost server.

ldapsearch -x -D "dc=Manager,dc=younglogic,dc=com" -H ldap://localhost  -w freeipa4all  -b ou=Groups,dc=younglogic,dc=com "(objectClass=*)"

Now set up the subtree for Keystone. I use file I call org.ldif

dn: dc=younglogic,dc=com
dc: younglogic
objectClass: dcObject
objectClass: organizationalUnit
ou: younglogic

dn: ou=Groups,dc=younglogic,dc=com
objectClass: top
objectClass: organizationalUnit
ou: groups

dn: ou=Users,dc=younglogic,dc=com
objectClass: top
objectClass: organizationalUnit
ou: users

dn: ou=Roles,dc=younglogic,dc=com
objectClass: top
objectClass: organizationalUnit
ou: users

Technically, the Roles ou is not required. My original thought was that this collection would contain the superset of roles possible for all of the Tenants. However, I have not implemented that.

Current code is commited to Github I will update this link if I rebase the branch.

Update: fixed typos in the config file segment. user_tree_dn etc should start with ou, not cn.

Programmatic EXTERNAL SASL connection to OpenLDAP

The documentation on the OpenLDAP site discusses modifying the ldif files used to start up the server.  If you try to do this on a Fedora or Debian based install,  you will find that the server does not start up.  The HASH of the files is stored and compared with the contents at start up time.  There is a better way.

On my OpenLDAP install,  there are three databases served by SLAPD.  The first two  are for  configuration and  monitoring.  The third is the one that acts as the backing store for authentication and other data that is publicly served.  When the server starts up,  it is configured with a common name of   cn=example,cn=com,  which is obviously sample data.  To modify this,  requires changing the values in the config database.

Below is an ldif file that would change the Common name, as well as set the userid and password for managing the directory

dn:  olcDatabase={2}hdb,cn=config
changetype: modify
replace: olcSuffix
olcSuffix: dc=younglogic,dc=com
-
replace: olcRootDN
olcRootDN: dc=Manager,dc=younglogic,dc=com
-
add: olcRootPW
olcRootPW: {SSHA}lBDIdfwvZkITal0k9tdhiCUolxpf6anu

I generated the HASH using the slappasswd command line tool.
To modify the config, you then execute ldapmodify.

sudo ldapmodify -Y EXTERNAL -H ldapi:///  -f /home/ayoung/etc/managerbase.ldif

What is this EXTERNAL? It is a SASL mechanism that uses the underlying system configured authentication. This is the NSS value that you would get back from getent. The default install protects the configuration database using the root credentials. The URL ldapi:/// is a Unix socket connection to /var/run/ldapi.

What happens if you want to modify the configuration pragmatically? The steps to make a SASL External connection are not to clear.  In order to figure out how to do it, I’ve started poking inside of the ldapmodify code from the openldap source. The CLI tools are under openldap/clients/tools/. The connection is created in the file common.c. From what I’ve seen elsewhere on the web, I know it needs to resolve to one of the ldap*bind calls. In my file, inside the function tool_bind, I see it on line 1469

	rc = ldap_sasl_interactive_bind_s(
          ld, binddn, sasl_mech,
	   sctrlsp, NULL, sasl_flags, lutil_sasl_interact, defaults )

Now, I’ve run this through ltrace and I’ve seen

ldap_sasl_interactive_bind_s(0x1abf290, 0, 0x1abf030, 0, 0

So I know to expect binddn to be null, and sasl_mech needs to have a real value. Look in the argument parsing part of the code for the -Y flag tells that this is a pass through of the string passed on the command line.

    case 'Y':
        /*error chcking ellided here*/
	sasl_mech = ber_strdup( optarg );

So that should be the string EXTERNAL for our purposes.

The next two parameters are 0, sctrlsp and (surprise) NULL.

sasl_flags looks like it is set to the default in the top of the file and never modified in our code path:

unsigned	sasl_flags = LDAP_SASL_AUTOMATIC;

That leaves the last two parameters. One is a callback function lutil_sasl_interact and one is the defaults structure. The function lutil_sasl_interact is defined in the file openldap/libraries/liblutil/sasl.c. Between it and the function interaction which it calls, we are talking about 200 lines of code. For now, I am just going to cut and paste that code into my C file and get all of the headers coorect to run it. Later, I’ll step through it in the debugger to see what it is really doing.

The defaults structure is also defined in the sasl/c file specified above. From the ldap_bind man page:

The interact function uses the provided defaults to handle requests from the SASL library for particular authentication parameters. There is no defined format for the defaults information; it is up to the caller to use whatever format is appropriate for the supplied interact function. The sasl_interact parameter comes from the underlying SASL library. When used with Cyrus SASL this is an array of sasl_interact_t structures. The Cyrus SASL library will prompt for a variety of inputs, including:…

Again, I will cut and paste this code into my file and get it running. In order to compile I need to add the flags

CFLAGS=-lldap -llber -lsasl2 -g -I/usr/include/sasl

Once I can compile and run, I can dump out the contents of the config directory. Stepping through the code I discover a few things. In the code that builds the defaults, the non-zero values are. defaults->authcid = “root” and defaults->mech “EXTERNAL”. When the function lutil_sasl_interact is called, the parameters are: The ldap structure from our init, flags=0, defaults, and in, which is cast to at sasl_interact_t. The only part of this that seems interesting to us is that it requests SASL_CB_USER from interact, which basically checks the user is root. The code then makes the most elegant use of a goto that I’ve seen in a long while, skips a whole load of interactive code, and returns the default:

use_default:
		/* input must be empty */
		interact->result = (dflt && *dflt) ? dflt : "";
		interact->len = strlen( interact->result )

This says to me that the interaction callback function could be reduced to:

int do_interact(
	LDAP *ld,
	unsigned flags,
	void *defaults,
	void *in )
{
	sasl_interact_t *interact = in;
	lutilSASLdefaults * sasl_defaults = (lutilSASLdefaults *)defaults;
	const char *dflt = interact->defresult;
	dflt = sasl_defaults->authzid;
	interact->result = (dflt && *dflt) ? dflt : "";
	interact->len = strlen( interact->result );
	return LDAP_SUCCESS;
}

But now I see that the defaults passed in are defined external to the ldap code. We can drop all of the pointers except the one to the authzid. In fact, we can just make this a char *.

Here’s the code in a functional state. It leaks memory, which would need to be cleaned up for a real application.

#include <sasl.h>
#include <ldap.h>
#include <stdio.h>

int do_interact(
		LDAP *ld,
		unsigned flags,
		void *defaults,
		void *in )
{
  sasl_interact_t *interact = in;
  char * sasl_defaults = (char  *)defaults;
  const char *dflt = interact->defresult;
  dflt = sasl_defaults;
  interact->result = (dflt && *dflt) ? dflt : "";
  interact->len = strlen( interact->result );
  return LDAP_SUCCESS;
}

int main(){
  printf("Start\n");
  LDAP *ldap;
  int rc;
  struct berval *servercredp;
  unsigned long version = LDAP_VERSION3;
  LDAPMessage *res;
  char ** vals;
  int message_count;
  int i,j,k;

  if (( rc = ldap_initialize(&ldap,  "ldapi:///")) != LDAP_SUCCESS)
    {
      perror ( NULL );
      return( 1 );
    }

  rc = ldap_set_option(ldap,
		       LDAP_OPT_PROTOCOL_VERSION,
		       (void*)&version);
  char * defaults;
  char * sasl_mech = "EXTERNAL";
  char * sasl_realm = NULL;
  char * sasl_authc_id = NULL;
  char * sasl_authz_id = NULL;
  struct berval	passwd = { 0, NULL };
  unsigned	sasl_flags = LDAP_SASL_AUTOMATIC;
  LDAPControl	**sctrlsp = NULL;

  ldap_get_option( ldap, LDAP_OPT_X_SASL_AUTHZID, &defaults );

  char *	binddn = NULL;
  rc = ldap_sasl_interactive_bind_s( ldap, binddn, sasl_mech,
				     sctrlsp,
				     NULL, sasl_flags, do_interact, defaults );

  if ((rc =  ldap_search_ext_s
       (
	ldap,
	"cn=config",
	LDAP_SCOPE_SUBTREE,
	"(objectClass=*)",
	NULL,
	0,
	NULL,
	NULL,
	NULL,
	0,
	&res ) != LDAP_SUCCESS))
    {
      printf("ldap_search  failed with 0x%x.\n",rc);
      perror ( NULL );
      return( 1 );
    }
  LDAPMessage *entry = ldap_first_entry( ldap, res );

  int entry_count = ldap_count_entries(ldap, res);
  for (i = 0 ; i < entry_count; i++){
    printf("dn: %s\n",ldap_get_dn(ldap, entry));
    BerElement * ber;
    char * attribute = ldap_first_attribute(ldap,entry, &ber);
    while(attribute){
      printf ("attribute = %s\n",attribute);
      attribute = ldap_next_attribute(ldap,entry, ber);
    }
    ber_free(ber,0);
    entry = ldap_next_entry(ldap, entry);

  }
  return 0;

}

Note: The reason I do SASL using a -I option in the makefile instead of sasl/sasl.h is that the code formatter is messing it up.

February 13, 2012

SELinux problems on Fedora 17.
Anyone that has tried Fedora 17 over the last couple of days, might have noticed SELinux going nuts and blocking logins. 

systemd had a bug which was causing transitions to break.

The way the system is supposed to work is during boot systemd reads in the policy file on disk and then loads policy into the kernel.
This causes all processes at that are running to be labeled kernel_t. 

systemd then reads the label on its image file /sbin/systemd (init_exec_t) and the label that it is currently running as (kernel_t), then it asks the kernel what label would the /sbin/systemd process get if kernel_t executed it.  The answer would be init_t, and then systemd is supposed to set the current label to init_t.   From that point on all processes started by systemd would transition to their proper domains.

Well just before systemd/Fedora 17 Alpha was about to be released.  Systemd changed the location of its executable from /bin/systemd to /usr/lib/systemd/systemd.  But they never changed the checking code.  We fixed policy to look at the new location and labeled /usr/lib/systemd/systemd correctly, but when systemd checked for the label of /bin/systemd, there was no file and systemd just continued running as kernel_t.  Since there are few rules for transitions of kernel_t to any other label, most of the system was labeled as kernel_t.  Finally when a user logged in via gdm or login or sshd, they were running as kernel_t and the code transitioned them to abrt_t, one of the few domains kernel_t will transition to.

systemd-42-1.fc17 fixes this problem, so if you update to this systemd or later, you should be able to run your system in enforcing mode. 

Needless to say, we have been flooded with bug reports...
DNS Managers in FreeIPA

The Domain Name System (DNS) is an essential part of systems management. If you need to manage multiple physical hosts you’d really benefit by a degree of control of some subset of DNS. With Virtual machines, the sheer number of hosts created demand a responsive DNS. Kerberos, X509 and other security mechanisms require a proper DNS configuration. Yet, for many organizations, DNS is locked down by IT to a very static set of records. Earlier articles discussed User Groups, Host Groups, and Netgroups. The final installment in this series discsusses how to delegate DNS Zone management in FreeIPA.

First, create a Zone for the project, and one DNS record

[root@f16server ~]# ipa dnszone-add beowulf.younglogic.com
Authoritative nameserver: f16server.ayoung.boston.devel.redhat.com
Administrator e-mail address [hostmaster.beowulf.younglogic.com.]:
Zone name: beowulf.younglogic.com
Authoritative nameserver: f16server.ayoung.boston.devel.redhat.com.
Administrator e-mail address: hostmaster.beowulf.younglogic.com.
SOA serial: 2012110201
SOA refresh: 3600
SOA retry: 900
SOA expire: 1209600
SOA minimum: 3600
Active zone: TRUE
Dynamic update: FALSE
[root@f16server ~]# ipa dnsrecord-add
Zone name: beowulf.younglogic.com
Record name: www1
[A record]: 10.10.2.1
[AAAA record]: feed:0123::babe
Record name: www1
A record: 10.10.2.1
AAAA record: feed:0123::babe

Here’s the LDAP details of what we just created:

[root@f16server ~]# ipa dnszone-show beowulf.younglogic.com --all --raw
dn: idnsname=beowulf.younglogic.com,cn=dns,dc=f16server,dc=ayoung,dc=boston,dc=devel,dc=redhat,dc=com
idnsname: beowulf.younglogic.com
idnssoamname: f16server.ayoung.boston.devel.redhat.com.
idnssoarname: hostmaster.beowulf.younglogic.com.
idnssoaserial: 2012110201
idnssoarefresh: 3600
idnssoaretry: 900
idnssoaexpire: 1209600
idnssoaminimum: 3600
idnszoneactive: TRUE
idnsallowdynupdate: FALSE
nsrecord: f16server.ayoung.boston.devel.redhat.com.
objectclass: top
objectclass: idnsrecord
objectclass: idnszone

Notice that the A and AAAA records are not visible in the DNS Zone object. Since we are not just modifying values of attributes, we can’t perform the same type of delegation as we did with User Groups, Host Groups or Netgroups. Lets take a look at the LDAP details of the Record.

[root@f16server ~]# ipa dnsrecord-show beowulf.younglogic.com www1 --all --raw
dn: idnsname=www1,idnsname=beowulf.younglogic.com,cn=dns,dc=f16server,dc=ayoung,dc=boston,dc=devel,dc=redhat,dc=com
idnsname: www1
arecord: 10.10.2.1
aaaarecord: feed:0123::babe
objectclass: top
objectclass: idnsrecord

A and AAAA records that have the same idnsname go into the same LDAP object. PTR and CNAME records would all be put into additional attributes of this object if they, too, had the same idnsname. This LDAP object is a subordinate object to the Zone, beowulf.younglogic.com.

Thus, we can use the Subtree permission type to manage access to this resource. The subtree is the distinguished name (DN) of the DNS Zone.

[root@f16server ~]# ipa permission-add 'beowulf-dns-modify'  --permissions=add,delete
[Attributes]:
[Type]:
[Member of group]:
[Filter]:
[Subtree]: idnsname=beowulf.younglogic.com,cn=dns,dc=f16server,dc=ayoung,dc=boston,dc=devel,dc=redhat,dc=com
[Target group]:
-------------------------------------
Added permission "beowulf-dns-modify"
-------------------------------------
  Permission name: beowulf-dns-modify
  Permissions: add, delete
  Subtree: ldap:///idnsname=beowulf.younglogic.com,cn=dns,dc=f16server,dc=ayoung,dc=boston,dc=devel,dc=redhat,dc=com

We could use the objectname and cn as we did before, but  subtree is better documentation to our intent.

Again, we need to add the permission to the privilege.

[root@f16server ~]# ipa privilege-add-permission beowulf-manage --permission=beowulf-dns-modify
  Privilege name: beowulf-manage
  Description: Manage the Assets of the Beowulf project
  Permissions: beowulf-manage, beowulf-manage-group, beowulf-hostgroup-modify,
               beowulf-netgroup-modify, beowulf-dns-modify
  Granting privilege to roles: beowulf-managers
-----------------------------
Number of permissions added 1
-----------------------------

Test it out with the admiyo account (that already has the Role beowulf-managers. This time, we’ll add both an A and AAAA record, which are managed by the same object in BINDs LDAP backend.

[root@f16server ~]# ipa privilege-add-permission beowulf-manage --permission=beowulf-dns-modify
  Privilege name: beowulf-manage
  Description: Manage the Assets of the Beowulf project
  Permissions: beowulf-manage, beowulf-manage-group, beowulf-hostgroup-modify,
               beowulf-netgroup-modify, beowulf-dns-modify
  Granting privilege to roles: beowulf-managers
-----------------------------
Number of permissions added 1
-----------------------------
[root@f16server ~]# kinit admiyo
Password for admiyo@F16SERVER.AYOUNG.BOSTON.DEVEL.REDHAT.COM:
[root@f16server ~]# ipa dnsrecord-add
Zone name: beowulf.younglogic.com
Record name: mail1
[A record]: 10.10.2.3
[AAAA record]: feed:babe:beef::cafe
  Record name: mail1
  A record: 10.10.2.3
  AAAA record: feed:babe:beef::cafe

These four articles have attempted to show how the access controls of FreeIPA allow a system administrator to delegate specific actions to power users in their organization. From the simplest and most targeted of Target Groups, through simple and then more complex filter queries, then finally subtree queries. While FreeIPA can abstract you away from having to understand LDAP,  it does not prevent you from doing so.  Instead,  LDAP know how built on top of the structure provided with FreeIPA can help to craft secure and flexible delegation policy.

February 12, 2012

Netgroup Managers in FreeIPA

The last two articles described how to delegate management of user groups and host groups. The other way to manage both hosts and users in FreeIPA is with Netgroups. Although Netgroups are a concept from NIS, FreeIPA takes them to the next level, and makes them into containers capable of managing both users and groups. This article shows how to delegate the control of a netgroup to a specified user.

First, create a netgroup

[root@f16server ~]# ipa netgroup-add
Netgroup name: beowulf-netgroup
Description: Beowulf Resources
---------------------------------
Added netgroup "beowulf-netgroup"
---------------------------------
  Netgroup name: beowulf-netgroup
  Description: Beowulf Resources
  NIS domain name: ayoung.boston.devel.redhat.com
  IPA unique ID: 71ea8d08-5530-11e1-9487-525400ff995b

To illustrate the differences between user groups, host groups, and netgroups, lets add some elements to the netgroup.

[root@f16server ~]# ipa netgroup-add-member beowulf-netgroup
[member user]: admiyo
[member group]: editors
[member host]: www1.ayoung.boston.devel.redhat.com
[member host group]: beowulf-hosts
[member netgroup]:
  Netgroup name: beowulf-netgroup
  Description: Beowulf Resources
  NIS domain name: ayoung.boston.devel.redhat.com
  Member User: admiyo
  Member Group: editors
  Member Host: www1.ayoung.boston.devel.redhat.com
  Member Hostgroup: beowulf-hosts

This shows the LDAP underpinning of the FreeIPA code. Note where the entities are stored.

[root@f16server ~]# ipa netgroup-show beowulf-netgroup --all --raw
  dn: ipauniqueid=71ea8d08-5530-11e1-9487-525400ff995b,cn=ng,cn=alt,dc=f16server,dc=ayoung,dc=boston,dc=devel,dc=redhat,dc=com
  cn: beowulf-netgroup
  description: Beowulf Resources
  nisdomainname: ayoung.boston.devel.redhat.com
  ipauniqueid: 71ea8d08-5530-11e1-9487-525400ff995b
  memberhost: fqdn=www1.ayoung.boston.devel.redhat.com,cn=computers,cn=accounts,dc=f16server,dc=ayoung,dc=boston,dc=devel,dc=redhat,dc=com
  memberhost: cn=beowulf-hosts,cn=hostgroups,cn=accounts,dc=f16server,dc=ayoung,dc=boston,dc=devel,dc=redhat,dc=com
  memberuser: cn=editors,cn=groups,cn=accounts,dc=f16server,dc=ayoung,dc=boston,dc=devel,dc=redhat,dc=com
  memberuser: uid=admiyo,cn=users,cn=accounts,dc=f16server,dc=ayoung,dc=boston,dc=devel,dc=redhat,dc=com
  objectclass: ipaobject
  objectclass: ipaassociation
  objectclass: ipanisnetgroup

Note that both users and user groups are in the memberuser field, where as hosts and host groups are in the memberhost field.

So to be able to modify the netgroup, the user needs permissions to the memberuser and memberhost attributes. For the objectclass, specify ipanisnetgroup.

Before moving on I deleted these members, as I want to use them again later on for testing.

[root@f16server ~]# ipa permission-add 'beowulf-netgroup-modify'  --permissions=write --attrs=memberhost,memberuser  --filter='(&(cn=beowulf-netgroup)(objectclass=ipanisnetgroup ))'
------------------------------------------
Added permission "beowulf-netgroup-modify"
------------------------------------------
  Permission name: beowulf-netgroup-modify
  Permissions: write
  Attributes: memberhost, memberuser
  Filter: (&(cn=beowulf-netgroup)(objectclass=ipanisnetgroup ))

[root@f16server ~]# ipa privilege-add-permission beowulf-manage --permission=beowulf-netgroup-modify
  Privilege name: beowulf-manage
  Description: Manage the Assets of the Beowulf project
  Permissions: beowulf-manage, beowulf-manage-group, beowulf-hostgroup-modify,
               beowulf-netgroup-modify
  Granting privilege to roles: beowulf-managers
-----------------------------
Number of permissions added 1
-----------------------------

Finally, to test.

[root@f16server ~]# kinit admiyo
Password for admiyo@F16SERVER.AYOUNG.BOSTON.DEVEL.REDHAT.COM:
[root@f16server ~]# ipa netgroup-add-member beowulf-netgroup --hosts www1.ayoung.boston.devel.redhat.com --users admiyo
  Netgroup name: beowulf-netgroup
  Description: Beowulf Resources
  NIS domain name: ayoung.boston.devel.redhat.com
  Member User: admiyo
  Member Group: editors
  Member Host: www1.ayoung.boston.devel.redhat.com
  Member Hostgroup: beowulf-hosts
-------------------------
Number of members added 2
-------------------------
[root@f16server ~]# ipa netgroup-remove-member beowulf-netgroup --hosts www1.ayoung.boston.devel.redhat.com --users admiyo
  Netgroup name: beowulf-netgroup
  Description: Beowulf Resources
  NIS domain name: ayoung.boston.devel.redhat.com
  Member Group: editors
  Member Hostgroup: beowulf-hosts
---------------------------
Number of members removed 2
---------------------------

Again, I deleted the elements that I added as admin before. If you add the same entry twice, you will get errors. You can delete them as the delegated user as well as add them.

Since Netgroups can be used pretty much anywhere that user groups and hostgroups can be used (SUDO, and HBAC especially) they are likely to become your first point of contact for management. Like user groups and hosts groups, they both provide nesting. In fact, a netgroup can be nested inside a host group or a user group, and elements will gain membership in the corresponding host groups or user groups.

Kerberos: delegation and s4u2proxy

One of the most obscure parts of the Kerberos protocol is delegation. And yet it is a very powerful and useful tool to let "agents" work on behalf of users w/o fully trusting them to do everything a user or an admin can.

So what is delegation ? Simply put is the ability to give a service a token that can be used on the user's behalf so that a service can act as if it were the user himself.

In FreeIPA, for example, the web framework used to mediate administration of the system is such an agent. The framework on it's own has absolutely no privileges over the rest of the system. It interacts almost exclusively with the LDAP server and authenticates to the LDAP server using delegated credentials from the user that is sending in the requests.

This is possible because through Kerberos and GSSAPI it is possible to delegate user's credentials during the Negotiate exchange that happens at the HTTP layer when a user contacts the Web Server and authenticates to it.

How does it work ?

Before we answer this question we have to make a step back and explain what kind of delegations are possible. Historically only one kind of very inflexible delegation was really implemented in standard Kerberos implementations like MIT's or Heimdal's. The full delegation (transmission) of the user's krbtgt to the target service.

This kind of delegation is perfect for services like SSH, where the user wants to have full access to their own credentials after they jumped on the target host, and they generally remain in full control of them.

The drawback of this method is that by transmitting the full krbtgt we are now giving another host potential access to each and all services our user has access to. And while that is "powerful" it is also sort of overly broad in many other situations. the other minor issue is that normally KDC's do not have fine grained authorization attached to this feature, meaning that a user (or often more generally a program acting on the user's machine) can delegate these credentials to any service in the network, w/o much control from admins.

Enter S4U constrained delegation

Luckily for us Microsoft introduced a new type of "constrained" delegation normally referred to as S4U. This is an extension to the age old Kerberos delegation method and adds 2 flavors of delegation each depending on the KDC for authorization; they are called Service-for-User-to-Self (S4U2Self) and Service-for-User-to-Proxy (S4U2Proxy).

Service-for-User-to-Self

S4U2Self allows a service to get a ticket for itself on behalf of a user, or in other terms is allows to get a ticket as if a user requested it using it's krbtgt form a KDC and then contacted the service.

This option may seem of little use, why would a service care for a ticket to itself ? If it is asking it, it already knows the identify of the user and can operate on its behalf right ? Wrong.

There are at least 3 aspects that makes this function useful. First of all you get the KDC to give you a ticket and therefore validate that the user identity actually exist and is active. Second it may attach a MS-PAC (or other authorization data to the ticket, allowing the service to know, form an authoritative source, authorization information about the user. Finally, it may allow the service to do further actions on behalf of a user by using S4U2Proxy constrained delegation on top.

All this is possible only if the KDC allows the specific service to request S4U2Self services. This is an additional layer of authorization that is very useful to admins, it allows them to limit what services can use this feature.

Service-for-User-to-Proxy

S4U2Proxy is the actual method used to perform impersonation against a 3rd service. To use S4U2Proxy a service A that wants to authenticate to service B on behalf of user X, contacts the KDC using a ticket for A from user X (this could also be a ticket obtained through S4U2Self) and sends this ticket to the KDC as evidence that user X did in fact contact service A. The KDC can now make authorization decisions about whether to allow service A to get a ticket for service B in the name of user X. Normally admins will allow this operation only for services that are authorized "Proxies" to other services.

In FreeIPA we just switched to using S4U2Proxy in order to reduce the attack surface against the web framework. By using S4U2Proxy we do not need the user to delegate us a full krbtgt. By doing this we allow the web framework to effectively be able to operate against the LDAP server and no other service in the domain

These 2 delegation methods are available now both in MIT's and Heimdal's Kerberos implementations. In MIT's case (which is the implementation we use in FreeIPA) it is really possible to use these features only if you use an LDAP back-end (or in general a custom back-end that implements the necessary kdb functions. The native back-end does not have support for these features, because it lacks meaningful grouping methods and Access Control facilities to control them.

In coding up the support for FreeIPA we ended up fixing a few bugs in MIT's implementation that will hopefully be available for general use in 1.11 (We have back ported patches to RHEL and Fedora). We also had to modify the Apache mod_auth_kerb module to properly deal with S4U2Proxy, which requires the requesting service to have a valid krbtgt in order to send the request to the KDC. Something mod_auth_kerb did not need before (you do not need a krbtgt if you are just validating a ticket).

Conclusion

S4U constrained delegation is extremely useful, it reduces attack surface by allowing admins to effectively constrain services, and gives admins a lot more control about what users can delegate to. Finally it also makes clients simpler, and this is a key winning feature. In the classic delegation scheme clients needs to decide on their own whether to delegate a krbtgt, which ultimately means either asking the user or always/never do it. And given it is quite dangerous to liberally forward your ticket to random services the default is generally to not delegate the krbtgt, making it very difficult to rely on this feature to make powerless agents. With S4U the user only needs a Forward-able TGT, but does not need to actually forward it at all. This is a reasonable compromise and does not require applications to make choice on user's behalf, nor to make user's need to make any decision. The decision rests on admins to allow certain service or not, and is taken generally once, when the service is put in production, greatly reducing the burden to administrators and the risks involved in the traditional delegation scheme.

Hostgroup Managers in FreeIPA

Last article I discussed delegating the authority to manage group membership using FreeIPA. A related topic delegating the ability to manage groups of hosts. There are two different collections for managing hosts: host groups, and netgroups. The approach to delegating authority for managing each of these is similar, but with important differences. First up: hostgroups.

To create a hostgroup for Beowulf hosts:

[root@f16server ~]# ipa hostgroup-add beowulf-hosts
Description: Hosts for the Beowulf project
-------------------------------
Added hostgroup "beowulf-hosts"
-------------------------------
  Host-group: beowulf-hosts
  Description: Hosts for the Beowulf project

Unlike the user groups, there is no preset form of ACI Permission for specifying a host group. Instead, we will have to specify the LDAP object that we wish to grant permission on. Again, it will be on the “member” attribute. Lets look at what we just created. To Look at the underlying LDAP object of something in FreeIPA, we use the entity-show command coupled with the –raw and –all flags

[root@f16server ~]# ipa hostgroup-show beowulf-hosts --all --raw
  dn: cn=beowulf-hosts,cn=hostgroups,cn=accounts,dc=f16server,dc=ayoung,dc=boston,dc=devel,dc=redhat,dc=com
  cn: beowulf-hosts
  description: Hosts for the Beowulf project
  ipauniqueid: 70999114-5513-11e1-bde4-525400ff995b
  mepmanagedentry: cn=beowulf-hosts,cn=ng,cn=alt,dc=f16server,dc=ayoung,dc=boston,dc=devel,dc=redhat,dc=com
  objectclass: ipaobject
  objectclass: ipahostgroup
  objectclass: nestedGroup
  objectclass: groupOfNames
  objectclass: top
  objectclass: mepOriginEntry

In order to specify this object, we will use the combination of the objectclass an a uniqu identifier. The best unique ID is the text value of the host group name, held in the common name field: cn: beowulf-hosts. THe appropriate objectclass is ipahostgroup, as that is the only one that indicates this is a group of hosts, all of the other objectclasses can potentially be used for other things. Here’s what creating the ACI Permission looks like (to include adding it to the privilge).

[root@f16server ~]# ipa permission-add 'beowulf-hostgroup-modify'  --permissions=write --attrs=member  --filter='(&(cn=beowulf-hosts)(objectclass=ipahostgroup ))'
-------------------------------------------
Added permission "beowulf-hostgroup-modify"
-------------------------------------------
  Permission name: beowulf-hostgroup-modify
  Permissions: write
  Attributes: member
  Filter: (&(cn=beowulf-hosts)(objectclass=ipahostgroup ))
[root@f16server ~]# ipa privilege-add-permission beowulf-manage --permission=beowulf-hostgroup-modify
  Privilege name: beowulf-manage
  Description: Manage the Assets of the Beowulf project
  Permissions: beowulf-manage, beowulf-manage-group, beowulf-dns-manage,
               beowulf-hostgroup-modify
  Granting privilege to roles: beowulf-managers
-----------------------------
Number of permissions added 1
-----------------------------

Since the user admiyo already has a role that contains this privilege, that user should now be able to manage adding and removing hosts from that host group.

[root@f16server ~]# kinit admiyo
Password for admiyo@F16SERVER.AYOUNG.BOSTON.DEVEL.REDHAT.COM:
[root@f16server ~]# ipa hostgroup-add-member beowulf-hosts --hosts www1.ayoung.boston.devel.redhat.com
  Host-group: beowulf-hosts
  Description: Hosts for the Beowulf project
  Member hosts: www1.ayoung.boston.devel.redhat.com
-------------------------
Number of members added 1
-------------------------

It took me a few tries to get the filter correct for this one. Note that the operators are prefix. Some filters will get through the CLI fine, but won’t select the object you want. To confirm that you do have the right object, I recommend using ldapsearch to get the query right before adding the permission.

[root@f16server ~]#  ldapsearch -x -b "dc=f16server,dc=ayoung,dc=boston,dc=devel,dc=redhat,dc=com" "(&( cn=beowulf-hosts)(objectclass=ipahostgroup))"
# extended LDIF
#
# LDAPv3
# base  with scope subtree
# filter: (&( cn=beowulf-hosts)(objectclass=ipahostgroup))
# requesting: ALL
#

# beowulf-hosts, hostgroups, accounts, f16server.ayoung.boston.devel.redhat.com
dn: cn=beowulf-hosts,cn=hostgroups,cn=accounts,dc=f16server,dc=ayoung,dc=boston,dc=devel,dc=redhat,dc=com
objectClass: ipaobject
objectClass: ipahostgroup
objectClass: nestedGroup
objectClass: groupOfNames
objectClass: top
objectClass: mepOriginEntry
cn: beowulf-hosts
description: Hosts for the Beowulf project
ipaUniqueID: 70999114-5513-11e1-bde4-525400ff995b
mepManagedEntry: cn=beowulf-hosts,cn=ng,cn=alt,dc=f16server,dc=ayoung,dc=boston,dc=devel,dc=redhat,dc=com
member: fqdn=www1.ayoung.boston.devel.redhat.com,cn=computers,cn=accounts,dc=f16server,dc=ayoung,dc=boston,dc=devel,dc=redhat,dc=com

# search result
search: 2
result: 0 Success

# numResponses: 2
# numEntries: 1

February 11, 2012

Group Managers in FreeIPA

The power of a hierarchical database lies in its access controls. FreeIPA gives you a set of tools that you can use in order to delegate authority using those access controls.

Here’s an example.  Let say you are running a web site where people can create projects.  In order to create a project,  you send in a ticket to  request the project creation.  Once that project has been created,  people ask you to join their projects.  Once the project is created,  as the project lead,  you can add and remove people from the project,  but they have to be in the system.

Yes,  I know,  very theoretical,  where would we ever see an organization like that?

A user named admiyo requests a project for people interested in Beowulf projects.  The IPA Admin creates it. In addition,  the admin has to create a Role, a Privilege, and a Permission  that will allow the user to manage that group,  assign the Permission to the Privilege and the Privilege to the Role.  Finally,  the Admin has to assign that role to the user admiyo.

[root@f16server ~]# ipa group-add beowulf --desc "Imagine a Beowulf Cluster...."
---------------------
Added group "beowulf"
---------------------
  Group name: beowulf
  Description: Imagine a Beowulf Cluster....
  GID: 500400007
[root@f16server ~]# ipa role-add
Role name: beowulf-managers
Description: Manage the Assets of the Beowulf project
-----------------------------
Added role "beowulf-managers"
-----------------------------
  Role name: beowulf-managers
  Description: Manage the Assets of the Beowulf project
[root@f16server ~]# ipa privilege-add
Privilege name: beowulf-manage
Description: Manage the Assets of the Beowulf project
--------------------------------
Added privilege "beowulf-manage"
--------------------------------
  Privilege name: beowulf-manage
  Description: Manage the Assets of the Beowulf project

For user groups, the simplest way to create the permission is to user the targetgroup keyword.

[root@f16server ~]# ipa permission-add 'beowulf-manage-group' --targetgroup=beowulf --permissions=write --attrs=member
---------------------------------------
Added permission "beowulf-manage-group"
---------------------------------------
  Permission name: beowulf-manage-group
  Permissions: write
  Attributes: member
  Target group: beowulf

Now the assignments:

[root@f16server ~]# ipa role-add-privilege Role name: beowulf-managers
[privilege]: beowulf-manage
  Role name: beowulf-managers
  Description: Manage the Assets of the Beowulf project
  Privileges: beowulf-manage
----------------------------
Number of privileges added 1
----------------------------
[root@f16server ~]# ipa privilege-add-permission Privilege name: beowulf-manage
[permission]: beowulf-manage-group
  Privilege name: beowulf-manage
  Description: Manage the Assets of the Beowulf project
  Permissions: beowulf-manage, beowulf-manage-group
  Granting privilege to roles: beowulf-managers
-----------------------------
Number of permissions added 1
-----------------------------
[root@f16server ~]# ipa role-add-member
Role name: beowulf-managers
[member user]: admiyo
[member group]:
[member host]:
[member host group]:
  Role name: beowulf-managers
  Description: Manage the Assets of the Beowulf project
  Member users: admiyo
  Privileges: beowulf-manage
-------------------------
Number of members added 1
-------------------------

I’d like to point out that I had very little idea what the CLI was going to ask for on these. I just trusted it to walk me through, and it did. The one exception was the creation of the permission,  as it doesn’t prompt for the –attrs field

Now to test it out.

[root@f16server ~]# kinit admiyo
Password for admiyo@F16SERVER.AYOUNG.BOSTON.DEVEL.REDHAT.COM:
[root@f16server ~]# ipa group-add-member
Group name: beowulf
[member user]: kfrog
[member group]:
  Group name: beowulf
  Description: Imagine a Beowulf Cluster....
  GID: 500400007
  Member users: kfrog
-------------------------
Number of members added 1
-------------------------

This same technique can be used with the other entities in FreeIPA. In the future, I’ll show how to do delegation for Host Groups and Netgroups. In theory, delegation of a DNS domain can be done the same way, but I haven’t worked through that yet.

This process can and should be streamlined (I’ve already submitted a ticket for that)  but could be fairly easily scripted, too.

February 09, 2012

Cool stuff – sftp+chroot+SELinux

Petr Lautrbach (openssh package maintainer) wrote a great blog about cool stuff – sftp+chroot+SELinux


February 07, 2012

secommunicate is a handy little tool to analyze policy communication
I wrote about setrans back in October. 

setrans is a tool that you could use to analyze policy to see if how one process domain transitions to another process domain.

Today I got asked what type should a user assign to a file so that one process type "syslogd_t" could write and another process type "httpd_t" could read.   

I answered the question that httpd_log_t would be a good candidate.  Then he asked could figure this out? 

My suggestion was he could use these commands.

# sesearch -A -s syslogd_t -c file -p write

Which will search for all types that syslogd_t can write.

# sesearch -A -s httpd_t -c file -p read

Which will search for types httpd_t can read, then he could look at the intersection of these commands.  

Only that did not work...

# sesearch -A -s syslogd_t -c file -p write

Does not return my suggestion of httpd_log_t.  It did however return an attribute "logfile" which includes httpd_log_t.
Attributes are the way to group lots of types together.  And the sesearch command does not expand out the attributes.

I decided to go off an play with python and create secommunicate.  The goal of this command is to print out a list of types that a source process type can write and a target process type can read.

This little python script takes a source process type and a target process type and an optional class, defaulting to "file".  It uses the sesearch python bindings to search the selinux policy for:
  • What class types can the source type write?
  • What class types can the target type read? 
  • It expands all attributes into the associated types
  • Then it generates the intersection of these types, and prints them out. 

./secommunicate syslogd_t httpd_t
puppet_tmp_t
afs_cache_t
dirsrv_var_log_t
nagios_log_t
httpd_log_t
user_cron_spool_t
root_t


./secommunicate -c chr_file syslogd_t httpd_t
user_tty_device_t
devtty_t
initrc_devpts_t
null_device_t
zero_device_t


Seems like it could be a handy tool.  

Not sure how we should package or ship setrans and secommunicate, or what the correct syntax would be, but for those struggling to understand policy these seem to be handy tools.

./secommunicate -h
usage: secommunicate [-h] [-c TCLASS] [-s SOURCEACCESS] [-t TARGETACCESS]
                     source target

SELinux Communication Analysys Tool

positional arguments:
  source                Source type
  target                Source type

optional arguments:
  -h, --help            show this help message and exit
  -c TCLASS, --class TCLASS
                        Class to use for communications, Default 'file'
  -s SOURCEACCESS, --sourceaccess SOURCEACCESS
                        Comma separate list of permissions for the source type
                        to use, Default 'open,write'
  -t TARGETACCESS, --targetaccess TARGETACCESS
                        Comma separated list of permissions for the target
                        type to use, Default 'open,read'


Note:
If you wanted to know if a one domain can communicate with another domain via signals, you could just use

sesearch -A -s syslogd_t -t httpd_t -c process
Found 1 semantic av rules:
   allow syslogd_t domain : process getattr ;

February 06, 2012

Dan Walsh on Twitter @rhatdan
I guess I never blogged this.  But I have been tweeting for a while as rhatdan.  (Not so creative name).

And as always I will almost never tweet something that does not have to do with SELinux or Security....

Follow me if you like.
Can we use SELinux for debugging of an application?

From time to time I am not able to find out a solution for a bug simply. I need to know if an access is really needed and which command or function causes it. This is the time for debugging.

I guess you know tools like strace, gdb, which help us with debugging. Today I would like to show you how SELinux could help us to understand what an application, a script or a command does.

I have recently got the following AVC msg:

type=AVC msg=audit(1328313263.274:55): avc: denied { read } for pid=869 comm=”smartdnotify” name=”group” dev=(removed) ino=293602 scontext=system_u:system_r:fsdaemon_t:s0 tcontext=system_u:object_r:passwd_file_t:s0 tclass=filenode=(removed)

which tells me that the fsdaemon_t domain is trying to access to the /etc/group file with the passwd_file_t label.

$ grep -r passwd_file_t /etc/selinux/targeted/contexts/files/

So I need to find a part of code which needs this access. Usually we see a similar AVC message if a getpw* function is called. That is the time for nm and grep commands.

$ nm -D PATHTO_BINARY |grep getpw
$ grep -r getpw SOURCE_CODE

If you get a result, you will be happy. If not, you need to continue with finding.

Our issue is a case where the smartdnotify command, which causes AVC message, is a shell script. I looked at this script and I got it.

$ cat /usr/libexec/smartmontools/smartdnotify |grep who
for t in $(who | awk ‘{ print $2; }’ | grep -e ‘^tty’ -e ‘^pts/’)

But what to do if you don’t know that the “who” command reads the /etc/group file? You could try to use SELinux to find out an answer. Everything what you need to do is to use SELinux tools.

1. Turn on full auditing system.
$ echo “-w /etc/shadow -p w” >> /etc/audit/audit.rules
$ service auditd restart

2. Generate a local test policy for the “who” command (or your application).
$ sepolgen -n debugwho -t 0 PATHTO/who

3. Remove the context declaration from the debugwho.fc policy file. It might cause a problem with a duplicate declaration.
$ echo “#no context” > debugwho.fc
$ sh debugwho.sh
$ chcon -t debugwho_exec_t PATHTO/who

Now you have loaded debug policy and you need to run the “who” command in this domain.

$ runcon -t system_u -r system_r -t initrc_t — runcon debugwho_t — who

The following transition will happen:

unconfined_t -> initrc_t -> debugwho_t

$ ausearch -m avc -ts recet |grep passwd

type=AVC msg=audit(1328540990.575:125): avc: denied { read } for pid=2258 comm=”who” name=”group” dev=”dm-1″ ino=527060 scontext=system_u:system_r:debugwho_t:s0-s0:c0.c1023 tcontext=system_u:object_r:passwd_file_t:s0 tclass=file

and you won.

Imagine you use it for more complicated applications, services which use python bindings for example.


Small change to semanage login record creation.
For those of you that use confined users, I have recently made a change to semanage that you may or may not notice.  This change will be back ported to RHEl6 also.

In the previous version of semanage, when you created a login user mapping, if you did not specify the level or range of the user, semanage would default the level to s0.

OLD
# semanage login -a -s staff_u dwalsh
# semanage login -l | grep dwalsh
dwalsh                    staff_u                   s0

In the new version of the tool, the semanage command will take the range of the SELinux user, staff_u, and assign it to the login record.

NEW
# semanage user -l | grep staff_u
staff_u         user       s0         s0-s0:c0.c1023                 staff_r sysadm_r system_r unconfined_r
# semanage login -a -s staff_u dwalsh
# semanage login -l | grep dwalsh
dwalsh                    staff_u                   s0-s0:c0.c1023          

I believe this is the correct behavior especially since if you specified a SELinux whose range did not include s0, the tool would blow up.

# semanage user -l | grep topsecret_u
topsecret_u         user       s15         s15-s15:c0.c1023                 staff_r sysadm_r system_r
# semanage login -a -s topsecret_u dwalsh
Would generate a error saying invalid range.

Of course if you specify the level/range it will override the SELinux user level.

February 03, 2012

Why I love Open Source... II
When SELinux does a full relabel, it prints a * for each 1000 files that it relabels.

Some users were complaining about a full relabel and not being able to estimate how much time was left. 

I explained to them that I did not know how many files were on the file system, so I could not estimate how much time was left.  They explained to me that there was ways to look at the file system and get then number of inodes, and then you could estimate how much time was left.  I told them patches accepted, and within a couple of days, I got a patch from John Reiser. 

As of policycoreutils-2.1.10-21.fc17

If you do a touch /.autorelabel; reboot or a fixfiles restore

You will see output like


# fixfiles  restore
10%

With the counter slowly rising.

Open source opens the possibility for all of us to contribute and make the whole better.

Thanks John.

February 02, 2012

A second Kerberos Realm

With the release of KRB5 1.10 A Kerberos workstation can finally have two different TGTs from two different KDCs active at the same time. Until this technology makes it into the major distributions, we are stuck with the limitation of the browser only knowing about one TGT/KDC/Realm at a time.  If you find yourself needing to talk to a second KDC without disrupting your primary,  here are the steps you can take.

  1. Start firefox as you normally would.
  2. Open up a command line prompt
  3. Get the Kerberos Configuration file for the new server.  This can be done by copying the new KDC’s  /etc/krb5.conf to a local file.  For this example  ~/etc/krb5-105.conf Set an environment variable pointing to the new file: export KRB5_CONFIG=/home/ayoung/etc/krb5-105.conf
  4. decide on a location for a second Kerberos Credential cache and set an environment variable to point to it:  export KRB5CCNAME=/home/ayoung/etc/krb5cc
  5. kinit to the new location. echo secretpassword | kinit admin
  6. Run firefox from the command line but using a new profile and not talking to the original instance:  firefox –no-remote -P
  7. Point the new firefox instance at a web page that is part of the new Kerberos Realm.

 

When you are done, make sure you shut down the new firefox instance prior to shutting down your default one, or Firefox will reassign your profiel on next start up to be the newly created profile as opposed to your default.

Once The new Kerberos release is available,  I’ll show how to avoid having to do all of the extra steps.

10 things you probably did not know about SELinux, #10 shipping policy versions
Can I install a policy module built on RHEL6 on a RHEL5 box?

First you need to understand policy is compiled statically.  Even if you use interfaces, all the rules are compiled into the policy.pp file.
If you use policy_module(mypol, 1.0), this will generate a gen_require(` ') block for all of the permissions, classes defined in policy. 
Meaning if you compile a policy on RHEL6 and install it on RHEL5 using policy_module(mypol,1.0) you are likely to fail with an error like:

# semodule -i mypol.pp
libsepol.permission_copy_callback: Module mypol depends on permission open in class file, not satisfied
libsemanage.semanage_link_sandbox: Link packages failed semodule:  Failed!


This is the compiler telling you that you tried to install a policy module that required the "open" permission and RHEL5 policy, and kernel for that matter, has no idea what the "open" permission is.

I guess the analogy would be compiling an executable on RHEL6 that uses a function call in a shared library that does not exists on a RHEL5 box, it won't work. 

Usually we recommend that you compile policy on the oldest machines policy that you plan on supporting, then it should be installable on all future versions of that policy.  We don't tend to remove accesses.

Can I install a policy module built on RHEL5 on a RHEL6 box?

Yes you can, but it probably will not work the way you expect!

In RHEL5 the access required to read a file was:

define(`read_file_perms',`{  getattr read ioctl lock }')

In RHEL6 the access required to read a file was:

define(`read_file_perms',`{ open getattr read ioctl lock }')

So if you compile in a line like:

allow httpd_t mysecret_t:file read_file_perms;

On RHEL5 this would allow the apache type to read files labeled mysecret_t, but if you compiled it on RHEL5 and installed it on RHEL6, apache would not be allowed to "open" the file so the access would fail.

Bottom Line:

If you want to ship policy for two MAJOR  DIFFERENT VERSIONS of RHEL then you would need to compile a version for RHEL5 and for RHEL6.

Policy should work for all Minor versions, as long as you compile on the oldest, supported version, although it might work if you compile on a newer version and install on an older version.

Meaning a compiled version of policy on RHEL6.1 should work on RHEL6.2, RHEL6.3 ...





February 01, 2012

More on deny_ptrace ...
This boolean brings into conflict two of my top goals with SELinux.

1. Make the system secure by default.

The problem with most security systems is NO ONE turns them on.  NO ONE increases the security of their system.
Now while these are exaggerations, I would bet you that 99 % of SELinux users never turn on confined users, or disable the unconfined module .  There are large numbers of people who run SELinux in permissive mode or even disabled.    If we shipped Fedora and RHEL with SELinux disabled, I would bet the number of people who would enable it would be infinitesimally small.    So when I add a feature, I always think about how it would help the vast majority of people.    Will this boolean make my Wife's computer more secure.

2. Keep the unconfined domain unconfined...

Read the blog for why uses expect things to just work, especially from their logged in accounts, especially if they are the admin.

Should deny_ptrace be on by default????

Well deny_ptrace actually confines the unconfined domain, so it conflicts with #2, but if I don't turn it on, for the most part people will not take advantage.  Most users would not see the benefit.  Right now I am going to turn it on by default (Of course I reserve the right to change my mind, or be beaten into submission.)  Any person who wants to disable it permanently can execute.

# setsebool -P deny_ptrace 0

Programmers and system admins if you get a "permission denied" or "Operation not supported" error with ptrace, strace or gdb, it is SELinux causing the problem, and if you need to debug a problem, you can turn the boolean on temporarily.

# setsebool deny_ptrace 0

And do your thing.

Since sysadmins and programmers understand Linux best, it would be easier for them to toggle the security feature.

Now some questions about this feature.

What happened to allow_ptrace boolean in RHEL versions and older Fedora's? 

I originally thought about extending allow_ptrace, but I thought I had better just create a new boolean and remove the old.

allow_ptrace only effected confined users. But since hardly anyone used confined users, I thought I needed a better way to describe the feature, and change its name.  I have removed allow_ptrace and now deny_ptrace will remove all ptrace, sys_ptrace that I know about from the system.

Does deny_ptrace guarantee no domains on my system can ptrace another domain? 

NO
If you load a custom policy with an "allow XYZ self:process ptrace", this boolean will not effect it.  So it only effects actually policy shipped by Fedora or Red Hat.
deny_ptrace does not effect permissive domains,  or permissive mode (obviously),  so if you want to make sure no processes can execute ptrace, you need to disable permissive domains.

After you turn on the deny_ptrace boolean, you can check if any domains are still able to ptrace by executing

# sesearch  -A -C -p ptrace,sys_ptrace | grep -v ^D

What about separation between root and users?

Well SELinux does not know anything about UID users, so root and non root mean nothing to SELinux.  The only way to get this distinction is by setting up confined users and then say run as staff_t as non root and then transition to unconfined_t, or sysadm_t or a confined admin type.  But since hardly anyone uses confined users, this is not an option, if I want to make most computers more secure.

Could you add a bunch of booleans that allows us to turn on and off ptrace per confined domain?

Well this is not really necessary, since most confined domains can not ptrace now, or only could ptrace because of some bugs in the kernel that generated ptrace avc's when running the ps command as root or if a process examined the /proc/PID files of another process.    We have fixed these kernel issues and are removing most domains ability to ptrace permanently, Ie turning deny_ptrace off DOES not allow every domain the ability to ptrace, only a few select domains that we believe might need it.  (Really just user domains.)

January 31, 2012

Fedora 17 New SELinux Feature part I - deny_ptrace
The deny_ptrace feature allows an administrator to toggle the ability of processes on the computer system from examining other processes on the system, including user processes.   It can even block processes running as root.

Most people do not realize that any program they run can examine the memory of any other process run by them.  Meaning the computer game you are running on your desktop can watch everything going on in Firefox or a programs like pwsafe or kinit or other program that attempts to hide passwords..

SELinux defines this access as ptrace and sys_ptrace.  These accesses allow one process to read the memory of another process.   ptrace allows developers and administrators to debug how a process is running using tools like strace, ptrace and gdb.    You can even use gdb (GNU Debugger) to manipulate another process running memory and environment. 

The problem is this is allowed by default. 

My wife does not debug programs, why is she allowed to debug them?  As a matter of fact most of the time, I am not debugging applications, so it would be more secure if we could disable it by default.

I created a feature for Fedora 17 called SELinuxDenyPtrace

Here is a youtube video demonstrating the SELinuxDenyPtrace feature.

Check it out.



January 30, 2012

Cloud Narrative

Identity Management (IdM) needs change as an organization grows in size. For an example, I’ll describe a fictional company, and take it from the smallest to largest stages. While, to some degree, the industry of this firm really doesn’t matter, I am going to use a small import business started by a single individual and scale it up to a multinational corporation. As the organization grows in size, the technical needs will drive the scope and scale of the identity management solutions required.
(This is my writing Cross posted from the FreeIPA wiki)

Scenario

Ms. N. Zappa has just come back from a masters degree program in Jakarta. While living in Indonesia, she established connections with several furniture producers, and she starts a small import/export business in the Boston area. She has contacts at a handful of stores already from previous experience. She moves back in with her folks, who have agreed that she can use a section of the garage for storage, and she outsources all technical issues to a small web services firm. They register the domain name ZappasImports.com for her, set up an account a large cloud provider who provide web and email services. Her information management needs are for tracking orders, suppliers, and customers, which she keeps in a set of spreadsheets that she backs up to the cloud on a nightly basis.

When there is just one person in Zappas, the IdM needs are purely between N Zappa and the cloud provider. Her Internet services contractor has set up an account with the Cloud provider. The Zappa account has two users associated with it: nzappa and the contractor. This authentication is done against the Cloud Providers Authentication Database.

Initial Setup

The contractor sets up three applications for Zappas. A static web server, remote backups, and email. The email server is a managed service, and runs on the same email server as many of the other clients of the Cloud Provider. At this point, the Cloud provider is really just an Internet Service Provider. The website has a simple WebDAV interface and runs as a virtual host on shared web server. Remote backups are done via WebDAV. The Cloud provider manages all these services in order to scale up the number of customers it can handle without overloading its own infrastructure. Because the web applications are run on shared servers, they are responsive. If the overall load increases, the Cloud provider can scale up by allocating more virtual machines.

Contractor with multiple Clients

Zappas is not the only company the web services company manages. They have a portfolio of customers. The cloud deployment approach matches their development methods and skill set. They do not want to have a separate account with the cloud provider for each of their clients. Instead, the user accounts are associated with the client accounts. In addition, the web services firm is itself a client of the cloud provider, with systems that are somewhat comparable to those that they are setting up for Zappas.

Initial Growth

There are two potential next steps. One is that the company adds personnel. The other is when Zappas wants to start tracking and authenticating people outside of her company. These are two fairly different directions. They can happen in either order. Lets look at the external issue first.

External Identity Management

After a few months of operations, she realizes that she is having a much lower rate of return customers than she anticipated. She wants to communicate better with the people that have bought from here before to encourage repeat business, as well as to gauge the relative degree of satisfaction her customers have had with their purchases.

Zappa’s sets up a single external application, a customer order portal. This runs on a dedicated virtual machine, and uses a software package that the cloud provider has pre-canned. It uses an internal database, either PostgreSQL or MySQL with a table for user accounts. Authentication is done via Basic-Auth. The system is accessed via Web over SSL. This requires that the Web server have a publicly routed static IP address. The Cloud Provider runs a certificate authority, and issues a certificate for the web service to Zappa’s Imports. The Customer database is pre-populated with email addresses from a spreadsheet. Passwords are set to expired, which allows the users to reset them using their email addresses as verification. She emails her customers about the system and they start using it.

She also starts a blog, to describe the process she goes through to find new furniture, to explain the history behind some of the more interesting designs, and to introduce people to the culture of Indonesia. Again, this starts off as a managed service by the Cloud service provider: a WordPress instance with another dedicated back-end database. At first she enables public commenting, but the high degree of spam dictates that she somehow authenticate the comments. Instead, she decides that the appropriate thing for her business is to limit comments to people that have either purchased or are thinking of purchasing furniture from her. She could choose to use OpenID or a different Web Single Sign on solution, but that provides her no way to cross reference posts with her customer database. She wants to integrate the two systems. She also is not really happy with the order tracking system, and thinks she might want to switch to a different software package. While all three software packages she has been looking at provide embedded Identity management, they are all incompatible with one another. However, all of them support external authentication. She decides to extract the IdM out into a dedicated system in order to federate her customer focused applications more easily.

Internal Identity Management

Her business grows and she gets an office manager. She rents space at a local warehouse and a small office nearby. They set up accounts with a handful of delivery companies and need to be able to integrate the tracking of packages. The international nature of the business dictates that they get an account that specializes in international trade. Zappas has sufficient business going direct to end consumers that they set up a web catalog and order placement system. This dictates that they have a content management system, and that they establish a relationship with professional photographers in the remote countries that can supply their catalog with high quality images. They have a handful of contractors on retainer that can deliver and assemble some of the more complex pieces. The organization grows a little further. The company is producing enough revenue that she has a full time sales manager. During the busy season, she also hires seasonal help.

When Zappas hires her first employee, she needs to set up a new email account. This is likely done in the Cloud provider’s IdM system. She also needs to add the new employees desktop to the back up system. While the new employee is nominally an office manager, in practical terms she is helping with all aspects of the business, which means she needs to be able to perform administrative activities on the systems hosted in the cloud. The IdM solution they’ve chose supports this by adding the user to a group specific to each of the applications.
Analysis

“There is nothing more practical than a good theory.” –Kurt Lewin

There are patterns that show up in all implementations of IdM systems. Recognizing them will help in implementation of future systems.

Delegation

Her organization may look simple, but Zappa’s Imports has most of the identity management needs of a large organization. She has distinct external contacts that she needs to segregate from each other. Each has a different set of permissible activities based on role. , but there are certain activities that the partners can do that the the office manager can’t. With the addition of the sales manager the organization has grown to the point that she can (and must) delegate management responsibilities: this is the critical point for an identity management system. The sales manager needs to be able to hire a temporary worker, give that worker limited access, and then revoke it after the busy period. Perhaps the temp can take orders, but is not allowed to handle returns. In addition, the sales manager needs to be able to schedule and track a contractor that is heading to a customer site to do an assembly.

The IdM system manages three types of relationships. First, it manages the relationship between The cloud provider and Zappa’s imports. Second, it manages relationships between the Zappa’s imports employees. Finally, it manages the relationships between Zappa’s Imports and the people that do business with Zappa’s. From Zappa’s perspective, adding a new application and adding an additional employee are related tasks. At first, both are handled by Ms. Zappa. By the end, are performed by employees who have been delegated the authority to perform these tasks.

Ownership

Probably the largest question in cloud IdM integration is who owns the information. The Zappas customer list and suppliers list are probably the most valuable assets of the company. If the cloud provider wants to maintain its own customers, they need to provide sufficient reason to trust their Id solution. On the other hand, they need to protect their own assets. In their organization, Ms. Zappa is a client, and she can add and remove servers based on her contract and quality of service agreement with the cloud provider. As the organization grows, this is certainly one of the actions she will want to delegate to the CTO, who will later delegate it to the Operations Manager when Zappa’s Imports grows to the size to hire one.
Avoiding Lock In

Although companies like Zappa’s are not going to be jumping from one cloud provider to another each week, they still want to avoid vendor lock in. Zappa’s applications should have no dependencies on elements internal to the cloud provider that cannot be redirected to a different cloud provider. This is going to be more and more important as the company scales up. A Cloud provider can prove to be a poor fit for an organization for multiple reasons, and not all of those can be foreseen upfront. In the case of Zappa’s, technology is an enabler for business, but it is not the company’s forte. By contracting with a decent internet services firm, she has offloaded some of the decisions. She shouldn’t be locked in indefinitely to a technology decision made today that is secondary to the core of the business.

It is helpful to think of the federation of Identity Management systems as single solutions, with carefully specified integration points between the component parts. By having two systems, you firewall off one segment of your users from another. However, it is worth noting that there are a couple issues this does not address. If there are two systems, and one is deemed canonical, and information is pushed from one to the other, they are acting as a single system, and thus the potential for elevation of privileges is still there.

Enterprise

A few years down the road, Zappa’s is doing well, and has grown to a middle sized companies. N Zappa maintains her role as CEO and President, but is completely out of the software side of the company. Dealing with the relationships essential to her business must be supported by technology, not derailed by the management of technology. Zappa’s has all of the major subdivisions that one would expect to see in a middle sized company. Marketing and Sales are now distinct operations. Operations has a full time call center as well as full time employees for deliveries that require assembly. IT has also grown to support the needs of the organization. On the supply side, several employees have been hired in remote offices to handle the purchasing in several countries. The full time Human Resources manager has contracted to a small number of staffing firms for filling the variations the yearly cycle.

Techno Mix

The information systems are now a mix of in-house, application service provider, and cloud hosted applications. Zappa’s works mainly with two cloud providers that offer differentiated offerings due to geographic location and international issues. Applications for supply, foreign tax and travel, and shipping are hosted in a company in Jakarta. The eCommerce web site and partner Business-to-Business portal is hosted stateside. Zappa’s has consolidated IdM in-house, and shares a subset of its user database with the various technology partners.

The load on the cloud providers systems has scaled up with the company. When orders were measured in single-digits per day, billing was likely at a flat rate. At scale, the daily variations and fluctuation are significant. Auditing the systems becomes a requirement for legal and financial reasons. Different portions of Zappa’s have different budgets, and pay for the usage of the cloud out of separate accounts.

Authentication Tokens

For authentication of employees, Zappa’s has moved from a userid/password model to a cryptographically secure system, based on technologies like Kerberos, hardware tokens, smart-cards and so forth. Different systems require the ability to accept different authentication mechanisms: the corporate blog needs a HW token in order to post an article, but allow OpenID authentication for a customer to post a follow up comment. Some of the suppliers and partners have advanced technologically as well, and have their own authentication systems that they want to use when performing business with Zappa’s. The wide number of web sites in use have dictated a single sign on solution that needs to span across the public internet, and that works around the fact that some of the sites only allow network traffic on ports 443 and 80.

By this point, a standardized mechanism for managing the IdM across all of these systems has become essential. Adding in a new application cannot force changes to the schema. Each additional application cannot silo its own user database. Centralized management is a must; replication to remote sites must be rapid. Elevation of privileges is a major risk and the IdM must have rock solid protections built in against it.

The cloud provider is an integral partner to Zappas. It has to provide seamless integration of Identity Management. Trust and audit are two sides of the same issue: Zappas needs to know what is going on at the Cloud provider. Access to the systems running as virtual machines in the cloud has to be tightly managed. At the same time, the cloud provider finds it self in the same relationship with many other companies, some of which are competitors to Zappos. For legal and financial reasons, the cloud providers needs to provide segregation between its clients. The number of clients it is managing means that the system has to work completely automated.

Conclusion

This narrative has attempted to put the scale and scope of identity management issues in a cloud deployment into to perspective. The fictional company matches the needs of many real companies, as well as many non-corporate entities. The scope of the identity management solutions vary with the scope of the problem or number of problems that they attempt to solve. As our fictional company grew, its needs changed, as did the corresponding Identity Management Solution. The ability to tune the software packages that your company uses will help determine how quickly the company can react to new business opportunities or deal with set backs. A larger organization has more contact points, more needs, and thus cannot as easily rewrite the configuration of their applications to deal with a different IdM solution.

January 16, 2012

Please don’t title your post “Conference Update”

Everyone at FUDcon posts a FUDcon update. Everyone at OLS posts and OLS update. They come in massive blocks, and I personally can’t process them all. Adam doesn’t scale. Instead, please post a shorter post with the crucial piece or pieces that you’ve learned, and title it that way. You can mention that you learned it at Fudcon, but please provide a better orienting title to you post. I do really want to read them. Since I can’t make it to all the conferences, I count on you, the community, to provide a filter.

January 09, 2012

Security Development and Open Source
So one of the really cool things about working at Red Hat is we get to actually talk about what we do. Openness is a really important ideal the company has. I'm currently working to create a security development program inside Red Hat, which is also going to have to be open source friendly. As this is interesting, hard, fun, hard, and useful, I'm going to do my best to keep the world filled in on how things are going. If someone else can benefit from my mistakes, I shall be very happy.

So after all the various things I've read regarding things like Microsoft's Security Development Lifecycle, BSIMM, CERT documentation, it's very clear that there is a lot of information regarding what a secure development program should look like. There is almost no information about actually starting one.

The Roadmap
A big challenge with starting a secure development program is that you can't just show up and start telling people how to do their jobs. You'll probably last two days before someone beats you up in the parking garage. This is especially true when you take open source into consideration. If I tried to tell the folks at Apache how to develop, I'd likely be laughed out of the room (or mailing list in this instance). A program like this needs careful planning. You'll get one chance to make it work, if you blow it, nobody will ever listen to you again.

This is where a sound roadmap comes into play. While the overall look of my roadmap continues to change as I talk to people, the first step has to be training. If we don't train the involved parties, nobody will understand what's going on or why certain practices should be adopted. This includes training from the point of basic security, all the way to training on various security concepts such as secure design, development, training, and response.

Phase 1: Training
Security is hard, if nobody knows what you're talking about, you will fail. It's also dangerous to assume everyone understands security basics. Security is one of those areas where the more you learn the less you know. It's also changing constantly. What was sound security advice a few years ago may not be anymore. Various security technologies continue to evolve, and new ones are developed. New exploitation techniques are constantly changing. It's very hard to keep tabs on everything.

Our current initial focus on training is going to focus on these topics:

Security basics. This includes information on the security development lifecycle as a whole, and understanding what a security flaw is, why it's a problem, and some history. If we don't know where we've been, it's hard to see where we're going.

Secure design. If you don't have a secure design before you start to write the code, it may become impossible to fix some problems without a significant amount of work. Secure design from the start will include topics like threat modeling, defense in depth, secure defaults, and principal of least privilege.

Secure development. This topic is very broad and has the potential to get overly technical. A huge challenge here is how much information is enough? It's not going to be productive if you end up creating developers who are so worried about security issues that their productivity drops to zero.

Secure testing. An important part security development is to test what you create. There is never going to software that is totally free of security flaws. By doing certain testing though you can catch some things before it leaves the door. This is where using things like dynamic and static testing is helpful. Agan though, there has to be certain sensible limits. At some point the law of diminishing returns kicks in. We need to figure out where that is.

There are of course other areas for training, but the above are some of my initial goals. I also hope to make some portion of this training material available to the open source community. I'm not entirely sure how all that will happen long term, but it's something on the list.

As my plans continue to grow and evolve, I'll be certain to fill in more details.
Until next time.

January 06, 2012

Cloud Identity Management

Openstack Keystone is the Identity Management (IdM) gateway for the rest of the Openstack infrastructure.  While it is fairly new code, and not feature complete as of yet,  it does show some interesting aspects of cloud identity management and the issues it involves.  That, of course, begets the question of what is required in a cloud Identity Management gateway.

First of all,  lets look at what IPA manages:

  1. Users
  2. Hosts
  3. Groupings of the above
  4. DNS (Not just names for hosts,  but also Kerberos autodiscovery)
  5. Policy (Sudo, HBAC. Policy, Directory Server Access)

The primary concept in Keystone not yet in IPA is Multitenancy. This can be thought of a form of Policy on top of groups.  I’ve started writing up the requirements.

Let me restate the definition of multitenancy:

Multitenancy is a policy of an identity management solution where a grouping segregates the visible of entities inside from those outside.

But not everyone will use FreeIPA,  and the Keystone target deployment is somewhat different from FreeIPA   Keystone in particular wants to be able to delegate back to the Tenant the management of their own set of resources in the cloud.

Hmmm… I think I can even convert that to a mission statement:

The mission of Openstack Keystone is to provide single sign-on for cloud management by delegating  IdM control of  the Tenancies to the Tenant Adminstrators.

I’ll leave that up there for a bit to see if someone can do me one better.

What do I mean by delegating to the tenant administrators.  I’ll give a couple examples.

  1. If the user has FreeIPA or Active Directory in the home system,  they should be able to use them to Administer access to their own resources in the cloud
  2. If a user becomes a reseller of Cloud services,  they should be able to manage nested tenancies for their clients

Here are some requirements of cloud IdM

  1. A user who wishes to user the cloud providers IdM solution should be able to provide essential services and access control for users in their organization
  2. A private cloud used to manage applications visile from outside the corporate firewall should be able to segregate  their customers, their suppliers, and their partners from each other, while maintaining an integrated  Identity Management Database.
  3. Cloud IdM  needs to provide a cryptographically secure system that is at least as strong as that  provided by the users IdM systems.  While Kerberos is not necessarily an option across corporate firewalls due to blocked ports,  the IdM implemented by the Cloud provider has to be based on the same principals. The cloud IdM system must provide a reasonable degree o f trust both the the end user and the system administrator with regard to the identity of one another.

Comments?

January 05, 2012

Muppet Princess Bride

So I watched the latest Muppet Movie with my family this weekend and it go me thinking: who would I cast for a Muppet Version of the Princess Bride?

Sick Kid in Bed:  Robin the Frog

Grandpa:  Kermit

Buttercup:  Janice

Westley:  Floyd

Vizzini:  Rizzo the Rat

Inigo Montoya:  Pepe the King Prawn

Fezzik:  Sweetums

Humperdinck: Link Hearthrob

Count Rugen: Professor Bunsen Honeydew

The Albino:  Beaker

Yellin the Spy Master:  Marvin Suggs

Miracle Max:  Waldorf

Valerie:  Statler (in drag)

Impressive Clergyman:  The Swedish Chef

The King: Gonzo the Great

The Queen: Camilla the Chicken

Old Lady Who Boos: Miss Piggy

 

January 03, 2012

What will 2012 bring for security?
So the year 2012 is finally here, the world is supposed to end this year (someday one of these predictions will be right). With every new year there are always a bunch of new exciting predictions about computer security. Most are wrong. If we knew what was going to happen, we'd stop it from happening, hopefully.

Rather than make a pointless prediction for 2012, I have a few goals for the year. As I announced previously, I'm working on a security effort inside Red Hat to bring proactive security measures to our products. The Red Hat Product Security Team if you will. Some of my current goals for the year (which are subject to change) stand as:

Security training materials
The team is working on various security training materials. Topics ranging from secure design, development, and testing. Some of this will stay internal to Red Hat, but I hope to make much of it public for the general open source community to leverage. I've done a fair amount of research on this topic. There is a lot of really quality material out there, but finding it can be difficult.

Security development principals for open source
There are numerous security development lifecycle programs out there, but none are geared for the unique challenges open source faces. I've yet to find a project that doesn't want to write secure code, or handle security flaws properly. I have found many that don't really know where to start though. While I've done a lot of investigating about existing security development programs, most lack the very crucial step of where and how to start. Stay tuned for updates in this area.

Investigate various security tools
There are a lot of interesting security tools out there. Things from static analysis, dynamic analysis, fuzzing, and testing. Some work well, some don't, some are hard to use. One of my goals is to sort this out, and make the findings available to anyone who is interested.

Work with open source projects
One of my biggest gripes about security efforts is they often work like this: "here's some information, good luck". Rather than just dump things like training materials and principals to the world, we need to work with projects who have an interest in this. One of the really hard, and really interesting aspects of open source is that every project is very different, and many use a lot of volunteers who aren't going to be receptive to the idea of a bunch of new process. I can't say I know how this one is going to end, but I have plenty of ideas where it can start.

In general I see 2012 as being very busy and exciting, which isn't a bad problem to have at all.

If you have any questions, or want to have a chat about any of this, feel free to mail me, bressers@redhat.com.

December 31, 2011

krb5-appl 1.0.1,1.0.2, MITKRB5-SA-2011-008/CVE-2011-4862, and Fedora 15 and 16

If you're concerned about MITKRB5-SA-2011-008, and you're still running Fedora 15, please go ahead and grab the candidate builds from the in-progress update and give the advisory some love. I'd like to push it to stable soonish anyway (and should be able to, in a couple of days), but in the meantime, there it is. The Fedora 16 and Raw Hide updates are already pushed, the former in part due to inadvertant abuse of the system. I expect.

The rest of you, of course, are forsaken.

By me, at least.

And the Fedora Project in general, though if I ignore that, it fuels my ego, so naturally I ignore that detail.

The internal Red Hat Security Response Team handled it for the Enterprise Linux product, so I didn't get a Big Damn Heroes moment mixed in with my otherwise humdrum vacation.

Speaking of vacation, I'm reminded now of the amount of tossing and turning that's usually required to go to sleep when you're not actually sleep-deprived, and... it's weird. I'm probably also more pleasant to be around just now. Don't get used to it.

December 22, 2011

SSSD Tips and Tricks Vol. 2 – LDAP

Multiple Search Bases

Starting with SSSD 1.7.0, the System Security Services Daemon now has the ability to search for users, groups and netgroups in multiple search bases. Some LDAP deployments divide groups into different trees so that individual clients can receive different “views” of a group. (This is especially useful for some application software that restricts access to hard-coded group names. In these cases, you can install the same application in different configurations by providing different views of that group).

In SSSD 1.7.0, we extended the ldap_search_base (and ldap_[user|group|netgroup]_search_base) options so that they will now take three pieces of information instead of one (the base itself). Search bases are specified by the pseudocode regular expression:

<base_dn>?<search_scope>?<search_filter>

The search filter can be either an empty string (indicating that no special filtering should be done) or it can be a valid LDAP search filter, which will be ANDed with the standard search filters SSSD uses internally.

“But that’s only one search base, you say!”. And you would be correct. You can add additional search bases by inserting another ‘?’ after the search filter of the preceding base.

For backwards-compatibility, a single search base can be specified simply by base_dn, which will be treated as

<base_dn>?subtree?

Paged lookups

For performance reasons, many LDAP servers limit the number of records that can be retrieved by an LDAP search at one time. Beginning with SSSD 1.6.0, the System Security Services Daemon can now perform paged searches to retrieve responses containing more entries than this limit. This is particularly useful for deployments with large group memberships or those with large numbers of users and groups with enumeration enabled.

SSSD now provides an option ldap_page_size that specifies how many records to request for each individual lookup. The default was set to 1000 records (chosen as it was the lowest common default value of OpenLDAP, 389 DS and Active Directory). However, if your LDAP server has been tuned to have a higher or lower value for this limit, you may wish to update this value to match.

As a general rule, you will want this page size to match the limit on the server, for maximum performance. A larger page size will mean fewer round-trips across the wire to LDAP.

Password Changes and Read-Only Replicas

Due to its use of the openldap client libraries, SSSD has a limitation when it comes to performing password changes. Normally, the way that a read-only replica will be set up is that it will be configured to return a referral to a read-write master LDAP server when a password-change attempt occurs. The client is expected to process this referral and then open a new connection to the read-write master.

Unfortunately, due to an open bug in the OpenLDAP client libraries (which SSSD uses internally for much of its LDAP communication), this referral is not processed correctly. As we’ve not had much traction with the OpenLDAP developers in fixing this bug, SSSD has implemented a workaround. We provide a new option ldap_chpass_uri (valid when using chpass_provider = ldap). It’s semantics are identical to that of ldap_uri, except that it will only be used when a password-change is implemented. This option allows the system administrator to specify a list of read-write servers against which the password-change should occur. The ldap_uri option can remain pointed at the read-only replicas for performance, without compromising the ability to perform password changes on the client.


December 12, 2011

10 things you probably did not know about SELinux #9 Backing up and Restoring Labels.
It has been a few years since I discusses backing up and restoring labels with SELinux.   

I was asked at the Lisa 11 conference by a backup utility developer, "How should he save and restore SELinux security contexts?"  He also asked whether or not his tool should always maintain these context?  Finally how should the tool react if the system would not allow the context to be restored? 

Interesting topic.  Lets first take a look at a few tools for backing up content with SELinux labels.

SELinux stores SELinux security labels (contexts) as extended attributes with the inode on the file system.  If an administrate wants to backup/restore files with the SELinux labels,  you need to use a utility that supports this.

When SELinux first shipped the only utility to do this was star (RHEL4) , GNU tar at that time did not support extended attributes.  Later extended attribute support was added to GNU tar.  ( tar --selinux -cvf /tmp/etc.tgz /etc ) Rsync also has support for maintaining extended attributes.  Even Dump/Restore can now support maintaining the extended attributes.

I often question is whether this is a good idea to maintain the labels.  In some cases your security goals require it.  For example backing up sensitivity labelled data (MLS) requires this.  If you have a file labelled TopSecret, you would definitely want to maintain this within the archive.

But most of us do not deal with sensitivity labelled data, and we would want to make sure the data on our system is labelled correctly based on the current security definition on our system.  Trying to maintain the SELinux labels and restore them can be a mistake in several cases. 

For example:

Target file system does not support extended attributes.

If you attempted to restore files to a file system that does not support extended attributes.  Does the administrator have a way to allow this?

Updating a machine for one version of the OS to another.

If you backed up your /home directory before updating from Fedora 15 to Fedora 16 and then restored the content of the archive, certain directories in you home directory will be mislabeled and potentially tools like googlechrome or colord will fail.  You would have been better off having the content restored the archive and then running restorecon -R - v /home.

Copying an archive from one machine to another machine with an older OS.

Attempting to maintain the labels would be wrong if you created an archive on a RHEL6 box and then attempting to restore the archive on a RHEL5 box.  If the RHEL5 kernel does not understand a label from a RHEL6 box, then the label will not be allowed to be placed on the disk.   In this case, again you would want to put the files down and then restore the labels. 

In this case it would be nice if the tools used to restore the content had the ability to label the content "correctly" based on the file_contexts definitions on the target system.  That way we would not have a race condition where the labels on the files are incorrect for a period of time.

In conclusion the backup/restore utility should:
  • allow the administrator to decide whether or not to save the SELinux labels and restore them.
  • Allow the administrator to specify the tool to restore the files using the default labels as specified on the target system (matchpathcon/setfscreatecon)
  • If the utility does not allow have the second option, in most cases the administrator should run restorecon on the restored files.

December 08, 2011

Why isn't setroubleshoot working in Fedora 16?
Well if you did a fresh install it does work.  But if you did an upgrade install from an older Fedora you have a problem.

setroubleshootd is a dbus service launched by the audit daemon.    In Fedora 16 all daemons that were running under as System V init scripts and were converted to systemd, no longer are started by default.  Meaning the auditd daemon is probably no longer running on your machines.  You might notice AVC messages showing up in /var/log/messages, rather then /var/log/audit/audit.log.

It is simple to fix this problem by executing

# systemctl enable auditd.service
# systemctl start auditd.service


This will re-enable the auditd daemon and your setroubleshoot daemon should start working again.  If you get any AVC messages, they will start showing up in the /var/log/audit/audit.log.


Enterprise Linux 6.1 to 6.2 risk report
Red Hat Enterprise Linux 6.2 was released this week (Dec 2011), just over six months since the release of 6.1 in May 2011. So let's use this opportunity to take a quick look back over the vulnerabilities and security updates made in that time, specifically for Red Hat Enterprise Linux 6 Server.

Errata count

The chart below illustrates the total number of security updates issued for Red Hat Enterprise Linux 6 Server if you had installed 6.1, up to and including the 6.2 release, broken down by severity. It's split into two columns, one for the packages you'd get if you did a default install, and the other if you installed every single package (which is unlikely as it would involve a bit of manual effort to select every one). For a given installation, the number of package updates and vulnerabilities that affected you will depend on exactly what you have installed or removed.

So, for a default install, from release of 6.1 up to and including 6.2, we shipped 36 advisories to address 121 vulnerabilities. 2 advisories were rated critical, 10 were important, and the remaining 24 were moderate and low.

Or, for all packages, from release of 6.1 up to and including 6.2, we shipped 88 advisories to address 218 vulnerabilities. 10 advisories were rated critical, 16 were important, and the remaining 62 were moderate and low.

Critical vulnerabilities

The 10 critical advisories addressed 31 critical vulnerabilities across 3 components:

  1. Two updates to the OpenJDK 6 Java Runtime (June 2011, October 2011) where a malicious web site presenting a Java applet could potentially run arbitrary code as the user running a web browser.
  2. Four updates to Firefox (June 2011, August 2011, September 2011, November 2011) where a malicious web site could potentially run arbitrary code as the user running Firefox.
  3. Four updates to Thunderbird (June 2011, August 2011, September 2011 November 2011) where a malicious email message could potentially run arbitrary code as the user running Thunderbird.

Updates to correct all of the 31 critical vulnerabilities were available via Red Hat Network either the same day or the next calendar day after the issues were public.

Other significant vulnerabilities

Although not in the definition of critical severity, also of interest during this period were a few flaws that were high risk or easily exploitable:

  • A flaw in Bind, CVE-2011-4313 fixed by RHSA-2011:1458 where a malicious client could cause Bind to stop responding, a denial of service attack. This flaw was discovered by it being accidentally triggered in the wild.

  • A flaw in the Apache HTTP Server, CVE-2011-3192, fixed by RHSA-2011:1245, where a remote attacker could cause a denial of service attack. This was discovered due to a public exploit.

  • A flaw in RPM, CVE-2011-3378 fixed by RHSA-2011:1349 where a specially-crafted RPM package that, when queried or installed, would cause rpm to crash or, potentially, execute arbitrary code prior to any signature checking. We're not aware of any working exploits for this issue.

  • Updates to blacklist the DigiNotar Certificate Authority.

Previous update releases

To compare these statistics with previous update releases we need to take into account that the time between each update release is different. So looking at a default installation and calculating the number of advisories per month gives the following chart:

This data is interesting to get a feel for the risk of running Enterprise Linux 6 Server, but isn't really useful for comparisons with other major versions, distributions, or operating systems -- for example, a default install of either Red Hat Enterprise Linux 4AS and 6 Server does not include Firefox, but a default install of 5 Server does. You can use our public security measurement data and tools, and run your own custom metrics for any given Red Hat product, package set, timescales, and severity range of interest.

Angelo

I was working at a local coffee shop when I noticed an old man walk in.  His hat had a Yin Yang on it.  It struck a memory and I Googled for a list of US Army division patches.  Easy access to modern technology told me more than I expected.  The 29th Infantry Division, the Blue and the Gray, landed at Bloody Omaha on June 6th, 1944.

I walked up to him and asked “You were with the 29th Division in WWII.”  I looked a man Great-Grandfather old, but strong for all that.

“Yes, I was.”

I held out my hand to shake his.  “Thank you.”

He was startled.  He offered me a seat and I took it.  I didn’t think to ask his name yet,  but later found out it was Angelo.

“Most people don’t know what it means.”

“I was an Army officer.  An infantryman.  I owe you a special debt.”  I told him. “My Grandfather was at Utah.  They’ve said that the fighting at Omaha was so fierce that it pulled forces from elsewhere.  If it hadn’t been so bad there, I might not be here.”  Not quite correct, now that I think about it.  William Spelman had managed to get his wife pregnant before deploying to England.  That was my Mom, so I would possibly still be here.  It was my Uncle and Cousins that owe their existence to my Grandfather’s survival.

Our conversation progressed non-linearly.  He had not been in the earlier invasions of Italy or Africa.  His job was specialized, so after Normandy, they shipped him to the pacific theater.  Has was with a unit attached to the 29th, not specifically assigned to it.  The boat that took him back stateside was taking Churchill as well, and the statesman’s quarters had to be re built, delaying their departure.   The late departure meant that he only got eight days of leave before shipping out to join the preparation for the invasion of Luzon.
He told the tale of one comrade, a normally happy-go-lucky guy that became quiet and withdrawn before Luzon.  “I’m not going to make it.”  He told Angelo.  “Everyone thinks that.”  They landed fairly unopposed at Luzon.  They only lost one man:  Angelo’s friend hit the deep water when disembarking and he drowned.

“I felt the same way, if we were going to Japan.”  He confided.  “I owe Truman my life.  If they hadn’t dropped the bomb, well, you know what they were saying?”  I assured him that I did.  The casualty projections for a Japan invasion were staggering.

We returned to talking about Europe.  “My grandfather was drafted.  He was older, and had worked on the rail road.  Back during the depression, he dropped out of school and started on the rail lines.  He was in logistics.  So by the time he deployed he was the company first Sargent.” Also, I realize now, a little inaccurate.  I have a photo of Grandpa Bill in a fairly clean uniform, carrying an M-1 carbine.  The date on the back of the photo is June 7, 1944.  I can’t remember the place, but I suspect it was Marie St. Eglise.  On the sleeve of his Eisenhower Jacket he has the rank of a Staff Sargent.  I had his jacket back when I was in High School, and it had three chevrons and two rockers with the First Sargent diamond in the middle.  I guess he was made Top later than June 6.  “Since he knew logistics, they put him with a transpo company.”

Angelo had been an “invasion specialist.”  Enlisting as young as he could, he had managed to learn cryptographic and radio skills in the days back when a computer was still the name of a human occupation.  They went in early, and broadcast back to the fleet.  I didn’t think to ask how he got in.

“War is horrible.  I heard people screaming ‘Don’t let me die.’”  He paused, lost in the past, momentarily unable to speak. “I don’t talk about this with most people.  My wife passed away a few years back.  I have dreams, and she used to wake me up. I go to the VA.  I have PSTD”   I didn’t correct the misordering of the acronym.

“We had been told they were evil, that the krouts were inhuman.  When we got to Germany, we saw that they were just people.  We thought that we were the good guys.  At some point I realized that they thought that they were the good guys.  We watched these films, you saw them marching so perfectly and you thought that they were unbeatable.  I thought, ‘how are we going to go up against this.’  But war.  War is horrible.  They were people, just like us.”
This was three or four days after the 67th anniversary of the Normandy Landing.  While the press had made a big deal about it on the 50th and 60th anniversaries, this year it had passed with barely a mention in the news, and Angelo was annoyed. “I wasn’t the hero.  It was those guys that didn’t come home that were the heros.”  It was just platitudes.  His face reflected the pain of the memories that came back, the people he had seen dead and dying, the friends and comrades that didn’t come back.

“Some of us will always remember, I assured him.”

Is it wrong of me to post this here?  He talked to me in confidence, the sharing between former soldiers.   But we should remember what those men with Baseball Caps with funny looking logos on it went through.  And what they still go through.

December 04, 2011

Troubles with policy development, part #1

Some time ago I got a question from a guy about some troubles with his policy development . I decided to write a set of blogs related to common troubles which either we or other folks could have in policy development.

Now back to the problem. This guy got a similar error message:

“/usr/bin/semodule_link: loading package libsepol.print_missing_requirements: rhcs’s global requirements were not met: type/attribute corosync_exec_t
/usr/bin/semodule_link: Error while linking packages”

through building of his custom policy.

We use “optional_policy” statement to declare a rule which could be invalid if an appropriate module (module containing a declaration of an interface) is disabled/removed or is not declared. Probably the following example is better than my definition.

optional_policy(`
corosync_exec(fenced_t)
‘)

allows the fenced binary to execute the Corosync Cluster Engine. Now how could this rule become invalid? Easily by disabling of the corosync policy module which contains this interface definition.

# semodule -d corosync

This is a way how we do the policy really modular. You can remove a module from the policy and everything should work fine, only a daemon or a user program will be without SELinux protection. You can check this out and make your policy being as minimal as you wish. Just be careful with removing of the unconfineduser policy module (see http://danwalsh.livejournal.com/42394.html).

So if you use an interface without “optional” statement and you disable/remove or do not add a module declaration into the module-*.conf file, you will get exactly the same error message.

Note: If the “optional_policy” declaration contains more rules then all these rules will become invalid for this block.


December 02, 2011

SELinux versus pam_securid.so
Seems to be my month for fighting pam modules from third parties.   I have heard that RSA corporation is recommending SELinux be turned off to run their products.  I just love it when a supposed security company recommends that customers turn on a key security component of the Operating System.  Now did RSA ever contact me to work through the problems,? No. 

Come on RSA you can do better then this. 

I am trying to avoid underhanded security comment about using SELinux to protect key assets of the company...

I worked with Joe Lucchesi, to get this pam module to work with SELinux.  Joe was having problems with sshd working with the pam module.  He was getting execstack errors.  Turns out the pam_securid.so file was shipped with the execstack flag turned on.  Execstack is a dangerous protection to allow a domain, since it turns off protection against buffer overflow attacks.  Most app never need this access.

Executing

execstack -c /lib64/security/pam_securid.so

Cleared the flag.  And allowed sshd to get past this AVC.  Whatever is causing this flag to be set, the build procedure or installation needs to be fixed.

The next problems we hit was pam_securid seems to be running netstat under the covers.  I recall we had this problem with the Netscape Certificate libraries. They used to execute netstat in order to generate entropy when using certificates, so I figure this is what is going on here.  I also see the sshd executing ps?  Probably  for the same reason.  

RSA guys please use /dev/urandom and /dev/random. 

We turned off the use of netstat in our libraries years ago.  Using netstat and ps causes me to have to allow login programs to search /sys/net and because of bugs in our kernel add a dontaudit for sys_ptrace.   

Finally secureid uses /var/ace to store its authorization content.  This should probably be under /var/lib/ace, I have added a label for this directory

/var/ace(/.*)?                 gen_context(system_u:object_r:var_auth_t,s0)

This should allow the pam_securid module to use the content in this directory.

Now Joe can run his pam_securid.so on his machine in enforcing mode with a small custom module until we push updates to fix the problem.

Bottom line.  If you are a third party and you are having problems running your tools with SELinux, please, please contact me or Red Hat and lets work through the problems, and give our users a better experience.

November 30, 2011

Checking My Work On Eight Tone Scales

My calculations on Eight Tone Scales was way too manually intensive for me to trust that I got it right. I should check my work.

  • generate the set of all strings of intervals of length 8.
    1. Generate an array of length 8 and populate it with all 1′s except the first value, which gets a 0.
    2. increment each digit. If the digit goes over five, overflow to the next digit. If the last digit overflows, we are done.
    3. Sum the digits. If they don’t add up to 8, throw it out
  • Convert them to a canonical form. We can make an array of 8 digits into an eight digit integer. Take the highest valued integer for each mode of the scale.
    1. Convert the digits into a single eight digit integer.
    2. Rotate the array by one and convert it to an 8 digit number.
    3. Compare the results of the previous two steps and keep the higher value.
    4. Repeat until we’ve rotated through all values in the array.
  • Put them into a Set which will only contain unique values to remove duplicates.
  • Sort the set
  •  

    Since I am moving on to a Python Project, I figured I’d code it up in python.

    #!/usr/bin/python
    
    def increment(intervals, index):
        if index >= len(intervals):
            return False
        intervals[index] += 1
        if intervals[index] > 5:
            intervals[index] = 1
            return increment(intervals, index + 1)
        return True
    
    def sums_to(intervals, sum):
        total = 0
        for val in intervals:
            total += val
        return sum == total
    
    def int_form(intervals):
        value = 0
        for digit in intervals:
            value *= 10
            value += digit
        return value
    
    def rotate(intervals):
        l = intervals[:]
        n = len(l) - 1
        head = l[:n]
        l[:n] = []
        l.extend(head)
        return l
    
    def max_int_form(intervals):
        copy_of = intervals[:]
        max = 0
        for digit in intervals:
            next_int_form = int_form(copy_of)
            if next_int_form > max:
                max = next_int_form
            copy_of = rotate(copy_of)
        return max
    
    intervals = [ 0, 1, 1, 1, 1, 1, 1, 1]
    scale_set = set()
    count = 0
    while increment (intervals,0):
        if sums_to(intervals, 12):
            scale_set.add(max_int_form(intervals))
    scales = list(scale_set)
    scales.sort()
    
    for scale in scales:
        count += 1
        print scale
    print count ," Scales generated"
    

    And the Output:

    [ayoung@ayoung python]$ ./eightone.py
    21212121
    22112121
    22112211
    22121121
    22121211
    22122111
    22211121
    22211211
    22212111
    22221111
    31111122
    31111212
    31111221
    31112112
    31112121
    31112211
    31113111
    31121112
    31121121
    31121211
    31122111
    31131111
    31211112
    31211121
    31211211
    31212111
    31221111
    31311111
    32111112
    32111121
    32111211
    32112111
    32121111
    32211111
    33111111
    41111112
    41111121
    41111211
    41112111
    41121111
    41211111
    42111111
    51111111
    43  Scales generated
    

November 28, 2011

Eight Tone Scales

How many Eight Tone Scales are there? At first glance, this might seem like a simple CS GRE type question: there are 12 notes, so it would be 12 select 8 unordered.  Not quite:

Why 8 notes:  because in a 4/4 measure,  there are 8 quarter notes,  so if you have  an 8 note scale,  you have one distinct pitch to play per note.

  • The bebop  scale is probably the best example of this:  add a #5 to a major scale and not only do you have 8 notes,  but each of the chord tones falls on the down beat,  not just for the Major Triad,  but for the Minor and Dominant seventh as well.
  • The Harmonic minor scale can be viewed as the relative minor  plus a flat 9,  with the distinctive minor third just skipping  the minor seventh.  If you add back in the seventh, you get an 8 note scale  that works well for most Eastern European style music.
  • The Diminished scale,  consisting of alternating half and whole steps  has 8 notes, and makes for some great runs as well.

So with those in mind,  I was wondering how many other 8 note scale there are.  I will ignore the other qualities that make an 8 note scale interesting for now:  I’m sure each will have some novelty to it.

So 12 choose 8  would give us (12!)/(8!)(4!)  or  495 scales,  the real number is much lower.  In the case of the three examples I post above,  note that the Harmonic Minor option really is just the same as the bebop scale,  just a different mode:  Played A to A instead of C to C.  So I will count these two as one scale, and the diminished scale as one scale.  Thus, all modes will be considered the same scale,  as will all transpositions:  C Bebop Major played from C to C is the same as F Bebop Major played from F to F.    We want to ignore 11 transpositions,  and 7 modes.  That gives me an answer of 6.42…which tells me I did something wrong….hmmm. Really,  we don’t just care about the number of scales,  but we want to be able to generate all of the scales,  and ignore the duplicates.  Lets apply some heuristics to reduce the number of duplications we have.

Another way to look at it is to look at the intervals between each note.  This is actually the more useful apporach,  as it is the template a musician would use to compose a specific instance of a scale.  We’ll use W for whole step and H for Half. For example,  the Bebop major scale is W W H W H  H W H.  Numerically,  this is 2 2 1 2 1 1 2 1  which sums to 12.  So we could look at it as generating the ordered sequences of 8 digits that sum to 12.  One nice feature of this is that we care about 8 distinct notes,  and we still have 8 elements:  the interval from the last note to looping around back to the first is also encapsulated in the sequence.   However,  we’ll have a couple scales unaccounted for with the W/H  approach, namely those that have an interval greater than 2.  How many of those are there?

If we start with 7  half steps,  we have a chromatic scale followed by an interval of 5H,  or a Major fourth in conventional intervals: H H H H H H H 5.

Note that any variation with a tritone in it is going to be a mode of this one.  For example H H 5 H H H H H is just starting on the 5th H.

Running total:  1 Scale.

If we steal a half step from  the 5,  and add it to a H,  we get a W  and an interval of 4H.  HHH HHH W 4.

If we fix the 4 in the first position,  It becomes a simple template like this:

4 XXX XXXX

Where we put the W in each position, and fill in the rest with Hs.

  1. 4 WHH HHHH
  2. 4 HWH HHHH
  3. 4 HHW HHHH
  4. 4 HHH WHHH
  5. 4 HHH HWHH
  6. 4 HHH HHWH
  7. 4 HHH HHHW

Running Total:  8 scales

If we steal a half step from the 4,  we can either add it to the W or to one of the H.

  •  HHH HHH 3 3
  •  HHH HH WW 3

Note if we once again steal a half step,  in order to generate distinct steps from this last 3,  we have to add it to another H.

HHHH WWWW

Which I’ll enumerate later.

In the case of both   HHH HHH 3 3  and  HHH HH WW 3  we can fix the first interval to be an H  and reduce the number of alternatives  by using the other remaining intervals  for the last.

So  in the case of   HHH HHH 3 3   we make the template   H XXX XXX 3 .  The Remaining 3 can go into any of the Xs,  and the rest are filled with Hs.

  1. H 3HH HHH 3
  2. H H3H HHH 3
  3. H HH3 HHH 3  (This one is symetric, which we’ll have to account for in our modes.)
  4. H HHH 3HH 3
  5. H HHH H3H 3
  6. H HHH HH3 3

Running total 14 scales.

For  HHH HH WW 3  There are two  variations:

  • H XXX XXX W
  • H XXX XXX  3

Note that  these cover all the combinations generated by  W XXX XXX 3.

First we’ll do all combinations where

H XXX XXX  3  Has the fewest permutations.  The Two Ws can be in either order and produce the same scale.

  1. H  WWH HHH 3
  2. H WHW HHH 3
  3. H WHH WHH 3 (Not symmetric due to the 3)
  4. H WHH HWH 3
  5. H WHH HHW 3
  6. H HWW HHH 3
  7. H HWH WHH 3
  8. H HWH HWH 3
  9. H HWH HHW 3
  10. H HHW WHH 3
  11. H HHW HWH 3
  12. H HHW HHW 3
  13. H HHH WWH 3
  14. H HHH WHW 3
  15. H HHH HWW 3

Running total  29 Scales.

It might be tempting to say that the there are 2X15 or 30 variations of   H XXX XXX W:  those where W  precedes 3 and those where 3 precedes W.  However,  scales “wrap around.” So anything of the form 3H is covered by the above combinations.  So we only need to account for scales with 3W in the middle.

  1. H 3WH HHH W
  2. H H3W HHH W
  3. H HH3 WHH W
  4. H HHH 3WH W
  5. H HHH H3W W

Running total  34 Scales.

The scale HHHHHH5  is the variation with the most half steps.  The one with the least?  Lets start from a scale with None:  The 6th note whole tone scale  W W W W W W.  (From A this would be A B C# D# F G).  If we split any one of those whole tones,  we get a seven note scale with two half steps and five whole steps.  Thus,  we have to split exactly two of them.  Splitting the first two gives us:  H H H H W W W W.  How many variations of this are there?  Again,  lets use the technique of fixing the First,  but now also the last, element of the Set.  We will state that the first element is always H  and the last is always  W.

H X X X X X X W.  This will filter out most modes,  but not all….back to that below. Simplest is all H and Ws together.

  1. H HHH WWWW

Running Total 35 Scales

Thos middle 6 places now must get filled by Six intervals,  3 Ws  and   3 Hs.  Another way to think of this is that we can put 0, 1, 2 or 3 Ws between each of the other intervals.    W can have  a run of 3  Injected into H HHHH W like this.  Note that we avoid the 4 in a row patterns from above.

  1. H WWW HHHH W
  2. H  H WWW HH W
  3. H  HH WWW H W

Running total  38 Scales.

Now we can either have W  followed by  WW.  We will  avoid all combinations where Those bump up against another W.

  1. H WHW WHH W
  2. H WHH WWH W

Running Total 40 Scales

And the opposite pattern WW followed by W:

  1. H WWH WHH W (Bebop)
  2. H WWH HWH W

Running total 42 Scales.

Bebop Major is W W H W H  H W H  If we wrap this around  by one,  moving the last   interval into the first  position,   we get  H W W H W H  H W,  which is variation 1 above.

The last  variation is where we have alternating H and W.  This is a very symmetric scale.  There are  Only two modes:  The one that starts with H W  and the one that starts with W H.

  1. H W H W H W H W  (Diminished)

Which gives a total of 43 scales.

Here’s the complete list:

  1. H H H H H H H 5.
  2. 4 WHH HHHH
  3. 4 HWH HHHH
  4. 4 HHW HHHH
  5. 4 HHH WHHH
  6. 4 HHH HWHH
  7. 4 HHH HHWH
  8. 4 HHH HHHW
  9. H 3HH HHH 3
  10. H H3H HHH 3
  11. H HH3 HHH 3  (symmetric)
  12. H HHH 3HH 3
  13. H HHH H3H 3
  14. H HHH HH3 3
  15. H  WWH HHH 3
  16. H WHW HHH 3
  17. H WHH WHH 3
  18. H WHH HWH 3
  19. H WHH HHW 3
  20. H HWW HHH 3
  21. H HWH WHH 3
  22. H HWH HWH 3
  23. H HWH HHW 3
  24. H HHW WHH 3
  25. H HHW HWH 3
  26. H HHW HHW 3
  27. H HHH WWH 3
  28. H HHH WHW 3
  29. H HHH HWW 3
  30. H 3WH HHH W
  31. H H3W HHH W
  32. H HH3 WHH W
  33. H HHH 3WH W
  34. H HHH H3W W
  35. H HHH WWWW
  36. H WWW HHHH W
  37. H  H WWW HH W
  38. H  HH WWW H W
  39. H WHW WHH W
  40. H WHH WWH W
  41. H WWH WHH W (Bebop)
  42. H WWH HWH W
  43. H W H W H W H W  (Diminished,  very symmetric)

 

So where do my Klezmer Bebop    ( A b C d D# e F g# A )  and My  8 Tone Scale    (E F# G G# A# C# D D# E.) fall in?

The Klezmer Bebop scale is  W H W H H H 3 H  rotated  to  H W H W H H H 3 which is scale 16 above.

The other 8 tone scale is W H H W 3 H H H, rotated to H H H W H H W 3 which is scale 26 above.

The standard blues scale  is usually  3 W H H 3 W,  a 6 tone scale.  Starting on A  this is A C D D# E G A.  This Could obviously be fitted into many of the above scales by splitting either the W or 3 intervals.  If You we are playing over an A Dominant 7th chord,  we can add in the  the Major 3  and Major  6th:  C# and F#.   A C C# D D# E F# G A  Or 3 H H H H W H W.  Rotated to H H H H W H W 3  That is 28 above.

November 21, 2011

Expanding Red Hat's Product Security Efforts
I'm rather excited to announce an expansion of Red Hat's product security efforts. I've been tasked with creating a team inside Red Hat to formalize our product security work. There is already a lot of really good work happening inside Red Hat in the security space. Technologies such as SELinux, ExecShield, secure development principals, and hardening in the toolchain have come a long way. However as happens with all decent sized companies, the left hand doesn't always know what the right hand is doing. Rather than letting good work go unnoticed, we're going to start formalizing some of these efforts to leverage what's being done, expand existing efforts into other product areas, and develop new programs.

Some additional efforts I would like to further are areas such as secure design principals, developer security training initiatives, secure coding practices, and security testing.

If you're interested in being a part of this effort, I have a number of open positions scattered around the world, feel free to apply directly or contact me if you have any questions. I'm quite happy to discuss location, so don't let that scare you off.

Software Engineer - Security Best Practices Development
Software Engineer - Tool Development
Software Engineer - New Security Technologies Development
Software Engineer - Code Audit Development
Developer Training

I don't expect any of this to be easy, but nothing worth doing is ever easy. I expect many challenges and rewards to come from this. Red Hat is in a unique and great position to take on such a task. Stay tuned for more updates.

November 20, 2011

Protected: The Truth About Passwords

This post is password protected. You must visit the website and enter the password to continue reading.


November 18, 2011

SELinux versus pam_google_authenticator...
I just became aware of a new PAM, pam_google_authenticator.

It is some kind of One TIme Password tool to allow you to add One Time Passwords to you Linux Login and I guess use your Android phone.

pam_google_authenticator causes login programs to  try and  write to ~/.google_authenticator by default.  SELinux does not like this.  SELinux prevents login programs from writing to random locations in the home directory.  It is usually not a good idea to rely on stuff in the home dir for authorization because the homedir may require authorization to be able to be mounted or decrypted. (kNFS for example).  

I got a bugzilla on sshd not being able to write to ~/.google_authenticator.  One option would be to set the label on the .google_authenticator as ssh_home_t.  I also did some "googling" and found the following entry:
http://code.google.com/p/google-authenticator/wiki/PamModuleInstructions

Comment by phil.may <snip>, Jul 7, 2011

If you are using Fedora and SELinux, you will need to use the right config. The default SELinux policy does not allow the SSH daemon to update the ~/.google_authenticator file.

In Fedora 14 (and possibly other versions) sshd runs under "sshd_t" and can only writelocations with certain SELinux labels. One such label is "var_auth_t" and the default policy sets this label on "/var/run/user/" Therefore, the following config works:

# If the user is NOT in group "otp_users", skip next module
auth [success=1 default=ignore] pam_succeed_if.so user notingroup otp_users
auth       required     pam_google_authenticator.so secret=/var/run/user/${USER}/.google_authenticator
auth       include      password-auth

BTW I have not tried this out on Fedora 16, and am curious if this will work, or does pam_google_authenticator expect the contents of .google_authenticator to survive a reboot.
Vulnerability Acknowledgements for Red Hat online services
When we get notified of a security issue affecting a Red Hat product in advance we give an acknowledgement in the security advisory and in our CVE database.

We've now created a page to give acknowledgements to the companies and individuals that report issues in our online services, such as finding a cross-site scripting flaw in a Red Hat web site, or a vulnerability in OpenShift.

November 17, 2011

Customizing the Kiosk OS.
I receve a decent amount of interest about the kiosk spin, but I have never formalized it as a fedora spin.  The reason for this is almost everyone who looks at it, likes the idea but they need to customize it, in one way or another.  

My vision of the Kiosk Operating system was that it was readonly and periodically an admin would recut/rebuild a newer version and then redestribute it to his machines.  It is fairly easy to build your own image.  Just download the kiosk kickstart file (kiosk.ks), make some customization and rebuild your ISO file using the livecd-tools.  The last step would be to install it to your favorite medium, USB Sticks or DVD. 

I recently received an email that requested:

"I have downloaded kiosk just this afternoon and tried on my laptop: as I have been requested for such a spin in our city library for eight computers, how can I build a spin with language/keyboard set as Italian??? (the standard procedure to change settings/Logout/login seems not to be working..) "

Here is how I would go about building the Italian version of the Kiosk Operating System.

On the currently released version of Fedora.  As I write this blog, we are at Fedora 16.  Login as root and and follow this procedure.

You are going to build the Kiosk Operating System using the spin-kickstarts, so we need to install the sortware.

# yum install spin-kickstarts livecd-tools
# cd /usr/share/spin-kickstarts


Make sure you have the latest kiosk.ks file from my people page. http://people.fedoraproject.org/~dwalsh/SELinux/kiosk/kiosk.ks

# rm -f kiosk.ks*
# wget http://people.fedoraproject.org/~dwalsh/SELinux/kiosk/kiosk.ks


Change the default language within the kickstart file.   You can use your favorite editor to do this, and modify "lang" line.  I will just use a sed command.

# sed -i 's/en_US.UTF8/it_IT.UTF-8/g' kiosk.ks

Now you can build a new kiosk image.  Replacing the name of the livecd with your own content.

# livecd-creator -t MYLIBRARY -f MYLIBRARY -c kiosk.ks --cache=/var/cache/kiosk

Now go get a cup of coffee since this will take a long while, maybe a half hour. 
When it finishes, you will have an ISO image named MYLIBRARY.iso.  You need to install the iso ont a dvd or to a usb stick using livecd-iso-to-disk.

# livecd-iso-to-disk --totaltimeout 1  ./MYLIBRARY.iso /dev/sdb1

Remove your USB stick and attempt a boot a machine using it.

Of course if you want to add some less then free packages to your kiosk operating system, you would edit the kickstart file and add your alternative repositories.

For additional information on building livecd please use:

http://fedoraproject.org/wiki/How_to_create_and_use_Live_USB

And on using kickstart files.

http://fedoraproject.org/wiki/Anaconda/Kickstart

November 15, 2011

REST and diffs

Chatting with co-worker Emily on the bus last night about REST, Git, and IPA lead to an epiphany of sorts. First, a little background.

The term REST (Representational State Transitions) comes from the original researchers attempt to reverse engineer the success of the Web. Moving backwards through time, we come to the original Tim Berners-Lee goal of developing a document sharing protocol. As such, the verb “PUT” maps to the changes of state: if you want to change a document, you PUT the new version of it to its URL.

However, the success of the web has not been based on that side of the HTTP protocol. Success has been based on using GET to fetch things and POST to change them. POST has been successful in that it provides two things you can’t get from the PUT semantics.

First, you can create a new identifier. With PUT, you have to know the URL that you are putting the document to. With POST, the Identifier is created for you.

Second, with PUT, you transmit the entire state of the document, but with POST you can send just small changes.

WebDAV was the first attempt I cam across to implement the whole HTTP protocol as designed. It allowed change the state of the server using PUT. Subversion developers called this “WebDA” as it left of the V–Versioning.

When Linus Torvalds was told that SVN was CVS fixed, his response stated that CVS, and by extension Subversion, we fundamentally flawed. Git does local revision control as well as remote revision control.

One thing that Git and SVN have in common, however, is the Atomic Commit. When you make changes to the state of the repository, you may modify more than one file. If the Commit is not Atomic, changes from two people might get intermingled, and the repository cannot be restored to a stable state. With an Atomic commit, the client sends the sets of changes to all of the files, and they get applied completely before any other changes are applied. A user can view the set of changes after the fact. In SVN, this is shown by revision number, in Git by the Hash of the commit.

So, moving back to REST, does it really make sense to focus on the PUT operator? It can only be used to add something that already has an identifier, it has to change an entire document, and it can’t change more than a single document.

Transactional databases have the concept of a log. A transaction log is a file that you always append to. The only time you delete from the transaction log is if you roll back an incomplete transaction. Once the commit record has been written to the log, the transaction is immutable. Git follows this rule, as do many messaging system. Changing the state of a system then can be viewed as sending the requested changes to a single resource, and allowing them to succeed or fail as a unit. It we allow the definition of PUT to contain only the change to the state of the system, we can PUT to a single URL and transform system wide state.

One advantage to using PUT semantics is that PUT is defined to be Idempotent. If you PUT the same value multiple times, the ensuing state of the system is only transformed once, and the second and succeeding PUTs do not change the system. Git commits are likewise idempotent…well, succeeding attempts to post a commit will fail, but the server will stay in the same state, so it is safe to do multiple times….not quite the same thing, but close enough. The reality is that each change to a git server is uniquely identified by its contents, and all of the changes, all of the indexed content of a git server is immutable. What changes are the branches, the named entry points into the system.

Thus a git based system could allow you to post a file to http://git.projectname.org/repository/e051de5d18522b1f9e0389dda68628a5401fa681 and, assuming that the file you posted matched the SHA256 fingerprint of the file, it would be accepted. So PUT might make sense in that perspective. But it would not a be a human interaction that did all for that, and the success of the Web is based on the Human readable scheme for URLs and the resources they reference.

So the question then is this: does what we now know from distributed revision control systems undermine the RESTful approach? I’d suspect that REST is the narrow center of the spectrum for updating changes on a server. We want to be able to manage state at the entire document level, at the Delta of a document, and via Delta of the overall system. You can represent these last two aspects with a RESTful architecture, but you have to so deliberately by designing them into your REST scheme. However, conceptually, they are outside the scope of the core HTTP approach.

November 11, 2011

When do we push most advisories?
We pushed an update to Flash Player for Red Hat Enterprise Linux Supplementary today, on a Friday, because it fixed Critical vulnerabilities. But we try not to push updates on a Friday unless they are critical and already public.

So let's take a look at the most common times and days we push advisories for Red Hat Enterprise Linux 4, 5, and 6 (including Supplementary) using a heatmap:

heatmap

The more advisories pushed for a given date and hour, the darker that section of the graph is. So the most popular times for pushing advisories are Tuesdays at 10am and 2pm Eastern US time, Fridays are pretty light for pushes, and there was nothing during the weekends. The spread of the graph shows that we push advisories when they are ready, rather than waiting to a fixed day and time, in order to reduce the risk to users.

All the data used to create this graph is available as part of our public metrics. Thanks to Sami Kerola for the R code from which I based my graph generation.

November 07, 2011

Tomcat Simple Bind to FreeIPA

An Identity Management Solution is no good if you can’t use it from your server applications.  Here are the steps you can go through to get your server working along side FreeIPA.

LDAP Approch  using Basic Auth:

The JNDI info you need can be found in: /etc/ipa/default.conf

 

host=ipa-server-3.ayoung.boston.devel.redhat.com
basedn=dc=ipa-server-3,dc=ayoung,dc=boston,dc=devel,dc=redhat,dc=com
realm=IPA-SERVER-3.AYOUNG.BOSTON.DEVEL.REDHAT.COM
domain=ayoung.boston.devel.redhat.com
xmlrpc_uri=https://ipa-server-3.ayoung.boston.devel.redhat.com/ipa/xml
ldap_uri=ldapi://%2fvar%2frun%2fslapd-IPA-SERVER-3-AYOUNG-BOSTON-DEVEL-REDHAT-COM.socket
enable_ra=True
ra_plugin=dogtag
mode=production

 

This should be specified in the IPA server as well as any enrolled IPA client.  Notice also the ldap_uri which should give you the information to connect, as well as the host line which tells you the DNS name of IPA server:  The most important value is the basedn.

Minor complaint:  using an equal sign as the separator between the key and value in this file makes it harder to script than it should be.

I do this to pull out the value for the basedn:

export  IPA_BASE_DN=`grep basedn /etc/ipa/default.conf | sed 's/basedn=//'`

To look up the set of groups you are assigned, you can use a simple bind where you are prompted for your password:

ldapsearch -W -D "uid=$USER,cn=users,cn=accounts,$IPA_BASE_DN" \
           -b "cn=groups,cn=accounts,$IPA_BASE_DN"  \
              "(member=uid=$USER,cn=users,cn=accounts,$IPA_BASE_DN)"

You can replace $USER with ‘Admin’ if you are just getting set up.  LDAP Configuration means that it finds the host  without you having to explicitly specify it.

To set up Tomcat to use LDAP, I tested things out using the manager app that ships with tomcat6. First, add the following stanza to the server.xml file for your tomcat instance. I put it right below the UserDatabase Realm that should be in there.

      <realm classname="org.apache.catalina.realm.JNDIRealm" connectionurl="ldap://localhost:389" rolebase="cn=groups,cn=accounts,dc=ipa-server-3,dc=example,dc=com" rolename="cn" rolesearch="(member={0})" userpattern="uid={0},cn=users,cn=accounts,dc=ipa-server-3,dc=example,dc=com">

I’ll use the classis example.com as the basis for the JDNI lookups.

I modified the web application by changing/var/lib/tomcat6/webapps/manager/WEB-INF/web.xml so that it use the Realm as defined here:

    BASIC
    org.apache.catalina.realm.JNDIRealm

In this solution, user groups are used for the roles. Create a group named manager-gui and add it to yourself, or the user that you want to have access to the WebApp. Now Browse http://yourserver:8080/manager/html and authenticate using the User credentials for IPA.

I’d like to point out that this solution does the Bind as the user, not as an administrator. This means that this session is confined by the access control (ACI) enforced by the Directory Server.

This gets you in the door, and will let you test that the LDAP and JNDI approach using Basic Authentication and Simple Bind works.  This is fine for testing and development, but I would recommend against it for production.  We can do better. In an upcoming article, I show how do the same type of authentication, but using Kerberos credentials and the GSSAPI.

October 27, 2011

Certificates for Web SSO

Kerberos is a single sign on solution. AFAICT, it is the only one that solves the problem completely: You confirm that you are who you say you are, and the remote side confirms that it is who you think it is. It doesn’t work over he public internet only due to the fact that most corporate firewalls block the ports it needs.  So  we want to be able to do Kerberos, or its equivalent from the browser.

There are two approaches:  we could try to do it in the context of existing technology, or we could extend the browser.  First a really quick overview.

When using Kerberos you do two things:

1. Go to a centralized location and authenticate yourself

2.  Use something from that centralized place to authenticate yourself to some other service.

Yeah, it is  overly simplified.  I’ll get into more details as I go.

OK:  so this kind of maps to the web single sign on technologies out there.  For example, OAuth and OpenID both work through redirects to a central auth server.  After authenticating yourself, you then receive a redirect back, but this time with an addition value that confirms that the centralized server recognized you.

Why are these not the same?  The devil is in the details.

First off,  when you go to the auth server in Kerberso (called the Key DIstribution center, or KDC)  the  trust is mutual.  The KDC send you something encrypted with your password.  Meaning the KDC has to know your password.  Thus,   you know that the KDC is really the right auth server, or your password won’t work.   WebSSO  doesn’t provide this.  IN fact, when you get redirected to, say, yahoo,  and prompted for a UID and password, you are potentially going to receive a phishing attack.  You provide your auth credentials to the remote server, and you get your token, but it could be configured to accept anything, and to just record your password.

Of course, the fact that you are authenticating with Basic Auth (UserID and Password)  is pretty bad in its own right.

Kerberos uses the Password, but it doesn’t pass across the network.  There is a big difference.  What does back and forth allows you and the KDC to authenticate, but if either side attempts to cheat, it gains no more information than it had before.

The nonce/cookie/token/whatever that you get from a web SSO solution is just a random number.  In most OpenID solutions, the Auth provider does not know anything about the services that it provides auth for, so it can’t say “these are legitimate” and, more importantly,  “these are not legitimate.”  It is easy to extend the systems to authenticate the requester, but it isn’t done baseline by the protocols.

In Kerberos, you get a  ticket specific for some service.  If the service you want the ticket for is unknown to the KDC, you don’t get a service ticket.

OK, so how could we make this work with current technology?  The first step is certificates.

The Auth provider should present to you a certificate, signed by a trusted third party.  Thus, you know the auth provider is who it says it is.  This is necessary but not sufficient.  An attacker can present a certificate that says “I am me”  but you still have to check that  you are talking to who you think you are talking.  Thus, you need to direct which URL provides your auth server, not the requesting service.  This is requirement #1.  Once you auth against your ID server, it should provide you with a certificate with a short lifetime.  This is the certificate that you would use for the remote service.  This is requirement #2.

Much of this can be short circuited.  If your machine has a client certificate, you can use that to authenticate to the remote server without having to go back to the auth server.  Its SSL Certificate can confirm its identity to you.  Since both certificates are signed by trusted third parties, both are confident that they are accurate.  The question, then, is why don’t more people do this?

Cost.  Getting a server that can sign other certificates is trivial.  There is a great Open Source  CA implementation that I happen to work on:  However, getting your CA certificate signed by one of the authorities in the Mozilla  or Internet Explorer known CA list costs big bucks.  $10,000 was one price that I heard quoted.  Lets say it is a million.  The fact is that it costs something significant.

There are other issues.   Probably the most significant is that there is no session timeout.  Once you have a certificate, you are signed in to any site that accepts that certificate.  No user interaction is required.  Ideally, a certificate based approach would be linked with a short, non-cacheable token like “enter the first letter of the day of week followed by a 4 digit PIN”.

User certificates are complicated to administer in the browser.  For example, to remove a certificate in the current version of Mozilla, You have to know to go to “Edit->Preferences->Advanced->Encryption->View Certificate->Your Certificates.  Also, if you accidentally use the wrong one to try and log in to a site, the only way to rectify this problem is to close the browser and go back to the site.  User certificates typically have long lifespans:  A year to two years is not uncommon.  If a certificate times out,  getting a new one can be tricky.

But there is a lot of technology to make it easy, too.  OK a little more crypto background:  A certificate is really just a decorated public key.  If you do SSH, you probably have had to generate a key pair, and then copied the key over to the remote site.  A Certificate takes that public key,  and a trusted service cryptographically ensures that the key is really from you.  So to get a certificate, you need to first generate key pair, then generate a signing request (CSR), send that in to get approved and signed, and get back the certificate.

All of this can be done by the browser.  Mozilla has a internal database that holds your password, and that holds your private keys and  certificates. It is (probably) in  ~/.mozilla/firefox/*.default/cert8.db.

You can see what is in there with  certutil -d ~/.mozilla/firefox/*.default -L

So the mechanisms all exist to do web single sign on with Certificates, but they are painful.  So we have two options:  build out the mechanisms for Certificate web SSO, or make Kerberos SSO  work through the current technology.

To do Kerberos SSO,  here’s what you would need.

Make it possible to get a Ticket granting ticket (TGT)  via  the web browser from the Key distribution Centery (KCD).  This means first setting up an SSL connection between  the browser and the KDC< and then using port 443.  The browser could do a post to the KDC, to request a ticket, buyt the most important part is that the browser pops up a dialog that is unmistakably the enter your Kerberos password/kinit  dialog, and not a phishing attempt.  The browser needs to be involved, and should probably have a spot on the border of the browser that is not in the client area.  This is a tricky design issue, and will require some smarts.

The mechanism to get a service ticket is pretty similar to getting the TGT, but could probably be hidden from the end user.

There should probably be a handful of notifications that are visible to the user.  Getting a TGT requires interaction, but anytime something requests a new service ticket, the user should probably be notified, to prevent requests happening behind his/her back.

One shortcoming with current Keberos implementations is that they only allow one TGT and KDC  at a time.  This limitation is well understood and discussed, and will need to be alleviated prior to Kerbers really being a viable SSO alternative.

October 25, 2011

Open Source how do I love thee, let me count the ways.
Yesterday I got contacted by Red Hat Support about a problem we had in libselinux.  If you are setting up confined users you can use the semanage login command to setup a group of linux users to be assigned to a confined user type.

# semanage login -a -s staff_u -r s0-s0:c0.c1023 %wheel

This command would cause all linux users in the wheel group to login as the staff_u SELinux user.  Well we had a bug in getseuserbyname function in libseliunux.  When you login to a system the pam_selinux module uses this function to figure out which SELinux user should be used for your UID.  There was a bug where we were not allocating enough memory for reading the entire group file contents.  Basically if the number of users within a group was too large, the library would stop reading.  

A customer of ours found the problem and reported it.  

Now the reason I love Open Source...

The customer did not stop there.  They downloaded our source, found the problem, built a patch and attached it to the bug report.  So all I had to do was apply the patch and start the errata process.   This is the type of stuff that can't happen in a closed source system, and is why Open Source is better...

Open source is like The Elves and the Shoemaker, just don't tell my boss.  :^)

October 21, 2011

10 things you probably did not know about SELinux.. #8 How to remove a port from a port type?
How do you remove a network port from a network port type?

First a little explanation.  Linux contains 65536 network ports for both UDP and TCP.
SELinux uses types to group network ports together.  If you want to see a listing of the port types on the system you can execute:

semanage  port -l
SELinux Port Type              Proto    Port Number

afs_bos_port_t                 udp      7007
afs_client_port_t              udp      7001
afs_fs_port_t                  tcp      2040
afs_fs_port_t                  udp      7000, 7005
...


Then we write rules in SELinux like

allow httpd_t http_port_t : tcp_socket name_bind ;

This rules says the apache process can execute the bind command using any port that is currently labeled http_port_t.

# semanage  port -l | grep http_port_t
http_port_t                    tcp      80, 443, 488, 8008, 8009, 8443


Now a fairly common question that gets asked is, can I remove these ports.   IE I do not want to allow apache to bind to port 8008.

How would I do this?

The simplest thing to do is to redefine port 8008 as a different port type that httpd can not bind to. 

The default port type for all unassigned ports  > 1024 is unreserved_port_t or ephemeral_port_t (Fedora 16)

# semanage  port -l | grep ^unreserved_port_t
unreserved_port_t              tcp      1024-32767, 61001-65535
unreserved_port_t              udp      1024-32767, 61001-65535
# semanage  port -l | grep ^ephemeral_port_t
ephemeral_port_t               tcp      32768-61000
ephemeral_port_t               udp      32768-61000


Note SELinux will use a more specific port type if the port has been defined, for example when the kernel sees tcp port 8008, it will use http_port_t rather then unreserved_port_t. 

But the admin can override this by adding his own port definition.

# semanage port -m -t unreserved_port_t -p tcp 8008

To prove this worked, I tested using apache.

# sed -i 's/Listen 80/Listen 8008/g' /etc/httpd/conf/httpd.conf
# semanage  port -m -t unreserved_port_t -p tcp 8008
# service httpd restart
Restarting httpd (via systemctl):  Job failed. See system logs and 'systemctl status' for details.  [FAILED]
# semanage port -d -p tcp 8008
# service httpd restart
Restarting httpd (via systemctl):                          [  OK  ]


NOTE:

Be careful doing this, because you have just changed the definition of http_port_t for ALL domains, not just the httpd_t domain.   Meaning if you were running firefox with a sandbox_web_t sandbox on the same machine, the firefox would no longer be able to connect to port 8008, because sandbox_web_t is only allowed to connect to http_port_t and 8008 is no longer defined as 8008.

October 19, 2011

How should you disable IPV6?
Blogging twice in the same day, a new record...

Lots of people are out there disabling IPV6, and when you do invariably you get a flood of AVC messages about different confined domains asking the kernel to load the kernel module net-pf-10.   

type=AVC msg=audit(10/18/11 23:40:10.233:978087) : avc:  denied  { module_request } for  pid=32265 comm=pickup kmod="net-pf-10" scontext=system_u:system_r:postfix_pickup_t:s0 tcontext=system_u:system_r:kernel_t:s0 tclass=system

Now I am not recommending that you enable or disable IPV6, but if you do want to disable it and run with SELinux turned on, please read the following:

Eric Paris reports

"I believe the networking kernel community recommends (and it will shut up these AVCs) that IPv6 be disabled by:

echo 1 > /proc/sys/net/ipv6/conf/all/disable_ipv6

It still loads the module but unhooks almost all of the calls into the module. (apparently the IPv6 module has become so ingrained in the kernel that a number of other things, like certain firewall modules, require it. I didn't design it, I'm just telling it how it is) "


We recommend that you do not disable the ipv6 module but add

net.ipv6.conf.all.disable_ipv6 = 1

to /etc/sysctl.conf

And the AVC messages should go away.

The setroubleshoot plugin in Fedora reflects this info.

Making a domain “unconfined”

Dan describes other cool SELinux stuff.