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