smtp: add SMTPS support (-t)
This commit is contained in:
parent
0dbde06bc7
commit
646eb150e1
2 changed files with 41 additions and 19 deletions
|
@ -6,7 +6,7 @@ smtp, smtpd \- mail transport
|
||||||
.ti -0.5i
|
.ti -0.5i
|
||||||
.B upas/smtp
|
.B upas/smtp
|
||||||
[
|
[
|
||||||
.B -aAdfips
|
.B -aAdfipst
|
||||||
] [
|
] [
|
||||||
.B -b
|
.B -b
|
||||||
.I busted-mx
|
.I busted-mx
|
||||||
|
@ -119,6 +119,9 @@ don't send any mail.
|
||||||
if the server supports the ESMTP extension to use TLS encryption, turn it on for
|
if the server supports the ESMTP extension to use TLS encryption, turn it on for
|
||||||
this session. See RFC3207 for details.
|
this session. See RFC3207 for details.
|
||||||
.TP
|
.TP
|
||||||
|
.B -t
|
||||||
|
preemtively establish TLS connection before SMTP handshake (SMTPS).
|
||||||
|
.TP
|
||||||
.B -u
|
.B -u
|
||||||
specify a user name to be used in authentication. The default name is
|
specify a user name to be used in authentication. The default name is
|
||||||
the current login id.
|
the current login id.
|
||||||
|
|
|
@ -6,6 +6,7 @@
|
||||||
#include <auth.h>
|
#include <auth.h>
|
||||||
|
|
||||||
static char* connect(char*);
|
static char* connect(char*);
|
||||||
|
static char* wraptls(void);
|
||||||
static char* dotls(char*);
|
static char* dotls(char*);
|
||||||
static char* doauth(char*);
|
static char* doauth(char*);
|
||||||
|
|
||||||
|
@ -26,7 +27,7 @@ int printheader(void);
|
||||||
void putcrnl(char*, int);
|
void putcrnl(char*, int);
|
||||||
void quit(char*);
|
void quit(char*);
|
||||||
char* rcptto(char*);
|
char* rcptto(char*);
|
||||||
char *rewritezone(char *);
|
char* rewritezone(char *);
|
||||||
|
|
||||||
#define Retry "Retry, Temporary Failure"
|
#define Retry "Retry, Temporary Failure"
|
||||||
#define Giveup "Permanent Failure"
|
#define Giveup "Permanent Failure"
|
||||||
|
@ -151,6 +152,9 @@ main(int argc, char **argv)
|
||||||
case 's':
|
case 's':
|
||||||
trysecure = 1;
|
trysecure = 1;
|
||||||
break;
|
break;
|
||||||
|
case 't':
|
||||||
|
trysecure = 2;
|
||||||
|
break;
|
||||||
case 'u':
|
case 'u':
|
||||||
user = EARGF(usage());
|
user = EARGF(usage());
|
||||||
break;
|
break;
|
||||||
|
@ -217,7 +221,9 @@ main(int argc, char **argv)
|
||||||
/* 10 minutes to get through the initial handshake */
|
/* 10 minutes to get through the initial handshake */
|
||||||
atnotify(timeout, 1);
|
atnotify(timeout, 1);
|
||||||
alarm(10*alarmscale);
|
alarm(10*alarmscale);
|
||||||
if((rv = hello(hellodomain, 0)) != 0)
|
if(trysecure > 1 && (rv = wraptls()) != nil)
|
||||||
|
goto error;
|
||||||
|
if((rv = hello(hellodomain, trysecure > 1)) != 0)
|
||||||
goto error;
|
goto error;
|
||||||
alarm(10*alarmscale);
|
alarm(10*alarmscale);
|
||||||
if((rv = mailfrom(s_to_c(from))) != 0)
|
if((rv = mailfrom(s_to_c(from))) != 0)
|
||||||
|
@ -313,13 +319,8 @@ connect(char* net)
|
||||||
static char smtpthumbs[] = "/sys/lib/tls/smtp";
|
static char smtpthumbs[] = "/sys/lib/tls/smtp";
|
||||||
static char smtpexclthumbs[] = "/sys/lib/tls/smtp.exclude";
|
static char smtpexclthumbs[] = "/sys/lib/tls/smtp.exclude";
|
||||||
|
|
||||||
/*
|
|
||||||
* exchange names with remote host, attempt to
|
|
||||||
* enable encryption and optionally authenticate.
|
|
||||||
* not fatal if we can't.
|
|
||||||
*/
|
|
||||||
static char *
|
static char *
|
||||||
dotls(char *me)
|
wraptls(void)
|
||||||
{
|
{
|
||||||
TLSconn *c;
|
TLSconn *c;
|
||||||
Thumbprint *goodcerts;
|
Thumbprint *goodcerts;
|
||||||
|
@ -327,33 +328,27 @@ dotls(char *me)
|
||||||
int fd;
|
int fd;
|
||||||
uchar hash[SHA1dlen];
|
uchar hash[SHA1dlen];
|
||||||
|
|
||||||
c = mallocz(sizeof(*c), 1); /* Note: not freed on success */
|
c = mallocz(sizeof(*c), 1);
|
||||||
if (c == nil)
|
if (c == nil)
|
||||||
return Giveup;
|
return Giveup;
|
||||||
|
|
||||||
dBprint("STARTTLS\r\n");
|
|
||||||
if (getreply() != 2)
|
|
||||||
return Giveup;
|
|
||||||
|
|
||||||
fd = tlsClient(Bfildes(&bout), c);
|
fd = tlsClient(Bfildes(&bout), c);
|
||||||
if (fd < 0) {
|
if (fd < 0) {
|
||||||
syslog(0, "smtp", "tlsClient to %q: %r", ddomain);
|
syslog(0, "smtp", "tlsClient to %q: %r", ddomain);
|
||||||
|
free(c);
|
||||||
return Giveup;
|
return Giveup;
|
||||||
}
|
}
|
||||||
goodcerts = initThumbprints(smtpthumbs, smtpexclthumbs);
|
goodcerts = initThumbprints(smtpthumbs, smtpexclthumbs);
|
||||||
if (goodcerts == nil) {
|
if (goodcerts == nil) {
|
||||||
free(c);
|
|
||||||
close(fd);
|
|
||||||
syslog(0, "smtp", "bad thumbprints in %s", smtpthumbs);
|
syslog(0, "smtp", "bad thumbprints in %s", smtpthumbs);
|
||||||
|
close(fd);
|
||||||
|
free(c);
|
||||||
return Giveup; /* how to recover? TLS is started */
|
return Giveup; /* how to recover? TLS is started */
|
||||||
}
|
}
|
||||||
|
|
||||||
/* compute sha1 hash of remote's certificate, see if we know it */
|
/* compute sha1 hash of remote's certificate, see if we know it */
|
||||||
sha1(c->cert, c->certlen, hash, nil);
|
sha1(c->cert, c->certlen, hash, nil);
|
||||||
if (!okThumbprint(hash, goodcerts)) {
|
if (!okThumbprint(hash, goodcerts)) {
|
||||||
/* TODO? if not excluded, add hash to thumb list */
|
/* TODO? if not excluded, add hash to thumb list */
|
||||||
free(c);
|
|
||||||
close(fd);
|
|
||||||
h = malloc(2*sizeof hash + 1);
|
h = malloc(2*sizeof hash + 1);
|
||||||
if (h != nil) {
|
if (h != nil) {
|
||||||
enc16(h, 2*sizeof hash + 1, hash, sizeof hash);
|
enc16(h, 2*sizeof hash + 1, hash, sizeof hash);
|
||||||
|
@ -363,9 +358,12 @@ dotls(char *me)
|
||||||
h, ddomain);
|
h, ddomain);
|
||||||
free(h);
|
free(h);
|
||||||
}
|
}
|
||||||
|
close(fd);
|
||||||
|
free(c);
|
||||||
return Giveup; /* how to recover? TLS is started */
|
return Giveup; /* how to recover? TLS is started */
|
||||||
}
|
}
|
||||||
freeThumbprints(goodcerts);
|
freeThumbprints(goodcerts);
|
||||||
|
free(c);
|
||||||
Bterm(&bin);
|
Bterm(&bin);
|
||||||
Bterm(&bout);
|
Bterm(&bout);
|
||||||
|
|
||||||
|
@ -378,6 +376,27 @@ dotls(char *me)
|
||||||
Binit(&bout, fd, OWRITE);
|
Binit(&bout, fd, OWRITE);
|
||||||
|
|
||||||
syslog(0, "smtp", "started TLS to %q", ddomain);
|
syslog(0, "smtp", "started TLS to %q", ddomain);
|
||||||
|
return nil;
|
||||||
|
}
|
||||||
|
|
||||||
|
/*
|
||||||
|
* exchange names with remote host, attempt to
|
||||||
|
* enable encryption and optionally authenticate.
|
||||||
|
* not fatal if we can't.
|
||||||
|
*/
|
||||||
|
static char *
|
||||||
|
dotls(char *me)
|
||||||
|
{
|
||||||
|
char *err;
|
||||||
|
|
||||||
|
dBprint("STARTTLS\r\n");
|
||||||
|
if (getreply() != 2)
|
||||||
|
return Giveup;
|
||||||
|
|
||||||
|
err = wraptls();
|
||||||
|
if (err != nil)
|
||||||
|
return err;
|
||||||
|
|
||||||
return(hello(me, 1));
|
return(hello(me, 1));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
Loading…
Reference in a new issue