email.php 20 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525
  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-2024
  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. //get the domain
  53. $domain_array = explode(":", $_SERVER["HTTP_HOST"]);
  54. $domain_name = $domain_array[0];
  55. //use the session username
  56. if (isset($_SESSION['username'])) {
  57. $_POST['username'] = $_SESSION['username'];
  58. $_REQUEST['username'] = $_SESSION['username'];
  59. }
  60. //request the username
  61. if (!isset($_POST['username']) && !isset($_POST['authentication_code'])) {
  62. //add multi-lingual support
  63. $language = new text;
  64. $text = $language->get(null, '/core/authentication');
  65. //initialize a template object
  66. $view = new template();
  67. $view->engine = 'smarty';
  68. $view->template_dir = $_SERVER["DOCUMENT_ROOT"].PROJECT_PATH.'/core/authentication/resources/views/';
  69. $view->cache_dir = sys_get_temp_dir();
  70. $view->init();
  71. //assign default values to the template
  72. $view->assign("project_path", PROJECT_PATH);
  73. $view->assign("login_destination_url", $settings['login']['destination']);
  74. $view->assign("favicon", $settings['theme']['favicon']);
  75. $view->assign("login_title", $text['label-username']);
  76. $view->assign("login_username", $text['label-username']);
  77. $view->assign("login_logo_width", $settings['theme']['login_logo_width']);
  78. $view->assign("login_logo_height", $settings['theme']['login_logo_height']);
  79. $view->assign("login_logo_source", $settings['theme']['logo']);
  80. $view->assign("button_login", $text['button-login']);
  81. $view->assign("message_delay", $settings['theme']['message_delay']);
  82. $view->assign("background_video", $settings['theme']['background_video']);
  83. //messages
  84. $view->assign('messages', message::html(true, ' '));
  85. //show the views
  86. $content = $view->render('username.htm');
  87. echo $content;
  88. exit;
  89. }
  90. //show the authentication code view
  91. if (!isset($_POST['authentication_code'])) {
  92. //get the username
  93. //if (!isset($this->username) && isset($_REQUEST['username'])) {
  94. // $this->username = $_REQUEST['username'];
  95. //}
  96. //get the user details
  97. $sql = "select user_uuid, username, user_email, contact_uuid \n";
  98. $sql .= "from v_users\n";
  99. $sql .= "where (\n";
  100. $sql .= " username = :username\n";
  101. $sql .= " or user_email = :username\n";
  102. $sql .= ")\n";
  103. if ($settings['users']['unique'] != "global") {
  104. //unique username per domain (not globally unique across system - example: email address)
  105. $sql .= "and domain_uuid = :domain_uuid ";
  106. $parameters['domain_uuid'] = $_SESSION["domain_uuid"];
  107. }
  108. $sql .= "and (user_type = 'default' or user_type is null) ";
  109. $parameters['username'] = $_REQUEST['username'];
  110. $database = new database;
  111. $row = $database->select($sql, $parameters, 'row');
  112. unset($parameters);
  113. //set class variables
  114. //if (!empty($row["user_email"])) {
  115. // $this->user_uuid = $row['user_uuid'];
  116. // $this->user_email = $row['user_email'];
  117. // $this->contact_uuid = $row['contact_uuid'];
  118. //}
  119. //set a few session variables
  120. $_SESSION["user_uuid"] = $row['user_uuid'];
  121. $_SESSION["username"] = $row['username'];
  122. $_SESSION["user_email"] = $row['user_email'];
  123. $_SESSION["contact_uuid"] = $row["contact_uuid"];
  124. //user not found
  125. if (empty($row) || !is_array($row) || @sizeof($row) == 0) {
  126. //clear submitted usernames
  127. unset($this->username, $_SESSION['username'], $_REQUEST['username'], $_POST['username']);
  128. //clear authentication session
  129. unset($_SESSION['authentication']);
  130. //build the result array
  131. $result["plugin"] = "email";
  132. $result["domain_uuid"] = $_SESSION["domain_uuid"];
  133. $result["domain_name"] = $_SESSION["domain_name"];
  134. $result["authorized"] = false;
  135. //retun the array
  136. return $result;
  137. }
  138. //user email not found
  139. else if (empty($row["user_email"])) {
  140. //clear submitted usernames
  141. unset($this->username, $_SESSION['username'], $_REQUEST['username'], $_POST['username']);
  142. //clear authentication session
  143. unset($_SESSION['authentication']);
  144. //build the result array
  145. $result["plugin"] = "email";
  146. $result["domain_name"] = $_SESSION["domain_name"];
  147. $result["username"] = $_REQUEST['username'];
  148. $result["user_uuid"] = $_SESSION["user_uuid"];
  149. $result["domain_uuid"] = $_SESSION["domain_uuid"];
  150. $result["contact_uuid"] = $_SESSION["contact_uuid"];
  151. $result["authorized"] = false;
  152. //add the failed login to user logs
  153. user_logs::add($result);
  154. //return the array
  155. return $result;
  156. }
  157. //authentication code
  158. $_SESSION["user"]["authentication"]["email"]["code"] = generate_password(6, 1);
  159. $_SESSION["user"]["authentication"]["email"]["epoch"] = time();
  160. //$_SESSION["authentication_address"] = $_SERVER['REMOTE_ADDR'];
  161. //$_SESSION["authentication_date"] = 'now()';
  162. //set the authentication code
  163. //$sql = "update v_users \n";
  164. //$sql .= "set auth_code = :auth_code \n";
  165. //$sql .= "where user_uuid = :user_uuid;";
  166. //$parameters['auth_code'] = $auth_code_hash;
  167. //$parameters['user_uuid'] = $this->user_uuid;
  168. //$database->execute($sql, $parameters);
  169. //unset($sql);
  170. //email settings
  171. //$email_address = $this->user_email;
  172. //$email_subject = 'Validation Code';
  173. //$email_body = 'Validation Code: '.$authentication_code;
  174. //send email with the authentication_code
  175. //ob_start();
  176. //$sent = !send_email($email_address, $email_subject, $email_body, $email_error, null, null, 3, 3) ? false : true;
  177. //$response = ob_get_clean();
  178. //get the language code
  179. $language_code = $_SESSION['domain']['language']['code'];
  180. //get the email template from the database
  181. $sql = "select template_subject, template_body ";
  182. $sql .= "from v_email_templates ";
  183. $sql .= "where (domain_uuid = :domain_uuid or domain_uuid is null) ";
  184. $sql .= "and template_language = :template_language ";
  185. $sql .= "and template_category = :template_category ";
  186. $sql .= "and template_subcategory = :template_subcategory ";
  187. $sql .= "and template_type = :template_type ";
  188. $sql .= "and template_enabled = 'true' ";
  189. $parameters['domain_uuid'] = $_SESSION["domain_uuid"];
  190. $parameters['template_language'] = $language_code;
  191. $parameters['template_category'] = 'authentication';
  192. $parameters['template_subcategory'] = 'email';
  193. $parameters['template_type'] = 'html';
  194. $database = new database;
  195. $row = $database->select($sql, $parameters, 'row');
  196. $email_subject = $row['template_subject'];
  197. $email_body = $row['template_body'];
  198. unset($sql, $parameters, $row);
  199. //replace variables in email subject
  200. $email_subject = str_replace('${domain_name}', $_SESSION["domain_name"], $email_subject);
  201. //replace variables in email body
  202. $email_body = str_replace('${domain_name}', $_SESSION["domain_name"], $email_body);
  203. $email_body = str_replace('${auth_code}', $_SESSION["user"]["authentication"]["email"]["code"], $email_body);
  204. //get the email from name and address
  205. $email_from_address = $_SESSION['email']['smtp_from']['text'];
  206. $email_from_name = $_SESSION['email']['smtp_from_name']['text'];
  207. //get the email send mode options: direct or email_queue
  208. $email_send_mode = $_SESSION['authentication']['email_send_mode']['text'] ?? 'email_queue';
  209. //send the email
  210. if ($email_send_mode == 'email_queue') {
  211. //set the variables
  212. $email_queue_uuid = uuid();
  213. $email_uuid = uuid();
  214. $hostname = gethostname();
  215. //add the temporary permissions
  216. $p = permissions::new();
  217. $p->add("email_queue_add", 'temp');
  218. $p->add("email_queue_edit", 'temp');
  219. $array['email_queue'][0]["email_queue_uuid"] = $email_queue_uuid;
  220. $array['email_queue'][0]["domain_uuid"] = $_SESSION["domain_uuid"];
  221. $array['email_queue'][0]["hostname"] = $hostname;
  222. $array['email_queue'][0]["email_date"] = 'now()';
  223. $array['email_queue'][0]["email_from"] = $email_from_address;
  224. $array['email_queue'][0]["email_to"] = $_SESSION["user_email"];
  225. $array['email_queue'][0]["email_subject"] = $email_subject;
  226. $array['email_queue'][0]["email_body"] = $email_body;
  227. $array['email_queue'][0]["email_status"] = 'waiting';
  228. $array['email_queue'][0]["email_retry_count"] = 3;
  229. $array['email_queue'][0]["email_uuid"] = $email_uuid;
  230. $array['email_queue'][0]["email_action_before"] = null;
  231. $array['email_queue'][0]["email_action_after"] = null;
  232. $database = new database;
  233. $database->app_name = 'email queue';
  234. $database->app_uuid = '5befdf60-a242-445f-91b3-2e9ee3e0ddf7';
  235. $database->save($array);
  236. $err = $database->message;
  237. unset($array);
  238. //remove the temporary permission
  239. $p->delete("email_queue_add", 'temp');
  240. $p->delete("email_queue_edit", 'temp');
  241. }
  242. else {
  243. //send email - direct
  244. $email = new email;
  245. $email->recipients = $_SESSION["user_email"];
  246. $email->subject = $email_subject;
  247. $email->body = $email_body;
  248. $email->from_address = $email_from_address;
  249. $email->from_name = $email_from_name;
  250. //$email->attachments = $email_attachments;
  251. $email->debug_level = 0;
  252. $email->method = 'direct';
  253. $sent = $email->send();
  254. }
  255. //debug informations
  256. //$email_response = $email->response;
  257. //$email_error = $email->email_error;
  258. //echo $email_response."<br />\n";
  259. //echo $email_error."<br />\n";
  260. //get the domain
  261. $domain_array = explode(":", $_SERVER["HTTP_HOST"]);
  262. $domain_name = $domain_array[0];
  263. //create token
  264. //$object = new token;
  265. //$token = $object->create('login');
  266. //add multi-lingual support
  267. $language = new text;
  268. $text = $language->get(null, '/core/authentication');
  269. //initialize a template object
  270. $view = new template();
  271. $view->engine = 'smarty';
  272. $view->template_dir = $_SERVER["DOCUMENT_ROOT"].PROJECT_PATH.'/core/authentication/resources/views/';
  273. $view->cache_dir = sys_get_temp_dir();
  274. $view->init();
  275. //assign default values to the template
  276. $view->assign("project_path", PROJECT_PATH);
  277. $view->assign("login_destination_url", $settings['login']['destination']);
  278. $view->assign("favicon", $settings['theme']['favicon']);
  279. $view->assign("login_title", $text['label-verify']);
  280. $view->assign("login_email_description", $text['label-email_description']);
  281. $view->assign("login_authentication_code", $text['label-authentication_code']);
  282. $view->assign("login_logo_width", $settings['theme']['login_logo_width']);
  283. $view->assign("login_logo_height", $settings['theme']['login_logo_height']);
  284. $view->assign("login_logo_source", $settings['theme']['logo']);
  285. $view->assign("button_verify", $text['label-verify']);
  286. $view->assign("message_delay", $settings['theme']['message_delay']);
  287. if (!empty($_SESSION['username'])) {
  288. $view->assign("username", $_SESSION['username']);
  289. $view->assign("button_cancel", $text['button-cancel']);
  290. }
  291. //messages
  292. $view->assign('messages', message::html(true, ' '));
  293. //show the views
  294. $content = $view->render('email.htm');
  295. echo $content;
  296. exit;
  297. }
  298. //if authorized then verify
  299. if (isset($_POST['authentication_code'])) {
  300. //check if the authentication code has expired. if expired return false
  301. if (!empty($_SESSION["user"]) && $_SESSION["user"]["authentication"]["email"]["epoch"] + 3 > time()) {
  302. //authentication code expired
  303. $result["plugin"] = "email";
  304. $result["domain_name"] = $_SESSION["domain_name"];
  305. $result["username"] = $_SESSION["username"];
  306. $result["error_message"] = 'code expired';
  307. $result["authorized"] = false;
  308. print_r($result);
  309. return $result;
  310. exit;
  311. }
  312. //get the user details
  313. $sql = "select user_uuid, user_email, contact_uuid\n";
  314. $sql .= "from v_users\n";
  315. $sql .= "where (\n";
  316. $sql .= " username = :username\n";
  317. $sql .= " or user_email = :username\n";
  318. $sql .= ")\n";
  319. if ($settings['users']['unique'] != "global") {
  320. //unique username per domain (not globally unique across system - example: email address)
  321. $sql .= "and domain_uuid = :domain_uuid ";
  322. $parameters['domain_uuid'] = $_SESSION["domain_uuid"];
  323. }
  324. $parameters['username'] = $_SESSION["username"];
  325. $database = new database;
  326. $row = $database->select($sql, $parameters, 'row');
  327. $this->user_uuid = $row['user_uuid'];
  328. $this->user_email = $row['user_email'];
  329. $this->contact_uuid = $row['contact_uuid'];
  330. unset($parameters);
  331. /*
  332. echo 'session code = '.$_SESSION["user"]["authentication"]["email"]["code"].'<br>';
  333. echo 'post code = '.$_POST['authentication_code'].'<br>';
  334. exit;
  335. */
  336. //validate the code
  337. if (!empty($_SESSION["user"]) && $_SESSION["user"]["authentication"]["email"]["code"] === $_POST['authentication_code']) {
  338. $auth_valid = true;
  339. }
  340. else {
  341. $auth_valid = false;
  342. }
  343. //clear posted authentication code
  344. unset($_POST['authentication_code']);
  345. //check if contacts app exists
  346. $contacts_exists = file_exists($_SERVER["DOCUMENT_ROOT"].PROJECT_PATH.'/app/contacts/') ? true : false;
  347. //get the user details
  348. if ($auth_valid) {
  349. //get user data from the database
  350. $sql = "select ";
  351. $sql .= " u.user_uuid, ";
  352. $sql .= " u.username, ";
  353. $sql .= " u.user_email, ";
  354. $sql .= " u.contact_uuid ";
  355. if ($contacts_exists) {
  356. $sql .= ",";
  357. $sql .= "c.contact_organization, ";
  358. $sql .= "c.contact_name_given, ";
  359. $sql .= "c.contact_name_family, ";
  360. $sql .= "a.contact_attachment_uuid ";
  361. }
  362. $sql .= "from ";
  363. $sql .= " v_users as u ";
  364. if ($contacts_exists) {
  365. $sql .= "left join v_contacts as c on u.contact_uuid = c.contact_uuid and u.contact_uuid is not null ";
  366. $sql .= "left join v_contact_attachments as a on u.contact_uuid = a.contact_uuid and u.contact_uuid is not null and a.attachment_primary = 1 and a.attachment_filename is not null and a.attachment_content is not null ";
  367. }
  368. $sql .= "where ";
  369. $sql .= " u.user_uuid = :user_uuid ";
  370. if ($settings['users']['unique'] != "global") {
  371. //unique username per domain (not globally unique across system - example: email address)
  372. $sql .= "and u.domain_uuid = :domain_uuid ";
  373. $parameters['domain_uuid'] = $_SESSION["domain_uuid"];
  374. }
  375. $parameters['user_uuid'] = $_SESSION["user_uuid"];
  376. $database = new database;
  377. $row = $database->select($sql, $parameters, 'row');
  378. unset($parameters);
  379. //set a few session variables
  380. //$_SESSION["username"] = $row['username']; //setting the username makes it skip the rest of the authentication
  381. //$_SESSION["user_email"] = $row['user_email'];
  382. //$_SESSION["contact_uuid"] = $row["contact_uuid"];
  383. }
  384. else {
  385. // //destroy session
  386. // session_unset();
  387. // session_destroy();
  388. // //$_SESSION['authentication']['plugin']
  389. // //send http 403
  390. // header('HTTP/1.0 403 Forbidden', true, 403);
  391. //
  392. // //redirect to the root of the website
  393. // header("Location: ".PROJECT_PATH."/");
  394. //
  395. // //exit the code
  396. // exit();
  397. //clear submitted usernames
  398. unset($this->username, $_SESSION['username'], $_REQUEST['username'], $_POST['username']);
  399. //clear authentication session
  400. unset($_SESSION['authentication']);
  401. }
  402. /*
  403. //check if user successfully logged in during the interval
  404. //$sql = "select user_log_uuid, timestamp, user_name, user_agent, remote_address ";
  405. $sql = "select count(*) as count ";
  406. $sql .= "from v_user_logs ";
  407. $sql .= "where domain_uuid = :domain_uuid ";
  408. $sql .= "and user_uuid = :user_uuid ";
  409. $sql .= "and user_agent = :user_agent ";
  410. $sql .= "and type = 'login' ";
  411. $sql .= "and result = 'success' ";
  412. $sql .= "and floor(extract(epoch from now()) - extract(epoch from timestamp)) > 3 ";
  413. $sql .= "and floor(extract(epoch from now()) - extract(epoch from timestamp)) < 300 ";
  414. $parameters['domain_uuid'] = $this->domain_uuid;
  415. $parameters['user_uuid'] = $this->user_uuid;
  416. $parameters['user_agent'] = $_SERVER['HTTP_USER_AGENT'];
  417. $database = new database;
  418. $user_log_count = $database->select($sql, $parameters, 'all');
  419. //view_array($user_log_count);
  420. unset($sql, $parameters);
  421. */
  422. //result array
  423. $result["plugin"] = "email";
  424. $result["domain_name"] = $_SESSION["domain_name"];
  425. $result["username"] = $_SESSION["username"];
  426. $result["user_uuid"] = $_SESSION["user_uuid"];
  427. $result["domain_uuid"] = $_SESSION["domain_uuid"];
  428. if ($contacts_exists) {
  429. $result["contact_uuid"] = $_SESSION["contact_uuid"];
  430. $result["contact_organization"] = $row["contact_organization"];
  431. $result["contact_name_given"] = $row["contact_name_given"];
  432. $result["contact_name_family"] = $row["contact_name_family"];
  433. $result["contact_image"] = $row["contact_attachment_uuid"];
  434. }
  435. $result["authorized"] = $auth_valid ? true : false;
  436. //add the failed login to user logs
  437. if (!$auth_valid) {
  438. user_logs::add($result);
  439. }
  440. //retun the array
  441. return $result;
  442. //$_SESSION['authentication']['plugin']['email']['plugin'] = "email";
  443. //$_SESSION['authentication']['plugin']['email']['domain_name'] = $_SESSION["domain_name"];
  444. //$_SESSION['authentication']['plugin']['email']['username'] = $row['username'];
  445. //$_SESSION['authentication']['plugin']['email']['user_uuid'] = $_SESSION["user_uuid"];
  446. //$_SESSION['authentication']['plugin']['email']['contact_uuid'] = $_SESSION["contact_uuid"];
  447. //$_SESSION['authentication']['plugin']['email']['domain_uuid'] = $_SESSION["domain_uuid"];
  448. //$_SESSION['authentication']['plugin']['email']['authorized'] = $auth_valid ? true : false;
  449. }
  450. }
  451. }
  452. ?>