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