xref: /plan9/sys/src/cmd/tlsclient.c (revision 3ff48bf5ed603850fcd251ddf13025d23d693782)
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