181 lines
6.0 KiB
PHP
181 lines
6.0 KiB
PHP
<?php
|
|
/**
|
|
* Office 365 Mass Verification - CLI Script
|
|
* Usage: php office-verify-cli.php [limit] [offset]
|
|
* Example: php office-verify-cli.php 100 0
|
|
*/
|
|
|
|
set_time_limit(0);
|
|
ini_set('memory_limit', '512M');
|
|
|
|
$limit = isset($argv[1]) ? intval($argv[1]) : 50;
|
|
$offset = isset($argv[2]) ? intval($argv[2]) : 0;
|
|
$filterStatus = isset($argv[3]) ? $argv[3] : '';
|
|
|
|
echo "=== Office 365 Mass Verification ===\n";
|
|
echo "Limit: $limit | Offset: $offset\n\n";
|
|
|
|
try {
|
|
$pdo = new PDO("pgsql:host=10.1.0.3;dbname=adx_system", "admin", "admin123");
|
|
$pdo->setAttribute(PDO::ATTR_ERRMODE, PDO::ERRMODE_EXCEPTION);
|
|
} catch (Exception $e) {
|
|
die("DB Error: " . $e->getMessage() . "\n");
|
|
}
|
|
|
|
function checkOfficeAccount($email, $password, $tenantDomain = null) {
|
|
$result = [
|
|
'password_status' => 'unknown',
|
|
'has_license' => null,
|
|
'has_mfa' => null,
|
|
'access_token' => null
|
|
];
|
|
|
|
if (empty($email) || empty($password)) return $result;
|
|
|
|
$tenant = $tenantDomain ?: 'common';
|
|
if (strpos($tenant, '.onmicrosoft.com') !== false) {
|
|
$tenant = str_replace('.onmicrosoft.com', '', $tenant);
|
|
}
|
|
|
|
$url = "https://login.microsoftonline.com/$tenant.onmicrosoft.com/oauth2/v2.0/token";
|
|
|
|
$postData = http_build_query([
|
|
'grant_type' => 'password',
|
|
'client_id' => '1b730954-1685-4b74-9bfd-dac224a7b894',
|
|
'username' => $email,
|
|
'password' => $password,
|
|
'scope' => 'https://graph.microsoft.com/.default'
|
|
]);
|
|
|
|
$ch = curl_init($url);
|
|
curl_setopt_array($ch, [
|
|
CURLOPT_POST => true,
|
|
CURLOPT_POSTFIELDS => $postData,
|
|
CURLOPT_RETURNTRANSFER => true,
|
|
CURLOPT_TIMEOUT => 15,
|
|
CURLOPT_SSL_VERIFYPEER => true,
|
|
CURLOPT_HTTPHEADER => ['Content-Type: application/x-www-form-urlencoded']
|
|
]);
|
|
|
|
$response = curl_exec($ch);
|
|
$httpCode = curl_getinfo($ch, CURLINFO_HTTP_CODE);
|
|
curl_close($ch);
|
|
|
|
$data = json_decode($response, true);
|
|
|
|
if ($httpCode === 200 && isset($data['access_token'])) {
|
|
$result['password_status'] = 'valid';
|
|
$result['has_mfa'] = false;
|
|
$result['access_token'] = $data['access_token'];
|
|
return $result;
|
|
}
|
|
|
|
if (isset($data['error'])) {
|
|
$errorDesc = $data['error_description'] ?? '';
|
|
|
|
if (strpos($errorDesc, 'AADSTS50126') !== false) {
|
|
$result['password_status'] = 'invalid';
|
|
$result['has_mfa'] = false;
|
|
}
|
|
elseif (strpos($errorDesc, 'AADSTS50076') !== false || strpos($errorDesc, 'AADSTS50079') !== false) {
|
|
$result['password_status'] = 'valid';
|
|
$result['has_mfa'] = true;
|
|
}
|
|
elseif (strpos($errorDesc, 'AADSTS50057') !== false) {
|
|
$result['password_status'] = 'disabled';
|
|
}
|
|
elseif (strpos($errorDesc, 'AADSTS50053') !== false) {
|
|
$result['password_status'] = 'locked';
|
|
}
|
|
elseif (strpos($errorDesc, 'AADSTS50034') !== false) {
|
|
$result['password_status'] = 'not_found';
|
|
}
|
|
elseif (strpos($errorDesc, 'AADSTS5000224') !== false) {
|
|
$result['password_status'] = 'tenant_gone';
|
|
}
|
|
elseif (strpos($errorDesc, 'AADSTS65001') !== false) {
|
|
$result['password_status'] = 'valid';
|
|
$result['has_mfa'] = false;
|
|
}
|
|
elseif (strpos($errorDesc, 'AADSTS50055') !== false) {
|
|
$result['password_status'] = 'expired';
|
|
}
|
|
elseif (strpos($errorDesc, 'AADSTS50058') !== false) {
|
|
$result['password_status'] = 'valid';
|
|
$result['has_mfa'] = true;
|
|
}
|
|
else {
|
|
$result['password_status'] = 'error';
|
|
}
|
|
}
|
|
|
|
return $result;
|
|
}
|
|
|
|
// Récupérer les comptes non vérifiés ou tous
|
|
$where = "admin_email IS NOT NULL AND admin_password IS NOT NULL AND admin_password != ''";
|
|
if ($filterStatus === 'pending') {
|
|
$where .= " AND (password_status IS NULL OR password_status = 'unknown')";
|
|
}
|
|
|
|
$sql = "SELECT id, admin_email, admin_password, tenant_domain FROM admin.office_accounts WHERE $where ORDER BY id DESC LIMIT $limit OFFSET $offset";
|
|
$accounts = $pdo->query($sql)->fetchAll(PDO::FETCH_ASSOC);
|
|
|
|
$total = count($accounts);
|
|
echo "Found $total accounts to verify\n";
|
|
echo str_repeat("-", 60) . "\n";
|
|
|
|
$stats = ['valid' => 0, 'invalid' => 0, 'mfa' => 0, 'tenant_gone' => 0, 'other' => 0];
|
|
$processed = 0;
|
|
|
|
foreach ($accounts as $acc) {
|
|
$processed++;
|
|
$email = $acc['admin_email'];
|
|
|
|
echo "[$processed/$total] $email ... ";
|
|
|
|
$checkResult = checkOfficeAccount($email, $acc['admin_password'], $acc['tenant_domain']);
|
|
|
|
$newStatus = 'Pending';
|
|
if ($checkResult['password_status'] === 'valid') {
|
|
$newStatus = 'Active';
|
|
$stats['valid']++;
|
|
if ($checkResult['has_mfa']) $stats['mfa']++;
|
|
echo "✓ VALID" . ($checkResult['has_mfa'] ? " (MFA)" : "") . "\n";
|
|
} elseif ($checkResult['password_status'] === 'invalid') {
|
|
$newStatus = 'Blocked';
|
|
$stats['invalid']++;
|
|
echo "✗ INVALID\n";
|
|
} elseif ($checkResult['password_status'] === 'tenant_gone') {
|
|
$newStatus = 'Blocked';
|
|
$stats['tenant_gone']++;
|
|
echo "✗ TENANT GONE\n";
|
|
} else {
|
|
$stats['other']++;
|
|
echo "? " . strtoupper($checkResult['password_status']) . "\n";
|
|
}
|
|
|
|
// Conversion boolean pour PostgreSQL
|
|
$hasLicense = null;
|
|
$hasMfa = $checkResult['has_mfa'] === null ? null : ($checkResult['has_mfa'] ? 't' : 'f');
|
|
|
|
$stmt = $pdo->prepare("UPDATE admin.office_accounts SET
|
|
password_status = ?, has_license = ?, has_mfa = ?,
|
|
last_check = NOW(), status = ? WHERE id = ?");
|
|
$stmt->execute([
|
|
$checkResult['password_status'], $hasLicense, $hasMfa,
|
|
$newStatus, $acc['id']
|
|
]);
|
|
|
|
// Pause pour éviter le rate limiting
|
|
usleep(300000); // 0.3 seconde
|
|
}
|
|
|
|
echo str_repeat("-", 60) . "\n";
|
|
echo "=== RÉSULTATS ===\n";
|
|
echo "✓ Valid: {$stats['valid']} ({$stats['mfa']} avec MFA)\n";
|
|
echo "✗ Invalid: {$stats['invalid']}\n";
|
|
echo "✗ Tenant Gone: {$stats['tenant_gone']}\n";
|
|
echo "? Other: {$stats['other']}\n";
|
|
echo "\nTerminé!\n";
|