1
0
mirror of https://github.com/mailcow/mailcow-dockerized.git synced 2024-11-21 17:16:54 +02:00

[Web] allow mbox sso_token login for mailcow and sogo

This commit is contained in:
FreddleSpl0it 2023-06-16 08:53:25 +02:00
parent 06cce79806
commit eb33166f3e
No known key found for this signature in database
GPG Key ID: 00E14E7634F4BEC5
6 changed files with 122 additions and 18 deletions

View File

@ -315,8 +315,14 @@ remote ${IPV4_NETWORK}.248 {
}
EOF
# Create random master Password for SOGo SSO
RAND_PASS=$(cat /dev/urandom | tr -dc 'a-z0-9' | fold -w 32 | head -n 1)
# Set SOGo SSO master Password
if [ -z "$SOGO_SSO_PASS" ]; then
# Set from env var
RAND_PASS=$SOGO_SSO_PASS
else
# Create random master Password
RAND_PASS=$(cat /dev/urandom | tr -dc 'a-z0-9' | fold -w 32 | head -n 1)
fi
echo -n ${RAND_PASS} > /etc/phpfpm/sogo-sso.pass
cat <<EOF > /etc/dovecot/sogo-sso.conf
# Autogenerated by mailcow

View File

@ -5303,3 +5303,64 @@ function mailbox($_action, $_type, $_data = null, $_extra = null) {
update_sogo_static_view();
}
}
function mailbox_sso($_action, $_data) {
global $pdo;
switch ($_action) {
case 'check':
$token = $_data;
$stmt = $pdo->prepare("SELECT `t1`.`username` FROM `mailbox_sso` AS `t1` JOIN `mailbox` AS `t2` ON `t1`.`username` = `t2`.`username` WHERE `t1`.`token` = :token AND `t1`.`created` > DATE_SUB(NOW(), INTERVAL '30' SECOND) AND `t2`.`active` = 1;");
$stmt->execute(array(
':token' => preg_replace('/[^a-zA-Z0-9-]/', '', $token)
));
$return = $stmt->fetch(PDO::FETCH_ASSOC);
return empty($return['username']) ? false : $return['username'];
case 'issue':
if ($_SESSION['mailcow_cc_role'] != "admin") {
$_SESSION['return'][] = array(
'type' => 'danger',
'log' => array(__FUNCTION__, $_action, $_data),
'msg' => 'access_denied'
);
return false;
}
$username = $_data['username'];
$stmt = $pdo->prepare("SELECT `username` FROM `mailbox`
WHERE `username` = :username");
$stmt->execute(array(':username' => $username));
$num_results = count($stmt->fetchAll(PDO::FETCH_ASSOC));
if ($num_results < 1) {
$_SESSION['return'][] = array(
'type' => 'danger',
'log' => array(__FUNCTION__, $_action, $_data),
'msg' => array('object_doesnt_exist', htmlspecialchars($username))
);
return false;
}
$token = implode('-', array(
strtoupper(bin2hex(random_bytes(3))),
strtoupper(bin2hex(random_bytes(3))),
strtoupper(bin2hex(random_bytes(3))),
strtoupper(bin2hex(random_bytes(3))),
strtoupper(bin2hex(random_bytes(3)))
));
$stmt = $pdo->prepare("INSERT INTO `mailbox_sso` (`username`, `token`)
VALUES (:username, :token)");
$stmt->execute(array(
':username' => $username,
':token' => $token
));
// perform cleanup
$pdo->query("DELETE FROM `mailbox_sso` WHERE created < DATE_SUB(NOW(), INTERVAL '30' SECOND);");
return ['token' => $token];
break;
}
}

View File

@ -3,7 +3,7 @@ function init_db_schema() {
try {
global $pdo;
$db_version = "14022023_1000";
$db_version = "15062023_2057";
$stmt = $pdo->query("SHOW TABLES LIKE 'versions'");
$num_results = count($stmt->fetchAll(PDO::FETCH_ASSOC));
@ -361,6 +361,19 @@ function init_db_schema() {
),
"attr" => "ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 ROW_FORMAT=DYNAMIC"
),
"mailbox_sso" => array(
"cols" => array(
"username" => "VARCHAR(255) NOT NULL",
"token" => "VARCHAR(255) NOT NULL",
"created" => "DATETIME(0) NOT NULL DEFAULT NOW(0)",
),
"keys" => array(
"primary" => array(
"" => array("token", "created")
),
),
"attr" => "ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 ROW_FORMAT=DYNAMIC"
),
"tags_mailbox" => array(
"cols" => array(
"tag_name" => "VARCHAR(255) NOT NULL",

View File

@ -1,13 +1,20 @@
<?php
// SSO Domain Admin
if (!empty($_GET['sso_token'])) {
// SSO Domain Admin
$username = domain_admin_sso('check', $_GET['sso_token']);
if ($username !== false) {
$_SESSION['mailcow_cc_username'] = $username;
$_SESSION['mailcow_cc_role'] = 'domainadmin';
header('Location: /mailbox');
}
// SSO Mailbox User
$username = mailbox_sso('check', $_GET['sso_token']);
if ($username !== false) {
$_SESSION['mailcow_cc_username'] = $username;
$_SESSION['mailcow_cc_role'] = 'user';
header('Location: /mailbox');
}
}
if (isset($_POST["verify_tfa_login"])) {

View File

@ -288,18 +288,26 @@ if (isset($_GET['query'])) {
case "domain-admin":
process_add_return(domain_admin('add', $attr));
break;
case "sso":
switch ($object) {
case "domain-admin":
$data = domain_admin_sso('issue', $attr);
if($data) {
echo json_encode($data);
exit(0);
}
process_add_return($data);
break;
}
break;
case "sso":
switch ($object) {
case "domain-admin":
$data = domain_admin_sso('issue', $attr);
if($data) {
echo json_encode($data);
exit(0);
}
process_add_return($data);
break;
case "mailbox":
$data = mailbox_sso('issue', $attr);
if($data) {
echo json_encode($data);
exit(0);
}
process_add_return($data);
break;
}
break;
case "admin":
process_add_return(admin('add', $attr));
break;

View File

@ -39,10 +39,19 @@ if (isset($_SERVER['PHP_AUTH_USER'])) {
elseif (isset($_GET['login'])) {
// load prerequisites only when required
require_once $_SERVER['DOCUMENT_ROOT'] . '/inc/prerequisites.inc.php';
$login = html_entity_decode(rawurldecode($_GET["login"]));
if (!empty($_GET['sso_token'])) {
$login = mailbox_sso('check', $_GET['sso_token']);
if ($login !== false) {
$_SESSION['mailcow_cc_username'] = $login;
$_SESSION['mailcow_cc_role'] = 'user';
}
}
// check if dual_login is active
$is_dual = (!empty($_SESSION["dual-login"]["username"])) ? true : false;
// check permissions (if dual_login is active, deny sso when acl is not given)
$login = html_entity_decode(rawurldecode($_GET["login"]));
if (isset($_SESSION['mailcow_cc_role']) &&
(($_SESSION['acl']['login_as'] == "1" && $ALLOW_ADMIN_EMAIL_LOGIN !== 0) || ($is_dual === false && $login == $_SESSION['mailcow_cc_username']))) {
if (filter_var($login, FILTER_VALIDATE_EMAIL)) {