email.php 19 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514
  1. <?php
  2. /*
  3. FusionPBX
  4. Version: MPL 1.1
  5. The contents of this file are subject to the Mozilla Public License Version
  6. 1.1 (the "License"); you may not use this file except in compliance with
  7. the License. You may obtain a copy of the License at
  8. http://www.mozilla.org/MPL/
  9. Software distributed under the License is distributed on an "AS IS" basis,
  10. WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License
  11. for the specific language governing rights and limitations under the
  12. License.
  13. The Original Code is FusionPBX
  14. The Initial Developer of the Original Code is
  15. Mark J Crane <[email protected]>
  16. Portions created by the Initial Developer are Copyright (C) 2008-2023
  17. the Initial Developer. All Rights Reserved.
  18. Contributor(s):
  19. Mark J Crane <[email protected]>
  20. */
  21. /**
  22. * plugin_email
  23. *
  24. * @method email time based one time password authenticate the user
  25. */
  26. class plugin_email {
  27. /**
  28. * Define variables and their scope
  29. */
  30. public $domain_name;
  31. public $domain_uuid;
  32. public $username;
  33. public $password;
  34. public $user_uuid;
  35. public $user_email;
  36. public $contact_uuid;
  37. public $debug;
  38. /**
  39. * time based one time password with email
  40. * @return array [authorized] => true or false
  41. */
  42. function email() {
  43. //pre-process some settings
  44. $settings['theme']['favicon'] = !empty($_SESSION['theme']['favicon']['text']) ? $_SESSION['theme']['favicon']['text'] : PROJECT_PATH.'/themes/default/favicon.ico';
  45. $settings['login']['destination'] = !empty($_SESSION['login']['destination']['text']) ? $_SESSION['login']['destination']['text'] : '';
  46. $settings['users']['unique'] = !empty($_SESSION['users']['unique']['text']) ? $_SESSION['users']['unique']['text'] : '';
  47. $settings['theme']['logo'] = !empty($_SESSION['theme']['logo']['text']) ? $_SESSION['theme']['logo']['text'] : PROJECT_PATH.'/themes/default/images/logo_login.png';
  48. $settings['theme']['login_logo_width'] = !empty($_SESSION['theme']['login_logo_width']['text']) ? $_SESSION['theme']['login_logo_width']['text'] : 'auto; max-width: 300px';
  49. $settings['theme']['login_logo_height'] = !empty($_SESSION['theme']['login_logo_height']['text']) ? $_SESSION['theme']['login_logo_height']['text'] : 'auto; max-height: 300px';
  50. $settings['theme']['message_delay'] = isset($_SESSION['theme']['message_delay']) ? 1000 * (float) $_SESSION['theme']['message_delay'] : 3000;
  51. $settings['theme']['background_video'] = isset($_SESSION['theme']['background_video'][0]) ? $_SESSION['theme']['background_video'][0] : null;
  52. //set a default template
  53. $_SESSION['domain']['template']['name'] = 'default';
  54. $_SESSION['theme']['menu_brand_image']['text'] = PROJECT_PATH.'/themes/default/images/logo.png';
  55. $_SESSION['theme']['menu_brand_type']['text'] = 'image';
  56. //get the domain
  57. $domain_array = explode(":", $_SERVER["HTTP_HOST"]);
  58. $domain_name = $domain_array[0];
  59. //temp directory
  60. $_SESSION['server']['temp']['dir'] = '/tmp';
  61. //use the session username
  62. if (isset($_SESSION['username'])) {
  63. $_POST['username'] = $_SESSION['username'];
  64. $_REQUEST['username'] = $_SESSION['username'];
  65. }
  66. //request the username
  67. if (!isset($_POST['username']) && !isset($_POST['authentication_code'])) {
  68. //add multi-lingual support
  69. $language = new text;
  70. $text = $language->get(null, '/core/authentication');
  71. //initialize a template object
  72. $view = new template();
  73. $view->engine = 'smarty';
  74. $view->template_dir = $_SERVER["DOCUMENT_ROOT"].PROJECT_PATH.'/core/authentication/resources/views/';
  75. $view->cache_dir = $_SESSION['server']['temp']['dir'];
  76. $view->init();
  77. //assign default values to the template
  78. $view->assign("project_path", PROJECT_PATH);
  79. $view->assign("login_destination_url", $settings['login']['destination']);
  80. $view->assign("favicon", $settings['theme']['favicon']);
  81. $view->assign("login_title", $text['label-username']);
  82. $view->assign("login_username", $text['label-username']);
  83. $view->assign("login_logo_width", $settings['theme']['login_logo_width']);
  84. $view->assign("login_logo_height", $settings['theme']['login_logo_height']);
  85. $view->assign("login_logo_source", $settings['theme']['logo']);
  86. $view->assign("button_login", $text['button-login']);
  87. $view->assign("message_delay", $settings['theme']['message_delay']);
  88. $view->assign("background_video", $settings['theme']['background_video']);
  89. //messages
  90. $view->assign('messages', message::html(true, ' '));
  91. //show the views
  92. $content = $view->render('username.htm');
  93. echo $content;
  94. exit;
  95. }
  96. //show the authentication code view
  97. if (!isset($_POST['authentication_code'])) {
  98. //get the username
  99. //if (!isset($this->username) && isset($_REQUEST['username'])) {
  100. // $this->username = $_REQUEST['username'];
  101. //}
  102. //get the user details
  103. $sql = "select user_uuid, username, user_email, contact_uuid \n";
  104. $sql .= "from v_users\n";
  105. $sql .= "where (\n";
  106. $sql .= " username = :username\n";
  107. $sql .= " or user_email = :username\n";
  108. $sql .= ")\n";
  109. if ($settings['users']['unique'] != "global") {
  110. //unique username per domain (not globally unique across system - example: email address)
  111. $sql .= "and domain_uuid = :domain_uuid ";
  112. $parameters['domain_uuid'] = $_SESSION["domain_uuid"];
  113. }
  114. $sql .= "and (user_type = 'default' or user_type is null) ";
  115. $parameters['username'] = $_REQUEST['username'];
  116. $database = new database;
  117. $row = $database->select($sql, $parameters, 'row');
  118. unset($parameters);
  119. //set class variables
  120. //if (!empty($row["user_email"])) {
  121. // $this->user_uuid = $row['user_uuid'];
  122. // $this->user_email = $row['user_email'];
  123. // $this->contact_uuid = $row['contact_uuid'];
  124. //}
  125. //set a few session variables
  126. $_SESSION["user_uuid"] = $row['user_uuid'];
  127. $_SESSION["username"] = $row['username'];
  128. $_SESSION["user_email"] = $row['user_email'];
  129. $_SESSION["contact_uuid"] = $row["contact_uuid"];
  130. //user not found
  131. if (empty($row) || !is_array($row) || @sizeof($row) == 0) {
  132. //clear submitted usernames
  133. unset($this->username, $_SESSION['username'], $_REQUEST['username'], $_POST['username']);
  134. //clear authentication session
  135. unset($_SESSION['authentication']);
  136. //build the result array
  137. $result["plugin"] = "email";
  138. $result["domain_uuid"] = $_SESSION["domain_uuid"];
  139. $result["domain_name"] = $_SESSION["domain_name"];
  140. $result["authorized"] = false;
  141. //retun the array
  142. return $result;
  143. }
  144. //user email not found
  145. else if (empty($row["user_email"])) {
  146. //clear submitted usernames
  147. unset($this->username, $_SESSION['username'], $_REQUEST['username'], $_POST['username']);
  148. //clear authentication session
  149. unset($_SESSION['authentication']);
  150. //build the result array
  151. $result["plugin"] = "email";
  152. $result["domain_name"] = $_SESSION["domain_name"];
  153. $result["username"] = $_REQUEST['username'];
  154. $result["user_uuid"] = $_SESSION["user_uuid"];
  155. $result["domain_uuid"] = $_SESSION["domain_uuid"];
  156. $result["contact_uuid"] = $_SESSION["contact_uuid"];
  157. $result["authorized"] = false;
  158. //add the failed login to user logs
  159. user_logs::add($result);
  160. //return the array
  161. return $result;
  162. }
  163. //authentication code
  164. $_SESSION["user"]["authentication"]["email"]["code"] = generate_password(6, 1);
  165. $_SESSION["user"]["authentication"]["email"]["epoch"] = time();
  166. //$_SESSION["authentication_address"] = $_SERVER['REMOTE_ADDR'];
  167. //$_SESSION["authentication_date"] = 'now()';
  168. //set the authentication code
  169. //$sql = "update v_users \n";
  170. //$sql .= "set auth_code = :auth_code \n";
  171. //$sql .= "where user_uuid = :user_uuid;";
  172. //$parameters['auth_code'] = $auth_code_hash;
  173. //$parameters['user_uuid'] = $this->user_uuid;
  174. //$database->execute($sql, $parameters);
  175. //unset($sql);
  176. //email settings
  177. //$email_address = $this->user_email;
  178. //$email_subject = 'Validation Code';
  179. //$email_body = 'Validation Code: '.$authentication_code;
  180. //send email with the authentication_code
  181. //ob_start();
  182. //$sent = !send_email($email_address, $email_subject, $email_body, $email_error, null, null, 3, 3) ? false : true;
  183. //$response = ob_get_clean();
  184. //get the language code
  185. $language_code = $_SESSION['domain']['language']['code'];
  186. //get the email template from the database
  187. $sql = "select template_subject, template_body ";
  188. $sql .= "from v_email_templates ";
  189. $sql .= "where (domain_uuid = :domain_uuid or domain_uuid is null) ";
  190. $sql .= "and template_language = :template_language ";
  191. $sql .= "and template_category = :template_category ";
  192. $sql .= "and template_subcategory = :template_subcategory ";
  193. $sql .= "and template_type = :template_type ";
  194. $sql .= "and template_enabled = 'true' ";
  195. $parameters['domain_uuid'] = $_SESSION["domain_uuid"];
  196. $parameters['template_language'] = $language_code;
  197. $parameters['template_category'] = 'authentication';
  198. $parameters['template_subcategory'] = 'email';
  199. $parameters['template_type'] = 'html';
  200. $database = new database;
  201. $row = $database->select($sql, $parameters, 'row');
  202. $email_subject = $row['template_subject'];
  203. $email_body = $row['template_body'];
  204. unset($sql, $parameters, $row);
  205. //replace variables in email subject
  206. $email_subject = str_replace('${domain_name}', $_SESSION["domain_name"], $email_subject);
  207. //replace variables in email body
  208. $email_body = str_replace('${domain_name}', $_SESSION["domain_name"], $email_body);
  209. $email_body = str_replace('${auth_code}', $_SESSION["user"]["authentication"]["email"]["code"], $email_body);
  210. //get the email from name and address
  211. $email_from_address = $_SESSION['email']['smtp_from']['text'];
  212. $email_from_name = $_SESSION['email']['smtp_from_name']['text'];
  213. //get the email send mode options: direct or email_queue
  214. $email_send_mode = $_SESSION['authentication']['email_send_mode']['text'] ?? 'email_queue';
  215. //send the email
  216. if ($email_send_mode == 'email_queue') {
  217. //set the variables
  218. $email_queue_uuid = uuid();
  219. $email_uuid = uuid();
  220. $hostname = gethostname();
  221. //add the temporary permissions
  222. $p = new permissions;
  223. $p->add("email_queue_add", 'temp');
  224. $p->add("email_queue_edit", 'temp');
  225. $array['email_queue'][0]["email_queue_uuid"] = $email_queue_uuid;
  226. $array['email_queue'][0]["domain_uuid"] = $_SESSION["domain_uuid"];
  227. $array['email_queue'][0]["hostname"] = $hostname;
  228. $array['email_queue'][0]["email_date"] = 'now()';
  229. $array['email_queue'][0]["email_from"] = $email_from_address;
  230. $array['email_queue'][0]["email_to"] = $_SESSION["user_email"];
  231. $array['email_queue'][0]["email_subject"] = $email_subject;
  232. $array['email_queue'][0]["email_body"] = $email_body;
  233. $array['email_queue'][0]["email_status"] = 'waiting';
  234. $array['email_queue'][0]["email_retry_count"] = 3;
  235. $array['email_queue'][0]["email_uuid"] = $email_uuid;
  236. $array['email_queue'][0]["email_action_before"] = null;
  237. $array['email_queue'][0]["email_action_after"] = null;
  238. $database = new database;
  239. $database->app_name = 'email queue';
  240. $database->app_uuid = '5befdf60-a242-445f-91b3-2e9ee3e0ddf7';
  241. $database->save($array);
  242. $err = $database->message;
  243. unset($array);
  244. //remove the temporary permission
  245. $p->delete("email_queue_add", 'temp');
  246. $p->delete("email_queue_edit", 'temp');
  247. }
  248. else {
  249. //send email - direct
  250. $email = new email;
  251. $email->recipients = $_SESSION["user_email"];
  252. $email->subject = $email_subject;
  253. $email->body = $email_body;
  254. $email->from_address = $email_from_address;
  255. $email->from_name = $email_from_name;
  256. //$email->attachments = $email_attachments;
  257. $email->debug_level = 0;
  258. $email->method = 'direct';
  259. $sent = $email->send();
  260. }
  261. //debug informations
  262. //$email_response = $email->response;
  263. //$email_error = $email->email_error;
  264. //echo $email_response."<br />\n";
  265. //echo $email_error."<br />\n";
  266. //set a default template
  267. $_SESSION['domain']['template']['name'] = 'default';
  268. $_SESSION['theme']['menu_brand_image']['text'] = PROJECT_PATH.'/themes/default/images/logo.png';
  269. $_SESSION['theme']['menu_brand_type']['text'] = 'image';
  270. //get the domain
  271. $domain_array = explode(":", $_SERVER["HTTP_HOST"]);
  272. $domain_name = $domain_array[0];
  273. //temp directory
  274. $_SESSION['server']['temp']['dir'] = '/tmp';
  275. //create token
  276. //$object = new token;
  277. //$token = $object->create('login');
  278. //add multi-lingual support
  279. $language = new text;
  280. $text = $language->get(null, '/core/authentication');
  281. //initialize a template object
  282. $view = new template();
  283. $view->engine = 'smarty';
  284. $view->template_dir = $_SERVER["DOCUMENT_ROOT"].PROJECT_PATH.'/core/authentication/resources/views/';
  285. $view->cache_dir = $_SESSION['server']['temp']['dir'];
  286. $view->init();
  287. //assign default values to the template
  288. $view->assign("project_path", PROJECT_PATH);
  289. $view->assign("login_destination_url", $settings['login']['destination']);
  290. $view->assign("favicon", $settings['theme']['favicon']);
  291. $view->assign("login_title", $text['label-verify']);
  292. $view->assign("login_email_description", $text['label-email_description']);
  293. $view->assign("login_authentication_code", $text['label-authentication_code']);
  294. $view->assign("login_logo_width", $settings['theme']['login_logo_width']);
  295. $view->assign("login_logo_height", $settings['theme']['login_logo_height']);
  296. $view->assign("login_logo_source", $settings['theme']['logo']);
  297. $view->assign("button_verify", $text['label-verify']);
  298. $view->assign("message_delay", $settings['theme']['message_delay']);
  299. if (!empty($_SESSION['username'])) {
  300. $view->assign("username", $_SESSION['username']);
  301. $view->assign("button_cancel", $text['button-cancel']);
  302. }
  303. //messages
  304. $view->assign('messages', message::html(true, ' '));
  305. //show the views
  306. $content = $view->render('email.htm');
  307. echo $content;
  308. exit;
  309. }
  310. //if authorized then verify
  311. if (isset($_POST['authentication_code'])) {
  312. //check if the authentication code has expired. if expired return false
  313. if (!empty($_SESSION["user"]) && $_SESSION["user"]["authentication"]["email"]["epoch"] + 3 > time()) {
  314. //authentication code expired
  315. $result["plugin"] = "email";
  316. $result["domain_name"] = $_SESSION["domain_name"];
  317. $result["username"] = $_SESSION["username"];
  318. $result["error_message"] = 'code expired';
  319. $result["authorized"] = false;
  320. print_r($result);
  321. return $result;
  322. exit;
  323. }
  324. //get the user details
  325. $sql = "select user_uuid, user_email, contact_uuid\n";
  326. $sql .= "from v_users\n";
  327. $sql .= "where (\n";
  328. $sql .= " username = :username\n";
  329. $sql .= " or user_email = :username\n";
  330. $sql .= ")\n";
  331. if ($settings['users']['unique'] != "global") {
  332. //unique username per domain (not globally unique across system - example: email address)
  333. $sql .= "and domain_uuid = :domain_uuid ";
  334. $parameters['domain_uuid'] = $_SESSION["domain_uuid"];
  335. }
  336. $parameters['username'] = $_SESSION["username"];
  337. $database = new database;
  338. $row = $database->select($sql, $parameters, 'row');
  339. $this->user_uuid = $row['user_uuid'];
  340. $this->user_email = $row['user_email'];
  341. $this->contact_uuid = $row['contact_uuid'];
  342. unset($parameters);
  343. /*
  344. echo 'session code = '.$_SESSION["user"]["authentication"]["email"]["code"].'<br>';
  345. echo 'post code = '.$_POST['authentication_code'].'<br>';
  346. exit;
  347. */
  348. //validate the code
  349. if (!empty($_SESSION["user"]) && $_SESSION["user"]["authentication"]["email"]["code"] === $_POST['authentication_code']) {
  350. $auth_valid = true;
  351. }
  352. else {
  353. $auth_valid = false;
  354. }
  355. //clear posted authentication code
  356. unset($_POST['authentication_code']);
  357. //get the user details
  358. if ($auth_valid) {
  359. //get user data from the database
  360. $sql = "select user_uuid, username, user_email, contact_uuid from v_users ";
  361. $sql .= "where user_uuid = :user_uuid ";
  362. if ($settings['users']['unique'] != "global") {
  363. //unique username per domain (not globally unique across system - example: email address)
  364. $sql .= "and domain_uuid = :domain_uuid ";
  365. $parameters['domain_uuid'] = $_SESSION["domain_uuid"];
  366. }
  367. $parameters['user_uuid'] = $_SESSION["user_uuid"];
  368. $database = new database;
  369. $row = $database->select($sql, $parameters, 'row');
  370. unset($parameters);
  371. //set a few session variables
  372. //$_SESSION["username"] = $row['username']; //setting the username makes it skip the rest of the authentication
  373. //$_SESSION["user_email"] = $row['user_email'];
  374. //$_SESSION["contact_uuid"] = $row["contact_uuid"];
  375. }
  376. else {
  377. // //destroy session
  378. // session_unset();
  379. // session_destroy();
  380. // //$_SESSION['authentication']['plugin']
  381. // //send http 403
  382. // header('HTTP/1.0 403 Forbidden', true, 403);
  383. //
  384. // //redirect to the root of the website
  385. // header("Location: ".PROJECT_PATH."/");
  386. //
  387. // //exit the code
  388. // exit();
  389. //clear submitted usernames
  390. unset($this->username, $_SESSION['username'], $_REQUEST['username'], $_POST['username']);
  391. //clear authentication session
  392. unset($_SESSION['authentication']);
  393. }
  394. /*
  395. //check if user successfully logged in during the interval
  396. //$sql = "select user_log_uuid, timestamp, user_name, user_agent, remote_address ";
  397. $sql = "select count(*) as count ";
  398. $sql .= "from v_user_logs ";
  399. $sql .= "where domain_uuid = :domain_uuid ";
  400. $sql .= "and user_uuid = :user_uuid ";
  401. $sql .= "and user_agent = :user_agent ";
  402. $sql .= "and type = 'login' ";
  403. $sql .= "and result = 'success' ";
  404. $sql .= "and floor(extract(epoch from now()) - extract(epoch from timestamp)) > 3 ";
  405. $sql .= "and floor(extract(epoch from now()) - extract(epoch from timestamp)) < 300 ";
  406. $parameters['domain_uuid'] = $this->domain_uuid;
  407. $parameters['user_uuid'] = $this->user_uuid;
  408. $parameters['user_agent'] = $_SERVER['HTTP_USER_AGENT'];
  409. $database = new database;
  410. $user_log_count = $database->select($sql, $parameters, 'all');
  411. //view_array($user_log_count);
  412. unset($sql, $parameters);
  413. */
  414. //result array
  415. $result["plugin"] = "email";
  416. $result["domain_name"] = $_SESSION["domain_name"];
  417. $result["username"] = $_SESSION["username"];
  418. $result["user_uuid"] = $_SESSION["user_uuid"];
  419. $result["domain_uuid"] = $_SESSION["domain_uuid"];
  420. $result["contact_uuid"] = $_SESSION["contact_uuid"];
  421. $result["authorized"] = $auth_valid ? true : false;
  422. //add the failed login to user logs
  423. if (!$auth_valid) {
  424. user_logs::add($result);
  425. }
  426. //retun the array
  427. return $result;
  428. //$_SESSION['authentication']['plugin']['email']['plugin'] = "email";
  429. //$_SESSION['authentication']['plugin']['email']['domain_name'] = $_SESSION["domain_name"];
  430. //$_SESSION['authentication']['plugin']['email']['username'] = $row['username'];
  431. //$_SESSION['authentication']['plugin']['email']['user_uuid'] = $_SESSION["user_uuid"];
  432. //$_SESSION['authentication']['plugin']['email']['contact_uuid'] = $_SESSION["contact_uuid"];
  433. //$_SESSION['authentication']['plugin']['email']['domain_uuid'] = $_SESSION["domain_uuid"];
  434. //$_SESSION['authentication']['plugin']['email']['authorized'] = $auth_valid ? true : false;
  435. }
  436. }
  437. }
  438. ?>