1*3ff48bf5SDavid du Colombier #include <u.h>
2*3ff48bf5SDavid du Colombier #include <libc.h>
3*3ff48bf5SDavid du Colombier #include <mp.h>
4*3ff48bf5SDavid du Colombier #include <libsec.h>
5*3ff48bf5SDavid du Colombier
6*3ff48bf5SDavid du Colombier void
usage(void)7*3ff48bf5SDavid du Colombier usage(void)
8*3ff48bf5SDavid du Colombier {
9*3ff48bf5SDavid du Colombier fprint(2, "usage: tlsclient [-t /sys/lib/tls/xxx] [-x /sys/lib/tls/xxx.exclude] dialstring\n");
10*3ff48bf5SDavid du Colombier exits("usage");
11*3ff48bf5SDavid du Colombier }
12*3ff48bf5SDavid du Colombier
13*3ff48bf5SDavid du Colombier void
xfer(int from,int to)14*3ff48bf5SDavid du Colombier xfer(int from, int to)
15*3ff48bf5SDavid du Colombier {
16*3ff48bf5SDavid du Colombier char buf[12*1024];
17*3ff48bf5SDavid du Colombier int n;
18*3ff48bf5SDavid du Colombier
19*3ff48bf5SDavid du Colombier while((n = read(from, buf, sizeof buf)) > 0)
20*3ff48bf5SDavid du Colombier if(write(to, buf, n) < 0)
21*3ff48bf5SDavid du Colombier break;
22*3ff48bf5SDavid du Colombier }
23*3ff48bf5SDavid du Colombier
24*3ff48bf5SDavid du Colombier void
main(int argc,char ** argv)25*3ff48bf5SDavid du Colombier main(int argc, char **argv)
26*3ff48bf5SDavid du Colombier {
27*3ff48bf5SDavid du Colombier int fd, netfd;
28*3ff48bf5SDavid du Colombier uchar digest[20];
29*3ff48bf5SDavid du Colombier TLSconn conn;
30*3ff48bf5SDavid du Colombier char *addr, *file, *filex;
31*3ff48bf5SDavid du Colombier Thumbprint *thumb;
32*3ff48bf5SDavid du Colombier
33*3ff48bf5SDavid du Colombier file = nil;
34*3ff48bf5SDavid du Colombier filex = nil;
35*3ff48bf5SDavid du Colombier thumb = nil;
36*3ff48bf5SDavid du Colombier ARGBEGIN{
37*3ff48bf5SDavid du Colombier case 't':
38*3ff48bf5SDavid du Colombier file = EARGF(usage());
39*3ff48bf5SDavid du Colombier break;
40*3ff48bf5SDavid du Colombier case 'x':
41*3ff48bf5SDavid du Colombier filex = EARGF(usage());
42*3ff48bf5SDavid du Colombier break;
43*3ff48bf5SDavid du Colombier default:
44*3ff48bf5SDavid du Colombier usage();
45*3ff48bf5SDavid du Colombier }ARGEND
46*3ff48bf5SDavid du Colombier
47*3ff48bf5SDavid du Colombier if(argc != 1)
48*3ff48bf5SDavid du Colombier usage();
49*3ff48bf5SDavid du Colombier
50*3ff48bf5SDavid du Colombier if(filex && !file)
51*3ff48bf5SDavid du Colombier sysfatal("specifying -x without -t is useless");
52*3ff48bf5SDavid du Colombier if(file){
53*3ff48bf5SDavid du Colombier thumb = initThumbprints(file, filex);
54*3ff48bf5SDavid du Colombier if(thumb == nil)
55*3ff48bf5SDavid du Colombier sysfatal("initThumbprints: %r");
56*3ff48bf5SDavid du Colombier }
57*3ff48bf5SDavid du Colombier
58*3ff48bf5SDavid du Colombier addr = argv[0];
59*3ff48bf5SDavid du Colombier if((netfd = dial(addr, 0, 0, 0)) < 0)
60*3ff48bf5SDavid du Colombier sysfatal("dial %s: %r", addr);
61*3ff48bf5SDavid du Colombier
62*3ff48bf5SDavid du Colombier memset(&conn, 0, sizeof conn);
63*3ff48bf5SDavid du Colombier fd = tlsClient(netfd, &conn);
64*3ff48bf5SDavid du Colombier if(fd < 0)
65*3ff48bf5SDavid du Colombier sysfatal("tlsclient: %r");
66*3ff48bf5SDavid du Colombier if(thumb){
67*3ff48bf5SDavid du Colombier if(conn.cert==nil || conn.certlen<=0)
68*3ff48bf5SDavid du Colombier sysfatal("server did not provide TLS certificate");
69*3ff48bf5SDavid du Colombier sha1(conn.cert, conn.certlen, digest, nil);
70*3ff48bf5SDavid du Colombier if(!okThumbprint(digest, thumb)){
71*3ff48bf5SDavid du Colombier fmtinstall('H', encodefmt);
72*3ff48bf5SDavid du Colombier sysfatal("server certificate %.*H not recognized", SHA1dlen, digest);
73*3ff48bf5SDavid du Colombier }
74*3ff48bf5SDavid du Colombier }
75*3ff48bf5SDavid du Colombier free(conn.cert);
76*3ff48bf5SDavid du Colombier close(netfd);
77*3ff48bf5SDavid du Colombier
78*3ff48bf5SDavid du Colombier rfork(RFNOTEG);
79*3ff48bf5SDavid du Colombier switch(fork()){
80*3ff48bf5SDavid du Colombier case -1:
81*3ff48bf5SDavid du Colombier fprint(2, "%s: fork: %r\n", argv0);
82*3ff48bf5SDavid du Colombier exits("dial");
83*3ff48bf5SDavid du Colombier case 0:
84*3ff48bf5SDavid du Colombier xfer(0, fd);
85*3ff48bf5SDavid du Colombier break;
86*3ff48bf5SDavid du Colombier default:
87*3ff48bf5SDavid du Colombier xfer(fd, 1);
88*3ff48bf5SDavid du Colombier break;
89*3ff48bf5SDavid du Colombier }
90*3ff48bf5SDavid du Colombier postnote(PNGROUP, getpid(), "die yankee pig dog");
91*3ff48bf5SDavid du Colombier exits(0);
92*3ff48bf5SDavid du Colombier }
93