HEX
Server: Apache
System: Linux vps-cdc32557.vps.ovh.ca 5.15.0-156-generic #166-Ubuntu SMP Sat Aug 9 00:02:46 UTC 2025 x86_64
User: hanode (1017)
PHP: 7.4.33
Disabled: pcntl_alarm,pcntl_fork,pcntl_waitpid,pcntl_wait,pcntl_wifexited,pcntl_wifstopped,pcntl_wifsignaled,pcntl_wifcontinued,pcntl_wexitstatus,pcntl_wtermsig,pcntl_wstopsig,pcntl_signal,pcntl_signal_get_handler,pcntl_signal_dispatch,pcntl_get_last_error,pcntl_strerror,pcntl_sigprocmask,pcntl_sigwaitinfo,pcntl_sigtimedwait,pcntl_exec,pcntl_getpriority,pcntl_setpriority,pcntl_async_signals,pcntl_unshare,
Upload Files
File: //usr/share/perl5/Virtualmin/Config/Plugin/SASL.pm
package Virtualmin::Config::Plugin::SASL;
use strict;
use warnings;
no warnings qw(once);
use parent 'Virtualmin::Config::Plugin';
use Time::HiRes qw( sleep );    # XXX Figure out how to not need this.

our $config_directory;
our (%gconfig, %miniserv);
our $trust_unknown_referers = 1;

sub new {
  my ($class, %args) = @_;

  # inherit from Plugin
  my $self = $class->SUPER::new(name => 'SASL', %args);

  return $self;
}

