]> git.defcon.no Git - hermes/blob - api/auth.php
First stab at a naive permissions-tool
[hermes] / api / auth.php
1 <?php
2 /*
3 # Copyright (c) 2012, Gjøvik University College
4 # All rights reserved.
5
6 # Redistribution and use in source and binary forms, with or without
7 # modification, are permitted provided that the following conditions are met:
8 # * Redistributions of source code must retain the above copyright
9 # notice, this list of conditions and the following disclaimer.
10 # * Redistributions in binary form must reproduce the above copyright
11 # notice, this list of conditions and the following disclaimer in the
12 # documentation and/or other materials provided with the distribution.
13 # * Neither the name of the Gjøvik University College nor the
14 # names of its contributors may be used to endorse or promote products
15 # derived from this software without specific prior written permission.
16 #
17 # THIS SOFTWARE IS PROVIDED BY Gjøvik University College ''AS IS'' AND ANY
18 # EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
19 # WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
20 # DISCLAIMED. IN NO EVENT SHALL Gjøvik University College BE LIABLE FOR ANY
21 # DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
22 # (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
23 # LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
24 # ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
25 # (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
26 # SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
27 */
28 require_once('config.php');
29 require_once('lib/auth_base.php');
30 require_once('lib/common_functions.php');
31 require_once('lib/db_functions.php');
32 require_once('lib/domain_functions.php');
33
34 $config = get_config();
35
36 $config['sql_link'] = @mysql_connect(
37 $config['sql_server'],
38 $config['sql_username'],
39 $config['sql_password']
40 );
41 if ( !$config['sql_link'] )
42 {
43 print json_encode( array( 'response' => 'failed', 'cause' => 'error', 'detail' => 'Database connection failed.'));
44 exit;
45 }
46
47 //*************************************************************************************
48 if ( ( $_SERVER['PATH_INFO'] == "/login" ) || ( $_SERVER['PATH_INFO'] == "/logout" ) )
49 {
50 switch ( $_SERVER['PATH_INFO'] )
51 {
52 case "/login":
53 // Allow login using username and password, or API key.
54 // On successful login, a named session should be started,
55 // some data related to the session should be stored,
56 // and the name of the session provided to the user
57 // in the result.
58 $type = false;
59 $authid = false;
60
61 if ( array_key_exists('username', $_POST)
62 && array_key_exists('password', $_POST) )
63 {
64 if ( 1 == authuser_verify( sql_clean($_POST['username']), sql_clean($_POST['password'])))
65 {
66 $type = "user";
67 $authid = $_POST['username'];
68 }
69 else
70 {
71 print json_encode( array( 'response' => 'failed', 'cause' => 'unauthorized', 'description' => 'Login failed') );
72 exit;
73 }
74 }
75 else if ( array_key_exists('api_key', $_POST) )
76 {
77 if ( verify_apikey( sql_clean( $_POST['api_key'] ) ) == 1 )
78 {
79 $type = "key";
80 $authid = $_POST['api_key'];
81 }
82 else
83 {
84 print json_encode( array( 'response' => 'failed', 'cause' => 'unauthorized', 'description' => 'Login failed') );
85 exit;
86 }
87 }
88 else
89 {
90 print json_encode ( array( 'response' => 'invalid') );
91 break;
92 }
93 $session_name = set_credentials( $authid, $type );
94 $auth_key = update_authkey( $session_name, $authid );
95 print json_encode( array( 'response' => 'ok', 'session' => $session_name, 'auth_key' => $auth_key ));
96 break;
97 case "/logout":
98 // De-authenticate/deauthorize the ongoing session.
99 // I.e. destroy session data, remove session cookies.
100 $session_name = "";
101 if ( array_key_exists('session', $_POST ) )
102 $session_name = $_POST['session'];
103 session_name($session_name);
104 session_start();
105 clear_credentials($session_name);
106
107 if ( $_SESSION )
108 print json_encode ( array( 'response' => 'wtffailed?') );
109 else
110 print json_encode ( array( 'response' => 'ok') );
111 break;
112 default:
113 print json_encode ( array( 'response' => 'invalid') );
114 }
115 }
116 else
117 {
118 token_auth();
119
120 switch ( $_SERVER['PATH_INFO'] )
121 {
122 case "/ping":
123 // API clients are required to periodically ping the server
124 // The time between pings (interval) is 5 minutes?
125 // A ping call refreshes cookie lifetimes, then
126 // generates and stores a new auth_key
127 // The ping required a valid session...
128 // A successful ping returns a 'response' => 'pong'
129 // along with the new auth_key.
130 $session_name = $_POST['session'];
131 $authid = $_SESSION['authid'];
132 $auth_key = update_authkey( $session_name, $authid );
133 print json_encode( array( 'response' => 'pong', 'auth_key' => $auth_key ));
134 break;
135 case "/new_apikey":
136 // If the current authorization has write access, create
137 // a new API key with requested access (ro/rw).
138 if ( ! can_write() )
139 simple_authfail();
140
141 if ( array_key_exists('host_ip', $_POST )
142 && array_key_exists('access', $_POST ))
143 {
144 $host = $_POST['host_ip'];
145 $access = $_POST['access'];
146
147 if (! preg_match("/^[0-9]{1,3}\.[0-9]{1,3}\.[0-9]{1,3}\.[0-9]{1,3}$/", $host) || ! authlevel_value( $access ) )
148 {
149 print json_encode ( array( 'response' => 'invalid', 'cause' => 'parameters' ) );
150 break;
151 }
152 $level = authlevel_value( $access );
153 $key = add_apikey( $host, $level );
154 if ( ! $key )
155 {
156 print json_encode( array( 'response' => 'failed', 'cause' => 'error', 'detail' => 'Database error.'));
157 break;
158 }
159 print json_encode( array( 'response' => 'ok', 'key' => $key, 'host' => $host, 'access' => authlevel_name( get_authorization( "key", $key ) ) ) );
160 break;
161 }
162 else print json_encode ( array( 'response' => 'invalid') );
163 break;
164 case "/remove_apikey":
165 // If the current authorization has write access,
166 // remove the given API key.
167 if ( ! can_write() )
168 simple_authfail();
169
170 if ( array_key_exists('api_key', $_POST ) )
171 {
172 $key = sql_clean( $_POST['api_key'] );
173 // Perform a key-verification, skipping host/remote-address check.
174 if ( ! verify_apikey( $key, true ) )
175 {
176 print json_encode( array ( 'response' => 'failed', 'cause' => 'nonexistant'));
177 break;
178 }
179 if ( ! remove_apikey( $key ) )
180 {
181 print json_encode( array( 'response' => 'failed', 'cause' => 'error', 'detail' => 'Database error.'));
182 break;
183 }
184 print json_encode( array( 'response' => 'ok', 'key' => $key ) );
185 break;
186 }
187 else print json_encode ( array( 'response' => 'invalid') );
188 break;
189 case "/list_apikeys":
190 // List valid API keys.
191 // Fail is current authorization does not have write access.
192 if ( ! can_write() )
193 simple_authfail();
194 $list = list_apikeys();
195 print json_encode( array( 'response' => 'ok', 'list' => $list ) );
196 break;
197 case "/authorize_user":
198 // Add or update a valid back-end user in authorization
199 // if the current authentication has write access.
200 // Since the user exists in backend, the only
201 // needed parameters should be username and access level
202 // If the authorization does not exist, add it.
203 // If the user is already authorized, replace access level.
204 if ( ! can_write() )
205 simple_authfail();
206
207 if ( array_key_exists('username', $_POST )
208 && array_key_exists('access', $_POST ))
209 {
210 $user = $_POST['username'];
211 $access = $_POST['access'];
212 $level = authlevel_value( $access );
213
214 if ( ! $level )
215 {
216 print json_encode ( array( 'response' => 'invalid', 'cause' => 'parameters' ) );
217 break;
218 }
219 if ( ! authuser_getinfo( $user ) )
220 {
221 print json_encode( array ( 'response' => 'failed', 'cause' => 'nonexistant'));
222 break;
223 }
224
225 if ( ! update_authorization( "user", $user, $level ) )
226 {
227 print json_encode( array( 'response' => 'failed', 'cause' => 'error', 'detail' => 'Database error.'));
228 break;
229 }
230
231 print json_encode( array( 'response' => 'ok', 'user' => $user, 'access' => authlevel_name( get_authorization( "user", $user ) ) ) );
232 break;
233 }
234 else print json_encode ( array( 'response' => 'invalid') );
235 break;
236
237 case "/remove_user":
238 // If the current authentication has write access:
239 // Remove authorization for the given users.
240 // Delete user from backend if backend is read-write.
241 if ( ! can_write() )
242 simple_authfail();
243
244 if ( array_key_exists('username', $_POST ))
245 {
246 $user = $_POST['username'];
247
248 $t_level = get_authorization( "user", $user );
249
250 if ( $t_level && ! remove_authorization( $user ) )
251 {
252 print json_encode( array( 'response' => 'failed', 'cause' => 'error', 'detail' => 'Database error.'));
253 break;
254 }
255 if ( ! authmethod_readonly() )
256 {
257 if ( !authuser_getinfo( $user ) )
258 {
259 print json_encode( array ( 'response' => 'failed', 'cause' => 'nonexistant'));
260 break;
261 }
262 if ( !authuser_delete( $user ) )
263 {
264 print json_encode( array( 'response' => 'failed', 'cause' => 'error', 'detail' => 'Database error.'));
265 break;
266 }
267 }
268
269 print json_encode( array( 'response' => 'ok', 'user' => $user ) );
270 break;
271 }
272 else print json_encode ( array( 'response' => 'invalid') );
273 break;
274
275 case "/list_users":
276 // List valid API user-acounts.
277 // Fail with notauthorized if current authentication
278 // does not have write access.
279 // Should not return users from backend,
280 // but should only return users with authorization.
281 if ( ! can_write() )
282 simple_authfail();
283 $list = list_authusers();
284 print json_encode( array( 'response' => 'ok', 'list' => $list ) );
285 break;
286
287 case "/add_user":
288 // Add user to backend if backend is read-write and
289 // the current authentication has write access.
290 // The created user should be added to authorizations
291 // with an access level of "limited_read (1)"
292 case "/update_user":
293 // Update the given user in the backend, if the backend
294 // is read-write, and the current authentication has
295 // write access.
296 print json_encode ( array( 'response' => 'notimplemented') );
297 break;
298 default:
299 print json_encode ( array( 'response' => 'invalid') );
300 }
301 }
302 //*************************************************************************************
303 mysql_close( $config['sql_link'] );
304 ?>