First checking of tcpwrappers plugin
authorJamie Cameron <jcameron@webmin.com>
Thu, 24 Jul 2008 07:29:33 +0000 (07:29 +0000)
committerJamie Cameron <jcameron@webmin.com>
Thu, 24 Jul 2008 07:29:33 +0000 (07:29 +0000)
22 files changed:
apache/apache-lib.pl
bind8/CHANGELOG
bind8/save_acls.cgi
change-user/change.cgi
custom/custom-lib.pl
lang/ru_RU
tcpwrappers/CHANGELOG [new file with mode: 0644]
tcpwrappers/backup_config.pl [new file with mode: 0644]
tcpwrappers/config [new file with mode: 0644]
tcpwrappers/config.info [new file with mode: 0644]
tcpwrappers/delete_rules.cgi [new file with mode: 0755]
tcpwrappers/edit_rule.cgi [new file with mode: 0755]
tcpwrappers/help/edit_rule.html [new file with mode: 0644]
tcpwrappers/help/intro.html [new file with mode: 0644]
tcpwrappers/images/icon.gif [new file with mode: 0644]
tcpwrappers/index.cgi [new file with mode: 0755]
tcpwrappers/lang/cz [new file with mode: 0644]
tcpwrappers/lang/en [new file with mode: 0644]
tcpwrappers/module.info [new file with mode: 0644]
tcpwrappers/save_rule.cgi [new file with mode: 0755]
tcpwrappers/tcpwrappers-lib.pl [new file with mode: 0644]
web-lib-funcs.pl

index 343e81e..9474f78 100644 (file)
@@ -462,7 +462,7 @@ close(HTACCESS);
 return \@conf;
 }
 
-# save_directive(name, &values, &parent-directives, &config)
+# save_directive(name, &values, &parent-directives, &config, [always-at-end])
 # Updates the config file(s) and the directives structure with new values
 # for the given directives.
 # If a directive's value is merely being changed, then its value only needs
