diff --git a/data/web/autodiscover.php b/data/web/autodiscover.php
index d3cda4004..3e31dc3dd 100644
--- a/data/web/autodiscover.php
+++ b/data/web/autodiscover.php
@@ -60,101 +60,31 @@ $pdo = new PDO($dsn, $database_user, $database_pass, $opt);
$iam_provider = identity_provider('init');
$iam_settings = identity_provider('get');
-$login_user = strtolower(trim($_SERVER['PHP_AUTH_USER']));
-$login_pass = trim(htmlspecialchars_decode($_SERVER['PHP_AUTH_PW']));
+// Passwordless autodiscover - no authentication required
+// Email will be extracted from the request body
+$login_user = null;
+$login_role = null;
-if (empty($_SERVER['PHP_AUTH_USER']) || empty($_SERVER['PHP_AUTH_PW'])) {
- $json = json_encode(
- array(
- "time" => time(),
- "ua" => $_SERVER['HTTP_USER_AGENT'],
- "user" => "none",
- "ip" => $_SERVER['REMOTE_ADDR'],
- "service" => "Error: must be authenticated"
- )
- );
- $redis->lPush('AUTODISCOVER_LOG', $json);
- header('WWW-Authenticate: Basic realm="' . $_SERVER['HTTP_HOST'] . '"');
- header('HTTP/1.0 401 Unauthorized');
- exit(0);
-}
-
-$login_role = check_login($login_user, $login_pass, array('service' => 'EAS'));
-
-if ($login_role === "user") {
- header("Content-Type: application/xml");
- echo '' . PHP_EOL;
+header("Content-Type: application/xml");
+echo '' . PHP_EOL;
?>
time(),
- "ua" => $_SERVER['HTTP_USER_AGENT'],
- "user" => $_SERVER['PHP_AUTH_USER'],
- "ip" => $_SERVER['REMOTE_ADDR'],
- "service" => "Error: invalid or missing request data"
- )
- );
- $redis->lPush('AUTODISCOVER_LOG', $json);
- $redis->lTrim('AUTODISCOVER_LOG', 0, 100);
- }
- catch (RedisException $e) {
- $_SESSION['return'][] = array(
- 'type' => 'danger',
- 'msg' => 'Redis: '.$e
- );
- return false;
- }
- list($usec, $sec) = explode(' ', microtime());
-?>
-
-
- 600
- Invalid Request
-
-
-
-
-Request->EMailAddress;
- } catch (Exception $e) {
- $email = $_SERVER['PHP_AUTH_USER'];
- }
-
- $username = trim($email);
- try {
- $stmt = $pdo->prepare("SELECT `name` FROM `mailbox` WHERE `username`= :username");
- $stmt->execute(array(':username' => $username));
- $MailboxData = $stmt->fetch(PDO::FETCH_ASSOC);
- }
- catch(PDOException $e) {
- die("Failed to determine name from SQL");
- }
- if (!empty($MailboxData['name'])) {
- $displayname = $MailboxData['name'];
- }
- else {
- $displayname = $email;
- }
+if(!$data) {
try {
$json = json_encode(
array(
"time" => time(),
"ua" => $_SERVER['HTTP_USER_AGENT'],
- "user" => $_SERVER['PHP_AUTH_USER'],
+ "user" => "none",
"ip" => $_SERVER['REMOTE_ADDR'],
- "service" => $autodiscover_config['autodiscoverType']
+ "service" => "Error: invalid or missing request data"
)
);
$redis->lPush('AUTODISCOVER_LOG', $json);
$redis->lTrim('AUTODISCOVER_LOG', 0, 100);
+ $redis->publish("F2B_CHANNEL", "Autodiscover: Invalid request by " . $_SERVER['REMOTE_ADDR']);
+ error_log("Autodiscover: Invalid request by " . $_SERVER['REMOTE_ADDR']);
}
catch (RedisException $e) {
$_SESSION['return'][] = array(
@@ -163,7 +93,143 @@ if ($login_role === "user") {
);
return false;
}
- if ($autodiscover_config['autodiscoverType'] == 'imap') {
+ list($usec, $sec) = explode(' ', microtime());
+?>
+
+
+ 600
+ Invalid Request
+
+
+
+
+Request->EMailAddress;
+} catch (Exception $e) {
+ // If parsing fails, return error
+ try {
+ $json = json_encode(
+ array(
+ "time" => time(),
+ "ua" => $_SERVER['HTTP_USER_AGENT'],
+ "user" => "none",
+ "ip" => $_SERVER['REMOTE_ADDR'],
+ "service" => "Error: could not parse email from request"
+ )
+ );
+ $redis->lPush('AUTODISCOVER_LOG', $json);
+ $redis->lTrim('AUTODISCOVER_LOG', 0, 100);
+ $redis->publish("F2B_CHANNEL", "Autodiscover: Malformed XML by " . $_SERVER['REMOTE_ADDR']);
+ error_log("Autodiscover: Malformed XML by " . $_SERVER['REMOTE_ADDR']);
+ }
+ catch (RedisException $e) {
+ // Silently fail
+ }
+ list($usec, $sec) = explode(' ', microtime());
+?>
+
+
+ 600
+ Invalid Request
+
+
+
+
+prepare("SELECT `mailbox`.`name`, `mailbox`.`active` FROM `mailbox`
+ INNER JOIN `domain` ON `mailbox`.`domain` = `domain`.`domain`
+ WHERE `mailbox`.`username` = :username
+ AND `mailbox`.`active` = '1'
+ AND `domain`.`active` = '1'");
+ $stmt->execute(array(':username' => $username));
+ $MailboxData = $stmt->fetch(PDO::FETCH_ASSOC);
+}
+catch(PDOException $e) {
+ // Database error - return error response with complete XML
+ list($usec, $sec) = explode(' ', microtime());
+?>
+
+
+ 500
+ Database Error
+
+
+
+
+ time(),
+ "ua" => $_SERVER['HTTP_USER_AGENT'],
+ "user" => $email,
+ "ip" => $_SERVER['REMOTE_ADDR'],
+ "service" => "Error: mailbox not found or inactive"
+ )
+ );
+ $redis->lPush('AUTODISCOVER_LOG', $json);
+ $redis->lTrim('AUTODISCOVER_LOG', 0, 100);
+ $redis->publish("F2B_CHANNEL", "Autodiscover: Invalid mailbox attempt by " . $_SERVER['REMOTE_ADDR']);
+ error_log("Autodiscover: Invalid mailbox attempt by " . $_SERVER['REMOTE_ADDR']);
+ }
+ catch (RedisException $e) {
+ // Silently fail
+ }
+ list($usec, $sec) = explode(' ', microtime());
+?>
+
+
+ 600
+ Invalid Request
+
+
+
+
+ time(),
+ "ua" => $_SERVER['HTTP_USER_AGENT'],
+ "user" => $email,
+ "ip" => $_SERVER['REMOTE_ADDR'],
+ "service" => $autodiscover_config['autodiscoverType']
+ )
+ );
+ $redis->lPush('AUTODISCOVER_LOG', $json);
+ $redis->lTrim('AUTODISCOVER_LOG', 0, 100);
+}
+catch (RedisException $e) {
+ $_SESSION['return'][] = array(
+ 'type' => 'danger',
+ 'msg' => 'Redis: '.$e
+ );
+ return false;
+}
+if ($autodiscover_config['autodiscoverType'] == 'imap') {
?>
@@ -238,6 +304,3 @@ if ($login_role === "user") {
}
?>
-
diff --git a/helper-scripts/dev_tests/view_autodiscover.sh b/helper-scripts/dev_tests/view_autodiscover.sh
new file mode 100755
index 000000000..a203370de
--- /dev/null
+++ b/helper-scripts/dev_tests/view_autodiscover.sh
@@ -0,0 +1,122 @@
+#!/bin/bash
+
+# Autodiscover XML Debug Script
+# Usage: ./view_autodiscover.sh [OPTIONS] [email@domain.com]
+
+# Function to display help
+show_help() {
+ cat << EOF
+Autodiscover XML Debug Script
+
+Usage: $0 [OPTIONS] [email@domain.com]
+
+OPTIONS:
+ -h, --help Show this help message
+ -d, --domain FQDN Override autodiscover domain (default: autodiscover.DOMAIN)
+ Example: -d mail.example.com
+
+EXAMPLES:
+ $0 user@example.com
+ Test autodiscover for user@example.com using autodiscover.example.com
+
+ $0 -d mail.example.com user@example.com
+ Test autodiscover for user@example.com using mail.example.com
+
+ $0 -d localhost:8443 user@example.com
+ Test autodiscover using localhost:8443 (useful for development)
+
+EOF
+ exit 0
+}
+
+# Initialize variables
+EMAIL=""
+DOMAIN_OVERRIDE=""
+
+# Parse command line arguments
+while [[ $# -gt 0 ]]; do
+ case $1 in
+ -h|--help)
+ show_help
+ ;;
+ -d|--domain)
+ DOMAIN_OVERRIDE="$2"
+ shift 2
+ ;;
+ -*)
+ echo "Error: Unknown option $1"
+ echo "Use -h or --help for usage information"
+ exit 1
+ ;;
+ *)
+ EMAIL="$1"
+ shift
+ ;;
+ esac
+done
+
+# Check if xmllint is available
+if ! command -v xmllint &> /dev/null; then
+ echo "WARNING: xmllint not found. Output will not be formatted."
+ echo "Install with: apt install libxml2-utils (Debian/Ubuntu) or yum install libxml2 (CentOS/RHEL)"
+ echo ""
+ USE_XMLLINT=false
+else
+ USE_XMLLINT=true
+fi
+
+# Get email address from user input if not provided
+if [ -z "$EMAIL" ]; then
+ read -p "Enter email address to test: " EMAIL
+fi
+
+# Validate email format
+if [[ ! "$EMAIL" =~ ^[a-zA-Z0-9._%+-]+@[a-zA-Z0-9.-]+\.[a-zA-Z]{2,}$ ]]; then
+ echo "Error: Invalid email address format"
+ exit 1
+fi
+
+# Extract domain from email
+EMAIL_DOMAIN="${EMAIL#*@}"
+
+# Determine autodiscover URL
+if [ -n "$DOMAIN_OVERRIDE" ]; then
+ AUTODISCOVER_URL="https://${DOMAIN_OVERRIDE}/Autodiscover/Autodiscover.xml"
+ echo "Testing Autodiscover for: $EMAIL"
+ echo "Override domain: $DOMAIN_OVERRIDE"
+else
+ AUTODISCOVER_URL="https://autodiscover.${EMAIL_DOMAIN}/Autodiscover/Autodiscover.xml"
+ echo "Testing Autodiscover for: $EMAIL"
+fi
+
+echo "URL: $AUTODISCOVER_URL"
+echo "============================================"
+echo ""
+
+# Make the request
+RESPONSE=$(curl -k -s -X POST "$AUTODISCOVER_URL" \
+ -H "Content-Type: text/xml" \
+ -d "
+
+
+ $EMAIL
+ http://schemas.microsoft.com/exchange/autodiscover/outlook/responseschema/2006a
+
+")
+
+# Check if response is empty
+if [ -z "$RESPONSE" ]; then
+ echo "Error: No response received from server"
+ exit 1
+fi
+
+# Format and display output
+if [ "$USE_XMLLINT" = true ]; then
+ echo "$RESPONSE" | xmllint --format - 2>&1
+else
+ echo "$RESPONSE"
+fi
+
+echo ""
+echo "============================================"
+echo "Response length: ${#RESPONSE} bytes"