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