Matthias Andreas Benkard | b382b10 | 2021-01-02 15:32:21 +0100 | [diff] [blame] | 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 | } |