| #include "std.h" |
| #include "dat.h" |
| #include <bio.h> |
| |
| int |
| memrandom(void *p, int n) |
| { |
| uchar *cp; |
| |
| for(cp = (uchar*)p; n > 0; n--) |
| *cp++ = fastrand(); |
| return 0; |
| } |
| |
| /* |
| * create a change uid capability |
| */ |
| static int caphashfd; |
| |
| static char* |
| mkcap(char *from, char *to) |
| { |
| uchar rand[20]; |
| char *cap; |
| char *key; |
| int nfrom, nto; |
| uchar hash[SHA1dlen]; |
| |
| if(caphashfd < 0) |
| return nil; |
| |
| /* create the capability */ |
| nto = strlen(to); |
| nfrom = strlen(from); |
| cap = emalloc(nfrom+1+nto+1+sizeof(rand)*3+1); |
| sprint(cap, "%s@%s", from, to); |
| memrandom(rand, sizeof(rand)); |
| key = cap+nfrom+1+nto+1; |
| enc64(key, sizeof(rand)*3, rand, sizeof(rand)); |
| |
| /* hash the capability */ |
| hmac_sha1((uchar*)cap, strlen(cap), (uchar*)key, strlen(key), hash, nil); |
| |
| /* give the kernel the hash */ |
| key[-1] = '@'; |
| if(write(caphashfd, hash, SHA1dlen) < 0){ |
| free(cap); |
| return nil; |
| } |
| |
| return cap; |
| } |
| |
| Attr* |
| addcap(Attr *a, char *from, Ticket *t) |
| { |
| char *cap; |
| |
| cap = mkcap(from, t->suid); |
| return addattr(a, "cuid=%q suid=%q cap=%q", t->cuid, t->suid, cap); |
| } |
| |
| /* bind in the default network and cs */ |
| static int |
| bindnetcs(void) |
| { |
| int srvfd; |
| |
| if(access("/net/tcp", AEXIST) < 0) |
| bind("#I", "/net", MBEFORE); |
| |
| if(access("/net/cs", AEXIST) < 0){ |
| if((srvfd = open("#s/cs", ORDWR)) >= 0){ |
| /* mount closes srvfd on success */ |
| if(mount(srvfd, -1, "/net", MBEFORE, "") >= 0) |
| return 0; |
| close(srvfd); |
| } |
| return -1; |
| } |
| return 0; |
| } |
| |
| int |
| _authdial(char *net, char *authdom) |
| { |
| int vanilla; |
| |
| vanilla = net==nil || strcmp(net, "/net")==0; |
| |
| if(!vanilla || bindnetcs()>=0) |
| return authdial(net, authdom); |
| |
| /* use the auth sever passed to us as an arg */ |
| if(authaddr == nil) |
| return -1; |
| return dial(netmkaddr(authaddr, "tcp", "567"), 0, 0, 0); |
| } |
| |
| Key* |
| plan9authkey(Attr *a) |
| { |
| char *dom; |
| Key *k; |
| |
| /* |
| * The only important part of a is dom. |
| * We don't care, for example, about user name. |
| */ |
| dom = strfindattr(a, "dom"); |
| if(dom) |
| k = keylookup("proto=p9sk1 role=server user? dom=%q", dom); |
| else |
| k = keylookup("proto=p9sk1 role=server user? dom?"); |
| if(k == nil) |
| werrstr("could not find plan 9 auth key dom %q", dom); |
| return k; |
| } |
| |
| /* |
| * prompt for a string with a possible default response |
| */ |
| char* |
| readcons(char *prompt, char *def, int raw) |
| { |
| int fdin, fdout, ctl, n; |
| char line[10]; |
| char *s; |
| |
| fdin = open("/dev/cons", OREAD); |
| if(fdin < 0) |
| fdin = 0; |
| fdout = open("/dev/cons", OWRITE); |
| if(fdout < 0) |
| fdout = 1; |
| if(def != nil) |
| fprint(fdout, "%s[%s]: ", prompt, def); |
| else |
| fprint(fdout, "%s: ", prompt); |
| if(raw){ |
| ctl = open("/dev/consctl", OWRITE); |
| if(ctl >= 0) |
| write(ctl, "rawon", 5); |
| } else |
| ctl = -1; |
| s = estrdup(""); |
| for(;;){ |
| n = read(fdin, line, 1); |
| if(n == 0){ |
| Error: |
| close(fdin); |
| close(fdout); |
| if(ctl >= 0) |
| close(ctl); |
| free(s); |
| return nil; |
| } |
| if(n < 0) |
| goto Error; |
| if(line[0] == 0x7f) |
| goto Error; |
| if(n == 0 || line[0] == '\n' || line[0] == '\r'){ |
| if(raw){ |
| write(ctl, "rawoff", 6); |
| write(fdout, "\n", 1); |
| } |
| close(ctl); |
| close(fdin); |
| close(fdout); |
| if(*s == 0 && def != nil) |
| s = estrappend(s, "%s", def); |
| return s; |
| } |
| if(line[0] == '\b'){ |
| if(strlen(s) > 0) |
| s[strlen(s)-1] = 0; |
| } else if(line[0] == 0x15) { /* ^U: line kill */ |
| if(def != nil) |
| fprint(fdout, "\n%s[%s]: ", prompt, def); |
| else |
| fprint(fdout, "\n%s: ", prompt); |
| |
| s[0] = 0; |
| } else { |
| s = estrappend(s, "%c", line[0]); |
| } |
| } |
| return nil; /* not reached */ |
| } |