Debut des restrictions sur IP

This commit is contained in:
Alan Garcia 2011-04-27 15:44:19 +00:00
parent fb0c32ddf3
commit db6b3b0d3a
7 changed files with 341 additions and 58 deletions

3
.gitattributes vendored
View File

@ -202,6 +202,7 @@ bureau/admin/images/plus.png -text
bureau/admin/images/quota.png -text
bureau/admin/images/stat.png -text
bureau/admin/index.php -text
bureau/admin/ip_main.php -text
bureau/admin/js/alternc.js -text
bureau/admin/js/jquery.min.js -text
bureau/admin/js/jquery_ui/css/smoothness/images/ui-bg_flat_0_aaaaaa_40x100.png -text
@ -251,6 +252,7 @@ bureau/admin/menu_aide.php -text
bureau/admin/menu_brouteur.php -text
bureau/admin/menu_dom.php -text
bureau/admin/menu_ftp.php -text
bureau/admin/menu_ip.php -text
bureau/admin/menu_lang.php -text
bureau/admin/menu_mail.php -text
bureau/admin/menu_mem.php -text
@ -428,6 +430,7 @@ install/upgrades/0.9.6.sql -text
install/upgrades/0.9.7.sql -text
install/upgrades/0.9.9.sql -text
install/upgrades/1.0.sql -text
install/upgrades/1.1.sql -text
install/upgrades/README -text
man/alternc-admintools.8 -text
man/alternc-admintools.fr.8 -text

128
bureau/admin/ip_main.php Normal file
View File

@ -0,0 +1,128 @@
<?php
require_once("../class/config.php");
include_once("head.php");
$fields = array (
"delete_id" => array ("get", "integer", ""),
"is_subnet" => array ("post", "string", ""),
"id" => array ("post", "integer", 0),
"ip" => array ("post", "string", ""),
"subnet" => array ("post", "integer" ,0),
"infos" => array ("post", "string" ,""),
);
getFields($fields);
if (!empty($delete_id)) {
if (! $authip->ip_delete($delete_id)) {
$error="Error during recording";
}
}
if (!empty($is_subnet) && !empty($ip)) {
if (! $authip->ip_save($id, $ip, $subnet, $infos)) {
$error="Error during recording";
}
}
?>
<h3><?php __("Access security"); ?></h3>
<hr id="topbar"/>
<br />
<?php if ($error) { ?>
<p class="error"><?php echo $error ?></p>
<?php } ?>
<table>
<tr>
<th colspan=2><?php __("IP address");?></th>
</tr>
<tr>
<td valign=top>
<table>
<tr><th><?php __("Type"); ?></th><th><?php __("IP"); ?></th><th><?php __("Informations"); ?></th><th colspan=2/></tr>
<?php foreach($authip->list_ip() as $i) {
if (checkip($i['ip'])) {
if ($i['subnet']==32) {
$txt="Address IPv4";
$ip="${i['ip']}";
} else {
$txt="Subnet IPv4";
$ip="${i['ip']}/${i['subnet']}";
}
} elseif (checkipv6($i['ip'])) {
if ($i['subnet']==128) {
$txt="Address IPv6";
$ip="${i['ip']}";
} else {
$txt="Subnet IPv6";
$ip="${i['ip']}/${i['subnet']}";
}
}
echo "<tr><td>$txt</td><td>$ip</td><td>${i['infos']}</td>";
?>
<td><div class="ina"><a href="javascript:edit_ip(<?php echo "'".htmlentities($i['id'])."','".htmlentities($i['ip'])."','".htmlentities($i['subnet'])."','".htmlentities($i['infos'])."'"; ?>);"><img src="images/edit.png" alt="<?php __("Edit"); ?>" /><?php __("Edit"); ?></a></div></td>
<td><div class="ina"><a href="ip_main.php?delete_id=<?php echo urlencode($i["id"]) ?>"><img src="images/delete.png" alt="<?php __("Delete"); ?>" /><?php __("Delete"); ?></a></div></td>
</tr>
<?php } ?>
</table>
</td>
<td valign=top>
<fieldset>
<legend><a href='javascript:switch_from_add_ip();'><?php __("Add an IP");?></a> - <a href="javascript:edit_ip('','<?php echo htmlentities($_SERVER['REMOTE_ADDR'])."','".(checkip($_SERVER['REMOTE_ADDR'])?"32":"128")."','Home IP'";?>);" ><?php echo __("Add my actual IP"); ?></a></legend>
<span id="form_add_ip">
<form method="post" action="ip_main.php" name="main" id="main">
<input type="hidden" name="id" value="" id="edit_id" >
<p><?php __("Do you want to add");?><br/>
<input type="radio" name="is_subnet" value="no" id="is_subnet_no" checked OnClick=$("#subnet_info").hide(); >
<label for="is_subnet_no"><?php __("Only 1 IP address");?></label><br/>
<input type="radio" name="is_subnet" value="yes" id="is_subnet_yes" OnClick=$("#subnet_info").show(); >
<label for="is_subnet_yes"><?php __("An entire subnet");?></label>
</p>
<p>
<?php __("Enter here the address you want (IPv4 or IPv6)"); ?> <br/>
<input type="text" size=20 maxlength=39 name="ip" id="edit_ip" /><span id="subnet_info">/<input type="text" size=4 maxlength=3 name="subnet" id="edit_subnet" /></span>
</p>
<p>
<?php __("Add a commentary");?><br/>
<input type="text" size=30 maxlength=200 name="infos" id="edit_infos" />
</p>
<input type="submit" class="inb" value="<?php __("Save")?>" />
</form>
</span>
</fieldset>
</td>
</tr>
</table>
<script type="text/javascript">
$("#subnet_info").hide();
$("#form_add_ip").hide();
function switch_from_add_ip() {
$("#form_add_ip").toggle();
}
function edit_ip(id, ip, subnet, infos) {
$("#form_add_ip").show();
$("#edit_id").val(id);
$("#edit_ip").val(ip);
$("#edit_subnet").val(subnet);
$("#edit_infos").val(infos);
if ( (subnet == 32) || (subnet == 128) ) {
$("is_subnet_no").attr('checked', true );
$("is_subnet_yes").attr('checked', false);
$("#subnet_info").hide();
} else {
$("is_subnet_no").attr('checked', false);
$("is_subnet_yes").attr('checked', true);
$("#subnet_info").show();
}
}
</script>
<?php include_once("foot.php"); ?>

