#include <u.h>
#include <libc.h>
-#include <bio.h>
#include <auth.h>
#include <fcall.h>
#include <libsec.h>
#define MaxStr 128
void remoteside(int);
-void fatal(int, char*, ...);
+void fatal(char*, ...);
void lclnoteproc(int);
void rmtnoteproc(void);
void catcher(void*, char*);
int exportpid;
char *system;
int cflag;
+int nflag;
int dbg;
char *user;
char *patternfile;
{
{ "p9", p9auth, srvp9auth,},
{ "netkey", netkeyauth, netkeysrvauth,},
-// { "none", noauth, srvnoauth,},
+ { "none", noauth, srvnoauth,},
{ nil, nil}
};
AuthMethod *am = authmethod; /* default is p9 */
int setam(char*);
+char *aan = "/bin/aan";
+char *anstring = "tcp!*!0";
+char *filterp = nil;
+
+int filter(int fd, char *host);
+
void
usage(void)
{
- fprint(2, "usage: cpu [-h system] [-u user] [-a authmethod] "
+ fprint(2, "usage: cpu [-p] [-h system] [-u user] [-a authmethod] "
"[-e 'crypt hash'] [-k keypattern] [-P patternfile] "
"[-c cmd arg ...]\n");
exits("usage");
void
main(int argc, char **argv)
{
- char dat[MaxStr], buf[MaxStr], cmd[MaxStr], *p, *err;
+ char dat[MaxStr], buf[MaxStr], cmd[MaxStr], *p, *s, *err;
int ac, fd, ms, data;
char *av[10];
user = getuser();
if(user == nil)
- fatal(1, "can't read user name");
+ fatal("can't read user name: %r");
ARGBEGIN{
case 'a':
p = EARGF(usage());
if(setam(p) < 0)
- fatal(0, "unknown auth method %s", p);
+ fatal("unknown auth method %s", p);
break;
case 'e':
ealgs = EARGF(usage());
case 'f':
/* ignored but accepted for compatibility */
break;
+ case 'n':
+ /* must be specified before -R/-O */
+ nflag++;
+ break;
+ case 'A':
+ anstring = EARGF(usage());
+ break;
case 'O':
p9authproto = "p9sk2";
remoteside(1); /* From listen */
break;
case 'c':
cflag++;
- cmd[0] = '!';
- cmd[1] = '\0';
- while(p = ARGF()) {
- strcat(cmd, " ");
- strcat(cmd, p);
- }
+ s = cmd;
+ *s++ = '!';
+ *s = 0;
+ while(p = ARGF())
+ s = seprint(s, cmd+sizeof(cmd), " %s", p);
break;
case 'k':
keyspec = smprint("%s %s", keyspec, EARGF(usage()));
user = EARGF(usage());
keyspec = smprint("%s user=%s", keyspec, user);
break;
+ case 'p':
+ filterp = aan;
+ break;
default:
usage();
}ARGEND;
if(system == nil) {
p = getenv("cpu");
if(p == 0)
- fatal(0, "set $cpu");
+ fatal("set $cpu");
system = p;
}
if(err = rexcall(&data, system, srvname))
- fatal(1, "%s: %s", err, system);
+ fatal("%s: %s: %r", err, system);
procsetname("%s", origargs);
/* Tell the remote side the command to execute and where our working directory is */
* of /mnt/term
*/
if(readstr(data, buf, sizeof(buf)) < 0)
- fatal(1, "waiting for FS: %r");
+ fatal("waiting for FS: %r");
if(strncmp("FS", buf, 2) != 0) {
print("remote cpu: %s", buf);
exits(buf);
}
av[ac] = nil;
exec(exportfs, av);
- fatal(1, "starting exportfs");
+ fatal("starting exportfs: %r");
}
void
-fatal(int syserr, char *fmt, ...)
+fatal(char *fmt, ...)
{
- Fmt f;
- char *str;
+ char buf[1024];
va_list arg;
- fmtstrinit(&f);
- fmtprint(&f, "cpu: ");
va_start(arg, fmt);
- fmtvprint(&f, fmt, arg);
+ vsnprint(buf, sizeof(buf), fmt, arg);
va_end(arg);
- if(syserr)
- fmtprint(&f, ": %r");
- str = fmtstrflush(&f);
-
- fprint(2, "%s\n", str);
- syslog(0, "cpu", str);
- exits(str);
+ fprint(2, "cpu: %s\n", buf);
+ syslog(0, "cpu", "%s", buf);
+ exits(buf);
}
char *negstr = "negotiating authentication method";
-char bug[256];
-
int
old9p(int fd)
{
int p[2];
if(pipe(p) < 0)
- fatal(1, "pipe");
+ fatal("pipe: %r");
- switch(rfork(RFPROC|RFFDG|RFNAMEG)) {
+ switch(rfork(RFPROC|RFMEM|RFFDG|RFNAMEG)) {
case -1:
- fatal(1, "rfork srvold9p");
+ fatal("rfork srvold9p: %r");
case 0:
if(fd != 1){
dup(fd, 1);
execl("/bin/srvold9p", "srvold9p", "-ds", nil);
} else
execl("/bin/srvold9p", "srvold9p", "-s", nil);
- fatal(1, "exec srvold9p");
+ fatal("exec srvold9p: %r");
default:
close(fd);
close(p[0]);
return p[1];
}
-/* Invoked with stdin, stdout and stderr connected to the network connection */
+/* Invoked with stdin and stdout connected to the network connection */
void
remoteside(int old)
{
/* negotiate authentication mechanism */
n = readstr(fd, cmd, sizeof(cmd));
if(n < 0)
- fatal(1, "authenticating");
- if(setamalg(cmd) < 0){
+ fatal("authenticating: %r");
+ filterp = nil;
+ if(!old && strcmp(cmd, "aan") == 0){
+ filterp = aan;
+ writestr(fd, "", nil, 1);
+ n = readstr(fd, cmd, sizeof(cmd));
+ if(n < 0)
+ fatal("authenticating: %r");
+ }
+ if(setamalg(cmd) < 0 || (nflag == 0 && am->sf == srvnoauth)) {
writestr(fd, "unsupported auth method", nil, 0);
- fatal(1, "bad auth method %s", cmd);
+ fatal("bad auth method %s", cmd);
} else
writestr(fd, "", "", 1);
fd = (*am->sf)(fd, user);
if(fd < 0)
- fatal(1, "srvauth");
+ fatal("srvauth: %r");
/* Set environment values for the user */
putenv("user", user);
- sprint(home, "/usr/%s", user);
+ snprint(home, sizeof(home), "/usr/%s", user);
putenv("home", home);
/* Now collect invoking cpu's current directory or possibly a command */
gotcmd = 0;
if(readstr(fd, xdir, sizeof(xdir)) < 0)
- fatal(1, "dir/cmd");
+ fatal("dir/cmd: %r");
if(xdir[0] == '!') {
strcpy(cmd, &xdir[1]);
gotcmd = 1;
if(readstr(fd, xdir, sizeof(xdir)) < 0)
- fatal(1, "dir");
+ fatal("dir: %r");
}
/* Establish the new process at the current working directory of the
execl("/bin/rc", "rc", "-lc", cmd, nil);
else
execl("/bin/rc", "rc", "-li", nil);
- fatal(1, "exec shell");
+ fatal("exec shell: %r");
}
char*
if((*fd = dial(na, 0, dir, 0)) < 0)
return "can't dial";
+ /* negotiate aan filter extension */
+ if(filterp == aan){
+ writestr(*fd, "aan", "negotiating aan", 0);
+ n = readstr(*fd, err, sizeof err);
+ if(n < 0)
+ return "negotiating aan";
+ if(*err){
+ werrstr(err);
+ return negstr;
+ }
+ }
+
/* negotiate authentication mechanism */
if(ealgs != nil)
snprint(msg, sizeof(msg), "%s %s", am->name, ealgs);
l = strlen(str);
n = write(fd, str, l+1);
if(!ignore && n < 0)
- fatal(1, "writing network: %s", thing);
+ fatal("writing network: %s: %r", thing);
}
int
if(readstr(fd, chall, sizeof chall) < 0)
break;
if(*chall == 0)
- return fd;
+ return filter(fd, system);
print("challenge: %s\nresponse: ", chall);
if(readln(resp, sizeof(resp)) < 0)
break;
int tries;
AuthInfo *ai;
- if(readstr(fd, user, 32) < 0)
+ if(readstr(fd, user, MaxStr) < 0)
return -1;
ai = nil;
return -1;
writestr(fd, "", "challenge", 1);
if(auth_chuid(ai, 0) < 0)
- fatal(1, "newns");
+ fatal("newns: %r");
auth_freeAI(ai);
- return fd;
+ return filter(fd, nil);
}
static void
static int
p9auth(int fd)
{
- uchar key[16];
- uchar digest[SHA1dlen];
+ uchar key[16], digest[SHA1dlen];
char fromclientsecret[21];
char fromserversecret[21];
- int i;
AuthInfo *ai;
+ int i;
procsetname("%s: auth_proxy proto=%q role=client %s",
origargs, p9authproto, keyspec);
ai = auth_proxy(fd, auth_getkey, "proto=%q role=client %s", p9authproto, keyspec);
if(ai == nil)
return -1;
- memmove(key+4, ai->secret, ai->nsecret);
- if(ealgs == nil)
+ if(ealgs == nil){
+ auth_freeAI(ai);
return fd;
+ }
+ assert(ai->nsecret <= sizeof(key)-4);
+ memmove(key+4, ai->secret, ai->nsecret);
+ auth_freeAI(ai);
/* exchange random numbers */
srand(truerand());
mksecret(fromclientsecret, digest);
mksecret(fromserversecret, digest+10);
+ if((fd = filter(fd, system)) < 0)
+ return -1;
+
/* set up encryption */
procsetname("pushssl");
- i = pushssl(fd, ealgs, fromclientsecret, fromserversecret, nil);
- if(i < 0)
+ fd = pushssl(fd, ealgs, fromclientsecret, fromserversecret, nil);
+ if(fd < 0)
werrstr("can't establish ssl connection: %r");
- return i;
+ return fd;
}
static int
for(i = 0; i < n; i++)
sprint(buf+2*i, "%2.2ux", p[i]);
- syslog(0, "cpu", buf);
+ syslog(0, "cpu", "%s", buf);
}
static int
srvp9auth(int fd, char *user)
{
- uchar key[16];
- uchar digest[SHA1dlen];
+ uchar key[16], digest[SHA1dlen];
char fromclientsecret[21];
char fromserversecret[21];
- int i;
AuthInfo *ai;
+ int i;
- ai = auth_proxy(0, nil, "proto=%q role=server %s", p9authproto, keyspec);
+ ai = auth_proxy(fd, nil, "proto=%q role=server %s", p9authproto, keyspec);
if(ai == nil)
return -1;
if(auth_chuid(ai, nil) < 0)
- return -1;
- strecpy(user, user+MaxStr, ai->cuid);
- memmove(key+4, ai->secret, ai->nsecret);
-
- if(ealgs == nil)
+ fatal("newns: %r");
+ snprint(user, MaxStr, "%s", ai->cuid);
+ if(ealgs == nil){
+ auth_freeAI(ai);
return fd;
+ }
+ assert(ai->nsecret <= sizeof(key)-4);
+ memmove(key+4, ai->secret, ai->nsecret);
+ auth_freeAI(ai);
/* exchange random numbers */
srand(truerand());
mksecret(fromclientsecret, digest);
mksecret(fromserversecret, digest+10);
+ if((fd = filter(fd, nil)) < 0)
+ return -1;
+
/* set up encryption */
- i = pushssl(fd, ealgs, fromserversecret, fromclientsecret, nil);
- if(i < 0)
+ fd = pushssl(fd, ealgs, fromserversecret, fromclientsecret, nil);
+ if(fd < 0)
werrstr("can't establish ssl connection: %r");
- return i;
+ return fd;
}
/*
return setam(s);
}
+int
+filter(int fd, char *host)
+{
+ char addr[128], buf[256], *s, *file, *argv[16];
+ int p[2], lfd, flags, len, argc;
+
+ if(filterp == nil)
+ return fd;
+ procsetname("filter %s", filterp);
+ flags = RFNOWAIT|RFPROC|RFMEM|RFFDG;
+ if(host == nil){
+ /* remote side */
+ if(announce(anstring, addr) < 0)
+ fatal("filter: Cannot announce %s: %r", anstring);
+ snprint(buf, sizeof(buf), "%s/local", addr);
+ if((lfd = open(buf, OREAD)) < 0)
+ fatal("filter: Cannot open %s: %r", buf);
+ if((len = read(lfd, buf, sizeof buf - 1)) < 0)
+ fatal("filter: Cannot read %s: %r", buf);
+ close(lfd);
+ buf[len] = 0;
+ if(s = strchr(buf, '\n'))
+ len = s - buf;
+ if(write(fd, buf, len) != len)
+ fatal("filter: cannot write port; %r");
+ } else {
+ /* client side */
+ flags |= RFNOTEG;
+ if((len = read(fd, buf, sizeof buf - 1)) < 0)
+ fatal("filter: cannot read port; %r");
+ buf[len] = '\0';
+ if((s = strrchr(buf, '!')) == nil)
+ fatal("filter: malformed remote port: %s", buf);
+ snprint(addr, sizeof(addr), "%s", netmkaddr(host, "tcp", s+1));
+ }
+
+ snprint(buf, sizeof(buf), "%s", filterp);
+ if((argc = tokenize(buf, argv, nelem(argv)-3)) <= 0)
+ fatal("filter: empty command");
+ if(host)
+ argv[argc++] = "-c";
+ argv[argc++] = addr;
+ argv[argc] = nil;
+ file = argv[0];
+ if(s = strrchr(argv[0], '/'))
+ argv[0] = s+1;
+
+ if(pipe(p) < 0)
+ fatal("filter: pipe; %r");
+
+ switch(rfork(flags)) {
+ case -1:
+ fatal("filter: rfork; %r\n");
+ case 0:
+ if (dup(p[0], 1) < 0)
+ fatal("filter: Cannot dup to 1; %r");
+ if (dup(p[0], 0) < 0)
+ fatal("filter: Cannot dup to 0; %r");
+ close(p[0]);
+ close(p[1]);
+ exec(file, argv);
+ fatal("filter: exec; %r");
+ default:
+ close(fd);
+ close(p[0]);
+ }
+ return p[1];
+}
+
char *rmtnotefile = "/mnt/term/dev/cpunote";
/*
ncpunote = 0;
for(;;){
n = read9pmsg(fd, buf, sizeof(buf));
- if(n <= 0){
+ if(n < 0){
if(dbg)
fprint(2, "read9pmsg(%d) returns %d: %r\n", fd, n);
break;
}
+ if(n == 0)
+ continue;
if(convM2S(buf, n, &f) <= BIT16SZ)
break;
if(dbg)