NSS commands and how to.

Posted by william in Random | Leave a comment

I have collated some knowledge on how to use NSS and it’s tools for some general purpose usage, including mod_nss.

Much of this is just assembling the contents of the certutil documentation.

In this I have NOT documented the process of deleting certificates, changing trust settings of existing certificates or changing key3.db passwords.

Create a new certificate database if one doesn’t exist (You should see key3.db, secmod.db and cert8.db if one exists).

certutil -N -d .

List all certificates in a database

certutil -L -d .

List all private keys in a database

certutil -K -d . [-f pwdfile.txt]

I have created a password file, which consists of random data on one line in a plain text file. Something like below would suffice. Alternately you can enter a password when prompted by the certutil commands. If you wish to use this for apache start up, you need to use pin.txt

echo "soeihcoraiocrthhrcrcae aoriao htuathhhohodrrcrcgg89y99itantmnomtn" > pwdfile.txt
echo "internal:soeihcoraiocrthhrcrcae aoriao htuathhhohodrrcrcgg89y99itantmnomtn" > pin.txt

Create a self signed certificate in your database. Note the -n, which creates a “nickname” (And should be unique) and is how applications reference your certificate and key. Also note the -s line, and the CN options. Finally, note the first line has the option -g, which defines the number of bits in the created certificate.

certutil -S -f pwdfile.txt -d . -t "C,," -x -n "Server-Cert" -g 2048\
-s "CN=nss.dev.firstyear.id.au,O=Testing,L=Adelaide,ST=South Australia,C=AU"
certutil -S -f pwdfile.txt -d . -t "C,," -x -n "Server-Cert2" \
-s "CN=nss2.dev.firstyear.id.au,O=Testing,L=Adelaide,ST=South Australia,C=AU"

To configure mod_nss, you should have a configuration similar to below – Most of this is the standard nss.conf that comes with mod_nss, but note the changes to NSSNickname, and the modified NSSPassPhraseDialog and NSSRandomSeed values. Yes, mod_nss supports SNI. There is documentation on the NSSCipherSuite that can be found by running “rpm -qd mod_nss”. Finally, make sure that apache has read access to the database files and the pin.txt file. If you leave NSSPassPhraseDialog as “builtin”, you cannot start httpd from systemctl. You must run apachectl so that you can enter the NSS database password on apache startup.

LoadModule nss_module modules/libmodnss.so
Listen 8443
NameVirtualHost *:8443
AddType application/x-x509-ca-cert .crt
AddType application/x-pkcs7-crl    .crl
NSSPassPhraseDialog  file:/etc/httpd/alias/pin.txt
NSSPassPhraseHelper /usr/sbin/nss_pcache
NSSSessionCacheSize 10000
NSSSessionCacheTimeout 100
NSSSession3CacheTimeout 86400
NSSEnforceValidCerts off
NSSRandomSeed startup file:/dev/urandom 512
NSSRenegotiation off
NSSRequireSafeNegotiation off
<VirtualHost *:8443>
ServerName nss.dev.firstyear.id.au:8443
ServerAlias nss.dev.firstyear.id.au
ErrorLog /etc/httpd/logs/nss1_error_log
TransferLog /etc/httpd/logs/nss1_access_log
LogLevel warn
NSSEngine on
NSSCipherSuite +rsa_rc4_128_md5,+rsa_rc4_128_sha,+rsa_3des_sha,-rsa_des_sha,-rsa_rc4_40_md5,-rsa_rc2_40_md5,-rsa_null_md5,-rsa_null_sha,+fips_3des_sha,-fips_des_sha,-fortezza,-fortezza_rc4_128_sha,-fortezza_null,-rsa_des_56_sha,-rsa_rc4_56_sha,+rsa_aes_128_sha,+rsa_aes_256_sha
NSSProtocol SSLv3,TLSv1
NSSNickname Server-cert
NSSCertificateDatabase /etc/httpd/alias
<Files ~ "\.(cgi|shtml|phtml|php3?)$">
    NSSOptions +StdEnvVars
