blob: bc9694d8e74d11e520c753d7a27a783a93664308 [file] [log] [blame]
Matthias Andreas Benkard4edeb9f2021-01-02 15:32:21 +01001<?php
2
3$ALLOW_ADMIN_EMAIL_LOGIN = (preg_match(
4 "/^([yY][eE][sS]|[yY])+$/",
5 $_ENV["ALLOW_ADMIN_EMAIL_LOGIN"]
6));
7
8$session_var_user_allowed = 'sogo-sso-user-allowed';
9$session_var_pass = 'sogo-sso-pass';
10
Matthias Andreas Benkard97f12022026-10-23 08:46:40 +020011// only the internal nginx auth_request loopback (127.0.0.1:65510) sets this;
12// external clients can never supply it (bare fastcgi param, not an HTTP header)
13$is_internal_auth = (($_SERVER['SOGO_AUTH_INTERNAL'] ?? '') === '1');
14
Matthias Andreas Benkard4edeb9f2021-01-02 15:32:21 +010015// validate credentials for basic auth requests
Matthias Andreas Benkard97f12022026-10-23 08:46:40 +020016if ($is_internal_auth && isset($_SERVER['PHP_AUTH_USER'])) {
Matthias Andreas Benkard4edeb9f2021-01-02 15:32:21 +010017 // load prerequisites only when required
18 require_once $_SERVER['DOCUMENT_ROOT'] . '/inc/prerequisites.inc.php';
Matthias Andreas Benkard97f12022026-10-23 08:46:40 +020019
Matthias Andreas Benkard4edeb9f2021-01-02 15:32:21 +010020 $username = $_SERVER['PHP_AUTH_USER'];
21 $password = $_SERVER['PHP_AUTH_PW'];
Matthias Andreas Benkard97f12022026-10-23 08:46:40 +020022
23 // Determine service type for protocol access check
24 $service = 'NONE';
Matthias Andreas Benkardb4b5cc12021-12-28 18:02:04 +010025 $original_uri = isset($_SERVER['HTTP_X_ORIGINAL_URI']) ? $_SERVER['HTTP_X_ORIGINAL_URI'] : '';
26 if (preg_match('/^(\/SOGo|)\/dav.*/', $original_uri) === 1) {
Matthias Andreas Benkard97f12022026-10-23 08:46:40 +020027 $service = 'DAV';
Matthias Andreas Benkardb4b5cc12021-12-28 18:02:04 +010028 }
29 elseif (preg_match('/^(\/SOGo|)\/Microsoft-Server-ActiveSync.*/', $original_uri) === 1) {
Matthias Andreas Benkard97f12022026-10-23 08:46:40 +020030 $service = 'EAS';
Matthias Andreas Benkardb4b5cc12021-12-28 18:02:04 +010031 }
Matthias Andreas Benkard97f12022026-10-23 08:46:40 +020032
33 $login_check = check_login($username, $password, array('service' => $service));
Matthias Andreas Benkard4edeb9f2021-01-02 15:32:21 +010034 if ($login_check === 'user') {
35 header("X-User: $username");
36 header("X-Auth: Basic ".base64_encode("$username:$password"));
37 header("X-Auth-Type: Basic");
38 exit;
39 } else {
40 header('HTTP/1.0 401 Unauthorized');
41 echo 'Invalid login';
42 exit;
43 }
44}
45// check permissions and redirect for direct GET ?login=xy requests
46elseif (isset($_GET['login'])) {
47 // load prerequisites only when required
48 require_once $_SERVER['DOCUMENT_ROOT'] . '/inc/prerequisites.inc.php';
Matthias Andreas Benkard8f915942021-08-16 10:57:25 +020049 // check if dual_login is active
50 $is_dual = (!empty($_SESSION["dual-login"]["username"])) ? true : false;
51 // check permissions (if dual_login is active, deny sso when acl is not given)
52 $login = html_entity_decode(rawurldecode($_GET["login"]));
Matthias Andreas Benkard8f915942021-08-16 10:57:25 +020053 if (isset($_SESSION['mailcow_cc_role']) &&
Matthias Andreas Benkardb4b5cc12021-12-28 18:02:04 +010054 (($_SESSION['acl']['login_as'] == "1" && $ALLOW_ADMIN_EMAIL_LOGIN !== 0) || ($is_dual === false && $login == $_SESSION['mailcow_cc_username']))) {
Matthias Andreas Benkard4edeb9f2021-01-02 15:32:21 +010055 if (filter_var($login, FILTER_VALIDATE_EMAIL)) {
Matthias Andreas Benkard8f915942021-08-16 10:57:25 +020056 if (user_get_alias_details($login) !== false) {
Matthias Andreas Benkard97f12022026-10-23 08:46:40 +020057 // enforce tenant boundary
58 if (!hasMailboxObjectAccess($_SESSION['mailcow_cc_username'], $_SESSION['mailcow_cc_role'], $login)) {
59 header("Location: /");
60 exit;
61 }
62 // Block SOGo access if pending actions (2FA setup, password update)
63 if (!empty($_SESSION['pending_tfa_setup']) || !empty($_SESSION['pending_pw_update'])) {
64 header("Location: /");
65 exit;
66 }
67 // register username in session
Matthias Andreas Benkard4edeb9f2021-01-02 15:32:21 +010068 $_SESSION[$session_var_user_allowed][] = $login;
Matthias Andreas Benkard97f12022026-10-23 08:46:40 +020069 // set dual login
70 if ($_SESSION['acl']['login_as'] == "1" && $ALLOW_ADMIN_EMAIL_LOGIN !== 0 && $is_dual === false && $_SESSION['mailcow_cc_role'] != "user"){
71 $_SESSION["dual-login"]["username"] = $_SESSION['mailcow_cc_username'];
72 $_SESSION["dual-login"]["role"] = $_SESSION['mailcow_cc_role'];
73 $_SESSION['mailcow_cc_username'] = $login;
74 $_SESSION['mailcow_cc_role'] = "user";
75 }
Matthias Andreas Benkardb4b5cc12021-12-28 18:02:04 +010076 // update sasl logs
Matthias Andreas Benkardb4b5cc12021-12-28 18:02:04 +010077 $stmt = $pdo->prepare("REPLACE INTO sasl_log (`service`, `app_password`, `username`, `real_rip`) VALUES ('SSO', 0, :username, :remote_addr)");
78 $stmt->execute(array(
79 ':username' => $login,
80 ':remote_addr' => ($_SERVER['HTTP_X_REAL_IP'] ?? $_SERVER['REMOTE_ADDR'])
81 ));
Matthias Andreas Benkard4edeb9f2021-01-02 15:32:21 +010082 // redirect to sogo (sogo will get the correct credentials via nginx auth_request
Matthias Andreas Benkard97f12022026-10-23 08:46:40 +020083 header("Location: /SOGo/so/");
Matthias Andreas Benkard4edeb9f2021-01-02 15:32:21 +010084 exit;
85 }
86 }
87 }
Matthias Andreas Benkard97f12022026-10-23 08:46:40 +020088 header("Location: /");
Matthias Andreas Benkard4edeb9f2021-01-02 15:32:21 +010089 exit;
90}
91// only check for admin-login on sogo GUI requests
Matthias Andreas Benkard97f12022026-10-23 08:46:40 +020092elseif ($is_internal_auth && isset($_SERVER['HTTP_X_ORIGINAL_URI']) && strcasecmp(substr($_SERVER['HTTP_X_ORIGINAL_URI'], 0, 9), "/SOGo/so/") === 0) {
Matthias Andreas Benkard4edeb9f2021-01-02 15:32:21 +010093 // this is an nginx auth_request call, we check for existing sogo-sso session variables
Matthias Andreas Benkard97f12022026-10-23 08:46:40 +020094 require_once $_SERVER['DOCUMENT_ROOT'] . '/inc/vars.inc.php';
95 if (file_exists($_SERVER['DOCUMENT_ROOT'] . '/inc/vars.local.inc.php')) {
96 include_once $_SERVER['DOCUMENT_ROOT'] . '/inc/vars.local.inc.php';
97 }
98 require_once $_SERVER['DOCUMENT_ROOT'] . '/inc/sessions.inc.php';
99
Matthias Andreas Benkard3c18a082022-12-27 17:32:58 +0100100 $email_list = array(
Matthias Andreas Benkard3c18a082022-12-27 17:32:58 +0100101 ($_SESSION['mailcow_cc_username'] ?? ''), // Current user
102 ($_SESSION["dual-login"]["username"] ?? ''), // Dual login user
103 );
104 foreach($email_list as $email) {
105 // check if this email is in session allowed list
106 if (
107 !empty($email) &&
108 filter_var($email, FILTER_VALIDATE_EMAIL) &&
109 is_array($_SESSION[$session_var_user_allowed]) &&
Matthias Andreas Benkard97f12022026-10-23 08:46:40 +0200110 in_array($email, $_SESSION[$session_var_user_allowed]) &&
111 !$_SESSION['pending_pw_update'] &&
112 !$_SESSION['pending_tfa_setup']
Matthias Andreas Benkard3c18a082022-12-27 17:32:58 +0100113 ) {
114 $username = $email;
Matthias Andreas Benkard97f12022026-10-23 08:46:40 +0200115 $password = file_get_contents("/etc/sogo-sso/sogo-sso.pass");
Matthias Andreas Benkard3c18a082022-12-27 17:32:58 +0100116 header("X-User: $username");
117 header("X-Auth: Basic ".base64_encode("$username:$password"));
118 header("X-Auth-Type: Basic");
119 exit;
120 }
Matthias Andreas Benkard4edeb9f2021-01-02 15:32:21 +0100121 }
122}
123
124// if username is empty, SOGo will use the normal login methods / login form
125header("X-User: ");
126header("X-Auth: ");
127header("X-Auth-Type: ");