CoSign
HOWTO: I found it difficult to install CoSign 2.0.2a because the documentation contains inaccuracies, and because it can be hard to debug configuration errors. Here's a working test configuration:
CoSign is composed of 3 main parts:
- filter: this is mod_cosign, allowing Apache to automatically check the user's CoSign cookie
- cgi: cosign.cgi and logout.cgi, for initial login and full logout
- cosignd: the daemon that centralises authentication sessions, can be called from different computers where filter and cgi are installed
Compilation and Installation
I'm using Apache2 here. Let's also try to use FHS-compliant paths.
Dependencies as Debian packages:
aptitude install build-essential apache2-prefork-dev openssl-dev
./configure --enable-apache2=/usr/bin/apxs2 \ --prefix=/var/lib/cosign \ --sbindir=/usr/local/sbin \ --mandir=/usr/local/share/man \ --with-filterdb=/var/lib/cosign/filter \ --with-cosigndb=/var/lib/cosign/daemon \ --with-cosignconf=/etc/cosign.conf \ --with-cosigncadir=/etc/cosign/certs/CA \ --with-cosigncert=/etc/cosign/certs/cert.pem \ --with-cosignkey=/etc/cosign/certs/key.pem
TODO: use /usr/lib and /usr/share appropriately, also allowing using the standard --prefix=/usr/local. Use FHS-compliant /usr/lib/cosign/cgi-ssl
Old versions of apxs (eg. Debian Sarge's) may not provide the libapr include path, resulting in lengthy compilation errors. In this case, provide it manually by prexifing the configure call with a CFLAGS variable:
CFLAGS=-I/usr/include/apr-0 ./configure --enable-apache2=...
Next:
make everything \ && sudo make install-all \ && sudo invoke-rc.d apache2 stop && sleep 1 && sudo invoke-rc.d apache2 start
# mod_cosign dir mkdir -p -m 750 /var/lib/cosign/filter chown www-data: /var/lib/cosign/filter # cosignd dir mkdir -p -m 750 /var/lib/cosign/daemon useradd cosign chown cosign /var/lib/cosign/daemon
# Copy customizable files somewhere else # so they're not overwritten by an unfortunate 'make install'.. cp -a /var/lib/cosign/templates /var/lib/cosign/templates-local cp -a /var/lib/cosign/html /var/lib/cosign/html-local cp -a /var/lib/cosign/services /var/lib/cosign/services-local
Apache2 configuration
/etc/apache2/sites-available/default:
# Automatically added in /etc/apache2/httpd.conf by 'make install-all' (via apxs2
)
LoadModule cosign_module /usr/lib/apache2/modules/mod_cosign.so
NameVirtualHost *:80
NameVirtualHost *:443
# TLS VirtualHost 'cause CoSign requires https login
<VirtualHost *:443>
SSLEngine On
SSLCertificateFile /etc/apache2/ssl/cert.pem
SSLCertificateKeyFile /etc/apache2/ssl/key.pem
Alias /cosign/ "/var/lib/cosign/html-local/"
ScriptAlias /cosign-bin/ "/var/lib/cosign/cgi-ssl/"
Include sites-available/common.inc
</VirtualHost>
<VirtualHost *:80>
Include sites-available/common.inc
</VirtualHost>
/etc/apache2/sites-available/common.inc:
CosignProtected Off CosignHostname localhost # Don't redirect to https if we come from http CosignHttpOnly On CosignRedirect https://localhost/cosign-bin/cosign.cgi CosignPostErrorRedirect https://localhost/cosign/post_error.html CosignService simpleservice CosignCrypto /etc/cosign/certs/mod_cosign.key /etc/cosign/certs/mod_cosign.crt /etc/cosign/certs/CA Alias /services/ "/usr/local/cosign/services-local/" <Directory "/usr/local/cosign/services-local/"> CosignProtected On </Directory>
If you're using Debian, you can easily enable SSL through:
a2enmod ssl echo "Listen 443" >> /etc/apache2/ports.conf
and restarting Apache.
If you need a simple self-signed certificate:
cd /etc/apache2/ssl/ openssl req -subj "/C=FR/ST=NPDC/L=Lievin/O=Cliss XXI/OU=SABDFL/CN=*/emailAddress=me@home/" \ -new -x509 -nodes -days 10000 -keyout key.pem -out cert.pem # check openssl x509 -noout -text -in cert.pem
CoSign configuration
Pitfalls:
- The
cgi
doesn't take more than 1 parameter - only service does. set cosignhost
is used by cgi, not cosignd. It specifies the host where cosignd runs, and is not related to replication.- Afaics 'factor' lines will always be ran and returns the name of the validated factor. This among others allows to filter which users can access to which service.
- TODO: fix documentation
- TODO: explain what
service
is for
/etc/cosign.conf:
# Allow CGI access from this host cgi localhost set cosignhost localhost set cosigncadir /etc/cosign/certs/CA/ set cosigncert /etc/cosign/certs/cgi.crt set cosignkey /etc/cosign/certs/cgi.key # Grant the given session type if credentials match the given factor cookie cosign-simpleservice reauth FACTOR-LDAP # Argument 3 and later are name of <FORM> fields from the template factor /usr/share/cosign/factor/ldap login password # Override the default template directories, # so our changes won't be ovewritten by an unfortunate 'make install' set cosigntmpldir /var/lib/cosign/templates-local set cosignlogouturl http://localhost/ set cosignloopurl https://localhost/cosign/looping.html
Certificates generation
We'll generate our own Certificate Authority.
TODO: during tests it's frequent to remove and rebuild everything. Typing password is really inconvenient in this case, and -passin
doesn't work for 'ca'. Please find a way to make this unattented!
# Base OpenSSL install mkdir -p -m 755 /etc/cosign/certs/CA cd /etc/cosign/certs umask 0027 mkdir -m 700 demoCA pushd demoCA mkdir -m 755 newcerts mkdir -m 700 private echo "01" > serial touch index.txt popd # Root CA # subj model from `openssl x509 -noout -text -in machin.cert` openssl req -new -subj "/C=FR/ST=NPDC/L=Lievin/O=Cliss XXI/OU=SSO/CN=Root CA/" \ -x509 -days 365 -keyout demoCA/private/cakey.pem -out demoCA/cacert.pem chmod a+r demoCA/cacert.pem # Certificate request and private key # cosignd openssl req -new -subj "/C=FR/ST=NPDC/L=Lievin/O=Cliss XXI/OU=SSO cosignd/CN=localhost/" \ -nodes -keyout "cosignd.key" -out "cosignd.csr" # Sign certificate openssl ca -in "cosignd.csr" -out "cosignd.crt" # CGI openssl req -new -subj "/C=FR/ST=NPDC/L=Lievin/O=Cliss XXI/OU=SSO cgi/CN=localhost/" \ -nodes -keyout "cgi.key" -out "cgi.csr" # Sign certificate openssl ca -in "cgi.csr" -out "cgi.crt" chgrp www-data cgi.key cgi.crt # mod_cosign openssl req -new -subj "/C=FR/ST=NPDC/L=Lievin/O=Cliss XXI/OU=SSO mod_cosign/CN=localhost/" \ -nodes -keyout "mod_cosign.key" -out "mod_cosign.csr" # Sign certificate openssl ca -in "mod_cosign.csr" -out "mod_cosign.crt" # Allowed certs path mkdir -m 755 CA ln demoCA/cacert.pem CA/ c_rehash CA/ # Tests - cf. http://www.umich.edu/~umweb/software/cosign/faq.html openssl verify -CApath CA/ -purpose sslclient cgi.crt mod_cosign.crt openssl verify -CApath CA/ -purpose sslserver cosignd.crt openssl s_client -connect localhost:6663 -cert cgi.crt -key cgi.key -CApath CA/ \ -showcerts -state -debug -crlf -starttls smtp # DO CHECK THAT YOU GET "Verify return code: 0 (ok)"!!! # (s_client won't stop on error)
cosignd server start
TODO: use/adapt scripts/startup/cosignd
# Launch server with different keys just in case: cd /var/lib/cosign/certs/ /usr/local/sbin/cosignd -y cosignd.crt -z cosignd.key -x /usr/local/cosign/certs/CA/ # CA path must be a full path, because cosignd chdir to /var/lib/cosign/daemon
Factor
Here's a simple LDAP factor (/usr/share/cosign/factor/ldap
):
#!/usr/bin/perl # Basic LDAP "factor" for CoSign # Copyright (C) 2007 Cliss XXI # # Permission is hereby granted, free of charge, to any person obtaining # a copy of this software and associated documentation files (the # "Software"), to deal in the Software without restriction, including # without limitation the rights to use, copy, modify, merge, publish, # distribute, sublicense, and/or sell copies of the Software, and to # permit persons to whom the Software is furnished to do so, subject to # the following conditions: # # The above copyright notice and this permission notice shall be included # in all copies or substantial portions of the Software. # # THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, # EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF # MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. # IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY # CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, # TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE # SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. # # Author: Sylvain Beucler <beuc@beuc.net> use strict; # Base configuration my $base = "ou=users,dc=cliss21,dc=com"; my $host = "ldap://192.168.1.149"; my $user_filter = "(objectClass=posixAccount)"; # ----- # If authentication is successful, the external authenticator writes # the factor name on stdout (file descriptor 1) and exits with a value # of 0. If an error occurs, the external authenticator writes an # error message on stdout and exits with a value of 1. All other exit # values are reserved for future use. # -- cosign.conf(5) use Net::LDAP; # Grab CoSign parameters from standard input my $login = <STDIN>; chomp $login; my $pass = <STDIN>; chomp $pass; # Get the login's DN my $binddn = ""; my $bindpw = ""; my $filter = "&$user_filter(uid=$login)"; my $attrs = []; my $ldap = Net::LDAP->new($host); if (!defined($ldap)) { # Be sure to catch the error manually and not use die, otherwise # the return code will be different than 1, making CoSign unhappy, # and the error will be print on stderr, so will be missing in the # web interface print "Cannot connect to LDAP server: $host\n"; exit 1; } $ldap->bind("$binddn", password => "$bindpw", version => 3); my $mesg = $ldap->search(base => $base, filter => $filter, attrs => $attrs); my $count = $mesg->count; if ($count == 0) { print "Unknown user: $login\n"; exit 1; } my $entry = $mesg->entry(); my $dn = $entry->dn(); # Try to login with the DN $binddn = $dn; $bindpw = $pass; my $result = $ldap->bind("$binddn", password => "$bindpw", version => 3); if ($result->code()) { print "Login failed (LDAP error: " . $result->error . ")\n"; exit 1; } $ldap->unbind(); print "FACTOR-LDAP\n"; # factor name exit 0; # success
Test
Now hit https://localhost/services/
Beyond
Check what monsterd is :)