xref: /plan9/sys/src/cmd/tlssrv.c (revision 3a32e1046e411eba43a878ebe72e5b0033495136)
1 #include <u.h>
2 #include <libc.h>
3 #include <bio.h>
4 #include <mp.h>
5 #include <libsec.h>
6 
7 enum{ BufSize = 8192 };
8 
9 char *remotesys, *logfile;
10 int debug, p[2];
11 
12 void
death(void *,char *)13 death(void *, char *)
14 {
15 	int pid;
16 
17 	close(0);
18 	close(1);
19 	close(p[1]);
20 	pid = getpid();
21 	postnote(PNGROUP, pid, "die");
22 	postnote(PNGROUP, pid, "die");
23 	postnote(PNGROUP, pid, "die");
24 	_exits(0);
25 }
26 
27 static void
dump(int fd,uchar * buf,int n,char * label)28 dump(int fd, uchar *buf, int n, char *label)
29 {
30 	Biobuf bout;
31 	int i;
32 
33 	Binit(&bout, fd, OWRITE);
34 	Bprint(&bout, "%s<%d>: ", label, n);
35 	if(n > 64)
36 		n = 64;
37 	for(i = 0; i < n; i++)
38 		Bprint(&bout, "%2.2x ", buf[i]);
39 	Bprint(&bout, "\n");
40 	Bterm(&bout);
41 }
42 
43 static void
xfer(int from,int to,int cfd,char * label)44 xfer(int from, int to, int cfd, char *label)
45 {
46 	uchar buf[BufSize];
47 	int n;
48 
49 	if(fork() == 0)
50 		return;
51 
52 	close(cfd);
53 	for(;;){
54 		n = read(from, buf, sizeof(buf));
55 		if(n <= 0){
56 			fprint(2, "%s EOF\n", label);
57 			close(to);
58 			close(from);
59 			death(nil, nil);
60 		}
61 		dump(2, buf, n, label);
62 		n = write(to, buf, n);
63 		if(n < 0){
64 			fprint(2, "%s write err\n", label);
65 			close(to);
66 			close(from);
67 			death(nil, nil);
68 		}
69 	}
70 }
71 
72 static int
dumper(int fd)73 dumper(int fd)
74 {
75 	int p[2];
76 
77 	if(pipe(p) < 0)
78 		sysfatal("can't make pipe: %r");
79 
80 	xfer(fd, p[0], p[1], "read");
81 	xfer(p[0], fd, p[1], "write");
82 	close(p[0]);
83 	return p[1];
84 }
85 
86 static int
reporter(char * fmt,...)87 reporter(char *fmt, ...)
88 {
89 	va_list ap;
90 	char buf[2000];
91 
92 	va_start(ap, fmt);
93 	if(logfile){
94 		vsnprint(buf, sizeof buf, fmt, ap);
95 		syslog(0, logfile, "%s tls reports %s", remotesys, buf);
96 	}else{
97 		fprint(2, "%s: %s tls reports ", argv0, remotesys);
98 		vfprint(2, fmt, ap);
99 		fprint(2, "\n");
100 	}
101 	va_end(ap);
102 	return 0;
103 }
104 
105 void
usage(void)106 usage(void)
107 {
108 	fprint(2, "usage: tlssrv -c cert [-D] [-l logfile] [-r remotesys] [cmd args...]\n");
109 	fprint(2, "  after  auth/secretpem key.pem > /mnt/factotum/ctl\n");
110 	exits("usage");
111 }
112 
113 void
main(int argc,char * argv[])114 main(int argc, char *argv[])
115 {
116 	TLSconn *conn;
117 	uchar buf[BufSize];
118 	char *cert;
119 	int n, fd, clearfd;
120 
121 	debug = 0;
122 	remotesys = nil;
123 	cert = nil;
124 	logfile = nil;
125 	ARGBEGIN{
126 	case 'D':
127 		debug++;
128 		break;
129 	case 'c':
130 		cert = EARGF(usage());
131 		break;
132 	case 'l':
133 		logfile = EARGF(usage());
134 		break;
135 	case 'r':
136 		remotesys = EARGF(usage());
137 		break;
138 	default:
139 		usage();
140 	}ARGEND
141 
142 	if(cert == nil)
143 		sysfatal("no certificate specified");
144 	if(remotesys == nil)
145 		remotesys = "";
146 	conn = (TLSconn*)mallocz(sizeof *conn, 1);
147 	if(conn == nil)
148 		sysfatal("out of memory");
149 	conn->chain = readcertchain(cert);
150 	if (conn->chain == nil)
151 		sysfatal("can't read certificate");
152 	conn->cert = conn->chain->pem;
153 	conn->certlen = conn->chain->pemlen;
154 	conn->chain = conn->chain->next;
155 	if(debug)
156 		conn->trace = reporter;
157 
158 	clearfd = 0;
159 	fd = 1;
160 	if(debug > 1)
161 		fd = dumper(fd);
162 	fd = tlsServer(fd, conn);
163 	if(fd < 0){
164 		reporter("failed: %r");
165 		exits(0);
166 	}
167 	reporter("open");
168 
169 	if(argc > 0){
170 		if(pipe(p) < 0)
171 			exits("pipe");
172 		switch(fork()){
173 		case 0:
174 			close(fd);
175 			dup(p[0], 0);
176 			dup(p[0], 1);
177 			close(p[1]);
178 			close(p[0]);
179 			exec(argv[0], argv);
180 			reporter("can't exec %s: %r", argv[0]);
181 			_exits("exec");
182 		case -1:
183 			exits("fork");
184 		default:
185 			close(p[0]);
186 			clearfd = p[1];
187 			break;
188 		}
189 	}
190 
191 	rfork(RFNOTEG);
192 	notify(death);
193 	switch(rfork(RFPROC)){
194 	case -1:
195 		sysfatal("can't fork");
196 	case 0:
197 		for(;;){
198 			n = read(clearfd, buf, BufSize);
199 			if(n <= 0)
200 				break;
201 			if(write(fd, buf, n) != n)
202 				break;
203 		}
204 		break;
205 	default:
206 		for(;;){
207 			n = read(fd, buf, BufSize);
208 			if(n <= 0)
209 				break;
210 			if(write(clearfd, buf, n) != n)
211 				break;
212 		}
213 		break;
214 	}
215 	death(nil, nil);
216 }
217