123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727 |
- #include "lib9.h"
- #include "auth.h"
- #include "libsec/libsec.h"
- char *cpuaddr = "plan9cpu";
- char *authaddr = "plan9auth";
- char *ealgs = "rc4_256 sha1";
- static char *pbmsg = "AS protocol botch";
- static char *ccmsg = "can't connect to AS";
- int debug = 0;
- int mousequeue = 1;
- int depth;
- static void fdwritestr(int, char*, char*, int);
- static int fdreadstr(int, char*, int);
- static void noteproc(char *pid);
- static void getpasswd(char *p, int len);
- static void userpasswd(char *key, int islocal);
- static int outin(char *prompt, char *def, int len);
- static char *checkkey(char *name, char *key);
- static int writefile(char *name, char *buf, int len);
- static int authtcp(void);
- static int sendmsg(int fd, char *msg);
- extern void procinit(void);
- extern char *hostlookup(char*);
- extern char *base;
- void usage(void);
- int nncpu(void);
- int setam(char*);
- int
- main(int argc, char *argv[])
- {
- char buf[128];
- int fd;
- /*
- * Needed by various parts of the code.
- * This is a huge bug.
- */
- assert(sizeof(char)==1);
- assert(sizeof(short)==2);
- assert(sizeof(ushort)==2);
- assert(sizeof(int)==4);
- assert(sizeof(uint)==4);
- assert(sizeof(long)==4);
- assert(sizeof(ulong)==4);
- assert(sizeof(vlong)==8);
- assert(sizeof(uvlong)==8);
- threadinit();
- procinit();
- ARGBEGIN {
- case 'a':
- authaddr = ARGF();
- break;
- case 'c':
- cpuaddr = ARGF();
- break;
- case 'd':
- depth = atoi(ARGF());
- break;
- case 'e':
- ealgs = ARGF();
- if(*ealgs == 0 || strcmp(ealgs, "clear") == 0)
- ealgs = nil;
- break;
- case 'n':
- setam("netkey");
- break;
- case 'm':
- mousequeue = !mousequeue;
- break;
- case 'r':
- base = ARGF();
- break;
- case 'o':
- /* from the outside */
- /*
- cpuaddr = "achille.cs.bell-labs.com";
- authaddr = "achille.cs.bell-labs.com";
- */
- break;
- case '@':
- /* from Comcast @Home */
- /*
- cpuaddr = "10.252.0.122";
- authaddr = "10.252.0.122";
- */
- break;
- default:
- usage();
- } ARGEND;
- if(argc != 0)
- usage();
-
- if(bind("#i", "/dev", MBEFORE) < 0)
- iprint("bind failed: %r\n");
- if(bind("#m", "/dev", MBEFORE) < 0)
- iprint("bind failed: %r\n");
- if(bind("#I", "/net", MBEFORE) < 0)
- iprint("bind failed: %r\n");
- authaddr = hostlookup(authaddr);
- cpuaddr = hostlookup(cpuaddr);
- fd = nncpu(); /* fd = cpu(); */
-
- /* Tell the remote side the command to execute and where our working directory is */
- fdwritestr(fd, "NO", "dir", 0);
- /*
- * old cpu protocol
- *
- if(fdreadstr(fd, buf, sizeof(buf)) < 0)
- fatal("bad pid");
- noteproc(buf);
- *
- */
-
- /* Wait for the other end to execute and start our file service
- * of /mnt/term */
- if(fdreadstr(fd, buf, sizeof(buf)) < 0)
- fatal("waiting for FS");
- if(strncmp("FS", buf, 2) != 0)
- fatal("remote cpu: %s", buf);
- if(fdreadstr(fd, buf, sizeof(buf)) < 0)
- fatal("waiting for root");
- if(write(fd, "OK", 2) < 2)
- fatal("ack root");
- export(fd);
- return 0;
- }
- int
- cpu(void)
- {
- int fd;
- char na[256];
- userpasswd(na, 0);
-
- netmkaddr(na, cpuaddr, "tcp", "17005");
- if((fd = dial(na, 0, 0, 0)) < 0) {
- fatal("can't dial %s: %r", na);
- }
- if(auth(fd, 0) < 0)
- fatal("can't authenticate: %r");
- return fd;
- }
- /* authentication mechanisms */
- static int netkeyauth(int, uchar*);
- typedef struct AuthMethod AuthMethod;
- struct AuthMethod {
- char *name; /* name of method */
- int (*cf)(int, uchar*); /* client side authentication */
- } authmethod[] =
- {
- { "p9", auth},
- { "netkey", netkeyauth},
- { nil, nil}
- };
- AuthMethod *am = authmethod; /* default is p9 */
- int
- setam(char *name)
- {
- for(am = authmethod; am->name != nil; am++)
- if(strcmp(am->name, name) == 0)
- return 0;
- am = authmethod;
- return -1;
- }
- static void
- mksecret(char *t, uchar *f)
- {
- sprint(t, "%2.2x%2.2x%2.2x%2.2x%2.2x%2.2x%2.2x%2.2x%2.2x%2.2x",
- f[0], f[1], f[2], f[3], f[4], f[5], f[6], f[7], f[8], f[9]);
- }
- char *negstr = "negotiating authentication method";
- int
- nncpu(void)
- {
- char na[128];
- char err[ERRLEN];
- uchar key[16];
- uchar digest[SHA1dlen];
- char fromclientsecret[21];
- char fromserversecret[21];
- int fd, n, i;
- netmkaddr(na, cpuaddr, "tcp", "17013");
- if((fd = dial(na, 0, 0, 0)) < 0) {
- fatal("can't dial %s: %r", na);
- }
- if(am->cf == auth)
- userpasswd(key+4, 0);
-
- /* negotiate authentication mechanism */
- if(ealgs != nil)
- snprint(na, sizeof(na), "%s %s", am->name, ealgs);
- else
- snprint(na, sizeof(na), "%s", am->name);
- fdwritestr(fd, na, negstr, 0);
- n = fdreadstr(fd, err, ERRLEN);
- if(n < 0)
- fatal(negstr);
- if(*err)
- fatal("%s: %s", negstr, err);
- /* authenticate */
- if((*am->cf)(fd, key+4) < 0)
- fatal("cannot authenticate with %s", am->name);
- if(ealgs == nil)
- return fd;
- /* ssl handshake */
- for(i = 0; i < 4; i++)
- key[i] = nrand(256);
- if(write(fd, key, 4) != 4 || readn(fd, key+12, 4) != 4)
- fatal("cannot exchange random numbers for ssl: %r");
- /* scramble into two secrets */
- sha1(key, sizeof(key), digest, nil);
- mksecret(fromclientsecret, digest);
- mksecret(fromserversecret, digest+10);
- /* set up encryption */
- fd = pushssl(fd, ealgs, fromclientsecret, fromserversecret, nil);
- if(fd < 0)
- fatal("cannot establish ssl connection: %r");
- return fd;
- }
- static int
- readln(char *buf, int n)
- {
- char *p = buf;
- n--;
- while(n > 0){
- if(read(0, p, 1) != 1)
- break;
- if(*p == '\n' || *p == '\r'){
- *p = 0;
- return p-buf;
- }
- p++;
- }
-
- *p = 0;
- return p-buf;
- }
- static int
- netkeyauth(int fd, uchar *secret)
- {
- char chall[NAMELEN];
- char resp[NAMELEN];
- USED(secret);
- strcpy(chall, getuser());
- print("user[%s]: ", chall);
- if(readln(resp, sizeof(resp)) < 0)
- return -1;
- if(*resp != 0)
- strcpy(chall, resp);
- fdwritestr(fd, chall, "challenge/response", 1);
- for(;;){
- if(fdreadstr(fd, chall, sizeof chall) < 0)
- break;
- if(*chall == 0)
- return 0;
- print("challenge: %s\nresponse: ", chall);
- if(readln(resp, sizeof(resp)) < 0)
- break;
- fdwritestr(fd, resp, "challenge/response", 1);
- }
- return -1;
- }
- void
- usage(void)
- {
- iprint("usage: %s [-o@] [-n] [-m] [-c cpusrv] [-a authsrv] [-e 'crypt hash'] [-r root]\n", argv0);
- exits(0);
- }
- void
- fdwritestr(int fd, char *str, char *thing, int ignore)
- {
- int l, n;
- l = strlen(str);
- n = write(fd, str, l+1);
- if(!ignore && n < 0)
- fatal("writing network: %s", thing);
- }
- int
- fdreadstr(int fd, char *str, int len)
- {
- int n;
- while(len) {
- n = read(fd, str, 1);
- if(n < 0)
- return -1;
- if(*str == '\0')
- return 0;
- str++;
- len--;
- }
- return -1;
- }
- void
- noteproc(char *pid)
- {
- char cmd[NAMELEN];
- int fd;
- char na[256];
- netmkaddr(na, cpuaddr, "tcp", "17006");
- if((fd = dial(na, 0, 0, 0)) < 0)
- fatal("can't dial");
- if(auth(fd, 0) < 0)
- fatal("can't authenticate");
- sprint(cmd, "%s", pid);
- fdwritestr(fd, cmd, "notepid", 0);
- return;
- /*
- notify(catcher);
- for(;;) {
- n = wait(&w);
- if(n < 0) {
- writestr(notechan, notebuf, "catcher", 1);
- errstr(syserr);
- if(strcmp(syserr, "interrupted") != 0){
- iprint("cpu: wait: %s\n", syserr);
- exits("waiterr");
- }
- }
- if(n == notepid)
- break;
- }
- exits(w.msg);
- */
- }
- static char password[NAMELEN];
- char username[NAMELEN];
- char *homsg = "can't set user name or key; please reboot";
- /*
- * get/set user name and password. verify password with auth server.
- */
- void
- userpasswd(char *hostkey, int islocal)
- {
- int fd;
- char *msg;
- if(*username == 0 || strcmp(username, "none") == 0){
- strcpy(username, "none");
- outin("user", username, sizeof(username));
- }
- if(!atlocalconsole()){
- print("not at local console; won't ask for password\n");
- p9sleep(10000);
- exits(0);
- }
-
- fd = -1;
- while(strcmp(username, "none") != 0){
- getpasswd(password, sizeof password);
- passtokey(hostkey, password);
- memset(password, 0, sizeof(password));
- fd = -1;
- if(islocal)
- break;
- msg = checkkey(username, hostkey);
- if(msg == 0)
- break;
- print("?%s\n", msg);
- outin("user", username, sizeof(username));
- }
- if(fd > 0)
- close(fd);
- /* set host's key */
- if(writefile("#c/key", hostkey, DESKEYLEN) < 0)
- fatal(homsg);
- /* set host's owner (and uid of current process) */
- if(writefile("#c/hostowner", username, strlen(username)) < 0)
- fatal(homsg);
- close(fd);
- }
- static char*
- fromauth(char *trbuf, char *tbuf)
- {
- int afd;
- char t;
- char *msg;
- static char error[2*ERRLEN];
- afd = authtcp();
- if(afd < 0) {
- sprint(error, "%s: %r", ccmsg);
- return error;
- }
- if(write(afd, trbuf, TICKREQLEN) < 0 || read(afd, &t, 1) != 1){
- close(afd);
- sprint(error, "%s: %r", pbmsg);
- return error;
- }
- switch(t){
- case AuthOK:
- msg = 0;
- if(readn(afd, tbuf, 2*TICKETLEN) < 0) {
- sprint(error, "%s: %r", pbmsg);
- msg = error;
- }
- break;
- case AuthErr:
- if(readn(afd, error, ERRLEN) < 0) {
- sprint(error, "%s: %r", pbmsg);
- msg = error;
- }
- else {
- error[ERRLEN-1] = 0;
- msg = error;
- }
- break;
- default:
- msg = pbmsg;
- break;
- }
- close(afd);
- return msg;
- }
- char*
- checkkey(char *name, char *key)
- {
- char *msg;
- Ticketreq tr;
- Ticket t;
- char trbuf[TICKREQLEN];
- char tbuf[2*TICKETLEN];
- memset(&tr, 0, sizeof tr);
- tr.type = AuthTreq;
- strcpy(tr.authid, name);
- strcpy(tr.hostid, name);
- strcpy(tr.uid, name);
- convTR2M(&tr, trbuf);
- msg = fromauth(trbuf, tbuf);
- if(msg == ccmsg){
- iprint("boot: can't contact auth server, passwd unchecked\n");
- return 0;
- }
- if(msg)
- return msg;
- convM2T(tbuf, &t, key);
- if(t.num == AuthTc && strcmp(name, t.cuid)==0)
- return 0;
- return "no match";
- }
- void
- getpasswd(char *p, int len)
- {
- char c;
- int i, n, fd;
- fd = open("#c/consctl", OWRITE);
- if(fd < 0)
- fatal("can't open consctl; please reboot");
- write(fd, "rawon", 5);
- Prompt:
- print("password: ");
- n = 0;
- for(;;){
- do{
- i = read(0, &c, 1);
- if(i < 0)
- fatal("can't read cons; please reboot");
- }while(i == 0);
- switch(c){
- case '\n':
- p[n] = '\0';
- close(fd);
- print("\n");
- return;
- case '\b':
- if(n > 0)
- n--;
- break;
- case 'u' - 'a' + 1: /* cntrl-u */
- print("\n");
- goto Prompt;
- default:
- if(n < len - 1)
- p[n++] = c;
- break;
- }
- }
- }
- int
- authtcp(void)
- {
- char na[256];
- netmkaddr(na, authaddr, "tcp", "567");
- return dial(na, 0, 0, 0);
- }
- int
- plumb(char *dir, char *dest, int *efd, char *here)
- {
- char buf[128];
- char name[128];
- int n;
- sprint(name, "%s/clone", dir);
- efd[0] = open(name, ORDWR);
- if(efd[0] < 0)
- return -1;
- n = read(efd[0], buf, sizeof(buf)-1);
- if(n < 0){
- close(efd[0]);
- return -1;
- }
- buf[n] = 0;
- sprint(name, "%s/%s/data", dir, buf);
- if(here){
- sprint(buf, "announce %s", here);
- if(sendmsg(efd[0], buf) < 0){
- close(efd[0]);
- return -1;
- }
- }
- sprint(buf, "connect %s", dest);
- if(sendmsg(efd[0], buf) < 0){
- close(efd[0]);
- return -1;
- }
- efd[1] = open(name, ORDWR);
- if(efd[1] < 0){
- close(efd[0]);
- return -1;
- }
- return efd[1];
- }
- int
- sendmsg(int fd, char *msg)
- {
- int n;
- n = strlen(msg);
- if(write(fd, msg, n) != n)
- return -1;
- return 0;
- }
- void
- warning(char *s)
- {
- char buf[ERRLEN];
- errstr(buf);
- iprint("boot: %s: %s\n", s, buf);
- }
- int
- readfile(char *name, char *buf, int len)
- {
- int f, n;
- buf[0] = 0;
- f = open(name, OREAD);
- if(f < 0)
- return -1;
- n = read(f, buf, len-1);
- if(n >= 0)
- buf[n] = 0;
- close(f);
- return 0;
- }
- int
- writefile(char *name, char *buf, int len)
- {
- int f, n;
- f = open(name, OWRITE);
- if(f < 0)
- return -1;
- n = write(f, buf, len);
- close(f);
- return (n != len) ? -1 : 0;
- }
- void
- srvcreate(char *name, int fd)
- {
- char *srvname;
- int f;
- char buf[2*NAMELEN];
- srvname = strrchr(name, '/');
- if(srvname)
- srvname++;
- else
- srvname = name;
- sprint(buf, "#s/%s", srvname);
- f = create(buf, 1, 0666);
- if(f < 0)
- fatal(buf);
- sprint(buf, "%d", fd);
- if(write(f, buf, strlen(buf)) != (int)strlen(buf))
- fatal("write");
- close(f);
- }
- int
- outin(char *prompt, char *def, int len)
- {
- int n;
- char buf[256];
- print("%s[%s]: ", prompt, *def ? def : "no default");
- n = read(0, buf, len);
- if(n <= 0)
- return -1;
-
- if(n != 1){
- buf[n-1] = 0;
- strcpy(def, buf);
- }
- return n;
- }
- /*
- * get second word of the terminal environment variable. If it
- * ends in "boot", get rid of that part.
- */
- void
- getconffile(char *conffile, char *terminal)
- {
- char *p, *q;
- char *s;
- int n;
- s = conffile;
- *conffile = 0;
- p = terminal;
- if((p = strchr(p, ' ')) == 0 || p[1] == ' ' || p[1] == 0)
- return;
- p++;
- for(q = p; *q && *q != ' '; q++)
- ;
- while(p < q)
- *conffile++ = *p++;
- *conffile = 0;
- /* dump a trailing boot */
- n = strlen(s);
- if(n > 4 && strcmp(s + n - 4, "boot") == 0)
- *(s+n-4) = 0;
- }
- /*
- * Case insensitive strcmp
- */
- int
- cistrncmp(char *a, char *b, int n)
- {
- unsigned ac, bc;
- while(n > 0){
- ac = *a++;
- bc = *b++;
- n--;
- if(ac >= 'A' && ac <= 'Z')
- ac = 'a' + (ac - 'A');
- if(bc >= 'A' && bc <= 'Z')
- bc = 'a' + (bc - 'A');
- ac -= bc;
- if(ac)
- return ac;
- if(bc == 0)
- break;
- }
- return 0;
- }
|