1<?php
2/**
3 *
4 * Built-in authentication module. Uses VirtualBox's set/getExtraData capability
5 * to store / retrieve user credentials. Called from API when authentication
6 * functions are requested.
7 *
8 * @author Ian Moore (imoore76 at yahoo dot com)
9 * @copyright Copyright (C) 2010-2015 Ian Moore (imoore76 at yahoo dot com)
10 * @version $Id: Builtin.php 595 2015-04-17 09:50:36Z imoore76 $
11 * @package phpVirtualBox
12 * @see vboxconnector
13 *
14 */
15class phpvbAuthBuiltin implements phpvbAuth {
16
17	/**
18	 *
19	 * A list of capabilities describing this authentication module.
20	 * @var array capability values:
21	 * 		@var boolean canChangePassword
22	 * 		@var boolean canModifyUsers
23	 * 		@var boolean canLogout
24	 *
25	 */
26	var $capabilities = array(
27			'canChangePassword' => true,
28			'canModifyUsers' => true,
29			'canLogout' => true
30		);
31
32	/**
33	 *
34	 * Log in function. Populates $_SESSION
35	 * @param string $username user name
36	 * @param string $password password
37	 */
38	function login($username, $password)
39	{
40		global $_SESSION;
41
42		$vbox = new vboxconnector(true);
43		$vbox->skipSessionCheck = true;
44		$vbox->connect();
45		$p = $vbox->vbox->getExtraData('phpvb/users/'.$username.'/pass');
46
47		// Check for initial login
48		if($username == 'admin' && !$p && !$vbox->vbox->getExtraData('phpvb/usersSetup')) {
49			$vbox->vbox->setExtraData('phpvb/usersSetup','1');
50			$vbox->vbox->setExtraData('phpvb/users/'.$username.'/pass', hash('sha512', 'admin'));
51			$vbox->vbox->setExtraData('phpvb/users/'.$username.'/admin', '1');
52			$p = hash('sha512', 'admin');
53		}
54
55		if($p == hash('sha512', $password)) {
56			$_SESSION['valid'] = true;
57			$_SESSION['user'] = $username;
58			$_SESSION['admin'] = intval($vbox->vbox->getExtraData('phpvb/users/'.$username.'/admin'));
59			$_SESSION['authCheckHeartbeat'] = time();
60			$_SESSION['uHash'] = $p;
61		}
62	}
63
64	/**
65	 *
66	 * Change password function.
67	 * @param string $old old password
68	 * @param string $new new password
69	 * @return boolean true on success
70	 */
71	function changePassword($old, $new)
72	{
73		global $_SESSION;
74
75		// Use main / auth server
76		$vbox = new vboxconnector(true);
77		$vbox->connect();
78		$p = $vbox->vbox->getExtraData('phpvb/users/'.$_SESSION['user'].'/pass');
79
80		if($p == hash('sha512', $old)) {
81			$np = hash('sha512', $new);
82			$vbox->vbox->setExtraData('phpvb/users/'.$_SESSION['user'].'/pass', $np);
83			$response['data']['result'] = 1;
84			$_SESSION['uHash'] = $np;
85			return true;
86		}
87		return false;
88	}
89
90	/**
91	 *
92	 * Revalidate login info and set authCheckHeartbeat session variable.
93	 * @param vboxconnector $vbox vboxconnector object instance
94	 */
95	function heartbeat($vbox)
96	{
97		global $_SESSION;
98
99		// Check to see if we only have 1 server or are already connected
100		// to the authentication master server
101		if(@$vbox->settings->authMaster || count($vbox->settings->servers) == 1) {
102			$vbcheck = &$vbox;
103		} else {
104			$vbcheck = new vboxconnector(true);
105		}
106
107		$vbcheck->connect();
108		$p = $vbcheck->vbox->getExtraData('phpvb/users/'.$_SESSION['user'].'/pass');
109		if(!@$p || @$_SESSION['uHash'] != $p) {
110			if(function_exists('session_destroy')) session_destroy();
111			unset($_SESSION['valid']);
112		} else {
113			$_SESSION['admin'] = intval($vbcheck->vbox->getExtraData('phpvb/users/'.$_SESSION['user'].'/admin'));
114			$_SESSION['authCheckHeartbeat'] = time();
115		}
116
117		if(!@$_SESSION['valid'])
118			throw new Exception(trans('Not logged in.','UIUsers'), vboxconnector::PHPVB_ERRNO_FATAL);
119	}
120
121	/**
122	 *
123	 * Log out user present in $_SESSION
124	 * @param array $response response passed byref by API and populated within function
125	 */
126	function logout(&$response)
127	{
128		global $_SESSION;
129		if(function_exists('session_destroy')) session_destroy();
130		else unset($_SESSION['valid']);
131		$response['data']['result'] = 1;
132	}
133
134	/**
135	 *
136	 * Return a list of users
137	 * @return array list of users
138	 */
139	function listUsers()
140	{
141		$response = array();
142
143		// Use main / auth server
144		$vbox = new vboxconnector(true);
145		$vbox->connect();
146
147		$keys = $vbox->vbox->getExtraDataKeys();
148		foreach($keys as $k) {
149			if(strpos($k,'phpvb/users/') === 0) {
150				$user = substr($k,12,strpos($k,'/',13)-12);
151				if(isset($response[$user])) continue;
152				$admin = intval($vbox->vbox->getExtraData('phpvb/users/'.$user.'/admin'));
153				$response[$user] = array('username'=>$user,'admin'=>$admin);
154			}
155		}
156		return $response;
157	}
158
159	/**
160	 *
161	 * Update user information such as password and admin status
162	 * @param array $vboxRequest request passed from API representing the request. Contains user, password and administration level.
163	 * @param boolean $skipExistCheck Do not check that the user exists first. Essentially, if this is set and the user does not exist, it is added.
164	 */
165	function updateUser($vboxRequest, $skipExistCheck)
166	{
167		global $_SESSION;
168
169		// Must be an admin
170		if(!$_SESSION['admin'])
171		    return;
172
173		// Use main / auth server
174		$vbox = new vboxconnector(true);
175		$vbox->connect();
176
177		// See if it exists
178		if(!$skipExistCheck && $vbox->vbox->getExtraData('phpvb/users/'.$vboxRequest['u'].'/pass'))
179			return;
180
181		if($vboxRequest['p'])
182			$vbox->vbox->setExtraData('phpvb/users/'.$vboxRequest['u'].'/pass', hash('sha512', $vboxRequest['p']));
183
184		$vbox->vbox->setExtraData('phpvb/users/'.$vboxRequest['u'].'/admin', ($vboxRequest['a'] ? '1' : '0'));
185	}
186
187	/**
188	 *
189	 * Remove the user $user
190	 * @param string $user Username to remove
191	 */
192	function deleteUser($user)
193	{
194		// Use main / auth server
195		$vbox = new vboxconnector(true);
196		$vbox->connect();
197
198		$vbox->vbox->setExtraData('phpvb/users/'.$user.'/pass','');
199		$vbox->vbox->setExtraData('phpvb/users/'.$user.'/admin','');
200		$vbox->vbox->setExtraData('phpvb/users/'.$user,'');
201	}
202}
203