Merge pull request 'Fix client certificate login' (!16) from fix-client-certificate-login into main
Reviewed-on: #16 Reviewed-by: Brian Mc Cullough <bmccullough@cacert.org> Reviewed-by: Dirk Astrath <dirk@cacert.org>
This commit is contained in:
commit
abfce60ed4
3 changed files with 78 additions and 19 deletions
|
@ -1,6 +1,6 @@
|
||||||
<? /*
|
<? /*
|
||||||
LibreSSL - CAcert web application
|
LibreSSL - CAcert web application
|
||||||
Copyright (C) 2004-2011 CAcert Inc.
|
Copyright (C) CAcert Inc.
|
||||||
|
|
||||||
This program is free software; you can redistribute it and/or modify
|
This program is free software; you can redistribute it and/or modify
|
||||||
it under the terms of the GNU General Public License as published by
|
it under the terms of the GNU General Public License as published by
|
||||||
|
@ -16,32 +16,91 @@
|
||||||
Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
|
Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
|
||||||
*/
|
*/
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Walk through the email address environment variables that Apache httpd
|
||||||
|
* might have set and put them into an array.
|
||||||
|
*
|
||||||
|
* The function ensures that unique addresses are returned.
|
||||||
|
*
|
||||||
|
* @return array
|
||||||
|
*/
|
||||||
|
function get_email_addresses_from_client_cert() {
|
||||||
|
$addresses = array();
|
||||||
|
$maxAddresses = 10; // implement a hard boundary to avoid endless loop
|
||||||
|
|
||||||
|
// try SAN email addresses first
|
||||||
|
$envNameBase = "SSL_CLIENT_SAN_Email";
|
||||||
|
for ($i = 0; $i <= $maxAddresses; $i++) {
|
||||||
|
$envName = sprintf("%s_%d", $envNameBase, $i);
|
||||||
|
if (!array_key_exists($envName, $_SERVER)) {
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
$addresses[] = $_SERVER[$envName];
|
||||||
|
}
|
||||||
|
|
||||||
|
if (count($addresses) > 0) {
|
||||||
|
return array_unique($addresses);
|
||||||
|
}
|
||||||
|
|
||||||
|
// fallback for older Apache httpd versions that do not support email SAN fields
|
||||||
|
$envNameBase = "SSL_CLIENT_S_DN_Email";
|
||||||
|
|
||||||
|
if (array_key_exists($envNameBase, $_SERVER)) {
|
||||||
|
$addresses[] = $_SERVER[$envNameBase];
|
||||||
|
}
|
||||||
|
|
||||||
|
for ($i = 1; $i <= $maxAddresses; $i++) {
|
||||||
|
$envName = sprintf("%s_%d", $envNameBase, $i);
|
||||||
|
if (array_key_exists($envName, $_SERVER)) {
|
||||||
|
$addresses[] = $_SERVER[$envName];
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return array_unique($addresses);
|
||||||
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Checks if the user may log in and retrieve the user id
|
* Checks if the user may log in and retrieve the user id
|
||||||
*
|
*
|
||||||
* Usually called with $_SERVER['SSL_CLIENT_M_SERIAL'] and
|
* Usually called with $_SERVER['SSL_CLIENT_M_SERIAL'] and
|
||||||
* $_SERVER['SSL_CLIENT_I_DN_CN']
|
* $_SERVER['SSL_CLIENT_I_DN_CN']
|
||||||
*
|
*
|
||||||
* @param $serial string
|
* @param $serial string
|
||||||
* usually $_SERVER['SSL_CLIENT_M_SERIAL']
|
* usually $_SERVER['SSL_CLIENT_M_SERIAL']
|
||||||
* @param $issuer_cn string
|
* @param $issuer_cn string
|
||||||
* usually $_SERVER['SSL_CLIENT_I_DN_CN']
|
* usually $_SERVER['SSL_CLIENT_I_DN_CN']
|
||||||
|
* @param $addresses array
|
||||||
|
* list of email addresses from the certificate
|
||||||
* @return int
|
* @return int
|
||||||
* the user id, -1 in case of error
|
* the user id, -1 in case of error
|
||||||
|
*
|
||||||
|
* @see get_email_addresses_from_client_cert()
|
||||||
*/
|
*/
|
||||||
function get_user_id_from_cert($serial, $issuer_cn)
|
function get_user_id_from_cert($serial, $issuer_cn, $addresses) {
|
||||||
{
|
$addresses_for_sql = array_map('mysql_real_escape_string', $addresses);
|
||||||
$query = "select `memid` from `emailcerts` where
|
|
||||||
`serial`='".mysql_escape_string($serial)."' and
|
$query = sprintf("SELECT DISTINCT ec.`memid`
|
||||||
`rootcert`= (select `id` from `root_certs` where
|
FROM `emailcerts` ec
|
||||||
`Cert_Text`='".mysql_escape_string($issuer_cn)."') and
|
JOIN root_certs r ON r.id = ec.rootcert
|
||||||
`revoked`=0 and disablelogin=0 and
|
JOIN email e ON ec.memid = e.memid
|
||||||
UNIX_TIMESTAMP(`expire`) - UNIX_TIMESTAMP() > 0";
|
WHERE ec.serial = '%s'
|
||||||
|
AND r.`Cert_Text` = '%s'
|
||||||
|
AND e.email IN ('%s')
|
||||||
|
AND ec.revoked = 0
|
||||||
|
AND ec.disablelogin = 0
|
||||||
|
AND UNIX_TIMESTAMP(ec.expire) > UNIX_TIMESTAMP()", mysql_real_escape_string($serial),
|
||||||
|
mysql_real_escape_string($issuer_cn), implode("', '", $addresses_for_sql));
|
||||||
|
|
||||||
$res = mysql_query($query);
|
$res = mysql_query($query);
|
||||||
if(mysql_num_rows($res) > 0)
|
if ($res === false) {
|
||||||
{
|
trigger_error(sprintf("MySQL error %d: %s", mysql_errno(), mysql_error()));
|
||||||
$row = mysql_fetch_assoc($res);
|
|
||||||
return intval($row['memid']);
|
return -1;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (mysql_num_rows($res) === 1) {
|
||||||
|
$row = mysql_fetch_row($res);
|
||||||
|
return intval($row[0]);
|
||||||
}
|
}
|
||||||
|
|
||||||
return -1;
|
return -1;
|
||||||
|
|
|
@ -54,7 +54,7 @@
|
||||||
if($_SERVER['HTTP_HOST'] == $_SESSION['_config']['securehostname'] && ($_SESSION['profile']['id'] == 0 || $_SESSION['profile']['loggedin'] == 0))
|
if($_SERVER['HTTP_HOST'] == $_SESSION['_config']['securehostname'] && ($_SESSION['profile']['id'] == 0 || $_SESSION['profile']['loggedin'] == 0))
|
||||||
{
|
{
|
||||||
$user_id = get_user_id_from_cert($_SERVER['SSL_CLIENT_M_SERIAL'],
|
$user_id = get_user_id_from_cert($_SERVER['SSL_CLIENT_M_SERIAL'],
|
||||||
$_SERVER['SSL_CLIENT_I_DN_CN']);
|
$_SERVER['SSL_CLIENT_I_DN_CN'], get_email_addresses_from_client_cert());
|
||||||
|
|
||||||
if($user_id >= 0)
|
if($user_id >= 0)
|
||||||
{
|
{
|
||||||
|
|
|
@ -153,7 +153,7 @@ require_once('../includes/notary.inc.php');
|
||||||
{
|
{
|
||||||
include_once("../includes/lib/general.php");
|
include_once("../includes/lib/general.php");
|
||||||
$user_id = get_user_id_from_cert($_SERVER['SSL_CLIENT_M_SERIAL'],
|
$user_id = get_user_id_from_cert($_SERVER['SSL_CLIENT_M_SERIAL'],
|
||||||
$_SERVER['SSL_CLIENT_I_DN_CN']);
|
$_SERVER['SSL_CLIENT_I_DN_CN'], get_email_addresses_from_client_cert());
|
||||||
|
|
||||||
if($user_id >= 0)
|
if($user_id >= 0)
|
||||||
{
|
{
|
||||||
|
|
Loading…
Reference in a new issue