</Files>
<Directory "/var/www/cgi-bin">
    NSSOptions +StdEnvVars
</Directory>
</VirtualHost>
<VirtualHost *:8443>
ServerName nss2.dev.firstyear.id.au:8443
ServerAlias nss2.dev.firstyear.id.au
ErrorLog /etc/httpd/logs/nss2_error_log
TransferLog /etc/httpd/logs/nss2_access_log
LogLevel warn
NSSEngine on
NSSCipherSuite +rsa_rc4_128_md5,+rsa_rc4_128_sha,+rsa_3des_sha,-rsa_des_sha,-rsa_rc4_40_md5,-rsa_rc2_40_md5,-rsa_null_md5,-rsa_null_sha,+fips_3des_sha,-fips_des_sha,-fortezza,-fortezza_rc4_128_sha,-fortezza_null,-rsa_des_56_sha,-rsa_rc4_56_sha,+rsa_aes_128_sha,+rsa_aes_256_sha
NSSProtocol SSLv3,TLSv1
NSSNickname Server-Cert2
NSSCertificateDatabase /etc/httpd/alias
<Files ~ "\.(cgi|shtml|phtml|php3?)$">
    NSSOptions +StdEnvVars
</Files>
<Directory "/var/www/cgi-bin">
    NSSOptions +StdEnvVars
</Directory>
</VirtualHost>

Create a self signed CA (In a different database from the one used by httpd.)

certutil -S -n CAissuer -t "C,C,C" -x -f pwdfile.txt -d . \
-s "CN=ca.nss.dev.firstyear.id.au,O=Testing,L=Adelaide,ST=South Australia,C=AU"

Create a certificate in the same database, and sign it.

certutil -S -n Test-Cert -t ",," -c CAissuer -f pwdfile.txt -d . \
-s "CN=test.nss.dev.firstyear.id.au,O=Testing,L=Adelaide,ST=South Australia,C=AU"

Test the new cert for validity as an SSL server.

certutil -V -d . -n Test-Cert -u V

View the new cert

certutil -L -d . -n Test-Cert

View the cert in ASCII form (This can be redirected to a file for use with openssl)

certutil -L -d . -n Test-Cert -a

In a second, seperate database to your CA.

Create a new certificate request

certutil -d . -R -o nss.dev.firstyear.id.au.csr -f pwdfile.txt \
-s "CN=nss.dev.firstyear.id.au,O=Testing,L=Adelaide,ST=South Australia,C=AU"

On the CA, review the CSR you have recieved.

/usr/lib[64]/nss/unsupported-tools/derdump -i /etc/httpd/alias/nss.dev.firstyear.id.au.csr
openssl req -inform DER -text -in /etc/httpd/alias/nss.dev.firstyear.id.au.csr

On the CA, sign the CSR.

certutil -C -d . -f pwdfile.txt -i /etc/httpd/alias/nss.dev.firstyear.id.au.csr \
-o /etc/httpd/alias/nss.dev.firstyear.id.au.crt -c CAissuer

Export the CA public certificate

certutil -L -d . -n CAissuer -r > ca.crt

Import the CA public certificate into the requesters database.

certutil -A -n "CAcert" -t "C,," -i /etc/pki/CA/nss/ca.crt -d .

Import the signed certificate into the requestors database.

certutil -A -n "Server-cert" -t ",," -i nss.dev.firstyear.id.au.crt -d .

Using openSSL create a server key, and make a CSR

openssl genrsa -out server.key 2048
openssl req -new -key server.key -out server.csr

On the CA, review the CSR.

openssl req -inform PEM -text -in server.csr

On the CA, sign the request. Note the use of -a that allows an ASCII formatted PEM input, and will create and ASCII PEM certificate output.

certutil -C -d . -f pwdfile.txt -i /root/server.csr -o /root/server.crt -a -c CAissuer

