100 lines
2.0 KiB
C
100 lines
2.0 KiB
C
#include <u.h>
|
|
#include <libc.h>
|
|
#include <auth.h>
|
|
#include <mp.h>
|
|
#include <libsec.h>
|
|
|
|
enum {
|
|
TLSFinishedLen = 12,
|
|
HFinished = 20,
|
|
};
|
|
|
|
static int
|
|
finished(int hand, int isclient)
|
|
{
|
|
int i, n;
|
|
uchar buf[500], buf2[500];
|
|
|
|
buf[0] = HFinished;
|
|
buf[1] = TLSFinishedLen>>16;
|
|
buf[2] = TLSFinishedLen>>8;
|
|
buf[3] = TLSFinishedLen;
|
|
n = TLSFinishedLen+4;
|
|
|
|
for(i=0; i<2; i++){
|
|
if(i==0)
|
|
memmove(buf+4, "client finished", TLSFinishedLen);
|
|
else
|
|
memmove(buf+4, "server finished", TLSFinishedLen);
|
|
if(isclient == 1-i){
|
|
if(write(hand, buf, n) != n)
|
|
return -1;
|
|
}else{
|
|
if(readn(hand, buf2, n) != n || memcmp(buf,buf2,n) != 0)
|
|
return -1;
|
|
}
|
|
}
|
|
return 1;
|
|
}
|
|
|
|
|
|
// given a plain fd and secrets established beforehand, return encrypted connection
|
|
int
|
|
pushtls(int fd, char *hashalg, char *encalg, int isclient, char *secret, char *dir)
|
|
{
|
|
char buf[8];
|
|
char dname[64];
|
|
int n, data, ctl, hand;
|
|
|
|
// open a new filter; get ctl fd
|
|
data = hand = -1;
|
|
// /net/tls uses decimal file descriptors to name channels, hence a
|
|
// user-level file server can't stand in for #a; may as well hard-code it.
|
|
ctl = open("#a/tls/clone", ORDWR);
|
|
if(ctl < 0)
|
|
goto error;
|
|
n = read(ctl, buf, sizeof(buf)-1);
|
|
if(n < 0)
|
|
goto error;
|
|
buf[n] = 0;
|
|
if(dir)
|
|
sprint(dir, "#a/tls/%s", buf);
|
|
|
|
// get application fd
|
|
sprint(dname, "#a/tls/%s/data", buf);
|
|
data = open(dname, ORDWR);
|
|
if(data < 0)
|
|
goto error;
|
|
|
|
// get handshake fd
|
|
sprint(dname, "#a/tls/%s/hand", buf);
|
|
hand = open(dname, ORDWR);
|
|
if(hand < 0)
|
|
goto error;
|
|
|
|
// speak a minimal handshake
|
|
if(fprint(ctl, "fd %d 0x301", fd) < 0 ||
|
|
fprint(ctl, "version 0x301") < 0 ||
|
|
fprint(ctl, "secret %s %s %d %s", hashalg, encalg, isclient, secret) < 0 ||
|
|
fprint(ctl, "changecipher") < 0 ||
|
|
finished(hand, isclient) < 0 ||
|
|
fprint(ctl, "opened") < 0){
|
|
close(hand);
|
|
hand = -1;
|
|
goto error;
|
|
}
|
|
close(ctl);
|
|
close(hand);
|
|
close(fd);
|
|
return data;
|
|
|
|
error:
|
|
if(data>=0)
|
|
close(data);
|
|
if(ctl>=0)
|
|
close(ctl);
|
|
if(hand>=0)
|
|
close(hand);
|
|
return -1;
|
|
}
|