Added new page for network ports
authorJamie Cameron <jcameron@webmin.com>
Sat, 26 Jan 2008 08:16:00 +0000 (08:16 +0000)
committerJamie Cameron <jcameron@webmin.com>
Sat, 26 Jan 2008 08:16:00 +0000 (08:16 +0000)
sendmail/CHANGELOG
sendmail/acl_security.pl
sendmail/defaultacl
sendmail/images/ports.gif [new file with mode: 0644]
sendmail/index.cgi
sendmail/lang/en
sendmail/list_opts.cgi
sendmail/list_ports.cgi [new file with mode: 0644]
sendmail/save_opts.cgi
sendmail/save_ports.cgi [new file with mode: 0644]
sendmail/sendmail-lib.pl

index 13e8db3..40ef944 100644 (file)
@@ -32,3 +32,4 @@ Added access control for the Spam Control page.
 ---- Changes since 1.390 ----
 Added a Module Config option to support ~/Maildir mailboxes (even though Sendmail doesn't support this natively).
 Added an option to show the directory queued messages are in, which is useful on systems with several queues.
+Network ports and addresses used by Sendmail can now be more easily edited on the new Network Ports page, which updates both sendmail.cf and any .mc file.
index ce7cd5f..bbd8f10 100644 (file)
@@ -99,9 +99,15 @@ print "</td> </tr>\n";
 print "<tr> <td><b>$text{'acl_flushq'}</b></td> <td>\n";
 printf "<input type=radio name=flushq value=1 %s> $text{'yes'}\n",
        $_[0]->{'flushq'} ? "checked" : "";
-printf "<input type=radio name=flushq value=0 %s> $text{'no'}</td> </tr>\n",
+printf "<input type=radio name=flushq value=0 %s> $text{'no'}</td>\n",
        $_[0]->{'flushq'} ? "" : "checked";
 
+print "<td><b>$text{'acl_ports'}</b></td> <td>\n";
+printf "<input type=radio name=ports value=1 %s> $text{'yes'}\n",
+       $_[0]->{'ports'} ? "checked" : "";
+printf "<input type=radio name=ports value=0 %s> $text{'no'}</td>\n",
+       $_[0]->{'ports'} ? "" : "checked";
+
 # Virtusers
 print "<tr> <td colspan=4><hr></td> </tr>\n";
 
@@ -198,6 +204,7 @@ printf "<input name=saddrs size=40 value='%s'></td> </tr>\n",
 sub acl_security_save
 {
 $_[0]->{'opts'} = $in{'opts'};
+$_[0]->{'ports'} = $in{'ports'};
 $_[0]->{'cws'} = $in{'cws'};
 $_[0]->{'masq'} = $in{'masq'};
 $_[0]->{'trusts'} = $in{'trusts'};
index 1a21098..956bdba 100644 (file)
@@ -28,3 +28,4 @@ manual=1
 qdomsmode=2
 flushq=1
 smode=1
+ports=1
diff --git a/sendmail/images/ports.gif b/sendmail/images/ports.gif
new file mode 100644 (file)
index 0000000..83f72ea
Binary files /dev/null and b/sendmail/images/ports.gif differ
index 0df7b7e..d16edcc 100755 (executable)
@@ -67,13 +67,14 @@ if (!$config{'mailq_count'}) {
        $mcount = scalar(@qfiles);
        }
 
-@olinks =  ( "list_opts.cgi", "list_aliases.cgi", "list_cws.cgi", "list_masq.cgi", "list_trusts.cgi", "list_virtusers.cgi", "list_mailers.cgi", "list_generics.cgi", "list_cgs.cgi", "list_domains.cgi", "list_access.cgi", "list_relay.cgi", "list_features.cgi", "list_mailq.cgi", "../mailboxes/" );
+@olinks =  ( "list_opts.cgi", "list_ports.cgi", "list_aliases.cgi", "list_cws.cgi", "list_masq.cgi", "list_trusts.cgi", "list_virtusers.cgi", "list_mailers.cgi", "list_generics.cgi", "list_cgs.cgi", "list_domains.cgi", "list_access.cgi", "list_relay.cgi", "list_features.cgi", "list_mailq.cgi", "../mailboxes/" );
 
-@otitles = ( "$text{'opts_title'} (O)", "$text{'aliases_title'} (aliases)", "$text{'cws_title'} (Cw)", "$text{'masq_title'} (CM)", "$text{'trusts_title'} (T)", "$text{'virtusers_title'} (virtuser)", "$text{'mailers_title'} (mailertable)", "$text{'generics_title'} (generics)", "$text{'cgs_title'} (CG)", "$text{'domains_title'} (domaintable)", "$text{'access_title'} (access)", "$text{'relay_title'} (CR)", $text{'features_title'}, "$text{'mailq_title'} (mailq)".(defined($mcount) ? "<br>".&text('mailq_count', $mcount) : ""), "$text{'boxes_title'}"); 
+@otitles = ( "$text{'opts_title'} (O)", $text{'ports_title'}, "$text{'aliases_title'} (aliases)", "$text{'cws_title'} (Cw)", "$text{'masq_title'} (CM)", "$text{'trusts_title'} (T)", "$text{'virtusers_title'} (virtuser)", "$text{'mailers_title'} (mailertable)", "$text{'generics_title'} (generics)", "$text{'cgs_title'} (CG)", "$text{'domains_title'} (domaintable)", "$text{'access_title'} (access)", "$text{'relay_title'} (CR)", $text{'features_title'}, "$text{'mailq_title'} (mailq)".(defined($mcount) ? "<br>".&text('mailq_count', $mcount) : ""), "$text{'boxes_title'}"); 
 
-@oicons =  ( "images/opts.gif", "images/aliases.gif", "images/cws.gif", "images/masq.gif", "images/trusts.gif", "images/virtusers.gif", "images/mailers.gif", "images/generics.gif", "images/cgs.gif", "images/domains.gif", "images/access.gif", "images/relay.gif", "images/features.gif", "images/mailq.gif", "images/boxes.gif" );
+@oicons =  ( "images/opts.gif", "images/ports.gif", "images/aliases.gif", "images/cws.gif", "images/masq.gif", "images/trusts.gif", "images/virtusers.gif", "images/mailers.gif", "images/generics.gif", "images/cgs.gif", "images/domains.gif", "images/access.gif", "images/relay.gif", "images/features.gif", "images/mailq.gif", "images/boxes.gif" );
 
 &filter_icons($access{'opts'}, "list_opts.cgi");
+&filter_icons($access{'ports'}, "list_ports.cgi");
 &filter_icons($access{'cws'}, "list_cws.cgi");
 &filter_icons($access{'masq'}, "list_masq.cgi");
 &filter_icons($access{'trusts'}, "list_trusts.cgi");
index c190469..c68e7f7 100644 (file)
@@ -603,6 +603,7 @@ file_emode=Unknown mode!
 file_err=Failed to edit file
 
 acl_opts=Can edit sendmail options?
+acl_ports=Can edit network ports?
 acl_cws=Can edit local domains?
 acl_masq=Can configure domain masquerading?
 acl_trusts=Can edit trusted users?
@@ -668,6 +669,7 @@ acl_usersu=With UID in range
 acl_spam=Spam control addresses this user can edit
 
 log_opts=Changed sendmail options
+log_ports=Change network ports
 log_alias_create=Created alias $1
 log_alias_modify=Modified alias $1
 log_alias_delete=Deleted alias $1
@@ -803,3 +805,27 @@ restart_ekill=Failed to signal sendmail processes : $1
 
 start_err=Failed to start sendmail
 start_ecannot=You are not allowed to start sendmail
+
+ports_title=Network Ports
+ports_name=Port name
+ports_addr=Listen on address
+ports_all=All
+ports_ip=IP
+ports_port=Listen on port
+ports_opts=Port options
+ports_mod_a=Require SMTP authentication
+ports_mod_b=Use same interface for outgoing email
+ports_mod_c=Rerform hostname canonification
+ports_mod_f=Require fully qualified hostname
+ports_mod_h=Use name of interface for HELO
+ports_mod_C=Don't perform hostname canonification
+ports_mod_E=Disallow ETRN
+ports_def1=Accept email on port 25 and all addresses
+ports_def0=Accept email only on ports below ..
+ports_err=Failed to save network ports
+ports_ecannot=You are not allowed to manage network ports
+ports_ename=Invalid port name in row $1
+ports_eclash=Duplicate port name in row $1
+ports_eaddress=Missing or invalid IP address in row $1
+ports_eport=Missing or invalid port number in row $1
+
index 04c0119..df9fd39 100755 (executable)
@@ -68,13 +68,6 @@ foreach $dmo ('priority', 'host', 'time') {
        }
 print "</td> </tr>\n";
 
-if ($ver >= 9) {
-       print "<tr>\n";
-       &options_input($text{'opts_daemon'}, "DaemonPortOptions", $conf,
-                     $default, 50);
-       print "</tr>\n";
-       }
-
 print "<tr>\n";
 &option_input($text{'opts_queuela'}, "QueueLA", $conf, $default, 6);
 &option_input($text{'opts_refusela'}, "RefuseLA", $conf, $default,6);
diff --git a/sendmail/list_ports.cgi b/sendmail/list_ports.cgi
new file mode 100644 (file)
index 0000000..7f966b4
--- /dev/null
@@ -0,0 +1,68 @@
+#!/usr/local/bin/perl
+# Show a list of TCP ports Sendmail uses
+
+require './sendmail-lib.pl';
+$access{'ports'} || &error($text{'ports_ecannot'});
+&ui_print_header(undef, $text{'ports_title'}, "");
+
+# Get and parse current setting
+$conf = &get_sendmailcf();
+foreach $dpo (&find_options("DaemonPortOptions", $conf)) {
+       local %opts;
+       foreach $o (split(/\s*,\s*/, $dpo->[1])) {
+               if ($o =~ /^([^=]+)=(\S+)$/) {
+                       $opts{$1} = $2;
+                       }
+               }
+       push(@ports, \%opts);
+       }
+
+# Show table of ports
+print &ui_form_start("save_ports.cgi");
+print &ui_radio("ports_def", @ports ? 0 : 1,
+       [ [ 1, $text{'ports_def1'} ], [ 0, $text{'ports_def0'} ] ])."<p>\n";
+print &ui_columns_start([
+       $text{'ports_name'},
+       $text{'ports_addr'},
+       $text{'ports_port'},
+       $text{'ports_opts'},
+       ], 100);
+$i = 0;
+@tds = ( "valign=top", "valign=top", "valign=top" );
+@known_opts = ( 'Name', 'Address', 'Port', 'Modifiers' );
+foreach $p (@ports, { }) {
+       @cols = ( );
+       foreach $k (@known_opts) {
+               $fk = substr($k, 0, 1);
+               if ($p->{$fk} && !$p->{$k}) {
+                       # Using first letter abbreviation only
+                       $p->{$k} = $p->{$fk};
+                       delete($p->{$fk});
+                       }
+               }
+       push(@cols, &ui_textbox("name_$i", $p->{'Name'}, 10));
+       push(@cols, &ui_opt_textbox("addr_$i", $p->{'Address'}, 15,
+                                   $text{'ports_all'}, $text{'ports_ip'}));
+       push(@cols, &ui_opt_textbox("port_$i", $p->{'Port'}, 6,
+                                   $text{'default'}." (25)"));
+       @mods = ( );
+       foreach $m (@port_modifier_flags) {
+               push(@mods, &ui_checkbox("mod_$i", $m, $text{'ports_mod_'.$m},
+                                        $p->{'Modifiers'} =~ /$m/));
+               }
+       push(@cols, &ui_grid_table(\@mods, 2));
+       print &ui_columns_row(\@cols, \@tds);
+
+       # Hidden field for other settings
+       foreach $k (@known_opts) {
+               delete($p->{$k});
+               }
+       print &ui_hidden("other_$i",
+               join(",", map { $_."=".$p->{$_} } keys %$p));
+       $i++;
+       }
+print &ui_columns_end();
+print &ui_form_end([ [ undef, $text{'save'} ] ]);
+
+&ui_print_footer("", $text{'index_return'});
+
index c2934cc..dbd1bc7 100755 (executable)
@@ -43,9 +43,6 @@ if ($ver >= 10) {
        &save_option("MaxRecipientsPerMessage", '\d+', $text{'opts_maxrcpt'});
        &save_option("BadRcptThrottle", '\d+', $text{'opts_maxbad'});
        }
-if ($ver >= 9) {
-       &save_options("DaemonPortOptions", '.*\S.*', $text{'opts_daemon'});
-       }
 &flush_file_lines();
 &unlock_file($config{'sendmail_cf'});
 &restart_sendmail();
diff --git a/sendmail/save_ports.cgi b/sendmail/save_ports.cgi
new file mode 100644 (file)
index 0000000..4b9496f
--- /dev/null
@@ -0,0 +1,91 @@
+#!/usr/local/bin/perl
+# Update the list of TCP ports Sendmail uses
+
+require './sendmail-lib.pl';
+require './features-lib.pl';
+
+&ReadParse();
+&error_setup($text{'ports_err'});
+$access{'ports'} || &error($text{'ports_ecannot'});
+
+# Parse and validate inputs
+@ports = ( );
+if (!$in{'ports_def'}) {
+       for($i=0; defined($name=$in{"name_$i"}); $i++) {
+               # Port name
+               next if (!$name);
+               $name =~ /^[a-z0-9\_]+$/i || &error(&text('ports_ename', $i+1));
+               $done{$name}++ && &error(&text('ports_eclash', $i+1));
+               @opts = ( "Name=$name" );
+
+               # IP address
+               if (!$in{"addr_${i}_def"}) {
+                       &check_ipaddress($in{"addr_$i"}) ||
+                               &error(&text('ports_eaddr', $i+1));
+                       push(@opts, "Address=".$in{"addr_$i"});
+                       }
+
+               # TCP port
+               if (!$in{"port_${i}_def"}) {
+                       $in{"port_$i"} =~ /^\d+$/ && $in{"port_$i"} > 0 &&
+                           $in{"port_$i"} < 65536 ||
+                               &error(&text('ports_eport', $i+1));
+                       push(@opts, "Port=".$in{"port_$i"});
+                       }
+
+               # Modifiers
+               @mods = split(/\0/, $in{"mod_$i"});
+               if (@mods) {
+                       push(@opts, "Modifiers=".join("", @mods));
+                       }
+
+               # Other options
+               push(@opts, split(/,/, $in{"other_$i"}));
+               push(@ports, join(",", @opts));
+               }
+       }
+
+# Update sendmail.cf
+&lock_file($config{'sendmail_cf'});
+$conf = &get_sendmailcf();
+@oldlist = map { $_->[0] } &find_options("DaemonPortOptions", $conf);
+@newlist = map { { 'type' => 'O',
+                  'values' => [ " DaemonPortOptions=$_" ] } } @ports;
+&save_directives($conf, \@oldlist, \@newlist);
+&flush_file_lines($config{'sendmail_cf'});
+&unlock_file($config{'sendmail_cf'});
+
+# Update .mc file too, if we have one
+if ($features_access) {
+       @features = &list_features();
+       if (@features) {
+               &lock_file($config{'sendmail_mc'});
+               @dpa = grep { $_->{'type'} == 0 &&
+                       $_->{'text'} =~ /^DAEMON_OPTIONS/ } @features;
+               for($i=0; $i<@dpa || $i<@ports; $i++) {
+                       if ($dpa[$i] && $ports[$i]) {
+                               # Modify
+                               $dpa[$i]->{'text'} =
+                                       "DAEMON_OPTIONS(`$ports[$i]')";
+                               &modify_feature($dpa[$i]);
+                               }
+                       elsif ($dpa[$i] && !$ports[$i]) {
+                               # No longer needed .. delete
+                               &delete_feature($dpa[$i]);
+                               }
+                       elsif (!$dpa[$i] && $ports[$i]) {
+                               # Add new feature
+                               $f = { 'type' => 0,
+                                  'text' => "DAEMON_OPTIONS(`$ports[$i]')" };
+                               &create_feature($f);
+                               }
+                       }
+               &unlock_file($config{'sendmail_mc'});
+               }
+       }
+
+# Restart Sendmail
+&restart_sendmail();
+&webmin_log("ports");
+&redirect("");
+
index ab53600..addf484 100644 (file)
@@ -6,8 +6,9 @@ do '../web-lib.pl';
 &init_config();
 do '../ui-lib.pl';
 %access = &get_module_acl();
-$features_access = $access{'opts'} && $access{'cws'} && $access{'masq'} && $access{'trusts'} && $access{'vmode'} && $access{'amode'} && $access{'omode'} && $access{'cgs'} && $access{'relay'} && $access{'mailers'} && $access{'access'} && $access{'domains'};
+$features_access = $access{'opts'} && $access{'ports'} && $access{'cws'} && $access{'masq'} && $access{'trusts'} && $access{'vmode'} && $access{'amode'} && $access{'omode'} && $access{'cgs'} && $access{'relay'} && $access{'mailers'} && $access{'access'} && $access{'domains'};
 $config{'perpage'} ||= 20;     # a value of 0 can cause problems
+@port_modifier_flags = ( 'a', 'b', 'c', 'f', 'h', 'C', 'E' );
 
 # get_sendmailcf()
 # Parses sendmail.cf and return a reference to an array of options.