Import an openSSL generated key and certificate into an NSS database.

openssl pkcs12 -export -in server.crt -inkey server.key -out server.p12 -name Test-Server-Cert
pk12util -i /root/server.p12 -d . -k pwdfile.txt

Export a secret key and certificate from an NSS database for use with openssl.

pk12util -o /root/server-export.p12 -d . -k pwdfile.txt -n Test-Server-Cert
openssl pkcs12 -in server-export.p12 -out file.pem -nodes

Note that file.pem contains both the CA cert, cert and private key. You can view just the private key with:

openssl pkcs12 -in server-export.p12 -out file.pem -nocerts -nodes

Or just the cert and CAcert with

openssl pkcs12 -in server-export.p12 -out file.pem -nokeys -nodes

You can easily make ASCII formatted PEM from here.

Finally, these commands all use the old DBM formatted NSS databases. To use the new “shareable” sqlite formatting, follow the steps found from this blog post.

Slow mac sleep

Posted by william in Random | Leave a comment

Recently, I have noticed that my shiny macbook pro 8,2, with 16GB of ram and it’s super fast intel SSD, was taking quite a long time to sleep – near 20 seconds to more than a minute in some cases. This caused me frustration to no avail.

However, recently, in an attempt to reclaim disk space from the SSD, in the form of a wasted 16GB chunk in /private/var/vm/sleepimage . This lead me to read the documentation on pmset.

hibernate mode is set to 3 by default – this means that when you close the lid on your MBP, it dumps the contents of ram to sleepimage, and then suspends to ram. This means in the case that you lose power while suspended, you can still restore your laptop state safely. I don’t feel I need this, so I ran the following.

sudo pmset -a hibernatemode 0
sudo rm /private/var/vm/sleepimage

Now I have saved 16GB of my SSD (And read write cycles) and my MBP sleeps in 2 seconds flat.

Samba 4 Internal DNS use

Posted by william in Random | Leave a comment

It took me a while to find this in an email from a mailing list.

To use the internal DNS from samba4 rather than attempting to use BIND9 append the line “–dns-backend=SAMBA_INTERNAL” to your provision step.

Mod_Selinux with Django

Posted by william in Random | Leave a comment

Django with mod_selinux

The mod_selinux module allows you to confine a spawned apache process into a specific selinux context. For example, you can do this via virtual hosts, or by LocationMatch directives.

Part of my curiosity wanted to see how this works. So I made up a small django application that would tell you the selinux context of an URL.

Install mod_selinux first

yum install mod_selinux mod_wsgi

Now we create a VirtualHost that we can use for the test application


NameVirtualHost *:80

<VirtualHost *:80>
    ServerAdmin william@firstyear.id.au
    DocumentRoot /var/empty
    ServerName 172.16.209.150

    <LocationMatch /selinux/test/c2>
    selinuxDomainVal	*:s0:c2
    </LocationMatch>
    <LocationMatch /selinux/test/c3>
    selinuxDomainVal	*:s0:c3
    </LocationMatch>

    #Alias /robots.txt /usr/local/wsgi/static/robots.txt
    #Alias /favicon.ico /usr/local/wsgi/static/favicon.ico

    AliasMatch ^/([^/]*\.css) /var/www/django_base/static/styles/$1

    Alias /media/ /var/www/django_base/media/
    Alias /static/ /var/www/django_base/static/

    <Directory /var/www/django_base/static>
    Order deny,allow
    Allow from all
    </Directory>

    <Directory /var/www/django_base/media>
    Order deny,allow
    Allow from all
    </Directory>

    WSGIScriptAlias / /var/www/django_base/django_base/wsgi.py

    <Directory /var/www/django_base/scripts>
    Order allow,deny
    Allow from all
    </Directory>
</VirtualHost>

We also need to alter /etc/httpd/conf.d/mod_selinux.conf to have MCS labels.

selinuxServerDomain     *:s0:c0.c100