# actions method performs whatever configuration is needed for this
# plugin. XXX Needs to make a backup so changes can be reverted.
sub actions {
  my $self = shift;

  use Cwd;
  my $cwd  = getcwd();
  my $root = $self->root();
  chdir($root);
  $0 = "$root/virtual-server/config-system.pl";
  push(@INC, $root);
  push(@INC, "$root/vendor_perl");
  eval 'use WebminCore';    ## no critic
  init_config();

  $self->spin();
  sleep 0.3;
  eval {
    my $res = 1;
    foreign_require("init", "init-lib.pl");
    init::enable_at_boot("saslauthd");
    my ($saslinit, $cf, $libdir);
    if ( $gconfig{'os_type'} eq "debian-linux"
      or $gconfig{'os_type'} eq "ubuntu-linux")
    {
      # Update saslauthd default to start on boot
      my $fn          = "/etc/default/saslauthd";
      my $sasldefault = read_file_lines($fn) or die "Failed to open $fn!";
      my $idx         = indexof("# START=yes", @$sasldefault);
      my $idx2        = grep {/START=/} @$sasldefault;
      if ($idx < 0) {
        $idx = indexof("START=no", @$sasldefault);
      }
      if ($idx >= 0) {
        $sasldefault->[$idx] = "START=yes";
      }
      if (!$idx2) {
        push(@{$sasldefault}, "START=yes");
      }

      # Substitute options and params if already in file
      my $added_opts = 0;
      my $added_params = 0;
      foreach my $l (@$sasldefault) {
        if ($l =~ /^OPTIONS/) {
          $l = 'OPTIONS="-c -m /var/spool/postfix/var/run/saslauthd -r"';
          $added_opts++;
        }
        if ($l =~ /^PARAMS/) {
          $l = 'PARAMS="-m /var/spool/postfix/var/run/saslauthd -r"';
          $added_params++;
        }
      }

      # Add them, if not
      push(@$sasldefault,
        'OPTIONS="-c -m /var/spool/postfix/var/run/saslauthd -r"')
          if (!$added_opts && !grep {/^OPTIONS/} @$sasldefault);
      push(@$sasldefault,
        'PARAMS="-m /var/spool/postfix/var/run/saslauthd -r"')
          if (!$added_params && !grep {/^PARAMS/} @$sasldefault);
      flush_file_lines($fn);

      $cf = "/etc/postfix/sasl/smtpd.conf";
      $self->logsystem("mkdir -p -m 755 /var/spool/postfix/var/run/saslauthd");
      $self->logsystem("adduser postfix sasl");
      $saslinit = "/etc/init.d/saslauthd";
      # Ubuntu 24.04 uses native saslauthd.service, so we need
      # to fix PIDFile location because chroot Postfix expects
      # it to be in /var/spool/postfix/var/run/saslauthd
      my $os_ver = $gconfig{'real_os_version'};
      if ($os_ver && $os_ver =~ /^(24)/) {
        my $systemd_saslauthd_override_path = "/etc/systemd/system/saslauthd.service.d";
        $self->logsystem("mkdir -p -m 755 $systemd_saslauthd_override_path")
          if (!-d $systemd_saslauthd_override_path);
        write_file_contents($systemd_saslauthd_override_path . "/override.conf",
          "[Service]\n".
          "PIDFile=/var/spool/postfix/var/run/saslauthd/saslauthd.pid\n");
        $self->logsystem("systemctl daemon-reload");
        $self->logsystem("systemctl restart saslauthd.service");
      }
    }
    elsif ($gconfig{'os_type'} eq 'solaris') {

      # Use CSW saslauthd
      my $lref = read_file_lines("/opt/csw/etc/saslauthd.init");
      foreach my $l (@$lref) {
        if ($l =~ /^\#+\s*MECHANISM/) {
          $l = "MECHANISM=pam";
        }
      }
      flush_file_lines("/opt/csw/etc/saslauthd.init");
      $cf       = "/opt/csw/lib/sasl2/smtpd.conf";
      $saslinit = "/etc/init.d/cswsaslauthd";
    }
    else {
      # I'm not liking all of this jiggery pokery...need a better way to
      # detect which lib directory to work in.XXX
      if ($gconfig{'os_type'} eq 'freebsd') { $libdir = "/usr/local/lib"; }
      else {
        if (-e "/usr/lib64" && -e "/usr/lib64/perl") { $libdir = "/usr/lib64"; }
        else                                         { $libdir = "/usr/lib"; }
      }
      if    (-e "/etc/sasl2/smtpd.conf") { $cf = "/etc/sasl2/smtpd.conf"; }
      elsif (-e "$libdir/sasl2")         { $cf = "$libdir/sasl2/smtpd.conf"; }
      elsif (-e "$libdir/sasl")          { $cf = "$libdir/sasl/smtpd.conf"; }
      else {
#print "No sasl library directory found.  SASL authentication probably won't work";
        $res = 0;
      }
      if ($gconfig{'os_type'} eq 'freebsd') {
        $saslinit = "/usr/local/etc/rc.d/saslauthd";
      }
      else { $saslinit = "/etc/init.d/saslauthd"; }
    }
    if ($cf) {
      if (!-e $cf) {
        $self->logsystem("touch $cf");
      }
      my $smtpdconf = read_file_lines($cf) or die "Failed to open $cf!";
      push(@$smtpdconf, "pwcheck_method: saslauthd")
        if (!grep {/^pwcheck_method/} @$smtpdconf);
      push(@$smtpdconf, "mech_list: plain login")
        if (!grep {/^mech_list/} @$smtpdconf);
      flush_file_lines($cf);

      init::start_action('saslauthd');
    }

    # Update flags to use realm as part of username
    my $saslconfig = "/etc/sysconfig/saslauthd";
    if (-r $saslconfig) {
      my $lref = read_file_lines($saslconfig);
      foreach my $l (@$lref) {
        if ($l =~ /^\s*FLAGS=\s*$/) {
          $l = "FLAGS=\"-r\"";
        }
        elsif ($l =~ /^\s*FLAGS="(.*)"$/ && $l !~ /-r/) {
          $l = "FLAGS=\"$1 -r\"";
        }
      }
      flush_file_lines($saslconfig);
    }

    $self->done(1);    # OK!
  };
  if ($@) {
    $self->done(0);
  }
}

1;