qmail-tls + qmail auth port ?

Evren Yurtesen eyurtese at tekniikka.turkuamk.fi
Thu Jul 10 03:31:16 PDT 2003


Hi,
There is no port for qmail-auth-tls in FreeBSD. Also the qmail-auth
patches fromm
http://members.elysium.pl/brush/qmail-smtpd-auth/
do not apply to qmail-tls port of FreeBSD because some files are
already patched with tls pathes.
I made diffs for FreeBSD's qmail-tls port that auth-patch can be applied
So there can be a FreeBSD qmail-auth-tls port perhaps :)
I attach it.
Did you get my point? :) 
Evren

-------------- next part --------------
A non-text attachment was scrubbed...
Name: qmail-smtpd-auth-0.31.tar.gz
Type: application/octet-stream
Size: 8798 bytes
Desc: 
Url : http://lists.freebsd.org/pipermail/freebsd-ports/attachments/20030710/e50fb49f/qmail-smtpd-auth-0.31.tar.obj
-------------- next part --------------
*** Makefile.orig	Fri Jul 11 09:53:58 2003
--- Makefile	Fri Jul 11 09:57:50 2003
***************
*** 136,141 ****
--- 136,145 ----
  compile auto_usera.c
  	./compile auto_usera.c
  
+ base64.o: \
+ compile base64.c base64.h stralloc.h substdio.h str.h
+ 	./compile base64.c
+ 
  binm1: \
  binm1.sh conf-qmail
  	cat binm1.sh \
***************
*** 1557,1563 ****
  substdio.h alloc.h auto_qmail.h control.h received.h constmap.h \
  error.h ipme.h ip.h ipalloc.h ip.h gen_alloc.h ip.h qmail.h \
  substdio.h str.h fmt.h scan.h byte.h case.h env.h now.h datetime.h \
! exit.h rcpthosts.h timeoutread.h timeoutwrite.h commands.h
  	./compile qmail-smtpd.c
  
  qmail-start: \
--- 1561,1568 ----
  substdio.h alloc.h auto_qmail.h control.h received.h constmap.h \
  error.h ipme.h ip.h ipalloc.h ip.h gen_alloc.h ip.h qmail.h \
  substdio.h str.h fmt.h scan.h byte.h case.h env.h now.h datetime.h \
! exit.h rcpthosts.h timeoutread.h timeoutwrite.h commands.h wait.h \
! fd.h base64.h
  	./compile qmail-smtpd.c
  
  qmail-start: \
*** TARGETS.orig	Fri Jul 11 09:53:58 2003
--- TARGETS	Fri Jul 11 09:57:50 2003
***************
*** 251,256 ****
--- 251,257 ----
  qmail-qmtpd.o
  rcpthosts.o
  qmail-qmtpd
+ base64.o
  qmail-smtpd.o
  qmail-smtpd
  sendmail.o
*** qmail-smtpd.8.orig	Fri Jul 11 09:53:58 2003
--- qmail-smtpd.8	Fri Jul 11 09:57:50 2003
***************
*** 3,8 ****
--- 3,13 ----
  qmail-smtpd \- receive mail via SMTP
  .SH SYNOPSIS
  .B qmail-smtpd
+ [
+ .I hostname
+ .I checkprogram
+ .I subprogram
+ ]
  .SH DESCRIPTION
  .B qmail-smtpd
  receives mail messages via the Simple Mail Transfer Protocol (SMTP)
***************
*** 32,38 ****
  header fields.
  
  .B qmail-smtpd
! supports ESMTP, including the 8BITMIME and PIPELINING options.
  .SH TRANSPARENCY
  .B qmail-smtpd
  converts the SMTP newline convention into the UNIX newline convention
--- 37,65 ----
  header fields.
  
  .B qmail-smtpd