And finally, download the test application tar ball, and unpack it to /var/www

cd /var/www
tar -xvzf django_selinux_test.tar.gz

Now, navigating to the right URL will show you the different SELinux contexts

http://localhost/selinux/test/test

Hello. Your processes context is [0, 'system_u:system_r:httpd_t:s0:c0.c100']

http://localhost/selinux/test/c2

Hello. Your processes context is [0, 'system_u:system_r:httpd_t:s0:c2']

http://localhost/selinux/test/c3

Hello. Your processes context is [0, 'system_u:system_r:httpd_t:s0:c3']

The best part about this is that this context is passed via the local unix socket to sepgsql – meaning that specific locations in your Django application can have different SELinux MCS labels, allowing mandatory access controls to tables and columns. Once I work out row-level permissions in sepgsql, these will also be available to django processes via this means.

Example of why you want this.

You have a shopping cart application. In your users profile page, you allow access to that URL to view / write to the credit card details of a user. In the main application, this column is in a different MCS – So exploitation of the django application, be it SQL injection, or remote shell execution – the credit cards remain in a separate domain, and thus inaccessible.

Additionally, these MCS labels are applied to files uploaded into /media for example, so you can use this to help restrict access to documents etc.

SEPGSQL – How to Fedora 16 / 17

Posted by william in Random | Leave a comment

First, we install what we will be using.

yum install postgresql postgresql-server postgresql-contrib

First, we want to setup sepgsql. sepgsql.so is part of the contrib package. These modules are installed on a per database basis, so we need to initdb first

postgresql-setup initdb

Edit vim /var/lib/pgsql/data/postgresql.conf +126

shared_preload_libraries = 'sepgsql'            # (change requires restart)

Now, we need to re-label all the default postgres tables.

su postgres
export PGDATA=/var/lib/pgsql/data
for DBNAME in template0 template1 postgres; do postgres --single -F -c exit_on_error=true $DBNAME /dev/null; done
exit

Now we can start postgresql.

systemctl start postgresql.service

Moment of truth – time to find out if we have selinux contexts in postgresql.

# su postgres
# psql -U postgres postgres -c 'select sepgsql_getcon();'
could not change directory to "/root"
                    sepgsql_getcon
-------------------------------------------------------
 unconfined_u:unconfined_r:unconfined_t:s0-s0:c0.c1023
(1 row)

We can create a new database. Lets call it setest. We also add an apache user for the django threads to connect to later. Finally, we want to setup password authentication, and change ownership of the new setest db to apache.

createdb setest
createuser
Enter name of role to add: apache
Shall the new role be a superuser? (y/n) n
Shall the new role be allowed to create databases? (y/n) n
Shall the new role be allowed to create more new roles? (y/n) n
psql -U postgres template1 -c "alter user apache with password 'password'"
psql -U postgres template1 -c "alter user postgres with password 'password'"
psql -U postgres template1 -c "alter database setest owner to apache"

Now we change our auth in postgres to be md5 in the file $PGDATA/pg_hdb.conf

# "local" is for Unix domain socket connections only
local   all             all                                     md5
# IPv4 local connections:
host    all             all             127.0.0.1/32            md5
# IPv6 local connections:
host    all             all             ::1/128                 md5
systemctl restart postgresql.service

Now you should be able to login in with a password as both users.

# psql -U postgres -W
Password for user postgres:
psql (9.1.3)
Type "help" for help.

postgres=#
# psql -U apache -W setest
Password for user apache:
psql (9.1.3)
Type "help" for help.

setest=#

Lets also take this chance, to take a look at the per column and per table selinux permissions.

psql -U postgres -W setest -c "SELECT objtype, objname, label FROM pg_seclabels WHERE provider = 'selinux' AND  objtype in ('table', 'column')"

To update these

SECURITY LABEL FOR selinux ON TABLE mytable IS 'system_u:object_r:sepgsql_table_t:s0';

See also

This is very useful, especially if combined with my next blog post ….