| <?php | |
| function acl($_action, $_scope = null, $_data = null) { | |
| global $pdo; | |
| global $lang; | |
| $_data_log = $_data; | |
| switch ($_action) { | |
| case 'edit': | |
| switch ($_scope) { | |
| case 'user': | |
| if (!is_array($_data['username'])) { | |
| $usernames = array(); | |
| $usernames[] = $_data['username']; | |
| } | |
| else { | |
| $usernames = $_data['username']; | |
| } | |
| foreach ($usernames as $username) { | |
| // Cast to array for single selections | |
| $acls = (array)$_data['user_acl']; | |
| // Create associative array from index array | |
| // All set items are given 1 as value | |
| foreach ($acls as $acl_key => $acl_val) { | |
| $acl_post[$acl_val] = 1; | |
| } | |
| // Users cannot change their own ACL | |
| if (!hasMailboxObjectAccess($_SESSION['mailcow_cc_username'], $_SESSION['mailcow_cc_role'], $username) | |
| || ($_SESSION['mailcow_cc_role'] != 'admin' && $_SESSION['mailcow_cc_role'] != 'domainadmin')) { | |
| $_SESSION['return'][] = array( | |
| 'type' => 'danger', | |
| 'log' => array(__FUNCTION__, $_action, $_scope, $_data_log), | |
| 'msg' => 'access_denied' | |
| ); | |
| continue; | |
| } | |
| // Read all available acl options by calling acl(get) | |
| // Set all available acl options we cannot find in the post data to 0, else 1 | |
| $is_now = acl('get', 'user', $username); | |
| if (!empty($is_now)) { | |
| foreach ($is_now as $acl_now_name => $acl_now_val) { | |
| $set_acls[$acl_now_name] = (isset($acl_post[$acl_now_name])) ? 1 : 0; | |
| } | |
| } | |
| else { | |
| $_SESSION['return'][] = array( | |
| 'type' => 'danger', | |
| 'log' => array(__FUNCTION__, $_action, $_scope, $_data_log), | |
| 'msg' => 'Cannot determine current ACL' | |
| ); | |
| continue; | |
| } | |
| foreach ($set_acls as $set_acl_key => $set_acl_val) { | |
| $stmt = $pdo->prepare("UPDATE `user_acl` SET " . $set_acl_key . " = " . intval($set_acl_val) . " | |
| WHERE `username` = :username"); | |
| $stmt->execute(array( | |
| ':username' => $username, | |
| )); | |
| } | |
| $_SESSION['return'][] = array( | |
| 'type' => 'success', | |
| 'log' => array(__FUNCTION__, $_action, $_scope, $_data_log), | |
| 'msg' => array('acl_saved', $username) | |
| ); | |
| } | |
| break; | |
| case 'domainadmin': | |
| if ($_SESSION['mailcow_cc_role'] != 'admin') { | |
| $_SESSION['return'][] = array( | |
| 'type' => 'danger', | |
| 'log' => array(__FUNCTION__, $_action, $_scope, $_data_log), | |
| 'msg' => 'access_denied' | |
| ); | |
| return false; | |
| } | |
| if (!is_array($_data['username'])) { | |
| $usernames = array(); | |
| $usernames[] = $_data['username']; | |
| } | |
| else { | |
| $usernames = $_data['username']; | |
| } | |
| foreach ($usernames as $username) { | |
| // Cast to array for single selections | |
| $acls = (array)$_data['da_acl']; | |
| // Create associative array from index array | |
| // All set items are given 1 as value | |
| foreach ($acls as $acl_key => $acl_val) { | |
| $acl_post[$acl_val] = 1; | |
| } | |
| // Users cannot change their own ACL | |
| if ($_SESSION['mailcow_cc_role'] != 'admin') { | |
| $_SESSION['return'][] = array( | |
| 'type' => 'danger', | |
| 'log' => array(__FUNCTION__, $_action, $_scope, $_data_log), | |
| 'msg' => 'access_denied' | |
| ); | |
| continue; | |
| } | |
| // Read all available acl options by calling acl(get) | |
| // Set all available acl options we cannot find in the post data to 0, else 1 | |
| $is_now = acl('get', 'domainadmin', $username); | |
| if (!empty($is_now)) { | |
| foreach ($is_now as $acl_now_name => $acl_now_val) { | |
| $set_acls[$acl_now_name] = (isset($acl_post[$acl_now_name])) ? 1 : 0; | |
| } | |
| } | |
| else { | |
| $_SESSION['return'][] = array( | |
| 'type' => 'danger', | |
| 'log' => array(__FUNCTION__, $_action, $_scope, $_data_log), | |
| 'msg' => 'Cannot determine current ACL' | |
| ); | |
| continue; | |
| } | |
| foreach ($set_acls as $set_acl_key => $set_acl_val) { | |
| $stmt = $pdo->prepare("UPDATE `da_acl` SET " . $set_acl_key . " = " . intval($set_acl_val) . " | |
| WHERE `username` = :username"); | |
| $stmt->execute(array( | |
| ':username' => $username, | |
| )); | |
| } | |
| $_SESSION['return'][] = array( | |
| 'type' => 'success', | |
| 'log' => array(__FUNCTION__, $_action, $_scope, $_data_log), | |
| 'msg' => array('acl_saved', $username) | |
| ); | |
| } | |
| break; | |
| } | |
| break; | |
| case 'get': | |
| switch ($_scope) { | |
| case 'user': | |
| if (!hasMailboxObjectAccess($_SESSION['mailcow_cc_username'], $_SESSION['mailcow_cc_role'], $_data)) { | |
| return false; | |
| } | |
| $stmt = $pdo->prepare("SELECT * FROM `user_acl` WHERE `username` = :username"); | |
| $stmt->execute(array(':username' => $_data)); | |
| $data = $stmt->fetch(PDO::FETCH_ASSOC); | |
| if ($_SESSION['mailcow_cc_role'] == 'domainadmin') { | |
| // Domain admins cannot see, add or remove user ACLs they don't have access to by themselves | |
| // Editing a user will use acl("get", "user") to determine granted ACLs and therefore block unallowed access escalation via form editing | |
| $self_da_acl = acl('get', 'domainadmin', $_SESSION['mailcow_cc_username']); | |
| foreach ($self_da_acl as $self_da_acl_key => $self_da_acl_val) { | |
| if ($self_da_acl_val == 0) { | |
| unset($data[$self_da_acl_key]); | |
| } | |
| } | |
| } | |
| if (!empty($data)) { | |
| unset($data['username']); | |
| return $data; | |
| } | |
| else { | |
| return false; | |
| } | |
| break; | |
| case 'domainadmin': | |
| if ($_SESSION['mailcow_cc_role'] != 'admin' && $_SESSION['mailcow_cc_role'] != 'domainadmin') { | |
| return false; | |
| } | |
| if ($_SESSION['mailcow_cc_role'] == 'domainadmin' && $_SESSION['mailcow_cc_username'] != $_data) { | |
| return false; | |
| } | |
| $stmt = $pdo->prepare("SELECT * FROM `da_acl` WHERE `username` = :username"); | |
| $stmt->execute(array(':username' => $_data)); | |
| $data = $stmt->fetch(PDO::FETCH_ASSOC); | |
| if (!empty($data)) { | |
| unset($data['username']); | |
| return $data; | |
| } | |
| else { | |
| return false; | |
| } | |
| break; | |
| } | |
| break; | |
| case 'to_session': | |
| if (!isset($_SESSION['mailcow_cc_role'])) { | |
| return false; | |
| } | |
| unset($_SESSION['acl']); | |
| $username = strtolower(trim($_SESSION['mailcow_cc_username'])); | |
| // Admins get access to all modules | |
| if ($_SESSION['mailcow_cc_role'] == 'admin' || | |
| (isset($_SESSION["dual-login"]["role"]) && $_SESSION["dual-login"]["role"] == 'admin')) { | |
| $stmt = $pdo->query("SHOW COLUMNS FROM `user_acl` WHERE `Field` != 'username';"); | |
| $acl_all = $stmt->fetchAll(PDO::FETCH_ASSOC); | |
| while ($row = array_shift($acl_all)) { | |
| $acl['acl'][$row['Field']] = 1; | |
| } | |
| $stmt = $pdo->query("SHOW COLUMNS FROM `da_acl` WHERE `Field` != 'username';"); | |
| $acl_all = $stmt->fetchAll(PDO::FETCH_ASSOC); | |
| while ($row = array_shift($acl_all)) { | |
| $acl['acl'][$row['Field']] = 1; | |
| } | |
| } | |
| elseif ($_SESSION['mailcow_cc_role'] == 'domainadmin' || | |
| (isset($_SESSION["dual-login"]["role"]) && $_SESSION["dual-login"]["role"] == 'domainadmin')) { | |
| // Read all exting user_acl modules and set to 1 | |
| $stmt = $pdo->query("SHOW COLUMNS FROM `user_acl` WHERE `Field` != 'username';"); | |
| $acl_all = $stmt->fetchAll(PDO::FETCH_ASSOC); | |
| while ($row = array_shift($acl_all)) { | |
| $acl['acl'][$row['Field']] = 1; | |
| } | |
| // Read da_acl rules for current user, OVERWRITE overlapping modules | |
| // This prevents access to a users sync jobs, when a domain admins was not given access to sync jobs | |
| $stmt = $pdo->prepare("SELECT * FROM `da_acl` WHERE `username` = :username"); | |
| $stmt->execute(array(':username' => (isset($_SESSION["dual-login"]["username"])) ? $_SESSION["dual-login"]["username"] : $username)); | |
| $acl_user = $stmt->fetch(PDO::FETCH_ASSOC); | |
| foreach ($acl_user as $acl_user_key => $acl_user_val) { | |
| $acl['acl'][$acl_user_key] = $acl_user_val; | |
| } | |
| unset($acl['acl']['username']); | |
| } | |
| elseif ($_SESSION['mailcow_cc_role'] == 'user') { | |
| $stmt = $pdo->prepare("SELECT * FROM `user_acl` WHERE `username` = :username"); | |
| $stmt->execute(array(':username' => $username)); | |
| $acl['acl'] = $stmt->fetch(PDO::FETCH_ASSOC); | |
| unset($acl['acl']['username']); | |
| } | |
| if (!empty($acl)) { | |
| $_SESSION = array_merge($_SESSION, $acl); | |
| } | |
| break; | |
| } | |
| } |