37
bureau/admin/menu_ip.php Normal file
View File

@ -0,0 +1,37 @@
<?php
/*
$Id: menu_ip.php
----------------------------------------------------------------------
AlternC - Web Hosting System
Copyright (C) 2002 by the AlternC Development Team.
http://alternc.org/
----------------------------------------------------------------------
Based on:
Valentin Lacambre's web hosting softwares: http://altern.org/
----------------------------------------------------------------------
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
----------------------------------------------------------------------
Original Author of file:
Purpose of file:
----------------------------------------------------------------------
*/
/* ############# IP ############# */
?>
<div class="menu-box">
<div class="menu-title"><img src="images/ip.png" alt="<?php __("Access security"); ?>" width=16px height=16px/>&nbsp;<a href="ip_main.php"><?php __("Access security"); ?></a> </div>
</div>

View File

@ -108,7 +108,7 @@ class m_admin {
$db->next_record();
reset($db->Record);
while (list($key,$val)=each($db->Record)) {
$c[$key]=$val;
$c[$key]=$val;
}
}
return $c;
@ -141,7 +141,7 @@ class m_admin {
$db->next_record();
reset($db->Record);
while (list($key,$val)=each($db->Record)) {
$c[$key]=$val;
$c[$key]=$val;
}
}
@ -150,7 +150,7 @@ class m_admin {
$db->next_record();
reset($db->Record);
while (list($key,$val)=each($db->Record)) {
$c[$key]=$val;
$c[$key]=$val;
}
}
@ -350,10 +350,10 @@ class m_admin {
if (!$db->f("cnt")) {
$db->query("SELECT max(m.uid)+1 as nextid FROM membres m");
if (!$db->next_record()) {
$uid=2000;
$uid=2000;
} else {
$uid=$db->Record["nextid"];
if ($uid<=2000) $uid=2000;
$uid=$db->Record["nextid"];
if ($uid<=2000) $uid=2000;
}
// on le créé ensuite dans system.membres et system.local
$db->query("INSERT INTO membres (uid,login,pass,mail,creator,canpass,type,created, notes) VALUES ('$uid','$login','$pass','$mail','$cuid','$canpass', '$type', NOW(), '$notes');");
@ -363,9 +363,9 @@ class m_admin {
// Declenchons les autres classes.
$mem->su($uid);
foreach($classes as $c) {
if (method_exists($GLOBALS[$c],"alternc_add_member")) {
$GLOBALS[$c]->alternc_add_member();
}
if (method_exists($GLOBALS[$c],"alternc_add_member")) {
$GLOBALS[$c]->alternc_add_member();
}
}
$mem->unsu();
return $uid;
@ -477,9 +477,9 @@ EOF;
}
if (($db->query("UPDATE local SET nom='$nom', prenom='$prenom' WHERE uid='$uid';"))
&&($db->query("UPDATE membres SET mail='$mail', canpass='$canpass', enabled='$enabled', `type`='$type', notes='$notes' $ssq WHERE uid='$uid';"))){
&&($db->query("UPDATE membres SET mail='$mail', canpass='$canpass', enabled='$enabled', `type`='$type', notes='$notes' $ssq WHERE uid='$uid';"))){
if($_POST['reset_quotas'] == "on")
$quota->addquotas();
$quota->addquotas();
$this->renew_update($uid, $duration);
return true;
}
@ -584,21 +584,21 @@ EOF;
// Send the event to the other classes :
foreach($classes as $c) {
if (method_exists($GLOBALS[$c],"alternc_del_member")) {
$GLOBALS[$c]->alternc_del_member();
}
if (method_exists($GLOBALS[$c],"alternc_del_member")) {
$GLOBALS[$c]->alternc_del_member();
}
}
if (($db->query("DELETE FROM membres WHERE uid='$uid';")) &&
($db->query("DELETE FROM local WHERE uid='$uid';"))) {
exec("/usr/lib/alternc/mem_del ".$tt["login"]);
$mem->unsu();
// If this user was (one day) an administrator one, he may have a list of his own accounts. Let's associate those accounts to nobody as a creator.
$db->query("UPDATE membres SET creator=2000 WHERE creator='$uid';");
return true;
($db->query("DELETE FROM local WHERE uid='$uid';"))) {
exec("/usr/lib/alternc/mem_del ".$tt["login"]);
$mem->unsu();
// If this user was (one day) an administrator one, he may have a list of his own accounts. Let's associate those accounts to nobody as a creator.
$db->query("UPDATE membres SET creator=2000 WHERE creator='$uid';");
return true;
} else {
$err->raise("admin",2);
$mem->unsu();
return false;
$err->raise("admin",2);
$mem->unsu();
return false;
}
}
@ -882,47 +882,47 @@ EOF;
$dontexist=false;
// Check du domaine
if ($c["gesdns"]==1) {
// Check du NS qui pointe chez nous
$out=array();
exec("dig +short NS ".escapeshellarg($c["domaine"]),$out);
if (count($out)==0) {
$dontexist=true;
} else {
if (!in_array($L_NS1.".",$out) || !in_array($L_NS2.".",$out)) {
$errno=1; $errstr.="NS for this domain are not $L_NS1 and $L_NS2 BUT ".implode(",",$out)."\n";
}
}
// Check du NS qui pointe chez nous
$out=array();
exec("dig +short NS ".escapeshellarg($c["domaine"]),$out);
if (count($out)==0) {
$dontexist=true;
} else {
if (!in_array($L_NS1.".",$out) || !in_array($L_NS2.".",$out)) {
$errno=1; $errstr.="NS for this domain are not $L_NS1 and $L_NS2 BUT ".implode(",",$out)."\n";
}
}
}
if ($c["gesmx"]==1 && !$dontexist) {
$out=array();
exec("dig +short MX ".escapeshellarg($c["domaine"]),$out);
$out2=array();
foreach($out as $o) {
list($t,$out2[])=explode(" ",$o);
}
if (!in_array($L_MX.".",$out2)) {
$errno=1; $errstr.="MX is not $L_MX BUT ".implode(",",$out2)."\n";
}
$out=array();
exec("dig +short MX ".escapeshellarg($c["domaine"]),$out);
$out2=array();
foreach($out as $o) {
list($t,$out2[])=explode(" ",$o);
}
if (!in_array($L_MX.".",$out2)) {
$errno=1; $errstr.="MX is not $L_MX BUT ".implode(",",$out2)."\n";
}
}
if (!$dontexist) {
// On liste les sous-domaine et on verifie qu'ils pointent bien chez nous...
$db->query("SELECT * FROM sub_domaines WHERE domaine='".addslashes($c["domaine"])."' ORDER BY sub;");
while ($db->next_record()) {
$d=$db->Record;
if ($d["type"]==0) {
// Check l'IP :
$out=array();
exec("dig +short A ".escapeshellarg($d["sub"].(($d["sub"]!="")?".":"").$c["domaine"]),$out);
if (!in_array($L_PUBLIC_IP,$out)) {
$errstr.="subdomain '".$d["sub"]."' don't point to $L_PUBLIC_IP but to ".implode(",",$out)."\n";
$errno=1;
}
}
}
// On liste les sous-domaine et on verifie qu'ils pointent bien chez nous...
$db->query("SELECT * FROM sub_domaines WHERE domaine='".addslashes($c["domaine"])."' ORDER BY sub;");
while ($db->next_record()) {
$d=$db->Record;
if ($d["type"]==0) {
// Check l'IP :
$out=array();
exec("dig +short A ".escapeshellarg($d["sub"].(($d["sub"]!="")?".":"").$c["domaine"]),$out);
if (!in_array($L_PUBLIC_IP,$out)) {
$errstr.="subdomain '".$d["sub"]."' don't point to $L_PUBLIC_IP but to ".implode(",",$out)."\n";
$errno=1;
}
}
}
}
if ($dontexist) {
$errno=2;
$errstr="Domain don't exist anymore !";
$errno=2;
$errstr="Domain don't exist anymore !";
}
if ($errno==0) $errstr="OK";
$checked[$c["domaine"]]=array("errno"=>$errno, "errstr"=>$errstr);

View File

@ -7,6 +7,7 @@ menu_ftp.php
menu_sta2.php
menu_sql.php
menu_quota.php
menu_ip.php
menu_aide.php
menu_lang.php
menu_mem.php

View File

@ -75,6 +75,39 @@ SQLAuthTypes Crypt
# Only mysql authentication enabled
SQLAuthenticate users
AuthPAM off
# What this SQL query do :
# - check if there is IP limitation for this account. If there isn't, allow everyone (by returning a TRUE)
# - if there is some limitation :
# - convert ip to integer (if convert impossible, it's an ipv6. Mysql6 will have ipv6 function, for mysql5 alternc create some function)
# - calculate the last IP of the subnet. If the subnet is 32, return the original IP
# - check that the user's ip is in an allowed range
# - add the IP range who are defined as "always from everyone" (uid=0. Not uid=2000, because we could want to have some limitation for the root account)
SQLUserWhereClause " \
true in ( \
select if(count(*)>0,false,(select value from variable where name='auth_ip_ftp_default_yes')) \
from authorised_ip_affected aia, ftpusers f \
where cast(aia.parameters as signed integer)=f.id and f.name='%U'\
UNION \
select \
ifnull(inet_aton('%h'),inet_aton6('%h')) \
between ifnull(inet_aton(ip),inet_aton6(ip)) \
and ifnull( inet_aton(ip) + if(subnet=32,0,conv( lpad('',(32-subnet),'1'), 2 , 10)) , inet_aton6(ip) + conv( lpad('',(128-subnet),'1'), 2 , 10) ) \
from authorised_ip ai, authorised_ip_affected aia, ftpusers f \
where f.name='%U' and cast(aia.parameters as signed integer)=f.id and ai.id=aia.authorised_ip_id and aia.protocol='ftp' \
UNION \
select \
ifnull(inet_aton('%h'),inet_aton6('%h')) \
between ifnull(inet_aton(ip),inet_aton6(ip)) \
and ifnull( inet_aton(ip) + if(subnet=32,0,conv( lpad('',(32-subnet),'1'), 2 , 10)) , inet_aton6(ip) + conv( lpad('',(128-subnet),'1'), 2 , 10) ) \
from authorised_ip ai \
where ai.uid=0 \
) \
"
# Uncomment this line if you want to debug Proftpd's SQL
#SQLLogFile /var/log/proftpd/sql.log
# Default : www-data.www-data
SQLDefaultGID 33
SQLDefaultUID 33

81
install/upgrades/1.1.sql Normal file
View File

@ -0,0 +1,81 @@
-- Add function who are not in mysql 5 to be able ton convert ipv6 to decimal (and reverse it)
DELIMITER //
CREATE FUNCTION INET_ATON6(n CHAR(39))
RETURNS DECIMAL(39) UNSIGNED
DETERMINISTIC
BEGIN
RETURN CAST(CONV(SUBSTRING(n FROM 1 FOR 4), 16, 10) AS DECIMAL(39))
* 5192296858534827628530496329220096 -- 65536 ^ 7
+ CAST(CONV(SUBSTRING(n FROM 6 FOR 4), 16, 10) AS DECIMAL(39))
* 79228162514264337593543950336 -- 65536 ^ 6
+ CAST(CONV(SUBSTRING(n FROM 11 FOR 4), 16, 10) AS DECIMAL(39))
* 1208925819614629174706176 -- 65536 ^ 5
+ CAST(CONV(SUBSTRING(n FROM 16 FOR 4), 16, 10) AS DECIMAL(39))
* 18446744073709551616 -- 65536 ^ 4
+ CAST(CONV(SUBSTRING(n FROM 21 FOR 4), 16, 10) AS DECIMAL(39))
* 281474976710656 -- 65536 ^ 3
+ CAST(CONV(SUBSTRING(n FROM 26 FOR 4), 16, 10) AS DECIMAL(39))
* 4294967296 -- 65536 ^ 2
+ CAST(CONV(SUBSTRING(n FROM 31 FOR 4), 16, 10) AS DECIMAL(39))
* 65536 -- 65536 ^ 1
+ CAST(CONV(SUBSTRING(n FROM 36 FOR 4), 16, 10) AS DECIMAL(39))
;
END;
//
DELIMITER ;
DELIMITER //
CREATE FUNCTION INET_NTOA6(n DECIMAL(39) UNSIGNED)
RETURNS CHAR(39)
DETERMINISTIC
BEGIN
DECLARE a CHAR(39) DEFAULT '';
DECLARE i INT DEFAULT 7;
DECLARE q DECIMAL(39) UNSIGNED DEFAULT 0;
DECLARE r INT DEFAULT 0;
WHILE i DO
-- DIV doesn't work with nubers > bigint
SET q := FLOOR(n / 65536);
SET r := n MOD 65536;
SET n := q;
SET a := CONCAT_WS(':', LPAD(CONV(r, 10, 16), 4, '0'), a);
SET i := i - 1;
END WHILE;
SET a := TRIM(TRAILING ':' FROM CONCAT_WS(':',
LPAD(CONV(n, 10, 16), 4, '0'),
a));
RETURN a;
END;
//
DELIMITER ;
-- New table for the authorised IP
CREATE TABLE IF NOT EXISTS `authorised_ip` (
`id` int(10) unsigned NOT NULL auto_increment,
`uid` int(11) unsigned NOT NULL default '0',
`ip` varchar(40) not null,
`subnet` integer(3) not null default 32,
`infos` varchar(255) not null default '',
PRIMARY KEY (`id`),
KEY `uid` (`uid`)
) ENGINE=MyISAM COMMENT='Table with list of authorised ip and subnet';
-- Who have authorised IP ?
CREATE TABLE IF NOT EXISTS `authorised_ip_affected` (
`id` int(10) unsigned NOT NULL auto_increment,
`authorised_ip_id` int(10) unsigned not null,
`protocol` varchar(15) not null,
`parameters` varchar(30) default '',
PRIMARY KEY (`id`)
) ENGINE=MyISAM COMMENT='Table with list of protocol <-> authorised ip and subnet';
INSERT IGNORE INTO `variable` (`name` ,`value` ,`comment`)
VALUES (
'auth_ip_ftp_default_yes', '1',
'This variable set if you want to allow all IP address to access FTP by default. If the user start to define some IP or subnet in the allow list, only those he defined will be allowed. This variable can take two value : 0 or 1.'
);