diff options
Diffstat (limited to 'sqmail-4.3.07/src/qmail-popup.c')
-rw-r--r-- | sqmail-4.3.07/src/qmail-popup.c | 303 |
1 files changed, 0 insertions, 303 deletions
diff --git a/sqmail-4.3.07/src/qmail-popup.c b/sqmail-4.3.07/src/qmail-popup.c deleted file mode 100644 index a2fd39d..0000000 --- a/sqmail-4.3.07/src/qmail-popup.c +++ /dev/null @@ -1,303 +0,0 @@ -#include <unistd.h> -#include "commands.h" -#include "fd.h" -#include "sig.h" -#include "stralloc.h" -#include "buffer.h" -#include "alloc.h" -#include "wait.h" -#include "str.h" -#include "byte.h" -#include "now.h" -#include "fmt.h" -#include "case.h" -#include "exit.h" -#include "timeout.h" -#include "env.h" -#include "tls_start.h" -#include "ip.h" -#include "qmail.h" - -#define PORT_POP3S "995" // string -#define FDIN 0 -#define FDOUT 1 -#define FDAUTH 3 -#define FDLOG 5 -#define POP3_TIMEOUT 1200 - -void die() { _exit(1); } - -ssize_t saferead(int fd,char *buf,int len) -{ - int r; - r = timeoutread(POP3_TIMEOUT,fd,buf,len); - if (r <= 0) die(); - return r; -} - -ssize_t safewrite(int fd,char *buf,int len) -{ - int r; - r = timeoutwrite(POP3_TIMEOUT,fd,buf,len); - if (r <= 0) die(); - return r; -} - -char inbuf[BUFSIZE_AUTH]; -buffer bi = BUFFER_INIT(saferead,FDIN,inbuf,sizeof(inbuf)); - -char outbuf[BUFSIZE_AUTH]; -buffer bo = BUFFER_INIT(safewrite,FDOUT,outbuf,sizeof(outbuf)); - -void outs(char *s) -{ - buffer_puts(&bo,s); -} -void flush() -{ - buffer_flush(&bo); -} -void err(char *s) -{ - outs("-ERR "); - outs(s); - outs("\r\n"); - flush(); -} - -/* Logging */ - -stralloc protocol = {0}; -stralloc auth = {0}; -char *localport; -char *remoteip; -char *remotehost; - -char strnum[FMT_ULONG]; -char logbuf[BUFSIZE_LOG]; -buffer bl = BUFFER_INIT(safewrite,FDLOG,logbuf,sizeof(logbuf)); - -void logs(char *s) { if (buffer_puts(&bl,s) == -1) _exit(1); } -void logp(char *s) { logs(" P:"); logs(s); } -void logh(char *s1, char *s2) { logs(" S:"); logs(s1); logs(":"); logs(s2); } -void logu(char *s) { logs(" ?~ '"); logs(s); logs("'"); } -void logn(char *s) { if (buffer_puts(&bl,s) == -1) _exit(1); if (buffer_flush(&bl) == -1) _exit(1); } -void logpid() { strnum[fmt_ulong(strnum,getpid())] = 0; logs("qmail-popup: pid "); logs(strnum); logs(" "); } -void log_pop(char *s1,char *s2,char *s3,char *s4,char *s5,char *s6) - { logpid(); logs(s1); logs(s2); logp(s3); logh(s4,s5), logu(s6), logn("\n"); } - -void die_usage() { err("usage: popup hostname subprogram"); die(); } -void die_nomem() { err("out of memory"); die(); } -void die_pipe() { err("unable to open pipe"); die(); } -void die_write() { err("unable to write pipe"); die(); } -void die_fork() { err("unable to fork"); die(); } -void die_childcrashed() { err("aack, child crashed"); } -void die_badauth() { err("authorization failed"); } -void die_tls() { err("TLS startup failed"); die(); } -void die_notls() { - err("TLS required but not negotiated"); - log_pop("Reject::STLS::","Any","POP3",remoteip,remotehost,"unknown"); - die(); -} - -void err_syntax() { err("syntax error"); } -void err_wantuser() { err("USER first"); } -void err_authoriz() { err("authorization first"); } - -void okay() { outs("+OK \r\n"); flush(); } -void pop3_quit() { okay(); die(); } - -void poplog_init() -{ - if (!stralloc_copys(&protocol,"POP3")) die_nomem(); - localport = env_get("TCP6LOCALPORT"); - if (!localport) localport = env_get("TCPLOCALPORT"); - if (!localport) localport = "unknown"; - if (!case_diffs(localport,PORT_POP3S)) - if (!stralloc_cats(&protocol,"S")) die_nomem(); - remoteip = env_get("TCP6REMOTEIP"); - if (remoteip && byte_equal(remoteip,7,V4MAPPREFIX)) remoteip = remoteip + 7; - if (!remoteip) remoteip = env_get("TCPREMOTEIP"); - if (!remoteip) remoteip = "unknown"; - remotehost = env_get("TCP6REMOTEHOST"); - if (!remotehost) remotehost = env_get("TCPREMOTEHOST"); - if (!remotehost) remotehost = "unknown"; -} - -char unique[FMT_ULONG + FMT_ULONG + 3]; -char *hostname; -stralloc username = {0}; -int seenuser = 0; -char **childargs; -char authbuf[BUFSIZE_AUTH]; -buffer ba; -int stls = 0; -int seenstls = 0; -int apop = 0; - -void doanddie(char *user,unsigned int userlen,char *pass) /* userlen: including 0 byte */ -{ - int child; - int wstat; - int pi[2]; - - if (fd_copy(2,1) == -1) die_pipe(); - close(FDAUTH); - if (pipe(pi) == -1) die_pipe(); - if (pi[0] != FDAUTH) die_pipe(); - switch (child = fork()) { - case -1: - die_fork(); - case 0: - close(pi[1]); - sig_pipedefault(); - execvp(*childargs,childargs); - _exit(1); - } - close(pi[0]); - buffer_init(&ba,write,pi[1],authbuf,sizeof(authbuf)); - if (buffer_put(&ba,user,userlen) == -1) die_write(); - if (buffer_put(&ba,pass,str_len(pass) + 1) == -1) die_write(); - if (buffer_puts(&ba,"<") == -1) die_write(); - if (buffer_puts(&ba,unique) == -1) die_write(); - if (buffer_puts(&ba,hostname) == -1) die_write(); - if (buffer_put(&ba,">",2) == -1) die_write(); - if (buffer_flush(&ba) == -1) die_write(); - close(pi[1]); - byte_zero(pass,str_len(pass)); - byte_zero(authbuf,sizeof(authbuf)); - if (wait_pid(&wstat,child) == -1) die(); - if (wait_crashed(wstat)) die_childcrashed(); - if (!stralloc_0(&auth)) die_nomem(); - if (!stralloc_0(&protocol)) die_nomem(); - if (wait_exitcode(wstat)) { - die_badauth(); - log_pop("Reject::AUTH::",auth.s,protocol.s,remoteip,remotehost,user); - } - else - log_pop("Accept::AUTH::",auth.s,protocol.s,remoteip,remotehost,user); - die(); -} - -void pop3_greet() -{ - char *s; - s = unique; - s += fmt_uint(s,getpid()); - *s++ = '.'; - s += fmt_ulong(s,(unsigned long) now()); - *s++ = '@'; - *s++ = 0; - - if (!apop) - outs("+OK\r\n"); - else { - outs("+OK <"); - outs(unique); - outs(hostname); - outs(">\r\n"); - } - flush(); -} - -void pop3_user(char *arg) -{ - if (stls == 2 && !seenstls) die_notls(); - if (!*arg) { err_syntax(); return; } - okay(); - seenuser = 1; - if (!stralloc_copys(&username,arg)) die_nomem(); - if (!stralloc_0(&username)) die_nomem(); -} - -void pop3_pass(char *arg) -{ - if (!seenuser) { err_wantuser(); return; } - if (!*arg) { err_syntax(); return; } - if (!stralloc_copys(&auth,"User")) die_nomem(); - doanddie(username.s,username.len,arg); -} - -void pop3_apop(char *arg) -{ - char *space; - - if (stls == 2 && !seenstls) die_notls(); - space = arg + str_chr(arg,' '); - if (!*space) { err_syntax(); return; } - *space++ = 0; - if (!stralloc_copys(&auth,"Apop")) die_nomem(); - doanddie(arg,space - arg,space); -} - -void pop3_capa(char *arg) -{ - outs("+OK capability list follows\r\n"); - outs("TOP\r\n"); - outs("USER\r\n"); - outs("UIDL\r\n"); - if (apop) - outs("APOP\r\n"); - if (stls > 0) - outs("STLS\r\n"); - outs(".\r\n"); - flush(); -} - -void pop3_stls(char *arg) -{ - if (stls == 0 || seenstls == 1) - return err("STLS not available"); - outs("+OK starting TLS negotiation\r\n"); - flush(); - - if (!starttls_init()) die_tls(); - buffer_init(&bi,saferead,FDIN,inbuf,sizeof(inbuf)); - seenstls = 1; - -/* reset state */ - seenuser = 0; - if (!stralloc_cats(&protocol,"S")) die_nomem(); -} - -struct commands pop3commands[] = { - { "user", pop3_user, 0 } -, { "pass", pop3_pass, 0 } -, { "apop", pop3_apop, 0 } -, { "quit", pop3_quit, 0 } -, { "capa", pop3_capa, 0 } -, { "stls", pop3_stls, 0 } -, { "noop", okay, 0 } -, { 0, err_authoriz, 0 } -}; - -int main(int argc,char **argv) -{ - char *pop3auth; - char *ucspitls; - - sig_alarmcatch(die); - sig_pipeignore(); - - hostname = argv[1]; - if (!hostname) die_usage(); - childargs = argv + 2; - if (!*childargs) die_usage(); - - ucspitls = env_get("UCSPITLS"); - if (ucspitls) { - stls = 1; - if (!case_diffs(ucspitls,"-")) stls = 0; - if (!case_diffs(ucspitls,"!")) stls = 2; - } - - pop3auth = env_get("POP3AUTH"); - if (pop3auth) { - if (case_starts(pop3auth,"apop")) apop = 2; - if (case_starts(pop3auth,"+apop")) apop = 1; - } - poplog_init(); - pop3_greet(); - commands(&bi,pop3commands); - die(); -} |