1<?php
2/**
3 * Copyright 2006 9Star Research, Inc. http://www.protectnetwork.org/
4 *
5 * See the enclosed file COPYING for license information (LGPL). If you did
6 * not receive this file, see http://www.horde.org/licenses/lgpl21.
7 *
8 * @author   Cassio Nishiguchi <cassio@protectnetwork.org>
9 * @category Horde
10 * @license  http://www.horde.org/licenses/lgpl21 LGPL-2.1
11 * @package  Auth
12 */
13
14/**
15 * The Horde_Auth_Shibboleth class only provides transparent authentication
16 * based on the headers set by a Shibboleth SP.
17 *
18 * Note that this class does not provide any actual SP functionality, it just
19 * takes the username from the HTTP headers that should be set by the
20 * Shibboleth SP.
21 *
22 * @author    Cassio Nishiguchi <cassio@protectnetwork.org>
23 * @category  Horde
24 * @copyright 2006 9Star Research, Inc.
25 * @license   http://www.horde.org/licenses/lgpl21 LGPL-2.1
26 * @package   Auth
27 */
28class Horde_Auth_Shibboleth extends Horde_Auth_Base
29{
30    /**
31     * An array of capabilities, so that the driver can report which
32     * operations it supports and which it doesn't.
33     *
34     * @var array
35     */
36    protected $_capabilities = array(
37        'transparent' => true
38    );
39
40    /**
41     * Constructor.
42     *
43     * @param array $params  Parameters:
44     * <pre>
45     * 'password_header' - (string) Name of the header holding the password of
46     *                     the logged in user.
47     * 'password_holder' - (string) Where the hordeauth password is stored.
48     * 'password_preference' - (string) Name of the Horde preference holding
49     *                         the password of the logged in user.
50     * 'username_header' - (string) [REQUIRED] Name of the header holding the
51     *                     username of the logged in user.
52     * </pre>
53     *
54     * @throws InvalidArgumentException
55     */
56    public function __construct(array $params = array())
57    {
58        if (!isset($params['username_header'])) {
59            throw new InvalidArgumentException('Missing username_header parameter.');
60        }
61
62        $params = array_merge(array(
63            'password_header' => '',
64            'password_holder' => '',
65            'password_preference' => ''
66        ), $params);
67
68        parent::__construct($params);
69    }
70
71    /**
72     * Not implemented.
73     *
74     * @param string $userId      The userID to check.
75     * @param array $credentials  An array of login credentials.
76     *
77     * @throws Horde_Auth_Exception
78     */
79    protected function _authenticate($userId, $credentials)
80    {
81        throw new Horde_Auth_Exception('Unsupported.');
82    }
83
84    /**
85     * Automatic authentication: checks if the username is set in the
86     * configured header.
87     *
88     * @return boolean  Whether or not the client is allowed.
89     */
90    public function transparent()
91    {
92        if (empty($_SERVER[$this->_params['username_header']])) {
93            return false;
94        }
95
96        $username = $_SERVER[$this->_params['username_header']];
97
98        // Remove scope from username, if present.
99        $this->setCredential('userId', $this->_removeScope($username));
100
101        // Set password for hordeauth login.
102        switch ($this->_params['password_holder']) {
103        case 'header':
104            $this->setCredential('credentials', array(
105                'password' => $_SERVER[$this->_params['password_header']]
106            ));
107            break;
108
109        case 'preferences':
110            $this->setCredential('credentials', array(
111                'password' => $_SERVER[$this->_params['password_preference']]
112            ));
113            break;
114        }
115
116        return true;
117    }
118
119    /**
120     * Removes the scope from the user name, if present.
121     *
122     * @param string $username  The full user name.
123     *
124     * @return string  The user name without scope.
125     */
126    protected function _removeScope($username)
127    {
128        $pos = strrpos($username, '@');
129        return ($pos !== false)
130            ? substr($username, 0, $pos)
131            : $username;
132    }
133
134}
135