smtp

netmotiv8

Verified User
Joined
Sep 26, 2003
Messages
234
Location
UK
Can u disable smtp per user? It is not an option to offer when creating a package. can this be made an option?

As part of our product range we offer 'LITE' hosting packages which do not allow smtp and instead user have to send outgoing mail via their ISP.
 
Hello,

That is not a feature that DA supports. It is possible with some perl knowledge, but beyond the scope of this forum (see /etc/exim.pl)

John
 
netmotiv8's post is a little ambiguous, but I read it as asking whether you could disable clients sending mail _through_ their account. This would only be allowed if you were using POP before SMTP or another SMTP authentication protocol. And if you were it should be trivial to disable it for a particular domain no?
 
Strange. What does DA use to do POP before SMTP? For me it's a one line mod to the pop-before-smtp Perl script.
 
chuckd said:
Strange. What does DA use to do POP before SMTP? For me it's a one line mod to the pop-before-smtp Perl script.
Chuck, I withdraw my "definitely" and look forward to you telling us how to do it :) .

I just don't have the time to investigate it, at least not through the end of the year.

Jeff
 
I wrote up a little program which does the checking of the /var/log/maillog file.

It checks for a modification time change every 2 seconds, and when it finds one, it opens the file, jumps to where it last read data, and reads the few new lines and makes the appropriate changes to the /etc/virtual/pophosts file. Because it's only looking for a change in the file "headers" and doesn't open the file unless required, it uses next to no resources. It keeps track of who authenticated when, so that 30 minutes later, their ip will be removed from the file.

It's homemade and hardcoded in superfast c++ :)

John
 
Very nice. Much better than using some of the other monstrosities available.

The pop-before-smtp.pl script is a beautiful example of Perl at its best. Recent versions have got larger due to an expanding user base, but I always remember being shocked by the simplicity of the original versions. Also uses very little resources but obviously couldn't be as lean as your proggy.
 
hmm... sorry for bumping this old thread.

I'm also interested in disabling SMTP on a per user basis, if possible.

I would like to offer SMTP as add-on, not as a default feature. Or at least a way to disable it for some users.

Is this possible? Is it too difficult to implement?

Thanks
 
The smtp server, exim, runs either serverwide or not at all. Even if you turn off the daemon it will still be called by programs that want to run it.

You can create a custom exim.conf file that will not forward email (either in or out or both) for specific users. Or you can pay someone to do it for you.

If you wish to do the latter we'd be a good company to check with, since we wrote the exim.conf file DA uses.

Jeff
 
hmm... I would like to learn how to do it. :cool:

I should say I have no idea about exim/perl.

I've been analizing the exim.conf and exim.pl files, also I've been using the following URL for references:
http://www.exim.org/exim-html-4.40/doc/html/spec.html

