summaryrefslogtreecommitdiff
path: root/sqmail-4.3.07/src/qmail-dkverify.c
diff options
context:
space:
mode:
Diffstat (limited to 'sqmail-4.3.07/src/qmail-dkverify.c')
-rw-r--r--sqmail-4.3.07/src/qmail-dkverify.c368
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);
-}