Subversion Repositories planix.SVN

Rev

Rev 2 | Details | Compare with Previous | Last modification | View Log | RSS feed

Rev Author Line No. Line
2 - 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
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
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
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
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
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
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
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
}