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