|
@@ -93,6 +93,7 @@ main(int argc, char **argv)
|
|
|
int i, ok, rcvrs;
|
|
|
char **errs;
|
|
|
|
|
|
+ quotefmtinstall();
|
|
|
errs = malloc(argc*sizeof(char*));
|
|
|
reply = s_new();
|
|
|
host = 0;
|
|
@@ -266,9 +267,13 @@ connect(char* net)
|
|
|
return 0;
|
|
|
}
|
|
|
|
|
|
+static char smtpthumbs[] = "/sys/lib/tls/smtp";
|
|
|
+static char smtpexclthumbs[] = "/sys/lib/tls/smtp.exclude";
|
|
|
+
|
|
|
/*
|
|
|
- * exchange names with remote host, possibly
|
|
|
- * enable encryption and do authentication.
|
|
|
+ * exchange names with remote host, attempt to
|
|
|
+ * enable encryption and optionally authenticate.
|
|
|
+ * not fatal if we can't.
|
|
|
*/
|
|
|
static char *
|
|
|
dotls(char *me)
|
|
@@ -282,35 +287,55 @@ dotls(char *me)
|
|
|
c = mallocz(sizeof(*c), 1); /* Note: not freed on success */
|
|
|
if (c == nil)
|
|
|
return Giveup;
|
|
|
+
|
|
|
dBprint("STARTTLS\r\n");
|
|
|
- getreply();
|
|
|
+ if (getreply() != 2)
|
|
|
+ return Giveup;
|
|
|
+
|
|
|
fd = tlsClient(Bfildes(&bout), c);
|
|
|
- if (fd < 0)
|
|
|
-{if(debug)fprint(2, "error starting tlsClient: %r\n");
|
|
|
+ if (fd < 0) {
|
|
|
+ syslog(0, "smtp", "tlsClient to %q: %r", ddomain);
|
|
|
return Giveup;
|
|
|
-}
|
|
|
- goodcerts = initThumbprints("/sys/lib/tls/smtp", "/sys/lib/tls/smtp.exclude");
|
|
|
+ }
|
|
|
+ goodcerts = initThumbprints(smtpthumbs, smtpexclthumbs);
|
|
|
if (goodcerts == nil) {
|
|
|
-if(debug)fprint(2, "bad cert\n");
|
|
|
free(c);
|
|
|
- return Giveup;
|
|
|
+ close(fd);
|
|
|
+ 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)) {
|
|
|
- h = malloc(2 * sizeof hash + 1);
|
|
|
+ /* TODO? if not excluded, add hash to thumb list */
|
|
|
+ free(c);
|
|
|
+ close(fd);
|
|
|
+ h = malloc(2*sizeof hash + 1);
|
|
|
if (h != nil) {
|
|
|
- enc16(h, 2 * sizeof hash + 1, hash, sizeof hash);
|
|
|
- print("x509 sha1=%s", h);
|
|
|
+ enc16(h, 2*sizeof hash + 1, hash, sizeof hash);
|
|
|
+ // print("x509 sha1=%s", h);
|
|
|
+ syslog(0, "smtp",
|
|
|
+ "remote cert. has bad thumbprint: x509 sha1=%s server=%q",
|
|
|
+ h, ddomain);
|
|
|
free(h);
|
|
|
}
|
|
|
- return Giveup;
|
|
|
+ return Giveup; /* how to recover? TLS is started */
|
|
|
}
|
|
|
freeThumbprints(goodcerts);
|
|
|
Bterm(&bin);
|
|
|
Bterm(&bout);
|
|
|
+
|
|
|
+ /*
|
|
|
+ * set up bin & bout to use the TLS fd, i/o upon which generates
|
|
|
+ * i/o on the original, underlying fd.
|
|
|
+ */
|
|
|
Binit(&bin, fd, OREAD);
|
|
|
fd = dup(fd, -1);
|
|
|
+if(debug)fprint(2, "bout fd = %d\n", fd);
|
|
|
Binit(&bout, fd, OWRITE);
|
|
|
+
|
|
|
+ syslog(0, "smtp", "started TLS to %q", ddomain);
|
|
|
return(hello(me, 1));
|
|
|
}
|
|
|
|
|
@@ -323,20 +348,16 @@ doauth(void)
|
|
|
|
|
|
if(user != nil)
|
|
|
p = auth_getuserpasswd(nil,
|
|
|
- "proto=pass service=smtp server=%q user=%q",
|
|
|
- ddomain, user);
|
|
|
+ "proto=pass service=smtp server=%q user=%q", ddomain, user);
|
|
|
else
|
|
|
p = auth_getuserpasswd(nil,
|
|
|
- "proto=pass service=smtp server=%q",
|
|
|
- ddomain);
|
|
|
+ "proto=pass service=smtp server=%q", ddomain);
|
|
|
if (p == nil)
|
|
|
return Giveup;
|
|
|
n = strlen(p->user) + strlen(p->passwd) + 3;
|
|
|
buf = malloc(n);
|
|
|
- if (buf == nil)
|
|
|
- return Retry; /* Out of memory */
|
|
|
base64 = malloc(2 * n);
|
|
|
- if (base64 == nil) {
|
|
|
+ if (buf == nil || base64 == nil) {
|
|
|
free(buf);
|
|
|
return Retry; /* Out of memory */
|
|
|
}
|