blob: 32026c071e6d3440245cd81a3487901e3f7cd8f5 [file] [log] [blame]
Matthias Andreas Benkard97f12022026-10-23 08:46:40 +02001<?php
2
3require_once(__DIR__ . '/../web/inc/vars.inc.php');
4if (file_exists(__DIR__ . '/../web/inc/vars.local.inc.php')) {
5 include_once(__DIR__ . '/../web/inc/vars.local.inc.php');
6}
7require_once __DIR__ . '/../web/inc/lib/vendor/autoload.php';
8
9// Init database
10//$dsn = $database_type . ':host=' . $database_host . ';dbname=' . $database_name;
11$dsn = $database_type . ":unix_socket=" . $database_sock . ";dbname=" . $database_name;
12$opt = [
13 PDO::ATTR_ERRMODE => PDO::ERRMODE_EXCEPTION,
14 PDO::ATTR_DEFAULT_FETCH_MODE => PDO::FETCH_ASSOC,
15 PDO::ATTR_EMULATE_PREPARES => false,
16];
17try {
18 $pdo = new PDO($dsn, $database_user, $database_pass, $opt);
19}
20catch (PDOException $e) {
21 logMsg("err", $e->getMessage());
22 session_destroy();
23 exit;
24}
25
26// Init Redis
27$redis = new Redis();
28try {
29 if (!empty(getenv('REDIS_SLAVEOF_IP'))) {
30 $redis->connect(getenv('REDIS_SLAVEOF_IP'), getenv('REDIS_SLAVEOF_PORT'));
31 }
32 else {
33 $redis->connect('redis-mailcow', 6379);
34 }
35 $redis->auth(getenv("REDISPASS"));
36}
37catch (Exception $e) {
38 echo "Exiting: " . $e->getMessage();
39 session_destroy();
40 exit;
41}
42
43function logMsg($priority, $message, $task = "LDAP Sync") {
44 global $redis;
45
46 $finalMsg = array(
47 "time" => time(),
48 "priority" => $priority,
49 "task" => $task,
50 "message" => $message
51 );
52 $redis->lPush('CRON_LOG', json_encode($finalMsg));
53}
54
55// Load core functions first
56require_once __DIR__ . '/../web/inc/functions.inc.php';
57require_once __DIR__ . '/../web/inc/functions.auth.inc.php';
58require_once __DIR__ . '/../web/inc/sessions.inc.php';
59require_once __DIR__ . '/../web/inc/functions.mailbox.inc.php';
60require_once __DIR__ . '/../web/inc/functions.ratelimit.inc.php';
61require_once __DIR__ . '/../web/inc/functions.acl.inc.php';
62
63$_SESSION['mailcow_cc_username'] = "admin";
64$_SESSION['mailcow_cc_role'] = "admin";
65$_SESSION['acl']['tls_policy'] = "1";
66$_SESSION['acl']['quarantine_notification'] = "1";
67$_SESSION['acl']['quarantine_category'] = "1";
68$_SESSION['acl']['ratelimit'] = "1";
69$_SESSION['acl']['sogo_access'] = "1";
70$_SESSION['acl']['protocol_access'] = "1";
71$_SESSION['acl']['mailbox_relayhost'] = "1";
72$_SESSION['acl']['unlimited_quota'] = "1";
73
74$iam_settings = identity_provider('get');
75if ($iam_settings['authsource'] != "ldap" || (intval($iam_settings['periodic_sync']) != 1 && intval($iam_settings['import_users']) != 1)) {
76 session_destroy();
77 exit;
78}
79
80// Set pagination variables
81$start = 0;
82$max = 100;
83
84// lock sync if already running
85$lock_file = '/tmp/iam-sync.lock';
86if (file_exists($lock_file)) {
87 $lock_file_parts = explode("\n", file_get_contents($lock_file));
88 $pid = $lock_file_parts[0];
89 if (count($lock_file_parts) > 1){
90 $last_execution = $lock_file_parts[1];
91 $elapsed_time = (time() - $last_execution) / 60;
92 if ($elapsed_time < intval($iam_settings['sync_interval'])) {
93 logMsg("warning", "Sync not ready (".number_format((float)$elapsed_time, 2, '.', '')."min / ".$iam_settings['sync_interval']."min)");
94 session_destroy();
95 exit;
96 }
97 }
98
99 if (posix_kill($pid, 0)) {
100 logMsg("warning", "Sync is already running");
101 session_destroy();
102 exit;
103 } else {
104 unlink($lock_file);
105 }
106}
107$lock_file_handle = fopen($lock_file, 'w');
108fwrite($lock_file_handle, getmypid());
109fclose($lock_file_handle);
110
111// Init Provider
112$iam_provider = identity_provider('init');
113
114// Get ldap users
115$ldap_query = $iam_provider->query();
116if (!empty($iam_settings['filter'])) {
117 $ldap_query = $ldap_query->rawFilter($iam_settings['filter']);
118}
119$response = $ldap_query->where($iam_settings['username_field'], "*")
120 ->where($iam_settings['attribute_field'], "*")
121 ->select([$iam_settings['username_field'], $iam_settings['attribute_field'], 'displayname'])
122 ->paginate($max);
123
124// Process the users
125foreach ($response as $user) {
126 // try get mailbox user
127 $stmt = $pdo->prepare("SELECT
128 mailbox.*,
129 domain.active AS d_active
130 FROM `mailbox`
131 INNER JOIN domain on mailbox.domain = domain.domain
132 WHERE `kind` NOT REGEXP 'location|thing|group'
133 AND `username` = :user");
134 $stmt->execute(array(':user' => $user[$iam_settings['username_field']][0]));
135 $row = $stmt->fetch(PDO::FETCH_ASSOC);
136
137 // check if matching attribute mapping exists
138 $user_template = $user[$iam_settings['attribute_field']][0];
139 $mapper_key = array_search($user_template, $iam_settings['mappers']);
140
141 if (empty($user[$iam_settings['username_field']][0])){
142 logMsg("warning", "Skipping user " . $user['displayname'][0] . " due to empty LDAP ". $iam_settings['username_field'] . " property.");
143 continue;
144 }
145
146 $_SESSION['access_all_exception'] = '1';
147 if (!$row && intval($iam_settings['import_users']) == 1){
148 if ($mapper_key === false){
149 if (!empty($iam_settings['default_template'])) {
150 $mbox_template = $iam_settings['default_template'];
151 } else {
152 logMsg("warning", "No matching attribute mapping found for user " . $user[$iam_settings['username_field']][0]);
153 continue;
154 }
155 } else {
156 $mbox_template = $iam_settings['templates'][$mapper_key];
157 }
158 // mailbox user does not exist, create...
159 logMsg("info", "Creating user " . $user[$iam_settings['username_field']][0]);
160 $create_res = mailbox('add', 'mailbox_from_template', array(
161 'domain' => explode('@', $user[$iam_settings['username_field']][0])[1],
162 'local_part' => explode('@', $user[$iam_settings['username_field']][0])[0],
163 'name' => $user['displayname'][0],
164 'authsource' => 'ldap',
165 'template' => $mbox_template
166 ));
167 if (!$create_res){
168 logMsg("err", "Could not create user " . $user[$iam_settings['username_field']][0]);
169 continue;
170 }
171 } else if ($row && intval($iam_settings['periodic_sync']) == 1 && $row['authsource'] == "ldap") {
172 if ($mapper_key === false){
173 logMsg("warning", "No matching attribute mapping found for user " . $user[$iam_settings['username_field']][0]);
174 continue;
175 }
176 $mbox_template = $iam_settings['templates'][$mapper_key];
177 // mailbox user does exist, sync attribtues...
178 logMsg("info", "Syncing attributes for user " . $user[$iam_settings['username_field']][0]);
179 mailbox('edit', 'mailbox_from_template', array(
180 'username' => $user[$iam_settings['username_field']][0],
181 'name' => $user['displayname'][0],
182 'template' => $mbox_template
183 ));
184 } else {
185 // skip mailbox user
186 logMsg("info", "Skipping user " . $user[$iam_settings['username_field']][0]);
187 }
188 $_SESSION['access_all_exception'] = '0';
189
190 sleep(0.025);
191}
192
193logMsg("info", "DONE!");
194// add last execution time to lock file
195$lock_file_handle = fopen($lock_file, 'w');
196fwrite($lock_file_handle, getmypid() . "\n" . time());
197fclose($lock_file_handle);
198session_destroy();