This file is indexed.

/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;
    }

}