2011-03-30 12:46:40 +00:00
|
|
|
#include <u.h>
|
|
|
|
#include <libc.h>
|
|
|
|
#include <bio.h>
|
|
|
|
#include <mp.h>
|
|
|
|
#include <libsec.h>
|
|
|
|
|
|
|
|
enum{ BufSize = 8192 };
|
|
|
|
|
|
|
|
char *remotesys, *logfile;
|
|
|
|
int debug, p[2];
|
|
|
|
|
|
|
|
void
|
|
|
|
death(void *, char *)
|
|
|
|
{
|
|
|
|
int pid;
|
|
|
|
|
|
|
|
close(0);
|
|
|
|
close(1);
|
|
|
|
close(p[1]);
|
|
|
|
pid = getpid();
|
|
|
|
postnote(PNGROUP, pid, "die");
|
|
|
|
postnote(PNGROUP, pid, "die");
|
|
|
|
postnote(PNGROUP, pid, "die");
|
|
|
|
_exits(0);
|
|
|
|
}
|
|
|
|
|
|
|
|
static void
|
|
|
|
dump(int fd, uchar *buf, int n, char *label)
|
|
|
|
{
|
|
|
|
Biobuf bout;
|
|
|
|
int i;
|
|
|
|
|
|
|
|
Binit(&bout, fd, OWRITE);
|
|
|
|
Bprint(&bout, "%s<%d>: ", label, n);
|
|
|
|
if(n > 64)
|
|
|
|
n = 64;
|
|
|
|
for(i = 0; i < n; i++)
|
|
|
|
Bprint(&bout, "%2.2x ", buf[i]);
|
|
|
|
Bprint(&bout, "\n");
|
|
|
|
Bterm(&bout);
|
|
|
|
}
|
|
|
|
|
|
|
|
static void
|
|
|
|
xfer(int from, int to, int cfd, char *label)
|
|
|
|
{
|
|
|
|
uchar buf[BufSize];
|
|
|
|
int n;
|
|
|
|
|
|
|
|
if(fork() == 0)
|
|
|
|
return;
|
|
|
|
|
|
|
|
close(cfd);
|
|
|
|
for(;;){
|
|
|
|
n = read(from, buf, sizeof(buf));
|
|
|
|
if(n <= 0){
|
|
|
|
fprint(2, "%s EOF\n", label);
|
|
|
|
close(to);
|
|
|
|
close(from);
|
|
|
|
death(nil, nil);
|
|
|
|
}
|
|
|
|
dump(2, buf, n, label);
|
|
|
|
n = write(to, buf, n);
|
|
|
|
if(n < 0){
|
|
|
|
fprint(2, "%s write err\n", label);
|
|
|
|
close(to);
|
|
|
|
close(from);
|
|
|
|
death(nil, nil);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
static int
|
|
|
|
dumper(int fd)
|
|
|
|
{
|
|
|
|
int p[2];
|
|
|
|
|
|
|
|
if(pipe(p) < 0)
|
|
|
|
sysfatal("can't make pipe: %r");
|
|
|
|
|
|
|
|
xfer(fd, p[0], p[1], "read");
|
|
|
|
xfer(p[0], fd, p[1], "write");
|
|
|
|
close(p[0]);
|
|
|
|
return p[1];
|
|
|
|
}
|
|
|
|
|
|
|
|
static int
|
|
|
|
reporter(char *fmt, ...)
|
|
|
|
{
|
|
|
|
va_list ap;
|
|
|
|
char buf[2000];
|
|
|
|
|
|
|
|
va_start(ap, fmt);
|
|
|
|
if(logfile){
|
|
|
|
vsnprint(buf, sizeof buf, fmt, ap);
|
|
|
|
syslog(0, logfile, "%s tls reports %s", remotesys, buf);
|
|
|
|
}else{
|
|
|
|
fprint(2, "%s: %s tls reports ", argv0, remotesys);
|
|
|
|
vfprint(2, fmt, ap);
|
|
|
|
fprint(2, "\n");
|
|
|
|
}
|
|
|
|
va_end(ap);
|
|
|
|
return 0;
|
|
|
|
}
|
|
|
|
|
|
|
|
void
|
|
|
|
usage(void)
|
|
|
|
{
|
|
|
|
fprint(2, "usage: tlssrv -c cert [-D] [-l logfile] [-r remotesys] [cmd args...]\n");
|
|
|
|
fprint(2, " after auth/secretpem key.pem > /mnt/factotum/ctl\n");
|
|
|
|
exits("usage");
|
|
|
|
}
|
|
|
|
|
|
|
|
void
|
|
|
|
main(int argc, char *argv[])
|
|
|
|
{
|
|
|
|
TLSconn *conn;
|
|
|
|
uchar buf[BufSize];
|
|
|
|
char *cert;
|
|
|
|
int n, fd, clearfd;
|
|
|
|
|
|
|
|
debug = 0;
|
|
|
|
remotesys = nil;
|
|
|
|
cert = nil;
|
|
|
|
logfile = nil;
|
|
|
|
ARGBEGIN{
|
|
|
|
case 'D':
|
|
|
|
debug++;
|
|
|
|
break;
|
|
|
|
case 'c':
|
|
|
|
cert = EARGF(usage());
|
|
|
|
break;
|
|
|
|
case 'l':
|
|
|
|
logfile = EARGF(usage());
|
|
|
|
break;
|
|
|
|
case 'r':
|
|
|
|
remotesys = EARGF(usage());
|
|
|
|
break;
|
|
|
|
default:
|
|
|
|
usage();
|
|
|
|
}ARGEND
|
|
|
|
|
|
|
|
if(cert == nil)
|
|
|
|
sysfatal("no certificate specified");
|
|
|
|
if(remotesys == nil)
|
|
|
|
remotesys = "";
|
|
|
|
conn = (TLSconn*)mallocz(sizeof *conn, 1);
|
|
|
|
if(conn == nil)
|
|
|
|
sysfatal("out of memory");
|
|
|
|
conn->chain = readcertchain(cert);
|
2013-09-14 17:19:08 +00:00
|
|
|
if(conn->chain == nil)
|
2011-03-30 12:46:40 +00:00
|
|
|
sysfatal("can't read certificate");
|
|
|
|
conn->cert = conn->chain->pem;
|
|
|
|
conn->certlen = conn->chain->pemlen;
|
|
|
|
conn->chain = conn->chain->next;
|
|
|
|
if(debug)
|
|
|
|
conn->trace = reporter;
|
|
|
|
|
|
|
|
clearfd = 0;
|
|
|
|
fd = 1;
|
|
|
|
if(debug > 1)
|
|
|
|
fd = dumper(fd);
|
|
|
|
fd = tlsServer(fd, conn);
|
|
|
|
if(fd < 0){
|
|
|
|
reporter("failed: %r");
|
|
|
|
exits(0);
|
|
|
|
}
|
|
|
|
reporter("open");
|
|
|
|
|
|
|
|
if(argc > 0){
|
|
|
|
if(pipe(p) < 0)
|
|
|
|
exits("pipe");
|
|
|
|
switch(fork()){
|
|
|
|
case 0:
|
|
|
|
close(fd);
|
|
|
|
dup(p[0], 0);
|
|
|
|
dup(p[0], 1);
|
|
|
|
close(p[1]);
|
|
|
|
close(p[0]);
|
|
|
|
exec(argv[0], argv);
|
|
|
|
reporter("can't exec %s: %r", argv[0]);
|
|
|
|
_exits("exec");
|
|
|
|
case -1:
|
|
|
|
exits("fork");
|
|
|
|
default:
|
|
|
|
close(p[0]);
|
|
|
|
clearfd = p[1];
|
|
|
|
break;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
rfork(RFNOTEG);
|
|
|
|
notify(death);
|
|
|
|
switch(rfork(RFPROC)){
|
|
|
|
case -1:
|
|
|
|
sysfatal("can't fork");
|
|
|
|
case 0:
|
|
|
|
for(;;){
|
|
|
|
n = read(clearfd, buf, BufSize);
|
|
|
|
if(n <= 0)
|
|
|
|
break;
|
|
|
|
if(write(fd, buf, n) != n)
|
|
|
|
break;
|
|
|
|
}
|
|
|
|
break;
|
|
|
|
default:
|
|
|
|
for(;;){
|
|
|
|
n = read(fd, buf, BufSize);
|
|
|
|
if(n <= 0)
|
|
|
|
break;
|
|
|
|
if(write(clearfd, buf, n) != n)
|
|
|
|
break;
|
|
|
|
}
|
|
|
|
break;
|
|
|
|
}
|
|
|
|
death(nil, nil);
|
|
|
|
}
|