免费注册 查看新帖 |

Chinaunix

  平台 论坛 博客 文库
12下一页
最近访问板块 发新帖
查看: 4030 | 回复: 10
打印 上一主题 下一主题

[Mail] 分析nimh.org的qmail-smtpd.c。关于不auth能发信的问题。 [复制链接]

论坛徽章:
0
跳转到指定楼层
1 [收藏(0)] [报告]
发表于 2003-07-03 12:22 |只看该作者 |倒序浏览
分析nimh.org的qmail-smtpd.c。关于不auth能发信的问题。
使用客户端软件becky  抓包和协议分析 Iris软件。

我安装qmail,并使用qmail-smtpd.c的来做auth,但发现如果客户端不选择“SMTP服务器需要认证”,客户端依然能够发信。
如果选择了“需要认证”,填写正确的用户名,密码。能够发信。如果用户名,密码错误,认证失败,不能发信。
两台机器,两台都有这种情况。

我非常奇怪,先使用Iris抓了包,客户端becky。
这是客户端不选择“需要认证”应答过程:s:,c:是我添加的。
s:220 203.95.1.133 ESMTP
c:EHLO [192.168.100.68]
s:250-203.95.1.133
s:250-AUTH=LOGIN
s:250-AUTH LOGIN
s:250-PIPELINING
s:250 8BITMIME
c:RSET
s:250 flushed
c:MAIL FROM:
s:250 ok
c:RCPT TO:
s:250 ok
cATA
s:354 go ahead
cate: Thu, 03 Jul 2003 11:41:37 +0800
c:From: "eric@203.95.1.133"
c:To: luojie@shol.com.cn
c:Subject: bbbbbbbbbbbbbbbbbbbb-with out auth
c:Message-Id: <20030703114015.A54C.EIRC@203.95.1.133>;
c:MIME-Version: 1.0
c:Content-Type: text/plain; charset="US-ASCII"
c:Content-Transfer-Encoding: 7bit
c:X-Mailer: Becky! ver. 2.06.02
c:
c:
c:
c:.
s:250 ok 1057203135 qp 28631
cUIT
s:221 203.95.1.133

这是选择了“需要认证”的应答过程: *****处是我加的注释
s:220 203.95.1.133 ESMTP
c:EHLO [192.168.100.68]
s:250-203.95.1.133
s:250-AUTH=LOGIN
s:250-AUTH LOGIN
s:250-PIPELINING
s:250 8BITMIME
c:AUTH LOGIN          **** 客户端发送认证应答
s:334 VXNlcm5hbWU6
c:aaaaa==             *****客户端用户名,base64编码过,我mark了。
s:334 UGFzc3dvcmQ6
c:bbbbbbbbbb==         *****客户端密码,base64编码过,我mark了。
s:235 go ahead
c:RSET
s:250 flushed
c:MAIL FROM:
s:250 ok
c:RCPT TO:
s:250 ok
cATA
s:354 go ahead
cate: Thu, 03 Jul 2003 11:23:32 +0800
c:From: "eric@203.95.1.133"
c:To: luojie@shol.com.cn
c:Subject: aaaaaaaaaaaaaaaaaaaaaaaa
c:Message-Id: <20030703112220.A544.EIRC@203.95.1.133>;
c:MIME-Version: 1.0
c:Content-Type: text/plain; charset="US-ASCII"
c:Content-Transfer-Encoding: 7bit
c:X-Mailer: Becky! ver. 2.06.02
c:
c:
c:
c:.
s:250 ok 1057202050 qp 28573
cUIT
s:221 203.95.1.133

可以看到,选择“不需要认证”,客户端没有发送auth login的命令,直接就RSET了。而服务器也就将smtp会话进行下去了。

我这时就看了看nimh.org的qmail-smtpd.c,给我的感觉是没有一个变量来表明你是否进行认证过了的标志。
smtpd是根据客户端的消息来响应的,如果客户端发送了auth,说我要验证,smtpd就给你验证,如果客户端不发送auth 命令
smtpd就不管。

nimh.org的qmail-smtpd.c我看了一下,倒数第13行定义了char *u;但好像没有使用过这个变量。
我修改了一下这个qmail-smtpd.c,主要是定义个一个flag,表明是否smtp认证过,如果没有认证过,直接发送mail 命令,程序
就退出。