Arggg... I hate computers! (I've been working with them since 1986) ;)

Here's my first try: What would happen making the following modifications to exim.conf ?
Code:
FIND:
domainlist local_domains = lsearch;/etc/virtual/domains

AFTER ADD:
domainlist local_domains_without_smtp = lsearch;/etc/virtual/domains_without_smtp

FIND:
  accept  hosts = :

AFTER ADD:
  deny  domains       = +local_domains_without_smtp

Jeff, can you give me a hand on this, please?
 
markus said:
hmm... I would like to learn how to do it. :cool:

I should say I have no idea about exim/perl.

I've been analizing the exim.conf and exim.pl files, also I've been using the following URL for references:
http://www.exim.org/exim-html-4.40/doc/html/spec.html

Arggg... I hate computers! (I've been working with them since 1986) ;)

Here's my first try: What would happen making the following modifications to exim.conf ?
Code:
FIND:
domainlist local_domains = lsearch;/etc/virtual/domains

AFTER ADD:
domainlist local_domains_without_smtp = lsearch;/etc/virtual/domains_without_smtp

FIND:
  accept  hosts = :

AFTER ADD:
  deny  domains       = +local_domains_without_smtp

Jeff, can you give me a hand on this, please?

Seeing as Jeff offered his services as a PAID service I don't think he would just give you the answer, Pay him a little money (he surely is not an unreasonable man) and get it done right the first time.

Regards,
Onno
 
You can get support here from lots of people, including me.

I'm happy to answer all questions I can as time and resources permit.

Right now I'm very busy working for paid clients and on finishing up the VirusBlocker exim.conf file.

And certainly you don't expect me to pay one of our programmers to answer questions here free, do you :rolleyes: ?

Jeff
 
Certainly, I never said I was willing to pay for this information. I just posted in the hope of getting a bit of help. If you're so busy doing bussiness, well congrats. :D

ok, I noticed a little bug in my previous "try". If anyone wants to give it a try, I believe I got it now.

Create a file /etc/virtual/domains_without_smtp, then insert a line for every local domain you want to deny SMTP access. Look at file /etc/virtual/domains for an example of its syntax. ...or look at this page for more information:
http://www.exim.org/exim-html-4.40/doc/html/spec_38.html

Code:
EDIT:
/etc/exim.conf

FIND:
domainlist local_domains = lsearch;/etc/virtual/domains

AFTER ADD:
domainlist local_domains_without_smtp = lsearch;/etc/virtual/domains_without_smtp

FIND:
# Deny unless sender address can be verified:
# This statement requires the sender address to be verified before any
# subsequent ACL statement can be used. If verification fails, the incoming
# recipient address is refused. Verification consists of trying to route the
# address, to see if a bounce message could be delivered to it. In the case of
# remote addresses, basic verification checks only the domain.

  require verify = sender

BEFORE ADD:
  deny sender_domains = +local_domains_without_smtp
I have made some tests and it seems to work. :rolleyes:

Does anyone see any problem on this approach?

Well, all it needs (if it works) is add an option to manage the contents of the file /etc/virtual/domains_without_smtp from the DA reseller panels or so.


Cheers
 
ok, my previous attempt also fail as the sender may use a different domain as return path.

So, I guess the only way to achieve this is at SMTP AUTH time, by touching the exim.pl script.

Here's a new attempt:

Code:
#
# OPEN:
#
/etc/exim.pl

#
# FIND:
#
		open(PASSFILE, "< $homepath/.shadow") || return "no";
		$crypted_pass = <PASSFILE>;
		close PASSFILE;

#
# AFTER ADD:
#
#+MOD: Is User Domain Allowed to use SMTP
		$domain = get_user_domain($username);
		if (not is_smtp_allowed($domain)) { return "no"; }
#-MOD: Is User Domain Allowed to use SMTP


#
# FIND:
#
		#the username contain a domain, which is now in $domain.
		#this is a pure virtual pop account.

		open(PASSFILE, "< /etc/virtual/$domain/passwd") || return "no";

#
# BEFORE ADD:
#
#+MOD: Is User Domain Allowed to use SMTP
		if (not is_smtp_allowed($domain)) { return "no"; }
#-MOD: Is User Domain Allowed to use SMTP


#
# FIND:
#
sub find_uid_apache

#
# BEFORE ADD:
#
#+MOD: Is User Domain Allowed to use SMTP
sub is_smtp_allowed
{
	my ($domain) = @_;
	open(DOMAINS,"/etc/virtual/domains_without_smtp");
	while (<DOMAINS>)
	{
		$_ =~ s/\n//;
		if ($domain eq $_)
		{
			return 0;
		}
	}
	close(DOMAINS);

	return 1;
}

sub get_user_domain
{
	my ($username) = @_;
	my $domain="";
	open(DOMAINOWNERS,"/etc/virtual/domainowners");
	while (<DOMAINOWNERS>)
	{
		$_ =~ s/\n//;
		my ($dmn,$usr) = split(/: /, $_);
		if ($usr eq $username)
		{
			return $dmn;
		}
	}
	close(DOMAINOWNERS);

	return -1;
}
#-MOD: Is User Domain Allowed to use SMTP

Here's the whole /etc/exim.pl file already modified:

Code:
#!/usr/bin/perl

#smtpauth
#called by exim to verify if an smtp user is allowed to
#send email through the server
#possible success:
# user is in /etc/virtual/domain.com/passwd and password matches
# user is in /etc/passwd and password matches in /etc/shadow

sub smtpauth
{
	$username	= Exim::expand_string('$1');
	$password	= Exim::expand_string('$2');
	$domain		= "";
	$unixuser	= 1;

	if ($username =~ /\@/)
	{
		$unixuser = 0;
		($username,$domain) = split(/\@/, $username);
		if ($domain eq "") { return "no"; }
	}

	if ($unixuser == 1)
	{
		#the username passed doesn't have a domain, so its a system account
		$homepath = (getpwnam($username))[7];
		if ($homepath eq "") { return 0; }
		open(PASSFILE, "< $homepath/.shadow") || return "no";
		$crypted_pass = <PASSFILE>;
		close PASSFILE;

#+MOD: Is User Domain Allowed to use SMTP
		$domain = get_user_domain($username);
		if (not is_smtp_allowed($domain)) { return "no"; }
#-MOD: Is User Domain Allowed to use SMTP

		if ($crypted_pass eq crypt($password, $crypted_pass)) { return "yes"; }
		else { return "no"; }
	}
	else
	{

#+MOD: Is User Domain Allowed to use SMTP
		if (not is_smtp_allowed($domain)) { return "no"; }
#-MOD: Is User Domain Allowed to use SMTP

		#the username contain a domain, which is now in $domain.
		#this is a pure virtual pop account.

		open(PASSFILE, "< /etc/virtual/$domain/passwd") || return "no";
		while (<PASSFILE>)
		{
			($test_user,$test_pass) = split(/:/,$_);
			$test_pass =~ s/\n//g; #snip out the newline at the end
			if ($test_user eq $username)
			{
				if ($test_pass eq crypt($password, $test_pass))
				{
					close PASSFILE;
					return "yes";
				}
			}
		}
		close PASSFILE;
		return "no";
	}

	return "no";
}

#+MOD: Is User Domain Allowed to use SMTP
sub is_smtp_allowed
{
	my ($domain) = @_;
	open(DOMAINS,"/etc/virtual/domains_without_smtp");
	while (<DOMAINS>)
	{
		$_ =~ s/\n//;
		if ($domain eq $_)
		{
			return 0;
		}
	}
	close(DOMAINS);

	return 1;
}

sub get_user_domain
{
	my ($username) = @_;
	my $domain="";
	open(DOMAINOWNERS,"/etc/virtual/domainowners");
	while (<DOMAINOWNERS>)
	{
		$_ =~ s/\n//;
		my ($dmn,$usr) = split(/: /, $_);
		if ($usr eq $username)
		{
			return $dmn;
		}
	}
	close(DOMAINOWNERS);

	return -1;
}
#-MOD: Is User Domain Allowed to use SMTP

sub find_uid_apache
{
	my ($work_path) = @_;
	my @pw;
	
	# $pwd will probably look like '/home/username/domains/domain.com/public_html'
	# it may or may not use /home though. others are /usr/home, but it's ultimately
	# specified in the /etc/passwd file.  We *could* parse through it, but for efficiency
	# reasons, we'll only check /home and /usr/home ..   if they change it, they can
	# manually adjust if needed.

	@dirs = split(/\//, $work_path);
	foreach $dir (@dirs)
	{
		# check the dir name for a valid user
		# get the home dir for that user
		# compare it with the first part of the work_path

		if ( (@pw = getpwnam($dir))  )
		{
			if ($work_path =~/^$pw[7]/)
			{
				return $pw[2];
			}
		}
	}
	return -1;
}

sub get_domain_owner
{
	my ($domain) = @_;
	my $username="";
	open(DOMAINOWNERS,"/etc/virtual/domainowners");
	while (<DOMAINOWNERS>)
	{
		$_ =~ s/\n//;
		my ($dmn,$usr) = split(/: /, $_);
		if ($dmn eq $domain)
		{
			return $usr;
		}
	}
	close(DOMAINOWNERS);

	return -1;
}

sub find_uid_auth_id
{
	# this will be passwed either
	# 'username' or '[email protected]'

	my ($auth_id) = @_;
	my $unixuser = 1;
	my $domain = "";
	my $user = "";
	my $username = $auth_id;
	my @pw;

	if ($auth_id =~ /\@/)
	{
		$unixuser = 0;
		($user,$domain) = split(/\@/, $auth_id);
		if ($domain eq "") { return "-1"; }
        }

	if (!$unixuser)
	{
		# we need to take $domain and get the user from /etc/virtual/domainowners
		# once we find it, set $username
		my $u = get_domain_owner($domain);;
		if ($u != -1)
		{
			$username = $u;
		}
	}

	#log_str("username found from $auth_id: $username:\n");

	if ( (@pw = getpwnam($username))  )
	{
		return $pw[2];
	}

	return -1;
}

sub find_uid_sender
{
	my $sender_address = Exim::expand_string('$sender_address');

	my ($user,$domain) = split(/\@/, $sender_address);

	my $username = get_domain_owner($domain);

	if ( (@pw = getpwnam($username))  )
	{
		return $pw[2];
	}

	return -1;
}

sub find_uid
{
        my $uid = Exim::expand_string('$originator_uid');
	my $username = getpwuid($uid);
        my $auth_id = Exim::expand_string('$authenticated_id');
        my $work_path = $ENV{'PWD'};

	if ($username eq "apache" || $username eq "nobody")
	{
		$uid = find_uid_apache($work_path);
		if ($uid != -1) { return $uid; }
	}
	
	$uid = find_uid_auth_id($auth_id);
	if ($uid != -1) { return $uid; }

	# we don't want to rely on this, but it's all thats left.
	return find_uid_sender;
}

sub uid_exempt
{
        my ($uid) = @_;
        if ($uid == 0) { return 1; }

        my $name = getpwuid($uid);
        if ($name eq "root") { return 1; }
        if ($name eq "diradmin") { return 1; }

        return 0;
}


#check_limits
#used to enforce limits for the number of emails sent
#by a user.  It also logs the bandwidth of the data
#for received mail.

sub check_limits
{
	my $count = 0;
	open (LIMIT, "/etc/virtual/limit");
	my $email_limit = int(<LIMIT>);
	close(LIMIT);	

	#find the curent user
	$uid = find_uid();

	#log_str("Found uid: $uid\n");

	if (uid_exempt($uid)) { return; }

	my $name="";
	if ($email_limit > 0)
	{
		#check this users limit
		if (($name = getpwuid($uid)))
		{
			$count = (stat("/etc/virtual/usage/$name"))[7];
			if ($count > $email_limit)
			{
				die("You ($name) have reach your daily email limit of $email_limit emails\n");
			}
		}
	}
	
	open(USAGE, ">>/etc/virtual/usage/$name");
	print USAGE "1";
	close(USAGE);
	chmod (0660, "/etc/virtual/usage/$name");

	log_bandwidth($uid);

	return "yes"
}

sub log_bandwidth
{
	my ($uid) = @_;
	my $name = getpwuid($uid);

	if (uid_exempt($uid)) { return; }

	if ($name eq "") { return; }

	my $bytes = Exim::expand_string('$message_size');

	if ($bytes == -1) { return; }

	open (BYTES, ">>/etc/virtual/usage/$name.bytes");
	print BYTES "$bytes\n";
	close(BYTES);
	chmod (0660, "/etc/virtual/usage/$name.bytes");
}

sub log_str
{
	my ($str) = @_;

	open (LOG, ">> /tmp/test.txt");

	print LOG $str;

	close(LOG);
}

Usage of file /etc/virtual/domains_without_smtp is the same, just enter denied domains, one per line.
 
Back
Top