[Web] Fix require_once to always include document root

[Web] Add system mails (send mails to all mailboxes via LMTP)
[Web] Allow to add more administrators
[Web] Fix domain administrator editing
[Web] Remove some foreign keys
[Web] Remove username from API
[Web] Remove more .php extension from code
[Web] More minor fixes
This commit is contained in:
André
2018-10-11 11:59:23 +02:00
parent 32f7ae1d2e
commit 9f0be1d8a8
37 changed files with 1013 additions and 437 deletions

View File

@@ -0,0 +1,276 @@
<?php
function admin($_action, $_data = null) {
if ($_SESSION['mailcow_cc_role'] != "admin") {
$_SESSION['return'][] = array(
'type' => 'danger',
'log' => array(__FUNCTION__, $_action, $_data_log),
'msg' => 'access_denied'
);
return false;
}
global $pdo;
global $lang;
$_data_log = $_data;
!isset($_data_log['password']) ?: $_data_log['password'] = '*';
!isset($_data_log['password2']) ?: $_data_log['password2'] = '*';
switch ($_action) {
case 'add':
$username = strtolower(trim($_data['username']));
$password = $_data['password'];
$password2 = $_data['password2'];
$active = intval($_data['active']);
if (!ctype_alnum(str_replace(array('_', '.', '-'), '', $username)) || empty ($username)) {
$_SESSION['return'][] = array(
'type' => 'danger',
'log' => array(__FUNCTION__, $_action, $_data_log),
'msg' => 'username_invalid'
);
return false;
}
$stmt = $pdo->prepare("SELECT `username` FROM `admin`
WHERE `username` = :username");
$stmt->execute(array(':username' => $username));
$num_results[] = count($stmt->fetchAll(PDO::FETCH_ASSOC));
$stmt = $pdo->prepare("SELECT `username` FROM `domain_admins`
WHERE `username` = :username");
$stmt->execute(array(':username' => $username));
$num_results[] = count($stmt->fetchAll(PDO::FETCH_ASSOC));
foreach ($num_results as $num_results_each) {
if ($num_results_each != 0) {
$_SESSION['return'][] = array(
'type' => 'danger',
'log' => array(__FUNCTION__, $_action, $_data_log),
'msg' => array('object_exists', htmlspecialchars($username))
);
return false;
}
}
if (!empty($password) && !empty($password2)) {
if (!preg_match('/' . $GLOBALS['PASSWD_REGEP'] . '/', $password)) {
$_SESSION['return'][] = array(
'type' => 'danger',
'log' => array(__FUNCTION__, $_action, $_data_log),
'msg' => 'password_complexity'
);
return false;
}
if ($password != $password2) {
$_SESSION['return'][] = array(
'type' => 'danger',
'log' => array(__FUNCTION__, $_action, $_data_log),
'msg' => 'password_mismatch'
);
return false;
}
$password_hashed = hash_password($password);
$stmt = $pdo->prepare("INSERT INTO `admin` (`username`, `password`, `superadmin`, `active`)
VALUES (:username, :password_hashed, '1', :active)");
$stmt->execute(array(
':username' => $username,
':password_hashed' => $password_hashed,
':active' => $active
));
}
else {
$_SESSION['return'][] = array(
'type' => 'danger',
'log' => array(__FUNCTION__, $_action, $_data_log),
'msg' => 'password_empty'
);
return false;
}
$_SESSION['return'][] = array(
'type' => 'success',
'log' => array(__FUNCTION__, $_action, $_data_log),
'msg' => array('admin_added', htmlspecialchars($username))
);
break;
case 'edit':
if (!is_array($_data['username'])) {
$usernames = array();
$usernames[] = $_data['username'];
}
else {
$usernames = $_data['username'];
}
foreach ($usernames as $username) {
$is_now = admin('details', $username);
if (!empty($is_now)) {
$active = (isset($_data['active'])) ? intval($_data['active']) : $is_now['active_int'];
$username_new = (!empty($_data['username_new'])) ? $_data['username_new'] : $is_now['username'];
}
else {
$_SESSION['return'][] = array(
'type' => 'danger',
'log' => array(__FUNCTION__, $_action, $_data_log),
'msg' => 'access_denied'
);
continue;
}
$password = $_data['password'];
$password2 = $_data['password2'];
if ($active == 0) {
$left_active = 0;
foreach (admin('get') as $admin) {
$left_active = $left_active + admin('details', $admin)['active_int'];
}
if ($left_active == 1) {
$_SESSION['return'][] = array(
'type' => 'warning',
'log' => array(__FUNCTION__, $_action, $_data_log),
'msg' => 'no_active_admin'
);
continue;
}
}
if (!ctype_alnum(str_replace(array('_', '.', '-'), '', $username_new))) {
$_SESSION['return'][] = array(
'type' => 'danger',
'log' => array(__FUNCTION__, $_action, $_data_log),
'msg' => array('username_invalid', $username_new)
);
continue;
}
if ($username_new != $username) {
if (!empty(admin('details', $username_new)['username'])) {
$_SESSION['return'][] = array(
'type' => 'danger',
'log' => array(__FUNCTION__, $_action, $_data_log),
'msg' => array('username_invalid', $username_new)
);
continue;
}
}
if (!empty($password) && !empty($password2)) {
if (!preg_match('/' . $GLOBALS['PASSWD_REGEP'] . '/', $password)) {
$_SESSION['return'][] = array(
'type' => 'danger',
'log' => array(__FUNCTION__, $_action, $_data_log),
'msg' => 'password_complexity'
);
continue;
}
if ($password != $password2) {
$_SESSION['return'][] = array(
'type' => 'danger',
'log' => array(__FUNCTION__, $_action, $_data_log),
'msg' => 'password_mismatch'
);
continue;
}
$password_hashed = hash_password($password);
$stmt = $pdo->prepare("UPDATE `admin` SET `username` = :username_new, `active` = :active, `password` = :password_hashed WHERE `username` = :username");
$stmt->execute(array(
':password_hashed' => $password_hashed,
':username_new' => $username_new,
':username' => $username,
':active' => $active
));
if (isset($_data['disable_tfa'])) {
$stmt = $pdo->prepare("UPDATE `tfa` SET `active` = '0' WHERE `username` = :username");
$stmt->execute(array(':username' => $username));
}
else {
$stmt = $pdo->prepare("UPDATE `tfa` SET `username` = :username_new WHERE `username` = :username");
$stmt->execute(array(':username_new' => $username_new, ':username' => $username));
}
}
else {
$stmt = $pdo->prepare("UPDATE `admin` SET `username` = :username_new, `active` = :active WHERE `username` = :username");
$stmt->execute(array(
':username_new' => $username_new,
':username' => $username,
':active' => $active
));
if (isset($_data['disable_tfa'])) {
$stmt = $pdo->prepare("UPDATE `tfa` SET `active` = '0' WHERE `username` = :username");
$stmt->execute(array(':username' => $username));
}
else {
$stmt = $pdo->prepare("UPDATE `tfa` SET `username` = :username_new WHERE `username` = :username");
$stmt->execute(array(':username_new' => $username_new, ':username' => $username));
}
}
$_SESSION['return'][] = array(
'type' => 'success',
'log' => array(__FUNCTION__, $_action, $_data_log),
'msg' => array('admin_modified', htmlspecialchars($username))
);
}
return true;
break;
case 'delete':
$usernames = (array)$_data['username'];
foreach ($usernames as $username) {
if ($_SESSION['mailcow_cc_role'] == $username) {
$_SESSION['return'][] = array(
'type' => 'warning',
'log' => array(__FUNCTION__, $_action, $_data_log),
'msg' => 'cannot_delete_self'
);
continue;
}
if (empty(admin('details', $username))) {
$_SESSION['return'][] = array(
'type' => 'danger',
'log' => array(__FUNCTION__, $_action, $_data_log),
'msg' => array('username_invalid', $username)
);
continue;
}
$stmt = $pdo->prepare("DELETE FROM `admin` WHERE `username` = :username");
$stmt->execute(array(
':username' => $username,
));
$stmt = $pdo->prepare("DELETE FROM `domain_admins` WHERE `username` = :username");
$stmt->execute(array(
':username' => $username,
));
$_SESSION['return'][] = array(
'type' => 'success',
'log' => array(__FUNCTION__, $_action, $_data_log),
'msg' => array('admin_removed', htmlspecialchars($username))
);
}
break;
case 'get':
$admins = array();
$stmt = $pdo->query("SELECT `username` FROM `admin` WHERE `superadmin` = '1'");
$rows = $stmt->fetchAll(PDO::FETCH_ASSOC);
while ($row = array_shift($rows)) {
$admins[] = $row['username'];
}
return $admins;
break;
case 'details':
$admindata = array();
$stmt = $pdo->prepare("SELECT
`tfa`.`active` AS `tfa_active_int`,
CASE `tfa`.`active` WHEN 1 THEN '".$lang['mailbox']['yes']."' ELSE '".$lang['mailbox']['no']."' END AS `tfa_active`,
`admin`.`username`,
`admin`.`created`,
`admin`.`active` AS `active_int`,
CASE `admin`.`active` WHEN 1 THEN '".$lang['mailbox']['yes']."' ELSE '".$lang['mailbox']['no']."' END AS `active`
FROM `admin`
LEFT OUTER JOIN `tfa` ON `tfa`.`username`=`admin`.`username`
WHERE `admin`.`username`= :admin AND `superadmin` = '1'");
$stmt->execute(array(
':admin' => $_data
));
$row = $stmt->fetch(PDO::FETCH_ASSOC);
if (empty($row)) {
return false;
}
$admindata['username'] = $row['username'];
$admindata['tfa_active'] = $row['tfa_active'];
$admindata['active'] = $row['active'];
$admindata['tfa_active_int'] = $row['tfa_active_int'];
$admindata['active_int'] = $row['active_int'];
$admindata['created'] = $row['created'];
return $admindata;
break;
}
}

View File

@@ -1,5 +1,4 @@
<?php
function domain_admin($_action, $_data = null) {
global $pdo;
global $lang;
@@ -195,6 +194,11 @@ function domain_admin($_action, $_data = null) {
$stmt->execute(array(
':username' => $username,
));
$stmt = $pdo->prepare("UPDATE `da_acl` SET `username` = :username_new WHERE `username` = :username");
$stmt->execute(array(
':username_new' => $username_new,
':username' => $username
));
if (!empty($domains)) {
foreach ($domains as $domain) {
$stmt = $pdo->prepare("INSERT INTO `domain_admins` (`username`, `domain`, `created`, `active`)
@@ -277,7 +281,6 @@ function domain_admin($_action, $_data = null) {
WHERE `username` = :user");
$stmt->execute(array(':user' => $username));
$row = $stmt->fetch(PDO::FETCH_ASSOC);
if (!verify_hash($row['password'], $password_old)) {
$_SESSION['return'][] = array(
'type' => 'danger',
@@ -286,7 +289,6 @@ function domain_admin($_action, $_data = null) {
);
return false;
}
if (!empty($password_new2) && !empty($password_new)) {
if ($password_new2 != $password_new) {
$_SESSION['return'][] = array(
@@ -329,7 +331,7 @@ function domain_admin($_action, $_data = null) {
}
$usernames = (array)$_data['username'];
foreach ($usernames as $username) {
if (!ctype_alnum(str_replace(array('_', '.', '-'), '', $username))) {
if (empty(domain_admin('details', $username))) {
$_SESSION['return'][] = array(
'type' => 'danger',
'log' => array(__FUNCTION__, $_action, $_data_log),
@@ -345,6 +347,10 @@ function domain_admin($_action, $_data = null) {
$stmt->execute(array(
':username' => $username,
));
$stmt = $pdo->prepare("DELETE FROM `da_acl` WHERE `username` = :username");
$stmt->execute(array(
':username' => $username,
));
$_SESSION['return'][] = array(
'type' => 'success',
'log' => array(__FUNCTION__, $_action, $_data_log),
@@ -362,7 +368,6 @@ function domain_admin($_action, $_data = null) {
);
return false;
}
$stmt = $pdo->query("SELECT DISTINCT
`username`
FROM `domain_admins`
@@ -374,23 +379,19 @@ function domain_admin($_action, $_data = null) {
while ($row = array_shift($rows)) {
$domainadmins[] = $row['username'];
}
return $domainadmins;
break;
case 'details':
$domainadmindata = array();
if ($_SESSION['mailcow_cc_role'] == "domainadmin" && $_data != $_SESSION['mailcow_cc_username']) {
return false;
}
elseif ($_SESSION['mailcow_cc_role'] != "admin" || !isset($_data)) {
return false;
}
if (!ctype_alnum(str_replace(array('_', '.', '-'), '', $_data))) {
return false;
}
$stmt = $pdo->prepare("SELECT
`tfa`.`active` AS `tfa_active_int`,
CASE `tfa`.`active` WHEN 1 THEN '".$lang['mailbox']['yes']."' ELSE '".$lang['mailbox']['no']."' END AS `tfa_active`,
@@ -413,7 +414,7 @@ function domain_admin($_action, $_data = null) {
$domainadmindata['active'] = $row['active'];
$domainadmindata['tfa_active_int'] = $row['tfa_active_int'];
$domainadmindata['active_int'] = $row['active_int'];
$domainadmindata['modified'] = $row['created'];
$domainadmindata['created'] = $row['created'];
// GET SELECTED
$stmt = $pdo->prepare("SELECT `domain` FROM `domain`
WHERE `domain` IN (

View File

@@ -28,7 +28,99 @@ function flush_memcached() {
// Dunno
}
}
function sys_mail($_data) {
if ($_SESSION['mailcow_cc_role'] != "admin") {
$_SESSION['return'][] = array(
'type' => 'danger',
'log' => array(__FUNCTION__),
'msg' => 'access_denied'
);
return false;
}
$excludes = $_data['mass_exclude'];
$includes = $_data['mass_include'];
$mailboxes = array();
$mass_from = $_data['mass_from'];
$mass_text = $_data['mass_text'];
$mass_subject = $_data['mass_subject'];
if (!filter_var($mass_from, FILTER_VALIDATE_EMAIL)) {
$_SESSION['return'][] = array(
'type' => 'danger',
'log' => array(__FUNCTION__),
'msg' => 'From address must be a valid email address'
);
return false;
}
if (empty($mass_subject)) {
$_SESSION['return'][] = array(
'type' => 'danger',
'log' => array(__FUNCTION__),
'msg' => 'Subject must not be empty'
);
return false;
}
if (empty($mass_text)) {
$_SESSION['return'][] = array(
'type' => 'danger',
'log' => array(__FUNCTION__),
'msg' => 'Text must not be empty'
);
return false;
}
$domains = array_merge(mailbox('get', 'domains'), mailbox('get', 'alias_domains'));
foreach ($domains as $domain) {
foreach (mailbox('get', 'mailboxes', $domain) as $mailbox) {
$mailboxes[] = $mailbox;
}
}
if (!empty($includes)) {
$rcpts = array_intersect($mailboxes, $includes);
}
elseif (!empty($excludes)) {
$rcpts = array_diff($mailboxes, $excludes);
}
else {
$rcpts = $mailboxes;
}
if (!empty($rcpts)) {
ini_set('max_execution_time', 0);
ini_set('max_input_time', 0);
$mail = new PHPMailer;
$mail->Timeout = 10;
$mail->SMTPOptions = array(
'ssl' => array(
'verify_peer' => false,
'verify_peer_name' => false,
'allow_self_signed' => true
)
);
$mail->isSMTP();
$mail->Host = 'dovecot-mailcow';
$mail->SMTPAuth = false;
$mail->Port = 24;
$mail->setFrom($mass_from);
$mail->Subject = $mass_subject;
$mail->CharSet ="UTF-8";
$mail->Body = $mass_text;
$mail->XMailer = 'MooMassMail';
foreach ($rcpts as $rcpt) {
$mail->AddAddress($rcpt);
if (!$mail->send()) {
$_SESSION['return'][] = array(
'type' => 'warning',
'log' => array(__FUNCTION__),
'msg' => 'Mailer error (RCPT "' . htmlspecialchars($rcpt) . '"): ' . str_replace('https://github.com/PHPMailer/PHPMailer/wiki/Troubleshooting', '', $mail->ErrorInfo)
);
}
$mail->ClearAllRecipients();
}
}
$_SESSION['return'][] = array(
'type' => 'success',
'log' => array(__FUNCTION__),
'msg' => 'Mass mail job completed, sent ' . count($rcpts) . ' mails'
);
}
function logger($_data = false) {
/*
logger() will be called as last function
@@ -106,21 +198,35 @@ function hasDomainAccess($username, $role, $domain) {
if (empty($domain) || !is_valid_domain_name($domain)) {
return false;
}
if ($role != 'admin' && $role != 'domainadmin' && $role != 'user') {
if ($role != 'admin' && $role != 'domainadmin') {
return false;
}
$stmt = $pdo->prepare("SELECT `domain` FROM `domain_admins`
WHERE (
`active`='1'
AND `username` = :username
AND (`domain` = :domain1 OR `domain` = (SELECT `target_domain` FROM `alias_domain` WHERE `alias_domain` = :domain2))
)
OR 'admin' = :role");
$stmt->execute(array(':username' => $username, ':domain1' => $domain, ':domain2' => $domain, ':role' => $role));
$num_results = count($stmt->fetchAll(PDO::FETCH_ASSOC));
if (!empty($num_results)) {
return true;
}
if ($role == 'admin') {
$stmt = $pdo->prepare("SELECT `domain` FROM `domain`
WHERE `domain` = :domain");
$stmt->execute(array(':domain' => $domain));
$num_results = count($stmt->fetchAll(PDO::FETCH_ASSOC));
$stmt = $pdo->prepare("SELECT `alias_domain` FROM `alias_domain`
WHERE `alias_domain` = :domain");
$stmt->execute(array(':domain' => $domain));
$num_results = $num_results + count($stmt->fetchAll(PDO::FETCH_ASSOC));
if ($num_results != 0) {
return true;
}
}
elseif ($role == 'domainadmin') {
$stmt = $pdo->prepare("SELECT `domain` FROM `domain_admins`
WHERE (
`active`='1'
AND `username` = :username
AND (`domain` = :domain1 OR `domain` = (SELECT `target_domain` FROM `alias_domain` WHERE `alias_domain` = :domain2))
)");
$stmt->execute(array(':username' => $username, ':domain1' => $domain, ':domain2' => $domain));
$num_results = count($stmt->fetchAll(PDO::FETCH_ASSOC));
if (!empty($num_results)) {
return true;
}
}
return false;
}
function hasMailboxObjectAccess($username, $role, $object) {
@@ -318,6 +424,9 @@ function check_login($user, $pass) {
}
else {
unset($_SESSION['ldelay']);
// Reactivate TFA if it was set to "deactivate TFA for next login"
$stmt = $pdo->prepare("UPDATE `tfa` SET `active`='1' WHERE `username` = :user");
$stmt->execute(array(':user' => $user));
$_SESSION['return'][] = array(
'type' => 'success',
'log' => array(__FUNCTION__, $user, '*'),
@@ -407,110 +516,6 @@ function formatBytes($size, $precision = 2) {
}
return round(pow(1024, $base - floor($base)), $precision) . $suffixes[floor($base)];
}
function edit_admin_account($_data) {
global $lang;
global $pdo;
$_data_log = $_data;
!isset($_data_log['admin_pass']) ?: $_data_log['admin_pass'] = '*';
!isset($_data_log['admin_pass2']) ?: $_data_log['admin_pass2'] = '*';
if ($_SESSION['mailcow_cc_role'] != "admin") {
$_SESSION['return'][] = array(
'type' => 'danger',
'log' => array(__FUNCTION__, $_data_log),
'msg' => 'access_denied'
);
return false;
}
$username_now = $_SESSION['mailcow_cc_username'];
$username = $_data['admin_user'];
$password = $_data['admin_pass'];
$password2 = $_data['admin_pass2'];
if (!ctype_alnum(str_replace(array('_', '.', '-'), '', $username)) || empty ($username)) {
$_SESSION['return'][] = array(
'type' => 'danger',
'log' => array(__FUNCTION__, $_data_log),
'msg' => 'username_invalid'
);
return false;
}
if (!empty($password) && !empty($password2)) {
if (!preg_match('/' . $GLOBALS['PASSWD_REGEP'] . '/', $password)) {
$_SESSION['return'][] = array(
'type' => 'danger',
'log' => array(__FUNCTION__, $_data_log),
'msg' => 'password_complexity'
);
return false;
}
if ($password != $password2) {
$_SESSION['return'][] = array(
'type' => 'danger',
'log' => array(__FUNCTION__, $_data_log),
'msg' => 'password_mismatch'
);
return false;
}
$password_hashed = hash_password($password);
try {
$stmt = $pdo->prepare("UPDATE `admin` SET
`password` = :password_hashed,
`username` = :username1
WHERE `username` = :username2");
$stmt->execute(array(
':password_hashed' => $password_hashed,
':username1' => $username,
':username2' => $username_now
));
}
catch (PDOException $e) {
$_SESSION['return'][] = array(
'type' => 'danger',
'log' => array(__FUNCTION__, $_data_log),
'msg' => array('mysql_error', $e)
);
return false;
}
}
else {
try {
$stmt = $pdo->prepare("UPDATE `admin` SET
`username` = :username1
WHERE `username` = :username2");
$stmt->execute(array(
':username1' => $username,
':username2' => $username_now
));
}
catch (PDOException $e) {
$_SESSION['return'][] = array(
'type' => 'danger',
'log' => array(__FUNCTION__, $_data_log),
'msg' => array('mysql_error', $e)
);
return false;
}
}
try {
$stmt = $pdo->prepare("UPDATE `domain_admins` SET `domain` = 'ALL', `username` = :username1 WHERE `username` = :username2");
$stmt->execute(array(':username1' => $username, ':username2' => $username_now));
$stmt = $pdo->prepare("UPDATE `tfa` SET `username` = :username1 WHERE `username` = :username2");
$stmt->execute(array(':username1' => $username, ':username2' => $username_now));
}
catch (PDOException $e) {
$_SESSION['return'][] = array(
'type' => 'danger',
'log' => array(__FUNCTION__, $_data_log),
'msg' => array('mysql_error', $e)
);
return false;
}
$_SESSION['mailcow_cc_username'] = $username;
$_SESSION['return'][] = array(
'type' => 'success',
'log' => array(__FUNCTION__, $_data_log),
'msg' => 'admin_modified'
);
}
function update_sogo_static_view() {
global $pdo;
global $lang;
@@ -1113,6 +1118,11 @@ function admin_api($action, $data = null) {
$allow_from = array_map('trim', preg_split( "/( |,|;|\n)/", $data['allow_from']));
foreach ($allow_from as $key => $val) {
if (!filter_var($val, FILTER_VALIDATE_IP)) {
$_SESSION['return'][] = array(
'type' => 'warning',
'log' => array(__FUNCTION__, $data),
'msg' => array('ip_invalid', htmlspecialchars($allow_from[$key]))
);
unset($allow_from[$key]);
continue;
}
@@ -1133,16 +1143,24 @@ function admin_api($action, $data = null) {
strtoupper(bin2hex(random_bytes(3))),
strtoupper(bin2hex(random_bytes(3)))
));
$stmt = $pdo->prepare("INSERT INTO `api` (`username`, `api_key`, `active`, `allow_from`)
SELECT `username`, :api_key, :active, :allow_from FROM `admin` WHERE `superadmin`='1' AND `active`='1'
ON DUPLICATE KEY UPDATE `active` = :active_u, `allow_from` = :allow_from_u ;");
$stmt->execute(array(
':api_key' => $api_key,
':active' => $active,
':active_u' => $active,
':allow_from' => $allow_from,
':allow_from_u' => $allow_from
));
$stmt = $pdo->query("SELECT `api_key` FROM `api`");
$num_results = count($stmt->fetchAll(PDO::FETCH_ASSOC));
if (empty($num_results)) {
$stmt = $pdo->prepare("INSERT INTO `api` (`api_key`, `active`, `allow_from`)
VALUES (:api_key, :active, :allow_from);");
$stmt->execute(array(
':api_key' => $api_key,
':active' => $active,
':allow_from' => $allow_from
));
}
else {
$stmt = $pdo->prepare("UPDATE `api` SET `active` = :active, `allow_from` = :allow_from ;");
$stmt->execute(array(
':active' => $active,
':allow_from' => $allow_from
));
}
break;
case "regen_key":
$api_key = implode('-', array(
@@ -1152,17 +1170,21 @@ function admin_api($action, $data = null) {
strtoupper(bin2hex(random_bytes(3))),
strtoupper(bin2hex(random_bytes(3)))
));
$stmt = $pdo->prepare("UPDATE `api` SET `api_key` = :api_key WHERE `username` IN
(SELECT `username` FROM `admin` WHERE `superadmin`='1' AND `active`='1')");
$stmt = $pdo->prepare("UPDATE `api` SET `api_key` = :api_key");
$stmt->execute(array(
':api_key' => $api_key
));
break;
case "get":
$stmt = $pdo->query("SELECT * FROM `api`");
$apidata = $stmt->fetch(PDO::FETCH_ASSOC);
return $apidata;
break;
}
$_SESSION['return'][] = array(
'type' => 'success',
'log' => array(__FUNCTION__, $data),
'msg' => 'admin_modified'
'msg' => 'admin_api_modified'
);
}
function rspamd_ui($action, $data = null) {
@@ -1233,21 +1255,6 @@ function rspamd_ui($action, $data = null) {
break;
}
}
function get_admin_details() {
// No parameter to be given, only one admin should exist
global $pdo;
global $lang;
$data = array();
if ($_SESSION['mailcow_cc_role'] != 'admin') {
return false;
}
$stmt = $pdo->query("SELECT `admin`.`username`, `api`.`active` AS `api_active`, `api`.`api_key`, `api`.`allow_from` FROM `admin`
LEFT OUTER JOIN `api` ON `admin`.`username` = `api`.`username`
WHERE `admin`.`superadmin`='1'
AND `admin`.`active`='1'");
$data = $stmt->fetch(PDO::FETCH_ASSOC);
return $data;
}
function get_u2f_registrations($username) {
global $pdo;
$sel = $pdo->prepare("SELECT * FROM `tfa` WHERE `authmech` = 'u2f' AND `username` = ? AND `active` = '1'");

View File

@@ -2277,7 +2277,7 @@ function mailbox($_action, $_type, $_data = null, $_extra = null) {
return false;
}
elseif (isset($_data) && hasDomainAccess($_SESSION['mailcow_cc_username'], $_SESSION['mailcow_cc_role'], $_data)) {
$stmt = $pdo->prepare("SELECT `username` FROM `mailbox` WHERE `kind` NOT REGEXP 'location|thing|group' AND `domain` != 'ALL' AND `domain` = :domain");
$stmt = $pdo->prepare("SELECT `username` FROM `mailbox` WHERE `kind` NOT REGEXP 'location|thing|group' AND `domain` = :domain");
$stmt->execute(array(
':domain' => $_data,
));
@@ -2535,7 +2535,7 @@ function mailbox($_action, $_type, $_data = null, $_extra = null) {
return false;
}
elseif (isset($_data) && hasDomainAccess($_SESSION['mailcow_cc_username'], $_SESSION['mailcow_cc_role'], $_data)) {
$stmt = $pdo->prepare("SELECT `username` FROM `mailbox` WHERE `kind` REGEXP 'location|thing|group' AND `domain` != 'ALL' AND `domain` = :domain");
$stmt = $pdo->prepare("SELECT `username` FROM `mailbox` WHERE `kind` REGEXP 'location|thing|group' AND `domain` = :domain");
$stmt->execute(array(
':domain' => $_data,
));
@@ -2680,8 +2680,7 @@ function mailbox($_action, $_type, $_data = null, $_extra = null) {
SELECT `domain` from `domain_admins`
WHERE (`active`='1' AND `username` = :username))
)
OR ('admin'= :role)
AND `domain` != 'ALL'");
OR 'admin'= :role");
$stmt->execute(array(
':username' => $_SESSION['mailcow_cc_username'],
':role' => $_SESSION['mailcow_cc_role'],

View File

@@ -3,7 +3,7 @@ function init_db_schema() {
try {
global $pdo;
$db_version = "03102018_1502";
$db_version = "07102018_1502";
$stmt = $pdo->query("SHOW TABLES LIKE 'versions'");
$num_results = count($stmt->fetchAll(PDO::FETCH_ASSOC));
@@ -135,7 +135,6 @@ function init_db_schema() {
),
"api" => array(
"cols" => array(
"username" => "VARCHAR(255) NOT NULL",
"api_key" => "VARCHAR(255) NOT NULL",
"allow_from" => "VARCHAR(512) NOT NULL",
"created" => "DATETIME(0) NOT NULL DEFAULT NOW(0)",
@@ -144,16 +143,8 @@ function init_db_schema() {
),
"keys" => array(
"primary" => array(
"" => array("username")
"" => array("api_key")
),
"fkey" => array(
"fk_username_api" => array(
"col" => "username",
"ref" => "admin.username",
"delete" => "CASCADE",
"update" => "CASCADE"
)
)
),
"attr" => "ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 ROW_FORMAT=DYNAMIC"
),
@@ -448,14 +439,6 @@ function init_db_schema() {
"keys" => array(
"primary" => array(
"" => array("username")
),
"fkey" => array(
"fk_domain_admin_acl" => array(
"col" => "username",
"ref" => "domain_admins.username",
"delete" => "CASCADE",
"update" => "NO ACTION"
)
)
),
"attr" => "ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 ROW_FORMAT=DYNAMIC"
@@ -987,22 +970,49 @@ DELIMITER ;';
WHERE `username` = :username");
$stmt->execute(array(':tls_enforce_in' => $tls_options['tls_enforce_in'], ':tls_enforce_out' => $tls_options['tls_enforce_out'], ':username' => $tls_user));
}
$_SESSION['return'][] = array(
'type' => 'success',
'log' => array(__FUNCTION__),
'msg' => 'db_init_complete'
);
if (php_sapi_name() == "cli") {
echo "DB initialization completed" . PHP_EOL;
} else {
$_SESSION['return'][] = array(
'type' => 'success',
'log' => array(__FUNCTION__),
'msg' => 'db_init_complete'
);
}
// Fix ACL
$stmt = $pdo->query("INSERT INTO `user_acl` (`username`) SELECT `username` FROM `mailbox` WHERE `kind` = '' AND NOT EXISTS (SELECT `username` FROM `user_acl`);");
$stmt = $pdo->query("INSERT INTO `da_acl` (`username`) SELECT DISTINCT `username` FROM `domain_admins` WHERE `username` != 'admin' AND NOT EXISTS (SELECT `username` FROM `da_acl`);");
// Fix domain_admins
$stmt = $pdo->query("DELETE FROM `domain_admins` WHERE `domain` = 'ALL';");
}
catch (PDOException $e) {
$_SESSION['return'][] = array(
'type' => 'danger',
'log' => array(__FUNCTION__),
'msg' => array('mysql_error', $e)
);
if (php_sapi_name() == "cli") {
echo "DB initialization failed: " . print_r($e, true) . PHP_EOL;
} else {
$_SESSION['return'][] = array(
'type' => 'danger',
'log' => array(__FUNCTION__),
'msg' => array('mysql_error', $e)
);
}
}
}
?>
if (php_sapi_name() == "cli") {
include '/web/inc/vars.inc.php';
$now = new DateTime();
$mins = $now->getOffset() / 60;
$sgn = ($mins < 0 ? -1 : 1);
$mins = abs($mins);
$hrs = floor($mins / 60);
$mins -= $hrs * 60;
$offset = sprintf('%+d:%02d', $hrs*$sgn, $mins);
$dsn = $database_type . ":unix_socket=" . $database_sock . ";dbname=" . $database_name;
$opt = [
PDO::ATTR_ERRMODE => PDO::ERRMODE_EXCEPTION,
PDO::ATTR_DEFAULT_FETCH_MODE => PDO::FETCH_ASSOC,
PDO::ATTR_EMULATE_PREPARES => false,
PDO::MYSQL_ATTR_INIT_COMMAND => "SET time_zone = '" . $offset . "', group_concat_max_len = 3423543543;",
];
$pdo = new PDO($dsn, $database_user, $database_pass, $opt);
init_db_schema();
}

View File

@@ -139,6 +139,7 @@ require_once $_SERVER['DOCUMENT_ROOT'] . '/inc/functions.mailbox.inc.php';
require_once $_SERVER['DOCUMENT_ROOT'] . '/inc/functions.customize.inc.php';
require_once $_SERVER['DOCUMENT_ROOT'] . '/inc/functions.address_rewriting.inc.php';
require_once $_SERVER['DOCUMENT_ROOT'] . '/inc/functions.domain_admin.inc.php';
require_once $_SERVER['DOCUMENT_ROOT'] . '/inc/functions.admin.inc.php';
require_once $_SERVER['DOCUMENT_ROOT'] . '/inc/functions.quarantine.inc.php';
require_once $_SERVER['DOCUMENT_ROOT'] . '/inc/functions.policy.inc.php';
require_once $_SERVER['DOCUMENT_ROOT'] . '/inc/functions.dkim.inc.php';

View File

@@ -28,16 +28,16 @@ if (!isset($_SESSION['SESS_REMOTE_UA'])) {
// API
if (!empty($_SERVER['HTTP_X_API_KEY'])) {
$stmt = $pdo->prepare("SELECT `username`, `allow_from` FROM `api` WHERE `api_key` = :api_key AND `active` = '1';");
$stmt = $pdo->prepare("SELECT `allow_from` FROM `api` WHERE `api_key` = :api_key AND `active` = '1';");
$stmt->execute(array(
':api_key' => preg_replace('/[^A-Z0-9-]/i', '', $_SERVER['HTTP_X_API_KEY'])
':api_key' => preg_replace('/[^a-zA-Z0-9-]/', '', $_SERVER['HTTP_X_API_KEY'])
));
$api_return = $stmt->fetch(PDO::FETCH_ASSOC);
if (!empty($api_return['username'])) {
$remote = get_remote_ip(false);
$allow_from = array_map('trim', preg_split( "/( |,|;|\n)/", $api_return['allow_from']));
if (in_array($remote, $allow_from)) {
$_SESSION['mailcow_cc_username'] = $api_return['username'];
$_SESSION['mailcow_cc_username'] = 'API';
$_SESSION['mailcow_cc_role'] = 'admin';
$_SESSION['mailcow_cc_api'] = true;
}
@@ -84,7 +84,7 @@ if (isset($_POST["logout"])) {
$_SESSION["mailcow_cc_username"] = $_SESSION["dual-login"]["username"];
$_SESSION["mailcow_cc_role"] = $_SESSION["dual-login"]["role"];
unset($_SESSION["dual-login"]);
header("Location: /mailbox.php");
header("Location: /mailbox");
exit();
}
else {

View File

@@ -6,7 +6,7 @@ if (isset($_POST["verify_tfa_login"])) {
unset($_SESSION['pending_mailcow_cc_username']);
unset($_SESSION['pending_mailcow_cc_role']);
unset($_SESSION['pending_tfa_method']);
header("Location: /user.php");
header("Location: /user");
}
}
@@ -17,19 +17,19 @@ if (isset($_POST["login_user"]) && isset($_POST["pass_user"])) {
$_SESSION['mailcow_cc_username'] = $login_user;
$_SESSION['mailcow_cc_role'] = "admin";
$_SESSION['mailcow_cc_last_login'] = last_login($login_user);
header("Location: /admin.php");
header("Location: /admin");
}
elseif ($as == "domainadmin") {
$_SESSION['mailcow_cc_username'] = $login_user;
$_SESSION['mailcow_cc_role'] = "domainadmin";
$_SESSION['mailcow_cc_last_login'] = last_login($login_user);
header("Location: /mailbox.php");
header("Location: /mailbox");
}
elseif ($as == "user") {
$_SESSION['mailcow_cc_username'] = $login_user;
$_SESSION['mailcow_cc_role'] = "user";
$_SESSION['mailcow_cc_last_login'] = last_login($login_user);
header("Location: /user.php");
header("Location: /user");
}
elseif ($as != "pending") {
unset($_SESSION['pending_mailcow_cc_username']);
@@ -49,7 +49,7 @@ if (isset($_SESSION['mailcow_cc_role']) && $_SESSION['acl']['login_as'] == "1")
$_SESSION["dual-login"]["role"] = $_SESSION['mailcow_cc_role'];
$_SESSION['mailcow_cc_username'] = $duallogin;
$_SESSION['mailcow_cc_role'] = "user";
header("Location: /user.php");
header("Location: /user");
}
}
else {
@@ -58,7 +58,7 @@ if (isset($_SESSION['mailcow_cc_role']) && $_SESSION['acl']['login_as'] == "1")
$_SESSION["dual-login"]["role"] = $_SESSION['mailcow_cc_role'];
$_SESSION['mailcow_cc_username'] = $duallogin;
$_SESSION['mailcow_cc_role'] = "domainadmin";
header("Location: /user.php");
header("Location: /user");
}
}
}
@@ -93,5 +93,8 @@ if (isset($_SESSION['mailcow_cc_role']) && $_SESSION['mailcow_cc_role'] == "admi
if (isset($_POST["rspamd_ui"])) {
rspamd_ui('edit', $_POST);
}
if (isset($_POST["mass_send"])) {
sys_mail($_POST);
}
}
?>

View File

@@ -87,7 +87,12 @@ $AVAILABLE_LANGUAGES = array('de', 'en', 'es', 'fr', 'lv', 'nl', 'pl', 'pt', 'ru
$DEFAULT_THEME = 'lumen';
// Password complexity as regular expression
$PASSWD_REGEP = '.{4,}';
// Min. 6 characters
//$PASSWD_REGEP = '.{6,}';
// Min. 6 characters, which must include at least one uppercase letter, one lowercase letter and one number
// $PASSWD_REGEP = '^(?=.*[A-Z])(?=.*[0-9])(?=.*[a-z]).{6,}$';
// Min. 6 characters, which must include at least one letter and one number
$PASSWD_REGEP = '^(?=.*[0-9])(?=.*[A-Za-z]).{6,}$';
// Show DKIM private keys - false by default
$SHOW_DKIM_PRIV_KEYS = false;