Merge branch 'master' into pu
This commit is contained in:
commit
81d3105d2b
|
@ -41,3 +41,8 @@ bureau/locales/fr_FR/LC_MESSAGES/messages.po~
|
|||
bureau/locales/it_IT/LC_MESSAGES/messages.po~
|
||||
bureau/locales/nl_NL/LC_MESSAGES/messages.po~
|
||||
bureau/locales/pt_BR/LC_MESSAGES/messages.po~
|
||||
.tx/alternc.alternc
|
||||
# Added for running tests; currently not used otherwise
|
||||
composer.lock
|
||||
composer.json
|
||||
vendor/
|
||||
|
|
10
.travis.yml
10
.travis.yml
|
@ -2,14 +2,16 @@ language: php
|
|||
services:
|
||||
- mysql
|
||||
php:
|
||||
- 7.1
|
||||
- 7.0
|
||||
- 5.6
|
||||
- 5.5
|
||||
- 5.4
|
||||
- 5.3
|
||||
script: ../vendor/bin/phpunit --coverage-clover=coverage.clover
|
||||
script:
|
||||
- grep --exclude-dir=../.git/ --exclude-dir=../vendor/ -l -r -e '#!/bin/[bash|sh]' ../ | uniq | xargs shellcheck
|
||||
- ../vendor/bin/phpcs --ignore=../vendor/ ../
|
||||
- ../vendor/bin/phpunit --coverage-clover=coverage.clover
|
||||
before_script:
|
||||
- composer require phpunit/dbunit
|
||||
- composer require 'phpunit/dbunit=<3.0.2' squizlabs/php_codesniffer
|
||||
- mysql -e 'create database alternc_test DEFAULT CHARACTER SET utf8 DEFAULT COLLATE utf8_general_ci;'
|
||||
- cd phpunit
|
||||
after_script:
|
||||
|
|
2
Makefile
2
Makefile
|
@ -48,7 +48,7 @@ install-common:
|
|||
# Installer and upgrade scripts
|
||||
test -d $(DESTDIR)/usr/share/alternc/install || mkdir -p $(DESTDIR)/usr/share/alternc/install
|
||||
cp -r install/* $(DESTDIR)/usr/share/alternc/install
|
||||
chmod a+x $(DESTDIR)/usr/share/alternc/install/alternc.install $(DESTDIR)/usr/share/alternc/install/dopo.sh $(DESTDIR)/usr/share/alternc/install/mysql.sh $(DESTDIR)/usr/share/alternc/install/newone.php $(DESTDIR)/usr/share/alternc/install/reset_root.php $(DESTDIR)/usr/share/alternc/install/upgrade_check.sh $(DESTDIR)/usr/share/alternc/install/upgrades/*.php $(DESTDIR)/usr/share/alternc/install/upgrades/*.sh
|
||||
chmod a+x $(DESTDIR)/usr/share/alternc/install/alternc.install $(DESTDIR)/usr/share/alternc/install/dopo.sh $(DESTDIR)/usr/share/alternc/install/mysql.sh $(DESTDIR)/usr/share/alternc/install/newone.php $(DESTDIR)/usr/share/alternc/install/reset_root.php $(DESTDIR)/usr/share/alternc/install/upgrade_check.sh $(DESTDIR)/usr/share/alternc/install/upgrades/*.php $(DESTDIR)/usr/share/alternc/install/upgrades/*.sh $(DESTDIR)/usr/share/alternc/install/variables.php
|
||||
|
||||
|
||||
# install AlternC itself:
|
||||
|
|
|
@ -147,7 +147,7 @@ $dom->unlock();
|
|||
}
|
||||
?></button>
|
||||
<?php if ($isedit) { ?>
|
||||
<button class="inb cancel" name="cancel" onclick="document.location = 'dom_edit.php?domain=<?php echo $domain; ?>'"><?php __("Cancel"); ?></button>
|
||||
<button class="inb cancel" type="button" name="cancel" onclick="document.location = 'dom_edit.php?domain=<?php echo $domain; ?>'"><?php __("Cancel"); ?></button>
|
||||
<?php } ?>
|
||||
</td>
|
||||
</tr>
|
||||
|
|
|
@ -39,7 +39,7 @@ if (!defined("ALTERNC_PANEL")) exit(); // must be included ;)
|
|||
if (file_exists("styles/style-custom.css") ) {
|
||||
echo '<link rel="stylesheet" href="styles/style-custom.css" type="text/css" />';
|
||||
}
|
||||
if (count($addhead['css'])) {
|
||||
if (isset($addhead) && count($addhead['css'])) {
|
||||
foreach($addhead['css'] as $css) echo $css."\n";
|
||||
}
|
||||
$favicon = variable_get('favicon', 'favicon.ico' ,'You can specify a favicon, for example /images/my_logo.ico', array('desc'=>'URL','type'=>'string'));
|
||||
|
@ -53,7 +53,7 @@ $favicon = variable_get('favicon', 'favicon.ico' ,'You can specify a favicon, fo
|
|||
<script src="/javascript/jquery-ui/jquery-ui.min.js" type="text/javascript"></script>
|
||||
<script src="/javascript/jquery-tablesorter/jquery.tablesorter.min.js" type="text/javascript"></script>
|
||||
<?php
|
||||
if (count($addhead['js'])) {
|
||||
if (isset($addhead) && count($addhead['js'])) {
|
||||
foreach($addhead['js'] as $js) echo $js."\n";
|
||||
}
|
||||
?>
|
||||
|
|
|
@ -87,7 +87,8 @@ if ( empty($logo) || ! $logo ) {
|
|||
</div>
|
||||
</div>
|
||||
<div class="block_login_page">
|
||||
|
||||
<a href="request_reset.php"><?php echo _('Request new password'); ?></a>
|
||||
<br />
|
||||
<?php __("You must accept the session cookie to log-in"); ?>
|
||||
<br />
|
||||
<?php echo _("If you want to use a different language, choose it in the list below"); ?>
|
||||
|
|
|
@ -81,7 +81,9 @@ echo "<p>";
|
|||
<input type="password" style="display: none" id="fakePassword" name="fakePassword" value="" />
|
||||
|
||||
<table border="1" cellspacing="0" cellpadding="4" class="tedit" >
|
||||
<tr><th><?php __("Old password"); ?></th><td><input type="password" class="int" name="oldpass" value="<?php isset($oldpass) ? : $oldpass=""; ehe($oldpass); ?>" size="20" maxlength="128" /></td></tr>
|
||||
<?php if ($mem->requires_old_password_for_change()): ?>
|
||||
<tr><th><?php __("Old password"); ?></th><td><input type="password" class="int" name="oldpass" value="<?php isset($oldpass) ? : $oldpass=""; ehe($oldpass); ?>" size="20" maxlength="128" /></td></tr>
|
||||
<?php endif; ?>
|
||||
<tr><th><?php __("New password"); ?> (1)</th><td><input type="password" class="int" autocomplete="off" id="newpass" name="newpass" value="<?php isset($newpass) ? : $newpass=""; ehe($newpass); ?>" size="20" maxlength="60" /><?php display_div_generate_password(DEFAULT_PASS_SIZE,"#newpass","#newpass2",$passwd_classcount); ?></td></tr>
|
||||
<tr><th><?php __("New password"); ?> (2)</th><td><input type="password" class="int" autocomplete="off" id="newpass2" name="newpass2" value="<?php isset($newpass2) ? : $newpass2=""; ehe($newpass2);?>" size="20" maxlength="61" /></td></tr>
|
||||
<tr class="trbtn"><td colspan="3"><input type="submit" class="inb ok" name="submit" value="<?php __("Change my password"); ?>" /></td></tr>
|
||||
|
@ -134,8 +136,13 @@ if ($mem->user["su"]) {
|
|||
</div> <!-- tabsmem -->
|
||||
|
||||
<script type="text/javascript">
|
||||
document.forms['main'].oldpass.focus();
|
||||
$(function() {$( "#tabsmem" ).tabs();});
|
||||
if (document.forms['main'].getElementsByClassName("oldpass").length > 0) {
|
||||
document.forms['main'].oldpass.focus();
|
||||
}
|
||||
else {
|
||||
document.getElementById('newpass').focus();
|
||||
}
|
||||
$(function() {$( "#tabsmem" ).tabs();});
|
||||
</script>
|
||||
|
||||
<?php include_once("foot.php"); ?>
|
||||
|
|
|
@ -0,0 +1,72 @@
|
|||
<?php
|
||||
|
||||
require_once("../class/config_nochk.php");
|
||||
|
||||
$request = FALSE;
|
||||
$valid_request = TRUE;
|
||||
if (isset($_REQUEST['name_or_email'])) {
|
||||
$request = TRUE;
|
||||
// Inserted into the global namespace by config.php
|
||||
$valid_request = !$fatalcsrf;
|
||||
if ($fatalcsrf) {
|
||||
$msg->raise('ERROR', _('Failed to validate CSRF token'));
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
// Show the form if nothing was submitted, or if what was submitted is not
|
||||
// a valid request (eg. doesn't pass CSRF).
|
||||
$show_form = !$request || ($request && !$valid_request);
|
||||
|
||||
if ($request && $valid_request) {
|
||||
$mem->send_reset_url($_REQUEST['name_or_email']);
|
||||
}
|
||||
|
||||
if (!isset($charset) || ! $charset) {
|
||||
$charset="UTF-8";
|
||||
}
|
||||
|
||||
@header("Content-Type: text/html; charset=$charset");
|
||||
require_once("html-head.php");
|
||||
?>
|
||||
|
||||
<body class="login_page">
|
||||
<div id="global">
|
||||
<div id="content">
|
||||
<?php
|
||||
// Getting logo. C.f. admin/index.php
|
||||
$logo = variable_get('logo_login', '' ,'You can specify a logo for the login page, example /images/my_logo.png .', array('desc'=>'URL','type'=>'string'));
|
||||
if ( empty($logo) || ! $logo ) {
|
||||
$logo = 'images/logo.png';
|
||||
}
|
||||
?>
|
||||
<p id='logo'> <img src="<?php echo $logo; ?>" border="0" height="100px" alt="<?php __("Web Hosting Control Panel"); ?>" title="<?php __("Web Hosting Control Panel"); ?>" />
|
||||
</p>
|
||||
<p> </p>
|
||||
<?php echo $msg->msg_html_all(); ?>
|
||||
<br/>
|
||||
<div class="block_list">
|
||||
<?php if ($show_form): ?>
|
||||
<div class="block_login_page">
|
||||
<div class="menu-box">
|
||||
<div class="menu-title"><?php echo _('Password reset'); ?></div>
|
||||
<form action="request_reset.php" method="post" name="passwordreset">
|
||||
<?php csrf_get(); ?>
|
||||
<div>
|
||||
<label for="name_or_email"><?php echo _('Username or e-mail'); ?></label>
|
||||
<input type="text" class="int" name="name_or_email">
|
||||
</div>
|
||||
<div class="submit"><input type="submit" class="inb" name="submit"></div>
|
||||
</form>
|
||||
</div>
|
||||
</div>
|
||||
<div class="block_list">
|
||||
<p><?php echo _('An e-mail with instructions will be sent'); ?></p>
|
||||
</div>
|
||||
<?php else: ?>
|
||||
<div><p><a href="index.php"><?php __('Return to login page'); ?></a></p></div>
|
||||
<?php endif; ?>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</body>
|
|
@ -0,0 +1,15 @@
|
|||
<?php
|
||||
|
||||
require_once("../class/config_nochk.php");
|
||||
|
||||
if (isset($_GET['uid']) && isset($_GET['token']) && isset($_GET['timestamp'])) {
|
||||
// We may have received a one-time use link.
|
||||
$logged_in = $mem->temporary_login($_GET['uid'], $_GET['timestamp'],
|
||||
$_GET['token']);
|
||||
if ($logged_in) {
|
||||
$msg->raise('INFO', 'admin/reset', _('Please change your password'));
|
||||
header("Location: /mem_param.php");
|
||||
exit;
|
||||
}
|
||||
}
|
||||
header("Location: /index.php");
|
|
@ -1,525 +0,0 @@
|
|||
<?php
|
||||
|
||||
/*
|
||||
----------------------------------------------------------------------
|
||||
LICENSE
|
||||
|
||||
This program is free software; you can redistribute it and/or
|
||||
modify it under the terms of the GNU General Public License (GPL)
|
||||
as published by the Free Software Foundation; either version 2
|
||||
of the License, or (at your option) any later version.
|
||||
|
||||
This program is distributed in the hope that it will be useful,
|
||||
but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
GNU General Public License for more details.
|
||||
|
||||
To read the license please visit http://www.gnu.org/copyleft/gpl.html
|
||||
----------------------------------------------------------------------
|
||||
*/
|
||||
|
||||
/**
|
||||
* bind9 file management class
|
||||
*
|
||||
* @copyright AlternC-Team 2000-2017 https://alternc.com/
|
||||
*/
|
||||
class system_bind {
|
||||
var $ZONE_TEMPLATE ="/etc/alternc/templates/bind/templates/zone.template";
|
||||
var $NAMED_TEMPLATE ="/etc/alternc/templates/bind/templates/named.template";
|
||||
var $NAMED_CONF ="/var/lib/alternc/bind/automatic.conf";
|
||||
var $RNDC ="/usr/sbin/rndc";
|
||||
|
||||
var $dkim_trusted_host_file = "/etc/opendkim/TrustedHosts";
|
||||
var $dkim_keytable_file = "/etc/opendkim/KeyTable";
|
||||
var $dkim_signingtable_file = "/etc/opendkim/SigningTable";
|
||||
|
||||
var $cache_conf_db = array();
|
||||
var $cache_get_persistent = array();
|
||||
var $cache_zone_file = array();
|
||||
var $cache_domain_summary = array();
|
||||
var $zone_file_directory = '/var/lib/alternc/bind/zones/';
|
||||
|
||||
|
||||
/**
|
||||
* Return the part of the conf we got from the database
|
||||
*
|
||||
* @global m_mysql $db
|
||||
* @param string $domain
|
||||
* @return array $this->cache_conf_db
|
||||
*/
|
||||
function conf_from_db($domain=false) {
|
||||
global $db;
|
||||
// Use cache, fill cache if empty
|
||||
if (empty($this->cache_conf_db)) {
|
||||
$db->query("
|
||||
select
|
||||
sd.domaine,
|
||||
replace(replace(dt.entry,'%TARGET%',sd.valeur), '%SUB%', if(length(sd.sub)>0,sd.sub,'@')) as entry
|
||||
from
|
||||
sub_domaines sd,
|
||||
domaines_type dt
|
||||
where
|
||||
sd.type=dt.name
|
||||
and sd.enable in ('ENABLE', 'ENABLED')
|
||||
order by entry ;");
|
||||
$t=array();
|
||||
while ($db->next_record()) {
|
||||
$t[$db->f('domaine')][] = $db->f('entry');
|
||||
}
|
||||
$this->cache_conf_db = $t;
|
||||
}
|
||||
if ($domain) {
|
||||
if (isset($this->cache_conf_db[$domain])) {
|
||||
return $this->cache_conf_db[$domain];
|
||||
} else {
|
||||
return array();
|
||||
}
|
||||
} // if domain
|
||||
return $this->cache_conf_db;
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Return full path of the zone configuration file
|
||||
*
|
||||
* @param string $domain
|
||||
* @return string
|
||||
*/
|
||||
function get_zone_file_uri($domain) {
|
||||
return $this->zone_file_directory.$domain;
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
*
|
||||
* @param string $domain
|
||||
* @return string zone file path
|
||||
*/
|
||||
function get_zone_file($domain) {
|
||||
// Use cache, fill cache if empty
|
||||
if (!isset($this->cache_zone_file[$domain]) ) {
|
||||
if (file_exists($this->get_zone_file_uri($domain))) {
|
||||
$this->cache_zone_file[$domain] = @file_get_contents($this->get_zone_file_uri($domain));
|
||||
} else {
|
||||
$this->cache_zone_file[$domain] = false;
|
||||
}
|
||||
}
|
||||
return $this->cache_zone_file[$domain] ;
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
*
|
||||
* @param string $domain
|
||||
* @return string
|
||||
*/
|
||||
function get_serial($domain) {
|
||||
// Return the next serial the domain must have.
|
||||
// Choose between a generated and an incremented.
|
||||
|
||||
// Calculated :
|
||||
$calc = date('Ymd').'00'."\n";
|
||||
|
||||
// Old one :
|
||||
$old=$calc; // default value
|
||||
$file = $this->get_zone_file($domain);
|
||||
preg_match_all("/\s*(\d{10})\s+\;\sserial\s?/", $file, $output_array);
|
||||
if (isset($output_array[1][0]) && !empty($output_array[1][0])) {
|
||||
$old = $output_array[1][0];
|
||||
}
|
||||
|
||||
// Return max between newly calculated, and old one incremented
|
||||
return max(array($calc,$old)) + 1 ;
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Return lines that are after ;;; END ALTERNC AUTOGENERATE CONFIGURATION
|
||||
*
|
||||
* @param string $domain
|
||||
* @return string
|
||||
*/
|
||||
function get_persistent($domain) {
|
||||
if ( ! isset($this->cache_get_persistent[$domain] )) {
|
||||
preg_match_all('/\;\s*END\sALTERNC\sAUTOGENERATE\sCONFIGURATION(.*)/s', $this->get_zone_file($domain), $output_array);
|
||||
if (isset($output_array[1][0]) && !empty($output_array[1][0])) {
|
||||
$this->cache_get_persistent[$domain] = $output_array[1][0];
|
||||
} else {
|
||||
$this->cache_get_persistent[$domain] = false;
|
||||
}
|
||||
} // isset
|
||||
return $this->cache_get_persistent[$domain];
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
*
|
||||
* @return string
|
||||
*/
|
||||
function get_zone_header() {
|
||||
return file_get_contents($this->ZONE_TEMPLATE);
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
*
|
||||
* @global m_dom $dom
|
||||
* @param string $domain
|
||||
* @return array Retourne un tableau
|
||||
*/
|
||||
function get_domain_summary($domain=false) {
|
||||
global $dom;
|
||||
|
||||
// Use cache if is filled, if not, fill it
|
||||
if (empty($this->cache_domain_summary)) {
|
||||
$this->cache_domain_summary = $dom->get_domain_all_summary();
|
||||
}
|
||||
|
||||
if ($domain) return $this->cache_domain_summary[$domain];
|
||||
else return $this->cache_domain_summary;
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
*
|
||||
* @param string $domain
|
||||
* @return boolean
|
||||
*/
|
||||
function dkim_delete($domain) {
|
||||
$target_dir = "/etc/opendkim/keys/$domain";
|
||||
if (file_exists($target_dir)) {
|
||||
@unlink("$target_dir/alternc_private");
|
||||
@unlink("$target_dir/alternc.txt");
|
||||
@rmdir($target_dir);
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Generate the domain DKIM key
|
||||
*
|
||||
* @param string $domain
|
||||
* @return null|boolean
|
||||
*/
|
||||
function dkim_generate_key($domain) {
|
||||
// Stop here if we do not manage the mail
|
||||
$domainInfo = $this->get_domain_summary($domain);
|
||||
if ( ! $domainInfo['gesmx'] ) return;
|
||||
|
||||
$target_dir = "/etc/opendkim/keys/$domain";
|
||||
|
||||
if (file_exists($target_dir.'/alternc.txt')) return; // Do not generate if exist
|
||||
|
||||
if (! is_dir($target_dir)) mkdir($target_dir); // create dir
|
||||
|
||||
// Generate the key
|
||||
$old_dir=getcwd();
|
||||
chdir($target_dir);
|
||||
exec('opendkim-genkey -r -d '.escapeshellarg($domain).' -s "alternc" ');
|
||||
chdir($old_dir);
|
||||
|
||||
// opendkim must be owner of the key
|
||||
chown("$target_dir/alternc.private", 'opendkim');
|
||||
chgrp("$target_dir/alternc.private", 'opendkim');
|
||||
|
||||
return true; // FIXME handle error
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Refresh DKIM configuration: be sure to list the domain having a private key (and only them)
|
||||
*/
|
||||
function dkim_refresh_list() {
|
||||
// so ugly... but there is only 1 pass, not 3. Still ugly.
|
||||
$trusted_host_new = "# WARNING: this file is auto generated by AlternC.\n# Add your changes after the last line\n";
|
||||
$keytable_new = "# WARNING: this file is auto generated by AlternC.\n# Add your changes after the last line\n";
|
||||
$signingtable_new = "# WARNING: this file is auto generated by AlternC.\n# Add your changes after the last line\n";
|
||||
|
||||
# Generate automatic entry
|
||||
foreach ($this->get_domain_summary() as $domain => $ds ) {
|
||||
// Skip if delete in progress, or if we do not manage dns or mail
|
||||
if ( ! $ds['gesdns'] || ! $ds['gesmx'] || strtoupper($ds['dns_action']) == 'DELETE' ) continue;
|
||||
|
||||
// Skip if there is no key generated
|
||||
if (! file_exists("/etc/opendkim/keys/$domain/alternc.txt")) continue;
|
||||
|
||||
// Modif the files.
|
||||
$trusted_host_new.="$domain\n";
|
||||
$keytable_new .="alternc._domainkey.$domain $domain:alternc:/etc/opendkim/keys/$domain/alternc.private\n";
|
||||
$signingtable_new.="$domain alternc._domainkey.$domain\n";
|
||||
}
|
||||
$trusted_host_new.="# END AUTOMATIC FILE. ADD YOUR CHANGES AFTER THIS LINE\n";
|
||||
$keytable_new .="# END AUTOMATIC FILE. ADD YOUR CHANGES AFTER THIS LINE\n";
|
||||
$signingtable_new.="# END AUTOMATIC FILE. ADD YOUR CHANGES AFTER THIS LINE\n";
|
||||
|
||||
# Get old files
|
||||
$trusted_host_old=@file_get_contents($this->dkim_trusted_host_file);
|
||||
$keytable_old =@file_get_contents($this->dkim_keytable_file);
|
||||
$signingtable_old=@file_get_contents($this->dkim_signingtable_file);
|
||||
|
||||
# Keep manuel entry
|
||||
preg_match_all('/\#\s*END\ AUTOMATIC\ FILE\.\ ADD\ YOUR\ CHANGES\ AFTER\ THIS\ LINE(.*)/s', $trusted_host_old, $output_array);
|
||||
if (isset($output_array[1][0]) && !empty($output_array[1][0])) {
|
||||
$trusted_host_new.=$output_array[1][0];
|
||||
}
|
||||
preg_match_all('/\#\s*END\ AUTOMATIC\ FILE\.\ ADD\ YOUR\ CHANGES\ AFTER\ THIS\ LINE(.*)/s', $keytable_old, $output_array);
|
||||
if (isset($output_array[1][0]) && !empty($output_array[1][0])) {
|
||||
$keytable_new.=$output_array[1][0];
|
||||
}
|
||||
preg_match_all('/\#\s*END\ AUTOMATIC\ FILE\.\ ADD\ YOUR\ CHANGES\ AFTER\ THIS\ LINE(.*)/s', $signingtable_old, $output_array);
|
||||
if (isset($output_array[1][0]) && !empty($output_array[1][0])) {
|
||||
$signingtable_new.=$output_array[1][0];
|
||||
}
|
||||
|
||||
// Save if there are some diff
|
||||
if ( $trusted_host_new != $trusted_host_old ) {
|
||||
file_put_contents($this->dkim_trusted_host_file, $trusted_host_new);
|
||||
}
|
||||
if ( $keytable_new != $keytable_old ) {
|
||||
file_put_contents($this->dkim_keytable_file, $keytable_new);
|
||||
}
|
||||
if ( $signingtable_new != $signingtable_old ) {
|
||||
file_put_contents($this->dkim_signingtable_file, $signingtable_new);
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
*
|
||||
* @param string $domain
|
||||
* @return string
|
||||
*/
|
||||
function dkim_entry($domain) {
|
||||
$keyfile="/etc/opendkim/keys/$domain/alternc.txt";
|
||||
$domainInfo = $this->get_domain_summary($domain);
|
||||
if (! file_exists($keyfile) && $domainInfo['gesmx'] ) {
|
||||
$this->dkim_generate_key($domain);
|
||||
}
|
||||
return @file_get_contents($keyfile);
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Conditionnal generation autoconfig entry for outlook / thunderbird
|
||||
* If entry with the same name allready exist, skip it.
|
||||
*
|
||||
* @param string $domain
|
||||
* @return string
|
||||
*/
|
||||
function mail_autoconfig_entry($domain) {
|
||||
$zone= implode("\n",$this->conf_from_db($domain))."\n".$this->get_persistent($domain);
|
||||
|
||||
$entry='';
|
||||
$domainInfo = $this->get_domain_summary($domain);
|
||||
if ( $domainInfo['gesmx'] ) {
|
||||
// If we manage the mail
|
||||
|
||||
// Check if there is no the same entry (defined or manual)
|
||||
// can be toto IN A or toto.fqdn.tld. IN A
|
||||
if (! preg_match("/autoconfig(\s|\.".str_replace('.','\.',$domain)."\.)/", $zone )) {
|
||||
$entry.="autoconfig IN CNAME %%fqdn%%.\n";
|
||||
}
|
||||
if (! preg_match("/autodiscover(\s|\.".str_replace('.','\.',$domain)."\.)/", $zone )) {
|
||||
$entry.="autodiscover IN CNAME %%fqdn%%.\n";
|
||||
}
|
||||
} // if gesmx
|
||||
return $entry;
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
*
|
||||
* Return a fully generated zone
|
||||
*
|
||||
* @global string $L_FQDN
|
||||
* @global string $L_NS1_HOSTNAME
|
||||
* @global string $L_NS2_HOSTNAME
|
||||
* @global string $L_DEFAULT_MX
|
||||
* @global string $L_DEFAULT_SECONDARY_MX
|
||||
* @global string $L_PUBLIC_IP
|
||||
* @param string $domain
|
||||
* @return string
|
||||
*/
|
||||
function get_zone($domain) {
|
||||
global $L_FQDN, $L_NS1_HOSTNAME, $L_NS2_HOSTNAME, $L_DEFAULT_MX, $L_DEFAULT_SECONDARY_MX, $L_PUBLIC_IP;
|
||||
|
||||
$zone =$this->get_zone_header();
|
||||
$zone.=implode("\n",$this->conf_from_db($domain));
|
||||
$zone.="\n;;;HOOKED ENTRY\n";
|
||||
|
||||
$zone.= $this->dkim_entry($domain);
|
||||
$zone.= $this->mail_autoconfig_entry($domain);
|
||||
|
||||
$zone.="\n;;; END ALTERNC AUTOGENERATE CONFIGURATION\n";
|
||||
$zone.=$this->get_persistent($domain);
|
||||
$domainInfo = $this->get_domain_summary($domain);
|
||||
|
||||
// FIXME check those vars
|
||||
$zone = strtr($zone, array(
|
||||
"%%fqdn%%"=>"$L_FQDN",
|
||||
"%%ns1%%"=>"$L_NS1_HOSTNAME",
|
||||
"%%ns2%%"=>"$L_NS2_HOSTNAME",
|
||||
"%%DEFAULT_MX%%"=>"$L_DEFAULT_MX",
|
||||
"%%DEFAULT_SECONDARY_MX%%"=>"$L_DEFAULT_SECONDARY_MX",
|
||||
"@@fqdn@@"=>"$L_FQDN",
|
||||
"@@ns1@@"=>"$L_NS1_HOSTNAME",
|
||||
"@@ns2@@"=>"$L_NS2_HOSTNAME",
|
||||
"@@DEFAULT_MX@@"=>"$L_DEFAULT_MX",
|
||||
"@@DEFAULT_SECONDARY_MX@@"=>"$L_DEFAULT_SECONDARY_MX",
|
||||
"@@DOMAINE@@"=>"$domain",
|
||||
"@@SERIAL@@"=>$this->get_serial($domain),
|
||||
"@@PUBLIC_IP@@"=>"$L_PUBLIC_IP",
|
||||
"@@ZONETTL@@"=> $domainInfo['zonettl'],
|
||||
));
|
||||
|
||||
return $zone;
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
*
|
||||
* @param string $domain
|
||||
*/
|
||||
function reload_zone($domain) {
|
||||
exec($this->RNDC." reload ".escapeshellarg($domain), $output, $return_value);
|
||||
if ($return_value != 0 ) {
|
||||
echo "ERROR: Reload zone failed for zone $domain\n";
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* return true if zone is locked
|
||||
*
|
||||
* @param string $domain
|
||||
* @return boolean
|
||||
*/
|
||||
function is_locked($domain) {
|
||||
preg_match_all("/(\;\s*LOCKED:YES)/i", $this->get_zone_file($domain), $output_array);
|
||||
if (isset($output_array[1][0]) && !empty($output_array[1][0])) {
|
||||
return true;
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
*
|
||||
* @global m_mysql $db
|
||||
* @global m_dom $dom
|
||||
* @param string $domain
|
||||
* @return boolean
|
||||
*/
|
||||
function save_zone($domain) {
|
||||
global $db, $dom;
|
||||
|
||||
// Do not save if the zone is LOCKED
|
||||
if ( $this->is_locked($domain)) {
|
||||
$dom->set_dns_result($domain, "The zone file of this domain is locked. Contact your administrator."); // If edit, change dummy_for_translation
|
||||
$dom->set_dns_action($domain, 'OK');
|
||||
return false;
|
||||
}
|
||||
|
||||
// Save file, and apply chmod/chown
|
||||
$file=$this->get_zone_file_uri($domain);
|
||||
file_put_contents($file, $this->get_zone($domain));
|
||||
chown($file, 'bind');
|
||||
chmod($file, 0640);
|
||||
|
||||
$dom->set_dns_action($domain, 'OK');
|
||||
return true; // fixme add tests
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Delete the zone configuration file
|
||||
*
|
||||
* @param string $domain
|
||||
* @return boolean
|
||||
*/
|
||||
function delete_zone($domain) {
|
||||
$file=$this->get_zone_file_uri($domain);
|
||||
if (file_exists($file)) {
|
||||
unlink($file);
|
||||
}
|
||||
$this->dkim_delete($domain);
|
||||
return true;
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
*
|
||||
* @global m_hooks $hooks
|
||||
* @return boolean
|
||||
*/
|
||||
function reload_named() {
|
||||
global $hooks;
|
||||
// Generate the new conf file
|
||||
$new_named_conf="// DO NOT EDIT\n// This file is generated by Alternc.\n// Every changes you'll make will be overwrited.\n";
|
||||
$tpl=file_get_contents($this->NAMED_TEMPLATE);
|
||||
foreach ($this->get_domain_summary() as $domain => $ds ) {
|
||||
if ( ! $ds['gesdns'] || strtoupper($ds['dns_action']) == 'DELETE' ) continue;
|
||||
$new_named_conf.=strtr($tpl, array("@@DOMAINE@@"=>$domain, "@@ZONE_FILE@@"=>$this->get_zone_file_uri($domain)));
|
||||
}
|
||||
|
||||
// Get the actual conf file
|
||||
$old_named_conf = @file_get_contents($this->NAMED_CONF);
|
||||
|
||||
// Apply new configuration only if there are some differences
|
||||
if ($old_named_conf != $new_named_conf ) {
|
||||
file_put_contents($this->NAMED_CONF,$new_named_conf);
|
||||
chown($this->NAMED_CONF, 'bind');
|
||||
chmod($this->NAMED_CONF, 0640);
|
||||
exec($this->RNDC." reconfig");
|
||||
$hooks->invoke_scripts("/usr/lib/alternc/reload.d", array('dns_reconfig') );
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Regenerate bind configuration and load it
|
||||
*
|
||||
* @global m_hooks $hooks
|
||||
* @param boolean $all
|
||||
* @return boolean
|
||||
*/
|
||||
function regenerate_conf($all=false) {
|
||||
global $hooks;
|
||||
|
||||
foreach ($this->get_domain_summary() as $domain => $ds ) {
|
||||
if ( ! $ds['gesdns'] && strtoupper($ds['dns_action']) == 'OK' ) continue; // Skip if we do not manage DNS and is up-to-date for this domain
|
||||
|
||||
if ( (strtoupper($ds['dns_action']) == 'DELETE' ) ||
|
||||
(strtoupper($ds['dns_action']) == 'UPDATE' && $ds['gesdns']==false ) // in case we update the zone to disable DNS management
|
||||
) {
|
||||
$this->delete_zone($domain);
|
||||
continue;
|
||||
}
|
||||
|
||||
if ( ( $all || strtoupper($ds['dns_action']) == 'UPDATE' ) && $ds['gesdns'] ) {
|
||||
$this->save_zone($domain);
|
||||
$hooks->invoke_scripts("/usr/lib/alternc/reload.d", array('dns_reload_zone', $domain) );
|
||||
$this->reload_zone($domain);
|
||||
}
|
||||
} // end foreach domain
|
||||
|
||||
$this->dkim_refresh_list();
|
||||
$this->reload_named();
|
||||
return true;
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
*
|
||||
*/
|
||||
private function dummy_for_translation() {
|
||||
_("The zone file of this domain is locked. Contact your administrator.");
|
||||
}
|
||||
|
||||
|
||||
} /* Class system_bind */
|
||||
|
|
@ -242,6 +242,26 @@ class DB_Sql {
|
|||
return $data;
|
||||
}
|
||||
|
||||
/* pdo equivalent of fetch() */
|
||||
function fetch($mode=PDO::FETCH_ASSOC) {
|
||||
if (!$this->pdo_query) {
|
||||
$this->halt("next_record called with no query pending.");
|
||||
return FALSE;
|
||||
}
|
||||
|
||||
$data = $this->pdo_query->fetch($mode);
|
||||
$this->Errno = $this->pdo_query->errorCode();
|
||||
$this->Error = $this->pdo_query->errorInfo();
|
||||
|
||||
if ($data == FALSE) {
|
||||
if ($this->Auto_Free)
|
||||
$this->free();
|
||||
return FALSE;
|
||||
}
|
||||
|
||||
return $data;
|
||||
}
|
||||
|
||||
/**
|
||||
* table locking
|
||||
*/
|
||||
|
|
|
@ -1245,3 +1245,54 @@ function _dovecot_hash($password) {
|
|||
$hash = _sha512cr($password);
|
||||
return '{SHA512-CRYPT}' . $hash;
|
||||
}
|
||||
|
||||
|
||||
// ------------------------------------------------------------
|
||||
/**
|
||||
* Add the line of text $line into file $file.
|
||||
* do not duplicate (check)
|
||||
* @param $file string the full path to the file where we should add the line
|
||||
* @param $line string the line to add (without the termination \n, WILL BE ADDED)
|
||||
* @return boolean TRUE if the line has been added, or FALSE if the line ALREADY EXISTED
|
||||
*/
|
||||
function add_line_to_file($file,$line) {
|
||||
$f=fopen($file,"rb");
|
||||
$found=false;
|
||||
while($s=fgets($f,1024)) {
|
||||
if (trim($s)==$line) {
|
||||
$found=true;
|
||||
return false;
|
||||
}
|
||||
}
|
||||
fclose($f);
|
||||
$f=fopen($file,"ab");
|
||||
fputs($f,trim($line)."\n");
|
||||
fclose($f);
|
||||
return true;
|
||||
}
|
||||
|
||||
|
||||
// ------------------------------------------------------------
|
||||
/**
|
||||
* Remove the line of text $line from file $file.
|
||||
* @param $file string the full path to the file where we should remove the line
|
||||
* @param $line string the line to add (without the termination \n, WILL BE REMOVED)
|
||||
* @return boolean TRUE if the line has been found and removed, or FALSE if the line DIDN'T EXIST
|
||||
*/
|
||||
function del_line_from_file($file,$line) {
|
||||
$f=fopen($file,"rb");
|
||||
$g=fopen($file.".new","wb");
|
||||
$found=false;
|
||||
while($s=fgets($f,1024)) {
|
||||
if (trim($s)!=$line) {
|
||||
fputs($g,$s);
|
||||
} else {
|
||||
$found=true;
|
||||
}
|
||||
}
|
||||
fclose($f);
|
||||
fclose($g);
|
||||
rename($file.".new",$file); // overwrite atomically
|
||||
return $found;
|
||||
}
|
||||
|
||||
|
|
|
@ -241,7 +241,7 @@ class m_action {
|
|||
* @global m_messages $msg
|
||||
* @global m_mysql $db
|
||||
* @param type $all
|
||||
* @return boolean
|
||||
* @return boolean|int The number of rows purged; False is there was an error
|
||||
*/
|
||||
function purge($all = null) {
|
||||
global $msg, $db;
|
||||
|
|
|
@ -0,0 +1,185 @@
|
|||
<?php
|
||||
|
||||
/*
|
||||
----------------------------------------------------------------------
|
||||
LICENSE
|
||||
|
||||
This program is free software; you can redistribute it and/or
|
||||
modify it under the terms of the GNU General Public License (GPL)
|
||||
as published by the Free Software Foundation; either version 2
|
||||
of the License, or (at your option) any later version.
|
||||
|
||||
This program is distributed in the hope that it will be useful,
|
||||
but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
GNU General Public License for more details.
|
||||
|
||||
To read the license please visit http://www.gnu.org/copyleft/gpl.html
|
||||
----------------------------------------------------------------------
|
||||
*/
|
||||
|
||||
/**
|
||||
* Manages APACHE 2.4+ vhosts templates in AlternC 3.5+
|
||||
*
|
||||
* @copyright AlternC-Team 2000-2018 https://alternc.com/
|
||||
*/
|
||||
class m_apache {
|
||||
|
||||
var $shouldreload;
|
||||
|
||||
// only values allowed for https in subdomaines table.
|
||||
var $httpsmodes=array("http","https","both");
|
||||
|
||||
// Slave AlternC instances can know the last reload time thanks to this
|
||||
var $reloadfile="/run/alternc/apache-reload";
|
||||
// Where do we find apache template files ?
|
||||
var $templatedir="/etc/alternc/templates/apache2";
|
||||
// Where do we store all Apache vhosts ?
|
||||
var $vhostroot="/var/lib/alternc/apache-vhost/";
|
||||
|
||||
// launched before any action by updatedomains
|
||||
function hook_updatedomains_web_pre() {
|
||||
$this->shouldreload=false;
|
||||
}
|
||||
|
||||
// launched for each FQDN for which we want a new vhost template
|
||||
function hook_updatedomains_web_add($subdomid) {
|
||||
global $msg,$db,$ssl,$L_FQDN;
|
||||
|
||||
$db->query("SELECT sd.*, dt.only_dns, dt.has_https_option, m.login FROM domaines_type dt, sub_domaines sd LEFT JOIN membres m ON m.uid=sd.compte WHERE dt.name=sd.type AND sd.web_action!='OK' AND id=?;",array($subdomid));
|
||||
$db->next_record();
|
||||
$subdom=$db->Record;
|
||||
|
||||
// security : only AlternC account's UIDs
|
||||
if ($subdom["compte"]<1999) {
|
||||
$msg->raise("ERROR","apache","Subdom ".$subdom["id"]." for domain ".$subdom["sub"].".".$subdom["domaine"]." has id ".$subdom["compte"].". Skipped");
|
||||
return 1;
|
||||
}
|
||||
|
||||
// search for the template file:
|
||||
$template = $this->templatedir."/".strtolower($subdom["type"]);
|
||||
if ($subdom["has_https_option"] && in_array($subdom["https"],$this->httpsmodes)) {
|
||||
$template.="-".$subdom["https"];
|
||||
}
|
||||
$template.=".conf";
|
||||
if (!is_file($template)) {
|
||||
$msg->raise("ERROR","apache","Template $template not found for subdom ".$subdom["id"]." for domain ".$subdom["sub"].".".$subdom["domaine"].". Skipped");
|
||||
return 1;
|
||||
}
|
||||
|
||||
$subdom["fqdn"]=$subdom["sub"].(($subdom["sub"])?".":"").$subdom["domaine"];
|
||||
// SSL information $subdom["certificate_id"] may be ZERO => it means "take id 0 which is snakeoil cert"
|
||||
$cert = $ssl->get_certificate_path($subdom["certificate_id"]);
|
||||
if ($cert["chain"]) {
|
||||
$chainline="SSLCertificateChainFile ".$cert["chain"];
|
||||
} else {
|
||||
$chainline="";
|
||||
}
|
||||
// Replace needed vars in template file
|
||||
$tpl=file_get_contents($template);
|
||||
$tpl = strtr($tpl, array(
|
||||
"%%LOGIN%%" => $subdom['login'],
|
||||
"%%fqdn%%" => $subdom['fqdn'],
|
||||
"%%document_root%%" => getuserpath($subdom['login']) . $subdom['valeur'],
|
||||
"%%account_root%%" => getuserpath($subdom['login']),
|
||||
"%%redirect%%" => $subdom['valeur'],
|
||||
"%%UID%%" => $subdom['compte'],
|
||||
"%%GID%%" => $subdom['compte'],
|
||||
"%%mail_account%%" => $subdom['login']."@".$L_FQDN,
|
||||
"%%user%%" => "FIXME",
|
||||
"%%CRT%%" => $cert["cert"],
|
||||
"%%KEY%%" => $cert["key"],
|
||||
"%%CHAINLINE%%" => $chainline,
|
||||
));
|
||||
// and write the template
|
||||
$confdir = $this->vhostroot."/".substr($subdom["compte"],-1)."/".$subdom["compte"];
|
||||
@mkdir($confdir,0755,true);
|
||||
file_put_contents($confdir."/".$subdom["fqdn"].".conf",$tpl);
|
||||
$this->shouldreload=true;
|
||||
|
||||
return 0; // shell meaning => OK ;)
|
||||
} // hook_updatedomains_web_add
|
||||
|
||||
|
||||
// ------------------------------------------------------------
|
||||
/**
|
||||
* launched for each FQDN for which we want to delete a vhost template
|
||||
*/
|
||||
function hook_updatedomains_web_del($subdomid) {
|
||||
global $db,$msg;
|
||||
$db->query("SELECT sd.*, dt.only_dns, dt.has_https_option, m.login FROM domaines_type dt, sub_domaines sd LEFT JOIN membres m ON m.uid=sd.compte WHERE dt.name=sd.type AND sd.web_action!='OK' AND id=?;",array($subdomid));
|
||||
$db->next_record();
|
||||
$subdom=$db->Record;
|
||||
$confdir = $this->vhostroot."/".substr($subdom["compte"],-1)."/".$subdom["compte"];
|
||||
$deleteme= $subdom["sub"].(($subdom["sub"])?".":"").$subdom["domaine"].".conf";
|
||||
@unlink($confdir."/".$deleteme);
|
||||
$this->shouldreload=true;
|
||||
}
|
||||
|
||||
|
||||
// ------------------------------------------------------------
|
||||
/**
|
||||
* launched at the very end of updatedomains
|
||||
*/
|
||||
function hook_updatedomains_web_post() {
|
||||
global $msg;
|
||||
if ($this->shouldreload) {
|
||||
|
||||
// concatenate all files into one
|
||||
$this->concat();
|
||||
|
||||
// reload apache
|
||||
$ret=0;
|
||||
exec("apache2ctl graceful 2>&1",$out,$ret);
|
||||
touch($this->reloadfile);
|
||||
if ($ret!=0) {
|
||||
$msg->raise("ERROR","apache","Error while reloading apache, error code is $ret\n".implode("\n",$out));
|
||||
} else {
|
||||
$msg->raise("INFO","apache","Apache reloaded");
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
// ------------------------------------------------------------
|
||||
/**
|
||||
* Concatenate all files under $this->vhostroot
|
||||
* into one (mindepth=2 though),
|
||||
* this function is faster than any shell stuff :D
|
||||
*/
|
||||
private function concat() {
|
||||
global $msg;
|
||||
$d=opendir($this->vhostroot);
|
||||
$f=fopen($this->vhostroot."/vhosts_all.conf.new","wb");
|
||||
if (!$f) {
|
||||
$msg->raise("FATAL","apache","Can't write vhosts_all file");
|
||||
return false;
|
||||
}
|
||||
while (($c=readdir($d))!==false) {
|
||||
if (substr($c,0,1)!="." && is_dir($this->vhostroot."/".$c)) {
|
||||
$this->subconcat($f,$this->vhostroot."/".$c);
|
||||
}
|
||||
}
|
||||
closedir($d);
|
||||
fclose($f);
|
||||
rename($this->vhostroot."/vhosts_all.conf.new", $this->vhostroot."/vhosts_all.conf");
|
||||
}
|
||||
|
||||
private function subconcat($f,$root) {
|
||||
// recursive cat :)
|
||||
$d=opendir($root);
|
||||
while (($c=readdir($d))!==false) {
|
||||
if (substr($c,0,1)!=".") {
|
||||
if (is_dir($root."/".$c)) {
|
||||
$this->subconcat($f,$root."/".$c); // RECURSIVE CALL
|
||||
}
|
||||
if (is_file($root."/".$c)) {
|
||||
fputs($f,file_get_contents($root."/".$c)."\n");
|
||||
}
|
||||
}
|
||||
}
|
||||
closedir($d);
|
||||
}
|
||||
|
||||
} // m_apache
|
||||
|
|
@ -0,0 +1,238 @@
|
|||
<?php
|
||||
|
||||
/*
|
||||
----------------------------------------------------------------------
|
||||
LICENSE
|
||||
|
||||
This program is free software; you can redistribute it and/or
|
||||
modify it under the terms of the GNU General Public License (GPL)
|
||||
as published by the Free Software Foundation; either version 2
|
||||
of the License, or (at your option) any later version.
|
||||
|
||||
This program is distributed in the hope that it will be useful,
|
||||
but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
GNU General Public License for more details.
|
||||
|
||||
To read the license please visit http://www.gnu.org/copyleft/gpl.html
|
||||
----------------------------------------------------------------------
|
||||
*/
|
||||
|
||||
/**
|
||||
* Manages BIND 9+ zone management templates in AlternC 3.5+
|
||||
*
|
||||
* @copyright AlternC-Team 2000-2018 https://alternc.com/
|
||||
*/
|
||||
class m_bind {
|
||||
|
||||
var $shouldreload;
|
||||
var $shouldreconfig;
|
||||
|
||||
var $ZONE_TEMPLATE ="/etc/alternc/templates/bind/templates/zone.template";
|
||||
var $NAMED_TEMPLATE ="/etc/alternc/templates/bind/templates/named.template";
|
||||
var $NAMED_CONF ="/var/lib/alternc/bind/automatic.conf";
|
||||
var $RNDC ="/usr/sbin/rndc";
|
||||
|
||||
var $zone_file_directory = '/var/lib/alternc/bind/zones';
|
||||
|
||||
// ------------------------------------------------------------
|
||||
/** Hook launched before any action by updatedomains
|
||||
* initialize the reload/reconfig flags used by POST
|
||||
* @NOTE launched as ROOT
|
||||
*/
|
||||
function hook_updatedomains_dns_pre() {
|
||||
$this->shouldreload=false;
|
||||
$this->shouldreconfig=false;
|
||||
}
|
||||
|
||||
|
||||
// ------------------------------------------------------------
|
||||
/**
|
||||
* Hook launched for each ZONE for which we want a zone update (or create)
|
||||
* update the zone, create it if necessary,
|
||||
* and ask for reload or reconfig of bind9 depending on what happened
|
||||
* @NOTE launched as ROOT
|
||||
*/
|
||||
function hook_updatedomains_dns_add($dominfo) {
|
||||
global $L_FQDN,$L_NS1_HOSTNAME,$L_NS2_HOSTNAME,$L_DEFAULT_MX,$L_DEFAULT_SECONDARY_MX,$L_PUBLIC_IP,$L_PUBLIC_IPV6;
|
||||
|
||||
$domain = $dominfo["domaine"];
|
||||
$ttl = $dominfo["zonettl"];
|
||||
|
||||
// does it already exist?
|
||||
if (file_exists($this->zone_file_directory."/".$domain)) {
|
||||
list($islocked,$serial,$more)=$this->read_zone($domain);
|
||||
$serial++; // only increment serial for new zones
|
||||
} else {
|
||||
$more="";
|
||||
$serial=date("Ymd")."00";
|
||||
$islocked=false;
|
||||
}
|
||||
if ($islocked) return;
|
||||
|
||||
// Prepare a new zonefile from a template
|
||||
$zone = file_get_contents($this->ZONE_TEMPLATE);
|
||||
|
||||
// add the SUBDOMAIN entries
|
||||
$zone .= $this->conf_from_db($domain);
|
||||
|
||||
// substitute ALTERNC & domain variables
|
||||
$zone = strtr($zone, array(
|
||||
"%%fqdn%%" => "$L_FQDN",
|
||||
"%%ns1%%" => "$L_NS1_HOSTNAME",
|
||||
"%%ns2%%" => "$L_NS2_HOSTNAME",
|
||||
"%%DEFAULT_MX%%" => "$L_DEFAULT_MX",
|
||||
"%%DEFAULT_SECONDARY_MX%%" => "$L_DEFAULT_SECONDARY_MX",
|
||||
"@@fqdn@@" => "$L_FQDN",
|
||||
"@@ns1@@" => "$L_NS1_HOSTNAME",
|
||||
"@@ns2@@" => "$L_NS2_HOSTNAME",
|
||||
"@@DEFAULT_MX@@" => "$L_DEFAULT_MX",
|
||||
"@@DEFAULT_SECONDARY_MX@@" => "$L_DEFAULT_SECONDARY_MX",
|
||||
"@@DOMAINE@@" => $domain,
|
||||
"@@SERIAL@@" => $serial,
|
||||
"@@PUBLIC_IP@@" => "$L_PUBLIC_IP",
|
||||
"@@PUBLIC_IPV6@@" => "$L_PUBLIC_IPV6",
|
||||
"@@ZONETTL@@" => $ttl,
|
||||
));
|
||||
|
||||
// add the "END ALTERNC CONF line";
|
||||
$zone .= ";;; END ALTERNC AUTOGENERATE CONFIGURATION\n";
|
||||
|
||||
// add the manually entered info:
|
||||
$zone .= $more;
|
||||
file_put_contents($this->zone_file_directory."/".$domain,$zone);
|
||||
|
||||
// add the line into bind9 conf:
|
||||
if (add_line_to_file(
|
||||
$this->NAMED_CONF,
|
||||
trim(strtr(
|
||||
file_get_contents($this->NAMED_TEMPLATE),
|
||||
array(
|
||||
"@@DOMAIN@@" => $domain,
|
||||
"@@ZONE_FILE@@" => $this->zone_file_directory."/".$domain
|
||||
)
|
||||
)))
|
||||
) {
|
||||
$this->shouldreconfig=true;
|
||||
} else {
|
||||
$this->shouldreload=true;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
// ------------------------------------------------------------
|
||||
/**
|
||||
* Hook launched for each ZONE for which we want a zone DELETE
|
||||
* remove the zone and its file,
|
||||
* and if any action happened, ask for bind RECONFIG at posttime
|
||||
* @NOTE launched as ROOT
|
||||
*/
|
||||
function hook_updatedomains_dns_del($dominfo) {
|
||||
$domain = $dominfo["domaine"];
|
||||
if (del_line_from_file(
|
||||
$this->NAMED_CONF,
|
||||
trim(strtr(
|
||||
file_get_contents($this->NAMED_TEMPLATE),
|
||||
array(
|
||||
"@@DOMAIN@@" => $domain,
|
||||
"@@ZONE_FILE@@" => $this->zone_file_directory."/".$domain
|
||||
)
|
||||
)))
|
||||
) {
|
||||
$this->shouldreconfig=true;
|
||||
} else {
|
||||
return;
|
||||
}
|
||||
@unlink($this->zone_file_directory."/".$domain);
|
||||
}
|
||||
|
||||
|
||||
// ------------------------------------------------------------
|
||||
/**
|
||||
* Hook function launched at the very end of updatedomains
|
||||
* here, we just reload OR reconfig (or both) bind9 depending
|
||||
* on what happened before.
|
||||
* @NOTE launched as ROOT
|
||||
*/
|
||||
function hook_updatedomains_dns_post() {
|
||||
global $msg;
|
||||
if ($this->shouldreload) {
|
||||
$ret=0;
|
||||
exec($this->RNDC." reload 2>&1",$out,$ret);
|
||||
if ($ret!=0) {
|
||||
$msg->raise("ERROR","bind","Error while reloading bind, error code is $ret\n".implode("\n",$out));
|
||||
} else {
|
||||
$msg->raise("INFO","bind","Bind reloaded");
|
||||
}
|
||||
}
|
||||
if ($this->shouldreconfig) {
|
||||
$ret=0;
|
||||
exec($this->RNDC." reconfig 2>&1",$out,$ret);
|
||||
if ($ret!=0) {
|
||||
$msg->raise("ERROR","bind","Error while reconfiguring bind, error code is $ret\n".implode("\n",$out));
|
||||
} else {
|
||||
$msg->raise("INFO","bind","Bind reconfigured");
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
// ------------------------------------------------------------
|
||||
/**
|
||||
* read a zone file for $domain,
|
||||
* @param $domain string the domain name
|
||||
* @return array with 3 informations:
|
||||
* is the domain locked? (boolean), what's the current serial (integer), the data after alternc conf (string of lines)
|
||||
*/
|
||||
function read_zone($domain) {
|
||||
$f=fopen($this->zone_file_directory."/".$domain,"rb");
|
||||
$islocked=false;
|
||||
$more="";
|
||||
$serial=date("Ymd")."00";
|
||||
while ($s=fgets($f,4096)) {
|
||||
if (preg_match("#\;\s*LOCKED:YES#i",$s)) {
|
||||
$islocked=true;
|
||||
}
|
||||
if (preg_match("/\s*(\d{10})\s+\;\sserial\s?/", $s,$mat)) {
|
||||
$serial=$mat[1];
|
||||
}
|
||||
if (preg_match('/\;\s*END\sALTERNC\sAUTOGENERATE\sCONFIGURATION(.*)/s', $s)) {
|
||||
break;
|
||||
}
|
||||
}
|
||||
while ($s=fgets($f,4096)) {
|
||||
$more.=$s;
|
||||
}
|
||||
return array($islocked,$serial,$more);
|
||||
}
|
||||
|
||||
|
||||
// ------------------------------------------------------------
|
||||
/**
|
||||
* Return the part of the conf we got from the sub_domaines table
|
||||
* @global m_mysql $db
|
||||
* @param string $domain
|
||||
* @return string a zonefile excerpt
|
||||
*/
|
||||
function conf_from_db($domain) {
|
||||
global $db;
|
||||
$db->query("
|
||||
SELECT
|
||||
REPLACE(REPLACE(dt.entry,'%TARGET%',sd.valeur), '%SUB%', if(length(sd.sub)>0,sd.sub,'@')) AS ENTRY
|
||||
FROM
|
||||
sub_domaines sd,
|
||||
domaines_type dt
|
||||
WHERE
|
||||
sd.type=dt.name
|
||||
AND sd.enable IN ('ENABLE', 'ENABLED')
|
||||
ORDER BY ENTRY ;");
|
||||
$t="";
|
||||
while ($db->next_record()) {
|
||||
$t.= $db->f('ENTRY')."\n";
|
||||
}
|
||||
return $t;
|
||||
}
|
||||
|
||||
|
||||
} // m_bind
|
||||
|
|
@ -54,15 +54,7 @@ class m_dom {
|
|||
* du domaine par update_domains.sh
|
||||
* @access private
|
||||
*/
|
||||
var $fic_lock_cron = "/run/alternc/cron.lock";
|
||||
|
||||
/**
|
||||
* Le cron a-t-il été bloqué ?
|
||||
* Il faut appeler les fonctions privées lock et unlock entre les
|
||||
* appels aux domaines.
|
||||
* @access private
|
||||
*/
|
||||
var $islocked = false;
|
||||
const fic_lock_cron = "/run/alternc/cron.lock";
|
||||
|
||||
var $type_local = "VHOST";
|
||||
var $type_url = "URL";
|
||||
|
@ -84,9 +76,10 @@ class m_dom {
|
|||
* Constructeur
|
||||
*/
|
||||
function m_dom() {
|
||||
global $L_FQDN;
|
||||
global $L_FQDN, $domislocked;
|
||||
$this->tld_no_check_at_all = variable_get('tld_no_check_at_all', 0, 'Disable ALL check on the TLD (users will be able to add any domain)', array('desc' => 'Disabled', 'type' => 'boolean'));
|
||||
variable_get('mailname_bounce', $L_FQDN, 'FQDN of the mail server, used to create vhost virtual mail_adress.', array('desc' => 'FQDN', 'type' => 'string'));
|
||||
$domislocked=false;
|
||||
}
|
||||
|
||||
|
||||
|
@ -642,35 +635,35 @@ class m_dom {
|
|||
* @param string $dom nom de domaine é effacer
|
||||
* @return boolean Retourne FALSE si une erreur s'est produite, TRUE sinon.
|
||||
*/
|
||||
function del_domain($dom) {
|
||||
function del_domain($domain) {
|
||||
global $db, $msg, $hooks;
|
||||
$msg->log("dom", "del_domain", $dom);
|
||||
$dom = strtolower($dom);
|
||||
$msg->log("dom", "del_domain", $domain);
|
||||
$domain = strtolower($domain);
|
||||
|
||||
$this->lock();
|
||||
if (!$r = $this->get_domain_all($dom)) {
|
||||
if (!$r = $this->get_domain_all($domain)) {
|
||||
return false;
|
||||
}
|
||||
$this->unlock();
|
||||
|
||||
// Call Hooks to delete the domain and the MX management:
|
||||
// TODO : the 2 calls below are using an OLD hook call, FIXME: remove them when unused
|
||||
$hooks->invoke("alternc_del_domain", array($dom));
|
||||
$hooks->invoke("alternc_del_mx_domain", array($dom));
|
||||
$hooks->invoke("alternc_del_domain", array($domain));
|
||||
$hooks->invoke("alternc_del_mx_domain", array($domain));
|
||||
// New hook calls:
|
||||
$hooks->invoke("hook_dom_del_domain", array($r["id"]));
|
||||
$hooks->invoke("hook_dom_del_mx_domain", array($r["id"]));
|
||||
|
||||
// Now mark the domain for deletion:
|
||||
$db->query("UPDATE sub_domaines SET web_action='DELETE' WHERE domaine= ?;", array($dom));
|
||||
$this->set_dns_action($dom, 'DELETE');
|
||||
$db->query("UPDATE sub_domaines SET web_action='DELETE' WHERE domaine= ?;", array($domain));
|
||||
$this->set_dns_action($domain, 'DELETE');
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
|
||||
function domshort($dom, $sub = "") {
|
||||
return str_replace("-", "", str_replace(".", "", empty($sub) ? "" : "$sub.") . $dom);
|
||||
function domshort($domain, $sub = "") {
|
||||
return str_replace("-", "", str_replace(".", "", empty($sub) ? "" : "$sub.") . $domain);
|
||||
}
|
||||
|
||||
|
||||
|
@ -694,11 +687,11 @@ class m_dom {
|
|||
* @return boolean Retourne FALSE si une erreur s'est produite, TRUE sinon.
|
||||
*/
|
||||
function add_domain($domain, $dns, $noerase = false, $force = false, $isslave = false, $slavedom = "") {
|
||||
global $db, $msg, $quota, $L_FQDN, $tld, $cuid, $hooks;
|
||||
global $db, $msg, $quota, $L_FQDN, $tld, $cuid, $hooks, $domislocked;
|
||||
$msg->log("dom", "add_domain", $domain);
|
||||
|
||||
// Locked ?
|
||||
if (!$this->islocked) {
|
||||
if (!$domislocked) {
|
||||
$msg->raise("ERROR", "dom", _("--- Program error --- No lock on the domains!"));
|
||||
return false;
|
||||
}
|
||||
|
@ -1037,10 +1030,10 @@ class m_dom {
|
|||
*
|
||||
*/
|
||||
function get_domain_all($dom) {
|
||||
global $db, $msg, $cuid;
|
||||
global $db, $msg, $cuid, $domislocked;
|
||||
$msg->debug("dom", "get_domain_all", $dom);
|
||||
// Locked ?
|
||||
if (!$this->islocked) {
|
||||
if (!$domislocked) {
|
||||
$msg->raise("ERROR", "dom", _("--- Program error --- No lock on the domains!"));
|
||||
return false;
|
||||
}
|
||||
|
@ -1072,13 +1065,14 @@ class m_dom {
|
|||
$db->query("SELECT sd.*, dt.description AS type_desc, dt.only_dns, dt.advanced, dt.has_https_option FROM sub_domaines sd LEFT JOIN domaines_type dt on UPPER(dt.name)=UPPER(sd.type) WHERE compte= ? AND domaine= ? ORDER BY dt.advanced,sd.sub,sd.type ;", array($cuid, $dom));
|
||||
// Pas de webmail, on le cochera si on le trouve.
|
||||
$r["sub"] = array();
|
||||
$data = $db->fetchAll();
|
||||
foreach($data as $i=>$record) {
|
||||
$i=0;
|
||||
while ($record=$db->fetch()) {
|
||||
$r["sub"][$i] = $record;
|
||||
// FIXME : replace sub by name and dest by valeur in the code that exploits this function :
|
||||
$r["sub"][$i]["name"] = $record["sub"];
|
||||
$r["sub"][$i]["dest"] = $record["valeur"];
|
||||
$r["sub"][$i]["fqdn"] = ((!empty($r["sub"][$i]["name"])) ? $r["sub"][$i]["name"] . "." : "") . $r["name"];
|
||||
$i++;
|
||||
}
|
||||
$db->free();
|
||||
return $r;
|
||||
|
@ -1098,10 +1092,10 @@ class m_dom {
|
|||
* Retourne FALSE si une erreur s'est produite.
|
||||
*/
|
||||
function get_sub_domain_all($sub_domain_id) {
|
||||
global $db, $msg, $cuid;
|
||||
global $db, $msg, $cuid, $domislocked;
|
||||
$msg->debug("dom", "get_sub_domain_all", $sub_domain_id);
|
||||
// Locked ?
|
||||
if (!$this->islocked) {
|
||||
if (!$domislocked) {
|
||||
$msg->raise("ERROR", "dom", _("--- Program error --- No lock on the domains!"));
|
||||
return false;
|
||||
}
|
||||
|
@ -1263,10 +1257,10 @@ class m_dom {
|
|||
* @return boolean true if the preference has been set
|
||||
*/
|
||||
function set_subdomain_ssl_provider($sub_domain_id,$provider) {
|
||||
global $db, $msg, $cuid, $ssl;
|
||||
global $db, $msg, $cuid, $ssl, $domislocked;
|
||||
$msg->log("dom", "set_sub_domain_ssl_provider", $sub_domain_id." / ".$provider);
|
||||
// Locked ?
|
||||
if (!$this->islocked) {
|
||||
if (!$domislocked) {
|
||||
$msg->raise("ERROR", "dom", _("--- Program error --- No lock on the domains!"));
|
||||
return false;
|
||||
}
|
||||
|
@ -1308,13 +1302,14 @@ class m_dom {
|
|||
* de $type (url, ip, dossier...)
|
||||
* @param string $https the HTTPS behavior : HTTP(redirect https to http),
|
||||
* HTTPS(redirect http to https) or BOTH (both hosted at the same place)
|
||||
* or nothing "" when not applicable for this domain type.
|
||||
* @return boolean Retourne FALSE si une erreur s'est produite, TRUE sinon.
|
||||
*/
|
||||
function set_sub_domain($dom, $sub, $type, $dest, $sub_domain_id = 0, $https) {
|
||||
global $db, $msg, $cuid, $bro;
|
||||
function set_sub_domain($dom, $sub, $type, $dest, $sub_domain_id = 0, $https="") {
|
||||
global $db, $msg, $cuid, $bro, $domislocked;
|
||||
$msg->log("dom", "set_sub_domain", $dom . "/" . $sub . "/" . $type . "/" . $dest);
|
||||
// Locked ?
|
||||
if (!$this->islocked) {
|
||||
if (!$domislocked) {
|
||||
$msg->raise("ERROR", "dom", _("--- Program error --- No lock on the domains!"));
|
||||
return false;
|
||||
}
|
||||
|
@ -1396,10 +1391,10 @@ class m_dom {
|
|||
*
|
||||
*/
|
||||
function del_sub_domain($sub_domain_id) {
|
||||
global $db, $msg;
|
||||
global $db, $msg, $domislocked;
|
||||
$msg->log("dom", "del_sub_domain", $sub_domain_id);
|
||||
// Locked ?
|
||||
if (!$this->islocked) {
|
||||
if (!$domislocked) {
|
||||
$msg->raise("ERROR", "dom", _("--- Program error --- No lock on the domains!"));
|
||||
return false;
|
||||
}
|
||||
|
@ -1442,11 +1437,11 @@ class m_dom {
|
|||
* TRUE sinon.
|
||||
*
|
||||
*/
|
||||
function edit_domain($dom, $dns, $gesmx, $force = false, $ttl = 86400) {
|
||||
global $db, $msg, $hooks;
|
||||
function edit_domain($dom, $dns, $gesmx, $force = false, $ttl = 3600) {
|
||||
global $db, $msg, $hooks, $domislocked;
|
||||
$msg->log("dom", "edit_domain", $dom . "/" . $dns . "/" . $gesmx);
|
||||
// Locked ?
|
||||
if (!$this->islocked && !$force) {
|
||||
if (!$domislocked && !$force) {
|
||||
$msg->raise("ERROR", "dom", _("--- Program error --- No lock on the domains!"));
|
||||
return false;
|
||||
}
|
||||
|
@ -1765,15 +1760,20 @@ class m_dom {
|
|||
* @access private
|
||||
*/
|
||||
function lock() {
|
||||
global $msg;
|
||||
global $msg,$domislocked;
|
||||
$msg->debug("dom", "lock");
|
||||
if ($this->islocked) {
|
||||
if ($domislocked) {
|
||||
$msg->raise("ERROR", "dom", _("--- Program error --- Lock already obtained!"));
|
||||
}
|
||||
while (file_exists($this->fic_lock_cron)) {
|
||||
// wait for the file to disappear, or at most 15min:
|
||||
while (file_exists(m_dom::fic_lock_cron) && filemtime(m_dom::fic_lock_cron)>(time()-900)) {
|
||||
clearstatcache();
|
||||
sleep(2);
|
||||
}
|
||||
$this->islocked = true;
|
||||
@touch(m_dom::fic_lock_cron);
|
||||
$domislocked = true;
|
||||
// extra safe :
|
||||
register_shutdown_function(array("m_dom","unlock"),1);
|
||||
return true;
|
||||
}
|
||||
|
||||
|
@ -1783,13 +1783,15 @@ class m_dom {
|
|||
* return true
|
||||
* @access private
|
||||
*/
|
||||
function unlock() {
|
||||
global $msg;
|
||||
function unlock($isshutdown=0) {
|
||||
global $msg,$domislocked;
|
||||
$msg->debug("dom", "unlock");
|
||||
if (!$this->islocked) {
|
||||
if (!$isshutdown && !$domislocked) {
|
||||
$msg->raise("ERROR", "dom", _("--- Program error --- No lock on the domains!"));
|
||||
}
|
||||
$this->islocked = false;
|
||||
// don't use $this since we may be called by register_shutdown_function out of an object instance.
|
||||
@unlink(m_dom::fic_lock_cron);
|
||||
$domislocked = false;
|
||||
return true;
|
||||
}
|
||||
|
||||
|
@ -1892,199 +1894,103 @@ class m_dom {
|
|||
|
||||
|
||||
/**
|
||||
* Return an array with all the needed parameters to generate conf
|
||||
* of a vhost.
|
||||
* If no parameters, return the parameters for ALL the vhost.
|
||||
* Optionnal parameters: id of the sub_domaines
|
||||
* */
|
||||
function generation_parameters($id = null, $only_apache = true) {
|
||||
global $db, $msg;
|
||||
$msg->log("dom", "generation_parameters");
|
||||
$params = "";
|
||||
/** 2016_05_18 : this comments was here before escaping the request... is there still something to do here ?
|
||||
* // BUG BUG BUG FIXME
|
||||
* // Suppression de comptes -> membres existe pas -> domaines a supprimer ne sont pas lister
|
||||
*/
|
||||
$query = "
|
||||
select
|
||||
sd.id as sub_id,
|
||||
lower(sd.type) as type,
|
||||
m.login,
|
||||
m.uid as uid,
|
||||
if(length(sd.sub)>0,concat_ws('.',sd.sub,sd.domaine),sd.domaine) as fqdn,
|
||||
concat_ws('@',m.login,v.value) as mail,
|
||||
sd.valeur
|
||||
from
|
||||
sub_domaines sd left join membres m on sd.compte=m.uid,
|
||||
variable v,
|
||||
domaines_type dt
|
||||
where
|
||||
v.name='mailname_bounce'
|
||||
and lower(dt.name) = lower(sd.type)";
|
||||
$query_args = array();
|
||||
|
||||
if (!is_null($id) && intval($id) == $id) {
|
||||
$query .= " AND sd.id = ? ";
|
||||
array_push($query_args, intval($id));
|
||||
}
|
||||
if ($only_apache) {
|
||||
$query .=" and dt.only_dns is false ";
|
||||
* complex process to manage domain and subdomain updates
|
||||
* Launched every minute by a cron as root
|
||||
* should launch hooks for each domain or subdomain,
|
||||
* so that apache & bind could do their job
|
||||
*/
|
||||
function update_domains() {
|
||||
global $db, $hooks;
|
||||
if (posix_getuid()!=0) {
|
||||
echo "FATAL: please lauch me as root\n";
|
||||
exit();
|
||||
}
|
||||
|
||||
$query .= "
|
||||
order by
|
||||
m.login,
|
||||
sd.domaine,
|
||||
sd.sub;";
|
||||
$this->lock();
|
||||
|
||||
// fix in case we forgot to delete SUBDOMAINS before deleting a DOMAIN
|
||||
$db->query("UPDATE sub_domaines sd, domaines d SET sd.web_action = 'DELETE' WHERE sd.domaine = d.domaine AND sd.compte=d.compte AND d.dns_action = 'DELETE';");
|
||||
|
||||
$db->query($query, $query_args);
|
||||
|
||||
$r = array();
|
||||
// Search for things to do on DOMAINS:
|
||||
$db->query("SELECT * FROM domaines WHERE dns_action!='OK';");
|
||||
$alldoms=array();
|
||||
while ($db->next_record()) {
|
||||
$r[$db->Record['sub_id']] = $db->Record;
|
||||
$alldoms[$db->Record["id"]]=$db->Record;
|
||||
}
|
||||
return $r;
|
||||
}
|
||||
// now launch hooks
|
||||
if (count($alldoms)) {
|
||||
$hooks->invoke("hook_updatedomains_dns_pre");
|
||||
foreach($alldoms as $id=>$onedom) {
|
||||
if ($onedom["gesdns"]==0 || $onedom["dns_action"]=="DELETE") {
|
||||
$ret = $hooks->invoke("hook_updatedomains_dns_del",array($onedom));
|
||||
} else {
|
||||
$ret = $hooks->invoke("hook_updatedomains_dns_add",array($onedom));
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Return an array with all informations of the domains_type
|
||||
* used to generate Apache conf.
|
||||
* Die if templates missing.
|
||||
* Warning: an Apache domains_type must have 'only_dns' == TRUE
|
||||
*
|
||||
* */
|
||||
function generation_domains_type() {
|
||||
global $dom;
|
||||
$d = array();
|
||||
foreach ($dom->domains_type_lst() as $k => $v) {
|
||||
if ($v['only_dns'] == true) {
|
||||
continue;
|
||||
if ($onedom["dns_action"]=="DELETE") {
|
||||
$db->query("DELETE FROM domaines WHERE domaine=?;",array($onedom));
|
||||
} else {
|
||||
// we keep the highest result returned by hooks...
|
||||
rsort($ret,SORT_NUMERIC); $returncode=$ret[0];
|
||||
$db->query("UPDATE domaines SET dns_result=?, dns_action='OK' WHERE domaine=?;",array($returncode,$onedom["domaine"]));
|
||||
}
|
||||
}
|
||||
if (!$j = file_get_contents(ALTERNC_APACHE2_GEN_TMPL_DIR . '/' . strtolower($k) . '.conf')) {
|
||||
die("Error: missing file for $k");
|
||||
}
|
||||
$d[$k] = $v;
|
||||
$d[$k]['tpl'] = $j;
|
||||
}
|
||||
return $d;
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Launch old fashionned hooks as there was in AlternC 1.0
|
||||
* @TODO: do we still need that?
|
||||
*/
|
||||
function generate_conf_oldhook($action, $lst_sub, $sub_obj = null) {
|
||||
if (is_null($sub_obj)) {
|
||||
$sub_obj = $this->generation_parameters(null, false);
|
||||
}
|
||||
if (!isset($lst_sub[strtoupper($action)]) || empty($lst_sub[strtoupper($action)])) {
|
||||
return false;
|
||||
$hooks->invoke("hook_updatedomains_dns_post");
|
||||
}
|
||||
|
||||
$lst_by_type = $lst_sub[strtoupper($action)];
|
||||
|
||||
foreach ($lst_by_type as $type => $lid_arr) {
|
||||
$script = "/etc/alternc/functions_hosting/hosting_" . strtolower($type) . ".sh";
|
||||
if (!@is_executable($script)) {
|
||||
continue;
|
||||
}
|
||||
foreach ($lid_arr as $lid) {
|
||||
$o = $sub_obj[$lid];
|
||||
$cmd = $script . " " . escapeshellcmd(strtolower($action)) . " ";
|
||||
$cmd .= escapeshellcmd($o['fqdn']) . " " . escapeshellcmd($o['valeur']);
|
||||
|
||||
system($cmd);
|
||||
}
|
||||
} // foreach $lst_by_type
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Generate apache configuration.
|
||||
* Die if a specific FQDN have 2 vhost conf.
|
||||
*
|
||||
* */
|
||||
function generate_apacheconf($p = null) {
|
||||
// Get the parameters
|
||||
$lst = $this->generation_parameters($p);
|
||||
|
||||
$gdt = $this->generation_domains_type();
|
||||
|
||||
// Initialize duplicate check
|
||||
$check_dup = array();
|
||||
|
||||
$ret = '';
|
||||
foreach ($lst as $p) {
|
||||
// Check if duplicate
|
||||
if (in_array($p['fqdn'], $check_dup)) {
|
||||
die("Error: duplicate fqdn : " . $p['fqdn']);
|
||||
// Search for things to do on SUB-DOMAINS:
|
||||
$db->query("SELECT sd.*, dt.only_dns FROM domaines_type dt, sub_domaines sd WHERE dt.name=sd.type AND sd.web_action!='OK';");
|
||||
$alldoms=array();
|
||||
$ignore=array();
|
||||
$delete=array();
|
||||
while ($db->next_record()) {
|
||||
// only_dns=1 => weird, we should not have web_action SET to something else than OK ... anyway, skip it
|
||||
if ($db->Record["only_dns"]) {
|
||||
if ($db->Record["web_action"]=="DELETE") {
|
||||
$delete[]=$db->Record["id"];
|
||||
} else {
|
||||
$ignore[]=$db->Record["id"];
|
||||
}
|
||||
} else {
|
||||
$check_dup[] = $p['fqdn'];
|
||||
$alldoms[$db->Record["id"]]=$db->Record;
|
||||
}
|
||||
}
|
||||
foreach($delete as $id) {
|
||||
$db->query("DELETE FROM sub_domaines WHERE id=?;",array($id));
|
||||
}
|
||||
foreach($ignore as $id) {
|
||||
// @FIXME (unsure it's useful) maybe we could check that no file exist for this subdomain ?
|
||||
$db->query("UPDATE sub_domaines SET web_action='OK' WHERE id=?;",array($id));
|
||||
}
|
||||
// now launch hooks
|
||||
if (count($alldoms)) {
|
||||
$hooks->invoke("hook_updatedomains_web_pre");
|
||||
foreach($alldoms as $id=>$subdom) {
|
||||
// is it a delete (DISABLED or DELETE)
|
||||
if ($subdom["web_action"]=="DELETE" || strtoupper(substr($subdom["enable"],0,7))=="DISABLE") {
|
||||
$ret = $hooks->invoke("hook_updatedomains_web_del",array($subdom["id"]));
|
||||
} else {
|
||||
$hooks->invoke("hook_updatedomains_web_before",array($subdom["id"])); // give a chance to get SSL cert before ;)
|
||||
$ret = $hooks->invoke("hook_updatedomains_web_add",array($subdom["id"]));
|
||||
$hooks->invoke("hook_updatedomains_web_after",array($subdom["id"]));
|
||||
}
|
||||
|
||||
// Get the needed template
|
||||
$tpl = $gdt[$p['type']] ['tpl'];
|
||||
|
||||
// Replace needed vars
|
||||
$tpl = strtr($tpl, array(
|
||||
"%%LOGIN%%" => $p['login'],
|
||||
"%%fqdn%%" => $p['fqdn'],
|
||||
"%%document_root%%" => getuserpath($p['login']) . $p['valeur'],
|
||||
"%%account_root%%" => getuserpath($p['login']),
|
||||
"%%redirect%%" => $p['valeur'],
|
||||
"%%UID%%" => $p['uid'],
|
||||
"%%GID%%" => $p['uid'],
|
||||
"%%mail_account%%" => $p['mail'],
|
||||
"%%user%%" => "FIXME",
|
||||
));
|
||||
|
||||
// Security check
|
||||
if ($p['uid'] < 1999) { // if UID is not an AlternC uid
|
||||
$ret.= "# ERROR: Sub_id: " . $p['sub_id'] . "- The uid seem to be dangerous\n";
|
||||
continue;
|
||||
if ($subdom["web_action"]=="DELETE") {
|
||||
$db->query("DELETE FROM sub_domaines WHERE id=?;",array($id));
|
||||
} else {
|
||||
// we keep the highest result returned by hooks...
|
||||
rsort($ret,SORT_NUMERIC); $returncode=$ret[0];
|
||||
$db->query("UPDATE sub_domaines SET web_result=?, web_action='OK' WHERE id=?;",array($returncode,$id));
|
||||
}
|
||||
}
|
||||
|
||||
// Return the conf
|
||||
$ret.= "# Sub_id: " . $p['sub_id'] . "\n" . $tpl;
|
||||
$hooks->invoke("hook_updatedomains_web_post");
|
||||
}
|
||||
|
||||
return $ret;
|
||||
|
||||
$this->unlock();
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Return an array with the list of id of sub_domains waiting for an action
|
||||
*/
|
||||
function generation_todo() {
|
||||
global $db, $msg;
|
||||
$msg->debug("dom", "generation_todo");
|
||||
$db->query("select id as sub_id, web_action, type from sub_domaines where web_action !='ok';");
|
||||
$r = array();
|
||||
while ($db->next_record()) {
|
||||
$r[strtoupper($db->Record['web_action'])][strtoupper($db->Record['type'])][] = $db->f('sub_id');
|
||||
}
|
||||
return $r;
|
||||
}
|
||||
|
||||
|
||||
function subdomain_modif_are_done($sub_domain_id, $action) {
|
||||
global $db;
|
||||
$sub_domain_id = intval($sub_domain_id);
|
||||
switch (strtolower($action)) {
|
||||
case "delete":
|
||||
$sql = "DELETE FROM sub_domaines WHERE id =$sub_domain_id;";
|
||||
break;
|
||||
default:
|
||||
$sql = "UPDATE sub_domaines SET web_action='OK' WHERE id='$sub_domain_id'; ";
|
||||
}
|
||||
$db->query($sql);
|
||||
return true;
|
||||
}
|
||||
|
||||
|
||||
|
||||
/**
|
||||
* @param string $dns_action
|
||||
*/
|
||||
|
@ -2095,15 +2001,8 @@ class m_dom {
|
|||
}
|
||||
|
||||
|
||||
function set_dns_result($domain, $dns_result) {
|
||||
global $db;
|
||||
$db->query("UPDATE domaines SET dns_result= ? WHERE domaine= ?; ", array($dns_result, $domain));
|
||||
return true;
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* List if there is problems in the domains.
|
||||
* List if there are problems on the domain.
|
||||
* Problems can appear when editing domains type properties
|
||||
*/
|
||||
function get_problems($domain) {
|
||||
|
@ -2160,6 +2059,8 @@ class m_dom {
|
|||
_("Default mail server");
|
||||
_("Default backup mail server");
|
||||
_("AlternC panel access");
|
||||
_("DKIM Key");
|
||||
_("Email autoconfiguration");
|
||||
}
|
||||
|
||||
} /* Class m_domains */
|
||||
|
|
|
@ -53,6 +53,11 @@ class m_hooks {
|
|||
// existe on l'execute et on rajoute ce qu'elle a retourné dans
|
||||
// un tableau
|
||||
$val = array();
|
||||
if (!$classes) {
|
||||
// Leaving early if classes isn't set prevents PHP warnings.
|
||||
// Happens frequently when running PHPUnit tests.
|
||||
return $val;
|
||||
}
|
||||
foreach ($classes as $c) {
|
||||
global $$c;
|
||||
if (method_exists($$c, $hname)) {
|
||||
|
|
|
@ -99,8 +99,8 @@ class m_lxc implements vm {
|
|||
}
|
||||
}
|
||||
|
||||
$msg = serialize($params);
|
||||
if (fwrite($fp, $msg . "\n") < 0) {
|
||||
$message = serialize($params);
|
||||
if (fwrite($fp, $message . "\n") < 0) {
|
||||
$this->error[] = 'Unable to send data';
|
||||
return FALSE;
|
||||
}
|
||||
|
@ -135,22 +135,22 @@ class m_lxc implements vm {
|
|||
$pass = $pass ? $pass : $mem->user['pass'];
|
||||
$uid = $uid ? $uid : $mem->user['uid'];
|
||||
|
||||
$msgg = array('action' => 'start', 'login' => $login, 'pass' => $pass, 'uid' => $uid);
|
||||
$msgg['mysql_host'] = $mysql->dbus->Host;
|
||||
$message = array('action' => 'start', 'login' => $login, 'pass' => $pass, 'uid' => $uid);
|
||||
$message['mysql_host'] = $mysql->dbus->Host;
|
||||
|
||||
$res = $this->sendMessage($msgg);
|
||||
$res = $this->sendMessage($message);
|
||||
if ($res === FALSE) {
|
||||
return $this->error;
|
||||
} else {
|
||||
$data = unserialize($res);
|
||||
$error = (int) $data['error'];
|
||||
$hostname = $data['hostname'];
|
||||
$msg = $data['msg'];
|
||||
$message = $data['msg'];
|
||||
$date_start = 'NOW()';
|
||||
$uid = $mem->user['uid'];
|
||||
|
||||
if ($error != 0) {
|
||||
$msg->raise("ERROR", 'lxc', _($msg));
|
||||
$msg->raise("ERROR", 'lxc', _($message));
|
||||
return FALSE;
|
||||
}
|
||||
$db->query("INSERT INTO vm_history (ip,date_start,uid,serialized_object) VALUES (?, ?, ?, ?);", array($hostname, $date_start, $uid, $res));
|
||||
|
@ -166,8 +166,8 @@ class m_lxc implements vm {
|
|||
global $mem;
|
||||
|
||||
$login = $login ? $login : $mem->user['login'];
|
||||
$msgg = array('action' => 'get', 'login' => $login);
|
||||
$res = $this->sendMessage($msgg);
|
||||
$message = array('action' => 'get', 'login' => $login);
|
||||
$res = $this->sendMessage($message);
|
||||
if (!$res) {
|
||||
return FALSE;
|
||||
}
|
||||
|
|
|
@ -309,7 +309,7 @@ ORDER BY
|
|||
}
|
||||
$db->query("SELECT a.id, a.address, a.password, a.`enabled`, a.mail_action, d.domaine AS domain, m.quota, m.quota*1024*1024 AS quotabytes, q.quota_dovecot as used, NOT ISNULL(m.id) AS islocal, a.type, r.recipients, m.lastlogin, a.domain_id
|
||||
FROM ((domaines d, address a LEFT JOIN mailbox m ON m.address_id=a.id) LEFT JOIN dovecot_quota q ON CONCAT(a.address,'@',d.domaine) = q.user) LEFT JOIN recipient r ON r.address_id=a.id
|
||||
WHERE " . $where . " AND d.id=a.domain_id " . $limit . " ;", $query_args);
|
||||
WHERE " . $where . " AND d.id=a.domain_id ORDER BY a.address ASC " . $limit . " ;", $query_args);
|
||||
if (!$db->next_record()) {
|
||||
$msg->raise("ERROR", "mail", _("No email found for this query"));
|
||||
return array();
|
||||
|
@ -466,12 +466,18 @@ ORDER BY
|
|||
}
|
||||
}
|
||||
$db->query("SELECT domaine FROM domaines WHERE id= ? ;", array($dom_id));
|
||||
if ($db->next_record()) {
|
||||
$db->query("UPDATE sub_domaines SET web_action='DELETE' WHERE domaine= ? AND type='txt' AND (sub='' AND valeur LIKE 'v=spf1 %') OR (sub='_dmarc' AND valeur LIKE 'v=dmarc1;%');", array($db->Record["domaine"]));
|
||||
$db->query("UPDATE sub_domaines SET web_action='DELETE' WHERE domaine= ? AND (type='defmx' OR type='defmx2');", array($db->Record["domaine"]));
|
||||
$db->query("UPDATE domaines SET dns_action='UPDATE' WHERE id= ? ;", array($dom_id));
|
||||
if (!$db->next_record()) {
|
||||
return false;
|
||||
}
|
||||
|
||||
$domain=$db->Record["domaine"];
|
||||
$db->query("UPDATE sub_domaines SET web_action='DELETE' WHERE domaine= ? AND (type='defmx' OR type='defmx2');", array($domain));
|
||||
|
||||
$this->del_dns_dmarc($domain);
|
||||
$this->del_dns_spf($domain);
|
||||
$this->del_dns_autoconf($domain);
|
||||
$this->dkim_del($domain);
|
||||
|
||||
$db->query("UPDATE domaines SET dns_action='UPDATE' WHERE id= ? ;", array($dom_id));
|
||||
return true;
|
||||
}
|
||||
|
||||
|
@ -912,6 +918,7 @@ ORDER BY
|
|||
}
|
||||
|
||||
|
||||
// ------------------------------------------------------------
|
||||
/**
|
||||
* hook function called by AlternC when a domain is created for
|
||||
* the current user account using the SLAVE DOMAIN feature
|
||||
|
@ -928,6 +935,7 @@ ORDER BY
|
|||
}
|
||||
|
||||
|
||||
// ------------------------------------------------------------
|
||||
/**
|
||||
* hook function called by AlternC when a domain is created for
|
||||
* the current user account
|
||||
|
@ -937,7 +945,7 @@ ORDER BY
|
|||
* @access private
|
||||
*/
|
||||
function hook_dom_add_mx_domain($domain_id) {
|
||||
global $msg, $mem, $db;
|
||||
global $msg, $mem, $db, $L_FQDN;
|
||||
$msg->log("mail", "hook_dom_add_mx_domain", $domain_id);
|
||||
|
||||
$db->query("SELECT value FROM variable where name='mailname_bounce';");
|
||||
|
@ -947,26 +955,30 @@ ORDER BY
|
|||
}
|
||||
$mailname = $db->f("value");
|
||||
// set spf & dmarc for this domain
|
||||
$db->query("SELECT domaine FROM domaines WHERE id= ?;", array($domain_id));
|
||||
$db->query("SELECT domaine,compte FROM domaines WHERE id= ?;", array($domain_id));
|
||||
if ($db->next_record()) {
|
||||
$domaine=$db->Record["domaine"];
|
||||
$compte=$db->Record["compte"];
|
||||
$this->set_dns_autoconf($domaine,$compte);
|
||||
if ($spf = variable_get("default_spf_value")) {
|
||||
$this->set_dns_spf($db->Record["domaine"], $spf);
|
||||
$this->set_dns_spf($domaine, $spf);
|
||||
}
|
||||
if ($dmarc = variable_get("default_dmarc_value")) {
|
||||
$this->set_dns_dmarc($db->Record["domaine"], $dmarc);
|
||||
$this->set_dns_dmarc($domaine, $dmarc);
|
||||
}
|
||||
}
|
||||
return $this->create_alias($domain_id, 'postmaster', $mem->user['login'] . '@' . $mailname);
|
||||
}
|
||||
|
||||
|
||||
// ------------------------------------------------------------
|
||||
/**
|
||||
* hook function called by variables when a variable is changed
|
||||
* @access private
|
||||
*/
|
||||
function hook_variable_set($name, $old, $new) {
|
||||
global $msg, $db;
|
||||
$msg->log("mail", "hook_variable_set($name,$old,$new)");
|
||||
$msg->log("mail", "hook_variable_set($name,$old,$new)");
|
||||
|
||||
if ($name == "default_spf_value") {
|
||||
$new = trim($new);
|
||||
|
@ -991,7 +1003,44 @@ ORDER BY
|
|||
}
|
||||
}
|
||||
|
||||
|
||||
// ------------------------------------------------------------
|
||||
/**
|
||||
* Add dns entries for autodiscover / autoconf on the domain
|
||||
*/
|
||||
function set_dns_autoconf($domain,$uid=-1) {
|
||||
global $db, $L_FQDN, $cuid;
|
||||
$changed=false;
|
||||
if ($uid==-1) $uid=$cuid;
|
||||
|
||||
$db->query("SELECT domaine,sub,type,valeur FROM sub_domaines WHERE domaine=? AND sub='autodiscover' AND type='autodiscover';",array($domain));
|
||||
if (!$db->next_record()) {
|
||||
$db->query("INSERT INTO sub_domaines SET domaine=?, compte=?, sub='autodiscover', type='autodiscover', valeur='';",array($domain,$uid));
|
||||
$changed=true;
|
||||
}
|
||||
$db->query("SELECT domaine,sub,type,valeur FROM sub_domaines WHERE domaine=? AND sub='autoconfig' AND type='autodiscover';",array($domain));
|
||||
if (!$db->next_record()) {
|
||||
$db->query("INSERT INTO sub_domaines SET domaine=?, compte=?, sub='autoconfig', type='autodiscover', valeur='';",array($domain,$uid));
|
||||
$changed=true;
|
||||
}
|
||||
if ($changed) {
|
||||
$db->query("UPDATE domaines SET dns_action='UPDATE' WHERE domaine= ?;", array($domain));
|
||||
}
|
||||
return $changed;
|
||||
}
|
||||
|
||||
|
||||
// ------------------------------------------------------------
|
||||
/**
|
||||
* delete the autoconf / autodiscover vhosts when removing a domain as MX
|
||||
*/
|
||||
function del_dns_autoconf($domain) {
|
||||
global $db, $L_FQDN, $cuid;
|
||||
$db->query("UPDATE sub_domaines SET web_action='DELETE' WHERE domaine= ? AND type='autodiscover' AND sub='autoconfig';", array($domain));
|
||||
$db->query("UPDATE sub_domaines SET web_action='DELETE' WHERE domaine= ? AND type='autodiscover' AND sub='autodiscover';", array($domain));
|
||||
}
|
||||
|
||||
// ------------------------------------------------------------
|
||||
/**
|
||||
* Set or UPDATE the DNS record for the domain $dom(str) to be $spf
|
||||
* account's login is current and if not it's $login.
|
||||
|
@ -999,7 +1048,8 @@ ORDER BY
|
|||
* @access private
|
||||
*/
|
||||
function set_dns_spf($domain, $spf, $previous = -1, $uid = -1, $login = -1) {
|
||||
global $db, $cuid, $mem;
|
||||
global $db, $cuid, $mem, $msg;
|
||||
$msg->debug("mail","set_dns_spf($domain, $spf, $previous, $uid, $login)");
|
||||
// defaults
|
||||
if ($uid === -1) {
|
||||
$uid = intval($cuid);
|
||||
|
@ -1021,7 +1071,18 @@ ORDER BY
|
|||
$db->query("UPDATE domaines SET dns_action='UPDATE' WHERE domaine= ?;", array($domain));
|
||||
}
|
||||
|
||||
// ------------------------------------------------------------
|
||||
/**
|
||||
* delete the SPF entries in the sub_domaine table for a domain
|
||||
* called by del_domain or del_mx_domain by hooks :
|
||||
*/
|
||||
function del_dns_spf($domain) {
|
||||
global $db;
|
||||
$db->query("UPDATE sub_domaines SET web_action='DELETE' WHERE domaine= ? AND type='txt' AND sub='' AND valeur LIKE 'v=spf1 %';", array($domain));
|
||||
}
|
||||
|
||||
|
||||
// ------------------------------------------------------------
|
||||
/**
|
||||
* Set or UPDATE the DNS record for the domain $dom(str) to be $dmarc
|
||||
* account's login is current and if not it's $login.
|
||||
|
@ -1029,7 +1090,8 @@ ORDER BY
|
|||
* @access private
|
||||
*/
|
||||
function set_dns_dmarc($domain, $dmarc, $previous = -1, $uid = -1, $login = -1) {
|
||||
global $db, $cuid, $mem, $L_FQDN;
|
||||
global $db, $cuid, $mem, $L_FQDN, $msg;
|
||||
$msg->debug("mail","set_dns_dmarc($domain, $dmarc, $previous, $uid, $login)");
|
||||
// defaults
|
||||
if ($uid === -1) {
|
||||
$uid = intval($cuid);
|
||||
|
@ -1055,5 +1117,151 @@ ORDER BY
|
|||
}
|
||||
|
||||
|
||||
// ------------------------------------------------------------
|
||||
/**
|
||||
* delete the DMARC entries in the sub_domaine table for a domain
|
||||
* called by del_domain or del_mx_domain by hooks :
|
||||
*/
|
||||
function del_dns_dmarc($domain) {
|
||||
global $db;
|
||||
$db->query("UPDATE sub_domaines SET web_action='DELETE' WHERE domaine= ? AND type='txt' AND sub='' AND valeur LIKE 'v=dmarc1 %';", array($domain));
|
||||
}
|
||||
|
||||
|
||||
/** Manage DKIM when adding / removing a domain MX management */
|
||||
var $shouldreloaddkim;
|
||||
|
||||
|
||||
// ------------------------------------------------------------
|
||||
/**
|
||||
* Hook launched before doing anything dns-related
|
||||
*/
|
||||
function hook_updatedomains_dns_pre() {
|
||||
global $db;
|
||||
// for each domain where we don't have the MX or the DNS, remove the DKIM setup
|
||||
$this->shouldreloaddkim=false;
|
||||
$db->query("SELECT domaine,compte,gesdns,gesmx FROM domaines WHERE dns_action!='OK';");
|
||||
$add=array();
|
||||
$del=array();
|
||||
while ($db->next_record()) {
|
||||
if ($db->Record["gesdns"]==0 || $db->Record["gesmx"]==0) {
|
||||
$del[]=$db->Record;
|
||||
} else {
|
||||
$add[]=$db->Record;
|
||||
}
|
||||
}
|
||||
foreach($add as $domain) {
|
||||
$this->dkim_add($domain["domaine"],$domain["compte"]);
|
||||
}
|
||||
foreach($del as $domain) {
|
||||
$this->dkim_del($domain["domaine"]);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
// ------------------------------------------------------------
|
||||
/**
|
||||
* Hook launched after doing anything dns-related
|
||||
*/
|
||||
function hook_updatedomains_dns_post() {
|
||||
if ($this->shouldreloaddkim) {
|
||||
exec("service opendkim reload");
|
||||
$this->shouldreloaddkim=false;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
// ------------------------------------------------------------
|
||||
/**
|
||||
* Add a domain into OpenDKIM configuration
|
||||
*/
|
||||
function dkim_add($domain,$uid) {
|
||||
global $db;
|
||||
$target_dir = "/etc/opendkim/keys/$domain";
|
||||
|
||||
// Create a dkim key when it's not already there :
|
||||
if (!file_exists($target_dir.'/alternc.txt')) {
|
||||
$this->shouldreloaddkim=true;
|
||||
if (! is_dir($target_dir)) mkdir($target_dir); // create dir
|
||||
// Generate the key, 1200 bits (better than 1024)
|
||||
$old_dir=getcwd();
|
||||
chdir($target_dir);
|
||||
exec('opendkim-genkey -b 1200 -r -d '.escapeshellarg($domain).' -s "alternc" ');
|
||||
chdir($old_dir);
|
||||
// opendkim must be owner of the key
|
||||
chown("$target_dir/alternc.private", 'opendkim');
|
||||
chgrp("$target_dir/alternc.private", 'opendkim');
|
||||
|
||||
add_line_to_file("/etc/opendkim/KeyTable","alternc._domainkey.".$domain." ".$domain.":alternc:/etc/opendkim/keys/".$domain."/alternc.private");
|
||||
add_line_to_file("/etc/opendkim/SigningTable",$domain." alternc._domainkey.".$domain);
|
||||
}
|
||||
|
||||
// Search for the subdomain entry, if it's not already there, create it:
|
||||
$db->query("SELECT id FROM sub_domaines WHERE domaine=? AND sub='alternc._domainkey';",array($domain));
|
||||
if (!$db->next_record()) {
|
||||
// Add subdomaine entry
|
||||
$dkim_key=$this->dkim_get_entry($domain);
|
||||
$db->query("INSERT INTO sub_domaines SET domaine=?, compte=?, sub='alternc._domainkey', type='dkim', valeur=?;",array($domain,$uid,$dkim_key));
|
||||
// no need to do DNS_ACTION="UPDATE" => we are in the middle of a HOOK, so dns WILL BE reloaded for this domain
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
// ------------------------------------------------------------
|
||||
/**
|
||||
* Delete a domain from OpenDKIM configuration
|
||||
*/
|
||||
function dkim_del($domain) {
|
||||
global $db;
|
||||
$target_dir = "/etc/opendkim/keys/$domain";
|
||||
if (file_exists($target_dir)) {
|
||||
$this->shouldreloaddkim=true;
|
||||
@unlink("$target_dir/alternc_private");
|
||||
@unlink("$target_dir/alternc.txt");
|
||||
@rmdir($target_dir);
|
||||
del_line_from_file("/etc/opendkim/KeyTable","alternc._domainkey.".$domain." ".$domain.":alternc:/etc/opendkim/keys/".$domain."/alternc.private");
|
||||
del_line_from_file("/etc/opendkim/SigningTable",$domain." alternc._domainkey.".$domain);
|
||||
}
|
||||
$db->query("DELETE FROM sub_domaines WHERE domaine=? AND sub='alternc._domainkey';",array($domain));
|
||||
// No need to do DNS_ACTION="UPDATE" => we are in the middle of a HOOK
|
||||
}
|
||||
|
||||
|
||||
// ------------------------------------------------------------
|
||||
/**
|
||||
* return the content of the TXT information to be added into the DB for DKIM subdomains
|
||||
* @param $domain string the name of the domain name
|
||||
* @return string the TXT entry (without quotes)
|
||||
* or false if an error occurred
|
||||
**/
|
||||
function dkim_get_entry($domain) {
|
||||
global $msg;
|
||||
$key=file_get_contents("/etc/opendkim/keys/".$domain."/alternc.txt");
|
||||
// easy: monoline key
|
||||
if (preg_match('#alternc._domainkey IN TXT "(.*)"#',$key,$mat)) {
|
||||
return $mat[1];
|
||||
} else {
|
||||
// Need to parse a multiligne key:
|
||||
$inkey=false; $result="";
|
||||
$lines=explode("\n",$key);
|
||||
foreach($lines as $line) {
|
||||
if (preg_match('#alternc._domainkey\s+IN\s+TXT\s+\( "(.*)"#',$line,$mat)) {
|
||||
$result.=$mat[1]; $inkey=true; continue;
|
||||
}
|
||||
if ($inkey && preg_match('#^\s*"(.*)"\s*\)#',$line,$mat)) {
|
||||
$result.=$mat[1]; $inkey=false; break;
|
||||
}
|
||||
if ($inkey && preg_match('#^\s*"(.*)"\s*$#',$line,$mat)) {
|
||||
$result.=$mat[1]; $inkey=true; continue;
|
||||
}
|
||||
}
|
||||
if ($result)
|
||||
return $result;
|
||||
}
|
||||
$msg->debug("mail","dkim_get_entry($domain) failed");
|
||||
return false;
|
||||
}
|
||||
|
||||
// @TODO hook after reloading DNS zones => if necessary, restart opendkim
|
||||
|
||||
} /* Class m_mail */
|
||||
|
|
|
@ -41,7 +41,6 @@ class m_mem {
|
|||
*/
|
||||
var $local;
|
||||
|
||||
|
||||
/**
|
||||
* Password kind used in this class (hook for admin class)
|
||||
*/
|
||||
|
@ -401,10 +400,14 @@ class m_mem {
|
|||
$msg->raise("ERROR", "mem", _("You are not allowed to change your password."));
|
||||
return false;
|
||||
}
|
||||
if (!password_verify($oldpass, $this->user['pass'])) {
|
||||
$msg->raise("ERROR", "mem", _("The old password is incorrect"));
|
||||
return false;
|
||||
|
||||
if ($this->requires_old_password_for_change()) {
|
||||
if (!password_verify($oldpass, $this->user['pass'])) {
|
||||
$msg->raise("ERROR", "mem", _("The old password is incorrect"));
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
if ($newpass != $newpass2) {
|
||||
$msg->raise("ERROR", "mem", _("The new passwords are differents, please retry"));
|
||||
return false;
|
||||
|
@ -418,11 +421,12 @@ class m_mem {
|
|||
$newpass = password_hash($newpass, PASSWORD_BCRYPT);
|
||||
$db->query("UPDATE membres SET pass= ? WHERE uid= ?;", array($newpass, $cuid));
|
||||
$msg->init_msgs();
|
||||
setcookie('require_old_password', '', 1);
|
||||
return true;
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
/**
|
||||
* Change the administrator preferences of an admin account
|
||||
* @param integer $admlist visualisation mode of the account list (0=large 1=short)
|
||||
* @return boolean TRUE if the preferences has been changed, FALSE if not.
|
||||
|
@ -678,4 +682,264 @@ Cordially.
|
|||
return true;
|
||||
}
|
||||
|
||||
/**
|
||||
* Sends a password-reset URL.
|
||||
*/
|
||||
public function send_reset_url($email_or_login) {
|
||||
global $msg, $L_FQDN, $L_HOSTING, $db;
|
||||
// Look up user by email_or_login.
|
||||
$db->query("SELECT * FROM membres WHERE login = ? OR mail = ? ;", array($email_or_login, $email_or_login));
|
||||
|
||||
$msg->log('mem', 'send_reset_url', 'Password reset requested for: ' . $email_or_login);
|
||||
// Give user feedback, even if we don't have an account stored.
|
||||
$msg->raise('INFO', 'mem', _('An e-mail with information on how to connect has been sent to the owner of the account if one exists'));
|
||||
|
||||
// It is possible here that a user could have multiple accounts for a
|
||||
// single e-mail since 'mail' is not a uniqe key in the membres table.
|
||||
// For the moment we'll just take the first account.
|
||||
if (!$db->num_rows()) {
|
||||
$msg->log('mem', 'send_reset_url', 'No member found with login or mail ' . $email_or_login);
|
||||
return FALSE;
|
||||
}
|
||||
if ($db->num_rows()) {
|
||||
$db->next_record();
|
||||
// Get a reset URL for the current timestamp.
|
||||
$url = $this->generate_reset_url($db->f('uid'));
|
||||
$mail = $db->f('mail');
|
||||
}
|
||||
if (!$url || !$mail) {
|
||||
return FALSE;
|
||||
}
|
||||
$duration = variable_get('password_reset_expiration', 86400, 'The number of seconds for which a password reset link is valid');
|
||||
$duration_hours = ($duration / 3600.0) . ' ' . _('hours');
|
||||
$message = sprintf(_('
|
||||
Hi,
|
||||
|
||||
someone requested a password reset for your account at %s (%s).
|
||||
|
||||
You may connect to your account and change your account by clicking on the following URL or copying it into your browser :
|
||||
|
||||
%s
|
||||
|
||||
This link may only be used once. You should change your password in your account settings once connected. This link will only be valid for %s, and no changes will be made if it is not used.
|
||||
'), $L_HOSTING, $L_FQDN, $url, $duration_hours);
|
||||
mail($mail, "Password reset request on {$L_HOSTING}", $message, "From: postmaster@{$L_FQDN}\nReply-to: postmaster@{$L_FQDN}");
|
||||
$msg->log('mem', 'send_reset_url', "Password reset e-mail sent for account {$uid} at {$mail}");
|
||||
}
|
||||
|
||||
/**
|
||||
* Generate a reset URL for an account given it's e-mail or login.
|
||||
*
|
||||
* @param $email_or_login
|
||||
* A string with the email or login.
|
||||
*
|
||||
* @returns string|boolean
|
||||
* A reset URL or FALSE in case of error.
|
||||
*/
|
||||
function generate_reset_url($uid) {
|
||||
global $db;
|
||||
$db->query("SELECT * FROM membres WHERE uid = ? ;", array($uid));
|
||||
if (!$db->num_rows()) {
|
||||
return FALSE;
|
||||
}
|
||||
if ($db->num_rows()) {
|
||||
$db->next_record();
|
||||
// Get a reset URL for the current timestamp.
|
||||
return $this->_get_reset_url(time(), $db->f('uid'), $db->f('login'), $db->f('pass'));
|
||||
}
|
||||
return FALSE;
|
||||
}
|
||||
|
||||
/**
|
||||
* Builds a full reset URL from the uid, login, password and timestamp.
|
||||
*
|
||||
* @returns string
|
||||
* A full URL.
|
||||
*/
|
||||
function _get_reset_url($timestamp, $uid, $login, $password) {
|
||||
global $db, $L_FQDN;
|
||||
$salt = variable_get('salt_password_reset', base64_encode(random_bytes(128)), 'The salt used when hasing password resets - change to invalidate all existing reset tokens') . $password;
|
||||
$data = $timestamp . $uid . $login;
|
||||
$token = hash_hmac('sha512', $data, $salt);
|
||||
// @TODO: Not sure where the bureau's preferred protocol is stored, but
|
||||
// since 3.5.0 https seems to be the default.
|
||||
return 'https://' . $L_FQDN . '/reset.php?' . http_build_query(array(
|
||||
'uid' => $uid,
|
||||
'timestamp' => $timestamp,
|
||||
'token' => $token,
|
||||
));
|
||||
}
|
||||
|
||||
/**
|
||||
* Logs a user in from a one-time login link.
|
||||
*/
|
||||
function temporary_login($uid, $timestamp, $token, $restrictip = 0, $authip_token = false) {
|
||||
global $db, $msg, $cuid, $authip;
|
||||
if (!$this->validate_reset_url($uid, $timestamp, $token)) {
|
||||
return FALSE;
|
||||
}
|
||||
$msg->log("mem", "temporary_login", $username);
|
||||
if ($msg->has_msgs("ERROR")) {
|
||||
return FALSE;
|
||||
}
|
||||
|
||||
$db->query("select * from membres where uid= ? ;", array($uid));
|
||||
if ($db->num_rows() == 0) {
|
||||
return FALSE;
|
||||
}
|
||||
$db->next_record();
|
||||
|
||||
// No password verification for temporary logins, the validation
|
||||
// is in validate_reset_url instead.
|
||||
if (!$db->f("enabled")) {
|
||||
$msg->raise("ERROR", "mem", _("This account is locked, contact the administrator."));
|
||||
return FALSE;
|
||||
}
|
||||
|
||||
$this->user = $db->Record;
|
||||
$cuid = $db->f("uid");
|
||||
if (panel_islocked() && $cuid != 2000) {
|
||||
$msg->raise("ALERT", "mem", _("This website is currently under maintenance, login is currently disabled."));
|
||||
return FALSE;
|
||||
}
|
||||
|
||||
// AuthIP
|
||||
$allowed_ip = FALSE;
|
||||
if ($authip_token) {
|
||||
$allowed_ip = $this->authip_tokencheck($authip_token);
|
||||
}
|
||||
|
||||
$aga = $authip->get_allowed('panel');
|
||||
foreach ($aga as $k => $v) {
|
||||
if ($authip->is_in_subnet(get_remote_ip(), $v['ip'], $v['subnet'])) {
|
||||
$allowed = TRUE;
|
||||
}
|
||||
}
|
||||
|
||||
// Error if there is rules, the IP is not allowed and it's not in the whitelisted IP
|
||||
if (sizeof($aga) > 1 && !$allowed_ip && !$authip->is_wl(get_remote_ip())) {
|
||||
$msg->raise("ERROR", "mem", _("Your IP isn't allowed to connect"));
|
||||
return FALSE;
|
||||
}
|
||||
// End AuthIP
|
||||
|
||||
if ($restrictip) {
|
||||
$ip = get_remote_ip();
|
||||
} else {
|
||||
$ip = "";
|
||||
}
|
||||
|
||||
// Close sessions that are more than 2 days old.
|
||||
$db->query("DELETE FROM sessions WHERE DATE_ADD(ts,INTERVAL 2 DAY)<NOW();");
|
||||
|
||||
// Delete old impersonations.
|
||||
if (isset($_COOKIE["oldid"])) {
|
||||
setcookie('oldid', '', 0, '/');
|
||||
}
|
||||
|
||||
// Open the session
|
||||
$sess = md5(mt_rand().mt_rand().mt_rand());
|
||||
$_REQUEST["session"] = $sess;
|
||||
$db->query("insert into sessions (sid,ip,uid) values (?, ?, ?);", array($sess, $ip, $cuid));
|
||||
setcookie("session", $sess, 0, "/");
|
||||
$msg->init_msgs();
|
||||
|
||||
// Fill in $local.
|
||||
$db->query("SELECT * FROM local WHERE uid= ? ;", array($cuid));
|
||||
if ($db->num_rows()) {
|
||||
$db->next_record();
|
||||
$this->local = $db->Record;
|
||||
}
|
||||
$this->resetlast();
|
||||
|
||||
// Set a cookie parameter to allow password change without requiring
|
||||
// previous one.
|
||||
$db->query('select lastlogin, pass from membres where uid = ?;', array($uid));
|
||||
if ($db->num_rows()) {
|
||||
$db->next_record();
|
||||
$cookie_data = $cuid . $db->f('lastlogin');
|
||||
$salt = variable_get('salt_password_reset', base64_encode(random_bytes(128))) . $db->f('pass');
|
||||
$c = setcookie('require_old_password', hash_hmac('sha512', $cookie_data, $salt), 0, '/');
|
||||
if (!$c) {
|
||||
$msg->log('mem', 'temporary_login', 'Failed to set cookie require_old_password');
|
||||
}
|
||||
}
|
||||
return TRUE;
|
||||
}
|
||||
|
||||
function requires_old_password_for_change() {
|
||||
global $cuid, $db;
|
||||
$cookie = $_COOKIE['require_old_password'];
|
||||
if (!$cookie) {
|
||||
return TRUE;
|
||||
}
|
||||
$db->query('select lastlogin, pass from membres where uid = ?;', array($cuid));
|
||||
if ($db->num_rows()) {
|
||||
$db->next_record();
|
||||
$cookie_data = $cuid . $db->f('lastlogin');
|
||||
$salt = variable_get('salt_password_reset', base64_encode(random_bytes(128))) . $db->f('pass');
|
||||
if ($cookie == hash_hmac('sha512', $cookie_data, $salt)) {
|
||||
return FALSE;
|
||||
}
|
||||
}
|
||||
return TRUE;
|
||||
}
|
||||
|
||||
/**
|
||||
* Validates a reset URL that has been received.
|
||||
*/
|
||||
function validate_reset_url($uid, $timestamp, $token) {
|
||||
global $cuid, $db, $msg;
|
||||
// Do not log a person in if they are logged in already.
|
||||
if ($this->checkid(false)) {
|
||||
$msg->raise('ERROR', 'mem', _('You are already logged in, you may not use a one-time login link'));
|
||||
$msg->log('mem', 'validate_reset_url', 'Refused one-time log-in since the user is already connected');
|
||||
return FALSE;
|
||||
}
|
||||
|
||||
// The timestamp is older than the age limit - invalid.
|
||||
$fail_message = _('The login-link has already been used or is expired');
|
||||
$duration = variable_get('password_reset_expiration', 86400, 'The number of seconds for which a password reset link is valid');
|
||||
if (time() - $timestamp >= $duration) {
|
||||
$msg->raise('ERROR', 'mem', $fail_message);
|
||||
$msg->log('mem', 'validate_reset_url', 'Refused one-time log-in since the time elapsed is greater than limit of ' . $duration);
|
||||
return FALSE;
|
||||
}
|
||||
|
||||
$db->query("SELECT * FROM membres WHERE uid = ? ;", array($uid));
|
||||
if (!$db->num_rows()) {
|
||||
$msg->raise('ERROR', 'mem', $fail_message);
|
||||
$msg->log('mem', 'validate_reset_url', 'Refused one-time log-in since a user with ID ' . $uid. ' does not exist');
|
||||
return FALSE;
|
||||
}
|
||||
$db->next_record();
|
||||
$last_login = strtotime($db->f('lastlogin'));
|
||||
// The timestamp is older than the most recent login - invalid.
|
||||
if ($last_login >= time() || $last_login >= $timestamp) {
|
||||
$msg->raise('ERROR', 'mem', $fail_message);
|
||||
$msg->log('mem', 'validate_reset_url', "Refused one-time log-in since the most recent login was more recent than the timestamp in the log-in link. Last: {$last_login}, Timestamp: {$timestamp}");
|
||||
return FALSE;
|
||||
}
|
||||
|
||||
// The account is locked or cannot change pass - invalid.
|
||||
if (!$db->f('enabled') || !$db->f('canpass')) {
|
||||
$msg->raise('ERROR', 'mem', $fail_message);
|
||||
$msg->log('mem', 'validate_reset_url', 'Refused one-time log-in since the user account is disabled or cannot change it\'s password.');
|
||||
return FALSE;
|
||||
}
|
||||
|
||||
// Using the current user info and timestamp the tokens generated
|
||||
// do not match - invalid. (Eg. user password changed, salt changed).
|
||||
$salt = variable_get('salt_password_reset', base64_encode(random_bytes(128))) . $db->f('pass');
|
||||
$data = $timestamp . $uid . $db->f('login');
|
||||
$ref_token = hash_hmac('sha512', $data, $salt);
|
||||
if ($token != $ref_token) {
|
||||
$msg->raise('ERROR', 'mem', $fail_message);
|
||||
return FALSE;
|
||||
}
|
||||
|
||||
$msg->raise('INFO', 'mem', _('You have used a one-time login link. Please set a new password now.'));
|
||||
return TRUE;
|
||||
}
|
||||
|
||||
} /* Class m_mem */
|
||||
|
|
|
@ -372,7 +372,34 @@ INSTR(CONCAT(sd.sub,IF(sd.sub!='','.',''),sd.domaine),'.')+1))=?
|
|||
return $db->Record;
|
||||
}
|
||||
|
||||
|
||||
|
||||
// -----------------------------------------------------------------
|
||||
/** Return paths to certificate, key, and chain for a certificate
|
||||
* given it's ID.
|
||||
* @param $id integer the certificate by id
|
||||
* @return array cert, key, chain (not mandatory) with full path.
|
||||
*/
|
||||
function get_certificate_path($id) {
|
||||
global $db, $msg, $cuid;
|
||||
$msg->log("ssl", "get_certificate_path",$id);
|
||||
$id = intval($id);
|
||||
$db->query("SELECT id FROM certificates WHERE id=?;",array($id));
|
||||
if (!$db->next_record()) {
|
||||
$msg->raise("ERROR","ssl", _("Can't find this Certificate"));
|
||||
// Return cert 0 info :)
|
||||
$id=0;
|
||||
}
|
||||
$chain=self::KEY_REPOSITORY."/".floor($id/1000)."/".$id.".chain";
|
||||
if (!file_exists($chain))
|
||||
$chain=false;
|
||||
|
||||
return array(
|
||||
"cert" => self::KEY_REPOSITORY."/".floor($id/1000)."/".$id.".pem",
|
||||
"key" => self::KEY_REPOSITORY."/".floor($id/1000)."/".$id.".key",
|
||||
"chain" => $chain
|
||||
);
|
||||
}
|
||||
|
||||
// -----------------------------------------------------------------
|
||||
/** Return all the valid certificates that can be used for a specific FQDN
|
||||
* return the list of certificates by order of preference
|
||||
|
@ -620,6 +647,34 @@ SELECT ?,?,?, FROM_UNIXTIME(?), FROM_UNIXTIME(?), ?, ?, sslcsr FROM certificate
|
|||
|
||||
}
|
||||
|
||||
|
||||
// -----------------------------------------------------------------
|
||||
/** Launched by hosting_functions.sh launched by update_domaines.sh
|
||||
* Action may be create/postinst/delete/enable/disable
|
||||
* Change the template for this domain name to have the proper CERTIFICATE
|
||||
* An algorithm determine the best possible certificate, which may be a BAD one
|
||||
* (like a generic self-signed for localhost as a last chance)
|
||||
*/
|
||||
public function hook_updatedomains_web_before($subdomid) {
|
||||
global $db, $msg, $dom;
|
||||
$msg->log("ssl", "hook_updatedomains_web_before($subdomid)");
|
||||
|
||||
$db->query("SELECT sd.*, dt.only_dns, dt.has_https_option, m.login FROM domaines_type dt, sub_domaines sd LEFT JOIN membres m ON m.uid=sd.compte WHERE dt.name=sd.type AND sd.web_action!='OK' AND id=?;",array($subdomid));
|
||||
$db->next_record();
|
||||
$subdom=$db->Record;
|
||||
$domtype=$dom->domains_type_get($subdom["type"]);
|
||||
// the domain type must be a "dns_only=false" one:
|
||||
if ($domtype["only_dns"]==true) {
|
||||
return; // nothing to do : this domain type does not involve Vhosts
|
||||
}
|
||||
$subdom["fqdn"]=$subdom["sub"].(($subdom["sub"])?".":"").$subdom["domaine"];
|
||||
|
||||
list($cert) = $this->get_valid_certs($subdom["fqdn"], $subdom["provider"]);
|
||||
$this->write_cert_file($cert);
|
||||
// Edit certif_hosts:
|
||||
$db->query("UPDATE sub_domaines SET certificate_id=? WHERE id=?;",array($cert["id"], $subdom["id"]));
|
||||
}
|
||||
|
||||
|
||||
// ----------------------------------------------------------------
|
||||
/** Search for the best certificate for a user and a fqdn
|
||||
|
@ -635,7 +690,25 @@ SELECT ?,?,?, FROM_UNIXTIME(?), FROM_UNIXTIME(?), ?, ?, sslcsr FROM certificate
|
|||
|
||||
// get the first good certificate:
|
||||
list($cert) = $this->get_valid_certs($fqdn, $subdom["provider"]);
|
||||
$this->write_cert_file($cert);
|
||||
// we have the files, let's fill the output array :
|
||||
$output=array(
|
||||
"id" => $cert["id"],
|
||||
"crt" => $CRTDIR . "/" . $cert["id"].".pem",
|
||||
"key" => $CRTDIR . "/" . $cert["id"].".key",
|
||||
);
|
||||
if (file_exists($CRTDIR . "/" . $cert["id"].".chain")) {
|
||||
$output["chain"] = $CRTDIR . "/" . $cert["id"].".chain";
|
||||
}
|
||||
return $output;
|
||||
}
|
||||
|
||||
|
||||
// -----------------------------------------------------------------
|
||||
/** Write certificate file into KEY_REPOSITORY
|
||||
* @param $cert array an array with ID sslcrt sslkey sslchain
|
||||
*/
|
||||
function write_cert_file($cert) {
|
||||
// we split the certificates by 1000
|
||||
$CRTDIR = self::KEY_REPOSITORY . "/" . floor($cert["id"]/1000);
|
||||
@mkdir($CRTDIR,0750,true);
|
||||
|
@ -667,16 +740,6 @@ SELECT ?,?,?, FROM_UNIXTIME(?), FROM_UNIXTIME(?), ?, ?, sslcsr FROM certificate
|
|||
chmod($CRTDIR . "/" . $cert["id"].".chain",0640);
|
||||
}
|
||||
}
|
||||
// we have the files, let's fill the output array :
|
||||
$output=array(
|
||||
"id" => $cert["id"],
|
||||
"crt" => $CRTDIR . "/" . $cert["id"].".pem",
|
||||
"key" => $CRTDIR . "/" . $cert["id"].".key",
|
||||
);
|
||||
if (file_exists($CRTDIR . "/" . $cert["id"].".chain")) {
|
||||
$output["chain"] = $CRTDIR . "/" . $cert["id"].".chain";
|
||||
}
|
||||
return $output;
|
||||
}
|
||||
|
||||
|
||||
|
|
|
@ -1601,24 +1601,20 @@ msgid "Quit"
|
|||
msgstr "Fermer"
|
||||
|
||||
#: ../admin/bro_main.php:73
|
||||
#, fuzzy, php-format
|
||||
msgid "The folder '%s' was successfully created"
|
||||
msgstr "L'utilisateur %s a été effacée avec succès"
|
||||
msgstr "Le dossier %s a été effacé avec succès"
|
||||
|
||||
#: ../admin/bro_main.php:79
|
||||
#, fuzzy, php-format
|
||||
msgid "The file '%s' was successfully created"
|
||||
msgstr "L'Email a été modifié avec succès"
|
||||
msgstr "Le fihier été créé avec succès"
|
||||
|
||||
#: ../admin/bro_main.php:94
|
||||
#, fuzzy, php-format
|
||||
msgid "The folder '%s' was successfully deleted"
|
||||
msgstr "L'utilisateur %s a été effacée avec succès"
|
||||
msgstr "Le dossier %s a été effacé avec succès"
|
||||
|
||||
#: ../admin/bro_main.php:96
|
||||
#, fuzzy, php-format
|
||||
msgid "The file '%s' was successfully deleted"
|
||||
msgstr "L'adresse email %s a été effacée avec succès"
|
||||
msgstr "Le fichier %s a été effacé avec succès"
|
||||
|
||||
#: ../admin/bro_main.php:102
|
||||
#, php-format
|
||||
|
@ -1663,39 +1659,32 @@ msgid "The file '%s' was successfully moved to '%s'"
|
|||
msgstr "L'Email a été modifié avec succès"
|
||||
|
||||
#: ../admin/bro_main.php:145
|
||||
#, fuzzy
|
||||
msgid "The files / folders were successfully moved"
|
||||
msgstr "Le répertoire protégé %s a été déprotégé avec succès"
|
||||
msgstr "Les fichiers / répertoires %s ont été déplacé avec succès"
|
||||
|
||||
#: ../admin/bro_main.php:153
|
||||
#, fuzzy, php-format
|
||||
msgid "The folder '%s' was successfully renamed to '%s'"
|
||||
msgstr "L'Email a été modifié avec succès"
|
||||
msgstr "Le dossier '%s' a été renommé '%s' avec succès"
|
||||
|
||||
#: ../admin/bro_main.php:155
|
||||
#, fuzzy, php-format
|
||||
msgid "The file '%s' was successfully renamed to '%s'"
|
||||
msgstr "L'Email a été modifié avec succès"
|
||||
msgstr "Le fichier '%s' a été renommé '%s' avec succès"
|
||||
|
||||
#: ../admin/bro_main.php:157
|
||||
#, fuzzy
|
||||
msgid "The files / folders were successfully renamed"
|
||||
msgstr "Le compte AlternC a été renouvelé avec succès"
|
||||
msgstr "Les fichiers / répertoires ont été renommés avec succès"
|
||||
|
||||
#: ../admin/bro_main.php:162
|
||||
#, fuzzy, php-format
|
||||
msgid "The file '%s' was successfully uploaded"
|
||||
msgstr "L'adresse email %s a été effacée avec succès"
|
||||
msgstr "Le fichier '%s' a été téléversé avec succès"
|
||||
|
||||
#: ../admin/bro_main.php:167
|
||||
#, fuzzy
|
||||
msgid "The permissions were successfully set"
|
||||
msgstr "L'Email a été modifié avec succès"
|
||||
msgstr "Les permissions ont été appliquées avec succès"
|
||||
|
||||
#: ../admin/bro_main.php:175
|
||||
#, fuzzy, php-format
|
||||
msgid "The extraction of the file '%s' succeeded"
|
||||
msgstr "Le mot de passe de l'utilisateur %s à été modifié avec succés"
|
||||
msgstr "L'extraction du fichier '%s' a été effectuée avec succés"
|
||||
|
||||
#: ../admin/bro_main.php:180 ../class/m_bro.php:74
|
||||
msgid "File browser"
|
||||
|
@ -2713,12 +2702,10 @@ msgid "Folder %s is protected"
|
|||
msgstr ""
|
||||
|
||||
#: ../admin/hta_doadduser.php:45
|
||||
#, fuzzy, php-format
|
||||
msgid "The user %s was added to the protected folder %s"
|
||||
msgstr "Modification de l'utilisateur %s dans le répertoire protégé %s"
|
||||
msgstr "L'utilisateur %s a été ajouté au répertoire protégé %s"
|
||||
|
||||
#: ../admin/hta_dodeluser.php:39
|
||||
#, fuzzy, php-format
|
||||
msgid "The user '%s' was successfully deleted"
|
||||
msgstr "L'utilisateur %s a été effacée avec succès"
|
||||
|
||||
|
@ -4273,9 +4260,8 @@ msgid "Create this new MySQL user"
|
|||
msgstr "Créer ce nouvel utilisateur MySQL"
|
||||
|
||||
#: ../admin/sql_users_del.php:38 ../class/m_mysql.php:770
|
||||
#, fuzzy, php-format
|
||||
msgid "The user '%s' has been successfully deleted"
|
||||
msgstr "L'utilisateur %s a été effacée avec succès"
|
||||
msgstr "L'utilisateur MySQL %s a été effacé avec succès"
|
||||
|
||||
#: ../admin/sql_users_del.php:49
|
||||
msgid "MySQL users"
|
||||
|
@ -4294,14 +4280,12 @@ msgid "Yes, delete the MySQL user"
|
|||
msgstr "Oui, effacer cet utilisateur MySQL"
|
||||
|
||||
#: ../admin/sql_users_doadd.php:41 ../admin/sql_users_doadd.php:50
|
||||
#, fuzzy, php-format
|
||||
msgid "The user '%s' has been successfully created."
|
||||
msgstr "L'utilisateur %s a été effacée avec succès"
|
||||
msgstr "L'utilisateur %s a été ajouté avec succès"
|
||||
|
||||
#: ../admin/sql_users_dopassword.php:35
|
||||
#, fuzzy, php-format
|
||||
msgid "Password changed for user '%s'."
|
||||
msgstr "Permettre le changement de mot de passe ?"
|
||||
msgstr "Mot de passe changé pour l'utilisateur '%s'."
|
||||
|
||||
#: ../admin/sql_users_dorights.php:49
|
||||
msgid "The rights has been successfully applied to the user"
|
||||
|
|
|
@ -14,8 +14,8 @@ PATH=/usr/local/sbin:/usr/local/bin:/usr/sbin:/usr/bin:/sbin:/bin
|
|||
0 5 * * * alterncpanel /usr/lib/alternc/sqlbackup.sh -t daily
|
||||
0 4 * * 0 alterncpanel /usr/lib/alternc/sqlbackup.sh -t weekly
|
||||
|
||||
# Every 5 minutes, spool waiting domain changes
|
||||
*/5 * * * * root /usr/lib/alternc/update_domains.sh
|
||||
# Every minute, spool waiting domain changes
|
||||
* * * * * root /usr/lib/alternc/update_domains.php
|
||||
|
||||
# Every 5 minutes, do mails actions
|
||||
*/5 * * * * root /usr/lib/alternc/update_mails.sh
|
||||
|
|
|
@ -42,8 +42,9 @@ case "$1" in
|
|||
|
||||
# corriger les permissions du chroot
|
||||
mkdir -p /var/spool/postfix/var/run/saslauthd || true
|
||||
dpkg-statoverride --quiet --update --add root sasl 710 /var/spool/postfix/var/run/saslauthd || true
|
||||
|
||||
if ! dpkg-statoverride --list /var/spool/postfix/var/run/saslauthd >/dev/null ; then
|
||||
dpkg-statoverride --quiet --update --add root sasl 710 /var/spool/postfix/var/run/saslauthd || true
|
||||
fi
|
||||
|
||||
db_get "alternc/alternc_mail"
|
||||
VMAIL_HOME="$RET"
|
||||
|
|
|
@ -59,12 +59,13 @@ Depends: debianutils (>= 1.13.1)
|
|||
, opendkim-tools
|
||||
, dovecot-sieve
|
||||
, dovecot-managesieved
|
||||
, default-mysql-client
|
||||
, default-mysql-client | mysql-client | mariadb-client
|
||||
, php5-curl | php7.0-curl
|
||||
, quota
|
||||
, pwgen
|
||||
, lsb-release
|
||||
, ${misc:Depends}
|
||||
Recommends: default-mysql-server
|
||||
Recommends: default-mysql-server | mysql-server | mariadb-server
|
||||
, ntp
|
||||
, unzip
|
||||
, bzip2
|
||||
|
@ -148,8 +149,9 @@ Depends: debianutils (>= 1.13.1)
|
|||
, opendkim-tools
|
||||
, dovecot-sieve
|
||||
, dovecot-managesieved
|
||||
, default-mysql-client
|
||||
, php5-curl
|
||||
, default-mysql-client | mysql-client | mariadb-client
|
||||
, php5-curl | php7.0-curl
|
||||
, lsb-release
|
||||
, ${misc:Depends}
|
||||
Recommends:
|
||||
quota
|
||||
|
|
|
@ -14,6 +14,7 @@ AssignUserId www-data www-data
|
|||
Options +FollowSymLinks
|
||||
AllowOverride None
|
||||
Require all denied
|
||||
Satisfy Any
|
||||
</Directory>
|
||||
#### End security parameters
|
||||
|
||||
|
|
|
@ -5,10 +5,6 @@
|
|||
DocumentRoot /usr/share/alternc/panel/admin
|
||||
ServerName %%fqdn%%
|
||||
|
||||
# Mail autoconfig
|
||||
ServerAlias autoconfig.*
|
||||
ServerAlias autodiscover.*
|
||||
|
||||
RewriteEngine on
|
||||
RewriteRule ^/admin/(.*) /$1 [R=301,L]
|
||||
|
||||
|
@ -17,20 +13,6 @@
|
|||
RewriteEngine On
|
||||
RewriteRule ^webmail /webmail-redirect.php [L]
|
||||
|
||||
# Mail autoconfig
|
||||
RewriteRule ^/mail/mailautoconfig.xml$ /mailautoconfig_thunderbird.php [L]
|
||||
RewriteRule ^/mail/config-v1.1.xml$ /mailautoconfig_thunderbird.php [L]
|
||||
RewriteRule ^mail/mailautoconfig.xml$ /mailautoconfig_thunderbird.php [L]
|
||||
RewriteRule ^mail/config-v1.1.xml$ /mailautoconfig_thunderbird.php [L]
|
||||
RewriteRule ^/autodiscover/autodiscover.xml$ /mailautoconfig_outlook.php [L]
|
||||
RewriteRule ^/Autodiscover/Autodiscover.xml$ /mailautoconfig_outlook.php [L]
|
||||
RewriteRule ^/Autodiscover.xml$ mailautoconfig_outlook.php [L]
|
||||
RewriteRule ^/autodiscover.xml$ mailautoconfig_outlook.php [L]
|
||||
RewriteRule ^autodiscover/autodiscover.xml$ /mailautoconfig_outlook.php [L]
|
||||
RewriteRule ^Autodiscover/Autodiscover.xml$ /mailautoconfig_outlook.php [L]
|
||||
RewriteRule ^Autodiscover.xml$ mailautoconfig_outlook.php [L]
|
||||
RewriteRule ^autodiscover.xml$ mailautoconfig_outlook.php [L]
|
||||
|
||||
|
||||
# will be used to define aliases such as /javascript /webmail /squirrelmail ...
|
||||
IncludeOptional /etc/alternc/apache-panel.d/*.conf
|
||||
|
|
|
@ -0,0 +1,57 @@
|
|||
|
||||
<VirtualHost *:80>
|
||||
DocumentRoot /usr/share/alternc/panel/admin
|
||||
|
||||
AssignUserId alterncpanel alterncpanel
|
||||
SetEnv LOGIN "0000-panel"
|
||||
|
||||
ServerName %%fqdn%%
|
||||
|
||||
RewriteEngine On
|
||||
# Mail autoconfig
|
||||
RewriteRule ^/mail/mailautoconfig.xml$ /mailautoconfig_thunderbird.php [L]
|
||||
RewriteRule ^/mail/config-v1.1.xml$ /mailautoconfig_thunderbird.php [L]
|
||||
RewriteRule ^mail/mailautoconfig.xml$ /mailautoconfig_thunderbird.php [L]
|
||||
RewriteRule ^mail/config-v1.1.xml$ /mailautoconfig_thunderbird.php [L]
|
||||
RewriteRule ^/autodiscover/autodiscover.xml$ /mailautoconfig_outlook.php [L]
|
||||
RewriteRule ^/Autodiscover/Autodiscover.xml$ /mailautoconfig_outlook.php [L]
|
||||
RewriteRule ^/Autodiscover.xml$ mailautoconfig_outlook.php [L]
|
||||
RewriteRule ^/autodiscover.xml$ mailautoconfig_outlook.php [L]
|
||||
RewriteRule ^autodiscover/autodiscover.xml$ /mailautoconfig_outlook.php [L]
|
||||
RewriteRule ^Autodiscover/Autodiscover.xml$ /mailautoconfig_outlook.php [L]
|
||||
RewriteRule ^Autodiscover.xml$ mailautoconfig_outlook.php [L]
|
||||
RewriteRule ^autodiscover.xml$ mailautoconfig_outlook.php [L]
|
||||
RewriteRule (.*) - [F]
|
||||
|
||||
</VirtualHost>
|
||||
|
||||
<VirtualHost *:443>
|
||||
DocumentRoot /usr/share/alternc/panel/admin
|
||||
|
||||
AssignUserId alterncpanel alterncpanel
|
||||
SetEnv LOGIN "0000-panel"
|
||||
|
||||
ServerName %%fqdn%%
|
||||
|
||||
RewriteEngine On
|
||||
# Mail autoconfig
|
||||
RewriteRule ^/mail/mailautoconfig.xml$ /mailautoconfig_thunderbird.php [L]
|
||||
RewriteRule ^/mail/config-v1.1.xml$ /mailautoconfig_thunderbird.php [L]
|
||||
RewriteRule ^mail/mailautoconfig.xml$ /mailautoconfig_thunderbird.php [L]
|
||||
RewriteRule ^mail/config-v1.1.xml$ /mailautoconfig_thunderbird.php [L]
|
||||
RewriteRule ^/autodiscover/autodiscover.xml$ /mailautoconfig_outlook.php [L]
|
||||
RewriteRule ^/Autodiscover/Autodiscover.xml$ /mailautoconfig_outlook.php [L]
|
||||
RewriteRule ^/Autodiscover.xml$ mailautoconfig_outlook.php [L]
|
||||
RewriteRule ^/autodiscover.xml$ mailautoconfig_outlook.php [L]
|
||||
RewriteRule ^autodiscover/autodiscover.xml$ /mailautoconfig_outlook.php [L]
|
||||
RewriteRule ^Autodiscover/Autodiscover.xml$ /mailautoconfig_outlook.php [L]
|
||||
RewriteRule ^Autodiscover.xml$ mailautoconfig_outlook.php [L]
|
||||
RewriteRule ^autodiscover.xml$ mailautoconfig_outlook.php [L]
|
||||
RewriteRule (.*) - [F]
|
||||
|
||||
SSLEngine On
|
||||
SSLCertificateFile %%CRT%%
|
||||
SSLCertificateKeyFile %%KEY%%
|
||||
%%CHAINLINE%%
|
||||
|
||||
</VirtualHost>
|
|
@ -7,6 +7,7 @@
|
|||
<Directory "%%document_root%%">
|
||||
php_admin_value open_basedir "%%account_root%%:/usr/share/php/"
|
||||
php_admin_value upload_tmp_dir %%account_root%%/tmp
|
||||
php_admin_value sys_temp_dir %%account_root%%/tmp
|
||||
php_admin_value sendmail_path '/usr/lib/alternc/sendmail "%%mail_account%%" '
|
||||
php_admin_flag mail.add_x_header on
|
||||
Options +MultiViews -FollowSymLinks +SymLinksIfOwnerMatch
|
||||
|
@ -21,6 +22,7 @@
|
|||
<Directory "%%document_root%%">
|
||||
php_admin_value open_basedir "%%account_root%%:/usr/share/php/"
|
||||
php_admin_value upload_tmp_dir %%account_root%%/tmp
|
||||
php_admin_value sys_temp_dir %%account_root%%/tmp
|
||||
php_admin_value sendmail_path '/usr/lib/alternc/sendmail "%%mail_account%%" '
|
||||
php_admin_flag mail.add_x_header on
|
||||
Options +MultiViews -FollowSymLinks +SymLinksIfOwnerMatch
|
||||
|
|
|
@ -8,10 +8,12 @@
|
|||
RewriteCond %{REQUEST_FILENAME} !/cgi-bin/
|
||||
RewriteCond %{REQUEST_FILENAME} !/.well-known/acme-challenge/
|
||||
RewriteRule ^/(.*)$ http://%%fqdn%%/$1 [R=301,L]
|
||||
|
||||
SSLEngine On
|
||||
SSLCertificateFile %%CRT%%
|
||||
SSLCertificateKeyFile %%KEY%%
|
||||
%%CHAINLINE%%
|
||||
|
||||
</Virtualhost>
|
||||
<VirtualHost *:80>
|
||||
ServerName %%fqdn%%
|
||||
|
@ -21,6 +23,7 @@
|
|||
<Directory "%%document_root%%">
|
||||
php_admin_value open_basedir "%%account_root%%:/usr/share/php/"
|
||||
php_admin_value upload_tmp_dir %%account_root%%/tmp
|
||||
php_admin_value sys_temp_dir %%account_root%%/tmp
|
||||
php_admin_value sendmail_path '/usr/lib/alternc/sendmail "%%mail_account%%" '
|
||||
php_admin_flag mail.add_x_header on
|
||||
Options -MultiViews -FollowSymLinks +SymLinksIfOwnerMatch
|
||||
|
|
|
@ -17,6 +17,7 @@
|
|||
<Directory "%%document_root%%">
|
||||
php_admin_value open_basedir "%%account_root%%:/usr/share/php/"
|
||||
php_admin_value upload_tmp_dir %%account_root%%/tmp
|
||||
php_admin_value sys_temp_dir %%account_root%%/tmp
|
||||
php_admin_value sendmail_path '/usr/lib/alternc/sendmail "%%mail_account%%" '
|
||||
php_admin_flag mail.add_x_header on
|
||||
Options +MultiViews -FollowSymLinks +SymLinksIfOwnerMatch
|
||||
|
|
|
@ -5,6 +5,7 @@
|
|||
acl "allslaves" {
|
||||
{
|
||||
127.0.0.1;
|
||||
::1;
|
||||
//AUTO-SLAVES//
|
||||
};
|
||||
};
|
||||
|
|
|
@ -1 +1 @@
|
|||
zone "@@DOMAINE@@" { type master; file "@@ZONE_FILE@@"; allow-query { any; }; };
|
||||
zone "@@DOMAIN@@" { type master; file "@@ZONE_FILE@@"; allow-query { any; }; };
|
||||
|
|
|
@ -76,6 +76,14 @@ fi
|
|||
|
||||
. /usr/lib/alternc/functions.sh
|
||||
|
||||
# get the information on running Sysv or Systemd init & boot system
|
||||
if [ -e /run/systemd/system ]
|
||||
then
|
||||
SYSTEMD=1
|
||||
else
|
||||
SYSTEMD=0
|
||||
fi
|
||||
|
||||
# Lock the jobs !
|
||||
lock_jobs
|
||||
|
||||
|
@ -91,7 +99,7 @@ TEMPLATE_DIR="/etc/alternc/templates"
|
|||
|
||||
# Find needed configuration files (without the initial '/')
|
||||
# replace this one unconditionnally
|
||||
CONFIG_FILES="etc/alternc/bureau.conf etc/apache2/envvars etc/alternc/apache2.conf etc/alternc/apache_logformat.conf etc/alternc/phpmyadmin.inc.php"
|
||||
CONFIG_FILES="etc/alternc/bureau.conf etc/apache2/envvars etc/alternc/apache2.conf etc/alternc/phpmyadmin.inc.php"
|
||||
|
||||
if [ -e /etc/bind/named.conf ]; then
|
||||
CONFIG_FILES="$CONFIG_FILES etc/bind/named.conf.options"
|
||||
|
@ -365,9 +373,8 @@ do
|
|||
fi
|
||||
done
|
||||
|
||||
# ensure dovecot, postfix, apache, can access ssl certificates:
|
||||
# ensure dovecot, postfix, can access ssl certificates:
|
||||
adduser dovecot ssl-cert
|
||||
adduser www-data ssl-cert
|
||||
adduser postfix ssl-cert
|
||||
|
||||
run-parts --arg=certificates /usr/lib/alternc/install.d
|
||||
|
@ -377,7 +384,6 @@ if [ -x /usr/sbin/apache2 ]; then
|
|||
run-parts --arg=apache2 /usr/lib/alternc/install.d
|
||||
a2enmod mpm_itk
|
||||
|
||||
s="apache2"
|
||||
# unused from AlternC 1.0, FIXME: remove it later
|
||||
if [ -L /etc/apache2/mods-enabled/vhost_alias.load ]
|
||||
then
|
||||
|
@ -410,7 +416,7 @@ if [ -x /usr/sbin/apache2 ]; then
|
|||
a2enconf alternc
|
||||
fi
|
||||
|
||||
SERVICES="$SERVICES $s"
|
||||
SERVICES="$SERVICES apache2"
|
||||
fi
|
||||
|
||||
# Manage sudoers.d include appearing in Squeeze:
|
||||
|
@ -608,6 +614,9 @@ fi
|
|||
chmod 640 /var/log/alternc/bureau.log /var/log/alternc/update_domains.log
|
||||
chown alterncpanel:adm /var/log/alternc/bureau.log /var/log/alternc/update_domains.log
|
||||
|
||||
# Launch a script that will populate AlternC variables as needed
|
||||
su - alterncpanel -s /bin/bash -c /usr/share/alternc/install/variables.php
|
||||
|
||||
# Creating admin user if needed
|
||||
HAS_ROOT=`mysql --defaults-file=/etc/alternc/my.cnf -e "SELECT COUNT(*) FROM membres WHERE login = 'admin' OR login = 'root' and su = 1" | tail -1`
|
||||
|
||||
|
@ -668,6 +677,16 @@ if [ "$(lsb_release -s -c)" == 'stretch' ] ; then
|
|||
systemctl daemon-reload
|
||||
fi
|
||||
|
||||
if [ "$SYSTEMD" = "1" -a "$(lsb_release -s -c)" = "stretch" ] ; then
|
||||
/lib/opendkim/opendkim.service.generate
|
||||
# Without adding '-u opendkim' after the service file is generated, opendkim
|
||||
# will run as root, which we do not want.
|
||||
if [ "$(grep -c 'u opendkim' /etc/systemd/system/opendkim.service.d/override.conf)" == 0 ] ; then
|
||||
sed -i -e 's/inet:8891@127.0.0.1/& -u opendkim/' /etc/systemd/system/opendkim.service.d/override.conf
|
||||
fi
|
||||
systemctl daemon-reload
|
||||
fi
|
||||
|
||||
# Add opendkim to service to restart
|
||||
SERVICES="$SERVICES opendkim bind9"
|
||||
|
||||
|
|
|
@ -115,7 +115,7 @@ CREATE TABLE IF NOT EXISTS domaines (
|
|||
noerase tinyint(4) NOT NULL default '0',
|
||||
dns_action enum ('OK','UPDATE','DELETE') NOT NULL default 'UPDATE',
|
||||
dns_result varchar(255) not null default '',
|
||||
zonettl int(10) unsigned NOT NULL default '86400',
|
||||
zonettl int(10) unsigned NOT NULL default '3600',
|
||||
PRIMARY KEY (id),
|
||||
UNIQUE KEY (domaine)
|
||||
) ENGINE=InnoDB;
|
||||
|
@ -479,16 +479,11 @@ CREATE TABLE IF NOT EXISTS `domaines_type` (
|
|||
PRIMARY KEY ( `name` )
|
||||
) ENGINE=InnoDB COMMENT = 'Type of domains allowed';
|
||||
|
||||
INSERT IGNORE INTO `domaines_type` (name, description, target, entry, compatibility, only_dns, need_dns, advanced, enable, has_https_option) values
|
||||
INSERT IGNORE INTO `domaines_type` (name, description, target, entry, compatibility, only_dns, need_dns, advanced, enable,has_https_option) VALUES
|
||||
-- Default vhost type to maintains compatibility across versions.
|
||||
-- This is overloaded depending on the value of the https column in sub_domaines
|
||||
('vhost', 'Locally hosted', 'DIRECTORY', '%SUB% IN A @@PUBLIC_IP@@', 'txt,defmx,defmx2,mx,mx2', false, false, false, 'ALL', true),
|
||||
-- The following 3 types (vhost-http, vhost-https, vhost-both) are overloads for vhost
|
||||
-- and are "disabled" to not be available from the interface, but still be valid domaine types
|
||||
-- when checking in m_ssl::updateDomain.
|
||||
('vhost-http','Locally hosted with http->https', 'DIRECTORY', '%SUB% IN A @@PUBLIC_IP@@', 'txt,defmx,defmx2,mx,mx2', false, false, false, 'NONE', false),
|
||||
('vhost-https','Locally hosted with http->https', 'DIRECTORY', '%SUB% IN A @@PUBLIC_IP@@', 'txt,defmx,defmx2,mx,mx2', false, false, false, 'NONE', false),
|
||||
('vhost-both', 'Locally hosted with http and https', 'DIRECTORY', '%SUB% IN A @@PUBLIC_IP@@', 'txt,defmx,defmx2,mx,mx2', false, false, false, 'NONE', false),
|
||||
('dkim', 'DKIM Key', 'TXT', '%SUB% IN TXT "%TARGET%"', 'txt,defmx,defmx2,mx,mx2,url,ip,ipv6', true, true, true, 'ADMIN', false),
|
||||
('autodiscover', 'Email autoconfiguration', 'NONE', '%SUB% IN A @@PUBLIC_IP@@', 'txt,defmx,defmx2,mx,mx2', false, true, true, 'ADMIN', false),
|
||||
('url', 'URL redirection', 'URL', '%SUB% IN A @@PUBLIC_IP@@', 'txt,defmx,defmx2', false, false, false, 'ALL', false),
|
||||
('ip', 'IPv4 redirect', 'IP', '%SUB% IN A %TARGET%', 'url,ip,ipv6,txt,mx,mx2,defmx,defmx2', true, true, false, 'ALL', false),
|
||||
('ipv6', 'IPv6 redirect', 'IPV6', '%SUB% IN AAAA %TARGET%', 'ip,ipv6,txt,mx,mx2,defmx,defmx2', true, true, true, 'ALL', false),
|
||||
|
@ -801,7 +796,6 @@ CREATE TABLE IF NOT EXISTS `certificates` (
|
|||
|
||||
|
||||
|
||||
-- make it re-exec-proof
|
||||
DELETE FROM alternc_status WHERE name='alternc_version';
|
||||
INSERT INTO alternc_status SET name='alternc_version',value='3.5.0.1.sql';
|
||||
-- make it re-exec-proof -- BUT don't overwrite existing value !
|
||||
INSERT IGNORE INTO alternc_status SET name='alternc_version',value='3.5.0.2.php';
|
||||
|
||||
|
|
|
@ -1,13 +1,22 @@
|
|||
-- upgrade from 3.4.10 and 3.4.11 (a bug prevented them to be inserted :/ )
|
||||
|
||||
-- migrating DKIM to be inside sub_domaines table
|
||||
INSERT IGNORE INTO `domaines_type` (name, description, target, entry, compatibility, only_dns, need_dns, advanced, enable) VALUES
|
||||
('dkim', 'DKIM Key', 'TXT', '%SUB% IN TXT "%TARGET%"', 'txt,defmx,defmx2,mx,mx2,url,ip,ipv6', true, true, true, 'ADMIN');
|
||||
-- migrating AUTODISCOVER / AUTOCONF to be inside sub_domaines table
|
||||
INSERT IGNORE INTO `domaines_type` (name, description, target, entry, compatibility, only_dns, need_dns, advanced, enable) VALUES
|
||||
('autodiscover', 'Email autoconfiguration', 'NONE', '%SUB% IN A @@PUBLIC_IP@@', 'txt,defmx,defmx2,mx,mx2', false, true, true, 'ADMIN');
|
||||
|
||||
|
||||
-- upgrade from 3.4.10 and 3.4.11 (a bug prevented them to be inserted :/ )
|
||||
ALTER TABLE mailbox MODIFY `lastlogin` DATETIME NOT NULL DEFAULT 0;
|
||||
ALTER TABLE mailbox ADD `lastloginsasl` DATETIME NOT NULL DEFAULT 0 AFTER `lastlogin`;
|
||||
ALTER TABLE `domaines` MODIFY `zonettl` INT(10) UNSIGNED NOT NULL default '3600';
|
||||
|
||||
ALTER TABLE `membres` MODIFY `pass` varchar(255);
|
||||
ALTER TABLE `ftpusers` MODIFY `encrypted_password` varchar(255);
|
||||
-- upgrade to better hashes ($6$, 20000 loops) in membres and ftpusers
|
||||
ALTER TABLE `membres` MODIFY `pass` VARCHAR(255);
|
||||
ALTER TABLE `ftpusers` MODIFY `encrypted_password` VARCHAR(255);
|
||||
|
||||
-- upgrade to merge alternc-ssl into alternc + change the way we work on SSL
|
||||
|
||||
DROP TABLE IF EXISTS `certif_alias`;
|
||||
|
||||
ALTER TABLE `certificates`
|
||||
|
@ -28,7 +37,8 @@ ALTER TABLE `domaines_type`
|
|||
UPDATE `domaines_type` SET `has_https_option`=1 WHERE name='vhost';
|
||||
|
||||
-- Backport old certif_hosts data to sub_domaines
|
||||
UPDATE `sub_domaines` LEFT JOIN `certif_hosts` ON `sub_domaines`.`id` = `certif_hosts`.`sub` SET `sub_domaines`.`certificate_id` = `certif_hosts`.`certif` WHERE 1;
|
||||
UPDATE `sub_domaines` LEFT JOIN `certif_hosts` ON `sub_domaines`.`id` = `certif_hosts`.`sub`
|
||||
SET `sub_domaines`.`certificate_id` = `certif_hosts`.`certif`;
|
||||
DROP TABLE IF EXISTS `certif_hosts`;
|
||||
|
||||
-- Set https status (http,https,both)
|
||||
|
@ -37,21 +47,22 @@ UPDATE `sub_domaines` SET `https` = "both" WHERE `type` LIKE '%-mixssl' AND http
|
|||
UPDATE `sub_domaines` SET `https` = "http" WHERE https = '';
|
||||
UPDATE `sub_domaines` SET `type` = REPLACE(`type`,'-ssl','');
|
||||
UPDATE `sub_domaines` SET `type` = REPLACE(`type`,'-mixssl','');
|
||||
-- Disable https status when domains_type don't provide this
|
||||
UPDATE `sub_domaines` SET `https` = '' WHERE type IN (select name FROM domaines_type WHERE has_https_option = 0);
|
||||
-- Disable https status when domains_type don't use it
|
||||
UPDATE `sub_domaines` SET `https` = '' WHERE type IN (SELECT name FROM domaines_type WHERE has_https_option = 0);
|
||||
|
||||
-- When two sudomain exists, we consider sub_domains with http and https feature
|
||||
-- When two subdomain exists, we consider sub_domains with http and https feature
|
||||
UPDATE sub_domaines AS sd INNER JOIN
|
||||
(SELECT MIN(id) id FROM `sub_domaines` GROUP BY domaine,sub,type HAVING count(id) > 1) sd1
|
||||
ON sd.id = sd1.id
|
||||
SET `https` = "both";
|
||||
-- Delete duplicate lines
|
||||
DELETE sd1 FROM sub_domaines sd1, sub_domaines sd2 WHERE sd1.id > sd2.id AND sd1.domaine = sd2.domaine AND sd1.sub = sd2.sub AND sd1.type = sd2.type AND sd1.https <> '' AND sd2.https <> '';
|
||||
DELETE sd1 FROM sub_domaines sd1, sub_domaines sd2
|
||||
WHERE sd1.id > sd2.id AND sd1.domaine = sd2.domaine AND sd1.sub = sd2.sub AND sd1.type = sd2.type
|
||||
AND sd1.https <> '' AND sd2.https <> '';
|
||||
|
||||
-- we need to regenerate all vhost, they will be by AlternC.install
|
||||
-- UPDATE `sub_domaines` SET `web_action` = 'UPDATE';
|
||||
|
||||
|
||||
-- change some variable names :
|
||||
|
||||
UPDATE variable
|
||||
|
@ -72,6 +83,6 @@ DELETE FROM variable WHERE name IN (
|
|||
'ftp_human_name'
|
||||
);
|
||||
|
||||
-- we'd like to prepare IPv6 ;)
|
||||
-- we'd like to prepare for IPv6 ;)
|
||||
ALTER TABLE `domaines_type` CHANGE `entry` `entry` TEXT DEFAULT '';
|
||||
|
||||
|
|
|
@ -0,0 +1,33 @@
|
|||
#!/usr/bin/php -q
|
||||
<?php
|
||||
|
||||
// we don't check our AlternC session
|
||||
if(!chdir("/usr/share/alternc/panel"))
|
||||
exit(1);
|
||||
require("/usr/share/alternc/panel/class/config_nochk.php");
|
||||
|
||||
$db->query("SELECT * FROM domaines WHERE gesdns=1 AND gesmx=1;");
|
||||
$add=array();
|
||||
while ($db->next_record()) {
|
||||
$add[$db->Record["domaine"]]=$db->Record["compte"];
|
||||
}
|
||||
foreach($add as $domain => $id) {
|
||||
// Convert DKIM keys into SUB_DOMAINES table
|
||||
if (file_exists("/etc/opendkim/keys/".$domain."/alternc.txt")) {
|
||||
$dkim_key = $mail->dkim_get_entry($domain);
|
||||
if ($dkim_key) {
|
||||
// Add subdomain dkim entry
|
||||
$db->query("INSERT INTO sub_domaines
|
||||
SET compte=?, domaine=?, sub='@', valeur=?, type='dkim', web_action='OK', web_result=0, enable='ENABLED';",
|
||||
array($id, $domain, $dkim_key)
|
||||
);
|
||||
// Alternc.INSTALL WILL reload DNS zones anyway, so fear not we don't set dns_action="RELOAD" here.
|
||||
}
|
||||
}
|
||||
// Convert autodiscover into SUB_DOMAINES table
|
||||
$db->query("INSERT INTO sub_domaines
|
||||
SET compte=?, domaine=?, sub='@', valeur='', type='autodiscover', web_action='UPDATE', web_result=0, enable='ENABLED';",
|
||||
array($id, $domain)
|
||||
);
|
||||
}
|
||||
|
|
@ -0,0 +1,17 @@
|
|||
#!/usr/bin/php
|
||||
<?php
|
||||
/**
|
||||
* This script set the required variables for AlternC at install time.
|
||||
* only create missing variable, don't overwrite them
|
||||
*/
|
||||
|
||||
// bootstrap
|
||||
if(!chdir("/usr/share/alternc/panel"))
|
||||
exit(1);
|
||||
require("/usr/share/alternc/panel/class/config_nochk.php");
|
||||
|
||||
variable_set('default_spf_value','a mx ?all', 'This variable (if set) tells the SPF/TXT DNS field that will be published as a SPF entry, telling which server(s) are allowed to send email for this one. You can still change it later in the advanced DNS entries for ONE domain, this entry is only set once for new domains (or when you change it here).');
|
||||
|
||||
variable_set('default_dmarc_value', 'p=none;pct=100;rua=%%ADMINMAIL%%;aspf=r;adkim=r', 'This variable (if set) tells the DMARC/TXT DNS field that will be published as a DMARC entry, telling which policy you apply to this domain name. You can still change it later in the advanced DNS entries for ONE domain, this entry is only set once for new domains (or when you change it here). You can use %%ADMINMAIL%% or %%USERMAIL%% to substitute to admin-account or alternc user-account email address.');
|
||||
// strict dmarc would be 'p=reject;pct=100;rua=%%ADMINMAIL%%;aspf=s;adkim=s'
|
||||
|
|
@ -5,6 +5,8 @@
|
|||
*/
|
||||
use PHPUnit\Framework\TestCase;
|
||||
use PHPUnit\DbUnit\TestCaseTrait;
|
||||
use PHPUnit\DbUnit\DataSet\YamlDataSet;
|
||||
use PHPUnit\DbUnit\DataSet\CompositeDataSet;
|
||||
|
||||
abstract class AlterncTest extends TestCase
|
||||
{
|
||||
|
@ -40,10 +42,10 @@ abstract class AlterncTest extends TestCase
|
|||
if( !is_file($file) ){
|
||||
throw new \Exception("missing $file");
|
||||
}
|
||||
$dataSet = new PHPUnit_Extensions_Database_DataSet_YamlDataSet($file);
|
||||
$dataSet = new YamlDataSet($file);
|
||||
$datasetList[] = $dataSet;
|
||||
}
|
||||
$compositeDataSet = new PHPUnit_Extensions_Database_DataSet_CompositeDataSet($datasetList);
|
||||
$compositeDataSet = new CompositeDataSet($datasetList);
|
||||
return $dataSet;
|
||||
}
|
||||
|
||||
|
|
|
@ -174,7 +174,7 @@ class m_actionTest extends AlterncTest {
|
|||
*/
|
||||
public function testPurge() {
|
||||
$result = $this->object->purge();
|
||||
$this->assertEquals(0, $result);
|
||||
$this->assertEquals(1, $result);
|
||||
$expectedTable = $this->loadDataSet("actions-empty.yml")->getTable("actions");
|
||||
$currentTable = $this->getConnection()->createQueryTable('actions', 'SELECT * FROM actions');
|
||||
$this->assertTablesEqual($expectedTable, $currentTable);
|
||||
|
|
|
@ -690,101 +690,6 @@ class m_domTest extends TestCase
|
|||
);
|
||||
}
|
||||
|
||||
/**
|
||||
* @covers m_dom::generation_parameters
|
||||
* @todo Implement testGeneration_parameters().
|
||||
*/
|
||||
public function testGeneration_parameters()
|
||||
{
|
||||
// Remove the following lines when you implement this test.
|
||||
$this->markTestIncomplete(
|
||||
'This test has not been implemented yet.'
|
||||
);
|
||||
}
|
||||
|
||||
/**
|
||||
* @covers m_dom::generation_domains_type
|
||||
* @todo Implement testGeneration_domains_type().
|
||||
*/
|
||||
public function testGeneration_domains_type()
|
||||
{
|
||||
// Remove the following lines when you implement this test.
|
||||
$this->markTestIncomplete(
|
||||
'This test has not been implemented yet.'
|
||||
);
|
||||
}
|
||||
|
||||
/**
|
||||
* @covers m_dom::generate_conf_oldhook
|
||||
* @todo Implement testGenerate_conf_oldhook().
|
||||
*/
|
||||
public function testGenerate_conf_oldhook()
|
||||
{
|
||||
// Remove the following lines when you implement this test.
|
||||
$this->markTestIncomplete(
|
||||
'This test has not been implemented yet.'
|
||||
);
|
||||
}
|
||||
|
||||
/**
|
||||
* @covers m_dom::generate_apacheconf
|
||||
* @todo Implement testGenerate_apacheconf().
|
||||
*/
|
||||
public function testGenerate_apacheconf()
|
||||
{
|
||||
// Remove the following lines when you implement this test.
|
||||
$this->markTestIncomplete(
|
||||
'This test has not been implemented yet.'
|
||||
);
|
||||
}
|
||||
|
||||
/**
|
||||
* @covers m_dom::generation_todo
|
||||
* @todo Implement testGeneration_todo().
|
||||
*/
|
||||
public function testGeneration_todo()
|
||||
{
|
||||
// Remove the following lines when you implement this test.
|
||||
$this->markTestIncomplete(
|
||||
'This test has not been implemented yet.'
|
||||
);
|
||||
}
|
||||
|
||||
/**
|
||||
* @covers m_dom::subdomain_modif_are_done
|
||||
* @todo Implement testSubdomain_modif_are_done().
|
||||
*/
|
||||
public function testSubdomain_modif_are_done()
|
||||
{
|
||||
// Remove the following lines when you implement this test.
|
||||
$this->markTestIncomplete(
|
||||
'This test has not been implemented yet.'
|
||||
);
|
||||
}
|
||||
|
||||
/**
|
||||
* @covers m_dom::set_dns_action
|
||||
* @todo Implement testSet_dns_action().
|
||||
*/
|
||||
public function testSet_dns_action()
|
||||
{
|
||||
// Remove the following lines when you implement this test.
|
||||
$this->markTestIncomplete(
|
||||
'This test has not been implemented yet.'
|
||||
);
|
||||
}
|
||||
|
||||
/**
|
||||
* @covers m_dom::set_dns_result
|
||||
* @todo Implement testSet_dns_result().
|
||||
*/
|
||||
public function testSet_dns_result()
|
||||
{
|
||||
// Remove the following lines when you implement this test.
|
||||
$this->markTestIncomplete(
|
||||
'This test has not been implemented yet.'
|
||||
);
|
||||
}
|
||||
|
||||
/**
|
||||
* @covers m_dom::get_problems
|
||||
|
|
|
@ -320,6 +320,9 @@ class m_mailTest extends AlterncTest
|
|||
public function testCreate_alias()
|
||||
{
|
||||
// Test #1580
|
||||
$this->markTestIncomplete(
|
||||
'This test has not been implemented yet.'
|
||||
);
|
||||
}
|
||||
|
||||
/**
|
||||
|
|
|
@ -22,50 +22,58 @@
|
|||
# Purpose of file: Fix permission, ACL and ownership of AlternC's files
|
||||
# ----------------------------------------------------------------------
|
||||
#
|
||||
red () { echo -e "\e[31m$@ \e[0m" ; }
|
||||
usage () {
|
||||
[[ -n "$@" ]] && red "$@\n"
|
||||
cat<<End-of-message
|
||||
Four optionals argument to chose from
|
||||
-l string : a specific login to fix
|
||||
-u integer : a specific uid to fix
|
||||
-f string : a specific file to fix according to a given uid
|
||||
-d string : a specific subdirectory to fix according to a given uid
|
||||
|
||||
# four optionals argument to chose from
|
||||
# -l string : a specific login to fix
|
||||
# -u integer : a specific uid to fix
|
||||
# -f string : a specific file to fix according to a given uid
|
||||
# -d string : a specific subdirectory to fix according to a given uid
|
||||
|
||||
# The u and l switch are used to fix a given user whole directory including his base directory ($ALTERNC_HTML/<letter>/<login>/
|
||||
# The f and d switch are used to fix a given file or directory under the user's base directory. They use the base directory to get the permissions they should use.
|
||||
# Be sure to have correct base directory permissions before attemplting to fix use those two switch
|
||||
|
||||
The u and l switch are used to fix a given user whole directory including his base directory ($ALTERNC_HTML/<letter>/<login>/
|
||||
The f and d switch are used to fix a given file or directory under the user's base directory. They use the base directory to get the permissions they should use.
|
||||
Be sure to have correct base directory permissions before attemplting to fix use those two switch
|
||||
End-of-message
|
||||
exit 1
|
||||
}
|
||||
query="SELECT uid,login FROM membres ORDER BY login"
|
||||
sub_dir=""
|
||||
file=""
|
||||
LOCK_FIXPERMS="/etc/alternc/disable_all_fixperms"
|
||||
|
||||
if [ -f "$LOCK_FIXPERMS" ] ; then
|
||||
(
|
||||
echo " ------------- "
|
||||
echo '/!\ WARNING /!\ '
|
||||
echo "The fixperms script is disabled"
|
||||
echo "To enable it, delete $LOCK_FIXPERMS "
|
||||
echo " ------------- "
|
||||
) 1>&2
|
||||
exit 0
|
||||
|
||||
usage "
|
||||
------------------------------------
|
||||
/!\ WARNING /!\
|
||||
The fixperms script is disabled
|
||||
To enable it, delete $LOCK_FIXPERMS
|
||||
------------------------------------
|
||||
"
|
||||
|
||||
fi
|
||||
|
||||
while getopts "l:u:f:d:" optname
|
||||
|
||||
while getopts "hl:u:f:d:" optname
|
||||
do
|
||||
case "$optname" in
|
||||
"h") usage
|
||||
;;
|
||||
|
||||
"l")
|
||||
if [[ "$OPTARG" =~ ^[a-zA-Z0-9_]+$ ]] ; then
|
||||
query="SELECT uid,login FROM membres WHERE login LIKE '$OPTARG' ORDER BY login"
|
||||
else
|
||||
echo "Bad login provided"
|
||||
exit
|
||||
usage "Bad login provided"
|
||||
fi
|
||||
;;
|
||||
"u")
|
||||
if [[ "$OPTARG" =~ ^[0-9]+$ ]] ; then
|
||||
query="SELECT uid,login FROM membres WHERE uid LIKE '$OPTARG' ORDER BY login"
|
||||
else
|
||||
echo "Bad uid provided"
|
||||
exit
|
||||
usage "Bad uid provided"
|
||||
fi
|
||||
;;
|
||||
"f")
|
||||
|
@ -79,17 +87,14 @@ do
|
|||
echo $sub_dir
|
||||
;;
|
||||
"?")
|
||||
echo "Unknown option $OPTARG - stop processing"
|
||||
exit
|
||||
usage "Unknown option $OPTARG - stop processing"
|
||||
;;
|
||||
":")
|
||||
echo "No argument value for option $OPTARG - stop processing"
|
||||
exit
|
||||
usage "No argument value for option $OPTARG - stop processing"
|
||||
;;
|
||||
*)
|
||||
# Should not occur
|
||||
echo "Unknown error while processing options"
|
||||
exit
|
||||
usage "Unknown error while processing options"
|
||||
;;
|
||||
esac
|
||||
done
|
||||
|
|
|
@ -1,223 +0,0 @@
|
|||
#!/bin/bash
|
||||
# dns.sh next-gen by Fufroma
|
||||
|
||||
# Init some vars
|
||||
. /etc/alternc/local.sh
|
||||
. /usr/lib/alternc/functions.sh
|
||||
|
||||
# Init some other vars
|
||||
ZONE_TEMPLATE="/etc/alternc/templates/bind/templates/zone.template"
|
||||
NAMED_TEMPLATE="/etc/alternc/templates/bind/templates/named.template"
|
||||
NAMED_CONF="/var/lib/alternc/bind/automatic.conf"
|
||||
RNDC="/usr/sbin/rndc"
|
||||
|
||||
dns_zone_file() {
|
||||
echo "/var/lib/alternc/bind/zones/$1"
|
||||
}
|
||||
|
||||
dns_is_locked() {
|
||||
local domain=$1
|
||||
if [ ! -r "$(dns_zone_file $domain)" ] ; then
|
||||
return 1
|
||||
fi
|
||||
grep "LOCKED:YES" "$(dns_zone_file $domain)"
|
||||
return $?
|
||||
}
|
||||
|
||||
dns_get_serial() {
|
||||
local domain=$1
|
||||
local serial=$(( $(grep "; serial" $(dns_zone_file $domain) 2>/dev/null|awk '{ print $1;}') + 1 ))
|
||||
local serial2=$(date +%Y%m%d00)
|
||||
if [ $serial -gt $serial2 ] ; then
|
||||
echo $serial
|
||||
else
|
||||
echo $serial2
|
||||
fi
|
||||
}
|
||||
|
||||
dns_get_zonettl() {
|
||||
local domain=$1
|
||||
local zonettl=$(
|
||||
$MYSQL_DO "SELECT zonettl FROM domaines d WHERE d.domaine='$domain';"
|
||||
)
|
||||
# default value
|
||||
if [ "$zonettl" == "" ] ; then
|
||||
zonettl="86400"
|
||||
fi
|
||||
if [ "$zonettl" -eq "0" ] ; then
|
||||
zonettl="86400"
|
||||
fi
|
||||
echo $zonettl
|
||||
}
|
||||
|
||||
dns_chmod() {
|
||||
local domain=$1
|
||||
chgrp bind $(dns_zone_file $domain)
|
||||
chmod 640 $(dns_zone_file $domain)
|
||||
return 0
|
||||
}
|
||||
|
||||
dns_named_conf() {
|
||||
local domain=$1
|
||||
|
||||
if [ ! -f "$(dns_zone_file $domain)" ] ; then
|
||||
echo Error : no file $(dns_zone_file $domain)
|
||||
return 1
|
||||
fi
|
||||
|
||||
# Add the entry
|
||||
grep -q "\"${domain/./\\.}\"" "$NAMED_CONF"
|
||||
if [ $? -ne 0 ] ; then
|
||||
local tempo=$(cat "$NAMED_TEMPLATE")
|
||||
tempo=${tempo/@@DOMAINE@@/$domain}
|
||||
tempo=${tempo/@@ZONE_FILE@@/$(dns_zone_file $domain)}
|
||||
echo $tempo >> "$NAMED_CONF"
|
||||
# Kindly ask Bind to reload its configuration
|
||||
# (the zone file is already created and populated)
|
||||
$RNDC reconfig
|
||||
# Hook it !
|
||||
run-parts --arg=dns_reconfig --arg="$domain" /usr/lib/alternc/reload.d
|
||||
fi
|
||||
|
||||
}
|
||||
|
||||
dns_delete() {
|
||||
local domain=$1
|
||||
|
||||
# Delete the zone file
|
||||
if [ -w "$(dns_zone_file $domain)" ] ; then
|
||||
rm -f "$(dns_zone_file $domain)"
|
||||
fi
|
||||
|
||||
local reg_domain=${domain/./\\.}
|
||||
|
||||
# Remove from the named conf
|
||||
local file=$(cat "$NAMED_CONF")
|
||||
echo -e "$file" |grep -v "\"$reg_domain\"" > "$NAMED_CONF"
|
||||
|
||||
# Remove the conf from openDKIM
|
||||
rm -rf "/etc/opendkim/keys/$domain"
|
||||
grep -v "^$reg_domain\$" /etc/opendkim/TrustedHosts >/etc/opendkim/TrustedHosts.alternc-tmp && mv /etc/opendkim/TrustedHosts.alternc-tmp /etc/opendkim/TrustedHosts
|
||||
grep -v "^alternc\._domainkey\.$reg_domain " /etc/opendkim/KeyTable >/etc/opendkim/KeyTable.alternc-tmp && mv /etc/opendkim/KeyTable.alternc-tmp /etc/opendkim/KeyTable
|
||||
grep -v "^$domain alternc\._domainkey\.$reg_domain\$" /etc/opendkim/SigningTable >/etc/opendkim/SigningTable.alternc-tmp && mv /etc/opendkim/SigningTable.alternc-tmp /etc/opendkim/SigningTable
|
||||
|
||||
# Ask the dns server for restart
|
||||
$RNDC reconfig
|
||||
# Hook it !
|
||||
run-parts --arg=dns_reconfig --arg="$domain" /usr/lib/alternc/reload.d
|
||||
}
|
||||
|
||||
# DNS regenerate
|
||||
dns_regenerate() {
|
||||
local domain=$1
|
||||
local manual_tag=";;; END ALTERNC AUTOGENERATE CONFIGURATION"
|
||||
local zone_file=$(dns_zone_file $domain)
|
||||
|
||||
# Check if locked
|
||||
dns_is_locked "$domain"
|
||||
if [ $? -eq 0 ]; then
|
||||
echo "DNS $domain LOCKED"
|
||||
return 1
|
||||
fi
|
||||
|
||||
# Get the serial number if there is one
|
||||
local serial=$(dns_get_serial "$domain")
|
||||
|
||||
# Get the zone ttl
|
||||
local zonettl=$(dns_get_zonettl "$domain")
|
||||
|
||||
# Generate the headers with the template
|
||||
local file=$(cat "$ZONE_TEMPLATE")
|
||||
|
||||
# Add the entry
|
||||
file=$(
|
||||
echo -e "$file"
|
||||
$MYSQL_DO "select distinct replace(replace(dt.entry,'%TARGET%',sd.valeur), '%SUB%', if(length(sd.sub)>0,sd.sub,'@')) as entry from sub_domaines sd,domaines_type dt where sd.type=dt.name and sd.domaine='$domain' and sd.enable in ('ENABLE', 'ENABLED') order by entry ;"
|
||||
)
|
||||
|
||||
##### Mail autodetect for thunderbird / outlook - START
|
||||
# If $file contain DEFAULT_MX
|
||||
if [ ! -z "$(echo -e "$file" |egrep 'DEFAULT_MX' )" ] ; then
|
||||
# If $file ! contain autoconfig -> add entry
|
||||
if [ -z "$(echo -e "$file" |egrep '^autoconfig' )" ] ; then
|
||||
file="$(echo -e "$file" ; echo -e "autoconfig IN CNAME $FQDN.\n")"
|
||||
fi
|
||||
# if $file ! contain autodiscover -> add entry
|
||||
if [ -z "$(echo -e "$file" |egrep '^autodiscover' )" ] ; then
|
||||
file="$(echo -e "$file" ; echo -e "autodiscover IN CNAME $FQDN.\n")"
|
||||
fi
|
||||
fi # End if containt DEFAULT_MX
|
||||
##### Mail autodetect for thunderbird / outlook - END
|
||||
|
||||
##### OpenDKIM signature management - START
|
||||
# If $file contain DEFAULT_MX
|
||||
if [ ! -z "$(echo -e "$file" |egrep 'DEFAULT_MX' )" ] ; then
|
||||
# If necessary, we generate the key:
|
||||
if [ ! -d "/etc/opendkim/keys/$domain" ] ; then
|
||||
mkdir -p "/etc/opendkim/keys/$domain"
|
||||
|
||||
pushd "/etc/opendkim/keys/$domain" >/dev/null
|
||||
opendkim-genkey -r -d "$domain" -s "alternc"
|
||||
chown opendkim:opendkim alternc.private
|
||||
popd
|
||||
|
||||
local reg_domain=${domain/./\\.}
|
||||
|
||||
grep -q "^$reg_domain\$" /etc/opendkim/TrustedHosts || echo "$domain" >>/etc/opendkim/TrustedHosts
|
||||
grep -q "^alternc\._domainkey\.$reg_domain " /etc/opendkim/KeyTable || echo "alternc._domainkey.$domain $domain:alternc:/etc/opendkim/keys/$domain/alternc.private" >> /etc/opendkim/KeyTable
|
||||
grep -q "^$domain alternc\._domainkey\.$reg_domain\$" /etc/opendkim/SigningTable || echo "$domain alternc._domainkey.$domain" >> /etc/opendkim/SigningTable
|
||||
fi
|
||||
# we add alternc._domainkey with the proper key
|
||||
|
||||
if [ -r "/etc/opendkim/keys/$domain/alternc.txt" ] ; then
|
||||
file="$(echo -e "$file" ; cat "/etc/opendkim/keys/$domain/alternc.txt")"
|
||||
fi
|
||||
fi
|
||||
##### OpenDKIM signature management - END
|
||||
|
||||
# Replace the vars by their values
|
||||
# Here we can add dynamic value for the default MX
|
||||
file=$( echo -e "$file" | sed -e "
|
||||
s/%%fqdn%%/$FQDN/g;
|
||||
s/%%ns1%%/$NS1_HOSTNAME/g;
|
||||
s/%%ns2%%/$NS2_HOSTNAME/g;
|
||||
s/%%DEFAULT_MX%%/$DEFAULT_MX/g;
|
||||
s/%%DEFAULT_SECONDARY_MX%%/$DEFAULT_SECONDARY_MX/g;
|
||||
s/@@fqdn@@/$FQDN/g;
|
||||
s/@@ns1@@/$NS1_HOSTNAME/g;
|
||||
s/@@ns2@@/$NS2_HOSTNAME/g;
|
||||
s/@@DEFAULT_MX@@/$DEFAULT_MX/g;
|
||||
s/@@DEFAULT_SECONDARY_MX@@/$DEFAULT_SECONDARY_MX/g;
|
||||
s/@@DOMAINE@@/$domain/g;
|
||||
s/@@SERIAL@@/$serial/g;
|
||||
s/@@PUBLIC_IP@@/$PUBLIC_IP/g;
|
||||
s/@@ZONETTL@@/$zonettl/g;
|
||||
" )
|
||||
|
||||
# Add the manually entered resource records (after the special tag ;;; END ALTERNC AUTOGENERATE CONFIGURATION)
|
||||
if [ -r "$zone_file" ] ; then
|
||||
file=$(
|
||||
echo -e "$file"
|
||||
grep -A 10000 "$manual_tag" "$zone_file"
|
||||
)
|
||||
fi
|
||||
# Add the special tag at the end of the zone, if it is not here yet:
|
||||
if ! echo -e "$file" | grep -q "$manual_tag"
|
||||
then
|
||||
file=$(echo -e "$file"; echo "$manual_tag")
|
||||
fi
|
||||
|
||||
# Init the file
|
||||
echo -e "$file" > "$zone_file"
|
||||
|
||||
# And set his rights
|
||||
dns_chmod $domain
|
||||
# Add it to named conf
|
||||
dns_named_conf $domain
|
||||
|
||||
# Hook it !
|
||||
run-parts --arg=dns_reload_zone --arg="$domain" /usr/lib/alternc/reload.d
|
||||
|
||||
# ask bind to reload the zone
|
||||
$RNDC reload $domain
|
||||
}
|
|
@ -1,225 +0,0 @@
|
|||
#!/bin/bash
|
||||
|
||||
. /usr/lib/alternc/functions.sh
|
||||
|
||||
TEMPLATE_DIR="/etc/alternc/templates/apache2"
|
||||
HOSTING_DIR="/etc/alternc/functions_hosting"
|
||||
|
||||
HTML_HOME="$ALTERNC_HTML"
|
||||
VHOST_DIR="/var/lib/alternc/apache-vhost"
|
||||
|
||||
launch_hooks() {
|
||||
local ACTION=$1
|
||||
|
||||
if [ ! $2 ] ; then
|
||||
# If no VTYPE specified
|
||||
return 0
|
||||
fi
|
||||
|
||||
local VTYPE=$2
|
||||
|
||||
EXITCODE=0
|
||||
if [ -x "$HOSTING_DIR/hosting_$VTYPE.sh" ] ; then
|
||||
# If a specific script exist for this VTYPE,
|
||||
# we launch it, and return his return code
|
||||
"$HOSTING_DIR/hosting_$VTYPE.sh" "$1" "$2" "$3" "$4"
|
||||
EXITCODE=$?
|
||||
fi
|
||||
# also launch ssl update domains hook
|
||||
/usr/lib/alternc/update_certs.sh "$1" "$2" "$3" "$4"
|
||||
|
||||
# No specific script, return 0
|
||||
return "$EXITCODE"
|
||||
}
|
||||
|
||||
host_conffile() {
|
||||
# Return the absolute path of a conf file for a FQDN
|
||||
local FQDN="$1"
|
||||
local U_ID=$(get_uid_by_domain "$FQDN")
|
||||
local CONFFILE="$VHOST_DIR/${U_ID:(-1)}/$U_ID/$FQDN.conf"
|
||||
echo $CONFFILE
|
||||
return 0
|
||||
}
|
||||
|
||||
host_create() {
|
||||
# Function to create a vhost for a website
|
||||
# First, it look if there is a special file for
|
||||
# this type of vhost
|
||||
# If there isn't, it use the default function
|
||||
# and the template file provided
|
||||
|
||||
local VTYPE="$1"
|
||||
|
||||
launch_hooks "create" "$1" "$2" "$3" "$4"
|
||||
if [ $? -gt 10 ] ; then
|
||||
# If the hooks return a value > 10
|
||||
# it's mean we do not continue the
|
||||
# "default" actions
|
||||
return $?
|
||||
fi
|
||||
|
||||
# There is no special script, I use the standart template
|
||||
# If I do not found template manualy define, I look
|
||||
# If there is an existing template with the good name
|
||||
|
||||
# First, usefull vars. Some may be empty or false, it's
|
||||
# OK, it will be solve in the "case" below
|
||||
local FQDN=$2
|
||||
local MAIL_ACCOUNT=$3
|
||||
local REDIRECT=$4 # Yes, TARGET_DIR and REDIRECT are the same
|
||||
local TARGET_DIR=$4 # It's used by different template
|
||||
local U_ID=$(get_uid_by_domain "$FQDN")
|
||||
local G_ID="$U_ID"
|
||||
local USER=$(get_account_by_domain $FQDN)
|
||||
local user_letter=`print_user_letter "$USER"`
|
||||
local DOCUMENT_ROOT="${HTML_HOME}/${user_letter}/${USER}$TARGET_DIR"
|
||||
local ACCOUNT_ROOT="${HTML_HOME}/${user_letter}/${USER}/"
|
||||
local FILE_TARGET=$(host_conffile "$FQDN")
|
||||
|
||||
# In case VTYPE don't have the same name as the template file,
|
||||
# here we can define it
|
||||
local TEMPLATE=''
|
||||
case $VTYPE in
|
||||
# "example")
|
||||
# TEMPLATE="$TEMPLATE_DIR/an-example.conf"
|
||||
# ;;
|
||||
*)
|
||||
# No template found, look if there is some in the
|
||||
# template dir
|
||||
[ -r "$TEMPLATE_DIR/$VTYPE" ] && TEMPLATE="$TEMPLATE_DIR/$VTYPE"
|
||||
[ ! "$TEMPLATE" ] && [ -r "$TEMPLATE_DIR/$VTYPE.conf" ] && TEMPLATE="$TEMPLATE_DIR/$VTYPE.conf"
|
||||
;;
|
||||
esac
|
||||
|
||||
# If TEMPLATE is empty, stop right here
|
||||
[ ! "$TEMPLATE" ] && return 6
|
||||
|
||||
# Forbid generation for website with UID/GID == 0
|
||||
if [[ $U_ID == 0 || $G_ID == 0 ]] ; then
|
||||
log_error "Fatal error: update_domains/function_dns/host_create : FQDN = $FQDN - TYPE = $VTYPE - UID = $U_ID - GID = $G_ID . Stopping generation"
|
||||
return 7
|
||||
fi
|
||||
|
||||
# Create a new conf file
|
||||
local TMP_FILE=$(mktemp "/tmp/alternc_host.XXXXXX")
|
||||
cp "$TEMPLATE" "$TMP_FILE"
|
||||
|
||||
# Substitute special characters :
|
||||
FQDN2="`echo $FQDN | sed -e 's/\\\\/\\\\\\\\/g' -e 's/#/\\\\#/g' -e 's/&/\\\\\\&/g'`"
|
||||
DOCUMENT_ROOT2="`echo $DOCUMENT_ROOT | sed -e 's/\\\\/\\\\\\\\/g' -e 's/#/\\\\#/g' -e 's/&/\\\\\\&/g'`"
|
||||
ACCOUNT_ROOT2="`echo $ACCOUNT_ROOT | sed -e 's/\\\\/\\\\\\\\/g' -e 's/#/\\\\#/g' -e 's/&/\\\\\\&/g'`"
|
||||
REDIRECT2="`echo $REDIRECT | sed -e 's/\\\\/\\\\\\\\/g' -e 's/#/\\\\#/g' -e 's/&/\\\\\\&/g'`"
|
||||
USER2="`echo $USER | sed -e 's/\\\\/\\\\\\\\/g' -e 's/#/\\\\#/g' -e 's/&/\\\\\\&/g'`"
|
||||
|
||||
# Put the good value in the conf file
|
||||
sed -i \
|
||||
-e "s#%%LOGIN%%#$USER#g" \
|
||||
-e "s#%%fqdn%%#$FQDN2#g" \
|
||||
-e "s#%%document_root%%#$DOCUMENT_ROOT2#g" \
|
||||
-e "s#%%account_root%%#$ACCOUNT_ROOT2#g" \
|
||||
-e "s#%%redirect%%#$REDIRECT2#g" \
|
||||
-e "s#%%UID%%#$U_ID#g" \
|
||||
-e "s#%%GID%%#$G_ID#g" \
|
||||
-e "s#%%mail_account%%#$MAIL_ACCOUNT#g" \
|
||||
-e "s#%%user%%#$USER2#g" \
|
||||
$TMP_FILE
|
||||
|
||||
## Fix for wildcard
|
||||
if [[ "$FQDN2" == "*."* ]]; then
|
||||
sed -i "s/ServerName/ServerAlias/" $TMP_FILE
|
||||
fi
|
||||
|
||||
# Check if all is right in the conf file
|
||||
# If not, put a debug message
|
||||
# NO : redirect and document_root COULD contains legitimate %% expressions (...)
|
||||
# local ISNOTGOOD=$(grep "%%" "$TMP_FILE")
|
||||
# [ "$ISNOTGOOD" ] && (echo "# There was a probleme in the generation : $ISNOTGOOD" > "$TMP_FILE" ; return 44 )
|
||||
|
||||
# Put the conf file in prod
|
||||
mkdir -p "$(dirname "$FILE_TARGET")"
|
||||
mv -f "$TMP_FILE" "$FILE_TARGET"
|
||||
|
||||
# Execute post-install hooks
|
||||
launch_hooks "postinst" "$1" "$2" "$3" "$4"
|
||||
if [ $? -gt 10 ] ; then
|
||||
# If the hooks return a value > 10
|
||||
# it's mean we do not continue the
|
||||
# "default" actions
|
||||
return $?
|
||||
fi
|
||||
|
||||
# All is quit, we return 0
|
||||
return 0
|
||||
}
|
||||
|
||||
host_disable() {
|
||||
host_change_enable "disable" "$1" "$2" "$3" "$4"
|
||||
}
|
||||
|
||||
host_enable() {
|
||||
host_change_enable "enable" "$1" "$2" "$3" "$4"
|
||||
}
|
||||
|
||||
host_change_enable() {
|
||||
# Function to enable or disable a host
|
||||
local STATE=$1
|
||||
|
||||
# Execute hooks
|
||||
launch_hooks "$1" "$2" "$3" "$4"
|
||||
if [ $? -gt 10 ] ; then
|
||||
# If the hooks return a value > 10
|
||||
# it's mean we do not continue the
|
||||
# "default" actions
|
||||
return $?
|
||||
fi
|
||||
|
||||
local TYPE=$2 # no use here, but one day, maybe... So here he is
|
||||
local FQDN=$3
|
||||
local FENABLED=$(host_conffile "$FQDN")
|
||||
local FDISABLED="$FENABLED-disabled"
|
||||
|
||||
case $STATE in
|
||||
"enable")
|
||||
local SOURCE="$FDISABLED"
|
||||
local TARGET="$FENABLED"
|
||||
;;
|
||||
"disable")
|
||||
local TARGET="$FDISABLED"
|
||||
local SOURCE="$FENABLED"
|
||||
;;
|
||||
*)
|
||||
return 1
|
||||
;;
|
||||
esac
|
||||
|
||||
if [ ! -e "$TARGET" ] && [ -e "$SOURCE" ] ; then
|
||||
# If the "target" file do not exist and the "source" file exist
|
||||
mv -f "$SOURCE" "$TARGET"
|
||||
else
|
||||
return 2
|
||||
fi
|
||||
}
|
||||
|
||||
host_delete() {
|
||||
local VTYPE=$1
|
||||
local FQDN=$2
|
||||
# Execute post-install hooks
|
||||
launch_hooks "delete" "$1" "$2" "$3" "$4"
|
||||
if [ $? -gt 10 ] ; then
|
||||
# If the hooks return a value > 10
|
||||
# it's mean we do not continue the
|
||||
# "default" actions
|
||||
return $?
|
||||
fi
|
||||
|
||||
# Fix of a longstanding BUG: we only DELETE the vhost file if the type is a vhost one !
|
||||
if [ -f "${TEMPLATE_DIR}/${VTYPE}.conf" ]
|
||||
then
|
||||
local FENABLED=$(host_conffile "$FQDN")
|
||||
local FDISABLED="$FENABLED-disabled"
|
||||
|
||||
[ -w "$FENABLED" ] && rm -f "$FENABLED"
|
||||
[ -w "$FDISABLED" ] && rm -f "$FDISABLED"
|
||||
fi
|
||||
}
|
||||
|
|
@ -1,85 +0,0 @@
|
|||
#!/usr/bin/php -q
|
||||
<?php
|
||||
|
||||
/**
|
||||
*
|
||||
* Generate Apache configuration for AlternC
|
||||
*
|
||||
* To force generation, /launch/generate_apache_conf.php force
|
||||
*
|
||||
* Return the number of vhost modified, return 0 if no action
|
||||
*
|
||||
**/
|
||||
|
||||
require_once("/usr/share/alternc/panel/class/config_nochk.php");
|
||||
ini_set("display_errors", 1);
|
||||
|
||||
|
||||
/*
|
||||
|
||||
FIXME :
|
||||
- add security check
|
||||
*/
|
||||
|
||||
// Check if we can modify Apache conf
|
||||
@touch(ALTERNC_VHOST_FILE);
|
||||
if ( ! is_writable( ALTERNC_VHOST_FILE )) {
|
||||
die("Error: ".ALTERNC_VHOST_FILE." is not writable\n");
|
||||
}
|
||||
|
||||
// Do we need to regenerate apache conf ?
|
||||
$db->query("select count(*) as c from sub_domaines where web_action != 'OK';");
|
||||
if (! $db->next_record()) $nb_todo = 0;
|
||||
$nb_todo = $db->f('c');
|
||||
|
||||
// But, we may have forced it
|
||||
if ( ! in_array('force', $argv) && $nb_todo < 1) {
|
||||
die('0');
|
||||
}
|
||||
|
||||
$todo = $dom->generation_todo();
|
||||
$parameters = $dom->generation_parameters();
|
||||
|
||||
// Generate apache conf
|
||||
$conf = $dom->generate_apacheconf();
|
||||
|
||||
if (! $conf) {
|
||||
die("Error: generate empty configuration\n");
|
||||
}
|
||||
|
||||
// Add some headers
|
||||
$conf2 = "###BEGIN OF ALTERNC AUTO-GENERATED FILE - DO NOT EDIT MANUALLY###
|
||||
# Generation: ".date('Y-m-d H:i:s');
|
||||
|
||||
// Do we need to include manual configuration ?
|
||||
if ( is_dir( ALTERNC_VHOST_MANUALCONF ) ) {
|
||||
$conf2.="\n## Manual VHOST\nInclude ".ALTERNC_VHOST_MANUALCONF."\n" ;
|
||||
} else {
|
||||
$conf2.="\n## Manual VHOST directory missing (".ALTERNC_VHOST_MANUALCONF.")\n" ;
|
||||
}
|
||||
|
||||
$conf2.="\n$conf\n\n###END OF ALTERNC AUTO-GENERATED FILE - DO NOT EDIT MANUALLY###\n";
|
||||
|
||||
// Write the conf !
|
||||
if (! file_put_contents(ALTERNC_VHOST_FILE, $conf2) ) {
|
||||
die("Error: writing content\n");
|
||||
}
|
||||
|
||||
// Update the database to inform that we did the job
|
||||
foreach ( $todo as $taction=>$tlist){
|
||||
foreach ($tlist as $ttype) {
|
||||
foreach($ttype as $tid) {
|
||||
$dom->subdomain_modif_are_done($tid, $taction);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// Hooks !
|
||||
foreach (array('DELETE', 'CREATE', 'UPDATE', 'ENABLE', 'DISABLE') as $y) {
|
||||
if (!isset($todo[$y]) || empty($todo[$y])) continue;
|
||||
$dom->generate_conf_oldhook($y, $todo); // old hooks for compatibility
|
||||
$hooks->invoke("hook_genconf", array($y, $todo[$y], $parameters)); // modern hooks
|
||||
}
|
||||
|
||||
echo $nb_todo;
|
||||
|
|
@ -1,24 +0,0 @@
|
|||
#!/usr/bin/php -q
|
||||
<?php
|
||||
|
||||
/**
|
||||
*
|
||||
* Generate Bind configuration for AlternC
|
||||
*
|
||||
* To force generation, /launch/generate_bind_conf.php --force
|
||||
*
|
||||
*
|
||||
**/
|
||||
|
||||
require_once("/usr/share/alternc/panel/class/config_nochk.php");
|
||||
ini_set("display_errors", 1);
|
||||
|
||||
$bind = new system_bind();
|
||||
|
||||
$force = false;
|
||||
if (in_array('--force', $argv)) { // Want to force
|
||||
$force=true;
|
||||
}
|
||||
|
||||
$bind->regenerate_conf($force);
|
||||
|
|
@ -4,7 +4,6 @@
|
|||
. /usr/lib/alternc/functions.sh
|
||||
|
||||
echo "This script will rebuild all web configuration and regenerate DNS."
|
||||
echo "Only files in $VHOST_MANUALCONF will be preserved."
|
||||
echo "Use --force to skip confirmation"
|
||||
|
||||
if [ ! "$1" == "--force" ] ; then
|
||||
|
@ -20,7 +19,6 @@ mysql_query "update domaines set dns_action = 'UPDATE' WHERE dns_action != '
|
|||
|
||||
echo "Now launching update_domains to rebuild."
|
||||
/usr/lib/alternc/update_domains.sh
|
||||
/usr/lib/alternc/generate_bind_conf.php --force
|
||||
|
||||
echo "Finish."
|
||||
|
||||
|
|
|
@ -1,35 +1,33 @@
|
|||
#!/bin/bash
|
||||
#!/usr/bin/php
|
||||
<?php
|
||||
|
||||
# Rebuild the bind configuration's file
|
||||
# with the IP of the slave dns
|
||||
// Rebuild the bind configuration's file
|
||||
// with the IP of the slave dns
|
||||
|
||||
PATH="/usr/local/sbin:/usr/local/bin:/usr/sbin:/usr/bin:/sbin:/bin"
|
||||
FLAGFILE="/run/alternc/refresh_slave";
|
||||
TPL="/etc/alternc/templates/bind/slaveip.conf"
|
||||
TARGET="/var/lib/alternc/bind/slaveip.conf"
|
||||
$FLAGFILE="/run/alternc/refresh_slave";
|
||||
$TPL="/etc/alternc/templates/bind/slaveip.conf";
|
||||
$TARGET="/var/lib/alternc/bind/slaveip.conf";
|
||||
|
||||
if [ ! -e "$FLAGFILE" ] ; then
|
||||
# Nothing to do
|
||||
exit 0
|
||||
fi
|
||||
if (!file_exists($FLAGFILE)) exit(0);
|
||||
|
||||
# Source some functions
|
||||
. /usr/lib/alternc/functions.sh
|
||||
// Bootstrap
|
||||
require_once("/usr/share/alternc/panel/class/config_nochk.php");
|
||||
|
||||
TMP=$(mktemp /tmp/slaveip.conf.XXXX)
|
||||
$db->query("SELECT ip,class FROM slaveip;");
|
||||
$str="";
|
||||
while ($db->next_record()) {
|
||||
$str.=" ".$db->Record["ip"]."/".$db->Record["class"].";\n";
|
||||
}
|
||||
|
||||
# Get the slave IP. Remove the "newline" caracters
|
||||
val=$(mysql_query "SELECT concat(ip,'::',class,'; ') FROM slaveip;"|tr '\n' ' ')
|
||||
file_put_contents($TARGET, str_replace("//AUTO-SLAVES//",$str, file_get_contents($TPL) ) );
|
||||
|
||||
# Add the slaves to the templates, re-add the missing "/" separator of subnet
|
||||
cat "$TPL" | sed -e "s/\/\/AUTO-SLAVES\/\//$val/g" -e "s/::/\//g" > "$TMP"
|
||||
chown($TARGET,"root");
|
||||
chgrp($TARGET,"bind");
|
||||
chmod($TARGET,0640);
|
||||
|
||||
# Activate the new configuration
|
||||
mv "$TMP" "$TARGET"
|
||||
chown root:bind "$TARGET"
|
||||
chmod 640 "$TARGET"
|
||||
putenv("PATH=/usr/local/sbin:/usr/local/bin:/usr/sbin:/usr/bin:/sbin:/bin");
|
||||
passthru("rndc reconfig");
|
||||
|
||||
unlink($FLAGFILE);
|
||||
|
||||
invoke-rc.d bind9 reload
|
||||
|
||||
# Remove FLAGSLAVE file
|
||||
rm -f "$FLAGFILE"
|
||||
|
|
|
@ -0,0 +1,10 @@
|
|||
#!/usr/bin/php -q
|
||||
<?php
|
||||
|
||||
// bootstrap
|
||||
require_once("/usr/share/alternc/panel/class/config_nochk.php");
|
||||
|
||||
putenv("PATH=/usr/local/sbin:/usr/local/bin:/usr/sbin:/usr/bin:/sbin:/bin");
|
||||
|
||||
$dom->update_domains();
|
||||
|
|
@ -1,168 +1,4 @@
|
|||
#!/bin/bash
|
||||
# Update domain next-gen by fufroma
|
||||
PATH=/usr/local/sbin:/usr/local/bin:/usr/sbin:/usr/bin:/sbin:/bin
|
||||
|
||||
for CONFIG_FILE in \
|
||||
/etc/alternc/local.sh \
|
||||
/usr/lib/alternc/functions.sh \
|
||||
/usr/lib/alternc/functions_hosting.sh \
|
||||
/usr/lib/alternc/functions_dns.sh
|
||||
do
|
||||
if [ ! -r "$CONFIG_FILE" ]; then
|
||||
echo "Can't access $CONFIG_FILE."
|
||||
exit 1
|
||||
fi
|
||||
. "$CONFIG_FILE"
|
||||
done
|
||||
|
||||
stop_if_jobs_locked
|
||||
|
||||
# Some vars
|
||||
umask 022
|
||||
LOCK_FILE="/usr/share/alternc/panel/cron.lock" # FIXME doesn't seem clean to be here
|
||||
OLDIFS="$IFS"
|
||||
NEWIFS=" "
|
||||
RELOAD_WEB="$(mktemp /tmp/alternc_reload_web.XXXX)"
|
||||
RELOAD_DNS="$(mktemp /tmp/alternc_reload_dns.XXXX)"
|
||||
B="µµ§§" # Strange letters to make split in query
|
||||
|
||||
# Somes check before start operations
|
||||
if [ `id -u` -ne 0 ]; then
|
||||
log_error "must be launched as root"
|
||||
elif [ -z "$DEFAULT_MX" -o -z "$PUBLIC_IP" ]; then
|
||||
log_error "Bad configuration. Please use: dpkg-reconfigure alternc"
|
||||
elif [ -f "$LOCK_FILE" ]; then
|
||||
process=$(ps f -p `cat "$LOCK_FILE"|tail -1`|tail -1|awk '{print $NF;}')
|
||||
if [ "$(basename $process)" = "$(basename "$0")" ] ; then
|
||||
log_error "last cron unfinished or stale lock file ($LOCK_FILE)."
|
||||
else
|
||||
rm "$LOCK_FILE"
|
||||
fi
|
||||
fi
|
||||
|
||||
# backward compatibility: single-server setup
|
||||
if [ -z "$ALTERNC_SLAVES" ] ; then
|
||||
ALTERNC_SLAVES="localhost"
|
||||
fi
|
||||
|
||||
# We lock the application
|
||||
echo $$ > "$LOCK_FILE"
|
||||
|
||||
echo "" > "$RELOAD_WEB"
|
||||
echo "" > "$RELOAD_DNS"
|
||||
|
||||
# For domains we want to delete completely, make sure all the tags are all right
|
||||
# set sub_domaines.web_action = delete where domaines.dns_action = DELETE
|
||||
mysql_query "update sub_domaines sd, domaines d set sd.web_action = 'DELETE' where sd.domaine = d.domaine and sd.compte=d.compte and d.dns_action = 'DELETE';"
|
||||
|
||||
# Sub_domaines we want to delete
|
||||
# sub_domaines.web_action = delete
|
||||
for sub in $( mysql_query "select concat_ws('$B', lower(sd.type), if(length(sd.sub)>0,concat_ws('.',sd.sub,sd.domaine),sd.domaine)) from sub_domaines sd where web_action ='DELETE';") ; do
|
||||
host_delete ${sub/$B/ }
|
||||
mysql_query "delete from sub_domaines where concat_ws('$B',lower(type), if(length(sub)>0,concat_ws('.',sub,domaine),domaine)) = '$sub' and web_action ='DELETE';"
|
||||
echo 1 > "$RELOAD_WEB"
|
||||
done
|
||||
|
||||
# Sub domaines we want to update
|
||||
# sub_domaines.web_action = update and sub_domains.only_dns = false
|
||||
IFS="$NEWIFS"
|
||||
mysql_query "
|
||||
select concat_ws('$IFS',sd.id, if(length(sd.https)>0,concat_ws('-',sd.type,sd.https),lower(sd.type)), if(length(sd.sub)>0,concat_ws('.',sd.sub,sd.domaine),sd.domaine), concat_ws('@',m.login,v.value), sd.valeur )
|
||||
from sub_domaines sd,membres m,variable v
|
||||
where sd.compte=m.uid and sd.web_action ='UPDATE' and v.name='mailname_bounce'
|
||||
;" | while read sdid type domain mail valeur ; do
|
||||
host_create "$type" "$domain" "$mail" "$valeur"
|
||||
mysql_query "update sub_domaines sd set web_action='OK',web_result='$?' where sd.id = '$sdid' ; "
|
||||
echo 1 > "$RELOAD_WEB"
|
||||
done
|
||||
|
||||
# Domaine to enable
|
||||
mysql_query "select concat_ws('$IFS',sd.id, if(length(sd.https)>0,concat_ws('-',sd.type,sd.https),lower(sd.type)),if(length(sd.sub)>0,concat_ws('.',sd.sub,sd.domaine),sd.domaine),sd.valeur) from sub_domaines sd where sd.enable ='ENABLE' ;"|while read sdid type domain valeur ; do
|
||||
host_enable "$type" "$domain" "$valeur"
|
||||
mysql_query "update sub_domaines sd set enable='ENABLED' where sd.id = '$sdid' ;"
|
||||
echo 1 > "$RELOAD_WEB"
|
||||
done
|
||||
|
||||
# Domains to disable
|
||||
mysql_query "select concat_ws('$IFS', sd.id, if(length(sd.https)>0,concat_ws('-',sd.type,sd.https),lower(sd.type)),if(length(sd.sub)>0,concat_ws('.',sd.sub,sd.domaine),sd.domaine),sd.valeur) from sub_domaines sd where sd.enable ='DISABLE' ;"|while read sdid type domain valeur ; do
|
||||
host_disable "$type" "$domain" "$valeur"
|
||||
mysql_query "update sub_domaines sd set enable='DISABLED' where sd.id = '$sdid' ;"
|
||||
echo 1 > "$RELOAD_WEB"
|
||||
done
|
||||
|
||||
# Domains we do not want to be the DNS serveur anymore :
|
||||
# domaines.dns_action = UPDATE and domaines.gesdns = 0
|
||||
for dom in `mysql_query "select domaine from domaines where dns_action = 'UPDATE' and gesdns = 0;"| tr '\n' ' '`
|
||||
do
|
||||
dns_delete $dom
|
||||
mysql_query "update domaines set dns_action = 'OK', dns_result = '$?' where domaine = '$dom'"
|
||||
echo 1 >"$RELOAD_DNS"
|
||||
done
|
||||
|
||||
# Domains we have to update the dns :
|
||||
# domaines.dns_action = UPDATE
|
||||
for dom in `mysql_query "select domaine from domaines where dns_action = 'UPDATE';" | tr '\n' ' '`
|
||||
do
|
||||
echo "dns_regenerate : domain=/$dom/"
|
||||
dns_regenerate $dom
|
||||
mysql_query "update domaines set dns_action = 'OK', dns_result = '$?' where domaine = '$dom'"
|
||||
echo 1 >"$RELOAD_DNS"
|
||||
done
|
||||
|
||||
# Domains we want to delete completely, now we do it
|
||||
# domaines.dns_action = DELETE
|
||||
for dom in `mysql_query "select domaine from domaines where dns_action = 'DELETE';" | tr '\n' ' '`
|
||||
do
|
||||
dns_delete $dom
|
||||
# Web configurations have already bean cleaned previously
|
||||
mysql_query "delete from sub_domaines where domaine='$dom'; delete from domaines where domaine='$dom';"
|
||||
echo 1 >"$RELOAD_DNS"
|
||||
done
|
||||
|
||||
if [ ! -z "$(cat "$RELOAD_WEB")" ] ; then
|
||||
|
||||
# Just to encourage user to use THIS directory and not another one
|
||||
test -d "$VHOST_MANUALCONF" || mkdir -p "$VHOST_MANUALCONF"
|
||||
|
||||
# Concat the apaches files
|
||||
tempo=$(mktemp "$VHOST_FILE.XXXXX")
|
||||
|
||||
(
|
||||
echo "###BEGIN OF ALTERNC AUTO-GENERATED FILE - DO NOT EDIT MANUALLY###"
|
||||
find "$VHOST_DIR"/ -mindepth 2 -type f -iname "*.conf" -print0 | xargs -0 cat
|
||||
echo "###END OF ALTERNC AUTO-GENERATED FILE - DO NOT EDIT MANUALLY###"
|
||||
) > "$tempo"
|
||||
|
||||
if [ $? -ne 0 ] ; then
|
||||
log_error " web file concatenation failed"
|
||||
fi
|
||||
touch "$VHOST_FILE"
|
||||
if [ ! -w "$VHOST_FILE" ] ; then
|
||||
log_error "cannot write on $VHOST_FILE"
|
||||
fi
|
||||
mv "$tempo" "$VHOST_FILE"
|
||||
|
||||
# We must reload apache
|
||||
# we assume we run apache on the master
|
||||
/usr/lib/alternc/alternc_reload apache || true
|
||||
# Launch hooks for apache reload
|
||||
run-parts --arg=web_reload /usr/lib/alternc/reload.d
|
||||
fi
|
||||
|
||||
# If we added / edited / deleted at least one dns zone file, we go here in the end:
|
||||
if [ ! -z "$(cat "$RELOAD_DNS")" ] ; then
|
||||
service opendkim restart
|
||||
run-parts --arg=dns_reload /usr/lib/alternc/reload.d
|
||||
fi
|
||||
|
||||
## FIXME : move the slave part into the /usr/lib/alternc/reload.d directory to be an hook
|
||||
#for slave in $ALTERNC_SLAVES; do
|
||||
# if [ "$slave" != "localhost" ]; then
|
||||
# ssh alternc@$slave alternc_reload 'apache' || true
|
||||
# fi
|
||||
#done
|
||||
|
||||
rm -f "$LOCK_FILE" "$RELOAD_ZONES" "$RELOAD_WEB" "$INOTIFY_UPDATE_DOMAIN" "$RELOAD_DNS"
|
||||
|
||||
exit 0
|
||||
# This is now done using PHP-only scripting
|
||||
|
||||
/usr/lib/alternc/update_domains.php
|
||||
|
|
Loading…
Reference in New Issue