diff options
Diffstat (limited to 'sqmail-4.3.07/src/qmail-dkverify.c')
-rw-r--r-- | sqmail-4.3.07/src/qmail-dkverify.c | 368 |
1 files changed, 0 insertions, 368 deletions
diff --git a/sqmail-4.3.07/src/qmail-dkverify.c b/sqmail-4.3.07/src/qmail-dkverify.c deleted file mode 100644 index 2cfe00a..0000000 --- a/sqmail-4.3.07/src/qmail-dkverify.c +++ /dev/null @@ -1,368 +0,0 @@ -#include <sys/types.h> -#include <sys/stat.h> -#include <unistd.h> -#include <fcntl.h> -#include <sys/socket.h> -#include "sig.h" -#include "stralloc.h" -#include "buffer.h" -#include "error.h" -#include "auto_qmail.h" -#include "str.h" -#include "exit.h" -#include "uint_t.h" -#include "fd.h" -#include "open.h" -#include "fmt.h" -#include "fmtqfn.h" -#include "readwrite.h" -#include "getln.h" -#include "qmail.h" -#include "wait.h" -#include "byte.h" -#include "case.h" -#include "control.h" -#include "pathexec.h" -#include "env.h" -#include "logmsg.h" - -#define WHO "qmail-dkverify" - -/** @file qmail-dkverify.c - @brief stub routine for DKIM signature verification and indication in received message - - Steps: - ------ - a) Store message with CRLF - b) Get DKIM signature from message - if given: - c) Call qmail-dkim for verification - d) Include results as appended header - e) Queue the message for processing - - */ - -char inbuf[BUFSIZE_LINE]; -buffer bi = BUFFER_INIT(read,0,inbuf,sizeof(inbuf)); // read buffer -char outbuf[BUFSIZE_MESS]; -buffer bo = BUFFER_INIT(write,1,outbuf,sizeof(outbuf)); // output message - -void die(int e) { _exit(e); } -void die_pipe(char *fn) { unlink(fn); die(53); }; -void die_write(char *fn) { unlink(fn); die(53); }; -void die_read() { die(54); }; -void out(char *s) { if (buffer_puts(&bo,s) == -1) _exit(111); } -void zero() { if (buffer_put(&bo,"\0",1) == -1) _exit(111); } -void zerodie() { zero(); buffer_flush(&bo); _exit(111); } - -void temp_nomem() -{ - out("ZOut of memory. (#4.3.0)\n"); - zerodie(); -} -void temp_chdir() -{ - out("ZUnable to switch to target directory. (#4.3.0)\n"); - zerodie(); -} -void temp_create() -{ - out("ZUnable to create DKIM stage file. (#4.3.0)\n"); - zerodie(); -} -void temp_unlink() -{ - out("ZUnable to unlink DKIM stage file. (#4.3.0)\n"); - zerodie(); -} -void temp_read() -{ - out("ZUnable to read message. (#4.3.0)\n"); - zerodie(); -} -void temp_socket() -{ - out("ZUnable to crate socket pair. (#4.3.0)\n"); - zerodie(); -} -void temp_control() -{ - out("ZUnable to read control files. (#4.3.0)\n"); - zerodie(); -} - -static stralloc me = {0}; -static stralloc senddomain = {0}; -static stralloc dkheader = {0}; -static stralloc fndkin = {0}; -static stralloc fndkout = {0}; -static stralloc result = {0}; - -void fnmake_dkim(unsigned long id) -{ - fndkin.len = fmtqfn(fndkin.s,"queue/dkim/",id,1); - id += id; - fndkout.len = fmtqfn(fndkout.s,"queue/dkim/",id,1); -} - -void dkim_stage() -{ - int r; - int fd; - int in, out; - struct stat st; - char tmpbuf[BUFSIZE_MESS + 2]; - - if (!stralloc_ready(&fndkin,FMTQFN)) temp_nomem(); - if (!stralloc_ready(&fndkout,FMTQFN)) temp_nomem(); - - fnmake_dkim(getpid()); // pre-staging - fd = open_excl(fndkin.s); - if (fd == -1) die_write(fndkin.s); - - buffer_init(&bi,read,0,inbuf,sizeof(inbuf)); - buffer_init(&bo,write,fd,outbuf,sizeof(outbuf)); - - while((r = buffer_get(&bi,inbuf,sizeof(inbuf)))) { // read into buffer - if (r == -1) temp_read(); - - for (in = out = 0; in < r; in++) { // reconstruct CRLF (ok) - if (inbuf[in] != '\n') { - tmpbuf[out++] = inbuf[in]; - } else { - tmpbuf[out++] = '\r'; - tmpbuf[out++] = '\n'; - } - } - if (out) buffer_put(&bo,tmpbuf,out); - } - - if (buffer_flush(&bo) == -1) die(51); - if (fstat(fd,&st) == -1) die_write(fndkin.s); - if (fsync(fd) == -1) die_write(fndkin.s); - if (close(fd) == -1) die_write(fndkin.s); -} - -int mess_dkim() -{ - stralloc line = {0}; - int match; - int fd; - int at = 0; - int ket = 0; - int end = 0; - int len = 0; - int r = 0; - int i; - - fd = open_read(fndkin.s); - if (fd == -1) die_read(); - buffer_init(&bi,read,fd,inbuf,sizeof(inbuf)); - - if (!stralloc_copys(&senddomain,"")) temp_nomem(); - - for (;;) { - if (getln(&bi,&line,&match,'\n') == -1) temp_read(); - if (case_starts(line.s,"DKIM-Signature: ")) r = 1; - if (r == 1) { - if (case_starts(line.s,"From: ")) { // fallback: From - at = str_chr(line.s,'@'); - if (at < line.len) { - end = str_chr(line.s,'\n'); // From: user@senddomain\n - ket = str_chr(line.s,'>'); // From: User <user@senddomain> - len = (ket < end) ? ket : end; - if (!stralloc_copyb(&senddomain,line.s + at + 1,len - at - 1)) temp_nomem(); - r = 2; - } - } - for (i = 0; i < line.len; ++i) { // d=domain.tld - if (*(line.s + i) == '=' && *(line.s + i - 1) == 'd') { - ++i; // gotcha - while (*(line.s + i) != ';') { - if (!stralloc_catb(&senddomain,line.s + i,1)) temp_nomem(); - i++; - r = 3; - } - } - } - } - if (r >= 2 || !match) break; - } - if (senddomain.len < 2) - if (!stralloc_copys(&senddomain,"unknown")) temp_nomem(); - if (!stralloc_0(&senddomain)) temp_nomem(); - - return r; -} - -int dkim_verify() -{ - int child; - int wstat; - char *(args[6]); - int r = -1; - - args[0] = "qmail-dkim"; - args[1] = "-V"; - args[2] = fndkin.s; - args[3] = "none"; - args[4] = fndkout.s; - args[5] = 0; - - if (!(child = fork())) { - pathexec(args); - if (errno) _exit(111); - _exit(100); - } - - wait_pid(&wstat,child); - if (wait_crashed(wstat)) return 1; - - switch (r = wait_exitcode(wstat)) { - case 10: return 1; - default: return 0; - } -} - -int dkim_result(const char *me) -{ - int max = 64; - int fd; - int j; - char ch; - int r = 0; - - if (!stralloc_copys(&result,"")) temp_nomem(); - - if ((fd = open_read(fndkout.s)) == -1) return 0; // nothing to read - while ((r = read(fd,inbuf,sizeof(inbuf))) > 0) - if (!stralloc_catb(&result,inbuf,r)) temp_nomem(); - - if (!stralloc_0(&result)) temp_nomem(); - - if (result.len > 2) { - if (case_starts(result.s,"pass")) r = 0; - if (case_starts(result.s,"fail")) r = 35; - } else - if (!stralloc_copys(&result,"unknown")) temp_nomem(); - - if (!stralloc_copys(&dkheader,"X-Authentication-Results: ")) temp_nomem(); - if (!stralloc_cats(&dkheader,senddomain.s)) temp_nomem(); - if (!stralloc_cats(&dkheader,"; dkim=")) temp_nomem(); - - for (j = 0; j < result.len; j++) { - ch = result.s[j]; - if (ch == '\r' || ch == '\n' || ch == '\0') continue; - if (j <= max) if (!stralloc_catb(&dkheader,&ch,1)) temp_nomem(); - if (ch == ' ' && (j > max)) { - if (!stralloc_cats(&dkheader,"\n ")) temp_nomem(); - max += max; - } - } - - if (!stralloc_cats(&dkheader,"; ")) temp_nomem(); - if (!stralloc_cats(&dkheader,me)) temp_nomem(); - if (!stralloc_0(&dkheader)) temp_nomem(); - - return r; -} - -int qmail_queue() -{ - int fd; - int r; - int child; - int wstat; - int pi[2]; - char *(args[2]); - char tmpbuf[BUFSIZE_MESS]; - int in, out; - - if (pipe(pi) == -1) die_pipe(fndkin.s); - - args[0] = "qmail-queue"; - args[1] = 0; - - switch (child = vfork()) { - case -1: - close(pi[0]); close(pi[1]); - die_write(fndkin.s); - case 0: - close(pi[1]); - if (fd_move(0,pi[0]) == -1) die_pipe(fndkin.s); - sig_pipedefault(); - pathexec(args); - if (errno) _exit(111); - _exit(100); - } - close(pi[0]); - - buffer_init(&bo,write,pi[1],outbuf,sizeof(outbuf)); - - if (dkheader.len > 2) { // write DKIM header - if (buffer_put(&bo,dkheader.s,dkheader.len - 1) == -1) die_write(fndkout.s); - if (buffer_put(&bo,"\n",1) == -1) die_write(fndkout.s); - if (buffer_flush(&bo) == -1) die_write(fndkout.s); - } - - /* read/write message; we need to remove the CR (ok) */ - - if ((fd = open_read(fndkin.s)) == -1) die_read(); - while ((r = read(fd,tmpbuf,sizeof(tmpbuf))) > 0) { - for (in = 0, out = 0; in < r; ++in) { - if (tmpbuf[in] == '\r') { - buffer_put(&bo,&tmpbuf[out],in - out); - out = in + 1; // \n to follow - } - } - } - - if (buffer_flush(&bo) == -1) die_write(fndkin.s); - close(pi[1]); - - wait_pid(&wstat,child); - if (wait_crashed(wstat)) return 1; - - switch (r = wait_exitcode(wstat)) { - case 10: return 1; - default: return 0; - } - - return 0; -} - -void dkim_unlink() -{ - if (unlink(fndkin.s) == -1) - if (errno != ENOENT) temp_unlink(); - if (unlink(fndkout.s) == -1) - if (errno != ENOENT) temp_unlink(); -} - -int main() -{ - int r = 0; - char *mode = 0; - - umask(033); - if (chdir(auto_qmail) == -1) temp_chdir(); - if (control_init() == -1) temp_control(); - if (control_readline(&me,"control/me") == -1) temp_control(); - if (!stralloc_0(&me)) temp_nomem(); - - dkim_stage(); - - if (mess_dkim()) { - dkim_verify(); - r = dkim_result(me.s); - } - - /* we are done: call qmail-queue */ - - mode = env_get("DKIM"); - if (!mode || *mode != '+') r = 0; - - qmail_queue(); - dkim_unlink(); - - _exit(r); -} |