functions.admin.inc.php 10 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272
  1. <?php
  2. function admin($_action, $_data = null) {
  3. if ($_SESSION['mailcow_cc_role'] != "admin") {
  4. $_SESSION['return'][] = array(
  5. 'type' => 'danger',
  6. 'log' => array(__FUNCTION__, $_action, $_data_log),
  7. 'msg' => 'access_denied'
  8. );
  9. return false;
  10. }
  11. global $pdo;
  12. global $lang;
  13. $_data_log = $_data;
  14. !isset($_data_log['password']) ?: $_data_log['password'] = '*';
  15. !isset($_data_log['password2']) ?: $_data_log['password2'] = '*';
  16. switch ($_action) {
  17. case 'add':
  18. $username = strtolower(trim($_data['username']));
  19. $password = $_data['password'];
  20. $password2 = $_data['password2'];
  21. $active = intval($_data['active']);
  22. if (!ctype_alnum(str_replace(array('_', '.', '-'), '', $username)) || empty ($username) || $username == 'API') {
  23. $_SESSION['return'][] = array(
  24. 'type' => 'danger',
  25. 'log' => array(__FUNCTION__, $_action, $_data_log),
  26. 'msg' => array('username_invalid', $username)
  27. );
  28. return false;
  29. }
  30. $stmt = $pdo->prepare("SELECT `username` FROM `admin`
  31. WHERE `username` = :username");
  32. $stmt->execute(array(':username' => $username));
  33. $num_results[] = count($stmt->fetchAll(PDO::FETCH_ASSOC));
  34. $stmt = $pdo->prepare("SELECT `username` FROM `domain_admins`
  35. WHERE `username` = :username");
  36. $stmt->execute(array(':username' => $username));
  37. $num_results[] = count($stmt->fetchAll(PDO::FETCH_ASSOC));
  38. foreach ($num_results as $num_results_each) {
  39. if ($num_results_each != 0) {
  40. $_SESSION['return'][] = array(
  41. 'type' => 'danger',
  42. 'log' => array(__FUNCTION__, $_action, $_data_log),
  43. 'msg' => array('object_exists', htmlspecialchars($username))
  44. );
  45. return false;
  46. }
  47. }
  48. if (!empty($password) && !empty($password2)) {
  49. if (!preg_match('/' . $GLOBALS['PASSWD_REGEP'] . '/', $password)) {
  50. $_SESSION['return'][] = array(
  51. 'type' => 'danger',
  52. 'log' => array(__FUNCTION__, $_action, $_data_log),
  53. 'msg' => 'password_complexity'
  54. );
  55. return false;
  56. }
  57. if ($password != $password2) {
  58. $_SESSION['return'][] = array(
  59. 'type' => 'danger',
  60. 'log' => array(__FUNCTION__, $_action, $_data_log),
  61. 'msg' => 'password_mismatch'
  62. );
  63. return false;
  64. }
  65. $password_hashed = hash_password($password);
  66. $stmt = $pdo->prepare("INSERT INTO `admin` (`username`, `password`, `superadmin`, `active`)
  67. VALUES (:username, :password_hashed, '1', :active)");
  68. $stmt->execute(array(
  69. ':username' => $username,
  70. ':password_hashed' => $password_hashed,
  71. ':active' => $active
  72. ));
  73. }
  74. else {
  75. $_SESSION['return'][] = array(
  76. 'type' => 'danger',
  77. 'log' => array(__FUNCTION__, $_action, $_data_log),
  78. 'msg' => 'password_empty'
  79. );
  80. return false;
  81. }
  82. $_SESSION['return'][] = array(
  83. 'type' => 'success',
  84. 'log' => array(__FUNCTION__, $_action, $_data_log),
  85. 'msg' => array('admin_added', htmlspecialchars($username))
  86. );
  87. break;
  88. case 'edit':
  89. if (!is_array($_data['username'])) {
  90. $usernames = array();
  91. $usernames[] = $_data['username'];
  92. }
  93. else {
  94. $usernames = $_data['username'];
  95. }
  96. foreach ($usernames as $username) {
  97. $is_now = admin('details', $username);
  98. if (!empty($is_now)) {
  99. $active = (isset($_data['active'])) ? intval($_data['active']) : $is_now['active'];
  100. $username_new = (!empty($_data['username_new'])) ? $_data['username_new'] : $is_now['username'];
  101. }
  102. else {
  103. $_SESSION['return'][] = array(
  104. 'type' => 'danger',
  105. 'log' => array(__FUNCTION__, $_action, $_data_log),
  106. 'msg' => 'access_denied'
  107. );
  108. continue;
  109. }
  110. $password = $_data['password'];
  111. $password2 = $_data['password2'];
  112. if ($active == 0) {
  113. $left_active = 0;
  114. foreach (admin('get') as $admin) {
  115. $left_active = $left_active + admin('details', $admin)['active'];
  116. }
  117. if ($left_active == 1) {
  118. $_SESSION['return'][] = array(
  119. 'type' => 'warning',
  120. 'log' => array(__FUNCTION__, $_action, $_data_log),
  121. 'msg' => 'no_active_admin'
  122. );
  123. continue;
  124. }
  125. }
  126. if (!ctype_alnum(str_replace(array('_', '.', '-'), '', $username_new))) {
  127. $_SESSION['return'][] = array(
  128. 'type' => 'danger',
  129. 'log' => array(__FUNCTION__, $_action, $_data_log),
  130. 'msg' => array('username_invalid', $username_new)
  131. );
  132. continue;
  133. }
  134. if ($username_new != $username) {
  135. if (!empty(admin('details', $username_new)['username'])) {
  136. $_SESSION['return'][] = array(
  137. 'type' => 'danger',
  138. 'log' => array(__FUNCTION__, $_action, $_data_log),
  139. 'msg' => array('username_invalid', $username_new)
  140. );
  141. continue;
  142. }
  143. }
  144. if (!empty($password) && !empty($password2)) {
  145. if (!preg_match('/' . $GLOBALS['PASSWD_REGEP'] . '/', $password)) {
  146. $_SESSION['return'][] = array(
  147. 'type' => 'danger',
  148. 'log' => array(__FUNCTION__, $_action, $_data_log),
  149. 'msg' => 'password_complexity'
  150. );
  151. continue;
  152. }
  153. if ($password != $password2) {
  154. $_SESSION['return'][] = array(
  155. 'type' => 'danger',
  156. 'log' => array(__FUNCTION__, $_action, $_data_log),
  157. 'msg' => 'password_mismatch'
  158. );
  159. continue;
  160. }
  161. $password_hashed = hash_password($password);
  162. $stmt = $pdo->prepare("UPDATE `admin` SET `username` = :username_new, `active` = :active, `password` = :password_hashed WHERE `username` = :username");
  163. $stmt->execute(array(
  164. ':password_hashed' => $password_hashed,
  165. ':username_new' => $username_new,
  166. ':username' => $username,
  167. ':active' => $active
  168. ));
  169. if (isset($_data['disable_tfa'])) {
  170. $stmt = $pdo->prepare("UPDATE `tfa` SET `active` = '0' WHERE `username` = :username");
  171. $stmt->execute(array(':username' => $username));
  172. }
  173. else {
  174. $stmt = $pdo->prepare("UPDATE `tfa` SET `username` = :username_new WHERE `username` = :username");
  175. $stmt->execute(array(':username_new' => $username_new, ':username' => $username));
  176. }
  177. }
  178. else {
  179. $stmt = $pdo->prepare("UPDATE `admin` SET `username` = :username_new, `active` = :active WHERE `username` = :username");
  180. $stmt->execute(array(
  181. ':username_new' => $username_new,
  182. ':username' => $username,
  183. ':active' => $active
  184. ));
  185. if (isset($_data['disable_tfa'])) {
  186. $stmt = $pdo->prepare("UPDATE `tfa` SET `active` = '0' WHERE `username` = :username");
  187. $stmt->execute(array(':username' => $username));
  188. }
  189. else {
  190. $stmt = $pdo->prepare("UPDATE `tfa` SET `username` = :username_new WHERE `username` = :username");
  191. $stmt->execute(array(':username_new' => $username_new, ':username' => $username));
  192. }
  193. }
  194. $_SESSION['return'][] = array(
  195. 'type' => 'success',
  196. 'log' => array(__FUNCTION__, $_action, $_data_log),
  197. 'msg' => array('admin_modified', htmlspecialchars($username))
  198. );
  199. }
  200. return true;
  201. break;
  202. case 'delete':
  203. $usernames = (array)$_data['username'];
  204. foreach ($usernames as $username) {
  205. if ($_SESSION['mailcow_cc_username'] == $username) {
  206. $_SESSION['return'][] = array(
  207. 'type' => 'warning',
  208. 'log' => array(__FUNCTION__, $_action, $_data_log),
  209. 'msg' => 'cannot_delete_self'
  210. );
  211. continue;
  212. }
  213. if (empty(admin('details', $username))) {
  214. $_SESSION['return'][] = array(
  215. 'type' => 'danger',
  216. 'log' => array(__FUNCTION__, $_action, $_data_log),
  217. 'msg' => array('username_invalid', $username)
  218. );
  219. continue;
  220. }
  221. $stmt = $pdo->prepare("DELETE FROM `admin` WHERE `username` = :username");
  222. $stmt->execute(array(
  223. ':username' => $username,
  224. ));
  225. $stmt = $pdo->prepare("DELETE FROM `domain_admins` WHERE `username` = :username");
  226. $stmt->execute(array(
  227. ':username' => $username,
  228. ));
  229. $_SESSION['return'][] = array(
  230. 'type' => 'success',
  231. 'log' => array(__FUNCTION__, $_action, $_data_log),
  232. 'msg' => array('admin_removed', htmlspecialchars($username))
  233. );
  234. }
  235. break;
  236. case 'get':
  237. $admins = array();
  238. $stmt = $pdo->query("SELECT `username` FROM `admin` WHERE `superadmin` = '1'");
  239. $rows = $stmt->fetchAll(PDO::FETCH_ASSOC);
  240. while ($row = array_shift($rows)) {
  241. $admins[] = $row['username'];
  242. }
  243. return $admins;
  244. break;
  245. case 'details':
  246. $admindata = array();
  247. $stmt = $pdo->prepare("SELECT
  248. `tfa`.`active` AS `tfa_active`,
  249. `admin`.`username`,
  250. `admin`.`created`,
  251. `admin`.`active` AS `active`
  252. FROM `admin`
  253. LEFT OUTER JOIN `tfa` ON `tfa`.`username`=`admin`.`username`
  254. WHERE `admin`.`username`= :admin AND `superadmin` = '1'");
  255. $stmt->execute(array(
  256. ':admin' => $_data
  257. ));
  258. $row = $stmt->fetch(PDO::FETCH_ASSOC);
  259. if (empty($row)) {
  260. return false;
  261. }
  262. $admindata['username'] = $row['username'];
  263. $admindata['tfa_active'] = (is_null($row['tfa_active'])) ? 0 : $row['tfa_active'];
  264. $admindata['active'] = $row['active'];
  265. $admindata['created'] = $row['created'];
  266. return $admindata;
  267. break;
  268. }
  269. }