我把程序上载上来,大家看看有什么问题。心里比较乱,可能我安装也有什么问题??不知道那位只使用了nimh.org的qmail-smtpd.c
做认证,能把服务器的IP地址告诉我吗?我telnet 25端口看看。

另外如果使用outlook express 6做客户端,我使用Iris抓包发现,如果选择“不认证”,outlook发送的hello命令是HELO,smtpd也
就不要求认证了。下面是我抓的包。

220 203.95.1.133 ESMTP
HELO lj
250 203.95.1.133
MAIL FROM:
250 ok

这是outlool express 6 选择了“认证”后抓的包,这是outlook发送的是“EHLO”
220 203.95.1.133 ESMTP
EHLO lj
250-203.95.1.133
250-AUTH=LOGIN
250-AUTH LOGIN
250-PIPELINING
250 8BITMIME
.................

论坛徽章:
0
2 [报告]
发表于 2003-07-03 13:12 |只看该作者

分析nimh.org的qmail-smtpd.c。关于不auth能发信的问题。

就加了几句,每一句的后面有注释 // add by luojie.
搜索一下,很快就可以把他们找出来
**********************************************
//看了整个程序,如果客户端不发送auth 命令,程序好像就不执行 auth这一段。
//造成我机器上的现象就是如果客户端选择,不需要auth ,就可以发信
//如果选择了需要auth,而认证用户名,密码错误,不能发信,正确,可以发信
//by luojie ;flytod@21cn.com MSN:flyod@21cn.com
#include "sig.h"
#include <stdio.h>;
#include "readwrite.h"
#include "stralloc.h"
#include "substdio.h"
#include "alloc.h"
#include "auto_qmail.h"
#include "control.h"
#include "received.h"
#include "constmap.h"
#include "error.h"
#include "ipme.h"
#include "ip.h"
#include "qmail.h"
#include "str.h"
#include "fmt.h"
#include "scan.h"
#include "byte.h"
#include "case.h"
#include "wait.h"
#include "env.h"
#include "now.h"
#include "exit.h"
#include "rcpthosts.h"
#include "timeoutread.h"
#include "timeoutwrite.h"
#include "commands.h"

#define MAXHOPS 100
#define USE_SMTPAUTH
int smtpauth_ok = 0; //add by luojie,标记是否smtp验证成功
unsigned int databytes = 0;
int timeout = 1200;

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 http://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_smtpauth() { out("553 sorry,  Authentication is required\r\n"; } //add by luojie,输入需要验证的消息
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};

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: http://pobox.com/~djb/qmail.html\r\n");
}
void smtp_quit()
{
  smtp_greet("221 "); out("\r\n"); flush(); _exit(0);
}

char *remoteip;
char *remotehost;
char *remoteinfo;
char *local;
char *relayclient;

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 = 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();
  if (control_rldef(&greeting,"control/smtpgreeting",1,(char *) 0) != 1)
    die_control();
  liphostok = control_rldef(&liphost,"control/localiphost",1,(char *) 0);
  if (liphostok == -1) die_control();
  if (control_readint(&timeout,"control/timeoutsmtpd") == -1) die_control();
  if (timeout <= 0) timeout = 1;

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

  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();

  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;

  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 = env_get("RELAYCLIENT");
  dohelo(remotehost);
}


stralloc addr = {0}; /* will be 0-terminated, if addrparse returns 1 */

int addrparse(arg)
char *arg;
{
  int i;
  char ch;
  char terminator;
  struct ip_address ip;
  int flagesc;
  int flagquoted;

  terminator = '>;';
  i = str_chr(arg,'<');
  if (arg)
    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) { /* copy arg to addr, stripping quotes */
    if (flagesc) {
      if (!stralloc_append(&addr,&ch)) die_nomem();
      flagesc = 0;
    }
    else {
      if (!flagquoted && (ch == terminator)) break;
      switch(ch) {
        case '\\': flagesc = 1; break;
        case '"': flagquoted = !flagquoted; break;
        default: if (!stralloc_append(&addr,&ch)) die_nomem();
      }
    }
  }
  /* could check for termination failure here, but why bother? */
  if (!stralloc_append(&addr,"")) die_nomem();

  if (liphostok) {
    i = byte_rchr(addr.s,addr.len,'@');
    if (i < addr.len) /* if not, partner should go read rfc 821 */
      if (addr.s[i + 1] == '[')
        if (!addr.s[i + 1 + ip_scanbracket(addr.s + i + 1,&ip)])
          if (ipme_is(&ip)) {
            addr.len = i + 1;
            if (!stralloc_cat(&addr,&liphost)) die_nomem();
            if (!stralloc_0(&addr)) die_nomem();
          }
  }

  if (addr.len >; 900) return 0;
  return 1;
}

