static char * ckthumbs(TLSconn *c) { Thumbprint *goodcerts; char *h, *err; uchar hash[SHA1dlen]; err = nil; goodcerts = initThumbprints(smtpthumbs, smtpexclthumbs); if (goodcerts == nil) { if (!okunksecure) syslog(0, "smtp", "bad thumbprints in %s", smtpthumbs); return Giveup; /* how to recover? TLS is started */ } /* compute sha1 hash of remote's certificate, see if we know it */ sha1(c->cert, c->certlen, hash, nil); if (!okThumbprint(hash, goodcerts) && !okunksecure) { h = malloc(2*sizeof hash + 1); if (h != nil) { enc16(h, 2*sizeof hash + 1, hash, sizeof hash); syslog(0, "smtp", "remote cert. has bad thumbprint: " "x509 sha1=%s server=%q", h, ddomain); free(h); } err = Giveup; /* how to recover? TLS is started */ } freeThumbprints(goodcerts); return err; }
static char * wraptls(void) { TLSconn *c; Thumbprint *goodcerts; char *h, *err; int fd; uchar hash[SHA1dlen]; goodcerts = nil; err = Giveup; c = mallocz(sizeof(*c), 1); if (c == nil) return err; fd = tlsClient(Bfildes(&bout), c); if (fd < 0) { syslog(0, "smtp", "tlsClient to %q: %r", ddomain); goto Out; } Bterm(&bout); Binit(&bout, fd, OWRITE); fd = dup(fd, Bfildes(&bin)); Bterm(&bin); Binit(&bin, fd, OREAD); goodcerts = initThumbprints(smtpthumbs, smtpexclthumbs); if (goodcerts == nil) { syslog(0, "smtp", "bad thumbprints in %s", smtpthumbs); goto Out; } /* compute sha1 hash of remote's certificate, see if we know it */ sha1(c->cert, c->certlen, hash, nil); if (!okThumbprint(hash, goodcerts)) { /* TODO? if not excluded, add hash to thumb list */ h = malloc(2*sizeof hash + 1); if (h == nil) goto Out; enc16(h, 2*sizeof hash + 1, hash, sizeof hash); syslog(0, "smtp", "remote cert. has bad thumbprint: x509 sha1=%s server=%q", h, ddomain); free(h); goto Out; } syslog(0, "smtp", "started TLS to %q", ddomain); err = nil; Out: if(goodcerts != nil) freeThumbprints(goodcerts); free(c->cert); free(c->sessionID); free(c); return err; }
// // open mailboxes of the form /pop/host/user or /apop/host/user // char* pop3mbox(Mailbox *mb, char *path) { char *f[10]; int nf, apop, ppop, popssl, apopssl, apoptls, popnotls, apopnotls, poptls; Pop *pop; quotefmtinstall(); popssl = strncmp(path, "/pops/", 6) == 0; apopssl = strncmp(path, "/apops/", 7) == 0; poptls = strncmp(path, "/poptls/", 8) == 0; popnotls = strncmp(path, "/popnotls/", 10) == 0; ppop = popssl || poptls || popnotls || strncmp(path, "/pop/", 5) == 0; apoptls = strncmp(path, "/apoptls/", 9) == 0; apopnotls = strncmp(path, "/apopnotls/", 11) == 0; apop = apopssl || apoptls || apopnotls || strncmp(path, "/apop/", 6) == 0; if(!ppop && !apop) return Enotme; path = strdup(path); if(path == nil) return "out of memory"; nf = getfields(path, f, nelem(f), 0, "/"); if(nf != 3 && nf != 4) { free(path); return "bad pop3 path syntax /[a]pop[tls|ssl]/system[/user]"; } pop = emalloc(sizeof(*pop)); pop->freep = path; pop->host = f[2]; if(nf < 4) pop->user = nil; else pop->user = f[3]; pop->ppop = ppop; pop->needssl = popssl || apopssl; pop->needtls = poptls || apoptls; pop->refreshtime = 60; pop->notls = popnotls || apopnotls; pop->thumb = initThumbprints("/sys/lib/tls/mail", "/sys/lib/tls/mail.exclude"); mb->aux = pop; mb->sync = pop3sync; mb->close = pop3close; mb->ctl = pop3ctl; mb->d = emalloc(sizeof(*mb->d)); return nil; }
static char* pop3ctl(Mailbox *mb, int argc, char **argv) { int n; Pop *pop; pop = mb->aux; if(argc < 1) return Epop3ctl; if(argc==1 && strcmp(argv[0], "debug")==0){ pop->debug = 1; return nil; } if(argc==1 && strcmp(argv[0], "nodebug")==0){ pop->debug = 0; return nil; } if(argc==1 && strcmp(argv[0], "thumbprint")==0){ if(pop->thumb) freeThumbprints(pop->thumb); pop->thumb = initThumbprints("/sys/lib/tls/mail", "/sys/lib/tls/mail.exclude"); } if(strcmp(argv[0], "refresh")==0){ if(argc==1){ pop->refreshtime = 60; return nil; } if(argc==2){ n = atoi(argv[1]); if(n < 15) return Epop3ctl; pop->refreshtime = n; return nil; } } return Epop3ctl; }