繁体中文
设为首页
加入收藏
当前位置:服务器技术首页 >> 邮件服务 >> 修正Qmail auth smtp中电子邮件地址任意的patch

修正Qmail auth smtp中电子邮件地址任意的patch

2004-11-15 08:00:00  作者:  来源:互联网  浏览次数:0  文字大小:【】【】【
简介:qmail 的auth smtp有两个patch, 分别在:http://members.elysium.pl/brush/qmail-smtpd-auth/和www.nimh.org/hacks/qmail-smtpd.c。 不过都有个问题,就是auth 的用户可以和mail from的用户不一样,这样就 给了垃...

qmail 的auth smtp有两个patch,

分别在:http://members.elysium.pl/brush/qmail-smtpd-auth/和www.nimh.org/hacks/qmail-smtpd.c。

不过都有个问题,就是auth 的用户可以和mail from的用户不一样,这样就

给了垃圾邮件发送者可乘之机,只要知道了某个用户的地址和口令,就可以

以自己的名义发信。同时认证用户的过程并不记录在邮件日志中,这给了系统管理员造成了很大不便,难以知道是哪个用户被黑掉了。

下面这个patch就是针对这种情况写的。

作用有两个:

1. 通过环境变量来控制是否记录认证过程。

2. 如果mail from和auth user name不一致,拒绝发送信件。

这个patch是基于www.nimh.org/hacks/qmail-smtpd.c,iceblood版本中实际上也是的这个。因此,用iceblood版本的可以直接使用。如果是用

http://members.elysium.pl/brush/qmail-smtpd-auth/版本的就需要自己

相应的修改了。

安装方法,如下,将下面这些内容存到qmail-smtpd.patch。放到qmail的源码目录。然后

1. patch < qmail-smtpd.patch

2. make qmail-smtpd

3. 替换qmail-smtpd

或者复制到新的执行文件例如qmail-smtpd.auth,这样你的旧版本就能保留

了,只需要在smtpd的启动脚本中,修改为对应的执行文件就可以。

如果你需要记录smtp认证的信息,在smtpd的启动脚本中定义环境变量,如下:

LOG_AUTH=1

export LOG_AUTH

缺省情况下,认证信息不记入log

[quote:d38fd091a9]

--- qmail-smtpd.c 2003-04-05 17:55:20.000000000 -0500

+++ qmail-smtpd.c.new 2003-04-05 17:50:58.000000000 -0500

@@ -304,7 +304,11 @@

if (!stralloc_copys(&rcptto,"")) die_nomem();

if (!stralloc_copys(&mailfrom,addr.s)) die_nomem();

if (!stralloc_0(&mailfrom)) die_nomem();

+ if (smtp_auth_validfrom(mailfrom.s)) {

out("250 ok\r\n");

+ } else {

+ out("must use username as From authenticated! (#5.7.1)\r\n");

+ }

}

