[Web, Dovecot] Allow to define scope of services for app passwords
This commit is contained in:
@@ -27,6 +27,11 @@ function app_passwd($_action, $_data = null) {
|
||||
$password = $_data['app_passwd'];
|
||||
$password2 = $_data['app_passwd2'];
|
||||
$active = intval($_data['active']);
|
||||
$protocols = (array)$_data['protocols'];
|
||||
$imap_access = (in_array('imap_access', $protocols)) ? 1 : 0;
|
||||
$dav_access = (in_array('dav_access', $protocols)) ? 1 : 0;
|
||||
$smtp_access = (in_array('smtp_access', $protocols)) ? 1 : 0;
|
||||
$eas_access = (in_array('eas_access', $protocols)) ? 1 : 0;
|
||||
$domain = mailbox('get', 'mailbox_details', $username)['domain'];
|
||||
if (empty($domain)) {
|
||||
$_SESSION['return'][] = array(
|
||||
@@ -61,13 +66,17 @@ function app_passwd($_action, $_data = null) {
|
||||
);
|
||||
return false;
|
||||
}
|
||||
$stmt = $pdo->prepare("INSERT INTO `app_passwd` (`name`, `mailbox`, `domain`, `password`, `active`)
|
||||
VALUES (:app_name, :mailbox, :domain, :password, :active)");
|
||||
$stmt = $pdo->prepare("INSERT INTO `app_passwd` (`name`, `mailbox`, `domain`, `password`, `imap_access`, `smtp_access`, `eas_access`, `dav_access`, `active`)
|
||||
VALUES (:app_name, :mailbox, :domain, :password, :imap_access, :smtp_access, :eas_access, :dav_access, :active)");
|
||||
$stmt->execute(array(
|
||||
':app_name' => $app_name,
|
||||
':mailbox' => $username,
|
||||
':domain' => $domain,
|
||||
':password' => $password_hashed,
|
||||
':imap_access' => $imap_access,
|
||||
':smtp_access' => $smtp_access,
|
||||
':eas_access' => $eas_access,
|
||||
':dav_access' => $dav_access,
|
||||
':active' => $active
|
||||
));
|
||||
$_SESSION['return'][] = array(
|
||||
@@ -84,6 +93,19 @@ function app_passwd($_action, $_data = null) {
|
||||
$app_name = (!empty($_data['app_name'])) ? $_data['app_name'] : $is_now['name'];
|
||||
$password = (!empty($_data['password'])) ? $_data['password'] : null;
|
||||
$password2 = (!empty($_data['password2'])) ? $_data['password2'] : null;
|
||||
if (isset($_data['protocols'])) {
|
||||
$protocols = (array)$_data['protocols'];
|
||||
$imap_access = (in_array('imap_access', $protocols)) ? 1 : 0;
|
||||
$dav_access = (in_array('dav_access', $protocols)) ? 1 : 0;
|
||||
$smtp_access = (in_array('smtp_access', $protocols)) ? 1 : 0;
|
||||
$eas_access = (in_array('eas_access', $protocols)) ? 1 : 0;
|
||||
}
|
||||
else {
|
||||
$imap_access = $is_now['imap_access'];
|
||||
$smtp_access = $is_now['smtp_access'];
|
||||
$dav_access = $is_now['dav_access'];
|
||||
$eas_access = $is_now['eas_access'];
|
||||
}
|
||||
$active = (isset($_data['active'])) ? intval($_data['active']) : $is_now['active'];
|
||||
}
|
||||
else {
|
||||
@@ -122,14 +144,23 @@ function app_passwd($_action, $_data = null) {
|
||||
':id' => $id
|
||||
));
|
||||
}
|
||||
|
||||
$stmt = $pdo->prepare("UPDATE `app_passwd` SET
|
||||
`name` = :app_name,
|
||||
`mailbox` = :username,
|
||||
`imap_access` = :imap_access,
|
||||
`smtp_access` = :smtp_access,
|
||||
`eas_access` = :eas_access,
|
||||
`dav_access` = :dav_access,
|
||||
`active` = :active
|
||||
WHERE `id` = :id");
|
||||
$stmt->execute(array(
|
||||
':app_name' => $app_name,
|
||||
':username' => $username,
|
||||
':imap_access' => $imap_access,
|
||||
':smtp_access' => $smtp_access,
|
||||
':eas_access' => $eas_access,
|
||||
':dav_access' => $dav_access,
|
||||
':active' => $active,
|
||||
':id' => $id
|
||||
));
|
||||
@@ -180,13 +211,7 @@ function app_passwd($_action, $_data = null) {
|
||||
break;
|
||||
case 'details':
|
||||
$app_passwd_data = array();
|
||||
$stmt = $pdo->prepare("SELECT `id`,
|
||||
`name`,
|
||||
`mailbox`,
|
||||
`domain`,
|
||||
`created`,
|
||||
`modified`,
|
||||
`active`
|
||||
$stmt = $pdo->prepare("SELECT *
|
||||
FROM `app_passwd`
|
||||
WHERE `id` = :id");
|
||||
$stmt->execute(array(':id' => $_data));
|
||||
|
@@ -807,10 +807,17 @@ function verify_hash($hash, $password) {
|
||||
}
|
||||
return false;
|
||||
}
|
||||
function check_login($user, $pass, $allow_app_passwords = false) {
|
||||
function check_login($user, $pass, $app_passwd_data = false) {
|
||||
global $pdo;
|
||||
global $redis;
|
||||
global $imap_server;
|
||||
|
||||
if ($app_passwd_data === false) {
|
||||
$app_passwd_data['eas'] = false;
|
||||
$app_passwd_data['dav'] = false;
|
||||
$app_passwd_data['proxyauth'] = false;
|
||||
}
|
||||
|
||||
if (!filter_var($user, FILTER_VALIDATE_EMAIL) && !ctype_alnum(str_replace(array('_', '.', '-'), '', $user))) {
|
||||
$_SESSION['return'][] = array(
|
||||
'type' => 'danger',
|
||||
@@ -819,6 +826,8 @@ function check_login($user, $pass, $allow_app_passwords = false) {
|
||||
);
|
||||
return false;
|
||||
}
|
||||
|
||||
// Validate admin
|
||||
$user = strtolower(trim($user));
|
||||
$stmt = $pdo->prepare("SELECT `password` FROM `admin`
|
||||
WHERE `superadmin` = '1'
|
||||
@@ -854,6 +863,8 @@ function check_login($user, $pass, $allow_app_passwords = false) {
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// Validate domain admin
|
||||
$stmt = $pdo->prepare("SELECT `password` FROM `admin`
|
||||
WHERE `superadmin` = '0'
|
||||
AND `active`='1'
|
||||
@@ -888,6 +899,8 @@ function check_login($user, $pass, $allow_app_passwords = false) {
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// Validate mailbox user
|
||||
$stmt = $pdo->prepare("SELECT `password` FROM `mailbox`
|
||||
INNER JOIN domain on mailbox.domain = domain.domain
|
||||
WHERE `kind` NOT REGEXP 'location|thing|group'
|
||||
@@ -896,7 +909,7 @@ function check_login($user, $pass, $allow_app_passwords = false) {
|
||||
AND `username` = :user");
|
||||
$stmt->execute(array(':user' => $user));
|
||||
$rows = $stmt->fetchAll(PDO::FETCH_ASSOC);
|
||||
if ($allow_app_passwords === true) {
|
||||
if ($app_passwd_data['eas'] === true) {
|
||||
$stmt = $pdo->prepare("SELECT `app_passwd`.`password` as `password`, `app_passwd`.`id` as `app_passwd_id` FROM `app_passwd`
|
||||
INNER JOIN `mailbox` ON `mailbox`.`username` = `app_passwd`.`mailbox`
|
||||
INNER JOIN `domain` ON `mailbox`.`domain` = `domain`.`domain`
|
||||
@@ -904,6 +917,20 @@ function check_login($user, $pass, $allow_app_passwords = false) {
|
||||
AND `mailbox`.`active` = '1'
|
||||
AND `domain`.`active` = '1'
|
||||
AND `app_passwd`.`active` = '1'
|
||||
AND `app_passwd`.`eas_access` = '1'
|
||||
AND `app_passwd`.`mailbox` = :user");
|
||||
$stmt->execute(array(':user' => $user));
|
||||
$rows = array_merge($rows, $stmt->fetchAll(PDO::FETCH_ASSOC));
|
||||
}
|
||||
elseif ($app_passwd_data['dav'] === true) {
|
||||
$stmt = $pdo->prepare("SELECT `app_passwd`.`password` as `password`, `app_passwd`.`id` as `app_passwd_id` FROM `app_passwd`
|
||||
INNER JOIN `mailbox` ON `mailbox`.`username` = `app_passwd`.`mailbox`
|
||||
INNER JOIN `domain` ON `mailbox`.`domain` = `domain`.`domain`
|
||||
WHERE `mailbox`.`kind` NOT REGEXP 'location|thing|group'
|
||||
AND `mailbox`.`active` = '1'
|
||||
AND `domain`.`active` = '1'
|
||||
AND `app_passwd`.`active` = '1'
|
||||
AND `app_passwd`.`dav_access` = '1'
|
||||
AND `app_passwd`.`mailbox` = :user");
|
||||
$stmt->execute(array(':user' => $user));
|
||||
$rows = array_merge($rows, $stmt->fetchAll(PDO::FETCH_ASSOC));
|
||||
@@ -916,9 +943,20 @@ function check_login($user, $pass, $allow_app_passwords = false) {
|
||||
'log' => array(__FUNCTION__, $user, '*'),
|
||||
'msg' => array('logged_in_as', $user)
|
||||
);
|
||||
if ($app_passwd_data['proxyauth'] === true) {
|
||||
$service = ($app_passwd_data['eas'] === true) ? 'EAS' : (($app_passwd_data['dav'] === true) ? 'DAV' : 'SSO');
|
||||
$stmt = $pdo->prepare("REPLACE INTO sasl_log (`service`, `app_password`, `username`, `real_rip`) VALUES (:service, :app_id, :username, :remote_addr)");
|
||||
$stmt->execute(array(
|
||||
':service' => $service,
|
||||
':app_id' => $row['app_passwd_id'],
|
||||
':username' => $user,
|
||||
':remote_addr' => $_SERVER['REMOTE_ADDR']
|
||||
));
|
||||
}
|
||||
return "user";
|
||||
}
|
||||
}
|
||||
|
||||
if (!isset($_SESSION['ldelay'])) {
|
||||
$_SESSION['ldelay'] = "0";
|
||||
$redis->publish("F2B_CHANNEL", "mailcow UI: Invalid password for " . $user . " by " . $_SERVER['REMOTE_ADDR']);
|
||||
@@ -929,11 +967,13 @@ function check_login($user, $pass, $allow_app_passwords = false) {
|
||||
$redis->publish("F2B_CHANNEL", "mailcow UI: Invalid password for " . $user . " by " . $_SERVER['REMOTE_ADDR']);
|
||||
error_log("mailcow UI: Invalid password for " . $user . " by " . $_SERVER['REMOTE_ADDR']);
|
||||
}
|
||||
|
||||
$_SESSION['return'][] = array(
|
||||
'type' => 'danger',
|
||||
'log' => array(__FUNCTION__, $user, '*'),
|
||||
'msg' => 'login_failed'
|
||||
);
|
||||
|
||||
sleep($_SESSION['ldelay']);
|
||||
return false;
|
||||
}
|
||||
|
@@ -3,7 +3,7 @@ function init_db_schema() {
|
||||
try {
|
||||
global $pdo;
|
||||
|
||||
$db_version = "23082021_2224";
|
||||
$db_version = "28102021_1600";
|
||||
|
||||
$stmt = $pdo->query("SHOW TABLES LIKE 'versions'");
|
||||
$num_results = count($stmt->fetchAll(PDO::FETCH_ASSOC));
|
||||
@@ -364,6 +364,10 @@ function init_db_schema() {
|
||||
"password" => "VARCHAR(255) NOT NULL",
|
||||
"created" => "DATETIME(0) NOT NULL DEFAULT NOW(0)",
|
||||
"modified" => "DATETIME ON UPDATE CURRENT_TIMESTAMP",
|
||||
"imap_access" => "TINYINT(1) NOT NULL DEFAULT '1'",
|
||||
"smtp_access" => "TINYINT(1) NOT NULL DEFAULT '1'",
|
||||
"dav_access" => "TINYINT(1) NOT NULL DEFAULT '1'",
|
||||
"eas_access" => "TINYINT(1) NOT NULL DEFAULT '1'",
|
||||
"active" => "TINYINT(1) NOT NULL DEFAULT '1'"
|
||||
),
|
||||
"keys" => array(
|
||||
|
Reference in New Issue
Block a user