! supports ESMTP, including the 8BITMIME, PIPELINING, and AUTH options.
! 
! .B qmail-smtpd
! can accept LOGIN, PLAIN, and CRAM-MD5 AUTH types.  It invokes
! .IR checkprogram ,
! which reads on file descriptor 3 the username, a 0 byte, the password
! or challenge derived from
! .IR hostname ,
! another 0 byte, a CRAM-MD5 response (if applicable to the AUTH type),
! and a final 0 byte.
! .I checkprogram
! invokes
! .I subprogram
! upon successful authentication, which should in turn return 0 to
! .BR qmail-smtpd ,
! effectively setting the environment variables RELAYCLIENT and TCPREMOTEINFO
! (any supplied value replaced with the authenticated username).
! .B qmail-smtpd
! will reject the authentication attempt if it receives a nonzero return
! value from
! .I checkprogram
! or
! .IR subprogram .
  .SH TRANSPARENCY
  .B qmail-smtpd
  converts the SMTP newline convention into the UNIX newline convention
***************
*** 222,224 ****
--- 249,254 ----
  qmail-newmrh(8),
  qmail-queue(8),
  qmail-remote(8)
+ .SH "HISTORY"
+ The patch enabling the ESMTP AUTH option is not part of the standard
+ qmail-1.03 distribution.
*** qmail-smtpd.c.orig	Fri Jul 11 09:53:59 2003
--- qmail-smtpd.c	Fri Jul 11 09:57:50 2003
***************
*** 23,29 ****
--- 23,32 ----
  #include "timeoutread.h"
  #include "timeoutwrite.h"
  #include "commands.h"
+ #include "wait.h"
+ #include "fd.h"
  
+ #define AUTHCRAM
  #define MAXHOPS 100
  unsigned int databytes = 0;
  int timeout = 1200;
***************
*** 94,99 ****
--- 97,111 ----
  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"); }
  
+ int err_child() { out("454 oops, problem with child and I can't auth (#4.3.0)\r\n"); return -1; }
+ int err_fork() { out("454 oops, child won't start and I can't auth (#4.3.0)\r\n"); return -1; }
+ int err_pipe() { out("454 oops, unable to open pipe and I can't auth (#4.3.0)\r\n"); return -1; }
+ int err_write() { out("454 oops, unable to write pipe and I can't auth (#4.3.0)\r\n"); return -1; }
+ void err_authd() { out("503 you're already authenticated (#5.5.0)\r\n"); }
+ void err_authmail() { out("503 no auth during mail transaction (#5.5.0)\r\n"); }
+ int err_noauth() { out("504 auth type unimplemented (#5.5.1)\r\n"); return -1; }
+ int err_authabrt() { out("501 auth exchange cancelled (#5.0.0)\r\n"); return -1; }
+ int err_input() { out("501 malformed auth input (#5.5.4)\r\n"); return -1; }
  
  stralloc greeting = {0};
  
***************
*** 283,288 ****
--- 295,307 ----
  void smtp_ehlo(arg) char *arg;
  {
    smtp_greet("250-");
+ #ifdef AUTHCRAM
+   out("\r\n250-AUTH LOGIN CRAM-MD5 PLAIN");
+   out("\r\n250-AUTH=LOGIN CRAM-MD5 PLAIN");
+ #else
+   out("\r\n250-AUTH LOGIN PLAIN");
+   out("\r\n250-AUTH=LOGIN PLAIN");
+ #endif
  #ifdef TLS
    if (!ssl) out("\r\n250-STARTTLS");
  #endif
***************
*** 620,629 ****
--- 639,864 ----
  }
  #endif
  
