[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:
@@ -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'");
|
||||
|
Reference in New Issue
Block a user