functions.admin.inc.php 10 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258
  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 (password_check($password_new, $password_new2) !== true) {
  49. return false;
  50. }
  51. // support pre hashed passwords
  52. if (preg_match('/^{(ARGON2I|ARGON2ID|BLF-CRYPT|CLEAR|CLEARTEXT|CRYPT|DES-CRYPT|LDAP-MD5|MD5|MD5-CRYPT|PBKDF2|PLAIN|PLAIN-MD4|PLAIN-MD5|PLAIN-TRUNC|PLAIN-TRUNC|SHA|SHA1|SHA256|SHA256-CRYPT|SHA512|SHA512-CRYPT|SMD5|SSHA|SSHA256|SSHA512)}/i', $password)) {
  53. $password_hashed = $password_new;
  54. }
  55. else {
  56. $password_hashed = hash_password($password_new);
  57. }
  58. $stmt = $pdo->prepare("INSERT INTO `admin` (`username`, `password`, `superadmin`, `active`)
  59. VALUES (:username, :password_hashed, '1', :active)");
  60. $stmt->execute(array(
  61. ':username' => $username,
  62. ':password_hashed' => $password_hashed,
  63. ':active' => $active
  64. ));
  65. $_SESSION['return'][] = array(
  66. 'type' => 'success',
  67. 'log' => array(__FUNCTION__, $_action, $_data_log),
  68. 'msg' => array('admin_added', htmlspecialchars($username))
  69. );
  70. break;
  71. case 'edit':
  72. if (!is_array($_data['username'])) {
  73. $usernames = array();
  74. $usernames[] = $_data['username'];
  75. }
  76. else {
  77. $usernames = $_data['username'];
  78. }
  79. foreach ($usernames as $username) {
  80. $is_now = admin('details', $username);
  81. if (!empty($is_now)) {
  82. $active = (isset($_data['active'])) ? intval($_data['active']) : $is_now['active'];
  83. $username_new = (!empty($_data['username_new'])) ? $_data['username_new'] : $is_now['username'];
  84. }
  85. else {
  86. $_SESSION['return'][] = array(
  87. 'type' => 'danger',
  88. 'log' => array(__FUNCTION__, $_action, $_data_log),
  89. 'msg' => 'access_denied'
  90. );
  91. continue;
  92. }
  93. $password = $_data['password'];
  94. $password2 = $_data['password2'];
  95. if ($active == 0) {
  96. $left_active = 0;
  97. foreach (admin('get') as $admin) {
  98. $left_active = $left_active + admin('details', $admin)['active'];
  99. }
  100. if ($left_active == 1) {
  101. $_SESSION['return'][] = array(
  102. 'type' => 'warning',
  103. 'log' => array(__FUNCTION__, $_action, $_data_log),
  104. 'msg' => 'no_active_admin'
  105. );
  106. continue;
  107. }
  108. }
  109. if (!ctype_alnum(str_replace(array('_', '.', '-'), '', $username_new))) {
  110. $_SESSION['return'][] = array(
  111. 'type' => 'danger',
  112. 'log' => array(__FUNCTION__, $_action, $_data_log),
  113. 'msg' => array('username_invalid', $username_new)
  114. );
  115. continue;
  116. }
  117. if ($username_new != $username) {
  118. if (!empty(admin('details', $username_new)['username'])) {
  119. $_SESSION['return'][] = array(
  120. 'type' => 'danger',
  121. 'log' => array(__FUNCTION__, $_action, $_data_log),
  122. 'msg' => array('username_invalid', $username_new)
  123. );
  124. continue;
  125. }
  126. }
  127. if (!empty($password) && !empty($password2)) {
  128. if (password_check($password, $password2) !== true) {
  129. return false;
  130. }
  131. // support pre hashed passwords
  132. if (preg_match('/^{(ARGON2I|ARGON2ID|BLF-CRYPT|CLEAR|CLEARTEXT|CRYPT|DES-CRYPT|LDAP-MD5|MD5|MD5-CRYPT|PBKDF2|PLAIN|PLAIN-MD4|PLAIN-MD5|PLAIN-TRUNC|PLAIN-TRUNC|SHA|SHA1|SHA256|SHA256-CRYPT|SHA512|SHA512-CRYPT|SMD5|SSHA|SSHA256|SSHA512)}/i', $password)) {
  133. $password_hashed = $password;
  134. }
  135. else {
  136. $password_hashed = hash_password($password);
  137. }
  138. $stmt = $pdo->prepare("UPDATE `admin` SET `username` = :username_new, `active` = :active, `password` = :password_hashed WHERE `username` = :username");
  139. $stmt->execute(array(
  140. ':password_hashed' => $password_hashed,
  141. ':username_new' => $username_new,
  142. ':username' => $username,
  143. ':active' => $active
  144. ));
  145. if (isset($_data['disable_tfa'])) {
  146. $stmt = $pdo->prepare("UPDATE `tfa` SET `active` = '0' WHERE `username` = :username");
  147. $stmt->execute(array(':username' => $username));
  148. }
  149. else {
  150. $stmt = $pdo->prepare("UPDATE `tfa` SET `username` = :username_new WHERE `username` = :username");
  151. $stmt->execute(array(':username_new' => $username_new, ':username' => $username));
  152. }
  153. }
  154. else {
  155. $stmt = $pdo->prepare("UPDATE `admin` SET `username` = :username_new, `active` = :active WHERE `username` = :username");
  156. $stmt->execute(array(
  157. ':username_new' => $username_new,
  158. ':username' => $username,
  159. ':active' => $active
  160. ));
  161. if (isset($_data['disable_tfa'])) {
  162. $stmt = $pdo->prepare("UPDATE `tfa` SET `active` = '0' WHERE `username` = :username");
  163. $stmt->execute(array(':username' => $username));
  164. }
  165. else {
  166. $stmt = $pdo->prepare("UPDATE `tfa` SET `username` = :username_new WHERE `username` = :username");
  167. $stmt->execute(array(':username_new' => $username_new, ':username' => $username));
  168. }
  169. }
  170. $_SESSION['return'][] = array(
  171. 'type' => 'success',
  172. 'log' => array(__FUNCTION__, $_action, $_data_log),
  173. 'msg' => array('admin_modified', htmlspecialchars($username))
  174. );
  175. }
  176. return true;
  177. break;
  178. case 'delete':
  179. $usernames = (array)$_data['username'];
  180. foreach ($usernames as $username) {
  181. if ($_SESSION['mailcow_cc_username'] == $username) {
  182. $_SESSION['return'][] = array(
  183. 'type' => 'warning',
  184. 'log' => array(__FUNCTION__, $_action, $_data_log),
  185. 'msg' => 'cannot_delete_self'
  186. );
  187. continue;
  188. }
  189. if (empty(admin('details', $username))) {
  190. $_SESSION['return'][] = array(
  191. 'type' => 'danger',
  192. 'log' => array(__FUNCTION__, $_action, $_data_log),
  193. 'msg' => array('username_invalid', $username)
  194. );
  195. continue;
  196. }
  197. $stmt = $pdo->prepare("DELETE FROM `admin` WHERE `username` = :username");
  198. $stmt->execute(array(
  199. ':username' => $username,
  200. ));
  201. $stmt = $pdo->prepare("DELETE FROM `domain_admins` WHERE `username` = :username");
  202. $stmt->execute(array(
  203. ':username' => $username,
  204. ));
  205. $stmt = $pdo->prepare("DELETE FROM `tfa` WHERE `username` = :username");
  206. $stmt->execute(array(
  207. ':username' => $username,
  208. ));
  209. $stmt = $pdo->prepare("DELETE FROM `fido2` WHERE `username` = :username");
  210. $stmt->execute(array(
  211. ':username' => $username,
  212. ));
  213. $_SESSION['return'][] = array(
  214. 'type' => 'success',
  215. 'log' => array(__FUNCTION__, $_action, $_data_log),
  216. 'msg' => array('admin_removed', htmlspecialchars($username))
  217. );
  218. }
  219. break;
  220. case 'get':
  221. $admins = array();
  222. $stmt = $pdo->query("SELECT `username` FROM `admin` WHERE `superadmin` = '1'");
  223. $rows = $stmt->fetchAll(PDO::FETCH_ASSOC);
  224. while ($row = array_shift($rows)) {
  225. $admins[] = $row['username'];
  226. }
  227. return $admins;
  228. break;
  229. case 'details':
  230. $admindata = array();
  231. $stmt = $pdo->prepare("SELECT
  232. `tfa`.`active` AS `tfa_active`,
  233. `admin`.`username`,
  234. `admin`.`created`,
  235. `admin`.`active` AS `active`
  236. FROM `admin`
  237. LEFT OUTER JOIN `tfa` ON `tfa`.`username`=`admin`.`username`
  238. WHERE `admin`.`username`= :admin AND `superadmin` = '1'");
  239. $stmt->execute(array(
  240. ':admin' => $_data
  241. ));
  242. $row = $stmt->fetch(PDO::FETCH_ASSOC);
  243. if (empty($row)) {
  244. return false;
  245. }
  246. $admindata['username'] = $row['username'];
  247. $admindata['tfa_active'] = (is_null($row['tfa_active'])) ? 0 : $row['tfa_active'];
  248. $admindata['tfa_active_int'] = (is_null($row['tfa_active'])) ? 0 : $row['tfa_active'];
  249. $admindata['active'] = $row['active'];
  250. $admindata['active_int'] = $row['active'];
  251. $admindata['created'] = $row['created'];
  252. return $admindata;
  253. break;
  254. }
  255. }