1 #include <u.h> 2 #include <libc.h> 3 #include <auth.h> 4 #include <mp.h> 5 #include <libsec.h> 6 7 enum { 8 TLSFinishedLen = 12, 9 HFinished = 20, 10 }; 11 12 static int 13 finished(int hand, int isclient) 14 { 15 int i, n; 16 uchar buf[500], buf2[500]; 17 18 buf[0] = HFinished; 19 buf[1] = TLSFinishedLen>>16; 20 buf[2] = TLSFinishedLen>>8; 21 buf[3] = TLSFinishedLen; 22 n = TLSFinishedLen+4; 23 24 for(i=0; i<2; i++){ 25 if(i==0) 26 memmove(buf+4, "client finished", TLSFinishedLen); 27 else 28 memmove(buf+4, "server finished", TLSFinishedLen); 29 if(isclient == 1-i){ 30 if(write(hand, buf, n) != n) 31 return -1; 32 }else{ 33 if(readn(hand, buf2, n) != n || memcmp(buf,buf2,n) != 0) 34 return -1; 35 } 36 } 37 return 1; 38 } 39 40 41 // given a plain fd and secrets established beforehand, return encrypted connection 42 int 43 pushtls(int fd, char *hashalg, char *encalg, int isclient, char *secret, char *dir) 44 { 45 char buf[8]; 46 char dname[64]; 47 int n, data, ctl, hand; 48 49 // open a new filter; get ctl fd 50 data = hand = -1; 51 // /net/tls uses decimal file descriptors to name channels, hence a 52 // user-level file server can't stand in for #a; may as well hard-code it. 53 ctl = open("#a/tls/clone", ORDWR); 54 if(ctl < 0) 55 goto error; 56 n = read(ctl, buf, sizeof(buf)-1); 57 if(n < 0) 58 goto error; 59 buf[n] = 0; 60 if(dir) 61 sprint(dir, "#a/tls/%s", buf); 62 63 // get application fd 64 sprint(dname, "#a/tls/%s/data", buf); 65 data = open(dname, ORDWR); 66 if(data < 0) 67 goto error; 68 69 // get handshake fd 70 sprint(dname, "#a/tls/%s/hand", buf); 71 hand = open(dname, ORDWR); 72 if(hand < 0) 73 goto error; 74 75 // speak a minimal handshake 76 if(fprint(ctl, "fd %d 0x301", fd) < 0 || 77 fprint(ctl, "version 0x301") < 0 || 78 fprint(ctl, "secret %s %s %d %s", hashalg, encalg, isclient, secret) < 0 || 79 fprint(ctl, "changecipher") < 0 || 80 finished(hand, isclient) < 0 || 81 fprint(ctl, "opened") < 0){ 82 close(hand); 83 hand = -1; 84 goto error; 85 } 86 close(ctl); 87 close(hand); 88 close(fd); 89 return data; 90 91 error: 92 if(data>=0) 93 close(data); 94 if(ctl>=0) 95 close(ctl); 96 if(hand>=0) 97 close(hand); 98 return -1; 99 } 100