+ 
+ char unique[FMT_ULONG + FMT_ULONG + 3];
+ static stralloc authin = {0};
+ static stralloc user = {0};
+ static stralloc pass = {0};
+ static stralloc resp = {0};
+ static stralloc slop = {0};
+ char *hostname;
+ char **childargs;
+ substdio ssup;
+ char upbuf[128];
+ int authd = 0;
+ 
+ int authgetl(void) {
+   int i;
+ 
+   if (!stralloc_copys(&authin, "")) die_nomem();
+ 
+   for (;;) {
+     if (!stralloc_readyplus(&authin,1)) die_nomem(); /* XXX */
+     i = substdio_get(&ssin,authin.s + authin.len,1);
+     if (i != 1) die_read();
+     if (authin.s[authin.len] == '\n') break;
+     ++authin.len;
+   }
+ 
+   if (authin.len > 0) if (authin.s[authin.len - 1] == '\r') --authin.len;
+   authin.s[authin.len] = 0;
+ 
+   if (*authin.s == '*' && *(authin.s + 1) == 0) { return err_authabrt(); }
+   if (authin.len == 0) { return err_input(); }
+   return authin.len;
+ }
+ 
+ int authenticate(void)
+ {
+   int child;
+   int wstat;
+   int pi[2];
+ 
+   if (!stralloc_0(&user)) die_nomem();
+   if (!stralloc_0(&pass)) die_nomem();
+   if (!stralloc_0(&resp)) die_nomem();
+ 
+   if (fd_copy(2,1) == -1) return err_pipe();
+   close(3);
+   if (pipe(pi) == -1) return err_pipe();
+   if (pi[0] != 3) return err_pipe();
+   switch(child = fork()) {
+     case -1:
+       return err_fork();
+     case 0:
+       close(pi[1]);
+       sig_pipedefault();
+       execvp(*childargs, childargs);
+       _exit(1);
+   }
+   close(pi[0]);
+ 
+   substdio_fdbuf(&ssup,write,pi[1],upbuf,sizeof upbuf);
+   if (substdio_put(&ssup,user.s,user.len) == -1) return err_write();
+   if (substdio_put(&ssup,pass.s,pass.len) == -1) return err_write();
+   if (substdio_put(&ssup,resp.s,resp.len) == -1) return err_write();
+   if (substdio_flush(&ssup) == -1) return err_write();
+ 
+   close(pi[1]);
+   byte_zero(pass.s,pass.len);
+   byte_zero(upbuf,sizeof upbuf);
+   if (wait_pid(&wstat,child) == -1) return err_child();
+   if (wait_crashed(wstat)) return err_child();
+   if (wait_exitcode(wstat)) { sleep(5); return 1; } /* no */
+   return 0; /* yes */
+ }
+ 
+ int auth_login(arg) char *arg;
+ {
+   int r;
+ 
+   if (*arg) {
+     if (r = b64decode(arg,str_len(arg),&user) == 1) return err_input();
+   }
+   else {
+     out("334 VXNlcm5hbWU6\r\n"); flush(); /* Username: */
+     if (authgetl() < 0) return -1;
+     if (r = b64decode(authin.s,authin.len,&user) == 1) return err_input();
+   }
+   if (r == -1) die_nomem();
+ 
+   out("334 UGFzc3dvcmQ6\r\n"); flush(); /* Password: */
+ 
+   if (authgetl() < 0) return -1;
+   if (r = b64decode(authin.s,authin.len,&pass) == 1) return err_input();
+   if (r == -1) die_nomem();
+ 
+   if (!user.len || !pass.len) return err_input();
+   return authenticate();  
+ }
+ 
+ int auth_plain(arg) char *arg;
+ {
+   int r, id = 0;
+ 
+   if (*arg) {
+     if (r = b64decode(arg,str_len(arg),&slop) == 1) return err_input();
+   }
+   else {
+     out("334 \r\n"); flush();
+     if (authgetl() < 0) return -1;
+     if (r = b64decode(authin.s,authin.len,&slop) == 1) return err_input();
+   }
+   if (r == -1 || !stralloc_0(&slop)) die_nomem();
+   while (slop.s[id]) id++; /* ignore authorize-id */
+ 
+   if (slop.len > id + 1)
+     if (!stralloc_copys(&user,slop.s + id + 1)) die_nomem();
+   if (slop.len > id + user.len + 2)
+     if (!stralloc_copys(&pass,slop.s + id + user.len + 2)) die_nomem();
+ 
+   if (!user.len || !pass.len) return err_input();
+   return authenticate();
+ }
+ 
+ #ifdef AUTHCRAM
+ int auth_cram()
+ {
+   int i, r;
+   char *s;
+ 
+   s = unique;
+   s += fmt_uint(s,getpid());
+   *s++ = '.';
+   s += fmt_ulong(s,(unsigned long) now());
+   *s++ = '@';
+   *s++ = 0;
+ 
+   if (!stralloc_copys(&pass,"<")) die_nomem();
+   if (!stralloc_cats(&pass,unique)) die_nomem();
+   if (!stralloc_cats(&pass,hostname)) die_nomem();
+   if (!stralloc_cats(&pass,">")) die_nomem();
+   if (b64encode(&pass,&slop) < 0) die_nomem();
+   if (!stralloc_0(&slop)) die_nomem();
+ 
+   out("334 ");
+   out(slop.s);
+   out("\r\n");
+   flush();
+ 
+   if (authgetl() < 0) return -1;
+   if (r = b64decode(authin.s,authin.len,&slop) == 1) return err_input();
+   if (r == -1 || !stralloc_0(&slop)) die_nomem();
+ 
+   i = str_chr(slop.s,' ');
+   s = slop.s + i;
+   while (*s == ' ') ++s;
+   slop.s[i] = 0;
+   if (!stralloc_copys(&user,slop.s)) die_nomem();
+   if (!stralloc_copys(&resp,s)) die_nomem();
+ 
+   if (!user.len || !resp.len) return err_input();
+   return authenticate();
+ }
+ #endif
+ 
+ struct authcmd {
+   char *text;
+   int (*fun)();
+ } authcmds[] = {
+   { "login", auth_login }
+ , { "plain", auth_plain }
+ #ifdef AUTHCRAM
+ , { "cram-md5", auth_cram }
+ #endif
+ , { 0, err_noauth }
+ };
+ 
+ void smtp_auth(arg)
+ char *arg;
+ {
+   int i;
+   char *cmd = arg;
+ 
+   if (!hostname || !*childargs)
+   {
+     out("503 auth not available (#5.3.3)\r\n");
+     return;
+   }
+   if (authd) { err_authd(); return; }
+   if (seenmail) { err_authmail(); return; }
+ 
+   if (!stralloc_copys(&user,"")) die_nomem();
+   if (!stralloc_copys(&pass,"")) die_nomem();
+   if (!stralloc_copys(&resp,"")) die_nomem();
+ 
+   i = str_chr(cmd,' ');   
+   arg = cmd + i;
+   while (*arg == ' ') ++arg;
+   cmd[i] = 0;
+ 
+   for (i = 0;authcmds[i].text;++i)
+     if (case_equals(authcmds[i].text,cmd)) break;
+ 
+   switch (authcmds[i].fun(arg)) {
+     case 0:
+       authd = 1;
+       relayclient = "";
+       remoteinfo = user.s;
+       if (!env_unset("TCPREMOTEINFO")) die_read();
+       if (!env_put2("TCPREMOTEINFO",remoteinfo)) die_nomem();
+       out("235 ok, go ahead (#2.0.0)\r\n");
+       break;
+     case 1:
+       out("535 authorization failed (#5.7.0)\r\n");
+   }
+ }
+ 
  struct commands smtpcommands[] = {
    { "rcpt", smtp_rcpt, 0 }
  , { "mail", smtp_mail, 0 }
  , { "data", smtp_data, flush }
+ , { "auth", smtp_auth, flush }
  , { "quit", smtp_quit, flush }
  , { "helo", smtp_helo, flush }
  , { "ehlo", smtp_ehlo, flush }
***************
*** 637,644 ****
  , { 0, err_unimpl, flush }
  } ;
  
! void main()
  {
    sig_pipeignore();
    if (chdir(auto_qmail) == -1) die_control();
    setup();
--- 872,884 ----
  , { 0, err_unimpl, flush }
  } ;
  
! void main(argc,argv)
! int argc;
! char **argv;
  {
+   hostname = argv[1];
+   childargs = argv + 2;
+ 
    sig_pipeignore();
    if (chdir(auto_qmail) == -1) die_control();
    setup();


More information about the freebsd-ports mailing list