upas/fs: fix memory leaks in tls code, handle tls in a common wraptls() function
This commit is contained in:
parent
efddf48500
commit
cb1dc365c2
5 changed files with 59 additions and 121 deletions
|
@ -216,6 +216,8 @@ char* delmessages(int, char**);
|
|||
char *flagmessages(int, char**);
|
||||
void digestmessage(Mailbox*, Message*);
|
||||
|
||||
int wraptls(int);
|
||||
|
||||
void eprint(char*, ...);
|
||||
void iprint(char *, ...);
|
||||
int newid(void);
|
||||
|
|
|
@ -60,8 +60,6 @@ struct Imap {
|
|||
int nuid;
|
||||
int muid;
|
||||
|
||||
Thumbprint *thumb;
|
||||
|
||||
/* open network connection */
|
||||
Biobuf bin;
|
||||
Biobuf bout;
|
||||
|
@ -760,44 +758,6 @@ imaperrstr(char *host, char *port)
|
|||
return buf;
|
||||
}
|
||||
|
||||
static int
|
||||
starttls(Imap *imap, TLSconn *tls)
|
||||
{
|
||||
char buf[Pathlen];
|
||||
uchar digest[SHA1dlen];
|
||||
int sfd, fd;
|
||||
|
||||
memset(tls, 0, sizeof *tls);
|
||||
sfd = tlsClient(imap->fd, tls);
|
||||
if(sfd < 0){
|
||||
werrstr("tlsClient: %r");
|
||||
return -1;
|
||||
}
|
||||
if(tls->cert == nil || tls->certlen <= 0){
|
||||
close(sfd);
|
||||
werrstr("server did not provide TLS certificate");
|
||||
return -1;
|
||||
}
|
||||
sha1(tls->cert, tls->certlen, digest, nil);
|
||||
if(!imap->thumb || !okThumbprint(digest, imap->thumb)){
|
||||
close(sfd);
|
||||
werrstr("server certificate %.*H not recognized",
|
||||
SHA1dlen, digest);
|
||||
return -1;
|
||||
}
|
||||
close(imap->fd);
|
||||
imap->fd = sfd;
|
||||
|
||||
if(imap->flags & Fdebug){
|
||||
snprint(buf, sizeof buf, "%s/ctl", tls->dir);
|
||||
fd = open(buf, OWRITE);
|
||||
fprint(fd, "debug");
|
||||
close(fd);
|
||||
}
|
||||
|
||||
return 1;
|
||||
}
|
||||
|
||||
static void
|
||||
imap4disconnect(Imap *imap)
|
||||
{
|
||||
|
@ -806,8 +766,10 @@ imap4disconnect(Imap *imap)
|
|||
Bterm(&imap->bout);
|
||||
imap->binit = 0;
|
||||
}
|
||||
close(imap->fd);
|
||||
imap->fd = -1;
|
||||
if(imap->fd >= 0){
|
||||
close(imap->fd);
|
||||
imap->fd = -1;
|
||||
}
|
||||
}
|
||||
|
||||
char*
|
||||
|
@ -827,7 +789,6 @@ static char*
|
|||
imap4dial(Imap *imap)
|
||||
{
|
||||
char *err, *port;
|
||||
TLSconn conn;
|
||||
|
||||
if(imap->fd >= 0){
|
||||
imap4cmd(imap, "noop");
|
||||
|
@ -841,9 +802,8 @@ imap4dial(Imap *imap)
|
|||
port = "imap";
|
||||
if((imap->fd = dial(netmkaddr(imap->host, "net", port), 0, 0, 0)) < 0)
|
||||
return imaperrstr(imap->host, port);
|
||||
if(imap->flags & Fssl && starttls(imap, &conn) == -1){
|
||||
if(imap->flags & Fssl && (imap->fd = wraptls(imap->fd)) < 0){
|
||||
err = imaperrstr(imap->host, port);
|
||||
free(conn.cert);
|
||||
imap4disconnect(imap);
|
||||
return err;
|
||||
}
|
||||
|
@ -1074,7 +1034,6 @@ out:
|
|||
static char*
|
||||
imap4ctl(Mailbox *mb, int argc, char **argv)
|
||||
{
|
||||
char *a, *b;
|
||||
Imap *imap;
|
||||
|
||||
imap = mb->aux;
|
||||
|
@ -1085,26 +1044,6 @@ imap4ctl(Mailbox *mb, int argc, char **argv)
|
|||
imap->flags ^= Fdebug;
|
||||
return nil;
|
||||
}
|
||||
if(strcmp(argv[0], "thumbprint") == 0){
|
||||
if(imap->thumb){
|
||||
freeThumbprints(imap->thumb);
|
||||
imap->thumb = 0;
|
||||
}
|
||||
a = "/sys/lib/tls/mail";
|
||||
b = "/sys/lib/tls/mail.exclude";
|
||||
switch(argc){
|
||||
default:
|
||||
return Eimap4ctl;
|
||||
case 4:
|
||||
b = argv[2];
|
||||
case 3:
|
||||
a = argv[1];
|
||||
case 2:
|
||||
break;
|
||||
}
|
||||
imap->thumb = initThumbprints(a, b);
|
||||
return nil;
|
||||
}
|
||||
if(argc == 2 && strcmp(argv[0], "uid") == 0){
|
||||
uvlong l;
|
||||
Message *m;
|
||||
|
@ -1253,9 +1192,6 @@ imap4mbox(Mailbox *mb, char *path)
|
|||
else
|
||||
imap->mbox = strdup(f[4]);
|
||||
mkmbox(imap, mb->path, mb->path + sizeof mb->path);
|
||||
if(imap->flags & Fssl)
|
||||
imap->thumb = initThumbprints("/sys/lib/tls/mail", "/sys/lib/tls/mail.exclude");
|
||||
|
||||
mb->aux = imap;
|
||||
mb->sync = imap4sync;
|
||||
mb->close = imap4close;
|
||||
|
|
|
@ -18,6 +18,7 @@ OFILES=\
|
|||
remove.$O\
|
||||
rename.$O\
|
||||
strtotm.$O\
|
||||
tls.$O\
|
||||
|
||||
LIB=../common/libcommon.a$O\
|
||||
|
||||
|
|
|
@ -32,7 +32,6 @@ struct Pop {
|
|||
Biobuf bout;
|
||||
int fd;
|
||||
char *lastline; /* from Brdstr */
|
||||
Thumbprint *thumb;
|
||||
};
|
||||
|
||||
static int
|
||||
|
@ -120,38 +119,6 @@ pop3log(char *fmt, ...)
|
|||
return 0;
|
||||
}
|
||||
|
||||
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)){
|
||||
close(fd);
|
||||
free(conn.cert);
|
||||
eprint("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;
|
||||
}
|
||||
|
||||
/*
|
||||
* get capability list, possibly start tls
|
||||
*/
|
||||
|
@ -182,8 +149,13 @@ pop3capa(Pop *pop)
|
|||
pop3cmd(pop, "STLS");
|
||||
if(!isokay(s = pop3resp(pop)))
|
||||
return s;
|
||||
if((s = pop3pushtls(pop)) != nil)
|
||||
return s;
|
||||
Bterm(&pop->bin);
|
||||
Bterm(&pop->bout);
|
||||
if((pop->fd = wraptls(pop->fd)) < 0)
|
||||
return geterrstr();
|
||||
pop->encrypted = 1;
|
||||
Binit(&pop->bin, pop->fd, OREAD);
|
||||
Binit(&pop->bout, pop->fd, OWRITE);
|
||||
}
|
||||
return nil;
|
||||
}
|
||||
|
@ -265,15 +237,11 @@ pop3dial(Pop *pop)
|
|||
|
||||
if((pop->fd = dial(netmkaddr(pop->host, "net", pop->needssl ? "pop3s" : "pop3"), 0, 0, 0)) < 0)
|
||||
return geterrstr();
|
||||
|
||||
if(pop->needssl){
|
||||
if((err = pop3pushtls(pop)) != nil)
|
||||
return err;
|
||||
}else{
|
||||
Binit(&pop->bin, pop->fd, OREAD);
|
||||
Binit(&pop->bout, pop->fd, OWRITE);
|
||||
}
|
||||
|
||||
if(pop->needssl && (pop->fd = wraptls(pop->fd)) < 0)
|
||||
return geterrstr();
|
||||
pop->encrypted = pop->needssl;
|
||||
Binit(&pop->bin, pop->fd, OREAD);
|
||||
Binit(&pop->bout, pop->fd, OWRITE);
|
||||
if(err = pop3login(pop)) {
|
||||
close(pop->fd);
|
||||
return err;
|
||||
|
@ -607,11 +575,6 @@ pop3ctl(Mailbox *mb, int argc, char **argv)
|
|||
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;
|
||||
|
@ -693,8 +656,6 @@ pop3mbox(Mailbox *mb, char *path)
|
|||
pop->needtls = poptls || apoptls;
|
||||
pop->refreshtime = 60;
|
||||
pop->notls = popnotls || apopnotls;
|
||||
pop->thumb = initThumbprints("/sys/lib/tls/mail", "/sys/lib/tls/mail.exclude");
|
||||
|
||||
mkmbox(pop, mb->path, mb->path + sizeof mb->path);
|
||||
mb->aux = pop;
|
||||
mb->sync = pop3sync;
|
||||
|
@ -704,4 +665,3 @@ pop3mbox(Mailbox *mb, char *path)
|
|||
mb->addfrom = 1;
|
||||
return nil;
|
||||
}
|
||||
|
||||
|
|
39
sys/src/cmd/upas/fs/tls.c
Normal file
39
sys/src/cmd/upas/fs/tls.c
Normal file
|
@ -0,0 +1,39 @@
|
|||
#include "common.h"
|
||||
#include <libsec.h>
|
||||
#include <auth.h>
|
||||
#include "dat.h"
|
||||
|
||||
int
|
||||
wraptls(int ofd)
|
||||
{
|
||||
uchar digest[SHA1dlen];
|
||||
Thumbprint *thumb;
|
||||
TLSconn conn;
|
||||
int fd;
|
||||
|
||||
memset(&conn, 0, sizeof conn);
|
||||
fd = tlsClient(ofd, &conn);
|
||||
if(fd < 0){
|
||||
close(ofd);
|
||||
return -1;
|
||||
}
|
||||
thumb = initThumbprints("/sys/lib/tls/mail", "/sys/lib/tls/mail.exclude");
|
||||
if(thumb != nil){
|
||||
if(conn.cert == nil || conn.certlen <= 0){
|
||||
werrstr("server did not provide TLS certificate");
|
||||
goto Err;
|
||||
}
|
||||
sha1(conn.cert, conn.certlen, digest, nil);
|
||||
if(!okThumbprint(digest, thumb)){
|
||||
werrstr("server certificate %.*H not recognized",
|
||||
SHA1dlen, digest);
|
||||
Err:
|
||||
close(fd);
|
||||
fd = -1;
|
||||
}
|
||||
freeThumbprints(thumb);
|
||||
}
|
||||
free(conn.cert);
|
||||
free(conn.sessionID);
|
||||
return fd;
|
||||
}
|
Loading…
Reference in a new issue