void smtp_rcpt(arg) char *arg; {

if (!seenmail) { err_wantmail(); return; }

@@ -527,6 +531,82 @@

static stralloc smtpauth = {0};

static char smtpauthlogin[65];

static char smtpauthpass[65];

+static int authd = 0;

+

+/* Author: gadfly@163.com.

+ * 1. Check consistent between auth user and 'From' user.

+ * 2. Read the LOG_AUTH enviroment variable to determine whether logging the auth info.

+ * LOG_AUTH=1, write the auth smtp info into syslog.

+ */

+#include

+

+#define SMTP_AUTH_SUCCESS 0

+#define SMTP_AUTH_FAILED 1

+

+int smtp_auth_validfrom(from) char * from;

+{

+ stralloc tmplogin={0},mydefaultdomain={0};

+ char authusername[256];

+ int k, userlen;

+

+ if (!authd) return 1;

+

+ authusername[255] = '\0';

+ userlen = k = str_len(smtpauthlogin);

+ k = byte_rchr(smtpauthlogin, k, '@');

+

+ if (k == userlen)

+ {

+ k = byte_rchr(smtpauthlogin, userlen, '%');

+

+ if (k == userlen)

+ {

+ if (control_readfile(&mydefaultdomain,"/var/qmail/control/me",1) != 1)

+ {

+ die_nomem();

+ }

+ if (!stralloc_copys(&tmplogin, smtpauthlogin) )

+ {

+ die_nomem();

+ }

+ if (!stralloc_cats(&tmplogin, "@") )

+ {

+ die_nomem();

+ }

+ if (!stralloc_cat(&tmplogin, &mydefaultdomain))

+ {

+ die_nomem();

+ }

+ strncpy(authusername, tmplogin.s, sizeof(authusername));

+ }

+ else

+ {

+ strcpy(authusername, smtpauthlogin);

+ authusername[k]='@';

+ }

+ }

+ else {

+ strcpy(authusername, smtpauthlogin);

+ }

+ return !strcasecmp(from, authusername);

+}

+

+

+void auth_smtplog(authlogin, authresult)

+char * authlogin;

+int authresult;

+{

+ char * x = env_get("LOG_AUTH");

+

+ if (!x || (*x != '1')) return;

+

+ if (authresult == SMTP_AUTH_SUCCESS) {

+ syslog(LOG_MAIL | LOG_INFO, "smtp auth: user name is %s, success!", authlogin);

+ } else {

+&

nbsp; syslog(LOG_MAIL | LOG_INFO, "smtp auth: user name is %s, failed!", authlogin);

+ }

+}

+

static int smtpauth_getl(void) {

int i;

if (!stralloc_copys(&smtpauth, "")) return -1;

@@ -611,11 +691,14 @@

wait_pid(&st, pid);

if (wait_exitcode(st) == 0) {

out("235 go ahead\r\n");

+ authd = 1;

+ auth_smtplog(smtpauthlogin, SMTP_AUTH_SUCCESS);

flush();

relayclient="";

return;

}

sleep(2);

+ auth_smtplog(smtpauthlogin, SMTP_AUTH_FAILED);

out("535 auth failure\r\n"); flush(); _exit(0);

/* done */

}

[/quote:d38fd091a9]

呵呵,正式用之前,各位多测试测试。

几种情况需要测测看:

1. 其它服务器发到本域,smtp过程是否正常,本域能否收到

2. from和auth user 不一样会出现什么情况, 一样的话,能否发信。

3. LOG_AUTH是否起作用。

呵呵,qmail的对齐用空格,实在不习惯,没办法,为保持一致,我也用了。

[b:d38fd091a9]更新版本[/b:d38fd091a9]

应一些朋友的要求,加了本地发信人发给本地,也需要auth的功能。

另外而且还加了一些注释,版本号。方法和前面一样。

代码如下:

[code:1:d38fd091a9]

--- qmail-smtpd.c2003-06-02 18:34:51.000000000 -0400

+++ qmail-smtpd.c.new2003-06-02 18:42:31.000000000 -0400

@@ -268,6 +268,7 @@

int r;

r = rcpthosts(addr.s,str_len(addr.s));

if (r == -1) die_control();

+ if (!localauthd()) return 0;

return r;

}

@@ -304,7 +305,11 @@

if (!stralloc_copys(&rcptto,"")) die_nomem();

if (!stralloc_copys(&mailfrom,addr.s)) die_nomem();

if (!stralloc_0(&mailfrom)) die_nomem();

- out("250 ok\r\n");

+ if (smtp_auth_validfrom(mailfrom.s)) {

+ out("250 ok\r\n");

+ } else {

+ out("must use username as From authenticated! (#5.7.1)\r\n");

+ }

}

