/usr/share/php/Horde/Auth/X509.php is in php-horde-auth 2.2.2-1ubuntu1.
This file is owned by root:root, with mode 0o644.
The actual contents of the file can be viewed below.
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 | <?php
/**
* Copyright 2013-2017 Horde LLC (http://www.horde.org)
*
* See the enclosed file COPYING for license information (LGPL). If you did
* not receive this file, see http://www.horde.org/licenses/lgpl21.
*
* @author Michael J Rubinsky <mrubinsk@horde.org>
* @category Horde
* @license http://www.horde.org/licenses/lgpl21 LGPL-2.1
* @package Auth
* @since 2.1.0
*/
/**
* The Horde_Auth_X509 class provides an authentication driver for using X509
* client certificates. Since X509 certificates do not provide the password,
* if the server setup requires the use of per-user passwords, a callback
* function may be passed to obtain it from.
*
* @author Michael J Rubinsky <mrubinsk@horde.org>
* @category Horde
* @copyright 2013-2017 Horde LLC
* @license http://www.horde.org/licenses/lgpl21 LGPL-2.1
* @package Auth
* @since 2.1.0
*/
class Horde_Auth_X509 extends Horde_Auth_Base
{
/**
* An array of capabilities, so that the driver can report which
* operations it supports and which it doesn't.
*
* @var array
*/
protected $_capabilities = array(
'transparent' => true
);
/**
* Constructor.
*
* @param array $params Parameters:
* - password: (string) If available, the password to use for the session.
* DEFAULT: no password used.
* - username_field: (string) Name of the $_SERVER field that
* the username can be found in. DEFAULT: 'SSL_CLIENT_S_DN_EMAILADDRESS'.
* - certificate_field: (string) Name of the $_SERVER field that contains
* the full certificate. DEFAULT: 'SSL_CLIENT_CERT'
* - ignore_purpose: (boolean) If true, will ignore any usage restrictions
* on the presented client certificate. I.e., if openssl_x509_checkpurpose
* returns false, authentication may still proceed. DEFAULT: false - ONLY
* ENABLE THIS IF YOU KNOW WHY YOU ARE DOING SO.
* - filter: (array) An array where the keys are field names and the
* values are the values those certificate fields MUST
* match to be considered valid. Keys in the format of
* fieldone:fieldtwo will be taken as parent:child.
* DEFAULT: no additionachecks applied.
*
* @throws InvalidArgumentException
*/
public function __construct(array $params = array())
{
$params = array_merge(array(
'password' => false,
'username_field' => 'SSL_CLIENT_S_DN_CN',
'certificate_field' => 'SSL_CLIENT_CERT',
'ignore_purpose' => true,
'filter' => array()
), $params);
parent::__construct($params);
}
/**
* Not implemented.
*
* @param string $userId The userID to check.
* @param array $credentials An array of login credentials.
*
* @throws Horde_Auth_Exception
*/
protected function _authenticate($userId, $credentials)
{
throw new Horde_Auth_Exception('Unsupported.');
}
/**
* Automatic authentication: checks if the username is set in the
* configured header.
*
* @return boolean Whether or not the client is allowed.
*/
public function transparent()
{
if (!is_callable('openssl_x509_parse')) {
throw new Horde_Auth_Exception('SSL not enabled on server.');
}
if (empty($_SERVER[$this->_params['username_field']]) ||
empty($_SERVER[$this->_params['certificate_field']])) {
return false;
}
// Valid for client auth?
$cert = openssl_x509_read($_SERVER[$this->_params['certificate_field']]);
if (!$this->_params['ignore_purpose'] &&
!openssl_x509_checkpurpose($cert, X509_PURPOSE_SSL_CLIENT) &&
!openssl_x509_checkpurpose($cert, X509_PURPOSE_ANY)) {
return false;
}
$c_parsed = openssl_x509_parse($cert);
foreach ($this->_params['filter'] as $key => $value) {
$keys = explode(':', $key);
$c = $c_parsed;
foreach ($keys as $k) {
$c = $c[$k];
}
if ($c != $value) {
return false;
}
}
// Handle any custom validation added by sub classes.
if (!$this->_validate($cert)) {
return false;
}
// Free resources.
openssl_x509_free($cert);
// Set credentials
$this->setCredential('userId', $_SERVER[$this->_params['username_field']]);
$cred = array('certificate_id' => $c_parsed['hash']);
if (!empty($this->_params['password'])) {
$cred['password'] = $this->_params['password'];
}
$this->setCredential('credentials', $cred);
return true;
}
/**
* Perform additional validation of certificate fields.
*
* @return boolean
*/
protected function _validate($certificate)
{
return true;
}
}
|