Marius Cramer
2015-08-06 37b29231e47a0c4458dc1c15d98588f16f07e1e2
commit | author | age
9f94a1 1 <?php
MF 2
3 /*
a7d804 4 Copyright (c) 2015 Michael Fürmann, Spicy Web (spicyweb.de)
9f94a1 5 All rights reserved.
MF 6
7 Redistribution and use in source and binary forms, with or without modification,
8 are permitted provided that the following conditions are met:
9
10     * Redistributions of source code must retain the above copyright notice,
11       this list of conditions and the following disclaimer.
12     * Redistributions in binary form must reproduce the above copyright notice,
13       this list of conditions and the following disclaimer in the documentation
14       and/or other materials provided with the distribution.
15     * Neither the name of ISPConfig nor the names of its contributors
16       may be used to endorse or promote products derived from this software without
17       specific prior written permission.
18
19 THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND
20 ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
21 WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
22 IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT,
23 INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING,
24 BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
25 DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY
26 OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
27 NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE,
28 EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
29 */
30
31 class xmpp_plugin {
32
33     var $plugin_name = 'xmpp_server_plugin';
34     var $class_name = 'xmpp_server_plugin';
35
36     var $xmpp_config_dir = '/etc/metronome';
37
f52de0 38     var $ssl_certificate_changed = false;
MF 39     var $ssl_certificate_deleted = false;
40
41
9f94a1 42     //* This function is called during ispconfig installation to determine
MF 43     //  if a symlink shall be created for this plugin.
44     function onInstall() {
45         global $conf;
46
47         if($conf['services']['xmpp'] == true) {
48             return true;
49         } else {
50             return false;
51         }
52
53     }
54
55     /*
56          This function is called when the plugin is loaded
57     */
58
59     function onLoad() {
60         global $app;
61
62         /*
63         Register for the events
64         */
65
66         $app->plugins->registerEvent('server_insert', 'xmpp_plugin', 'insert');
67         $app->plugins->registerEvent('server_update', 'xmpp_plugin', 'update');
f52de0 68
MF 69         $app->plugins->registerEvent('xmpp_domain_insert', 'xmpp_plugin', 'ssl');
70         $app->plugins->registerEvent('xmpp_domain_update', 'xmpp_plugin', 'ssl');
71         $app->plugins->registerEvent('xmpp_domain_delete', 'xmpp_plugin', 'ssl');
72
9f94a1 73         $app->plugins->registerEvent('xmpp_domain_insert', 'xmpp_plugin', 'domainInsert');
MF 74         $app->plugins->registerEvent('xmpp_domain_update', 'xmpp_plugin', 'domainUpdate');
75         $app->plugins->registerEvent('xmpp_domain_delete', 'xmpp_plugin', 'domainDelete');
3e994a 76         $app->plugins->registerEvent('xmpp_user_insert', 'xmpp_plugin', 'userInsert');
MF 77         $app->plugins->registerEvent('xmpp_user_update', 'xmpp_plugin', 'userUpdate');
78         $app->plugins->registerEvent('xmpp_user_delete', 'xmpp_plugin', 'userDelete');
9f94a1 79
MF 80     }
81
82     function insert($event_name, $data) {
83         global $app, $conf;
84
85         $this->update($event_name, $data);
86
87     }
88
89     // The purpose of this plugin is to rewrite the main.cf file
90     function update($event_name, $data) {
91         global $app, $conf;
92
93         // get the config
94         $app->uses("getconf,system,tpl");
95
96
97         $old_ini_data = $app->ini_parser->parse_ini_string($data['old']['config']);
98         $xmpp_config = $app->getconf->get_server_config($conf['server_id'], 'xmpp');
99
a7d804 100         // Global server config
9f94a1 101         $tpl = new tpl();
MF 102         $tpl->newTemplate('metronome_conf_global.master');
103         $tpl->setVar('ipv6', $xmpp_config['xmpp_use_ipv6']=='y'?'true':'false');
104         $tpl->setVar('bosh_timeout', intval($xmpp_config['xmpp_bosh_max_inactivity']));
105         $tpl->setVar('port_http', intval($xmpp_config['xmpp_port_http']));
106         $tpl->setVar('port_https', intval($xmpp_config['xmpp_port_https']));
107         $tpl->setVar('port_pastebin', intval($xmpp_config['xmpp_port_pastebin']));
108         $tpl->setVar('port_bosh', intval($xmpp_config['xmpp_port_bosh']));
a7d804 109         // Global server admins (for all hosted domains)
9f94a1 110         $admins = '';
MF 111         foreach(explode(',', $xmpp_config['xmpp_server_admins']) AS $a)
112             $admins.= "\t\"".trim($a)."\",\n";
113         $tpl->setVar('server_admins', $admins);
114         unset($admins);
a7d804 115         // enabled modules, so own modules or simmilar prosody-modules can easily be added
9f94a1 116         $modules = '';
MF 117         foreach(explode(',', $xmpp_config['xmpp_modules_enabled']) AS $m)
118             $modules.= "\t\"".trim($m)."\",\n";
119         $tpl->setVar('modules_enabled', $modules);
120         unset($modules);
121         $app->system->file_put_contents($this->xmpp_config_dir.'/global.cfg.lua', $tpl->grab());
122         unset($tpl);
123
e3ba29 124         $app->services->restartServiceDelayed('metronome', 'restart');
9f94a1 125         return;
MF 126     }
127
128     function domainInsert($event_name, $data) {
129         global $app, $conf;
130
131         $this->domainUpdate($event_name, $data);
132
133     }
134
135     function domainUpdate($event_name, $data){
136         global $app, $conf;
137
138         // get the config
139         $app->uses("getconf,system,tpl");
140
141         // Collections
142         $status_hosts = array($data['new']['domain']);
143         $status_comps = array();
144
145         // Create main host file
146         $tpl = new tpl();
147         $tpl->newTemplate('metronome_conf_host.master');
148         $tpl->setVar('domain', $data['new']['domain']);
149         $tpl->setVar('active', $data['new']['active'] == 'y' ? 'true' : 'false');
150         $tpl->setVar('public_registration', $data['new']['public_registration'] == 'y' ? 'true' : 'false');
a7d804 151         // Domain admins
9f94a1 152         $admins = array();
MF 153         foreach(explode(',',$data['new']['domain_admins']) AS $adm){
154             $admins[] = trim($adm);
155         }
156         $tpl->setVar('domain_admins', "\t\t\"".implode("\",\n\t\t\"",$admins)."\"\n");
157
a7d804 158         // Enable / Disable features
9f94a1 159         if($data['new']['use_pubsub']=='y'){
MF 160             $tpl->setVar('use_pubsub', 'true');
161             $status_comps[] = 'pubsub.'.$data['new']['domain'];
162         }else{
163             $tpl->setVar('use_pubsub', 'false');
164         }
165         if($data['new']['use_proxy']=='y'){
166             $tpl->setVar('use_proxy', 'true');
167             $status_comps[] = 'proxy.'.$data['new']['domain'];
168         }else{
169             $tpl->setVar('use_proxy', 'false');
170         }
171
172         if($data['new']['use_anon_host']=='y'){
173             $tpl->setVar('use_anon_host', 'true');
174             $status_hosts[] = 'anon.'.$data['new']['domain'];
175         }else{
176             $tpl->setVar('use_anon_host', 'false');
177         }
178         if($data['new']['use_vjud']=='y'){
179             $tpl->setVar('use_vjud', 'true');
180             $tpl->setVar('vjud_opt_mode', 'opt-'.$data['new']['vjud_opt_mode']);
181             $status_comps[] = 'vjud.'.$data['new']['domain'];
182         }else{
183             $tpl->setVar('use_vjud', 'false');
184         }
185
186         $tpl->setVar('use_muc', $data['new']['use_muc_host']=='y'?'true':'false');
187         if($data['new']['use_muc_host'] == 'y'){
188             $status_comps[] = 'muc.'.$data['new']['domain'];
189             $tpl->setVar('muc_restrict_room_creation', $data['new']['muc_restrict_room_creation']);
190             $tpl->setVar('muc_name', strlen($data['new']['muc_name']) ? $data['new']['muc_name'] : $data['new']['domain'].' Chatrooms');
a7d804 191             // Admins for MUC channels
9f94a1 192             $admins = array();
MF 193             foreach(explode(',',$data['new']['muc_admins']) AS $adm){
194                 $admins[] = trim($adm);
195             }
196             $tpl->setVar('muc_admins', "\t\t\"".implode("\",\n\t\t\"",$admins)."\"\n");
197             $tpl->setVar('use_pastebin', $data['new']['use_pastebin']=='y'?'true':'false');
198             $tpl->setVar('pastebin_expire', intval($data['new']['pastebin_expire_after']));
199             $tpl->setVar('pastebin_trigger', $data['new']['pastebin_trigger']);
200             $tpl->setVar('use_archive', $data['new']['use_http_archive']=='y'?'true':'false');
201             $tpl->setVar('archive_join', $data['new']['http_archive_show_join']=='y'?'true':'false');
202             $tpl->setVar('archive_status', $data['new']['http_archive_show_status']=='y'?'true':'false');
203
204         }
205
f52de0 206         // Check for SSL
MF 207         if(strlen($data['new']['ssl_cert']) && strlen($data['new']['ssl_key']) && !$this->ssl_certificate_deleted || $this->ssl_certificate_changed)
208             $tpl->setVar('ssl_cert', true);
209
9f94a1 210         $app->system->file_put_contents($this->xmpp_config_dir.'/hosts/'.$data['new']['domain'].'.cfg.lua', $tpl->grab());
MF 211         unset($tpl);
212
213         // Create status host file
214         if($data['new']['use_status_host']=='y'){
215             $tpl = new tpl;
216             $tpl->newTemplate('metronome_conf_status.master');
217             $tpl->setVar('domain', $data['new']['domain']);
218             $tpl->setVar('status_hosts', "\t\t\"".implode("\",\n\t\t\"",$status_hosts)."\"\n");
219             $tpl->setVar('status_comps', "\t\t\"".implode("\",\n\t\t\"",$status_comps)."\"\n");
220             $app->system->file_put_contents($this->xmpp_config_dir.'/status/'.$data['new']['domain'].'.cfg.lua', $tpl->grab());
221             unset($tpl);
222         }
e3ba29 223
f52de0 224         $app->services->restartServiceDelayed('metronome', 'reload');
9f94a1 225     }
MF 226
227     function domainDelete($event_name, $data){
228         global $app, $conf;
229
230         // get the config
231         $app->uses("system");
232         $domain = $data['old']['domain'];
233         $folder = str_replace('-', '%2d', str_replace('.', '%2e', $str = urlencode($domain)));
234
235         // Remove config files
236         $app->system->unlink("/etc/metronome/hosts/$domain.cfg.lua");
237         $app->system->unlink("/etc/metronome/status/$domain.cfg.lua");
238         $app->system->unlink("/etc/metronome/certs/$domain.cert");
239         $app->system->unlink("/etc/metronome/certs/$domain.key");
240         $app->system->unlink("/etc/metronome/certs/$domain.csr");
241         // Remove all stored data
242         var_dump('rm -rf /var/lib/metronome/'.$folder);
243         exec('rm -rf /var/lib/metronome/'.$folder);
244         exec('rm -rf /var/lib/metronome/*%2e'.$folder);
245
a7d804 246         $app->services->restartServiceDelayed('metronome', 'reload');
9f94a1 247     }
MF 248
3e994a 249     function userInsert($event_name, $data){
MF 250         //$data['new']['auth_method']
251         // Check domain for auth settings
252         // Don't allow manual user creation for mailaccount controlled domains
253
254         // maybe metronomectl adduser for new local users
255     }
256     function userUpdate($event_name, $data){
257         // Check domain for auth settings
258         // Don't allow manual user update for mailaccount controlled domains
259
260         // maybe metronomectl passwd for existing local users
261     }
262     function userDelete($event_name, $data){
263         // Check domain for auth settings
264         // Don't allow manual user deletion for mailaccount controlled domains
265
266         // Remove account from metronome
267         exec('metronomectl deluser '.$data['old']['jid']);
268     }
269
f52de0 270     // Handle the creation of SSL certificates
MF 271     function ssl($event_name, $data) {
272         global $app, $conf;
273
274         $app->uses('system,tpl');
275
276         // load the server configuration options
277         $app->uses('getconf');
278         $web_config = $app->getconf->get_server_config($conf['server_id'], 'web');
279
280         $ssl_dir = '/etc/metronome/certs';
281         $domain = $data['new']['domain'];
282         $cnf_file = $ssl_dir.'/'.$domain.'.cnf';
283         $key_file = $ssl_dir.'/'.$domain.'.key';
284         $csr_file = $ssl_dir.'/'.$domain.'.csr';
285         $crt_file = $ssl_dir.'/'.$domain.'.cert';
286
287         //* Create a SSL Certificate, but only if this is not a mirror server.
288         if($data['new']['ssl_action'] == 'create' && $conf['mirror_server_id'] == 0) {
289
290             $this->ssl_certificate_changed = true;
291
292             //* Rename files if they exist
293             if(file_exists($cnf_file)) $app->system->rename($cnf_file, $cnf_file.'.bak');
294             if(file_exists($key_file)){
295                 $app->system->rename($key_file, $key_file.'.bak');
296                 $app->system->chmod($key_file.'.bak', 0400);
297                 $app->system->chown($key_file.'.bak', 'metronome');
298             }
299             if(file_exists($csr_file)) $app->system->rename($csr_file, $csr_file.'.bak');
300             if(file_exists($crt_file)) $app->system->rename($crt_file, $crt_file.'.bak');
301
302             // Write new CNF file
303             $tpl = new tpl();
304             $tpl->newTemplate('metronome_conf_ssl.master');
305             $tpl->setVar('domain', $domain);
306             $tpl->setVar('ssl_country', $data['new']['ssl_country']);
307             $tpl->setVar('ssl_locality', $data['new']['ssl_locality']);
308             $tpl->setVar('ssl_organisation', $data['new']['ssl_organisation']);
309             $tpl->setVar('ssl_organisation_unit', $data['new']['ssl_organisation_unit']);
310             $tpl->setVar('ssl_email', $data['new']['ssl_email']);
311             $app->system->file_put_contents($cnf_file, $tpl->grab());
312
313             // Generate new key, csr and cert
314             exec("(cd /etc/metronome/certs && make $domain.key)");
315             exec("(cd /etc/metronome/certs && make $domain.csr)");
316             exec("(cd /etc/metronome/certs && make $domain.cert)");
317
2af58c 318             $ssl_key = $app->system->file_get_contents($key_file);
f52de0 319             $app->system->chmod($key_file, 0400);
MF 320             $app->system->chown($key_file, 'metronome');
2af58c 321             $ssl_request = $app->system->file_get_contents($csr_file);
MC 322             $ssl_cert = $app->system->file_get_contents($crt_file);
f52de0 323             /* Update the DB of the (local) Server */
2af58c 324             $app->db->query("UPDATE xmpp_domain SET ssl_request = ?, ssl_cert = ?, ssl_key = ? WHERE domain = ?", $ssl_request, $ssl_cert, $ssl_key, $data['new']['domain']);
MC 325             $app->db->query("UPDATE xmpp_domain SET ssl_action = '' WHERE domain = ?", $data['new']['domain']);
f52de0 326             /* Update also the master-DB of the Server-Farm */
2af58c 327             $app->dbmaster->query("UPDATE xmpp_domain SET ssl_request = ?, ssl_cert = ?, ssl_key = ? WHERE domain = ?", $ssl_request, $ssl_cert, $ssl_key, $data['new']['domain']);
MC 328             $app->dbmaster->query("UPDATE xmpp_domain SET ssl_action = '' WHERE domain = ?", $data['new']['domain']);
f52de0 329             $app->log('Creating XMPP SSL Cert for: '.$domain, LOGLEVEL_DEBUG);
MF 330         }
331
332         //* Save a SSL certificate to disk
333         if($data["new"]["ssl_action"] == 'save') {
334             $this->ssl_certificate_changed = true;
335
336             //* Rename files if they exist
337             if(file_exists($cnf_file)) $app->system->rename($cnf_file, $cnf_file.'.bak');
338             if(file_exists($key_file)){
339                 $app->system->rename($key_file, $key_file.'.bak');
340                 $app->system->chmod($key_file.'.bak', 0400);
341                 $app->system->chown($key_file.'.bak', 'metronome');
342             }
343             if(file_exists($csr_file)) $app->system->rename($csr_file, $csr_file.'.bak');
344             if(file_exists($crt_file)) $app->system->rename($crt_file, $crt_file.'.bak');
345
346             //* Write new ssl files
347             if(trim($data["new"]["ssl_request"]) != '')
348                 $app->system->file_put_contents($csr_file, $data["new"]["ssl_request"]);
349             if(trim($data["new"]["ssl_cert"]) != '')
350                 $app->system->file_put_contents($crt_file, $data["new"]["ssl_cert"]);
351
352             //* Write the key file, if field is empty then import the key into the db
353             if(trim($data["new"]["ssl_key"]) != '') {
354                 $app->system->file_put_contents($key_file, $data["new"]["ssl_key"]);
355                 $app->system->chmod($key_file, 0400);
356                 $app->system->chown($key_file, 'metronome');
357             } else {
2af58c 358                 $ssl_key = $app->system->file_get_contents($key_file);
f52de0 359                 /* Update the DB of the (local) Server */
2af58c 360                 $app->db->query("UPDATE xmpp_domain SET ssl_key = ? WHERE domain = ?", $ssl_key, $data['new']['domain']);
f52de0 361                 /* Update also the master-DB of the Server-Farm */
2af58c 362                 $app->dbmaster->query("UPDATE xmpp_domain SET ssl_key = '$ssl_key' WHERE domain = ?", $data['new']['domain']);
f52de0 363             }
MF 364
365             /* Update the DB of the (local) Server */
2af58c 366             $app->db->query("UPDATE xmpp_domain SET ssl_action = '' WHERE domain = ?", $data['new']['domain']);
f52de0 367
MF 368             /* Update also the master-DB of the Server-Farm */
2af58c 369             $app->dbmaster->query("UPDATE xmpp_domain SET ssl_action = '' WHERE domain = ?", $data['new']['domain']);
f52de0 370             $app->log('Saving XMPP SSL Cert for: '.$domain, LOGLEVEL_DEBUG);
MF 371         }
372
373         //* Delete a SSL certificate
374         if($data['new']['ssl_action'] == 'del') {
375             $this->ssl_certificate_deleted = true;
376             $app->system->unlink($csr_file);
377             $app->system->unlink($crt_file);
378             $app->system->unlink($key_file);
379             $app->system->unlink($cnf_file);
380             $app->system->unlink($csr_file.'.bak');
381             $app->system->unlink($crt_file.'.bak');
382             $app->system->unlink($key_file.'.bak');
383             $app->system->unlink($cnf_file.'.bak');
384             /* Update the DB of the (local) Server */
2af58c 385             $app->db->query("UPDATE xmpp_domain SET ssl_request = '', ssl_cert = '', ssl_key = '' WHERE domain = ?", $data['new']['domain']);
MC 386             $app->db->query("UPDATE xmpp_domain SET ssl_action = '' WHERE domain = ?", $data['new']['domain']);
f52de0 387             /* Update also the master-DB of the Server-Farm */
2af58c 388             $app->dbmaster->query("UPDATE xmpp_domain SET ssl_request = '', ssl_cert = '', ssl_key = '' WHERE domain = ?", $data['new']['domain']);
MC 389             $app->dbmaster->query("UPDATE xmpp_domain SET ssl_action = '' WHERE domain = ?", $data['new']['domain']);
f52de0 390             $app->log('Deleting SSL Cert for: '.$domain, LOGLEVEL_DEBUG);
MF 391         }
392
393     }
394
9f94a1 395 } // end class
MF 396
397 ?>