Différences entre versions de « CoSign »
imported>SylvainBeucler m |
imported>SylvainBeucler m (sample ldap factor) |
||
| Ligne 172 : | Ligne 172 : | ||
/usr/local/sbin/cosignd -y cosignd.crt -z cosignd.key -x /usr/local/cosign/certs/CA/ | /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 | # CA path must be a full path, because cosignd chdir to /var/lib/cosign/daemon | ||
| + | |||
| + | == Factor == | ||
| + | |||
| + | Here's a simple LDAP factor: | ||
| + | |||
| + | #!/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; | ||
| + | use Net::LDAP::LDIF; | ||
| + | my $debug = 0; | ||
| + | |||
| + | sub debug { | ||
| + | if ($debug) { | ||
| + | print "DEBUG:"; | ||
| + | print @_; | ||
| + | print "\n"; | ||
| + | } | ||
| + | } | ||
| + | |||
| + | # Grab CoSign parameters from standard input | ||
| + | my $login = <STDIN>; chomp $login; | ||
| + | debug($login); | ||
| + | my $pass = <STDIN>; chomp $pass; | ||
| + | debug($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 == | == Test == | ||
Version du 16 mai 2007 à 13:00
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 try to use FHS-compliant paths.
./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
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
Apache2 configuration
/etc/apache2/sites-available/default:
# Automatically added in /etc/apache2/httpd.conf by 'make install-all' 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/" 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 /usr/local/cosign/certs/mod_cosign.key /usr/local/cosign/certs/mod_cosign.crt /usr/local/cosign/certs/CA Alias /cosign/ "/var/lib/cosign/html/" ScriptAlias /cosign-bin/ "/var/lib/cosign/cgi-ssl/" Alias /services/ "/usr/local/cosign/services/" <Directory "/usr/local/cosign/services"> CosignProtected On </Directory>
CoSign configuration
Pitfalls:
- The
cgidoesn't take more than 1 parameter - only service does. set cosignhostis 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
serviceis 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 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 mkdir -p /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/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;
use Net::LDAP::LDIF;
my $debug = 0;
sub debug {
if ($debug) {
print "DEBUG:";
print @_;
print "\n";
}
}
# Grab CoSign parameters from standard input
my $login = <STDIN>; chomp $login;
debug($login);
my $pass = <STDIN>; chomp $pass;
debug($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 :)