void smtp_rcpt(arg) char *arg; {

if (!seenmail) { err_wantmail(); return; }

@@ -527,6 +532,89 @@

static stralloc smtpauth = {0};

static char smtpauthlogin[65];

static char smtpauthpass[65];

+static int authd = 0;

+

+/* Author: gadfly@163.com. Version: 1.2.

+ * 1. Check consistent between auth user and 'From' user.

+ * 2. Read the LOG_AUTH enviroment variable to determine whether logging the auth info.

+ * LOG_AUTH=1, write the auth smtp info into syslog.

+ * 3. If mail from local, rcpt to local domain, user must auth before send data.

+ */

+#include

+

+#define SMTP_AUTH_SUCCESS 0

+#define SMTP_AUTH_FAILED 1

+

+int localauthd() {

+

+ if (rcpthosts(mailfrom.s, strlen(mailfrom.s)) && !authd) return 0;

+ return 1;

+}

+

+int smtp_auth_validfrom(from) char * from;

+{

+ stralloc tmplogin={0},mydefaultdomain={0};

+ char authusername[256];

+ int k, userlen;

+

+ if (!authd) return 1;

+

+ authusername[255] = '\0';

+ userlen = k = str_len(smtpauthlogin);

+ k = byte_rchr(smtpauthlogin, k, '@');

+

+ if (k == userlen)

+ {

+ k = byte_rchr(smtpauthlogin, userlen, '%');

+

+ if (k == userlen)

+ {

+ if (control_readfile(&mydefaultdomain,"/var/qmail/control/me",1) != 1)

+ {

+ die_nomem();

+ }

+ if (!stralloc_copys(&tmplogin, smtpauthlogin) )

+ {

+ di

e_nomem();

+ }

+ if (!stralloc_cats(&tmplogin, "@") )

+ {

+ die_nomem();

+ }

+ if (!stralloc_cat(&tmplogin, &mydefaultdomain))

+ {

+ die_nomem();

+ }

+ strncpy(authusername, tmplogin.s, sizeof(authusername));

+ }

+ else

+ {

+ strcpy(authusername, smtpauthlogin);

+ authusername[k]='@';

+ }

+ }

+ else {

+ strcpy(authusername, smtpauthlogin);

+ }

+ return !strcasecmp(from, authusername);

+}

+

+

+void auth_smtplog(authlogin, authresult)

+char * authlogin;

+int authresult;

+{

+ char * x = env_get("LOG_AUTH");

+

+ if (!x || (*x != '1')) return;

+

+ if (authresult == SMTP_AUTH_SUCCESS) {

+ syslog(LOG_MAIL | LOG_INFO, "smtp auth: user name is %s, success!", authlogin);

+ } else {

+ syslog(LOG_MAIL | LOG_INFO, "smtp auth: user name is %s, failed!", authlogin);

+ }

+}

+

static int smtpauth_getl(void) {

int i;

if (!stralloc_copys(&smtpauth, "")) return -1;

@@ -611,11 +699,14 @@

wait_pid(&st, pid);

if (wait_exitcode(st) == 0) {

out("235 go ahead\r\n");

+ authd = 1;

+ auth_smtplog(smtpauthlogin, SMTP_AUTH_SUCCESS);

flush();

 

; relayclient="";

return;

}

sleep(2);

+ auth_smtplog(smtpauthlogin, SMTP_AUTH_FAILED);

out("535 auth failure\r\n"); flush(); _exit(0);

/* done */

}

[/code:1:d38fd091a9]

另外,感谢erehw提供的空间可以下载这个patch。

http://gadfly.shanji.com/qmail-smtpd/

[b:d38fd091a9]

由于网页上的代码贴上去,格式有问题。

我就不再更新了。

请各位到以上的url下载。

或给我发信索要

[/b:d38fd091a9]

Fun-FreeBSD 回复于:2003-04-05 18:32:03

好啊,可惜我没在公司,周一到公司试一下~

peng 回复于:2003-04-06 21:22:10

gadfly真强啊!

看来做研发的就是厉害啊。

好文章。

gadfly 回复于:2003-04-07 00:40:49

晕,这上面的patch中,每行前面的空格都不显示出来,复制下来肯定没法用.

本站的ftp服务也关了.

如果手工复制下来,需要在每行没有@或+开头的代码行前面加个空格,

就可以使用了.

如果觉得麻烦,可以给我发信,我把patch发给你们. gadfly@163.com

最好能有个上载的地方 :-(

gadfly 回复于:2003-04-07 00:42:59

peng老大过奖了,都在技术的苦海中苦苦挣扎. 兄弟们得携手共进才是.

说不定还有不少问题呢

gadfly 回复于:2003-04-07 11:43:57

由于,有网友给我发信提了一些问题,我想还是到这里说比较方便。

其实下面的问题,在我上面都说明了。没办法,我还是重点说一下

FAQ:

1. patch是基于哪一个auth的?

auth smtp有两个patch,

分别在:http://members.elysium.pl/brush/qmail-smtpd-auth/

和www.nimh.org/hacks/qmail-smtpd.c。

基于的是后者。

如果你们auth smtp用的是前者,我提供的patch就不能直接使用。

等我有时间,在写一个基于前者的patch吧。

2. patch执行后的结果是什么?

晕,刚发现,www.nimh.org/hacks/qmail-smtpd.c又更新了,做的糟糕,没有版本信息,我还不知道我针对的哪一个版本。下次我也要加上版本信息了。

现在只好说: iceblood版本: 正常执行成功的话,没有任何输出。

最新版本(nimh.org主页上的):输出入下:

[quote:de306b6c4e]

Hunk #1 succeeded at 252 (offset -52 lines).

Hunk #2 succeeded at 498 (offset -33 lines).

Hunk #3 succeeded at 633 (offset -58 lines).

[/quote:de306b6c4e]

但是还好,编译出来的可以正常使用。

3.编译出来的大小没有区别?

这个和系统环境相关,不是绝对的。只要前两个没问题,你就看测试结果吧。

4.网页上的patch不好用?

是的,因为格式的原因,手工复制下来,需要在每行没有@或+开头的代码行前面加个空格, 就可以使用了.

如果觉得麻烦,可以给我发信,我把patch发给你们. gadfly@163.com

最好能有个上载的地方

netloafer 回复于:2003-04-07 12:13:31

gadfly真是强呀~~

有关资料可以上传到linux版的FTP服务器上~~~~

gadfly 回复于:2003-04-07 12:23:03

[quote:cf2cc80f45="netloafer"]

gadfly真是强呀~~

有关资料可以上传到linux版的FTP服务器上~~~~

[/quote:cf2cc80f45]

呵呵,过奖了。

ftpserver我昨天试过了,还是没有开。

听说因为受攻击,还影响了电信的其他业务,现在已经关闭了。只有另寻他途。

夜未眠 回复于:2003-04-28 19:41:16

针对http://members.e

lysium.pl/brush/qmail-smtpd-auth/认证补丁再加上楼主所说的功能.

[ 非patch ]

首先你要打补丁,然后照下面的方法修改qmail-smtpd.c源代码.

1.增加全局变量:

stralloc authusername={0}; //全局变量用于记录认证的email地址

2.在认证成功后将mailfrom存入上面的authusername中,也就是在函数

int authenticate(void)最后return 0;语句前插入下面的语句

/*将用户名存入全局变量 authusername*/

if(!stralloc_copy(&authusername,&user)) return 1;

3.在void smtp_rcpt(arg)函数的if (relayclient) {语句后插入下面的语句.

if(case_diffs(authusername.s,mailfrom.s)) {

err_noauth(); //认证用户名与mailfrom中的地址不符

/*在这儿加入log代码*/

return; //出错返回

}

===========================================================

一个问题:也不知道我想的对不对,在此提出与各位讨论.

但是我觉得你的patch和我上面的方法好象都有一个问题.就是如果远程连接到服务器25号端口,不通过认证。一样可以向control/rcpthosts中列出的地址发邮件(就象是别的MTA与你对话一样,别人的MTA不可能知道你的用户名和密码)因为不通过认证那么relayclient将会是null,那么就会进行rcpthosts的比较,如果rcpt 指定的email地址在rcpthosts中列出,qmail会接收并转发该邮件,如果一个快速请求对一个慢速服务器,那是什么情况?

有人想把用户名与mailfrom地址比较的操作放在if(relayclient)这前,前面我说了,别人的MTA不会知道你的用户名及密码。如果你这样作了,你将收不到邮件。

我想就一台服务器再打补丁也是白打。可以用两台服务器比较安全,分别打不同的补丁<也就是在前面提到的if(relayclient)处>,一台专收,一台专发。两台之间进行通信。这样可能才能比较安全.

不知道各位大虾有什么看法。不仿在此讨论讨论..

tutux 回复于:2003-04-28 21:04:37

[quote:3284d68729="夜未眠"] ]

首先你要打补丁,然后照下面的方法修改qmail-smtpd.c源代码.

1.增加全局变量:

stralloc authusername={0}; //全局变量用于记录认证的email地址

2.在认证成功后将mailfrom存入上面的authusern..........[/quote:3284d68729]

[quote:3284d68729]就是如果远程连接到服务器25号端口,不通过认证。一样可以向control/rcpthosts中列出的地址发邮件(就象是别的MTA与你对话一样,别人的MTA不可能知道你的用户名和密码)因为不通过认证那么relayclient将会是null,那么就会进行rcpthosts的比较,如果rcpt 指定的email地址在rcpthosts中列出,qmail会接收并转发该邮件,如果一个快速请求对一个慢速服务器,那是什么情况?

[/quote:3284d68729]

这个情况,是暂时没办法的啦。

iceblood 回复于:2003-04-29 08:50:32

谢谢,希望加精。

能否mail给我一份?

我尽快把qmail-smtpd.c替换掉。

gadfly 回复于:2003-04-29 12:22:51

to 夜未眠:

大概明白你的意思.

1.smtp的这种机制下,安全就是相对的,我知道你服务器的域和用户,我就可以向你发信。

2.其实你说的分开,也就是将mail relay(本域用户

向外发信)和mail receive(用于MTA)之间,我记得和peng以前讨论过,确实可以这么做.而且不同的patch确实能使效率提高,同时又起到了分流的作用.不过大部分的情况下,效率的问题并不大, 这两者还是合一的.不过我想用不同的patch,效率上的提高还是有限的。即使有效率问题,完全可以通过多服务器负载均衡来避免.

3.你说白打,我的理解你是针对发往本域的,我同意。不过这些patch基本上都是针对relay的,从这个角度来说,patch是很有作用的.

to iceblood:

看不到你的mail address。不知如何给你

iceblood 回复于:2003-04-29 14:32:09

晕到~一时忽疏~居然忘记留下地址,现在补上~

iceblood@163.com

夜未眠 回复于:2003-04-29 18:20:36

to gadfly

我都不是很清楚自已在说什么,谁叫我表达能力太差呢。大哥居然能够理解我的意图,佩服佩服。

haohaoo 回复于:2003-04-30 12:54:06

[quote:6770b16ed1]这个patch是基于www.nimh.org/hacks/qmail-smtpd.c,iceblood版本中实际上也是的这个。因此,用iceblood版本的可以直接使用。[/quote:6770b16ed1]

那要怎么用?你还没有说呢?下载qmail-smtpd.c后要怎么办?我用iceblood版本已经安装好了,要怎么打?

gadfly 回复于:2003-04-30 13:31:52

不仔细看?

[quote:7de698ebbe]

安装方法,如下,将下面这些内容存到qmail-smtpd.patch。放到qmail的源码目录。然后

1. patch < qmail-smtpd.patch

2. make qmail-smtpd

3. 替换qmail-smtpd

[/quote:7de698ebbe]

haohaoo 回复于:2003-04-30 17:45:54

[quote:f25e681436="gadfly"][/quote:f25e681436]

有看啊,不过我说iceblood版本已经安装好了的啊?

是不是把包解开,然后把qmail-smtpd.c改名,然后编译好后,把qmail-smtpd拿到已安装的机器上去替换就行了?

gadfly 回复于:2003-04-30 21:01:19

??

不用改名,解包后按我说的步骤作就好了

haohaoo 回复于:2003-05-02 12:55:18

我替换掉qmail-smtpd后还是出问题啊,smtp不用验证就可以发信啊

ryanxyz 回复于:2003-05-02 20:43:25

我一開始就用了gadfly兄的patch

完全沒有問題

一次搞定 如果是從網頁上複製下來的

需要注意空白的問題

microcao 回复于:2003-05-04 20:45:08

我来补充一下

首先

http://nimh.org/ 的补丁地址改变了不在本来的地方了新地地方是

http://nimh.org/dl/

其次推荐所有使用 http://nimh.org/ 发布的 qmail-smtpd.c 的朋友

换成另外一个补丁

http://www.cuni.cz/~vhor/qmail/smtpauth-en.html

这个补丁是在 http://nimh.org/ 基础上改进来的, 他解决了楼主说的问题

增加了系统认证的日志应该是比较完善的!

gadfly 回复于:2003-05-05 20:12:23

[quote:a5ea51c1db="microcao"]

http://www.cuni.cz/~vhor/qmail/smtpauth-en.html

这个补丁是在 http://nimh.org/ 基础上改进来的, 他解决了楼主说的问题

增加了系统认证的日志应该是比较完善的!

[/quote:a5ea51c1db]

呵呵,看了你写的链接上的说明以及代码,我都没看到检查mail from和auth login name的一致性。另外syslog也就两个地方用到了,不觉的它的更完善。而且是直接写日志,而不是通过环境变量来判断是否写日志。

所以结论是那个链接上的patch没有解决本文涉及的问题.

IPphone 回复于:2003-05-12 16:04:00

哈,原来这有这么多高手在的呢??求教一个问题:我用的是http://members.elysium.pl/brush/qmail-smtpd-auth/

上的补丁,完成后可以认证发邮件,可问题是我在OUTLOOK上去掉认证时一样还是可以发送邮件。我曾经怀疑那个relayclient的问题,就是它还是在我每次收邮件时会记录我的客户端IP让它可以忘外发邮件;于是我去掉roaming-users重新编译vpopmail,但是那样就不能给外面发邮件了。各位大大能不能告诉我哪里出问题了??

gadfly,可不可以给我一份你的补丁程序??地址是:xzj35@msn.com

gadfly 回复于:2003-05-12 16:33:15

你说的这个问题,不少的网友都遇到过。iceblood的

包中带的qmail-smt

pd-auth*.tar.gz就是这个patch。

我没有仔细研究,反正其它问题排除,我帮他们改用了qmail-smtpd.c,也就是http://nimh.org/ 上的,这个问题就不存在了。

patch 给你发过去了。

IPphone 回复于:2003-05-12 16:51:20

[quote:529282cb58="gadfly"]你说的这个问题,不少的网友都遇到过。iceblood的

包中带的qmail-smtpd-auth*.tar.gz就是这个patch。

我没有仔细研究,反正其它问题排除,我帮他们改用了qmail-smtpd.c,也就是http://nimh.org/ 上的,这个问题?.........[/quote:529282cb58]

谢了!!我再玩玩看。

gadfly 回复于:2003-05-18 12:45:25

由于网友xmubeta用这个patch遇到了问题,

我仔细察看了一下代码。

确实如xmubeta 所说,代码有点问题。

问题出在,以前我给的patch,smtp_auth_validfrom的调用和定义的参数都不一致。

编译居然也不报错,也是DJK风格的一个缺点:所有的内部函数都不预定义,即使预定义也不定义参数,所以编译不报错。

好了,我把我的patch改过来了。

改动的地方只有一个,原来是

if (smtp_auth_validfrom(mailfrom)) {

现在是

if (smtp_auth_validfrom(mailfrom.s)) {

谢谢xmubeta的指正。

至于为什么原来的patch在linux不出错,在solaris上出错。

我理解是linux上将结构传入参数,转化成char *的时候,实际上是将第一个结构成员转化了,而这个正好是mailfrom.s。所以没有问题。

而solaris上就有所不同了,所以造成错误。

iceblood, patch我给你重发了。

gadfly 回复于:2003-06-02 18:51:47

应一些朋友的要求,加了本地发信人发给本地,也需要auth的功能。

另外而且还加了一些注释,版本号。方法和前面一样。

我稍微测试了一下。各位测恻看吧。

[code:1:e9fa54356d]

--- qmail-smtpd.c 2003-06-02 18:34:51.000000000 -0400

+++ qmail-smtpd.c.new 2003-06-02 18:42:31.000000000 -0400

@@ -268,6 +268,7 @@

int r;

r = rcpthosts(addr.s,str_len(addr.s));

if (r == -1) die_control();

+ if (!localauthd()) return 0;

return r;

}

@@ -304,7 +305,11 @@

if (!stralloc_copys(&rcptto,"")) die_nomem();

if (!stralloc_copys(&mailfrom,addr.s)) die_nomem();

if (!stralloc_0(&mailfrom)) die_nomem();

- out("250 ok\r\n");

+ if (smtp_auth_validfrom(mailfrom.s)) {

+ out("250 ok\r\n");

+ } else {

+ out("must use username as From authenticated! (#5.7.1)\r\n");

+ }

}

void smtp_rcpt(arg) char *arg; {

if (!seenmail) { err_wantmail(); return; }

@@ -527,6 +532,89

@@

static stralloc smtpauth = {0};

static char smtpauthlogin[65];

static char smtpauthpass[65];

+static int authd = 0;

+

+/* Author: gadfly@163.com. Version: 1.2.

+ * 1. Check consistent between auth user and 'From' user.

+ * 2. Read the LOG_AUTH enviroment variable to determine whether logging the auth info.

+ * LOG_AUTH=1, write the auth smtp info into syslog.

+ * 3. If mail from local, rcpt to local domain, user must auth before send data.

+ */

+#include

+

+#define SMTP_AUTH_SUCCESS 0

+#define SMTP_AUTH_FAILED 1

+

+int localauthd() {

+

+ if (rcpthosts(mailfrom.s, strlen(mailfrom.s)) && !authd) return 0;

+ return 1;

+}

+

+int smtp_auth_validfrom(from) char * from;

+{

+ stralloc tmplogin={0},mydefaultdomain={0};

+ char authusername[256];

+ int k, userlen;

+

+ if (!authd) return 1;

+

+ authusername[255] = '\0';

+ userlen = k = str_len(smtpauthlogin);

+ k = byte_rchr(smtpauthlogin, k, '@');

+

+ if (k == userlen)

+ {

+ k = byte_rchr(smtpauthlogin, userlen, '%');

+

+ if (k == userlen)

+ {

+ if (control_readfile(&mydefaultdomain,"/var/qmail/control/me",1) != 1)

+ {

+ die_nomem();

+ }

+ if (!stralloc_copys(&tmplogin, smtpauthlogin) )

+ {

+ die_nomem();

+ }

+ if (!stralloc_cats(&tmplogin, "@") )

+  

;{

+ die_nomem();

+ }

+ if (!stralloc_cat(&tmplogin, &mydefaultdomain))

+ {

+ die_nomem();

+ }

+ strncpy(authusername, tmplogin.s, sizeof(authusername));

+ }

+ else

+ {

+ strcpy(authusername, smtpauthlogin);

+ authusername[k]='@';

+ }

+ }

+ else {

+ strcpy(authusername, smtpauthlogin);

+ }

+ return !strcasecmp(from, authusername);

+}

+

+

+void auth_smtplog(authlogin, authresult)

+char * authlogin;

+int authresult;

+{

+ char * x = env_get("LOG_AUTH");

+

+ if (!x || (*x != '1')) return;

+

+ if (authresult == SMTP_AUTH_SUCCESS) {

+ syslog(LOG_MAIL | LOG_INFO, "smtp auth: user name is %s, success!", authlogin);

+ } else {

+ syslog(LOG_MAIL | LOG_INFO, "smtp auth: user name is %s, failed!", authlogin);

+ }

+}

+

static int smtpauth_getl(void) {

int i;

if (!stralloc_copys(&smtpauth, "")) return -1;

@@ -611,11 +699,14 @@

wait_pid(&st, pid);

if (wait_exitcode(st) == 0) {

out("235 go ahead\r\n");

+ authd = 1;

+ auth_smtplog(smtpauthlogin, SMTP_AUTH_SUCCESS);

flush();

relayclient="";

return;

}

sleep(2);

+ auth_smtplog(smtpauthlogin, SMTP_AUTH

责任编辑:admin
相关文章