|
很多人对qmail smtp的认证机制,环境变量,执行顺序不太了解。 仔细看完这一大篇代码后相信你会明白很多你过去不太明白的问题。 当然你要有一点点c语言基础。也只要一点点。 Come from: ChongQing Gearbox co.,ltd 这份文件还不完善,如果您完善了它请发一份给我: beggar110@163.com 这份文件是给想深入了解qmail和想hacker qmail的人读的,如果你只是想建立一个能够运作的mail服务器,没有必要读下去了。它将浪费你很多的时间。 如果你对qmail控制文件还不是很了解,阅读这份文件之前,请先阅读rainbow的《qmail控制文件详解》 在这里你可以找到www.chinaunix.net/forum/viewtopic.php?t=1126 好的。开始我们qmail内部的漫游吧!!!Let's go! 代码: qmail 总览 tcpserver MUA | | V V qmail-smtpd qmail-inject | | +----------->qmail-queue<-----------+ | | qmail-send | +------------+------------+ | | V V qmail-rspawn qmail-lspawn | | V V qmail-remote qmail-local | | | | V V INTERNET <----qmail-pop3d | | vchkpw | | qmail-popup | | tcpserver--+ qmail-smtpd.c源代码分析(去掉了所有include) qmail -smtpd是由tcpserver或由tcp-env启动。tcpserver负责监听端口,如果指定了-x rule.cbd,tcpserver会先决断是断开连接还是启动qmail子进程。如果没有指定-x参数启动tcpserver,那么直接启动 qmail-smtpd.启动qmail-smtpd之前将来自网络的数据连接重定向到qmail-smtpd的fd0,fd1.还会初始化一些 qmail-smtpd需要的环境变量,如TCPREMOTEIP. tcp-env只会初始化qmail-smtpd的环境变量,不负责监听端口及重定向网络连接。所以tcp-env要和inetd配合使用。当然,由于初始化环境变量的工作tcpserver也会作,所以没有必要tcpserver和tcp-env配合使用. qmail-smtpd完成邮件smtp命令的接收,并调用相应的处理程序。 检查mail 中的地址是否在control/badmailfrom中定义(MAIL命令) 检查是否设置了RELAYCLIENT环境变量或 rcpt 中的地址是否是control/rcpthosts中定义(RCPT命令) 需要明确的是qmail-smtpd只是简单的接收邮件内容传送给qmail-queue,并不对邮件进行转发(DATA命令)。 当然还要向qmail-queue传送mailfrom,mailto 代码: #define MAXHOPS 100 unsigned int databytes = 0; //邮件最大长度:0=无限 int timeout = 1200; //默认超时20分钟 //向网络写,超时值为control/timeoutsmtpd指定的值。没有这个文件则取默认值20分钟 int safewrite(fd,buf,len) int fd; char *buf; int len; { int r; r = timeoutwrite(timeout,fd,buf,len); if (r <= 0) _exit(1); return r; } char ssoutbuf[512]; substdio ssout = SUBSTDIO_FDBUF(safewrite,1,ssoutbuf,sizeof ssoutbuf); void flush() { substdio_flush(&ssout); } void out(s) char *s; { substdio_puts(&ssout,s); } //错误处理函数 void die_read() { _exit(1); } void die_alarm() { out("451 timeout (#4.4.2)\r\n"); flush(); _exit(1); } void die_nomem() { out("421 out of memory (#4.3.0)\r\n"); flush(); _exit(1); } void die_control() { out("421 unable to read controls (#4.3.0)\r\n"); flush(); _exit(1); } void die_ipme() { out("421 unable to figure out my IP addresses (#4.3.0)\r\n"); flush(); _exit(1); } void straynewline() { out("451 See pobox.com/~djb/docs/smtplf.html.\r\n"); flush(); _exit(1); } void err_bmf() { out("553 sorry, your envelope sender is in my badmailfrom list (#5.7.1)\r\n"); } void err_nogateway() { out("553 sorry, that domain isn't in my list of allowed rcpthosts (#5.7.1)\r\n"); } void err_unimpl() { out("502 unimplemented (#5.5.1)\r\n"); } void err_syntax() { out("555 syntax error (#5.5.4)\r\n"); } void err_wantmail() { out("503 MAIL first (#5.5.1)\r\n"); } void err_wantrcpt() { out("503 RCPT first (#5.5.1)\r\n"); } void err_noop() { out("250 ok\r\n"); } void err_vrfy() { out("252 send some mail, i'll try my best\r\n"); } void err_qqt() { out("451 qqt failure (#4.3.0)\r\n"); } stralloc greeting = {0}; //输出提示信息*code void smtp_greet(code) char *code; { substdio_puts(&ssout,code); substdio_put(&ssout,greeting.s,greeting.len); } void smtp_help() { out("214 qmail home page: void>pobox.com/~djb/qmail.html\r\n"); } void smtp_quit() { smtp_greet("221 "); out("\r\n"); flush(); _exit(0); } char *remoteip; //远端ip地址 char *remotehost; //远端主机名 char *remoteinfo; //远端信息 char *local; //本地主机 char *relayclient; //是否检查rcpthosts文件 stralloc helohost = {0}; char *fakehelo; /* pointer into helohost, or 0 */ void dohelo(arg) char *arg; { if (!stralloc_copys(&helohost,arg)) die_nomem(); if (!stralloc_0(&helohost)) die_nomem(); //fakehelo变量,如果helo 参数指定的主机名与TCPREMOTEHOST环境变量中的主机名不同则 //fakehelo的值为helo命令的参数指定的主机名.如果两者相同则fekehelo为NULL; //data命令处理程式用到这个变量 fakehelo = case_diffs(remotehost,helohost.s) ? helohost.s : 0; } int liphostok = 0; stralloc liphost = {0}; int bmfok = 0; stralloc bmf = {0}; struct constmap mapbmf; void setup() { char *x; unsigned long u; if (control_init() == -1) die_control(); //control/me //读入欢迎信息greeting,如果不存在则从me文件复制 if (control_rldef(&greeting,"control/smtpgreeting",1,(char *) 0) != 1) die_control(); //读入localiphost,如果文件不存在则从me文件复制 liphostok = control_rldef(&liphost,"control/localiphost",1,(char *) 0); if (liphostok == -1) die_control(); //读control/timeoutsmtpd存入timeout,用于控制超时的情况. if (control_readint(&timeout,"control/timeoutsmtpd") == -1) die_control(); if (timeout <= 0) timeout = 1; if (rcpthosts_init() == -1) die_control(); //读入badmailfrom文件存入 bmf bmfok = control_readfile(&bmf,"control/badmailfrom",0); if (bmfok == -1) die_control(); if (bmfok) if (!constmap_init(&mapbmf,bmf.s,bmf.len,0)) die_nomem(); //读入databytes文件存入 databytes,如果该文件不存在,则将 //databytes的值设为0. if (control_readint(&databytes,"control/databytes") == -1) die_control(); x = env_get("DATABYTES"); if (x) { scan_ulong(x,&u); databytes = u; } if (!(databytes + 1)) --databytes; //取tcp-environ环境变量,如果环境变量没有设置,将它的值设置为unknow. //这些信息来自tcpserver,或tcp-env之类的程式 remoteip = env_get("TCPREMOTEIP"); if (!remoteip) remoteip = "unknown"; local = env_get("TCPLOCALHOST"); if (!local) local = env_get("TCPLOCALIP"); if (!local) local = "unknown"; remotehost = env_get("TCPREMOTEHOST"); if (!remotehost) remotehost = "unknown"; remoteinfo = env_get("TCPREMOTEINFO"); //从环境变量RELAYCLIENT读入. //如果RELAYCLIENT变量没有设置那么relayclient将会是NULL. relayclient = env_get("RELAYCLIENT"); dohelo(remotehost); } stralloc addr = {0}; /* will be 0-terminated, if addrparse returns 1 */ //对命令参数arg进行邮件地址分析 //并将分离出的email地址存入全局缓存addr //成功返回值为1,失败返回0 int addrparse(arg) char *arg; { int i; char ch; char terminator; struct ip_address ip; int flagesc; int flagquoted; //分离出邮件地址 //例如: arg="",或 arg=": email@eg.org " //执行下面这段程式后arg="email@eg.org" terminator = '>'; i = str_chr(arg,'<'); if (arg[i]) arg += i + 1; else { /* partner should go read rfc 821 */ terminator = ' '; arg += str_chr(arg,':'); if (*arg == ':') ++arg; while (*arg == ' ') ++arg; } /* strip source route */ if (*arg == '@') while (*arg) if (*arg++ == ':') break; if (!stralloc_copys(&addr,"")) die_nomem(); flagesc = 0; flagquoted = 0; for (i = 0;ch = arg[i];++i) { /* copy arg to addr, stripping quotes */ Linux联盟收集整理
 |
频道声明:本频道的文章除部分特别声明禁止转载的专稿外,可以自由转载.但请务必注明出出处和原始作者 文章版权归本频道与文章作者所有.对于被频道转载文章的个人和网站,我们表示深深的谢意。
| 原始作者:佚名 |
录入时间:2007-1-2 3:24:20 |
| 信息来源:不详 |
投稿信箱:itqoo@126.com |
|
|
 |
|