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