More on webmin-level awl management
authorJamie Cameron <jcameron@webmin.com>
Tue, 1 Apr 2008 00:52:35 +0000 (00:52 +0000)
committerJamie Cameron <jcameron@webmin.com>
Tue, 1 Apr 2008 00:52:35 +0000 (00:52 +0000)
spam/acl_security.pl
spam/delete_awl.cgi
spam/edit_awl.cgi
spam/index.cgi
spam/lang/en
spam/spam-lib.pl

index 1df871e..6b8ed1b 100644 (file)
@@ -5,19 +5,34 @@ require 'spam-lib.pl';
 # Output HTML for editing security options for the spam module
 sub acl_security_form
 {
+# Allowed features
 print "<tr> <td valign=top><b>$text{'acl_avail'}</b></td>\n";
 print "<td><select name=avail rows=6 multiple>\n";
 local %avail = map { $_, 1 } split(/,/, $_[0]->{'avail'});
 foreach $a ('white', 'score', 'report', 'user', 'header', 'setup', 'procmail',
-           'db') {
+           'db', 'awl') {
        printf "<option value=%s %s>%s\n",
                $a, $avail{$a} ? "selected" : "", $text{$a."_title"};
        }
 print "</select></td> </tr>\n";
 
+# Config file to edit
 print "<tr> <td><b>$text{'acl_file'}</b></td>\n";
 print "<td>",&ui_opt_textbox("file", $_[0]->{'file'}, 40, $text{'acl_filedef'}),
       "</td> </tr>\n";
+
+# Allowed auto-whitelist users
+print "<tr> <td><b>$text{'acl_awl'}</b></td>\n";
+print "<td>",&ui_radio("awl_mode", $_[0]->{'awl_groups'} ? 2 :
+                                   $_[0]->{'awl_users'} ? 1 : 0,
+       [ [ 0, $text{'acl_awl0'}."<br>\n" ],
+         [ 1, &text('acl_awl1',
+               &ui_textbox("awl_users", $_[0]->{'awl_users'}, 40).
+               &user_chooser_button("awl_users", 1)."<br>\n" ],
+         [ 2, &text('acl_awl2',
+               &ui_textbox("awl_groups", $_[0]->{'awl_groups'}, 40).
+               &group_chooser_button("awl_users", 1)."<br>\n" ],
+       ]),"</td> </tr>\n";
 }
 
 # acl_security_save(&options)
@@ -26,5 +41,13 @@ sub acl_security_save
 {
 $_[0]->{'avail'} = join(",", split(/\0/, $in{'avail'}));
 $_[0]->{'file'} = $in{'file_def'} ? undef : $in{'file'};
+delete($_[0]->{'awl_users'});
+delete($_[0]->{'awl_groups'});
+if ($in{'awl_mode'} == 1) {
+       $_[0]->{'awl_users'} = $in{'awl_users'};
+       }
+elsif ($in{'awl_mode'} == 2) {
+       $_[0]->{'awl_groups'} = $in{'awl_groups'};
+       }
 }
 
index 5752ea8..b07a516 100644 (file)
@@ -7,7 +7,7 @@ require './spam-lib.pl';
 &ReadParse();
 
 # Check stuff
-&open_auto_whitelist_dbm() || &error($text{'dawl_eopen'});
+&open_auto_whitelist_dbm($in{'user'}) || &error($text{'dawl_eopen'});
 @d = split(/\0/, $in{'d'});
 @d || &error($text{'dawl_enone'});
 
@@ -18,5 +18,6 @@ foreach $d (@d) {
        }
 
 &close_auto_whitelist_dbm();
-&redirect("edit_awl.cgi?search=".&urlize($in{'search'}));
+&redirect("edit_awl.cgi?search=".&urlize($in{'search'}).
+         "&user=".&urlize($in{'user'}));
 
index e5e2dd4..15ffc85 100644 (file)
@@ -1,19 +1,40 @@
 #!/usr/local/bin/perl
 # Display entries in the auto-whitelist
+# XXX delete all
+# XXX access control
 
 require './spam-lib.pl';
 &can_use_check("awl");
 &ui_print_header(undef, $text{'awl_title'}, "");
 &ReadParse();
+$formno = 0;
+
+# Check if we need a username
+if (&supports_auto_whitelist() == 2) {
+       print &ui_form_start("edit_awl.cgi");
+       print "<b>$text{'awl_user'}</b>\n";
+       print &ui_user_textbox("user", $in{'user'}),"\n",
+             &ui_submit($text{'awl_uok'});
+       print &ui_form_end();
+
+       if (!$in{'user'}) {
+               # Can't do any more
+               &ui_print_footer("", $text{'index_return'});
+               return;
+               }
+       }
 
 # Open the DBM, or give up
-$ok = &open_auto_whitelist_dbm();
-if ($ok == 0) {
-       &ui_print_endpage(&text('awl_cannot',
-                               &get_auto_whitelist_file()));
+$awf = &get_auto_whitelist_file($in{'user'});
+$ok = &open_auto_whitelist_dbm($in{'user'});
+if (!$awf) {
+       &ui_print_endpage("<b>".&text('awl_nofile')."</b>");
+       }
+elsif ($ok == 0) {
+       &ui_print_endpage("<b>".&text('awl_cannot', $awf)."</b>");
        }
 elsif ($ok < 0) {
-       &ui_print_endpage(&text('awl_empty', &get_auto_whitelist_file()));
+       &ui_print_endpage("<b>".&text('awl_empty', $awf)."</b>");
        }
 
 # Show search form
@@ -22,7 +43,9 @@ print &ui_form_start("edit_awl.cgi");
 print "<b>$text{'awl_search'}</b>\n";
 print &ui_textbox("search", $in{'search'}, 30),"\n",
       &ui_submit($text{'awl_ok'});
+print &ui_hidden("user", $in{'user'});
 print &ui_form_end();
+$formno++;
 if ($in{'search'}) {
        @keys = grep { /\Q$in{'search'}\E/i } @keys;
        print &text('awl_searching',
@@ -32,7 +55,8 @@ if ($in{'search'}) {
 # Show table
 print &ui_form_start("delete_awl.cgi", "post");
 print &ui_hidden("search", $in{'search'});
-@links = ( &select_all_link("d", 1), &select_invert_link("d", 1) );
+print &ui_hidden("user", $in{'user'});
+@links = ( &select_all_link("d", $formno), &select_invert_link("d", $formno) );
 @tds = ( "width=5" );
 print &ui_links_row(\@links);
 print &ui_columns_start([ "",
index b55ec46..d2d61ac 100755 (executable)
@@ -130,7 +130,7 @@ else {
                push(@pages, 'setup') if ($spam_enabled == 0);
                push(@pages, 'procmail') if ($delivery_enabled == 1);
                push(@pages, 'db') if (!$module_info{'usermin'});
-               push(@pages, 'awl') if (&get_auto_whitelist_file());
+               push(@pages, 'awl') if (&supports_auto_whitelist());
                @pages = grep { &can_use_page($_) } @pages;
                $sfolder = $module_info{'usermin'} ? &spam_file_folder()
                                                   : undef;
index 9d99df8..0df69b2 100644 (file)
@@ -254,6 +254,10 @@ apply_none=No SpamAssassin daemon processes found!
 acl_avail=Icons available to user
 acl_file=SpamAssassin configuration file to edit
 acl_filedef=Global config file
+acl_awl=Allowed users for auto-whitelist editing
+acl_awl0=All users
+acl_awl1=Only listed users $1
+acl_awl2=Only members of groups $1
 
 search_escore=Missing or invalid spam score
 search_results5=$1 mail messages with spam score at or above $2 ..
@@ -351,6 +355,9 @@ awl_unknown=Unknown
 awl_delete=Remove Selected Entries
 awl_cannot=Usermin could not open your auto-whitelist file <tt>$1</tt>, perhaps because it is in an un-supported format.
 awl_empty=Your auto-whitelist file <tt>$1</tt> does not contain any entries. It will be populated by SpamAsssassin as mail is processed by the system.
+awl_user=Show auto-whitelist for user:
+awl_uok=Show
+awl_nofile=This user does not have an auto-whitelist file.
 
 dawl_err=Failed to delete from auto-whitelist
 dawl_eopen=Could not open whitelist
index f93564a..ee1f592 100644 (file)
@@ -933,22 +933,25 @@ $get_ldap_user_cache{$user} = $uinfo;
 return $uinfo;
 }
 
-# get_auto_whitelist_file()
+# get_auto_whitelist_file([user])
 # Returns the base path to the auto whitelist DBM, if any. 
 sub get_auto_whitelist_file
 {
+local ($user) = @_;
 local $conf = &get_config();
 local $awp = &find("auto_whitelist_path", $conf);
 if (!$awp) {
-       $awp = &find_default("auto_whitelist_path",
-               "~/.spamassassin/auto-whitelist");
+       $awp = &find_default("auto_whitelist_path");
        }
+$awp ||= "~/.spamassassin/auto-whitelist";
 if ($awp !~ /^\//) {
        # Make absolute
-       return undef if (!$module_info{'usermin'});
-       $awp =~ s/^(\~|\$HOME)\//$remote_user_info[7]\//;
+       local @uinfo = $module_info{'usermin'} ? @remote_user_info :
+                      $user ? getpwnam($user) : ( );
+       return undef if (scalar(@uinfo) == 0);
+       $awp =~ s/^(\~|\$HOME)\//$uinfo[7]\//;
        if ($awp !~ /^\//) {
-               $awp = "$remote_user_info[7]/$awp";
+               $awp = "$uinfo[7]/$awp";
                }
        }
 # Does it exist?
@@ -959,12 +962,13 @@ if (!-r $awp) {
 return $awp;
 }
 
-# open_auto_whitelist_dbm()
+# open_auto_whitelist_dbm([user])
 # Ties the %awl hash to the autowhitelist DBM file. Returns 1 if successful, or
 # 0 if it could not be opened, or -1 if empty.
 sub open_auto_whitelist_dbm
 {
-local $awp = &get_auto_whitelist_file();
+local ($user) = @_;
+local $awp = &get_auto_whitelist_file($user);
 return 0 if (!$awp);
 local $anyok;
 foreach my $cls ('DB_File', 'GDBM_File', 'SDBM_File') {
@@ -987,5 +991,45 @@ sub close_auto_whitelist_dbm
 untie(%awl);
 }
 
+# supports_auto_whitelist()
+# Returns 1 if SpamAssassin is doing auto-whitelisting for the current user,
+# 2 if for multiple users.
+sub supports_auto_whitelist
+{
+if ($module_info{'usermin'}) {
+       return &get_auto_whitelist_file() ? 1 : 0;
+       }
+else {
+       return 2;
+       }
+}
+
+sub can_edit_awl
+{
+local ($user) = @_;
+return 1 if ($module_info{'usermin'});         # Only one user anyway
+if ($_[0]->{'awl_users'}) {
+       # Check if on user list
+       return &indexof($user, split(/\s+/, $_[0]->{'awl_users'})) >= 0;
+       }
+elsif ($_[0]->{'awl_groups'}) {
+       # Check if the user is a member of any of the allowed groups
+       local %ugroups;
+       local @uinfo = getpwnam($user);
+       return 0 if (!defined(@uinfo));
+       local @ginfo = getgrgid($uinfo[3]);
+       $ugroups{$ginfo[0]}++ if (defined(@ginfo));
+       foreach my $o (&other_groups($user)) {
+               $ugroups{$o}++;
+               }
+       local @can = grep { $ugroups{$_} } split(/\s+/, $_[0]->{'awl_groups'});
+       return @can ? 1 : 0;
+       }
+else {
+       # No restrictions
+       return 1;
+       }
+}
+
 1;