static char* pop3pushtls(Pop *pop) { int fd; uchar digest[SHA1dlen]; TLSconn conn; memset(&conn, 0, sizeof conn); // conn.trace = pop3log; fd = tlsClient(pop->fd, &conn); if(fd < 0) return "tls error"; if(conn.cert==nil || conn.certlen <= 0){ close(fd); return "server did not provide TLS certificate"; } sha1(conn.cert, conn.certlen, digest, nil); if(!pop->thumb || !okThumbprint(digest, pop->thumb)){ fmtinstall('H', encodefmt); close(fd); free(conn.cert); fprint(2, "upas/fs pop3: server certificate %.*H not recognized\n", SHA1dlen, digest); return "bad server certificate"; } free(conn.cert); close(pop->fd); pop->fd = fd; pop->encrypted = 1; Binit(&pop->bin, pop->fd, OREAD); Binit(&pop->bout, pop->fd, OWRITE); return nil; }
static int starttls(Imap *imap, TLSconn *connp) { int sfd; uchar digest[SHA1dlen]; fmtinstall('H', encodefmt); memset(connp, 0, sizeof *connp); sfd = tlsClient(imap->fd, connp); if(sfd < 0) { werrstr("tlsClient: %r"); return -1; } if(connp->cert==nil || connp->certlen <= 0) { close(sfd); werrstr("server did not provide TLS certificate"); return -1; } sha1(connp->cert, connp->certlen, digest, nil); /* * don't do this any more. our local it people are rotating their * certificates faster than we can keep up. */ if(0 && (!imap->thumb || !okThumbprint(digest, imap->thumb))) { close(sfd); werrstr("server certificate %.*H not recognized", SHA1dlen, digest); return -1; } close(imap->fd); imap->fd = sfd; return sfd; }
static void loadThumbprints(char *file, Thumbprint *table, Thumbprint *crltab) { Thumbprint *entry; Biobuf *bin; char *line, *field[50]; uchar sum[SHA1dlen]; int i; bin = Bopen(file, OREAD); if(bin == nil) return; for(; (line = Brdstr(bin, '\n', 1)) != 0; free(line)){ if(tokenize(line, field, nelem(field)) < 2) continue; if(strcmp(field[0], "#include") == 0){ loadThumbprints(field[1], table, crltab); continue; } if(strcmp(field[0], "x509") != 0 || strncmp(field[1], "sha1=", strlen("sha1=")) != 0) continue; field[1] += strlen("sha1="); dec16(sum, sizeof(sum), field[1], strlen(field[1])); if(crltab && okThumbprint(sum, crltab)) continue; entry = (Thumbprint*)emalloc(sizeof(*entry)); memcpy(entry->sha1, sum, SHA1dlen); i = ((sum[0]<<8) + sum[1]) & (ThumbTab-1); entry->next = table[i].next; table[i].next = entry; } Bterm(bin); }
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; }