Subversion Repositories planix.SVN

Rev

Details | Last modification | View Log | RSS feed

Rev Author Line No. Line
2 - 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[64];
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);
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
	sprint(dname, "#a/tls/%s/data", buf);
64
	data = open(dname, ORDWR);
65
	if(data < 0)
66
		goto error;
67
 
68
	// get handshake fd
69
	sprint(dname, "#a/tls/%s/hand", buf);
70
	hand = open(dname, ORDWR);
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
}