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; }
int encodefmt(Fmt *f) { char *out; char *buf, *p; int len; int ilen; int rv; uchar *b; char obuf[64]; /* rsc optimization */ b = va_arg(f->args, uchar*); if(b == 0) return fmtstrcpy(f, "<nil>"); ilen = f->prec; f->prec = 0; if(!(f->flags&FmtPrec) || ilen < 0) goto error; f->flags &= ~FmtPrec; switch(f->r){ case '<': len = (8*ilen+4)/5 + 3; break; case '[': len = (8*ilen+5)/6 + 4; break; case 'H': len = 2*ilen + 1; break; default: goto error; } if(len > sizeof(obuf)){ buf = malloc(len); if(buf == nil) goto error; } else buf = obuf; /* convert */ out = buf; switch(f->r){ case '<': rv = enc32(out, len, b, ilen); break; case '[': rv = enc64(out, len, b, ilen); break; case 'H': rv = enc16(out, len, b, ilen); if(rv >= 0 && (f->flags & FmtLong)) for(p = buf; *p; p++) *p = tolower((uchar)*p); break; default: rv = -1; break; } if(rv < 0) goto error; fmtstrcpy(f, buf); if(buf != obuf) free(buf); return 0; error: return fmtstrcpy(f, "<encodefmt>"); }