Subversion Repositories planix.SVN

Rev

Rev 2 | Details | Compare with Previous | Last modification | View Log | RSS feed

Rev Author Line No. Line
2 - 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
}