xref: /plan9/sys/src/cmd/unix/drawterm/libc/pushtls.c (revision 1a4050f5b2ddf426a278e3233ccd7b6bcb0639b8)
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
finished(int hand,int isclient)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
pushtls(int fd,char * hashalg,char * encalg,int isclient,char * secret,char * dir)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