int bmfcheck()
{
  int j;
  if (!bmfok) return 0;
  if (constmap(&mapbmf,addr.s,addr.len - 1)) return 1;
  j = byte_rchr(addr.s,addr.len,'@');
  if (j < addr.len)
    if (constmap(&mapbmf,addr.s + j,addr.len - j - 1)) return 1;
  return 0;
}

int addrallowed()
{
  int r;
  r = rcpthosts(addr.s,str_len(addr.s));
  if (r == -1) die_control();
  return r;
}


int seenmail = 0;
int flagbarf; /* defined if seenmail */
stralloc mailfrom = {0};
stralloc rcptto = {0};

void smtp_helo(arg) char *arg;
{
  smtp_greet("250 "); out("\r\n");
  seenmail = 0; dohelo(arg);
}
void smtp_ehlo(arg) char *arg;
{
  smtp_greet("250-");
#ifdef USE_SMTPAUTH
  out("\r\n250-AUTH=LOGIN\r\n250-AUTH LOGIN");
#endif
  out("\r\n250-PIPELINING\r\n250 8BITMIME\r\n");
  seenmail = 0; dohelo(arg);
}
void smtp_rset()
{
  seenmail = 0;
  out("250 flushed\r\n");
}
void smtp_mail(arg) char *arg;
{
  if (!smtpauth_ok) { err_smtpauth(); smtp_quit(); } //add by luojie 接受mail 命令,如果没有smtp认证过,退出
  if (!addrparse(arg)) { err_syntax(); return; }
  flagbarf = bmfcheck();
  seenmail = 1;
  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");
}
void smtp_rcpt(arg) char *arg; {
  if (!seenmail) { err_wantmail(); return; }
  if (!addrparse(arg)) { err_syntax(); return; }
  if (flagbarf) { err_bmf(); return; }
  if (relayclient) {
    --addr.len;
    if (!stralloc_cats(&addr,relayclient)) die_nomem();
    if (!stralloc_0(&addr)) die_nomem();
  }
  else
    if (!addrallowed()) { err_nogateway(); return; }
  if (!stralloc_cats(&rcptto,"T")) die_nomem();
  if (!stralloc_cats(&rcptto,addr.s)) die_nomem();
  if (!stralloc_0(&rcptto)) die_nomem();
  out("250 ok\r\n");
}


int saferead(fd,buf,len) int fd; char *buf; int len;
{
  int r;
  flush();
  r = timeoutread(timeout,fd,buf,len);
  if (r == -1) if (errno == error_timeout) die_alarm();
  if (r <= 0) die_read();
  return r;
}

char ssinbuf[1024];
substdio ssin = SUBSTDIO_FDBUF(saferead,0,ssinbuf,sizeof ssinbuf);

struct qmail qqt;
unsigned int bytestooverflow = 0;

void put(ch)
char *ch;
{
  if (bytestooverflow)
    if (!--bytestooverflow)
      qmail_fail(&qqt);
  qmail_put(&qqt,ch,1);
}

