Matthias Andreas Benkard | b382b10 | 2021-01-02 15:32:21 +0100 | [diff] [blame] | 1 | <?php |
| 2 | require_once $_SERVER['DOCUMENT_ROOT'] . '/inc/vars.inc.php'; |
| 3 | require_once $_SERVER['DOCUMENT_ROOT'] . '/inc/functions.inc.php'; |
| 4 | $default_autodiscover_config = $autodiscover_config; |
| 5 | if(file_exists('inc/vars.local.inc.php')) { |
| 6 | include_once 'inc/vars.local.inc.php'; |
| 7 | } |
| 8 | $autodiscover_config = array_merge($default_autodiscover_config, $autodiscover_config); |
| 9 | |
| 10 | // Redis |
| 11 | $redis = new Redis(); |
| 12 | try { |
| 13 | if (!empty(getenv('REDIS_SLAVEOF_IP'))) { |
| 14 | $redis->connect(getenv('REDIS_SLAVEOF_IP'), getenv('REDIS_SLAVEOF_PORT')); |
| 15 | } |
| 16 | else { |
| 17 | $redis->connect('redis-mailcow', 6379); |
| 18 | } |
| 19 | } |
| 20 | catch (Exception $e) { |
| 21 | exit; |
| 22 | } |
| 23 | |
| 24 | error_reporting(0); |
| 25 | |
| 26 | $data = trim(file_get_contents("php://input")); |
| 27 | |
| 28 | if (strpos($data, 'autodiscover/outlook/responseschema') !== false) { |
| 29 | $autodiscover_config['autodiscoverType'] = 'imap'; |
| 30 | if ($autodiscover_config['useEASforOutlook'] == 'yes' && |
| 31 | // Office for macOS does not support EAS |
| 32 | strpos($_SERVER['HTTP_USER_AGENT'], 'Mac') === false && |
| 33 | // Outlook 2013 (version 15) or higher |
| 34 | preg_match('/(Outlook|Office).+1[5-9]\./', $_SERVER['HTTP_USER_AGENT']) |
| 35 | ) { |
| 36 | $autodiscover_config['autodiscoverType'] = 'activesync'; |
| 37 | } |
| 38 | } |
| 39 | |
| 40 | if (getenv('SKIP_SOGO') == "y") { |
| 41 | $autodiscover_config['autodiscoverType'] = 'imap'; |
| 42 | } |
| 43 | |
| 44 | //$dsn = $database_type . ":host=" . $database_host . ";dbname=" . $database_name; |
| 45 | $dsn = $database_type . ":unix_socket=" . $database_sock . ";dbname=" . $database_name; |
| 46 | $opt = [ |
| 47 | PDO::ATTR_ERRMODE => PDO::ERRMODE_EXCEPTION, |
| 48 | PDO::ATTR_DEFAULT_FETCH_MODE => PDO::FETCH_ASSOC, |
| 49 | PDO::ATTR_EMULATE_PREPARES => false, |
| 50 | ]; |
| 51 | $pdo = new PDO($dsn, $database_user, $database_pass, $opt); |
| 52 | $login_user = strtolower(trim($_SERVER['PHP_AUTH_USER'])); |
| 53 | $login_pass = trim(htmlspecialchars_decode($_SERVER['PHP_AUTH_PW'])); |
| 54 | |
| 55 | if (empty($_SERVER['PHP_AUTH_USER']) || empty($_SERVER['PHP_AUTH_PW'])) { |
| 56 | $json = json_encode( |
| 57 | array( |
| 58 | "time" => time(), |
| 59 | "ua" => $_SERVER['HTTP_USER_AGENT'], |
| 60 | "user" => "none", |
Matthias Andreas Benkard | 12a5735 | 2021-12-28 18:02:04 +0100 | [diff] [blame^] | 61 | "ip" => $_SERVER['REMOTE_ADDR'], |
Matthias Andreas Benkard | b382b10 | 2021-01-02 15:32:21 +0100 | [diff] [blame] | 62 | "service" => "Error: must be authenticated" |
| 63 | ) |
| 64 | ); |
| 65 | $redis->lPush('AUTODISCOVER_LOG', $json); |
| 66 | header('WWW-Authenticate: Basic realm="' . $_SERVER['HTTP_HOST'] . '"'); |
| 67 | header('HTTP/1.0 401 Unauthorized'); |
| 68 | exit(0); |
| 69 | } |
| 70 | |
Matthias Andreas Benkard | 12a5735 | 2021-12-28 18:02:04 +0100 | [diff] [blame^] | 71 | $login_role = check_login($login_user, $login_pass, true); |
Matthias Andreas Benkard | b382b10 | 2021-01-02 15:32:21 +0100 | [diff] [blame] | 72 | |
| 73 | if ($login_role === "user") { |
| 74 | header("Content-Type: application/xml"); |
| 75 | echo '<?xml version="1.0" encoding="utf-8" ?>' . PHP_EOL; |
| 76 | ?> |
| 77 | <Autodiscover xmlns="http://schemas.microsoft.com/exchange/autodiscover/responseschema/2006"> |
| 78 | <?php |
| 79 | if(!$data) { |
| 80 | try { |
| 81 | $json = json_encode( |
| 82 | array( |
| 83 | "time" => time(), |
| 84 | "ua" => $_SERVER['HTTP_USER_AGENT'], |
| 85 | "user" => $_SERVER['PHP_AUTH_USER'], |
Matthias Andreas Benkard | 12a5735 | 2021-12-28 18:02:04 +0100 | [diff] [blame^] | 86 | "ip" => $_SERVER['REMOTE_ADDR'], |
Matthias Andreas Benkard | b382b10 | 2021-01-02 15:32:21 +0100 | [diff] [blame] | 87 | "service" => "Error: invalid or missing request data" |
| 88 | ) |
| 89 | ); |
| 90 | $redis->lPush('AUTODISCOVER_LOG', $json); |
| 91 | $redis->lTrim('AUTODISCOVER_LOG', 0, 100); |
| 92 | } |
| 93 | catch (RedisException $e) { |
| 94 | $_SESSION['return'][] = array( |
| 95 | 'type' => 'danger', |
| 96 | 'msg' => 'Redis: '.$e |
| 97 | ); |
| 98 | return false; |
| 99 | } |
| 100 | list($usec, $sec) = explode(' ', microtime()); |
| 101 | ?> |
| 102 | <Response> |
| 103 | <Error Time="<?=date('H:i:s', $sec) . substr($usec, 0, strlen($usec) - 2);?>" Id="2477272013"> |
| 104 | <ErrorCode>600</ErrorCode> |
| 105 | <Message>Invalid Request</Message> |
| 106 | <DebugData /> |
| 107 | </Error> |
| 108 | </Response> |
| 109 | </Autodiscover> |
| 110 | <?php |
| 111 | exit(0); |
| 112 | } |
| 113 | try { |
| 114 | $discover = new SimpleXMLElement($data); |
| 115 | $email = $discover->Request->EMailAddress; |
| 116 | } catch (Exception $e) { |
| 117 | $email = $_SERVER['PHP_AUTH_USER']; |
| 118 | } |
| 119 | |
| 120 | $username = trim($email); |
| 121 | try { |
| 122 | $stmt = $pdo->prepare("SELECT `name` FROM `mailbox` WHERE `username`= :username"); |
| 123 | $stmt->execute(array(':username' => $username)); |
| 124 | $MailboxData = $stmt->fetch(PDO::FETCH_ASSOC); |
| 125 | } |
| 126 | catch(PDOException $e) { |
| 127 | die("Failed to determine name from SQL"); |
| 128 | } |
| 129 | if (!empty($MailboxData['name'])) { |
| 130 | $displayname = $MailboxData['name']; |
| 131 | } |
| 132 | else { |
| 133 | $displayname = $email; |
| 134 | } |
| 135 | try { |
| 136 | $json = json_encode( |
| 137 | array( |
| 138 | "time" => time(), |
| 139 | "ua" => $_SERVER['HTTP_USER_AGENT'], |
| 140 | "user" => $_SERVER['PHP_AUTH_USER'], |
Matthias Andreas Benkard | 12a5735 | 2021-12-28 18:02:04 +0100 | [diff] [blame^] | 141 | "ip" => $_SERVER['REMOTE_ADDR'], |
Matthias Andreas Benkard | b382b10 | 2021-01-02 15:32:21 +0100 | [diff] [blame] | 142 | "service" => $autodiscover_config['autodiscoverType'] |
| 143 | ) |
| 144 | ); |
| 145 | $redis->lPush('AUTODISCOVER_LOG', $json); |
| 146 | $redis->lTrim('AUTODISCOVER_LOG', 0, 100); |
| 147 | } |
| 148 | catch (RedisException $e) { |
| 149 | $_SESSION['return'][] = array( |
| 150 | 'type' => 'danger', |
| 151 | 'msg' => 'Redis: '.$e |
| 152 | ); |
| 153 | return false; |
| 154 | } |
| 155 | if ($autodiscover_config['autodiscoverType'] == 'imap') { |
| 156 | ?> |
| 157 | <Response xmlns="http://schemas.microsoft.com/exchange/autodiscover/outlook/responseschema/2006a"> |
| 158 | <User> |
| 159 | <DisplayName><?=htmlspecialchars($displayname, ENT_XML1 | ENT_QUOTES, 'UTF-8');?></DisplayName> |
| 160 | </User> |
| 161 | <Account> |
| 162 | <AccountType>email</AccountType> |
| 163 | <Action>settings</Action> |
| 164 | <Protocol> |
| 165 | <Type>IMAP</Type> |
| 166 | <Server><?=$autodiscover_config['imap']['server'];?></Server> |
| 167 | <Port><?=$autodiscover_config['imap']['port'];?></Port> |
| 168 | <DomainRequired>off</DomainRequired> |
| 169 | <LoginName><?=$email;?></LoginName> |
| 170 | <SPA>off</SPA> |
| 171 | <SSL>on</SSL> |
| 172 | <AuthRequired>on</AuthRequired> |
| 173 | </Protocol> |
| 174 | <Protocol> |
| 175 | <Type>SMTP</Type> |
| 176 | <Server><?=$autodiscover_config['smtp']['server'];?></Server> |
| 177 | <Port><?=$autodiscover_config['smtp']['port'];?></Port> |
| 178 | <DomainRequired>off</DomainRequired> |
| 179 | <LoginName><?=$email;?></LoginName> |
| 180 | <SPA>off</SPA> |
| 181 | <SSL>on</SSL> |
| 182 | <AuthRequired>on</AuthRequired> |
| 183 | <UsePOPAuth>on</UsePOPAuth> |
| 184 | <SMTPLast>off</SMTPLast> |
| 185 | </Protocol> |
| 186 | <?php |
| 187 | if (getenv('SKIP_SOGO') != "y") { |
| 188 | ?> |
| 189 | <Protocol> |
| 190 | <Type>CalDAV</Type> |
| 191 | <Server>https://<?=$autodiscover_config['caldav']['server'];?><?php if ($autodiscover_config['caldav']['port'] != 443) echo ':'.$autodiscover_config['caldav']['port']; ?>/SOGo/dav/<?=$email;?>/</Server> |
| 192 | <DomainRequired>off</DomainRequired> |
| 193 | <LoginName><?=$email;?></LoginName> |
| 194 | </Protocol> |
| 195 | <Protocol> |
| 196 | <Type>CardDAV</Type> |
| 197 | <Server>https://<?=$autodiscover_config['carddav']['server'];?><?php if ($autodiscover_config['caldav']['port'] != 443) echo ':'.$autodiscover_config['carddav']['port']; ?>/SOGo/dav/<?=$email;?>/</Server> |
| 198 | <DomainRequired>off</DomainRequired> |
| 199 | <LoginName><?=$email;?></LoginName> |
| 200 | </Protocol> |
| 201 | <?php |
| 202 | } |
| 203 | ?> |
| 204 | </Account> |
| 205 | </Response> |
| 206 | <?php |
| 207 | } |
| 208 | else if ($autodiscover_config['autodiscoverType'] == 'activesync') { |
| 209 | ?> |
| 210 | <Response xmlns="http://schemas.microsoft.com/exchange/autodiscover/mobilesync/responseschema/2006"> |
| 211 | <Culture>en:en</Culture> |
| 212 | <User> |
| 213 | <DisplayName><?=htmlspecialchars($displayname, ENT_XML1 | ENT_QUOTES, 'UTF-8');?></DisplayName> |
| 214 | <EMailAddress><?=$email;?></EMailAddress> |
| 215 | </User> |
| 216 | <Action> |
| 217 | <Settings> |
| 218 | <Server> |
| 219 | <Type>MobileSync</Type> |
| 220 | <Url><?=$autodiscover_config['activesync']['url'];?></Url> |
| 221 | <Name><?=$autodiscover_config['activesync']['url'];?></Name> |
| 222 | </Server> |
| 223 | </Settings> |
| 224 | </Action> |
| 225 | </Response> |
| 226 | <?php |
| 227 | } |
| 228 | ?> |
| 229 | </Autodiscover> |
| 230 | <?php |
| 231 | } |
| 232 | ?> |