@@ -477,7 +477,7 @@ for($i=0; $i<@old || $i<@{$_[1]}; $i++) {
                # a new directive is being added. If other directives of this
                # type exist, add it after them. Otherwise, put it at the end of
                # the first file in the section
-               if ($change) {
+               if ($change && !$_[4]) {
                        # Have changed some old directive.. add this new one
                        # after it, and update change
                        local(%v, $j);
index fa589c8..fc8e7c9 100644 (file)
@@ -78,3 +78,4 @@ When adding a cluster slave server, multiple views can be entered to have slave
 Record names or values entered like ns.foo.com in the domain foo.com automatically have a . added to make them absolute as the user presumably expected, rather than being coverted to ns.foo.com.foo.com.
 Update serial number (by default) when editing records manually.
 Try downloading root zone files from the IP for rs.internic.net if the hostname cannot be resolved, to avoid catch-22 problem.
+Access control lists are now automatically re-ordered to handle dependencies.
index 34c2ce4..df505ea 100755 (executable)
@@ -7,6 +7,8 @@ $access{'defaults'} || &error($text{'acls_ecannot'});
 &error_setup($text{'acls_err'});
 &ReadParse();
 
+# Convert inputs into ACL structures
+%depmap = ( );
 &lock_file(&make_chroot($config{'named_conf'}));
 $conf = &get_config();
 for($i=0; defined($name = $in{"name_$i"}); $i++) {
@@ -25,8 +27,22 @@ for($i=0; defined($name = $in{"name_$i"}); $i++) {
                      'members' => [ map { my ($n, @w)=split(/\s+/, $_);
                                           { 'name' => $n,
                                             'values' => \@w } } @vals ] });
+
+       # Record this ACL as a dependency of some ACL it refers to
+       foreach (@vals) {
+               my ($n, @w)=split(/\s+/, $_);
+               if ($n !~ /^[0-9\.]+$/) {
+                       push(@{$depmap{$n}}, $name);
+                       }
+               }
        }
 
+# Sort the list so that depended-on ACLs come first
+@acls = sort { my $an = $a->{'values'}->[0];
+              my $bn = $b->{'values'}->[0];
+              &indexof($an, @{$depmap{$bn}}) >= 0 ? 1 :
+              &indexof($bn, @{$depmap{$an}}) >= 0 ? -1 : 0 } @acls;
+
 &save_directive(&get_config_parent(), 'acl', \@acls, 0, 0, 1);
 &flush_file_lines();
 &unlock_file(&make_chroot($config{'named_conf'}));
index 8521f12..0e54799 100755 (executable)
@@ -45,6 +45,7 @@ if ($access{'theme'}) {
        }
 if ($access{'pass'} && &can_change_pass($user) && !$in{'pass_def'}) {
        $user->{'pass'} = &acl::encrypt_password($in{'pass'});
+       $user->{'temppass'} = 0;
        }
 &acl::modify_user($user->{'name'}, $user);
 print "$text{'change_done'}<p>\n";
index e9b768a..ef4496d 100644 (file)
@@ -1,8 +1,5 @@
 # custom-lib.pl
 # Functions for storing custom commands
-# XXX variable in file editors
-# XXX don't need quoting option
-# XXX don't need upload type, or password, or text box, or option
 
 do '../web-lib.pl';
 &init_config();
index ccb6824..efb5113 100644 (file)
@@ -2,7 +2,6 @@ acl_feedback=
 acl_feedback0=Íåò
 acl_feedback1=Äà, íî íå âêëþ÷àòü ôàéëû íàñòðîéêè
 acl_feedback2=Äà
-acl_feedback3=Äà, âìåñòå ñ êîíôèãóðàöèîííûìè ôàéëàìè
 acl_gedit=Âèäèìûå ãðóïïû
 acl_gedit_all=Âñå ãðóïïû
 acl_gedit_except=Âñå ãðóïïû êðîìå óêàçàííûõ
@@ -10,8 +9,6 @@ acl_gedit_gid=
 acl_gedit_none=Íè îäíîé ãðóïïû
 acl_gedit_only=Òîëüêî óêàçàííûå ãðóïïû
 acl_home=Äîìàøíèé êàòàëîã ïîëüçîâàòåëÿ
-acl_nodot=Ñêðûòü ôàéëû, èìåíà êîòîðûõ íà÷èíàþòñÿ ñ ñèìâîëà (.) â ñåëåêòîðå ôàéëîâ?
-acl_readonly=Ïîëüçîâàòåëü â äåìîíñòðàöèîííîì ðåæèìå?<br>(Íåêîòîðûå ìîäóëè ìîãóò áûòü íåäîñòóïíû)
 acl_root=Êîðíåâîé êàòàëîã
 acl_rpc=Ïðèíèìàòü çàïðîñû RPC?
 acl_rpc0=Íåò
@@ -33,8 +30,7 @@ category_net=
 category_servers=Ñëóæáû
 category_syslet=Ñèñëåòû
 category_system=Ñèñòåìà
-category_webmin=ZTL
-chooser_date=Âûáðàòü Äàòó
+category_webmin=Webmin
 chooser_dir=Êàòàëîã $1
 chooser_ok=ÎÊ
 chooser_title1=Âûáîð ôàéëà..
@@ -43,7 +39,6 @@ config_dir=
 config_eaccess=Ó âàñ íåäîñòàòî÷íî ïðàâ äëÿ äîñòóïà ê ýòîìó ìîäóëþ
 config_ecannot=Ó âàñ íåäîñòàòî÷íî ïðàâ íà íàñòðîéêó ýòîãî ìîäóëÿ
 config_err=Íå óäàëîñü ñîõðàíèòü íàñòðîéêè
-config_ewebmin=Ïàðàìåòð type 14 ðàáîòàåò òîëüêî â ZTL
 config_header=Íàñòðîéêè ìîäóëÿ $1
 config_nochange=Íå èçìåíÿòü
 config_none=Íåò
@@ -59,19 +54,16 @@ day_5=
 day_6=Ñóááîòà
 default=Ïî óìîë÷àíèþ
 delete=Óäàëèòü
-efileclose=Íåâîçìîæíî ïèñàòü â $1 êîãäà çàêðûâàåòñÿ : $2
-efileopen=Íåâîçìîæíî îòêðûòü $1 äëÿ çàïèñè : $2
 efilewrite=Íå óäàëîñü çàïèñàòü â $1 : $2
 elock_tries=Íå óäàëîñü çàáëîêèðîâàòü ôàéë $1 ïîñëå $2 ìèíóò
 emodule=Äîñòóï çàïðåùåí : Ïîëüçîâàòåëü $1 íå èìååò ïðàâ íà èñïîëüçîâàíèå ìîäóëÿ $2
 error=Îøèáêà
-error_previous=ïðåäûäóùàÿ ñòðàíèöà
 feedback_all=All modules
 feedback_attach=Additional files to attach
 feedback_config=Include module configuration in email?
 feedback_configdesc=If this is selected, the email will include the configuration of the related module and the contents of any config files that the module uses. For example, if the feedback was related to the <i>Users and Groups</i> module, your <tt>/etc/passwd</tt> and <tt>/etc/shadow</tt> files would be sent.
-feedback_desc=This form allows you to report bugs on make suggestions to the ZTL developers regarding any problems or missing features that you have found. When the Send button is clicked, the details entered into the form will be emailed to $1.
-feedback_desc2=This feedback will be sent to the developer of End User ZTL, not your system administrator, ISP or hosting company. Please write your feedback in english, even if you are currently running ZTL in another language.
+feedback_desc=This form allows you to report bugs on make suggestions to the Webmin developers regarding any problems or missing features that you have found. When the Send button is clicked, the details entered into the form will be emailed to $1.
+feedback_desc2=This feedback will be sent to the developer of Usermin, not your system administrator, ISP or hosting company. Please write your feedback in english, even if you are currently running Webmin in another language.
 feedback_ecannot=You are not allowed to send feedback
 feedback_ecannot2=You are not allowed to send feedback containing config files
 feedback_econfig=You do not have full access to the selected module.
@@ -91,7 +83,7 @@ feedback_osdesc=If this option is selected, the automatic feedback email will in
 feedback_prog=Sent feedback to $1 using sendmail program $2
 feedback_send=Send Feedback
 feedback_text=Description of problem or suggestion
-feedback_title=ZTL Feedback
+feedback_title=Webmin Feedback
 feedback_to=Send feedback to addresses
 feedback_via=Sent feedback to $1 via SMTP server $2
 find=Íàéòè
@@ -105,9 +97,8 @@ groups_title2=
 header_config=Íàñòðîéêà ìîäóëÿ
 header_help=Ñïðàâêà..
 header_module=Ìåíþ ìîäóëÿ
-header_servers=Ñåðâåðû ZTL
-header_statusmsg=$1 âîø¸ë â  $2 $3 íà $4 ($5)
-header_webmin=Ãëàâíîå ìåíþ ZTL
+header_servers=Ñåðâåðû Webmin
+header_webmin=Ãëàâíîå ìåíþ Webmin
 help_eexec=Îøèáêà $1 : $2
 help_efile=Íå óäàëîñü ïðî÷èòàòü ôàéë ñïðàâêè $1
 help_eheader=Îòñóòñòâóåò &lt;çàãîëîâîê&gt; ðàçäåëà
@@ -117,52 +108,17 @@ help_epath=
 help_err=Íå óäàëîñü âûâåñòè ñïðàâêó
 helpsearch=Ïîèñê â ñïðàâêå..
 index=ìåíþ
-index_chpass=Èçìåíèòü Ïàðîëü
-index_configure_mod=Êîíôèãóðèðîâàòü ýòî ìîäóëü
-index_diskspace=Äèñêîâîå Ïðîñòðàíñòâî
-index_hostname=Õîñò
-index_logout_hint=Âûéòè èç èíòåðôåéñà Ïîëüçâàòåëÿ ZTL
-index_mainpage=Ãëàâíàÿ Ñòðàíèöà
-index_mainpage2=Ãëàâíàÿ Ñòðàíèöà
-index_mainpage_url=/home/index.cgi
-index_os=ÎÑ
-index_remoteip=Óäàë¸ííûé IP
-index_return=èíäåêñ
-index_time=Âðåìÿ
-index_title_login=Âîéòè â èíòåðôåéñ Ïîëüçîâàòåëÿ ZTL
-index_title_system=Èíôîðìàöèÿ î Ñèñòåìå
-index_title_user=Èíôîðìàöèÿ î Ïîëüçîâàòåëå
-index_uptime=Âðåìÿ Ðàáîòû
-index_user=Unix Ïîëüçîâàòåëü
-index_ver=âåð.
-link_essl=Perl ìîäóëü Net::SSLeay, íåîáõîäèìûé ÷òîáû óñòàíîâèòü HTTPS ñîåäèíåíèÿ, íå óñòàíîâëåí â Âàøåé ñèñòåìå.
-longcategory_=Ìîäóëè, êîòîðûå íå îòíîñÿòñÿ íè ê êàêîé äðóãîé êàòåãîðèè
-longcategory_cluster=Ìîäóëè, êîòîðûå ìîãóò óïðàâëÿòü íåñêîëüêèìè ñåðâåðàìè èç îäíîãî èíòåðôåéñà
-longcategory_hardware=Ìîäóëè äëÿ ïðèíòåðà, äèñêîâ è äðóãîé êîíôèãóðàöèè àïïàðàòíîãî îáåñïå÷åíèÿ
-longcategory_info=Ìîäóëè, îòîáðàæàþùèå èíôîðìàöèþ î Âàøåé ñèñòåìå
-longcategory_net=Ìîäóëè äëÿ êîíôèãóðàöèè ñåòè è ñåòåâûõ ñåðâèñîâ
-longcategory_servers=Ìîäóëè äëÿ êîíôèãóðàöèè web, email, FTP è äðóãèõ ñåðâèñîâ
-longcategory_system=Ìîäóëè äëÿ ïîëüçîâàòåëåé, ôàéëîâûõ ñèñòåì è äðóãèõ íàñòðîåê ñèñòåìû
-longcategory_webmin=Ìîäóëè äëÿ êîíôèãóðèðîâàíèÿ ZTL
 main_feedback=Îòçûâ..
 main_homepage=Äîìàøíÿÿ ñòðàíèöà
 main_logout=Âûéòè
-main_none=Âû íå èìååòå äîñòóïà íè ê îäíîìó ìîäóëþ ZTL.
-main_readonly=(ðåæèì ÷òåíèÿ)
+main_none=Âû íå èìååòå äîñòóïà íè ê îäíîìó ìîäóëþ Webmin.
 main_return=Âåðíóòüñÿ ê $1
 main_skill=Îïûòíîñòü
 main_switch=Ñìåíèòü ïîëüçîâàòåëÿ..
-main_title=ZTL $1 íà $2 ($3)
-main_title2=ZTL
+main_title=Webmin $1 íà $2 ($3)
+main_title2=Webmin
 main_version=Âåðñèÿ $1 íà $2 ($3)
 modify=Èçìåíèòü
-modules_all=Âñå ìîäóëè
-modules_cancel=Âûõîä
-modules_clear=Î÷èñòèòü
-modules_ok=Îê
-modules_sel=Âûáðàííûå Ìîäóëè
-modules_title1=Âûáðàòü Ìîäóëè ..
-modules_title2=Âûáðàòü Ìîäóëü ..
 month_1=ßíâàðü
 month_10=Îêòÿáðü
 month_11=Íîÿáðü
@@ -177,42 +133,17 @@ month_8=
 month_9=Ñåíòÿáðü
 no=Íåò
 ok=ÎÊ
-pam_header=Âîéòè â ZTL
-pam_login=Ïðîäîëæèòü
-pam_mesg=Âû äîëæíû îòâåòèòü íà íèæåóêàçàííûé âîïðîñ ÷òîáû âîéòè íà ñåðâåð ZTL íà $1.
-pam_mesg2=Âû äîëæíû îòâåòèòü íà íèæåóêàçàííûé âîïðîñ ÷òîáû âîéòè â ñèñòåìó.
-pam_restart=Ïåðåçàãðóçèòü
-password_clear=Î÷èñòèòü
-password_done=Âàø ïàðîëü áûë óäà÷íî èçìåí¸í. Âû ìîæåòå òåïåðü <a href='$1'>çàéòè îïÿòü</a> ñ íîâûì ïàðîëåì.
-password_emodpam=Perl ìîäóëü Authen::PAM, íåîáõîäèìûé ÷òîáû ïðîâîäèòü èçìåíåíèÿ ïàðîëåé, íå óñòàíîâëåí!
-password_enew1=Íîâûõ ïàðîëåé íå áûëî ââåäåíî
-password_enew2=Âàø íîâûé ïàðîëü íå ïîäõîäèò
-password_eold=Òåêóùèé ïàðîëü- íåïðàâèëüíûé
-password_epam=Îøèáêà PAM : $1
-password_err=Íåâîçìîæíî èçìåíèòü ïàðîëü
-password_euser=Âàøå èìÿ ó÷¸òíîé çàïèñè íå áûëî íàéäåíî ôàéëå ïàðîëåé!
-password_expired=Âàø ïàðîëü áîëüøå íåäåéñòâèòåëåí, äîëæåí áûòü âûáðàí íîâûé
-password_header=Âûáåðèòå Íîâûé Ïàðîëü
-password_new1=Íîâûé ïàðîëü
-password_new2=Åù¸ ðàç íîâûé ïàðîëü
-password_ok=Èçìåíèòü
-password_old=Òåêóùèé ïàðîëü
-password_user=Èìÿ ïîëüçîâàòåëÿ
-programname=ZTL
+programname=Webmin
 progress_data=Ïîëó÷åíî $1 áàéò ($2 %)
 progress_data2=Ïîëó÷åíî $1 áàéò
 progress_done=.. Çàãðóçêà çàâåðøåíà.
-progress_incache=Íàéäåíî $1 â êýøå ..
 progress_nosize=Çàãðóçêà $1 ..
 progress_size=Çàãðóçêà $1 ($2 áàéò) ..
-readparse_cdheader=Îòñóòñòâóåò çàãîëîâîê Ðàññòàíîâêè Êîíòåíòà
-readparse_enc=Îæèäàëàñü êîäèðîâêà form-data, íî èñïîëüçîâàëàñü íîðìàëüíàÿ êîäèðîâêà
-readparse_max=Ðàçìåð äàííûõ äîñòèã ìàêñèìàëüíîãî ðàçìåðà $1 áàéò
 referer_again=Áîëüøå íå ïîêàçûâàòü ýòî ïðåäóïðåæäåíèå.
-referer_ok=Ïðîäîëæèòü âûïîëíåíèå ïðîãðàììû ZTL
+referer_ok=Ïðîäîëæèòü âûïîëíåíèå ïðîãðàììû Webmin
 referer_title=Ïðåäóïðåæäåíèå î áåçîïàñíîñòè
-referer_warn=<b>Âíèìàíèå!</b> ZTL îïðåäåëèë, ÷òî ññûëêà íà ïðîãðàììó $2 áûëà ïðîèçâåäåíà ñ URL $1, êîòîðûé íàõîäèòñÿ âíå ñåðâåðà ZTL. Ýòî ìîæåò áûòü ïîïûòêîé îáìàíóòü âàø ñåðâåð ñ öåëüþ çàïóñêà îïàñíîé êîìàíäû..
-referer_warn_unknown=<b>Âíèìàíèå!</b> ZTL îïðåäåëèë, ÷òî ññûëêà íà ïðîãðàììó $1 áûëà ïðîèçâåäåíà ñ íåèçâåñòíîãî URL, êîòîðûé íàõîäèòñÿ âíå ñåðâåðà ZTL. Ýòî ìîæåò áûòü ïîïûòêîé îáìàíóòü âàø ñåðâåð ñ öåëüþ çàïóñêà îïàñíîé êîìàíäû..
+referer_warn=<b>Âíèìàíèå!</b> Webmin îïðåäåëèë, ÷òî ññûëêà íà ïðîãðàììó $2 áûëà ïðîèçâåäåíà ñ URL $1, êîòîðûé íàõîäèòñÿ âíå ñåðâåðà Webmin. Ýòî ìîæåò áûòü ïîïûòêîé îáìàíóòü âàø ñåðâåð ñ öåëüþ çàïóñêà îïàñíîé êîìàíäû..
+referer_warn_unknown=<b>Âíèìàíèå!</b> Webmin îïðåäåëèë, ÷òî ññûëêà íà ïðîãðàììó $1 áûëà ïðîèçâåäåíà ñ íåèçâåñòíîãî URL, êîòîðûé íàõîäèòñÿ âíå ñåðâåðà Webmin. Ýòî ìîæåò áûòü ïîïûòêîé îáìàíóòü âàø ñåðâåð ñ öåëüþ çàïóñêà îïàñíîé êîìàíäû..
 reset=Ñáðîñèòü
 save=Ñîõðàíèòü
 sday_0=Âñ
@@ -224,10 +155,10 @@ sday_5=
 sday_6=Ñá
 session_clear=Î÷èñòèòü
 session_failed=Ïîïûòêà âõîäà íå óäàëàñü. Ïîïðîáóéòå åùå ðàç.
-session_header=Âõîä â ZTL
+session_header=Âõîä â Webmin
 session_login=Âõîä
 session_logout=Ïðîèçâåäåí óñïåøíûé âûõîä. Ïðè æåëàíèè âû ìîæåòå âîéòè åùå ðàç.
-session_mesg=Äëÿ âõîäà â ñåðâåð ZTL íà $1 íåîáõîäèìî óêàçàòü èìÿ ïîëüçîâàòåëÿ è ïàðîëü.
+session_mesg=Äëÿ âõîäà â ñåðâåð Webmin íà $1 íåîáõîäèìî óêàçàòü èìÿ ïîëüçîâàòåëÿ è ïàðîëü.
 session_mesg2=Äëÿ âõîäà íåîáõîäèìî óêàçàòü èìÿ ïîëüçîâàòåëÿ è ïàðîëü.
 session_pass=Ïàðîëü
 session_save=Çàïîìíèòü èìÿ ïîëüçîâàòåëÿ è ïàðîëü?
@@ -248,28 +179,12 @@ smonth_6=
 smonth_7=Èþë
 smonth_8=Àâã
 smonth_9=Ñåí
-st_ftp=FTP Äîñòóï
-st_mail=Ïî÷òîâûé ÿùèê
-st_smb=Êëèåíò Windows
 switch_remote_euser=Ïîëüçîâàòåëü Unix $1 íå ñóùåñòâóåò.
-ui_checkmandatory=Íè÷åãî íå áûëî âûáðàíî
-ui_edate=Íåïðàâèëüíàÿ äàòà
-ui_errors=Ðàçëè÷íûå îøèáêè áûëè íàéäåíû :
-ui_etime=Íåïðàâèëüíîå âðåìÿ
-ui_mandatory=Ýòî ïîëå- îáÿçàòåëüíî
-ui_nothing=Íè÷åãî íå ââåäåíî
-ui_paging=Ïîêàçûâàòü ñòðîêè ñ $1 ïî $2 èç $3
-ui_rowlabel=$2 â ñòðîêå $1 :
-ui_searchcol=Íàéòè ñòðîêè ãäå
-ui_searchfor=Âêëþ÷àåò â ñåáÿ òåêñò
-ui_searchok=Èñêàòü
-ui_selall=Âûáðàòü âñ¸.
-ui_selinv=Èíâåðòèðîâàòü âûáîðêó.
 users_all=Âñå ïîëüçîâàòåëè
 users_cancel=Îòìåíà
 users_clear=Î÷èñòèòü
 users_ok=ÎÊ
-users_sel=Âûáðàííûå Ïîëüçîâàòåëè
-users_title1=Âûáðàòü Ïîëüçîâàòåëåé..
-users_title2=Âûáðàòü Ïîëüçîâàòåëÿ..
+users_sel=Âûáðàííûå ïîëüçîâàòåëè
+users_title1=Âûáîð ïîëüçîâàòåëåé..
+users_title2=Âûáîð ïîëüçîâàòåëÿ..
 yes=Äà
diff --git a/tcpwrappers/CHANGELOG b/tcpwrappers/CHANGELOG
new file mode 100644 (file)
index 0000000..e6a8d12
--- /dev/null
@@ -0,0 +1 @@
+Initial version
diff --git a/tcpwrappers/backup_config.pl b/tcpwrappers/backup_config.pl
new file mode 100644 (file)
index 0000000..c0a5c9c
--- /dev/null
@@ -0,0 +1,40 @@
+
+do 'wrappers-lib.pl';
+
+# backup_config_files()
+# Returns files and directories that can be backed up
+sub backup_config_files
+{
+return ( $config{'hosts_allow'}, $config{'hosts_deny'} );
+}
+
+# pre_backup(&files)
+# Called before the files are actually read
+sub pre_backup
+{
+return undef;
+}
+
+# post_backup(&files)
+# Called after the files are actually read
+sub post_backup
+{
+return undef;
+}
+
+# pre_restore(&files)
+# Called before the files are restored from a backup
+sub pre_restore
+{
+return undef;
+}
+
+# post_restore(&files)
+# Called after the files are restored from a backup
+sub post_restore
+{
+return undef;
+}
+
+1;
+
diff --git a/tcpwrappers/config b/tcpwrappers/config
new file mode 100644 (file)
index 0000000..3e51a1e
--- /dev/null
@@ -0,0 +1,2 @@
+hosts_allow=/etc/hosts.allow
+hosts_deny=/etc/hosts.deny
diff --git a/tcpwrappers/config.info b/tcpwrappers/config.info
new file mode 100644 (file)
index 0000000..405f79b
--- /dev/null
@@ -0,0 +1,2 @@
+hosts_allow=TCP wrappers allow file,0
+hosts_deny=TCP wrappers deny file,0
diff --git a/tcpwrappers/delete_rules.cgi b/tcpwrappers/delete_rules.cgi
new file mode 100755 (executable)
index 0000000..b718c84
--- /dev/null
@@ -0,0 +1,25 @@
+#!/usr/local/bin/perl
+# Delete multiple rules
+
+require './tcpwrappers-lib.pl';
+&ReadParse();
+&error_setup($text{'del_err'});
+
+@d = split(/\0/, $in{'d'});
+@d || &error($text{'del_enone'});
+$file = $in{'allow'} ? $config{'hosts_allow'} : $config{'hosts_deny'};
+@rules = &list_rules($file);
+
+# Do the delete
+&lock_file($file);
+
+foreach $d (@d) {
+    ($rule) = grep { $_->{'id'} == $d } @rules;
+    $rule || &error($text{'edit_eid'});
+    &delete_rule($file, $rule);
+}
+
+&unlock_file($file);
+&webmin_log("delete", "rules", scalar(@d));
+
+&redirect("");
diff --git a/tcpwrappers/edit_rule.cgi b/tcpwrappers/edit_rule.cgi
new file mode 100755 (executable)
index 0000000..7be188b
--- /dev/null
@@ -0,0 +1,98 @@
+#!/usr/local/bin/perl
+# Creating or editing rule
+
+require './tcpwrappers-lib.pl';
+&ReadParse();
+
+@xservices = &list_services();
+unshift @xservices, "ALL" if (@xservices);
+
+if ($in{'new'}) {
+    &ui_print_header(undef, $text{'edit_title1'}, "", "edit_rule");
+} else {
+    &ui_print_header(undef, $text{'edit_title2'}, "", "edit_rule");
+    @rules = &list_rules($in{'allow'} ? $config{'hosts_allow'} : $config{'hosts_deny'});
+    ($rule) = grep { $_->{'id'} == $in{'id'} } @rules;
+    $rule || &error($text{'edit_eid'});
+
+    # parse services (daemons)
+    if ($rule->{'service'} =~ /^(.+) EXCEPT (.*)$/) {
+       @services = split /,\s?|\s+/, $1;
+       @eservices = split /,\s?|\s+/, $2;
+    } else {
+       @services = split /,\s?|\s+/, $rule->{'service'};
+    } 
+
+    if (@xservices) {
+       # try to find all services (daemons) in xinetd/inetd
+               foreach my $rule_service (@services, @eservices) {
+                   $found = 0;
+               foreach my $xinet_service (@xservices) { $found = 1 if ($rule_service eq $xinet_service); }
+                   unless ($found) {
+                       # not found -> let user to edit custom service
+                       @xservices = ();
+                   }
+               }
+    }
+    # parse hosts
+    if ($rule->{'host'} =~ /^(.+) EXCEPT (.*)$/) {
+       $hosts = $1;
+       $ehosts = $2
+    } else {
+       $hosts = $rule->{'host'};
+    } 
+}
+
+# Form header
+print &ui_form_start("save_rule.cgi", "post");
+print &ui_hidden("new", $in{'new'}),"\n";
+print &ui_hidden("id", $in{'id'}),"\n";
+print &ui_hidden($in{'allow'} ? 'allow' : 'deny', 1),"\n";
+#print &ui_table_start($text{'edit_header'}, "width=100%", 5);
+print &ui_table_start($text{'edit_header'}, "", 5);
+
+
+# Services
+if (@xservices) {
+    # listed from (x)inetd
+    print &ui_table_row("<b>$text{'edit_service'}</b> ", &ui_select("service", \@services, \@xservices, 10, 1));
+    print &ui_table_row("EXCEPT", &ui_select("service_except", \@eservices, \@xservices, 10, 1));
+} else {
+    print &ui_table_row("<b>$text{'edit_service'}</b> ", &ui_textbox("service_custom", join(",",@services), 23));
+    print &ui_table_row("EXCEPT", &ui_textbox("service_except_custom", join(",",@eservices), 23));    
+}
+print &ui_table_hr();
+
+# Hosts
+@wildcards = ("ALL","KNOWN","UNKNOWN","LOCAL","PARANOID");
+$found = '';
+foreach my $w (@wildcards) {
+    $found = $w if ($w eq $hosts);
+}
+print &ui_table_row("<b>$text{'edit_hosts'}</b> ", &ui_opt_textbox("host_text", ($found ? "" : $hosts), 41, &ui_select("host_select", $found, \@wildcards)), 3);
+print &ui_table_row("", "<b>EXCEPT</b> ".&ui_textbox("host_except", $ehosts, 50), 3);
+print &ui_table_hr();
+
+# Shell commands
+@directives = ('none', 'spawn', 'twist');
+@cmds = split /:/, $rule->{'cmd'} if (!$in{'new'});
+print &ui_table_row($text{'edit_cmd'}, "", 3);
+for ($i = 0; $i <= $#cmds; $i++) {
+    $cmds[$i] =~ s/^\s*//;
+    my $choosed = $cmds[$i] =~ /^(spawn|twist)/ ? $1 : 'none';
+    $cmds[$i] =~ s/^\s*${choosed}\s*// if ($cmds[$i] =~ /^\s*(spawn)|(twist)/); 
+    print &ui_table_row("", &ui_select("cmd_directive_$i", $choosed, \@directives).' '.&ui_textbox("cmd_$i", $cmds[$i], 50), 3);
+}
+# Row for new command
+print &ui_table_row("", &ui_select("cmd_directive_$i", undef, \@directives).' '.&ui_textbox("cmd_$i", "", 50), 3);
+print &ui_hidden("cmd_count", $i),"\n";
+
+
+# Form footer
+print &ui_table_end();
+print &ui_form_end([
+       $in{'new'} ? ( [ "create", $text{'create'} ] )
+                  : ( [ "save", $text{'save'} ],
+                      [ "delete", $text{'delete'} ] ) ]);
+
+&ui_print_footer("", $text{'index_return'});
diff --git a/tcpwrappers/help/edit_rule.html b/tcpwrappers/help/edit_rule.html
new file mode 100644 (file)
index 0000000..e8ffed2
--- /dev/null
@@ -0,0 +1,59 @@
+<header>TCP Wrappers</header>
+
+<h3>Patterns</h3>
+The access control language implements the following patterns:
+<ul>
+<li>A  string  that begins with a '.' character. A host name is matched if the last components of its name match the specified pattern.  For example, the pattern '.tue.nl' matches the host name 'wzv.win.tue.nl'.</li>
+<li>A string that ends with a '.' character. A host address is matched if its first  numeric  fields  match  the  given  string.   For  example,  the  pattern '131.155.' matches the address of (almost) every host on the Eindhoven University network (131.155.x.x).</li>
+<li>A  string  that begins with an '@' character is treated as an NIS (formerly YP) netgroup name. A host name is matched if it is a host member of the specified netgroup. Netgroup matches are not supported for daemon process names or for client user names.</li>
+<li>An expression of the form 'n.n.n.n/m.m.m.m' is interpreted as a 'net/mask' pair. An IPv4 host address is matched if 'net' is equal to the bitwise  AND  of the  address  and  the  'mask'.  For  example, the net/mask pattern '131.155.72.0/255.255.254.0' matches every address in the range '131.155.72.0' through '131.155.73.255'.</li>
+<li>An expression of the form '[n:n:n:n:n:n:n:n]/m' is interpreted as a '[net]/prefixlen' pair. An IPv6 host address is matched if 'prefixlen' bits  of  'net' is  equal  to  the  'prefixlen'  bits  of  the  address. For example, the [net]/prefixlen pattern '[3ffe:505:2:1::]/64' matches every address in the range '3ffe:505:2:1:'? through '3ffe:505:2:1:ffff:ffff:ffff:ffff'.</li>
+<li>A string that begins with a '/' character is treated as a file name. A host name or address is matched if it matches any  host  name  or  address  pattern listed in the named file. The file format is zero or more lines with zero or more host name or address patterns separated by whitespace.  A file name pattern can be used anywhere a host name or address pattern can be used.</li>
+<li>Wildcards '*' and '?' can be used to match hostnames or IP addresses.  This method of matching cannot be used in  conjunction  with  'net/mask'  matching, hostname matching beginning with '.' or IP address matching ending with '.'.</li>
+</ul>
+
+<h3>Wildcards</h3>
+The access control language supports explicit wildcards:
+<table border>
+<tr><td><b>ALL</b></td><td>The universal wildcard, always matches.</td></tr>
+<tr><td><b>LOCAL</b></td><td>Matches any host whose name does not contain a dot character.</td></tr>
+<tr><td><b>UNKNOWN</b></td><td>
+              Matches  any user whose name is unknown, and matches any host whose name or address are unknown.  This pattern should be used with care: host names may be
+              unavailable due to temporary name server problems. A network address will be unavailable when the software cannot figure out what type of  network  it  is
+              talking to.</td></tr>
+<tr><td><b>KNOWN</b></td><td>Matches  any  user  whose  name  is known, and matches any host whose name and address are known. This pattern should be used with care: host names may be
+              unavailable due to temporary name server problems.  A network address will be unavailable when the software cannot figure out what type of network  it  is
+              talking to.</td></tr>
+<tr><td><b>PARANOID</b></td><td>
+              Matches  any  host  whose  name  does  not match its address.  When tcpd is built with -DPARANOID (default mode), it drops requests from such clients even
+              before looking at the access control tables.  Build without -DPARANOID when you want more control over such requests.</td></tr>
+</table>
+
+<h3>Operators</h3>
+<b>EXCEPT</b> Intended use is of the form: 'list_1 EXCEPT list_2'; this construct matches anything that matches list_1 unless it matches list_2.   The  EXCEPT  operator
+              can be used in daemon_lists and in client_lists. The EXCEPT operator can be nested: if the control language would permit the use of parentheses, 'a EXCEPT
+              b EXCEPT c' would parse as '(a EXCEPT (b EXCEPT c))'.
+
+<h3>Shell Commands</h3>
+       If the first-matched access control rule contains a shell command, that command is subjected to %<letter> substitutions (see next section).  The result  is  exe-
+       cuted  by  a  /bin/sh child process with standard input, output and error connected to /dev/null.  Specify an '&' at the end of the command if you do not want to
+       wait until it has completed.<p />
+
+       Shell commands should not rely on the PATH setting of the inetd.  Instead, they should use absolute path names, or they should begin with an explicit  PATH=what-
+       ever statement.
+<h3>% Expansions</h3>
+The following expansions are available within shell commands:
+<table>
+<tr><td>%a (%A)</td><td>The client (server) host address.</td></tr>
+<tr><td>%c</td><td>Client information: user@host, user@address, a host name, or just an address, depending on how much information is available.</td></tr>
+<tr><td>%d</td><td>The daemon process name (argv[0] value).</td></tr>
+<tr><td>%h (%H)</td><td>The client (server) host name or address, if the host name is unavailable.</td></tr>
+<tr><td>%n (%N)</td><td>The client (server) host name (or "unknown" or "paranoid").</td></tr>
+<tr><td>%p</td><td>The daemon process id.</td></tr>
+<tr><td>%s</td><td>Server information: daemon@host, daemon@address, or just a daemon name, depending on how much information is available.</td></tr>
+<tr><td>%u</td><td>The client user name (or "unknown").</td></tr>
+<tr><td>%%</td><td>Expands to a single '%? character.</td></tr>
+</table>
+Characters in % expansions that may confuse the shell are replaced by underscores.
+
+<hr />
diff --git a/tcpwrappers/help/intro.html b/tcpwrappers/help/intro.html
new file mode 100644 (file)
index 0000000..08dbcd9
--- /dev/null
@@ -0,0 +1,19 @@
+<header>TCP Wrappers</header>
+
+<h3>Introduction</h3>
+This module uses a simple access control language that is based on client (host name/address, user name), and server (process name, host name/address)
+patterns.<p />
+An extended version of the access control language is described in the hosts_options(5) document. The extensions are turned on at program build time by  building
+with -DPROCESS_OPTIONS.
+                            
+<h3>Access Control Files</h3>
+The access control software consults two files. The search stops at the first match:
+<ul>                                                 
+<li>Access will be granted when a (daemon,client) pair matches an entry in the /etc/hosts.allow file.</li>
+<li>Otherwise, access will be denied when a (daemon,client) pair matches an entry in the /etc/hosts.deny file.</li>
+<li>Otherwise, access will be granted.</li>
+</ul>
+A non-existing access control file is treated as if it were an empty file. Thus, access control can be turned off by providing no access control files.
+                                                                             
+
+<hr />
diff --git a/tcpwrappers/images/icon.gif b/tcpwrappers/images/icon.gif
new file mode 100644 (file)
index 0000000..b146c13
Binary files /dev/null and b/tcpwrappers/images/icon.gif differ
diff --git a/tcpwrappers/index.cgi b/tcpwrappers/index.cgi
new file mode 100755 (executable)
index 0000000..10c7a4d
--- /dev/null
@@ -0,0 +1,51 @@
+#!/usr/local/bin/perl
+# index.cgi
+
+require './tcpwrappers-lib.pl';
+
+&ui_print_header(undef, $text{'index_title'}, "", "intro", 1, 1);
+
+# ALLOWED HOSTS & DENIED HOSTS
+foreach my $type ('allow', 'deny') {
+    my $file = $type eq 'allow' ? $config{'hosts_allow'} : $config{'hosts_deny'};
+    @rules = &list_rules($file);
+    print "<font size=+1>".($type eq 'allow' ? $text{'index_allowtitle'} : $text{'index_denytitle'})."</font><p />\n";
+    if (@rules) {
+       print &ui_form_start("delete_rules.cgi", "post");
+       print &ui_hidden($type, 1),"\n";
+       print &select_all_link("d"),"\n";
+       print &select_invert_link("d"),"\n";
+       print "<a href='edit_rule.cgi?$type=1&new=1'>$text{'index_add'}</a><br />\n";
+       
+       @tds = ( "width=5" );
+       print &ui_columns_start([
+                                "",
+                                $text{'index_service'},
+                                $text{'index_hosts'},
+                                $text{'index_cmd'},
+                                ], "width=100%", 0, \@tds);
+       foreach my $r (@rules) {
+           print &ui_checked_columns_row([
+                                          "<a href='edit_rule.cgi?$type=1&id=$r->{'id'}'>$r->{'service'}</a>",
+                                          $r->{'host'},
+                                          $r->{'cmd'} ? join("<br>", split /:/, $r->{'cmd'}) : $text{'index_none'},
+                                          ], \@tds, "d", $r->{'id'});
+       }
+       print &ui_columns_end();
+       
+       print &select_all_link("d"),"\n";
+       print &select_invert_link("d"),"\n";
+       print "<a href='edit_rule.cgi?$type=1&new=1'>$text{'index_add'}</a><br />\n";
+       print &ui_form_end([ [ "delete", $text{'index_delete'} ] ]);
+    } else {
+       if (-r $file) {
+           print "<b>".&text('index_norule', $file)."</b><br />\n";
+           print "<a href='edit_rule.cgi?$type=1&new=1'>$text{'index_add'}</a><p />\n";
+       } else {
+           print "<br>".&text('index_nofile', $file)."</b><p />\n";
+       }
+    }   
+    print "<hr />\n" if ($type eq 'allow');
+}
+
+&ui_print_footer("/", $text{'index_return'});
diff --git a/tcpwrappers/lang/cz b/tcpwrappers/lang/cz
new file mode 100644 (file)
index 0000000..48c16c6
--- /dev/null
@@ -0,0 +1,28 @@
+index_title=TCP Wrappers
+index_return=index
+index_allowtitle=Povolený pøístup
+index_denytitle=Zakázaný pøístup
+index_norule=Soubor '$1' neobsahuje ¾ádná pravidla.
+index_nofile=Soubor '$1' neexistuje - zkontrolujte va¹i <a href="/config.cgi?tcpwrappers">konfiguraci modulu</a>
+index_add=Pøidat pravidlo
+index_service=Démon
+index_hosts=Klienti
+index_cmd=Pøíkaz
+index_delete=Smazat oznaèené
+index_none=není
+
+edit_title1=Vytvoøit pravidlo
+edit_title2=Upravit pravidlo
+edit_eid=Pravidlo nebylo nalezeno
+edit_header=Nastavení pravidla
+edit_service=Démoni
+edit_hosts=Klienti
+edit_cmd=Pøíkazy
+edit_efound=Démon '$1' nebyl nalezen v konfiguraci xinetd.
+
+save_errtitle=Chyba pøi ukládání pravidla
+save_ehost=Klient obsahuje nepovolené znaky
+save_ecmd=Pøíkaz obsahuje nepovolené znaky
+
+del_errtitle=Chyba pøi mazání pravidla
+del_enone=Není oznaèeno ¾ádné pravidlo
diff --git a/tcpwrappers/lang/en b/tcpwrappers/lang/en
new file mode 100644 (file)
index 0000000..0bf36ea
--- /dev/null
@@ -0,0 +1,29 @@
+index_title=TCP Wrappers
+index_return=index
+index_allowtitle=Allowed hosts
+index_denytitle=Denied hosts
+index_norule=File '$1' doesn't contain any rules.
+index_nofile=File '$1' doesn't exist - check your <a href="/config.cgi?tcpwrappers">module configuration</a>
+index_add=Add rule
+index_service=Daemon
+index_hosts=Hosts
+index_cmd=Command
+index_delete=Delete Selected
+index_none=none
+
+edit_title1=Create rule
+edit_title2=Edit rule
+edit_eid=This rule was not found
+edit_header=Rule options
+edit_service=Service
+edit_hosts=Hosts
+edit_cmd=Shell commands
+edit_efound=Daemon '$1' was not found in xinetd configuration.
+
+save_errtitle=Error on save rule
+save_ehost=Host input contains bad characters
+save_ecmd=Command input contains bad characters
+save_eservice=Daemon names contain bad characters
+
+del_errtitle=Error on rules delete
+del_enone=No rules marked to delete
diff --git a/tcpwrappers/module.info b/tcpwrappers/module.info
new file mode 100644 (file)
index 0000000..056f5b4
--- /dev/null
@@ -0,0 +1,5 @@
+name=tcpwrappers
+desc=TCP Wrappers
+category=net
+version=0.3
+longdesc=Configure the TCP wrappers networking access control files
diff --git a/tcpwrappers/save_rule.cgi b/tcpwrappers/save_rule.cgi
new file mode 100755 (executable)
index 0000000..579cfb7
--- /dev/null
@@ -0,0 +1,71 @@
+#!/usr/local/bin/perl
+# Create, update or delete a rule
+
+require './tcpwrappers-lib.pl';
+&ReadParse();
+&error_setup($text{'save_errtitle'});
+$file = $in{'allow'} ? $config{'hosts_allow'} : $config{'hosts_deny'};
+@rules = &list_rules($file);
+
+if (!$in{'new'}) {
+    ($rule) = grep { $_->{'id'} == $in{'id'} } @rules;
+    $rule || &error($text{'edit_eid'});
+}
+        
+&lock_file($file);
+if ($in{'delete'}) {
+    # Delete one rule
+    &delete_rule($file, $rule);
+} else {
+    # Check input
+    &error($text{'save_eservice'}) if ($in{'service_custom'} && $in{'service_custom'} !~ /^[\w\d\s\-\/\.,]+$/);
+    &error($text{'save_eservice'}) if ($in{'service_except_custom'} && $in{'service_except_custom'} !~ /^[\w\d\s\-\/\.,]+$/);
+
+    &error($text{'save_ehost'}) if ($in{'host_text_def'} == 0 && $in{'host_text'} !~ /^[\w\d\s\-\/\@\.,]+$/);
+    &error($text{'save_ehost'}) if ($in{'host_except'} && $in{'host_except'} !~ /^[\w\d\s\-\/\@\.,]+$/);
+
+    for (my $i = 0; $i <= $in{'cmd_count'}; $i++) {
+       &error($text{'save_ecmd'}) if ($in{'cmd_'.$i} && $in{'cmd_'.$i} !~ /^[\w\d\s\-\/\@\%\|\(\)\'\"\&\.,]+$/);
+    }
+
+}
+
+# Build rule record
+if ($in{'service_custom'}) {
+    $service = $in{'service_custom'}." EXCEPT ".$in{'service_except_custom'};
+} else {
+    # listed from (x)inetd
+    $service = join(",", split /\0/, $in{'service'});
+    if ($in{'service_except'}) {
+       $service .= " EXCEPT ".join(",", split /\0/, $in{'service_except'});
+    }
+}
+
+$host = $in{'host_text_def'} ? $in{'host_select'} : $in{'host_text'};
+if ($in{'host_except'}) {
+    $host .= " EXCEPT ".$in{'host_except'};
+}
+
+$cmd = '';
+for (my $i = 0; $i <= $in{'cmd_count'}; $i++) {
+    next unless ($in{'cmd_'.$i});
+    $cmd .= $cmd ? " : " : '';
+    $cmd .= $in{'cmd_directive_'.$i} ne 'none' ? $in{'cmd_directive_'.$i}.' ' : '';
+    $cmd .= $in{'cmd_'.$i};
+}
+
+my %newrule = ( 'service' => $service,
+               'host' => $host,
+               'cmd' => $cmd
+               );
+
+# Save to file
+if ($in{'new'}) {
+    &create_rule($file, \%newrule);
+} else {
+    &modify_rule($file, $rule, \%newrule);
+}
+
+&unlock_file($file);
+&webmin_log($in{'new'} ? "create" : $in{'delete'} ? "delete" : "modify", "rule", $rule->{'id'});
+&redirect("");
diff --git a/tcpwrappers/tcpwrappers-lib.pl b/tcpwrappers/tcpwrappers-lib.pl
new file mode 100644 (file)
index 0000000..ca13b11
--- /dev/null
@@ -0,0 +1,119 @@
+# tcpwrappers-lib.pl
+# Library for TCP Wrappers
+
+do '../web-lib.pl';
+&init_config();
+do '../ui-lib.pl';
+
+# list_rules($filename)
+# Parse rules from /etc/hosts.*
+# File format described in "man 5 hosts_access"
+sub list_rules {
+    my $file = shift;
+    my @ret;
+    my $id = 0;
+
+    open(HOSTS, $file) || return ();
+    my $line;
+    my $last_line = '';
+    my $lnum = 0;
+    while ($line = <HOSTS>) {
+       my ($slnum, $elnum) = ($lnum, $lnum);
+       s/\r|\n//g;
+
+       while ($line =~ /^(.*)\\/) {
+           # Continuation line! Read the next one and append it
+           local $before = $1;
+           local $nxt = <HOSTS>;
+           $nxt =~ s/\r|\n//g;
+           $line = $before.$nxt;
+           $elnum++; $lnum++;
+        }
+
+       if ($line =~ /^\#(.*)/) {
+           # Comment
+           $cmt = $cmt ? $cmt."\n".$1 : $1;
+       } elsif ($line =~ /^\s*$/) {
+           $cmt = undef;
+       } else {
+           my @cmtlines = split(/\n/, $cmt);
+           $cmt = undef;
+           my ($service, $host, $cmd) = split /:/, $line, 3;
+           $service =~ s/^\s*//; $service =~ s/\s*$//;
+           $host =~ s/^\s*//; $host =~ s/\s*$//;
+           
+           push @ret, { 'id' => $id++,
+                        'service' => $service,
+                        'host' => $host,
+                        'cmd' => $cmd,
+                        'line' => $slnum-scalar(@cmtlines),
+                        'eline' => $elnum
+                        };
+       }
+       $lnum++;
+    }
+    close FILE;
+
+    return @ret;
+}
+
+# list_services()
+# List system services from (x)inetd or return ()
+sub list_services {
+    my @ret;
+
+    if (&foreign_installed("xinetd")) {
+       &foreign_require("xinetd", "xinetd-lib.pl");
+       my @conf = &foreign_call('xinetd', 'get_xinetd_config');
+       foreach $x (@conf) {
+           next if ($x->{'quick'}{'server'}[0] !~ /\/([^\/]+)$/);
+           push @ret, $1;
+       }
+    } elsif (&foreign_installed("inetd")) {
+       &foreign_require("inetd", "inetd-lib.pl");
+       my @conf = &foreign_call('inetd', 'list_inets');
+       foreach $x (@conf) {
+           next unless ($x->[9] =~ /^(\S+)/);
+           push @ret, $1;
+       }
+    }
+
+    return &unique(@ret);
+}
+
+# delete_rule($filename, &rule)
+# Removes one rule entry from the file
+sub delete_rule {
+    my ($filename, $rule) = @_;
+
+    my $lref = &read_file_lines($filename);
+    my $len = $rule->{'eline'} - $rule->{'line'} + 1;
+    splice(@$lref, $rule->{'line'}, $len);
+    &flush_file_lines($filename);
+}
+
+# create_rule($filename, &rule)
+# Adds new rule
+sub create_rule {
+    my ($file, $rule) = @_;
+
+    my $lref = &read_file_lines($file);
+    my $newline = $rule->{'service'}.' : '.$rule->{'host'}.($rule->{'cmd'} ? ' : '.$rule->{'cmd'} : '');
+    push(@$lref, $newline);
+    &flush_file_lines($file);
+}
+
+# modify_rule($filename, &old_rule, &new_rule)
+# Updates rule
+sub modify_rule {
+    my ($filename, $oldrule, $newrule) = @_;
+
+    my @newline = ($newrule->{'service'}.' : '.$newrule->{'host'}.($newrule->{'cmd'} ? ' : '.$newrule->{'cmd'} : ''));
+
+    my $lref = &read_file_lines($filename);
+    my $len = $oldrule->{'eline'} - $oldrule->{'line'} + 1;
+    splice(@$lref, $oldrule->{'line'}, $len, @newline);
+    &flush_file_lines($filename);
+}
+
+1;
index 34f7339..c6d8fd4 100755 (executable)
@@ -210,6 +210,7 @@ $fh = $_[0];
 syswrite $fh, $str, length($str);
 }
 
+
 # check_ipaddress(ip)
 # Check if some IP address is properly formatted
 sub check_ipaddress
@@ -225,18 +226,38 @@ return $_[0] =~ /^(\d+)\.(\d+)\.(\d+)\.(\d+)$/ &&
 # Check if some IP address is properly formatted for IPv6
 sub check_ip6address
 {
-local @blocks = split(/:/, $_[0]);
-return 0 if (@blocks == 0 || @blocks > 8);
-local $b;
-local $empty = 0;
-foreach $b (@blocks) {
-       return 0 if ($b ne "" && $b !~ /^[0-9a-f]{1,4}$/i);
-       $empty++ if ($b eq "");
-       }
-return 0 if ($empty > 1 && !($_[0] =~ /^::/ && $empty == 2));
-return 1;
+  local @blocks = split(/:/, $_[0]);
+  return 0 if (@blocks == 0 || @blocks > 8);
+
+  # The address/netmask format is accepted. So we're looking for a "/" to isolate a possible netmask.
+  # After that, we delete the netmask to control the address only format, but we verify whether the netmask 
+  # value is in [0;128].
+  local $ib = $#blocks;
+  local $where = index($blocks[$ib],"/");
+  local $m=0;
+  if ($where != -1) {
+    local $b = substr($blocks[$ib],0,$where);
+    $m = substr($blocks[$ib],$where+1,length($blocks[$ib])-($where+1));
+    $blocks[$ib]=$b;
+  }
+
+  # The netmask must take its value in [0;128] 
+  return 0 if ($m <0 || $m >128); 
+
+  # Check the different blocks of the address : 16 bits block in hexa notation.
+  # Possibility of 1 empty block or 2 if the address begins with "::".
+  local $b;
+  local $empty = 0;
+  foreach $b (@blocks) {
+         return 0 if ($b ne "" && $b !~ /^[0-9a-f]{1,4}$/i);
+         $empty++ if ($b eq "");
+         }
+  return 0 if ($empty > 1 && !($_[0] =~ /^::/ && $empty == 2));
+  return 1;
 }
 
+
+
 # generate_icon(image, title, link, [href], [width], [height],
 #              [before-title], [after-title])
 # Prints HTML for an icon image