diff --git a/modules/authX509/docs/authX509.txt b/modules/authX509/docs/authX509.txt index 4992e617f1edcb68b69a29a0a8893c2e0877cbe3..8cb3ff352fe044ccd0e4a1d7bdf0f009e1afc188 100644 --- a/modules/authX509/docs/authX509.txt +++ b/modules/authX509/docs/authX509.txt @@ -1,7 +1,7 @@ Using the X509 authentication source with simpleSAMLphp ======================================================= -The authX509 module provide X509 authentication with certificate +The authX509 module provides X509 authentication with certificate validation. For now there is only one authentication source: * authX509userCert Validate against LDAP userCertificate attribute @@ -27,22 +27,22 @@ Note that SSLVerifyClient can be set to optional if you want to support both certificate and plain login authentication at the same time (more on this later). -If your server or your client (or both!) have TLS renegociation disabled +If your server or your client (or both!) have TLS renegotiation disabled as a workaround for CVE-2009-3555, then the configuration directive above must not appear in a <Directory>, <Location>, or in a name-based -<VirtualHost>. You can only use them server-wide, or in <VirtualHost> -with different IP address/port combinaisons. +<VirtualHost>. You can only use them server-wide, or in <VirtualHost>s +with different IP address/port combinations. Setting up the authX509 module ------------------------------ -The first thing you need to do is to enable the cas module: +The first thing you need to do is to enable the module: touch modules/authX509/enable Then you must add it as an authentication source. Here is an -example authsource.php +example authsources.php entry: 'x509' => array( 'authX509:X509userCert', @@ -52,8 +52,8 @@ example authsource.php 'search.enable' => TRUE, 'search.attributes' => array('uid', 'mail'), 'search.base' => 'dc=example,dc=net', - 'x509attributes' => array('UID' => 'uid'), - 'ldapusercert' => array('userCertificate;binary'), + 'authX509:x509attributes' => array('UID' => 'uid'), + 'authX509:ldapusercert' => array('userCertificate;binary'), ), The configuration is the same as for the LDAP module, except for @@ -62,16 +62,18 @@ two options: * x509attributes is used to map a certificate subject attribute to an LDAP attribute. It is used to find the certificate owner in LDAP from the certificate subject. If multiple - mappings are provided, any mappping will match (this - is a logical OR). Default is array('UID' => 'uid') + mappings are provided, any mapping will match (this + is a logical OR). Default is array('UID' => 'uid'). * ldapusercert the LDAP attribute in which the user certificate will - be found. Default is userCertificate;binary + be found. Default is userCertificate;binary. This can + be set to NULL to avoid looking up the certificate in + LDAP. Uploading certificate in LDAP ----------------------------- -Certificate are usually stored in LDAP as DER, in binary. Here is +Certificates are usually stored in LDAP as DER, in binary. Here is how to convert from PEM to DER: openssl x509 -in cert.pem -inform PEM -outform DER -out cert.der @@ -84,8 +86,8 @@ Here is some LDIF to upload the certificate in the directory: userCertificate;binary:< file:///path/to/cert.der -Supporting both certificate and login authentications -===================================================== +Supporting both certificate and login authentication +==================================================== In your Apache configuration, set SSLVerifyClient to optional. Then you can hack your metadata/saml20-idp-hosted.php file that way: diff --git a/modules/authX509/lib/Auth/Source/X509userCert.php b/modules/authX509/lib/Auth/Source/X509userCert.php index e7e73dc912801e33088af22cc7afae5ebc8904a8..ca9a527881b1ea7459f226f214e3eb884f64492b 100644 --- a/modules/authX509/lib/Auth/Source/X509userCert.php +++ b/modules/authX509/lib/Auth/Source/X509userCert.php @@ -46,7 +46,7 @@ class sspmod_authX509_Auth_Source_X509userCert extends SimpleSAML_Auth_Source { $this->x509attributes = $config['authX509:x509attributes']; - if (isset($config['authX509:ldapusercert'])) + if (array_key_exists('authX509:ldapusercert', $config)) $this->ldapusercert = $config['authX509:ldapusercert']; @@ -142,18 +142,20 @@ class sspmod_authX509_Auth_Source_X509userCert extends SimpleSAML_Auth_Source { return; } - $dn = FALSE; + $dn = NULL; foreach ($this->x509attributes as $x509_attr => $ldap_attr) { /* value is scalar */ - $value = $client_cert_data['subject'][$x509_attr]; - SimpleSAML_Logger::info('authX509: cert '. - $x509_attr.' = '.$value); - $dn = $ldapcf->searchfordn($ldap_attr, $value, TRUE); - if ($dn !== FALSE) - break; + if (array_key_exists($x509_attr, $client_cert_data['subject'])) { + $value = $client_cert_data['subject'][$x509_attr]; + SimpleSAML_Logger::info('authX509: cert '. + $x509_attr.' = '.$value); + $dn = $ldapcf->searchfordn($ldap_attr, $value, TRUE); + if ($dn !== NULL) + break; + } } - if ($dn === FALSE) { + if ($dn === NULL) { SimpleSAML_Logger::error('authX509: cert has '. 'no matching user in LDAP'); $state['authX509.error'] = "UNKNOWNCERT"; @@ -163,6 +165,16 @@ class sspmod_authX509_Auth_Source_X509userCert extends SimpleSAML_Auth_Source { return; } + if ($this->ldapusercert === NULL) { // do not check for certificate match + $attributes = $ldapcf->getAttributes($dn); + assert('is_array($attributes)'); + $state['Attributes'] = $attributes; + $this->authSuccesful($state); + + assert('FALSE'); /* NOTREACHED */ + return; + } + $ldap_certs = $ldapcf->getAttributes($dn, $this->ldapusercert); if ($ldap_certs === FALSE) { SimpleSAML_Logger::error('authX509: no certificate '.