diff options
Diffstat (limited to 'src/qmail-dksign.c')
-rw-r--r-- | src/qmail-dksign.c | 381 |
1 files changed, 222 insertions, 159 deletions
diff --git a/src/qmail-dksign.c b/src/qmail-dksign.c index 5135cd4..06fee37 100644 --- a/src/qmail-dksign.c +++ b/src/qmail-dksign.c @@ -1,29 +1,31 @@ -#include <sys/types.h> +#include <arpa/inet.h> +#include <netinet/in.h> #include <sys/socket.h> #include <sys/stat.h> -#include <netinet/in.h> -#include <arpa/inet.h> +#include <sys/types.h> #include <unistd.h> -#include "sig.h" -#include "stralloc.h" + #include "buffer.h" -#include "error.h" -#include "auto_qmail.h" -#include "control.h" -#include "str.h" -#include "exit.h" #include "case.h" #include "constmap.h" -#include "uint_t.h" +#include "error.h" +#include "exit.h" #include "fd.h" +#include "fmt.h" #include "logmsg.h" #include "open.h" -#include "fmt.h" -#include "fmtqfn.h" +#include "pathexec.h" #include "readwrite.h" -#include "qmail.h" +#include "sig.h" +#include "str.h" +#include "stralloc.h" +#include "uint_t.h" #include "wait.h" -#include "pathexec.h" + +#include "auto_qmail.h" +#include "control.h" +#include "fmtqfn.h" +#include "qmail.h" #include "rcpthosts.h" #define WHO "qmail-dksign" @@ -54,21 +56,42 @@ */ char bufin[1000]; // RFC 5322: 998 chars - why? -buffer bi = BUFFER_INIT(read,0,bufin,sizeof(bufin)); +buffer bi = BUFFER_INIT(read, 0, bufin, sizeof(bufin)); char bufout[1000]; -buffer bo = BUFFER_INIT(write,1,bufout,sizeof(bufout)); +buffer bo = BUFFER_INIT(write, 1, bufout, sizeof(bufout)); -void die(int e) { _exit(e); } -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 die(int e) +{ + _exit(e); +} +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); +} stralloc fndkin = {0}; stralloc fndkout = {0}; -stralloc sender = {0}; // will be re-written +stralloc sender = {0}; // will be re-written stralloc senddomain = {0}; stralloc originator = {0}; stralloc dkimdomains = {0}; @@ -78,34 +101,35 @@ stralloc ecckey = {0}; stralloc rsakey = {0}; char *dkimparams = 0; -void temp_nomem() +void temp_nomem() { out("ZOut of memory. (#4.3.0)\n"); zerodie(); } -void temp_chdir() +void temp_chdir() { out("ZUnable to switch to target directory. (#4.3.0)\n"); zerodie(); } -void temp_create() +void temp_create() { out("ZUnable to create DKIM stage file: "); out(error_str(errno)); - out(fndkin.s); out(". (#4.3.0)\n"); + out(fndkin.s); + out(". (#4.3.0)\n"); zerodie(); } -void temp_unlink() +void temp_unlink() { out("ZUnable to unlink DKIM stage file. (#4.3.0)\n"); zerodie(); } -void temp_control() +void temp_control() { out("ZUnable to read DKIM control files. (#4.3.0)\n"); zerodie(); } -void perm_usage() +void perm_usage() { out("Zqmail-dksign was invoked improperly. (#5.3.5)\n"); zerodie(); @@ -116,12 +140,12 @@ void temp_read() zerodie(); } void temp_nosignkey() -{ +{ out("DCan't read sign key: "); out(rsakey.s); out(" or "); out(ecckey.s); - out(". (#4.3.0)\n"); + out(". (#4.3.0)\n"); zerodie(); } @@ -132,46 +156,50 @@ int get_controls() if (control_init() == -1) temp_control(); - switch (control_readfile(&dkimdomains,"control/dkimdomains",0)) { + switch (control_readfile(&dkimdomains, "control/dkimdomains", 0)) { case -1: return 0; - case 0: if (!constmap_init(&mapdkimdomains,"",0,1)) temp_nomem(); break; - case 1: if (!constmap_init(&mapdkimdomains,dkimdomains.s,dkimdomains.len,1)) temp_nomem(); break; + case 0: + if (!constmap_init(&mapdkimdomains, "", 0, 1)) temp_nomem(); + break; + case 1: + if (!constmap_init(&mapdkimdomains, dkimdomains.s, dkimdomains.len, 1)) temp_nomem(); + break; } -/* Check for disabled DKIM send domains */ + /* Check for disabled DKIM send domains */ - if (!stralloc_copys(&domname,"!")) temp_nomem(); - if (!stralloc_cats(&domname,senddomain.s)) temp_nomem(); - if (constmap(&mapdkimdomains,domname.s,domname.len)) return 0; + if (!stralloc_copys(&domname, "!")) temp_nomem(); + if (!stralloc_cats(&domname, senddomain.s)) temp_nomem(); + if (constmap(&mapdkimdomains, domname.s, domname.len)) return 0; -/* Parenting domains; senddomain 0-terminated; lowercase */ + /* Parenting domains; senddomain 0-terminated; lowercase */ for (i = 0; i <= senddomain.len; ++i) { if ((i == 0) || (senddomain.s[i] == '.')) - if ((dkimparams = constmap(&mapdkimdomains,senddomain.s + i,senddomain.len - i - 1))) { - if (!stralloc_copys(&sender,senddomain.s + i)) temp_nomem(); + if ((dkimparams = constmap(&mapdkimdomains, senddomain.s + i, senddomain.len - i - 1))) { + if (!stralloc_copys(&sender, senddomain.s + i)) temp_nomem(); if (!stralloc_0(&sender)) temp_nomem(); return 3; } } -/* We sign only senddomains we take responsibility for: rcpthosts */ + /* We sign only senddomains we take responsibility for: rcpthosts */ - if ((dkimparams = constmap(&mapdkimdomains,"=",1))) { + if ((dkimparams = constmap(&mapdkimdomains, "=", 1))) { if (rcpthosts_init() == -1) temp_control(); - if (rcpthosts(originator.s,originator.len)) { - if ((control_readline(&sender,"control/defaultdomain") != 1)) - if (control_readline(&sender,"control/me") == -1) temp_control(); + if (rcpthosts(originator.s, originator.len)) { + if ((control_readline(&sender, "control/defaultdomain") != 1)) + if (control_readline(&sender, "control/me") == -1) temp_control(); if (!stralloc_0(&sender)) temp_nomem(); return 2; } } -/* Default settings for MTA: 'defaultdomain' or even 'me' */ + /* Default settings for MTA: 'defaultdomain' or even 'me' */ - if ((dkimparams = constmap(&mapdkimdomains,"*",1))) { - if ((control_readline(&sender,"control/defaultdomain") != 1)) - if (control_readline(&sender,"control/me") == -1) temp_control(); + if ((dkimparams = constmap(&mapdkimdomains, "*", 1))) { + if ((control_readline(&sender, "control/defaultdomain") != 1)) + if (control_readline(&sender, "control/me") == -1) temp_control(); if (!stralloc_0(&sender)) temp_nomem(); return 1; } @@ -179,18 +207,18 @@ int get_controls() return 0; } -void fnmake_dkim(unsigned long id) -{ - fndkin.len = fmtqfn(fndkin.s,"queue/dkim/",id,1); +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); + fndkout.len = fmtqfn(fndkout.s, "queue/dkim/", id, 1); } void dkim_unlink() { - if (unlink(fndkin.s) == -1) + if (unlink(fndkin.s) == -1) if (errno != ENOENT) temp_unlink(); - if (unlink(fndkout.s) == -1) + if (unlink(fndkout.s) == -1) if (errno != ENOENT) temp_unlink(); } @@ -201,33 +229,33 @@ void dkim_stage() char ch; struct stat st; - if (!stralloc_ready(&fndkin,FMTQFN)) temp_nomem(); - if (!stralloc_ready(&fndkout,FMTQFN)) temp_nomem(); + if (!stralloc_ready(&fndkin, FMTQFN)) temp_nomem(); + if (!stralloc_ready(&fndkout, FMTQFN)) temp_nomem(); fnmake_dkim(getpid()); // pre-staging - dkim_unlink(); // duplicate, left over file + dkim_unlink(); // duplicate, left over file fd = open_excl(fndkin.s); if (fd == -1) die_write(fndkin.s); - buffer_init(&bi,read,0,bufin,sizeof(bufin)); - buffer_init(&bo,write,fd,bufout,sizeof(bufout)); + buffer_init(&bi, read, 0, bufin, sizeof(bufin)); + buffer_init(&bo, write, fd, bufout, sizeof(bufout)); for (;;) { - r = buffer_get(&bi,&ch,1); + r = buffer_get(&bi, &ch, 1); if (r == 0) break; if (r == -1) temp_read(); if (ch == '\r') continue; while (ch != '\n') { - buffer_put(&bo,&ch,1); - r = buffer_get(&bi,&ch,1); + buffer_put(&bo, &ch, 1); + r = buffer_get(&bi, &ch, 1); if (r == -1) temp_read(); } - buffer_put(&bo,"\r\n",2); + buffer_put(&bo, "\r\n", 2); } if (buffer_flush(&bo) == -1) die(51); - if (fstat(fd,&st) == -1) die_read(); + if (fstat(fd, &st) == -1) die_read(); if (fsync(fd) == -1) die_write(fndkin.s); if (close(fd) == -1) die_write(fndkin.s); } @@ -261,28 +289,61 @@ stralloc length = {0}; // -l -z<hash> - set signature type (1=sha1, 2=sha256, 3=both, 4=ed25519, 5=hybrid) */ -int dkim_sign(const char *rsakeyfile,const char *ecckeyfile,const char *fnin,const char *fnout) +int dkim_sign(const char *rsakeyfile, const char *ecckeyfile, const char *fnin, const char *fnout) { int child; int wstat; char *(args[17]); int i = 0; - args[i] = "qmail-dkim"; ++i; - args[i] = "-s"; ++i; - args[i] = "-q"; ++i; - if (sdid.len > 3) { args[i] = sdid.s; ++i; } - if (selector.len > 3) { args[i] = selector.s; ++i; } - if (selectore.len > 3) { args[i] = selectore.s; ++i; } - if (auid.len > 3) { args[i] = auid.s; ++i; } - if (expire.len > 3) { args[i] = expire.s; ++i; } - if (canon.len > 2) { args[i] = canon.s; ++i; } - if (hash.len > 2) { args[i] = hash.s; ++i; } - if (length.len > 2) { args[i] = length.s; ++i; } - args[i] = fnin; ++i; - args[i] = rsakeyfile; ++i; - args[i] = fnout; ++i; - if (str_len(ecckeyfile) > 3) { args[i] = ecckeyfile; ++i; } + args[i] = "qmail-dkim"; + ++i; + args[i] = "-s"; + ++i; + args[i] = "-q"; + ++i; + if (sdid.len > 3) { + args[i] = sdid.s; + ++i; + } + if (selector.len > 3) { + args[i] = selector.s; + ++i; + } + if (selectore.len > 3) { + args[i] = selectore.s; + ++i; + } + if (auid.len > 3) { + args[i] = auid.s; + ++i; + } + if (expire.len > 3) { + args[i] = expire.s; + ++i; + } + if (canon.len > 2) { + args[i] = canon.s; + ++i; + } + if (hash.len > 2) { + args[i] = hash.s; + ++i; + } + if (length.len > 2) { + args[i] = length.s; + ++i; + } + args[i] = fnin; + ++i; + args[i] = rsakeyfile; + ++i; + args[i] = fnout; + ++i; + if (str_len(ecckeyfile) > 3) { + args[i] = ecckeyfile; + ++i; + } args[i] = 0; if (!(child = vfork())) { @@ -291,16 +352,16 @@ int dkim_sign(const char *rsakeyfile,const char *ecckeyfile,const char *fnin,con _exit(100); } - wait_pid(&wstat,child); + wait_pid(&wstat, child); if (wait_crashed(wstat)) return 1; switch (wait_exitcode(wstat)) { - case 1: return 1; + case 1: return 1; default: return 0; } } -int qmail_remote(char **qargs,int fd) +int qmail_remote(char **qargs, int fd) { int child; int wstat; @@ -314,20 +375,20 @@ int qmail_remote(char **qargs,int fd) if (!(child = vfork())) { if (fd) { - if (fd_move(0,fd) == -1) _exit(111); - if (fd_copy(2,1) == -1) _exit(111); + if (fd_move(0, fd) == -1) _exit(111); + if (fd_copy(2, 1) == -1) _exit(111); } pathexec(args); if (errno) _exit(111); _exit(100); } - - wait_pid(&wstat,child); + + wait_pid(&wstat, child); if (wait_crashed(wstat)) return 1; switch (wait_exitcode(wstat)) { case 111: return 1; - default: return 0; + default: return 0; } } @@ -338,104 +399,106 @@ void dkim_setup() /* defaults: selector=default, IETF format, q=dns/txt, z=2, c=r */ - if (!stralloc_copys(&sdid,"-d")) temp_nomem(); - if (!stralloc_cat(&sdid,&sender)) temp_nomem(); + if (!stralloc_copys(&sdid, "-d")) temp_nomem(); + if (!stralloc_cat(&sdid, &sender)) temp_nomem(); if (!stralloc_0(&sdid)) temp_nomem(); - if (!stralloc_copys(&selector,"-ydefault")) temp_nomem(); + if (!stralloc_copys(&selector, "-ydefault")) temp_nomem(); if (!stralloc_0(&selector)) temp_nomem(); - if (!stralloc_copys(&selectore,"-Yeddy")) temp_nomem(); + if (!stralloc_copys(&selectore, "-Yeddy")) temp_nomem(); if (!stralloc_0(&selectore)) temp_nomem(); - if (!stralloc_copys(&canon,"-cr")) temp_nomem(); + if (!stralloc_copys(&canon, "-cr")) temp_nomem(); if (!stralloc_0(&canon)) temp_nomem(); - if (!stralloc_copys(&hash,"-z2")) temp_nomem(); + if (!stralloc_copys(&hash, "-z2")) temp_nomem(); if (!stralloc_0(&hash)) temp_nomem(); /* domain:selector,selectore|sdid|[auid|~]|expire|c:z:l; c=[r|s|t|u], z=[1,2,3,4,5], l=l */ if (dkimparams && *dkimparams) { - i = str_chr(dkimparams,'|'); + i = str_chr(dkimparams, '|'); pos = dkimparams + i; - if (*pos == '|' || *pos == '\0') { // selector + if (*pos == '|' || *pos == '\0') { // selector dkimparams[i] = '\0'; - c = str_chr(dkimparams,','); // selectore=eddy + c = str_chr(dkimparams, ','); // selectore=eddy if (dkimparams[c] == ',') { dkimparams[c] = '\0'; if (str_len(dkimparams + c + 1)) { - if (!stralloc_copys(&selectore,"-Y")) temp_nomem(); - if (!stralloc_cats(&selectore,dkimparams + c + 1)) temp_nomem(); + if (!stralloc_copys(&selectore, "-Y")) temp_nomem(); + if (!stralloc_cats(&selectore, dkimparams + c + 1)) temp_nomem(); if (!stralloc_0(&selectore)) temp_nomem(); } - } else if (str_len(dkimparams)) { // selector=default - if (!stralloc_copys(&selector,"-y")) temp_nomem(); - if (!stralloc_cats(&selector,dkimparams)) temp_nomem(); + } else if (str_len(dkimparams)) { // selector=default + if (!stralloc_copys(&selector, "-y")) temp_nomem(); + if (!stralloc_cats(&selector, dkimparams)) temp_nomem(); if (!stralloc_0(&selector)) temp_nomem(); } - j = str_chr(dkimparams + i + 1,'|'); + j = str_chr(dkimparams + i + 1, '|'); pos = dkimparams + i + j + 1; - if (*pos == '|' || *pos == '\0') { // sdid; domain in DKIM header + if (*pos == '|' || *pos == '\0') { // sdid; domain in DKIM header dkimparams[i + j + 1] = '\0'; - if (!stralloc_copys(&sdid,"-d")) temp_nomem(); - if (!stralloc_cats(&sdid,dkimparams + i + 1)) temp_nomem(); + if (!stralloc_copys(&sdid, "-d")) temp_nomem(); + if (!stralloc_cats(&sdid, dkimparams + i + 1)) temp_nomem(); if (!stralloc_0(&sdid)) temp_nomem(); - k = str_chr(dkimparams + i + j + 2,'|'); + k = str_chr(dkimparams + i + j + 2, '|'); pos = dkimparams + i + j + k + 2; - if (*pos == '|' || *pos == '\0') { // auid = identifier + if (*pos == '|' || *pos == '\0') { // auid = identifier dkimparams[i + j + k + 2] = '\0'; - if (!stralloc_copys(&auid,"-i")) temp_nomem(); + if (!stralloc_copys(&auid, "-i")) temp_nomem(); if (dkimparams[i + j + 2] == '~') { - if (!stralloc_cat(&auid,&originator)) temp_nomem(); - } else - if (!stralloc_cats(&auid,dkimparams + i + j + 2)) temp_nomem(); - + if (!stralloc_cat(&auid, &originator)) temp_nomem(); + } else if (!stralloc_cats(&auid, dkimparams + i + j + 2)) + temp_nomem(); + if (!stralloc_0(&auid)) temp_nomem(); - - l = str_chr(dkimparams + i + j + k + 3,'|'); + + l = str_chr(dkimparams + i + j + k + 3, '|'); pos = dkimparams + i + j + k + l + 3; - if (*pos == '|' || *pos == '\0') { // expire after n secs + if (*pos == '|' || *pos == '\0') { // expire after n secs dkimparams[i + j + k + l + 3] = '\0'; - if (!stralloc_copys(&expire,"-x")) temp_nomem(); - if (!stralloc_cats(&expire,dkimparams + i + j + k + 3)) temp_nomem(); + if (!stralloc_copys(&expire, "-x")) temp_nomem(); + if (!stralloc_cats(&expire, dkimparams + i + j + k + 3)) temp_nomem(); if (!stralloc_0(&expire)) temp_nomem(); - /* Options to follow */ + /* Options to follow */ opt = dkimparams + i + j + k + l + 4; if (*opt == '\0') return; - if (*opt != ':') { - if (!stralloc_copys(&canon,"-c")) temp_nomem(); // canonicalization - if (!stralloc_catb(&canon,opt,1)) temp_nomem(); + if (*opt != ':') { + if (!stralloc_copys(&canon, "-c")) temp_nomem(); // canonicalization + if (!stralloc_catb(&canon, opt, 1)) temp_nomem(); if (!stralloc_0(&canon)) temp_nomem(); - ++opt; if (*opt == '\0') return; // next colon + ++opt; + if (*opt == '\0') return; // next colon } if (*opt != ':' || *opt == '\0') return; if (*opt == ':') ++opt; if (*opt != ':') { - if (!stralloc_copys(&hash,"-z")) temp_nomem(); // hash - if (!stralloc_catb(&hash,opt,1)) temp_nomem(); + if (!stralloc_copys(&hash, "-z")) temp_nomem(); // hash + if (!stralloc_catb(&hash, opt, 1)) temp_nomem(); if (!stralloc_0(&hash)) temp_nomem(); - ++opt; if (*opt == '\0') return; // next colon + ++opt; + if (*opt == '\0') return; // next colon } if (*opt != ':' || *opt == '\0') return; if (*opt == ':') ++opt; if (*opt != ':' && *opt == 'l') { - if (!stralloc_copys(&length,"-l")) temp_nomem(); // length + if (!stralloc_copys(&length, "-l")) temp_nomem(); // length if (!stralloc_0(&length)) temp_nomem(); } } } - } - } + } + } } return; } -int main(int argc,char **args) +int main(int argc, char **args) { - int i; - int fdin = 0; // initial read from FD 0 + int i; + int fdin = 0; // initial read from FD 0 int nkey = 0; char *(qargs[4]); struct stat st; @@ -451,15 +514,15 @@ int main(int argc,char **args) if (chdir(auto_qmail) == -1) temp_chdir(); if (str_len(args[2]) > 2) { - i = str_chr(args[2],'@'); - if (*(args[2] + i) == '@') - if (!stralloc_copys(&senddomain,args[2] + i + 1)) temp_nomem(); + i = str_chr(args[2], '@'); + if (*(args[2] + i) == '@') + if (!stralloc_copys(&senddomain, args[2] + i + 1)) temp_nomem(); } - if (!stralloc_0(&senddomain)) temp_nomem(); - if (!stralloc_copys(&originator,args[2])) temp_nomem(); + if (!stralloc_0(&senddomain)) temp_nomem(); + if (!stralloc_copys(&originator, args[2])) temp_nomem(); - if (!get_controls()) { - qmail_remote(qargs,fdin); + if (!get_controls()) { + qmail_remote(qargs, fdin); _exit(0); } @@ -467,34 +530,34 @@ int main(int argc,char **args) /* Setup keys: they are composed from selector */ - case_lowerb(sender.s,sender.len); // needs to be lowercase - if (!stralloc_copys(&rsakey,DOMAINKEYS)) temp_nomem(); - if (!stralloc_cats(&rsakey,sender.s)) temp_nomem(); - if (!stralloc_cats(&rsakey,"/")) temp_nomem(); + case_lowerb(sender.s, sender.len); // needs to be lowercase + if (!stralloc_copys(&rsakey, DOMAINKEYS)) temp_nomem(); + if (!stralloc_cats(&rsakey, sender.s)) temp_nomem(); + if (!stralloc_cats(&rsakey, "/")) temp_nomem(); - if (!stralloc_copys(&ecckey,DOMAINKEYS)) temp_nomem(); - if (!stralloc_cats(&ecckey,sender.s)) temp_nomem(); - if (!stralloc_cats(&ecckey,"/")) temp_nomem(); + if (!stralloc_copys(&ecckey, DOMAINKEYS)) temp_nomem(); + if (!stralloc_cats(&ecckey, sender.s)) temp_nomem(); + if (!stralloc_cats(&ecckey, "/")) temp_nomem(); /* RSA key common for SHA1 and SHA256: rsakeyfile -> selector */ - if (!stralloc_cats(&rsakey,selector.s + 2)) temp_nomem(); // -y prepended + if (!stralloc_cats(&rsakey, selector.s + 2)) temp_nomem(); // -y prepended if (!stralloc_0(&rsakey)) temp_nomem(); - if (stat(rsakey.s,&st) != -1) + if (stat(rsakey.s, &st) != -1) if (open_read(rsakey.s) > 0) ++nkey; /* ECC key follows: ecckeyfile -> (,)selector2 */ - if (!stralloc_cats(&ecckey,selectore.s + 2)) temp_nomem(); // -Y prepended + if (!stralloc_cats(&ecckey, selectore.s + 2)) temp_nomem(); // -Y prepended if (!stralloc_0(&ecckey)) temp_nomem(); - if (stat(ecckey.s,&st) != -1) + if (stat(ecckey.s, &st) != -1) if (open_read(ecckey.s) > 0) ++nkey; /* We got keys - go for staging */ - - if (nkey) { // otherwise no key exists; why bother + + if (nkey) { // otherwise no key exists; why bother dkim_stage(); - if (!dkim_sign(rsakey.s,ecckey.s,fndkin.s,fndkout.s)) { + if (!dkim_sign(rsakey.s, ecckey.s, fndkin.s, fndkout.s)) { fdin = open_read(fndkout.s); if (fdin == -1) die_read(); } else { @@ -503,8 +566,8 @@ int main(int argc,char **args) } } else temp_nosignkey(); - - qmail_remote(qargs,fdin); // closes fdin + + qmail_remote(qargs, fdin); // closes fdin if (nkey) dkim_unlink(); _exit(0); |