1<?php
2/*
3 * $Id: ActiveDirectory.php 501 2013-07-11 17:44:37Z imooreyahoo@gmail.com $
4* Experimental!
5*/
6class phpvbAuthActiveDirectory implements phpvbAuth {
7
8	var $capabilities = array(
9		'canChangePassword' => false,
10		'canLogout' => true
11	);
12
13	var $config = array(
14		'host' => '127.0.0.1',
15		'admin_group' => null,
16		'adminUser' => null,
17		'user_group' => null,
18		'container' => 'CN=Users',
19		'domain' =>   'internal.local',
20		'filter' => '(&(objectclass=User)(objectCategory=Person))'
21	);
22
23	/**
24	 * Constructor
25	 * @param array $userConfig - user configuration for this module
26	 */
27	function phpvbAuthActiveDirectory($userConfig = null) {
28		// Merge user config
29		if($userConfig) {
30			$this->config = array_merge($this->config,$userConfig);
31		}
32	}
33
34	/**
35	 * Test log in and set $_SESSION vars
36	 * @param string $username
37	 * @param string $password
38	 * @see phpvbAuth::login()
39	 */
40	function login($username, $password)
41	{
42		global $_SESSION;
43
44
45		/*
46		 * Check for LDAP functionality and provide some direction
47		 */
48		if(!function_exists('ldap_connect')) {
49
50			$ex = 'LDAP support is not enabled in your PHP configuration.';
51
52			if(strtolower(substr(PHP_OS, 0, 3)) == 'win') {
53
54				ob_start();
55				phpinfo(INFO_GENERAL);
56				$phpinfo = ob_get_contents();
57				ob_end_clean();
58				preg_match('/Loaded Configuration File <\/td><td.*?>(.*?)\s*</', $phpinfo, $phpinfo);
59
60				$ex .= ' You probably just need to uncomment the line ;extension=php_ldap.dll in php.ini'.
61						(count($phpinfo) > 1 ? ' (' .trim($phpinfo[1]).')' : '') . ' by removing the ";" and restart your web server.';
62
63			} else if(strtolower(substr(PHP_OS, 0, 5)) == 'Linux') {
64
65				$ex .= ' You probably need to install the php5-ldap (or similar depending on your distribution) package and restart your web server.';
66
67			}
68			throw new Exception($ex);
69		}
70
71		$_SESSION['valid'] = false;
72
73		// Connect to server
74		if(!($auth = ldap_connect($this->config['host']))) {
75			throw new Exception('Active Directory error ('.ldap_errno($auth).') ' . ldap_error($auth));
76		}
77
78		// Set relevant LDAP options
79		ldap_set_option($auth,LDAP_OPT_PROTOCOL_VERSION, 3);
80
81
82		// Main login /bind
83		if(!($bind = @ldap_bind($auth, $username . "@" .$this->config['domain'], $password))) {
84			if(ldap_errno($auth) == 49) return false;
85			throw new Exception('Active Directory error ('.ldap_errno($auth).') ' . ldap_error($auth));
86		}
87
88
89		// Get user information from AD
90		////////////////////////////////////
91
92
93		// Set filter and sanitize username before sending it to AD
94		$filter = "(sAMAccountName=" .
95			str_replace(array(',','=','+','<','>',';','\\','"','#','(',')','*',chr(0)), '', $username) . ")";
96		if($this->config['filter'] && false) {
97			$filter = '(&'. $this->config['filter'] .' ('. $filter .'))';
98		}
99
100		$result = @ldap_search($auth,
101				$this->config['container'] . ',DC=' . join(',DC=', explode('.', $this->config['domain'])),
102				$filter, array("memberof","useraccountcontrol"));
103
104		if(!result) throw new Exception ("Unable to search Active Directory server: " . ldap_error($auth));
105		@list($entries) = @ldap_get_entries($auth, $result);
106		@ldap_unbind($auth);
107		if(!$entries) {
108			throw new Exception("Permission denied");
109		}
110
111
112		// Check for disabled user
113		if((intval($entries['useraccountcontrol'][0]) & 2)) {
114			throw new Exception('This account is disabled in Active Directory.');
115		}
116
117		// check for valid admin group
118		if($this->config['admin_group']) {
119			foreach($entries['memberof'] as $group) {
120				list($group) = explode(',', $group);
121				if(strtolower($group) == strtolower('cn='.$this->config['admin_group'])) {
122					$_SESSION['admin'] = $_SESSION['valid'] = true;
123					break;
124				}
125			}
126		}
127
128		// Admin user explicitly set?
129		if(!$_SESSION['admin'] && $this->config['adminUser']) {
130			$_SESSION['admin'] = (strtolower($this->config['adminUser']) == strtolower($username));
131			// Admin is ok
132			$_SESSION['valid'] = ($_SESSION['admin'] || $_SESSION['valid']);
133		}
134
135		// check for valid user group
136		if($this->config['user_group'] && !$_SESSION['valid']) {
137			foreach($entries['memberof'] as $group) {
138				list($group) = explode(',', $group);
139				if(strtolower($group) == strtolower('cn='.$this->config['user_group'])) {
140					$_SESSION['valid'] = true;
141					break;
142				}
143			}
144		} else {
145			$_SESSION['valid'] = true;
146		}
147
148		if(!$_SESSION['valid'])
149			throw new Exception("Permission denied");
150
151		// Admin user explicitly set?
152		if(!$_SESSION['admin'] && $this->config['adminUser']) {
153			$_SESSION['admin'] = (strtolower($this->config['adminUser']) == strtolower($username));
154		}
155
156		// No admin information specified makes everyone an admin
157		if(!$this->config['adminUser'] && !$this->config['admin_group'])
158			$_SESSION['admin'] = true;
159
160		// user has permission. establish session variables
161		$_SESSION['user'] = $username;
162		$_SESSION['authCheckHeartbeat'] = time();
163
164
165		return true;
166
167	}
168
169	function heartbeat($vbox)
170	{
171		global $_SESSION;
172
173		$_SESSION['valid'] = true;
174		$_SESSION['authCheckHeartbeat'] = time();
175	}
176
177	function changePassword($old, $new)
178	{
179	}
180
181	function logout(&$response)
182	{
183		global $_SESSION;
184		if(function_exists('session_destroy')) session_destroy();
185		else unset($_SESSION['valid']);
186		$response['data']['result'] = 1;
187	}
188
189	function listUsers()
190	{
191
192	}
193
194	function updateUser($vboxRequest, $skipExistCheck)
195	{
196
197	}
198
199	function deleteUser($user)
200	{
201
202	}
203}
204