functions.acl.inc.php 9.5 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226
  1. <?php
  2. function acl($_action, $_scope = null, $_data = null) {
  3. global $pdo;
  4. global $lang;
  5. $_data_log = $_data;
  6. switch ($_action) {
  7. case 'edit':
  8. switch ($_scope) {
  9. case 'user':
  10. if (!is_array($_data['username'])) {
  11. $usernames = array();
  12. $usernames[] = $_data['username'];
  13. }
  14. else {
  15. $usernames = $_data['username'];
  16. }
  17. foreach ($usernames as $username) {
  18. // Cast to array for single selections
  19. $acls = (array)$_data['user_acl'];
  20. // Create associative array from index array
  21. // All set items are given 1 as value
  22. foreach ($acls as $acl_key => $acl_val) {
  23. $acl_post[$acl_val] = 1;
  24. }
  25. // Users cannot change their own ACL
  26. if (!hasMailboxObjectAccess($_SESSION['mailcow_cc_username'], $_SESSION['mailcow_cc_role'], $username)
  27. || ($_SESSION['mailcow_cc_role'] != 'admin' && $_SESSION['mailcow_cc_role'] != 'domainadmin')) {
  28. $_SESSION['return'][] = array(
  29. 'type' => 'danger',
  30. 'log' => array(__FUNCTION__, $_action, $_scope, $_data_log),
  31. 'msg' => 'access_denied'
  32. );
  33. continue;
  34. }
  35. // Read all available acl options by calling acl(get)
  36. // Set all available acl options we cannot find in the post data to 0, else 1
  37. $is_now = acl('get', 'user', $username);
  38. if (!empty($is_now)) {
  39. foreach ($is_now as $acl_now_name => $acl_now_val) {
  40. $set_acls[$acl_now_name] = (isset($acl_post[$acl_now_name])) ? 1 : 0;
  41. }
  42. }
  43. else {
  44. $_SESSION['return'][] = array(
  45. 'type' => 'danger',
  46. 'log' => array(__FUNCTION__, $_action, $_scope, $_data_log),
  47. 'msg' => 'Cannot determine current ACL'
  48. );
  49. continue;
  50. }
  51. foreach ($set_acls as $set_acl_key => $set_acl_val) {
  52. $stmt = $pdo->prepare("UPDATE `user_acl` SET " . $set_acl_key . " = " . intval($set_acl_val) . "
  53. WHERE `username` = :username");
  54. $stmt->execute(array(
  55. ':username' => $username,
  56. ));
  57. }
  58. $_SESSION['return'][] = array(
  59. 'type' => 'success',
  60. 'log' => array(__FUNCTION__, $_action, $_scope, $_data_log),
  61. 'msg' => array('acl_saved', $username)
  62. );
  63. }
  64. break;
  65. case 'domainadmin':
  66. if ($_SESSION['mailcow_cc_role'] != 'admin') {
  67. $_SESSION['return'][] = array(
  68. 'type' => 'danger',
  69. 'log' => array(__FUNCTION__, $_action, $_scope, $_data_log),
  70. 'msg' => 'access_denied'
  71. );
  72. return false;
  73. }
  74. if (!is_array($_data['username'])) {
  75. $usernames = array();
  76. $usernames[] = $_data['username'];
  77. }
  78. else {
  79. $usernames = $_data['username'];
  80. }
  81. foreach ($usernames as $username) {
  82. // Cast to array for single selections
  83. $acls = (array)$_data['da_acl'];
  84. // Create associative array from index array
  85. // All set items are given 1 as value
  86. foreach ($acls as $acl_key => $acl_val) {
  87. $acl_post[$acl_val] = 1;
  88. }
  89. // Users cannot change their own ACL
  90. if ($_SESSION['mailcow_cc_role'] != 'admin') {
  91. $_SESSION['return'][] = array(
  92. 'type' => 'danger',
  93. 'log' => array(__FUNCTION__, $_action, $_scope, $_data_log),
  94. 'msg' => 'access_denied'
  95. );
  96. continue;
  97. }
  98. // Read all available acl options by calling acl(get)
  99. // Set all available acl options we cannot find in the post data to 0, else 1
  100. $is_now = acl('get', 'domainadmin', $username);
  101. if (!empty($is_now)) {
  102. foreach ($is_now as $acl_now_name => $acl_now_val) {
  103. $set_acls[$acl_now_name] = (isset($acl_post[$acl_now_name])) ? 1 : 0;
  104. }
  105. }
  106. else {
  107. $_SESSION['return'][] = array(
  108. 'type' => 'danger',
  109. 'log' => array(__FUNCTION__, $_action, $_scope, $_data_log),
  110. 'msg' => 'Cannot determine current ACL'
  111. );
  112. continue;
  113. }
  114. foreach ($set_acls as $set_acl_key => $set_acl_val) {
  115. $stmt = $pdo->prepare("UPDATE `da_acl` SET " . $set_acl_key . " = " . intval($set_acl_val) . "
  116. WHERE `username` = :username");
  117. $stmt->execute(array(
  118. ':username' => $username,
  119. ));
  120. }
  121. $_SESSION['return'][] = array(
  122. 'type' => 'success',
  123. 'log' => array(__FUNCTION__, $_action, $_scope, $_data_log),
  124. 'msg' => array('acl_saved', $username)
  125. );
  126. }
  127. break;
  128. }
  129. break;
  130. case 'get':
  131. switch ($_scope) {
  132. case 'user':
  133. if (!hasMailboxObjectAccess($_SESSION['mailcow_cc_username'], $_SESSION['mailcow_cc_role'], $_data)) {
  134. return false;
  135. }
  136. $stmt = $pdo->prepare("SELECT * FROM `user_acl` WHERE `username` = :username");
  137. $stmt->execute(array(':username' => $_data));
  138. $data = $stmt->fetch(PDO::FETCH_ASSOC);
  139. if ($_SESSION['mailcow_cc_role'] == 'domainadmin') {
  140. // Domain admins cannot see, add or remove user ACLs they don't have access to by themselves
  141. // Editing a user will use acl("get", "user") to determine granted ACLs and therefore block unallowed access escalation via form editing
  142. $self_da_acl = acl('get', 'domainadmin', $_SESSION['mailcow_cc_username']);
  143. foreach ($self_da_acl as $self_da_acl_key => $self_da_acl_val) {
  144. if ($self_da_acl_val == 0) {
  145. unset($data[$self_da_acl_key]);
  146. }
  147. }
  148. }
  149. if (!empty($data)) {
  150. unset($data['username']);
  151. return $data;
  152. }
  153. else {
  154. return false;
  155. }
  156. break;
  157. case 'domainadmin':
  158. if ($_SESSION['mailcow_cc_role'] != 'admin' && $_SESSION['mailcow_cc_role'] != 'domainadmin') {
  159. return false;
  160. }
  161. if ($_SESSION['mailcow_cc_role'] == 'domainadmin' && $_SESSION['mailcow_cc_username'] != $_data) {
  162. return false;
  163. }
  164. $stmt = $pdo->prepare("SELECT * FROM `da_acl` WHERE `username` = :username");
  165. $stmt->execute(array(':username' => $_data));
  166. $data = $stmt->fetch(PDO::FETCH_ASSOC);
  167. if (!empty($data)) {
  168. unset($data['username']);
  169. return $data;
  170. }
  171. else {
  172. return false;
  173. }
  174. break;
  175. }
  176. break;
  177. case 'to_session':
  178. if (!isset($_SESSION['mailcow_cc_role'])) {
  179. return false;
  180. }
  181. unset($_SESSION['acl']);
  182. $username = strtolower(trim($_SESSION['mailcow_cc_username']));
  183. // Admins get access to all modules
  184. if ($_SESSION['mailcow_cc_role'] == 'admin' ||
  185. (isset($_SESSION["dual-login"]["role"]) && $_SESSION["dual-login"]["role"] == 'admin')) {
  186. $stmt = $pdo->query("SHOW COLUMNS FROM `user_acl` WHERE `Field` != 'username';");
  187. $acl_all = $stmt->fetchAll(PDO::FETCH_ASSOC);
  188. while ($row = array_shift($acl_all)) {
  189. $acl['acl'][$row['Field']] = 1;
  190. }
  191. $stmt = $pdo->query("SHOW COLUMNS FROM `da_acl` WHERE `Field` != 'username';");
  192. $acl_all = $stmt->fetchAll(PDO::FETCH_ASSOC);
  193. while ($row = array_shift($acl_all)) {
  194. $acl['acl'][$row['Field']] = 1;
  195. }
  196. }
  197. elseif ($_SESSION['mailcow_cc_role'] == 'domainadmin' ||
  198. (isset($_SESSION["dual-login"]["role"]) && $_SESSION["dual-login"]["role"] == 'domainadmin')) {
  199. // Read all exting user_acl modules and set to 1
  200. $stmt = $pdo->query("SHOW COLUMNS FROM `user_acl` WHERE `Field` != 'username';");
  201. $acl_all = $stmt->fetchAll(PDO::FETCH_ASSOC);
  202. while ($row = array_shift($acl_all)) {
  203. $acl['acl'][$row['Field']] = 1;
  204. }
  205. // Read da_acl rules for current user, OVERWRITE overlapping modules
  206. // This prevents access to a users sync jobs, when a domain admins was not given access to sync jobs
  207. $stmt = $pdo->prepare("SELECT * FROM `da_acl` WHERE `username` = :username");
  208. $stmt->execute(array(':username' => (isset($_SESSION["dual-login"]["username"])) ? $_SESSION["dual-login"]["username"] : $username));
  209. $acl_user = $stmt->fetch(PDO::FETCH_ASSOC);
  210. foreach ($acl_user as $acl_user_key => $acl_user_val) {
  211. $acl['acl'][$acl_user_key] = $acl_user_val;
  212. }
  213. unset($acl['acl']['username']);
  214. }
  215. elseif ($_SESSION['mailcow_cc_role'] == 'user') {
  216. $stmt = $pdo->prepare("SELECT * FROM `user_acl` WHERE `username` = :username");
  217. $stmt->execute(array(':username' => $username));
  218. $acl['acl'] = $stmt->fetch(PDO::FETCH_ASSOC);
  219. unset($acl['acl']['username']);
  220. }
  221. if (!empty($acl)) {
  222. $_SESSION = array_merge($_SESSION, $acl);
  223. }
  224. break;
  225. }
  226. }