void blast(hops)
int *hops;
{
  char ch;
  int state;
  int flaginheader;
  int pos; /* number of bytes since most recent \n, if fih */
  int flagmaybex; /* 1 if this line might match RECEIVED, if fih */
  int flagmaybey; /* 1 if this line might match \r\n, if fih */
  int flagmaybez; /* 1 if this line might match DELIVERED, if fih */

  state = 1;
  *hops = 0;
  flaginheader = 1;
  pos = 0; flagmaybex = flagmaybey = flagmaybez = 1;
  for (;;) {
    substdio_get(&ssin,&ch,1);
    if (flaginheader) {
      if (pos < 9) {
        if (ch != "delivered"[pos]) if (ch != "DELIVERED"[pos]) flagmaybez = 0;
        if (flagmaybez) if (pos == ++*hops;
        if (pos <
          if (ch != "received"[pos]) if (ch != "RECEIVED"[pos]) flagmaybex = 0;
        if (flagmaybex) if (pos == 7) ++*hops;
        if (pos < 2) if (ch != "\r\n"[pos]) flagmaybey = 0;
        if (flagmaybey) if (pos == 1) flaginheader = 0;
      }
      ++pos;
      if (ch == '\n') { pos = 0; flagmaybex = flagmaybey = flagmaybez = 1; }
    }
    switch(state) {
      case 0:
        if (ch == '\n') straynewline();
        if (ch == '\r') { state = 4; continue; }
        break;
      case 1: /* \r\n */
        if (ch == '\n') straynewline();
        if (ch == '.') { state = 2; continue; }
        if (ch == '\r') { state = 4; continue; }
        state = 0;
        break;
      case 2: /* \r\n + . */
        if (ch == '\n') straynewline();
        if (ch == '\r') { state = 3; continue; }
        state = 0;
        break;
      case 3: /* \r\n + .\r */
        if (ch == '\n') return;
        put(".");
        put("\r");
        if (ch == '\r') { state = 4; continue; }
        state = 0;
        break;
      case 4: /* + \r */
        if (ch == '\n') { state = 1; break; }
        if (ch != '\r') { put("\r"); state = 0; }
    }
    put(&ch);
  }
}

char accept_buf[FMT_ULONG];
void acceptmessage(qp) unsigned long qp;
{
  datetime_sec when;
  when = now();
  out("250 ok ");
  accept_buf[fmt_ulong(accept_buf,(unsigned long) when)] = 0;
  out(accept_buf);
  out(" qp ");
  accept_buf[fmt_ulong(accept_buf,qp)] = 0;
  out(accept_buf);
  out("\r\n");
}

void smtp_data() {
  int hops;
  unsigned long qp;
  char *qqx;

  if (!seenmail) { err_wantmail(); return; }
  if (!rcptto.len) { err_wantrcpt(); return; }
  seenmail = 0;
  if (databytes) bytestooverflow = databytes + 1;
  if (qmail_open(&qqt) == -1) { err_qqt(); return; }
  qp = qmail_qp(&qqt);
  out("354 go ahead\r\n");

  received(&qqt,"SMTP",local,remoteip,remotehost,remoteinfo,fakehelo);
  blast(&hops);
  hops = (hops >;= MAXHOPS);
  if (hops) qmail_fail(&qqt);
  qmail_from(&qqt,mailfrom.s);
  qmail_put(&qqt,rcptto.s,rcptto.len);

  qqx = qmail_close(&qqt);
  if (!*qqx) { acceptmessage(qp); return; }
  if (hops) { out("554 too many hops, this message is looping (#5.4.6)\r\n"); return; }
  if (databytes) if (!bytestooverflow) { out("552 sorry, that message size exceeds my databytes limit (#5.3.4)\r\n"); return; }
  if (*qqx == 'D') out("554 "); else out("451 ");
  out(qqx + 1);
  out("\r\n");
}

#ifdef USE_SMTPAUTH
static unsigned char *base64_alphabet =
"ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/=";
static int unbase64(ch) int ch; {
  int i;
  if (ch == '=') return 0;
  for (i = 0; i < 64; i++)
    if (ch == base64_alphabet)
      return i;
  return 0;
}
static int base64_dec_buffer(str,dst,len) const char *str;void *dst;int len;
{
  int i, j, l;
  unsigned char input[4], output[3], *result = (char *)dst;
  if (str == 0)
    return 0;
  l = str_len(str);
  if (dst == 0 || l >; len)
    return (l / 4) * 3;
  memset(dst,0,len);
  for (i=j=0; i<l; i +=4) {
    input[0] = unbase64(str);
    input[1] = unbase64(str[i+1]);
    input[2] = unbase64(str[i+2]);
    input[3] = unbase64(str[i+3]);
    output[0] = (input[0] << 2) | (input[1] >;>; 4);
    output[1] = (input[1] << 4) | (input[2] >;>; 2);
    output[2] = (input[2] << 6) | (input[3]);
    result[j] = output[0];
    if (str[i+1] == '=') return j+1;
    result[j+1]=output[1];
    if (str[i+2] == '=') return j+2;
    result[j+2]=output[2];
    j += 3;
  }
  return j;
}
static stralloc smtpauth = {0};
static char smtpauthlogin[65];
static char smtpauthpass[65];
static int smtpauth_getl(void) {
  int i;
  if (!stralloc_copys(&smtpauth, "")) return -1;
  for (;;) {
    if (!stralloc_readyplus(&smtpauth,1)) return -1;
    i = substdio_get(&ssin, smtpauth.s + smtpauth.len, 1);
    if (i != 1) return i;
    if (smtpauth.s[smtpauth.len] == '\n') break;
    ++smtpauth.len;
  }
  if (smtpauth.len >; 0) if (smtpauth.s[smtpauth.len-1] == '\r') --smtpauth.len;
  smtpauth.s[smtpauth.len] = 0;
  return smtpauth.len;
}
static char **smtpauth_argv;
void smtp_auth(arg) char *arg; {
  int st, pid, fds[2];
  /* netscape 4.5 sends AUTH LOGIN <base64encodedusername>;
     microsoft outlook express sends AUTH LOGIN

     idea is simple

     use an external program to test authority
     if success, set 'RELAYCLIENT'
     otherwise, let them know nicely (hangup)

     note, i really don't like djb's coding style even though i'm using it here.
     i think using spaces for tabs is bad.
                                                -mrs.brisby@nimh.org
  */
  while (arg && *arg && *arg != ' ') arg++;

  /* pass over the space */
  while (arg && *arg && *arg == ' ') arg++;

  if (arg && *arg) {
    /* here's the base64 encoded login */
    base64_dec_buffer(arg, smtpauthlogin, sizeof(smtpauthlogin));
  } else {
    out("334 VXNlcm5hbWU6\r\n"); /* b64 <- 'Username:' */
    flush();
    if (smtpauth_getl() >; 0)
      base64_dec_buffer(smtpauth.s, smtpauthlogin, sizeof(smtpauthlogin));
    else
      die_read();
  }
  out("334 UGFzc3dvcmQ6\r\n"); /* b64 <- 'Password:' */
  flush();
  if (smtpauth_getl() >; 0)
    base64_dec_buffer(smtpauth.s, smtpauthpass, sizeof(smtpauthpass));
  else
    die_read();
  if (pipe(fds)) {
    out("535 pipe failure\r\n");
    flush();
    _exit(0);
  }
  /* spawn external program

  external program should return '0' if it was successful,

  submit: /bin/checkpassword /bin/true
  
  */
  switch ((pid=fork())) {
    case -1: die_nomem();
    case 0: close(fds[1]);
      fd_copy(3,fds[0]);
      execvp(smtpauth_argv[1], smtpauth_argv+1);
      die_nomem();
  };
  close(fds[0]);
  write(fds[1], smtpauthlogin, str_len(smtpauthlogin)+1);
  write(fds[1], smtpauthpass, str_len(smtpauthpass)+1);
  close(fds[1]);
  wait_pid(&st, pid);
  if (wait_exitcode(st) == 0) {
    smtpauth_ok = 1; //add by luojie ,标记验证通过
    out("235 go ahead\r\n");
    flush();
    relayclient="";
    return;
  }
  sleep(2);
  out("535 auth failure\r\n"); flush(); _exit(0);
  /* done */
}
#endif

struct commands smtpcommands[] = {
  { "rcpt", smtp_rcpt, 0 }
, { "mail", smtp_mail, 0 }
, { "data", smtp_data, flush }
#ifdef USE_SMTPAUTH
, { "auth", smtp_auth, flush }
#endif
, { "quit", smtp_quit, flush }
, { "helo", smtp_helo, flush }
, { "ehlo", smtp_ehlo, flush }
, { "rset", smtp_rset, 0 }
, { "help", smtp_help, flush }
, { "noop", err_noop, flush }
, { "vrfy", err_vrfy, flush }
, { 0, err_unimpl, flush }
} ;

void main(argc,argv) int argc; char **argv;
{
#ifdef USE_SMTPAUTH
  char *u;

  smtpauth_argv = argv;
#endif
  sig_pipeignore();
  if (chdir(auto_qmail) == -1) die_control();
  setup();
  if (ipme_init() != 1) die_ipme();
  smtp_greet("220 ");
  out(" ESMTP\r\n");
  if (commands(&ssin,&smtpcommands) == 0) die_read();
  die_nomem();
}

论坛徽章:
1
荣誉版主
日期:2011-11-23 16:44:17
3 [报告]
发表于 2003-07-03 15:42 |只看该作者

分析nimh.org的qmail-smtpd.c。关于不auth能发信的问题。

几个问题:
1.你的smtp启动脚本怎么写的?
2.
c:MAIL FROM:
s:250 ok
c:RCPT TO:
这个你都没填写内容?

3.有没有用到tcprules的cdb文件?


另外,我一直使用这个patch的,没有问题。

论坛徽章:
1
荣誉版主
日期:2011-11-23 16:44:17
4 [报告]
发表于 2003-07-03 16:48 |只看该作者

分析nimh.org的qmail-smtpd.c。关于不auth能发信的问题。

我手工测试了一下。
Mail From:
rcpt to:
不写地址的确不需要auth能过,但是,会认为是服务器上的一个用户。所以这样写是发不出去的,会推给postmaster。

论坛徽章:
0
5 [报告]
发表于 2003-07-04 00:55 |只看该作者

分析nimh.org的qmail-smtpd.c。关于不auth能发信的问题。

是呀,我都快被这个patch弄的抓狂了。按道理来说,经过这么多人的使用,应该是没有问题的。我就是没有办法了,才看来他的源代码。发现服务器smtpd调用auth函数是客户端要求的,如果客户端不要求的话,auth这段代码不会执行的。


1,启动脚本是:
csh -cf '/opt/qmail/rc' &
tcpserver -u 1008 -g 100 -c 100 0 smtp /opt/qmail/bin/qmail-smtpd /bin/checkpassword /bin/true &
没有pop3服务。
2,Mail from,rcpt to:不知道怎么回事,应该都有的,我明天上班再抓一席。
3,没有使用tcprules的的cdb文件,这个只是限制tcp链接的规则。应该对这个没有影响。

我的rcpthost删掉了,因为这个Qmail就是一个转发的Qmail,没有本地用户。如果你把rcpthost删除呢?结果会如何?

论坛徽章:
1
荣誉版主
日期:2011-11-23 16:44:17
6 [报告]
发表于 2003-07-04 09:21 |只看该作者

分析nimh.org的qmail-smtpd.c。关于不auth能发信的问题。

把你的rc打出来我看看。

论坛徽章:
0
7 [报告]
发表于 2003-07-04 10:42 |只看该作者

分析nimh.org的qmail-smtpd.c。关于不auth能发信的问题。

cat rc
#!/bin/sh

# Using splogger to send the log through syslog.
# Using qmail-local to deliver messages to ~/Mailbox by default.

exec env - PATH="/opt/qmail/binPATH" \
qmail-start ./Maildir/ splogger qmail

========================================
我现在仔细想了一下,可能是因为我把rcpthosts删除了的关系。如果作为一个非openrely的smtpd,如果不auth的话,它应该只接受本域的邮件。

正如你说说:如果你rcpt to:是本域的用户,这个smtpd就接受,否则退回到postmaster。

以21cn为例,他页面上提供的smtp服务器是:smtp.21cn.com,ip地址是202.104.32.230,但21cn的mx记录IP地址是:202.104.32.234。分别telnet这两个IP的25 端口,有不同的反映。

telnet smtp.21cn.cn 25.
ehlo的回应是需要你auth ,如果你这是输入mail from: luojie@xxx.com.cn
提示是:553 From <luojie@xxx.com.cn>;, message blocked.
这次21cn认为我是一个邮件客户端

telnet 202.104.32.234 25,21cn.com的mx记录。
EHLO flytod的回应是不需要认证,
你再输入mail from:luojie@xxx.com.cn
然后你就可以输入rcpt to:。如果to是到21cn.com的,smtpd会接受,
如果to到其他域的,会被阻止。553 Relay restriction.
这次21cn认为我是一个smtp服务器,正在向他relay到21cn的邮件。

这些记录我都抓在这个帖子了:http://www.chinaunix.net/forum/viewtopic.php?t=104457

而我现在要配置的服务器是需要auth(auth程序是使用自己的库),然后所有的邮件都转发到另外一个固定的smtp服务器。所以我的rcpthosts必须删除,而删除了后,如果用户采用smtp服务器之间的应答连接上来,我会将任何邮件都relay的,这样实际上就是一个openrelay的服务器了。按照我的修改后,我的Qmail服务器实际上不能接受其他smtp的连接,因为所有的命令都需要auth的。我的域名的mx记录不能指向这台Qmail服务器,不然我是收不到任何邮件的。别的smtp服务器连接过来都需要认证,他们会疯掉的。

不知道是否表述清楚了我的意思????

通过这次思考,我再次深刻的了解了smtp协议。对两个smtp服务器之间的会话清楚了。如果我编一个发垃圾邮件的程序,就按照域名的mx记录,直接找到那台smtp服务器,直接relay邮件这个域的邮件,这样的话根本就不需要认证。

论坛徽章:
1
荣誉版主
日期:2011-11-23 16:44:17
8 [报告]
发表于 2003-07-04 12:42 |只看该作者

分析nimh.org的qmail-smtpd.c。关于不auth能发信的问题。

在精华区,有个讨论mx的帖子。好像也有个讨论mx和smtp relay的帖子。

你可以看看。

smtp relay的意思就是通过邮件服务器发往外域,mx的作用主要是为了接受本域的信件,让其它服务器通过mx能够找到这个服务器。接受本域的信件是不需要auth的。

论坛徽章:
0
9 [报告]
发表于 2003-08-01 14:02 |只看该作者

分析nimh.org的qmail-smtpd.c。关于不auth能发信的问题。

这个问题我也遇到过,看看/home/vpopmail/etc下的tcp.smtp.cdb中是否包含了你的IP地址,如果你配置vpopmail的时候把
--enable-roaming-users设置成y的话,在你收了一次邮件后会自动把你的IP地址加到openrelay中的,然后隔一端时间后由crontab重新删除。
我测试的确实如此,如果重新生产tcp.smtp.cdb后,直接发送邮件,则如果不选认证,是没有办法发信的,但如果收了一次信,也就是用pop3登陆过一次,就可以不用认证发信了,当然,如果选了认证,就必须写对用户名和密码。

但是我也发现另外一个问题,就是如果我用户名正确,密码错误,好像系统等了一会,但最后还是把邮件给发了,但如果用户名不正确,就没有办法发了。
我用的是easyqmail的那个大的补丁包。
maillog提示密码错误,但还是login成功了。这可能才真正是qmail-smtpd.c的问题啊。
附:
Aug 1 12:34:22 webserver vpopmail[22405]: vchkpw-smtp: password fail (pass: 'aaaaaaa1ddd')
demo@abc.cn:192.168.1.189
Aug 1 12:34:27 webserver vpopmail[22408]: vchkpw-smtp: (PLAIN) login success demo@abc.cn:1
92.168.1.189
Aug 1 12:34:27 webserver qmail: 1059712467.142717 new msg 69306
Aug 1 12:34:27 webserver qmail: 1059712467.142822 info msg 69306: bytes 618 from <demo@abc.cn>; qp 22411 uid 507
下面是我的启动脚本
#!/bin/sh
PATH="/var/qmail/bin:/usr/local/bin:/usr/bin:/bin:/usr/local/sbin:/usr/sbin:/sbinPATH"
tcpserver -H -R -x /home/vpopmail/etc/tcp.smtp.cdb \
-u `id -u vpopmail` -g `id -g vpopmail` 0 25 \
/var/qmail/bin/qmail-smtpd abc.cn /home/vpopmail/bin/vchkpw /bin/true 2>;&1 | /var/qmail/bin/splogger qmail-smtpd &

论坛徽章:
1
荣誉版主
日期:2011-11-23 16:44:17
10 [报告]
发表于 2003-08-01 15:33 |只看该作者

分析nimh.org的qmail-smtpd.c。关于不auth能发信的问题。

用nimh.org的patch,smtpd的启动脚本中,qmail-smtpd 后面是不需要带域名的。

这个精华区有讨论
您需要登录后才可以回帖 登录 | 注册

本版积分规则 发表回复

  

北京盛拓优讯信息技术有限公司. 版权所有 京ICP备16024965号-6 北京市公安局海淀分局网监中心备案编号:11010802020122 niuxiaotong@pcpop.com 17352615567
未成年举报专区
中国互联网协会会员  联系我们:huangweiwei@itpub.net
感谢所有关心和支持过ChinaUnix的朋友们 转载本站内容请注明原作者名及出处

清除 Cookies - ChinaUnix - Archiver - WAP - TOP