]> git.defcon.no Git - hermes/blob - api/user.php
Moving documentation to doc/
[hermes] / api / user.php
1 <?php
2 require_once('config.php');
3 require_once('lib/user_functions.php');
4 require_once('lib/common_functions.php');
5 require_once('lib/db_functions.php');
6 require_once('lib/phone_functions.php');
7
8 $config = get_config();
9
10 $config['sql_link'] = @mysql_connect(
11 $config['sql_server'],
12 $config['sql_username'],
13 $config['sql_password']
14 );
15 if ( !$config['sql_link'] )
16 {
17 print json_encode( array( 'response' => 'failed', 'cause' => 'error', 'detail' => 'Database connection failed.'));
18 exit;
19 }
20
21 //*************************************************************************************
22 switch ( $_SERVER['PATH_INFO'] )
23 {
24 case "/get":
25 // Required GET parameters:
26 // user: authentication username, SIP-username without domain component
27 // domain: Domain/realm of the user. username + '@' + domain == SIP address.
28
29 if ( array_key_exists('user', $_GET) ||
30 ( array_key_exists('username', $_GET) && array_key_exists('domain', $_GET )))
31 {
32 $username = "";
33 $domain = "";
34 if ( array_key_exists('username', $_GET) )
35 {
36 $username = $_GET['username'];
37 $domain = $_GET['domain'];
38 }
39 else
40 {
41 $user = split_sipaddress($_GET['user']);
42 if ( !$user )
43 {
44 print json_encode ( array( 'response' => 'failed', 'cause' => 'invalid', 'detail' => 'Invalid SIP address') );
45 break;
46 }
47 list ( $username, $domain ) = $user;
48 }
49
50 // Now, do funky stuff.
51 /*
52 Test if user exists in both 'kamailio.subscribers' and 'provision.users'
53 * Return 'response' => 'ok', 'type' => 'local', 'user' => complete user object.
54 Test if user exists in 'provision.user' only
55 * Return 'response' => 'ok', 'type' => 'remote', 'user' => complete user object.
56 If user does is neither local nor remote
57 * Return 'response' => 'failed' with 'cause' => 'nonexistant'
58 On failure, return 'response' => 'failed' with 'cause' => 'error' (may set 'detail' => 'message')
59
60 */
61 // Dummy-response:
62 $userdata = get_userdata( $username, $domain );
63 if ( $userdata )
64 {
65 print json_encode( array( 'response' => 'ok', 'user' => $userdata ));
66 }
67 else
68 {
69 print json_encode( array ( 'response' => 'failed', 'cause' => 'nonexistant', 'detail' => 'Request for user ' . $username . '@' . $domain . ' failed.'));
70 }
71 }
72 else
73 print json_encode ( array( 'response' => 'invalid') );
74 break;
75 case "/list":
76 /*
77 Simply list all users in user@domain format
78 Perform a search operation if 'search' exists as a GET-parameter
79 * The search should try to do a "smart search" on SIP-usernames:
80 * Try to search with names in in username@domain format
81 * Do the search with wildcards before and after input text.
82 * The search must be done in the provisioning tables, to be able
83 to match non-local users.
84 * SQL SELECT CONCAT() WHERE CONCAT() must be used *shrug*
85 */
86 $search = null;
87 if ( array_key_exists ( 'search', $_GET ) )
88 $search = $_GET['search']; // TODO: Add some sanitation and input validation!
89 $list = list_users( $search );
90 print json_encode( array( 'response' => 'ok', 'list' => $list ));
91 break;
92 case "/add_local":
93 /*
94 What to do??
95 Required parameters should be...
96 ( username & domain ) | user
97 displayname
98 email
99
100 Verify that domain is local (lookup in the 'kamailio.domain' table.
101 Verify that the username is available (nonexistant for domain in kamilio.subscribers (and provision.users?))
102 * Autocreate password
103 * Add username, domain, email and created password to the 'kamailio.subscriber' table
104 * Get the registrar+port, proxy+port from the 'provision.servers' table.
105 * standard dialplan from configuration.
106 * Add to the 'provision.users' table:
107 username -> username
108 password -> generated password
109 displayname -> displayname
110 domain -> domain
111 registrar -> provision.servers.registrar
112 r_port -> provision.servers.r_port
113 proxy -> provision.servers.proxy
114 p_port -> provision.servers.p_port
115 authid -> username
116 dialplan -> standard dialplan
117 linetext -> username
118 * Return 'response' => 'ok' with a full user object in JSON format.
119 If any of the tests fail, return 'response' => 'failed' with 'cause' => "description" on JSON format.
120
121 */
122 // Test required parameters:
123 if (
124 ( ( array_key_exists( 'username', $_GET) && array_key_exists( 'domain', $_GET ) ) || array_key_exists('user', $_GET) )
125 && array_key_exists( 'displayname', $_GET )
126 && array_key_exists( 'email', $_GET ) )
127 {
128 $username = "";
129 $domain = "";
130 if ( array_key_exists('username', $_GET) )
131 {
132 $username = $_GET['username'];
133 $domain = $_GET['domain'];
134 }
135 else
136 {
137 $user = split_sipaddress($_GET['user']);
138 if ( !$user )
139 {
140 print json_encode ( array( 'response' => 'failed', 'cause' => 'invalid', 'detail' => 'Invalid SIP address') );
141 break;
142 }
143 list ( $username, $domain ) = $user;
144 }
145
146 $password = generate_password();
147 $displayname = $_GET['displayname'];
148 $email = $_GET['email'];
149
150 if ( !is_kamailio_domain( $domain ) )
151 {
152 print json_encode ( array( 'response' => 'failed', 'cause' => 'nxdomain', 'detail' => 'The selected domain is not local' ));
153 break;
154 }
155
156 $servers = get_servers( $domain );
157 if ( !$servers )
158 {
159 print json_encode( array( 'response' => 'failed', 'cause' => 'servfail', 'detail' => 'Servers lookup failed for domain '. $domain ) );
160 break;
161 }
162 $registrar = $servers['registrar'];
163 $r_port = $servers['r_port'];
164 $proxy = $servers['proxy'];
165 $p_port = $servers['p_port'];
166 $authid = $username;
167 $linetext = $username;
168 $dialplan = $config['standard_dialplan'];
169
170 if ( is_provision_user ( $username, $domain ) )
171 {
172 print json_encode ( array( 'response' => 'failed', 'cause' => 'exists', 'detail' => 'User already exists in provisioning configuration' ));
173 break;
174 }
175 if ( is_kamailio_subscriber ( $username, $domain ) )
176 {
177 print json_encode ( array( 'response' => 'failed', 'cause' => 'exists', 'detail' => 'User already exists as a Kamailio subscriber' ));
178 break;
179 }
180 $kam_res = add_kamailio_subscriber( $username, $domain, $password, $email );
181 if ( !$kam_res )
182 {
183 print json_encode( array( 'response' => 'failed', 'cause' => 'dbfail', 'detail' => 'Failed to add kamailio subscriber.' ) );
184 break;
185 }
186 $pro_res = add_provision_user( $username, $password, $domain, $authid, $registrar, $r_port, $proxy, $p_port, $displayname, $dialplan, $linetext );
187 if ( !$pro_res )
188 {
189 // Rollback data added to Kamailio! Try to simulate atomicity, or atleast maintain integrity...
190 delete_kamailio_subscriber( $username, $domain );
191 // Give errormessage, and quit.
192 print json_encode( array( 'response' => 'failed', 'cause' => 'dbfail', 'detail' => 'Failed to add user for provisioning. Rolled back kamailio subscriber' ) );
193 break;
194 }
195 $userdata = get_userdata( $username, $domain );
196 if ( !$userdata )
197 {
198 // Rollback data added to Kamailio! Try to simulate atomicity, or atleast maintain integrity...
199 delete_kamailio_subscriber( $username, $domain );
200 delete_provision_user( $username, $domain );
201 // Give errormessage, and quit.
202 print json_encode( array( 'response' => 'failed', 'cause' => 'dbfail', 'detail' => 'Failed to read recently added data. Operations rolled back' ) );
203
204 }
205 print json_encode( array( 'response' => 'ok', 'user' => $userdata ));
206 }
207 else
208 print json_encode( array( 'response' => 'invalid', 'cause' => 'parameters' ) );
209 break;
210 case "/add_remote":
211 /*
212 Required parameters should be...
213 ( username & domain ) | user
214 displayname
215 password
216 registrar
217 Optional parameters
218 r_port
219 proxy
220 p_port
221 authid
222 dialplan
223 linetext
224
225 Verify that the domain is not a local kamailio domain (REMOTE user..)
226 Verify that the username+domain is not already registered in 'provision.users'.
227 * If r_port is empty, set to 5060
228 * If proxy/port is empty, set to registrar/port
229 * If authid is empty, set to username
230 * If dialplan is empty, set to standard dialplan
231 * If linetext is empty, set to username@domain
232 * Add to the 'provision.users' table:
233 username -> username
234 password -> supplied password
235 displayname -> displayname
236 domain -> domain
237 registrar -> registrar
238 r_port -> r_port
239 proxy -> proxy
240 p_port -> p_port
241 authid -> authid
242 dialplan -> dialplan
243 linetext -> linetext
244 * Return 'response' => 'ok' with a full user object in JSON format.
245 If any of the tests fail, return 'response' => 'failed' with 'cause' => "description" in JSON format.
246 */
247
248
249 // Test required parameters:
250 if (
251 ( ( array_key_exists( 'username', $_GET) && array_key_exists( 'domain', $_GET ) ) || array_key_exists('user', $_GET) )
252 && array_key_exists( 'displayname', $_GET )
253 && array_key_exists( 'password', $_GET )
254 && array_key_exists( 'registrar', $_GET ) )
255 {
256 $username = "";
257 $domain = "";
258 if ( array_key_exists('username', $_GET) )
259 {
260 $username = $_GET['username'];
261 $domain = $_GET['domain'];
262 }
263 else
264 {
265 $user = split_sipaddress($_GET['user']);
266 if ( !$user )
267 {
268 print json_encode ( array( 'response' => 'failed', 'cause' => 'invalid', 'detail' => 'Invalid SIP address') );
269 break;
270 }
271 list ( $username, $domain ) = $user;
272 }
273
274 $password = $_GET['password'];
275 $displayname = $_GET['displayname'];
276 $registrar = $_GET['registrar'];
277 $r_port = ( array_key_exists('r_port', $_GET) ) ? $_GET['r_port'] : 5060;
278
279 $proxy = ( array_key_exists('proxy', $_GET) ) ? $_GET['proxy'] : $registrar;
280 $p_port = ( array_key_exists('p_port', $_GET) ) ? $_GET['p_port'] : $r_port;
281 $authid = ( array_key_exists('authid', $_GET) ) ? $_GET['authid'] : $username;
282 $dialplan = ( array_key_exists('dialplan', $_GET) ) ? $_GET['dialplan'] : $config['standard_dialplan'];
283 $linetext = ( array_key_exists('linetext', $_GET) ) ? $_GET['linetext'] : $username . '@' . $domain;
284
285 if ( is_kamailio_domain( $domain ) )
286 {
287 print json_encode ( array( 'response' => 'failed', 'cause' => 'domain', 'detail' => 'The selected domain is local, cannot add remote user' ));
288 break;
289 }
290
291 if ( is_provision_user ( $username, $domain ) )
292 {
293 print json_encode ( array( 'response' => 'failed', 'cause' => 'exists', 'detail' => 'User already exists in provisioning configuration' ));
294 break;
295 }
296 if ( is_kamailio_subscriber ( $username, $domain ) )
297 {
298 print json_encode ( array( 'response' => 'failed', 'cause' => 'exists', 'detail' => 'User already exists as a Kamailio subscriber' ));
299 break;
300 }
301
302 $pro_res = add_provision_user( $username, $password, $domain, $authid, $registrar, $r_port, $proxy, $p_port, $displayname, $dialplan, $linetext );
303 if ( !$pro_res )
304 {
305 // Give errormessage, and quit.
306 print json_encode( array( 'response' => 'failed', 'cause' => 'dbfail', 'detail' => 'Failed to add user for provisioning.' ) );
307 break;
308 }
309 $userdata = get_userdata( $username, $domain );
310 if ( !$userdata )
311 {
312 // Rollback data added!
313 delete_provision_user( $username, $domain );
314 // Give errormessage, and quit.
315 print json_encode( array( 'response' => 'failed', 'cause' => 'dbfail', 'detail' => 'Failed to read recently added data. Operations rolled back' ) );
316
317 }
318 print json_encode( array( 'response' => 'ok', 'user' => $userdata ));
319 }
320 else
321 print json_encode( array( 'response' => 'invalid', 'cause' => 'parameters' ) );
322 break;
323 case "/remove":
324 /*
325 Required parameters should be...
326 ( username & domain ) | user
327
328 * Verify that no associations/relations exist in 'provision.phones'
329 * Verify that the user exists in 'provision.users'
330 * Remove from 'provision.users'
331 * Test to see of user exists in 'kamailio.subscriber'.
332 * Remove from 'kamailio.subscribers'
333 * Return response' => 'ok', 'type' => 'local'
334 * If not in 'kamailio.subscribers'
335 * Return response' => 'ok', 'type' => 'remote'
336 * If associations exist, return 'response' => 'failed', 'cause' => 'inuse'
337 * If no such user exists, return 'response' => 'failed' with 'cause' => 'nonexistant'
338 * On other failures, return 'response' => 'failed' with 'cause' => 'error' (may set 'detail' => 'message')
339 */
340 if ( ( array_key_exists( 'username', $_GET) && array_key_exists( 'domain', $_GET ) )
341 || array_key_exists('user', $_GET) )
342
343 {
344 $username = "";
345 $domain = "";
346 if ( array_key_exists('username', $_GET) )
347 {
348 $username = $_GET['username'];
349 $domain = $_GET['domain'];
350 }
351 else
352 {
353 $user = split_sipaddress($_GET['user']);
354 if ( !$user )
355 {
356 print json_encode ( array( 'response' => 'failed', 'cause' => 'invalid', 'detail' => 'Invalid SIP address') );
357 break;
358 }
359 list ( $username, $domain ) = $user;
360 }
361
362 if ( get_user_phones ( $username, $domain ) )
363 {
364 print json_encode( array( 'response' => 'failed', 'cause' => 'inuse', 'detail' => 'User has associated provisioning. Remove and retry.' ) );
365 break;
366 }
367 if ( is_provision_user( $username, $domain ) || is_kamailio_subscriber( $username, $domain ) )
368 {
369 delete_provision_user( $username, $domain );
370 delete_kamailio_subscriber( $username, $domain );
371 print json_encode( array ( 'response' => 'ok', 'detail' => 'User ' . $username . '@' . $domain . ' deleted.'));
372 break;
373 }
374 else
375 {
376 print json_encode( array ( 'response' => 'failed', 'cause' => 'nonexistant', 'detail' => 'Unable to remove nonexistant user.'));
377 break;
378 }
379
380 break;
381
382 }
383 print json_encode ( array( 'response' => 'invalid') );
384 break;
385 case "/change_pw":
386 /*
387 Required parameters should be...
388 ( username & domain ) | user
389 password
390
391 * Verify that no associations/relations exist in 'provision.phones'
392 * Verify that the user exists ...
393 * Test to see of user exists in 'provision.users'
394 * Test to see of user exists in 'kamailio.subscriber'.
395 * If no such user exists, return 'response' => 'failed' with 'cause' => 'nonexistant'
396 * Update user passwords in 'provision' and 'kamailio' as appropriate
397 * On other failures, return 'response' => 'failed' with 'cause' => 'error' (may set 'detail' => 'message')
398 */
399 if ( array_key_exists('password', $_GET) &&
400 ( ( array_key_exists( 'username', $_GET) && array_key_exists( 'domain', $_GET ) )
401 || array_key_exists('user', $_GET) ))
402
403 {
404 $username = "";
405 $domain = "";
406 if ( array_key_exists('username', $_GET) )
407 {
408 $username = $_GET['username'];
409 $domain = $_GET['domain'];
410 }
411 else
412 {
413 $user = split_sipaddress($_GET['user']);
414 if ( !$user )
415 {
416 print json_encode ( array( 'response' => 'failed', 'cause' => 'invalid', 'detail' => 'Invalid SIP address') );
417 break;
418 }
419 list ( $username, $domain ) = $user;
420 }
421 $password = $_GET['password'];
422
423 // Check compatibility of password? TODO...
424 // Fetch old password for rollback? TODO...
425 // Verify that user exists for provisioning
426 if ( ! is_provision_user( $username, $domain ) )
427 {
428 print json_encode( array ( 'response' => 'failed', 'cause' => 'nonexistant', 'detail' => '' . $username . '@' . $domain . ' does not exist.'));
429 break;
430 }
431 if ( is_provision_user( $username, $domain ) )
432 {
433 // Update provisioning password
434 if ( update_provision_pw( $username, $domain, $password ) < 0 )
435 {
436 print json_encode( array( 'response' => 'failed', 'cause' => 'dbfail', 'detail' => 'Failed to update provisioning password' ) );
437 break;
438 }
439 }
440 // Check for user in kamailio
441 if ( is_kamailio_subscriber( $username, $domain ) )
442 {
443 // Update kamailio password
444 if ( update_kamailio_pw( $username, $domain, $password ) < 0 )
445 {
446 print json_encode( array( 'response' => 'failed', 'cause' => 'dbfail', 'detail' => 'Failed to update kamailio password' ) );
447 break;
448 }
449 }
450 print json_encode( array ( 'response' => 'ok', 'detail' => 'Password changed for user '.$username.'@'.$domain.'.'));
451 break;
452 }
453 else
454 print json_encode( array( 'response' => 'invalid', 'cause' => 'parameters' ) );
455 break;
456
457
458 case "/change_email":
459 /*
460 Required parameters should be...
461 ( username & domain ) | user
462 email
463 */
464 if ( array_key_exists('email', $_GET) &&
465 ( ( array_key_exists( 'username', $_GET) && array_key_exists( 'domain', $_GET ) )
466 || array_key_exists('user', $_GET) ))
467
468 {
469 $username = "";
470 $domain = "";
471 if ( array_key_exists('username', $_GET) )
472 {
473 $username = $_GET['username'];
474 $domain = $_GET['domain'];
475 }
476 else
477 {
478 $user = split_sipaddress($_GET['user']);
479 if ( !$user )
480 {
481 print json_encode ( array( 'response' => 'failed', 'cause' => 'invalid', 'detail' => 'Invalid SIP address') );
482 break;
483 }
484 list ( $username, $domain ) = $user;
485 }
486 $email = $_GET['email'];
487
488 // Check for user in kamailio
489 if ( is_kamailio_subscriber( $username, $domain ) )
490 {
491 // Update kamailio email
492 if ( update_kamailio_email( $username, $domain, $email ) < 0 )
493 {
494 print json_encode( array( 'response' => 'failed', 'cause' => 'dbfail', 'detail' => 'Failed to update kamailio email' ) );
495 break;
496 }
497 }
498 print json_encode( array ( 'response' => 'ok', 'user' => $username.'@'.$domain, 'email' => $email));
499 break;
500 }
501 else
502 print json_encode( array( 'response' => 'invalid', 'cause' => 'parameters' ) );
503 break;
504
505
506
507
508
509
510
511 case "/update":
512 /*
513 Required parameters should be...
514 ( username & domain ) | user
515
516 * Verify that no associations/relations exist in 'provision.phones'
517 * Verify that the user exists ...
518 * Test to see of user exists in 'provision.users'
519 * Test to see of user exists in 'kamailio.subscriber'.
520 * If no such user exists, return 'response' => 'failed' with 'cause' => 'nonexistant'
521 * Get update parameters, and change as appropriate ;)
522 * On other failures, return 'response' => 'failed' with 'cause' => 'error' (may set 'detail' => 'message')
523 */
524 if ( ( array_key_exists( 'username', $_GET) && array_key_exists( 'domain', $_GET ) )
525 || array_key_exists('user', $_GET) )
526
527 {
528 $username = "";
529 $domain = "";
530 if ( array_key_exists('username', $_GET) )
531 {
532 $username = $_GET['username'];
533 $domain = $_GET['domain'];
534 }
535 else
536 {
537 $user = split_sipaddress($_GET['user']);
538 if ( !$user )
539 {
540 print json_encode ( array( 'response' => 'failed', 'cause' => 'invalid', 'detail' => 'Invalid SIP address') );
541 break;
542 }
543 list ( $username, $domain ) = $user;
544 }
545 if ( ! is_provision_user ( $username, $domain ) )
546 {
547 print json_encode( array ( 'response' => 'failed', 'cause' => 'nonexistant', 'detail' => '' . $username . '@' . $domain . ' does not exist.'));
548 break;
549 }
550 $updated = array();
551 $failed = array();
552 $error = 1;
553 $result_text = "";
554 $params = array('displayname', 'dialplan', 'linetext', 'registrar', 'r_port', 'proxy', 'p_port');
555 foreach ( $params as $p )
556 {
557 if ( array_key_exists($p, $_GET ) )
558 {
559 $data = $_GET[$p];
560 $t = update_provision_data($p, $username, $domain, $data);
561 if ( $t != true )
562 {
563 $error = $t;
564 array_push($failed, $p);
565 }
566 else
567 {
568 array_push( $updated, $p);
569 }
570 }
571 }
572 $res = array();
573 if ( ( $error == 1 ) || ( $error == 0 ) )
574 {
575 $res['response'] = 'ok';
576 $res['skipped'] = $failed;
577 }
578 else if ( $error == -1 )
579 {
580 $res['response'] = 'failed';
581 $res['cause'] = 'param';
582 $res['detail'] = 'Invalid parameters';
583 $res['failed'] = $failed;
584 }
585 else if ( $error == -2 )
586 {
587 $res['response'] = 'failed';
588 $res['cause'] = 'dbfail';
589 $res['detail'] = 'Database failure';
590 $res['failed'] = $failed;
591 }
592 else
593 $res['response'] = 'error'; // Wait, what?
594
595 $res['updated'] = $updated;
596
597 print json_encode ( $res );
598 }
599 else
600 print json_encode( array( 'response' => 'invalid', 'cause' => 'parameters' ) );
601 break;
602 case "/gen_pw":
603 print generate_password();
604 break;
605 default:
606 print json_encode ( array( 'response' => 'invalid') );
607 }
608 mysql_close( $config['sql_link'] );
609 ?>